From 4d6a6ec507820a02d956c7a28cfe78b53b4ea852 Mon Sep 17 00:00:00 2001 From: Jing Xu Date: Wed, 1 Mar 2017 17:15:14 -0800 Subject: [PATCH 001/448] Add bind mount /etc/resolv.conf from host to containerized mounter Currently, in containerized mounter rootfs, there is no DNS setup. By bind mount the host's /etc/resolv.conf to mounter rootfs, vm hosts name could be resolved when using host name during mount. --- cluster/gce/gci/configure-helper.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/cluster/gce/gci/configure-helper.sh b/cluster/gce/gci/configure-helper.sh index 8b2b608e72b..8cf7ad87dde 100644 --- a/cluster/gce/gci/configure-helper.sh +++ b/cluster/gce/gci/configure-helper.sh @@ -890,6 +890,7 @@ function prepare-mounter-rootfs { mount --make-rshared "${CONTAINERIZED_MOUNTER_ROOTFS}/var/lib/kubelet" mount --bind -o ro /proc "${CONTAINERIZED_MOUNTER_ROOTFS}/proc" mount --bind -o ro /dev "${CONTAINERIZED_MOUNTER_ROOTFS}/dev" + mount --bind -o ro /etc/resolv.conf "${CONTAINERIZED_MOUNTER_ROOTFS}/etc/resolv.conf" } # A helper function for removing salt configuration and comments from a file. From f880e0d5ec35e24646b712de8c28e6fd9e69decb Mon Sep 17 00:00:00 2001 From: FengyunPan Date: Tue, 2 May 2017 12:26:33 +0800 Subject: [PATCH 002/448] Return clusterErr rather than err The updateClusterIngressUIDToMasters() should return clusterErr, not err. And do not log fallbackUID when fallbackUID is nil. --- .../ingress/ingress_controller.go | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/federation/pkg/federation-controller/ingress/ingress_controller.go b/federation/pkg/federation-controller/ingress/ingress_controller.go index ad9ff847636..088bf368649 100644 --- a/federation/pkg/federation-controller/ingress/ingress_controller.go +++ b/federation/pkg/federation-controller/ingress/ingress_controller.go @@ -608,9 +608,10 @@ func (ic *IngressController) updateClusterIngressUIDToMasters(cluster *federatio clusterObj, clusterErr := api.Scheme.DeepCopy(cluster) // Make a clone so that we don't clobber our input param cluster, ok := clusterObj.(*federationapi.Cluster) if clusterErr != nil || !ok { - glog.Errorf("Internal error: Failed clone cluster resource while attempting to add master ingress UID annotation (%q = %q) from master cluster %q to cluster %q, will try again later: %v", uidAnnotationKey, masterUID, masterCluster.Name, cluster.Name, err) - return "", err + glog.Errorf("Internal error: Failed clone cluster resource while attempting to add master ingress UID annotation (%q = %q) from master cluster %q to cluster %q, will try again later: %v", uidAnnotationKey, masterUID, masterCluster.Name, cluster.Name, clusterErr) + return "", clusterErr } + if err == nil { if masterCluster.Name != cluster.Name { // We're not the master, need to get in sync if cluster.ObjectMeta.Annotations == nil { @@ -629,8 +630,9 @@ func (ic *IngressController) updateClusterIngressUIDToMasters(cluster *federatio return cluster.ObjectMeta.Annotations[uidAnnotationKey], nil } } else { - glog.V(2).Infof("No master cluster found to source an ingress UID from for cluster %q. Attempting to elect new master cluster %q with ingress UID %q = %q", cluster.Name, cluster.Name, uidAnnotationKey, fallbackUID) + glog.V(2).Infof("No master cluster found to source an ingress UID from for cluster %q.", cluster.Name) if fallbackUID != "" { + glog.V(2).Infof("Attempting to elect new master cluster %q with ingress UID %q = %q", cluster.Name, uidAnnotationKey, fallbackUID) if cluster.ObjectMeta.Annotations == nil { cluster.ObjectMeta.Annotations = map[string]string{} } @@ -643,7 +645,7 @@ func (ic *IngressController) updateClusterIngressUIDToMasters(cluster *federatio return fallbackUID, nil } } else { - glog.Errorf("No master cluster exists, and fallbackUID for cluster %q is invalid (%q). This probably means that no clusters have an ingress controller configmap with key %q. Federated Ingress currently supports clusters running Google Loadbalancer Controller (\"GLBC\")", cluster.Name, fallbackUID, uidKey) + glog.Errorf("No master cluster exists, and fallbackUID for cluster %q is nil. This probably means that no clusters have an ingress controller configmap with key %q. Federated Ingress currently supports clusters running Google Loadbalancer Controller (\"GLBC\")", cluster.Name, uidKey) return "", err } } From a1b568ccb80c3c2464d52b48f52ef4563af472c0 Mon Sep 17 00:00:00 2001 From: xiangpengzhao Date: Thu, 6 Apr 2017 12:27:05 +0800 Subject: [PATCH 003/448] Add default=false to usage of kube-apiserver allow-privileged flag --- cmd/kube-apiserver/app/options/options.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/kube-apiserver/app/options/options.go b/cmd/kube-apiserver/app/options/options.go index c3719901b43..ec517aeaca6 100644 --- a/cmd/kube-apiserver/app/options/options.go +++ b/cmd/kube-apiserver/app/options/options.go @@ -138,7 +138,7 @@ func (s *ServerRunOptions) AddFlags(fs *pflag.FlagSet) { "Amount of time to retain events.") fs.BoolVar(&s.AllowPrivileged, "allow-privileged", s.AllowPrivileged, - "If true, allow privileged containers.") + "If true, allow privileged containers. [default=false]") fs.StringVar(&s.SSHUser, "ssh-user", s.SSHUser, "If non-empty, use secure SSH proxy to the nodes, using this user name") From 4f8cbc15ac1870e0f979654c74f18c3d4bb425da Mon Sep 17 00:00:00 2001 From: Alexander Staubo Date: Wed, 10 May 2017 16:17:12 -0400 Subject: [PATCH 004/448] kubectl: 'apply view-last-applied' must not use printf(), as this will cause format codes in the YAML/JSON to be interpreted. --- pkg/kubectl/cmd/apply_view_last_applied.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/kubectl/cmd/apply_view_last_applied.go b/pkg/kubectl/cmd/apply_view_last_applied.go index 1461a143a83..4f2b753555e 100644 --- a/pkg/kubectl/cmd/apply_view_last_applied.go +++ b/pkg/kubectl/cmd/apply_view_last_applied.go @@ -143,13 +143,13 @@ func (o *ViewLastAppliedOptions) RunApplyViewLastApplied() error { if err != nil { return err } - fmt.Fprintf(o.Out, string(jsonBuffer.Bytes())) + fmt.Fprint(o.Out, string(jsonBuffer.Bytes())) case "yaml": yamlOutput, err := yaml.JSONToYAML([]byte(str)) if err != nil { return err } - fmt.Fprintf(o.Out, string(yamlOutput)) + fmt.Fprint(o.Out, string(yamlOutput)) } } From fa563dce15a397a96edbf769094140c54baedab3 Mon Sep 17 00:00:00 2001 From: xilabao Date: Tue, 16 May 2017 09:00:08 +0800 Subject: [PATCH 005/448] fix self link error of generic resources in describe command --- pkg/printers/internalversion/describe.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pkg/printers/internalversion/describe.go b/pkg/printers/internalversion/describe.go index 064c43fe53f..98c60f4032c 100644 --- a/pkg/printers/internalversion/describe.go +++ b/pkg/printers/internalversion/describe.go @@ -224,7 +224,7 @@ func printUnstructuredContent(w PrefixWriter, level int, content map[string]inte if slice.ContainsString(skip, skipExpr, nil) { continue } - w.Write(level, fmt.Sprintf("%s:\n", smartLabelFor(field))) + w.Write(level, "%s:\n", smartLabelFor(field)) printUnstructuredContent(w, level+1, typedValue, skipExpr, skip...) case []interface{}: @@ -232,13 +232,13 @@ func printUnstructuredContent(w PrefixWriter, level int, content map[string]inte if slice.ContainsString(skip, skipExpr, nil) { continue } - w.Write(level, fmt.Sprintf("%s:\n", smartLabelFor(field))) + w.Write(level, "%s:\n", smartLabelFor(field)) for _, child := range typedValue { switch typedChild := child.(type) { case map[string]interface{}: printUnstructuredContent(w, level+1, typedChild, skipExpr, skip...) default: - w.Write(level+1, fmt.Sprintf("%v\n", typedChild)) + w.Write(level+1, "%v\n", typedChild) } } @@ -247,7 +247,7 @@ func printUnstructuredContent(w PrefixWriter, level int, content map[string]inte if slice.ContainsString(skip, skipExpr, nil) { continue } - w.Write(level, fmt.Sprintf("%s:\t%v\n", smartLabelFor(field), typedValue)) + w.Write(level, "%s:\t%v\n", smartLabelFor(field), typedValue) } } } From 41d7655e11c564f70b473bb8a9bf7e30831accbd Mon Sep 17 00:00:00 2001 From: jayunit100 Date: Mon, 22 May 2017 11:33:41 -0400 Subject: [PATCH 006/448] Add ownership for the future of scheduler_perf and kubemark --- test/integration/scheduler_perf/OWNERS | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 test/integration/scheduler_perf/OWNERS diff --git a/test/integration/scheduler_perf/OWNERS b/test/integration/scheduler_perf/OWNERS new file mode 100644 index 00000000000..3db647a9578 --- /dev/null +++ b/test/integration/scheduler_perf/OWNERS @@ -0,0 +1,14 @@ +approvers: +- davidopp +- gmarek +- jayunit100 +- timothysc +- wojtek-t +reviewers: +- davidopp +- jayunit100 +- k82cn +- ravisantoshgudimetla +- sjug +- timothysc +- wojtek-t From ea196490a0fc1117f4a7c75c24230f0d7ecb17c3 Mon Sep 17 00:00:00 2001 From: xilabao Date: Wed, 26 Apr 2017 16:37:36 +0800 Subject: [PATCH 007/448] add validate to not allow mix --config with other arguments --- cmd/kubeadm/app/apis/kubeadm/validation/BUILD | 2 + .../app/apis/kubeadm/validation/validation.go | 9 ++++ .../kubeadm/validation/validation_test.go | 41 +++++++++++++++++++ cmd/kubeadm/app/cmd/init.go | 7 +++- cmd/kubeadm/app/cmd/join.go | 35 ++++++++-------- cmd/kubeadm/test/cmd/init_test.go | 28 +++++++++++++ cmd/kubeadm/test/cmd/join_test.go | 28 +++++++++++++ 7 files changed, 132 insertions(+), 18 deletions(-) diff --git a/cmd/kubeadm/app/apis/kubeadm/validation/BUILD b/cmd/kubeadm/app/apis/kubeadm/validation/BUILD index 5ff38a39453..0ca8dcf761d 100644 --- a/cmd/kubeadm/app/apis/kubeadm/validation/BUILD +++ b/cmd/kubeadm/app/apis/kubeadm/validation/BUILD @@ -15,6 +15,7 @@ go_test( tags = ["automanaged"], deps = [ "//cmd/kubeadm/app/apis/kubeadm:go_default_library", + "//vendor/github.com/spf13/pflag:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library", ], ) @@ -30,6 +31,7 @@ go_library( "//pkg/api/validation:go_default_library", "//pkg/kubeapiserver/authorizer/modes:go_default_library", "//pkg/registry/core/service/ipallocator:go_default_library", + "//vendor/github.com/spf13/pflag:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/validation:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library", ], diff --git a/cmd/kubeadm/app/apis/kubeadm/validation/validation.go b/cmd/kubeadm/app/apis/kubeadm/validation/validation.go index e338c4aefcf..f603fc9eec5 100644 --- a/cmd/kubeadm/app/apis/kubeadm/validation/validation.go +++ b/cmd/kubeadm/app/apis/kubeadm/validation/validation.go @@ -24,6 +24,8 @@ import ( "path/filepath" "strings" + "github.com/spf13/pflag" + "k8s.io/apimachinery/pkg/util/validation" "k8s.io/apimachinery/pkg/util/validation/field" "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" @@ -239,3 +241,10 @@ func ValidateCloudProvider(provider string, fldPath *field.Path) field.ErrorList allErrs = append(allErrs, field.Invalid(fldPath, provider, "cloudprovider not supported")) return allErrs } + +func ValidateMixedArguments(flag *pflag.FlagSet) error { + if flag.Changed("config") && flag.NFlag() != 1 { + return fmt.Errorf("can not mix '--config' with other arguments") + } + return nil +} diff --git a/cmd/kubeadm/app/apis/kubeadm/validation/validation_test.go b/cmd/kubeadm/app/apis/kubeadm/validation/validation_test.go index 4c80c082e91..1fa82834e44 100644 --- a/cmd/kubeadm/app/apis/kubeadm/validation/validation_test.go +++ b/cmd/kubeadm/app/apis/kubeadm/validation/validation_test.go @@ -19,6 +19,8 @@ package validation import ( "testing" + "github.com/spf13/pflag" + "k8s.io/apimachinery/pkg/util/validation/field" "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" ) @@ -227,3 +229,42 @@ func TestValidateNodeConfiguration(t *testing.T) { } } } + +func TestValidateMixedArguments(t *testing.T) { + var tests = []struct { + args []string + expected bool + }{ + {[]string{"--foo=bar"}, true}, + {[]string{"--config=hello"}, true}, + {[]string{"--foo=bar", "--config=hello"}, false}, + } + + var cfgPath string + var skipPreFlight bool + + for _, rt := range tests { + f := pflag.NewFlagSet("test", pflag.ContinueOnError) + if f.Parsed() { + t.Error("f.Parse() = true before Parse") + } + f.String("foo", "", "string value") + f.StringVar(&cfgPath, "config", cfgPath, "Path to kubeadm config file") + f.BoolVar( + &skipPreFlight, "skip-preflight-checks", skipPreFlight, + "Skip preflight checks normally run before modifying the system", + ) + if err := f.Parse(rt.args); err != nil { + t.Fatal(err) + } + + actual := ValidateMixedArguments(f) + if (actual == nil) != rt.expected { + t.Errorf( + "failed ValidateMixedArguments:\n\texpected: %t\n\t actual: %t", + rt.expected, + (actual == nil), + ) + } + } +} diff --git a/cmd/kubeadm/app/cmd/init.go b/cmd/kubeadm/app/cmd/init.go index c7819668dea..0ce6cd69b9c 100644 --- a/cmd/kubeadm/app/cmd/init.go +++ b/cmd/kubeadm/app/cmd/init.go @@ -83,7 +83,7 @@ func NewCmdInit(out io.Writer) *cobra.Command { i, err := NewInit(cfgPath, internalcfg, skipPreFlight, skipTokenPrint) kubeadmutil.CheckErr(err) - kubeadmutil.CheckErr(i.Validate()) + kubeadmutil.CheckErr(i.Validate(cmd)) kubeadmutil.CheckErr(i.Run(out)) }, } @@ -191,7 +191,10 @@ type Init struct { } // Validate validates configuration passed to "kubeadm init" -func (i *Init) Validate() error { +func (i *Init) Validate(cmd *cobra.Command) error { + if err := validation.ValidateMixedArguments(cmd.PersistentFlags()); err != nil { + return err + } return validation.ValidateMasterConfiguration(i.cfg).ToAggregate() } diff --git a/cmd/kubeadm/app/cmd/join.go b/cmd/kubeadm/app/cmd/join.go index 031b89c15e6..c8ce2ca20bf 100644 --- a/cmd/kubeadm/app/cmd/join.go +++ b/cmd/kubeadm/app/cmd/join.go @@ -63,26 +63,26 @@ func NewCmdJoin(out io.Writer) *cobra.Command { Use: "join [DiscoveryTokenAPIServers]", Short: "Run this on any machine you wish to join an existing cluster", Long: dedent.Dedent(` - When joining a kubeadm initialized cluster, we need to establish - bidirectional trust. This is split into discovery (having the Node - trust the Kubernetes Master) and TLS bootstrap (having the Kubernetes + When joining a kubeadm initialized cluster, we need to establish + bidirectional trust. This is split into discovery (having the Node + trust the Kubernetes Master) and TLS bootstrap (having the Kubernetes Master trust the Node). - There are 2 main schemes for discovery. The first is to use a shared - token along with the IP address of the API server. The second is to - provide a file (a subset of the standard kubeconfig file). This file - can be a local file or downloaded via an HTTPS URL. The forms are - kubeadm join --discovery-token abcdef.1234567890abcdef 1.2.3.4:6443, + There are 2 main schemes for discovery. The first is to use a shared + token along with the IP address of the API server. The second is to + provide a file (a subset of the standard kubeconfig file). This file + can be a local file or downloaded via an HTTPS URL. The forms are + kubeadm join --discovery-token abcdef.1234567890abcdef 1.2.3.4:6443, kubeadm join --discovery-file path/to/file.conf, or kubeadm join - --discovery-file https://url/file.conf. Only one form can be used. If - the discovery information is loaded from a URL, HTTPS must be used and + --discovery-file https://url/file.conf. Only one form can be used. If + the discovery information is loaded from a URL, HTTPS must be used and the host installed CA bundle is used to verify the connection. - The TLS bootstrap mechanism is also driven via a shared token. This is + The TLS bootstrap mechanism is also driven via a shared token. This is used to temporarily authenticate with the Kubernetes Master to submit a - certificate signing request (CSR) for a locally created key pair. By - default kubeadm will set up the Kubernetes Master to automatically - approve these signing requests. This token is passed in with the + certificate signing request (CSR) for a locally created key pair. By + default kubeadm will set up the Kubernetes Master to automatically + approve these signing requests. This token is passed in with the --tls-bootstrap-token abcdef.1234567890abcdef flag. Often times the same token is used for both parts. In this case, the @@ -97,7 +97,7 @@ func NewCmdJoin(out io.Writer) *cobra.Command { j, err := NewJoin(cfgPath, args, internalcfg, skipPreFlight) kubeadmutil.CheckErr(err) - kubeadmutil.CheckErr(j.Validate()) + kubeadmutil.CheckErr(j.Validate(cmd)) kubeadmutil.CheckErr(j.Run(out)) }, } @@ -166,7 +166,10 @@ func NewJoin(cfgPath string, args []string, cfg *kubeadmapi.NodeConfiguration, s return &Join{cfg: cfg}, nil } -func (j *Join) Validate() error { +func (j *Join) Validate(cmd *cobra.Command) error { + if err := validation.ValidateMixedArguments(cmd.PersistentFlags()); err != nil { + return err + } return validation.ValidateNodeConfiguration(j.cfg).ToAggregate() } diff --git a/cmd/kubeadm/test/cmd/init_test.go b/cmd/kubeadm/test/cmd/init_test.go index be6a8c3e832..9ce3b95daac 100644 --- a/cmd/kubeadm/test/cmd/init_test.go +++ b/cmd/kubeadm/test/cmd/init_test.go @@ -137,3 +137,31 @@ func TestCmdInitAPIPort(t *testing.T) { kubeadmReset() } } + +func TestCmdInitArgsMixed(t *testing.T) { + if *kubeadmCmdSkip { + t.Log("kubeadm cmd tests being skipped") + t.Skip() + } + + var initTest = []struct { + args string + expected bool + }{ + {"--api-port=1000 --config=/etc/kubernets/kubeadm.config", false}, + } + + for _, rt := range initTest { + _, _, actual := RunCmd(*kubeadmPath, "init", rt.args, "--skip-preflight-checks") + if (actual == nil) != rt.expected { + t.Errorf( + "failed CmdInitArgsMixed running 'kubeadm init %s' with an error: %v\n\texpected: %t\n\t actual: %t", + rt.args, + actual, + rt.expected, + (actual == nil), + ) + } + kubeadmReset() + } +} diff --git a/cmd/kubeadm/test/cmd/join_test.go b/cmd/kubeadm/test/cmd/join_test.go index 5e82b2accb8..5d4214f8bbe 100644 --- a/cmd/kubeadm/test/cmd/join_test.go +++ b/cmd/kubeadm/test/cmd/join_test.go @@ -191,3 +191,31 @@ func TestCmdJoinBadArgs(t *testing.T) { kubeadmReset() } } + +func TestCmdJoinArgsMixed(t *testing.T) { + if *kubeadmCmdSkip { + t.Log("kubeadm cmd tests being skipped") + t.Skip() + } + + var initTest = []struct { + args string + expected bool + }{ + {"--discovery-token=abcdef.1234567890abcdef --config=/etc/kubernets/kubeadm.config", false}, + } + + for _, rt := range initTest { + _, _, actual := RunCmd(*kubeadmPath, "join", rt.args, "--skip-preflight-checks") + if (actual == nil) != rt.expected { + t.Errorf( + "failed CmdJoinArgsMixed running 'kubeadm join %s' with an error: %v\n\texpected: %t\n\t actual: %t", + rt.args, + actual, + rt.expected, + (actual == nil), + ) + } + kubeadmReset() + } +} From fe4afa8643153b30a559b7ccfbbb9f0ab6bf836a Mon Sep 17 00:00:00 2001 From: xilabao Date: Fri, 19 May 2017 17:47:07 +0800 Subject: [PATCH 008/448] allow output patch string in edit command --- hack/make-rules/test-cmd-util.sh | 2 +- hack/verify-flags/known-flags.txt | 1 + pkg/kubectl/cmd/edit.go | 1 + pkg/kubectl/cmd/edit_test.go | 4 ++ .../edit/testcase-edit-output-patch/0.request | 0 .../testcase-edit-output-patch/0.response | 38 +++++++++++++++++++ .../edit/testcase-edit-output-patch/1.edited | 32 ++++++++++++++++ .../testcase-edit-output-patch/1.original | 31 +++++++++++++++ .../edit/testcase-edit-output-patch/2.request | 10 +++++ .../testcase-edit-output-patch/2.response | 38 +++++++++++++++++++ .../edit/testcase-edit-output-patch/test.yaml | 32 ++++++++++++++++ pkg/kubectl/cmd/util/editor/editoptions.go | 9 +++++ 12 files changed, 197 insertions(+), 1 deletion(-) create mode 100755 pkg/kubectl/cmd/testdata/edit/testcase-edit-output-patch/0.request create mode 100755 pkg/kubectl/cmd/testdata/edit/testcase-edit-output-patch/0.response create mode 100755 pkg/kubectl/cmd/testdata/edit/testcase-edit-output-patch/1.edited create mode 100755 pkg/kubectl/cmd/testdata/edit/testcase-edit-output-patch/1.original create mode 100755 pkg/kubectl/cmd/testdata/edit/testcase-edit-output-patch/2.request create mode 100755 pkg/kubectl/cmd/testdata/edit/testcase-edit-output-patch/2.response create mode 100644 pkg/kubectl/cmd/testdata/edit/testcase-edit-output-patch/test.yaml diff --git a/hack/make-rules/test-cmd-util.sh b/hack/make-rules/test-cmd-util.sh index 234d9aa02fa..7bb678d56f7 100644 --- a/hack/make-rules/test-cmd-util.sh +++ b/hack/make-rules/test-cmd-util.sh @@ -731,7 +731,7 @@ __EOF__ 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:' - EDITOR=/tmp/tmp-editor.sh kubectl edit "${kube_flags[@]}" pods/valid-pod + [[ "$(EDITOR=/tmp/tmp-editor.sh kubectl edit "${kube_flags[@]}" pods/valid-pod --output-patch=true | grep Patch:)" ]] # Post-condition: valid-pod POD has image gcr.io/google_containers/serve_hostname kube::test::get_object_assert pods "{{range.items}}{{$image_field}}:{{end}}" 'gcr.io/google_containers/serve_hostname:' # cleaning diff --git a/hack/verify-flags/known-flags.txt b/hack/verify-flags/known-flags.txt index 6a78067ff41..8889fb1b6f9 100644 --- a/hack/verify-flags/known-flags.txt +++ b/hack/verify-flags/known-flags.txt @@ -520,6 +520,7 @@ output-base output-directory output-file-base output-package +output-patch output-print-type output-version out-version diff --git a/pkg/kubectl/cmd/edit.go b/pkg/kubectl/cmd/edit.go index fecb026fa30..e4728b60746 100644 --- a/pkg/kubectl/cmd/edit.go +++ b/pkg/kubectl/cmd/edit.go @@ -107,6 +107,7 @@ func NewCmdEdit(f cmdutil.Factory, out, errOut io.Writer) *cobra.Command { 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", gruntime.GOOS == "windows", "Use Windows line-endings (default Unix line-endings)") cmdutil.AddApplyAnnotationVarFlags(cmd, &options.ApplyAnnotation) diff --git a/pkg/kubectl/cmd/edit_test.go b/pkg/kubectl/cmd/edit_test.go index dd5c7b217b0..9ed51efa41b 100644 --- a/pkg/kubectl/cmd/edit_test.go +++ b/pkg/kubectl/cmd/edit_test.go @@ -49,6 +49,7 @@ type EditTestCase struct { Args []string `yaml:"args"` Filename string `yaml:"filename"` Output string `yaml:"outputFormat"` + OutputPatch string `yaml:"outputPatch"` SaveConfig string `yaml:"saveConfig"` Namespace string `yaml:"namespace"` ExpectedStdout []string `yaml:"expectedStdout"` @@ -248,6 +249,9 @@ func TestEdit(t *testing.T) { if len(testcase.Output) > 0 { cmd.Flags().Set("output", testcase.Output) } + if len(testcase.OutputPatch) > 0 { + cmd.Flags().Set("output-patch", testcase.OutputPatch) + } if len(testcase.SaveConfig) > 0 { cmd.Flags().Set("save-config", testcase.SaveConfig) } diff --git a/pkg/kubectl/cmd/testdata/edit/testcase-edit-output-patch/0.request b/pkg/kubectl/cmd/testdata/edit/testcase-edit-output-patch/0.request new file mode 100755 index 00000000000..e69de29bb2d diff --git a/pkg/kubectl/cmd/testdata/edit/testcase-edit-output-patch/0.response b/pkg/kubectl/cmd/testdata/edit/testcase-edit-output-patch/0.response new file mode 100755 index 00000000000..9d4d9c7750a --- /dev/null +++ b/pkg/kubectl/cmd/testdata/edit/testcase-edit-output-patch/0.response @@ -0,0 +1,38 @@ +{ + "apiVersion": "v1", + "kind": "Service", + "metadata": { + "annotations": { + "kubectl.kubernetes.io/last-applied-configuration": "{\"kind\":\"Service\",\"apiVersion\":\"v1\",\"metadata\":{\"name\":\"svc1\",\"creationTimestamp\":null,\"labels\":{\"app\":\"svc1\"}},\"spec\":{\"ports\":[{\"name\":\"80\",\"protocol\":\"TCP\",\"port\":80,\"targetPort\":80}],\"selector\":{\"app\":\"svc1\"},\"type\":\"ClusterIP\"},\"status\":{\"loadBalancer\":{}}}\n" + }, + "creationTimestamp": "2017-02-27T19:40:53Z", + "labels": { + "app": "svc1" + }, + "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": {} + } +} + diff --git a/pkg/kubectl/cmd/testdata/edit/testcase-edit-output-patch/1.edited b/pkg/kubectl/cmd/testdata/edit/testcase-edit-output-patch/1.edited new file mode 100755 index 00000000000..cce0483ddab --- /dev/null +++ b/pkg/kubectl/cmd/testdata/edit/testcase-edit-output-patch/1.edited @@ -0,0 +1,32 @@ +# Please edit the object below. Lines beginning with a '#' will be ignored, +# and an empty file will abort the edit. If an error occurs while saving this file will be +# reopened with the relevant failures. +# +apiVersion: v1 +kind: Service +metadata: + annotations: + kubectl.kubernetes.io/last-applied-configuration: | + {"kind":"Service","apiVersion":"v1","metadata":{"name":"svc1","creationTimestamp":null,"labels":{"app":"svc1"}},"spec":{"ports":[{"name":"80","protocol":"TCP","port":80,"targetPort":80}],"selector":{"app":"svc1"},"type":"ClusterIP"},"status":{"loadBalancer":{}}} + 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: {} diff --git a/pkg/kubectl/cmd/testdata/edit/testcase-edit-output-patch/1.original b/pkg/kubectl/cmd/testdata/edit/testcase-edit-output-patch/1.original new file mode 100755 index 00000000000..1748e03ca75 --- /dev/null +++ b/pkg/kubectl/cmd/testdata/edit/testcase-edit-output-patch/1.original @@ -0,0 +1,31 @@ +# Please edit the object below. Lines beginning with a '#' will be ignored, +# and an empty file will abort the edit. If an error occurs while saving this file will be +# reopened with the relevant failures. +# +apiVersion: v1 +kind: Service +metadata: + annotations: + kubectl.kubernetes.io/last-applied-configuration: | + {"kind":"Service","apiVersion":"v1","metadata":{"name":"svc1","creationTimestamp":null,"labels":{"app":"svc1"}},"spec":{"ports":[{"name":"80","protocol":"TCP","port":80,"targetPort":80}],"selector":{"app":"svc1"},"type":"ClusterIP"},"status":{"loadBalancer":{}}} + creationTimestamp: 2017-02-27T19:40:53Z + labels: + app: svc1 + 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: {} diff --git a/pkg/kubectl/cmd/testdata/edit/testcase-edit-output-patch/2.request b/pkg/kubectl/cmd/testdata/edit/testcase-edit-output-patch/2.request new file mode 100755 index 00000000000..b26622634f6 --- /dev/null +++ b/pkg/kubectl/cmd/testdata/edit/testcase-edit-output-patch/2.request @@ -0,0 +1,10 @@ +{ + "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" + } + } +} \ No newline at end of file diff --git a/pkg/kubectl/cmd/testdata/edit/testcase-edit-output-patch/2.response b/pkg/kubectl/cmd/testdata/edit/testcase-edit-output-patch/2.response new file mode 100755 index 00000000000..cf658cb8d1c --- /dev/null +++ b/pkg/kubectl/cmd/testdata/edit/testcase-edit-output-patch/2.response @@ -0,0 +1,38 @@ +{ + "kind": "Service", + "apiVersion": "v1", + "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" + }, + "name": "svc1", + "namespace": "edit-test", + "selfLink": "/api/v1/namespaces/edit-test/services/svc1", + "uid": "a6c11186-fd24-11e6-b53c-480fcf4a5275", + "resourceVersion":"1045", + "creationTimestamp":"2017-02-27T19:40:53Z", + "labels": { + "app": "svc1", + "new-label": "new-value" + } + }, + "spec": { + "clusterIP": "10.0.0.204", + "ports": [ + { + "name": "80", + "port": 80, + "protocol": "TCP", + "targetPort": 80 + } + ], + "selector": { + "app": "svc1" + }, + "sessionAffinity": "None", + "type": "ClusterIP" + }, + "status": { + "loadBalancer": {} + } +} diff --git a/pkg/kubectl/cmd/testdata/edit/testcase-edit-output-patch/test.yaml b/pkg/kubectl/cmd/testdata/edit/testcase-edit-output-patch/test.yaml new file mode 100644 index 00000000000..0b0f92f9754 --- /dev/null +++ b/pkg/kubectl/cmd/testdata/edit/testcase-edit-output-patch/test.yaml @@ -0,0 +1,32 @@ +# kubectl create namespace edit-test +# kubectl create service clusterip svc1 --tcp 80 --namespace=edit-test --save-config +# kubectl edit service svc1 --namespace=edit-test --save-config=true --output-patch=true +description: edit with flag --output-patch=true should output the patch +mode: edit +args: +- service +- svc1 +saveConfig: "true" +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 +expectedExitCode: 0 +steps: +- type: request + expectedMethod: GET + expectedPath: /api/v1/namespaces/edit-test/services/svc1 + expectedInput: 0.request + resultingStatusCode: 200 + resultingOutput: 0.response +- type: edit + expectedInput: 1.original + resultingOutput: 1.edited +- type: request + expectedMethod: PATCH + expectedPath: /api/v1/namespaces/edit-test/services/svc1 + expectedContentType: application/strategic-merge-patch+json + expectedInput: 2.request + resultingStatusCode: 200 + resultingOutput: 2.response diff --git a/pkg/kubectl/cmd/util/editor/editoptions.go b/pkg/kubectl/cmd/util/editor/editoptions.go index 3a5e649bcde..9d31388aa6e 100644 --- a/pkg/kubectl/cmd/util/editor/editoptions.go +++ b/pkg/kubectl/cmd/util/editor/editoptions.go @@ -52,6 +52,7 @@ type EditOptions struct { resource.FilenameOptions Output string + OutputPatch bool WindowsLineEndings bool cmdutil.ValidateOptions @@ -95,6 +96,10 @@ func (o *EditOptions) Complete(f cmdutil.Factory, out, errOut io.Writer, args [] } o.editPrinterOptions = getPrinter(o.Output) + if o.OutputPatch && o.EditMode != NormalEditMode { + return fmt.Errorf("the edit mode doesn't support output the patch") + } + cmdNamespace, enforceNamespace, err := f.DefaultNamespace() if err != nil { return err @@ -452,6 +457,10 @@ func (o *EditOptions) visitToPatch( } } + if o.OutputPatch { + fmt.Fprintf(o.Out, "Patch: %s\n", string(patch)) + } + patched, err := resource.NewHelper(info.Client, info.Mapping).Patch(info.Namespace, info.Name, patchType, patch) if err != nil { fmt.Fprintln(o.ErrOut, results.addError(err, info)) From 340e8b18527a0dc16cb5bae65974f773c6fce667 Mon Sep 17 00:00:00 2001 From: nikhiljindal Date: Thu, 1 Jun 2017 13:19:50 -0700 Subject: [PATCH 009/448] Deleting ServiceReaper --- pkg/kubectl/stop.go | 17 -------------- pkg/kubectl/stop_test.go | 49 ++++++++++++---------------------------- 2 files changed, 14 insertions(+), 52 deletions(-) diff --git a/pkg/kubectl/stop.go b/pkg/kubectl/stop.go index ccae1ce6684..2203362ab5a 100644 --- a/pkg/kubectl/stop.go +++ b/pkg/kubectl/stop.go @@ -82,9 +82,6 @@ func ReaperFor(kind schema.GroupKind, c internalclientset.Interface) (Reaper, er case api.Kind("Pod"): return &PodReaper{c.Core()}, nil - case api.Kind("Service"): - return &ServiceReaper{c.Core()}, nil - case batch.Kind("Job"): return &JobReaper{c.Batch(), c.Core(), Interval, Timeout}, nil @@ -127,9 +124,6 @@ type DeploymentReaper struct { type PodReaper struct { client coreclient.PodsGetter } -type ServiceReaper struct { - client coreclient.ServicesGetter -} type StatefulSetReaper struct { client appsclient.StatefulSetsGetter podClient coreclient.PodsGetter @@ -522,14 +516,3 @@ func (reaper *PodReaper) Stop(namespace, name string, timeout time.Duration, gra } return pods.Delete(name, gracePeriod) } - -func (reaper *ServiceReaper) Stop(namespace, name string, timeout time.Duration, gracePeriod *metav1.DeleteOptions) error { - services := reaper.client.Services(namespace) - _, err := services.Get(name, metav1.GetOptions{}) - if err != nil { - return err - } - falseVar := false - deleteOptions := &metav1.DeleteOptions{OrphanDependents: &falseVar} - return services.Delete(name, deleteOptions) -} diff --git a/pkg/kubectl/stop_test.go b/pkg/kubectl/stop_test.go index dd8752903e7..0d2f5ea9daa 100644 --- a/pkg/kubectl/stop_test.go +++ b/pkg/kubectl/stop_test.go @@ -558,26 +558,26 @@ func (c *noSuchPod) Get(name string, options metav1.GetOptions) (*api.Pod, error return nil, fmt.Errorf("%s does not exist", name) } -type noDeleteService struct { - coreclient.ServiceInterface +type noDeletePod struct { + coreclient.PodInterface } -func (c *noDeleteService) Delete(service string, o *metav1.DeleteOptions) error { +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, noDeleteService bool + noSuchPod, noDeletePod bool } func (c *reaperFake) Core() coreclient.CoreInterface { - return &reaperCoreFake{c.Clientset.Core(), c.noSuchPod, c.noDeleteService} + return &reaperCoreFake{c.Clientset.Core(), c.noSuchPod, c.noDeletePod} } type reaperCoreFake struct { coreclient.CoreInterface - noSuchPod, noDeleteService bool + noSuchPod, noDeletePod bool } func (c *reaperCoreFake) Pods(namespace string) coreclient.PodInterface { @@ -585,25 +585,16 @@ func (c *reaperCoreFake) Pods(namespace string) coreclient.PodInterface { if c.noSuchPod { return &noSuchPod{pods} } - return pods -} - -func (c *reaperCoreFake) Services(namespace string) coreclient.ServiceInterface { - services := c.CoreInterface.Services(namespace) - if c.noDeleteService { - return &noDeleteService{services} + if c.noDeletePod { + return &noDeletePod{pods} } - return services + return pods } func pod() *api.Pod { return &api.Pod{ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceDefault, Name: "foo"}} } -func service() *api.Service { - return &api.Service{ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceDefault, Name: "foo"}} -} - func TestSimpleStop(t *testing.T) { tests := []struct { fake *reaperFake @@ -624,18 +615,6 @@ func TestSimpleStop(t *testing.T) { expectError: false, test: "stop pod succeeds", }, - { - fake: &reaperFake{ - Clientset: fake.NewSimpleClientset(service()), - }, - kind: api.Kind("Service"), - actions: []testcore.Action{ - testcore.NewGetAction(api.Resource("services").WithVersion(""), metav1.NamespaceDefault, "foo"), - testcore.NewDeleteAction(api.Resource("services").WithVersion(""), metav1.NamespaceDefault, "foo"), - }, - expectError: false, - test: "stop service succeeds", - }, { fake: &reaperFake{ Clientset: fake.NewSimpleClientset(), @@ -648,15 +627,15 @@ func TestSimpleStop(t *testing.T) { }, { fake: &reaperFake{ - Clientset: fake.NewSimpleClientset(service()), - noDeleteService: true, + Clientset: fake.NewSimpleClientset(pod()), + noDeletePod: true, }, - kind: api.Kind("Service"), + kind: api.Kind("Pod"), actions: []testcore.Action{ - testcore.NewGetAction(api.Resource("services").WithVersion(""), metav1.NamespaceDefault, "foo"), + testcore.NewGetAction(api.Resource("pods").WithVersion(""), metav1.NamespaceDefault, "foo"), }, expectError: true, - test: "stop service fails, can't delete", + test: "stop pod fails, can't delete", }, } for _, test := range tests { From 02af4b31a6784d5fe8c5f785a9a470a4e930c22b Mon Sep 17 00:00:00 2001 From: zhangxiaoyu-zidif Date: Fri, 2 Jun 2017 17:35:33 +0800 Subject: [PATCH 010/448] Use t.Fatalf instead --- pkg/kubectl/cmd/run_test.go | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/pkg/kubectl/cmd/run_test.go b/pkg/kubectl/cmd/run_test.go index 7f1eed8eee6..c493b932dd0 100644 --- a/pkg/kubectl/cmd/run_test.go +++ b/pkg/kubectl/cmd/run_test.go @@ -297,14 +297,12 @@ func TestGenerateService(t *testing.T) { body := objBody(codec, &test.service) data, err := ioutil.ReadAll(req.Body) if err != nil { - t.Errorf("unexpected error: %v", err) - t.FailNow() + t.Fatalf("unexpected error: %v", err) } defer req.Body.Close() svc := &api.Service{} if err := runtime.DecodeInto(codec, data, svc); err != nil { - t.Errorf("unexpected error: %v", err) - t.FailNow() + t.Fatalf("unexpected error: %v", err) } // Copy things that are defaulted by the system test.service.Annotations = svc.Annotations From 6bc2d4257bcd784c7d0f7d806bc7f1c75a694053 Mon Sep 17 00:00:00 2001 From: zhengjiajin <393926893@qq.com> Date: Fri, 2 Jun 2017 18:33:05 +0800 Subject: [PATCH 011/448] fix some err message --- .../pkg/federation-controller/service/servicecontroller.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/federation/pkg/federation-controller/service/servicecontroller.go b/federation/pkg/federation-controller/service/servicecontroller.go index 2e89f150951..f89446221ec 100644 --- a/federation/pkg/federation-controller/service/servicecontroller.go +++ b/federation/pkg/federation-controller/service/servicecontroller.go @@ -417,7 +417,7 @@ func (s *ServiceController) reconcileService(key string) reconciliationStatus { namespace, name, err := cache.SplitMetaNamespaceKey(key) if err != nil { - runtime.HandleError(fmt.Errorf("Invalid key %q recieved, unable to split key to namespace and name, err: %v", key, err)) + runtime.HandleError(fmt.Errorf("Invalid key %q received, unable to split key to namespace and name, err: %v", key, err)) return statusNonRecoverableError } @@ -440,7 +440,7 @@ func (s *ServiceController) reconcileService(key string) reconciliationStatus { } fedService, ok := fedServiceObj.(*v1.Service) if err != nil || !ok { - runtime.HandleError(fmt.Errorf("Unknown obj recieved from store: %#v, %v", fedServiceObj, err)) + runtime.HandleError(fmt.Errorf("Unknown obj received from store: %#v, %v", fedServiceObj, err)) return statusNonRecoverableError } From fb4fc7d7d108a94053671160894011e84f821742 Mon Sep 17 00:00:00 2001 From: Shiyang Wang Date: Tue, 18 Apr 2017 13:09:13 +0800 Subject: [PATCH 012/448] fix JSONPath parser will not filter strings containing parentheses --- .../k8s.io/client-go/util/jsonpath/parser.go | 92 +++++++++++++++++-- .../client-go/util/jsonpath/parser_test.go | 10 ++ 2 files changed, 93 insertions(+), 9 deletions(-) diff --git a/staging/src/k8s.io/client-go/util/jsonpath/parser.go b/staging/src/k8s.io/client-go/util/jsonpath/parser.go index 39782afc6ea..2f02de1a315 100644 --- a/staging/src/k8s.io/client-go/util/jsonpath/parser.go +++ b/staging/src/k8s.io/client-go/util/jsonpath/parser.go @@ -17,6 +17,7 @@ limitations under the License. package jsonpath import ( + "errors" "fmt" "regexp" "strconv" @@ -42,6 +43,8 @@ type Parser struct { width int } +var ErrSyntax = errors.New("invalid syntax") + // Parse parsed the given text and return a node Parser. // If an error is encountered, parsing stops and an empty // Parser is returned with the error @@ -159,8 +162,8 @@ func (p *Parser) parseInsideAction(cur *ListNode) error { p.consumeText() case r == '[': return p.parseArray(cur) - case r == '"': - return p.parseQuote(cur) + case r == '"' || r == '\'': + return p.parseQuote(cur, r) case r == '.': return p.parseField(cur) case r == '+' || r == '-' || unicode.IsDigit(r): @@ -334,13 +337,33 @@ Loop: func (p *Parser) parseFilter(cur *ListNode) error { p.pos += len("[?(") p.consumeText() + begin := false + end := false + var pair rune + Loop: for { - switch p.next() { + r := p.next() + switch r { case eof, '\n': return fmt.Errorf("unterminated filter") + case '"', '\'': + if begin == false { + //save the paired rune + begin = true + pair = r + continue + } + //only add when met paired rune + if p.input[p.pos-2] != '\\' && r == pair { + end = true + } case ')': - break Loop + //in rightParser below quotes only appear zero or once + //and must be paired at the beginning and end + if begin == end { + break Loop + } } } if p.next() != ']' { @@ -370,19 +393,22 @@ Loop: return p.parseInsideAction(cur) } -// parseQuote unquotes string inside double quote -func (p *Parser) parseQuote(cur *ListNode) error { +// parseQuote unquotes string inside double or single quote +func (p *Parser) parseQuote(cur *ListNode, end rune) error { Loop: for { switch p.next() { case eof, '\n': return fmt.Errorf("unterminated quoted string") - case '"': - break Loop + case end: + //if it's not escape break the Loop + if p.input[p.pos-2] != '\\' { + break Loop + } } } value := p.consumeText() - s, err := strconv.Unquote(value) + s, err := UnquoteExtend(value) if err != nil { return fmt.Errorf("unquote string %s error %v", value, err) } @@ -447,3 +473,51 @@ func isAlphaNumeric(r rune) bool { func isBool(s string) bool { return s == "true" || s == "false" } + +//UnquoteExtend is almost same as strconv.Unquote(), but it support parse single quotes as a string +func UnquoteExtend(s string) (string, error) { + n := len(s) + if n < 2 { + return "", ErrSyntax + } + quote := s[0] + if quote != s[n-1] { + return "", ErrSyntax + } + s = s[1 : n-1] + + if quote != '"' && quote != '\'' { + return "", ErrSyntax + } + + // Is it trivial? Avoid allocation. + if !contains(s, '\\') && !contains(s, quote) { + return s, nil + } + + var runeTmp [utf8.UTFMax]byte + buf := make([]byte, 0, 3*len(s)/2) // Try to avoid more allocations. + for len(s) > 0 { + c, multibyte, ss, err := strconv.UnquoteChar(s, quote) + if err != nil { + return "", err + } + s = ss + if c < utf8.RuneSelf || !multibyte { + buf = append(buf, byte(c)) + } else { + n := utf8.EncodeRune(runeTmp[:], c) + buf = append(buf, runeTmp[:n]...) + } + } + return string(buf), nil +} + +func contains(s string, c byte) bool { + for i := 0; i < len(s); i++ { + if s[i] == c { + return true + } + } + return false +} diff --git a/staging/src/k8s.io/client-go/util/jsonpath/parser_test.go b/staging/src/k8s.io/client-go/util/jsonpath/parser_test.go index 48dd4f610ae..7abc5ae553a 100644 --- a/staging/src/k8s.io/client-go/util/jsonpath/parser_test.go +++ b/staging/src/k8s.io/client-go/util/jsonpath/parser_test.go @@ -61,6 +61,16 @@ var parserTests = []parserTest{ newList(), newIdentifier("end"), }, false}, {"malformat input", `{\\\}`, []Node{}, true}, + {"paired parentheses in quotes", `{[?(@.status.nodeInfo.osImage == "()")]}`, + []Node{newList(), newFilter(newList(), newList(), "=="), newList(), newField("status"), newField("nodeInfo"), newField("osImage"), newList(), newText("()")}, false}, + {"paired parentheses in double quotes and with double quotes escape", `{[?(@.status.nodeInfo.osImage == "(\"\")")]}`, + []Node{newList(), newFilter(newList(), newList(), "=="), newList(), newField("status"), newField("nodeInfo"), newField("osImage"), newList(), newText("(\"\")")}, false}, + {"unregular parentheses in double quotes", `{[?(@.test == "())(")]}`, + []Node{newList(), newFilter(newList(), newList(), "=="), newList(), newField("test"), newList(), newText("())(")}, false}, + {"plain text in single quotes", `{[?(@.status.nodeInfo.osImage == 'Linux')]}`, + []Node{newList(), newFilter(newList(), newList(), "=="), newList(), newField("status"), newField("nodeInfo"), newField("osImage"), newList(), newText("Linux")}, false}, + {"test filter suffix", `{[?(@.status.nodeInfo.osImage == "{[()]}")]}`, + []Node{newList(), newFilter(newList(), newList(), "=="), newList(), newField("status"), newField("nodeInfo"), newField("osImage"), newList(), newText("{[()]}")}, false}, } func collectNode(nodes []Node, cur Node) []Node { From 87f877962468a83efe4f46ec01582d8703a4e899 Mon Sep 17 00:00:00 2001 From: Shiyang Wang Date: Sat, 3 Jun 2017 10:48:28 +0800 Subject: [PATCH 013/448] add more unit test --- staging/src/k8s.io/client-go/util/jsonpath/parser_test.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/staging/src/k8s.io/client-go/util/jsonpath/parser_test.go b/staging/src/k8s.io/client-go/util/jsonpath/parser_test.go index 7abc5ae553a..4f71a60ac7b 100644 --- a/staging/src/k8s.io/client-go/util/jsonpath/parser_test.go +++ b/staging/src/k8s.io/client-go/util/jsonpath/parser_test.go @@ -71,6 +71,12 @@ var parserTests = []parserTest{ []Node{newList(), newFilter(newList(), newList(), "=="), newList(), newField("status"), newField("nodeInfo"), newField("osImage"), newList(), newText("Linux")}, false}, {"test filter suffix", `{[?(@.status.nodeInfo.osImage == "{[()]}")]}`, []Node{newList(), newFilter(newList(), newList(), "=="), newList(), newField("status"), newField("nodeInfo"), newField("osImage"), newList(), newText("{[()]}")}, false}, + {"double inside single", `{[?(@.status.nodeInfo.osImage == "''")]}`, + []Node{newList(), newFilter(newList(), newList(), "=="), newList(), newField("status"), newField("nodeInfo"), newField("osImage"), newList(), newText("''")}, false}, + {"single inside double", `{[?(@.status.nodeInfo.osImage == '""')]}`, + []Node{newList(), newFilter(newList(), newList(), "=="), newList(), newField("status"), newField("nodeInfo"), newField("osImage"), newList(), newText("\"\"")}, false}, + {"single containing escaped single", `{[?(@.status.nodeInfo.osImage == '\\\'')]}`, + []Node{newList(), newFilter(newList(), newList(), "=="), newList(), newField("status"), newField("nodeInfo"), newField("osImage"), newList(), newText("\\'")}, false}, } func collectNode(nodes []Node, cur Node) []Node { From 750d0d8730e6c2883146528241c1a1e209fb6b76 Mon Sep 17 00:00:00 2001 From: Xing Zhou Date: Mon, 5 Jun 2017 10:47:59 +0800 Subject: [PATCH 014/448] Fixed a comment typo --- pkg/controller/volume/attachdetach/reconciler/reconciler.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/controller/volume/attachdetach/reconciler/reconciler.go b/pkg/controller/volume/attachdetach/reconciler/reconciler.go index 3b56bfcfa1b..ae3326eee7d 100644 --- a/pkg/controller/volume/attachdetach/reconciler/reconciler.go +++ b/pkg/controller/volume/attachdetach/reconciler/reconciler.go @@ -35,7 +35,7 @@ import ( "k8s.io/kubernetes/pkg/volume/util/operationexecutor" ) -// Reconciler runs a periodic loop to reconcile the desired state of the with +// Reconciler runs a periodic loop to reconcile the desired state of the world with // the actual state of the world by triggering attach detach operations. // Note: This is distinct from the Reconciler implemented by the kubelet volume // manager. This reconciles state for the attach/detach controller. That From ec12e6cc9d9f0a760906c70affd6d881d26a74b0 Mon Sep 17 00:00:00 2001 From: Slava Semushin Date: Mon, 5 Jun 2017 17:07:33 +0200 Subject: [PATCH 015/448] Improve error reporting when flex driver has failed to initialize. --- pkg/volume/flexvolume/driver-call.go | 4 ++-- pkg/volume/plugins.go | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pkg/volume/flexvolume/driver-call.go b/pkg/volume/flexvolume/driver-call.go index 3866e535c48..0c6ac4fb2c2 100644 --- a/pkg/volume/flexvolume/driver-call.go +++ b/pkg/volume/flexvolume/driver-call.go @@ -143,7 +143,7 @@ func (dc *DriverCall) Run() (*DriverStatus, error) { if isCmdNotSupportedErr(err) { dc.plugin.unsupported(dc.Command) } else { - glog.Warningf("FlexVolume: driver call failed: executable: %s, args: %s, error: %s, output: %s", execPath, dc.args, execErr.Error(), output) + glog.Warningf("FlexVolume: driver call failed: executable: %s, args: %s, error: %s, output: %q", execPath, dc.args, execErr.Error(), output) } return nil, err } @@ -215,7 +215,7 @@ func isCmdNotSupportedErr(err error) bool { func handleCmdResponse(cmd string, output []byte) (*DriverStatus, error) { var status DriverStatus if err := json.Unmarshal(output, &status); err != nil { - glog.Errorf("Failed to unmarshal output for command: %s, output: %s, error: %s", cmd, string(output), err.Error()) + glog.Errorf("Failed to unmarshal output for command: %s, output: %q, error: %s", cmd, string(output), err.Error()) return nil, err } else if status.Status == StatusNotSupported { glog.V(5).Infof("%s command is not supported by the driver", cmd) diff --git a/pkg/volume/plugins.go b/pkg/volume/plugins.go index 41721d1eeaf..611d9b55e0a 100644 --- a/pkg/volume/plugins.go +++ b/pkg/volume/plugins.go @@ -362,7 +362,7 @@ func (pm *VolumePluginMgr) InitPlugins(plugins []VolumePlugin, host VolumeHost) } err := plugin.Init(host) if err != nil { - glog.Errorf("Failed to load volume plugin %s, error: %s", plugin, err.Error()) + glog.Errorf("Failed to load volume plugin %s, error: %s", name, err.Error()) allErrs = append(allErrs, err) continue } From 92d17069033d488925bd65b313438ce6ff286066 Mon Sep 17 00:00:00 2001 From: zhengjiajin <393926893@qq.com> Date: Tue, 6 Jun 2017 20:33:38 +0800 Subject: [PATCH 016/448] controller-manager: fix horizontal-pod-autoscaler-use-rest-clients flag help info --- cmd/kube-controller-manager/app/options/options.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/kube-controller-manager/app/options/options.go b/cmd/kube-controller-manager/app/options/options.go index 7d81d8e276d..5ff3ff1c52b 100644 --- a/cmd/kube-controller-manager/app/options/options.go +++ b/cmd/kube-controller-manager/app/options/options.go @@ -225,7 +225,7 @@ func (s *CMServer) AddFlags(fs *pflag.FlagSet, allControllers []string, disabled fs.BoolVar(&s.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.ReconcilerSyncLoopPeriod.Duration, "attach-detach-reconcile-sync-period", s.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.EnableTaintManager, "enable-taint-manager", s.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.HorizontalPodAutoscalerUseRESTClients, "horizontal-pod-autoscaler-use-rest-clients", s.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 horizonal pod autoscaler.") + fs.BoolVar(&s.HorizontalPodAutoscalerUseRESTClients, "horizontal-pod-autoscaler-use-rest-clients", s.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.") leaderelection.BindFlags(&s.LeaderElection, fs) From 5a99edaeb08df78ccd7d008d7ea03d7d3e741e56 Mon Sep 17 00:00:00 2001 From: Bo Ingram Date: Sun, 4 Jun 2017 20:04:13 -0600 Subject: [PATCH 017/448] deletePod handler in the deployment controller shouldn't set owner refs --- .../deployment/deployment_controller.go | 2 +- .../deployment/deployment_controller_test.go | 76 ++++++++++++++++++- .../deployment/util/deployment_util.go | 14 ++-- 3 files changed, 81 insertions(+), 11 deletions(-) diff --git a/pkg/controller/deployment/deployment_controller.go b/pkg/controller/deployment/deployment_controller.go index f5963acba3d..9becf2255b6 100644 --- a/pkg/controller/deployment/deployment_controller.go +++ b/pkg/controller/deployment/deployment_controller.go @@ -356,7 +356,7 @@ 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 { // Sync if this Deployment now has no more Pods. - rsList, err := dc.getReplicaSetsForDeployment(d) + rsList, err := util.ListReplicaSets(d, util.RsListFromClient(dc.client)) if err != nil { return } diff --git a/pkg/controller/deployment/deployment_controller_test.go b/pkg/controller/deployment/deployment_controller_test.go index a1544c5e82f..53b606007ce 100644 --- a/pkg/controller/deployment/deployment_controller_test.go +++ b/pkg/controller/deployment/deployment_controller_test.go @@ -415,11 +415,81 @@ func TestPodDeletionDoesntEnqueueRecreateDeployment(t *testing.T) { foo := newDeployment("foo", 1, nil, nil, nil, map[string]string{"foo": "bar"}) foo.Spec.Strategy.Type = extensions.RecreateDeploymentStrategyType - rs := newReplicaSet(foo, "foo-1", 1) - pod := generatePodFromRS(rs) + rs1 := newReplicaSet(foo, "foo-1", 1) + rs2 := newReplicaSet(foo, "foo-1", 1) + pod1 := generatePodFromRS(rs1) + pod2 := generatePodFromRS(rs2) f.dLister = append(f.dLister, foo) - f.rsLister = append(f.rsLister, rs) + // Let's pretend this is a different pod. The gist is that the pod lister needs to + // return a non-empty list. + f.podLister = append(f.podLister, pod1, pod2) + + c, _ := f.newController() + enqueued := false + c.enqueueDeployment = func(d *extensions.Deployment) { + if d.Name == "foo" { + enqueued = true + } + } + + c.deletePod(pod1) + + if enqueued { + t.Errorf("expected deployment %q not to be queued after pod deletion", foo.Name) + } +} + +// TestPodDeletionPartialReplicaSetOwnershipEnqueueRecreateDeployment ensures that +// the deletion of a pod will requeue a Recreate deployment iff there is no other +// pod returned from the client in the case where a deployment has multiple replica +// sets, some of which have empty owner references. +func TestPodDeletionPartialReplicaSetOwnershipEnqueueRecreateDeployment(t *testing.T) { + f := newFixture(t) + + foo := newDeployment("foo", 1, nil, nil, nil, map[string]string{"foo": "bar"}) + foo.Spec.Strategy.Type = extensions.RecreateDeploymentStrategyType + rs1 := newReplicaSet(foo, "foo-1", 1) + rs2 := newReplicaSet(foo, "foo-2", 2) + rs2.OwnerReferences = nil + pod := generatePodFromRS(rs1) + + f.dLister = append(f.dLister, foo) + f.rsLister = append(f.rsLister, rs1, rs2) + f.objects = append(f.objects, foo, rs1, rs2) + + c, _ := f.newController() + enqueued := false + c.enqueueDeployment = func(d *extensions.Deployment) { + if d.Name == "foo" { + enqueued = true + } + } + + c.deletePod(pod) + + if !enqueued { + t.Errorf("expected deployment %q to be queued after pod deletion", foo.Name) + } +} + +// TestPodDeletionPartialReplicaSetOwnershipDoesntEnqueueRecreateDeployment that the +// deletion of a pod will not requeue a Recreate deployment iff there are other pods +// returned from the client in the case where a deployment has multiple replica sets, +// some of which have empty owner references. +func TestPodDeletionPartialReplicaSetOwnershipDoesntEnqueueRecreateDeployment(t *testing.T) { + f := newFixture(t) + + foo := newDeployment("foo", 1, nil, nil, nil, map[string]string{"foo": "bar"}) + foo.Spec.Strategy.Type = extensions.RecreateDeploymentStrategyType + rs1 := newReplicaSet(foo, "foo-1", 1) + rs2 := newReplicaSet(foo, "foo-2", 2) + rs2.OwnerReferences = nil + pod := generatePodFromRS(rs1) + + f.dLister = append(f.dLister, foo) + f.rsLister = append(f.rsLister, rs1, rs2) + f.objects = append(f.objects, foo, rs1, rs2) // Let's pretend this is a different pod. The gist is that the pod lister needs to // return a non-empty list. f.podLister = append(f.podLister, pod) diff --git a/pkg/controller/deployment/util/deployment_util.go b/pkg/controller/deployment/util/deployment_util.go index ea6ff569a99..b80094388a2 100644 --- a/pkg/controller/deployment/util/deployment_util.go +++ b/pkg/controller/deployment/util/deployment_util.go @@ -489,7 +489,7 @@ func getReplicaSetFraction(rs extensions.ReplicaSet, d extensions.Deployment) in // 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 clientset.Interface) ([]*extensions.ReplicaSet, []*extensions.ReplicaSet, *extensions.ReplicaSet, error) { - rsList, err := ListReplicaSets(deployment, rsListFromClient(c)) + rsList, err := ListReplicaSets(deployment, RsListFromClient(c)) if err != nil { return nil, nil, nil, err } @@ -507,7 +507,7 @@ func GetAllReplicaSets(deployment *extensions.Deployment, c clientset.Interface) // 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 clientset.Interface) ([]*extensions.ReplicaSet, []*extensions.ReplicaSet, error) { - rsList, err := ListReplicaSets(deployment, rsListFromClient(c)) + rsList, err := ListReplicaSets(deployment, RsListFromClient(c)) if err != nil { return nil, nil, err } @@ -517,15 +517,15 @@ func GetOldReplicaSets(deployment *extensions.Deployment, c clientset.Interface) // 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 clientset.Interface) (*extensions.ReplicaSet, error) { - rsList, err := ListReplicaSets(deployment, rsListFromClient(c)) + rsList, err := ListReplicaSets(deployment, RsListFromClient(c)) if err != nil { return nil, err } return FindNewReplicaSet(deployment, rsList) } -// rsListFromClient returns an rsListFunc that wraps the given client. -func rsListFromClient(c clientset.Interface) rsListFunc { +// RsListFromClient returns an rsListFunc that wraps the given client. +func RsListFromClient(c clientset.Interface) RsListFunc { return func(namespace string, options metav1.ListOptions) ([]*extensions.ReplicaSet, error) { rsList, err := c.Extensions().ReplicaSets(namespace).List(options) if err != nil { @@ -547,14 +547,14 @@ func podListFromClient(c clientset.Interface) podListFunc { } // TODO: switch this to full namespacers -type rsListFunc func(string, metav1.ListOptions) ([]*extensions.ReplicaSet, error) +type RsListFunc func(string, metav1.ListOptions) ([]*extensions.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 *extensions.Deployment, getRSList RsListFunc) ([]*extensions.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 From cf8e3ccf1959942342ed0c10f6b43d46beb65e04 Mon Sep 17 00:00:00 2001 From: Cao Shufeng Date: Tue, 6 Jun 2017 19:31:29 +0800 Subject: [PATCH 018/448] Add Validate() function for audit options --- cmd/kube-apiserver/app/options/validation.go | 3 + hack/verify-flags/known-flags.txt | 1 + .../apiserver/pkg/server/options/audit.go | 58 +++++++++++++++---- 3 files changed, 50 insertions(+), 12 deletions(-) diff --git a/cmd/kube-apiserver/app/options/validation.go b/cmd/kube-apiserver/app/options/validation.go index 3a9bbbfea65..fb937bdf7db 100644 --- a/cmd/kube-apiserver/app/options/validation.go +++ b/cmd/kube-apiserver/app/options/validation.go @@ -63,6 +63,9 @@ func (options *ServerRunOptions) Validate() []error { if errs := options.Authentication.Validate(); len(errs) > 0 { errors = append(errors, errs...) } + if errs := options.Audit.Validate(); len(errs) > 0 { + errors = append(errors, errs...) + } if errs := options.InsecureServing.Validate("insecure-port"); len(errs) > 0 { errors = append(errors, errs...) } diff --git a/hack/verify-flags/known-flags.txt b/hack/verify-flags/known-flags.txt index b504324bb95..5264757787c 100644 --- a/hack/verify-flags/known-flags.txt +++ b/hack/verify-flags/known-flags.txt @@ -46,6 +46,7 @@ audit-log-maxage audit-log-maxbackup audit-log-maxsize audit-log-path +audit-policy-file audit-webhook-config-file audit-webhook-mode authentication-kubeconfig diff --git a/staging/src/k8s.io/apiserver/pkg/server/options/audit.go b/staging/src/k8s.io/apiserver/pkg/server/options/audit.go index b5f310af041..d1421e66dd1 100644 --- a/staging/src/k8s.io/apiserver/pkg/server/options/audit.go +++ b/staging/src/k8s.io/apiserver/pkg/server/options/audit.go @@ -81,6 +81,33 @@ func NewAuditOptions() *AuditOptions { } } +// Validate checks invalid config combination +func (o *AuditOptions) Validate() []error { + allErrors := []error{} + + if !advancedAuditingEnabled() { + if len(o.PolicyFile) > 0 { + allErrors = append(allErrors, fmt.Errorf("feature '%s' must be enabled to set option --audit-policy-file", features.AdvancedAuditing)) + } + if len(o.WebhookOptions.ConfigFile) > 0 { + allErrors = append(allErrors, fmt.Errorf("feature '%s' must be enabled to set option --audit-webhook-config-file", features.AdvancedAuditing)) + } + } else { + // check webhook mode + validMode := false + for _, m := range pluginwebhook.AllowedModes { + if m == o.WebhookOptions.Mode { + validMode = true + break + } + } + if !validMode { + allErrors = append(allErrors, fmt.Errorf("invalid audit webhook mode %s, allowed modes are %q", o.WebhookOptions.Mode, strings.Join(pluginwebhook.AllowedModes, ","))) + } + } + return allErrors +} + func (o *AuditOptions) AddFlags(fs *pflag.FlagSet) { fs.StringVar(&o.PolicyFile, "audit-policy-file", o.PolicyFile, "Path to the file that defines the audit policy configuration. Requires the 'AdvancedAuditing' feature gate."+ @@ -91,13 +118,19 @@ func (o *AuditOptions) AddFlags(fs *pflag.FlagSet) { } func (o *AuditOptions) ApplyTo(c *server.Config) error { - // Apply generic options. + // Apply legacy audit options if advanced audit is not enabled. + if !advancedAuditingEnabled() { + return o.LogOptions.legacyApplyTo(c) + } + + // Apply advanced options if advanced audit is enabled. + // 1. Apply generic options. if err := o.applyTo(c); err != nil { return err } - // Apply plugin options. - if err := o.LogOptions.applyTo(c); err != nil { + // 2. Apply plugin options. + if err := o.LogOptions.advancedApplyTo(c); err != nil { return err } if err := o.WebhookOptions.applyTo(c); err != nil { @@ -111,9 +144,6 @@ func (o *AuditOptions) applyTo(c *server.Config) error { return nil } - if !advancedAuditingEnabled() { - return fmt.Errorf("feature '%s' must be enabled to set an audit policy", features.AdvancedAuditing) - } p, err := policy.LoadPolicyFromFile(o.PolicyFile) if err != nil { return fmt.Errorf("loading audit policy file: %v", err) @@ -133,7 +163,7 @@ func (o *AuditLogOptions) AddFlags(fs *pflag.FlagSet) { "The maximum size in megabytes of the audit log file before it gets rotated.") } -func (o *AuditLogOptions) applyTo(c *server.Config) error { +func (o *AuditLogOptions) getWriter() io.Writer { if o.Path == "" { return nil } @@ -147,14 +177,21 @@ func (o *AuditLogOptions) applyTo(c *server.Config) error { MaxSize: o.MaxSize, } } - c.LegacyAuditWriter = w + return w +} - if advancedAuditingEnabled() { +func (o *AuditLogOptions) advancedApplyTo(c *server.Config) error { + if w := o.getWriter(); w != nil { c.AuditBackend = appendBackend(c.AuditBackend, pluginlog.NewBackend(w)) } return nil } +func (o *AuditLogOptions) legacyApplyTo(c *server.Config) error { + c.LegacyAuditWriter = o.getWriter() + return nil +} + func (o *AuditWebhookOptions) AddFlags(fs *pflag.FlagSet) { fs.StringVar(&o.ConfigFile, "audit-webhook-config-file", o.ConfigFile, "Path to a kubeconfig formatted file that defines the audit webhook configuration."+ @@ -170,9 +207,6 @@ func (o *AuditWebhookOptions) applyTo(c *server.Config) error { return nil } - if !advancedAuditingEnabled() { - return fmt.Errorf("feature '%s' must be enabled to set an audit webhook", features.AdvancedAuditing) - } webhook, err := pluginwebhook.NewBackend(o.ConfigFile, o.Mode) if err != nil { return fmt.Errorf("initializing audit webhook: %v", err) From c03a6ecca0199be15652c73bb93235c5adccb7a7 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Mon, 15 May 2017 09:42:21 -0400 Subject: [PATCH 019/448] Allow NetworkPolicy.spec updates --- pkg/apis/networking/validation/validation.go | 6 +- .../networking/validation/validation_test.go | 59 ++++++++++--------- 2 files changed, 32 insertions(+), 33 deletions(-) diff --git a/pkg/apis/networking/validation/validation.go b/pkg/apis/networking/validation/validation.go index e2db31430fe..12272d50289 100644 --- a/pkg/apis/networking/validation/validation.go +++ b/pkg/apis/networking/validation/validation.go @@ -17,8 +17,6 @@ limitations under the License. package validation import ( - "reflect" - unversionedvalidation "k8s.io/apimachinery/pkg/apis/meta/v1/validation" "k8s.io/apimachinery/pkg/util/intstr" "k8s.io/apimachinery/pkg/util/validation" @@ -92,8 +90,6 @@ func ValidateNetworkPolicy(np *networking.NetworkPolicy) field.ErrorList { func ValidateNetworkPolicyUpdate(update, old *networking.NetworkPolicy) field.ErrorList { allErrs := field.ErrorList{} allErrs = append(allErrs, apivalidation.ValidateObjectMetaUpdate(&update.ObjectMeta, &old.ObjectMeta, field.NewPath("metadata"))...) - if !reflect.DeepEqual(update.Spec, old.Spec) { - allErrs = append(allErrs, field.Forbidden(field.NewPath("spec"), "updates to networkpolicy spec are forbidden.")) - } + allErrs = append(allErrs, ValidateNetworkPolicySpec(&update.Spec, field.NewPath("spec"))...) return allErrs } diff --git a/pkg/apis/networking/validation/validation_test.go b/pkg/apis/networking/validation/validation_test.go index 6001d5bc4e6..154d783bf15 100644 --- a/pkg/apis/networking/validation/validation_test.go +++ b/pkg/apis/networking/validation/validation_test.go @@ -271,8 +271,8 @@ func TestValidateNetworkPolicyUpdate(t *testing.T) { old networking.NetworkPolicy update networking.NetworkPolicy } - successCases := []npUpdateTest{ - { + successCases := map[string]npUpdateTest{ + "no change": { old: networking.NetworkPolicy{ ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "bar"}, Spec: networking.NetworkPolicySpec{ @@ -292,32 +292,6 @@ func TestValidateNetworkPolicyUpdate(t *testing.T) { }, }, }, - } - - for _, successCase := range successCases { - successCase.old.ObjectMeta.ResourceVersion = "1" - successCase.update.ObjectMeta.ResourceVersion = "1" - if errs := ValidateNetworkPolicyUpdate(&successCase.update, &successCase.old); len(errs) != 0 { - t.Errorf("expected success: %v", errs) - } - } - errorCases := map[string]npUpdateTest{ - "change name": { - old: networking.NetworkPolicy{ - ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "bar"}, - Spec: networking.NetworkPolicySpec{ - PodSelector: metav1.LabelSelector{}, - Ingress: []networking.NetworkPolicyIngressRule{}, - }, - }, - update: networking.NetworkPolicy{ - ObjectMeta: metav1.ObjectMeta{Name: "baz", Namespace: "bar"}, - Spec: networking.NetworkPolicySpec{ - PodSelector: metav1.LabelSelector{}, - Ingress: []networking.NetworkPolicyIngressRule{}, - }, - }, - }, "change spec": { old: networking.NetworkPolicy{ ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "bar"}, @@ -338,7 +312,36 @@ func TestValidateNetworkPolicyUpdate(t *testing.T) { }, } + for testName, successCase := range successCases { + successCase.old.ObjectMeta.ResourceVersion = "1" + successCase.update.ObjectMeta.ResourceVersion = "1" + if errs := ValidateNetworkPolicyUpdate(&successCase.update, &successCase.old); len(errs) != 0 { + t.Errorf("expected success (%s): %v", testName, errs) + } + } + + errorCases := map[string]npUpdateTest{ + "change name": { + old: networking.NetworkPolicy{ + ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "bar"}, + Spec: networking.NetworkPolicySpec{ + PodSelector: metav1.LabelSelector{}, + Ingress: []networking.NetworkPolicyIngressRule{}, + }, + }, + update: networking.NetworkPolicy{ + ObjectMeta: metav1.ObjectMeta{Name: "baz", Namespace: "bar"}, + Spec: networking.NetworkPolicySpec{ + PodSelector: metav1.LabelSelector{}, + Ingress: []networking.NetworkPolicyIngressRule{}, + }, + }, + }, + } + for testName, errorCase := range errorCases { + errorCase.old.ObjectMeta.ResourceVersion = "1" + errorCase.update.ObjectMeta.ResourceVersion = "1" if errs := ValidateNetworkPolicyUpdate(&errorCase.update, &errorCase.old); len(errs) == 0 { t.Errorf("expected failure: %s", testName) } From d863c3554605146a4d1863c02cbc41cf30586526 Mon Sep 17 00:00:00 2001 From: shashidharatd Date: Wed, 7 Jun 2017 21:49:16 +0530 Subject: [PATCH 020/448] Cleanup federation/cluster scripts from deprecated bringup method --- federation/cluster/common.sh | 342 -------------------------- federation/cluster/federation-down.sh | 3 +- federation/cluster/federation-up.sh | 14 +- federation/cluster/template.go | 76 ------ 4 files changed, 4 insertions(+), 431 deletions(-) delete mode 100644 federation/cluster/template.go diff --git a/federation/cluster/common.sh b/federation/cluster/common.sh index d0610a6523b..e9a8ba088d0 100644 --- a/federation/cluster/common.sh +++ b/federation/cluster/common.sh @@ -46,11 +46,6 @@ if [[ -z "${HOST_CLUSTER_CONTEXT}" ]]; then HOST_CLUSTER_CONTEXT="${CLUSTER_CONTEXT}" fi -# kube-dns configuration. -KUBEDNS_CONFIGMAP_NAME="kube-dns" -KUBEDNS_CONFIGMAP_NAMESPACE="kube-system" -KUBEDNS_FEDERATION_FLAG="federations" - function federation_cluster_contexts() { local -r contexts=$("${KUBE_ROOT}/cluster/kubectl.sh" config get-contexts -o name) federation_contexts=() @@ -69,347 +64,10 @@ function federation_cluster_contexts() { } -#-----------------------------------------------------------------# -# NOTE: # -# Everything below this line is deprecated. It will be removed # -# once we have sufficient confidence in kubefed based testing. # -#-----------------------------------------------------------------# - -# optional override -# FEDERATION_IMAGE_REPO_BASE: repo which federated images are tagged under (default gcr.io/google_containers) -# FEDERATION_NAMESPACE: name of the namespace will created for the federated components in the underlying cluster. -# KUBE_PLATFORM -# KUBE_ARCH -# KUBE_BUILD_STAGE - source "${KUBE_ROOT}/cluster/common.sh" host_kubectl="${KUBE_ROOT}/cluster/kubectl.sh --namespace=${FEDERATION_NAMESPACE}" -# If $FEDERATION_PUSH_REPO_BASE isn't set, then set the GCR registry name -# based on the detected project name for gce and gke providers. -FEDERATION_PUSH_REPO_BASE=${FEDERATION_PUSH_REPO_BASE:-} -if [[ -z "${FEDERATION_PUSH_REPO_BASE}" ]]; then - if [[ "${KUBERNETES_PROVIDER}" == "gke" || "${KUBERNETES_PROVIDER}" == "gce" ]]; then - # Populates $PROJECT - detect-project - if [[ ${PROJECT} == *':'* ]]; then - echo "${PROJECT} contains ':' and can not be used as FEDERATION_PUSH_REPO_BASE. Please set FEDERATION_PUSH_REPO_BASE explicitly." - exit 1 - fi - FEDERATION_PUSH_REPO_BASE=gcr.io/${PROJECT} - else - echo "Must set FEDERATION_PUSH_REPO_BASE env var" - exit 1 - fi -fi - -FEDERATION_IMAGE_REPO_BASE=${FEDERATION_IMAGE_REPO_BASE:-'gcr.io/google_containers'} - -KUBE_PLATFORM=${KUBE_PLATFORM:-linux} -KUBE_ARCH=${KUBE_ARCH:-amd64} -KUBE_BUILD_STAGE=${KUBE_BUILD_STAGE:-release-stage} - -source "${KUBE_ROOT}/cluster/common.sh" - -host_kubectl="${KUBE_ROOT}/cluster/kubectl.sh --namespace=${FEDERATION_NAMESPACE}" - -# required: -# FEDERATION_PUSH_REPO_BASE: repo to which federated container images will be pushed -# FEDERATION_IMAGE_TAG: reference and pull all federated images with this tag. -function create-federation-api-objects { -( - : "${FEDERATION_PUSH_REPO_BASE?Must set FEDERATION_PUSH_REPO_BASE env var}" - : "${FEDERATION_IMAGE_TAG?Must set FEDERATION_IMAGE_TAG env var}" - - export FEDERATION_APISERVER_DEPLOYMENT_NAME="federation-apiserver" - export FEDERATION_APISERVER_IMAGE_REPO="${FEDERATION_PUSH_REPO_BASE}/hyperkube-amd64" - export FEDERATION_APISERVER_IMAGE_TAG="${FEDERATION_IMAGE_TAG}" - - export FEDERATION_CONTROLLER_MANAGER_DEPLOYMENT_NAME="federation-controller-manager" - export FEDERATION_CONTROLLER_MANAGER_IMAGE_REPO="${FEDERATION_PUSH_REPO_BASE}/hyperkube-amd64" - export FEDERATION_CONTROLLER_MANAGER_IMAGE_TAG="${FEDERATION_IMAGE_TAG}" - - if [[ -z "${FEDERATION_DNS_PROVIDER:-}" ]]; then - # Set the appropriate value based on cloud provider. - if [[ "$KUBERNETES_PROVIDER" == "gce" || "${KUBERNETES_PROVIDER}" == "gke" ]]; then - echo "setting dns provider to google-clouddns" - export FEDERATION_DNS_PROVIDER="google-clouddns" - elif [[ "${KUBERNETES_PROVIDER}" == "aws" ]]; then - echo "setting dns provider to aws-route53" - export FEDERATION_DNS_PROVIDER="aws-route53" - else - echo "Must set FEDERATION_DNS_PROVIDER env var" - exit 1 - fi - fi - - export FEDERATION_SERVICE_CIDR=${FEDERATION_SERVICE_CIDR:-"10.10.0.0/24"} - - #Only used for providers that require a nodeport service (vagrant for now) - #We will use loadbalancer services where we can - export FEDERATION_API_NODEPORT=32111 - export FEDERATION_NAMESPACE - export FEDERATION_NAME="${FEDERATION_NAME:-federation}" - export DNS_ZONE_NAME="${DNS_ZONE_NAME:-federation.example.}" # See https://tools.ietf.org/html/rfc2606 - - template="go run ${KUBE_ROOT}/federation/cluster/template.go" - - FEDERATION_KUBECONFIG_PATH="${KUBE_ROOT}/federation/cluster/kubeconfig" - - federation_kubectl="${KUBE_ROOT}/cluster/kubectl.sh --context=federation-cluster --namespace=default" - - manifests_root="${KUBE_ROOT}/federation/manifests/" - - $template "${manifests_root}/federation-ns.yaml" | $host_kubectl apply -f - - - cleanup-federation-api-objects - - export FEDERATION_API_HOST="" - export KUBE_MASTER_IP="" - export IS_DNS_NAME="false" - if [[ "$KUBERNETES_PROVIDER" == "vagrant" ]];then - # The vagrant approach is to use a nodeport service, and point kubectl at one of the nodes - $template "${manifests_root}/federation-apiserver-nodeport-service.yaml" | $host_kubectl create -f - - node_addresses=`$host_kubectl get nodes -o=jsonpath='{.items[*].status.addresses[?(@.type=="InternalIP")].address}'` - FEDERATION_API_HOST=`printf "$node_addresses" | cut -d " " -f1` - KUBE_MASTER_IP="${FEDERATION_API_HOST}:${FEDERATION_API_NODEPORT}" - elif [[ "$KUBERNETES_PROVIDER" == "gce" || "$KUBERNETES_PROVIDER" == "gke" || "$KUBERNETES_PROVIDER" == "aws" ]];then - - # Any providers where ingress is a DNS name should tick this box. - # TODO(chom): attempt to do this automatically - if [[ "$KUBERNETES_PROVIDER" == "aws" ]];then - IS_DNS_NAME="true" - fi - # any capable providers should use a loadbalancer service - # we check for ingress.ip and ingress.hostname, so should work for any loadbalancer-providing provider - # allows 30x5 = 150 seconds for loadbalancer creation - $template "${manifests_root}/federation-apiserver-lb-service.yaml" | $host_kubectl create -f - - for i in {1..30};do - echo "attempting to get federation-apiserver loadbalancer hostname ($i / 30)" - LB_STATUS=`${host_kubectl} get -o=jsonpath svc/${FEDERATION_APISERVER_DEPLOYMENT_NAME} --template '{.status.loadBalancer}'` - # Check if ingress field has been set in load balancer status. - if [[ "${LB_STATUS}" != *"ingress"* ]]; then - echo "Waiting for load balancer status to be set" - sleep 5 - continue - fi - for field in ip hostname;do - FEDERATION_API_HOST=`${host_kubectl} get -o=jsonpath svc/${FEDERATION_APISERVER_DEPLOYMENT_NAME} --template '{.status.loadBalancer.ingress[*].'"${field}}"` - if [[ ! -z "${FEDERATION_API_HOST// }" ]];then - break 2 - fi - done - if [[ $i -eq 30 ]];then - echo "Could not find ingress hostname for federation-apiserver loadbalancer service" - exit 1 - fi - sleep 5 - done - KUBE_MASTER_IP="${FEDERATION_API_HOST}:443" - else - echo "provider ${KUBERNETES_PROVIDER} is not (yet) supported for e2e testing" - exit 1 - fi - echo "Found federation-apiserver host at $FEDERATION_API_HOST" - - FEDERATION_API_TOKEN="$(dd if=/dev/urandom bs=128 count=1 2>/dev/null | base64 | tr -d "=+/" | dd bs=32 count=1 2>/dev/null)" - export FEDERATION_API_KNOWN_TOKENS="${FEDERATION_API_TOKEN},admin,admin" - gen-kube-basicauth - export FEDERATION_API_BASIC_AUTH="${KUBE_PASSWORD},${KUBE_USER},admin" - - # Create a kubeconfig with credentials for federation-apiserver. We will - # then use this kubeconfig to create a secret which the federation - # controller manager can use to talk to the federation-apiserver. - # Note that the file name should be "kubeconfig" so that the secret key gets the same name. - KUBECONFIG_DIR=$(dirname ${KUBECONFIG:-$DEFAULT_KUBECONFIG}) - CONTEXT=${FEDERATION_KUBE_CONTEXT} \ - KUBE_BEARER_TOKEN="$FEDERATION_API_TOKEN" \ - KUBE_USER="${KUBE_USER}" \ - KUBE_PASSWORD="${KUBE_PASSWORD}" \ - KUBECONFIG="${KUBECONFIG_DIR}/federation/federation-apiserver/kubeconfig" \ - create-kubeconfig - - # Create secret with federation-apiserver's kubeconfig - $host_kubectl create secret generic federation-apiserver-kubeconfig --from-file="${KUBECONFIG_DIR}/federation/federation-apiserver/kubeconfig" --namespace="${FEDERATION_NAMESPACE}" - - # Create secrets with all the kubernetes-apiserver's kubeconfigs. - # Note: This is used only by the test setup (where kubernetes clusters are - # brought up with FEDERATION=true). Users are expected to create this secret - # themselves. - for dir in ${KUBECONFIG_DIR}/federation/kubernetes-apiserver/*; do - # We create a secret with the same name as the directory name (which is - # same as cluster name in kubeconfig). - # Massage the name so that it is valid (should not contain "_" and max 253 - # chars) - name=$(basename $dir) - name=$(echo "$name" | sed -e "s/_/-/g") # Replace "_" by "-" - name=${name:0:252} - echo "Creating secret with name: $name" - $host_kubectl create secret generic ${name} --from-file="${dir}/kubeconfig" --namespace="${FEDERATION_NAMESPACE}" - done - - # Create server certificates. - kube::util::ensure-temp-dir - echo "Creating federation apiserver certs for federation api host: ${FEDERATION_API_HOST} ( is this a dns name?: ${IS_DNS_NAME} )" - MASTER_NAME="federation-apiserver" create-federation-apiserver-certs ${FEDERATION_API_HOST} - export FEDERATION_APISERVER_CA_CERT_BASE64="${FEDERATION_APISERVER_CA_CERT_BASE64}" - export FEDERATION_APISERVER_CERT_BASE64="${FEDERATION_APISERVER_CERT_BASE64}" - export FEDERATION_APISERVER_KEY_BASE64="${FEDERATION_APISERVER_KEY_BASE64}" - - # Enable the NamespaceLifecycle admission control by default. - export FEDERATION_ADMISSION_CONTROL="${FEDERATION_ADMISSION_CONTROL:-NamespaceLifecycle}" - - for file in federation-etcd-pvc.yaml federation-apiserver-{deployment,secrets}.yaml federation-controller-manager-deployment.yaml; do - echo "Creating manifest: ${file}" - $template "${manifests_root}/${file}" - $template "${manifests_root}/${file}" | $host_kubectl create -f - - done - - # Update the users kubeconfig to include federation-apiserver credentials. - CONTEXT=${FEDERATION_KUBE_CONTEXT} \ - KUBE_BEARER_TOKEN="${FEDERATION_API_TOKEN}" \ - KUBE_USER="${KUBE_USER}" \ - KUBE_PASSWORD="${KUBE_PASSWORD}" \ - SECONDARY_KUBECONFIG=true \ - create-kubeconfig - - # Don't finish provisioning until federation-apiserver pod is running - for i in {1..30};do - #TODO(colhom): in the future this needs to scale out for N pods. This assumes just one pod - phase="$($host_kubectl get -o=jsonpath pods -lapp=federated-cluster,module=federation-apiserver --template '{.items[*].status.phase}')" - echo "Waiting for federation-apiserver to be running...(phase= $phase)" - if [[ "$phase" == "Running" ]];then - echo "federation-apiserver pod is running!" - break - fi - - if [[ $i -eq 30 ]];then - echo "federation-apiserver pod is not running! giving up." - exit 1 - fi - - sleep 4 - done - - # Verify that federation-controller-manager pod is running. - for i in {1..30};do - #TODO(colhom): in the future this needs to scale out for N pods. This assumes just one pod - phase="$($host_kubectl get -o=jsonpath pods -lapp=federated-cluster,module=federation-controller-manager --template '{.items[*].status.phase}')" - echo "Waiting for federation-controller-manager to be running...(phase= $phase)" - if [[ "$phase" == "Running" ]];then - echo "federation-controller-manager pod is running!" - break - fi - - if [[ $i -eq 30 ]];then - echo "federation-controller-manager pod is not running! giving up." - exit 1 - fi - - sleep 4 - done -) -} - -# Creates the required certificates for federation apiserver. -# $1: The public IP or DNS name for the master. -# -# Assumed vars -# KUBE_TEMP -# MASTER_NAME -# IS_DNS_NAME=true|false -function create-federation-apiserver-certs { - local primary_cn - local sans - - if [[ "${IS_DNS_NAME:-}" == "true" ]];then - primary_cn="$(printf "${1}" | sha1sum | tr " -" " ")" - sans="DNS:${1},DNS:${MASTER_NAME}" - else - primary_cn="${1}" - sans="IP:${1},DNS:${MASTER_NAME}" - fi - - echo "Generating certs for alternate-names: ${sans}" - - local kube_temp="${KUBE_TEMP}/federation" - mkdir -p "${kube_temp}" - KUBE_TEMP="${kube_temp}" PRIMARY_CN="${primary_cn}" SANS="${sans}" generate-certs - - local cert_dir="${kube_temp}/easy-rsa-master/easyrsa3" - # By default, linux wraps base64 output every 76 cols, so we use 'tr -d' to remove whitespaces. - # Note 'base64 -w0' doesn't work on Mac OS X, which has different flags. - FEDERATION_APISERVER_CA_CERT_BASE64=$(cat "${cert_dir}/pki/ca.crt" | base64 | tr -d '\r\n') - FEDERATION_APISERVER_CERT_BASE64=$(cat "${cert_dir}/pki/issued/${MASTER_NAME}.crt" | base64 | tr -d '\r\n') - FEDERATION_APISERVER_KEY_BASE64=$(cat "${cert_dir}/pki/private/${MASTER_NAME}.key" | base64 | tr -d '\r\n') -} - - -# Required -# FEDERATION_PUSH_REPO_BASE: the docker repo where federated images will be pushed -# FEDERATION_IMAGE_TAG: the tag of the image to be pushed -function push-federation-images { - : "${FEDERATION_PUSH_REPO_BASE?Must set FEDERATION_PUSH_REPO_BASE env var}" - : "${FEDERATION_IMAGE_TAG?Must set FEDERATION_IMAGE_TAG env var}" - - source "${KUBE_ROOT}/build/common.sh" - source "${KUBE_ROOT}/hack/lib/util.sh" - - local FEDERATION_BINARIES=${FEDERATION_BINARIES:-"hyperkube-amd64"} - - local bin_dir="${KUBE_ROOT}/_output/${KUBE_BUILD_STAGE}/server/${KUBE_PLATFORM}-${KUBE_ARCH}/kubernetes/server/bin" - - if [[ ! -d "${bin_dir}" ]];then - echo "${bin_dir} does not exist! Run make quick-release or make release" - exit 1 - fi - - for binary in ${FEDERATION_BINARIES}; do - local bin_path="${bin_dir}/${binary}" - - if [[ ! -f "${bin_path}" ]]; then - echo "${bin_path} does not exist!" - exit 1 - fi - - local docker_build_path="${bin_path}.dockerbuild" - local docker_file_path="${docker_build_path}/Dockerfile" - - rm -rf ${docker_build_path} - mkdir -p ${docker_build_path} - - ln "${bin_path}" "${docker_build_path}/${binary}" - printf " FROM debian:jessie \n ADD ${binary} /usr/local/bin/${binary}\n" > ${docker_file_path} - - local docker_image_tag="${FEDERATION_PUSH_REPO_BASE}/${binary}:${FEDERATION_IMAGE_TAG}" - - # Build the docker image on-the-fly. - # - # NOTE: This is only a temporary fix until the proposal in issue - # https://github.com/kubernetes/kubernetes/issues/28630 is implemented. - # Also, the new turn up mechanism completely obviates this step. - # - # TODO(madhusudancs): Remove this code when the new turn up mechanism work - # is merged. - kube::log::status "Building docker image ${docker_image_tag} from the binary" - docker build --pull -q -t "${docker_image_tag}" ${docker_build_path} >/dev/null - - rm -rf ${docker_build_path} - - kube::log::status "Pushing ${docker_image_tag}" - if [[ "${FEDERATION_PUSH_REPO_BASE}" == "gcr.io/"* ]]; then - echo " -> GCR repository detected. Using gcloud" - gcloud docker -- push "${docker_image_tag}" - else - docker push "${docker_image_tag}" - fi - - kube::log::status "Deleting docker image ${docker_image_tag}" - docker rmi "${docker_image_tag}" 2>/dev/null || true - done -} - function cleanup-federation-api-objects { # This is a cleanup function. We cannot stop on errors here. So disable # errexit in this function. diff --git a/federation/cluster/federation-down.sh b/federation/cluster/federation-down.sh index 8aca4580399..dfbe63edae9 100755 --- a/federation/cluster/federation-down.sh +++ b/federation/cluster/federation-down.sh @@ -21,8 +21,7 @@ set -o pipefail KUBE_ROOT=$(readlink -m $(dirname "${BASH_SOURCE}")/../../) # For $FEDERATION_NAME, $FEDERATION_NAMESPACE, $FEDERATION_KUBE_CONTEXT, -# $HOST_CLUSTER_CONTEXT, $KUBEDNS_CONFIGMAP_NAME and -# $KUBEDNS_CONFIGMAP_NAMESPACE. +# and $HOST_CLUSTER_CONTEXT. source "${KUBE_ROOT}/federation/cluster/common.sh" # federation_clusters returns a list of all the clusters in diff --git a/federation/cluster/federation-up.sh b/federation/cluster/federation-up.sh index 62efca9cdfc..bb46280f65f 100755 --- a/federation/cluster/federation-up.sh +++ b/federation/cluster/federation-up.sh @@ -30,8 +30,7 @@ KUBE_ROOT=$(dirname "${BASH_SOURCE}")/../.. # "${KUBE_ROOT}/cluster/lib/logging.sh" and DEFAULT_KUBECONFIG source "${KUBE_ROOT}/cluster/common.sh" # For $FEDERATION_NAME, $FEDERATION_NAMESPACE, $FEDERATION_KUBE_CONTEXT, -# $HOST_CLUSTER_CONTEXT, $KUBEDNS_CONFIGMAP_NAME, -# $KUBEDNS_CONFIGMAP_NAMESPACE and $KUBEDNS_FEDERATION_FLAG. +# and $HOST_CLUSTER_CONTEXT. source "${KUBE_ROOT}/federation/cluster/common.sh" DNS_ZONE_NAME="${FEDERATION_DNS_ZONE_NAME:-}" @@ -113,12 +112,5 @@ function join_clusters() { done } -USE_KUBEFED="${USE_KUBEFED:-}" - -if [[ "${USE_KUBEFED}" == "true" ]]; then - init - join_clusters -else - export FEDERATION_IMAGE_TAG="$(get_version)" - create-federation-api-objects -fi +init +join_clusters diff --git a/federation/cluster/template.go b/federation/cluster/template.go deleted file mode 100644 index 3a550763f34..00000000000 --- a/federation/cluster/template.go +++ /dev/null @@ -1,76 +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 is a simple script that makes *every* environment variable available -as a go template field of the same name - -$ echo "hello world, MYVAR={{.MYVAR}}" > test.txt -$ MYVAR=foobar go run template.go test.txt -> hello world, MYVAR=foobar - -If you want the base64 version of any MYVAR, simple use {{.MYVAR_BASE64}} -*/ - -package main - -import ( - "encoding/base64" - "flag" - "fmt" - "io" - "os" - "path" - "strings" - "text/template" -) - -func main() { - flag.Parse() - env := make(map[string]string) - envList := os.Environ() - - for i := range envList { - pieces := strings.SplitN(envList[i], "=", 2) - if len(pieces) == 2 { - env[pieces[0]] = pieces[1] - env[pieces[0]+"_BASE64"] = base64.StdEncoding.EncodeToString([]byte(pieces[1])) - } else { - fmt.Fprintf(os.Stderr, "Invalid environ found: %s\n", envList[i]) - os.Exit(2) - } - } - - for i := 0; i < flag.NArg(); i++ { - inpath := flag.Arg(i) - - if err := templateYamlFile(env, inpath, os.Stdout); err != nil { - panic(err) - } - } -} - -func templateYamlFile(params map[string]string, inpath string, out io.Writer) error { - if tmpl, err := template.New(path.Base(inpath)).Option("missingkey=zero").ParseFiles(inpath); err != nil { - return err - } else { - if err := tmpl.Execute(out, params); err != nil { - return err - } - } - _, err := out.Write([]byte("\n---\n")) - return err -} From 81f927d58c270559e66c01de9d6a4d6364d4570d Mon Sep 17 00:00:00 2001 From: shashidharatd Date: Wed, 7 Jun 2017 22:05:08 +0530 Subject: [PATCH 021/448] Auto generated file --- federation/cluster/BUILD | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/federation/cluster/BUILD b/federation/cluster/BUILD index 500bdb28821..6cc62052baf 100644 --- a/federation/cluster/BUILD +++ b/federation/cluster/BUILD @@ -2,24 +2,6 @@ package(default_visibility = ["//visibility:public"]) licenses(["notice"]) -load( - "@io_bazel_rules_go//go:def.bzl", - "go_binary", - "go_library", -) - -go_binary( - name = "cluster", - library = ":go_default_library", - tags = ["automanaged"], -) - -go_library( - name = "go_default_library", - srcs = ["template.go"], - tags = ["automanaged"], -) - filegroup( name = "package-srcs", srcs = glob(["**"]), From 7adf8d8cac89eb68bc10a58827ef08e74e047913 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ky=C3=A2ne=20Pichou?= Date: Wed, 7 Jun 2017 19:08:29 +0200 Subject: [PATCH 022/448] Fix a typo in deletion log of apiserver --- staging/src/k8s.io/apiserver/pkg/endpoints/handlers/rest.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/rest.go b/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/rest.go index 03d02bcb40c..4bab1446cb6 100644 --- a/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/rest.go +++ b/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/rest.go @@ -991,7 +991,7 @@ func DeleteResource(r rest.GracefulDeleter, allowsOptions bool, scope RequestSco } } - trace.Step("About do delete object from database") + trace.Step("About to delete object from database") wasDeleted := true result, err := finishRequest(timeout, func() (runtime.Object, error) { obj, deleted, err := r.Delete(ctx, name, options) From a70ec5ba409f1d9f254fb76a50f6919c04877a03 Mon Sep 17 00:00:00 2001 From: Cao Shufeng Date: Fri, 9 Jun 2017 11:26:06 +0800 Subject: [PATCH 023/448] [trivial]fix function name in comment --- pkg/kubectl/cmd/logs.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/kubectl/cmd/logs.go b/pkg/kubectl/cmd/logs.go index 3f06f03e55c..f507dfabec5 100644 --- a/pkg/kubectl/cmd/logs.go +++ b/pkg/kubectl/cmd/logs.go @@ -87,7 +87,7 @@ type LogsOptions struct { Out io.Writer } -// NewCmdLog creates a new pod logs command +// NewCmdLogs creates a new pod logs command func NewCmdLogs(f cmdutil.Factory, out io.Writer) *cobra.Command { o := &LogsOptions{} cmd := &cobra.Command{ From 6e43ee92a8b26348a13b8f7b130fd2770fd240cb Mon Sep 17 00:00:00 2001 From: zhengjiajin <393926893@qq.com> Date: Fri, 9 Jun 2017 17:50:25 +0800 Subject: [PATCH 024/448] servicecontroller: trivial fix error message naming --- .../pkg/federation-controller/service/servicecontroller.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/federation/pkg/federation-controller/service/servicecontroller.go b/federation/pkg/federation-controller/service/servicecontroller.go index ffc278af8cb..34bf5438207 100644 --- a/federation/pkg/federation-controller/service/servicecontroller.go +++ b/federation/pkg/federation-controller/service/servicecontroller.go @@ -409,7 +409,7 @@ func (s *ServiceController) reconcileService(key string) reconciliationStatus { namespace, name, err := cache.SplitMetaNamespaceKey(key) if err != nil { - runtime.HandleError(fmt.Errorf("Invalid key %q recieved, unable to split key to namespace and name, err: %v", key, err)) + runtime.HandleError(fmt.Errorf("Invalid key %q received, unable to split key to namespace and name, err: %v", key, err)) return statusNonRecoverableError } @@ -432,7 +432,7 @@ func (s *ServiceController) reconcileService(key string) reconciliationStatus { } fedService, ok := fedServiceObj.(*v1.Service) if err != nil || !ok { - runtime.HandleError(fmt.Errorf("Unknown obj recieved from store: %#v, %v", fedServiceObj, err)) + runtime.HandleError(fmt.Errorf("Unknown obj received from store: %#v, %v", fedServiceObj, err)) return statusNonRecoverableError } From 24ee14540ad40079611f4223519196cfbfa2677b Mon Sep 17 00:00:00 2001 From: Xiang Date: Sun, 11 Jun 2017 09:59:38 -0700 Subject: [PATCH 025/448] scheduler/util: remove bad print format Backoff do not have any context on pod. Remove the previous bad printing format. --- plugin/pkg/scheduler/util/backoff_utils.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/plugin/pkg/scheduler/util/backoff_utils.go b/plugin/pkg/scheduler/util/backoff_utils.go index 90566bbfbaf..9226f4cca5b 100644 --- a/plugin/pkg/scheduler/util/backoff_utils.go +++ b/plugin/pkg/scheduler/util/backoff_utils.go @@ -18,11 +18,12 @@ package util import ( "fmt" - "github.com/golang/glog" - ktypes "k8s.io/apimachinery/pkg/types" "sync" "sync/atomic" "time" + + "github.com/golang/glog" + ktypes "k8s.io/apimachinery/pkg/types" ) type clock interface { @@ -74,7 +75,7 @@ func (entry *backoffEntry) getBackoff(maxDuration time.Duration) time.Duration { newDuration = maxDuration } entry.backoff = newDuration - glog.V(4).Infof("Backing off %s for pod %+v", duration.String(), entry) + glog.V(4).Infof("Backing off %s", duration.String()) return duration } From ce54d9072bd637db5441a9c7b92c8d0eb0511629 Mon Sep 17 00:00:00 2001 From: xiangpengzhao Date: Sat, 10 Jun 2017 12:55:47 +0800 Subject: [PATCH 026/448] Validate if service has duplicate targetPort --- pkg/api/validation/validation.go | 16 ++++++++++++ pkg/api/validation/validation_test.go | 36 +++++++++++++++++++++++++++ 2 files changed, 52 insertions(+) diff --git a/pkg/api/validation/validation.go b/pkg/api/validation/validation.go index 78e055dde9f..cf48bca084e 100644 --- a/pkg/api/validation/validation.go +++ b/pkg/api/validation/validation.go @@ -2865,6 +2865,22 @@ func ValidateService(service *api.Service) field.ErrorList { nodePorts[key] = true } + // Check for duplicate TargetPort + portsPath = specPath.Child("ports") + targetPorts := make(map[api.ServicePort]bool) + for i, port := range service.Spec.Ports { + if (port.TargetPort.Type == intstr.Int && port.TargetPort.IntVal == 0) || (port.TargetPort.Type == intstr.String && port.TargetPort.StrVal == "") { + continue + } + portPath := portsPath.Index(i) + key := api.ServicePort{Protocol: port.Protocol, TargetPort: port.TargetPort} + _, found := targetPorts[key] + if found { + allErrs = append(allErrs, field.Duplicate(portPath.Child("targetPort"), port.TargetPort)) + } + targetPorts[key] = true + } + // Validate SourceRange field and annotation _, ok := service.Annotations[api.AnnotationLoadBalancerSourceRangesKey] if len(service.Spec.LoadBalancerSourceRanges) > 0 || ok { diff --git a/pkg/api/validation/validation_test.go b/pkg/api/validation/validation_test.go index b56c059ea45..426669c7e1a 100644 --- a/pkg/api/validation/validation_test.go +++ b/pkg/api/validation/validation_test.go @@ -6033,6 +6033,42 @@ func TestValidateService(t *testing.T) { }, numErrs: 0, }, + { + name: "invalid duplicate targetports (number with same protocol)", + tweakSvc: func(s *api.Service) { + s.Spec.Type = api.ServiceTypeClusterIP + s.Spec.Ports = append(s.Spec.Ports, api.ServicePort{Name: "q", Port: 1, Protocol: "TCP", TargetPort: intstr.FromInt(8080)}) + s.Spec.Ports = append(s.Spec.Ports, api.ServicePort{Name: "r", Port: 2, Protocol: "TCP", TargetPort: intstr.FromInt(8080)}) + }, + numErrs: 1, + }, + { + name: "invalid duplicate targetports (name with same protocol)", + tweakSvc: func(s *api.Service) { + s.Spec.Type = api.ServiceTypeClusterIP + s.Spec.Ports = append(s.Spec.Ports, api.ServicePort{Name: "q", Port: 1, Protocol: "TCP", TargetPort: intstr.FromString("http")}) + s.Spec.Ports = append(s.Spec.Ports, api.ServicePort{Name: "r", Port: 2, Protocol: "TCP", TargetPort: intstr.FromString("http")}) + }, + numErrs: 1, + }, + { + name: "valid duplicate targetports (number with different protocols)", + tweakSvc: func(s *api.Service) { + s.Spec.Type = api.ServiceTypeClusterIP + s.Spec.Ports = append(s.Spec.Ports, api.ServicePort{Name: "q", Port: 1, Protocol: "TCP", TargetPort: intstr.FromInt(8080)}) + s.Spec.Ports = append(s.Spec.Ports, api.ServicePort{Name: "r", Port: 2, Protocol: "UDP", TargetPort: intstr.FromInt(8080)}) + }, + numErrs: 0, + }, + { + name: "valid duplicate targetports (name with different protocols)", + tweakSvc: func(s *api.Service) { + s.Spec.Type = api.ServiceTypeClusterIP + s.Spec.Ports = append(s.Spec.Ports, api.ServicePort{Name: "q", Port: 1, Protocol: "TCP", TargetPort: intstr.FromString("http")}) + s.Spec.Ports = append(s.Spec.Ports, api.ServicePort{Name: "r", Port: 2, Protocol: "UDP", TargetPort: intstr.FromString("http")}) + }, + numErrs: 0, + }, { name: "valid type - cluster", tweakSvc: func(s *api.Service) { From c2cb2b3c717bad6e9aa0b000a1f61a0eb1c73e87 Mon Sep 17 00:00:00 2001 From: Dane LeBlanc Date: Tue, 6 Jun 2017 19:44:42 -0400 Subject: [PATCH 027/448] Add IPv6 test cases to kube-proxy server test. fixes #47313 --- cmd/kube-proxy/app/BUILD | 3 + cmd/kube-proxy/app/server_test.go | 217 ++++++++++++++++++++++-------- 2 files changed, 165 insertions(+), 55 deletions(-) diff --git a/cmd/kube-proxy/app/BUILD b/cmd/kube-proxy/app/BUILD index 65ab9ca3210..3c317f472a5 100644 --- a/cmd/kube-proxy/app/BUILD +++ b/cmd/kube-proxy/app/BUILD @@ -72,10 +72,13 @@ go_test( deps = [ "//pkg/api:go_default_library", "//pkg/apis/componentconfig:go_default_library", + "//pkg/apis/componentconfig/v1alpha1:go_default_library", "//pkg/util:go_default_library", + "//pkg/util/configz:go_default_library", "//pkg/util/iptables:go_default_library", "//vendor/github.com/stretchr/testify/assert: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/cmd/kube-proxy/app/server_test.go b/cmd/kube-proxy/app/server_test.go index b7337fe6c2b..673ae0ae79b 100644 --- a/cmd/kube-proxy/app/server_test.go +++ b/cmd/kube-proxy/app/server_test.go @@ -17,6 +17,7 @@ limitations under the License. package app import ( + "errors" "fmt" "reflect" "runtime" @@ -27,10 +28,13 @@ import ( "github.com/stretchr/testify/assert" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + k8sRuntime "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/diff" "k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/apis/componentconfig" + "k8s.io/kubernetes/pkg/apis/componentconfig/v1alpha1" "k8s.io/kubernetes/pkg/util" + "k8s.io/kubernetes/pkg/util/configz" "k8s.io/kubernetes/pkg/util/iptables" ) @@ -134,23 +138,67 @@ func Test_getProxyMode(t *testing.T) { } } -// This test verifies that Proxy Server does not crash when CleanupAndExit is true. +// TestNewOptionsFailures tests failure modes for NewOptions() +func TestNewOptionsFailures(t *testing.T) { + + // Create a fake scheme builder that generates an error + errString := fmt.Sprintf("Simulated error") + genError := func(scheme *k8sRuntime.Scheme) error { + return errors.New(errString) + } + fakeSchemeBuilder := k8sRuntime.NewSchemeBuilder(genError) + + simulatedErrorTest := func(target string) { + var addToScheme *func(s *k8sRuntime.Scheme) error + if target == "componentconfig" { + addToScheme = &componentconfig.AddToScheme + } else { + addToScheme = &v1alpha1.AddToScheme + } + restoreValue := *addToScheme + restore := func() { + *addToScheme = restoreValue + } + defer restore() + *addToScheme = fakeSchemeBuilder.AddToScheme + _, err := NewOptions() + assert.Error(t, err, fmt.Sprintf("Simulated error in component %s", target)) + } + + // Simulate errors in calls to AddToScheme() + faultTargets := []string{"componentconfig", "v1alpha1"} + for _, target := range faultTargets { + simulatedErrorTest(target) + } +} + +// This test verifies that NewProxyServer does not crash when CleanupAndExit is true. func TestProxyServerWithCleanupAndExit(t *testing.T) { - options, err := NewOptions() - if err != nil { - t.Fatal(err) + // Each bind address below is a separate test case + bindAddresses := []string{ + "0.0.0.0", + "2001:db8::1", } + for _, addr := range bindAddresses { + options, err := NewOptions() + if err != nil { + t.Fatalf("Unexpected error with address %s: %v", addr, err) + } - options.config = &componentconfig.KubeProxyConfiguration{ - BindAddress: "0.0.0.0", + options.config = &componentconfig.KubeProxyConfiguration{ + BindAddress: addr, + } + options.CleanupAndExit = true + + proxyserver, err := NewProxyServer(options.config, options.CleanupAndExit, options.scheme, options.master) + + assert.Nil(t, err, "unexpected error in NewProxyServer, addr: %s", addr) + assert.NotNil(t, proxyserver, "nil proxy server obj, addr: %s", addr) + assert.NotNil(t, proxyserver.IptInterface, "nil iptables intf, addr: %s", addr) + + // Clean up config for next test case + configz.Delete("componentconfig") } - options.CleanupAndExit = true - - proxyserver, err := NewProxyServer(options.config, options.CleanupAndExit, options.scheme, options.master) - - assert.Nil(t, err) - assert.NotNil(t, proxyserver) - assert.NotNil(t, proxyserver.IptInterface) } func TestGetConntrackMax(t *testing.T) { @@ -211,16 +259,18 @@ func TestGetConntrackMax(t *testing.T) { } } +// TestLoadConfig tests proper operation of loadConfig() func TestLoadConfig(t *testing.T) { - yaml := `apiVersion: componentconfig/v1alpha1 -bindAddress: 9.8.7.6 + + yamlTemplate := `apiVersion: componentconfig/v1alpha1 +bindAddress: %s clientConnection: acceptContentTypes: "abc" burst: 100 contentType: content-type kubeconfig: "/path/to/kubeconfig" qps: 7 -clusterCIDR: "1.2.3.0/24" +clusterCIDR: "%s" configSyncPeriod: 15s conntrack: max: 4 @@ -229,7 +279,7 @@ conntrack: tcpCloseWaitTimeout: 10s tcpEstablishedTimeout: 20s featureGates: "all" -healthzBindAddress: 1.2.3.4:12345 +healthzBindAddress: "%s" hostnameOverride: "foo" iptables: masqueradeAll: true @@ -237,7 +287,7 @@ iptables: minSyncPeriod: 10s syncPeriod: 60s kind: KubeProxyConfiguration -metricsBindAddress: 2.3.4.5:23456 +metricsBindAddress: "%s" mode: "iptables" oomScoreAdj: 17 portRange: "2-7" @@ -245,47 +295,104 @@ resourceContainer: /foo udpTimeoutMilliseconds: 123ms ` - expected := &componentconfig.KubeProxyConfiguration{ - BindAddress: "9.8.7.6", - ClientConnection: componentconfig.ClientConnectionConfiguration{ - AcceptContentTypes: "abc", - Burst: 100, - ContentType: "content-type", - KubeConfigFile: "/path/to/kubeconfig", - QPS: 7, + testCases := []struct { + name string + bindAddress string + clusterCIDR string + healthzBindAddress string + metricsBindAddress string + }{ + { + name: "IPv4 config", + bindAddress: "9.8.7.6", + clusterCIDR: "1.2.3.0/24", + healthzBindAddress: "1.2.3.4:12345", + metricsBindAddress: "2.3.4.5:23456", }, - ClusterCIDR: "1.2.3.0/24", - ConfigSyncPeriod: metav1.Duration{Duration: 15 * time.Second}, - Conntrack: componentconfig.KubeProxyConntrackConfiguration{ - Max: 4, - MaxPerCore: 2, - Min: 1, - TCPCloseWaitTimeout: metav1.Duration{Duration: 10 * time.Second}, - TCPEstablishedTimeout: metav1.Duration{Duration: 20 * time.Second}, + { + name: "IPv6 config", + bindAddress: "2001:db8::1", + clusterCIDR: "fd00:1::0/64", + healthzBindAddress: "[fd00:1::5]:12345", + metricsBindAddress: "[fd00:2::5]:23456", }, - FeatureGates: "all", - HealthzBindAddress: "1.2.3.4:12345", - HostnameOverride: "foo", - IPTables: componentconfig.KubeProxyIPTablesConfiguration{ - MasqueradeAll: true, - MasqueradeBit: util.Int32Ptr(17), - MinSyncPeriod: metav1.Duration{Duration: 10 * time.Second}, - SyncPeriod: metav1.Duration{Duration: 60 * time.Second}, - }, - MetricsBindAddress: "2.3.4.5:23456", - Mode: "iptables", - OOMScoreAdj: util.Int32Ptr(17), - PortRange: "2-7", - ResourceContainer: "/foo", - UDPIdleTimeout: metav1.Duration{Duration: 123 * time.Millisecond}, } - options, err := NewOptions() - assert.NoError(t, err) + for _, tc := range testCases { + expected := &componentconfig.KubeProxyConfiguration{ + BindAddress: tc.bindAddress, + ClientConnection: componentconfig.ClientConnectionConfiguration{ + AcceptContentTypes: "abc", + Burst: 100, + ContentType: "content-type", + KubeConfigFile: "/path/to/kubeconfig", + QPS: 7, + }, + ClusterCIDR: tc.clusterCIDR, + ConfigSyncPeriod: metav1.Duration{Duration: 15 * time.Second}, + Conntrack: componentconfig.KubeProxyConntrackConfiguration{ + Max: 4, + MaxPerCore: 2, + Min: 1, + TCPCloseWaitTimeout: metav1.Duration{Duration: 10 * time.Second}, + TCPEstablishedTimeout: metav1.Duration{Duration: 20 * time.Second}, + }, + FeatureGates: "all", + HealthzBindAddress: tc.healthzBindAddress, + HostnameOverride: "foo", + IPTables: componentconfig.KubeProxyIPTablesConfiguration{ + MasqueradeAll: true, + MasqueradeBit: util.Int32Ptr(17), + MinSyncPeriod: metav1.Duration{Duration: 10 * time.Second}, + SyncPeriod: metav1.Duration{Duration: 60 * time.Second}, + }, + MetricsBindAddress: tc.metricsBindAddress, + Mode: "iptables", + OOMScoreAdj: util.Int32Ptr(17), + PortRange: "2-7", + ResourceContainer: "/foo", + UDPIdleTimeout: metav1.Duration{Duration: 123 * time.Millisecond}, + } - config, err := options.loadConfig([]byte(yaml)) - assert.NoError(t, err) - if !reflect.DeepEqual(expected, config) { - t.Fatalf("unexpected config, diff = %s", diff.ObjectDiff(config, expected)) + options, err := NewOptions() + assert.NoError(t, err, "unexpected error for %s: %v", tc.name, err) + + yaml := fmt.Sprintf( + yamlTemplate, tc.bindAddress, tc.clusterCIDR, + tc.healthzBindAddress, tc.metricsBindAddress) + config, err := options.loadConfig([]byte(yaml)) + assert.NoError(t, err, "unexpected error for %s: %v", tc.name, err) + if !reflect.DeepEqual(expected, config) { + t.Fatalf("unexpected config for %s test, diff = %s", tc.name, diff.ObjectDiff(config, expected)) + } + } +} + +// TestLoadConfigFailures tests failure modes for loadConfig() +func TestLoadConfigFailures(t *testing.T) { + testCases := []struct { + name string + config string + expErr string + }{ + { + name: "Decode error test", + config: "Twas bryllyg, and ye slythy toves", + expErr: "could not find expected ':'", + }, + { + name: "Bad config type test", + config: "kind: KubeSchedulerConfiguration", + expErr: "unexpected config type", + }, + } + version := "apiVersion: componentconfig/v1alpha1" + for _, tc := range testCases { + options, _ := NewOptions() + config := fmt.Sprintf("%s\n%s", version, tc.config) + _, err := options.loadConfig([]byte(config)) + if assert.Error(t, err, tc.name) { + assert.Contains(t, err.Error(), tc.expErr, tc.name) + } } } From f244e3cb7c1b617cba32f29902f068f57c97ffad Mon Sep 17 00:00:00 2001 From: zhangxiaoyu-zidif Date: Tue, 13 Jun 2017 19:48:42 +0800 Subject: [PATCH 028/448] delete unused return --- test/e2e/scheduling/predicates.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/test/e2e/scheduling/predicates.go b/test/e2e/scheduling/predicates.go index d104c987458..ae636eb8fb5 100644 --- a/test/e2e/scheduling/predicates.go +++ b/test/e2e/scheduling/predicates.go @@ -276,7 +276,7 @@ var _ = framework.KubeDescribe("SchedulerPredicates [Serial]", func() { By("Trying to relaunch the pod, now with labels.") labelPodName := "with-labels" - _ = createPausePod(f, pausePodConfig{ + createPausePod(f, pausePodConfig{ Name: labelPodName, NodeSelector: map[string]string{ "kubernetes.io/hostname": nodeName, @@ -350,7 +350,7 @@ var _ = framework.KubeDescribe("SchedulerPredicates [Serial]", func() { By("Trying to relaunch the pod, now with labels.") labelPodName := "with-labels" - _ = createPausePod(f, pausePodConfig{ + createPausePod(f, pausePodConfig{ Name: labelPodName, Affinity: &v1.Affinity{ NodeAffinity: &v1.NodeAffinity{ @@ -463,7 +463,7 @@ var _ = framework.KubeDescribe("SchedulerPredicates [Serial]", func() { By("Trying to launch the pod, now with podAffinity.") labelPodName := "with-podaffinity-" + string(uuid.NewUUID()) - _ = createPausePod(f, pausePodConfig{ + createPausePod(f, pausePodConfig{ Name: labelPodName, Affinity: &v1.Affinity{ PodAffinity: &v1.PodAffinity{ @@ -574,7 +574,7 @@ var _ = framework.KubeDescribe("SchedulerPredicates [Serial]", func() { By("Trying to launch the pod, now with multiple pod affinities with diff LabelOperators.") labelPodName := "with-podaffinity-" + string(uuid.NewUUID()) - _ = createPausePod(f, pausePodConfig{ + createPausePod(f, pausePodConfig{ Name: labelPodName, Affinity: &v1.Affinity{ PodAffinity: &v1.PodAffinity{ @@ -689,7 +689,7 @@ var _ = framework.KubeDescribe("SchedulerPredicates [Serial]", func() { By("Trying to relaunch the pod, now with tolerations.") tolerationPodName := "with-tolerations" - _ = createPausePod(f, pausePodConfig{ + createPausePod(f, pausePodConfig{ Name: tolerationPodName, Tolerations: []v1.Toleration{{Key: testTaint.Key, Value: testTaint.Value, Effect: testTaint.Effect}}, NodeSelector: map[string]string{labelKey: labelValue}, From da1bea34276e4f540607db7205262688f42b0d73 Mon Sep 17 00:00:00 2001 From: "Timothy St. Clair" Date: Tue, 13 Jun 2017 09:07:39 -0500 Subject: [PATCH 029/448] Add timothysc to kubeadm reviewers --- cmd/kubeadm/OWNERS | 1 + 1 file changed, 1 insertion(+) diff --git a/cmd/kubeadm/OWNERS b/cmd/kubeadm/OWNERS index 7987f09f4d0..77bb47edbcf 100644 --- a/cmd/kubeadm/OWNERS +++ b/cmd/kubeadm/OWNERS @@ -12,3 +12,4 @@ reviewers: - lukemarsden - dmmcquay - krousey +- timothysc From b99e57149d81aef8b0bbb3181f851257d18a2569 Mon Sep 17 00:00:00 2001 From: ymqytw Date: Tue, 13 Jun 2017 14:53:09 -0700 Subject: [PATCH 030/448] fix env flag --- pkg/kubectl/cmd/run.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/kubectl/cmd/run.go b/pkg/kubectl/cmd/run.go index 831fea073dd..910efa48f34 100644 --- a/pkg/kubectl/cmd/run.go +++ b/pkg/kubectl/cmd/run.go @@ -117,7 +117,7 @@ func addRunFlags(cmd *cobra.Command) { cmd.Flags().IntP("replicas", "r", 1, "Number of replicas to create for this container. Default is 1.") cmd.Flags().Bool("rm", false, "If true, delete resources created in this command for attached containers.") 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().StringSlice("env", []string{}, "Environment variables to set in the container") + cmd.Flags().StringArray("env", []string{}, "Environment variables to set in the container") 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().Int("hostport", -1, "The host port mapping for the container port. To demonstrate a single-machine container.") cmd.Flags().StringP("labels", "l", "", "Labels to apply to the pod(s).") @@ -257,7 +257,7 @@ func Run(f cmdutil.Factory, cmdIn io.Reader, cmdOut, cmdErr io.Writer, cmd *cobr params["args"] = args[1:] } - params["env"] = cmdutil.GetFlagStringSlice(cmd, "env") + params["env"] = cmdutil.GetFlagStringArray(cmd, "env") obj, _, mapper, mapping, err := createGeneratedObject(f, cmd, generator, names, params, cmdutil.GetFlagString(cmd, "overrides"), namespace) if err != nil { From ec3bbf733dae25321bc644a802fc20708763c710 Mon Sep 17 00:00:00 2001 From: Ma Shimiao Date: Wed, 14 Jun 2017 11:54:23 +0800 Subject: [PATCH 031/448] remove unneeded variable Signed-off-by: Ma Shimiao --- cmd/cloud-controller-manager/app/controllermanager.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/cmd/cloud-controller-manager/app/controllermanager.go b/cmd/cloud-controller-manager/app/controllermanager.go index e2defbcb917..cac86a4ced8 100644 --- a/cmd/cloud-controller-manager/app/controllermanager.go +++ b/cmd/cloud-controller-manager/app/controllermanager.go @@ -253,9 +253,8 @@ func StartControllers(s *options.CloudControllerManagerServer, kubeconfig *restc // 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. - var versionStrings []string err = wait.PollImmediate(time.Second, 10*time.Second, func() (bool, error) { - if versionStrings, err = restclient.ServerAPIVersions(kubeconfig); err == nil { + if _, err = restclient.ServerAPIVersions(kubeconfig); err == nil { return true, nil } glog.Errorf("Failed to get api versions from server: %v", err) From 22e4abafaec6408675eb0832aa95a0586090518e Mon Sep 17 00:00:00 2001 From: zhangxiaoyu-zidif Date: Wed, 14 Jun 2017 20:57:48 +0800 Subject: [PATCH 032/448] Refactor slice intersection --- .../scheduler/algorithm/predicates/predicates.go | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/plugin/pkg/scheduler/algorithm/predicates/predicates.go b/plugin/pkg/scheduler/algorithm/predicates/predicates.go index 95939bf5043..5f286def512 100644 --- a/plugin/pkg/scheduler/algorithm/predicates/predicates.go +++ b/plugin/pkg/scheduler/algorithm/predicates/predicates.go @@ -886,11 +886,17 @@ func PodFitsHostPorts(pod *v1.Pod, meta interface{}, nodeInfo *schedulercache.No // search two arrays and return true if they have at least one common element; return false otherwise func haveSame(a1, a2 []string) bool { - for _, val1 := range a1 { - for _, val2 := range a2 { - if val1 == val2 { - return true - } + m := map[string]int{} + + for _, val := range a1 { + m[val] = 1 + } + for _, val := range a2 { + m[val] = m[val] + 1 + } + for _, val := range m { + if val > 1 { + return true } } return false From 404cda27777133b225f1484949a52a850187d0e4 Mon Sep 17 00:00:00 2001 From: Yang Guo Date: Wed, 14 Jun 2017 11:44:25 -0700 Subject: [PATCH 033/448] Changes node e2e tests to use new Ubuntu image --- test/e2e_node/jenkins/image-config-serial.yaml | 9 +++------ test/e2e_node/jenkins/image-config.yaml | 9 +++------ 2 files changed, 6 insertions(+), 12 deletions(-) diff --git a/test/e2e_node/jenkins/image-config-serial.yaml b/test/e2e_node/jenkins/image-config-serial.yaml index 359bbcdb77f..70e0801f389 100644 --- a/test/e2e_node/jenkins/image-config-serial.yaml +++ b/test/e2e_node/jenkins/image-config-serial.yaml @@ -2,12 +2,9 @@ # `gcloud compute --project disks create --image=https://www.googleapis.com/compute/v1/projects//global/images/` # `gcloud compute --project images create --source-disk=` images: - ubuntu-docker10: - image: e2e-node-ubuntu-trusty-docker10-v2-image # docker 1.10.3 - project: kubernetes-node-e2e-images - ubuntu-docker12: - image: e2e-node-ubuntu-trusty-docker12-v2-image # docker 1.12.6 - project: kubernetes-node-e2e-images + ubuntu: + image: ubuntu-gke-1604-xenial-v20170420-1 # docker 1.12.6 + project: ubuntu-os-gke-cloud coreos-alpha: image: coreos-alpha-1122-0-0-v20160727 # docker 1.11.2 project: coreos-cloud diff --git a/test/e2e_node/jenkins/image-config.yaml b/test/e2e_node/jenkins/image-config.yaml index 735a2683502..25f4fd503bb 100644 --- a/test/e2e_node/jenkins/image-config.yaml +++ b/test/e2e_node/jenkins/image-config.yaml @@ -2,12 +2,9 @@ # `gcloud compute --project disks create --image=https://www.googleapis.com/compute/v1/projects//global/images/` # `gcloud compute --project images create --source-disk=` images: - ubuntu-docker10: - image: e2e-node-ubuntu-trusty-docker10-v2-image # docker 1.10.3 - project: kubernetes-node-e2e-images - ubuntu-docker12: - image: e2e-node-ubuntu-trusty-docker12-v2-image # docker 1.12.6 - project: kubernetes-node-e2e-images + ubuntu: + image: ubuntu-gke-1604-xenial-v20170420-1 # docker 1.12.6 + project: ubuntu-os-gke-cloud coreos-alpha: image: coreos-alpha-1122-0-0-v20160727 # docker 1.11.2 project: coreos-cloud From 6abed5883f163231c6ee9e8eccd03ce1807ef511 Mon Sep 17 00:00:00 2001 From: xilabao Date: Tue, 13 Jun 2017 17:27:05 +0800 Subject: [PATCH 034/448] print non-existent key in configmap --- pkg/volume/configmap/configmap.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/pkg/volume/configmap/configmap.go b/pkg/volume/configmap/configmap.go index 4e869293bd7..61c6d4cc542 100644 --- a/pkg/volume/configmap/configmap.go +++ b/pkg/volume/configmap/configmap.go @@ -266,9 +266,7 @@ func MakePayload(mappings []v1.KeyToPath, configMap *v1.ConfigMap, defaultMode * if optional { continue } - err_msg := "references non-existent config key" - glog.Errorf(err_msg) - return nil, fmt.Errorf(err_msg) + return nil, fmt.Errorf("configmap references non-existent config key: %s", ktp.Key) } fileProjection.Data = []byte(content) From 285ac8935f7b29603251f420a51f0465b7f8c0cf Mon Sep 17 00:00:00 2001 From: Mitsuhiro Tanino Date: Thu, 15 Jun 2017 18:00:29 -0400 Subject: [PATCH 035/448] iSCSi plugin: Remove redundant nil check --- pkg/volume/iscsi/iscsi_util.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/volume/iscsi/iscsi_util.go b/pkg/volume/iscsi/iscsi_util.go index 7190859b542..9b5d3cb7a59 100755 --- a/pkg/volume/iscsi/iscsi_util.go +++ b/pkg/volume/iscsi/iscsi_util.go @@ -114,7 +114,7 @@ func waitForPathToExistInternal(devicePath *string, maxRetries int, deviceTransp if err == nil { return true } - if err != nil && !os.IsNotExist(err) { + if !os.IsNotExist(err) { return false } if i == maxRetries-1 { From 882c9b61bd7858fba626bdbf452b68272f2f4ea1 Mon Sep 17 00:00:00 2001 From: ravisantoshgudimetla Date: Sun, 18 Jun 2017 16:38:56 -0400 Subject: [PATCH 036/448] Small fix for number of pods and nodes in test function --- test/integration/scheduler_perf/scheduler_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/integration/scheduler_perf/scheduler_test.go b/test/integration/scheduler_perf/scheduler_test.go index f3fc6e4ec14..da355a1a4c8 100644 --- a/test/integration/scheduler_perf/scheduler_test.go +++ b/test/integration/scheduler_perf/scheduler_test.go @@ -42,7 +42,7 @@ func TestSchedule100Node3KPods(t *testing.T) { if testing.Short() { t.Skip("Skipping because we want to run short tests") } - config := getBaseConfig(1000, 30000) + config := getBaseConfig(100, 3000) writePodAndNodeTopologyToConfig(config) min := schedulePods(config) if min < threshold3K { From e7f6376b1a920b2fb7d5b3298b339c2b47725a4e Mon Sep 17 00:00:00 2001 From: xilabao Date: Thu, 9 Mar 2017 14:08:34 +0800 Subject: [PATCH 037/448] add extra args validate --- cmd/kubeadm/app/preflight/BUILD | 4 ++ cmd/kubeadm/app/preflight/checks.go | 49 ++++++++++++++++++++++++ cmd/kubeadm/app/preflight/checks_test.go | 11 ++++++ 3 files changed, 64 insertions(+) diff --git a/cmd/kubeadm/app/preflight/BUILD b/cmd/kubeadm/app/preflight/BUILD index c3fcafba251..19adbf9ab09 100644 --- a/cmd/kubeadm/app/preflight/BUILD +++ b/cmd/kubeadm/app/preflight/BUILD @@ -13,15 +13,19 @@ go_library( srcs = ["checks.go"], tags = ["automanaged"], deps = [ + "//cmd/kube-apiserver/app/options:go_default_library", + "//cmd/kube-controller-manager/app/options:go_default_library", "//cmd/kubeadm/app/apis/kubeadm:go_default_library", "//cmd/kubeadm/app/constants:go_default_library", "//pkg/api/validation:go_default_library", "//pkg/kubeapiserver/authorizer/modes:go_default_library", "//pkg/util/initsystem:go_default_library", "//pkg/util/node:go_default_library", + "//plugin/cmd/kube-scheduler/app/options: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", ], ) diff --git a/cmd/kubeadm/app/preflight/checks.go b/cmd/kubeadm/app/preflight/checks.go index 3ebbd6f38ee..133a12758b5 100644 --- a/cmd/kubeadm/app/preflight/checks.go +++ b/cmd/kubeadm/app/preflight/checks.go @@ -35,15 +35,19 @@ import ( "github.com/PuerkitoBio/purell" "github.com/blang/semver" + "github.com/spf13/pflag" "net/url" + apiservoptions "k8s.io/kubernetes/cmd/kube-apiserver/app/options" + cmoptions "k8s.io/kubernetes/cmd/kube-controller-manager/app/options" kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants" "k8s.io/kubernetes/pkg/api/validation" authzmodes "k8s.io/kubernetes/pkg/kubeapiserver/authorizer/modes" "k8s.io/kubernetes/pkg/util/initsystem" "k8s.io/kubernetes/pkg/util/node" + schoptions "k8s.io/kubernetes/plugin/cmd/kube-scheduler/app/options" "k8s.io/kubernetes/test/e2e_node/system" ) @@ -313,6 +317,46 @@ func (hst HTTPProxyCheck) 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 +} + +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.NewCMServer() + s.AddFlags(flags, []string{}, []string{}) + warnings = append(warnings, argsCheck("kube-controller-manager", eac.ControllerManagerExtraArgs, flags)...) + } + if len(eac.SchedulerExtraArgs) > 0 { + flags := pflag.NewFlagSet("", pflag.ContinueOnError) + s := schoptions.NewSchedulerServer() + s.AddFlags(flags) + warnings = append(warnings, argsCheck("kube-scheduler", eac.SchedulerExtraArgs, flags)...) + } + return warnings, nil +} + type SystemVerificationCheck struct{} func (sysver SystemVerificationCheck) Check() (warnings, errors []error) { @@ -509,6 +553,11 @@ func RunInitMasterChecks(cfg *kubeadmapi.MasterConfiguration) error { InPathCheck{executable: "socat", mandatory: false}, InPathCheck{executable: "tc", mandatory: false}, InPathCheck{executable: "touch", mandatory: false}, + ExtraArgsCheck{ + APIServerExtraArgs: cfg.APIServerExtraArgs, + ControllerManagerExtraArgs: cfg.ControllerManagerExtraArgs, + SchedulerExtraArgs: cfg.SchedulerExtraArgs, + }, } if len(cfg.Etcd.Endpoints) == 0 { diff --git a/cmd/kubeadm/app/preflight/checks_test.go b/cmd/kubeadm/app/preflight/checks_test.go index f575b8d8238..f790f354291 100644 --- a/cmd/kubeadm/app/preflight/checks_test.go +++ b/cmd/kubeadm/app/preflight/checks_test.go @@ -239,6 +239,17 @@ func TestRunChecks(t *testing.T) { {[]Checker{FileContentCheck{Path: "/", Content: []byte("does not exist")}}, false, ""}, {[]Checker{InPathCheck{executable: "foobarbaz"}}, true, "[preflight] WARNING: foobarbaz not found in system path\n"}, {[]Checker{InPathCheck{executable: "foobarbaz", mandatory: true}}, 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, "[preflight] WARNING: kube-apiserver: failed to parse extra argument --secure-port=foo\n"}, + {[]Checker{ExtraArgsCheck{ + APIServerExtraArgs: map[string]string{"invalid-argument": "foo"}, + }}, true, "[preflight] WARNING: kube-apiserver: failed to parse extra argument --invalid-argument=foo\n"}, } for _, rt := range tokenTest { buf := new(bytes.Buffer) From 867790faa3f98fe4de8707890428bf5baaca8121 Mon Sep 17 00:00:00 2001 From: yiqinguo <468894985@qq.com> Date: Wed, 21 Jun 2017 15:15:22 +0800 Subject: [PATCH 038/448] Remove repeat type conversions --- pkg/kubelet/config/common.go | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/pkg/kubelet/config/common.go b/pkg/kubelet/config/common.go index cd4b62d98d6..7c31fabedad 100644 --- a/pkg/kubelet/config/common.go +++ b/pkg/kubelet/config/common.go @@ -109,12 +109,14 @@ func tryDecodeSinglePod(data []byte, defaultFn defaultFunc) (parsed bool, pod *v if err != nil { return false, pod, err } + + newPod, ok := obj.(*api.Pod) // Check whether the object could be converted to single pod. - if _, ok := obj.(*api.Pod); !ok { + if !ok { err = fmt.Errorf("invalid pod: %#v", obj) return false, pod, err } - newPod := obj.(*api.Pod) + // Apply default values and validate the pod. if err = defaultFn(newPod); err != nil { return true, pod, err @@ -135,12 +137,14 @@ func tryDecodePodList(data []byte, defaultFn defaultFunc) (parsed bool, pods v1. if err != nil { return false, pods, err } + + newPods, ok := obj.(*api.PodList) // Check whether the object could be converted to list of pods. - if _, ok := obj.(*api.PodList); !ok { + if !ok { err = fmt.Errorf("invalid pods list: %#v", obj) return false, pods, err } - newPods := obj.(*api.PodList) + // Apply default values and validate pods. for i := range newPods.Items { newPod := &newPods.Items[i] From a990e60193565d8433e21141e182093b3b602763 Mon Sep 17 00:00:00 2001 From: Paul Tyng Date: Mon, 19 Jun 2017 08:23:42 -0400 Subject: [PATCH 039/448] Set default User-Agent on http probe If unspecified in probe definition, User-Agent will be set to `kube-probe/` on httpGet probe types instead of the default Go User-Agent. --- pkg/probe/http/BUILD | 1 + pkg/probe/http/http.go | 9 +++++++ pkg/probe/http/http_test.go | 50 +++++++++++++++++++++++++++++-------- 3 files changed, 49 insertions(+), 11 deletions(-) diff --git a/pkg/probe/http/BUILD b/pkg/probe/http/BUILD index c7e22d2c769..8109f37279f 100644 --- a/pkg/probe/http/BUILD +++ b/pkg/probe/http/BUILD @@ -14,6 +14,7 @@ go_library( tags = ["automanaged"], deps = [ "//pkg/probe:go_default_library", + "//pkg/version:go_default_library", "//vendor/github.com/golang/glog:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/net:go_default_library", ], diff --git a/pkg/probe/http/http.go b/pkg/probe/http/http.go index d0744e792ea..b9821be05fc 100644 --- a/pkg/probe/http/http.go +++ b/pkg/probe/http/http.go @@ -26,6 +26,7 @@ import ( utilnet "k8s.io/apimachinery/pkg/util/net" "k8s.io/kubernetes/pkg/probe" + "k8s.io/kubernetes/pkg/version" "github.com/golang/glog" ) @@ -68,6 +69,14 @@ func DoHTTPProbe(url *url.URL, headers http.Header, client HTTPGetInterface) (pr // Convert errors into failures to catch timeouts. return probe.Failure, err.Error(), nil } + if _, ok := headers["User-Agent"]; !ok { + if headers == nil { + headers = http.Header{} + } + // explicitly set User-Agent so it's not set to default Go value + v := version.Get() + headers.Set("User-Agent", fmt.Sprintf("kube-probe/%s.%s", v.Major, v.Minor)) + } req.Header = headers if headers.Get("Host") != "" { req.Host = headers.Get("Host") diff --git a/pkg/probe/http/http_test.go b/pkg/probe/http/http_test.go index c1cf9a2c2c7..6e9efb86d29 100644 --- a/pkg/probe/http/http_test.go +++ b/pkg/probe/http/http_test.go @@ -40,12 +40,25 @@ func TestHTTPProbeChecker(t *testing.T) { } } + // Echo handler that returns the contents of request headers in the body + headerEchoHandler := func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(200) + output := "" + for k, arr := range r.Header { + for _, v := range arr { + output += fmt.Sprintf("%s: %s\n", k, v) + } + } + w.Write([]byte(output)) + } + prober := New() testCases := []struct { handler func(w http.ResponseWriter, r *http.Request) reqHeaders http.Header health probe.Result accBody string + notBody string }{ // The probe will be filled in below. This is primarily testing that an HTTP GET happens. { @@ -54,23 +67,35 @@ func TestHTTPProbeChecker(t *testing.T) { accBody: "ok body", }, { - // Echo handler that returns the contents of request headers in the body - handler: func(w http.ResponseWriter, r *http.Request) { - w.WriteHeader(200) - output := "" - for k, arr := range r.Header { - for _, v := range arr { - output += fmt.Sprintf("%s: %s\n", k, v) - } - } - w.Write([]byte(output)) - }, + handler: headerEchoHandler, reqHeaders: http.Header{ "X-Muffins-Or-Cupcakes": {"muffins"}, }, health: probe.Success, accBody: "X-Muffins-Or-Cupcakes: muffins", }, + { + handler: headerEchoHandler, + reqHeaders: http.Header{ + "User-Agent": {"foo/1.0"}, + }, + health: probe.Success, + accBody: "User-Agent: foo/1.0", + }, + { + handler: headerEchoHandler, + reqHeaders: http.Header{ + "User-Agent": {""}, + }, + health: probe.Success, + notBody: "User-Agent", + }, + { + handler: headerEchoHandler, + reqHeaders: http.Header{}, + health: probe.Success, + accBody: "User-Agent: kube-probe/", + }, { // Echo handler that returns the contents of Host in the body handler: func(w http.ResponseWriter, r *http.Request) { @@ -130,6 +155,9 @@ func TestHTTPProbeChecker(t *testing.T) { if !strings.Contains(output, test.accBody) { t.Errorf("Expected response body to contain %v, got %v", test.accBody, output) } + if test.notBody != "" && strings.Contains(output, test.notBody) { + t.Errorf("Expected response not to contain %v, got %v", test.notBody, output) + } } }() } From 5100925a90a4affe1220e40fa8b49675f1be9baf Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Wed, 21 Jun 2017 11:04:08 -0500 Subject: [PATCH 040/448] dockershim: checkpoint HostNetwork property To ensure kubelet doesn't attempt network teardown on HostNetwork containers that no longer exist but are still checkpointed, make sure we preserve the HostNetwork property in checkpoints. If the checkpoint indicates the container was a HostNetwork one, don't tear down the network since that would fail anyway. Related: https://github.com/kubernetes/kubernetes/issues/44307#issuecomment-299548609 --- pkg/kubelet/dockershim/docker_checkpoint.go | 1 + pkg/kubelet/dockershim/docker_checkpoint_test.go | 9 +++++++-- pkg/kubelet/dockershim/docker_sandbox.go | 13 +++++++------ 3 files changed, 15 insertions(+), 8 deletions(-) diff --git a/pkg/kubelet/dockershim/docker_checkpoint.go b/pkg/kubelet/dockershim/docker_checkpoint.go index 6d0136c56fa..6ad1d794169 100644 --- a/pkg/kubelet/dockershim/docker_checkpoint.go +++ b/pkg/kubelet/dockershim/docker_checkpoint.go @@ -50,6 +50,7 @@ type PortMapping struct { // CheckpointData contains all types of data that can be stored in the checkpoint. type CheckpointData struct { PortMappings []*PortMapping `json:"port_mappings,omitempty"` + HostNetwork bool `json:"host_network,omitempty"` } // PodSandboxCheckpoint is the checkpoint structure for a sandbox diff --git a/pkg/kubelet/dockershim/docker_checkpoint_test.go b/pkg/kubelet/dockershim/docker_checkpoint_test.go index 477c9204d90..c10b8f1e502 100644 --- a/pkg/kubelet/dockershim/docker_checkpoint_test.go +++ b/pkg/kubelet/dockershim/docker_checkpoint_test.go @@ -48,18 +48,22 @@ func TestPersistentCheckpointHandler(t *testing.T) { &port443, }, } + checkpoint1.Data.HostNetwork = true checkpoints := []struct { - podSandboxID string - checkpoint *PodSandboxCheckpoint + podSandboxID string + checkpoint *PodSandboxCheckpoint + expectHostNetwork bool }{ { "id1", checkpoint1, + true, }, { "id2", NewPodSandboxCheckpoint("ns2", "sandbox2"), + false, }, } @@ -72,6 +76,7 @@ func TestPersistentCheckpointHandler(t *testing.T) { 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() diff --git a/pkg/kubelet/dockershim/docker_sandbox.go b/pkg/kubelet/dockershim/docker_sandbox.go index 70c5bcb0ded..b1240cce5bc 100644 --- a/pkg/kubelet/dockershim/docker_sandbox.go +++ b/pkg/kubelet/dockershim/docker_sandbox.go @@ -171,14 +171,14 @@ func (ds *dockerService) RunPodSandbox(config *runtimeapi.PodSandboxConfig) (id // after us? func (ds *dockerService) StopPodSandbox(podSandboxID string) error { var namespace, name string + var hostNetwork bool var checkpointErr, statusErr error - needNetworkTearDown := false // Try to retrieve sandbox information from docker daemon or sandbox checkpoint status, statusErr := ds.PodSandboxStatus(podSandboxID) if statusErr == nil { nsOpts := status.GetLinux().GetNamespaces().GetOptions() - needNetworkTearDown = nsOpts != nil && !nsOpts.HostNetwork + hostNetwork = nsOpts != nil && nsOpts.HostNetwork m := status.GetMetadata() namespace = m.Namespace name = m.Name @@ -211,10 +211,8 @@ func (ds *dockerService) StopPodSandbox(podSandboxID string) error { } else { namespace = checkpoint.Namespace name = checkpoint.Name + hostNetwork = checkpoint.Data != nil && checkpoint.Data.HostNetwork } - - // Always trigger network plugin to tear down - needNetworkTearDown = true } // WARNING: The following operations made the following assumption: @@ -226,7 +224,7 @@ func (ds *dockerService) StopPodSandbox(podSandboxID string) error { // since it is stopped. With empty network namespcae, CNI bridge plugin will conduct best // effort clean up and will not return error. errList := []error{} - if needNetworkTearDown { + if !hostNetwork { cID := kubecontainer.BuildContainerID(runtimeName, podSandboxID) err := ds.network.TearDownPod(namespace, name, cID) if err == nil { @@ -642,6 +640,9 @@ func constructPodSandboxCheckpoint(config *runtimeapi.PodSandboxConfig) *PodSand Protocol: &proto, }) } + if nsOptions := config.GetLinux().GetSecurityContext().GetNamespaceOptions(); nsOptions != nil { + checkpoint.Data.HostNetwork = nsOptions.HostNetwork + } return checkpoint } From 65b2f71ee7faa0f85aea4a02713380a7bb8334d4 Mon Sep 17 00:00:00 2001 From: Koonwah Chen Date: Wed, 21 Jun 2017 15:27:10 -0700 Subject: [PATCH 041/448] Add ApiEndpoint support to GCE config. --- pkg/cloudprovider/providers/gce/gce.go | 51 ++++++++++++++++---------- 1 file changed, 32 insertions(+), 19 deletions(-) diff --git a/pkg/cloudprovider/providers/gce/gce.go b/pkg/cloudprovider/providers/gce/gce.go index 90e2570a429..4e60519daaf 100644 --- a/pkg/cloudprovider/providers/gce/gce.go +++ b/pkg/cloudprovider/providers/gce/gce.go @@ -137,6 +137,7 @@ type Config struct { NodeTags []string `gcfg:"node-tags"` NodeInstancePrefix string `gcfg:"node-instance-prefix"` Multizone bool `gcfg:"multizone"` + ApiEndpoint string `gcfg:"api-endpoint"` } } @@ -155,6 +156,7 @@ func (g *GCECloud) GetComputeService() *compute.Service { // newGCECloud creates a new instance of GCECloud. func newGCECloud(config io.Reader) (*GCECloud, error) { + apiEndpoint := "" projectID, zone, err := getProjectAndZone() if err != nil { return nil, err @@ -169,7 +171,7 @@ func newGCECloud(config io.Reader) (*GCECloud, error) { if err != nil { return nil, err } - networkURL := gceNetworkURL(projectID, networkName) + networkURL := gceNetworkURL(apiEndpoint, projectID, networkName) subnetworkURL := "" // By default, Kubernetes clusters only run against one zone @@ -185,22 +187,23 @@ func newGCECloud(config io.Reader) (*GCECloud, error) { return nil, err } glog.Infof("Using GCE provider config %+v", cfg) + if cfg.Global.ApiEndpoint != "" { + apiEndpoint = cfg.Global.ApiEndpoint + } if cfg.Global.ProjectID != "" { projectID = cfg.Global.ProjectID } - if cfg.Global.NetworkName != "" { - if strings.Contains(cfg.Global.NetworkName, "/") { - networkURL = cfg.Global.NetworkName - } else { - networkURL = gceNetworkURL(cfg.Global.ProjectID, cfg.Global.NetworkName) - } + + if cfg.Global.NetworkName != "" && strings.Contains(cfg.Global.NetworkName, "/"){ + networkURL = cfg.Global.NetworkName + }else { + networkURL = gceNetworkURL(apiEndpoint, projectID, networkName) } - if cfg.Global.SubnetworkName != "" { - if strings.Contains(cfg.Global.SubnetworkName, "/") { + + if cfg.Global.SubnetworkName != "" && strings.Contains(cfg.Global.SubnetworkName, "/"){ subnetworkURL = cfg.Global.SubnetworkName - } else { - subnetworkURL = gceSubnetworkURL(cfg.Global.ProjectID, region, cfg.Global.SubnetworkName) - } + }else { + subnetworkURL = gceSubnetworkURL(apiEndpoint, cfg.Global.ProjectID, region, cfg.Global.SubnetworkName) } if cfg.Global.TokenURL != "" { tokenSource = NewAltTokenSource(cfg.Global.TokenURL, cfg.Global.TokenBody) @@ -212,7 +215,7 @@ func newGCECloud(config io.Reader) (*GCECloud, error) { } } - return CreateGCECloud(projectID, region, zone, managedZones, networkURL, subnetworkURL, + return CreateGCECloud(apiEndpoint, projectID, region, zone, managedZones, networkURL, subnetworkURL, nodeTags, nodeInstancePrefix, tokenSource, true /* useMetadataServer */) } @@ -220,7 +223,7 @@ func newGCECloud(config io.Reader) (*GCECloud, error) { // If no networkUrl is specified, loads networkName via rest call. // If no tokenSource is specified, uses oauth2.DefaultTokenSource. // If managedZones is nil / empty all zones in the region will be managed. -func CreateGCECloud(projectID, region, zone string, managedZones []string, networkURL, subnetworkURL string, nodeTags []string, +func CreateGCECloud(apiEndpoint, projectID, region, zone string, managedZones []string, networkURL, subnetworkURL string, nodeTags []string, nodeInstancePrefix string, tokenSource oauth2.TokenSource, useMetadataServer bool) (*GCECloud, error) { client, err := newOauthClient(tokenSource) @@ -233,6 +236,10 @@ func CreateGCECloud(projectID, region, zone string, managedZones []string, netwo return nil, err } + if apiEndpoint != "" { + service.BasePath = fmt.Sprintf("%sprojects/", apiEndpoint) + } + client, err = newOauthClient(tokenSource) serviceBeta, err := computebeta.New(client) if err != nil { @@ -249,7 +256,7 @@ func CreateGCECloud(projectID, region, zone string, managedZones []string, netwo if err != nil { return nil, err } - networkURL = gceNetworkURL(projectID, networkName) + networkURL = gceNetworkURL(apiEndpoint, projectID, networkName) } networkProjectID, err := getProjectIDInURL(networkURL) @@ -365,12 +372,18 @@ func (gce *GCECloud) ScrubDNS(nameservers, searches []string) (nsOut, srchOut [] // GCECloud implements cloudprovider.Interface. var _ cloudprovider.Interface = (*GCECloud)(nil) -func gceNetworkURL(project, network string) string { - return fmt.Sprintf("https://www.googleapis.com/compute/v1/projects/%s/global/networks/%s", project, network) +func gceNetworkURL(api_endpoint, project, network string) string { + if api_endpoint == "" { + api_endpoint = "https://www.googleapis.com/compute/v1/" + } + return fmt.Sprintf("%sprojects/%s/global/networks/%s", api_endpoint, project, network) } -func gceSubnetworkURL(project, region, subnetwork string) string { - return fmt.Sprintf("https://www.googleapis.com/compute/v1/projects/%s/regions/%s/subnetworks/%s", project, region, subnetwork) +func gceSubnetworkURL(api_endpoint, project, region, subnetwork string) string { + if api_endpoint == "" { + api_endpoint = "https://www.googleapis.com/compute/v1/" + } + return fmt.Sprintf("%sprojects/%s/regions/%s/subnetworks/%s", api_endpoint, project, region, subnetwork) } // getProjectIDInURL parses typical full resource URLS and shorter URLS From 4ee6b42a4d26d79f7d2694d95963fcd5b32b3369 Mon Sep 17 00:00:00 2001 From: Cao Shufeng Date: Fri, 16 Jun 2017 17:57:07 +0800 Subject: [PATCH 042/448] Fix invalid filename in kubelet log Fixes: https://github.com/kubernetes/kubernetes/issues/47641 --- pkg/kubelet/config/file.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pkg/kubelet/config/file.go b/pkg/kubelet/config/file.go index 421d19fa992..cb4ae650e5c 100644 --- a/pkg/kubelet/config/file.go +++ b/pkg/kubelet/config/file.go @@ -23,6 +23,7 @@ import ( "os" "path/filepath" "sort" + "strings" "time" "github.com/golang/glog" @@ -44,6 +45,9 @@ type sourceFile struct { } 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 := new(path, nodeName, period, updates) glog.V(1).Infof("Watching path %q", path) go wait.Forever(config.run, period) From d170b0ca802b2ea7d18dc682d3376d19fa072e13 Mon Sep 17 00:00:00 2001 From: yiqinguo <468894985@qq.com> Date: Thu, 22 Jun 2017 20:17:28 +0800 Subject: [PATCH 043/448] Add type conversion judgment --- pkg/kubelet/dockershim/docker_service.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pkg/kubelet/dockershim/docker_service.go b/pkg/kubelet/dockershim/docker_service.go index 59cebc405fe..6a8a5b97e11 100644 --- a/pkg/kubelet/dockershim/docker_service.go +++ b/pkg/kubelet/dockershim/docker_service.go @@ -455,10 +455,13 @@ func (ds *dockerService) getDockerVersionFromCache() (*dockertypes.Version, erro // We only store on key in the cache. const dummyKey = "version" value, err := ds.versionCache.Get(dummyKey) - dv := value.(*dockertypes.Version) if err != nil { return nil, err } + dv, ok := value.(*dockertypes.Version) + if !ok { + return nil, fmt.Errorf("Converted to *dockertype.Version error") + } return dv, nil } From 890d356d5c788f85aa542ac945c12fc78fb8846c Mon Sep 17 00:00:00 2001 From: Koonwah Chen Date: Thu, 22 Jun 2017 14:57:21 -0700 Subject: [PATCH 044/448] update e2e for GCE ApiEndpoint support --- test/e2e/e2e.go | 3 ++- test/e2e/framework/test_context.go | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/test/e2e/e2e.go b/test/e2e/e2e.go index ee8d7fa76b2..7f7a46db593 100644 --- a/test/e2e/e2e.go +++ b/test/e2e/e2e.go @@ -80,7 +80,8 @@ func setupProviderConfig() error { if !framework.TestContext.CloudConfig.MultiZone { managedZones = []string{zone} } - cloudConfig.Provider, err = gcecloud.CreateGCECloud(framework.TestContext.CloudConfig.ProjectID, + cloudConfig.Provider, err = gcecloud.CreateGCECloud(framework.TestContext.CloudConfig.ApiEndpoint, + framework.TestContext.CloudConfig.ProjectID, region, zone, managedZones, "" /* networkUrl */, "" /* subnetworkUrl */, nil, /* nodeTags */ "" /* nodeInstancePerfix */, nil /* tokenSource */, false /* useMetadataServer */) if err != nil { diff --git a/test/e2e/framework/test_context.go b/test/e2e/framework/test_context.go index 07ed74b2822..b89780df1b0 100644 --- a/test/e2e/framework/test_context.go +++ b/test/e2e/framework/test_context.go @@ -133,6 +133,7 @@ type NodeTestContextType struct { } type CloudConfig struct { + ApiEndpoint string ProjectID string Zone string MultiZone bool @@ -203,6 +204,7 @@ func RegisterClusterFlags() { // TODO: Flags per provider? Rename gce-project/gce-zone? cloudConfig := &TestContext.CloudConfig flag.StringVar(&cloudConfig.MasterName, "kube-master", "", "Name of the kubernetes master. Only required if provider is gce or gke") + flag.StringVar(&cloudConfig.ApiEndpoint, "gce-api-endpoint", "", "The GCE ApiEndpoint being used, if applicable") flag.StringVar(&cloudConfig.ProjectID, "gce-project", "", "The GCE project being used, if applicable") flag.StringVar(&cloudConfig.Zone, "gce-zone", "", "GCE zone being used, if applicable") flag.BoolVar(&cloudConfig.MultiZone, "gce-multizone", false, "If true, start GCE cloud provider with multizone support.") From 38b060c4fd3dbdffb6fe307259cb73559d546586 Mon Sep 17 00:00:00 2001 From: wlan0 Date: Thu, 22 Jun 2017 16:11:10 -0700 Subject: [PATCH 045/448] enable docs and man page autogeneration for cloud-controller-manager --- cmd/genkubedocs/BUILD | 1 + cmd/genkubedocs/gen_kube_docs.go | 5 +++++ cmd/genman/BUILD | 1 + cmd/genman/gen_kube_man.go | 8 ++++++++ docs/.generated_docs | 2 ++ docs/admin/cloud-controller-manager.md | 3 +++ docs/man/man1/cloud-controller-manager.1 | 3 +++ hack/lib/util.sh | 2 ++ 8 files changed, 25 insertions(+) create mode 100644 docs/admin/cloud-controller-manager.md create mode 100644 docs/man/man1/cloud-controller-manager.1 diff --git a/cmd/genkubedocs/BUILD b/cmd/genkubedocs/BUILD index a947a1283d9..61f0c4f5133 100644 --- a/cmd/genkubedocs/BUILD +++ b/cmd/genkubedocs/BUILD @@ -19,6 +19,7 @@ go_library( srcs = ["gen_kube_docs.go"], tags = ["automanaged"], deps = [ + "//cmd/cloud-controller-manager/app:go_default_library", "//cmd/genutils:go_default_library", "//cmd/kube-apiserver/app:go_default_library", "//cmd/kube-controller-manager/app:go_default_library", diff --git a/cmd/genkubedocs/gen_kube_docs.go b/cmd/genkubedocs/gen_kube_docs.go index 0cdd763c661..faebb60e83b 100644 --- a/cmd/genkubedocs/gen_kube_docs.go +++ b/cmd/genkubedocs/gen_kube_docs.go @@ -21,6 +21,7 @@ import ( "os" "github.com/spf13/cobra/doc" + ccmapp "k8s.io/kubernetes/cmd/cloud-controller-manager/app" "k8s.io/kubernetes/cmd/genutils" apiservapp "k8s.io/kubernetes/cmd/kube-apiserver/app" cmapp "k8s.io/kubernetes/cmd/kube-controller-manager/app" @@ -56,6 +57,10 @@ func main() { // generate docs for kube-controller-manager controllermanager := cmapp.NewControllerManagerCommand() doc.GenMarkdownTree(controllermanager, outDir) + case "cloud-controller-manager": + // generate docs for cloud-controller-manager + cloudcontrollermanager := ccmapp.NewCloudControllerManagerCommand() + doc.GenMarkdownTree(cloudcontrollermanager, outDir) case "kube-proxy": // generate docs for kube-proxy proxy := proxyapp.NewProxyCommand() diff --git a/cmd/genman/BUILD b/cmd/genman/BUILD index 06dd45cd035..b6e57067d74 100644 --- a/cmd/genman/BUILD +++ b/cmd/genman/BUILD @@ -19,6 +19,7 @@ go_library( srcs = ["gen_kube_man.go"], tags = ["automanaged"], deps = [ + "//cmd/cloud-controller-manager/app:go_default_library", "//cmd/genutils:go_default_library", "//cmd/kube-apiserver/app:go_default_library", "//cmd/kube-controller-manager/app:go_default_library", diff --git a/cmd/genman/gen_kube_man.go b/cmd/genman/gen_kube_man.go index 85361844ffb..f8974951252 100644 --- a/cmd/genman/gen_kube_man.go +++ b/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" + ccmapp "k8s.io/kubernetes/cmd/cloud-controller-manager/app" "k8s.io/kubernetes/cmd/genutils" apiservapp "k8s.io/kubernetes/cmd/kube-apiserver/app" cmapp "k8s.io/kubernetes/cmd/kube-controller-manager/app" @@ -73,6 +74,13 @@ func main() { for _, c := range controllermanager.Commands() { genMarkdown(c, "kube-controller-manager", outDir) } + case "cloud-controller-manager": + //generate manpage for cloud-controller-manager + controllermanager := ccmapp.NewCloudControllerManagerCommand() + genMarkdown(controllermanager, "", outDir) + for _, c := range controllermanager.Commands() { + genMarkdown(c, "cloud-controller-manager", outDir) + } case "kube-proxy": // generate manpage for kube-proxy proxy := proxyapp.NewProxyCommand() diff --git a/docs/.generated_docs b/docs/.generated_docs index fd5cb22a437..75538e38274 100644 --- a/docs/.generated_docs +++ b/docs/.generated_docs @@ -1,4 +1,5 @@ docs/.generated_docs +docs/admin/cloud-controller-manager.md docs/admin/federation-apiserver.md docs/admin/federation-controller-manager.md docs/admin/kube-apiserver.md @@ -6,6 +7,7 @@ docs/admin/kube-controller-manager.md docs/admin/kube-proxy.md docs/admin/kube-scheduler.md docs/admin/kubelet.md +docs/man/man1/cloud-controller-manager.1 docs/man/man1/kube-apiserver.1 docs/man/man1/kube-controller-manager.1 docs/man/man1/kube-proxy.1 diff --git a/docs/admin/cloud-controller-manager.md b/docs/admin/cloud-controller-manager.md new file mode 100644 index 00000000000..b6fd7a0f989 --- /dev/null +++ b/docs/admin/cloud-controller-manager.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/docs/man/man1/cloud-controller-manager.1 b/docs/man/man1/cloud-controller-manager.1 new file mode 100644 index 00000000000..b6fd7a0f989 --- /dev/null +++ b/docs/man/man1/cloud-controller-manager.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/hack/lib/util.sh b/hack/lib/util.sh index c32f47c77fc..2c23f14494b 100755 --- a/hack/lib/util.sh +++ b/hack/lib/util.sh @@ -205,6 +205,7 @@ kube::util::gen-docs() { mkdir -p "${dest}/docs/admin/" "${genkubedocs}" "${dest}/docs/admin/" "kube-apiserver" "${genkubedocs}" "${dest}/docs/admin/" "kube-controller-manager" + "${genkubedocs}" "${dest}/docs/admin/" "cloud-controller-manager" "${genkubedocs}" "${dest}/docs/admin/" "kube-proxy" "${genkubedocs}" "${dest}/docs/admin/" "kube-scheduler" "${genkubedocs}" "${dest}/docs/admin/" "kubelet" @@ -218,6 +219,7 @@ kube::util::gen-docs() { mkdir -p "${dest}/docs/man/man1/" "${genman}" "${dest}/docs/man/man1/" "kube-apiserver" "${genman}" "${dest}/docs/man/man1/" "kube-controller-manager" + "${genman}" "${dest}/docs/man/man1/" "cloud-controller-manager" "${genman}" "${dest}/docs/man/man1/" "kube-proxy" "${genman}" "${dest}/docs/man/man1/" "kube-scheduler" "${genman}" "${dest}/docs/man/man1/" "kubelet" From c9b772e9a9bd02a00647dbb37d5fab6a17e051a9 Mon Sep 17 00:00:00 2001 From: xilabao Date: Fri, 16 Jun 2017 16:22:50 +0800 Subject: [PATCH 046/448] update the err of hostPorts in psp --- pkg/security/podsecuritypolicy/provider.go | 19 ++++++++++++++++++- .../podsecuritypolicy/provider_test.go | 4 ++-- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/pkg/security/podsecuritypolicy/provider.go b/pkg/security/podsecuritypolicy/provider.go index e92c6419fc9..2431e0ba5ec 100644 --- a/pkg/security/podsecuritypolicy/provider.go +++ b/pkg/security/podsecuritypolicy/provider.go @@ -18,6 +18,7 @@ package podsecuritypolicy import ( "fmt" + "strings" "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/validation/field" @@ -318,7 +319,7 @@ func (s *simpleProvider) hasInvalidHostPort(container *api.Container, fldPath *f allErrs := field.ErrorList{} for _, cp := range container.Ports { if cp.HostPort > 0 && !s.isValidHostPort(int(cp.HostPort)) { - detail := fmt.Sprintf("Host port %d is not allowed to be used. Allowed ports: %v", cp.HostPort, s.psp.Spec.HostPorts) + detail := fmt.Sprintf("Host port %d is not allowed to be used. Allowed ports: [%s]", cp.HostPort, hostPortRangesToString(s.psp.Spec.HostPorts)) allErrs = append(allErrs, field.Invalid(fldPath.Child("hostPort"), cp.HostPort, detail)) } } @@ -339,3 +340,19 @@ func (s *simpleProvider) isValidHostPort(port int) bool { func (s *simpleProvider) GetPSPName() string { return s.psp.Name } + +func hostPortRangesToString(ranges []extensions.HostPortRange) string { + formattedString := "" + if ranges != nil { + strRanges := []string{} + for _, r := range ranges { + if r.Min == r.Max { + strRanges = append(strRanges, fmt.Sprintf("%d", r.Min)) + } else { + strRanges = append(strRanges, fmt.Sprintf("%d-%d", r.Min, r.Max)) + } + } + formattedString = strings.Join(strRanges, ",") + } + return formattedString +} diff --git a/pkg/security/podsecuritypolicy/provider_test.go b/pkg/security/podsecuritypolicy/provider_test.go index 8cdfd65f07d..714cb4a2a56 100644 --- a/pkg/security/podsecuritypolicy/provider_test.go +++ b/pkg/security/podsecuritypolicy/provider_test.go @@ -473,7 +473,7 @@ func TestValidateContainerSecurityContextFailures(t *testing.T) { "failHostPortPSP": { pod: failHostPortPod, psp: defaultPSP(), - expectedError: "Host port 1 is not allowed to be used. Allowed ports: []", + expectedError: "Host port 1 is not allowed to be used. Allowed ports: []", }, "failReadOnlyRootFS - nil": { pod: defaultPod(), @@ -508,7 +508,7 @@ func TestValidateContainerSecurityContextFailures(t *testing.T) { continue } if !strings.Contains(errs[0].Error(), v.expectedError) { - t.Errorf("%s received unexpected error %v", k, errs) + t.Errorf("%s received unexpected error %v\nexpected: %s", k, errs, v.expectedError) } } } From f98bc7d45435d0a48a48178ebe439296c554fb4c Mon Sep 17 00:00:00 2001 From: allencloud Date: Fri, 23 Jun 2017 11:41:18 +0800 Subject: [PATCH 047/448] fix CopyStrings and ShuffleStrings for slice when slice is nil Signed-off-by: allencloud --- pkg/util/slice/slice.go | 6 ++++++ pkg/util/slice/slice_test.go | 35 ++++++++++++++++++++++++++++------- 2 files changed, 34 insertions(+), 7 deletions(-) diff --git a/pkg/util/slice/slice.go b/pkg/util/slice/slice.go index 1b8f67c0c17..205b597c404 100644 --- a/pkg/util/slice/slice.go +++ b/pkg/util/slice/slice.go @@ -26,6 +26,9 @@ import ( // CopyStrings copies the contents of the specified string slice // into a new slice. func CopyStrings(s []string) []string { + if s == nil { + return nil + } c := make([]string, len(s)) copy(c, s) return c @@ -41,6 +44,9 @@ func SortStrings(s []string) []string { // ShuffleStrings copies strings from the specified slice into a copy in random // order. It returns a new slice. func ShuffleStrings(s []string) []string { + if s == nil { + return nil + } shuffled := make([]string, len(s)) perm := utilrand.Perm(len(s)) for i, j := range perm { diff --git a/pkg/util/slice/slice_test.go b/pkg/util/slice/slice_test.go index 7d74437df16..1c02f420411 100644 --- a/pkg/util/slice/slice_test.go +++ b/pkg/util/slice/slice_test.go @@ -22,15 +22,29 @@ import ( ) func TestCopyStrings(t *testing.T) { - src := []string{"a", "c", "b"} - dest := CopyStrings(src) + var src1 []string + dest1 := CopyStrings(src1) - if !reflect.DeepEqual(src, dest) { - t.Errorf("%v and %v are not equal", src, dest) + if !reflect.DeepEqual(src1, dest1) { + t.Errorf("%v and %v are not equal", src1, dest1) } - src[0] = "A" - if reflect.DeepEqual(src, dest) { + src2 := []string{} + dest2 := CopyStrings(src2) + + if !reflect.DeepEqual(src2, dest2) { + t.Errorf("%v and %v are not equal", src2, dest2) + } + + src3 := []string{"a", "c", "b"} + dest3 := CopyStrings(src3) + + if !reflect.DeepEqual(src3, dest3) { + t.Errorf("%v and %v are not equal", src3, dest3) + } + + src3[0] = "A" + if reflect.DeepEqual(src3, dest3) { t.Errorf("CopyStrings didn't make a copy") } } @@ -50,9 +64,16 @@ func TestSortStrings(t *testing.T) { } func TestShuffleStrings(t *testing.T) { - src := []string{"a", "b", "c", "d", "e", "f"} + var src []string dest := ShuffleStrings(src) + if dest != nil { + t.Errorf("ShuffleStrings for a nil slice got a non-nil slice") + } + + src = []string{"a", "b", "c", "d", "e", "f"} + dest = ShuffleStrings(src) + if len(src) != len(dest) { t.Errorf("Shuffled slice is wrong length, expected %v got %v", len(src), len(dest)) } From 37951c336b64704ba539b6b126a7ee76c409981d Mon Sep 17 00:00:00 2001 From: Federico Gimenez Date: Thu, 15 Jun 2017 12:46:52 +0200 Subject: [PATCH 048/448] OpenStack for cloud-controller-manager --- .../openstack/openstack_instances.go | 71 ++++++++++++++++++- .../providers/openstack/openstack_test.go | 46 +++++++++++- 2 files changed, 111 insertions(+), 6 deletions(-) diff --git a/pkg/cloudprovider/providers/openstack/openstack_instances.go b/pkg/cloudprovider/providers/openstack/openstack_instances.go index fd94eacfbc8..d75024c39e5 100644 --- a/pkg/cloudprovider/providers/openstack/openstack_instances.go +++ b/pkg/cloudprovider/providers/openstack/openstack_instances.go @@ -18,6 +18,8 @@ package openstack import ( "errors" + "fmt" + "net/url" "github.com/golang/glog" "github.com/gophercloud/gophercloud" @@ -107,7 +109,24 @@ func (i *Instances) NodeAddresses(name types.NodeName) ([]v1.NodeAddress, error) // This method 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 (i *Instances) NodeAddressesByProviderID(providerID string) ([]v1.NodeAddress, error) { - return []v1.NodeAddress{}, errors.New("unimplemented") + instanceID, err := instanceIDFromProviderID(providerID) + + if err != nil { + return []v1.NodeAddress{}, err + } + + server, err := servers.Get(i.compute, instanceID).Extract() + + if err != nil { + return []v1.NodeAddress{}, err + } + + addresses, err := nodeAddresses(server) + if err != nil { + return []v1.NodeAddress{}, err + } + + return addresses, nil } // ExternalID returns the cloud provider ID of the specified instance (deprecated). @@ -142,10 +161,56 @@ func (i *Instances) InstanceID(name types.NodeName) (string, error) { // This method 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 (i *Instances) InstanceTypeByProviderID(providerID string) (string, error) { - return "", errors.New("unimplemented") + instanceID, err := instanceIDFromProviderID(providerID) + + if err != nil { + return "", err + } + + server, err := servers.Get(i.compute, instanceID).Extract() + + if err != nil { + return "", err + } + + return srvInstanceType(server) } // InstanceType returns the type of the specified instance. func (i *Instances) InstanceType(name types.NodeName) (string, error) { - return "", nil + srv, err := getServerByName(i.compute, name) + + if err != nil { + return "", err + } + + return srvInstanceType(srv) +} + +func srvInstanceType(srv *servers.Server) (string, error) { + val, ok := srv.Flavor["name"] + + if !ok { + return "", fmt.Errorf("flavor name not present in server info") + } + + flavor, ok := val.(string) + + if !ok { + return "", fmt.Errorf("flavor name is not a string") + } + + return flavor, nil +} + +func instanceIDFromProviderID(providerID string) (instanceID string, err error) { + parsedID, err := url.Parse(providerID) + if err != nil { + return "", err + } + if parsedID.Scheme != ProviderName { + return "", fmt.Errorf("unrecognized provider %q", parsedID.Scheme) + } + + return parsedID.Host, nil } diff --git a/pkg/cloudprovider/providers/openstack/openstack_test.go b/pkg/cloudprovider/providers/openstack/openstack_test.go index 6ac40884e6e..13ed9ced468 100644 --- a/pkg/cloudprovider/providers/openstack/openstack_test.go +++ b/pkg/cloudprovider/providers/openstack/openstack_test.go @@ -18,9 +18,6 @@ package openstack import ( "fmt" - "github.com/gophercloud/gophercloud" - "github.com/gophercloud/gophercloud/openstack/blockstorage/v1/apiversions" - "github.com/gophercloud/gophercloud/openstack/compute/v2/servers" "os" "reflect" "sort" @@ -28,7 +25,11 @@ import ( "testing" "time" + "github.com/gophercloud/gophercloud" + "github.com/gophercloud/gophercloud/openstack/blockstorage/v1/apiversions" + "github.com/gophercloud/gophercloud/openstack/compute/v2/servers" "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/rand" "k8s.io/apimachinery/pkg/util/wait" @@ -449,3 +450,42 @@ func TestCinderAutoDetectApiVersion(t *testing.T) { } } } + +func TestInstanceIDFromProviderID(t *testing.T) { + testCases := []struct { + providerID string + instanceID string + fail bool + }{ + { + providerID: "openstack://7b9cf879-7146-417c-abfd-cb4272f0c935", + instanceID: "7b9cf879-7146-417c-abfd-cb4272f0c935", + fail: false, + }, + { + providerID: "7b9cf879-7146-417c-abfd-cb4272f0c935", + instanceID: "", + fail: true, + }, + { + providerID: "other-provider://7b9cf879-7146-417c-abfd-cb4272f0c935", + instanceID: "", + fail: true, + }, + } + + for _, test := range testCases { + instanceID, err := instanceIDFromProviderID(test.providerID) + if (err != nil) != test.fail { + t.Errorf("%s yielded `err != nil` as %t. expected %t", test.providerID, (err != nil), test.fail) + } + + if test.fail { + continue + } + + if instanceID != test.instanceID { + t.Errorf("%s yielded %s. expected %s", test.providerID, instanceID, test.instanceID) + } + } +} From 47a62e90f774ad1f4e1700eed783313018a091c6 Mon Sep 17 00:00:00 2001 From: Klaus Ma Date: Sun, 4 Jun 2017 11:26:09 +0800 Subject: [PATCH 049/448] Added helper funcs to schedulercache.Resource. --- .../algorithm/predicates/predicates.go | 24 +--- plugin/pkg/scheduler/schedulercache/BUILD | 1 - .../scheduler/schedulercache/cache_test.go | 53 +------- .../pkg/scheduler/schedulercache/node_info.go | 115 +++++++++--------- 4 files changed, 69 insertions(+), 124 deletions(-) diff --git a/plugin/pkg/scheduler/algorithm/predicates/predicates.go b/plugin/pkg/scheduler/algorithm/predicates/predicates.go index 5b3c5b6997b..624fc23a81b 100644 --- a/plugin/pkg/scheduler/algorithm/predicates/predicates.go +++ b/plugin/pkg/scheduler/algorithm/predicates/predicates.go @@ -500,30 +500,15 @@ func (c *VolumeZoneChecker) predicate(pod *v1.Pod, meta interface{}, nodeInfo *s // // Result: CPU: 3, Memory: 3G func GetResourceRequest(pod *v1.Pod) *schedulercache.Resource { - result := schedulercache.Resource{} + result := &schedulercache.Resource{} for _, container := range pod.Spec.Containers { - for rName, rQuantity := range container.Resources.Requests { - switch rName { - case v1.ResourceMemory: - result.Memory += rQuantity.Value() - case v1.ResourceCPU: - result.MilliCPU += rQuantity.MilliValue() - case v1.ResourceNvidiaGPU: - result.NvidiaGPU += rQuantity.Value() - case v1.ResourceStorageOverlay: - result.StorageOverlay += rQuantity.Value() - default: - if v1helper.IsOpaqueIntResourceName(rName) { - result.AddOpaque(rName, rQuantity.Value()) - } - } - } + result.Add(container.Resources.Requests) } + // Account for storage requested by emptydir volumes // If the storage medium is memory, should exclude the size for _, vol := range pod.Spec.Volumes { if vol.EmptyDir != nil && vol.EmptyDir.Medium != v1.StorageMediumMemory { - result.StorageScratch += vol.EmptyDir.SizeLimit.Value() } } @@ -558,7 +543,8 @@ func GetResourceRequest(pod *v1.Pod) *schedulercache.Resource { } } } - return &result + + return result } func podName(pod *v1.Pod) string { diff --git a/plugin/pkg/scheduler/schedulercache/BUILD b/plugin/pkg/scheduler/schedulercache/BUILD index 5c933280d9b..5697b560490 100644 --- a/plugin/pkg/scheduler/schedulercache/BUILD +++ b/plugin/pkg/scheduler/schedulercache/BUILD @@ -41,7 +41,6 @@ go_test( library = ":go_default_library", tags = ["automanaged"], deps = [ - "//pkg/api/v1/helper:go_default_library", "//plugin/pkg/scheduler/algorithm/priorities/util:go_default_library", "//plugin/pkg/scheduler/util:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", diff --git a/plugin/pkg/scheduler/schedulercache/cache_test.go b/plugin/pkg/scheduler/schedulercache/cache_test.go index 549a41edddb..ea59ea42cec 100644 --- a/plugin/pkg/scheduler/schedulercache/cache_test.go +++ b/plugin/pkg/scheduler/schedulercache/cache_test.go @@ -26,7 +26,6 @@ import ( "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" - v1helper "k8s.io/kubernetes/pkg/api/v1/helper" priorityutil "k8s.io/kubernetes/plugin/pkg/scheduler/algorithm/priorities/util" schedutil "k8s.io/kubernetes/plugin/pkg/scheduler/util" ) @@ -507,76 +506,32 @@ func TestForgetPod(t *testing.T) { } } -// addResource adds ResourceList into Resource. -func addResource(r *Resource, 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() - default: - if v1helper.IsOpaqueIntResourceName(rName) { - r.AddOpaque(rName, rQuant.Value()) - } - } - } -} - // getResourceRequest returns the resource request of all containers in Pods; // excuding initContainers. func getResourceRequest(pod *v1.Pod) v1.ResourceList { result := &Resource{} for _, container := range pod.Spec.Containers { - addResource(result, container.Resources.Requests) + result.Add(container.Resources.Requests) } return result.ResourceList() } -// newResource returns a new Resource by ResourceList. -func newResource(rl v1.ResourceList) *Resource { - res := &Resource{} - - for rName, rQuantity := range rl { - switch rName { - case v1.ResourceMemory: - res.Memory = rQuantity.Value() - case v1.ResourceCPU: - res.MilliCPU = rQuantity.MilliValue() - case v1.ResourceNvidiaGPU: - res.NvidiaGPU += rQuantity.Value() - default: - if v1helper.IsOpaqueIntResourceName(rName) { - res.SetOpaque(rName, rQuantity.Value()) - } - } - } - - return res -} - // buildNodeInfo creates a NodeInfo by simulating node operations in cache. func buildNodeInfo(node *v1.Node, pods []*v1.Pod) *NodeInfo { expected := NewNodeInfo() // Simulate SetNode. expected.node = node - expected.allocatableResource = newResource(node.Status.Allocatable) + expected.allocatableResource = NewResource(node.Status.Allocatable) expected.taints = node.Spec.Taints expected.generation++ for _, pod := range pods { // Simulate AddPod expected.pods = append(expected.pods, pod) - addResource(expected.requestedResource, getResourceRequest(pod)) - addResource(expected.nonzeroRequest, getResourceRequest(pod)) + expected.requestedResource.Add(getResourceRequest(pod)) + expected.nonzeroRequest.Add(getResourceRequest(pod)) expected.usedPorts = schedutil.GetUsedPorts(pod) expected.generation++ } diff --git a/plugin/pkg/scheduler/schedulercache/node_info.go b/plugin/pkg/scheduler/schedulercache/node_info.go index 315a25ede24..647279b98ef 100644 --- a/plugin/pkg/scheduler/schedulercache/node_info.go +++ b/plugin/pkg/scheduler/schedulercache/node_info.go @@ -47,9 +47,6 @@ type NodeInfo struct { // We store allocatedResources (which is Node.Status.Allocatable.*) explicitly // as int64, to avoid conversions and accessing map. allocatableResource *Resource - // We store allowedPodNumber (which is Node.Status.Allocatable.Pods().Value()) - // explicitly as int, to avoid conversions and improve performance. - allowedPodNumber int // Cached tains of the node for faster lookup. taints []v1.Taint @@ -66,20 +63,60 @@ type NodeInfo struct { // Resource is a collection of compute resource. type Resource struct { - MilliCPU int64 - Memory int64 - NvidiaGPU int64 - StorageScratch int64 - StorageOverlay int64 + MilliCPU int64 + Memory int64 + NvidiaGPU int64 + StorageScratch int64 + StorageOverlay int64 + // We store allowedPodNumber (which is Node.Status.Allocatable.Pods().Value()) + // explicitly as int, to avoid conversions and improve performance. + AllowedPodNumber int OpaqueIntResources map[v1.ResourceName]int64 } +// New 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.ResourceStorage: + r.StorageScratch += rQuant.Value() + case v1.ResourceStorageOverlay: + r.StorageOverlay += rQuant.Value() + default: + if v1helper.IsOpaqueIntResourceName(rName) { + r.AddOpaque(rName, rQuant.Value()) + } + } + } +} + 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.ResourceStorageOverlay: *resource.NewQuantity(r.StorageOverlay, resource.BinarySI), + v1.ResourceStorage: *resource.NewQuantity(r.StorageScratch, resource.BinarySI), } for rName, rQuant := range r.OpaqueIntResources { result[rName] = *resource.NewQuantity(rQuant, resource.DecimalSI) @@ -89,11 +126,12 @@ func (r *Resource) ResourceList() v1.ResourceList { func (r *Resource) Clone() *Resource { res := &Resource{ - MilliCPU: r.MilliCPU, - Memory: r.Memory, - NvidiaGPU: r.NvidiaGPU, - StorageOverlay: r.StorageOverlay, - StorageScratch: r.StorageScratch, + MilliCPU: r.MilliCPU, + Memory: r.Memory, + NvidiaGPU: r.NvidiaGPU, + AllowedPodNumber: r.AllowedPodNumber, + StorageOverlay: r.StorageOverlay, + StorageScratch: r.StorageScratch, } if r.OpaqueIntResources != nil { res.OpaqueIntResources = make(map[v1.ResourceName]int64) @@ -124,7 +162,6 @@ func NewNodeInfo(pods ...*v1.Pod) *NodeInfo { requestedResource: &Resource{}, nonzeroRequest: &Resource{}, allocatableResource: &Resource{}, - allowedPodNumber: 0, generation: 0, usedPorts: make(map[int]bool), } @@ -166,10 +203,10 @@ func (n *NodeInfo) PodsWithAffinity() []*v1.Pod { } func (n *NodeInfo) AllowedPodNumber() int { - if n == nil { + if n == nil || n.allocatableResource == nil { return 0 } - return n.allowedPodNumber + return n.allocatableResource.AllowedPodNumber } func (n *NodeInfo) Taints() ([]v1.Taint, error) { @@ -223,7 +260,6 @@ func (n *NodeInfo) Clone() *NodeInfo { requestedResource: n.requestedResource.Clone(), nonzeroRequest: n.nonzeroRequest.Clone(), allocatableResource: n.allocatableResource.Clone(), - allowedPodNumber: n.allowedPodNumber, taintsErr: n.taintsErr, memoryPressureCondition: n.memoryPressureCondition, diskPressureCondition: n.diskPressureCondition, @@ -253,7 +289,8 @@ func (n *NodeInfo) String() string { for i, pod := range n.pods { podKeys[i] = pod.Name } - return fmt.Sprintf("&NodeInfo{Pods:%v, RequestedResource:%#v, NonZeroRequest: %#v, UsedPort: %#v}", podKeys, n.requestedResource, n.nonzeroRequest, n.usedPorts) + 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 { @@ -345,23 +382,9 @@ func (n *NodeInfo) removePod(pod *v1.Pod) error { } func calculateResource(pod *v1.Pod) (res Resource, non0_cpu int64, non0_mem int64) { + resPtr := &res for _, c := range pod.Spec.Containers { - for rName, rQuant := range c.Resources.Requests { - switch rName { - case v1.ResourceCPU: - res.MilliCPU += rQuant.MilliValue() - case v1.ResourceMemory: - res.Memory += rQuant.Value() - case v1.ResourceNvidiaGPU: - res.NvidiaGPU += rQuant.Value() - case v1.ResourceStorageOverlay: - res.StorageOverlay += rQuant.Value() - default: - if v1helper.IsOpaqueIntResourceName(rName) { - res.AddOpaque(rName, rQuant.Value()) - } - } - } + resPtr.Add(c.Resources.Requests) non0_cpu_req, non0_mem_req := priorityutil.GetNonzeroRequests(&c.Resources.Requests) non0_cpu += non0_cpu_req @@ -397,26 +420,9 @@ func (n *NodeInfo) updateUsedPorts(pod *v1.Pod, used bool) { // Sets the overall node information. func (n *NodeInfo) SetNode(node *v1.Node) error { n.node = node - for rName, rQuant := range node.Status.Allocatable { - switch rName { - case v1.ResourceCPU: - n.allocatableResource.MilliCPU = rQuant.MilliValue() - case v1.ResourceMemory: - n.allocatableResource.Memory = rQuant.Value() - case v1.ResourceNvidiaGPU: - n.allocatableResource.NvidiaGPU = rQuant.Value() - case v1.ResourcePods: - n.allowedPodNumber = int(rQuant.Value()) - case v1.ResourceStorage: - n.allocatableResource.StorageScratch = rQuant.Value() - case v1.ResourceStorageOverlay: - n.allocatableResource.StorageOverlay = rQuant.Value() - default: - if v1helper.IsOpaqueIntResourceName(rName) { - n.allocatableResource.SetOpaque(rName, rQuant.Value()) - } - } - } + + n.allocatableResource = NewResource(node.Status.Allocatable) + n.taints = node.Spec.Taints for i := range node.Status.Conditions { cond := &node.Status.Conditions[i] @@ -441,7 +447,6 @@ func (n *NodeInfo) RemoveNode(node *v1.Node) error { // node removal. This is handled correctly in cache.go file. n.node = nil n.allocatableResource = &Resource{} - n.allowedPodNumber = 0 n.taints, n.taintsErr = nil, nil n.memoryPressureCondition = v1.ConditionUnknown n.diskPressureCondition = v1.ConditionUnknown From fad8b45667ae555cc459c4b51d82f9d13c6da2d3 Mon Sep 17 00:00:00 2001 From: Cao Shufeng Date: Fri, 23 Jun 2017 17:53:35 +0800 Subject: [PATCH 050/448] [trivial]fix function name in comment --- plugin/pkg/auth/authorizer/node/node_authorizer.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin/pkg/auth/authorizer/node/node_authorizer.go b/plugin/pkg/auth/authorizer/node/node_authorizer.go index 5e5d7362c65..c98625f7560 100644 --- a/plugin/pkg/auth/authorizer/node/node_authorizer.go +++ b/plugin/pkg/auth/authorizer/node/node_authorizer.go @@ -48,7 +48,7 @@ type NodeAuthorizer struct { nodeRules []rbacapi.PolicyRule } -// New returns a new node authorizer +// NewAuthorizer returns a new node authorizer func NewAuthorizer(graph *Graph, identifier nodeidentifier.NodeIdentifier, rules []rbacapi.PolicyRule) authorizer.Authorizer { return &NodeAuthorizer{ graph: graph, From 5462d06ce302156994c95176d0291f5265547d72 Mon Sep 17 00:00:00 2001 From: Cosmin Cojocar Date: Thu, 8 Jun 2017 15:05:11 +0200 Subject: [PATCH 051/448] Add client cert authentication for Azure cloud provider --- pkg/cloudprovider/providers/azure/azure.go | 66 ++++++++++++++++--- .../providers/azure/azure_test.go | 10 +++ 2 files changed, 66 insertions(+), 10 deletions(-) diff --git a/pkg/cloudprovider/providers/azure/azure.go b/pkg/cloudprovider/providers/azure/azure.go index ca2e48b7e6c..21e20566bc1 100644 --- a/pkg/cloudprovider/providers/azure/azure.go +++ b/pkg/cloudprovider/providers/azure/azure.go @@ -17,6 +17,8 @@ limitations under the License. package azure import ( + "crypto/rsa" + "crypto/x509" "fmt" "io" "io/ioutil" @@ -34,6 +36,7 @@ import ( "github.com/Azure/go-autorest/autorest/azure" "github.com/ghodss/yaml" "github.com/golang/glog" + "golang.org/x/crypto/pkcs12" "k8s.io/apimachinery/pkg/util/wait" ) @@ -80,6 +83,10 @@ type Config struct { AADClientID string `json:"aadClientId" yaml:"aadClientId"` // The ClientSecret for an AAD application with RBAC access to talk to Azure RM APIs AADClientSecret string `json:"aadClientSecret" yaml:"aadClientSecret"` + // The path of a client certificate for an AAD application with RBAC access to talk to Azure RM APIs + AADClientCertPath string `json:"aadClientCertPath" yaml:"aadClientCertPath"` + // The password of the client certificate for an AAD application with RBAC access to talk to Azure RM APIs + AADClientCertPassword string `json:"aadClientCertPassword" yaml:"aadClientCertPassword"` // Enable exponential backoff to manage resource request retries CloudProviderBackoff bool `json:"cloudProviderBackoff" yaml:"cloudProviderBackoff"` // Backoff retry limit @@ -119,6 +126,54 @@ func init() { cloudprovider.RegisterCloudProvider(CloudProviderName, NewCloud) } +// decodePkcs12 decodes a PKCS#12 client certificate by extracting the public certificate and +// the private RSA key +func decodePkcs12(pkcs []byte, password string) (*x509.Certificate, *rsa.PrivateKey, error) { + privateKey, certificate, err := pkcs12.Decode(pkcs, password) + if err != nil { + return nil, nil, fmt.Errorf("decoding the PKCS#12 client certificate: %v", err) + } + rsaPrivateKey, isRsaKey := privateKey.(*rsa.PrivateKey) + if !isRsaKey { + return nil, nil, fmt.Errorf("PKCS#12 certificate must contain a RSA private key") + } + + return certificate, rsaPrivateKey, nil +} + +// newServicePrincipalToken creates a new service principal token based on the configuration +func newServicePrincipalToken(az *Cloud) (*azure.ServicePrincipalToken, error) { + oauthConfig, err := az.Environment.OAuthConfigForTenant(az.TenantID) + if err != nil { + return nil, fmt.Errorf("creating the OAuth config: %v", err) + } + + if len(az.AADClientSecret) > 0 { + return azure.NewServicePrincipalToken( + *oauthConfig, + az.AADClientID, + az.AADClientSecret, + az.Environment.ServiceManagementEndpoint) + } else if len(az.AADClientCertPath) > 0 && len(az.AADClientCertPassword) > 0 { + certData, err := ioutil.ReadFile(az.AADClientCertPath) + if err != nil { + return nil, fmt.Errorf("reading the client certificate from file %s: %v", az.AADClientCertPath, err) + } + certificate, privateKey, err := decodePkcs12(certData, az.AADClientSecret) + if err != nil { + return nil, fmt.Errorf("decoding the client certificate: %v", err) + } + return azure.NewServicePrincipalTokenFromCertificate( + *oauthConfig, + az.AADClientID, + certificate, + privateKey, + az.Environment.ServiceManagementEndpoint) + } else { + return nil, fmt.Errorf("No credentials provided for AAD application %s", az.AADClientID) + } +} + // NewCloud returns a Cloud with initialized clients func NewCloud(configReader io.Reader) (cloudprovider.Interface, error) { var az Cloud @@ -141,16 +196,7 @@ func NewCloud(configReader io.Reader) (cloudprovider.Interface, error) { } } - oauthConfig, err := az.Environment.OAuthConfigForTenant(az.TenantID) - if err != nil { - return nil, err - } - - servicePrincipalToken, err := azure.NewServicePrincipalToken( - *oauthConfig, - az.AADClientID, - az.AADClientSecret, - az.Environment.ServiceManagementEndpoint) + servicePrincipalToken, err := newServicePrincipalToken(&az) if err != nil { return nil, err } diff --git a/pkg/cloudprovider/providers/azure/azure_test.go b/pkg/cloudprovider/providers/azure/azure_test.go index 788be6451c8..6c4e634f5b6 100644 --- a/pkg/cloudprovider/providers/azure/azure_test.go +++ b/pkg/cloudprovider/providers/azure/azure_test.go @@ -585,6 +585,8 @@ func TestNewCloudFromJSON(t *testing.T) { "subscriptionId": "--subscription-id--", "aadClientId": "--aad-client-id--", "aadClientSecret": "--aad-client-secret--", + "aadClientCertPath": "--aad-client-cert-path--", + "aadClientCertPassword": "--aad-client-cert-password--", "resourceGroup": "--resource-group--", "location": "--location--", "subnetName": "--subnet-name--", @@ -625,6 +627,8 @@ tenantId: --tenant-id-- subscriptionId: --subscription-id-- aadClientId: --aad-client-id-- aadClientSecret: --aad-client-secret-- +aadClientCertPath: --aad-client-cert-path-- +aadClientCertPassword: --aad-client-cert-password-- resourceGroup: --resource-group-- location: --location-- subnetName: --subnet-name-- @@ -659,6 +663,12 @@ func validateConfig(t *testing.T, config string) { if azureCloud.AADClientSecret != "--aad-client-secret--" { t.Errorf("got incorrect value for AADClientSecret") } + if azureCloud.AADClientCertPath != "--aad-client-cert-path--" { + t.Errorf("got incorrect value for AADClientCertPath") + } + if azureCloud.AADClientCertPassword != "--aad-client-cert-password--" { + t.Errorf("got incorrect value for AADClientCertPassword") + } if azureCloud.ResourceGroup != "--resource-group--" { t.Errorf("got incorrect value for ResourceGroup") } From 2c8ec115dba40e712ab968992c3d1fcfb41ec680 Mon Sep 17 00:00:00 2001 From: Cosmin Cojocar Date: Sat, 10 Jun 2017 09:03:02 +0200 Subject: [PATCH 052/448] Fix tests after rebasing --- pkg/cloudprovider/providers/azure/azure_test.go | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/pkg/cloudprovider/providers/azure/azure_test.go b/pkg/cloudprovider/providers/azure/azure_test.go index 6c4e634f5b6..fd5a806e98e 100644 --- a/pkg/cloudprovider/providers/azure/azure_test.go +++ b/pkg/cloudprovider/providers/azure/azure_test.go @@ -608,15 +608,20 @@ func TestNewCloudFromJSON(t *testing.T) { // Test Backoff and Rate Limit defaults (json) func TestCloudDefaultConfigFromJSON(t *testing.T) { - config := `{}` + config := `{ + "aadClientId": "--aad-client-id--", + "aadClientSecret": "--aad-client-secret--" + }` validateEmptyConfig(t, config) } // Test Backoff and Rate Limit defaults (yaml) func TestCloudDefaultConfigFromYAML(t *testing.T) { - config := `` - + config := ` +aadClientId: --aad-client-id-- +aadClientSecret: --aad-client-secret-- +` validateEmptyConfig(t, config) } From fcdceb2e50f139afaef19375bcbf9405cfa21d6d Mon Sep 17 00:00:00 2001 From: Cosmin Cojocar Date: Wed, 14 Jun 2017 13:28:23 +0200 Subject: [PATCH 053/448] Add the pcks12 package to the build of Azure cloud provider --- pkg/cloudprovider/providers/azure/BUILD | 1 + pkg/cloudprovider/providers/azure/azure_test.go | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/pkg/cloudprovider/providers/azure/BUILD b/pkg/cloudprovider/providers/azure/BUILD index be58887a2fd..a84c4b6671a 100644 --- a/pkg/cloudprovider/providers/azure/BUILD +++ b/pkg/cloudprovider/providers/azure/BUILD @@ -43,6 +43,7 @@ go_library( "//vendor/github.com/golang/glog:go_default_library", "//vendor/github.com/rubiojr/go-vhd/vhd:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", + "//vendor/golang.org/x/crypto/pkcs12: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/wait:go_default_library", diff --git a/pkg/cloudprovider/providers/azure/azure_test.go b/pkg/cloudprovider/providers/azure/azure_test.go index fd5a806e98e..1c86f2e1a78 100644 --- a/pkg/cloudprovider/providers/azure/azure_test.go +++ b/pkg/cloudprovider/providers/azure/azure_test.go @@ -585,8 +585,8 @@ func TestNewCloudFromJSON(t *testing.T) { "subscriptionId": "--subscription-id--", "aadClientId": "--aad-client-id--", "aadClientSecret": "--aad-client-secret--", - "aadClientCertPath": "--aad-client-cert-path--", - "aadClientCertPassword": "--aad-client-cert-password--", + "aadClientCertPath": "--aad-client-cert-path--", + "aadClientCertPassword": "--aad-client-cert-password--", "resourceGroup": "--resource-group--", "location": "--location--", "subnetName": "--subnet-name--", From 0235cb9e3c5198eaf21185b8a789b8b6d438dcba Mon Sep 17 00:00:00 2001 From: Cosmin Cojocar Date: Fri, 23 Jun 2017 13:20:10 +0200 Subject: [PATCH 054/448] Fix dependencies order after rebase --- pkg/cloudprovider/providers/azure/BUILD | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/cloudprovider/providers/azure/BUILD b/pkg/cloudprovider/providers/azure/BUILD index a84c4b6671a..4e68e86fdd6 100644 --- a/pkg/cloudprovider/providers/azure/BUILD +++ b/pkg/cloudprovider/providers/azure/BUILD @@ -42,8 +42,8 @@ go_library( "//vendor/github.com/ghodss/yaml:go_default_library", "//vendor/github.com/golang/glog:go_default_library", "//vendor/github.com/rubiojr/go-vhd/vhd:go_default_library", - "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/golang.org/x/crypto/pkcs12: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/errors:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library", From d6a5175c0549d5a4c01953091a2e21ecb2871e07 Mon Sep 17 00:00:00 2001 From: Robert Rati Date: Thu, 22 Jun 2017 15:08:20 -0400 Subject: [PATCH 055/448] Use %q formatter for error messages from the AWS SDK. #47789 --- pkg/cloudprovider/providers/aws/aws.go | 92 +++++++++---------- .../providers/aws/aws_instancegroups.go | 4 +- .../providers/aws/aws_loadbalancer.go | 18 ++-- pkg/cloudprovider/providers/aws/aws_routes.go | 8 +- pkg/cloudprovider/providers/aws/tags.go | 4 +- 5 files changed, 63 insertions(+), 63 deletions(-) diff --git a/pkg/cloudprovider/providers/aws/aws.go b/pkg/cloudprovider/providers/aws/aws.go index d96692adeb9..95191d0b6dc 100644 --- a/pkg/cloudprovider/providers/aws/aws.go +++ b/pkg/cloudprovider/providers/aws/aws.go @@ -604,7 +604,7 @@ func (s *awsSdkEC2) DescribeInstances(request *ec2.DescribeInstancesInput) ([]*e response, err := s.ec2.DescribeInstances(request) if err != nil { recordAwsMetric("describe_instance", 0, err) - return nil, fmt.Errorf("error listing AWS instances: %v", err) + return nil, fmt.Errorf("error listing AWS instances: %q", err) } for _, reservation := range response.Reservations { @@ -627,7 +627,7 @@ func (s *awsSdkEC2) DescribeSecurityGroups(request *ec2.DescribeSecurityGroupsIn // Security groups are not paged response, err := s.ec2.DescribeSecurityGroups(request) if err != nil { - return nil, fmt.Errorf("error listing AWS security groups: %v", err) + return nil, fmt.Errorf("error listing AWS security groups: %q", err) } return response.SecurityGroups, nil } @@ -658,7 +658,7 @@ func (s *awsSdkEC2) DescribeVolumes(request *ec2.DescribeVolumesInput) ([]*ec2.V if err != nil { recordAwsMetric("describe_volume", 0, err) - return nil, fmt.Errorf("error listing AWS volumes: %v", err) + return nil, fmt.Errorf("error listing AWS volumes: %q", err) } results = append(results, response.Volumes...) @@ -694,7 +694,7 @@ func (s *awsSdkEC2) DescribeSubnets(request *ec2.DescribeSubnetsInput) ([]*ec2.S // Subnets are not paged response, err := s.ec2.DescribeSubnets(request) if err != nil { - return nil, fmt.Errorf("error listing AWS subnets: %v", err) + return nil, fmt.Errorf("error listing AWS subnets: %q", err) } return response.Subnets, nil } @@ -727,7 +727,7 @@ func (s *awsSdkEC2) DescribeRouteTables(request *ec2.DescribeRouteTablesInput) ( // Not paged response, err := s.ec2.DescribeRouteTables(request) if err != nil { - return nil, fmt.Errorf("error listing AWS route tables: %v", err) + return nil, fmt.Errorf("error listing AWS route tables: %q", err) } return response.RouteTables, nil } @@ -816,7 +816,7 @@ func newAWSCloud(config io.Reader, awsServices Services) (*Cloud, error) { metadata, err := awsServices.Metadata() if err != nil { - return nil, fmt.Errorf("error creating AWS metadata client: %v", err) + return nil, fmt.Errorf("error creating AWS metadata client: %q", err) } cfg, err := readAWSCloudConfig(config, metadata) @@ -963,7 +963,7 @@ func (c *Cloud) NodeAddresses(name types.NodeName) ([]v1.NodeAddress, error) { internalIP, err := c.metadata.GetMetadata("local-ipv4") if err != nil { - return nil, fmt.Errorf("error querying AWS metadata for %q: %v", "local-ipv4", err) + return nil, fmt.Errorf("error querying AWS metadata for %q: %q", "local-ipv4", err) } addresses = append(addresses, v1.NodeAddress{Type: v1.NodeInternalIP, Address: internalIP}) @@ -999,7 +999,7 @@ func (c *Cloud) NodeAddresses(name types.NodeName) ([]v1.NodeAddress, error) { instance, err := c.getInstanceByNodeName(name) if err != nil { - return nil, fmt.Errorf("getInstanceByNodeName failed for %q with %v", name, err) + return nil, fmt.Errorf("getInstanceByNodeName failed for %q with %q", name, err) } return extractNodeAddresses(instance) } @@ -1090,7 +1090,7 @@ func (c *Cloud) InstanceID(nodeName types.NodeName) (string, error) { } inst, err := c.getInstanceByNodeName(nodeName) if err != nil { - return "", fmt.Errorf("getInstanceByNodeName failed for %q with %v", nodeName, err) + return "", fmt.Errorf("getInstanceByNodeName failed for %q with %q", nodeName, err) } return "/" + orEmpty(inst.Placement.AvailabilityZone) + "/" + orEmpty(inst.InstanceId), nil } @@ -1119,7 +1119,7 @@ func (c *Cloud) InstanceType(nodeName types.NodeName) (string, error) { } inst, err := c.getInstanceByNodeName(nodeName) if err != nil { - return "", fmt.Errorf("getInstanceByNodeName failed for %q with %v", nodeName, err) + return "", fmt.Errorf("getInstanceByNodeName failed for %q with %q", nodeName, err) } return aws.StringValue(inst.InstanceType), nil } @@ -1376,7 +1376,7 @@ func (d *awsDisk) describeVolume() (*ec2.Volume, error) { volumes, err := d.ec2.DescribeVolumes(request) if err != nil { - return nil, fmt.Errorf("error querying ec2 for volume %q: %v", volumeID, err) + return nil, fmt.Errorf("error querying ec2 for volume %q: %q", volumeID, err) } if len(volumes) == 0 { return nil, fmt.Errorf("no volumes found for volume %q", volumeID) @@ -1462,7 +1462,7 @@ func (d *awsDisk) deleteVolume() (bool, error) { return false, volume.NewDeletedVolumeInUseError(err.Error()) } } - return false, fmt.Errorf("error deleting EBS volume %q: %v", d.awsID, err) + return false, fmt.Errorf("error deleting EBS volume %q: %q", d.awsID, err) } return true, nil } @@ -1475,7 +1475,7 @@ func (c *Cloud) buildSelfAWSInstance() (*awsInstance, error) { } instanceID, err := c.metadata.GetMetadata("instance-id") if err != nil { - return nil, fmt.Errorf("error fetching instance-id from ec2 metadata service: %v", err) + return nil, fmt.Errorf("error fetching instance-id from ec2 metadata service: %q", err) } // We want to fetch the hostname via the EC2 metadata service @@ -1488,7 +1488,7 @@ func (c *Cloud) buildSelfAWSInstance() (*awsInstance, error) { // have two code paths. instance, err := c.getInstanceByID(instanceID) if err != nil { - return nil, fmt.Errorf("error finding instance %s: %v", instanceID, err) + return nil, fmt.Errorf("error finding instance %s: %q", instanceID, err) } return newAWSInstance(c.ec2, instance), nil } @@ -1517,19 +1517,19 @@ func wrapAttachError(err error, disk *awsDisk, instance string) error { if awsError.Code() == "VolumeInUse" { info, err := disk.describeVolume() if err != nil { - glog.Errorf("Error describing volume %q: %v", disk.awsID, err) + glog.Errorf("Error describing volume %q: %q", disk.awsID, err) } else { for _, a := range info.Attachments { if disk.awsID != awsVolumeID(aws.StringValue(a.VolumeId)) { glog.Warningf("Expected to get attachment info of volume %q but instead got info of %q", disk.awsID, aws.StringValue(a.VolumeId)) } else if aws.StringValue(a.State) == "attached" { - return fmt.Errorf("Error attaching EBS volume %q to instance %q: %v. The volume is currently attached to instance %q", disk.awsID, instance, awsError, aws.StringValue(a.InstanceId)) + return fmt.Errorf("Error attaching EBS volume %q to instance %q: %q. The volume is currently attached to instance %q", disk.awsID, instance, awsError, aws.StringValue(a.InstanceId)) } } } } } - return fmt.Errorf("Error attaching EBS volume %q to instance %q: %v", disk.awsID, instance, err) + return fmt.Errorf("Error attaching EBS volume %q to instance %q: %q", disk.awsID, instance, err) } // AttachDisk implements Volumes.AttachDisk @@ -1541,7 +1541,7 @@ func (c *Cloud) AttachDisk(diskName KubernetesVolumeID, nodeName types.NodeName, awsInstance, info, err := c.getFullInstance(nodeName) if err != nil { - return "", fmt.Errorf("error finding instance %s: %v", nodeName, err) + return "", fmt.Errorf("error finding instance %s: %q", nodeName, err) } if readOnly { @@ -1659,7 +1659,7 @@ func (c *Cloud) DetachDisk(diskName KubernetesVolumeID, nodeName types.NodeName) response, err := c.ec2.DetachVolume(&request) if err != nil { - return "", fmt.Errorf("error detaching EBS volume %q from %q: %v", disk.awsID, awsInstance.awsID, err) + return "", fmt.Errorf("error detaching EBS volume %q from %q: %q", disk.awsID, awsInstance.awsID, err) } if response == nil { return "", errors.New("no response from DetachVolume") @@ -1771,9 +1771,9 @@ func (c *Cloud) CreateDisk(volumeOptions *VolumeOptions) (KubernetesVolumeID, er _, delerr := c.DeleteDisk(volumeName) if delerr != nil { // delete did not succeed, we have a stray volume! - return "", fmt.Errorf("error tagging volume %s, could not delete the volume: %v", volumeName, delerr) + return "", fmt.Errorf("error tagging volume %s, could not delete the volume: %q", volumeName, delerr) } - return "", fmt.Errorf("error tagging volume %s: %v", volumeName, err) + return "", fmt.Errorf("error tagging volume %s: %q", volumeName, err) } return volumeName, nil @@ -1959,7 +1959,7 @@ func (c *Cloud) describeLoadBalancer(name string) (*elb.LoadBalancerDescription, func (c *Cloud) findVPCID() (string, error) { macs, err := c.metadata.GetMetadata("network/interfaces/macs/") if err != nil { - return "", fmt.Errorf("Could not list interfaces of the instance: %v", err) + return "", fmt.Errorf("Could not list interfaces of the instance: %q", err) } // loop over interfaces, first vpc id returned wins @@ -2088,7 +2088,7 @@ func isEqualUserGroupPair(l, r *ec2.UserIdGroupPair, compareGroupUserIDs bool) b func (c *Cloud) setSecurityGroupIngress(securityGroupID string, permissions IPPermissionSet) (bool, error) { group, err := c.findSecurityGroup(securityGroupID) if err != nil { - glog.Warning("Error retrieving security group", err) + glog.Warningf("Error retrieving security group %q", err) return false, err } @@ -2134,7 +2134,7 @@ func (c *Cloud) setSecurityGroupIngress(securityGroupID string, permissions IPPe request.IpPermissions = add.List() _, err = c.ec2.AuthorizeSecurityGroupIngress(request) if err != nil { - return false, fmt.Errorf("error authorizing security group ingress: %v", err) + return false, fmt.Errorf("error authorizing security group ingress: %q", err) } } if remove.Len() != 0 { @@ -2145,7 +2145,7 @@ func (c *Cloud) setSecurityGroupIngress(securityGroupID string, permissions IPPe request.IpPermissions = remove.List() _, err = c.ec2.RevokeSecurityGroupIngress(request) if err != nil { - return false, fmt.Errorf("error revoking security group ingress: %v", err) + return false, fmt.Errorf("error revoking security group ingress: %q", err) } } @@ -2158,7 +2158,7 @@ func (c *Cloud) setSecurityGroupIngress(securityGroupID string, permissions IPPe func (c *Cloud) addSecurityGroupIngress(securityGroupID string, addPermissions []*ec2.IpPermission) (bool, error) { group, err := c.findSecurityGroup(securityGroupID) if err != nil { - glog.Warningf("Error retrieving security group: %v", err) + glog.Warningf("Error retrieving security group: %q", err) return false, err } @@ -2201,8 +2201,8 @@ func (c *Cloud) addSecurityGroupIngress(securityGroupID string, addPermissions [ request.IpPermissions = changes _, err = c.ec2.AuthorizeSecurityGroupIngress(request) if err != nil { - glog.Warning("Error authorizing security group ingress", err) - return false, fmt.Errorf("error authorizing security group ingress: %v", err) + glog.Warning("Error authorizing security group ingress %q", err) + return false, fmt.Errorf("error authorizing security group ingress: %q", err) } return true, nil @@ -2214,7 +2214,7 @@ func (c *Cloud) addSecurityGroupIngress(securityGroupID string, addPermissions [ func (c *Cloud) removeSecurityGroupIngress(securityGroupID string, removePermissions []*ec2.IpPermission) (bool, error) { group, err := c.findSecurityGroup(securityGroupID) if err != nil { - glog.Warningf("Error retrieving security group: %v", err) + glog.Warningf("Error retrieving security group: %q", err) return false, err } @@ -2256,7 +2256,7 @@ func (c *Cloud) removeSecurityGroupIngress(securityGroupID string, removePermiss request.IpPermissions = changes _, err = c.ec2.RevokeSecurityGroupIngress(request) if err != nil { - glog.Warningf("Error revoking security group ingress: %v", err) + glog.Warningf("Error revoking security group ingress: %q", err) return false, err } @@ -2319,7 +2319,7 @@ func (c *Cloud) ensureSecurityGroup(name string, description string) (string, er } } if !ignore { - glog.Error("Error creating security group: ", err) + glog.Errorf("Error creating security group: %q", err) return "", err } time.Sleep(1 * time.Second) @@ -2338,7 +2338,7 @@ func (c *Cloud) ensureSecurityGroup(name string, description string) (string, er // will add the missing tags. We could delete the security // group here, but that doesn't feel like the right thing, as // the caller is likely to retry the create - return "", fmt.Errorf("error tagging security group: %v", err) + return "", fmt.Errorf("error tagging security group: %q", err) } return groupID, nil } @@ -2363,7 +2363,7 @@ func (c *Cloud) findSubnets() ([]*ec2.Subnet, error) { subnets, err := c.ec2.DescribeSubnets(request) if err != nil { - return nil, fmt.Errorf("error describing subnets: %v", err) + return nil, fmt.Errorf("error describing subnets: %q", err) } var matches []*ec2.Subnet @@ -2386,7 +2386,7 @@ func (c *Cloud) findSubnets() ([]*ec2.Subnet, error) { subnets, err = c.ec2.DescribeSubnets(request) if err != nil { - return nil, fmt.Errorf("error describing subnets: %v", err) + return nil, fmt.Errorf("error describing subnets: %q", err) } return subnets, nil @@ -2407,7 +2407,7 @@ func (c *Cloud) findELBSubnets(internalELB bool) ([]string, error) { rRequest.Filters = []*ec2.Filter{vpcIDFilter} rt, err := c.ec2.DescribeRouteTables(rRequest) if err != nil { - return nil, fmt.Errorf("error describe route table: %v", err) + return nil, fmt.Errorf("error describe route table: %q", err) } subnetsByAZ := make(map[string]*ec2.Subnet) @@ -2553,7 +2553,7 @@ func (c *Cloud) buildELBSecurityGroupList(serviceName types.NamespacedName, load sgDescription := fmt.Sprintf("Security group for Kubernetes ELB %s (%v)", loadBalancerName, serviceName) securityGroupID, err = c.ensureSecurityGroup(sgName, sgDescription) if err != nil { - glog.Error("Error creating load balancer security group: ", err) + glog.Errorf("Error creating load balancer security group: %q", err) return nil, err } } @@ -2770,7 +2770,7 @@ func (c *Cloud) EnsureLoadBalancer(clusterName string, apiService *v1.Service, n // Find the subnets that the ELB will live in subnetIDs, err := c.findELBSubnets(internalELB) if err != nil { - glog.Error("Error listing subnets in VPC: ", err) + glog.Errorf("Error listing subnets in VPC: %q", err) return nil, err } @@ -2846,7 +2846,7 @@ func (c *Cloud) EnsureLoadBalancer(clusterName string, apiService *v1.Service, n glog.V(4).Infof("service %v (%v) needs health checks on :%d%s)", apiService.Name, loadBalancerName, healthCheckNodePort, path) err = c.ensureLoadBalancerHealthCheck(loadBalancer, "HTTP", healthCheckNodePort, path) if err != nil { - return nil, fmt.Errorf("Failed to ensure health check for localized service %v on node port %v: %v", loadBalancerName, healthCheckNodePort, err) + return nil, fmt.Errorf("Failed to ensure health check for localized service %v on node port %v: %q", loadBalancerName, healthCheckNodePort, err) } } else { glog.V(4).Infof("service %v does not need custom health checks", apiService.Name) @@ -2868,13 +2868,13 @@ func (c *Cloud) EnsureLoadBalancer(clusterName string, apiService *v1.Service, n err = c.updateInstanceSecurityGroupsForLoadBalancer(loadBalancer, instances) if err != nil { - glog.Warningf("Error opening ingress rules for the load balancer to the instances: %v", err) + glog.Warningf("Error opening ingress rules for the load balancer to the instances: %q", err) return nil, err } err = c.ensureLoadBalancerInstances(orEmpty(loadBalancer.LoadBalancerName), loadBalancer.Instances, instances) if err != nil { - glog.Warningf("Error registering instances with the load balancer: %v", err) + glog.Warningf("Error registering instances with the load balancer: %q", err) return nil, err } @@ -2964,7 +2964,7 @@ func (c *Cloud) getTaggedSecurityGroups() (map[string]*ec2.SecurityGroup, error) request.Filters = c.tagging.addFilters(nil) groups, err := c.ec2.DescribeSecurityGroups(request) if err != nil { - return nil, fmt.Errorf("error querying security groups: %v", err) + return nil, fmt.Errorf("error querying security groups: %q", err) } m := make(map[string]*ec2.SecurityGroup) @@ -3016,7 +3016,7 @@ func (c *Cloud) updateInstanceSecurityGroupsForLoadBalancer(lb *elb.LoadBalancer describeRequest.Filters = c.tagging.addFilters(filters) response, err := c.ec2.DescribeSecurityGroups(describeRequest) if err != nil { - return fmt.Errorf("error querying security groups for ELB: %v", err) + return fmt.Errorf("error querying security groups for ELB: %q", err) } for _, sg := range response { if !c.tagging.hasClusterTag(sg.Tags) { @@ -3028,7 +3028,7 @@ func (c *Cloud) updateInstanceSecurityGroupsForLoadBalancer(lb *elb.LoadBalancer taggedSecurityGroups, err := c.getTaggedSecurityGroups() if err != nil { - return fmt.Errorf("error querying for tagged security groups: %v", err) + return fmt.Errorf("error querying for tagged security groups: %q", err) } // Open the firewall from the load balancer to the instance @@ -3133,7 +3133,7 @@ func (c *Cloud) EnsureLoadBalancerDeleted(clusterName string, service *v1.Servic // De-authorize the load balancer security group from the instances security group err = c.updateInstanceSecurityGroupsForLoadBalancer(lb, nil) if err != nil { - glog.Error("Error deregistering load balancer from instance security groups: ", err) + glog.Errorf("Error deregistering load balancer from instance security groups: %q", err) return err } } @@ -3146,7 +3146,7 @@ func (c *Cloud) EnsureLoadBalancerDeleted(clusterName string, service *v1.Servic _, err = c.elb.DeleteLoadBalancer(request) if err != nil { // TODO: Check if error was because load balancer was concurrently deleted - glog.Error("Error deleting load balancer: ", err) + glog.Errorf("Error deleting load balancer: %q", err) return err } } @@ -3188,7 +3188,7 @@ func (c *Cloud) EnsureLoadBalancerDeleted(clusterName string, service *v1.Servic } } if !ignore { - return fmt.Errorf("error while deleting load balancer security group (%s): %v", securityGroupID, err) + return fmt.Errorf("error while deleting load balancer security group (%s): %q", securityGroupID, err) } } } diff --git a/pkg/cloudprovider/providers/aws/aws_instancegroups.go b/pkg/cloudprovider/providers/aws/aws_instancegroups.go index af3ff541a0a..6bf63ae6fe6 100644 --- a/pkg/cloudprovider/providers/aws/aws_instancegroups.go +++ b/pkg/cloudprovider/providers/aws/aws_instancegroups.go @@ -37,7 +37,7 @@ func ResizeInstanceGroup(asg ASG, instanceGroupName string, size int) error { MaxSize: aws.Int64(int64(size)), } if _, err := asg.UpdateAutoScalingGroup(request); err != nil { - return fmt.Errorf("error resizing AWS autoscaling group: %v", err) + return fmt.Errorf("error resizing AWS autoscaling group: %q", err) } return nil } @@ -57,7 +57,7 @@ func DescribeInstanceGroup(asg ASG, instanceGroupName string) (InstanceGroupInfo } response, err := asg.DescribeAutoScalingGroups(request) if err != nil { - return nil, fmt.Errorf("error listing AWS autoscaling group (%s): %v", instanceGroupName, err) + return nil, fmt.Errorf("error listing AWS autoscaling group (%s): %q", instanceGroupName, err) } if len(response.AutoScalingGroups) == 0 { diff --git a/pkg/cloudprovider/providers/aws/aws_loadbalancer.go b/pkg/cloudprovider/providers/aws/aws_loadbalancer.go index d08403d5785..0a6504ae661 100644 --- a/pkg/cloudprovider/providers/aws/aws_loadbalancer.go +++ b/pkg/cloudprovider/providers/aws/aws_loadbalancer.go @@ -139,7 +139,7 @@ func (c *Cloud) ensureLoadBalancer(namespacedName types.NamespacedName, loadBala glog.V(2).Info("Detaching load balancer from removed subnets") _, err := c.elb.DetachLoadBalancerFromSubnets(request) if err != nil { - return nil, fmt.Errorf("error detaching AWS loadbalancer from subnets: %v", err) + return nil, fmt.Errorf("error detaching AWS loadbalancer from subnets: %q", err) } dirty = true } @@ -151,7 +151,7 @@ func (c *Cloud) ensureLoadBalancer(namespacedName types.NamespacedName, loadBala glog.V(2).Info("Attaching load balancer to added subnets") _, err := c.elb.AttachLoadBalancerToSubnets(request) if err != nil { - return nil, fmt.Errorf("error attaching AWS loadbalancer to subnets: %v", err) + return nil, fmt.Errorf("error attaching AWS loadbalancer to subnets: %q", err) } dirty = true } @@ -170,7 +170,7 @@ func (c *Cloud) ensureLoadBalancer(namespacedName types.NamespacedName, loadBala glog.V(2).Info("Applying updated security groups to load balancer") _, err := c.elb.ApplySecurityGroupsToLoadBalancer(request) if err != nil { - return nil, fmt.Errorf("error applying AWS loadbalancer security groups: %v", err) + return nil, fmt.Errorf("error applying AWS loadbalancer security groups: %q", err) } dirty = true } @@ -230,7 +230,7 @@ func (c *Cloud) ensureLoadBalancer(namespacedName types.NamespacedName, loadBala glog.V(2).Info("Deleting removed load balancer listeners") _, err := c.elb.DeleteLoadBalancerListeners(request) if err != nil { - return nil, fmt.Errorf("error deleting AWS loadbalancer listeners: %v", err) + return nil, fmt.Errorf("error deleting AWS loadbalancer listeners: %q", err) } dirty = true } @@ -242,7 +242,7 @@ func (c *Cloud) ensureLoadBalancer(namespacedName types.NamespacedName, loadBala glog.V(2).Info("Creating added load balancer listeners") _, err := c.elb.CreateLoadBalancerListeners(request) if err != nil { - return nil, fmt.Errorf("error creating AWS loadbalancer listeners: %v", err) + return nil, fmt.Errorf("error creating AWS loadbalancer listeners: %q", err) } dirty = true } @@ -339,7 +339,7 @@ func (c *Cloud) ensureLoadBalancer(namespacedName types.NamespacedName, loadBala modifyAttributesRequest.LoadBalancerAttributes = loadBalancerAttributes _, err = c.elb.ModifyLoadBalancerAttributes(modifyAttributesRequest) if err != nil { - return nil, fmt.Errorf("Unable to update load balancer attributes during attribute sync: %v", err) + return nil, fmt.Errorf("Unable to update load balancer attributes during attribute sync: %q", err) } dirty = true } @@ -411,7 +411,7 @@ func (c *Cloud) ensureLoadBalancerHealthCheck(loadBalancer *elb.LoadBalancerDesc _, err := c.elb.ConfigureHealthCheck(request) if err != nil { - return fmt.Errorf("error configuring load-balancer health-check for %q: %v", name, err) + return fmt.Errorf("error configuring load-balancer health-check for %q: %q", name, err) } return nil @@ -486,7 +486,7 @@ func (c *Cloud) createProxyProtocolPolicy(loadBalancerName string) error { glog.V(2).Info("Creating proxy protocol policy on load balancer") _, err := c.elb.CreateLoadBalancerPolicy(request) if err != nil { - return fmt.Errorf("error creating proxy protocol policy on load balancer: %v", err) + return fmt.Errorf("error creating proxy protocol policy on load balancer: %q", err) } return nil @@ -505,7 +505,7 @@ func (c *Cloud) setBackendPolicies(loadBalancerName string, instancePort int64, } _, err := c.elb.SetLoadBalancerPoliciesForBackendServer(request) if err != nil { - return fmt.Errorf("error adjusting AWS loadbalancer backend policies: %v", err) + return fmt.Errorf("error adjusting AWS loadbalancer backend policies: %q", err) } return nil diff --git a/pkg/cloudprovider/providers/aws/aws_routes.go b/pkg/cloudprovider/providers/aws/aws_routes.go index f24220d78fa..c2563ace17b 100644 --- a/pkg/cloudprovider/providers/aws/aws_routes.go +++ b/pkg/cloudprovider/providers/aws/aws_routes.go @@ -131,7 +131,7 @@ func (c *Cloud) configureInstanceSourceDestCheck(instanceID string, sourceDestCh _, err := c.ec2.ModifyInstanceAttribute(request) if err != nil { - return fmt.Errorf("error configuring source-dest-check on instance %s: %v", instanceID, err) + return fmt.Errorf("error configuring source-dest-check on instance %s: %q", instanceID, err) } return nil } @@ -178,7 +178,7 @@ func (c *Cloud) CreateRoute(clusterName string, nameHint string, route *cloudpro _, err = c.ec2.DeleteRoute(request) if err != nil { - return fmt.Errorf("error deleting blackholed AWS route (%s): %v", aws.StringValue(deleteRoute.DestinationCidrBlock), err) + return fmt.Errorf("error deleting blackholed AWS route (%s): %q", aws.StringValue(deleteRoute.DestinationCidrBlock), err) } } @@ -190,7 +190,7 @@ func (c *Cloud) CreateRoute(clusterName string, nameHint string, route *cloudpro _, err = c.ec2.CreateRoute(request) if err != nil { - return fmt.Errorf("error creating AWS route (%s): %v", route.DestinationCIDR, err) + return fmt.Errorf("error creating AWS route (%s): %q", route.DestinationCIDR, err) } return nil @@ -210,7 +210,7 @@ func (c *Cloud) DeleteRoute(clusterName string, route *cloudprovider.Route) erro _, err = c.ec2.DeleteRoute(request) if err != nil { - return fmt.Errorf("error deleting AWS route (%s): %v", route.DestinationCIDR, err) + return fmt.Errorf("error deleting AWS route (%s): %q", route.DestinationCIDR, err) } return nil diff --git a/pkg/cloudprovider/providers/aws/tags.go b/pkg/cloudprovider/providers/aws/tags.go index ef89d17266b..2b0ff8c2c7c 100644 --- a/pkg/cloudprovider/providers/aws/tags.go +++ b/pkg/cloudprovider/providers/aws/tags.go @@ -179,7 +179,7 @@ func (c *awsTagging) readRepairClusterTags(client EC2, resourceID string, lifecy } if err := c.createTags(client, resourceID, lifecycle, addTags); err != nil { - return fmt.Errorf("error adding missing tags to resource %q: %v", resourceID, err) + return fmt.Errorf("error adding missing tags to resource %q: %q", resourceID, err) } return nil @@ -222,7 +222,7 @@ func (t *awsTagging) createTags(client EC2, resourceID string, lifecycle Resourc // We could check that the error is retryable, but the error code changes based on what we are tagging // SecurityGroup: InvalidGroup.NotFound - glog.V(2).Infof("Failed to create tags; will retry. Error was %v", err) + glog.V(2).Infof("Failed to create tags; will retry. Error was %q", err) lastErr = err return false, nil }) From b4c9314520fe6c10fa0e791eb0918bb38e503098 Mon Sep 17 00:00:00 2001 From: Hasanat Kazmi Date: Fri, 23 Jun 2017 08:34:53 -0700 Subject: [PATCH 056/448] removed 'Storage' option from 'kubectl top' like options --- pkg/generated/bindata.go | 30 +++++++++---------- .../kubectl/default/LC_MESSAGES/k8s.po | 12 ++++---- translations/kubectl/en_US/LC_MESSAGES/k8s.po | 12 ++++---- translations/kubectl/template.pot | 6 ++-- 4 files changed, 30 insertions(+), 30 deletions(-) diff --git a/pkg/generated/bindata.go b/pkg/generated/bindata.go index 7312705f6c0..3b46cac4b29 100644 --- a/pkg/generated/bindata.go +++ b/pkg/generated/bindata.go @@ -3075,18 +3075,18 @@ msgstr "Describe one or many contexts" # https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/top_node.go#L77 #: pkg/kubectl/cmd/top_node.go:78 -msgid "Display Resource (CPU/Memory/Storage) usage of nodes" -msgstr "Display Resource (CPU/Memory/Storage) usage of nodes" +msgid "Display Resource (CPU/Memory) usage of nodes" +msgstr "Display Resource (CPU/Memory) usage of nodes" # https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/top_pod.go#L79 #: pkg/kubectl/cmd/top_pod.go:80 -msgid "Display Resource (CPU/Memory/Storage) usage of pods" -msgstr "Display Resource (CPU/Memory/Storage) usage of pods" +msgid "Display Resource (CPU/Memory) usage of pods" +msgstr "Display Resource (CPU/Memory) usage of pods" # https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/top.go#L43 #: pkg/kubectl/cmd/top.go:44 -msgid "Display Resource (CPU/Memory/Storage) usage." -msgstr "Display Resource (CPU/Memory/Storage) usage." +msgid "Display Resource (CPU/Memory) usage." +msgstr "Display Resource (CPU/Memory) usage." # https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/clusterinfo.go#L49 #: pkg/kubectl/cmd/clusterinfo.go:51 @@ -6551,18 +6551,18 @@ msgstr "Describe one or many contexts" # https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/top_node.go#L77 #: pkg/kubectl/cmd/top_node.go:78 -msgid "Display Resource (CPU/Memory/Storage) usage of nodes" -msgstr "Display Resource (CPU/Memory/Storage) usage of nodes" +msgid "Display Resource (CPU/Memory) usage of nodes" +msgstr "Display Resource (CPU/Memory) usage of nodes" # https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/top_pod.go#L79 #: pkg/kubectl/cmd/top_pod.go:80 -msgid "Display Resource (CPU/Memory/Storage) usage of pods" -msgstr "Display Resource (CPU/Memory/Storage) usage of pods" +msgid "Display Resource (CPU/Memory) usage of pods" +msgstr "Display Resource (CPU/Memory) usage of pods" # https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/top.go#L43 #: pkg/kubectl/cmd/top.go:44 -msgid "Display Resource (CPU/Memory/Storage) usage." -msgstr "Display Resource (CPU/Memory/Storage) usage." +msgid "Display Resource (CPU/Memory) usage." +msgstr "Display Resource (CPU/Memory) usage." # https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/clusterinfo.go#L49 #: pkg/kubectl/cmd/clusterinfo.go:51 @@ -9105,15 +9105,15 @@ msgid "Describe one or many contexts" msgstr "" #: pkg/kubectl/cmd/top_node.go:78 -msgid "Display Resource (CPU/Memory/Storage) usage of nodes" +msgid "Display Resource (CPU/Memory) usage of nodes" msgstr "" #: pkg/kubectl/cmd/top_pod.go:80 -msgid "Display Resource (CPU/Memory/Storage) usage of pods" +msgid "Display Resource (CPU/Memory) usage of pods" msgstr "" #: pkg/kubectl/cmd/top.go:44 -msgid "Display Resource (CPU/Memory/Storage) usage." +msgid "Display Resource (CPU/Memory) usage." msgstr "" #: pkg/kubectl/cmd/clusterinfo.go:51 diff --git a/translations/kubectl/default/LC_MESSAGES/k8s.po b/translations/kubectl/default/LC_MESSAGES/k8s.po index fcbf43fbe11..6d80e41167e 100644 --- a/translations/kubectl/default/LC_MESSAGES/k8s.po +++ b/translations/kubectl/default/LC_MESSAGES/k8s.po @@ -2850,18 +2850,18 @@ msgstr "Describe one or many contexts" # https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/top_node.go#L77 #: pkg/kubectl/cmd/top_node.go:78 -msgid "Display Resource (CPU/Memory/Storage) usage of nodes" -msgstr "Display Resource (CPU/Memory/Storage) usage of nodes" +msgid "Display Resource (CPU/Memory) usage of nodes" +msgstr "Display Resource (CPU/Memory) usage of nodes" # https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/top_pod.go#L79 #: pkg/kubectl/cmd/top_pod.go:80 -msgid "Display Resource (CPU/Memory/Storage) usage of pods" -msgstr "Display Resource (CPU/Memory/Storage) usage of pods" +msgid "Display Resource (CPU/Memory) usage of pods" +msgstr "Display Resource (CPU/Memory) usage of pods" # https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/top.go#L43 #: pkg/kubectl/cmd/top.go:44 -msgid "Display Resource (CPU/Memory/Storage) usage." -msgstr "Display Resource (CPU/Memory/Storage) usage." +msgid "Display Resource (CPU/Memory) usage." +msgstr "Display Resource (CPU/Memory) usage." # https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/clusterinfo.go#L49 #: pkg/kubectl/cmd/clusterinfo.go:51 diff --git a/translations/kubectl/en_US/LC_MESSAGES/k8s.po b/translations/kubectl/en_US/LC_MESSAGES/k8s.po index bc814d701fc..3dad3733f38 100644 --- a/translations/kubectl/en_US/LC_MESSAGES/k8s.po +++ b/translations/kubectl/en_US/LC_MESSAGES/k8s.po @@ -2849,18 +2849,18 @@ msgstr "Describe one or many contexts" # https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/top_node.go#L77 #: pkg/kubectl/cmd/top_node.go:78 -msgid "Display Resource (CPU/Memory/Storage) usage of nodes" -msgstr "Display Resource (CPU/Memory/Storage) usage of nodes" +msgid "Display Resource (CPU/Memory) usage of nodes" +msgstr "Display Resource (CPU/Memory) usage of nodes" # https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/top_pod.go#L79 #: pkg/kubectl/cmd/top_pod.go:80 -msgid "Display Resource (CPU/Memory/Storage) usage of pods" -msgstr "Display Resource (CPU/Memory/Storage) usage of pods" +msgid "Display Resource (CPU/Memory) usage of pods" +msgstr "Display Resource (CPU/Memory) usage of pods" # https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/top.go#L43 #: pkg/kubectl/cmd/top.go:44 -msgid "Display Resource (CPU/Memory/Storage) usage." -msgstr "Display Resource (CPU/Memory/Storage) usage." +msgid "Display Resource (CPU/Memory) usage." +msgstr "Display Resource (CPU/Memory) usage." # https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/clusterinfo.go#L49 #: pkg/kubectl/cmd/clusterinfo.go:51 diff --git a/translations/kubectl/template.pot b/translations/kubectl/template.pot index 6cf179aa1b4..2a6eea3e129 100644 --- a/translations/kubectl/template.pot +++ b/translations/kubectl/template.pot @@ -1688,15 +1688,15 @@ msgid "Describe one or many contexts" msgstr "" #: pkg/kubectl/cmd/top_node.go:78 -msgid "Display Resource (CPU/Memory/Storage) usage of nodes" +msgid "Display Resource (CPU/Memory) usage of nodes" msgstr "" #: pkg/kubectl/cmd/top_pod.go:80 -msgid "Display Resource (CPU/Memory/Storage) usage of pods" +msgid "Display Resource (CPU/Memory) usage of pods" msgstr "" #: pkg/kubectl/cmd/top.go:44 -msgid "Display Resource (CPU/Memory/Storage) usage." +msgid "Display Resource (CPU/Memory) usage." msgstr "" #: pkg/kubectl/cmd/clusterinfo.go:51 From a97a9f9dd555025bd39a2e9fa933e9e1487e9ee2 Mon Sep 17 00:00:00 2001 From: FengyunPan Date: Thu, 8 Jun 2017 19:55:23 +0800 Subject: [PATCH 057/448] Display for clusterIP and port when service is ExternalName --- pkg/printers/internalversion/printers.go | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/pkg/printers/internalversion/printers.go b/pkg/printers/internalversion/printers.go index 9eb1b85d64d..3f76036153c 100644 --- a/pkg/printers/internalversion/printers.go +++ b/pkg/printers/internalversion/printers.go @@ -745,7 +745,14 @@ func printService(svc *api.Service, w io.Writer, options printers.PrintOptions) namespace := svc.Namespace svcType := svc.Spec.Type internalIP := svc.Spec.ClusterIP + if len(internalIP) == 0 { + internalIP = "" + } externalIP := getServiceExternalIP(svc, options.Wide) + svcPorts := makePortString(svc.Spec.Ports) + if len(svcPorts) == 0 { + svcPorts = "" + } if options.WithNamespace { if _, err := fmt.Fprintf(w, "%s\t", namespace); err != nil { @@ -757,7 +764,7 @@ func printService(svc *api.Service, w io.Writer, options printers.PrintOptions) string(svcType), internalIP, externalIP, - makePortString(svc.Spec.Ports), + svcPorts, translateTimestamp(svc.CreationTimestamp), ); err != nil { return err From b9c1848fbda45ff2a06ec9ce46a6c2d48b12fea0 Mon Sep 17 00:00:00 2001 From: FengyunPan Date: Sat, 24 Jun 2017 00:10:33 +0800 Subject: [PATCH 058/448] Fix output extra comma When running 'kubectl get service', I get a extra comma in result: 'EXTERNAL-IP:,172.16.0.12', but except: 'EXTERNAL-IP:172.16.0.12'. --- pkg/printers/internalversion/printers.go | 8 +- pkg/printers/internalversion/printers_test.go | 119 +++++++++++++++++- 2 files changed, 121 insertions(+), 6 deletions(-) diff --git a/pkg/printers/internalversion/printers.go b/pkg/printers/internalversion/printers.go index 3f76036153c..1cbb32e3ddb 100644 --- a/pkg/printers/internalversion/printers.go +++ b/pkg/printers/internalversion/printers.go @@ -715,8 +715,12 @@ func getServiceExternalIP(svc *api.Service, wide bool) string { case api.ServiceTypeLoadBalancer: lbIps := loadBalancerStatusStringer(svc.Status.LoadBalancer, wide) if len(svc.Spec.ExternalIPs) > 0 { - result := append(strings.Split(lbIps, ","), svc.Spec.ExternalIPs...) - return strings.Join(result, ",") + results := []string{} + if len(lbIps) > 0 { + results = append(results, strings.Split(lbIps, ",")...) + } + results = append(results, svc.Spec.ExternalIPs...) + return strings.Join(results, ",") } if len(lbIps) > 0 { return lbIps diff --git a/pkg/printers/internalversion/printers_test.go b/pkg/printers/internalversion/printers_test.go index 3baac7df667..3243b24efd5 100644 --- a/pkg/printers/internalversion/printers_test.go +++ b/pkg/printers/internalversion/printers_test.go @@ -2320,6 +2320,8 @@ func TestPrintPodShowLabels(t *testing.T) { } func TestPrintService(t *testing.T) { + single_ExternalIP := []string{"80.11.12.10"} + mul_ExternalIP := []string{"80.11.12.10", "80.11.12.11"} tests := []struct { service api.Service expect string @@ -2331,8 +2333,10 @@ func TestPrintService(t *testing.T) { Spec: api.ServiceSpec{ Type: api.ServiceTypeClusterIP, Ports: []api.ServicePort{ - {Protocol: "tcp", - Port: 2233}, + { + Protocol: "tcp", + Port: 2233, + }, }, ClusterIP: "10.9.8.7", }, @@ -2340,13 +2344,14 @@ func TestPrintService(t *testing.T) { "test1\tClusterIP\t10.9.8.7\t\t2233/tcp\t\n", }, { - // Test name, cluster ip, port:nodePort with protocol + // Test NodePort service api.Service{ ObjectMeta: metav1.ObjectMeta{Name: "test2"}, Spec: api.ServiceSpec{ Type: api.ServiceTypeNodePort, Ports: []api.ServicePort{ - {Protocol: "tcp", + { + Protocol: "tcp", Port: 8888, NodePort: 9999, }, @@ -2356,6 +2361,112 @@ func TestPrintService(t *testing.T) { }, "test2\tNodePort\t10.9.8.7\t\t8888:9999/tcp\t\n", }, + { + // Test LoadBalancer service + api.Service{ + ObjectMeta: metav1.ObjectMeta{Name: "test3"}, + Spec: api.ServiceSpec{ + Type: api.ServiceTypeLoadBalancer, + Ports: []api.ServicePort{ + { + Protocol: "tcp", + Port: 8888, + }, + }, + ClusterIP: "10.9.8.7", + }, + }, + "test3\tLoadBalancer\t10.9.8.7\t\t8888/tcp\t\n", + }, + { + // Test LoadBalancer service with single ExternalIP and no LoadBalancerStatus + api.Service{ + ObjectMeta: metav1.ObjectMeta{Name: "test4"}, + Spec: api.ServiceSpec{ + Type: api.ServiceTypeLoadBalancer, + Ports: []api.ServicePort{ + { + Protocol: "tcp", + Port: 8888, + }, + }, + ClusterIP: "10.9.8.7", + ExternalIPs: single_ExternalIP, + }, + }, + "test4\tLoadBalancer\t10.9.8.7\t80.11.12.10\t8888/tcp\t\n", + }, + { + // Test LoadBalancer service with single ExternalIP + api.Service{ + ObjectMeta: metav1.ObjectMeta{Name: "test5"}, + Spec: api.ServiceSpec{ + Type: api.ServiceTypeLoadBalancer, + Ports: []api.ServicePort{ + { + Protocol: "tcp", + Port: 8888, + }, + }, + ClusterIP: "10.9.8.7", + ExternalIPs: single_ExternalIP, + }, + Status: api.ServiceStatus{ + LoadBalancer: api.LoadBalancerStatus{ + Ingress: []api.LoadBalancerIngress{ + { + IP: "3.4.5.6", + Hostname: "test.cluster.com", + }, + }, + }, + }, + }, + "test5\tLoadBalancer\t10.9.8.7\t3.4.5.6,80.11.12.10\t8888/tcp\t\n", + }, + { + // Test LoadBalancer service with mul ExternalIPs + api.Service{ + ObjectMeta: metav1.ObjectMeta{Name: "test6"}, + Spec: api.ServiceSpec{ + Type: api.ServiceTypeLoadBalancer, + Ports: []api.ServicePort{ + { + Protocol: "tcp", + Port: 8888, + }, + }, + ClusterIP: "10.9.8.7", + ExternalIPs: mul_ExternalIP, + }, + Status: api.ServiceStatus{ + LoadBalancer: api.LoadBalancerStatus{ + Ingress: []api.LoadBalancerIngress{ + { + IP: "2.3.4.5", + Hostname: "test.cluster.local", + }, + { + IP: "3.4.5.6", + Hostname: "test.cluster.com", + }, + }, + }, + }, + }, + "test6\tLoadBalancer\t10.9.8.7\t2.3.4.5,3.4.5.6,80.11.12.10,80.11.12.11\t8888/tcp\t\n", + }, + { + // Test ExternalName service + api.Service{ + ObjectMeta: metav1.ObjectMeta{Name: "test7"}, + Spec: api.ServiceSpec{ + Type: api.ServiceTypeExternalName, + ExternalName: "my.database.example.com", + }, + }, + "test7\tExternalName\t\tmy.database.example.com\t\t\n", + }, } buf := bytes.NewBuffer([]byte{}) From 321ed7f7cf7aacf121e691a890888fabb38dc30c Mon Sep 17 00:00:00 2001 From: Dan Mace Date: Fri, 23 Jun 2017 15:12:35 -0400 Subject: [PATCH 059/448] Enable vmodule support for all components Support vmodule (via `LOG_SPEC`) for all local cluster components. --- hack/local-up-cluster.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/hack/local-up-cluster.sh b/hack/local-up-cluster.sh index e9cb8b99f33..18f5a735f74 100755 --- a/hack/local-up-cluster.sh +++ b/hack/local-up-cluster.sh @@ -574,6 +574,7 @@ function start_controller_manager { CTLRMGR_LOG=${LOG_DIR}/kube-controller-manager.log ${CONTROLPLANE_SUDO} "${GO_OUT}/hyperkube" controller-manager \ --v=${LOG_LEVEL} \ + --vmodule="${LOG_SPEC}" \ --service-account-private-key-file="${SERVICE_ACCOUNT_KEY}" \ --root-ca-file="${ROOT_CA_FILE}" \ --cluster-signing-cert-file="${CLUSTER_SIGNING_CERT_FILE}" \ @@ -649,6 +650,7 @@ function start_kubelet { 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}" \ From 224dba9a136e3e4014d88b3c2546418066bac026 Mon Sep 17 00:00:00 2001 From: Antoine Pelisse Date: Fri, 26 May 2017 14:00:24 -0700 Subject: [PATCH 060/448] openapi: Fetch protobuf rather than Json This is much faster. --- pkg/kubectl/cmd/util/BUILD | 4 +- pkg/kubectl/cmd/util/cached_discovery.go | 4 +- pkg/kubectl/cmd/util/cached_discovery_test.go | 6 +- pkg/kubectl/cmd/util/openapi/BUILD | 6 +- pkg/kubectl/cmd/util/openapi/openapi.go | 124 +++++++++++------- pkg/kubectl/cmd/util/openapi/openapi_cache.go | 3 +- .../cmd/util/openapi/openapi_cache_test.go | 24 ++-- .../Godeps/Godeps.json | 8 -- .../src/k8s.io/apiserver/Godeps/Godeps.json | 8 -- .../src/k8s.io/client-go/Godeps/Godeps.json | 36 +++-- staging/src/k8s.io/client-go/discovery/BUILD | 7 +- .../client-go/discovery/discovery_client.go | 19 ++- .../discovery/discovery_client_test.go | 63 +++++---- .../src/k8s.io/client-go/discovery/fake/BUILD | 2 +- .../client-go/discovery/fake/discovery.go | 6 +- .../client-go/discovery/restmapper_test.go | 6 +- .../k8s.io/kube-aggregator/Godeps/Godeps.json | 8 -- .../sample-apiserver/Godeps/Godeps.json | 8 -- 18 files changed, 192 insertions(+), 150 deletions(-) diff --git a/pkg/kubectl/cmd/util/BUILD b/pkg/kubectl/cmd/util/BUILD index d17bbce08ea..722e7e395a4 100644 --- a/pkg/kubectl/cmd/util/BUILD +++ b/pkg/kubectl/cmd/util/BUILD @@ -46,8 +46,8 @@ go_library( "//pkg/version:go_default_library", "//vendor/github.com/emicklei/go-restful-swagger12:go_default_library", "//vendor/github.com/evanphx/json-patch:go_default_library", - "//vendor/github.com/go-openapi/spec: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/core/v1:go_default_library", @@ -108,7 +108,7 @@ go_test( "//pkg/kubectl/resource:go_default_library", "//pkg/util/exec:go_default_library", "//vendor/github.com/emicklei/go-restful-swagger12:go_default_library", - "//vendor/github.com/go-openapi/spec: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", diff --git a/pkg/kubectl/cmd/util/cached_discovery.go b/pkg/kubectl/cmd/util/cached_discovery.go index 5b13e22f525..e48e479eaf0 100644 --- a/pkg/kubectl/cmd/util/cached_discovery.go +++ b/pkg/kubectl/cmd/util/cached_discovery.go @@ -25,8 +25,8 @@ import ( "time" "github.com/emicklei/go-restful-swagger12" - "github.com/go-openapi/spec" "github.com/golang/glog" + "github.com/googleapis/gnostic/OpenAPIv2" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -237,7 +237,7 @@ func (d *CachedDiscoveryClient) SwaggerSchema(version schema.GroupVersion) (*swa return d.delegate.SwaggerSchema(version) } -func (d *CachedDiscoveryClient) OpenAPISchema() (*spec.Swagger, error) { +func (d *CachedDiscoveryClient) OpenAPISchema() (*openapi_v2.Document, error) { return d.delegate.OpenAPISchema() } diff --git a/pkg/kubectl/cmd/util/cached_discovery_test.go b/pkg/kubectl/cmd/util/cached_discovery_test.go index e11e9b48015..ac8799cf5da 100644 --- a/pkg/kubectl/cmd/util/cached_discovery_test.go +++ b/pkg/kubectl/cmd/util/cached_discovery_test.go @@ -23,7 +23,7 @@ import ( "time" "github.com/emicklei/go-restful-swagger12" - "github.com/go-openapi/spec" + "github.com/googleapis/gnostic/OpenAPIv2" "github.com/stretchr/testify/assert" "k8s.io/apimachinery/pkg/api/errors" @@ -171,7 +171,7 @@ func (c *fakeDiscoveryClient) SwaggerSchema(version schema.GroupVersion) (*swagg return &swagger.ApiDeclaration{}, nil } -func (c *fakeDiscoveryClient) OpenAPISchema() (*spec.Swagger, error) { +func (c *fakeDiscoveryClient) OpenAPISchema() (*openapi_v2.Document, error) { c.openAPICalls = c.openAPICalls + 1 - return &spec.Swagger{}, nil + return &openapi_v2.Document{}, nil } diff --git a/pkg/kubectl/cmd/util/openapi/BUILD b/pkg/kubectl/cmd/util/openapi/BUILD index 20d3e25e248..fb7ff7fe20a 100644 --- a/pkg/kubectl/cmd/util/openapi/BUILD +++ b/pkg/kubectl/cmd/util/openapi/BUILD @@ -22,6 +22,8 @@ go_library( "//pkg/version:go_default_library", "//vendor/github.com/go-openapi/spec:go_default_library", "//vendor/github.com/golang/glog:go_default_library", + "//vendor/github.com/googleapis/gnostic/OpenAPIv2:go_default_library", + "//vendor/gopkg.in/yaml.v2: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/discovery:go_default_library", @@ -41,12 +43,14 @@ go_test( tags = ["automanaged"], deps = [ "//pkg/kubectl/cmd/util/openapi:go_default_library", - "//vendor/github.com/go-openapi/loads:go_default_library", "//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/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/gopkg.in/yaml.v2:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", ], ) diff --git a/pkg/kubectl/cmd/util/openapi/openapi.go b/pkg/kubectl/cmd/util/openapi/openapi.go index de07e06bd87..0da0cf60340 100644 --- a/pkg/kubectl/cmd/util/openapi/openapi.go +++ b/pkg/kubectl/cmd/util/openapi/openapi.go @@ -20,8 +20,10 @@ import ( "fmt" "strings" - "github.com/go-openapi/spec" + "gopkg.in/yaml.v2" + "github.com/golang/glog" + "github.com/googleapis/gnostic/OpenAPIv2" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/util/sets" @@ -98,7 +100,7 @@ type Kind struct { PrimitiveType string // Extensions are openapi extensions for the object definition. - Extensions spec.Extensions + Extensions map[string]interface{} // Fields are the fields defined for this Kind Fields map[string]Type @@ -130,21 +132,45 @@ type Type struct { // Extensions are extensions for this field and may contain // metadata from the types.go struct field tags. // e.g. contains patchStrategy, patchMergeKey, etc - Extensions spec.Extensions + Extensions map[string]interface{} +} + +func vendorExtensionToMap(e []*openapi_v2.NamedAny) map[string]interface{} { + var 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 + } + if values == nil { + values = make(map[string]interface{}) + } + values[na.GetName()] = value + } + + return values } // NewOpenAPIData parses the resource definitions in openapi data by groupversionkind and name -func NewOpenAPIData(s *spec.Swagger) (*Resources, error) { +func NewOpenAPIData(doc *openapi_v2.Document) (*Resources, error) { o := &Resources{ GroupVersionKindToName: map[schema.GroupVersionKind]string{}, NameToDefinition: map[string]Kind{}, } // Parse and index definitions by name - for name, d := range s.Definitions { - definition := o.parseDefinition(name, d) - o.NameToDefinition[name] = definition + for _, ns := range doc.GetDefinitions().GetAdditionalProperties() { + definition := o.parseDefinition(ns.GetName(), ns.GetValue()) + o.NameToDefinition[ns.GetName()] = definition if len(definition.GroupVersionKind.Kind) > 0 { - o.GroupVersionKindToName[definition.GroupVersionKind] = name + o.GroupVersionKindToName[definition.GroupVersionKind] = ns.GetName() } } @@ -185,12 +211,12 @@ func (o *Resources) getTypeNames(elem Type) []string { return t } -func (o *Resources) parseDefinition(name string, s spec.Schema) Kind { +func (o *Resources) parseDefinition(name string, s *openapi_v2.Schema) Kind { gvk, err := o.getGroupVersionKind(s) value := Kind{ Name: name, GroupVersionKind: gvk, - Extensions: s.Extensions, + Extensions: vendorExtensionToMap(s.GetVendorExtension()), Fields: map[string]Type{}, } if err != nil { @@ -202,13 +228,13 @@ func (o *Resources) parseDefinition(name string, s spec.Schema) Kind { if o.isPrimitive(s) { value.PrimitiveType = o.getTypeNameForField(s) } - for fieldname, property := range s.Properties { - value.Fields[fieldname] = o.parseField(property) + for _, ns := range s.GetProperties().GetAdditionalProperties() { + value.Fields[ns.GetName()] = o.parseField(ns.GetValue()) } return value } -func (o *Resources) parseField(s spec.Schema) Type { +func (o *Resources) parseField(s *openapi_v2.Schema) Type { def := Type{ TypeName: o.getTypeNameForField(s), IsPrimitive: o.isPrimitive(s), @@ -225,14 +251,14 @@ func (o *Resources) parseField(s spec.Schema) Type { def.ElementType = &d } - def.Extensions = s.Extensions + def.Extensions = vendorExtensionToMap(s.GetVendorExtension()) return def } // isArray returns true if s is an array type. -func (o *Resources) isArray(s spec.Schema) bool { - if len(s.Properties) > 0 { +func (o *Resources) isArray(s *openapi_v2.Schema) bool { + if len(s.GetProperties().GetAdditionalProperties()) > 0 { // Open API can have embedded type definitions, but Kubernetes doesn't generate these. // This should just be a sanity check against changing the format. return false @@ -241,8 +267,8 @@ func (o *Resources) isArray(s spec.Schema) bool { } // isMap returns true if s is a map type. -func (o *Resources) isMap(s spec.Schema) bool { - if len(s.Properties) > 0 { +func (o *Resources) isMap(s *openapi_v2.Schema) bool { + if len(s.GetProperties().GetAdditionalProperties()) > 0 { // Open API can have embedded type definitions, but Kubernetes doesn't generate these. // This should just be a sanity check against changing the format. return false @@ -253,8 +279,8 @@ func (o *Resources) isMap(s spec.Schema) bool { // isPrimitive returns true if s is a primitive type // Note: For object references that represent primitive types - e.g. IntOrString - this will // be false, and the referenced Kind will have a non-empty "PrimitiveType". -func (o *Resources) isPrimitive(s spec.Schema) bool { - if len(s.Properties) > 0 { +func (o *Resources) isPrimitive(s *openapi_v2.Schema) bool { + if len(s.GetProperties().GetAdditionalProperties()) > 0 { // Open API can have embedded type definitions, but Kubernetes doesn't generate these. // This should just be a sanity check against changing the format. return false @@ -266,96 +292,96 @@ func (o *Resources) isPrimitive(s spec.Schema) bool { return false } -func (*Resources) getType(s spec.Schema) string { - if len(s.Type) != 1 { +func (*Resources) getType(s *openapi_v2.Schema) string { + if len(s.GetType().GetValue()) != 1 { return "" } - return strings.ToLower(s.Type[0]) + return strings.ToLower(s.GetType().GetValue()[0]) } -func (o *Resources) getTypeNameForField(s spec.Schema) string { +func (o *Resources) getTypeNameForField(s *openapi_v2.Schema) string { // Get the reference for complex types if o.isDefinitionReference(s) { return o.nameForDefinitionField(s) } // Recurse if type is array if o.isArray(s) { - return fmt.Sprintf("%s array", o.getTypeNameForField(*s.Items.Schema)) + return fmt.Sprintf("%s array", o.getTypeNameForField(s.GetItems().GetSchema()[0])) } if o.isMap(s) { - return fmt.Sprintf("%s map", o.getTypeNameForField(*s.AdditionalProperties.Schema)) + return fmt.Sprintf("%s map", o.getTypeNameForField(s.GetAdditionalProperties().GetSchema())) } // Get the value for primitive types if o.isPrimitive(s) { - return fmt.Sprintf("%s", s.Type[0]) + return fmt.Sprintf("%s", s.GetType().GetValue()[0]) } return "" } // isDefinitionReference returns true s is a complex type that should have a Kind. -func (o *Resources) isDefinitionReference(s spec.Schema) bool { - if len(s.Properties) > 0 { +func (o *Resources) isDefinitionReference(s *openapi_v2.Schema) bool { + if len(s.GetProperties().GetAdditionalProperties()) > 0 { // Open API can have embedded type definitions, but Kubernetes doesn't generate these. // This should just be a sanity check against changing the format. return false } - if len(s.Type) > 0 { + if len(s.GetType().GetValue()) > 0 { // Definition references won't have a type return false } - p := s.SchemaProps.Ref.GetPointer().String() - return len(p) > 0 && strings.HasPrefix(p, "/definitions/") + p := s.GetXRef() + return len(p) > 0 && strings.HasPrefix(p, "#/definitions/") } // getElementType returns the type of an element for arrays // returns an error if s is not an array. -func (o *Resources) getElementType(s spec.Schema) (spec.Schema, error) { +func (o *Resources) getElementType(s *openapi_v2.Schema) (*openapi_v2.Schema, error) { if !o.isArray(s) { - return spec.Schema{}, fmt.Errorf("%v is not an array type", s.Type) + return &openapi_v2.Schema{}, fmt.Errorf("%v is not an array type", o.getTypeNameForField(s)) } - return *s.Items.Schema, nil + return s.GetItems().GetSchema()[0], nil } -// getElementType returns the type of an element for maps +// getValueType returns the type of an element for maps // returns an error if s is not a map. -func (o *Resources) getValueType(s spec.Schema) (spec.Schema, error) { +func (o *Resources) getValueType(s *openapi_v2.Schema) (*openapi_v2.Schema, error) { if !o.isMap(s) { - return spec.Schema{}, fmt.Errorf("%v is not an map type", s.Type) + return &openapi_v2.Schema{}, fmt.Errorf("%v is not an map type", o.getTypeNameForField(s)) } - return *s.AdditionalProperties.Schema, nil + return s.GetAdditionalProperties().GetSchema(), nil } // nameForDefinitionField returns the definition name for the schema (field) if it is a complex type -func (o *Resources) nameForDefinitionField(s spec.Schema) string { - p := s.SchemaProps.Ref.GetPointer().String() +func (o *Resources) nameForDefinitionField(s *openapi_v2.Schema) string { + p := s.GetXRef() if len(p) == 0 { return "" } // Strip the "definitions/" pieces of the reference - return strings.Replace(p, "/definitions/", "", -1) + return strings.Replace(p, "#/definitions/", "", -1) } // getGroupVersionKind implements OpenAPIData // getGVK parses the gropuversionkind for a resource definition from the x-kubernetes // extensions -// Expected format for s.Extensions: map[string][]map[string]string // map[x-kubernetes-group-version-kind:[map[Group:authentication.k8s.io Version:v1 Kind:TokenReview]]] -func (o *Resources) getGroupVersionKind(s spec.Schema) (schema.GroupVersionKind, error) { +func (o *Resources) getGroupVersionKind(s *openapi_v2.Schema) (schema.GroupVersionKind, error) { empty := schema.GroupVersionKind{} + extensionMap := vendorExtensionToMap(s.GetVendorExtension()) // Get the extensions - extList, f := s.Extensions[groupVersionKindExtensionKey] + extList, f := extensionMap[groupVersionKindExtensionKey] if !f { - return empty, fmt.Errorf("No %s extension present in %v", groupVersionKindExtensionKey, s.Extensions) + return empty, fmt.Errorf("No %s extension present in %v", groupVersionKindExtensionKey, extensionMap) } // Expect a empty of a list with 1 element extListCasted, ok := extList.([]interface{}) if !ok { - return empty, fmt.Errorf("%s extension has unexpected type %T in %s", groupVersionKindExtensionKey, extListCasted, s.Extensions) + return empty, fmt.Errorf("%s extension has unexpected type %T in %s", groupVersionKindExtensionKey, extListCasted, extensionMap) } if len(extListCasted) == 0 { return empty, fmt.Errorf("No Group Version Kind found in %v", extListCasted) @@ -366,9 +392,9 @@ func (o *Resources) getGroupVersionKind(s spec.Schema) (schema.GroupVersionKind, gvk := extListCasted[0] // Expect a empty of a map with 3 entries - gvkMap, ok := gvk.(map[string]interface{}) + gvkMap, ok := gvk.(map[interface{}]interface{}) if !ok { - return empty, fmt.Errorf("%s extension has unexpected type %T in %s", groupVersionKindExtensionKey, gvk, s.Extensions) + return empty, fmt.Errorf("%s extension has unexpected type %T in %s", groupVersionKindExtensionKey, gvk, extList) } group, ok := gvkMap["group"].(string) if !ok { diff --git a/pkg/kubectl/cmd/util/openapi/openapi_cache.go b/pkg/kubectl/cmd/util/openapi/openapi_cache.go index 25f55171c03..98d7341c43d 100644 --- a/pkg/kubectl/cmd/util/openapi/openapi_cache.go +++ b/pkg/kubectl/cmd/util/openapi/openapi_cache.go @@ -187,7 +187,6 @@ func linkFiles(old, new string) error { // registerBinaryEncodingTypes registers the types so they can be binary encoded by gob func registerBinaryEncodingTypes() { - gob.Register(map[string]interface{}{}) + gob.Register(map[interface{}]interface{}{}) gob.Register([]interface{}{}) - gob.Register(Resources{}) } diff --git a/pkg/kubectl/cmd/util/openapi/openapi_cache_test.go b/pkg/kubectl/cmd/util/openapi/openapi_cache_test.go index 1f61d221789..19c47bc0a45 100644 --- a/pkg/kubectl/cmd/util/openapi/openapi_cache_test.go +++ b/pkg/kubectl/cmd/util/openapi/openapi_cache_test.go @@ -23,8 +23,10 @@ import ( "path/filepath" "sync" - "github.com/go-openapi/loads" - "github.com/go-openapi/spec" + "gopkg.in/yaml.v2" + + "github.com/googleapis/gnostic/OpenAPIv2" + "github.com/googleapis/gnostic/compiler" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" @@ -220,7 +222,7 @@ type fakeOpenAPIClient struct { err error } -func (f *fakeOpenAPIClient) OpenAPISchema() (*spec.Swagger, error) { +func (f *fakeOpenAPIClient) OpenAPISchema() (*openapi_v2.Document, error) { f.calls = f.calls + 1 if f.err != nil { @@ -235,11 +237,11 @@ var data apiData type apiData struct { sync.Once - data *spec.Swagger + data *openapi_v2.Document err error } -func (d *apiData) OpenAPISchema() (*spec.Swagger, error) { +func (d *apiData) OpenAPISchema() (*openapi_v2.Document, error) { d.Do(func() { // Get the path to the swagger.json file wd, err := os.Getwd() @@ -261,14 +263,18 @@ func (d *apiData) OpenAPISchema() (*spec.Swagger, error) { d.err = err return } - // Load the openapi document - doc, err := loads.Spec(specpath) + spec, err := ioutil.ReadFile(specpath) if err != nil { d.err = err return } - - d.data = doc.Spec() + var info yaml.MapSlice + err = yaml.Unmarshal(spec, &info) + if err != nil { + d.err = err + return + } + d.data, d.err = openapi_v2.NewDocument(info, compiler.NewContext("$root", nil)) }) return d.data, d.err } diff --git a/staging/src/k8s.io/apiextensions-apiserver/Godeps/Godeps.json b/staging/src/k8s.io/apiextensions-apiserver/Godeps/Godeps.json index 709cfb456b8..7c976e00f11 100644 --- a/staging/src/k8s.io/apiextensions-apiserver/Godeps/Godeps.json +++ b/staging/src/k8s.io/apiextensions-apiserver/Godeps/Godeps.json @@ -106,10 +106,6 @@ "ImportPath": "github.com/ghodss/yaml", "Rev": "73d445a93680fa1a78ae23a5839bad48f32ba1ee" }, - { - "ImportPath": "github.com/go-openapi/analysis", - "Rev": "b44dc874b601d9e4e2f6e19140e794ba24bead3b" - }, { "ImportPath": "github.com/go-openapi/jsonpointer", "Rev": "46af16f9f7b149af66e5d1bd010e3574dc06de98" @@ -118,10 +114,6 @@ "ImportPath": "github.com/go-openapi/jsonreference", "Rev": "13c6e3589ad90f49bd3e3bbe2c2cb3d7a4142272" }, - { - "ImportPath": "github.com/go-openapi/loads", - "Rev": "18441dfa706d924a39a030ee2c3b1d8d81917b38" - }, { "ImportPath": "github.com/go-openapi/spec", "Rev": "6aced65f8501fe1217321abf0749d354824ba2ff" diff --git a/staging/src/k8s.io/apiserver/Godeps/Godeps.json b/staging/src/k8s.io/apiserver/Godeps/Godeps.json index a8ae808dbfd..6b500d9b9ce 100644 --- a/staging/src/k8s.io/apiserver/Godeps/Godeps.json +++ b/staging/src/k8s.io/apiserver/Godeps/Godeps.json @@ -326,10 +326,6 @@ "ImportPath": "github.com/ghodss/yaml", "Rev": "73d445a93680fa1a78ae23a5839bad48f32ba1ee" }, - { - "ImportPath": "github.com/go-openapi/analysis", - "Rev": "b44dc874b601d9e4e2f6e19140e794ba24bead3b" - }, { "ImportPath": "github.com/go-openapi/jsonpointer", "Rev": "46af16f9f7b149af66e5d1bd010e3574dc06de98" @@ -338,10 +334,6 @@ "ImportPath": "github.com/go-openapi/jsonreference", "Rev": "13c6e3589ad90f49bd3e3bbe2c2cb3d7a4142272" }, - { - "ImportPath": "github.com/go-openapi/loads", - "Rev": "18441dfa706d924a39a030ee2c3b1d8d81917b38" - }, { "ImportPath": "github.com/go-openapi/spec", "Rev": "6aced65f8501fe1217321abf0749d354824ba2ff" diff --git a/staging/src/k8s.io/client-go/Godeps/Godeps.json b/staging/src/k8s.io/client-go/Godeps/Godeps.json index 38823c3f48b..d925a58fb88 100644 --- a/staging/src/k8s.io/client-go/Godeps/Godeps.json +++ b/staging/src/k8s.io/client-go/Godeps/Godeps.json @@ -98,10 +98,6 @@ "ImportPath": "github.com/ghodss/yaml", "Rev": "73d445a93680fa1a78ae23a5839bad48f32ba1ee" }, - { - "ImportPath": "github.com/go-openapi/analysis", - "Rev": "b44dc874b601d9e4e2f6e19140e794ba24bead3b" - }, { "ImportPath": "github.com/go-openapi/jsonpointer", "Rev": "46af16f9f7b149af66e5d1bd010e3574dc06de98" @@ -110,10 +106,6 @@ "ImportPath": "github.com/go-openapi/jsonreference", "Rev": "13c6e3589ad90f49bd3e3bbe2c2cb3d7a4142272" }, - { - "ImportPath": "github.com/go-openapi/loads", - "Rev": "18441dfa706d924a39a030ee2c3b1d8d81917b38" - }, { "ImportPath": "github.com/go-openapi/spec", "Rev": "6aced65f8501fe1217321abf0749d354824ba2ff" @@ -142,10 +134,38 @@ "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/google/gofuzz", "Rev": "44d81051d367757e1c7c6a5a86423ece9afcf63c" }, + { + "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/hashicorp/golang-lru", "Rev": "a0d98a5f288019575c6d1f4bb1573fef2d1fcdc4" diff --git a/staging/src/k8s.io/client-go/discovery/BUILD b/staging/src/k8s.io/client-go/discovery/BUILD index a1dbf33e007..c111ec854cd 100644 --- a/staging/src/k8s.io/client-go/discovery/BUILD +++ b/staging/src/k8s.io/client-go/discovery/BUILD @@ -19,9 +19,9 @@ go_library( tags = ["automanaged"], deps = [ "//vendor/github.com/emicklei/go-restful-swagger12:go_default_library", - "//vendor/github.com/go-openapi/loads:go_default_library", - "//vendor/github.com/go-openapi/spec:go_default_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/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", @@ -46,7 +46,8 @@ go_test( tags = ["automanaged"], deps = [ "//vendor/github.com/emicklei/go-restful-swagger12:go_default_library", - "//vendor/github.com/go-openapi/spec:go_default_library", + "//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", diff --git a/staging/src/k8s.io/client-go/discovery/discovery_client.go b/staging/src/k8s.io/client-go/discovery/discovery_client.go index 64f32cefb32..45ae17c35e2 100644 --- a/staging/src/k8s.io/client-go/discovery/discovery_client.go +++ b/staging/src/k8s.io/client-go/discovery/discovery_client.go @@ -24,9 +24,9 @@ import ( "strings" "github.com/emicklei/go-restful-swagger12" + "github.com/golang/protobuf/proto" + "github.com/googleapis/gnostic/OpenAPIv2" - "github.com/go-openapi/loads" - "github.com/go-openapi/spec" "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -97,7 +97,7 @@ type SwaggerSchemaInterface interface { // OpenAPISchemaInterface has a method to retrieve the open API schema. type OpenAPISchemaInterface interface { // OpenAPISchema retrieves and parses the swagger API schema the server supports. - OpenAPISchema() (*spec.Swagger, error) + OpenAPISchema() (*openapi_v2.Document, error) } // DiscoveryClient implements the functions that discover server-supported API groups, @@ -375,19 +375,18 @@ func (d *DiscoveryClient) SwaggerSchema(version schema.GroupVersion) (*swagger.A return &schema, nil } -// OpenAPISchema fetches the open api schema using a rest client and parses the json. -// Warning: this is very expensive (~1.2s) -func (d *DiscoveryClient) OpenAPISchema() (*spec.Swagger, error) { - data, err := d.restClient.Get().AbsPath("/swagger.json").Do().Raw() +// OpenAPISchema fetches the open api schema using a rest client and parses the proto. +func (d *DiscoveryClient) OpenAPISchema() (*openapi_v2.Document, error) { + data, err := d.restClient.Get().AbsPath("/swagger-2.0.0.pb-v1").Do().Raw() if err != nil { return nil, err } - msg := json.RawMessage(data) - doc, err := loads.Analyzed(msg, "") + document := &openapi_v2.Document{} + err = proto.Unmarshal(data, document) if err != nil { return nil, err } - return doc.Spec(), err + return document, nil } // withRetries retries the given recovery function in case the groups supported by the server change after ServerGroup() returns. diff --git a/staging/src/k8s.io/client-go/discovery/discovery_client_test.go b/staging/src/k8s.io/client-go/discovery/discovery_client_test.go index 86a2b075a89..e0c908ee39d 100644 --- a/staging/src/k8s.io/client-go/discovery/discovery_client_test.go +++ b/staging/src/k8s.io/client-go/discovery/discovery_client_test.go @@ -19,14 +19,16 @@ package discovery_test import ( "encoding/json" "fmt" + "mime" "net/http" "net/http/httptest" "reflect" "testing" "github.com/emicklei/go-restful-swagger12" + "github.com/gogo/protobuf/proto" + "github.com/googleapis/gnostic/OpenAPIv2" - "github.com/go-openapi/spec" "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -327,30 +329,44 @@ func TestGetSwaggerSchemaFail(t *testing.T) { } } -var returnedOpenAPI = spec.Swagger{ - SwaggerProps: spec.SwaggerProps{ - Definitions: spec.Definitions{ - "fake.type.1": spec.Schema{ - SchemaProps: spec.SchemaProps{ - Properties: map[string]spec.Schema{ - "count": { - SchemaProps: spec.SchemaProps{ - Type: []string{"integer"}, +var returnedOpenAPI = openapi_v2.Document{ + Definitions: &openapi_v2.Definitions{ + AdditionalProperties: []*openapi_v2.NamedSchema{ + { + Name: "fake.type.1", + Value: &openapi_v2.Schema{ + Properties: &openapi_v2.Properties{ + AdditionalProperties: []*openapi_v2.NamedSchema{ + { + Name: "count", + Value: &openapi_v2.Schema{ + Type: &openapi_v2.TypeItem{ + Value: []string{"integer"}, + }, + }, }, }, }, }, }, - "fake.type.2": spec.Schema{ - SchemaProps: spec.SchemaProps{ - Properties: map[string]spec.Schema{ - "count": { - SchemaProps: spec.SchemaProps{ - Type: []string{"array"}, - Items: &spec.SchemaOrArray{ - Schema: &spec.Schema{ - SchemaProps: spec.SchemaProps{ - Type: []string{"string"}, + { + Name: "fake.type.2", + Value: &openapi_v2.Schema{ + Properties: &openapi_v2.Properties{ + AdditionalProperties: []*openapi_v2.NamedSchema{ + { + Name: "count", + Value: &openapi_v2.Schema{ + Type: &openapi_v2.TypeItem{ + Value: []string{"array"}, + }, + Items: &openapi_v2.ItemsItem{ + Schema: []*openapi_v2.Schema{ + { + Type: &openapi_v2.TypeItem{ + Value: []string{"string"}, + }, + }, }, }, }, @@ -366,19 +382,20 @@ var returnedOpenAPI = spec.Swagger{ func openapiSchemaFakeServer() (*httptest.Server, error) { var sErr error server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { - if req.URL.Path != "/swagger.json" { + if req.URL.Path != "/swagger-2.0.0.pb-v1" { sErr = fmt.Errorf("Unexpected url %v", req.URL) } if req.Method != "GET" { sErr = fmt.Errorf("Unexpected method %v", req.Method) } - output, err := json.Marshal(returnedOpenAPI) + mime.AddExtensionType(".pb-v1", "application/com.github.googleapis.gnostic.OpenAPIv2@68f4ded+protobuf") + + output, err := proto.Marshal(&returnedOpenAPI) if err != nil { sErr = err return } - w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusOK) w.Write(output) })) diff --git a/staging/src/k8s.io/client-go/discovery/fake/BUILD b/staging/src/k8s.io/client-go/discovery/fake/BUILD index 470146966e4..8f8f078633f 100644 --- a/staging/src/k8s.io/client-go/discovery/fake/BUILD +++ b/staging/src/k8s.io/client-go/discovery/fake/BUILD @@ -13,7 +13,7 @@ go_library( tags = ["automanaged"], deps = [ "//vendor/github.com/emicklei/go-restful-swagger12:go_default_library", - "//vendor/github.com/go-openapi/spec:go_default_library", + "//vendor/github.com/googleapis/gnostic/OpenAPIv2: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", diff --git a/staging/src/k8s.io/client-go/discovery/fake/discovery.go b/staging/src/k8s.io/client-go/discovery/fake/discovery.go index 2108bad05f3..02e77cfe71f 100644 --- a/staging/src/k8s.io/client-go/discovery/fake/discovery.go +++ b/staging/src/k8s.io/client-go/discovery/fake/discovery.go @@ -20,8 +20,8 @@ import ( "fmt" "github.com/emicklei/go-restful-swagger12" + "github.com/googleapis/gnostic/OpenAPIv2" - "github.com/go-openapi/spec" "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -93,7 +93,9 @@ func (c *FakeDiscovery) SwaggerSchema(version schema.GroupVersion) (*swagger.Api return &swagger.ApiDeclaration{}, nil } -func (c *FakeDiscovery) OpenAPISchema() (*spec.Swagger, error) { return &spec.Swagger{}, nil } +func (c *FakeDiscovery) OpenAPISchema() (*openapi_v2.Document, error) { + return &openapi_v2.Document{}, nil +} func (c *FakeDiscovery) RESTClient() restclient.Interface { return nil diff --git a/staging/src/k8s.io/client-go/discovery/restmapper_test.go b/staging/src/k8s.io/client-go/discovery/restmapper_test.go index 6bc16ccbf41..338925f1b74 100644 --- a/staging/src/k8s.io/client-go/discovery/restmapper_test.go +++ b/staging/src/k8s.io/client-go/discovery/restmapper_test.go @@ -29,7 +29,7 @@ import ( "k8s.io/client-go/rest/fake" "github.com/emicklei/go-restful-swagger12" - "github.com/go-openapi/spec" + "github.com/googleapis/gnostic/OpenAPIv2" "github.com/stretchr/testify/assert" ) @@ -348,6 +348,6 @@ func (c *fakeCachedDiscoveryInterface) SwaggerSchema(version schema.GroupVersion return &swagger.ApiDeclaration{}, nil } -func (c *fakeCachedDiscoveryInterface) OpenAPISchema() (*spec.Swagger, error) { - return &spec.Swagger{}, nil +func (c *fakeCachedDiscoveryInterface) OpenAPISchema() (*openapi_v2.Document, error) { + return &openapi_v2.Document{}, nil } diff --git a/staging/src/k8s.io/kube-aggregator/Godeps/Godeps.json b/staging/src/k8s.io/kube-aggregator/Godeps/Godeps.json index 06f49869cf0..22dc8e3c6e0 100644 --- a/staging/src/k8s.io/kube-aggregator/Godeps/Godeps.json +++ b/staging/src/k8s.io/kube-aggregator/Godeps/Godeps.json @@ -114,10 +114,6 @@ "ImportPath": "github.com/ghodss/yaml", "Rev": "73d445a93680fa1a78ae23a5839bad48f32ba1ee" }, - { - "ImportPath": "github.com/go-openapi/analysis", - "Rev": "b44dc874b601d9e4e2f6e19140e794ba24bead3b" - }, { "ImportPath": "github.com/go-openapi/jsonpointer", "Rev": "46af16f9f7b149af66e5d1bd010e3574dc06de98" @@ -126,10 +122,6 @@ "ImportPath": "github.com/go-openapi/jsonreference", "Rev": "13c6e3589ad90f49bd3e3bbe2c2cb3d7a4142272" }, - { - "ImportPath": "github.com/go-openapi/loads", - "Rev": "18441dfa706d924a39a030ee2c3b1d8d81917b38" - }, { "ImportPath": "github.com/go-openapi/spec", "Rev": "6aced65f8501fe1217321abf0749d354824ba2ff" diff --git a/staging/src/k8s.io/sample-apiserver/Godeps/Godeps.json b/staging/src/k8s.io/sample-apiserver/Godeps/Godeps.json index b57cfc0326a..34b0b993045 100644 --- a/staging/src/k8s.io/sample-apiserver/Godeps/Godeps.json +++ b/staging/src/k8s.io/sample-apiserver/Godeps/Godeps.json @@ -106,10 +106,6 @@ "ImportPath": "github.com/ghodss/yaml", "Rev": "73d445a93680fa1a78ae23a5839bad48f32ba1ee" }, - { - "ImportPath": "github.com/go-openapi/analysis", - "Rev": "b44dc874b601d9e4e2f6e19140e794ba24bead3b" - }, { "ImportPath": "github.com/go-openapi/jsonpointer", "Rev": "46af16f9f7b149af66e5d1bd010e3574dc06de98" @@ -118,10 +114,6 @@ "ImportPath": "github.com/go-openapi/jsonreference", "Rev": "13c6e3589ad90f49bd3e3bbe2c2cb3d7a4142272" }, - { - "ImportPath": "github.com/go-openapi/loads", - "Rev": "18441dfa706d924a39a030ee2c3b1d8d81917b38" - }, { "ImportPath": "github.com/go-openapi/spec", "Rev": "6aced65f8501fe1217321abf0749d354824ba2ff" From 00b62df55483a8addb71af69db5ca413ac5f9863 Mon Sep 17 00:00:00 2001 From: Daniel Nardo Date: Fri, 23 Jun 2017 16:16:23 -0700 Subject: [PATCH 061/448] Do not set CNI on a private master when enabling network policy. --- cluster/gce/gci/configure-helper.sh | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/cluster/gce/gci/configure-helper.sh b/cluster/gce/gci/configure-helper.sh index 95be26aae7c..d9d38a6dd5b 100644 --- a/cluster/gce/gci/configure-helper.sh +++ b/cluster/gce/gci/configure-helper.sh @@ -912,7 +912,11 @@ function start-kubelet { flags+=" --cni-bin-dir=/home/kubernetes/bin" if [[ "${NETWORK_POLICY_PROVIDER:-}" == "calico" ]]; then # Calico uses CNI always. - flags+=" --network-plugin=cni" + if [[ "${KUBERNETES_PRIVATE_MASTER:-}" == "true" ]]; then + flags+=" --network-plugin=${NETWORK_PROVIDER}" + else + flags+=" --network-plugin=cni" + fi else # Otherwise use the configured value. flags+=" --network-plugin=${NETWORK_PROVIDER}" From 9b70ab1379c9699e4bc1894a7560522392c05941 Mon Sep 17 00:00:00 2001 From: Manjunath A Kumatagi Date: Mon, 12 Jun 2017 14:37:12 +0530 Subject: [PATCH 062/448] Multi Arch test images --- test/images/{hostexec => }/Makefile | 34 ++++-- test/images/clusterapi-tester/BASEIMAGE | 5 + test/images/clusterapi-tester/BUILD | 2 +- test/images/clusterapi-tester/Dockerfile | 6 +- test/images/clusterapi-tester/Makefile | 26 ++-- test/images/clusterapi-tester/NAME | 1 + test/images/clusterapi-tester/VERSION | 1 + .../{main.go => clusterapi-tester.go} | 0 test/images/dnsutils/BASEIMAGE | 4 + test/images/dnsutils/Dockerfile | 4 +- test/images/dnsutils/NAME | 1 + test/images/dnsutils/VERSION | 1 + test/images/entrypoint-tester/Makefile | 25 ++-- test/images/entrypoint-tester/NAME | 1 + test/images/entrypoint-tester/VERSION | 1 + test/images/fakegitserver/Dockerfile | 7 +- test/images/fakegitserver/Makefile | 28 ++--- test/images/fakegitserver/NAME | 1 + test/images/fakegitserver/VERSION | 1 + test/images/fakegitserver/prepare.sh | 26 ---- test/images/goproxy/Makefile | 25 ++-- test/images/goproxy/NAME | 1 + test/images/goproxy/VERSION | 1 + test/images/hostexec/BASEIMAGE | 4 + test/images/hostexec/Dockerfile | 6 +- test/images/hostexec/NAME | 1 + test/images/hostexec/VERSION | 1 + test/images/image-util.sh | 112 ++++++++++++++++++ test/images/iperf/BASEIMAGE | 4 + test/images/iperf/Dockerfile | 5 +- test/images/iperf/Makefile | 31 ----- test/images/iperf/NAME | 1 + test/images/iperf/VERSION | 1 + test/images/jessie-dnsutils/BASEIMAGE | 4 + test/images/jessie-dnsutils/Dockerfile | 4 +- test/images/jessie-dnsutils/Makefile | 27 ----- test/images/jessie-dnsutils/NAME | 1 + test/images/jessie-dnsutils/VERSION | 1 + test/images/logs-generator/BASEIMAGE | 4 + test/images/logs-generator/Dockerfile | 8 +- test/images/logs-generator/Makefile | 27 ++--- test/images/logs-generator/NAME | 1 + test/images/logs-generator/VERSION | 1 + test/images/mount-tester-user/BASEIMAGE | 5 + test/images/mount-tester-user/Dockerfile | 2 +- test/images/mount-tester-user/Makefile | 26 ---- test/images/mount-tester-user/NAME | 1 + test/images/mount-tester-user/VERSION | 1 + test/images/mount-tester/Dockerfile | 4 +- test/images/mount-tester/Makefile | 26 ++-- test/images/mount-tester/NAME | 1 + test/images/mount-tester/VERSION | 1 + test/images/n-way-http/BASEIMAGE | 5 + test/images/n-way-http/Dockerfile | 6 +- test/images/n-way-http/Makefile | 26 ++-- test/images/n-way-http/NAME | 1 + test/images/n-way-http/VERSION | 1 + test/images/net/BASEIMAGE | 4 + test/images/net/Dockerfile | 5 +- test/images/net/Makefile | 34 ++---- test/images/net/NAME | 1 + test/images/net/VERSION | 1 + test/images/netexec/BASEIMAGE | 5 + test/images/netexec/Dockerfile | 5 +- test/images/netexec/Makefile | 28 ++--- test/images/netexec/NAME | 1 + test/images/netexec/VERSION | 1 + test/images/network-tester/BUILD | 2 +- test/images/network-tester/Dockerfile | 4 +- test/images/network-tester/Makefile | 27 ++--- test/images/network-tester/NAME | 1 + test/images/network-tester/VERSION | 1 + .../{webserver.go => nettest.go} | 0 test/images/port-forward-tester/Makefile | 25 ++-- test/images/port-forward-tester/NAME | 1 + test/images/port-forward-tester/VERSION | 1 + test/images/porter/Makefile | 42 ++----- test/images/porter/NAME | 1 + test/images/porter/VERSION | 1 + test/images/resource-consumer/.gitignore | 3 + test/images/resource-consumer/BASEIMAGE | 4 + test/images/resource-consumer/Dockerfile | 8 +- test/images/resource-consumer/Makefile | 36 ++---- test/images/resource-consumer/NAME | 1 + test/images/resource-consumer/VERSION | 1 + .../resource-consumer/controller/BASEIMAGE | 5 + .../resource-consumer/controller/Dockerfile | 2 +- .../controller}/Makefile | 24 ++-- test/images/resource-consumer/controller/NAME | 1 + .../resource-consumer/controller/VERSION | 1 + test/images/serve_hostname/BASEIMAGE | 5 + test/images/serve_hostname/Dockerfile | 2 +- test/images/serve_hostname/Makefile | 91 ++------------ test/images/serve_hostname/NAME | 1 + test/images/serve_hostname/VERSION | 1 + 95 files changed, 449 insertions(+), 480 deletions(-) rename test/images/{hostexec => }/Makefile (53%) create mode 100644 test/images/clusterapi-tester/BASEIMAGE create mode 100644 test/images/clusterapi-tester/NAME create mode 100644 test/images/clusterapi-tester/VERSION rename test/images/clusterapi-tester/{main.go => clusterapi-tester.go} (100%) create mode 100644 test/images/dnsutils/BASEIMAGE create mode 100644 test/images/dnsutils/NAME create mode 100644 test/images/dnsutils/VERSION create mode 100644 test/images/entrypoint-tester/NAME create mode 100644 test/images/entrypoint-tester/VERSION create mode 100644 test/images/fakegitserver/NAME create mode 100644 test/images/fakegitserver/VERSION delete mode 100755 test/images/fakegitserver/prepare.sh create mode 100644 test/images/goproxy/NAME create mode 100644 test/images/goproxy/VERSION create mode 100644 test/images/hostexec/BASEIMAGE create mode 100644 test/images/hostexec/NAME create mode 100644 test/images/hostexec/VERSION create mode 100755 test/images/image-util.sh create mode 100644 test/images/iperf/BASEIMAGE delete mode 100644 test/images/iperf/Makefile create mode 100644 test/images/iperf/NAME create mode 100644 test/images/iperf/VERSION create mode 100644 test/images/jessie-dnsutils/BASEIMAGE delete mode 100644 test/images/jessie-dnsutils/Makefile create mode 100644 test/images/jessie-dnsutils/NAME create mode 100644 test/images/jessie-dnsutils/VERSION create mode 100644 test/images/logs-generator/BASEIMAGE create mode 100644 test/images/logs-generator/NAME create mode 100644 test/images/logs-generator/VERSION create mode 100644 test/images/mount-tester-user/BASEIMAGE delete mode 100644 test/images/mount-tester-user/Makefile create mode 100644 test/images/mount-tester-user/NAME create mode 100644 test/images/mount-tester-user/VERSION create mode 100644 test/images/mount-tester/NAME create mode 100644 test/images/mount-tester/VERSION create mode 100644 test/images/n-way-http/BASEIMAGE create mode 100644 test/images/n-way-http/NAME create mode 100644 test/images/n-way-http/VERSION create mode 100644 test/images/net/BASEIMAGE create mode 100644 test/images/net/NAME create mode 100644 test/images/net/VERSION create mode 100644 test/images/netexec/BASEIMAGE create mode 100644 test/images/netexec/NAME create mode 100644 test/images/netexec/VERSION create mode 100644 test/images/network-tester/NAME create mode 100644 test/images/network-tester/VERSION rename test/images/network-tester/{webserver.go => nettest.go} (100%) create mode 100644 test/images/port-forward-tester/NAME create mode 100644 test/images/port-forward-tester/VERSION create mode 100644 test/images/porter/NAME create mode 100644 test/images/porter/VERSION create mode 100644 test/images/resource-consumer/.gitignore create mode 100644 test/images/resource-consumer/BASEIMAGE create mode 100644 test/images/resource-consumer/NAME create mode 100644 test/images/resource-consumer/VERSION create mode 100644 test/images/resource-consumer/controller/BASEIMAGE rename test/images/{dnsutils => resource-consumer/controller}/Makefile (54%) create mode 100644 test/images/resource-consumer/controller/NAME create mode 100644 test/images/resource-consumer/controller/VERSION create mode 100644 test/images/serve_hostname/BASEIMAGE create mode 100644 test/images/serve_hostname/NAME create mode 100644 test/images/serve_hostname/VERSION diff --git a/test/images/hostexec/Makefile b/test/images/Makefile similarity index 53% rename from test/images/hostexec/Makefile rename to test/images/Makefile index 04b4008e4c2..9d5aeb5ebc5 100644 --- a/test/images/hostexec/Makefile +++ b/test/images/Makefile @@ -1,4 +1,4 @@ -# Copyright 2016 The Kubernetes Authors. +# 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. @@ -12,19 +12,29 @@ # See the License for the specific language governing permissions and # limitations under the License. -.PHONY: all image push clean +REGISTRY ?= gcr.io/k8s-e2e-images +GOARM=7 +QEMUVERSION=v2.7.0 +GOLANG_VERSION=1.8.3 +export -TAG = 1.2 -PREFIX = gcr.io/google_containers +ifndef WHAT +$(error WHAT is a required variable, ex: make all WHAT=net) +endif +# Build code. +# +# Args: +# WHAT: Directory names to build. +# +# Example: +# make all WHAT=clusterapi-tester +all: all-container -all: push +all-container: + ./image-util.sh build $(WHAT) -image: - docker build --pull -t $(PREFIX)/hostexec:$(TAG) . +all-push: all-container + ./image-util.sh push $(WHAT) -push: image - gcloud docker -- push $(PREFIX)/hostexec:$(TAG) - -clean: - rm -f hostexec +.PHONY: all all-push all-container diff --git a/test/images/clusterapi-tester/BASEIMAGE b/test/images/clusterapi-tester/BASEIMAGE new file mode 100644 index 00000000000..44329aaa5b1 --- /dev/null +++ b/test/images/clusterapi-tester/BASEIMAGE @@ -0,0 +1,5 @@ +amd64=busybox +arm=arm32v6/busybox +arm64=arm64v8/busybox +ppc64le=ppc64le/busybox +s390x=s390x/busybox diff --git a/test/images/clusterapi-tester/BUILD b/test/images/clusterapi-tester/BUILD index 2e20ac80d0e..98c5c2c528c 100644 --- a/test/images/clusterapi-tester/BUILD +++ b/test/images/clusterapi-tester/BUILD @@ -16,7 +16,7 @@ go_binary( go_library( name = "go_default_library", - srcs = ["main.go"], + srcs = ["clusterapi-tester.go"], tags = ["automanaged"], deps = [ "//pkg/client/clientset_generated/internalclientset:go_default_library", diff --git a/test/images/clusterapi-tester/Dockerfile b/test/images/clusterapi-tester/Dockerfile index 9327d227545..cfb8401d859 100644 --- a/test/images/clusterapi-tester/Dockerfile +++ b/test/images/clusterapi-tester/Dockerfile @@ -12,6 +12,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -FROM busybox -ADD main main -ENTRYPOINT ["/main"] +FROM BASEIMAGE +ADD clusterapi-tester /clusterapi-tester +ENTRYPOINT ["/clusterapi-tester"] diff --git a/test/images/clusterapi-tester/Makefile b/test/images/clusterapi-tester/Makefile index 02a0e5616b6..369c5cad87e 100644 --- a/test/images/clusterapi-tester/Makefile +++ b/test/images/clusterapi-tester/Makefile @@ -12,20 +12,16 @@ # See the License for the specific language governing permissions and # limitations under the License. -all: push +BIN=clusterapi-tester +ARCH ?= amd64 +TARGET ?= $(CURDIR) +GOLANG_VERSION ?= latest -# 0.0 shouldn't clobber any released builds -TAG = 1.0 -PREFIX = gcr.io/google_containers/clusterapi-tester +bin: + docker run --rm -it -v $(TARGET):$(TARGET):Z -v `pwd`/../../../:/go/src/k8s.io/kubernetes:Z \ + golang:$(GOLANG_VERSION) \ + /bin/bash -c "\ + cd /go/src/k8s.io/kubernetes/test/images/clusterapi-tester && \ + CGO_ENABLED=0 GOARM=$(GOARM) GOARCH=$(ARCH) go build -a -installsuffix cgo --ldflags '-w' -o $(TARGET)/$(BIN)" -main: main.go - CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -ldflags '-w' -o main ./main.go - -container: main - docker build --pull -t $(PREFIX):$(TAG) . - -push: container - gcloud docker -- push $(PREFIX):$(TAG) - -clean: - rm -f main +.PHONY: bin diff --git a/test/images/clusterapi-tester/NAME b/test/images/clusterapi-tester/NAME new file mode 100644 index 00000000000..97185c48995 --- /dev/null +++ b/test/images/clusterapi-tester/NAME @@ -0,0 +1 @@ +clusterapi-tester diff --git a/test/images/clusterapi-tester/VERSION b/test/images/clusterapi-tester/VERSION new file mode 100644 index 00000000000..9459d4ba2a0 --- /dev/null +++ b/test/images/clusterapi-tester/VERSION @@ -0,0 +1 @@ +1.1 diff --git a/test/images/clusterapi-tester/main.go b/test/images/clusterapi-tester/clusterapi-tester.go similarity index 100% rename from test/images/clusterapi-tester/main.go rename to test/images/clusterapi-tester/clusterapi-tester.go diff --git a/test/images/dnsutils/BASEIMAGE b/test/images/dnsutils/BASEIMAGE new file mode 100644 index 00000000000..114844f395e --- /dev/null +++ b/test/images/dnsutils/BASEIMAGE @@ -0,0 +1,4 @@ +amd64=alpine:3.6 +arm=arm32v6/alpine:3.6 +arm64=arm64v8/alpine:3.6 +ppc64le=ppc64le/alpine:3.6 diff --git a/test/images/dnsutils/Dockerfile b/test/images/dnsutils/Dockerfile index 2d037e9f843..d041c62703f 100644 --- a/test/images/dnsutils/Dockerfile +++ b/test/images/dnsutils/Dockerfile @@ -12,6 +12,8 @@ # See the License for the specific language governing permissions and # limitations under the License. -FROM alpine +FROM BASEIMAGE + +CROSS_BUILD_COPY qemu-QEMUARCH-static /usr/bin/ RUN apk add --no-cache bind-tools diff --git a/test/images/dnsutils/NAME b/test/images/dnsutils/NAME new file mode 100644 index 00000000000..bca3eb0f23f --- /dev/null +++ b/test/images/dnsutils/NAME @@ -0,0 +1 @@ +dnsutils diff --git a/test/images/dnsutils/VERSION b/test/images/dnsutils/VERSION new file mode 100644 index 00000000000..9459d4ba2a0 --- /dev/null +++ b/test/images/dnsutils/VERSION @@ -0,0 +1 @@ +1.1 diff --git a/test/images/entrypoint-tester/Makefile b/test/images/entrypoint-tester/Makefile index a15e6670582..9d7c516fae6 100644 --- a/test/images/entrypoint-tester/Makefile +++ b/test/images/entrypoint-tester/Makefile @@ -12,19 +12,16 @@ # See the License for the specific language governing permissions and # limitations under the License. -TAG = 0.1 -PREFIX = kubernetes +BIN=ep +ARCH ?= amd64 +TARGET ?= $(CURDIR) +GOLANG_VERSION ?= latest -all: push +bin: + docker run --rm -it -v $(TARGET):$(TARGET):Z -v `pwd`/../../../:/go/src/k8s.io/kubernetes:Z \ + golang:$(GOLANG_VERSION) \ + /bin/bash -c "\ + cd /go/src/k8s.io/kubernetes/test/images/entrypoint-tester && \ + CGO_ENABLED=0 GOARM=$(GOARM) GOARCH=$(ARCH) go build -a -installsuffix cgo --ldflags '-w' -o $(TARGET)/$(BIN) ." -ep: ep.go - CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -ldflags '-w' ./ep.go - -image: ep - sudo docker build --pull -t $(PREFIX)/eptest:$(TAG) . - -push: image - sudo docker push $(PREFIX)/eptest:$(TAG) - -clean: - rm -f ep +.PHONY: bin diff --git a/test/images/entrypoint-tester/NAME b/test/images/entrypoint-tester/NAME new file mode 100644 index 00000000000..e2d8e243c18 --- /dev/null +++ b/test/images/entrypoint-tester/NAME @@ -0,0 +1 @@ +ep diff --git a/test/images/entrypoint-tester/VERSION b/test/images/entrypoint-tester/VERSION new file mode 100644 index 00000000000..3b04cfb60da --- /dev/null +++ b/test/images/entrypoint-tester/VERSION @@ -0,0 +1 @@ +0.2 diff --git a/test/images/fakegitserver/Dockerfile b/test/images/fakegitserver/Dockerfile index 8ec3654f010..e25b13e1d6a 100644 --- a/test/images/fakegitserver/Dockerfile +++ b/test/images/fakegitserver/Dockerfile @@ -13,6 +13,7 @@ # limitations under the License. FROM scratch -ADD GITHASH.txt / -ADD gitserver / -ENTRYPOINT ["/gitserver"] +COPY GITHASH.txt / +COPY fakegitserver / +ENTRYPOINT ["/fakegitserver"] + diff --git a/test/images/fakegitserver/Makefile b/test/images/fakegitserver/Makefile index 98b19cfb1c7..b99b9e049f2 100644 --- a/test/images/fakegitserver/Makefile +++ b/test/images/fakegitserver/Makefile @@ -12,21 +12,17 @@ # See the License for the specific language governing permissions and # limitations under the License. -.PHONY: all image push clean +BIN=fakegitserver +ARCH ?= amd64 +TARGET ?= $(CURDIR) +GOLANG_VERSION ?= latest -TAG = 0.1 -PREFIX = gcr.io/google_containers -IMAGE = fakegitserver -ARCH = amd64 +bin: + docker run --rm -it -v $(TARGET):$(TARGET):Z -v `pwd`/../../../:/go/src/k8s.io/kubernetes:Z \ + golang:$(GOLANG_VERSION) \ + /bin/bash -c "\ + cd /go/src/k8s.io/kubernetes/test/images/fakegitserver && \ + CGO_ENABLED=0 GOARM=$(GOARM) GOARCH=$(ARCH) go build -a -installsuffix cgo --ldflags '-w' -o $(TARGET)/$(BIN) ." + @echo $(shell git rev-parse HEAD) > $(TARGET)/GITHASH.txt -image: - ./prepare.sh $(ARCH) - docker build --pull -t $(PREFIX)/$(IMAGE):$(TAG) . - -push: image - gcloud docker -- push $(PREFIX)/$(IMAGE):$(TAG) - -all: push - -clean: - rm -f gitserver GITHASH.txt +.PHONY: bin diff --git a/test/images/fakegitserver/NAME b/test/images/fakegitserver/NAME new file mode 100644 index 00000000000..1f1e4b248bf --- /dev/null +++ b/test/images/fakegitserver/NAME @@ -0,0 +1 @@ +fakegitserver diff --git a/test/images/fakegitserver/VERSION b/test/images/fakegitserver/VERSION new file mode 100644 index 00000000000..3b04cfb60da --- /dev/null +++ b/test/images/fakegitserver/VERSION @@ -0,0 +1 @@ +0.2 diff --git a/test/images/fakegitserver/prepare.sh b/test/images/fakegitserver/prepare.sh deleted file mode 100755 index 414e0447974..00000000000 --- a/test/images/fakegitserver/prepare.sh +++ /dev/null @@ -1,26 +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. - -set -e -set -x - -ARCH=$1 - -# Build the binary. -CGO_ENABLED=0 GOOS=linux GOARCH=${ARCH} go build -a -installsuffix cgo -ldflags '-w' ./gitserver.go - -# Write down the current commit hash. -echo $(git rev-parse HEAD) >> GITHASH.txt diff --git a/test/images/goproxy/Makefile b/test/images/goproxy/Makefile index f7408cbd95d..ce0b1bcaa58 100644 --- a/test/images/goproxy/Makefile +++ b/test/images/goproxy/Makefile @@ -12,19 +12,16 @@ # See the License for the specific language governing permissions and # limitations under the License. -TAG = 0.1 -PREFIX = gcr.io/google_containers +BIN=goproxy +ARCH ?= amd64 +TARGET ?= $(CURDIR) +GOLANG_VERSION ?= latest -all: push +bin: + docker run --rm -it -v $(TARGET):$(TARGET):Z -v `pwd`/../../../:/go/src/k8s.io/kubernetes:Z \ + golang:$(GOLANG_VERSION) \ + /bin/bash -c "\ + cd /go/src/k8s.io/kubernetes/test/images/goproxy && \ + CGO_ENABLED=0 GOARM=$(GOARM) GOARCH=$(ARCH) go build -a -installsuffix cgo --ldflags '-w' -o $(TARGET)/$(BIN) ." -goproxy: goproxy.go - CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -ldflags '-w' ./goproxy.go - -image: goproxy - docker build --pull -t $(PREFIX)/goproxy:$(TAG) . - -push: image - gcloud docker -- push $(PREFIX)/goproxy:$(TAG) - -clean: - rm -f goproxy +.PHONY: bin diff --git a/test/images/goproxy/NAME b/test/images/goproxy/NAME new file mode 100644 index 00000000000..663e1754bde --- /dev/null +++ b/test/images/goproxy/NAME @@ -0,0 +1 @@ +goproxy diff --git a/test/images/goproxy/VERSION b/test/images/goproxy/VERSION new file mode 100644 index 00000000000..3b04cfb60da --- /dev/null +++ b/test/images/goproxy/VERSION @@ -0,0 +1 @@ +0.2 diff --git a/test/images/hostexec/BASEIMAGE b/test/images/hostexec/BASEIMAGE new file mode 100644 index 00000000000..114844f395e --- /dev/null +++ b/test/images/hostexec/BASEIMAGE @@ -0,0 +1,4 @@ +amd64=alpine:3.6 +arm=arm32v6/alpine:3.6 +arm64=arm64v8/alpine:3.6 +ppc64le=ppc64le/alpine:3.6 diff --git a/test/images/hostexec/Dockerfile b/test/images/hostexec/Dockerfile index 98f2565f7c2..af6a4cb6181 100644 --- a/test/images/hostexec/Dockerfile +++ b/test/images/hostexec/Dockerfile @@ -12,12 +12,14 @@ # See the License for the specific language governing permissions and # limitations under the License. -FROM alpine:3.2 +FROM BASEIMAGE + +CROSS_BUILD_COPY qemu-QEMUARCH-static /usr/bin/ # install necessary packages: # - curl, nc: used by a lot of e2e tests # - iproute2: includes ss used in NodePort tests -run apk --update add curl netcat-openbsd iproute2 && rm -rf /var/cache/apk/* +RUN apk --update add curl netcat-openbsd iproute2 && rm -rf /var/cache/apk/* # wait forever CMD rm -f /fifo && mkfifo /fifo && exec cat Date: Mon, 26 Jun 2017 16:30:43 +0800 Subject: [PATCH 063/448] modify the meassage in kubectl secret command when the envFile path is not an file path --- pkg/kubectl/secret.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/kubectl/secret.go b/pkg/kubectl/secret.go index 6f5f01b833d..ecb2f34e95a 100644 --- a/pkg/kubectl/secret.go +++ b/pkg/kubectl/secret.go @@ -217,7 +217,7 @@ func handleFromEnvFileSource(secret *api.Secret, envFileSource string) error { } } if info.IsDir() { - return fmt.Errorf("must be a file") + return fmt.Errorf("env secret file cannot be a directory") } return addFromEnvFile(envFileSource, func(key, value string) error { From c8a08afc8c959c69bafb1cd7ee23f7cbbbdb5c7f Mon Sep 17 00:00:00 2001 From: Manjunath A Kumatagi Date: Mon, 26 Jun 2017 15:25:32 +0530 Subject: [PATCH 064/448] Port some more images --- test/images/no-snat-test-proxy/BASEIMAGE | 4 ++++ test/images/no-snat-test-proxy/Dockerfile | 7 +++--- test/images/no-snat-test-proxy/Makefile | 24 +++++++++---------- test/images/no-snat-test-proxy/NAME | 1 + test/images/no-snat-test-proxy/VERSION | 1 + test/images/no-snat-test/BASEIMAGE | 4 ++++ test/images/no-snat-test/Dockerfile | 7 +++--- test/images/no-snat-test/Makefile | 24 +++++++++---------- test/images/no-snat-test/NAME | 1 + test/images/no-snat-test/VERSION | 1 + test/images/nvidia-cuda/BASEIMAGE | 2 ++ test/images/nvidia-cuda/Dockerfile | 6 +++-- test/images/nvidia-cuda/Makefile | 28 ----------------------- test/images/nvidia-cuda/NAME | 1 + test/images/nvidia-cuda/VERSION | 1 + test/images/redis/BASEIMAGE | 4 ++++ test/images/redis/Dockerfile | 4 +++- test/images/redis/Makefile | 26 --------------------- test/images/redis/NAME | 1 + test/images/redis/VERSION | 1 + 20 files changed, 57 insertions(+), 91 deletions(-) create mode 100644 test/images/no-snat-test-proxy/BASEIMAGE create mode 100644 test/images/no-snat-test-proxy/NAME create mode 100644 test/images/no-snat-test-proxy/VERSION create mode 100644 test/images/no-snat-test/BASEIMAGE create mode 100644 test/images/no-snat-test/NAME create mode 100644 test/images/no-snat-test/VERSION create mode 100644 test/images/nvidia-cuda/BASEIMAGE delete mode 100644 test/images/nvidia-cuda/Makefile create mode 100644 test/images/nvidia-cuda/NAME create mode 100644 test/images/nvidia-cuda/VERSION create mode 100644 test/images/redis/BASEIMAGE delete mode 100644 test/images/redis/Makefile create mode 100644 test/images/redis/NAME create mode 100644 test/images/redis/VERSION diff --git a/test/images/no-snat-test-proxy/BASEIMAGE b/test/images/no-snat-test-proxy/BASEIMAGE new file mode 100644 index 00000000000..114844f395e --- /dev/null +++ b/test/images/no-snat-test-proxy/BASEIMAGE @@ -0,0 +1,4 @@ +amd64=alpine:3.6 +arm=arm32v6/alpine:3.6 +arm64=arm64v8/alpine:3.6 +ppc64le=ppc64le/alpine:3.6 diff --git a/test/images/no-snat-test-proxy/Dockerfile b/test/images/no-snat-test-proxy/Dockerfile index 232126642f0..04a89a96bc0 100644 --- a/test/images/no-snat-test-proxy/Dockerfile +++ b/test/images/no-snat-test-proxy/Dockerfile @@ -12,9 +12,8 @@ # See the License for the specific language governing permissions and # limitations under the License. -FROM alpine:3.5 +FROM BASEIMAGE -ADD no-snat-test-proxy /usr/bin/no-snat-test-proxy -RUN chmod +x /usr/bin/no-snat-test-proxy +COPY no-snat-test-proxy / -ENTRYPOINT ["/usr/bin/no-snat-test-proxy"] \ No newline at end of file +ENTRYPOINT ["/no-snat-test-proxy"] diff --git a/test/images/no-snat-test-proxy/Makefile b/test/images/no-snat-test-proxy/Makefile index 84579326670..507a70a3d0c 100644 --- a/test/images/no-snat-test-proxy/Makefile +++ b/test/images/no-snat-test-proxy/Makefile @@ -12,18 +12,16 @@ # See the License for the specific language governing permissions and # limitations under the License. -REGISTRY?=gcr.io/google_containers -REGISTRY_TAG?=1.0.1 -ARCH?=amd64 -NAME?=no-snat-test-proxy +BIN=no-snat-test-proxy +ARCH ?= amd64 +TARGET ?= $(CURDIR) +GOLANG_VERSION ?= latest -build: - go build --ldflags '-linkmode external -extldflags "-static"' -o $(NAME) main.go - docker build -t $(REGISTRY)/$(NAME)-$(ARCH):$(REGISTRY_TAG) . - rm $(NAME) +bin: + docker run --rm -it -v $(TARGET):$(TARGET):Z -v `pwd`/../../../:/go/src/k8s.io/kubernetes:Z \ + golang:$(GOLANG_VERSION) \ + /bin/bash -c "\ + cd /go/src/k8s.io/kubernetes/test/images/no-snat-test-proxy && \ + CGO_ENABLED=0 GOARM=$(GOARM) GOARCH=$(ARCH) go build -a -installsuffix cgo --ldflags '-w' -o $(TARGET)/$(BIN)" -push: build - gcloud docker -- push $(REGISTRY)/$(NAME)-$(ARCH):$(REGISTRY_TAG) - -all: build -.PHONY: build push \ No newline at end of file +.PHONY: bin diff --git a/test/images/no-snat-test-proxy/NAME b/test/images/no-snat-test-proxy/NAME new file mode 100644 index 00000000000..f7643dc3ab8 --- /dev/null +++ b/test/images/no-snat-test-proxy/NAME @@ -0,0 +1 @@ +no-snat-test-proxy diff --git a/test/images/no-snat-test-proxy/VERSION b/test/images/no-snat-test-proxy/VERSION new file mode 100644 index 00000000000..6d7de6e6abe --- /dev/null +++ b/test/images/no-snat-test-proxy/VERSION @@ -0,0 +1 @@ +1.0.2 diff --git a/test/images/no-snat-test/BASEIMAGE b/test/images/no-snat-test/BASEIMAGE new file mode 100644 index 00000000000..114844f395e --- /dev/null +++ b/test/images/no-snat-test/BASEIMAGE @@ -0,0 +1,4 @@ +amd64=alpine:3.6 +arm=arm32v6/alpine:3.6 +arm64=arm64v8/alpine:3.6 +ppc64le=ppc64le/alpine:3.6 diff --git a/test/images/no-snat-test/Dockerfile b/test/images/no-snat-test/Dockerfile index 1cd01aafd41..b56749dbfa9 100644 --- a/test/images/no-snat-test/Dockerfile +++ b/test/images/no-snat-test/Dockerfile @@ -12,9 +12,8 @@ # See the License for the specific language governing permissions and # limitations under the License. -FROM alpine:3.5 +FROM BASEIMAGE -ADD no-snat-test /usr/bin/no-snat-test -RUN chmod +x /usr/bin/no-snat-test +COPY no-snat-test / -ENTRYPOINT ["/usr/bin/no-snat-test"] \ No newline at end of file +ENTRYPOINT ["/no-snat-test"] diff --git a/test/images/no-snat-test/Makefile b/test/images/no-snat-test/Makefile index 5ca0c239992..60e604cce9a 100644 --- a/test/images/no-snat-test/Makefile +++ b/test/images/no-snat-test/Makefile @@ -12,18 +12,16 @@ # See the License for the specific language governing permissions and # limitations under the License. -REGISTRY?=gcr.io/google_containers -REGISTRY_TAG?=1.0.1 -ARCH?=amd64 -NAME?=no-snat-test +BIN=no-snat-test +ARCH ?= amd64 +TARGET ?= $(CURDIR) +GOLANG_VERSION ?= latest -build: - go build --ldflags '-linkmode external -extldflags "-static"' -o $(NAME) main.go - docker build -t $(REGISTRY)/$(NAME)-$(ARCH):$(REGISTRY_TAG) . - rm $(NAME) +bin: + docker run --rm -it -v $(TARGET):$(TARGET):Z -v `pwd`/../../../:/go/src/k8s.io/kubernetes:Z \ + golang:$(GOLANG_VERSION) \ + /bin/bash -c "\ + cd /go/src/k8s.io/kubernetes/test/images/no-snat-test && \ + CGO_ENABLED=0 GOARM=$(GOARM) GOARCH=$(ARCH) go build -a -installsuffix cgo --ldflags '-w' -o $(TARGET)/$(BIN)" -push: build - gcloud docker -- push $(REGISTRY)/$(NAME)-$(ARCH):$(REGISTRY_TAG) - -all: build -.PHONY: build push \ No newline at end of file +.PHONY: bin diff --git a/test/images/no-snat-test/NAME b/test/images/no-snat-test/NAME new file mode 100644 index 00000000000..97de61b8657 --- /dev/null +++ b/test/images/no-snat-test/NAME @@ -0,0 +1 @@ +no-snat-test diff --git a/test/images/no-snat-test/VERSION b/test/images/no-snat-test/VERSION new file mode 100644 index 00000000000..6d7de6e6abe --- /dev/null +++ b/test/images/no-snat-test/VERSION @@ -0,0 +1 @@ +1.0.2 diff --git a/test/images/nvidia-cuda/BASEIMAGE b/test/images/nvidia-cuda/BASEIMAGE new file mode 100644 index 00000000000..a7b6d587069 --- /dev/null +++ b/test/images/nvidia-cuda/BASEIMAGE @@ -0,0 +1,2 @@ +amd64=nvidia/cuda:8.0-devel-ubuntu16.04 +ppc64le=nvidia/cuda-ppc64le:8.0-devel-ubuntu16.04 diff --git a/test/images/nvidia-cuda/Dockerfile b/test/images/nvidia-cuda/Dockerfile index 2d68b97f5f7..c7b9cfdc31e 100644 --- a/test/images/nvidia-cuda/Dockerfile +++ b/test/images/nvidia-cuda/Dockerfile @@ -12,7 +12,9 @@ # See the License for the specific language governing permissions and # limitations under the License. -FROM nvidia/cuda:8.0-devel-ubuntu16.04 +FROM BASEIMAGE + +CROSS_BUILD_COPY qemu-QEMUARCH-static /usr/bin/ RUN apt-get update && apt-get install -y --no-install-recommends \ cuda-samples-$CUDA_PKG_VERSION && \ @@ -21,4 +23,4 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ WORKDIR /usr/local/cuda/samples/0_Simple/vectorAdd RUN make -CMD ./vectorAdd \ No newline at end of file +CMD ./vectorAdd diff --git a/test/images/nvidia-cuda/Makefile b/test/images/nvidia-cuda/Makefile deleted file mode 100644 index 616f796c66f..00000000000 --- a/test/images/nvidia-cuda/Makefile +++ /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. - -.PHONY: all push build - -TAG ?= v0.1 - -REGISTRY ?= gcr.io/google-containers -IMAGE = $(REGISTRY)/cuda-vector-add - -build: - docker build --pull -t $(IMAGE):$(TAG) . - -push: - gcloud docker -- push $(IMAGE):$(TAG) - -all: build diff --git a/test/images/nvidia-cuda/NAME b/test/images/nvidia-cuda/NAME new file mode 100644 index 00000000000..a3cf7cef8ba --- /dev/null +++ b/test/images/nvidia-cuda/NAME @@ -0,0 +1 @@ +cuda-vector-add diff --git a/test/images/nvidia-cuda/VERSION b/test/images/nvidia-cuda/VERSION new file mode 100644 index 00000000000..60fe1f267ba --- /dev/null +++ b/test/images/nvidia-cuda/VERSION @@ -0,0 +1 @@ +v0.2 diff --git a/test/images/redis/BASEIMAGE b/test/images/redis/BASEIMAGE new file mode 100644 index 00000000000..114844f395e --- /dev/null +++ b/test/images/redis/BASEIMAGE @@ -0,0 +1,4 @@ +amd64=alpine:3.6 +arm=arm32v6/alpine:3.6 +arm64=arm64v8/alpine:3.6 +ppc64le=ppc64le/alpine:3.6 diff --git a/test/images/redis/Dockerfile b/test/images/redis/Dockerfile index ecc3ed7c323..0add11c3d44 100644 --- a/test/images/redis/Dockerfile +++ b/test/images/redis/Dockerfile @@ -12,7 +12,9 @@ # See the License for the specific language governing permissions and # limitations under the License. -FROM alpine:3.5 +FROM BASEIMAGE + +CROSS_BUILD_COPY qemu-QEMUARCH-static /usr/bin/ RUN apk add --no-cache redis diff --git a/test/images/redis/Makefile b/test/images/redis/Makefile deleted file mode 100644 index 58ff57da82e..00000000000 --- a/test/images/redis/Makefile +++ /dev/null @@ -1,26 +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. - -TAG ?= e2e -PREFIX ?= gcr.io/k8s-testimages - -all: push - -image: - docker build --pull -t $(PREFIX)/redis:$(TAG) . - -push: image - gcloud docker -- push $(PREFIX)/redis:$(TAG) - -clean: diff --git a/test/images/redis/NAME b/test/images/redis/NAME new file mode 100644 index 00000000000..7800f0fad3f --- /dev/null +++ b/test/images/redis/NAME @@ -0,0 +1 @@ +redis diff --git a/test/images/redis/VERSION b/test/images/redis/VERSION new file mode 100644 index 00000000000..49d59571fbf --- /dev/null +++ b/test/images/redis/VERSION @@ -0,0 +1 @@ +0.1 From 037c9e896517856927019b2f747a65a5734a5735 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucas=20K=C3=A4ldstr=C3=B6m?= Date: Mon, 26 Jun 2017 12:56:06 +0300 Subject: [PATCH 065/448] kubeadm: Expose only the cluster-info ConfigMap in the kube-public ns --- cmd/kubeadm/app/phases/apiconfig/clusterroles.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/kubeadm/app/phases/apiconfig/clusterroles.go b/cmd/kubeadm/app/phases/apiconfig/clusterroles.go index 64d624a3b17..91a7b28b392 100644 --- a/cmd/kubeadm/app/phases/apiconfig/clusterroles.go +++ b/cmd/kubeadm/app/phases/apiconfig/clusterroles.go @@ -105,7 +105,7 @@ func createRoles(clientset *clientset.Clientset) error { Namespace: metav1.NamespacePublic, }, Rules: []rbac.PolicyRule{ - rbachelper.NewRule("get").Groups("").Resources("configmaps").RuleOrDie(), + rbachelper.NewRule("get").Groups("").Resources("configmaps").Names("cluster-info").RuleOrDie(), }, }, } From b664a0db3d4df32e19ae08221eb3a1e74ac77712 Mon Sep 17 00:00:00 2001 From: yiqinguo <468894985@qq.com> Date: Mon, 26 Jun 2017 19:04:10 +0800 Subject: [PATCH 066/448] Add err judgment --- pkg/volume/util.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pkg/volume/util.go b/pkg/volume/util.go index e0900cb1e8c..a674d37829c 100644 --- a/pkg/volume/util.go +++ b/pkg/volume/util.go @@ -180,7 +180,10 @@ func (c *realRecyclerClient) Event(eventtype, message string) { } func (c *realRecyclerClient) WatchPod(name, namespace string, stopChannel chan struct{}) (<-chan watch.Event, error) { - podSelector, _ := fields.ParseSelector("metadata.name=" + name) + podSelector, err := fields.ParseSelector("metadata.name=" + name) + if err != nil { + return nil, err + } options := metav1.ListOptions{ FieldSelector: podSelector.String(), Watch: true, From e25a5b1546392221c79e4d48dff4643c2341a002 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucas=20K=C3=A4ldstr=C3=B6m?= Date: Mon, 26 Jun 2017 14:46:15 +0300 Subject: [PATCH 067/448] Remove old node role label that is not used by kubeadm --- cmd/kubeadm/app/apis/kubeadm/BUILD | 1 - .../app/apis/kubeadm/well_known_labels.go | 43 ------------------- pkg/printers/internalversion/BUILD | 1 - pkg/printers/internalversion/describe.go | 1 - pkg/printers/internalversion/printers.go | 18 -------- pkg/printers/internalversion/printers_test.go | 10 ----- 6 files changed, 74 deletions(-) delete mode 100644 cmd/kubeadm/app/apis/kubeadm/well_known_labels.go diff --git a/cmd/kubeadm/app/apis/kubeadm/BUILD b/cmd/kubeadm/app/apis/kubeadm/BUILD index a4241545803..7bcc07f6104 100644 --- a/cmd/kubeadm/app/apis/kubeadm/BUILD +++ b/cmd/kubeadm/app/apis/kubeadm/BUILD @@ -14,7 +14,6 @@ go_library( "env.go", "register.go", "types.go", - "well_known_labels.go", ], tags = ["automanaged"], deps = [ diff --git a/cmd/kubeadm/app/apis/kubeadm/well_known_labels.go b/cmd/kubeadm/app/apis/kubeadm/well_known_labels.go deleted file mode 100644 index f2fb530fdc0..00000000000 --- a/cmd/kubeadm/app/apis/kubeadm/well_known_labels.go +++ /dev/null @@ -1,43 +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 kubeadm - -// Role labels are applied to Nodes to mark their purpose. In particular, we -// usually want to distinguish the master, so that we can isolate privileged -// pods and operations. -// -// Originally we relied on not registering the master, on the fact that the -// master was Unschedulable, and on static manifests for master components. -// But we now do register masters in many environments, are generally moving -// away from static manifests (for better manageability), and working towards -// deprecating the unschedulable field (replacing it with taints & tolerations -// instead). -// -// Even with tainting, a label remains the easiest way of making a positive -// selection, so that pods can schedule only to master nodes for example, and -// thus installations will likely define a label for their master nodes. -// -// So that we can recognize master nodes in consequent places though (such as -// kubectl get nodes), we encourage installations to use the well-known labels. -// We define NodeLabelRole, which is the preferred form, but we will also recognize -// other forms that are known to be in widespread use (NodeLabelKubeadmAlphaRole). - -const ( - // NodeLabelKubeadmAlphaRole is a label that kubeadm applies to a Node as a hint that it has a particular purpose. - // Use of NodeLabelRole is preferred. - NodeLabelKubeadmAlphaRole = "kubeadm.alpha.kubernetes.io/role" -) diff --git a/pkg/printers/internalversion/BUILD b/pkg/printers/internalversion/BUILD index a5d5caee37b..53759eed328 100644 --- a/pkg/printers/internalversion/BUILD +++ b/pkg/printers/internalversion/BUILD @@ -59,7 +59,6 @@ go_library( ], tags = ["automanaged"], deps = [ - "//cmd/kubeadm/app/apis/kubeadm:go_default_library", "//federation/apis/federation:go_default_library", "//federation/client/clientset_generated/federation_internalclientset:go_default_library", "//pkg/api:go_default_library", diff --git a/pkg/printers/internalversion/describe.go b/pkg/printers/internalversion/describe.go index 6ed8a1a94f2..677018dd9fc 100644 --- a/pkg/printers/internalversion/describe.go +++ b/pkg/printers/internalversion/describe.go @@ -2360,7 +2360,6 @@ func describeNode(node *api.Node, nodeNonTerminatedPodsList *api.PodList, events return tabbedString(func(out io.Writer) error { w := NewPrefixWriter(out) w.Write(LEVEL_0, "Name:\t%s\n", node.Name) - w.Write(LEVEL_0, "Role:\t%s\n", findNodeRole(node)) printLabelsMultiline(w, "Labels", node.Labels) printAnnotationsMultiline(w, "Annotations", node.Annotations) printNodeTaintsMultiline(w, "Taints", node.Spec.Taints) diff --git a/pkg/printers/internalversion/printers.go b/pkg/printers/internalversion/printers.go index 9eb1b85d64d..b13fe317391 100644 --- a/pkg/printers/internalversion/printers.go +++ b/pkg/printers/internalversion/printers.go @@ -32,7 +32,6 @@ import ( "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/sets" - "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" "k8s.io/kubernetes/federation/apis/federation" "k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api/events" @@ -1112,10 +1111,6 @@ func printNode(node *api.Node, w io.Writer, options printers.PrintOptions) error if node.Spec.Unschedulable { status = append(status, "SchedulingDisabled") } - role := findNodeRole(node) - if role != "" { - status = append(status, role) - } if _, err := fmt.Fprintf(w, "%s\t%s\t%s\t%s", name, strings.Join(status, ","), translateTimestamp(node.CreationTimestamp), node.Status.NodeInfo.KubeletVersion); err != nil { return err @@ -1155,19 +1150,6 @@ func getNodeExternalIP(node *api.Node) string { return "" } -// findNodeRole returns the role of a given node, or "" if none found. -// The role is determined by looking in order for: -// * a kubernetes.io/role label -// * a kubeadm.alpha.kubernetes.io/role label -// If no role is found, ("", nil) is returned -func findNodeRole(node *api.Node) string { - if role := node.Labels[kubeadm.NodeLabelKubeadmAlphaRole]; role != "" { - return role - } - // No role found - return "" -} - func printNodeList(list *api.NodeList, w io.Writer, options printers.PrintOptions) error { for _, node := range list.Items { if err := printNode(&node, w, options); err != nil { diff --git a/pkg/printers/internalversion/printers_test.go b/pkg/printers/internalversion/printers_test.go index 3baac7df667..f8bc17d1d98 100644 --- a/pkg/printers/internalversion/printers_test.go +++ b/pkg/printers/internalversion/printers_test.go @@ -704,16 +704,6 @@ func TestPrintNodeStatus(t *testing.T) { }, status: "Unknown,SchedulingDisabled", }, - { - node: api.Node{ - ObjectMeta: metav1.ObjectMeta{ - Name: "foo12", - Labels: map[string]string{"kubeadm.alpha.kubernetes.io/role": "node"}, - }, - Status: api.NodeStatus{Conditions: []api.NodeCondition{{Type: api.NodeReady, Status: api.ConditionTrue}}}, - }, - status: "Ready,node", - }, } for _, test := range table { From a2a99c786ac01fa7ec32e829c777c6d335c24528 Mon Sep 17 00:00:00 2001 From: Paul Michali Date: Thu, 18 May 2017 14:11:42 -0400 Subject: [PATCH 068/448] IPv6 support for getting node IP As part of ChooseHostInterface(), it will call a function to try to get the global IP for the host, by looking at all the system interfaces and select the first IP that is not a loopback, link-local, or point-to-point IP. This commit does the following: - Allows IPv6 non-local IPs to be selected. - IPv4 takes priority (checks all interfaces for IPv4 addresses and then checks all interfaces for IPv6), for backward compatibility. - Adds UTs for code coverage (was no coverage of underlying function), increasing from 62% to 84%. - Improved logging and reporting for error conditions. - Minor renaming of functions and variables for readability. --- .../apimachinery/pkg/util/net/interface.go | 114 +++++--- .../pkg/util/net/interface_test.go | 249 +++++++++++++++--- 2 files changed, 290 insertions(+), 73 deletions(-) diff --git a/staging/src/k8s.io/apimachinery/pkg/util/net/interface.go b/staging/src/k8s.io/apimachinery/pkg/util/net/interface.go index a1e53d2e436..95d398c86e5 100644 --- a/staging/src/k8s.io/apimachinery/pkg/util/net/interface.go +++ b/staging/src/k8s.io/apimachinery/pkg/util/net/interface.go @@ -29,6 +29,13 @@ import ( "github.com/golang/glog" ) +type AddressFamily uint + +const ( + familyIPv4 AddressFamily = 4 + familyIPv6 AddressFamily = 6 +) + type Route struct { Interface string Destination net.IP @@ -96,6 +103,10 @@ func isInterfaceUp(intf *net.Interface) bool { return false } +func isLoopbackOrPointToPoint(intf *net.Interface) bool { + return intf.Flags&(net.FlagLoopback|net.FlagPointToPoint) != 0 +} + //getFinalIP method receives all the IP addrs of a Interface //and returns a nil if the address is Loopback, Ipv6, link-local or nil. //It returns a valid IPv4 if an Ipv4 address is found in the array. @@ -149,50 +160,65 @@ func getIPFromInterface(intfName string, nw networkInterfacer) (net.IP, error) { return nil, nil } -func flagsSet(flags net.Flags, test net.Flags) bool { - return flags&test != 0 +// memberOF tells if the IP is of the desired family. Used for checking interface addresses. +func memberOf(ip net.IP, family AddressFamily) bool { + if ip.To4() != nil { + return family == familyIPv4 + } else { + return family == familyIPv6 + } } -func flagsClear(flags net.Flags, test net.Flags) bool { - return flags&test == 0 -} - -func chooseHostInterfaceNativeGo() (net.IP, error) { - intfs, err := net.Interfaces() +// chooseIPFromHostInterfaces looks at all system interfaces, trying to find one that is up that +// has a global unicast address (non-loopback, non-link local, non-point2point), and returns the IP. +// Searches for IPv4 addresses, and then IPv6 addresses. +func chooseIPFromHostInterfaces(nw networkInterfacer) (net.IP, error) { + intfs, err := nw.Interfaces() if err != nil { return nil, err } - i := 0 - var ip net.IP - for i = range intfs { - if flagsSet(intfs[i].Flags, net.FlagUp) && flagsClear(intfs[i].Flags, net.FlagLoopback|net.FlagPointToPoint) { - addrs, err := intfs[i].Addrs() + if len(intfs) == 0 { + return nil, fmt.Errorf("no interfaces found on host.") + } + for _, family := range []AddressFamily{familyIPv4, familyIPv6} { + glog.V(4).Infof("Looking for system interface with a global IPv%d address", uint(family)) + for _, intf := range intfs { + if !isInterfaceUp(&intf) { + glog.V(4).Infof("Skipping: down interface %q", intf.Name) + continue + } + if isLoopbackOrPointToPoint(&intf) { + glog.V(4).Infof("Skipping: LB or P2P interface %q", intf.Name) + continue + } + addrs, err := nw.Addrs(&intf) if err != nil { return nil, err } - if len(addrs) > 0 { - for _, addr := range addrs { - if addrIP, _, err := net.ParseCIDR(addr.String()); err == nil { - if addrIP.To4() != nil { - ip = addrIP.To4() - if !ip.IsLinkLocalMulticast() && !ip.IsLinkLocalUnicast() { - break - } - } - } + if len(addrs) == 0 { + glog.V(4).Infof("Skipping: no addresses on interface %q", intf.Name) + continue + } + for _, addr := range addrs { + ip, _, err := net.ParseCIDR(addr.String()) + if err != nil { + return nil, fmt.Errorf("Unable to parse CIDR for interface %q: %s", intf.Name, err) } - if ip != nil { - // This interface should suffice. - break + if !memberOf(ip, family) { + glog.V(4).Infof("Skipping: no address family match for %q on interface %q.", ip, intf.Name) + continue } + // TODO: Decide if should open up to allow IPv6 LLAs in future. + if !ip.IsGlobalUnicast() { + glog.V(4).Infof("Skipping: non-global address %q on interface %q.", ip, intf.Name) + continue + } + glog.V(4).Infof("Found global unicast address %q on interface %q.", ip, intf.Name) + return ip, nil } } } - if ip == nil { - return nil, fmt.Errorf("no acceptable interface from host") - } - glog.V(4).Infof("Choosing interface %s (IP %v) as default", intfs[i].Name, ip) - return ip, nil + return nil, fmt.Errorf("no acceptable interface with global unicast address found on host") } //ChooseHostInterface is a method used fetch an IP for a daemon. @@ -200,39 +226,41 @@ func chooseHostInterfaceNativeGo() (net.IP, error) { //For a node with no internet connection ,it returns error //For a multi n/w interface node it returns the IP of the interface with gateway on it. func ChooseHostInterface() (net.IP, error) { + var nw networkInterfacer = networkInterface{} inFile, err := os.Open("/proc/net/route") if err != nil { if os.IsNotExist(err) { - return chooseHostInterfaceNativeGo() + return chooseIPFromHostInterfaces(nw) } return nil, err } defer inFile.Close() - var nw networkInterfacer = networkInterface{} return chooseHostInterfaceFromRoute(inFile, nw) } +// networkInterfacer defines an interface for several net library functions. Production +// code will forward to net library functions, and unit tests will override the methods +// for testing purposes. type networkInterfacer interface { InterfaceByName(intfName string) (*net.Interface, error) Addrs(intf *net.Interface) ([]net.Addr, error) + Interfaces() ([]net.Interface, error) } +// networkInterface implements the networkInterfacer interface for production code, just +// wrapping the underlying net library function calls. type networkInterface struct{} func (_ networkInterface) InterfaceByName(intfName string) (*net.Interface, error) { - intf, err := net.InterfaceByName(intfName) - if err != nil { - return nil, err - } - return intf, nil + return net.InterfaceByName(intfName) } func (_ networkInterface) Addrs(intf *net.Interface) ([]net.Addr, error) { - addrs, err := intf.Addrs() - if err != nil { - return nil, err - } - return addrs, nil + return intf.Addrs() +} + +func (_ networkInterface) Interfaces() ([]net.Interface, error) { + return net.Interfaces() } func chooseHostInterfaceFromRoute(inFile io.Reader, nw networkInterfacer) (net.IP, error) { diff --git a/staging/src/k8s.io/apimachinery/pkg/util/net/interface_test.go b/staging/src/k8s.io/apimachinery/pkg/util/net/interface_test.go index fc66904c57e..ab810cca5cd 100644 --- a/staging/src/k8s.io/apimachinery/pkg/util/net/interface_test.go +++ b/staging/src/k8s.io/apimachinery/pkg/util/net/interface_test.go @@ -73,6 +73,30 @@ eth0 00000000 0120372D 0001 0 0 0 00000000 eth0 00000000 00000000 0001 0 0 2048 00000000 0 0 0 ` +const ( + flagUp = net.FlagUp | net.FlagBroadcast | net.FlagMulticast + flagDown = net.FlagBroadcast | net.FlagMulticast + flagLoopback = net.FlagUp | net.FlagLoopback + flagP2P = net.FlagUp | net.FlagPointToPoint +) + +func makeIntf(index int, name string, flags net.Flags) net.Interface { + mac := net.HardwareAddr{0, 0x32, 0x7d, 0x69, 0xf7, byte(0x30 + index)} + return net.Interface{ + Index: index, + MTU: 1500, + Name: name, + HardwareAddr: mac, + Flags: flags} +} + +var ( + downIntf = makeIntf(1, "eth3", flagDown) + loopbackIntf = makeIntf(1, "lo", flagLoopback) + p2pIntf = makeIntf(1, "lo", flagP2P) + upIntf = makeIntf(1, "eth3", flagUp) +) + func TestGetRoutes(t *testing.T) { testCases := []struct { tcase string @@ -189,15 +213,19 @@ func (_ validNetworkInterface) InterfaceByName(intfName string) (*net.Interface, func (_ validNetworkInterface) Addrs(intf *net.Interface) ([]net.Addr, error) { var ifat []net.Addr ifat = []net.Addr{ - addrStruct{val: "fe80::2f7:6fff:fe6e:2956/64"}, addrStruct{val: "10.254.71.145/17"}} + addrStruct{val: "2001::200/64"}, addrStruct{val: "10.254.71.145/17"}} return ifat, nil } +func (_ validNetworkInterface) Interfaces() ([]net.Interface, error) { + return []net.Interface{upIntf}, nil +} +// First is link-local, second is not. type validNetworkInterfaceWithLinkLocal struct { } func (_ validNetworkInterfaceWithLinkLocal) InterfaceByName(intfName string) (*net.Interface, error) { - c := net.Interface{Index: 0, MTU: 0, Name: "eth0", HardwareAddr: nil, Flags: net.FlagUp} + c := net.Interface{Index: 0, MTU: 0, Name: "eth3", HardwareAddr: nil, Flags: net.FlagUp} return &c, nil } func (_ validNetworkInterfaceWithLinkLocal) Addrs(intf *net.Interface) ([]net.Addr, error) { @@ -205,20 +233,57 @@ func (_ validNetworkInterfaceWithLinkLocal) Addrs(intf *net.Interface) ([]net.Ad ifat = []net.Addr{addrStruct{val: "169.254.162.166/16"}, addrStruct{val: "45.55.47.146/19"}} return ifat, nil } - -type validNetworkInterfacewithIpv6Only struct { +func (_ validNetworkInterfaceWithLinkLocal) Interfaces() ([]net.Interface, error) { + return []net.Interface{upIntf}, nil } -func (_ validNetworkInterfacewithIpv6Only) InterfaceByName(intfName string) (*net.Interface, error) { - c := net.Interface{Index: 0, MTU: 0, Name: "eth3", HardwareAddr: nil, Flags: net.FlagUp} - return &c, nil +// Interface with only IPv6 address +type ipv6NetworkInterface struct { } -func (_ validNetworkInterfacewithIpv6Only) Addrs(intf *net.Interface) ([]net.Addr, error) { + +func (_ ipv6NetworkInterface) InterfaceByName(intfName string) (*net.Interface, error) { + return &upIntf, nil +} +func (_ ipv6NetworkInterface) Addrs(intf *net.Interface) ([]net.Addr, error) { var ifat []net.Addr - ifat = []net.Addr{addrStruct{val: "fe80::2f7:6fff:fe6e:2956/64"}} + ifat = []net.Addr{addrStruct{val: "2001::200/64"}} return ifat, nil } +func (_ ipv6NetworkInterface) Interfaces() ([]net.Interface, error) { + return []net.Interface{upIntf}, nil +} +// Only with link local addresses +type networkInterfaceWithOnlyLinkLocals struct { +} + +func (_ networkInterfaceWithOnlyLinkLocals) InterfaceByName(intfName string) (*net.Interface, error) { + return &upIntf, nil +} +func (_ networkInterfaceWithOnlyLinkLocals) Addrs(intf *net.Interface) ([]net.Addr, error) { + var ifat []net.Addr + ifat = []net.Addr{addrStruct{val: "169.254.162.166/16"}, addrStruct{val: "fe80::200/10"}} + return ifat, nil +} +func (_ networkInterfaceWithOnlyLinkLocals) Interfaces() ([]net.Interface, error) { + return []net.Interface{upIntf}, nil +} + +// Unable to get interface(s) +type failGettingNetworkInterface struct { +} + +func (_ failGettingNetworkInterface) InterfaceByName(intfName string) (*net.Interface, error) { + return nil, fmt.Errorf("unable get Interface") +} +func (_ failGettingNetworkInterface) Addrs(intf *net.Interface) ([]net.Addr, error) { + return nil, nil +} +func (_ failGettingNetworkInterface) Interfaces() ([]net.Interface, error) { + return nil, fmt.Errorf("mock failed getting all interfaces") +} + +// No interfaces type noNetworkInterface struct { } @@ -228,30 +293,105 @@ func (_ noNetworkInterface) InterfaceByName(intfName string) (*net.Interface, er func (_ noNetworkInterface) Addrs(intf *net.Interface) ([]net.Addr, error) { return nil, nil } - -type networkInterfacewithNoAddrs struct { +func (_ noNetworkInterface) Interfaces() ([]net.Interface, error) { + return []net.Interface{}, nil } -func (_ networkInterfacewithNoAddrs) InterfaceByName(intfName string) (*net.Interface, error) { - c := net.Interface{Index: 0, MTU: 0, Name: "eth3", HardwareAddr: nil, Flags: net.FlagUp} - return &c, nil -} -func (_ networkInterfacewithNoAddrs) Addrs(intf *net.Interface) ([]net.Addr, error) { - return nil, fmt.Errorf("unable get Addrs") +// Interface is down +type downNetworkInterface struct { } -type networkInterfacewithIpv6addrs struct { +func (_ downNetworkInterface) InterfaceByName(intfName string) (*net.Interface, error) { + return &downIntf, nil } - -func (_ networkInterfacewithIpv6addrs) InterfaceByName(intfName string) (*net.Interface, error) { - c := net.Interface{Index: 0, MTU: 0, Name: "eth3", HardwareAddr: nil, Flags: net.FlagUp} - return &c, nil -} -func (_ networkInterfacewithIpv6addrs) Addrs(intf *net.Interface) ([]net.Addr, error) { +func (_ downNetworkInterface) Addrs(intf *net.Interface) ([]net.Addr, error) { var ifat []net.Addr - ifat = []net.Addr{addrStruct{val: "fe80::2f7:6ffff:fe6e:2956/64"}} + ifat = []net.Addr{ + addrStruct{val: "fe80::2f7:6fff:fe6e:2956/64"}, addrStruct{val: "10.254.71.145/17"}} return ifat, nil } +func (_ downNetworkInterface) Interfaces() ([]net.Interface, error) { + return []net.Interface{downIntf}, nil +} + +// Loopback interface +type loopbackNetworkInterface struct { +} + +func (_ loopbackNetworkInterface) InterfaceByName(intfName string) (*net.Interface, error) { + return &loopbackIntf, nil +} +func (_ loopbackNetworkInterface) Addrs(intf *net.Interface) ([]net.Addr, error) { + var ifat []net.Addr + ifat = []net.Addr{ + addrStruct{val: "::1/128"}, addrStruct{val: "127.0.0.1/8"}} + return ifat, nil +} +func (_ loopbackNetworkInterface) Interfaces() ([]net.Interface, error) { + return []net.Interface{loopbackIntf}, nil +} + +// Point to point interface +type p2pNetworkInterface struct { +} + +func (_ p2pNetworkInterface) InterfaceByName(intfName string) (*net.Interface, error) { + return &p2pIntf, nil +} +func (_ p2pNetworkInterface) Addrs(intf *net.Interface) ([]net.Addr, error) { + var ifat []net.Addr + ifat = []net.Addr{ + addrStruct{val: "::1/128"}, addrStruct{val: "127.0.0.1/8"}} + return ifat, nil +} +func (_ p2pNetworkInterface) Interfaces() ([]net.Interface, error) { + return []net.Interface{p2pIntf}, nil +} + +// Unable to get IP addresses for interface +type networkInterfaceFailGetAddrs struct { +} + +func (_ networkInterfaceFailGetAddrs) InterfaceByName(intfName string) (*net.Interface, error) { + return &upIntf, nil +} +func (_ networkInterfaceFailGetAddrs) Addrs(intf *net.Interface) ([]net.Addr, error) { + return nil, fmt.Errorf("unable to get Addrs") +} +func (_ networkInterfaceFailGetAddrs) Interfaces() ([]net.Interface, error) { + return []net.Interface{upIntf}, nil +} + +// No addresses for interface +type networkInterfaceWithNoAddrs struct { +} + +func (_ networkInterfaceWithNoAddrs) InterfaceByName(intfName string) (*net.Interface, error) { + return &upIntf, nil +} +func (_ networkInterfaceWithNoAddrs) Addrs(intf *net.Interface) ([]net.Addr, error) { + ifat := []net.Addr{} + return ifat, nil +} +func (_ networkInterfaceWithNoAddrs) Interfaces() ([]net.Interface, error) { + return []net.Interface{upIntf}, nil +} + +// Invalid addresses for interface +type networkInterfaceWithInvalidAddr struct { +} + +func (_ networkInterfaceWithInvalidAddr) InterfaceByName(intfName string) (*net.Interface, error) { + return &upIntf, nil +} +func (_ networkInterfaceWithInvalidAddr) Addrs(intf *net.Interface) ([]net.Addr, error) { + var ifat []net.Addr + ifat = []net.Addr{addrStruct{val: "10.20.30.40.50/24"}} + return ifat, nil +} +func (_ networkInterfaceWithInvalidAddr) Interfaces() ([]net.Interface, error) { + return []net.Interface{upIntf}, nil +} func TestGetIPFromInterface(t *testing.T) { testCases := []struct { @@ -261,7 +401,7 @@ func TestGetIPFromInterface(t *testing.T) { expected net.IP }{ {"valid", "eth3", validNetworkInterface{}, net.ParseIP("10.254.71.145")}, - {"ipv6", "eth3", validNetworkInterfacewithIpv6Only{}, nil}, + {"ipv6", "eth3", ipv6NetworkInterface{}, nil}, {"nothing", "eth3", noNetworkInterface{}, nil}, } for _, tc := range testCases { @@ -282,14 +422,14 @@ func TestChooseHostInterfaceFromRoute(t *testing.T) { {"valid_routefirst", strings.NewReader(gatewayfirst), validNetworkInterface{}, net.ParseIP("10.254.71.145")}, {"valid_routelast", strings.NewReader(gatewaylast), validNetworkInterface{}, net.ParseIP("10.254.71.145")}, {"valid_routemiddle", strings.NewReader(gatewaymiddle), validNetworkInterface{}, net.ParseIP("10.254.71.145")}, - {"valid_routemiddle_ipv6", strings.NewReader(gatewaymiddle), validNetworkInterfacewithIpv6Only{}, nil}, + {"valid_routemiddle_ipv6", strings.NewReader(gatewaymiddle), ipv6NetworkInterface{}, nil}, {"no internet connection", strings.NewReader(noInternetConnection), validNetworkInterface{}, nil}, - {"no non-link-local ip", strings.NewReader(gatewayfirstLinkLocal), validNetworkInterfaceWithLinkLocal{}, net.ParseIP("45.55.47.146")}, + {"1st ip link-local", strings.NewReader(gatewayfirstLinkLocal), validNetworkInterfaceWithLinkLocal{}, net.ParseIP("45.55.47.146")}, {"no route", strings.NewReader(nothing), validNetworkInterface{}, nil}, {"no route file", nil, validNetworkInterface{}, nil}, {"no interfaces", nil, noNetworkInterface{}, nil}, - {"no interface Addrs", strings.NewReader(gatewaymiddle), networkInterfacewithNoAddrs{}, nil}, - {"Invalid Addrs", strings.NewReader(gatewaymiddle), networkInterfacewithIpv6addrs{}, nil}, + {"no interface Addrs", strings.NewReader(gatewaymiddle), networkInterfaceWithNoAddrs{}, nil}, + {"Invalid Addrs", strings.NewReader(gatewaymiddle), ipv6NetworkInterface{}, nil}, } for _, tc := range testCases { ip, err := chooseHostInterfaceFromRoute(tc.inFile, tc.nw) @@ -298,3 +438,52 @@ func TestChooseHostInterfaceFromRoute(t *testing.T) { } } } +func TestMemberOf(t *testing.T) { + testCases := []struct { + tcase string + ip net.IP + family AddressFamily + expected bool + }{ + {"ipv4 is 4", net.ParseIP("10.20.30.40"), familyIPv4, true}, + {"ipv4 is 6", net.ParseIP("10.10.10.10"), familyIPv6, false}, + {"ipv6 is 4", net.ParseIP("2001::100"), familyIPv4, false}, + {"ipv6 is 6", net.ParseIP("2001::100"), familyIPv6, true}, + } + for _, tc := range testCases { + if memberOf(tc.ip, tc.family) != tc.expected { + t.Errorf("case[%s]: expected %+v", tc.tcase, tc.expected) + } + } +} + +func TestGetIPFromHostInterfaces(t *testing.T) { + testCases := []struct { + tcase string + nw networkInterfacer + expected net.IP + errStrFrag string + }{ + {"fail get I/Fs", failGettingNetworkInterface{}, nil, "failed getting all interfaces"}, + {"no interfaces", noNetworkInterface{}, nil, "no interfaces"}, + {"I/F not up", downNetworkInterface{}, nil, "no acceptable"}, + {"loopback only", loopbackNetworkInterface{}, nil, "no acceptable"}, + {"P2P I/F only", p2pNetworkInterface{}, nil, "no acceptable"}, + {"fail get addrs", networkInterfaceFailGetAddrs{}, nil, "unable to get Addrs"}, + {"no addresses", networkInterfaceWithNoAddrs{}, nil, "no acceptable"}, + {"invalid addr", networkInterfaceWithInvalidAddr{}, nil, "invalid CIDR"}, + {"no matches", networkInterfaceWithOnlyLinkLocals{}, nil, "no acceptable"}, + {"ipv4", validNetworkInterface{}, net.ParseIP("10.254.71.145"), ""}, + {"ipv6", ipv6NetworkInterface{}, net.ParseIP("2001::200"), ""}, + } + + for _, tc := range testCases { + ip, err := chooseIPFromHostInterfaces(tc.nw) + if !ip.Equal(tc.expected) { + t.Errorf("case[%s]: expected %+v, got %+v with err : %v", tc.tcase, tc.expected, ip, err) + } + if err != nil && !strings.Contains(err.Error(), tc.errStrFrag) { + t.Errorf("case[%s]: unable to find %q in error string %q", tc.tcase, tc.errStrFrag, err.Error()) + } + } +} From 38f3a9cc4b552f176283cca20d9315b83c3ac131 Mon Sep 17 00:00:00 2001 From: Haoran Wang Date: Mon, 26 Jun 2017 10:33:01 +0800 Subject: [PATCH 069/448] add options enable tokencleaner,bootstrapsigner controller --- hack/local-up-cluster.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/hack/local-up-cluster.sh b/hack/local-up-cluster.sh index e9cb8b99f33..dd4724063e3 100755 --- a/hack/local-up-cluster.sh +++ b/hack/local-up-cluster.sh @@ -98,6 +98,9 @@ ADMISSION_CONTROL_CONFIG_FILE=${ADMISSION_CONTROL_CONFIG_FILE:-""} # START_MODE can be 'all', 'kubeletonly', or 'nokubelet' START_MODE=${START_MODE:-"all"} +# A list of controllers to enable +KUBE_CONTROLLERS="${KUBE_CONTROLLERS:-"*"}" + # sanity check for OpenStack provider if [ "${CLOUD_PROVIDER}" == "openstack" ]; then if [ "${CLOUD_CONFIG}" == "" ]; then @@ -586,6 +589,7 @@ function start_controller_manager { --cloud-config="${CLOUD_CONFIG}" \ --kubeconfig "$CERT_DIR"/controller.kubeconfig \ --use-service-account-credentials \ + --controllers="${KUBE_CONTROLLERS}" \ --master="https://${API_HOST}:${API_SECURE_PORT}" >"${CTLRMGR_LOG}" 2>&1 & CTLRMGR_PID=$! } From 211554a37fbb8390584012e3c3e75ea7d2753477 Mon Sep 17 00:00:00 2001 From: Jeff Grafton Date: Fri, 23 Jun 2017 00:03:40 -0700 Subject: [PATCH 070/448] bazel: update rules_docker and use official busybox base image --- build/BUILD | 21 ++++----------------- build/root/WORKSPACE | 33 +++++++++++++-------------------- 2 files changed, 17 insertions(+), 37 deletions(-) diff --git a/build/BUILD b/build/BUILD index f87cc21e335..5f08ab29c54 100644 --- a/build/BUILD +++ b/build/BUILD @@ -21,36 +21,23 @@ filegroup( tags = ["automanaged"], ) -docker_build( - name = "busybox", - debs = [ - "@busybox_deb//file", - ], - symlinks = { - "/bin/sh": "/bin/busybox", - "/usr/bin/busybox": "/bin/busybox", - "/usr/sbin/busybox": "/bin/busybox", - "/sbin/busybox": "/bin/busybox", - }, -) - # This list should roughly match kube::build::get_docker_wrapped_binaries() # in build/common.sh. DOCKERIZED_BINARIES = { "cloud-controller-manager": { - "base": ":busybox", + "base": "@official_busybox//image:image.tar", "target": "//cmd/cloud-controller-manager:cloud-controller-manager", }, "kube-apiserver": { - "base": ":busybox", + "base": "@official_busybox//image:image.tar", "target": "//cmd/kube-apiserver:kube-apiserver", }, "kube-controller-manager": { - "base": ":busybox", + "base": "@official_busybox//image:image.tar", "target": "//cmd/kube-controller-manager:kube-controller-manager", }, "kube-scheduler": { - "base": ":busybox", + "base": "@official_busybox//image:image.tar", "target": "//plugin/cmd/kube-scheduler:kube-scheduler", }, "kube-proxy": { diff --git a/build/root/WORKSPACE b/build/root/WORKSPACE index f57923a8bc6..dae5b035e78 100644 --- a/build/root/WORKSPACE +++ b/build/root/WORKSPACE @@ -24,9 +24,9 @@ http_archive( http_archive( name = "io_bazel_rules_docker", - sha256 = "261fbd8fda1d06a12a0479019b46acd302c6aaa8df8e49383dc37917f20492a1", - strip_prefix = "rules_docker-52d9faf209ff6d16eb850b6b66d03483735e0633", - urls = ["https://github.com/bazelbuild/rules_docker/archive/52d9faf209ff6d16eb850b6b66d03483735e0633.tar.gz"], + sha256 = "bbf0ea808ab6c599307b321f360aef2e6a31da4a35aaf14eca305c9878cca0b3", + strip_prefix = "rules_docker-d0cf5ea34a6f900370b91227b95e9f0a13722c70", + urls = ["https://github.com/bazelbuild/rules_docker/archive/d0cf5ea34a6f900370b91227b95e9f0a13722c70.tar.gz"], ) load("@io_bazel_rules_go//go:def.bzl", "go_repositories") @@ -38,22 +38,6 @@ go_repositories( docker_repositories() -# for building docker base images -debs = ( - ( - "busybox_deb", - "5f81f140777454e71b9e5bfdce9c89993de5ddf4a7295ea1cfda364f8f630947", - "http://ftp.us.debian.org/debian/pool/main/b/busybox/busybox-static_1.22.0-19+b3_amd64.deb", - "https://storage.googleapis.com/kubernetes-release/debs/busybox-static_1.22.0-19+b3_amd64.deb", - ), -) - -[http_file( - name = name, - sha256 = sha256, - url = url, -) for name, sha256, origin, url in debs] - http_file( name = "kubernetes_cni", sha256 = "05ab3937bc68562e989dc143362ec4d4275262ba9f359338aed720fc914457a5", @@ -62,7 +46,16 @@ http_file( docker_pull( name = "debian-iptables-amd64", - digest = "sha256:bc20977ac38abfb43071b4c61c4b7edb30af894c05eb06758dd61d05118d2842", # v7 + digest = "sha256:bc20977ac38abfb43071b4c61c4b7edb30af894c05eb06758dd61d05118d2842", registry = "gcr.io", repository = "google-containers/debian-iptables-amd64", + tag = "v7", # ignored, but kept here for documentation +) + +docker_pull( + name = "official_busybox", + digest = "sha256:be3c11fdba7cfe299214e46edc642e09514dbb9bbefcd0d3836c05a1e0cd0642", + registry = "index.docker.io", + repository = "library/busybox", + tag = "latest", # ignored, but kept here for documentation ) From 7a279e5972505d0365fab5ca9542828e3a2bc8a6 Mon Sep 17 00:00:00 2001 From: shikhi7 Date: Tue, 27 Jun 2017 06:12:56 +0530 Subject: [PATCH 071/448] Formatted Dockerfile to be cleaner and precise --- .../phabricator/php-phabricator/Dockerfile | 26 +++++++++++-------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/examples/phabricator/php-phabricator/Dockerfile b/examples/phabricator/php-phabricator/Dockerfile index f39b9421af9..779e799ce6c 100644 --- a/examples/phabricator/php-phabricator/Dockerfile +++ b/examples/phabricator/php-phabricator/Dockerfile @@ -15,21 +15,25 @@ FROM ubuntu:14.04 # Install all the required packages. -RUN apt-get update -RUN apt-get -y install \ +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 -RUN a2enmod rewrite -RUN apt-get source php5 -RUN (cd `ls -1F | grep '^php5-.*/$'`/ext/pcntl && phpize && ./configure && make && sudo make install) + 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 -RUN cd /home/www-data && git clone https://github.com/phacility/arcanist.git -RUN cd /home/www-data && git clone https://github.com/phacility/phabricator.git -RUN chown -R www-data /home/www-data -RUN chgrp -R www-data /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 From 78d111b75f08f25cf428c605aca40616ce97f626 Mon Sep 17 00:00:00 2001 From: Cheng Xing Date: Mon, 26 Jun 2017 18:41:14 -0700 Subject: [PATCH 072/448] Ensures node becomes schedulable at the end of tests that delete nodes --- test/e2e/storage/pd.go | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/test/e2e/storage/pd.go b/test/e2e/storage/pd.go index 30beca7003b..ec21cf047b7 100644 --- a/test/e2e/storage/pd.go +++ b/test/e2e/storage/pd.go @@ -429,8 +429,9 @@ var _ = framework.KubeDescribe("Pod Disks", func() { podClient.Delete(host0Pod.Name, metav1.NewDeleteOptions(0)) detachAndDeletePDs(diskName, []types.NodeName{host0Name}) framework.WaitForNodeToBeReady(f.ClientSet, string(host0Name), nodeStatusTimeout) + framework.WaitForAllNodesSchedulable(f.ClientSet, nodeStatusTimeout) nodes = framework.GetReadySchedulableNodesOrDie(f.ClientSet) - Expect(len(nodes.Items)).To(Equal(initialGroupSize)) + Expect(len(nodes.Items)).To(Equal(initialGroupSize), "Requires node count to return to initial group size.") }() By("submitting host0Pod to kubernetes") @@ -480,7 +481,7 @@ var _ = framework.KubeDescribe("Pod Disks", func() { originalCount := len(nodes.Items) containerName := "mycontainer" nodeToDelete := &nodes.Items[0] - defer func() error { + defer func() { By("Cleaning up PD-RW test env") detachAndDeletePDs(diskName, []types.NodeName{host0Name}) nodeToDelete.ObjectMeta.SetResourceVersion("0") @@ -489,11 +490,9 @@ var _ = framework.KubeDescribe("Pod Disks", func() { framework.ExpectNoError(err, "Unable to re-create the deleted node") framework.ExpectNoError(framework.WaitForGroupSize(framework.TestContext.CloudConfig.NodeInstanceGroup, int32(initialGroupSize)), "Unable to get the node group back to the original size") framework.WaitForNodeToBeReady(f.ClientSet, nodeToDelete.Name, nodeStatusTimeout) + framework.WaitForAllNodesSchedulable(f.ClientSet, nodeStatusTimeout) nodes = framework.GetReadySchedulableNodesOrDie(f.ClientSet) - if len(nodes.Items) != originalCount { - return fmt.Errorf("The node count is not back to original count") - } - return nil + Expect(len(nodes.Items)).To(Equal(originalCount), "Requires node count to return to original node count.") }() By("submitting host0Pod to kubernetes") From 2ab0c655068e35128533fb7f9ca452aa99588bcf Mon Sep 17 00:00:00 2001 From: zhengjiajin <393926893@qq.com> Date: Tue, 27 Jun 2017 12:21:49 +0800 Subject: [PATCH 073/448] Update docs for user-guide --- cluster/addons/fluentd-gcp/fluentd-gcp-image/README.md | 2 +- examples/volumes/azure_disk/README.md | 2 +- examples/volumes/nfs/README.md | 3 ++- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/cluster/addons/fluentd-gcp/fluentd-gcp-image/README.md b/cluster/addons/fluentd-gcp/fluentd-gcp-image/README.md index f4caa66c8ee..468c0344876 100644 --- a/cluster/addons/fluentd-gcp/fluentd-gcp-image/README.md +++ b/cluster/addons/fluentd-gcp/fluentd-gcp-image/README.md @@ -1,6 +1,6 @@ # Collecting Docker Log Files with Fluentd and sending to GCP. -The image was moved to the the +The image was moved to the [new location](https://github.com/kubernetes/contrib/tree/master/fluentd/fluentd-gcp-image). [![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/cluster/addons/fluentd-gcp/fluentd-gcp-image/README.md?pixel)]() diff --git a/examples/volumes/azure_disk/README.md b/examples/volumes/azure_disk/README.md index 35edc7ca8d4..d456356f161 100644 --- a/examples/volumes/azure_disk/README.md +++ b/examples/volumes/azure_disk/README.md @@ -7,7 +7,7 @@ In the pod, you need to provide the following information: - *diskName*: (required) the name of the VHD blob object. - *diskURI*: (required) the URI of the vhd blob object. - *cachingMode*: (optional) disk caching mode. Must be one of None, ReadOnly, or ReadWrite. Default is None. -- *fsType*: (optional) the filesytem type to mount. Default is ext4. +- *fsType*: (optional) the filesystem type to mount. Default is ext4. - *readOnly*: (optional) whether the filesystem is used as readOnly. Default is false. diff --git a/examples/volumes/nfs/README.md b/examples/volumes/nfs/README.md index f5a9d662087..2fa5ebe098d 100644 --- a/examples/volumes/nfs/README.md +++ b/examples/volumes/nfs/README.md @@ -85,7 +85,8 @@ Replace the invalid IP in the [nfs PV](nfs-pv.yaml). (In the future, we'll be able to tie these together using the service names, but for now, you have to hardcode the IP.) -Create the the [persistent volume](https://kubernetes.io/docs/user-guide/persistent-volumes.md) +Create the [persistent volume](https://kubernetes.io/docs/concepts/storage/persistent-volumes/) + and the persistent volume claim for your NFS server. The persistent volume and claim gives us an indirection that allow multiple pods to refer to the NFS server using a symbolic name rather than the hardcoded server address. From 4e9abca6d0a6ab955f7ff01757ad266dff609fba Mon Sep 17 00:00:00 2001 From: xiangpengzhao Date: Mon, 22 May 2017 14:23:23 +0800 Subject: [PATCH 074/448] Allocate clusterIP when change service type from ExternalName to ClusterIP --- .../core/service/portallocator/operation.go | 18 +- pkg/registry/core/service/rest.go | 157 +++++++++++++----- test/e2e/dns.go | 10 +- test/e2e/framework/service_util.go | 38 ++++- test/e2e/service.go | 61 ++++++- 5 files changed, 224 insertions(+), 60 deletions(-) diff --git a/pkg/registry/core/service/portallocator/operation.go b/pkg/registry/core/service/portallocator/operation.go index 08d9d587815..00dd7f03cf4 100644 --- a/pkg/registry/core/service/portallocator/operation.go +++ b/pkg/registry/core/service/portallocator/operation.go @@ -28,7 +28,7 @@ package portallocator // ... // write(updatedOwner) /// op.Commit() -type portAllocationOperation struct { +type PortAllocationOperation struct { pa Interface allocated []int releaseDeferred []int @@ -36,8 +36,8 @@ type portAllocationOperation struct { } // Creates a portAllocationOperation, tracking a set of allocations & releases -func StartOperation(pa Interface) *portAllocationOperation { - op := &portAllocationOperation{} +func StartOperation(pa Interface) *PortAllocationOperation { + op := &PortAllocationOperation{} op.pa = pa op.allocated = []int{} op.releaseDeferred = []int{} @@ -46,14 +46,14 @@ func StartOperation(pa Interface) *portAllocationOperation { } // Will rollback unless marked as shouldRollback = false by a Commit(). Call from a defer block -func (op *portAllocationOperation) Finish() { +func (op *PortAllocationOperation) Finish() { if op.shouldRollback { op.Rollback() } } // (Try to) undo any operations we did -func (op *portAllocationOperation) Rollback() []error { +func (op *PortAllocationOperation) Rollback() []error { errors := []error{} for _, allocated := range op.allocated { @@ -72,7 +72,7 @@ func (op *portAllocationOperation) Rollback() []error { // (Try to) perform any deferred operations. // Note that even if this fails, we don't rollback; we always want to err on the side of over-allocation, // and Commit should be called _after_ the owner is written -func (op *portAllocationOperation) Commit() []error { +func (op *PortAllocationOperation) Commit() []error { errors := []error{} for _, release := range op.releaseDeferred { @@ -94,7 +94,7 @@ func (op *portAllocationOperation) Commit() []error { } // Allocates a port, and record it for future rollback -func (op *portAllocationOperation) Allocate(port int) error { +func (op *PortAllocationOperation) Allocate(port int) error { err := op.pa.Allocate(port) if err == nil { op.allocated = append(op.allocated, port) @@ -103,7 +103,7 @@ func (op *portAllocationOperation) Allocate(port int) error { } // Allocates a port, and record it for future rollback -func (op *portAllocationOperation) AllocateNext() (int, error) { +func (op *PortAllocationOperation) AllocateNext() (int, error) { port, err := op.pa.AllocateNext() if err == nil { op.allocated = append(op.allocated, port) @@ -112,6 +112,6 @@ func (op *portAllocationOperation) AllocateNext() (int, error) { } // Marks a port so that it will be released if this operation Commits -func (op *portAllocationOperation) ReleaseDeferred(port int) { +func (op *PortAllocationOperation) ReleaseDeferred(port int) { op.releaseDeferred = append(op.releaseDeferred, port) } diff --git a/pkg/registry/core/service/rest.go b/pkg/registry/core/service/rest.go index a369708579d..576bc599918 100644 --- a/pkg/registry/core/service/rest.go +++ b/pkg/registry/core/service/rest.go @@ -357,58 +357,45 @@ func (rs *REST) Update(ctx genericapirequest.Context, name string, objInfo rest. return nil, false, errors.NewInvalid(api.Kind("Service"), service.Name, errs) } + // TODO: this should probably move to strategy.PrepareForCreate() + releaseServiceIP := false + defer func() { + if releaseServiceIP { + if helper.IsServiceIPSet(service) { + rs.serviceIPs.Release(net.ParseIP(service.Spec.ClusterIP)) + } + } + }() + nodePortOp := portallocator.StartOperation(rs.serviceNodePorts) defer nodePortOp.Finish() - assignNodePorts := shouldAssignNodePorts(service) - - oldNodePorts := CollectServiceNodePorts(oldService) - - newNodePorts := []int{} - if assignNodePorts { - for i := range service.Spec.Ports { - servicePort := &service.Spec.Ports[i] - nodePort := int(servicePort.NodePort) - if nodePort != 0 { - if !contains(oldNodePorts, nodePort) { - err := nodePortOp.Allocate(nodePort) - if err != nil { - el := field.ErrorList{field.Invalid(field.NewPath("spec", "ports").Index(i).Child("nodePort"), nodePort, err.Error())} - return nil, false, errors.NewInvalid(api.Kind("Service"), service.Name, el) - } - } - } else { - nodePort, err = nodePortOp.AllocateNext() - if err != nil { - // TODO: what error should be returned here? It's not a - // field-level validation failure (the field is valid), and it's - // not really an internal error. - return nil, false, errors.NewInternalError(fmt.Errorf("failed to allocate a nodePort: %v", err)) - } - servicePort.NodePort = int32(nodePort) - } - // Detect duplicate node ports; this should have been caught by validation, so we panic - if contains(newNodePorts, nodePort) { - panic("duplicate node port") - } - newNodePorts = append(newNodePorts, nodePort) + // Update service from ExternalName to non-ExternalName, should initialize ClusterIP. + if oldService.Spec.Type == api.ServiceTypeExternalName && service.Spec.Type != api.ServiceTypeExternalName { + if releaseServiceIP, err = rs.initClusterIP(service); err != nil { + return nil, false, err } - } else { - // Validate should have validated that nodePort == 0 } - - // The comparison loops are O(N^2), but we don't expect N to be huge - // (there's a hard-limit at 2^16, because they're ports; and even 4 ports would be a lot) - for _, oldNodePort := range oldNodePorts { - if contains(newNodePorts, oldNodePort) { - continue + // Update service from non-ExternalName to ExternalName, should release ClusterIP if exists. + if oldService.Spec.Type != api.ServiceTypeExternalName && service.Spec.Type == api.ServiceTypeExternalName { + if helper.IsServiceIPSet(oldService) { + rs.serviceIPs.Release(net.ParseIP(oldService.Spec.ClusterIP)) } - nodePortOp.ReleaseDeferred(oldNodePort) } - - // Remove any LoadBalancerStatus now if Type != LoadBalancer; - // although loadbalancer delete is actually asynchronous, we don't need to expose the user to that complexity. + // Update service from NodePort or LoadBalancer to ExternalName or ClusterIP, should release NodePort if exists. + if (oldService.Spec.Type == api.ServiceTypeNodePort || oldService.Spec.Type == api.ServiceTypeLoadBalancer) && + (service.Spec.Type == api.ServiceTypeExternalName || service.Spec.Type == api.ServiceTypeClusterIP) { + rs.releaseNodePort(oldService, nodePortOp) + } + // Update service from any type to NodePort or LoadBalancer, should update NodePort. + if service.Spec.Type == api.ServiceTypeNodePort || service.Spec.Type == api.ServiceTypeLoadBalancer { + if err := rs.updateNodePort(oldService, service, nodePortOp); err != nil { + return nil, false, err + } + } + // Update service from LoadBalancer to non-LoadBalancer, should remove any LoadBalancerStatus. if service.Spec.Type != api.ServiceTypeLoadBalancer { + // Although loadbalancer delete is actually asynchronous, we don't need to expose the user to that complexity. service.Status.LoadBalancer = api.LoadBalancerStatus{} } @@ -425,13 +412,14 @@ func (rs *REST) Update(ctx genericapirequest.Context, name string, objInfo rest. } out, err := rs.registry.UpdateService(ctx, service) - if err == nil { el := nodePortOp.Commit() if el != nil { // problems should be fixed by an eventual reconciliation / restart glog.Errorf("error(s) committing NodePorts changes: %v", el) } + + releaseServiceIP = false } return out, false, err @@ -570,3 +558,82 @@ func (rs *REST) allocateHealthCheckNodePort(service *api.Service) error { } return nil } + +// The return bool value indicates if the caller should release clusterIP before return +func (rs *REST) initClusterIP(service *api.Service) (bool, error) { + switch { + case service.Spec.ClusterIP == "": + // Allocate next available. + ip, err := rs.serviceIPs.AllocateNext() + if err != nil { + // TODO: what error should be returned here? It's not a + // field-level validation failure (the field is valid), and it's + // not really an internal error. + return false, errors.NewInternalError(fmt.Errorf("failed to allocate a serviceIP: %v", err)) + } + service.Spec.ClusterIP = ip.String() + return true, nil + case service.Spec.ClusterIP != api.ClusterIPNone && service.Spec.ClusterIP != "": + // Try to respect the requested IP. + if err := rs.serviceIPs.Allocate(net.ParseIP(service.Spec.ClusterIP)); err != nil { + // TODO: when validation becomes versioned, this gets more complicated. + el := field.ErrorList{field.Invalid(field.NewPath("spec", "clusterIP"), service.Spec.ClusterIP, err.Error())} + return false, errors.NewInvalid(api.Kind("Service"), service.Name, el) + } + return true, nil + } + + return false, nil +} + +func (rs *REST) updateNodePort(oldService, service *api.Service, nodePortOp *portallocator.PortAllocationOperation) error { + oldNodePorts := CollectServiceNodePorts(oldService) + + newNodePorts := []int{} + for i := range service.Spec.Ports { + servicePort := &service.Spec.Ports[i] + nodePort := int(servicePort.NodePort) + if nodePort != 0 { + if !contains(oldNodePorts, nodePort) { + err := nodePortOp.Allocate(nodePort) + if err != nil { + el := field.ErrorList{field.Invalid(field.NewPath("spec", "ports").Index(i).Child("nodePort"), nodePort, err.Error())} + return errors.NewInvalid(api.Kind("Service"), service.Name, el) + } + } + } else { + nodePort, err := nodePortOp.AllocateNext() + if err != nil { + // TODO: what error should be returned here? It's not a + // field-level validation failure (the field is valid), and it's + // not really an internal error. + return errors.NewInternalError(fmt.Errorf("failed to allocate a nodePort: %v", err)) + } + servicePort.NodePort = int32(nodePort) + } + // Detect duplicate node ports; this should have been caught by validation, so we panic + if contains(newNodePorts, nodePort) { + panic("duplicate node port") + } + newNodePorts = append(newNodePorts, nodePort) + } + + // The comparison loops are O(N^2), but we don't expect N to be huge + // (there's a hard-limit at 2^16, because they're ports; and even 4 ports would be a lot) + for _, oldNodePort := range oldNodePorts { + if contains(newNodePorts, oldNodePort) { + continue + } + nodePortOp.ReleaseDeferred(oldNodePort) + } + + return nil +} + +func (rs *REST) releaseNodePort(service *api.Service, nodePortOp *portallocator.PortAllocationOperation) { + nodePorts := CollectServiceNodePorts(service) + + for _, nodePort := range nodePorts { + nodePortOp.ReleaseDeferred(nodePort) + } +} diff --git a/test/e2e/dns.go b/test/e2e/dns.go index 82e2de5f17a..9f78b22ecdc 100644 --- a/test/e2e/dns.go +++ b/test/e2e/dns.go @@ -225,7 +225,6 @@ func assertFilesContain(fileNames []string, fileDir string, pod *v1.Pod, client } func validateDNSResults(f *framework.Framework, pod *v1.Pod, fileNames []string) { - By("submitting the pod to kubernetes") podClient := f.ClientSet.Core().Pods(f.Namespace.Name) defer func() { @@ -254,7 +253,6 @@ func validateDNSResults(f *framework.Framework, pod *v1.Pod, fileNames []string) } func validateTargetedProbeOutput(f *framework.Framework, pod *v1.Pod, fileNames []string, value string) { - By("submitting the pod to kubernetes") podClient := f.ClientSet.Core().Pods(f.Namespace.Name) defer func() { @@ -424,6 +422,10 @@ var _ = framework.KubeDescribe("DNS", func() { }) It("should provide DNS for ExternalName services", func() { + // TODO(xiangpengzhao): allow AWS when pull-kubernetes-e2e-kops-aws and pull-kubernetes-e2e-gce-etcd3 + // have the same "service-cluster-ip-range". See: https://github.com/kubernetes/kubernetes/issues/47224 + framework.SkipUnlessProviderIs("gce") + // Create a test ExternalName service. By("Creating a test externalName service") serviceName := "dns-test-service-3" @@ -469,7 +471,7 @@ var _ = framework.KubeDescribe("DNS", func() { By("changing the service to type=ClusterIP") _, err = framework.UpdateService(f.ClientSet, f.Namespace.Name, serviceName, func(s *v1.Service) { s.Spec.Type = v1.ServiceTypeClusterIP - s.Spec.ClusterIP = "127.1.2.3" + s.Spec.ClusterIP = "10.0.0.123" s.Spec.Ports = []v1.ServicePort{ {Port: 80, Name: "http", Protocol: "TCP"}, } @@ -484,6 +486,6 @@ var _ = framework.KubeDescribe("DNS", func() { By("creating a third pod to probe DNS") pod3 := createDNSPod(f.Namespace.Name, wheezyProbeCmd, jessieProbeCmd, true) - validateTargetedProbeOutput(f, pod3, []string{wheezyFileName, jessieFileName}, "127.1.2.3") + validateTargetedProbeOutput(f, pod3, []string{wheezyFileName, jessieFileName}, "10.0.0.123") }) }) diff --git a/test/e2e/framework/service_util.go b/test/e2e/framework/service_util.go index f0bb2162ee4..d123803db80 100644 --- a/test/e2e/framework/service_util.go +++ b/test/e2e/framework/service_util.go @@ -35,6 +35,7 @@ import ( "k8s.io/apimachinery/pkg/util/sets" "k8s.io/apimachinery/pkg/util/uuid" "k8s.io/apimachinery/pkg/util/wait" + "k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/client/clientset_generated/clientset" "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" "k8s.io/kubernetes/pkg/client/retry" @@ -177,6 +178,31 @@ func (j *ServiceTestJig) CreateUDPServiceOrFail(namespace string, tweak func(svc return result } +// CreateExternalNameServiceOrFail creates a new ExternalName type Service based on the jig's defaults. +// Callers can provide a function to tweak the Service object before it is created. +func (j *ServiceTestJig) CreateExternalNameServiceOrFail(namespace string, tweak func(svc *v1.Service)) *v1.Service { + svc := &v1.Service{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: namespace, + Name: j.Name, + Labels: j.Labels, + }, + Spec: v1.ServiceSpec{ + Selector: j.Labels, + ExternalName: "foo.example.com", + Type: v1.ServiceTypeExternalName, + }, + } + if tweak != nil { + tweak(svc) + } + result, err := j.Client.Core().Services(namespace).Create(svc) + if err != nil { + Failf("Failed to create ExternalName Service %q: %v", svc.Name, err) + } + return result +} + func (j *ServiceTestJig) ChangeServiceType(namespace, name string, newType v1.ServiceType, timeout time.Duration) { ingressIP := "" svc := j.UpdateServiceOrFail(namespace, name, func(s *v1.Service) { @@ -373,8 +399,18 @@ func (j *ServiceTestJig) SanityCheckService(svc *v1.Service, svcType v1.ServiceT if svc.Spec.Type != svcType { Failf("unexpected Spec.Type (%s) for service, expected %s", svc.Spec.Type, svcType) } + + if svcType != v1.ServiceTypeExternalName { + if svc.Spec.ExternalName != "" { + Failf("unexpected Spec.ExternalName (%s) for service, expected empty", svc.Spec.ExternalName) + } + if svc.Spec.ClusterIP != api.ClusterIPNone && svc.Spec.ClusterIP == "" { + Failf("didn't get ClusterIP for non-ExternamName service") + } + } + expectNodePorts := false - if svcType != v1.ServiceTypeClusterIP { + if svcType != v1.ServiceTypeClusterIP && svcType != v1.ServiceTypeExternalName { expectNodePorts = true } for i, port := range svc.Spec.Ports { diff --git a/test/e2e/service.go b/test/e2e/service.go index 2165e43e039..60e8bb11406 100644 --- a/test/e2e/service.go +++ b/test/e2e/service.go @@ -789,6 +789,65 @@ var _ = framework.KubeDescribe("Services", func() { } }) + It("should be able to change the type from ExternalName to ClusterIP", func() { + serviceName := "externalname-service" + ns := f.Namespace.Name + jig := framework.NewServiceTestJig(cs, serviceName) + + By("creating a service " + serviceName + " with the type=ExternalName in namespace " + ns) + externalNameService := jig.CreateExternalNameServiceOrFail(ns, nil) + jig.SanityCheckService(externalNameService, v1.ServiceTypeExternalName) + By("changing the ExternalName service to type=ClusterIP") + clusterIPService := jig.UpdateServiceOrFail(ns, externalNameService.Name, func(s *v1.Service) { + s.Spec.Type = v1.ServiceTypeClusterIP + s.Spec.ExternalName = "" + s.Spec.Ports = []v1.ServicePort{ + {Port: 80, Name: "http", Protocol: "TCP"}, + } + }) + jig.SanityCheckService(clusterIPService, v1.ServiceTypeClusterIP) + }) + + It("should be able to change the type from ExternalName to NodePort", func() { + serviceName := "externalname-service" + ns := f.Namespace.Name + jig := framework.NewServiceTestJig(cs, serviceName) + + By("creating a service " + serviceName + " with the type=ExternalName in namespace " + ns) + externalNameService := jig.CreateExternalNameServiceOrFail(ns, nil) + jig.SanityCheckService(externalNameService, v1.ServiceTypeExternalName) + By("changing the ExternalName service to type=NodePort") + nodePortService := jig.UpdateServiceOrFail(ns, externalNameService.Name, func(s *v1.Service) { + s.Spec.Type = v1.ServiceTypeNodePort + s.Spec.ExternalName = "" + s.Spec.Ports = []v1.ServicePort{ + {Port: 80, Name: "http", Protocol: "TCP"}, + } + }) + jig.SanityCheckService(nodePortService, v1.ServiceTypeNodePort) + }) + + It("should be able to change the type from ExternalName to LoadBalancer", func() { + serviceName := "externalname-service" + ns := f.Namespace.Name + loadBalancerCreateTimeout := framework.LoadBalancerCreateTimeoutDefault + jig := framework.NewServiceTestJig(cs, serviceName) + + By("creating a service " + serviceName + " with the type=ExternalName in namespace " + ns) + externalNameService := jig.CreateExternalNameServiceOrFail(ns, nil) + jig.SanityCheckService(externalNameService, v1.ServiceTypeExternalName) + By("changing the ExternalName service to type=LoadBalancer") + loadBalancerIPService := jig.UpdateServiceOrFail(ns, externalNameService.Name, func(s *v1.Service) { + s.Spec.Type = v1.ServiceTypeLoadBalancer + s.Spec.ExternalName = "" + s.Spec.Ports = []v1.ServicePort{ + {Port: 80, Name: "http", Protocol: "TCP"}, + } + }) + loadBalancerIPService = jig.WaitForLoadBalancerOrFail(ns, loadBalancerIPService.Name, loadBalancerCreateTimeout) + jig.SanityCheckService(loadBalancerIPService, v1.ServiceTypeLoadBalancer) + }) + It("should use same NodePort with same port but different protocols", func() { serviceName := "nodeports" ns := f.Namespace.Name @@ -866,7 +925,7 @@ var _ = framework.KubeDescribe("Services", func() { } port := result.Spec.Ports[0] if port.NodePort == 0 { - framework.Failf("got unexpected Spec.Ports[0].nodePort for new service: %v", result) + framework.Failf("got unexpected Spec.Ports[0].NodePort for new service: %v", result) } By("creating service " + serviceName2 + " with conflicting NodePort") From 415f13ea4e49bc58d9ae06420aa62dc69442b15b Mon Sep 17 00:00:00 2001 From: xiangpengzhao Date: Thu, 15 Jun 2017 11:48:26 +0800 Subject: [PATCH 075/448] Modify e2e tests for service type update. --- test/e2e/framework/service_util.go | 4 ++ test/e2e/service.go | 66 +++++++++++++++++++++++------- 2 files changed, 55 insertions(+), 15 deletions(-) diff --git a/test/e2e/framework/service_util.go b/test/e2e/framework/service_util.go index d123803db80..9d1d18b9f01 100644 --- a/test/e2e/framework/service_util.go +++ b/test/e2e/framework/service_util.go @@ -407,6 +407,10 @@ func (j *ServiceTestJig) SanityCheckService(svc *v1.Service, svcType v1.ServiceT if svc.Spec.ClusterIP != api.ClusterIPNone && svc.Spec.ClusterIP == "" { Failf("didn't get ClusterIP for non-ExternamName service") } + } else { + if svc.Spec.ClusterIP != "" { + Failf("unexpected Spec.ClusterIP (%s) for ExternamName service, expected empty", svc.Spec.ClusterIP) + } } expectNodePorts := false diff --git a/test/e2e/service.go b/test/e2e/service.go index 60e8bb11406..78291b12a82 100644 --- a/test/e2e/service.go +++ b/test/e2e/service.go @@ -796,6 +796,11 @@ var _ = framework.KubeDescribe("Services", func() { By("creating a service " + serviceName + " with the type=ExternalName in namespace " + ns) externalNameService := jig.CreateExternalNameServiceOrFail(ns, nil) + defer func() { + framework.Logf("Cleaning up the ExternalName to ClusterIP test service") + err := cs.Core().Services(ns).Delete(serviceName, nil) + Expect(err).NotTo(HaveOccurred()) + }() jig.SanityCheckService(externalNameService, v1.ServiceTypeExternalName) By("changing the ExternalName service to type=ClusterIP") clusterIPService := jig.UpdateServiceOrFail(ns, externalNameService.Name, func(s *v1.Service) { @@ -815,6 +820,11 @@ var _ = framework.KubeDescribe("Services", func() { By("creating a service " + serviceName + " with the type=ExternalName in namespace " + ns) externalNameService := jig.CreateExternalNameServiceOrFail(ns, nil) + defer func() { + framework.Logf("Cleaning up the ExternalName to NodePort test service") + err := cs.Core().Services(ns).Delete(serviceName, nil) + Expect(err).NotTo(HaveOccurred()) + }() jig.SanityCheckService(externalNameService, v1.ServiceTypeExternalName) By("changing the ExternalName service to type=NodePort") nodePortService := jig.UpdateServiceOrFail(ns, externalNameService.Name, func(s *v1.Service) { @@ -827,25 +837,51 @@ var _ = framework.KubeDescribe("Services", func() { jig.SanityCheckService(nodePortService, v1.ServiceTypeNodePort) }) - It("should be able to change the type from ExternalName to LoadBalancer", func() { - serviceName := "externalname-service" + It("should be able to change the type from ClusterIP to ExternalName", func() { + serviceName := "clusterip-service" ns := f.Namespace.Name - loadBalancerCreateTimeout := framework.LoadBalancerCreateTimeoutDefault jig := framework.NewServiceTestJig(cs, serviceName) - By("creating a service " + serviceName + " with the type=ExternalName in namespace " + ns) - externalNameService := jig.CreateExternalNameServiceOrFail(ns, nil) - jig.SanityCheckService(externalNameService, v1.ServiceTypeExternalName) - By("changing the ExternalName service to type=LoadBalancer") - loadBalancerIPService := jig.UpdateServiceOrFail(ns, externalNameService.Name, func(s *v1.Service) { - s.Spec.Type = v1.ServiceTypeLoadBalancer - s.Spec.ExternalName = "" - s.Spec.Ports = []v1.ServicePort{ - {Port: 80, Name: "http", Protocol: "TCP"}, - } + By("creating a service " + serviceName + " with the type=ClusterIP in namespace " + ns) + clusterIPService := jig.CreateTCPServiceOrFail(ns, nil) + defer func() { + framework.Logf("Cleaning up the ClusterIP to ExternalName test service") + err := cs.Core().Services(ns).Delete(serviceName, nil) + Expect(err).NotTo(HaveOccurred()) + }() + jig.SanityCheckService(clusterIPService, v1.ServiceTypeClusterIP) + By("changing the ClusterIP service to type=ExternalName") + externalNameService := jig.UpdateServiceOrFail(ns, clusterIPService.Name, func(s *v1.Service) { + s.Spec.Type = v1.ServiceTypeExternalName + s.Spec.ExternalName = "foo.example.com" + s.Spec.ClusterIP = "" }) - loadBalancerIPService = jig.WaitForLoadBalancerOrFail(ns, loadBalancerIPService.Name, loadBalancerCreateTimeout) - jig.SanityCheckService(loadBalancerIPService, v1.ServiceTypeLoadBalancer) + jig.SanityCheckService(externalNameService, v1.ServiceTypeExternalName) + }) + + It("should be able to change the type from NodePort to ExternalName", func() { + serviceName := "nodeport-service" + ns := f.Namespace.Name + jig := framework.NewServiceTestJig(cs, serviceName) + + By("creating a service " + serviceName + " with the type=NodePort in namespace " + ns) + nodePortService := jig.CreateTCPServiceOrFail(ns, func(svc *v1.Service) { + svc.Spec.Type = v1.ServiceTypeNodePort + }) + defer func() { + framework.Logf("Cleaning up the NodePort to ExternalName test service") + err := cs.Core().Services(ns).Delete(serviceName, nil) + Expect(err).NotTo(HaveOccurred()) + }() + jig.SanityCheckService(nodePortService, v1.ServiceTypeNodePort) + By("changing the NodePort service to type=ExternalName") + externalNameService := jig.UpdateServiceOrFail(ns, nodePortService.Name, func(s *v1.Service) { + s.Spec.Type = v1.ServiceTypeExternalName + s.Spec.ExternalName = "foo.example.com" + s.Spec.ClusterIP = "" + s.Spec.Ports[0].NodePort = 0 + }) + jig.SanityCheckService(externalNameService, v1.ServiceTypeExternalName) }) It("should use same NodePort with same port but different protocols", func() { From 0f65b218a07e3a5edda16484604dcf1f76bae793 Mon Sep 17 00:00:00 2001 From: xiangpengzhao Date: Tue, 27 Jun 2017 16:54:35 +0800 Subject: [PATCH 076/448] Add Pod UID (metadata.uid) to downward API env var --- pkg/api/types.go | 4 ++-- pkg/api/v1/conversion.go | 1 + pkg/api/validation/validation.go | 5 +++-- pkg/api/validation/validation_test.go | 26 ++++++++++++++++++++++---- pkg/fieldpath/fieldpath.go | 2 ++ 5 files changed, 30 insertions(+), 8 deletions(-) diff --git a/pkg/api/types.go b/pkg/api/types.go index b59f7202e4c..37540b09146 100644 --- a/pkg/api/types.go +++ b/pkg/api/types.go @@ -1008,7 +1008,7 @@ type DownwardAPIVolumeSource struct { type DownwardAPIVolumeFile struct { // 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 '..' Path string - // Required: Selects a field of the pod: only annotations, labels, name and namespace are supported. + // Required: Selects a field of the pod: only annotations, labels, name, namespace and uid are supported. // +optional FieldRef *ObjectFieldSelector // Selects a resource of the container: only resources limits and requests @@ -1373,7 +1373,7 @@ type EnvVar struct { // Only one of its fields may be set. type EnvVarSource struct { // Selects a field of the pod: supports metadata.name, metadata.namespace, metadata.labels, metadata.annotations, - // spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP. + // metadata.uid, spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP. // +optional FieldRef *ObjectFieldSelector // Selects a resource of the container: only resources limits and requests diff --git a/pkg/api/v1/conversion.go b/pkg/api/v1/conversion.go index 2b07586d7b5..585e7c285fe 100644 --- a/pkg/api/v1/conversion.go +++ b/pkg/api/v1/conversion.go @@ -188,6 +188,7 @@ func addConversionFuncs(scheme *runtime.Scheme) error { "metadata.labels", "metadata.name", "metadata.namespace", + "metadata.uid", "spec.nodeName", "spec.restartPolicy", "spec.serviceAccountName", diff --git a/pkg/api/validation/validation.go b/pkg/api/validation/validation.go index 901e67f7edf..ba1bc08ddab 100644 --- a/pkg/api/validation/validation.go +++ b/pkg/api/validation/validation.go @@ -804,7 +804,8 @@ var validDownwardAPIFieldPathExpressions = sets.NewString( "metadata.name", "metadata.namespace", "metadata.labels", - "metadata.annotations") + "metadata.annotations", + "metadata.uid") func validateDownwardAPIVolumeFile(file *api.DownwardAPIVolumeFile, fldPath *field.Path) field.ErrorList { allErrs := field.ErrorList{} @@ -1552,7 +1553,7 @@ func ValidateEnv(vars []api.EnvVar, fldPath *field.Path) field.ErrorList { return allErrs } -var validFieldPathExpressionsEnv = sets.NewString("metadata.name", "metadata.namespace", "spec.nodeName", "spec.serviceAccountName", "status.hostIP", "status.podIP") +var validFieldPathExpressionsEnv = sets.NewString("metadata.name", "metadata.namespace", "metadata.uid", "spec.nodeName", "spec.serviceAccountName", "status.hostIP", "status.podIP") var validContainerResourceFieldPathExpressions = sets.NewString("limits.cpu", "limits.memory", "requests.cpu", "requests.memory") func validateEnvVarValueFrom(ev api.EnvVar, fldPath *field.Path) field.ErrorList { diff --git a/pkg/api/validation/validation_test.go b/pkg/api/validation/validation_test.go index b8bb79f9804..f4e54de5ebe 100644 --- a/pkg/api/validation/validation_test.go +++ b/pkg/api/validation/validation_test.go @@ -2584,6 +2584,24 @@ func TestValidateEnv(t *testing.T) { }, }, }, + { + Name: "abc", + ValueFrom: &api.EnvVarSource{ + FieldRef: &api.ObjectFieldSelector{ + APIVersion: api.Registry.GroupOrDie(api.GroupName).GroupVersion.String(), + FieldPath: "metadata.namespace", + }, + }, + }, + { + Name: "abc", + ValueFrom: &api.EnvVarSource{ + FieldRef: &api.ObjectFieldSelector{ + APIVersion: api.Registry.GroupOrDie(api.GroupName).GroupVersion.String(), + FieldPath: "metadata.uid", + }, + }, + }, { Name: "abc", ValueFrom: &api.EnvVarSource{ @@ -2644,7 +2662,7 @@ func TestValidateEnv(t *testing.T) { }, } if errs := ValidateEnv(successCase, field.NewPath("field")); len(errs) != 0 { - t.Errorf("expected success: %v", errs) + t.Errorf("expected success, got: %v", errs) } errorCases := []struct { @@ -2823,7 +2841,7 @@ func TestValidateEnv(t *testing.T) { }, }, }}, - expectedError: `[0].valueFrom.fieldRef.fieldPath: Unsupported value: "metadata.labels": supported values: metadata.name, metadata.namespace, spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP`, + expectedError: `[0].valueFrom.fieldRef.fieldPath: Unsupported value: "metadata.labels": supported values: metadata.name, metadata.namespace, metadata.uid, spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP`, }, { name: "invalid fieldPath annotations", @@ -2836,7 +2854,7 @@ func TestValidateEnv(t *testing.T) { }, }, }}, - expectedError: `[0].valueFrom.fieldRef.fieldPath: Unsupported value: "metadata.annotations": supported values: metadata.name, metadata.namespace, spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP`, + expectedError: `[0].valueFrom.fieldRef.fieldPath: Unsupported value: "metadata.annotations": supported values: metadata.name, metadata.namespace, metadata.uid, spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP`, }, { name: "unsupported fieldPath", @@ -2849,7 +2867,7 @@ func TestValidateEnv(t *testing.T) { }, }, }}, - expectedError: `valueFrom.fieldRef.fieldPath: Unsupported value: "status.phase": supported values: metadata.name, metadata.namespace, spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP`, + expectedError: `valueFrom.fieldRef.fieldPath: Unsupported value: "status.phase": supported values: metadata.name, metadata.namespace, metadata.uid, spec.nodeName, spec.serviceAccountName, status.hostIP, status.podIP`, }, } for _, tc := range errorCases { diff --git a/pkg/fieldpath/fieldpath.go b/pkg/fieldpath/fieldpath.go index 4001da7997c..caf0096ca0e 100644 --- a/pkg/fieldpath/fieldpath.go +++ b/pkg/fieldpath/fieldpath.go @@ -51,6 +51,8 @@ func ExtractFieldPathAsString(obj interface{}, fieldPath string) (string, error) return accessor.GetName(), nil case "metadata.namespace": return accessor.GetNamespace(), nil + case "metadata.uid": + return string(accessor.GetUID()), nil } return "", fmt.Errorf("unsupported fieldPath: %v", fieldPath) From 0b01cd743b0e9de4d6b19e0eb25b7b9a23ca0e8d Mon Sep 17 00:00:00 2001 From: Konstantinos Tsakalozos Date: Thu, 15 Jun 2017 18:05:34 +0300 Subject: [PATCH 077/448] Improve security of Juju deployed clusters --- .../templates/apilb.conf | 3 - cluster/juju/layers/kubernetes-e2e/README.md | 3 +- cluster/juju/layers/kubernetes-e2e/layer.yaml | 1 + .../juju/layers/kubernetes-e2e/metadata.yaml | 3 + .../kubernetes-e2e/reactive/kubernetes_e2e.py | 68 ++++++-- .../juju/layers/kubernetes-master/config.yaml | 5 + .../reactive/kubernetes_master.py | 162 ++++++++++++++---- .../reactive/kubernetes_worker.py | 80 +++++++-- 8 files changed, 254 insertions(+), 71 deletions(-) diff --git a/cluster/juju/layers/kubeapi-load-balancer/templates/apilb.conf b/cluster/juju/layers/kubeapi-load-balancer/templates/apilb.conf index 0cb18f58e72..88f185acef3 100644 --- a/cluster/juju/layers/kubeapi-load-balancer/templates/apilb.conf +++ b/cluster/juju/layers/kubeapi-load-balancer/templates/apilb.conf @@ -33,9 +33,6 @@ server { proxy_set_header Connection $http_connection; proxy_set_header X-Stream-Protocol-Version $http_x_stream_protocol_version; - proxy_ssl_certificate {{ server_certificate }}; - proxy_ssl_certificate_key {{ server_key }}; - add_header X-Stream-Protocol-Version $upstream_http_x_stream_protocol_version; proxy_pass https://target_service; diff --git a/cluster/juju/layers/kubernetes-e2e/README.md b/cluster/juju/layers/kubernetes-e2e/README.md index d60fbd0c2dc..3f516d7fc42 100644 --- a/cluster/juju/layers/kubernetes-e2e/README.md +++ b/cluster/juju/layers/kubernetes-e2e/README.md @@ -21,7 +21,8 @@ and then relate the `kubernetes-e2e` charm. ```shell juju deploy kubernetes-core juju deploy cs:~containers/kubernetes-e2e -juju add-relation kubernetes-e2e kubernetes-master +juju add-relation kubernetes-e2e:kube-control kubernetes-master:kube-control +juju add-relation kubernetes-e2e:kubernetes-master kubernetes-master:kube-api-endpoint juju add-relation kubernetes-e2e easyrsa ``` diff --git a/cluster/juju/layers/kubernetes-e2e/layer.yaml b/cluster/juju/layers/kubernetes-e2e/layer.yaml index 06d431b0452..b913883bb0d 100644 --- a/cluster/juju/layers/kubernetes-e2e/layer.yaml +++ b/cluster/juju/layers/kubernetes-e2e/layer.yaml @@ -4,6 +4,7 @@ includes: - layer:tls-client - layer:snap - interface:http + - interface:kube-control options: tls-client: ca_certificate_path: '/srv/kubernetes/ca.crt' diff --git a/cluster/juju/layers/kubernetes-e2e/metadata.yaml b/cluster/juju/layers/kubernetes-e2e/metadata.yaml index a67fd67ee62..9f4690a1e2b 100644 --- a/cluster/juju/layers/kubernetes-e2e/metadata.yaml +++ b/cluster/juju/layers/kubernetes-e2e/metadata.yaml @@ -14,6 +14,8 @@ series: requires: kubernetes-master: interface: http + kube-control: + interface: kube-control resources: kubectl: type: file @@ -23,3 +25,4 @@ resources: type: file filename: kubernetes-test.snap description: kubernetes-test snap + diff --git a/cluster/juju/layers/kubernetes-e2e/reactive/kubernetes_e2e.py b/cluster/juju/layers/kubernetes-e2e/reactive/kubernetes_e2e.py index 1ab6f5f7391..76a97aa0d63 100644 --- a/cluster/juju/layers/kubernetes-e2e/reactive/kubernetes_e2e.py +++ b/cluster/juju/layers/kubernetes-e2e/reactive/kubernetes_e2e.py @@ -38,15 +38,22 @@ def reset_delivery_states(): @when('kubernetes-e2e.installed') +def report_status(): + ''' Report the status of the charm. ''' + messaging() + + def messaging(): ''' Probe our relations to determine the propper messaging to the end user ''' missing_services = [] if not is_state('kubernetes-master.available'): - missing_services.append('kubernetes-master') + missing_services.append('kubernetes-master:http') if not is_state('certificates.available'): missing_services.append('certificates') + if not is_state('kubeconfig.ready'): + missing_services.append('kubernetes-master:kube-control') if missing_services: if len(missing_services) > 1: @@ -80,16 +87,15 @@ def install_snaps(): @when('tls_client.ca.saved', 'tls_client.client.certificate.saved', 'tls_client.client.key.saved', 'kubernetes-master.available', - 'kubernetes-e2e.installed') + 'kubernetes-e2e.installed', 'kube-control.auth.available') @when_not('kubeconfig.ready') -def prepare_kubeconfig_certificates(master): +def prepare_kubeconfig_certificates(master, kube_control): ''' Prepare the data to feed to create the kubeconfig file. ''' layer_options = layer.options('tls-client') # Get all the paths to the tls information required for kubeconfig. ca = layer_options.get('ca_certificate_path') - key = layer_options.get('client_key_path') - cert = layer_options.get('client_certificate_path') + creds = kube_control.get_auth_credentials() servers = get_kube_api_servers(master) @@ -97,17 +103,28 @@ def prepare_kubeconfig_certificates(master): kubeconfig_path = '/home/ubuntu/.kube/config' # Create kubernetes configuration in the default location for ubuntu. - create_kubeconfig('/root/.kube/config', servers[0], ca, key, cert, - user='root') - create_kubeconfig(kubeconfig_path, servers[0], ca, key, cert, - user='ubuntu') + create_kubeconfig('/root/.kube/config', servers[0], ca, + token=creds['client_token'], user='root') + create_kubeconfig(kubeconfig_path, servers[0], ca, + token=creds['client_token'], user='ubuntu') # Set permissions on the ubuntu users kubeconfig to ensure a consistent UX cmd = ['chown', 'ubuntu:ubuntu', kubeconfig_path] check_call(cmd) - + messaging() set_state('kubeconfig.ready') +@when('kube-control.connected') +def request_credentials(kube_control): + """ Request authorization creds.""" + + # The kube-cotrol interface is created to support RBAC. + # At this point we might as well do the right thing and return the hostname + # even if it will only be used when we enable RBAC + user = 'system:masters' + kube_control.set_auth_request(user) + + @when('kubernetes-e2e.installed', 'kubeconfig.ready') def set_app_version(): ''' Declare the application version to juju ''' @@ -124,19 +141,40 @@ def set_app_version(): hookenv.application_version_set(version_from.rstrip()) -def create_kubeconfig(kubeconfig, server, ca, key, certificate, user='ubuntu', - context='juju-context', cluster='juju-cluster'): +def create_kubeconfig(kubeconfig, server, ca, key=None, certificate=None, + user='ubuntu', context='juju-context', + cluster='juju-cluster', password=None, token=None): '''Create a configuration for Kubernetes based on path using the supplied arguments for values of the Kubernetes server, CA, key, certificate, user context and cluster.''' + if not key and not certificate and not password and not token: + raise ValueError('Missing authentication mechanism.') + + # token and password are mutually exclusive. Error early if both are + # present. The developer has requested an impossible situation. + # see: kubectl config set-credentials --help + if token and password: + raise ValueError('Token and Password are mutually exclusive.') # Create the config file with the address of the master server. cmd = 'kubectl config --kubeconfig={0} set-cluster {1} ' \ '--server={2} --certificate-authority={3} --embed-certs=true' check_call(split(cmd.format(kubeconfig, cluster, server, ca))) + # Delete old users + cmd = 'kubectl config --kubeconfig={0} unset users' + check_call(split(cmd.format(kubeconfig))) # Create the credentials using the client flags. - cmd = 'kubectl config --kubeconfig={0} set-credentials {1} ' \ - '--client-key={2} --client-certificate={3} --embed-certs=true' - check_call(split(cmd.format(kubeconfig, user, key, certificate))) + cmd = 'kubectl config --kubeconfig={0} ' \ + 'set-credentials {1} '.format(kubeconfig, user) + + if key and certificate: + cmd = '{0} --client-key={1} --client-certificate={2} '\ + '--embed-certs=true'.format(cmd, key, certificate) + if password: + cmd = "{0} --username={1} --password={2}".format(cmd, user, password) + # This is mutually exclusive from password. They will not work together. + if token: + cmd = "{0} --token={1}".format(cmd, token) + check_call(split(cmd)) # Create a default context with the cluster. cmd = 'kubectl config --kubeconfig={0} set-context {1} ' \ '--cluster={2} --user={3}' diff --git a/cluster/juju/layers/kubernetes-master/config.yaml b/cluster/juju/layers/kubernetes-master/config.yaml index 0fde833377a..b58087c24e3 100644 --- a/cluster/juju/layers/kubernetes-master/config.yaml +++ b/cluster/juju/layers/kubernetes-master/config.yaml @@ -26,3 +26,8 @@ options: default: "stable" description: | Snap channel to install Kubernetes master services from + client_password: + type: string + default: "" + description: | + Password to be used for admin user (leave empty for random password). diff --git a/cluster/juju/layers/kubernetes-master/reactive/kubernetes_master.py b/cluster/juju/layers/kubernetes-master/reactive/kubernetes_master.py index 387d2559720..6158c1c47db 100644 --- a/cluster/juju/layers/kubernetes-master/reactive/kubernetes_master.py +++ b/cluster/juju/layers/kubernetes-master/reactive/kubernetes_master.py @@ -37,7 +37,7 @@ 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.helpers import data_changed +from charms.reactive.helpers import data_changed, any_file_changed from charms.kubernetes.common import get_version from charms.kubernetes.common import retry from charms.kubernetes.flagmanager import FlagManager @@ -77,8 +77,8 @@ def reset_states_for_delivery(): '''An upgrade charm event was triggered by Juju, react to that here.''' migrate_from_pre_snaps() install_snaps() + set_state('reconfigure.authentication.setup') remove_state('authentication.setup') - remove_state('kubernetes-master.components.started') def rename_file_idempotent(source, destination): @@ -162,6 +162,22 @@ def channel_changed(): install_snaps() +@when('config.changed.client_password', 'leadership.is_leader') +def password_changed(): + """Handle password change via the charms config.""" + password = hookenv.config('client_password') + if password == "" and is_state('client.password.initialised'): + # password_changed is called during an upgrade. Nothing to do. + return + elif password == "": + # Password not initialised + password = token_generator() + setup_basic_auth(password, "admin", "admin") + set_state('reconfigure.authentication.setup') + remove_state('authentication.setup') + set_state('client.password.initialised') + + @when('cni.connected') @when_not('cni.configured') def configure_cni(cni): @@ -187,19 +203,23 @@ def setup_leader_authentication(): keys = [service_key, basic_auth, known_tokens] # Try first to fetch data from an old leadership broadcast. - if not get_keys_from_leader(keys): - if not os.path.isfile(basic_auth): - setup_basic_auth('admin', 'admin', 'admin') + if not get_keys_from_leader(keys) \ + or is_state('reconfigure.authentication.setup'): + last_pass = get_password('basic_auth.csv', 'admin') + setup_basic_auth(last_pass, 'admin', 'admin') + if not os.path.isfile(known_tokens): setup_tokens(None, 'admin', 'admin') setup_tokens(None, 'kubelet', 'kubelet') setup_tokens(None, 'kube_proxy', 'kube_proxy') + # Generate the default service account token key os.makedirs('/root/cdk', exist_ok=True) if not os.path.isfile(service_key): cmd = ['openssl', 'genrsa', '-out', service_key, '2048'] check_call(cmd) + remove_state('reconfigure.authentication.setup') api_opts.add('service-account-key-file', service_key) controller_opts.add('service-account-private-key-file', service_key) @@ -215,32 +235,36 @@ def setup_leader_authentication(): # eg: # {'/root/cdk/serviceaccount.key': 'RSA:2471731...'} charms.leadership.leader_set(leader_data) - + remove_state('kubernetes-master.components.started') set_state('authentication.setup') @when_not('leadership.is_leader') -@when_not('authentication.setup') def setup_non_leader_authentication(): - api_opts = FlagManager('kube-apiserver') - controller_opts = FlagManager('kube-controller-manager') service_key = '/root/cdk/serviceaccount.key' basic_auth = '/root/cdk/basic_auth.csv' known_tokens = '/root/cdk/known_tokens.csv' - hookenv.status_set('maintenance', 'Rendering authentication templates.') - keys = [service_key, basic_auth, known_tokens] if not get_keys_from_leader(keys): # the keys were not retrieved. Non-leaders have to retry. return + if not any_file_changed(keys) and is_state('authentication.setup'): + # No change detected and we have already setup the authentication + return + + hookenv.status_set('maintenance', 'Rendering authentication templates.') + api_opts = FlagManager('kube-apiserver') api_opts.add('basic-auth-file', basic_auth) api_opts.add('token-auth-file', known_tokens) api_opts.add('service-account-key-file', service_key) + + controller_opts = FlagManager('kube-controller-manager') controller_opts.add('service-account-private-key-file', service_key) + remove_state('kubernetes-master.components.started') set_state('authentication.setup') @@ -346,6 +370,22 @@ def send_cluster_dns_detail(kube_control): kube_control.set_dns(53, hookenv.config('dns_domain'), dns_ip) +@when('kube-control.auth.requested') +@when('authentication.setup') +@when('leadership.is_leader') +def send_tokens(kube_control): + """Send the tokens to the workers.""" + kubelet_token = get_token('kubelet') + proxy_token = get_token('kube_proxy') + admin_token = get_token('admin') + + # Send the data + requests = kube_control.auth_user() + for request in requests: + kube_control.sign_auth_request(request[0], kubelet_token, + proxy_token, admin_token) + + @when_not('kube-control.connected') def missing_kube_control(): """Inform the operator they need to add the kube-control relation. @@ -443,7 +483,7 @@ def addons_ready(): @when('loadbalancer.available', 'certificates.ca.available', - 'certificates.client.cert.available') + 'certificates.client.cert.available', 'authentication.setup') def loadbalancer_kubeconfig(loadbalancer, ca, client): # Get the potential list of loadbalancers from the relation object. hosts = loadbalancer.get_addresses_ports() @@ -455,7 +495,8 @@ def loadbalancer_kubeconfig(loadbalancer, ca, client): build_kubeconfig(server) -@when('certificates.ca.available', 'certificates.client.cert.available') +@when('certificates.ca.available', 'certificates.client.cert.available', + 'authentication.setup') @when_not('loadbalancer.available') def create_self_config(ca, client): '''Create a kubernetes configuration for the master unit.''' @@ -664,37 +705,54 @@ def build_kubeconfig(server): # Get all the paths to the tls information required for kubeconfig. ca = layer_options.get('ca_certificate_path') ca_exists = ca and os.path.isfile(ca) - key = layer_options.get('client_key_path') - key_exists = key and os.path.isfile(key) - cert = layer_options.get('client_certificate_path') - cert_exists = cert and os.path.isfile(cert) + client_pass = get_password('basic_auth.csv', 'admin') # Do we have everything we need? - if ca_exists and key_exists and cert_exists: - # Cache last server string to know if we need to regenerate the config. - if not data_changed('kubeconfig.server', server): - return + if ca_exists and client_pass: # Create an absolute path for the kubeconfig file. kubeconfig_path = os.path.join(os.sep, 'home', 'ubuntu', 'config') # Create the kubeconfig on this system so users can access the cluster. - create_kubeconfig(kubeconfig_path, server, ca, key, cert) + + create_kubeconfig(kubeconfig_path, server, ca, + user='admin', password=client_pass) # Make the config file readable by the ubuntu users so juju scp works. cmd = ['chown', 'ubuntu:ubuntu', kubeconfig_path] check_call(cmd) -def create_kubeconfig(kubeconfig, server, ca, key, certificate, user='ubuntu', - context='juju-context', cluster='juju-cluster'): +def create_kubeconfig(kubeconfig, server, ca, key=None, certificate=None, + user='ubuntu', context='juju-context', + cluster='juju-cluster', password=None, token=None): '''Create a configuration for Kubernetes based on path using the supplied arguments for values of the Kubernetes server, CA, key, certificate, user context and cluster.''' + if not key and not certificate and not password and not token: + raise ValueError('Missing authentication mechanism.') + + # token and password are mutually exclusive. Error early if both are + # present. The developer has requested an impossible situation. + # see: kubectl config set-credentials --help + if token and password: + raise ValueError('Token and Password are mutually exclusive.') # Create the config file with the address of the master server. cmd = 'kubectl config --kubeconfig={0} set-cluster {1} ' \ '--server={2} --certificate-authority={3} --embed-certs=true' check_call(split(cmd.format(kubeconfig, cluster, server, ca))) + # Delete old users + cmd = 'kubectl config --kubeconfig={0} unset users' + check_call(split(cmd.format(kubeconfig))) # Create the credentials using the client flags. - cmd = 'kubectl config --kubeconfig={0} set-credentials {1} ' \ - '--client-key={2} --client-certificate={3} --embed-certs=true' - check_call(split(cmd.format(kubeconfig, user, key, certificate))) + cmd = 'kubectl config --kubeconfig={0} ' \ + 'set-credentials {1} '.format(kubeconfig, user) + + if key and certificate: + cmd = '{0} --client-key={1} --client-certificate={2} '\ + '--embed-certs=true'.format(cmd, key, certificate) + if password: + cmd = "{0} --username={1} --password={2}".format(cmd, user, password) + # This is mutually exclusive from password. They will not work together. + if token: + cmd = "{0} --token={1}".format(cmd, token) + check_call(split(cmd)) # Create a default context with the cluster. cmd = 'kubectl config --kubeconfig={0} set-context {1} ' \ '--cluster={2} --user={3}' @@ -781,7 +839,6 @@ def configure_master_services(): api_opts.add('service-cluster-ip-range', service_cidr()) api_opts.add('min-request-timeout', '300') api_opts.add('v', '4') - api_opts.add('client-ca-file', ca_cert_path) api_opts.add('tls-cert-file', server_cert_path) api_opts.add('tls-private-key-file', server_key_path) api_opts.add('kubelet-certificate-authority', ca_cert_path) @@ -821,6 +878,7 @@ def configure_master_services(): cmd = ['snap', 'set', 'kube-apiserver'] + api_opts.to_s().split(' ') check_call(cmd) + cmd = ( ['snap', 'set', 'kube-controller-manager'] + controller_opts.to_s().split(' ') @@ -830,14 +888,16 @@ def configure_master_services(): check_call(cmd) -def setup_basic_auth(username='admin', password='admin', user='admin'): +def setup_basic_auth(password=None, username='admin', uid='admin'): '''Create the htacces file and the tokens.''' root_cdk = '/root/cdk' if not os.path.isdir(root_cdk): os.makedirs(root_cdk) htaccess = os.path.join(root_cdk, 'basic_auth.csv') + if not password: + password = token_generator() with open(htaccess, 'w') as stream: - stream.write('{0},{1},{2}'.format(username, password, user)) + stream.write('{0},{1},{2}'.format(password, username, uid)) def setup_tokens(token, username, user): @@ -847,12 +907,49 @@ def setup_tokens(token, username, user): os.makedirs(root_cdk) known_tokens = os.path.join(root_cdk, 'known_tokens.csv') if not token: - alpha = string.ascii_letters + string.digits - token = ''.join(random.SystemRandom().choice(alpha) for _ in range(32)) + token = token_generator() with open(known_tokens, 'a') as stream: stream.write('{0},{1},{2}\n'.format(token, username, user)) +def get_password(csv_fname, user): + '''Get the password of user within the csv file provided.''' + root_cdk = '/root/cdk' + if not os.path.isdir(root_cdk): + return None + tokens_fname = os.path.join(root_cdk, csv_fname) + with open(tokens_fname, 'r') as stream: + for line in stream: + record = line.split(',') + if record[1] == user: + return record[0] + return None + + +def get_token(username): + """Grab a token from the static file if present. """ + return get_password('known_tokens.csv', username) + + +def set_token(password, save_salt): + ''' Store a token so it can be recalled later by token_generator. + + param: password - the password to be stored + param: save_salt - the key to store the value of the token.''' + db = unitdata.kv() + db.set(save_salt, password) + return db.get(save_salt) + + +def token_generator(length=32): + ''' Generate a random token for use in passwords and account tokens. + + param: length - the length of the token to generate''' + alpha = string.ascii_letters + string.digits + token = ''.join(random.SystemRandom().choice(alpha) for _ in range(length)) + return token + + @retry(times=3, delay_secs=10) def all_kube_system_pods_running(): ''' Check pod status in the kube-system namespace. Returns True if all @@ -866,7 +963,6 @@ def all_kube_system_pods_running(): return False result = json.loads(output) - for pod in result['items']: status = pod['status']['phase'] if status != 'Running': diff --git a/cluster/juju/layers/kubernetes-worker/reactive/kubernetes_worker.py b/cluster/juju/layers/kubernetes-worker/reactive/kubernetes_worker.py index d42c9241a6c..0187fd4c806 100644 --- a/cluster/juju/layers/kubernetes-worker/reactive/kubernetes_worker.py +++ b/cluster/juju/layers/kubernetes-worker/reactive/kubernetes_worker.py @@ -303,9 +303,10 @@ def watch_for_changes(kube_api, kube_control, cni): @when('kubernetes-worker.snaps.installed', 'kube-api-endpoint.available', 'tls_client.ca.saved', 'tls_client.client.certificate.saved', 'tls_client.client.key.saved', 'tls_client.server.certificate.saved', - 'tls_client.server.key.saved', 'kube-control.dns.available', + 'tls_client.server.key.saved', + 'kube-control.dns.available', 'kube-control.auth.available', 'cni.available', 'kubernetes-worker.restart-needed') -def start_worker(kube_api, kube_control, cni): +def start_worker(kube_api, kube_control, auth_control, cni): ''' Start kubelet using the provided API and DNS info.''' servers = get_kube_api_servers(kube_api) # Note that the DNS server doesn't necessarily exist at this point. We know @@ -320,10 +321,13 @@ def start_worker(kube_api, kube_control, cni): hookenv.log('Waiting for cluster cidr.') return + creds = kube_control.get_auth_credentials() + data_changed('kube-control.creds', creds) + # set --allow-privileged flag for kubelet set_privileged() - create_config(random.choice(servers)) + create_config(random.choice(servers), creds) configure_worker_services(servers, dns, cluster_cidr) set_state('kubernetes-worker.config.created') restart_unit_services() @@ -428,27 +432,25 @@ def arch(): return architecture -def create_config(server): +def create_config(server, creds): '''Create a kubernetes configuration for the worker unit.''' # Get the options from the tls-client layer. layer_options = layer.options('tls-client') # Get all the paths to the tls information required for kubeconfig. ca = layer_options.get('ca_certificate_path') - key = layer_options.get('client_key_path') - cert = layer_options.get('client_certificate_path') # Create kubernetes configuration in the default location for ubuntu. - create_kubeconfig('/home/ubuntu/.kube/config', server, ca, key, cert, - user='ubuntu') + create_kubeconfig('/home/ubuntu/.kube/config', server, ca, + token=creds['client_token'], user='ubuntu') # Make the config dir readable by the ubuntu users so juju scp works. cmd = ['chown', '-R', 'ubuntu:ubuntu', '/home/ubuntu/.kube'] check_call(cmd) # Create kubernetes configuration in the default location for root. - create_kubeconfig('/root/.kube/config', server, ca, key, cert, - user='root') + create_kubeconfig('/root/.kube/config', server, ca, + token=creds['client_token'], user='root') # Create kubernetes configuration for kubelet, and kube-proxy services. - create_kubeconfig(kubeconfig_path, server, ca, key, cert, - user='kubelet') + create_kubeconfig(kubeconfig_path, server, ca, + token=creds['kubelet_token'], user='kubelet') def configure_worker_services(api_servers, dns, cluster_cidr): @@ -463,16 +465,15 @@ def configure_worker_services(api_servers, dns, cluster_cidr): kubelet_opts.add('require-kubeconfig', 'true') kubelet_opts.add('kubeconfig', kubeconfig_path) kubelet_opts.add('network-plugin', 'cni') - kubelet_opts.add('logtostderr', 'true') kubelet_opts.add('v', '0') kubelet_opts.add('address', '0.0.0.0') kubelet_opts.add('port', '10250') kubelet_opts.add('cluster-dns', dns['sdn-ip']) kubelet_opts.add('cluster-domain', dns['domain']) - kubelet_opts.add('anonymous-auth', 'false') kubelet_opts.add('client-ca-file', ca_cert_path) kubelet_opts.add('tls-cert-file', server_cert_path) kubelet_opts.add('tls-private-key-file', server_key_path) + kubelet_opts.add('logtostderr', 'true') kube_proxy_opts = FlagManager('kube-proxy') kube_proxy_opts.add('cluster-cidr', cluster_cidr) @@ -487,19 +488,40 @@ def configure_worker_services(api_servers, dns, cluster_cidr): check_call(cmd) -def create_kubeconfig(kubeconfig, server, ca, key, certificate, user='ubuntu', - context='juju-context', cluster='juju-cluster'): +def create_kubeconfig(kubeconfig, server, ca, key=None, certificate=None, + user='ubuntu', context='juju-context', + cluster='juju-cluster', password=None, token=None): '''Create a configuration for Kubernetes based on path using the supplied arguments for values of the Kubernetes server, CA, key, certificate, user context and cluster.''' + if not key and not certificate and not password and not token: + raise ValueError('Missing authentication mechanism.') + + # token and password are mutually exclusive. Error early if both are + # present. The developer has requested an impossible situation. + # see: kubectl config set-credentials --help + if token and password: + raise ValueError('Token and Password are mutually exclusive.') # Create the config file with the address of the master server. cmd = 'kubectl config --kubeconfig={0} set-cluster {1} ' \ '--server={2} --certificate-authority={3} --embed-certs=true' check_call(split(cmd.format(kubeconfig, cluster, server, ca))) + # Delete old users + cmd = 'kubectl config --kubeconfig={0} unset users' + check_call(split(cmd.format(kubeconfig))) # Create the credentials using the client flags. - cmd = 'kubectl config --kubeconfig={0} set-credentials {1} ' \ - '--client-key={2} --client-certificate={3} --embed-certs=true' - check_call(split(cmd.format(kubeconfig, user, key, certificate))) + cmd = 'kubectl config --kubeconfig={0} ' \ + 'set-credentials {1} '.format(kubeconfig, user) + + if key and certificate: + cmd = '{0} --client-key={1} --client-certificate={2} '\ + '--embed-certs=true'.format(cmd, key, certificate) + if password: + cmd = "{0} --username={1} --password={2}".format(cmd, user, password) + # This is mutually exclusive from password. They will not work together. + if token: + cmd = "{0} --token={1}".format(cmd, token) + check_call(split(cmd)) # Create a default context with the cluster. cmd = 'kubectl config --kubeconfig={0} set-context {1} ' \ '--cluster={2} --user={3}' @@ -761,6 +783,26 @@ def notify_master_gpu_not_enabled(kube_control): kube_control.set_gpu(False) +@when('kube-control.connected') +def request_kubelet_and_proxy_credentials(kube_control): + """ Request kubelet node authorization with a well formed kubelet user. + This also implies that we are requesting kube-proxy auth. """ + + # The kube-cotrol interface is created to support RBAC. + # At this point we might as well do the right thing and return the hostname + # even if it will only be used when we enable RBAC + nodeuser = 'system:node:{}'.format(gethostname()) + kube_control.set_auth_request(nodeuser) + + +@when('kube-control.auth.available') +def catch_change_in_creds(kube_control): + """Request a service restart in case credential updates were detected.""" + creds = kube_control.get_auth_credentials() + if data_changed('kube-control.creds', creds): + set_state('kubernetes-worker.restart-needed') + + @when_not('kube-control.connected') def missing_kube_control(): """Inform the operator they need to add the kube-control relation. From 3d48091ce80e7971cc3a30d00b9c63f1101d967d Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Thu, 25 May 2017 11:47:12 -0400 Subject: [PATCH 078/448] Fix ebtables_test.go to actually get run, and to pass --- pkg/util/ebtables/ebtables_test.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pkg/util/ebtables/ebtables_test.go b/pkg/util/ebtables/ebtables_test.go index 37d5b5ad654..91f6feeb652 100644 --- a/pkg/util/ebtables/ebtables_test.go +++ b/pkg/util/ebtables/ebtables_test.go @@ -23,7 +23,7 @@ import ( "k8s.io/kubernetes/pkg/util/exec" ) -func testEnsureChain(t *testing.T) { +func TestEnsureChain(t *testing.T) { fcmd := exec.FakeCmd{ CombinedOutputScript: []exec.FakeCombinedOutputAction{ // Does not Exists @@ -75,7 +75,7 @@ func testEnsureChain(t *testing.T) { } } -func testEnsureRule(t *testing.T) { +func TestEnsureRule(t *testing.T) { fcmd := exec.FakeCmd{ CombinedOutputScript: []exec.FakeCombinedOutputAction{ // Exists @@ -118,7 +118,7 @@ Bridge chain: TEST, entries: 0, policy: ACCEPT`), nil if exists { t.Errorf("expected exists = false") } - errStr := "Failed to ensure rule: exist 2, output: " + errStr := "Failed to ensure rule: exit 2, output: " if err == nil || err.Error() != errStr { t.Errorf("expected error: %q", errStr) } From 127eb53d4de1928251b9a00b4351fc789f877d7b Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Fri, 26 May 2017 14:43:24 -0400 Subject: [PATCH 079/448] Fix the names of some iptables tests The delete tests were copy+pasted from the create tests, and the names not fully updated to match. --- pkg/util/iptables/iptables_test.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pkg/util/iptables/iptables_test.go b/pkg/util/iptables/iptables_test.go index 824cede9127..c7b3fbb5981 100644 --- a/pkg/util/iptables/iptables_test.go +++ b/pkg/util/iptables/iptables_test.go @@ -333,7 +333,7 @@ func TestEnsureRuleErrorCreating(t *testing.T) { } } -func TestDeleteRuleAlreadyExists(t *testing.T) { +func TestDeleteRuleDoesNotExist(t *testing.T) { fcmd := exec.FakeCmd{ CombinedOutputScript: []exec.FakeCombinedOutputAction{ // iptables version check @@ -368,7 +368,7 @@ func TestDeleteRuleAlreadyExists(t *testing.T) { } } -func TestDeleteRuleNew(t *testing.T) { +func TestDeleteRuleExists(t *testing.T) { fcmd := exec.FakeCmd{ CombinedOutputScript: []exec.FakeCombinedOutputAction{ // iptables version check @@ -438,7 +438,7 @@ func TestDeleteRuleErrorChecking(t *testing.T) { } } -func TestDeleteRuleErrorCreating(t *testing.T) { +func TestDeleteRuleErrorDeleting(t *testing.T) { fcmd := exec.FakeCmd{ CombinedOutputScript: []exec.FakeCombinedOutputAction{ // iptables version check From d716557f4de529848f2de62b6a59d19af5bbebc4 Mon Sep 17 00:00:00 2001 From: Robert Pothier Date: Mon, 26 Jun 2017 14:51:45 -0400 Subject: [PATCH 080/448] Support IPv6 in kubenet_linux.go When running kubenet with IPv6, there is a panic as there is IPv4 specific code the Event function. With this change, Event will support IPv4 and IPv6 --- pkg/kubelet/network/kubenet/kubenet_linux.go | 2 +- .../network/kubenet/kubenet_linux_test.go | 70 +++++++++++++------ 2 files changed, 48 insertions(+), 24 deletions(-) diff --git a/pkg/kubelet/network/kubenet/kubenet_linux.go b/pkg/kubelet/network/kubenet/kubenet_linux.go index 55a769f71a0..92126513b0d 100644 --- a/pkg/kubelet/network/kubenet/kubenet_linux.go +++ b/pkg/kubelet/network/kubenet/kubenet_linux.go @@ -259,7 +259,7 @@ func (plugin *kubenetNetworkPlugin) Event(name string, details map[string]interf if err == nil { setHairpin := plugin.hairpinMode == componentconfig.HairpinVeth // Set bridge address to first address in IPNet - cidr.IP.To4()[3] += 1 + 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) diff --git a/pkg/kubelet/network/kubenet/kubenet_linux_test.go b/pkg/kubelet/network/kubenet/kubenet_linux_test.go index c3fad8ca3f2..02022f847bb 100644 --- a/pkg/kubelet/network/kubenet/kubenet_linux_test.go +++ b/pkg/kubelet/network/kubenet/kubenet_linux_test.go @@ -232,37 +232,61 @@ func TestGenerateMacAddress(t *testing.T) { // TestInvocationWithoutRuntime invokes the plugin without a runtime. // This is how kubenet is invoked from the cri. func TestTearDownWithoutRuntime(t *testing.T) { - fhost := nettest.NewFakeHost(nil) - fhost.Legacy = false - fhost.Runtime = nil - mockcni := &mock_cni.MockCNI{} - - fexec := &exec.FakeExec{ - CommandScript: []exec.FakeCommandAction{}, - LookPathFunc: func(file string) (string, error) { - return fmt.Sprintf("/fake-bin/%s", file), nil + testCases := []struct { + podCIDR string + ip string + expectedGateway string + }{ + { + podCIDR: "10.0.0.1/24", + ip: "10.0.0.1", + expectedGateway: "10.0.0.1", + }, + { + podCIDR: "2001:beef::1/48", + ip: "2001:beef::1", + expectedGateway: "2001:beef::1", }, } + for _, tc := range testCases { + fhost := nettest.NewFakeHost(nil) + fhost.Legacy = false + fhost.Runtime = nil + mockcni := &mock_cni.MockCNI{} - kubenet := newFakeKubenetPlugin(map[kubecontainer.ContainerID]string{}, fexec, fhost) - kubenet.cniConfig = mockcni - kubenet.iptables = ipttest.NewFake() + fexec := &exec.FakeExec{ + CommandScript: []exec.FakeCommandAction{}, + LookPathFunc: func(file string) (string, error) { + return fmt.Sprintf("/fake-bin/%s", file), nil + }, + } - details := make(map[string]interface{}) - details[network.NET_PLUGIN_EVENT_POD_CIDR_CHANGE_DETAIL_CIDR] = "10.0.0.1/24" - kubenet.Event(network.NET_PLUGIN_EVENT_POD_CIDR_CHANGE, details) + kubenet := newFakeKubenetPlugin(map[kubecontainer.ContainerID]string{}, fexec, fhost) + kubenet.cniConfig = mockcni + kubenet.iptables = ipttest.NewFake() - existingContainerID := kubecontainer.BuildContainerID("docker", "123") - kubenet.podIPs[existingContainerID] = "10.0.0.1" + details := make(map[string]interface{}) + details[network.NET_PLUGIN_EVENT_POD_CIDR_CHANGE_DETAIL_CIDR] = tc.podCIDR + kubenet.Event(network.NET_PLUGIN_EVENT_POD_CIDR_CHANGE, details) - mockcni.On("DelNetwork", mock.AnythingOfType("*libcni.NetworkConfig"), mock.AnythingOfType("*libcni.RuntimeConf")).Return(nil) + if kubenet.gateway.String() != tc.expectedGateway { + t.Errorf("generated gateway: %q, expecting: %q", kubenet.gateway.String(), tc.expectedGateway) + } + if kubenet.podCidr != tc.podCIDR { + t.Errorf("generated podCidr: %q, expecting: %q", kubenet.podCidr, tc.podCIDR) + } + existingContainerID := kubecontainer.BuildContainerID("docker", "123") + kubenet.podIPs[existingContainerID] = tc.ip - if err := kubenet.TearDownPod("namespace", "name", existingContainerID); err != nil { - t.Fatalf("Unexpected error in TearDownPod: %v", err) + mockcni.On("DelNetwork", mock.AnythingOfType("*libcni.NetworkConfig"), mock.AnythingOfType("*libcni.RuntimeConf")).Return(nil) + + if err := kubenet.TearDownPod("namespace", "name", existingContainerID); err != nil { + t.Fatalf("Unexpected error in TearDownPod: %v", err) + } + // Assert that the CNI DelNetwork made it through and we didn't crash + // without a runtime. + mockcni.AssertExpectations(t) } - // Assert that the CNI DelNetwork made it through and we didn't crash - // without a runtime. - mockcni.AssertExpectations(t) } //TODO: add unit test for each implementation of network plugin interface From 1e7384c99753d830b3886d1386a6ae3d9c3ac08f Mon Sep 17 00:00:00 2001 From: Kris Date: Tue, 27 Jun 2017 12:10:43 -0700 Subject: [PATCH 081/448] Adding a retry to the master version checking --- test/e2e/framework/BUILD | 1 + test/e2e/framework/upgrade_util.go | 12 ++++++++++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/test/e2e/framework/BUILD b/test/e2e/framework/BUILD index 4eddbf59951..e1b7222a209 100644 --- a/test/e2e/framework/BUILD +++ b/test/e2e/framework/BUILD @@ -128,6 +128,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/apimachinery/pkg/version: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/dynamic:go_default_library", diff --git a/test/e2e/framework/upgrade_util.go b/test/e2e/framework/upgrade_util.go index 8e5f4609e05..ae8a3c98d3a 100644 --- a/test/e2e/framework/upgrade_util.go +++ b/test/e2e/framework/upgrade_util.go @@ -20,7 +20,10 @@ import ( "fmt" "path" "strings" + "time" + "k8s.io/apimachinery/pkg/util/wait" + "k8s.io/apimachinery/pkg/version" "k8s.io/kubernetes/pkg/client/clientset_generated/clientset" ) @@ -38,8 +41,13 @@ func RealVersion(s string) (string, error) { func CheckMasterVersion(c clientset.Interface, want string) error { Logf("Checking master version") - v, err := c.Discovery().ServerVersion() - if err != nil { + var err error + var v *version.Info + waitErr := wait.PollImmediate(5*time.Second, 2*time.Minute, func() (bool, error) { + v, err = c.Discovery().ServerVersion() + return err != nil, nil + }) + if waitErr != nil { return fmt.Errorf("CheckMasterVersion() couldn't get the master version: %v", err) } // We do prefix trimming and then matching because: From bd38dd4d12b77126ba9c129b74b2b444f9f2a3a1 Mon Sep 17 00:00:00 2001 From: Antoine Pelisse Date: Tue, 27 Jun 2017 13:04:09 -0700 Subject: [PATCH 082/448] openapi: Read Accept-Content to send gzip if needed --- .../pkg/server/openapi/openapi_handler.go | 30 +++++++++++-------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/staging/src/k8s.io/apiserver/pkg/server/openapi/openapi_handler.go b/staging/src/k8s.io/apiserver/pkg/server/openapi/openapi_handler.go index 1ed6e9a3475..7280dde08d2 100644 --- a/staging/src/k8s.io/apiserver/pkg/server/openapi/openapi_handler.go +++ b/staging/src/k8s.io/apiserver/pkg/server/openapi/openapi_handler.go @@ -26,6 +26,7 @@ import ( "strings" "time" + "github.com/NYTimes/gziphandler" "github.com/go-openapi/spec" "github.com/golang/protobuf/proto" "github.com/googleapis/gnostic/OpenAPIv2" @@ -75,19 +76,22 @@ func RegisterOpenAPIService(openapiSpec *spec.Swagger, servePath string, mux *ge for _, file := range files { path := servePathBase + file.ext getData := file.getData - mux.HandleFunc(path, func(w http.ResponseWriter, r *http.Request) { - if r.URL.Path != path { - w.WriteHeader(http.StatusNotFound) - w.Write([]byte("Path not found!")) - return - } - o.update(r) - data := getData() - etag := computeEtag(data) - w.Header().Set("Etag", etag) - // ServeContent will take care of caching using eTag. - http.ServeContent(w, r, path, o.lastModified, bytes.NewReader(data)) - }) + mux.Handle(path, gziphandler.GzipHandler(http.HandlerFunc( + func(w http.ResponseWriter, r *http.Request) { + if r.URL.Path != path { + w.WriteHeader(http.StatusNotFound) + w.Write([]byte("Path not found!")) + return + } + o.update(r) + data := getData() + etag := computeEtag(data) + w.Header().Set("Etag", etag) + + // ServeContent will take care of caching using eTag. + http.ServeContent(w, r, path, o.lastModified, bytes.NewReader(data)) + }), + )) } return &o, nil From f617df7d6a63692ae8e0b2863f3b44f6ea02d355 Mon Sep 17 00:00:00 2001 From: Antoine Pelisse Date: Tue, 27 Jun 2017 13:04:36 -0700 Subject: [PATCH 083/448] Add NYTimes/gziphandler dependency --- Godeps/Godeps.json | 4 + Godeps/LICENSES | 21 ++ .../Godeps/Godeps.json | 4 + .../src/k8s.io/apiserver/Godeps/Godeps.json | 4 + .../k8s.io/apiserver/pkg/server/openapi/BUILD | 1 + .../k8s.io/kube-aggregator/Godeps/Godeps.json | 4 + .../sample-apiserver/Godeps/Godeps.json | 4 + vendor/BUILD | 1 + .../github.com/NYTimes/gziphandler/.gitignore | 1 + .../NYTimes/gziphandler/.travis.yml | 6 + vendor/github.com/NYTimes/gziphandler/BUILD | 30 ++ .../NYTimes/gziphandler/CODE_OF_CONDUCT.md | 75 ++++ .../NYTimes/gziphandler/CONTRIBUTING.md | 30 ++ .../github.com/NYTimes/gziphandler/LICENSE.md | 13 + .../github.com/NYTimes/gziphandler/README.md | 52 +++ vendor/github.com/NYTimes/gziphandler/gzip.go | 332 ++++++++++++++++++ .../NYTimes/gziphandler/gzip_go18.go | 43 +++ 17 files changed, 625 insertions(+) create mode 100644 vendor/github.com/NYTimes/gziphandler/.gitignore create mode 100644 vendor/github.com/NYTimes/gziphandler/.travis.yml create mode 100644 vendor/github.com/NYTimes/gziphandler/BUILD create mode 100644 vendor/github.com/NYTimes/gziphandler/CODE_OF_CONDUCT.md create mode 100644 vendor/github.com/NYTimes/gziphandler/CONTRIBUTING.md create mode 100644 vendor/github.com/NYTimes/gziphandler/LICENSE.md create mode 100644 vendor/github.com/NYTimes/gziphandler/README.md create mode 100644 vendor/github.com/NYTimes/gziphandler/gzip.go create mode 100644 vendor/github.com/NYTimes/gziphandler/gzip_go18.go diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json index 8238ba1ea3c..ee061560507 100644 --- a/Godeps/Godeps.json +++ b/Godeps/Godeps.json @@ -95,6 +95,10 @@ "Comment": "v0.4.2", "Rev": "f533f7a102197536779ea3a8cb881d639e21ec5a" }, + { + "ImportPath": "github.com/NYTimes/gziphandler", + "Rev": "56545f4a5d46df9a6648819d1664c3a03a13ffdb" + }, { "ImportPath": "github.com/PuerkitoBio/purell", "Comment": "v1.0.0", diff --git a/Godeps/LICENSES b/Godeps/LICENSES index 72a219de0c1..d42b969303d 100644 --- a/Godeps/LICENSES +++ b/Godeps/LICENSES @@ -64587,6 +64587,27 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ================================================================================ +================================================================================ += vendor/github.com/NYTimes/gziphandler licensed under: = + +Copyright (c) 2015 The New York Times Company + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this library except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT 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/NYTimes/gziphandler/LICENSE.md e30b94cbe70132b181f72f953fbb3c82 - +================================================================================ + + ================================================================================ = vendor/github.com/onsi/ginkgo licensed under: = diff --git a/staging/src/k8s.io/apiextensions-apiserver/Godeps/Godeps.json b/staging/src/k8s.io/apiextensions-apiserver/Godeps/Godeps.json index 709cfb456b8..94892d33e82 100644 --- a/staging/src/k8s.io/apiextensions-apiserver/Godeps/Godeps.json +++ b/staging/src/k8s.io/apiextensions-apiserver/Godeps/Godeps.json @@ -10,6 +10,10 @@ "ImportPath": "bitbucket.org/ww/goautoneg", "Rev": "75cd24fc2f2c2a2088577d12123ddee5f54e0675" }, + { + "ImportPath": "github.com/NYTimes/gziphandler", + "Rev": "56545f4a5d46df9a6648819d1664c3a03a13ffdb" + }, { "ImportPath": "github.com/PuerkitoBio/purell", "Rev": "8a290539e2e8629dbc4e6bad948158f790ec31f4" diff --git a/staging/src/k8s.io/apiserver/Godeps/Godeps.json b/staging/src/k8s.io/apiserver/Godeps/Godeps.json index a8ae808dbfd..a94b7452087 100644 --- a/staging/src/k8s.io/apiserver/Godeps/Godeps.json +++ b/staging/src/k8s.io/apiserver/Godeps/Godeps.json @@ -10,6 +10,10 @@ "ImportPath": "bitbucket.org/ww/goautoneg", "Rev": "75cd24fc2f2c2a2088577d12123ddee5f54e0675" }, + { + "ImportPath": "github.com/NYTimes/gziphandler", + "Rev": "56545f4a5d46df9a6648819d1664c3a03a13ffdb" + }, { "ImportPath": "github.com/PuerkitoBio/purell", "Rev": "8a290539e2e8629dbc4e6bad948158f790ec31f4" diff --git a/staging/src/k8s.io/apiserver/pkg/server/openapi/BUILD b/staging/src/k8s.io/apiserver/pkg/server/openapi/BUILD index 9c879babc28..eec3d062920 100644 --- a/staging/src/k8s.io/apiserver/pkg/server/openapi/BUILD +++ b/staging/src/k8s.io/apiserver/pkg/server/openapi/BUILD @@ -36,6 +36,7 @@ go_library( ], tags = ["automanaged"], deps = [ + "//vendor/github.com/NYTimes/gziphandler:go_default_library", "//vendor/github.com/emicklei/go-restful:go_default_library", "//vendor/github.com/go-openapi/spec:go_default_library", "//vendor/github.com/golang/protobuf/proto:go_default_library", diff --git a/staging/src/k8s.io/kube-aggregator/Godeps/Godeps.json b/staging/src/k8s.io/kube-aggregator/Godeps/Godeps.json index 06f49869cf0..acb3affee26 100644 --- a/staging/src/k8s.io/kube-aggregator/Godeps/Godeps.json +++ b/staging/src/k8s.io/kube-aggregator/Godeps/Godeps.json @@ -10,6 +10,10 @@ "ImportPath": "bitbucket.org/ww/goautoneg", "Rev": "75cd24fc2f2c2a2088577d12123ddee5f54e0675" }, + { + "ImportPath": "github.com/NYTimes/gziphandler", + "Rev": "56545f4a5d46df9a6648819d1664c3a03a13ffdb" + }, { "ImportPath": "github.com/PuerkitoBio/purell", "Rev": "8a290539e2e8629dbc4e6bad948158f790ec31f4" diff --git a/staging/src/k8s.io/sample-apiserver/Godeps/Godeps.json b/staging/src/k8s.io/sample-apiserver/Godeps/Godeps.json index b57cfc0326a..6ceccf7dedf 100644 --- a/staging/src/k8s.io/sample-apiserver/Godeps/Godeps.json +++ b/staging/src/k8s.io/sample-apiserver/Godeps/Godeps.json @@ -10,6 +10,10 @@ "ImportPath": "bitbucket.org/ww/goautoneg", "Rev": "75cd24fc2f2c2a2088577d12123ddee5f54e0675" }, + { + "ImportPath": "github.com/NYTimes/gziphandler", + "Rev": "56545f4a5d46df9a6648819d1664c3a03a13ffdb" + }, { "ImportPath": "github.com/PuerkitoBio/purell", "Rev": "8a290539e2e8629dbc4e6bad948158f790ec31f4" diff --git a/vendor/BUILD b/vendor/BUILD index 63adadb16e4..63323ae6722 100644 --- a/vendor/BUILD +++ b/vendor/BUILD @@ -26,6 +26,7 @@ filegroup( "//vendor/github.com/Azure/go-autorest/autorest:all-srcs", "//vendor/github.com/MakeNowJust/heredoc:all-srcs", "//vendor/github.com/Microsoft/go-winio:all-srcs", + "//vendor/github.com/NYTimes/gziphandler:all-srcs", "//vendor/github.com/PuerkitoBio/purell:all-srcs", "//vendor/github.com/PuerkitoBio/urlesc:all-srcs", "//vendor/github.com/Sirupsen/logrus:all-srcs", diff --git a/vendor/github.com/NYTimes/gziphandler/.gitignore b/vendor/github.com/NYTimes/gziphandler/.gitignore new file mode 100644 index 00000000000..1377554ebea --- /dev/null +++ b/vendor/github.com/NYTimes/gziphandler/.gitignore @@ -0,0 +1 @@ +*.swp diff --git a/vendor/github.com/NYTimes/gziphandler/.travis.yml b/vendor/github.com/NYTimes/gziphandler/.travis.yml new file mode 100644 index 00000000000..d2b67f69c1c --- /dev/null +++ b/vendor/github.com/NYTimes/gziphandler/.travis.yml @@ -0,0 +1,6 @@ +language: go + +go: + - 1.7 + - 1.8 + - tip diff --git a/vendor/github.com/NYTimes/gziphandler/BUILD b/vendor/github.com/NYTimes/gziphandler/BUILD new file mode 100644 index 00000000000..68761bbfd8f --- /dev/null +++ b/vendor/github.com/NYTimes/gziphandler/BUILD @@ -0,0 +1,30 @@ +package(default_visibility = ["//visibility:public"]) + +licenses(["notice"]) + +load( + "@io_bazel_rules_go//go:def.bzl", + "go_library", +) + +go_library( + name = "go_default_library", + srcs = [ + "gzip.go", + "gzip_go18.go", + ], + tags = ["automanaged"], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], +) diff --git a/vendor/github.com/NYTimes/gziphandler/CODE_OF_CONDUCT.md b/vendor/github.com/NYTimes/gziphandler/CODE_OF_CONDUCT.md new file mode 100644 index 00000000000..cdbca194c34 --- /dev/null +++ b/vendor/github.com/NYTimes/gziphandler/CODE_OF_CONDUCT.md @@ -0,0 +1,75 @@ +--- +layout: code-of-conduct +version: v1.0 +--- + +This code of conduct outlines our expectations for participants within the **NYTimes/gziphandler** community, as well as steps to reporting unacceptable behavior. We are committed to providing a welcoming and inspiring community for all and expect our code of conduct to be honored. Anyone who violates this code of conduct may be banned from the community. + +Our open source community strives to: + +* **Be friendly and patient.** +* **Be welcoming**: We strive to be a community that welcomes and supports people of all backgrounds and identities. This includes, but is not limited to members of any race, ethnicity, culture, national origin, colour, immigration status, social and economic class, educational level, sex, sexual orientation, gender identity and expression, age, size, family status, political belief, religion, and mental and physical ability. +* **Be considerate**: Your work will be used by other people, and you in turn will depend on the work of others. Any decision you take will affect users and colleagues, and you should take those consequences into account when making decisions. Remember that we're a world-wide community, so you might not be communicating in someone else's primary language. +* **Be respectful**: Not all of us will agree all the time, but disagreement is no excuse for poor behavior and poor manners. We might all experience some frustration now and then, but we cannot allow that frustration to turn into a personal attack. It’s important to remember that a community where people feel uncomfortable or threatened is not a productive one. +* **Be careful in the words that we choose**: we are a community of professionals, and we conduct ourselves professionally. Be kind to others. Do not insult or put down other participants. Harassment and other exclusionary behavior aren't acceptable. +* **Try to understand why we disagree**: Disagreements, both social and technical, happen all the time. It is important that we resolve disagreements and differing views constructively. Remember that we’re different. The strength of our community comes from its diversity, people from a wide range of backgrounds. Different people have different perspectives on issues. Being unable to understand why someone holds a viewpoint doesn’t mean that they’re wrong. Don’t forget that it is human to err and blaming each other doesn’t get us anywhere. Instead, focus on helping to resolve issues and learning from mistakes. + +## Definitions + +Harassment includes, but is not limited to: + +- Offensive comments related to gender, gender identity and expression, sexual orientation, disability, mental illness, neuro(a)typicality, physical appearance, body size, race, age, regional discrimination, political or religious affiliation +- Unwelcome comments regarding a person’s lifestyle choices and practices, including those related to food, health, parenting, drugs, and employment +- Deliberate misgendering. This includes deadnaming or persistently using a pronoun that does not correctly reflect a person's gender identity. You must address people by the name they give you when not addressing them by their username or handle +- Physical contact and simulated physical contact (eg, textual descriptions like “*hug*” or “*backrub*”) without consent or after a request to stop +- Threats of violence, both physical and psychological +- Incitement of violence towards any individual, including encouraging a person to commit suicide or to engage in self-harm +- Deliberate intimidation +- Stalking or following +- Harassing photography or recording, including logging online activity for harassment purposes +- Sustained disruption of discussion +- Unwelcome sexual attention, including gratuitous or off-topic sexual images or behaviour +- Pattern of inappropriate social contact, such as requesting/assuming inappropriate levels of intimacy with others +- Continued one-on-one communication after requests to cease +- Deliberate “outing” of any aspect of a person’s identity without their consent except as necessary to protect others from intentional abuse +- Publication of non-harassing private communication + +Our open source community prioritizes marginalized people’s safety over privileged people’s comfort. We will not act on complaints regarding: + +- ‘Reverse’ -isms, including ‘reverse racism,’ ‘reverse sexism,’ and ‘cisphobia’ +- Reasonable communication of boundaries, such as “leave me alone,” “go away,” or “I’m not discussing this with you” +- Refusal to explain or debate social justice concepts +- Communicating in a ‘tone’ you don’t find congenial +- Criticizing racist, sexist, cissexist, or otherwise oppressive behavior or assumptions + + +### Diversity Statement + +We encourage everyone to participate and are committed to building a community for all. Although we will fail at times, we seek to treat everyone both as fairly and equally as possible. Whenever a participant has made a mistake, we expect them to take responsibility for it. If someone has been harmed or offended, it is our responsibility to listen carefully and respectfully, and do our best to right the wrong. + +Although this list cannot be exhaustive, we explicitly honor diversity in age, gender, gender identity or expression, culture, ethnicity, language, national origin, political beliefs, profession, race, religion, sexual orientation, socioeconomic status, and technical ability. We will not tolerate discrimination based on any of the protected +characteristics above, including participants with disabilities. + +### Reporting Issues + +If you experience or witness unacceptable behavior—or have any other concerns—please report it by contacting us via **code@nytimes.com**. All reports will be handled with discretion. In your report please include: + +- Your contact information. +- Names (real, nicknames, or pseudonyms) of any individuals involved. If there are additional witnesses, please +include them as well. Your account of what occurred, and if you believe the incident is ongoing. If there is a publicly available record (e.g. a mailing list archive or a public IRC logger), please include a link. +- Any additional information that may be helpful. + +After filing a report, a representative will contact you personally, review the incident, follow up with any additional questions, and make a decision as to how to respond. If the person who is harassing you is part of the response team, they will recuse themselves from handling your incident. If the complaint originates from a member of the response team, it will be handled by a different member of the response team. We will respect confidentiality requests for the purpose of protecting victims of abuse. + +### Attribution & Acknowledgements + +We all stand on the shoulders of giants across many open source communities. We'd like to thank the communities and projects that established code of conducts and diversity statements as our inspiration: + +* [Django](https://www.djangoproject.com/conduct/reporting/) +* [Python](https://www.python.org/community/diversity/) +* [Ubuntu](http://www.ubuntu.com/about/about-ubuntu/conduct) +* [Contributor Covenant](http://contributor-covenant.org/) +* [Geek Feminism](http://geekfeminism.org/about/code-of-conduct/) +* [Citizen Code of Conduct](http://citizencodeofconduct.org/) + +This Code of Conduct was based on https://github.com/todogroup/opencodeofconduct diff --git a/vendor/github.com/NYTimes/gziphandler/CONTRIBUTING.md b/vendor/github.com/NYTimes/gziphandler/CONTRIBUTING.md new file mode 100644 index 00000000000..b89a9eb4fb2 --- /dev/null +++ b/vendor/github.com/NYTimes/gziphandler/CONTRIBUTING.md @@ -0,0 +1,30 @@ +# Contributing to NYTimes/gziphandler + +This is an open source project started by handful of developers at The New York Times and open to the entire Go community. + +We really appreciate your help! + +## Filing issues + +When filing an issue, make sure to answer these five questions: + +1. What version of Go are you using (`go version`)? +2. What operating system and processor architecture are you using? +3. What did you do? +4. What did you expect to see? +5. What did you see instead? + +## Contributing code + +Before submitting changes, please follow these guidelines: + +1. Check the open issues and pull requests for existing discussions. +2. Open an issue to discuss a new feature. +3. Write tests. +4. Make sure code follows the ['Go Code Review Comments'](https://github.com/golang/go/wiki/CodeReviewComments). +5. Make sure your changes pass `go test`. +6. Make sure the entire test suite passes locally and on Travis CI. +7. Open a Pull Request. +8. [Squash your commits](http://gitready.com/advanced/2009/02/10/squashing-commits-with-rebase.html) after receiving feedback and add a [great commit message](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html). + +Unless otherwise noted, the gziphandler source files are distributed under the Apache 2.0-style license found in the LICENSE.md file. diff --git a/vendor/github.com/NYTimes/gziphandler/LICENSE.md b/vendor/github.com/NYTimes/gziphandler/LICENSE.md new file mode 100644 index 00000000000..b7e2ecb63f9 --- /dev/null +++ b/vendor/github.com/NYTimes/gziphandler/LICENSE.md @@ -0,0 +1,13 @@ +Copyright (c) 2015 The New York Times Company + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this library except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT 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/NYTimes/gziphandler/README.md b/vendor/github.com/NYTimes/gziphandler/README.md new file mode 100644 index 00000000000..6d724607072 --- /dev/null +++ b/vendor/github.com/NYTimes/gziphandler/README.md @@ -0,0 +1,52 @@ +Gzip Handler +============ + +This is a tiny Go package which wraps HTTP handlers to transparently gzip the +response body, for clients which support it. Although it's usually simpler to +leave that to a reverse proxy (like nginx or Varnish), this package is useful +when that's undesirable. + + +## Usage + +Call `GzipHandler` with any handler (an object which implements the +`http.Handler` interface), and it'll return a new handler which gzips the +response. For example: + +```go +package main + +import ( + "io" + "net/http" + "github.com/NYTimes/gziphandler" +) + +func main() { + withoutGz := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "text/plain") + io.WriteString(w, "Hello, World") + }) + + withGz := gziphandler.GzipHandler(withoutGz) + + http.Handle("/", withGz) + http.ListenAndServe("0.0.0.0:8000", nil) +} +``` + + +## Documentation + +The docs can be found at [godoc.org][docs], as usual. + + +## License + +[Apache 2.0][license]. + + + + +[docs]: https://godoc.org/github.com/nytimes/gziphandler +[license]: https://github.com/nytimes/gziphandler/blob/master/LICENSE.md diff --git a/vendor/github.com/NYTimes/gziphandler/gzip.go b/vendor/github.com/NYTimes/gziphandler/gzip.go new file mode 100644 index 00000000000..ea6dba1e79d --- /dev/null +++ b/vendor/github.com/NYTimes/gziphandler/gzip.go @@ -0,0 +1,332 @@ +package gziphandler + +import ( + "bufio" + "compress/gzip" + "fmt" + "io" + "net" + "net/http" + "strconv" + "strings" + "sync" +) + +const ( + vary = "Vary" + acceptEncoding = "Accept-Encoding" + contentEncoding = "Content-Encoding" + contentType = "Content-Type" + contentLength = "Content-Length" +) + +type codings map[string]float64 + +const ( + // DefaultQValue is the default qvalue to assign to an encoding if no explicit qvalue is set. + // This is actually kind of ambiguous in RFC 2616, so hopefully it's correct. + // The examples seem to indicate that it is. + DefaultQValue = 1.0 + + // DefaultMinSize defines the minimum size to reach to enable compression. + // It's 512 bytes. + DefaultMinSize = 512 +) + +// gzipWriterPools stores a sync.Pool for each compression level for reuse of +// gzip.Writers. Use poolIndex to covert a compression level to an index into +// gzipWriterPools. +var gzipWriterPools [gzip.BestCompression - gzip.BestSpeed + 2]*sync.Pool + +func init() { + for i := gzip.BestSpeed; i <= gzip.BestCompression; i++ { + addLevelPool(i) + } + addLevelPool(gzip.DefaultCompression) +} + +// poolIndex maps a compression level to its index into gzipWriterPools. It +// assumes that level is a valid gzip compression level. +func poolIndex(level int) int { + // gzip.DefaultCompression == -1, so we need to treat it special. + if level == gzip.DefaultCompression { + return gzip.BestCompression - gzip.BestSpeed + 1 + } + return level - gzip.BestSpeed +} + +func addLevelPool(level int) { + gzipWriterPools[poolIndex(level)] = &sync.Pool{ + New: func() interface{} { + // NewWriterLevel only returns error on a bad level, we are guaranteeing + // that this will be a valid level so it is okay to ignore the returned + // error. + w, _ := gzip.NewWriterLevel(nil, level) + return w + }, + } +} + +// GzipResponseWriter provides an http.ResponseWriter interface, which gzips +// bytes before writing them to the underlying response. This doesn't close the +// writers, so don't forget to do that. +// It can be configured to skip response smaller than minSize. +type GzipResponseWriter struct { + http.ResponseWriter + index int // Index for gzipWriterPools. + gw *gzip.Writer + + code int // Saves the WriteHeader value. + + minSize int // Specifed the minimum response size to gzip. If the response length is bigger than this value, it is compressed. + buf []byte // Holds the first part of the write before reaching the minSize or the end of the write. +} + +// Write appends data to the gzip writer. +func (w *GzipResponseWriter) Write(b []byte) (int, error) { + // If content type is not set. + if _, ok := w.Header()[contentType]; !ok { + // It infer it from the uncompressed body. + w.Header().Set(contentType, http.DetectContentType(b)) + } + + // GZIP responseWriter is initialized. Use the GZIP responseWriter. + if w.gw != nil { + n, err := w.gw.Write(b) + return n, err + } + + // Save the write into a buffer for later use in GZIP responseWriter (if content is long enough) or at close with regular responseWriter. + // On the first write, w.buf changes from nil to a valid slice + w.buf = append(w.buf, b...) + + // If the global writes are bigger than the minSize, compression is enable. + if len(w.buf) >= w.minSize { + err := w.startGzip() + if err != nil { + return 0, err + } + } + + return len(b), nil +} + +// startGzip initialize any GZIP specific informations. +func (w *GzipResponseWriter) startGzip() error { + + // Set the GZIP header. + w.Header().Set(contentEncoding, "gzip") + + // if the Content-Length is already set, then calls to Write on gzip + // will fail to set the Content-Length header since its already set + // See: https://github.com/golang/go/issues/14975. + w.Header().Del(contentLength) + + // Write the header to gzip response. + if w.code != 0 { + w.ResponseWriter.WriteHeader(w.code) + } + + // Initialize the GZIP response. + w.init() + + // Flush the buffer into the gzip reponse. + n, err := w.gw.Write(w.buf) + + // This should never happen (per io.Writer docs), but if the write didn't + // accept the entire buffer but returned no specific error, we have no clue + // what's going on, so abort just to be safe. + if err == nil && n < len(w.buf) { + return io.ErrShortWrite + } + + w.buf = nil + return err +} + +// WriteHeader just saves the response code until close or GZIP effective writes. +func (w *GzipResponseWriter) WriteHeader(code int) { + w.code = code +} + +// init graps a new gzip writer from the gzipWriterPool and writes the correct +// content encoding header. +func (w *GzipResponseWriter) init() { + // Bytes written during ServeHTTP are redirected to this gzip writer + // before being written to the underlying response. + gzw := gzipWriterPools[w.index].Get().(*gzip.Writer) + gzw.Reset(w.ResponseWriter) + w.gw = gzw +} + +// Close will close the gzip.Writer and will put it back in the gzipWriterPool. +func (w *GzipResponseWriter) Close() error { + if w.gw == nil { + // Gzip not trigged yet, write out regular response. + if w.code != 0 { + w.ResponseWriter.WriteHeader(w.code) + } + if w.buf != nil { + _, writeErr := w.ResponseWriter.Write(w.buf) + // Returns the error if any at write. + if writeErr != nil { + return fmt.Errorf("gziphandler: write to regular responseWriter at close gets error: %q", writeErr.Error()) + } + } + return nil + } + + err := w.gw.Close() + gzipWriterPools[w.index].Put(w.gw) + w.gw = nil + return err +} + +// Flush flushes the underlying *gzip.Writer and then the underlying +// http.ResponseWriter if it is an http.Flusher. This makes GzipResponseWriter +// an http.Flusher. +func (w *GzipResponseWriter) Flush() { + if w.gw != nil { + w.gw.Flush() + } + + if fw, ok := w.ResponseWriter.(http.Flusher); ok { + fw.Flush() + } +} + +// Hijack implements http.Hijacker. If the underlying ResponseWriter is a +// Hijacker, its Hijack method is returned. Otherwise an error is returned. +func (w *GzipResponseWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) { + if hj, ok := w.ResponseWriter.(http.Hijacker); ok { + return hj.Hijack() + } + return nil, nil, fmt.Errorf("http.Hijacker interface is not supported") +} + +// verify Hijacker interface implementation +var _ http.Hijacker = &GzipResponseWriter{} + +// MustNewGzipLevelHandler behaves just like NewGzipLevelHandler except that in +// an error case it panics rather than returning an error. +func MustNewGzipLevelHandler(level int) func(http.Handler) http.Handler { + wrap, err := NewGzipLevelHandler(level) + if err != nil { + panic(err) + } + return wrap +} + +// NewGzipLevelHandler returns a wrapper function (often known as middleware) +// which can be used to wrap an HTTP handler to transparently gzip the response +// body if the client supports it (via the Accept-Encoding header). Responses will +// be encoded at the given gzip compression level. An error will be returned only +// if an invalid gzip compression level is given, so if one can ensure the level +// is valid, the returned error can be safely ignored. +func NewGzipLevelHandler(level int) (func(http.Handler) http.Handler, error) { + return NewGzipLevelAndMinSize(level, DefaultMinSize) +} + +// NewGzipLevelAndMinSize behave as NewGzipLevelHandler except it let the caller +// specify the minimum size before compression. +func NewGzipLevelAndMinSize(level, minSize int) (func(http.Handler) http.Handler, error) { + if level != gzip.DefaultCompression && (level < gzip.BestSpeed || level > gzip.BestCompression) { + return nil, fmt.Errorf("invalid compression level requested: %d", level) + } + if minSize < 0 { + return nil, fmt.Errorf("minimum size must be more than zero") + } + return func(h http.Handler) http.Handler { + index := poolIndex(level) + + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Header().Add(vary, acceptEncoding) + + if acceptsGzip(r) { + gw := &GzipResponseWriter{ + ResponseWriter: w, + index: index, + minSize: minSize, + } + defer gw.Close() + + h.ServeHTTP(gw, r) + } else { + h.ServeHTTP(w, r) + } + }) + }, nil +} + +// GzipHandler wraps an HTTP handler, to transparently gzip the response body if +// the client supports it (via the Accept-Encoding header). This will compress at +// the default compression level. +func GzipHandler(h http.Handler) http.Handler { + wrapper, _ := NewGzipLevelHandler(gzip.DefaultCompression) + return wrapper(h) +} + +// acceptsGzip returns true if the given HTTP request indicates that it will +// accept a gzipped response. +func acceptsGzip(r *http.Request) bool { + acceptedEncodings, _ := parseEncodings(r.Header.Get(acceptEncoding)) + return acceptedEncodings["gzip"] > 0.0 +} + +// parseEncodings attempts to parse a list of codings, per RFC 2616, as might +// appear in an Accept-Encoding header. It returns a map of content-codings to +// quality values, and an error containing the errors encountered. It's probably +// safe to ignore those, because silently ignoring errors is how the internet +// works. +// +// See: http://tools.ietf.org/html/rfc2616#section-14.3. +func parseEncodings(s string) (codings, error) { + c := make(codings) + var e []string + + for _, ss := range strings.Split(s, ",") { + coding, qvalue, err := parseCoding(ss) + + if err != nil { + e = append(e, err.Error()) + } else { + c[coding] = qvalue + } + } + + // TODO (adammck): Use a proper multi-error struct, so the individual errors + // can be extracted if anyone cares. + if len(e) > 0 { + return c, fmt.Errorf("errors while parsing encodings: %s", strings.Join(e, ", ")) + } + + return c, nil +} + +// parseCoding parses a single conding (content-coding with an optional qvalue), +// as might appear in an Accept-Encoding header. It attempts to forgive minor +// formatting errors. +func parseCoding(s string) (coding string, qvalue float64, err error) { + for n, part := range strings.Split(s, ";") { + part = strings.TrimSpace(part) + qvalue = DefaultQValue + + if n == 0 { + coding = strings.ToLower(part) + } else if strings.HasPrefix(part, "q=") { + qvalue, err = strconv.ParseFloat(strings.TrimPrefix(part, "q="), 64) + + if qvalue < 0.0 { + qvalue = 0.0 + } else if qvalue > 1.0 { + qvalue = 1.0 + } + } + } + + if coding == "" { + err = fmt.Errorf("empty content-coding") + } + + return +} diff --git a/vendor/github.com/NYTimes/gziphandler/gzip_go18.go b/vendor/github.com/NYTimes/gziphandler/gzip_go18.go new file mode 100644 index 00000000000..fa9665b7e80 --- /dev/null +++ b/vendor/github.com/NYTimes/gziphandler/gzip_go18.go @@ -0,0 +1,43 @@ +// +build go1.8 + +package gziphandler + +import "net/http" + +// Push initiates an HTTP/2 server push. +// Push returns ErrNotSupported if the client has disabled push or if push +// is not supported on the underlying connection. +func (w *GzipResponseWriter) Push(target string, opts *http.PushOptions) error { + pusher, ok := w.ResponseWriter.(http.Pusher) + if ok && pusher != nil { + return pusher.Push(target, setAcceptEncodingForPushOptions(opts)) + } + return http.ErrNotSupported +} + +// setAcceptEncodingForPushOptions sets "Accept-Encoding" : "gzip" for PushOptions without overriding existing headers. +func setAcceptEncodingForPushOptions(opts *http.PushOptions) *http.PushOptions { + + if opts == nil { + opts = &http.PushOptions{ + Header: http.Header{ + acceptEncoding: []string{"gzip"}, + }, + } + return opts + } + + if opts.Header == nil { + opts.Header = http.Header{ + acceptEncoding: []string{"gzip"}, + } + return opts + } + + if encoding := opts.Header.Get(acceptEncoding); encoding == "" { + opts.Header.Add(acceptEncoding, "gzip") + return opts + } + + return opts +} From 903bc643b127f4407732309b424de15a0275b70e Mon Sep 17 00:00:00 2001 From: Zach Loafman Date: Tue, 27 Jun 2017 16:14:55 -0700 Subject: [PATCH 084/448] Bump GCE ContainerVM to container-vm-v20170627 Remove the built-in kubelet (finally), pick up security fixes. --- cluster/gce/config-default.sh | 2 +- cluster/gce/config-test.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cluster/gce/config-default.sh b/cluster/gce/config-default.sh index 533c91cba55..e4510e5a8e6 100755 --- a/cluster/gce/config-default.sh +++ b/cluster/gce/config-default.sh @@ -67,7 +67,7 @@ fi # containervm. If you are updating the containervm version, 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-v20170214} +CVM_VERSION=${CVM_VERSION:-container-vm-v20170627} GCI_VERSION=${KUBE_GCI_VERSION:-cos-stable-59-9460-64-0} MASTER_IMAGE=${KUBE_GCE_MASTER_IMAGE:-} MASTER_IMAGE_PROJECT=${KUBE_GCE_MASTER_PROJECT:-cos-cloud} diff --git a/cluster/gce/config-test.sh b/cluster/gce/config-test.sh index 79a37c6fca6..6aa2533c831 100755 --- a/cluster/gce/config-test.sh +++ b/cluster/gce/config-test.sh @@ -66,7 +66,7 @@ fi # containervm. If you are updating the containervm version, 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-v20170214} +CVM_VERSION=${CVM_VERSION:-container-vm-v20170627} GCI_VERSION=${KUBE_GCI_VERSION:-cos-stable-59-9460-64-0} MASTER_IMAGE=${KUBE_GCE_MASTER_IMAGE:-} MASTER_IMAGE_PROJECT=${KUBE_GCE_MASTER_PROJECT:-cos-cloud} From 6fd36c10adf35c015d4fcabb95c52e83e4fd46d1 Mon Sep 17 00:00:00 2001 From: Alexander Campbell Date: Wed, 14 Jun 2017 14:14:42 -0700 Subject: [PATCH 085/448] kubectl/cmd: many small refactors * Rename variables and functions to match Go convention. For example, UsageError --> UsageErrorf. * Remove redundant or unreachable code. * Simplify some utility functions (no functionality changes). * Fix hanging 'if { return } else { return }' constructs. * Fix several incorrect printf verbs. --- pkg/kubectl/cmd/annotate.go | 6 +-- pkg/kubectl/cmd/apply.go | 2 +- pkg/kubectl/cmd/apply_set_last_applied.go | 2 +- pkg/kubectl/cmd/apply_test.go | 2 +- pkg/kubectl/cmd/apply_view_last_applied.go | 2 +- pkg/kubectl/cmd/attach.go | 13 ++++--- pkg/kubectl/cmd/autoscale.go | 2 +- pkg/kubectl/cmd/certificates.go | 2 +- pkg/kubectl/cmd/clusterinfo_dump.go | 2 +- pkg/kubectl/cmd/completion.go | 6 +-- pkg/kubectl/cmd/config/rename_context.go | 2 +- pkg/kubectl/cmd/convert.go | 2 +- pkg/kubectl/cmd/cp.go | 14 ++++--- pkg/kubectl/cmd/create.go | 9 ++--- pkg/kubectl/cmd/create_secret.go | 4 +- pkg/kubectl/cmd/create_service.go | 2 +- pkg/kubectl/cmd/delete.go | 2 +- pkg/kubectl/cmd/describe.go | 4 +- pkg/kubectl/cmd/drain.go | 2 +- pkg/kubectl/cmd/exec.go | 6 +-- pkg/kubectl/cmd/explain.go | 4 +- pkg/kubectl/cmd/expose.go | 13 +++---- pkg/kubectl/cmd/get.go | 12 +++--- pkg/kubectl/cmd/label.go | 6 +-- pkg/kubectl/cmd/logs.go | 10 ++--- pkg/kubectl/cmd/patch.go | 5 ++- pkg/kubectl/cmd/portforward.go | 4 +- pkg/kubectl/cmd/replace.go | 4 +- pkg/kubectl/cmd/rollingupdate.go | 30 +++++++-------- pkg/kubectl/cmd/rollout/rollout_history.go | 4 +- pkg/kubectl/cmd/rollout/rollout_pause.go | 4 +- pkg/kubectl/cmd/rollout/rollout_resume.go | 4 +- pkg/kubectl/cmd/rollout/rollout_status.go | 4 +- pkg/kubectl/cmd/rollout/rollout_undo.go | 4 +- pkg/kubectl/cmd/run.go | 25 ++++++------- pkg/kubectl/cmd/run_test.go | 9 ++--- pkg/kubectl/cmd/scale.go | 4 +- pkg/kubectl/cmd/set/set_image.go | 2 +- pkg/kubectl/cmd/set/set_selector.go | 2 +- pkg/kubectl/cmd/taint.go | 4 +- pkg/kubectl/cmd/top_node.go | 4 +- pkg/kubectl/cmd/top_pod.go | 4 +- pkg/kubectl/cmd/util/helpers.go | 43 ++++++++++------------ pkg/kubectl/cmd/util/helpers_test.go | 2 +- pkg/kubectl/cmd/util/printing.go | 2 +- pkg/kubectl/cmd/version.go | 8 +--- 46 files changed, 148 insertions(+), 155 deletions(-) diff --git a/pkg/kubectl/cmd/annotate.go b/pkg/kubectl/cmd/annotate.go index ed36be72385..e60c0ed4584 100644 --- a/pkg/kubectl/cmd/annotate.go +++ b/pkg/kubectl/cmd/annotate.go @@ -117,10 +117,10 @@ func NewCmdAnnotate(f cmdutil.Factory, out io.Writer) *cobra.Command { Example: annotateExample, Run: func(cmd *cobra.Command, args []string) { if err := options.Complete(out, cmd, args); err != nil { - cmdutil.CheckErr(cmdutil.UsageError(cmd, err.Error())) + cmdutil.CheckErr(cmdutil.UsageErrorf(cmd, "%v", err)) } if err := options.Validate(); err != nil { - cmdutil.CheckErr(cmdutil.UsageError(cmd, err.Error())) + cmdutil.CheckErr(cmdutil.UsageErrorf(cmd, "%v", err)) } cmdutil.CheckErr(options.RunAnnotate(f, cmd)) }, @@ -167,7 +167,7 @@ func (o *AnnotateOptions) Complete(out io.Writer, cmd *cobra.Command, args []str // Validate checks to the AnnotateOptions to see if there is sufficient information run the command. func (o AnnotateOptions) Validate() error { - if len(o.resources) < 1 && cmdutil.IsFilenameEmpty(o.Filenames) { + if len(o.resources) < 1 && cmdutil.IsFilenameSliceEmpty(o.Filenames) { return fmt.Errorf("one or more resources must be specified as or /") } if len(o.newAnnotations) < 1 && len(o.removeAnnotations) < 1 { diff --git a/pkg/kubectl/cmd/apply.go b/pkg/kubectl/cmd/apply.go index 7618a0368d3..669f5f1e138 100644 --- a/pkg/kubectl/cmd/apply.go +++ b/pkg/kubectl/cmd/apply.go @@ -137,7 +137,7 @@ func NewCmdApply(f cmdutil.Factory, out, errOut io.Writer) *cobra.Command { func validateArgs(cmd *cobra.Command, args []string) error { if len(args) != 0 { - return cmdutil.UsageError(cmd, "Unexpected args: %v", args) + return cmdutil.UsageErrorf(cmd, "Unexpected args: %v", args) } return nil diff --git a/pkg/kubectl/cmd/apply_set_last_applied.go b/pkg/kubectl/cmd/apply_set_last_applied.go index 188e54b09b7..cf967578b19 100644 --- a/pkg/kubectl/cmd/apply_set_last_applied.go +++ b/pkg/kubectl/cmd/apply_set_last_applied.go @@ -161,7 +161,7 @@ func (o *SetLastAppliedOptions) Validate(f cmdutil.Factory, cmd *cobra.Command) return cmdutil.AddSourceToErr(fmt.Sprintf("retrieving current configuration of:\n%v\nfrom server for:", info), info.Source, err) } if oringalBuf == nil && !o.CreateAnnotation { - return cmdutil.UsageError(cmd, "no last-applied-configuration annotation found on resource: %s, to create the annotation, run the command with --create-annotation", info.Name) + 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) } //only add to PatchBufferList when changed diff --git a/pkg/kubectl/cmd/apply_test.go b/pkg/kubectl/cmd/apply_test.go index 838624f38ba..ef0f9c394da 100644 --- a/pkg/kubectl/cmd/apply_test.go +++ b/pkg/kubectl/cmd/apply_test.go @@ -55,7 +55,7 @@ func TestApplyExtraArgsFail(t *testing.T) { func validateApplyArgs(cmd *cobra.Command, args []string) error { if len(args) != 0 { - return cmdutil.UsageError(cmd, "Unexpected args: %v", args) + return cmdutil.UsageErrorf(cmd, "Unexpected args: %v", args) } return nil } diff --git a/pkg/kubectl/cmd/apply_view_last_applied.go b/pkg/kubectl/cmd/apply_view_last_applied.go index 033da8b9d94..37b519e21ca 100644 --- a/pkg/kubectl/cmd/apply_view_last_applied.go +++ b/pkg/kubectl/cmd/apply_view_last_applied.go @@ -166,6 +166,6 @@ func (o *ViewLastAppliedOptions) ValidateOutputArgs(cmd *cobra.Command) error { o.OutputFormat = "yaml" return nil default: - return cmdutil.UsageError(cmd, "Unexpected -o output mode: %s, the flag 'output' must be one of yaml|json", format) + return cmdutil.UsageErrorf(cmd, "Unexpected -o output mode: %s, the flag 'output' must be one of yaml|json", format) } } diff --git a/pkg/kubectl/cmd/attach.go b/pkg/kubectl/cmd/attach.go index bdb3f352def..8917b275796 100644 --- a/pkg/kubectl/cmd/attach.go +++ b/pkg/kubectl/cmd/attach.go @@ -17,6 +17,7 @@ limitations under the License. package cmd import ( + "errors" "fmt" "io" "net/url" @@ -127,10 +128,10 @@ type AttachOptions struct { // Complete verifies command line arguments and loads data from the command environment func (p *AttachOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, argsIn []string) error { if len(argsIn) == 0 { - return cmdutil.UsageError(cmd, "at least one argument is required for attach") + return cmdutil.UsageErrorf(cmd, "at least 1 argument is required for attach") } if len(argsIn) > 2 { - return cmdutil.UsageError(cmd, fmt.Sprintf("expected fewer than three arguments: POD or TYPE/NAME or TYPE NAME, saw %d: %s", len(argsIn), 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() @@ -140,7 +141,7 @@ func (p *AttachOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, argsIn [ p.GetPodTimeout, err = cmdutil.GetPodRunningTimeoutFlag(cmd) if err != nil { - return cmdutil.UsageError(cmd, err.Error()) + return cmdutil.UsageErrorf(cmd, err.Error()) } builder := f.NewBuilder(true). @@ -189,13 +190,13 @@ func (p *AttachOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, argsIn [ func (p *AttachOptions) Validate() error { allErrs := []error{} if len(p.PodName) == 0 { - allErrs = append(allErrs, fmt.Errorf("pod name must be specified")) + allErrs = append(allErrs, errors.New("pod name must be specified")) } if p.Out == nil || p.Err == nil { - allErrs = append(allErrs, fmt.Errorf("both output and error output must be provided")) + allErrs = append(allErrs, errors.New("both output and error output must be provided")) } if p.Attach == nil || p.PodClient == nil || p.Config == nil { - allErrs = append(allErrs, fmt.Errorf("client, client config, and attach must be provided")) + allErrs = append(allErrs, errors.New("client, client config, and attach must be provided")) } return utilerrors.NewAggregate(allErrs) } diff --git a/pkg/kubectl/cmd/autoscale.go b/pkg/kubectl/cmd/autoscale.go index 4d0fadf1e9c..288ee072384 100644 --- a/pkg/kubectl/cmd/autoscale.go +++ b/pkg/kubectl/cmd/autoscale.go @@ -108,7 +108,7 @@ func RunAutoscale(f cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []s generators := f.Generators("autoscale") generator, found := generators[generatorName] if !found { - return cmdutil.UsageError(cmd, fmt.Sprintf("generator %q not found.", generatorName)) + return cmdutil.UsageErrorf(cmd, "generator %q not found.", generatorName) } names := generator.ParamNames() diff --git a/pkg/kubectl/cmd/certificates.go b/pkg/kubectl/cmd/certificates.go index 2f3b57ba3d4..107a5639779 100644 --- a/pkg/kubectl/cmd/certificates.go +++ b/pkg/kubectl/cmd/certificates.go @@ -59,7 +59,7 @@ func (options *CertificateOptions) Complete(cmd *cobra.Command, args []string) e } func (options *CertificateOptions) Validate() error { - if len(options.csrNames) < 1 && cmdutil.IsFilenameEmpty(options.Filenames) { + if len(options.csrNames) < 1 && cmdutil.IsFilenameSliceEmpty(options.Filenames) { return fmt.Errorf("one or more CSRs must be specified as or -f ") } return nil diff --git a/pkg/kubectl/cmd/clusterinfo_dump.go b/pkg/kubectl/cmd/clusterinfo_dump.go index 49efaf82b9a..f1d420fd7a4 100644 --- a/pkg/kubectl/cmd/clusterinfo_dump.go +++ b/pkg/kubectl/cmd/clusterinfo_dump.go @@ -91,7 +91,7 @@ func setupOutputWriter(cmd *cobra.Command, defaultWriter io.Writer, filename str func dumpClusterInfo(f cmdutil.Factory, cmd *cobra.Command, out io.Writer) error { timeout, err := cmdutil.GetPodRunningTimeoutFlag(cmd) if err != nil { - return cmdutil.UsageError(cmd, err.Error()) + return cmdutil.UsageErrorf(cmd, err.Error()) } clientset, err := f.ClientSet() diff --git a/pkg/kubectl/cmd/completion.go b/pkg/kubectl/cmd/completion.go index 47ce1cb9547..09f8f5cead4 100644 --- a/pkg/kubectl/cmd/completion.go +++ b/pkg/kubectl/cmd/completion.go @@ -116,14 +116,14 @@ func NewCmdCompletion(out io.Writer, boilerPlate string) *cobra.Command { func RunCompletion(out io.Writer, boilerPlate string, cmd *cobra.Command, args []string) error { if len(args) == 0 { - return cmdutil.UsageError(cmd, "Shell not specified.") + return cmdutil.UsageErrorf(cmd, "Shell not specified.") } if len(args) > 1 { - return cmdutil.UsageError(cmd, "Too many arguments. Expected only the shell type.") + return cmdutil.UsageErrorf(cmd, "Too many arguments. Expected only the shell type.") } run, found := completion_shells[args[0]] if !found { - return cmdutil.UsageError(cmd, "Unsupported shell type %q.", args[0]) + return cmdutil.UsageErrorf(cmd, "Unsupported shell type %q.", args[0]) } if len(boilerPlate) == 0 { diff --git a/pkg/kubectl/cmd/config/rename_context.go b/pkg/kubectl/cmd/config/rename_context.go index 7d00eb83ac8..359c58d5d4d 100644 --- a/pkg/kubectl/cmd/config/rename_context.go +++ b/pkg/kubectl/cmd/config/rename_context.go @@ -70,7 +70,7 @@ func NewCmdConfigRenameContext(out io.Writer, configAccess clientcmd.ConfigAcces cmdutil.CheckErr(err) } if err := options.Validate(); err != nil { - cmdutil.UsageError(cmd, err.Error()) + cmdutil.UsageErrorf(cmd, err.Error()) } if err := options.RunRenameContext(out); err != nil { cmdutil.CheckErr(err) diff --git a/pkg/kubectl/cmd/convert.go b/pkg/kubectl/cmd/convert.go index c96e9420bd8..e43b00e67c8 100644 --- a/pkg/kubectl/cmd/convert.go +++ b/pkg/kubectl/cmd/convert.go @@ -122,7 +122,7 @@ func (o *ConvertOptions) Complete(f cmdutil.Factory, out io.Writer, cmd *cobra.C return err } if !api.Registry.IsEnabledVersion(o.outputVersion) { - cmdutil.UsageError(cmd, "'%s' is not a registered version.", o.outputVersion) + cmdutil.UsageErrorf(cmd, "'%s' is not a registered version.", o.outputVersion) } // build the builder diff --git a/pkg/kubectl/cmd/cp.go b/pkg/kubectl/cmd/cp.go index fd9eaeacd29..1e561ea1298 100644 --- a/pkg/kubectl/cmd/cp.go +++ b/pkg/kubectl/cmd/cp.go @@ -18,7 +18,7 @@ package cmd import ( "archive/tar" - "fmt" + "errors" "io" "io/ioutil" "os" @@ -80,13 +80,17 @@ type fileSpec struct { File string } +var errFileSpecDoesntMatchFormat = errors.New("Filespec must match the canonical format: [[namespace/]pod:]file/path") + func extractFileSpec(arg string) (fileSpec, error) { pieces := strings.Split(arg, ":") if len(pieces) == 1 { return fileSpec{File: arg}, nil } if len(pieces) != 2 { - return fileSpec{}, fmt.Errorf("Unexpected fileSpec: %s, expected [[namespace/]pod:]file/path", arg) + // FIXME Kubernetes can't copy files that contain a ':' + // character. + return fileSpec{}, errFileSpecDoesntMatchFormat } file := pieces[1] @@ -105,12 +109,12 @@ func extractFileSpec(arg string) (fileSpec, error) { }, nil } - return fileSpec{}, fmt.Errorf("Unexpected file spec: %s, expected [[namespace/]pod:]file/path", arg) + return fileSpec{}, errFileSpecDoesntMatchFormat } func runCopy(f cmdutil.Factory, cmd *cobra.Command, out, cmderr io.Writer, args []string) error { if len(args) != 2 { - return cmdutil.UsageError(cmd, cpUsageStr) + return cmdutil.UsageErrorf(cmd, cpUsageStr) } srcSpec, err := extractFileSpec(args[0]) if err != nil { @@ -126,7 +130,7 @@ func runCopy(f cmdutil.Factory, cmd *cobra.Command, out, cmderr io.Writer, args if len(destSpec.PodName) != 0 { return copyToPod(f, cmd, out, cmderr, srcSpec, destSpec) } - return cmdutil.UsageError(cmd, "One of src or dest must be a remote file specification") + return cmdutil.UsageErrorf(cmd, "One of src or dest must be a remote file specification") } func copyToPod(f cmdutil.Factory, cmd *cobra.Command, stdout, stderr io.Writer, src, dest fileSpec) error { diff --git a/pkg/kubectl/cmd/create.go b/pkg/kubectl/cmd/create.go index 6e0c6c4e428..f3658199e55 100644 --- a/pkg/kubectl/cmd/create.go +++ b/pkg/kubectl/cmd/create.go @@ -64,7 +64,7 @@ func NewCmdCreate(f cmdutil.Factory, out, errOut io.Writer) *cobra.Command { Long: createLong, Example: createExample, Run: func(cmd *cobra.Command, args []string) { - if cmdutil.IsFilenameEmpty(options.FilenameOptions.Filenames) { + if cmdutil.IsFilenameSliceEmpty(options.FilenameOptions.Filenames) { defaultRunFunc := cmdutil.DefaultSubCommandRun(errOut) defaultRunFunc(cmd, args) return @@ -106,7 +106,7 @@ func NewCmdCreate(f cmdutil.Factory, out, errOut io.Writer) *cobra.Command { func ValidateArgs(cmd *cobra.Command, args []string) error { if len(args) != 0 { - return cmdutil.UsageError(cmd, "Unexpected args: %v", args) + return cmdutil.UsageErrorf(cmd, "Unexpected args: %v", args) } return nil } @@ -229,7 +229,7 @@ func createAndRefresh(info *resource.Info) error { // 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) == 0 { - return "", cmdutil.UsageError(cmd, "NAME is required") + return "", cmdutil.UsageErrorf(cmd, "NAME is required") } return args[0], nil } @@ -241,8 +241,7 @@ type CreateSubcommandOptions struct { // 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 + DryRun bool OutputFormat string } diff --git a/pkg/kubectl/cmd/create_secret.go b/pkg/kubectl/cmd/create_secret.go index 10c9d51eb1a..0358bb162ef 100644 --- a/pkg/kubectl/cmd/create_secret.go +++ b/pkg/kubectl/cmd/create_secret.go @@ -176,7 +176,7 @@ func CreateSecretDockerRegistry(f cmdutil.Factory, cmdOut io.Writer, cmd *cobra. 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.UsageError(cmd, "flag %s is required", requiredFlag) + return cmdutil.UsageErrorf(cmd, "flag %s is required", requiredFlag) } } var generator kubectl.StructuredGenerator @@ -241,7 +241,7 @@ func CreateSecretTLS(f cmdutil.Factory, cmdOut io.Writer, cmd *cobra.Command, ar requiredFlags := []string{"cert", "key"} for _, requiredFlag := range requiredFlags { if value := cmdutil.GetFlagString(cmd, requiredFlag); len(value) == 0 { - return cmdutil.UsageError(cmd, "flag %s is required", requiredFlag) + return cmdutil.UsageErrorf(cmd, "flag %s is required", requiredFlag) } } var generator kubectl.StructuredGenerator diff --git a/pkg/kubectl/cmd/create_service.go b/pkg/kubectl/cmd/create_service.go index 4995427fee4..44a74360c49 100644 --- a/pkg/kubectl/cmd/create_service.go +++ b/pkg/kubectl/cmd/create_service.go @@ -83,7 +83,7 @@ func NewCmdCreateServiceClusterIP(f cmdutil.Factory, cmdOut io.Writer) *cobra.Co } func errUnsupportedGenerator(cmd *cobra.Command, generatorName string) error { - return cmdutil.UsageError(cmd, "Generator %s not supported. ", generatorName) + return cmdutil.UsageErrorf(cmd, "Generator %s not supported. ", generatorName) } // CreateServiceClusterIP implements the behavior to run the create service clusterIP command diff --git a/pkg/kubectl/cmd/delete.go b/pkg/kubectl/cmd/delete.go index 8e9e178fe62..42ce9353ada 100644 --- a/pkg/kubectl/cmd/delete.go +++ b/pkg/kubectl/cmd/delete.go @@ -137,7 +137,7 @@ func NewCmdDelete(f cmdutil.Factory, out, errOut io.Writer) *cobra.Command { cmdutil.CheckErr(err) } if err := options.Validate(cmd); err != nil { - cmdutil.CheckErr(cmdutil.UsageError(cmd, err.Error())) + cmdutil.CheckErr(cmdutil.UsageErrorf(cmd, err.Error())) } if err := options.RunDelete(); err != nil { cmdutil.CheckErr(err) diff --git a/pkg/kubectl/cmd/describe.go b/pkg/kubectl/cmd/describe.go index ee8b6bd9cfa..f047a42789b 100644 --- a/pkg/kubectl/cmd/describe.go +++ b/pkg/kubectl/cmd/describe.go @@ -110,9 +110,9 @@ func RunDescribe(f cmdutil.Factory, out, cmdErr io.Writer, cmd *cobra.Command, a if allNamespaces { enforceNamespace = false } - if len(args) == 0 && cmdutil.IsFilenameEmpty(options.Filenames) { + if len(args) == 0 && cmdutil.IsFilenameSliceEmpty(options.Filenames) { fmt.Fprint(cmdErr, "You must specify the type of resource to describe. ", validResources) - return cmdutil.UsageError(cmd, "Required resource not specified.") + return cmdutil.UsageErrorf(cmd, "Required resource not specified.") } builder, err := f.NewUnstructuredBuilder(true) diff --git a/pkg/kubectl/cmd/drain.go b/pkg/kubectl/cmd/drain.go index 1eaaa4cf599..a25b2476226 100644 --- a/pkg/kubectl/cmd/drain.go +++ b/pkg/kubectl/cmd/drain.go @@ -197,7 +197,7 @@ func NewCmdDrain(f cmdutil.Factory, out, errOut io.Writer) *cobra.Command { func (o *DrainOptions) SetupDrain(cmd *cobra.Command, args []string) error { var err error if len(args) != 1 { - return cmdutil.UsageError(cmd, fmt.Sprintf("USAGE: %s [flags]", cmd.Use)) + return cmdutil.UsageErrorf(cmd, "USAGE: %s [flags]", cmd.Use) } if o.client, err = o.Factory.ClientSet(); err != nil { diff --git a/pkg/kubectl/cmd/exec.go b/pkg/kubectl/cmd/exec.go index d74d1893efd..84d76f1a332 100644 --- a/pkg/kubectl/cmd/exec.go +++ b/pkg/kubectl/cmd/exec.go @@ -152,19 +152,19 @@ type ExecOptions struct { func (p *ExecOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, argsIn []string, argsLenAtDash int) error { // Let kubectl exec follow rules for `--`, see #13004 issue if len(p.PodName) == 0 && (len(argsIn) == 0 || argsLenAtDash == 0) { - return cmdutil.UsageError(cmd, execUsageStr) + return cmdutil.UsageErrorf(cmd, execUsageStr) } if len(p.PodName) != 0 { printDeprecationWarning("exec POD_NAME", "-p POD_NAME") if len(argsIn) < 1 { - return cmdutil.UsageError(cmd, execUsageStr) + return cmdutil.UsageErrorf(cmd, execUsageStr) } p.Command = argsIn } else { p.PodName = argsIn[0] p.Command = argsIn[1:] if len(p.Command) < 1 { - return cmdutil.UsageError(cmd, execUsageStr) + return cmdutil.UsageErrorf(cmd, execUsageStr) } } diff --git a/pkg/kubectl/cmd/explain.go b/pkg/kubectl/cmd/explain.go index 7a8230f3254..e2967e03da4 100644 --- a/pkg/kubectl/cmd/explain.go +++ b/pkg/kubectl/cmd/explain.go @@ -66,10 +66,10 @@ func NewCmdExplain(f cmdutil.Factory, out, cmdErr io.Writer) *cobra.Command { func RunExplain(f cmdutil.Factory, out, cmdErr io.Writer, cmd *cobra.Command, args []string) error { if len(args) == 0 { fmt.Fprint(cmdErr, "You must specify the type of resource to explain. ", validResources) - return cmdutil.UsageError(cmd, "Required resource not specified.") + return cmdutil.UsageErrorf(cmd, "Required resource not specified.") } if len(args) > 1 { - return cmdutil.UsageError(cmd, "We accept only this format: explain RESOURCE") + return cmdutil.UsageErrorf(cmd, "We accept only this format: explain RESOURCE") } recursive := cmdutil.GetFlagBool(cmd, "recursive") diff --git a/pkg/kubectl/cmd/expose.go b/pkg/kubectl/cmd/expose.go index 20580d8b399..140c9a74431 100644 --- a/pkg/kubectl/cmd/expose.go +++ b/pkg/kubectl/cmd/expose.go @@ -17,7 +17,6 @@ limitations under the License. package cmd import ( - "fmt" "io" "regexp" "strings" @@ -136,7 +135,7 @@ func RunExpose(f cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []stri Do() err = r.Err() if err != nil { - return cmdutil.UsageError(cmd, err.Error()) + return cmdutil.UsageErrorf(cmd, err.Error()) } // Get the generator, setup and validate all required parameters @@ -144,7 +143,7 @@ func RunExpose(f cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []stri generators := f.Generators("expose") generator, found := generators[generatorName] if !found { - return cmdutil.UsageError(cmd, fmt.Sprintf("generator %q not found.", generatorName)) + return cmdutil.UsageErrorf(cmd, "generator %q not found.", generatorName) } names := generator.ParamNames() @@ -170,7 +169,7 @@ func RunExpose(f cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []stri if s, found := params["selector"]; found && kubectl.IsZero(s) { s, err := f.MapBasedSelectorForObject(info.Object) if err != nil { - return cmdutil.UsageError(cmd, fmt.Sprintf("couldn't retrieve selectors via --selector flag or introspection: %s", err)) + return cmdutil.UsageErrorf(cmd, "couldn't retrieve selectors via --selector flag or introspection: %v", err) } params["selector"] = s } @@ -182,12 +181,12 @@ func RunExpose(f cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []stri if port, found := params["port"]; found && kubectl.IsZero(port) { ports, err := f.PortsForObject(info.Object) if err != nil { - return cmdutil.UsageError(cmd, fmt.Sprintf("couldn't find port via --port flag or introspection: %s", err)) + return cmdutil.UsageErrorf(cmd, "couldn't find port via --port flag or introspection: %v", err) } switch len(ports) { case 0: if !isHeadlessService { - return cmdutil.UsageError(cmd, "couldn't find port via --port flag or introspection") + return cmdutil.UsageErrorf(cmd, "couldn't find port via --port flag or introspection") } case 1: params["port"] = ports[0] @@ -201,7 +200,7 @@ func RunExpose(f cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []stri if _, found := params["protocol"]; found { protocolsMap, err := f.ProtocolsForObject(info.Object) if err != nil { - return cmdutil.UsageError(cmd, fmt.Sprintf("couldn't find protocol via introspection: %s", err)) + return cmdutil.UsageErrorf(cmd, "couldn't find protocol via introspection: %v", err) } if protocols := kubectl.MakeProtocols(protocolsMap); !kubectl.IsZero(protocols) { params["protocols"] = protocols diff --git a/pkg/kubectl/cmd/get.go b/pkg/kubectl/cmd/get.go index 833b86da611..eb3bea9ab82 100644 --- a/pkg/kubectl/cmd/get.go +++ b/pkg/kubectl/cmd/get.go @@ -51,7 +51,7 @@ type GetOptions struct { } var ( - get_long = templates.LongDesc(` + getLong = templates.LongDesc(` Display one or many resources. ` + validResources + ` @@ -63,7 +63,7 @@ var ( 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.`) - get_example = templates.Examples(i18n.T(` + getExample = templates.Examples(i18n.T(` # List all pods in ps output format. kubectl get pods @@ -115,8 +115,8 @@ func NewCmdGet(f cmdutil.Factory, out io.Writer, errOut io.Writer) *cobra.Comman 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]", Short: i18n.T("Display one or many resources"), - Long: get_long, - Example: get_example, + Long: getLong, + Example: getExample, Run: func(cmd *cobra.Command, args []string) { err := RunGet(f, out, errOut, cmd, args, options) cmdutil.CheckErr(err) @@ -182,7 +182,7 @@ func RunGet(f cmdutil.Factory, out, errOut io.Writer, cmd *cobra.Command, args [ enforceNamespace = false } - if len(args) == 0 && cmdutil.IsFilenameEmpty(options.Filenames) { + if len(args) == 0 && cmdutil.IsFilenameSliceEmpty(options.Filenames) { fmt.Fprint(errOut, "You must specify the type of resource to get. ", validResources) fullCmdName := cmd.Parent().CommandPath() @@ -191,7 +191,7 @@ func RunGet(f cmdutil.Factory, out, errOut io.Writer, cmd *cobra.Command, args [ usageString = fmt.Sprintf("%s\nUse \"%s explain \" for a detailed description of that resource (e.g. %[2]s explain pods).", usageString, fullCmdName) } - return cmdutil.UsageError(cmd, usageString) + return cmdutil.UsageErrorf(cmd, usageString) } export := cmdutil.GetFlagBool(cmd, "export") diff --git a/pkg/kubectl/cmd/label.go b/pkg/kubectl/cmd/label.go index 33f2a1e9c33..1d8776f9d83 100644 --- a/pkg/kubectl/cmd/label.go +++ b/pkg/kubectl/cmd/label.go @@ -115,10 +115,10 @@ func NewCmdLabel(f cmdutil.Factory, out io.Writer) *cobra.Command { Example: labelExample, Run: func(cmd *cobra.Command, args []string) { if err := options.Complete(out, cmd, args); err != nil { - cmdutil.CheckErr(cmdutil.UsageError(cmd, err.Error())) + cmdutil.CheckErr(cmdutil.UsageErrorf(cmd, err.Error())) } if err := options.Validate(); err != nil { - cmdutil.CheckErr(cmdutil.UsageError(cmd, err.Error())) + cmdutil.CheckErr(cmdutil.UsageErrorf(cmd, err.Error())) } cmdutil.CheckErr(options.RunLabel(f, cmd)) }, @@ -162,7 +162,7 @@ func (o *LabelOptions) Complete(out io.Writer, cmd *cobra.Command, args []string // Validate checks to the LabelOptions to see if there is sufficient information run the command. func (o *LabelOptions) Validate() error { - if len(o.resources) < 1 && cmdutil.IsFilenameEmpty(o.FilenameOptions.Filenames) { + if len(o.resources) < 1 && cmdutil.IsFilenameSliceEmpty(o.FilenameOptions.Filenames) { return fmt.Errorf("one or more resources must be specified as or /") } if len(o.newLabels) < 1 && len(o.removeLabels) < 1 { diff --git a/pkg/kubectl/cmd/logs.go b/pkg/kubectl/cmd/logs.go index dc71d58b536..08e18b8f41b 100644 --- a/pkg/kubectl/cmd/logs.go +++ b/pkg/kubectl/cmd/logs.go @@ -127,21 +127,21 @@ func (o *LogsOptions) Complete(f cmdutil.Factory, out io.Writer, cmd *cobra.Comm switch len(args) { case 0: if len(selector) == 0 { - return cmdutil.UsageError(cmd, logsUsageStr) + return cmdutil.UsageErrorf(cmd, "%s", logsUsageStr) } case 1: o.ResourceArg = args[0] if len(selector) != 0 { - return cmdutil.UsageError(cmd, "only a selector (-l) or a POD name is allowed") + return cmdutil.UsageErrorf(cmd, "only a selector (-l) or a POD name is allowed") } case 2: if cmd.Flag("container").Changed { - return cmdutil.UsageError(cmd, "only one of -c or an inline [CONTAINER] arg is allowed") + return cmdutil.UsageErrorf(cmd, "only one of -c or an inline [CONTAINER] arg is allowed") } o.ResourceArg = args[0] containerName = args[1] default: - return cmdutil.UsageError(cmd, logsUsageStr) + return cmdutil.UsageErrorf(cmd, "%s", logsUsageStr) } var err error o.Namespace, _, err = f.DefaultNamespace() @@ -183,7 +183,7 @@ func (o *LogsOptions) Complete(f cmdutil.Factory, out io.Writer, cmd *cobra.Comm if len(selector) != 0 { if logOptions.Follow { - return cmdutil.UsageError(cmd, "only one of follow (-f) or selector (-l) is allowed") + return cmdutil.UsageErrorf(cmd, "only one of follow (-f) or selector (-l) is allowed") } if logOptions.TailLines == nil { logOptions.TailLines = &selectorTail diff --git a/pkg/kubectl/cmd/patch.go b/pkg/kubectl/cmd/patch.go index 96a0b6d3852..8e3111ac1c4 100644 --- a/pkg/kubectl/cmd/patch.go +++ b/pkg/kubectl/cmd/patch.go @@ -136,13 +136,14 @@ func RunPatch(f cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []strin ok := false patchType, ok = patchTypes[patchTypeString] if !ok { - return cmdutil.UsageError(cmd, fmt.Sprintf("--type must be one of %v, not %q", sets.StringKeySet(patchTypes).List(), patchTypeString)) + return cmdutil.UsageErrorf(cmd, "--type must be one of %v, not %q", + sets.StringKeySet(patchTypes).List(), patchTypeString) } } patch := cmdutil.GetFlagString(cmd, "patch") if len(patch) == 0 { - return cmdutil.UsageError(cmd, "Must specify -p to patch") + return cmdutil.UsageErrorf(cmd, "Must specify -p to patch") } patchBytes, err := yaml.ToJSON([]byte(patch)) if err != nil { diff --git a/pkg/kubectl/cmd/portforward.go b/pkg/kubectl/cmd/portforward.go index 75e9e33ef37..8e9e15e9736 100644 --- a/pkg/kubectl/cmd/portforward.go +++ b/pkg/kubectl/cmd/portforward.go @@ -81,7 +81,7 @@ func NewCmdPortForward(f cmdutil.Factory, cmdOut, cmdErr io.Writer) *cobra.Comma cmdutil.CheckErr(err) } if err := opts.Validate(); err != nil { - cmdutil.CheckErr(cmdutil.UsageError(cmd, err.Error())) + cmdutil.CheckErr(cmdutil.UsageErrorf(cmd, "%v", err.Error())) } if err := opts.RunPortForward(); err != nil { cmdutil.CheckErr(err) @@ -118,7 +118,7 @@ func (o *PortForwardOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, arg var err error o.PodName = cmdutil.GetFlagString(cmd, "pod") if len(o.PodName) == 0 && len(args) == 0 { - return cmdutil.UsageError(cmd, "POD is required for port-forward") + return cmdutil.UsageErrorf(cmd, "POD is required for port-forward") } if len(o.PodName) != 0 { diff --git a/pkg/kubectl/cmd/replace.go b/pkg/kubectl/cmd/replace.go index 32183579c7c..d73abe52e7b 100644 --- a/pkg/kubectl/cmd/replace.go +++ b/pkg/kubectl/cmd/replace.go @@ -103,8 +103,8 @@ func RunReplace(f cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []str } force := cmdutil.GetFlagBool(cmd, "force") - if cmdutil.IsFilenameEmpty(options.Filenames) { - return cmdutil.UsageError(cmd, "Must specify --filename to replace") + if cmdutil.IsFilenameSliceEmpty(options.Filenames) { + return cmdutil.UsageErrorf(cmd, "Must specify --filename to replace") } shortOutput := cmdutil.GetFlagString(cmd, "output") == "name" diff --git a/pkg/kubectl/cmd/rollingupdate.go b/pkg/kubectl/cmd/rollingupdate.go index 274e36190e5..9940c9f6e60 100644 --- a/pkg/kubectl/cmd/rollingupdate.go +++ b/pkg/kubectl/cmd/rollingupdate.go @@ -114,26 +114,26 @@ func validateArguments(cmd *cobra.Command, filenames, args []string) error { errors := []error{} if len(deploymentKey) == 0 { - errors = append(errors, cmdutil.UsageError(cmd, "--deployment-label-key can not be empty")) + errors = append(errors, cmdutil.UsageErrorf(cmd, "--deployment-label-key can not be empty")) } if len(filenames) > 1 { - errors = append(errors, cmdutil.UsageError(cmd, "May only specify a single filename for new controller")) + errors = append(errors, cmdutil.UsageErrorf(cmd, "May only specify a single filename for new controller")) } if !rollback { if len(filenames) == 0 && len(image) == 0 { - errors = append(errors, cmdutil.UsageError(cmd, "Must specify --filename or --image for new controller")) + errors = append(errors, cmdutil.UsageErrorf(cmd, "Must specify --filename or --image for new controller")) } else if len(filenames) != 0 && len(image) != 0 { - errors = append(errors, cmdutil.UsageError(cmd, "--filename and --image can not both be specified")) + errors = append(errors, cmdutil.UsageErrorf(cmd, "--filename and --image can not both be specified")) } } else { if len(filenames) != 0 || len(image) != 0 { - errors = append(errors, cmdutil.UsageError(cmd, "Don't specify --filename or --image on rollback")) + errors = append(errors, cmdutil.UsageErrorf(cmd, "Don't specify --filename or --image on rollback")) } } if len(args) < 1 { - errors = append(errors, cmdutil.UsageError(cmd, "Must specify the controller to update")) + errors = append(errors, cmdutil.UsageErrorf(cmd, "Must specify the controller to update")) } return utilerrors.NewAggregate(errors) @@ -213,20 +213,20 @@ func RunRollingUpdate(f cmdutil.Factory, out io.Writer, cmd *cobra.Command, args // when creating resource(s) from a stream. if list, ok := obj.(*api.List); ok { if len(list.Items) > 1 { - return cmdutil.UsageError(cmd, "%s specifies multiple items", filename) + return cmdutil.UsageErrorf(cmd, "%s specifies multiple items", filename) } if len(list.Items) == 0 { - return cmdutil.UsageError(cmd, "please make sure %s exists and is not empty", filename) + return cmdutil.UsageErrorf(cmd, "please make sure %s exists and is not empty", filename) } obj = list.Items[0] } newRc, ok = obj.(*api.ReplicationController) if !ok { if gvks, _, err := typer.ObjectKinds(obj); err == nil { - return cmdutil.UsageError(cmd, "%s contains a %v not a ReplicationController", filename, gvks[0]) + return cmdutil.UsageErrorf(cmd, "%s contains a %v not a ReplicationController", filename, gvks[0]) } glog.V(4).Infof("Object %#v is not a ReplicationController", obj) - return cmdutil.UsageError(cmd, "%s does not specify a valid ReplicationController", filename) + return cmdutil.UsageErrorf(cmd, "%s does not specify a valid ReplicationController", filename) } infos, err := request.Infos() if err != nil || len(infos) != 1 { @@ -247,7 +247,7 @@ func RunRollingUpdate(f cmdutil.Factory, out io.Writer, cmd *cobra.Command, args } if newRc != nil { if inProgressImage := newRc.Spec.Template.Spec.Containers[0].Image; inProgressImage != image { - return cmdutil.UsageError(cmd, "Found existing in-progress update to image (%s).\nEither continue in-progress update with --image=%s or rollback with --rollback", inProgressImage, inProgressImage) + 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) } fmt.Fprintf(out, "Found existing update in progress (%s), resuming.\n", newRc.Name) } else { @@ -261,7 +261,7 @@ func RunRollingUpdate(f cmdutil.Factory, out io.Writer, cmd *cobra.Command, args } if oldRc.Spec.Template.Spec.Containers[0].Image == image { if len(pullPolicy) == 0 { - return cmdutil.UsageError(cmd, "--image-pull-policy (Always|Never|IfNotPresent) must be provided when --image is the same as existing container image") + return cmdutil.UsageErrorf(cmd, "--image-pull-policy (Always|Never|IfNotPresent) must be provided when --image is the same as existing container image") } config.PullPolicy = api.PullPolicy(pullPolicy) } @@ -292,12 +292,12 @@ func RunRollingUpdate(f cmdutil.Factory, out io.Writer, cmd *cobra.Command, args } if newRc == nil { - return cmdutil.UsageError(cmd, "Could not find %s to rollback.\n", newName) + return cmdutil.UsageErrorf(cmd, "Could not find %s to rollback.\n", newName) } } if oldName == newRc.Name { - return cmdutil.UsageError(cmd, "%s cannot have the same name as the existing ReplicationController %s", + return cmdutil.UsageErrorf(cmd, "%s cannot have the same name as the existing ReplicationController %s", filename, oldName) } @@ -314,7 +314,7 @@ func RunRollingUpdate(f cmdutil.Factory, out io.Writer, cmd *cobra.Command, args } } if !hasLabel { - return cmdutil.UsageError(cmd, "%s must specify a matching key with non-equal value in Selector for %s", + return cmdutil.UsageErrorf(cmd, "%s must specify a matching key with non-equal value in Selector for %s", filename, oldName) } // TODO: handle scales during rolling update diff --git a/pkg/kubectl/cmd/rollout/rollout_history.go b/pkg/kubectl/cmd/rollout/rollout_history.go index 20785d4a890..b236176813b 100644 --- a/pkg/kubectl/cmd/rollout/rollout_history.go +++ b/pkg/kubectl/cmd/rollout/rollout_history.go @@ -66,8 +66,8 @@ func NewCmdRolloutHistory(f cmdutil.Factory, out io.Writer) *cobra.Command { } func RunHistory(f cmdutil.Factory, cmd *cobra.Command, out io.Writer, args []string, options *resource.FilenameOptions) error { - if len(args) == 0 && cmdutil.IsFilenameEmpty(options.Filenames) { - return cmdutil.UsageError(cmd, "Required resource not specified.") + if len(args) == 0 && cmdutil.IsFilenameSliceEmpty(options.Filenames) { + return cmdutil.UsageErrorf(cmd, "Required resource not specified.") } revision := cmdutil.GetFlagInt64(cmd, "revision") if revision < 0 { diff --git a/pkg/kubectl/cmd/rollout/rollout_pause.go b/pkg/kubectl/cmd/rollout/rollout_pause.go index b436305f99d..baf6d589360 100644 --- a/pkg/kubectl/cmd/rollout/rollout_pause.go +++ b/pkg/kubectl/cmd/rollout/rollout_pause.go @@ -96,8 +96,8 @@ func NewCmdRolloutPause(f cmdutil.Factory, out io.Writer) *cobra.Command { } func (o *PauseConfig) CompletePause(f cmdutil.Factory, cmd *cobra.Command, out io.Writer, args []string) error { - if len(args) == 0 && cmdutil.IsFilenameEmpty(o.Filenames) { - return cmdutil.UsageError(cmd, cmd.Use) + if len(args) == 0 && cmdutil.IsFilenameSliceEmpty(o.Filenames) { + return cmdutil.UsageErrorf(cmd, "%s", cmd.Use) } o.Mapper, o.Typer = f.Object() diff --git a/pkg/kubectl/cmd/rollout/rollout_resume.go b/pkg/kubectl/cmd/rollout/rollout_resume.go index e5560082586..cf370f4ca0a 100644 --- a/pkg/kubectl/cmd/rollout/rollout_resume.go +++ b/pkg/kubectl/cmd/rollout/rollout_resume.go @@ -94,8 +94,8 @@ func NewCmdRolloutResume(f cmdutil.Factory, out io.Writer) *cobra.Command { } func (o *ResumeConfig) CompleteResume(f cmdutil.Factory, cmd *cobra.Command, out io.Writer, args []string) error { - if len(args) == 0 && cmdutil.IsFilenameEmpty(o.Filenames) { - return cmdutil.UsageError(cmd, cmd.Use) + if len(args) == 0 && cmdutil.IsFilenameSliceEmpty(o.Filenames) { + return cmdutil.UsageErrorf(cmd, "%s", cmd.Use) } o.Mapper, o.Typer = f.Object() diff --git a/pkg/kubectl/cmd/rollout/rollout_status.go b/pkg/kubectl/cmd/rollout/rollout_status.go index 744d9e6f2b4..548722f45be 100644 --- a/pkg/kubectl/cmd/rollout/rollout_status.go +++ b/pkg/kubectl/cmd/rollout/rollout_status.go @@ -73,8 +73,8 @@ func NewCmdRolloutStatus(f cmdutil.Factory, out io.Writer) *cobra.Command { } func RunStatus(f cmdutil.Factory, cmd *cobra.Command, out io.Writer, args []string, options *resource.FilenameOptions) error { - if len(args) == 0 && cmdutil.IsFilenameEmpty(options.Filenames) { - return cmdutil.UsageError(cmd, "Required resource not specified.") + if len(args) == 0 && cmdutil.IsFilenameSliceEmpty(options.Filenames) { + return cmdutil.UsageErrorf(cmd, "Required resource not specified.") } cmdNamespace, enforceNamespace, err := f.DefaultNamespace() diff --git a/pkg/kubectl/cmd/rollout/rollout_undo.go b/pkg/kubectl/cmd/rollout/rollout_undo.go index 0614d0f0dd3..abbea42e507 100644 --- a/pkg/kubectl/cmd/rollout/rollout_undo.go +++ b/pkg/kubectl/cmd/rollout/rollout_undo.go @@ -96,8 +96,8 @@ func NewCmdRolloutUndo(f cmdutil.Factory, out io.Writer) *cobra.Command { } func (o *UndoOptions) CompleteUndo(f cmdutil.Factory, cmd *cobra.Command, out io.Writer, args []string) error { - if len(args) == 0 && cmdutil.IsFilenameEmpty(o.Filenames) { - return cmdutil.UsageError(cmd, "Required resource not specified.") + if len(args) == 0 && cmdutil.IsFilenameSliceEmpty(o.Filenames) { + return cmdutil.UsageErrorf(cmd, "Required resource not specified.") } o.ToRevision = cmdutil.GetFlagInt64(cmd, "to-revision") diff --git a/pkg/kubectl/cmd/run.go b/pkg/kubectl/cmd/run.go index af1fe13dac5..6e0d13f5c0a 100644 --- a/pkg/kubectl/cmd/run.go +++ b/pkg/kubectl/cmd/run.go @@ -138,12 +138,12 @@ func addRunFlags(cmd *cobra.Command) { func RunRun(f cmdutil.Factory, cmdIn io.Reader, cmdOut, cmdErr io.Writer, cmd *cobra.Command, args []string, argsLenAtDash int) error { // Let kubectl run follow rules for `--`, see #13004 issue if len(args) == 0 || argsLenAtDash == 0 { - return cmdutil.UsageError(cmd, "NAME is required for run") + return cmdutil.UsageErrorf(cmd, "NAME is required for run") } timeout, err := cmdutil.GetPodRunningTimeoutFlag(cmd) if err != nil { - return cmdutil.UsageError(cmd, err.Error()) + return cmdutil.UsageErrorf(cmd, "%v", err) } // validate image name @@ -156,11 +156,11 @@ func RunRun(f cmdutil.Factory, cmdIn io.Reader, cmdOut, cmdErr io.Writer, cmd *c interactive := cmdutil.GetFlagBool(cmd, "stdin") tty := cmdutil.GetFlagBool(cmd, "tty") if tty && !interactive { - return cmdutil.UsageError(cmd, "-i/--stdin is required for containers with -t/--tty=true") + return cmdutil.UsageErrorf(cmd, "-i/--stdin is required for containers with -t/--tty=true") } replicas := cmdutil.GetFlagInt(cmd, "replicas") if interactive && replicas != 1 { - return cmdutil.UsageError(cmd, fmt.Sprintf("-i/--stdin requires that replicas is 1, found %d", replicas)) + return cmdutil.UsageErrorf(cmd, "-i/--stdin requires that replicas is 1, found %d", replicas) } namespace, _, err := f.DefaultNamespace() @@ -172,7 +172,7 @@ func RunRun(f cmdutil.Factory, cmdIn io.Reader, cmdOut, cmdErr io.Writer, cmd *c return err } if restartPolicy != api.RestartPolicyAlways && replicas != 1 { - return cmdutil.UsageError(cmd, fmt.Sprintf("--restart=%s requires that --replicas=1, found %d", restartPolicy, replicas)) + return cmdutil.UsageErrorf(cmd, "--restart=%s requires that --replicas=1, found %d", restartPolicy, replicas) } attachFlag := cmd.Flags().Lookup("attach") @@ -184,11 +184,11 @@ func RunRun(f cmdutil.Factory, cmdIn io.Reader, cmdOut, cmdErr io.Writer, cmd *c remove := cmdutil.GetFlagBool(cmd, "rm") if !attach && remove { - return cmdutil.UsageError(cmd, "--rm should only be used for attached containers") + return cmdutil.UsageErrorf(cmd, "--rm should only be used for attached containers") } if attach && cmdutil.GetDryRunFlag(cmd) { - return cmdutil.UsageError(cmd, "--dry-run can't be used with attached containers options (--attach, --stdin, or --tty)") + return cmdutil.UsageErrorf(cmd, "--dry-run can't be used with attached containers options (--attach, --stdin, or --tty)") } if err := verifyImagePullPolicy(cmd); err != nil { @@ -242,7 +242,7 @@ func RunRun(f cmdutil.Factory, cmdIn io.Reader, cmdOut, cmdErr io.Writer, cmd *c generators := f.Generators("run") generator, found := generators[generatorName] if !found { - return cmdutil.UsageError(cmd, fmt.Sprintf("generator %q not found.", generatorName)) + return cmdutil.UsageErrorf(cmd, "generator %q not found", generatorName) } names := generator.ParamNames() params := kubectl.MakeParams(cmd, names) @@ -261,7 +261,7 @@ func RunRun(f cmdutil.Factory, cmdIn io.Reader, cmdOut, cmdErr io.Writer, cmd *c if cmdutil.GetFlagBool(cmd, "expose") { serviceGenerator := cmdutil.GetFlagString(cmd, "service-generator") if len(serviceGenerator) == 0 { - return cmdutil.UsageError(cmd, fmt.Sprintf("No service generator specified")) + return cmdutil.UsageErrorf(cmd, "No service generator specified") } if err := generateService(f, cmd, args, serviceGenerator, params, namespace, cmdOut); err != nil { return err @@ -368,6 +368,7 @@ func RunRun(f cmdutil.Factory, cmdIn io.Reader, cmdOut, cmdErr io.Writer, cmd *c default: return fmt.Errorf("pod %s/%s left in phase %s", pod.Namespace, pod.Name, pod.Status.Phase) } + } outputFormat := cmdutil.GetFlagString(cmd, "output") @@ -491,9 +492,8 @@ func getRestartPolicy(cmd *cobra.Command, interactive bool) (api.RestartPolicy, return api.RestartPolicyOnFailure, nil case api.RestartPolicyNever: return api.RestartPolicyNever, nil - default: - return "", cmdutil.UsageError(cmd, fmt.Sprintf("invalid restart policy: %s", restart)) } + return "", cmdutil.UsageErrorf(cmd, "invalid restart policy: %s") } func verifyImagePullPolicy(cmd *cobra.Command) error { @@ -503,9 +503,8 @@ func verifyImagePullPolicy(cmd *cobra.Command) error { return nil case "": return nil - default: - return cmdutil.UsageError(cmd, fmt.Sprintf("invalid image pull policy: %s", pullPolicy)) } + 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) error { diff --git a/pkg/kubectl/cmd/run_test.go b/pkg/kubectl/cmd/run_test.go index ed3b7860a9e..6520c25515b 100644 --- a/pkg/kubectl/cmd/run_test.go +++ b/pkg/kubectl/cmd/run_test.go @@ -168,12 +168,11 @@ func TestRunArgsFollowDashRules(t *testing.T) { Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { if req.URL.Path == "/namespaces/test/replicationcontrollers" { return &http.Response{StatusCode: 201, Header: defaultHeader(), Body: objBody(codec, rc)}, nil - } else { - return &http.Response{ - StatusCode: http.StatusOK, - Body: ioutil.NopCloser(bytes.NewBuffer([]byte("{}"))), - }, nil } + return &http.Response{ + StatusCode: http.StatusOK, + Body: ioutil.NopCloser(bytes.NewBuffer([]byte("{}"))), + }, nil }), } tf.Namespace = "test" diff --git a/pkg/kubectl/cmd/scale.go b/pkg/kubectl/cmd/scale.go index 722c17f8f1b..c8579cdcf4e 100644 --- a/pkg/kubectl/cmd/scale.go +++ b/pkg/kubectl/cmd/scale.go @@ -108,7 +108,7 @@ func RunScale(f cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []strin Do() err = r.Err() if resource.IsUsageError(err) { - return cmdutil.UsageError(cmd, err.Error()) + return cmdutil.UsageErrorf(cmd, "%v", err) } if err != nil { return err @@ -116,7 +116,7 @@ func RunScale(f cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []strin count := cmdutil.GetFlagInt(cmd, "replicas") if count < 0 { - return cmdutil.UsageError(cmd, "The --replicas=COUNT flag is required, and COUNT must be greater than or equal to 0") + return cmdutil.UsageErrorf(cmd, "The --replicas=COUNT flag is required, and COUNT must be greater than or equal to 0") } infos := []*resource.Info{} diff --git a/pkg/kubectl/cmd/set/set_image.go b/pkg/kubectl/cmd/set/set_image.go index 74daefc3449..b6eaf019d57 100644 --- a/pkg/kubectl/cmd/set/set_image.go +++ b/pkg/kubectl/cmd/set/set_image.go @@ -158,7 +158,7 @@ func (o *ImageOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []st func (o *ImageOptions) Validate() error { errors := []error{} - if len(o.Resources) < 1 && cmdutil.IsFilenameEmpty(o.Filenames) { + if len(o.Resources) < 1 && cmdutil.IsFilenameSliceEmpty(o.Filenames) { errors = append(errors, fmt.Errorf("one or more resources must be specified as or /")) } if len(o.ContainerImages) < 1 { diff --git a/pkg/kubectl/cmd/set/set_selector.go b/pkg/kubectl/cmd/set/set_selector.go index 3cbb8597077..26b0693f973 100644 --- a/pkg/kubectl/cmd/set/set_selector.go +++ b/pkg/kubectl/cmd/set/set_selector.go @@ -142,7 +142,7 @@ func (o *SelectorOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args [ // Validate basic inputs func (o *SelectorOptions) Validate() error { - if len(o.resources) < 1 && cmdutil.IsFilenameEmpty(o.fileOptions.Filenames) { + if len(o.resources) < 1 && cmdutil.IsFilenameSliceEmpty(o.fileOptions.Filenames) { return fmt.Errorf("one or more resources must be specified as or /") } if o.selector == nil { diff --git a/pkg/kubectl/cmd/taint.go b/pkg/kubectl/cmd/taint.go index 2b2cb42933b..ca9c0547715 100644 --- a/pkg/kubectl/cmd/taint.go +++ b/pkg/kubectl/cmd/taint.go @@ -102,7 +102,7 @@ func NewCmdTaint(f cmdutil.Factory, out io.Writer) *cobra.Command { cmdutil.CheckErr(err) } if err := options.Validate(); err != nil { - cmdutil.CheckErr(cmdutil.UsageError(cmd, err.Error())) + cmdutil.CheckErr(cmdutil.UsageErrorf(cmd, err.Error())) } if err := options.RunTaint(); err != nil { cmdutil.CheckErr(err) @@ -244,7 +244,7 @@ func (o *TaintOptions) Complete(f cmdutil.Factory, out io.Writer, cmd *cobra.Com } if o.taintsToAdd, o.taintsToRemove, err = parseTaints(taintArgs); err != nil { - return cmdutil.UsageError(cmd, err.Error()) + return cmdutil.UsageErrorf(cmd, err.Error()) } o.builder = f.NewBuilder(true). ContinueOnError(). diff --git a/pkg/kubectl/cmd/top_node.go b/pkg/kubectl/cmd/top_node.go index 1ddabbc96b3..e432a457622 100644 --- a/pkg/kubectl/cmd/top_node.go +++ b/pkg/kubectl/cmd/top_node.go @@ -83,7 +83,7 @@ func NewCmdTopNode(f cmdutil.Factory, out io.Writer) *cobra.Command { cmdutil.CheckErr(err) } if err := options.Validate(); err != nil { - cmdutil.CheckErr(cmdutil.UsageError(cmd, err.Error())) + cmdutil.CheckErr(cmdutil.UsageErrorf(cmd, "%v", err)) } if err := options.RunTopNode(); err != nil { cmdutil.CheckErr(err) @@ -101,7 +101,7 @@ func (o *TopNodeOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args [] if len(args) == 1 { o.ResourceName = args[0] } else if len(args) > 1 { - return cmdutil.UsageError(cmd, cmd.Use) + return cmdutil.UsageErrorf(cmd, "%s", cmd.Use) } clientset, err := f.ClientSet() diff --git a/pkg/kubectl/cmd/top_pod.go b/pkg/kubectl/cmd/top_pod.go index 79479dcbf00..689e6e3e2fe 100644 --- a/pkg/kubectl/cmd/top_pod.go +++ b/pkg/kubectl/cmd/top_pod.go @@ -85,7 +85,7 @@ func NewCmdTopPod(f cmdutil.Factory, out io.Writer) *cobra.Command { cmdutil.CheckErr(err) } if err := options.Validate(); err != nil { - cmdutil.CheckErr(cmdutil.UsageError(cmd, err.Error())) + cmdutil.CheckErr(cmdutil.UsageErrorf(cmd, "%v", err)) } if err := options.RunTopPod(); err != nil { cmdutil.CheckErr(err) @@ -105,7 +105,7 @@ func (o *TopPodOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []s if len(args) == 1 { o.ResourceName = args[0] } else if len(args) > 1 { - return cmdutil.UsageError(cmd, cmd.Use) + return cmdutil.UsageErrorf(cmd, "%s", cmd.Use) } o.Namespace, _, err = f.DefaultNamespace() diff --git a/pkg/kubectl/cmd/util/helpers.go b/pkg/kubectl/cmd/util/helpers.go index 1e9fc4478b7..7a1d76d3222 100644 --- a/pkg/kubectl/cmd/util/helpers.go +++ b/pkg/kubectl/cmd/util/helpers.go @@ -117,31 +117,32 @@ var ErrExit = fmt.Errorf("exit") // This method is generic to the command in use and may be used by non-Kubectl // commands. func CheckErr(err error) { - checkErr("", err, fatalErrHandler) + checkErr(err, fatalErrHandler) } // checkErrWithPrefix works like CheckErr, but adds a caller-defined prefix to non-nil errors func checkErrWithPrefix(prefix string, err error) { - checkErr(prefix, err, fatalErrHandler) + checkErr(err, fatalErrHandler) } // 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 checkErr(err error, handleErr func(string, int)) { // unwrap aggregates of 1 if agg, ok := err.(utilerrors.Aggregate); ok && len(agg.Errors()) == 1 { err = agg.Errors()[0] } - switch { - case err == nil: + if err == nil { return + } + + switch { case err == ErrExit: handleErr("", DefaultErrorExitCode) - return case kerrors.IsInvalid(err): details := err.(*kerrors.StatusError).Status().Details - s := fmt.Sprintf("%sThe %s %q is invalid", prefix, details.Kind, details.Name) + s := fmt.Sprintf("The %s %q is invalid", details.Kind, details.Name) if len(details.Causes) > 0 { errs := statusCausesToAggrError(details.Causes) handleErr(MultilineError(s+": ", errs), DefaultErrorExitCode) @@ -149,22 +150,22 @@ func checkErr(prefix string, err error, handleErr func(string, int)) { handleErr(s, DefaultErrorExitCode) } case clientcmd.IsConfigurationInvalid(err): - handleErr(MultilineError(fmt.Sprintf("%sError in configuration: ", prefix), err), DefaultErrorExitCode) + handleErr(MultilineError("Error in configuration: ", err), DefaultErrorExitCode) default: switch err := err.(type) { case *meta.NoResourceMatchError: switch { case len(err.PartialResource.Group) > 0 && len(err.PartialResource.Version) > 0: - handleErr(fmt.Sprintf("%sthe server doesn't have a resource type %q in group %q and version %q", prefix, err.PartialResource.Resource, err.PartialResource.Group, err.PartialResource.Version), DefaultErrorExitCode) + handleErr(fmt.Sprintf("the server doesn't have a resource type %q in group %q and version %q", err.PartialResource.Resource, err.PartialResource.Group, err.PartialResource.Version), DefaultErrorExitCode) case len(err.PartialResource.Group) > 0: - handleErr(fmt.Sprintf("%sthe server doesn't have a resource type %q in group %q", prefix, err.PartialResource.Resource, err.PartialResource.Group), DefaultErrorExitCode) + handleErr(fmt.Sprintf("the server doesn't have a resource type %q in group %q", err.PartialResource.Resource, err.PartialResource.Group), DefaultErrorExitCode) case len(err.PartialResource.Version) > 0: - handleErr(fmt.Sprintf("%sthe server doesn't have a resource type %q in version %q", prefix, err.PartialResource.Resource, err.PartialResource.Version), DefaultErrorExitCode) + handleErr(fmt.Sprintf("the server doesn't have a resource type %q in version %q", err.PartialResource.Resource, err.PartialResource.Version), DefaultErrorExitCode) default: - handleErr(fmt.Sprintf("%sthe server doesn't have a resource type %q", prefix, err.PartialResource.Resource), DefaultErrorExitCode) + handleErr(fmt.Sprintf("the server doesn't have a resource type %q", err.PartialResource.Resource), DefaultErrorExitCode) } case utilerrors.Aggregate: - handleErr(MultipleErrors(prefix, err.Errors()), DefaultErrorExitCode) + handleErr(MultipleErrors(``, err.Errors()), DefaultErrorExitCode) case utilexec.ExitError: // do not print anything, only terminate with given error handleErr("", err.ExitStatus()) @@ -297,26 +298,23 @@ func messageForError(err error) string { return msg } -func UsageError(cmd *cobra.Command, format string, args ...interface{}) error { +func UsageErrorf(cmd *cobra.Command, format string, args ...interface{}) error { msg := fmt.Sprintf(format, args...) return fmt.Errorf("%s\nSee '%s -h' for help and examples.", msg, cmd.CommandPath()) } -func IsFilenameEmpty(filenames []string) bool { +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"); w && err == nil { + if w, err := cmd.Flags().GetBool("watch"); err == nil && w { return true } - if wo, err := cmd.Flags().GetBool("watch-only"); wo && err == nil { - return true - } - - return false + wo, err := cmd.Flags().GetBool("watch-only") + return err == nil && wo } func GetFlagString(cmd *cobra.Command, flag string) string { @@ -533,7 +531,6 @@ func UpdateObject(info *resource.Info, codec runtime.Codec, updateFn func(runtim return info.Object, nil } -// AddCmdRecordFlag adds --record flag to command 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.") } @@ -802,7 +799,7 @@ func DefaultSubCommandRun(out io.Writer) func(c *cobra.Command, args []string) { // RequireNoArguments exits with a usage error if extra arguments are provided. func RequireNoArguments(c *cobra.Command, args []string) { if len(args) > 0 { - CheckErr(UsageError(c, fmt.Sprintf(`unknown command %q`, strings.Join(args, " ")))) + CheckErr(UsageErrorf(c, "unknown command %q", strings.Join(args, " "))) } } diff --git a/pkg/kubectl/cmd/util/helpers_test.go b/pkg/kubectl/cmd/util/helpers_test.go index ff34381787e..37278802153 100644 --- a/pkg/kubectl/cmd/util/helpers_test.go +++ b/pkg/kubectl/cmd/util/helpers_test.go @@ -284,7 +284,7 @@ func testCheckError(t *testing.T, tests []checkErrTestCase) { } for _, test := range tests { - checkErr("", test.err, errHandle) + checkErr(test.err, errHandle) if errReturned != test.expectedErr { t.Fatalf("Got: %s, expected: %s", errReturned, test.expectedErr) diff --git a/pkg/kubectl/cmd/util/printing.go b/pkg/kubectl/cmd/util/printing.go index e71a5fdc7c5..b1e9b3527d5 100644 --- a/pkg/kubectl/cmd/util/printing.go +++ b/pkg/kubectl/cmd/util/printing.go @@ -100,7 +100,7 @@ func PrintSuccess(mapper meta.RESTMapper, shortOutput bool, out io.Writer, resou func ValidateOutputArgs(cmd *cobra.Command) error { outputMode := GetFlagString(cmd, "output") if outputMode != "" && outputMode != "name" { - return UsageError(cmd, "Unexpected -o output mode: %v. We only support '-o name'.", outputMode) + return UsageErrorf(cmd, "Unexpected -o output mode: %v. We only support '-o name'.", outputMode) } return nil } diff --git a/pkg/kubectl/cmd/version.go b/pkg/kubectl/cmd/version.go index 8e0b7b4ba3c..3447524ff34 100644 --- a/pkg/kubectl/cmd/version.go +++ b/pkg/kubectl/cmd/version.go @@ -118,11 +118,5 @@ func retrieveServerVersion(f cmdutil.Factory) (*apimachineryversion.Info, error) // Always request fresh data from the server discoveryClient.Invalidate() - - serverVersion, err := discoveryClient.ServerVersion() - if err != nil { - return nil, err - } - - return serverVersion, nil + return discoveryClient.ServerVersion() } From a58232ab418b303fc53a25651ac900da888d0e6c Mon Sep 17 00:00:00 2001 From: xiangpengzhao Date: Thu, 15 Jun 2017 19:48:16 +0800 Subject: [PATCH 086/448] Add unit test case for initClusterIP and updateNodePort --- .../core/service/ipallocator/allocator.go | 3 + .../core/service/portallocator/allocator.go | 3 + pkg/registry/core/service/rest.go | 10 +- pkg/registry/core/service/rest_test.go | 266 ++++++++++++++++++ 4 files changed, 277 insertions(+), 5 deletions(-) diff --git a/pkg/registry/core/service/ipallocator/allocator.go b/pkg/registry/core/service/ipallocator/allocator.go index 7adb30101bb..fe25a30212c 100644 --- a/pkg/registry/core/service/ipallocator/allocator.go +++ b/pkg/registry/core/service/ipallocator/allocator.go @@ -33,6 +33,9 @@ type Interface interface { AllocateNext() (net.IP, error) Release(net.IP) error ForEach(func(net.IP)) + + // For testing + Has(ip net.IP) bool } var ( diff --git a/pkg/registry/core/service/portallocator/allocator.go b/pkg/registry/core/service/portallocator/allocator.go index 7badfe7ad4c..c73253f2dcb 100644 --- a/pkg/registry/core/service/portallocator/allocator.go +++ b/pkg/registry/core/service/portallocator/allocator.go @@ -34,6 +34,9 @@ type Interface interface { AllocateNext() (int, error) Release(int) error ForEach(func(int)) + + // For testing + Has(int) bool } var ( diff --git a/pkg/registry/core/service/rest.go b/pkg/registry/core/service/rest.go index 576bc599918..9195e9c5e5e 100644 --- a/pkg/registry/core/service/rest.go +++ b/pkg/registry/core/service/rest.go @@ -559,7 +559,7 @@ func (rs *REST) allocateHealthCheckNodePort(service *api.Service) error { return nil } -// The return bool value indicates if the caller should release clusterIP before return +// The return bool value indicates if a cluster IP is allocated successfully. func (rs *REST) initClusterIP(service *api.Service) (bool, error) { switch { case service.Spec.ClusterIP == "": @@ -586,19 +586,19 @@ func (rs *REST) initClusterIP(service *api.Service) (bool, error) { return false, nil } -func (rs *REST) updateNodePort(oldService, service *api.Service, nodePortOp *portallocator.PortAllocationOperation) error { +func (rs *REST) updateNodePort(oldService, newService *api.Service, nodePortOp *portallocator.PortAllocationOperation) error { oldNodePorts := CollectServiceNodePorts(oldService) newNodePorts := []int{} - for i := range service.Spec.Ports { - servicePort := &service.Spec.Ports[i] + for i := range newService.Spec.Ports { + servicePort := &newService.Spec.Ports[i] nodePort := int(servicePort.NodePort) if nodePort != 0 { if !contains(oldNodePorts, nodePort) { err := nodePortOp.Allocate(nodePort) if err != nil { el := field.ErrorList{field.Invalid(field.NewPath("spec", "ports").Index(i).Child("nodePort"), nodePort, err.Error())} - return errors.NewInvalid(api.Kind("Service"), service.Name, el) + return errors.NewInvalid(api.Kind("Service"), newService.Name, el) } } } else { diff --git a/pkg/registry/core/service/rest_test.go b/pkg/registry/core/service/rest_test.go index f6c1b1bed98..100eadb26c5 100644 --- a/pkg/registry/core/service/rest_test.go +++ b/pkg/registry/core/service/rest_test.go @@ -1276,3 +1276,269 @@ func TestServiceRegistryExternalTrafficAnnotationClusterIP(t *testing.T) { t.Errorf("Unexpected allocation of health check node port annotation %s", api.BetaAnnotationHealthCheckNodePort) } } + +func TestInitClusterIP(t *testing.T) { + storage, _ := NewTestREST(t, nil) + + testCases := []struct { + name string + svc *api.Service + expectClusterIP bool + }{ + { + name: "Allocate new ClusterIP", + svc: &api.Service{ + ObjectMeta: metav1.ObjectMeta{Name: "foo"}, + Spec: api.ServiceSpec{ + Selector: map[string]string{"bar": "baz"}, + SessionAffinity: api.ServiceAffinityNone, + Type: api.ServiceTypeClusterIP, + Ports: []api.ServicePort{{ + Port: 6502, + Protocol: api.ProtocolTCP, + TargetPort: intstr.FromInt(6502), + }}, + }, + }, + expectClusterIP: true, + }, + { + name: "Allocate specified ClusterIP", + svc: &api.Service{ + ObjectMeta: metav1.ObjectMeta{Name: "foo"}, + Spec: api.ServiceSpec{ + Selector: map[string]string{"bar": "baz"}, + SessionAffinity: api.ServiceAffinityNone, + Type: api.ServiceTypeClusterIP, + ClusterIP: "1.2.3.4", + Ports: []api.ServicePort{{ + Port: 6502, + Protocol: api.ProtocolTCP, + TargetPort: intstr.FromInt(6502), + }}, + }, + }, + expectClusterIP: true, + }, + { + name: "Shouldn't allocate ClusterIP", + svc: &api.Service{ + ObjectMeta: metav1.ObjectMeta{Name: "foo"}, + Spec: api.ServiceSpec{ + Selector: map[string]string{"bar": "baz"}, + SessionAffinity: api.ServiceAffinityNone, + Type: api.ServiceTypeClusterIP, + ClusterIP: api.ClusterIPNone, + Ports: []api.ServicePort{{ + Port: 6502, + Protocol: api.ProtocolTCP, + TargetPort: intstr.FromInt(6502), + }}, + }, + }, + expectClusterIP: false, + }, + } + + for _, test := range testCases { + hasAllocatedIP, err := storage.initClusterIP(test.svc) + if err != nil { + t.Errorf("%q: unexpected error: %v", test.name, err) + } + + if hasAllocatedIP != test.expectClusterIP { + t.Errorf("%q: expected %v, but got %v", test.name, test.expectClusterIP, hasAllocatedIP) + } + + if test.expectClusterIP { + if !storage.serviceIPs.Has(net.ParseIP(test.svc.Spec.ClusterIP)) { + t.Errorf("%q: unexpected ClusterIP %q, out of range", test.name, test.svc.Spec.ClusterIP) + } + } + + if test.name == "Allocate specified ClusterIP" && test.svc.Spec.ClusterIP != "1.2.3.4" { + t.Errorf("%q: expected ClusterIP %q, but got %q", test.name, "1.2.3.4", test.svc.Spec.ClusterIP) + } + } +} + +func TestUpdateNodePort(t *testing.T) { + storage, _ := NewTestREST(t, nil) + nodePortOp := portallocator.StartOperation(storage.serviceNodePorts) + defer nodePortOp.Finish() + + testCases := []struct { + name string + oldService *api.Service + newService *api.Service + expectSpecifiedNodePorts []int + }{ + { + name: "Old service and new service have the same NodePort", + oldService: &api.Service{ + ObjectMeta: metav1.ObjectMeta{Name: "foo"}, + Spec: api.ServiceSpec{ + Selector: map[string]string{"bar": "baz"}, + SessionAffinity: api.ServiceAffinityNone, + Type: api.ServiceTypeNodePort, + Ports: []api.ServicePort{{ + Port: 6502, + Protocol: api.ProtocolTCP, + TargetPort: intstr.FromInt(6502), + NodePort: 30053, + }}, + }, + }, + newService: &api.Service{ + ObjectMeta: metav1.ObjectMeta{Name: "foo"}, + Spec: api.ServiceSpec{ + Selector: map[string]string{"bar": "baz"}, + SessionAffinity: api.ServiceAffinityNone, + Type: api.ServiceTypeNodePort, + Ports: []api.ServicePort{{ + Port: 6502, + Protocol: api.ProtocolTCP, + TargetPort: intstr.FromInt(6502), + NodePort: 30053, + }}, + }, + }, + expectSpecifiedNodePorts: []int{30053}, + }, + { + name: "Old service has more NodePorts than new service has", + oldService: &api.Service{ + ObjectMeta: metav1.ObjectMeta{Name: "foo"}, + Spec: api.ServiceSpec{ + Selector: map[string]string{"bar": "baz"}, + SessionAffinity: api.ServiceAffinityNone, + Type: api.ServiceTypeNodePort, + Ports: []api.ServicePort{ + { + Name: "port-tcp", + Port: 53, + TargetPort: intstr.FromInt(6502), + Protocol: api.ProtocolTCP, + NodePort: 30053, + }, + { + Name: "port-udp", + Port: 53, + TargetPort: intstr.FromInt(6502), + Protocol: api.ProtocolUDP, + NodePort: 30053, + }, + }, + }, + }, + newService: &api.Service{ + ObjectMeta: metav1.ObjectMeta{Name: "foo"}, + Spec: api.ServiceSpec{ + Selector: map[string]string{"bar": "baz"}, + SessionAffinity: api.ServiceAffinityNone, + Type: api.ServiceTypeNodePort, + Ports: []api.ServicePort{ + { + Name: "port-tcp", + Port: 53, + TargetPort: intstr.FromInt(6502), + Protocol: api.ProtocolTCP, + NodePort: 30053, + }, + }, + }, + }, + expectSpecifiedNodePorts: []int{30053}, + }, + { + name: "Change protocol of ServicePort without changing NodePort", + oldService: &api.Service{ + ObjectMeta: metav1.ObjectMeta{Name: "foo"}, + Spec: api.ServiceSpec{ + Selector: map[string]string{"bar": "baz"}, + SessionAffinity: api.ServiceAffinityNone, + Type: api.ServiceTypeNodePort, + Ports: []api.ServicePort{ + { + Name: "port-tcp", + Port: 53, + TargetPort: intstr.FromInt(6502), + Protocol: api.ProtocolTCP, + NodePort: 30053, + }, + }, + }, + }, + newService: &api.Service{ + ObjectMeta: metav1.ObjectMeta{Name: "foo"}, + Spec: api.ServiceSpec{ + Selector: map[string]string{"bar": "baz"}, + SessionAffinity: api.ServiceAffinityNone, + Type: api.ServiceTypeNodePort, + Ports: []api.ServicePort{ + { + Name: "port-udp", + Port: 53, + TargetPort: intstr.FromInt(6502), + Protocol: api.ProtocolUDP, + NodePort: 30053, + }, + }, + }, + }, + expectSpecifiedNodePorts: []int{30053}, + }, + { + name: "Should allocate NodePort when changing service type to NodePort", + oldService: &api.Service{ + ObjectMeta: metav1.ObjectMeta{Name: "foo"}, + Spec: api.ServiceSpec{ + Selector: map[string]string{"bar": "baz"}, + SessionAffinity: api.ServiceAffinityNone, + Type: api.ServiceTypeClusterIP, + Ports: []api.ServicePort{{ + Port: 6502, + Protocol: api.ProtocolTCP, + TargetPort: intstr.FromInt(6502), + }}, + }, + }, + newService: &api.Service{ + ObjectMeta: metav1.ObjectMeta{Name: "foo"}, + Spec: api.ServiceSpec{ + Selector: map[string]string{"bar": "baz"}, + SessionAffinity: api.ServiceAffinityNone, + Type: api.ServiceTypeNodePort, + Ports: []api.ServicePort{{ + Port: 6502, + Protocol: api.ProtocolTCP, + TargetPort: intstr.FromInt(6502), + }}, + }, + }, + expectSpecifiedNodePorts: []int{}, + }, + } + + for _, test := range testCases { + err := storage.updateNodePort(test.oldService, test.newService, nodePortOp) + if err != nil { + t.Errorf("%q: unexpected error: %v", test.name, err) + continue + } + _ = nodePortOp.Commit() + + serviceNodePorts := CollectServiceNodePorts(test.newService) + + if len(test.expectSpecifiedNodePorts) == 0 { + for _, nodePort := range serviceNodePorts { + if !storage.serviceNodePorts.Has(nodePort) { + t.Errorf("%q: unexpected NodePort %d, out of range", test.name, nodePort) + } + } + } else if !reflect.DeepEqual(serviceNodePorts, test.expectSpecifiedNodePorts) { + t.Errorf("%q: expected NodePorts %v, but got %v", test.name, test.expectSpecifiedNodePorts, serviceNodePorts) + } + + } +} From 82f782006604f3eec8c59204df5c54178037f38a Mon Sep 17 00:00:00 2001 From: Vishnu kannan Date: Mon, 26 Jun 2017 12:49:00 -0700 Subject: [PATCH 087/448] Kubelet: Centralize Capacity discovery of standard resources in Container manager. Have storage derive node capacity from container manager. Move certain cAdvisor interfaces to the cAdvisor package in the process. This patch fixes a bug in container manager where it was writing to a map without synchronization. Signed-off-by: Vishnu kannan --- pkg/kubelet/cadvisor/cadvisor_linux.go | 13 ++++++ pkg/kubelet/cadvisor/cadvisor_unsupported.go | 4 ++ pkg/kubelet/cadvisor/cadvisor_windows.go | 4 ++ pkg/kubelet/cadvisor/testing/cadvisor_fake.go | 4 ++ pkg/kubelet/cadvisor/testing/cadvisor_mock.go | 5 +++ pkg/kubelet/cadvisor/types.go | 3 ++ pkg/kubelet/cm/container_manager.go | 3 ++ pkg/kubelet/cm/container_manager_linux.go | 19 ++++++++ pkg/kubelet/cm/container_manager_stub.go | 4 ++ pkg/kubelet/cm/node_container_manager.go | 12 ----- pkg/kubelet/kubelet.go | 2 +- pkg/kubelet/kubelet_cadvisor.go | 13 ------ pkg/kubelet/kubelet_cadvisor_test.go | 32 ------------- pkg/kubelet/kubelet_node_status.go | 28 +++++------- pkg/kubelet/kubelet_node_status_test.go | 45 +++++++++++++++++++ 15 files changed, 115 insertions(+), 76 deletions(-) diff --git a/pkg/kubelet/cadvisor/cadvisor_linux.go b/pkg/kubelet/cadvisor/cadvisor_linux.go index f0392063e09..cdbe96a27e4 100644 --- a/pkg/kubelet/cadvisor/cadvisor_linux.go +++ b/pkg/kubelet/cadvisor/cadvisor_linux.go @@ -225,3 +225,16 @@ func (cc *cadvisorClient) getFsInfo(label string) (cadvisorapiv2.FsInfo, error) func (cc *cadvisorClient) WatchEvents(request *events.Request) (*events.EventChannel, error) { return cc.WatchForEvents(request) } + +// HasDedicatedImageFs returns true if the imagefs has a dedicated device. +func (cc *cadvisorClient) HasDedicatedImageFs() (bool, error) { + imageFsInfo, err := cc.ImagesFsInfo() + if err != nil { + return false, err + } + rootFsInfo, err := cc.RootFsInfo() + if err != nil { + return false, err + } + return imageFsInfo.Device != rootFsInfo.Device, nil +} diff --git a/pkg/kubelet/cadvisor/cadvisor_unsupported.go b/pkg/kubelet/cadvisor/cadvisor_unsupported.go index 23378242775..788629c3392 100644 --- a/pkg/kubelet/cadvisor/cadvisor_unsupported.go +++ b/pkg/kubelet/cadvisor/cadvisor_unsupported.go @@ -76,3 +76,7 @@ func (cu *cadvisorUnsupported) RootFsInfo() (cadvisorapiv2.FsInfo, error) { func (cu *cadvisorUnsupported) WatchEvents(request *events.Request) (*events.EventChannel, error) { return nil, unsupportedErr } + +func (cu *cadvisorUnsupported) HasDedicatedImageFs() (bool, error) { + return false, unsupportedErr +} diff --git a/pkg/kubelet/cadvisor/cadvisor_windows.go b/pkg/kubelet/cadvisor/cadvisor_windows.go index 832208658fc..f7e265ec678 100644 --- a/pkg/kubelet/cadvisor/cadvisor_windows.go +++ b/pkg/kubelet/cadvisor/cadvisor_windows.go @@ -73,3 +73,7 @@ func (cu *cadvisorClient) RootFsInfo() (cadvisorapiv2.FsInfo, error) { func (cu *cadvisorClient) WatchEvents(request *events.Request) (*events.EventChannel, error) { return &events.EventChannel{}, nil } + +func (cu *cadvisorClient) HasDedicatedImageFs() (bool, error) { + return false, nil +} diff --git a/pkg/kubelet/cadvisor/testing/cadvisor_fake.go b/pkg/kubelet/cadvisor/testing/cadvisor_fake.go index 894c6f0c976..64566712504 100644 --- a/pkg/kubelet/cadvisor/testing/cadvisor_fake.go +++ b/pkg/kubelet/cadvisor/testing/cadvisor_fake.go @@ -73,3 +73,7 @@ func (c *Fake) RootFsInfo() (cadvisorapiv2.FsInfo, error) { func (c *Fake) WatchEvents(request *events.Request) (*events.EventChannel, error) { return new(events.EventChannel), nil } + +func (c *Fake) HasDedicatedImageFs() (bool, error) { + return false, nil +} diff --git a/pkg/kubelet/cadvisor/testing/cadvisor_mock.go b/pkg/kubelet/cadvisor/testing/cadvisor_mock.go index a6ba72c8784..7848039178a 100644 --- a/pkg/kubelet/cadvisor/testing/cadvisor_mock.go +++ b/pkg/kubelet/cadvisor/testing/cadvisor_mock.go @@ -83,3 +83,8 @@ func (c *Mock) WatchEvents(request *events.Request) (*events.EventChannel, error args := c.Called() return args.Get(0).(*events.EventChannel), args.Error(1) } + +func (c *Mock) HasDedicatedImageFs() (bool, error) { + args := c.Called() + return args.Get(0).(bool), args.Error(1) +} diff --git a/pkg/kubelet/cadvisor/types.go b/pkg/kubelet/cadvisor/types.go index de7d334c1b7..2a97ba35237 100644 --- a/pkg/kubelet/cadvisor/types.go +++ b/pkg/kubelet/cadvisor/types.go @@ -41,4 +41,7 @@ type Interface interface { // Get events streamed through passedChannel that fit the request. WatchEvents(request *events.Request) (*events.EventChannel, error) + + // HasDedicatedImageFs returns true iff a dedicated image filesystem exists for storing images. + HasDedicatedImageFs() (bool, error) } diff --git a/pkg/kubelet/cm/container_manager.go b/pkg/kubelet/cm/container_manager.go index 467a97ca045..77e5dd187e4 100644 --- a/pkg/kubelet/cm/container_manager.go +++ b/pkg/kubelet/cm/container_manager.go @@ -60,6 +60,9 @@ type ContainerManager interface { // GetNodeAllocatable returns the amount of compute resources that have to be reserved from scheduling. GetNodeAllocatableReservation() v1.ResourceList + // GetCapacity returns the amount of compute resources tracked by container manager available on the node. + GetCapacity() v1.ResourceList + // UpdateQOSCgroups performs housekeeping updates to ensure that the top // level QoS containers have their desired state in a thread-safe way UpdateQOSCgroups() error diff --git a/pkg/kubelet/cm/container_manager_linux.go b/pkg/kubelet/cm/container_manager_linux.go index 8a144c4c03a..c652feb9ae4 100644 --- a/pkg/kubelet/cm/container_manager_linux.go +++ b/pkg/kubelet/cm/container_manager_linux.go @@ -224,6 +224,25 @@ func NewContainerManager(mountUtil mount.Interface, cadvisorInterface cadvisor.I } else { return nil, err } + rootfs, err := cadvisorInterface.RootFsInfo() + if err != nil { + capacity[v1.ResourceStorageScratch] = resource.MustParse("0Gi") + } else { + for rName, rCap := range cadvisor.StorageScratchCapacityFromFsInfo(rootfs) { + capacity[rName] = rCap + } + } + + if hasDedicatedImageFs, _ := cadvisorInterface.HasDedicatedImageFs(); hasDedicatedImageFs { + imagesfs, err := cadvisorInterface.ImagesFsInfo() + if err != nil { + glog.Errorf("Failed to get Image filesystem information: %v", err) + } else { + for rName, rCap := range cadvisor.StorageOverlayCapacityFromFsInfo(imagesfs) { + capacity[rName] = rCap + } + } + } cgroupRoot := nodeConfig.CgroupRoot cgroupManager := NewCgroupManager(subsystems, nodeConfig.CgroupDriver) diff --git a/pkg/kubelet/cm/container_manager_stub.go b/pkg/kubelet/cm/container_manager_stub.go index caa9c611d5a..941913aceee 100644 --- a/pkg/kubelet/cm/container_manager_stub.go +++ b/pkg/kubelet/cm/container_manager_stub.go @@ -58,6 +58,10 @@ func (cm *containerManagerStub) GetNodeAllocatableReservation() v1.ResourceList return nil } +func (cm *containerManagerStub) GetCapacity() v1.ResourceList { + return nil +} + func (cm *containerManagerStub) NewPodContainerManager() PodContainerManager { return &podContainerManagerStub{} } diff --git a/pkg/kubelet/cm/node_container_manager.go b/pkg/kubelet/cm/node_container_manager.go index 11f321ed8c3..bb6359f2d4e 100644 --- a/pkg/kubelet/cm/node_container_manager.go +++ b/pkg/kubelet/cm/node_container_manager.go @@ -29,7 +29,6 @@ import ( clientv1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" "k8s.io/apimachinery/pkg/types" - "k8s.io/kubernetes/pkg/kubelet/cadvisor" "k8s.io/kubernetes/pkg/kubelet/events" evictionapi "k8s.io/kubernetes/pkg/kubelet/eviction/api" ) @@ -184,17 +183,6 @@ func (cm *containerManagerImpl) getNodeAllocatableAbsolute() v1.ResourceList { // GetNodeAllocatable returns amount of compute or storage resource that have to be reserved on this node from scheduling. func (cm *containerManagerImpl) GetNodeAllocatableReservation() v1.ResourceList { evictionReservation := hardEvictionReservation(cm.HardEvictionThresholds, cm.capacity) - if _, ok := cm.capacity[v1.ResourceStorage]; !ok { - if cm.cadvisorInterface != nil { - if rootfs, err := cm.cadvisorInterface.RootFsInfo(); err == nil { - for rName, rCap := range cadvisor.StorageScratchCapacityFromFsInfo(rootfs) { - cm.capacity[rName] = rCap - } - } else { - glog.Warning("Error getting rootfs info: %v", err) - } - } - } result := make(v1.ResourceList) for k := range cm.capacity { value := resource.NewQuantity(0, resource.DecimalSI) diff --git a/pkg/kubelet/kubelet.go b/pkg/kubelet/kubelet.go index c76cb7532cd..bdbf2aaddaf 100644 --- a/pkg/kubelet/kubelet.go +++ b/pkg/kubelet/kubelet.go @@ -1301,7 +1301,7 @@ func (kl *Kubelet) initializeRuntimeDependentModules() { glog.Fatalf("Failed to start cAdvisor %v", err) } // eviction manager must start after cadvisor because it needs to know if the container runtime has a dedicated imagefs - kl.evictionManager.Start(kl, kl.GetActivePods, kl.podResourcesAreReclaimed, kl, evictionMonitoringPeriod) + kl.evictionManager.Start(kl.cadvisor, kl.GetActivePods, kl.podResourcesAreReclaimed, kl, evictionMonitoringPeriod) } // Run starts the kubelet reacting to config updates diff --git a/pkg/kubelet/kubelet_cadvisor.go b/pkg/kubelet/kubelet_cadvisor.go index dcb3de9728e..779095f5675 100644 --- a/pkg/kubelet/kubelet_cadvisor.go +++ b/pkg/kubelet/kubelet_cadvisor.go @@ -45,19 +45,6 @@ func (kl *Kubelet) GetContainerInfo(podFullName string, podUID types.UID, contai return &ci, nil } -// HasDedicatedImageFs returns true if the imagefs has a dedicated device. -func (kl *Kubelet) HasDedicatedImageFs() (bool, error) { - imageFsInfo, err := kl.ImagesFsInfo() - if err != nil { - return false, err - } - rootFsInfo, err := kl.RootFsInfo() - if err != nil { - return false, err - } - return imageFsInfo.Device != rootFsInfo.Device, nil -} - // GetContainerInfoV2 returns stats (from Cadvisor) for containers. func (kl *Kubelet) GetContainerInfoV2(name string, options cadvisorapiv2.RequestOptions) (map[string]cadvisorapiv2.ContainerInfo, error) { return kl.cadvisor.ContainerInfoV2(name, options) diff --git a/pkg/kubelet/kubelet_cadvisor_test.go b/pkg/kubelet/kubelet_cadvisor_test.go index bfbdc9e8812..aa269f68f9d 100644 --- a/pkg/kubelet/kubelet_cadvisor_test.go +++ b/pkg/kubelet/kubelet_cadvisor_test.go @@ -24,7 +24,6 @@ import ( "github.com/stretchr/testify/require" cadvisorapi "github.com/google/cadvisor/info/v1" - cadvisorapiv2 "github.com/google/cadvisor/info/v2" "k8s.io/apimachinery/pkg/types" kubecontainer "k8s.io/kubernetes/pkg/kubelet/container" kubecontainertest "k8s.io/kubernetes/pkg/kubelet/container/testing" @@ -251,34 +250,3 @@ func TestGetRawContainerInfoSubcontainers(t *testing.T) { assert.Len(t, result, 2) mockCadvisor.AssertExpectations(t) } - -func TestHasDedicatedImageFs(t *testing.T) { - testCases := map[string]struct { - imageFsInfo cadvisorapiv2.FsInfo - rootFsInfo cadvisorapiv2.FsInfo - expected bool - }{ - "has-dedicated-image-fs": { - imageFsInfo: cadvisorapiv2.FsInfo{Device: "123"}, - rootFsInfo: cadvisorapiv2.FsInfo{Device: "456"}, - expected: true, - }, - "has-unified-image-fs": { - imageFsInfo: cadvisorapiv2.FsInfo{Device: "123"}, - rootFsInfo: cadvisorapiv2.FsInfo{Device: "123"}, - expected: false, - }, - } - for testName, testCase := range testCases { - testKubelet := newTestKubelet(t, false /* controllerAttachDetachEnabled */) - defer testKubelet.Cleanup() - kubelet := testKubelet.kubelet - mockCadvisor := testKubelet.fakeCadvisor - mockCadvisor.On("Start").Return(nil) - mockCadvisor.On("ImagesFsInfo").Return(testCase.imageFsInfo, nil) - mockCadvisor.On("RootFsInfo").Return(testCase.rootFsInfo, nil) - actual, err := kubelet.HasDedicatedImageFs() - assert.NoError(t, err, "test [%s]", testName) - assert.Equal(t, testCase.expected, actual, "test [%s]", testName) - } -} diff --git a/pkg/kubelet/kubelet_node_status.go b/pkg/kubelet/kubelet_node_status.go index 09e4230122f..493ac03eaba 100644 --- a/pkg/kubelet/kubelet_node_status.go +++ b/pkg/kubelet/kubelet_node_status.go @@ -549,6 +549,7 @@ func (kl *Kubelet) setNodeStatusMachineInfo(node *v1.Node) { node.Status.Capacity[v1.ResourcePods] = *resource.NewQuantity( int64(kl.maxPods), resource.DecimalSI) } + if node.Status.NodeInfo.BootID != "" && node.Status.NodeInfo.BootID != info.BootID { // TODO: This requires a transaction, either both node status is updated @@ -557,25 +558,16 @@ func (kl *Kubelet) setNodeStatusMachineInfo(node *v1.Node) { "Node %s has been rebooted, boot id: %s", kl.nodeName, info.BootID) } node.Status.NodeInfo.BootID = info.BootID - } - if utilfeature.DefaultFeatureGate.Enabled(features.LocalStorageCapacityIsolation) { - rootfs, err := kl.GetCachedRootFsInfo() - if err != nil { - node.Status.Capacity[v1.ResourceStorageScratch] = resource.MustParse("0Gi") - } else { - for rName, rCap := range cadvisor.StorageScratchCapacityFromFsInfo(rootfs) { - node.Status.Capacity[rName] = rCap - } - } - - if hasDedicatedImageFs, _ := kl.HasDedicatedImageFs(); hasDedicatedImageFs { - imagesfs, err := kl.ImagesFsInfo() - if err != nil { - node.Status.Capacity[v1.ResourceStorageOverlay] = resource.MustParse("0Gi") - } else { - for rName, rCap := range cadvisor.StorageOverlayCapacityFromFsInfo(imagesfs) { - node.Status.Capacity[rName] = rCap + if utilfeature.DefaultFeatureGate.Enabled(features.LocalStorageCapacityIsolation) { + // TODO: all the node resources should use GetCapacity instead of deriving the + // capacity for every node status request + initialCapacity := kl.containerManager.GetCapacity() + if initialCapacity != nil { + node.Status.Capacity[v1.ResourceStorageScratch] = initialCapacity[v1.ResourceStorageScratch] + imageCapacity, ok := initialCapacity[v1.ResourceStorageOverlay] + if ok { + node.Status.Capacity[v1.ResourceStorageOverlay] = imageCapacity } } } diff --git a/pkg/kubelet/kubelet_node_status_test.go b/pkg/kubelet/kubelet_node_status_test.go index 69f4278b161..6337e8bd117 100644 --- a/pkg/kubelet/kubelet_node_status_test.go +++ b/pkg/kubelet/kubelet_node_status_test.go @@ -115,12 +115,17 @@ func applyNodeStatusPatch(originalNode *v1.Node, patch []byte) (*v1.Node, error) type localCM struct { cm.ContainerManager allocatable v1.ResourceList + capacity v1.ResourceList } func (lcm *localCM) GetNodeAllocatableReservation() v1.ResourceList { return lcm.allocatable } +func (lcm *localCM) GetCapacity() v1.ResourceList { + return lcm.capacity +} + func TestUpdateNewNodeStatus(t *testing.T) { // generate one more than maxImagesInNodeStatus in inputImageList inputImageList, expectedImageList := generateTestingImageList(maxImagesInNodeStatus + 1) @@ -134,6 +139,10 @@ func TestUpdateNewNodeStatus(t *testing.T) { v1.ResourceCPU: *resource.NewMilliQuantity(200, resource.DecimalSI), v1.ResourceMemory: *resource.NewQuantity(100E6, resource.BinarySI), }, + capacity: v1.ResourceList{ + v1.ResourceCPU: *resource.NewMilliQuantity(2000, resource.DecimalSI), + v1.ResourceMemory: *resource.NewQuantity(10E9, resource.BinarySI), + }, } kubeClient := testKubelet.fakeKubeClient existingNode := v1.Node{ObjectMeta: metav1.ObjectMeta{Name: testKubeletHostname}} @@ -251,6 +260,18 @@ func TestUpdateNewNodeOutOfDiskStatusWithTransitionFrequency(t *testing.T) { testKubelet := newTestKubelet(t, false /* controllerAttachDetachEnabled */) defer testKubelet.Cleanup() kubelet := testKubelet.kubelet + kubelet.containerManager = &localCM{ + ContainerManager: cm.NewStubContainerManager(), + allocatable: v1.ResourceList{ + v1.ResourceCPU: *resource.NewMilliQuantity(200, resource.DecimalSI), + v1.ResourceMemory: *resource.NewQuantity(100E6, resource.BinarySI), + }, + capacity: v1.ResourceList{ + v1.ResourceCPU: *resource.NewMilliQuantity(2000, resource.DecimalSI), + v1.ResourceMemory: *resource.NewQuantity(20E9, resource.BinarySI), + }, + } + kubeClient := testKubelet.fakeKubeClient existingNode := v1.Node{ObjectMeta: metav1.ObjectMeta{Name: testKubeletHostname}} kubeClient.ReactionChain = fake.NewSimpleClientset(&v1.NodeList{Items: []v1.Node{existingNode}}).ReactionChain @@ -319,6 +340,10 @@ func TestUpdateExistingNodeStatus(t *testing.T) { v1.ResourceCPU: *resource.NewMilliQuantity(200, resource.DecimalSI), v1.ResourceMemory: *resource.NewQuantity(100E6, resource.BinarySI), }, + capacity: v1.ResourceList{ + v1.ResourceCPU: *resource.NewMilliQuantity(2000, resource.DecimalSI), + v1.ResourceMemory: *resource.NewQuantity(20E9, resource.BinarySI), + }, } kubeClient := testKubelet.fakeKubeClient @@ -503,6 +528,18 @@ func TestUpdateExistingNodeOutOfDiskStatusWithTransitionFrequency(t *testing.T) testKubelet := newTestKubelet(t, false /* controllerAttachDetachEnabled */) defer testKubelet.Cleanup() kubelet := testKubelet.kubelet + kubelet.containerManager = &localCM{ + ContainerManager: cm.NewStubContainerManager(), + allocatable: v1.ResourceList{ + v1.ResourceCPU: *resource.NewMilliQuantity(200, resource.DecimalSI), + v1.ResourceMemory: *resource.NewQuantity(100E6, resource.BinarySI), + }, + capacity: v1.ResourceList{ + v1.ResourceCPU: *resource.NewMilliQuantity(2000, resource.DecimalSI), + v1.ResourceMemory: *resource.NewQuantity(20E9, resource.BinarySI), + }, + } + clock := testKubelet.fakeClock // Do not set nano second, because apiserver function doesn't support nano second. (Only support // RFC3339). @@ -658,6 +695,10 @@ func TestUpdateNodeStatusWithRuntimeStateError(t *testing.T) { v1.ResourceCPU: *resource.NewMilliQuantity(200, resource.DecimalSI), v1.ResourceMemory: *resource.NewQuantity(100E6, resource.BinarySI), }, + capacity: v1.ResourceList{ + v1.ResourceCPU: *resource.NewMilliQuantity(2000, resource.DecimalSI), + v1.ResourceMemory: *resource.NewQuantity(10E9, resource.BinarySI), + }, } clock := testKubelet.fakeClock @@ -1113,6 +1154,10 @@ func TestUpdateNewNodeStatusTooLargeReservation(t *testing.T) { allocatable: v1.ResourceList{ v1.ResourceCPU: *resource.NewMilliQuantity(40000, resource.DecimalSI), }, + capacity: v1.ResourceList{ + v1.ResourceCPU: *resource.NewMilliQuantity(2000, resource.DecimalSI), + v1.ResourceMemory: *resource.NewQuantity(10E9, resource.BinarySI), + }, } kubeClient := testKubelet.fakeKubeClient existingNode := v1.Node{ObjectMeta: metav1.ObjectMeta{Name: testKubeletHostname}} From 159fa86d989e7a26e80fe80537efa09369d2e6c5 Mon Sep 17 00:00:00 2001 From: Guangya Liu Date: Fri, 9 Jun 2017 06:59:28 +0800 Subject: [PATCH 088/448] Follow up for https://github.com/kubernetes/kubernetes/pull/47003 --- .../src/k8s.io/apimachinery/pkg/util/errors/errors.go | 2 +- .../apimachinery/pkg/util/errors/errors_test.go | 11 ++++++++--- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/staging/src/k8s.io/apimachinery/pkg/util/errors/errors.go b/staging/src/k8s.io/apimachinery/pkg/util/errors/errors.go index bdea0e16c72..26e7eb2082f 100644 --- a/staging/src/k8s.io/apimachinery/pkg/util/errors/errors.go +++ b/staging/src/k8s.io/apimachinery/pkg/util/errors/errors.go @@ -21,7 +21,7 @@ import ( "fmt" ) -// MessagesgCountMap contains occurance for each error message. +// MessageCountMap contains occurance for each error message. type MessageCountMap map[string]int // Aggregate represents an object that contains multiple errors, but does not diff --git a/staging/src/k8s.io/apimachinery/pkg/util/errors/errors_test.go b/staging/src/k8s.io/apimachinery/pkg/util/errors/errors_test.go index 3335326cab1..0ad3967d285 100644 --- a/staging/src/k8s.io/apimachinery/pkg/util/errors/errors_test.go +++ b/staging/src/k8s.io/apimachinery/pkg/util/errors/errors_test.go @@ -266,7 +266,7 @@ func TestFlatten(t *testing.T) { func TestCreateAggregateFromMessageCountMap(t *testing.T) { testCases := []struct { name string - mcp MessageCountMap + mcm MessageCountMap expected Aggregate }{ { @@ -279,6 +279,11 @@ func TestCreateAggregateFromMessageCountMap(t *testing.T) { MessageCountMap{"abc": 2, "ghi": 1}, aggregate{fmt.Errorf("abc (repeated 2 times)"), fmt.Errorf("ghi")}, }, + { + "input has multiple messages", + MessageCountMap{"ghi": 1, "abc": 2}, + aggregate{fmt.Errorf("abc (repeated 2 times)"), fmt.Errorf("ghi")}, + }, } var expected, agg []error @@ -288,8 +293,8 @@ func TestCreateAggregateFromMessageCountMap(t *testing.T) { expected = testCase.expected.Errors() sort.Slice(expected, func(i, j int) bool { return expected[i].Error() < expected[j].Error() }) } - if testCase.mcp != nil { - agg = CreateAggregateFromMessageCountMap(testCase.mcp).Errors() + if testCase.mcm != nil { + agg = CreateAggregateFromMessageCountMap(testCase.mcm).Errors() sort.Slice(agg, func(i, j int) bool { return agg[i].Error() < agg[j].Error() }) } if !reflect.DeepEqual(expected, agg) { From 9e31eb280a70db59cce6434417b16c57972ed1a3 Mon Sep 17 00:00:00 2001 From: xiangpengzhao Date: Fri, 9 Jun 2017 23:22:37 +0800 Subject: [PATCH 089/448] Populate endpoints and allow ports with headless service --- pkg/api/validation/validation.go | 4 +- pkg/api/validation/validation_test.go | 19 ++- .../endpoint/endpoints_controller.go | 121 ++++++++++-------- .../endpoint/endpoints_controller_test.go | 41 ++++++ pkg/kubectl/service_basic.go | 4 +- pkg/kubectl/service_basic_test.go | 24 +++- pkg/kubectl/service_test.go | 20 +++ pkg/proxy/iptables/proxier_test.go | 4 + 8 files changed, 161 insertions(+), 76 deletions(-) diff --git a/pkg/api/validation/validation.go b/pkg/api/validation/validation.go index 99c63f9a382..fc119192491 100644 --- a/pkg/api/validation/validation.go +++ b/pkg/api/validation/validation.go @@ -4012,13 +4012,11 @@ func validateEndpointSubsets(subsets []api.EndpointSubset, oldSubsets []api.Endp ss := &subsets[i] idxPath := fldPath.Index(i) + // EndpointSubsets must include endpoint address. For headless service, we allow its endpoints not to have ports. if len(ss.Addresses) == 0 && len(ss.NotReadyAddresses) == 0 { //TODO: consider adding a RequiredOneOf() error for this and similar cases allErrs = append(allErrs, field.Required(idxPath, "must specify `addresses` or `notReadyAddresses`")) } - if len(ss.Ports) == 0 { - allErrs = append(allErrs, field.Required(idxPath.Child("ports"), "")) - } for addr := range ss.Addresses { allErrs = append(allErrs, validateEndpointAddress(&ss.Addresses[addr], idxPath.Child("addresses").Index(addr), ipToNodeName)...) } diff --git a/pkg/api/validation/validation_test.go b/pkg/api/validation/validation_test.go index e29e97aaad4..788b2ee59ef 100644 --- a/pkg/api/validation/validation_test.go +++ b/pkg/api/validation/validation_test.go @@ -9463,6 +9463,14 @@ func TestValidateEndpoints(t *testing.T) { }, }, }, + "empty ports": { + ObjectMeta: metav1.ObjectMeta{Name: "mysvc", Namespace: "namespace"}, + Subsets: []api.EndpointSubset{ + { + Addresses: []api.EndpointAddress{{IP: "10.10.3.3"}}, + }, + }, + }, } for k, v := range successCases { @@ -9505,17 +9513,6 @@ func TestValidateEndpoints(t *testing.T) { }, errorType: "FieldValueRequired", }, - "empty ports": { - endpoints: api.Endpoints{ - ObjectMeta: metav1.ObjectMeta{Name: "mysvc", Namespace: "namespace"}, - Subsets: []api.EndpointSubset{ - { - Addresses: []api.EndpointAddress{{IP: "10.10.3.3"}}, - }, - }, - }, - errorType: "FieldValueRequired", - }, "invalid IP": { endpoints: api.Endpoints{ ObjectMeta: metav1.ObjectMeta{Name: "mysvc", Namespace: "namespace"}, diff --git a/pkg/controller/endpoint/endpoints_controller.go b/pkg/controller/endpoint/endpoints_controller.go index f13b80f8de0..78cf37a95a7 100644 --- a/pkg/controller/endpoint/endpoints_controller.go +++ b/pkg/controller/endpoint/endpoints_controller.go @@ -354,8 +354,6 @@ func (e *EndpointController) syncService(key string) error { return err } - subsets := []v1.EndpointSubset{} - var tolerateUnreadyEndpoints bool if v, ok := service.Annotations[TolerateUnreadyEndpointsAnnotation]; ok { b, err := strconv.ParseBool(v) @@ -366,61 +364,59 @@ func (e *EndpointController) syncService(key string) error { } } - readyEps := 0 - notReadyEps := 0 + subsets := []v1.EndpointSubset{} + var totalReadyEps int = 0 + var totalNotReadyEps int = 0 + for _, pod := range pods { + if len(pod.Status.PodIP) == 0 { + glog.V(5).Infof("Failed to find an IP for pod %s/%s", pod.Namespace, pod.Name) + continue + } + if !tolerateUnreadyEndpoints && pod.DeletionTimestamp != nil { + glog.V(5).Infof("Pod is being deleted %s/%s", pod.Namespace, pod.Name) + continue + } - for i := range service.Spec.Ports { - servicePort := &service.Spec.Ports[i] + epa := v1.EndpointAddress{ + IP: pod.Status.PodIP, + NodeName: &pod.Spec.NodeName, + TargetRef: &v1.ObjectReference{ + Kind: "Pod", + Namespace: pod.ObjectMeta.Namespace, + Name: pod.ObjectMeta.Name, + UID: pod.ObjectMeta.UID, + ResourceVersion: pod.ObjectMeta.ResourceVersion, + }} - portName := servicePort.Name - portProto := servicePort.Protocol - portNum, err := podutil.FindPort(pod, servicePort) - if err != nil { - glog.V(4).Infof("Failed to find port for service %s/%s: %v", service.Namespace, service.Name, err) - continue - } - if len(pod.Status.PodIP) == 0 { - glog.V(5).Infof("Failed to find an IP for pod %s/%s", pod.Namespace, pod.Name) - continue - } - if !tolerateUnreadyEndpoints && pod.DeletionTimestamp != nil { - glog.V(5).Infof("Pod is being deleted %s/%s", pod.Namespace, pod.Name) - continue + hostname := pod.Spec.Hostname + if len(hostname) > 0 && pod.Spec.Subdomain == service.Name && service.Namespace == pod.Namespace { + epa.Hostname = hostname + } + + // 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) } + } else { + for i := range service.Spec.Ports { + servicePort := &service.Spec.Ports[i] - epp := v1.EndpointPort{Name: portName, Port: int32(portNum), Protocol: portProto} - epa := v1.EndpointAddress{ - IP: pod.Status.PodIP, - NodeName: &pod.Spec.NodeName, - TargetRef: &v1.ObjectReference{ - Kind: "Pod", - Namespace: pod.ObjectMeta.Namespace, - Name: pod.ObjectMeta.Name, - UID: pod.ObjectMeta.UID, - ResourceVersion: pod.ObjectMeta.ResourceVersion, - }} + portName := servicePort.Name + portProto := servicePort.Protocol + portNum, err := podutil.FindPort(pod, servicePort) + if err != nil { + glog.V(4).Infof("Failed to find port for service %s/%s: %v", service.Namespace, service.Name, err) + continue + } - hostname := pod.Spec.Hostname - if len(hostname) > 0 && - pod.Spec.Subdomain == service.Name && - service.Namespace == pod.Namespace { - epa.Hostname = hostname - } - - if tolerateUnreadyEndpoints || podutil.IsPodReady(pod) { - subsets = append(subsets, v1.EndpointSubset{ - Addresses: []v1.EndpointAddress{epa}, - Ports: []v1.EndpointPort{epp}, - }) - readyEps++ - } else { - glog.V(5).Infof("Pod is out of service: %v/%v", pod.Namespace, pod.Name) - subsets = append(subsets, v1.EndpointSubset{ - NotReadyAddresses: []v1.EndpointAddress{epa}, - Ports: []v1.EndpointPort{epp}, - }) - notReadyEps++ + var readyEps, notReadyEps int + 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 } } } @@ -457,7 +453,7 @@ func (e *EndpointController) syncService(key string) error { newEndpoints.Annotations = make(map[string]string) } - glog.V(4).Infof("Update endpoints for %v/%v, ready: %d not ready: %d", service.Namespace, service.Name, readyEps, notReadyEps) + glog.V(4).Infof("Update endpoints for %v/%v, ready: %d not ready: %d", service.Namespace, service.Name, totalReadyEps, totalNotReadyEps) createEndpoints := len(currentEndpoints.ResourceVersion) == 0 if createEndpoints { // No previous endpoints, create them @@ -508,3 +504,24 @@ func (e *EndpointController) checkLeftoverEndpoints() { e.queue.Add(key) } } + +func addEndpointSubset(subsets []v1.EndpointSubset, pod *v1.Pod, epa v1.EndpointAddress, + epp v1.EndpointPort, tolerateUnreadyEndpoints bool) ([]v1.EndpointSubset, int, int) { + var readyEps int = 0 + var notReadyEps int = 0 + if tolerateUnreadyEndpoints || podutil.IsPodReady(pod) { + subsets = append(subsets, v1.EndpointSubset{ + Addresses: []v1.EndpointAddress{epa}, + Ports: []v1.EndpointPort{epp}, + }) + readyEps++ + } else { + glog.V(5).Infof("Pod is out of service: %v/%v", pod.Namespace, pod.Name) + subsets = append(subsets, v1.EndpointSubset{ + NotReadyAddresses: []v1.EndpointAddress{epa}, + Ports: []v1.EndpointPort{epp}, + }) + notReadyEps++ + } + return subsets, readyEps, notReadyEps +} diff --git a/pkg/controller/endpoint/endpoints_controller_test.go b/pkg/controller/endpoint/endpoints_controller_test.go index bd3a81a60bf..9a45cd84e27 100644 --- a/pkg/controller/endpoint/endpoints_controller_test.go +++ b/pkg/controller/endpoint/endpoints_controller_test.go @@ -620,3 +620,44 @@ func TestWaitsForAllInformersToBeSynced2(t *testing.T) { }() } } + +func TestSyncEndpointsHeadlessService(t *testing.T) { + ns := "headless" + testServer, endpointsHandler := makeTestServer(t, ns) + defer testServer.Close() + endpoints := newController(testServer.URL) + endpoints.endpointsStore.Add(&v1.Endpoints{ + ObjectMeta: metav1.ObjectMeta{ + Name: "foo", + Namespace: ns, + ResourceVersion: "1", + }, + Subsets: []v1.EndpointSubset{{ + Addresses: []v1.EndpointAddress{{IP: "6.7.8.9", NodeName: &emptyNodeName}}, + Ports: []v1.EndpointPort{{Port: 1000, Protocol: "TCP"}}, + }}, + }) + addPods(endpoints.podStore, ns, 1, 1, 0) + endpoints.serviceStore.Add(&v1.Service{ + ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: ns}, + Spec: v1.ServiceSpec{ + Selector: map[string]string{}, + ClusterIP: api.ClusterIPNone, + Ports: []v1.ServicePort{}, + }, + }) + endpoints.syncService(ns + "/foo") + data := runtime.EncodeOrDie(testapi.Default.Codec(), &v1.Endpoints{ + ObjectMeta: metav1.ObjectMeta{ + Name: "foo", + Namespace: ns, + ResourceVersion: "1", + }, + 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"}}, + }}, + }) + endpointsHandler.ValidateRequestCount(t, 1) + endpointsHandler.ValidateRequest(t, testapi.Default.ResourcePath("endpoints", ns, "foo"), "PUT", &data) +} diff --git a/pkg/kubectl/service_basic.go b/pkg/kubectl/service_basic.go index a28a76f3cc8..d53cc60fcd2 100644 --- a/pkg/kubectl/service_basic.go +++ b/pkg/kubectl/service_basic.go @@ -179,6 +179,7 @@ func (s ServiceExternalNameGeneratorV1) Generate(params map[string]interface{}) } // validate validates required fields are set to support structured generation +// TODO(xiangpengzhao): validate ports are identity mapped for headless service when we enforce that in validation.validateServicePort. func (s ServiceCommonGeneratorV1) validate() error { if len(s.Name) == 0 { return fmt.Errorf("name must be specified") @@ -189,9 +190,6 @@ func (s ServiceCommonGeneratorV1) validate() error { if s.ClusterIP == api.ClusterIPNone && s.Type != api.ServiceTypeClusterIP { return fmt.Errorf("ClusterIP=None can only be used with ClusterIP service type") } - if s.ClusterIP == api.ClusterIPNone && len(s.TCP) > 0 { - return fmt.Errorf("can not map ports with clusterip=None") - } if s.ClusterIP != api.ClusterIPNone && len(s.TCP) == 0 && s.Type != api.ServiceTypeExternalName { return fmt.Errorf("at least one tcp port specifier must be provided") } diff --git a/pkg/kubectl/service_basic_test.go b/pkg/kubectl/service_basic_test.go index b0363e7dfca..a7fea486085 100644 --- a/pkg/kubectl/service_basic_test.go +++ b/pkg/kubectl/service_basic_test.go @@ -57,13 +57,6 @@ func TestServiceBasicGenerate(t *testing.T) { serviceType: api.ServiceTypeClusterIP, expectErr: true, }, - { - name: "clusterip-none and port mapping", - tcp: []string{"456:9898"}, - clusterip: "None", - serviceType: api.ServiceTypeClusterIP, - expectErr: true, - }, { name: "clusterip-none-wrong-type", tcp: []string{}, @@ -88,6 +81,23 @@ func TestServiceBasicGenerate(t *testing.T) { }, expectErr: false, }, + { + name: "clusterip-none-and-port-mapping", + tcp: []string{"456:9898"}, + clusterip: "None", + serviceType: api.ServiceTypeClusterIP, + expected: &api.Service{ + ObjectMeta: metav1.ObjectMeta{ + Name: "clusterip-none-and-port-mapping", + Labels: map[string]string{"app": "clusterip-none-and-port-mapping"}, + }, + Spec: api.ServiceSpec{Type: "ClusterIP", + Ports: []api.ServicePort{{Name: "456-9898", Protocol: "TCP", Port: 456, TargetPort: intstr.IntOrString{Type: 0, IntVal: 9898, StrVal: ""}, NodePort: 0}}, + Selector: map[string]string{"app": "clusterip-none-and-port-mapping"}, + ClusterIP: "None", ExternalIPs: []string(nil), LoadBalancerIP: ""}, + }, + expectErr: false, + }, { name: "loadbalancer-ok", tcp: []string{"456:9898"}, diff --git a/pkg/kubectl/service_test.go b/pkg/kubectl/service_test.go index 6266779c52d..bd80422ea31 100644 --- a/pkg/kubectl/service_test.go +++ b/pkg/kubectl/service_test.go @@ -560,6 +560,26 @@ func TestGenerateService(t *testing.T) { }, }, }, + { + generator: ServiceGeneratorV2{}, + params: map[string]interface{}{ + "selector": "foo=bar", + "name": "test", + "cluster-ip": "None", + }, + expected: api.Service{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test", + }, + Spec: api.ServiceSpec{ + Selector: map[string]string{ + "foo": "bar", + }, + Ports: []api.ServicePort{}, + ClusterIP: api.ClusterIPNone, + }, + }, + }, } for _, test := range tests { obj, err := test.generator.Generate(test.params) diff --git a/pkg/proxy/iptables/proxier_test.go b/pkg/proxy/iptables/proxier_test.go index 989c244776e..31e7b1f9d9c 100644 --- a/pkg/proxy/iptables/proxier_test.go +++ b/pkg/proxy/iptables/proxier_test.go @@ -1154,6 +1154,10 @@ func TestBuildServiceMapServiceHeadless(t *testing.T) { svc.Spec.ClusterIP = api.ClusterIPNone svc.Spec.Ports = addTestPort(svc.Spec.Ports, "rpc", "UDP", 1234, 0, 0) }), + makeTestService("somewhere-else", "headless-without-port", func(svc *api.Service) { + svc.Spec.Type = api.ServiceTypeClusterIP + svc.Spec.ClusterIP = api.ClusterIPNone + }), ) // Headless service should be ignored From 0525b84a45b521125aecb1c2cd50484c41aff262 Mon Sep 17 00:00:00 2001 From: Konstantinos Tsakalozos Date: Wed, 28 Jun 2017 10:47:45 +0300 Subject: [PATCH 090/448] Disable anonymous-auth --- .../juju/layers/kubernetes-worker/reactive/kubernetes_worker.py | 1 + 1 file changed, 1 insertion(+) diff --git a/cluster/juju/layers/kubernetes-worker/reactive/kubernetes_worker.py b/cluster/juju/layers/kubernetes-worker/reactive/kubernetes_worker.py index 0187fd4c806..e82a19e2ec1 100644 --- a/cluster/juju/layers/kubernetes-worker/reactive/kubernetes_worker.py +++ b/cluster/juju/layers/kubernetes-worker/reactive/kubernetes_worker.py @@ -470,6 +470,7 @@ def configure_worker_services(api_servers, dns, cluster_cidr): kubelet_opts.add('port', '10250') kubelet_opts.add('cluster-dns', dns['sdn-ip']) kubelet_opts.add('cluster-domain', dns['domain']) + kubelet_opts.add('anonymous-auth', 'false') kubelet_opts.add('client-ca-file', ca_cert_path) kubelet_opts.add('tls-cert-file', server_cert_path) kubelet_opts.add('tls-private-key-file', server_key_path) From 3f57d8dba38bc1e96396fd90eaf6524ae5bfa2a0 Mon Sep 17 00:00:00 2001 From: gmarek Date: Wed, 28 Jun 2017 10:35:58 +0200 Subject: [PATCH 091/448] Add generic NoSchedule toleration to fluentd in gcp config as a quick-fix for #44445 --- cluster/addons/fluentd-gcp/fluentd-gcp-ds.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cluster/addons/fluentd-gcp/fluentd-gcp-ds.yaml b/cluster/addons/fluentd-gcp/fluentd-gcp-ds.yaml index ba7bc37676c..d9e5775bb21 100644 --- a/cluster/addons/fluentd-gcp/fluentd-gcp-ds.yaml +++ b/cluster/addons/fluentd-gcp/fluentd-gcp-ds.yaml @@ -107,6 +107,9 @@ spec: effect: "NoSchedule" - operator: "Exists" effect: "NoExecute" + #TODO: remove this toleration once #44445 is properly fixed. + - operator: "Exists" + effect: "NoSchedule" terminationGracePeriodSeconds: 30 volumes: - name: varlog From f12dc94fa969f071fd66bb250731dc60edc7b740 Mon Sep 17 00:00:00 2001 From: xiangpengzhao Date: Wed, 28 Jun 2017 16:43:00 +0800 Subject: [PATCH 092/448] Fix kube-proxy panic when running with "--cleanup-iptables=true" --- cmd/kube-proxy/app/server.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/cmd/kube-proxy/app/server.go b/cmd/kube-proxy/app/server.go index 45bb03de73e..1f7a33ad6a0 100644 --- a/cmd/kube-proxy/app/server.go +++ b/cmd/kube-proxy/app/server.go @@ -447,7 +447,7 @@ func NewProxyServer(config *componentconfig.KubeProxyConfiguration, cleanupAndEx // We omit creation of pretty much everything if we run in cleanup mode if cleanupAndExit { - return &ProxyServer{IptInterface: iptInterface}, nil + return &ProxyServer{IptInterface: iptInterface, CleanupAndExit: cleanupAndExit}, nil } client, eventClient, err := createClients(config.ClientConnection, master) @@ -627,7 +627,9 @@ func (s *ProxyServer) Run() error { } } - s.Broadcaster.StartRecordingToSink(&v1core.EventSinkImpl{Interface: s.EventClient.Events("")}) + if s.Broadcaster != nil && s.EventClient != nil { + s.Broadcaster.StartRecordingToSink(&v1core.EventSinkImpl{Interface: s.EventClient.Events("")}) + } // Start up a healthz server if requested if s.HealthzServer != nil { From ea1bf3860b8c370621569fb11845d5585ede5f9b Mon Sep 17 00:00:00 2001 From: Aleksandra Malinowska Date: Thu, 22 Jun 2017 16:12:15 +0200 Subject: [PATCH 093/448] add volumes test --- test/e2e/autoscaling/BUILD | 1 + .../autoscaling/cluster_size_autoscaling.go | 143 ++++++++++++++++++ 2 files changed, 144 insertions(+) diff --git a/test/e2e/autoscaling/BUILD b/test/e2e/autoscaling/BUILD index 8f3dca42214..b53160c6cd3 100644 --- a/test/e2e/autoscaling/BUILD +++ b/test/e2e/autoscaling/BUILD @@ -32,6 +32,7 @@ go_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/errors: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", diff --git a/test/e2e/autoscaling/cluster_size_autoscaling.go b/test/e2e/autoscaling/cluster_size_autoscaling.go index 6250cc073c1..8c8f1706abf 100644 --- a/test/e2e/autoscaling/cluster_size_autoscaling.go +++ b/test/e2e/autoscaling/cluster_size_autoscaling.go @@ -33,6 +33,8 @@ import ( "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/fields" + "k8s.io/apimachinery/pkg/labels" + utilerrors "k8s.io/apimachinery/pkg/util/errors" "k8s.io/apimachinery/pkg/util/intstr" "k8s.io/apimachinery/pkg/util/sets" "k8s.io/apimachinery/pkg/util/uuid" @@ -252,6 +254,100 @@ var _ = framework.KubeDescribe("Cluster size autoscaling [Slow]", func() { framework.ExpectNoError(framework.WaitForClusterSize(c, nodeCount+newPods, scaleUpTimeout)) }) + It("should increase cluster size if pod requesting EmptyDir volume is pending [Feature:ClusterSizeAutoscalingScaleUp", func() { + By("creating pods") + pods := nodeCount + newPods := 1 + labels := map[string]string{ + "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") + + 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") + + framework.ExpectNoError(waitForAllCaPodsReadyInNamespace(f, c)) + framework.ExpectNoError(framework.WaitForClusterSize(c, nodeCount+newPods, scaleUpTimeout)) + }) + + It("should increase cluster size if pod requesting volume is pending [Feature:ClusterSizeAutoscalingScaleUp", func() { + framework.SkipUnlessProviderIs("gce", "gke") + + volumeLabels := labels.Set{ + framework.VolumeSelectorKey: f.Namespace.Name, + } + selector := metav1.SetAsLabelSelector(volumeLabels) + + By("creating volume & pvc") + diskName, err := framework.CreatePDWithRetry() + framework.ExpectNoError(err) + pvConfig := framework.PersistentVolumeConfig{ + NamePrefix: "gce-", + Labels: volumeLabels, + PVSource: v1.PersistentVolumeSource{ + GCEPersistentDisk: &v1.GCEPersistentDiskVolumeSource{ + PDName: diskName, + FSType: "ext3", + ReadOnly: false, + }, + }, + Prebind: nil, + } + pvcConfig := framework.PersistentVolumeClaimConfig{ + Annotations: map[string]string{ + v1.BetaStorageClassAnnotation: "", + }, + Selector: selector, + } + + pv, pvc, err := framework.CreatePVPVC(c, pvConfig, pvcConfig, f.Namespace.Name, false) + framework.ExpectNoError(err) + framework.ExpectNoError(framework.WaitOnPVandPVC(c, f.Namespace.Name, pv, pvc)) + + defer func() { + errs := framework.PVPVCCleanup(c, f.Namespace.Name, pv, pvc) + if len(errs) > 0 { + framework.Failf("failed to delete PVC and/or PV. Errors: %v", utilerrors.NewAggregate(errs)) + } + pv, pvc = nil, nil + if diskName != "" { + framework.ExpectNoError(framework.DeletePDWithRetry(diskName)) + } + }() + + By("creating pods") + pods := nodeCount + labels := map[string]string{ + "anti-affinity": "yes", + } + 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") + glog.Infof("RC and pods not using volume deleted") + }() + + By("waiting for all pods before triggering scale up") + framework.ExpectNoError(waitForAllCaPodsReadyInNamespace(f, c)) + + By("creating a pod requesting PVC") + pvcPodName := "pvc-pod" + newPods := 1 + 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.ExpectNoError(waitForAllCaPodsReadyInNamespace(f, c)) + }() + + framework.ExpectNoError(waitForAllCaPodsReadyInNamespace(f, c)) + framework.ExpectNoError(framework.WaitForClusterSize(c, nodeCount+newPods, scaleUpTimeout)) + }) + It("should add node to the particular mig [Feature:ClusterSizeAutoscalingScaleUp]", func() { labelKey := "cluster-autoscaling-test.special-node" labelValue := "true" @@ -916,6 +1012,53 @@ func runAntiAffinityPods(f *framework.Framework, namespace string, pods int, id return nil } +func runVolumeAntiAffinityPods(f *framework.Framework, namespace string, pods int, id string, podLabels, antiAffinityLabels map[string]string, volumes []v1.Volume) error { + config := &testutils.RCConfig{ + Affinity: buildAntiAffinity(antiAffinityLabels), + Volumes: volumes, + Client: f.ClientSet, + InternalClient: f.InternalClientset, + Name: id, + Namespace: namespace, + Timeout: scaleUpTimeout, + Image: framework.GetPauseImageName(f.ClientSet), + Replicas: pods, + Labels: podLabels, + } + err := framework.RunRC(*config) + if err != nil { + return err + } + _, err = f.ClientSet.Core().ReplicationControllers(namespace).Get(id, metav1.GetOptions{}) + if err != nil { + return err + } + return nil +} + +var emptyDirVolumes = []v1.Volume{ + { + Name: "empty-volume", + VolumeSource: v1.VolumeSource{ + EmptyDir: &v1.EmptyDirVolumeSource{}, + }, + }, +} + +func buildVolumes(pv *v1.PersistentVolume, pvc *v1.PersistentVolumeClaim) []v1.Volume { + return []v1.Volume{ + { + Name: pv.Name, + VolumeSource: v1.VolumeSource{ + PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{ + ClaimName: pvc.Name, + ReadOnly: false, + }, + }, + }, + } +} + func buildAntiAffinity(labels map[string]string) *v1.Affinity { return &v1.Affinity{ PodAntiAffinity: &v1.PodAntiAffinity{ From e2633865b14c55857c9285998496e26a691f0de5 Mon Sep 17 00:00:00 2001 From: Maciej Pytel Date: Wed, 28 Jun 2017 12:21:12 +0200 Subject: [PATCH 094/448] Fix minor bug in autoscaler e2e cleanup --- test/e2e/autoscaling/cluster_size_autoscaling.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/test/e2e/autoscaling/cluster_size_autoscaling.go b/test/e2e/autoscaling/cluster_size_autoscaling.go index b36bce4a22f..8f5cc40e6a1 100644 --- a/test/e2e/autoscaling/cluster_size_autoscaling.go +++ b/test/e2e/autoscaling/cluster_size_autoscaling.go @@ -93,6 +93,7 @@ var _ = framework.KubeDescribe("Cluster size autoscaling [Slow]", func() { nodes := framework.GetReadySchedulableNodesOrDie(f.ClientSet) nodeCount = len(nodes.Items) + By(fmt.Sprintf("Initial number of schedulable nodes: %v", nodeCount)) Expect(nodeCount).NotTo(BeZero()) cpu := nodes.Items[0].Status.Capacity[v1.ResourceCPU] mem := nodes.Items[0].Status.Capacity[v1.ResourceMemory] @@ -114,7 +115,11 @@ var _ = framework.KubeDescribe("Cluster size autoscaling [Slow]", func() { AfterEach(func() { By(fmt.Sprintf("Restoring initial size of the cluster")) setMigSizes(originalSizes) - framework.ExpectNoError(framework.WaitForClusterSize(c, nodeCount, scaleDownTimeout)) + expectedNodes := 0 + for _, size := range originalSizes { + expectedNodes += size + } + framework.ExpectNoError(framework.WaitForClusterSize(c, expectedNodes, scaleDownTimeout)) nodes, err := c.Core().Nodes().List(metav1.ListOptions{}) framework.ExpectNoError(err) for _, n := range nodes.Items { From 7baff10bfc5fcffbd63bccce24cee7dafb3400b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucas=20K=C3=A4ldstr=C3=B6m?= Date: Wed, 28 Jun 2017 15:06:39 +0300 Subject: [PATCH 095/448] kubeadm: Start using Tolerations in yaml code again --- cmd/kubeadm/app/phases/addons/addons.go | 8 -------- cmd/kubeadm/app/phases/addons/manifests.go | 21 ++++++++------------- 2 files changed, 8 insertions(+), 21 deletions(-) diff --git a/cmd/kubeadm/app/phases/addons/addons.go b/cmd/kubeadm/app/phases/addons/addons.go index 3c3ab5f113c..ffdfcb77ca4 100644 --- a/cmd/kubeadm/app/phases/addons/addons.go +++ b/cmd/kubeadm/app/phases/addons/addons.go @@ -110,7 +110,6 @@ func CreateKubeProxyAddon(configMapBytes, daemonSetbytes []byte, client *clients if err := kuberuntime.DecodeInto(api.Codecs.UniversalDecoder(), daemonSetbytes, kubeproxyDaemonSet); err != nil { return fmt.Errorf("unable to decode kube-proxy daemonset %v", err) } - kubeproxyDaemonSet.Spec.Template.Spec.Tolerations = []v1.Toleration{kubeadmconstants.MasterToleration} if _, err := client.ExtensionsV1beta1().DaemonSets(metav1.NamespaceSystem).Create(kubeproxyDaemonSet); err != nil { if !apierrors.IsAlreadyExists(err) { @@ -129,13 +128,6 @@ func CreateKubeDNSAddon(deploymentBytes, serviceBytes []byte, client *clientset. if err := kuberuntime.DecodeInto(api.Codecs.UniversalDecoder(), deploymentBytes, kubednsDeployment); err != nil { return fmt.Errorf("unable to decode kube-dns deployment %v", err) } - kubednsDeployment.Spec.Template.Spec.Tolerations = []v1.Toleration{ - kubeadmconstants.MasterToleration, - { - Key: "CriticalAddonsOnly", - Operator: "Exists", - }, - } if _, err := client.ExtensionsV1beta1().Deployments(metav1.NamespaceSystem).Create(kubednsDeployment); err != nil { if !apierrors.IsAlreadyExists(err) { diff --git a/cmd/kubeadm/app/phases/addons/manifests.go b/cmd/kubeadm/app/phases/addons/manifests.go index db441015bf3..e2b47072b12 100644 --- a/cmd/kubeadm/app/phases/addons/manifests.go +++ b/cmd/kubeadm/app/phases/addons/manifests.go @@ -79,10 +79,9 @@ spec: name: kube-proxy hostNetwork: true serviceAccountName: kube-proxy - # TODO: Why doesn't the Decoder recognize this new field and decode it properly? Right now it's ignored - # tolerations: - # - key: {{ .MasterTaintKey }} - # effect: NoSchedule + tolerations: + - key: {{ .MasterTaintKey }} + effect: NoSchedule volumes: - name: kube-proxy configMap: @@ -92,7 +91,6 @@ spec: KubeDNSVersion = "1.14.2" KubeDNSDeployment = ` - apiVersion: extensions/v1beta1 kind: Deployment metadata: @@ -116,8 +114,6 @@ spec: metadata: labels: k8s-app: kube-dns - annotations: - scheduler.alpha.kubernetes.io/critical-pod: '' spec: volumes: - name: kube-dns-config @@ -243,12 +239,11 @@ spec: cpu: 10m dnsPolicy: Default # Don't use cluster DNS. serviceAccountName: kube-dns - # TODO: Why doesn't the Decoder recognize this new field and decode it properly? Right now it's ignored - # tolerations: - # - key: CriticalAddonsOnly - # operator: Exists - # - key: {{ .MasterTaintKey }} - # effect: NoSchedule + tolerations: + - key: CriticalAddonsOnly + operator: Exists + - key: {{ .MasterTaintKey }} + effect: NoSchedule # TODO: Remove this affinity field as soon as we are using manifest lists affinity: nodeAffinity: From 10ce8e2c0d3103c2b3571e212c064b849886323f Mon Sep 17 00:00:00 2001 From: gmarek Date: Wed, 28 Jun 2017 14:27:52 +0200 Subject: [PATCH 096/448] Fix bug cluster-subnet logic --- cluster/gce/util.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cluster/gce/util.sh b/cluster/gce/util.sh index 3c281f60eeb..e384ca336d8 100755 --- a/cluster/gce/util.sh +++ b/cluster/gce/util.sh @@ -510,7 +510,7 @@ function make-gcloud-network-argument() { ret="${ret},aliases=pods-default:${alias_size}" ret="${ret} --no-can-ip-forward" else - if [[ ${PREEXISTING_NETWORK} = "true" && "${PREEXISTING_NETWORK_MODE}" != "custom" ]]; then + if [[ ${ENABLE_BIG_CLUSTER_SUBNETS} != "true" || (${PREEXISTING_NETWORK} = "true" && "${PREEXISTING_NETWORK_MODE}" != "custom") ]]; then ret="--network ${network}" else ret="--subnet=${network}" From 60778cdaa42e8d5f12c73ca541c27f1bd32c302c Mon Sep 17 00:00:00 2001 From: Manjunath A Kumatagi Date: Wed, 28 Jun 2017 19:19:25 +0530 Subject: [PATCH 097/448] Move go build to image-utils --- test/images/clusterapi-tester/Makefile | 10 ++++------ test/images/entrypoint-tester/Makefile | 10 ++++------ test/images/fakegitserver/Makefile | 13 ++++++------- test/images/goproxy/Makefile | 10 ++++------ test/images/image-util.sh | 18 +++++++++++++++++- test/images/logs-generator/Makefile | 10 ++++------ test/images/mount-tester/Makefile | 10 ++++------ test/images/n-way-http/Makefile | 10 ++++------ test/images/net/Makefile | 10 ++++------ test/images/netexec/Makefile | 10 ++++------ test/images/network-tester/Makefile | 10 ++++------ test/images/no-snat-test-proxy/Makefile | 10 ++++------ test/images/no-snat-test/Makefile | 10 ++++------ test/images/port-forward-tester/Makefile | 10 ++++------ test/images/porter/Makefile | 10 ++++------ test/images/resource-consumer/Makefile | 10 ++++------ .../resource-consumer/controller/Makefile | 12 ++++++------ test/images/serve_hostname/Makefile | 10 ++++------ 18 files changed, 89 insertions(+), 104 deletions(-) diff --git a/test/images/clusterapi-tester/Makefile b/test/images/clusterapi-tester/Makefile index 369c5cad87e..7e7d827fdc6 100644 --- a/test/images/clusterapi-tester/Makefile +++ b/test/images/clusterapi-tester/Makefile @@ -12,16 +12,14 @@ # See the License for the specific language governing permissions and # limitations under the License. -BIN=clusterapi-tester +SRCS = clusterapi-tester ARCH ?= amd64 TARGET ?= $(CURDIR) GOLANG_VERSION ?= latest +SRC_DIR = $(notdir $(shell pwd)) +export bin: - docker run --rm -it -v $(TARGET):$(TARGET):Z -v `pwd`/../../../:/go/src/k8s.io/kubernetes:Z \ - golang:$(GOLANG_VERSION) \ - /bin/bash -c "\ - cd /go/src/k8s.io/kubernetes/test/images/clusterapi-tester && \ - CGO_ENABLED=0 GOARM=$(GOARM) GOARCH=$(ARCH) go build -a -installsuffix cgo --ldflags '-w' -o $(TARGET)/$(BIN)" + ../image-util.sh bin $(SRCS) .PHONY: bin diff --git a/test/images/entrypoint-tester/Makefile b/test/images/entrypoint-tester/Makefile index 9d7c516fae6..79201cd4197 100644 --- a/test/images/entrypoint-tester/Makefile +++ b/test/images/entrypoint-tester/Makefile @@ -12,16 +12,14 @@ # See the License for the specific language governing permissions and # limitations under the License. -BIN=ep +SRCS=ep ARCH ?= amd64 TARGET ?= $(CURDIR) GOLANG_VERSION ?= latest +SRC_DIR = $(notdir $(shell pwd)) +export bin: - docker run --rm -it -v $(TARGET):$(TARGET):Z -v `pwd`/../../../:/go/src/k8s.io/kubernetes:Z \ - golang:$(GOLANG_VERSION) \ - /bin/bash -c "\ - cd /go/src/k8s.io/kubernetes/test/images/entrypoint-tester && \ - CGO_ENABLED=0 GOARM=$(GOARM) GOARCH=$(ARCH) go build -a -installsuffix cgo --ldflags '-w' -o $(TARGET)/$(BIN) ." + ../image-util.sh bin $(SRCS) .PHONY: bin diff --git a/test/images/fakegitserver/Makefile b/test/images/fakegitserver/Makefile index b99b9e049f2..34f07dc9da3 100644 --- a/test/images/fakegitserver/Makefile +++ b/test/images/fakegitserver/Makefile @@ -12,17 +12,16 @@ # See the License for the specific language governing permissions and # limitations under the License. -BIN=fakegitserver +SRCS = fakegitserver ARCH ?= amd64 TARGET ?= $(CURDIR) GOLANG_VERSION ?= latest +SRC_DIR = $(notdir $(shell pwd)) +export + +IGNORE := $(shell git rev-parse HEAD > $(TARGET)/GITHASH.txt) bin: - docker run --rm -it -v $(TARGET):$(TARGET):Z -v `pwd`/../../../:/go/src/k8s.io/kubernetes:Z \ - golang:$(GOLANG_VERSION) \ - /bin/bash -c "\ - cd /go/src/k8s.io/kubernetes/test/images/fakegitserver && \ - CGO_ENABLED=0 GOARM=$(GOARM) GOARCH=$(ARCH) go build -a -installsuffix cgo --ldflags '-w' -o $(TARGET)/$(BIN) ." - @echo $(shell git rev-parse HEAD) > $(TARGET)/GITHASH.txt + ../image-util.sh bin $(SRCS) .PHONY: bin diff --git a/test/images/goproxy/Makefile b/test/images/goproxy/Makefile index ce0b1bcaa58..35282790f0e 100644 --- a/test/images/goproxy/Makefile +++ b/test/images/goproxy/Makefile @@ -12,16 +12,14 @@ # See the License for the specific language governing permissions and # limitations under the License. -BIN=goproxy +SRCS=goproxy ARCH ?= amd64 TARGET ?= $(CURDIR) GOLANG_VERSION ?= latest +SRC_DIR = $(notdir $(shell pwd)) +export bin: - docker run --rm -it -v $(TARGET):$(TARGET):Z -v `pwd`/../../../:/go/src/k8s.io/kubernetes:Z \ - golang:$(GOLANG_VERSION) \ - /bin/bash -c "\ - cd /go/src/k8s.io/kubernetes/test/images/goproxy && \ - CGO_ENABLED=0 GOARM=$(GOARM) GOARCH=$(ARCH) go build -a -installsuffix cgo --ldflags '-w' -o $(TARGET)/$(BIN) ." + ../image-util.sh bin $(SRCS) .PHONY: bin diff --git a/test/images/image-util.sh b/test/images/image-util.sh index e6c8ade0819..96ccaddfe4a 100755 --- a/test/images/image-util.sh +++ b/test/images/image-util.sh @@ -21,6 +21,8 @@ set -o pipefail TASK=$1 IMAGE=$2 +KUBE_ROOT="$(cd "$(dirname "${BASH_SOURCE}")/../.." && pwd -P)" + # Mapping of go ARCH to actual architectures shipped part of multiarch/qemu-user-static project declare -A QEMUARCHS=( ["amd64"]="x86_64" ["arm"]="arm" ["arm64"]="aarch64" ["ppc64le"]="ppc64le" ["s390x"]="s390x" ) @@ -109,4 +111,18 @@ push() { done } -eval ${TASK} +# This function is for building the go code +bin() { + for SRC in $@; + do + docker run --rm -it -v ${TARGET}:${TARGET}:Z -v ${KUBE_ROOT}:/go/src/k8s.io/kubernetes:Z \ + golang:${GOLANG_VERSION} \ + /bin/bash -c "\ + cd /go/src/k8s.io/kubernetes/test/images/${SRC_DIR} && \ + CGO_ENABLED=0 GOARM=${GOARM} GOARCH=${ARCH} go build -a -installsuffix cgo --ldflags '-w' -o ${TARGET}/${SRC} ./$(dirname ${SRC})" + done +} + +shift + +eval ${TASK} "$@" diff --git a/test/images/logs-generator/Makefile b/test/images/logs-generator/Makefile index da955f391cf..86902a2dac6 100644 --- a/test/images/logs-generator/Makefile +++ b/test/images/logs-generator/Makefile @@ -12,16 +12,14 @@ # See the License for the specific language governing permissions and # limitations under the License. -BIN=logs-generator +SRCS=logs-generator ARCH ?= amd64 TARGET ?= $(CURDIR) GOLANG_VERSION ?= latest +SRC_DIR = $(notdir $(shell pwd)) +export bin: - docker run --rm -it -v $(TARGET):$(TARGET):Z -v `pwd`/../../../:/go/src/k8s.io/kubernetes:Z \ - golang:$(GOLANG_VERSION) \ - /bin/bash -c "\ - cd /go/src/k8s.io/kubernetes/test/images/logs-generator && \ - CGO_ENABLED=0 GOARM=$(GOARM) GOARCH=$(ARCH) go build -a -installsuffix cgo --ldflags '-w' -o $(TARGET)/$(BIN) ." + ../image-util.sh bin $(SRCS) .PHONY: bin diff --git a/test/images/mount-tester/Makefile b/test/images/mount-tester/Makefile index facb75ab96b..969e8080d10 100644 --- a/test/images/mount-tester/Makefile +++ b/test/images/mount-tester/Makefile @@ -12,16 +12,14 @@ # See the License for the specific language governing permissions and # limitations under the License. -BIN=mounttest +SRCS=mounttest ARCH ?= amd64 TARGET ?= $(CURDIR) GOLANG_VERSION ?= latest +SRC_DIR = $(notdir $(shell pwd)) +export bin: - docker run --rm -it -v $(TARGET):$(TARGET):Z -v `pwd`/../../../:/go/src/k8s.io/kubernetes:Z \ - golang:$(GOLANG_VERSION) \ - /bin/bash -c "\ - cd /go/src/k8s.io/kubernetes/test/images/mount-tester && \ - CGO_ENABLED=0 GOARM=$(GOARM) GOARCH=$(ARCH) go build -a -installsuffix cgo --ldflags '-w' -o $(TARGET)/$(BIN) ." + ../image-util.sh bin $(SRCS) .PHONY: bin diff --git a/test/images/n-way-http/Makefile b/test/images/n-way-http/Makefile index 5d324cd85a6..2847ed3f1ca 100644 --- a/test/images/n-way-http/Makefile +++ b/test/images/n-way-http/Makefile @@ -12,16 +12,14 @@ # See the License for the specific language governing permissions and # limitations under the License. -BIN=n-way-http +SRCS=n-way-http ARCH ?= amd64 TARGET ?= $(CURDIR) GOLANG_VERSION ?= latest +SRC_DIR = $(notdir $(shell pwd)) +export bin: - docker run --rm -it -v $(TARGET):$(TARGET):Z -v `pwd`/../../../:/go/src/k8s.io/kubernetes:Z \ - golang:$(GOLANG_VERSION) \ - /bin/bash -c "\ - cd /go/src/k8s.io/kubernetes/test/images/n-way-http && \ - CGO_ENABLED=0 GOARM=$(GOARM) GOARCH=$(ARCH) go build -a -installsuffix cgo --ldflags '-w' -o $(TARGET)/$(BIN) ." + ../image-util.sh bin $(SRCS) .PHONY: bin diff --git a/test/images/net/Makefile b/test/images/net/Makefile index 9313191bc6c..aabdea01c6f 100644 --- a/test/images/net/Makefile +++ b/test/images/net/Makefile @@ -12,16 +12,14 @@ # See the License for the specific language governing permissions and # limitations under the License. -BIN=net +SRCS=net ARCH ?= amd64 TARGET ?= $(CURDIR) GOLANG_VERSION ?= latest +SRC_DIR = $(notdir $(shell pwd)) +export bin: - docker run --rm -it -v $(TARGET):$(TARGET):Z -v `pwd`/../../../:/go/src/k8s.io/kubernetes:Z \ - golang:$(GOLANG_VERSION) \ - /bin/bash -c "\ - cd /go/src/k8s.io/kubernetes/test/images/net && \ - CGO_ENABLED=0 GOARM=$(GOARM) GOARCH=$(ARCH) go build -a -installsuffix cgo --ldflags '-w' -o $(TARGET)/$(BIN) ." + ../image-util.sh bin $(SRCS) .PHONY: bin diff --git a/test/images/netexec/Makefile b/test/images/netexec/Makefile index ddc44efae3b..eb604a5d6c3 100644 --- a/test/images/netexec/Makefile +++ b/test/images/netexec/Makefile @@ -12,16 +12,14 @@ # See the License for the specific language governing permissions and # limitations under the License. -BIN=netexec +SRCS=netexec ARCH ?= amd64 TARGET ?= $(CURDIR) GOLANG_VERSION ?= latest +SRC_DIR = $(notdir $(shell pwd)) +export bin: - docker run --rm -it -v $(TARGET):$(TARGET):Z -v `pwd`/../../../:/go/src/k8s.io/kubernetes:Z \ - golang:$(GOLANG_VERSION) \ - /bin/bash -c "\ - cd /go/src/k8s.io/kubernetes/test/images/netexec && \ - CGO_ENABLED=0 GOARM=$(GOARM) GOARCH=$(ARCH) go build -a -installsuffix cgo --ldflags '-w' -o $(TARGET)/$(BIN) ." + ../image-util.sh bin $(SRCS) .PHONY: bin diff --git a/test/images/network-tester/Makefile b/test/images/network-tester/Makefile index 94c0670872f..e591ddecef5 100644 --- a/test/images/network-tester/Makefile +++ b/test/images/network-tester/Makefile @@ -12,16 +12,14 @@ # See the License for the specific language governing permissions and # limitations under the License. -BIN=nettest +SRCS=nettest ARCH ?= amd64 TARGET ?= $(CURDIR) GOLANG_VERSION ?= latest +SRC_DIR = $(notdir $(shell pwd)) +export bin: - docker run --rm -it -v $(TARGET):$(TARGET):Z -v `pwd`/../../../:/go/src/k8s.io/kubernetes:Z \ - golang:$(GOLANG_VERSION) \ - /bin/bash -c "\ - cd /go/src/k8s.io/kubernetes/test/images/network-tester && \ - CGO_ENABLED=0 GOARM=$(GOARM) GOARCH=$(ARCH) go build -a -installsuffix cgo --ldflags '-w' -o $(TARGET)/$(BIN) ." + ../image-util.sh bin $(SRCS) .PHONY: bin diff --git a/test/images/no-snat-test-proxy/Makefile b/test/images/no-snat-test-proxy/Makefile index 507a70a3d0c..882b56fd090 100644 --- a/test/images/no-snat-test-proxy/Makefile +++ b/test/images/no-snat-test-proxy/Makefile @@ -12,16 +12,14 @@ # See the License for the specific language governing permissions and # limitations under the License. -BIN=no-snat-test-proxy +SRCS=no-snat-test-proxy ARCH ?= amd64 TARGET ?= $(CURDIR) GOLANG_VERSION ?= latest +SRC_DIR = $(notdir $(shell pwd)) +export bin: - docker run --rm -it -v $(TARGET):$(TARGET):Z -v `pwd`/../../../:/go/src/k8s.io/kubernetes:Z \ - golang:$(GOLANG_VERSION) \ - /bin/bash -c "\ - cd /go/src/k8s.io/kubernetes/test/images/no-snat-test-proxy && \ - CGO_ENABLED=0 GOARM=$(GOARM) GOARCH=$(ARCH) go build -a -installsuffix cgo --ldflags '-w' -o $(TARGET)/$(BIN)" + ../image-util.sh bin $(SRCS) .PHONY: bin diff --git a/test/images/no-snat-test/Makefile b/test/images/no-snat-test/Makefile index 60e604cce9a..3c257410da3 100644 --- a/test/images/no-snat-test/Makefile +++ b/test/images/no-snat-test/Makefile @@ -12,16 +12,14 @@ # See the License for the specific language governing permissions and # limitations under the License. -BIN=no-snat-test +SRCS=no-snat-test ARCH ?= amd64 TARGET ?= $(CURDIR) GOLANG_VERSION ?= latest +SRC_DIR = $(notdir $(shell pwd)) +export bin: - docker run --rm -it -v $(TARGET):$(TARGET):Z -v `pwd`/../../../:/go/src/k8s.io/kubernetes:Z \ - golang:$(GOLANG_VERSION) \ - /bin/bash -c "\ - cd /go/src/k8s.io/kubernetes/test/images/no-snat-test && \ - CGO_ENABLED=0 GOARM=$(GOARM) GOARCH=$(ARCH) go build -a -installsuffix cgo --ldflags '-w' -o $(TARGET)/$(BIN)" + ../image-util.sh bin $(SRCS) .PHONY: bin diff --git a/test/images/port-forward-tester/Makefile b/test/images/port-forward-tester/Makefile index 71acb8f88d5..c6a37e9bc0e 100644 --- a/test/images/port-forward-tester/Makefile +++ b/test/images/port-forward-tester/Makefile @@ -12,16 +12,14 @@ # See the License for the specific language governing permissions and # limitations under the License. -BIN=portforwardtester +SRSC=portforwardtester ARCH ?= amd64 TARGET ?= $(CURDIR) GOLANG_VERSION ?= latest +SRC_DIR = $(notdir $(shell pwd)) +export bin: - docker run --rm -it -v $(TARGET):$(TARGET):Z -v `pwd`/../../../:/go/src/k8s.io/kubernetes:Z \ - golang:$(GOLANG_VERSION) \ - /bin/bash -c "\ - cd /go/src/k8s.io/kubernetes/test/images/port-forward-tester && \ - CGO_ENABLED=0 GOARM=$(GOARM) GOARCH=$(ARCH) go build -a -installsuffix cgo --ldflags '-w' -o $(TARGET)/$(BIN) ." + ../image-util.sh bin $(SRCS) .PHONY: bin diff --git a/test/images/porter/Makefile b/test/images/porter/Makefile index d36e960b8cb..eefe96f71a0 100644 --- a/test/images/porter/Makefile +++ b/test/images/porter/Makefile @@ -12,16 +12,14 @@ # See the License for the specific language governing permissions and # limitations under the License. -BIN=porter +SRCS=porter ARCH ?= amd64 TARGET ?= $(CURDIR) GOLANG_VERSION ?= latest +SRC_DIR = $(notdir $(shell pwd)) +export bin: - docker run --rm -it -v $(TARGET):$(TARGET):Z -v `pwd`/../../../:/go/src/k8s.io/kubernetes:Z \ - golang:$(GOLANG_VERSION) \ - /bin/bash -c "\ - cd /go/src/k8s.io/kubernetes/test/images/porter && \ - CGO_ENABLED=0 GOARM=$(GOARM) GOARCH=$(ARCH) go build -a -installsuffix cgo --ldflags '-w' -o $(TARGET)/$(BIN) ." + ../image-util.sh bin $(SRCS) .PHONY: bin diff --git a/test/images/resource-consumer/Makefile b/test/images/resource-consumer/Makefile index b0ae0b41028..44b90a03920 100644 --- a/test/images/resource-consumer/Makefile +++ b/test/images/resource-consumer/Makefile @@ -12,16 +12,14 @@ # See the License for the specific language governing permissions and # limitations under the License. +SRCS = consumer consume-cpu/consume-cpu ARCH ?= amd64 TARGET ?= $(CURDIR) GOLANG_VERSION ?= latest +SRC_DIR = $(notdir $(shell pwd)) +export bin: - docker run --rm -it -v $(TARGET):$(TARGET):Z -v `pwd`/../../../:/go/src/k8s.io/kubernetes:Z \ - golang:$(GOLANG_VERSION) \ - /bin/bash -c "\ - cd /go/src/k8s.io/kubernetes/test/images/resource-consumer && \ - CGO_ENABLED=0 GOARM=$(GOARM) GOARCH=$(ARCH) go build -a -installsuffix cgo --ldflags '-w' -o $(TARGET)/consume-cpu/consume-cpu ./consume-cpu/consume_cpu.go && \ - CGO_ENABLED=0 GOARM=$(GOARM) GOARCH=$(ARCH) go build -a -installsuffix cgo --ldflags '-w' -o $(TARGET)/consumer ." + ../image-util.sh bin $(SRCS) .PHONY: bin diff --git a/test/images/resource-consumer/controller/Makefile b/test/images/resource-consumer/controller/Makefile index 7570296320a..24564eeeefa 100644 --- a/test/images/resource-consumer/controller/Makefile +++ b/test/images/resource-consumer/controller/Makefile @@ -12,14 +12,14 @@ # See the License for the specific language governing permissions and # limitations under the License. -BIN=controller +SRCS=controller ARCH ?= amd64 TARGET ?= $(CURDIR) GOLANG_VERSION ?= latest +SRC_DIR = resource-consumer/$(notdir $(shell pwd)) +export bin: - docker run --rm -it -v $(TARGET):$(TARGET):Z -v `pwd`/../../../../:/go/src/k8s.io/kubernetes:Z \ - golang:$(GOLANG_VERSION) \ - /bin/bash -c "\ - cd /go/src/k8s.io/kubernetes/test/images/resource-consumer/controller && \ - CGO_ENABLED=0 GOARM=$(GOARM) GOARCH=$(ARCH) go build -a -installsuffix cgo --ldflags '-w' -o $(TARGET)/$(BIN) ." + ../../image-util.sh bin $(SRCS) + +.PHONY: bin diff --git a/test/images/serve_hostname/Makefile b/test/images/serve_hostname/Makefile index 879bcd9948d..1c2ea577518 100644 --- a/test/images/serve_hostname/Makefile +++ b/test/images/serve_hostname/Makefile @@ -12,16 +12,14 @@ # See the License for the specific language governing permissions and # limitations under the License. -BIN=serve_hostname +SRCS=serve_hostname ARCH ?= amd64 TARGET ?= $(CURDIR) GOLANG_VERSION ?= latest +SRC_DIR = $(notdir $(shell pwd)) +export bin: - docker run --rm -it -v $(TARGET):$(TARGET):Z -v `pwd`/../../../:/go/src/k8s.io/kubernetes:Z \ - golang:$(GOLANG_VERSION) \ - /bin/bash -c "\ - cd /go/src/k8s.io/kubernetes/test/images/serve_hostname && \ - CGO_ENABLED=0 GOARM=$(GOARM) GOARCH=$(ARCH) go build -a -installsuffix cgo --ldflags '-w' -o $(TARGET)/$(BIN) ." + ../image-util.sh bin $(SRCS) .PHONY: bin From 43280e274db67545fd7f765db4fde2f00ef97f89 Mon Sep 17 00:00:00 2001 From: Piotr Szczesniak Date: Wed, 28 Jun 2017 16:40:29 +0200 Subject: [PATCH 098/448] Bumped Heapster to v1.4.0 --- .../google/heapster-controller.yaml | 16 ++++++++-------- .../heapster-controller-combined.yaml | 16 ++++++++-------- .../influxdb/heapster-controller.yaml | 16 ++++++++-------- .../stackdriver/heapster-controller.yaml | 12 ++++++------ .../standalone/heapster-controller.yaml | 12 ++++++------ 5 files changed, 36 insertions(+), 36 deletions(-) diff --git a/cluster/addons/cluster-monitoring/google/heapster-controller.yaml b/cluster/addons/cluster-monitoring/google/heapster-controller.yaml index 989b5d30f85..a8aeb03c0ae 100644 --- a/cluster/addons/cluster-monitoring/google/heapster-controller.yaml +++ b/cluster/addons/cluster-monitoring/google/heapster-controller.yaml @@ -23,29 +23,29 @@ metadata: apiVersion: extensions/v1beta1 kind: Deployment metadata: - name: heapster-v1.4.0-beta.0 + name: heapster-v1.4.0 namespace: kube-system labels: k8s-app: heapster kubernetes.io/cluster-service: "true" addonmanager.kubernetes.io/mode: Reconcile - version: v1.4.0-beta.0 + version: v1.4.0 spec: replicas: 1 selector: matchLabels: k8s-app: heapster - version: v1.4.0-beta.0 + version: v1.4.0 template: metadata: labels: k8s-app: heapster - version: v1.4.0-beta.0 + version: v1.4.0 annotations: scheduler.alpha.kubernetes.io/critical-pod: '' spec: containers: - - image: gcr.io/google_containers/heapster-amd64:v1.4.0-beta.0 + - image: gcr.io/google_containers/heapster-amd64:v1.4.0 name: heapster livenessProbe: httpGet: @@ -65,7 +65,7 @@ spec: - name: usr-ca-certs mountPath: /usr/share/ca-certificates readOnly: true - - image: gcr.io/google_containers/heapster-amd64:v1.4.0-beta.0 + - image: gcr.io/google_containers/heapster-amd64:v1.4.0 name: eventer command: - /eventer @@ -103,7 +103,7 @@ spec: - --memory={{ base_metrics_memory }} - --extra-memory={{metrics_memory_per_node}}Mi - --threshold=5 - - --deployment=heapster-v1.4.0-beta.0 + - --deployment=heapster-v1.4.0 - --container=heapster - --poll-period=300000 - --estimator=exponential @@ -132,7 +132,7 @@ spec: - --memory={{base_eventer_memory}} - --extra-memory={{eventer_memory_per_node}}Ki - --threshold=5 - - --deployment=heapster-v1.4.0-beta.0 + - --deployment=heapster-v1.4.0 - --container=eventer - --poll-period=300000 - --estimator=exponential diff --git a/cluster/addons/cluster-monitoring/googleinfluxdb/heapster-controller-combined.yaml b/cluster/addons/cluster-monitoring/googleinfluxdb/heapster-controller-combined.yaml index 67535c4d4b1..71b132a5c50 100644 --- a/cluster/addons/cluster-monitoring/googleinfluxdb/heapster-controller-combined.yaml +++ b/cluster/addons/cluster-monitoring/googleinfluxdb/heapster-controller-combined.yaml @@ -23,29 +23,29 @@ metadata: apiVersion: extensions/v1beta1 kind: Deployment metadata: - name: heapster-v1.4.0-beta.0 + name: heapster-v1.4.0 namespace: kube-system labels: k8s-app: heapster kubernetes.io/cluster-service: "true" addonmanager.kubernetes.io/mode: Reconcile - version: v1.4.0-beta.0 + version: v1.4.0 spec: replicas: 1 selector: matchLabels: k8s-app: heapster - version: v1.4.0-beta.0 + version: v1.4.0 template: metadata: labels: k8s-app: heapster - version: v1.4.0-beta.0 + version: v1.4.0 annotations: scheduler.alpha.kubernetes.io/critical-pod: '' spec: containers: - - image: gcr.io/google_containers/heapster-amd64:v1.4.0-beta.0 + - image: gcr.io/google_containers/heapster-amd64:v1.4.0 name: heapster livenessProbe: httpGet: @@ -66,7 +66,7 @@ spec: - name: usr-ca-certs mountPath: /usr/share/ca-certificates readOnly: true - - image: gcr.io/google_containers/heapster-amd64:v1.4.0-beta.0 + - image: gcr.io/google_containers/heapster-amd64:v1.4.0 name: eventer command: - /eventer @@ -104,7 +104,7 @@ spec: - --memory={{ base_metrics_memory }} - --extra-memory={{ metrics_memory_per_node }}Mi - --threshold=5 - - --deployment=heapster-v1.4.0-beta.0 + - --deployment=heapster-v1.4.0 - --container=heapster - --poll-period=300000 - --estimator=exponential @@ -133,7 +133,7 @@ spec: - --memory={{ base_eventer_memory }} - --extra-memory={{ eventer_memory_per_node }}Ki - --threshold=5 - - --deployment=heapster-v1.4.0-beta.0 + - --deployment=heapster-v1.4.0 - --container=eventer - --poll-period=300000 - --estimator=exponential diff --git a/cluster/addons/cluster-monitoring/influxdb/heapster-controller.yaml b/cluster/addons/cluster-monitoring/influxdb/heapster-controller.yaml index 0b5ac12087a..9d9d616b9f4 100644 --- a/cluster/addons/cluster-monitoring/influxdb/heapster-controller.yaml +++ b/cluster/addons/cluster-monitoring/influxdb/heapster-controller.yaml @@ -23,29 +23,29 @@ metadata: apiVersion: extensions/v1beta1 kind: Deployment metadata: - name: heapster-v1.4.0-beta.0 + name: heapster-v1.4.0 namespace: kube-system labels: k8s-app: heapster kubernetes.io/cluster-service: "true" addonmanager.kubernetes.io/mode: Reconcile - version: v1.4.0-beta.0 + version: v1.4.0 spec: replicas: 1 selector: matchLabels: k8s-app: heapster - version: v1.4.0-beta.0 + version: v1.4.0 template: metadata: labels: k8s-app: heapster - version: v1.4.0-beta.0 + version: v1.4.0 annotations: scheduler.alpha.kubernetes.io/critical-pod: '' spec: containers: - - image: gcr.io/google_containers/heapster-amd64:v1.4.0-beta.0 + - image: gcr.io/google_containers/heapster-amd64:v1.4.0 name: heapster livenessProbe: httpGet: @@ -58,7 +58,7 @@ spec: - /heapster - --source=kubernetes.summary_api:'' - --sink=influxdb:http://monitoring-influxdb:8086 - - image: gcr.io/google_containers/heapster-amd64:v1.4.0-beta.0 + - image: gcr.io/google_containers/heapster-amd64:v1.4.0 name: eventer command: - /eventer @@ -89,7 +89,7 @@ spec: - --memory={{ base_metrics_memory }} - --extra-memory={{ metrics_memory_per_node }}Mi - --threshold=5 - - --deployment=heapster-v1.4.0-beta.0 + - --deployment=heapster-v1.4.0 - --container=heapster - --poll-period=300000 - --estimator=exponential @@ -118,7 +118,7 @@ spec: - --memory={{ base_eventer_memory }} - --extra-memory={{ eventer_memory_per_node }}Ki - --threshold=5 - - --deployment=heapster-v1.4.0-beta.0 + - --deployment=heapster-v1.4.0 - --container=eventer - --poll-period=300000 - --estimator=exponential diff --git a/cluster/addons/cluster-monitoring/stackdriver/heapster-controller.yaml b/cluster/addons/cluster-monitoring/stackdriver/heapster-controller.yaml index b41f1024d17..ed78824e7b3 100644 --- a/cluster/addons/cluster-monitoring/stackdriver/heapster-controller.yaml +++ b/cluster/addons/cluster-monitoring/stackdriver/heapster-controller.yaml @@ -21,29 +21,29 @@ metadata: apiVersion: extensions/v1beta1 kind: Deployment metadata: - name: heapster-v1.4.0-beta.0 + name: heapster-v1.4.0 namespace: kube-system labels: k8s-app: heapster kubernetes.io/cluster-service: "true" addonmanager.kubernetes.io/mode: Reconcile - version: v1.4.0-beta.0 + version: v1.4.0 spec: replicas: 1 selector: matchLabels: k8s-app: heapster - version: v1.4.0-beta.0 + version: v1.4.0 template: metadata: labels: k8s-app: heapster - version: v1.4.0-beta.0 + version: v1.4.0 annotations: scheduler.alpha.kubernetes.io/critical-pod: '' spec: containers: - - image: gcr.io/google_containers/heapster-amd64:v1.4.0-beta.0 + - image: gcr.io/google_containers/heapster-amd64:v1.4.0 name: heapster livenessProbe: httpGet: @@ -89,7 +89,7 @@ spec: - --memory={{ base_metrics_memory }} - --extra-memory={{metrics_memory_per_node}}Mi - --threshold=5 - - --deployment=heapster-v1.4.0-beta.0 + - --deployment=heapster-v1.4.0 - --container=heapster - --poll-period=300000 - --estimator=exponential diff --git a/cluster/addons/cluster-monitoring/standalone/heapster-controller.yaml b/cluster/addons/cluster-monitoring/standalone/heapster-controller.yaml index 751d67bb047..79b701dae99 100644 --- a/cluster/addons/cluster-monitoring/standalone/heapster-controller.yaml +++ b/cluster/addons/cluster-monitoring/standalone/heapster-controller.yaml @@ -21,29 +21,29 @@ metadata: apiVersion: extensions/v1beta1 kind: Deployment metadata: - name: heapster-v1.4.0-beta.0 + name: heapster-v1.4.0 namespace: kube-system labels: k8s-app: heapster kubernetes.io/cluster-service: "true" addonmanager.kubernetes.io/mode: Reconcile - version: v1.4.0-beta.0 + version: v1.4.0 spec: replicas: 1 selector: matchLabels: k8s-app: heapster - version: v1.4.0-beta.0 + version: v1.4.0 template: metadata: labels: k8s-app: heapster - version: v1.4.0-beta.0 + version: v1.4.0 annotations: scheduler.alpha.kubernetes.io/critical-pod: '' spec: containers: - - image: gcr.io/google_containers/heapster-amd64:v1.4.0-beta.0 + - image: gcr.io/google_containers/heapster-amd64:v1.4.0 name: heapster livenessProbe: httpGet: @@ -80,7 +80,7 @@ spec: - --memory={{ base_metrics_memory }} - --extra-memory={{ metrics_memory_per_node }}Mi - --threshold=5 - - --deployment=heapster-v1.4.0-beta.0 + - --deployment=heapster-v1.4.0 - --container=heapster - --poll-period=300000 - --estimator=exponential From 8880ba64cf5f1e0247965003e05b900822e40330 Mon Sep 17 00:00:00 2001 From: "Christopher M. Luciano" Date: Wed, 28 Jun 2017 10:48:20 -0400 Subject: [PATCH 099/448] Add OWNERS file to kubelet gpu package GPU support is ramping up and we do not have a lot of reviewers that are familiar with the codebase. I added myself as a reviewer and copied a few people from the kubelet OWNERS file as approvers. Signed-off-by: Christopher M. Luciano --- pkg/kubelet/gpu/OWNERS | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 pkg/kubelet/gpu/OWNERS diff --git a/pkg/kubelet/gpu/OWNERS b/pkg/kubelet/gpu/OWNERS new file mode 100644 index 00000000000..ceb7c93336d --- /dev/null +++ b/pkg/kubelet/gpu/OWNERS @@ -0,0 +1,8 @@ +approvers: +- dchen1107 +- derekwaynecarr +- vishh +- yuyuhong +reviewers: +- cmluciano +- sig-node-reviewers \ No newline at end of file From b18fd60badfce3c0bd2c3ce817273049a36d46c3 Mon Sep 17 00:00:00 2001 From: gmarek Date: Wed, 28 Jun 2017 16:44:59 +0200 Subject: [PATCH 100/448] Use multiple clients in the density test --- test/e2e/perf/density.go | 44 ++++++++++++++++++++++------------------ test/e2e/perf/load.go | 6 +++--- 2 files changed, 27 insertions(+), 23 deletions(-) diff --git a/test/e2e/perf/density.go b/test/e2e/perf/density.go index 110c3ede923..dad05c7e01e 100644 --- a/test/e2e/perf/density.go +++ b/test/e2e/perf/density.go @@ -59,11 +59,11 @@ const ( var MaxContainerFailures = 0 type DensityTestConfig struct { - Configs []testutils.RunObjectConfig - ClientSet clientset.Interface - InternalClientset internalclientset.Interface - PollInterval time.Duration - PodCount int + Configs []testutils.RunObjectConfig + ClientSets []clientset.Interface + InternalClientsets []internalclientset.Interface + PollInterval time.Duration + PodCount int // What kind of resource we want to create kind schema.GroupKind SecretConfigs []*testutils.SecretConfig @@ -220,7 +220,7 @@ func runDensityTest(dtc DensityTestConfig) time.Duration { }() } logStopCh := make(chan struct{}) - go logPodStartupStatus(dtc.ClientSet, dtc.PodCount, map[string]string{"type": "densityPod"}, dtc.PollInterval, logStopCh) + go logPodStartupStatus(dtc.ClientSets[0], dtc.PodCount, map[string]string{"type": "densityPod"}, dtc.PollInterval, logStopCh) wg.Wait() startupTime := time.Now().Sub(startTime) close(logStopCh) @@ -229,7 +229,7 @@ func runDensityTest(dtc DensityTestConfig) time.Duration { // Print some data about Pod to Node allocation By("Printing Pod to Node allocation data") - podList, err := dtc.ClientSet.Core().Pods(metav1.NamespaceAll).List(metav1.ListOptions{}) + podList, err := dtc.ClientSets[0].Core().Pods(metav1.NamespaceAll).List(metav1.ListOptions{}) framework.ExpectNoError(err) pausePodAllocation := make(map[string]int) systemPodAllocation := make(map[string][]string) @@ -254,6 +254,7 @@ func runDensityTest(dtc DensityTestConfig) time.Duration { func cleanupDensityTest(dtc DensityTestConfig) { defer GinkgoRecover() By("Deleting created Collections") + numberOfClients := len(dtc.ClientSets) // We explicitly delete all pods to have API calls necessary for deletion accounted in metrics. for i := range dtc.Configs { name := dtc.Configs[i].GetName() @@ -261,11 +262,11 @@ func cleanupDensityTest(dtc DensityTestConfig) { 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.ClientSet, kind, namespace, name) + 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.ClientSet, dtc.InternalClientset, kind, namespace, name) + err := framework.DeleteResourceAndPods(dtc.ClientSets[i%numberOfClients], dtc.InternalClientsets[i%numberOfClients], kind, namespace, name) framework.ExpectNoError(err) } } @@ -279,8 +280,8 @@ func cleanupDensityTest(dtc DensityTestConfig) { } for i := range dtc.DaemonConfigs { framework.ExpectNoError(framework.DeleteResourceAndPods( - dtc.ClientSet, - dtc.InternalClientset, + dtc.ClientSets[i%numberOfClients], + dtc.InternalClientsets[i%numberOfClients], extensions.Kind("DaemonSet"), dtc.DaemonConfigs[i].Namespace, dtc.DaemonConfigs[i].Name, @@ -535,15 +536,18 @@ var _ = framework.KubeDescribe("Density", func() { } } + // Single client is running out of http2 connections in delete phase, hence we need more. + clients, internalClients, err = createClients(2) + dConfig := DensityTestConfig{ - ClientSet: f.ClientSet, - InternalClientset: f.InternalClientset, - Configs: configs, - PodCount: totalPods, - PollInterval: DensityPollInterval, - kind: itArg.kind, - SecretConfigs: secretConfigs, - ConfigMapConfigs: configMapConfigs, + ClientSets: clients, + InternalClientsets: internalClients, + Configs: configs, + PodCount: totalPods, + PollInterval: DensityPollInterval, + kind: itArg.kind, + SecretConfigs: secretConfigs, + ConfigMapConfigs: configMapConfigs, } for i := 0; i < itArg.daemonsPerNode; i++ { @@ -804,7 +808,7 @@ var _ = framework.KubeDescribe("Density", func() { } } dConfig := DensityTestConfig{ - ClientSet: f.ClientSet, + ClientSets: []clientset.Interface{f.ClientSet}, Configs: configs, PodCount: totalPods, PollInterval: DensityPollInterval, diff --git a/test/e2e/perf/load.go b/test/e2e/perf/load.go index 5fc13896657..6c3c4e21977 100644 --- a/test/e2e/perf/load.go +++ b/test/e2e/perf/load.go @@ -288,9 +288,9 @@ var _ = framework.KubeDescribe("Load capacity", func() { } }) -func createClients(numberOfClients int) ([]*clientset.Clientset, []*internalclientset.Clientset, error) { - clients := make([]*clientset.Clientset, numberOfClients) - internalClients := make([]*internalclientset.Clientset, numberOfClients) +func createClients(numberOfClients int) ([]clientset.Interface, []internalclientset.Interface, error) { + clients := make([]clientset.Interface, numberOfClients) + internalClients := make([]internalclientset.Interface, numberOfClients) for i := 0; i < numberOfClients; i++ { config, err := framework.LoadConfig() Expect(err).NotTo(HaveOccurred()) From 37c2cfe92c61f4a1ea9404bb017ddad95dd95e36 Mon Sep 17 00:00:00 2001 From: Maciej Pytel Date: Wed, 28 Jun 2017 16:10:41 +0200 Subject: [PATCH 101/448] Add retry to RC creation in autoscaler e2e --- .../autoscaling/cluster_size_autoscaling.go | 30 ++++++++++++------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/test/e2e/autoscaling/cluster_size_autoscaling.go b/test/e2e/autoscaling/cluster_size_autoscaling.go index 8f5cc40e6a1..6128f426382 100644 --- a/test/e2e/autoscaling/cluster_size_autoscaling.go +++ b/test/e2e/autoscaling/cluster_size_autoscaling.go @@ -48,13 +48,15 @@ import ( ) const ( - defaultTimeout = 3 * time.Minute - resizeTimeout = 5 * time.Minute - scaleUpTimeout = 5 * time.Minute - scaleUpTriggerTimeout = 2 * time.Minute - scaleDownTimeout = 20 * time.Minute - podTimeout = 2 * time.Minute - nodesRecoverTimeout = 5 * time.Minute + defaultTimeout = 3 * time.Minute + resizeTimeout = 5 * time.Minute + scaleUpTimeout = 5 * time.Minute + scaleUpTriggerTimeout = 2 * time.Minute + scaleDownTimeout = 20 * time.Minute + podTimeout = 2 * time.Minute + nodesRecoverTimeout = 5 * time.Minute + rcCreationRetryTimeout = 4 * time.Minute + rcCreationRetryDelay = 20 * time.Second gkeEndpoint = "https://test-container.sandbox.googleapis.com" gkeUpdateTimeout = 15 * time.Minute @@ -771,10 +773,18 @@ func ReserveMemory(f *framework.Framework, id string, replicas, megabytes int, e Replicas: replicas, MemRequest: request, } - err := framework.RunRC(*config) - if expectRunning { - framework.ExpectNoError(err) + for start := time.Now(); time.Since(start) < rcCreationRetryTimeout; time.Sleep(rcCreationRetryDelay) { + err := framework.RunRC(*config) + if err != nil && strings.Contains(err.Error(), "Error creating replication controller") { + glog.Warningf("Failed to create memory reservation: %v", err) + continue + } + if expectRunning { + framework.ExpectNoError(err) + } + return } + framework.Failf("Failed to reserve memory within timeout") } // WaitForClusterSize waits until the cluster size matches the given function. From 439cb3e74f0d288e10a95d0d610160336a602d94 Mon Sep 17 00:00:00 2001 From: Adam Worrall Date: Tue, 27 Jun 2017 17:11:32 -0700 Subject: [PATCH 102/448] Log the OS images used during cluster creation --- test/e2e/e2e.go | 5 ++ test/e2e/framework/google_compute.go | 97 ++++++++++++++++++++++++++++ 2 files changed, 102 insertions(+) diff --git a/test/e2e/e2e.go b/test/e2e/e2e.go index 8b2158a9999..b1dab7e0979 100644 --- a/test/e2e/e2e.go +++ b/test/e2e/e2e.go @@ -118,6 +118,11 @@ var _ = ginkgo.SynchronizedBeforeSuite(func() []byte { framework.Failf("Failed to setup provider config: %v", err) } + switch framework.TestContext.Provider { + case "gce", "gke": + framework.LogClusterImageSources() + } + c, err := framework.LoadClientset() if err != nil { glog.Fatal("Error loading client: ", err) diff --git a/test/e2e/framework/google_compute.go b/test/e2e/framework/google_compute.go index 726726b397a..8b6fbedfe19 100644 --- a/test/e2e/framework/google_compute.go +++ b/test/e2e/framework/google_compute.go @@ -17,8 +17,11 @@ limitations under the License. package framework import ( + "encoding/json" "fmt" + "io/ioutil" "os/exec" + "path/filepath" "regexp" "strings" "time" @@ -96,3 +99,97 @@ func DeleteGCEStaticIP(name string) error { } return nil } + +// Returns master & node image string, or error +func lookupClusterImageSources() (string, string, error) { + // Given args for a gcloud compute command, run it with other args, and return the values, + // whether separated by newlines, commas or semicolons. + gcloudf := func(argv ...string) ([]string, error) { + args := []string{"compute"} + args = append(args, argv...) + args = append(args, "--project", TestContext.CloudConfig.ProjectID, + "--zone", TestContext.CloudConfig.Zone) + outputBytes, err := exec.Command("gcloud", args...).CombinedOutput() + str := strings.Replace(string(outputBytes), ",", "\n", -1) + str = strings.Replace(str, ";", "\n", -1) + lines := strings.Split(str, "\n") + if err != nil { + Logf("lookupDiskImageSources: gcloud error with [%#v]; err:%v", argv, err) + for _, l := range lines { + Logf(" > %s", l) + } + } + return lines, err + } + + // Given a GCE instance, look through its disks, finding one that has a sourceImage + host2image := func(instance string) (string, error) { + // gcloud compute instances describe {INSTANCE} --format="get(disks[].source)" + // gcloud compute disks describe {DISKURL} --format="get(sourceImage)" + disks, err := gcloudf("instances", "describe", instance, "--format=get(disks[].source)") + if err != nil { + return "", err + } else if len(disks) == 0 { + return "", fmt.Errorf("instance %q had no findable disks", instance) + } + // Loop over disks, looking for the boot disk + for _, disk := range disks { + lines, err := gcloudf("disks", "describe", disk, "--format=get(sourceImage)") + if err != nil { + return "", err + } else if len(lines) > 0 && lines[0] != "" { + return lines[0], nil // break, we're done + } + } + return "", fmt.Errorf("instance %q had no disk with a sourceImage", instance) + } + + // gcloud compute instance-groups list-instances {GROUPNAME} --format="get(instance)" + nodeName := "" + instGroupName := strings.Split(TestContext.CloudConfig.NodeInstanceGroup, ",")[0] + if lines, err := gcloudf("instance-groups", "list-instances", instGroupName, "--format=get(instance)"); err != nil { + return "", "", err + } else if len(lines) == 0 { + return "", "", fmt.Errorf("no instances inside instance-group %q", instGroupName) + } else { + nodeName = lines[0] + } + + nodeImg, err := host2image(nodeName) + if err != nil { + return "", "", err + } + frags := strings.Split(nodeImg, "/") + nodeImg = frags[len(frags)-1] + + masterName := TestContext.CloudConfig.MasterName + masterImg, err := host2image(masterName) + if err != nil { + return "", "", err + } + frags = strings.Split(masterImg, "/") + masterImg = frags[len(frags)-1] + + return masterImg, nodeImg, nil +} + +func LogClusterImageSources() { + masterImg, nodeImg, err := lookupClusterImageSources() + if err != nil { + Logf("Cluster image sources lookup failed: %v\n", err) + return + } + Logf("cluster-master-image: %s", masterImg) + Logf("cluster-node-image: %s", nodeImg) + + images := map[string]string{ + "master_os_image": masterImg, + "node_os_image": nodeImg, + } + + outputBytes, _ := json.MarshalIndent(images, "", " ") + filePath := filepath.Join(TestContext.OutputDir, "images.json") + if err := ioutil.WriteFile(filePath, outputBytes, 0644); err != nil { + Logf("cluster images sources, could not write to %q: %v", filePath, err) + } +} From 547d820588935119e23444cf9e0182aa700b1cef Mon Sep 17 00:00:00 2001 From: Dan Mace Date: Mon, 26 Jun 2017 10:07:06 -0400 Subject: [PATCH 103/448] Fix Unstructured field accessor Fix the Unstructured GetDeletionGracePeriodSeconds accessor which was always returning nil regardless of the underlying stored value. The field value always appearing nil prevents Custom Resource instances from being deleted when garbage collection is enabled for CRs and when DeletePropagationOrphan is used. More generally, this fix means that delete-on-update now works for CR instances. Add some test coverage for Unstructured metadata deserialization. The Unstructured DeletionGracePeriodSeconds field marshals as a value type from JSON and as a pointer type via SetDeletionGracePeriodSeconds. The GetDeletionGracePeriodSeconds method now supports handling both int64 and *int64 values so that either underlying value can be returned. Add a reflection-based unit test which attempts to exercise all the Object Get/Set methods for nil handling. --- ...pis_meta_v1_unstructed_unstructure_test.go | 119 +++++++++++++++--- .../test/integration/finalization_test.go | 11 +- .../apis/meta/v1/unstructured/unstructured.go | 14 ++- 3 files changed, 114 insertions(+), 30 deletions(-) diff --git a/pkg/apimachinery/tests/apis_meta_v1_unstructed_unstructure_test.go b/pkg/apimachinery/tests/apis_meta_v1_unstructed_unstructure_test.go index 617e6a0f8ce..db3f0a3872c 100644 --- a/pkg/apimachinery/tests/apis_meta_v1_unstructed_unstructure_test.go +++ b/pkg/apimachinery/tests/apis_meta_v1_unstructed_unstructure_test.go @@ -87,13 +87,13 @@ func TestDecode(t *testing.T) { }, }, { - json: []byte(`{"items": [{"metadata": {"name": "object1"}, "apiVersion": "test", "kind": "test_kind"}, {"metadata": {"name": "object2"}, "apiVersion": "test", "kind": "test_kind"}], "apiVersion": "test", "kind": "test_list"}`), + json: []byte(`{"items": [{"metadata": {"name": "object1", "deletionGracePeriodSeconds": 10}, "apiVersion": "test", "kind": "test_kind"}, {"metadata": {"name": "object2"}, "apiVersion": "test", "kind": "test_kind"}], "apiVersion": "test", "kind": "test_list"}`), want: &unstructured.UnstructuredList{ Object: map[string]interface{}{"apiVersion": "test", "kind": "test_list"}, Items: []unstructured.Unstructured{ { Object: map[string]interface{}{ - "metadata": map[string]interface{}{"name": "object1"}, + "metadata": map[string]interface{}{"name": "object1", "deletionGracePeriodSeconds": int64(10)}, "apiVersion": "test", "kind": "test_kind", }, @@ -125,19 +125,22 @@ func TestDecode(t *testing.T) { func TestUnstructuredGetters(t *testing.T) { trueVar := true + ten := int64(10) unstruct := unstructured.Unstructured{ Object: map[string]interface{}{ "kind": "test_kind", "apiVersion": "test_version", "metadata": map[string]interface{}{ - "name": "test_name", - "namespace": "test_namespace", - "generateName": "test_generateName", - "uid": "test_uid", - "resourceVersion": "test_resourceVersion", - "selfLink": "test_selfLink", - "creationTimestamp": "2009-11-10T23:00:00Z", - "deletionTimestamp": "2010-11-10T23:00:00Z", + "name": "test_name", + "namespace": "test_namespace", + "generateName": "test_generateName", + "uid": "test_uid", + "resourceVersion": "test_resourceVersion", + "generation": ten, + "deletionGracePeriodSeconds": ten, + "selfLink": "test_selfLink", + "creationTimestamp": "2009-11-10T23:00:00Z", + "deletionTimestamp": "2010-11-10T23:00:00Z", "labels": map[string]interface{}{ "test_label": "test_value", }, @@ -244,25 +247,34 @@ func TestUnstructuredGetters(t *testing.T) { if got, want := unstruct.GetClusterName(), "cluster123"; got != want { t.Errorf("GetClusterName()=%v, want %v", got, want) } + if got, want := unstruct.GetDeletionGracePeriodSeconds(), &ten; !reflect.DeepEqual(got, want) { + t.Errorf("GetDeletionGracePeriodSeconds()=%v, want %v", got, want) + } + if got, want := unstruct.GetGeneration(), ten; !reflect.DeepEqual(got, want) { + t.Errorf("GetGeneration()=%v, want %v", got, want) + } } func TestUnstructuredSetters(t *testing.T) { unstruct := unstructured.Unstructured{} trueVar := true + ten := int64(10) want := unstructured.Unstructured{ Object: map[string]interface{}{ "kind": "test_kind", "apiVersion": "test_version", "metadata": map[string]interface{}{ - "name": "test_name", - "namespace": "test_namespace", - "generateName": "test_generateName", - "uid": "test_uid", - "resourceVersion": "test_resourceVersion", - "selfLink": "test_selfLink", - "creationTimestamp": "2009-11-10T23:00:00Z", - "deletionTimestamp": "2010-11-10T23:00:00Z", + "name": "test_name", + "namespace": "test_namespace", + "generateName": "test_generateName", + "uid": "test_uid", + "resourceVersion": "test_resourceVersion", + "selfLink": "test_selfLink", + "creationTimestamp": "2009-11-10T23:00:00Z", + "deletionTimestamp": "2010-11-10T23:00:00Z", + "deletionGracePeriodSeconds": &ten, + "generation": ten, "labels": map[string]interface{}{ "test_label": "test_value", }, @@ -326,6 +338,8 @@ func TestUnstructuredSetters(t *testing.T) { unstruct.SetOwnerReferences(newOwnerReferences) unstruct.SetFinalizers([]string{"finalizer.1", "finalizer.2"}) unstruct.SetClusterName("cluster123") + unstruct.SetDeletionGracePeriodSeconds(&ten) + unstruct.SetGeneration(ten) if !reflect.DeepEqual(unstruct, want) { t.Errorf("Wanted: \n%s\n Got:\n%s", want, unstruct) @@ -493,3 +507,72 @@ func TestDecodeNumbers(t *testing.T) { t.Fatalf("Expected\n\t%#v, got \n\t%#v", pod, pod2) } } + +// TestAccessorMethods does opaque roundtrip testing against an Unstructured +// instance's Object methods to ensure that what is "Set" matches what you +// subsequently "Get" without any assertions against internal state. +func TestAccessorMethods(t *testing.T) { + int64p := func(i int) *int64 { + v := int64(i) + return &v + } + tests := []struct { + accessor string + val interface{} + nilVal reflect.Value + }{ + {accessor: "Namespace", val: "foo"}, + {accessor: "Name", val: "bar"}, + {accessor: "GenerateName", val: "baz"}, + {accessor: "UID", val: types.UID("uid")}, + {accessor: "ResourceVersion", val: "1"}, + {accessor: "Generation", val: int64(5)}, + {accessor: "SelfLink", val: "/foo"}, + // TODO: Handle timestamps, which are being marshalled as UTC and + // unmarshalled as Local. + // https://github.com/kubernetes/kubernetes/issues/21402 + // {accessor: "CreationTimestamp", val: someTime}, + // {accessor: "DeletionTimestamp", val: someTimeP}, + {accessor: "DeletionTimestamp", nilVal: reflect.ValueOf((*metav1.Time)(nil))}, + {accessor: "DeletionGracePeriodSeconds", val: int64p(10)}, + {accessor: "DeletionGracePeriodSeconds", val: int64p(0)}, + {accessor: "DeletionGracePeriodSeconds", nilVal: reflect.ValueOf((*int64)(nil))}, + {accessor: "Labels", val: map[string]string{"foo": "bar"}}, + {accessor: "Annotations", val: map[string]string{"foo": "bar"}}, + {accessor: "Initializers", val: &metav1.Initializers{Pending: []metav1.Initializer{{Name: "foo"}}}}, + {accessor: "Initializers", val: &metav1.Initializers{}}, + {accessor: "Initializers", nilVal: reflect.ValueOf((*metav1.Initializers)(nil))}, + {accessor: "Finalizers", val: []string{"foo"}}, + {accessor: "OwnerReferences", val: []metav1.OwnerReference{{Name: "foo"}}}, + {accessor: "ClusterName", val: "foo"}, + } + for i, test := range tests { + t.Logf("evaluating test %d (%s)", i, test.accessor) + + u := &unstructured.Unstructured{} + setter := reflect.ValueOf(u).MethodByName("Set" + test.accessor) + getter := reflect.ValueOf(u).MethodByName("Get" + test.accessor) + + args := []reflect.Value{} + if test.val != nil { + args = append(args, reflect.ValueOf(test.val)) + } else { + args = append(args, test.nilVal) + } + setter.Call(args) + + ret := getter.Call([]reflect.Value{}) + actual := ret[0].Interface() + + var expected interface{} + if test.val != nil { + expected = test.val + } else { + expected = test.nilVal.Interface() + } + + if e, a := expected, actual; !reflect.DeepEqual(e, a) { + t.Fatalf("%s: expected %v (%T), got %v (%T)", test.accessor, e, e, a, a) + } + } +} diff --git a/staging/src/k8s.io/apiextensions-apiserver/test/integration/finalization_test.go b/staging/src/k8s.io/apiextensions-apiserver/test/integration/finalization_test.go index c9cfc9401ff..12634870431 100644 --- a/staging/src/k8s.io/apiextensions-apiserver/test/integration/finalization_test.go +++ b/staging/src/k8s.io/apiextensions-apiserver/test/integration/finalization_test.go @@ -69,7 +69,8 @@ func TestFinalization(t *testing.T) { require.NoError(t, err) // Removing the finalizers to allow the following delete remove the object. - // This step will fail if previous delete wrongly removed the object. + // This step will fail if previous delete wrongly removed the object. The + // object will be deleted as part of the finalizer update. for { gottenNoxuInstance.SetFinalizers(nil) _, err = noxuResourceClient.Update(gottenNoxuInstance) @@ -83,14 +84,6 @@ func TestFinalization(t *testing.T) { require.NoError(t, err) } - // Now when finalizer is not there it should be possible to actually remove the object from the server. - err = noxuResourceClient.Delete(name, &metav1.DeleteOptions{ - Preconditions: &metav1.Preconditions{ - UID: &uid, - }, - }) - require.NoError(t, err) - // Check that the object is actually gone. _, err = noxuResourceClient.Get(name, metav1.GetOptions{}) require.Error(t, err) diff --git a/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/unstructured.go b/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/unstructured.go index fed687e9bd3..d428193738b 100644 --- a/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/unstructured.go +++ b/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/unstructured.go @@ -136,10 +136,15 @@ func getNestedInt64(obj map[string]interface{}, fields ...string) int64 { } func getNestedInt64Pointer(obj map[string]interface{}, fields ...string) *int64 { - if str, ok := getNestedField(obj, fields...).(*int64); ok { - return str + nested := getNestedField(obj, fields...) + switch n := nested.(type) { + case int64: + return &n + case *int64: + return n + default: + return nil } - return nil } func getNestedSlice(obj map[string]interface{}, fields ...string) []string { @@ -470,6 +475,9 @@ func (u *Unstructured) GetInitializers() *metav1.Initializers { } func (u *Unstructured) SetInitializers(initializers *metav1.Initializers) { + if u.Object == nil { + u.Object = make(map[string]interface{}) + } if initializers == nil { setNestedField(u.Object, nil, "metadata", "initializers") return From faf7dff7630156ae3f5af6ba973c37917b205049 Mon Sep 17 00:00:00 2001 From: Kris Date: Wed, 28 Jun 2017 12:25:20 -0700 Subject: [PATCH 104/448] Add traceroute logging on connection failure --- test/e2e/framework/upgrade_util.go | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/test/e2e/framework/upgrade_util.go b/test/e2e/framework/upgrade_util.go index ae8a3c98d3a..fa12401289e 100644 --- a/test/e2e/framework/upgrade_util.go +++ b/test/e2e/framework/upgrade_util.go @@ -18,6 +18,7 @@ package framework import ( "fmt" + "os/exec" "path" "strings" "time" @@ -39,13 +40,34 @@ func RealVersion(s string) (string, error) { return strings.TrimPrefix(strings.TrimSpace(v), "v"), nil } +func traceRouteToMaster() { + path, err := exec.LookPath("traceroute") + if err != nil { + Logf("Could not find traceroute program") + return + } + + cmd := exec.Command(path, "-I", GetMasterHost()) + out, err := cmd.Output() + if len(out) != 0 { + Logf(string(out)) + } + if exiterr, ok := err.(*exec.ExitError); err != nil && ok { + Logf("error while running traceroute: %s", exiterr.Stderr) + } +} + func CheckMasterVersion(c clientset.Interface, want string) error { Logf("Checking master version") var err error var v *version.Info waitErr := wait.PollImmediate(5*time.Second, 2*time.Minute, func() (bool, error) { v, err = c.Discovery().ServerVersion() - return err != nil, nil + if err != nil { + traceRouteToMaster() + return false, nil + } + return true, nil }) if waitErr != nil { return fmt.Errorf("CheckMasterVersion() couldn't get the master version: %v", err) From cc8bb857f922e50081d745687a2420b1140f5b53 Mon Sep 17 00:00:00 2001 From: Shyam Jeedigunta Date: Wed, 28 Jun 2017 19:50:58 +0200 Subject: [PATCH 105/448] Allow creating special node for heapster in GCE --- cluster/gce/config-default.sh | 4 + cluster/gce/config-test.sh | 4 + cluster/gce/container-linux/node-helper.sh | 15 ++-- cluster/gce/debian/node-helper.sh | 13 ++- cluster/gce/gci/node-helper.sh | 21 +++-- cluster/gce/util.sh | 93 ++++++++++++++++++---- 6 files changed, 118 insertions(+), 32 deletions(-) diff --git a/cluster/gce/config-default.sh b/cluster/gce/config-default.sh index e4510e5a8e6..0613dffdeae 100755 --- a/cluster/gce/config-default.sh +++ b/cluster/gce/config-default.sh @@ -118,6 +118,10 @@ ENABLE_L7_LOADBALANCING="${KUBE_ENABLE_L7_LOADBALANCING:-glbc}" # standalone - Heapster only. Metrics available via Heapster REST API. ENABLE_CLUSTER_MONITORING="${KUBE_ENABLE_CLUSTER_MONITORING:-influxdb}" +# One special node out of NUM_NODES would be created of this type if specified. +# Useful for scheduling heapster in large clusters with nodes of small size. +HEAPSTER_MACHINE_TYPE="${HEAPSTER_MACHINE_TYPE:-}" + # Historically fluentd was a manifest pod and then was migrated to DaemonSet. # To avoid situation during cluster upgrade when there are two instances # of fluentd running on a node, kubelet need to mark node on which diff --git a/cluster/gce/config-test.sh b/cluster/gce/config-test.sh index 6aa2533c831..76374026179 100755 --- a/cluster/gce/config-test.sh +++ b/cluster/gce/config-test.sh @@ -128,6 +128,10 @@ ENABLE_L7_LOADBALANCING="${KUBE_ENABLE_L7_LOADBALANCING:-glbc}" # standalone - Heapster only. Metrics available via Heapster REST API. ENABLE_CLUSTER_MONITORING="${KUBE_ENABLE_CLUSTER_MONITORING:-influxdb}" +# One special node out of NUM_NODES would be created of this type if specified. +# Useful for scheduling heapster in large clusters with nodes of small size. +HEAPSTER_MACHINE_TYPE="${HEAPSTER_MACHINE_TYPE:-}" + # Set etcd image (e.g. 3.0.17-alpha.1) and version (e.g. 3.0.17) if you need # non-default version. ETCD_IMAGE="${TEST_ETCD_IMAGE:-}" diff --git a/cluster/gce/container-linux/node-helper.sh b/cluster/gce/container-linux/node-helper.sh index 784d36af05a..c2432c5b0ea 100755 --- a/cluster/gce/container-linux/node-helper.sh +++ b/cluster/gce/container-linux/node-helper.sh @@ -17,14 +17,19 @@ # A library of helper functions and constant for the Container Linux distro. source "${KUBE_ROOT}/cluster/gce/container-linux/helper.sh" +function get-node-instance-metadata { + local metadata="" + metadata+="kube-env=${KUBE_TEMP}/node-kube-env.yaml," + metadata+="user-data=${KUBE_ROOT}/cluster/gce/container-linux/node.yaml," + metadata+="configure-sh=${KUBE_ROOT}/cluster/gce/container-linux/configure.sh," + metadata+="cluster-name=${KUBE_TEMP}/cluster-name.txt" + echo "${metadata}" +} + # $1: template name (required). function create-node-instance-template { local template_name="$1" - create-node-template "$template_name" "${scope_flags[*]}" \ - "kube-env=${KUBE_TEMP}/node-kube-env.yaml" \ - "user-data=${KUBE_ROOT}/cluster/gce/container-linux/node.yaml" \ - "configure-sh=${KUBE_ROOT}/cluster/gce/container-linux/configure.sh" \ - "cluster-name=${KUBE_TEMP}/cluster-name.txt" + create-node-template "$template_name" "${scope_flags[*]}" "$(get-node-instance-metadata)" # TODO(euank): We should include update-strategy here. We should also switch to ignition } diff --git a/cluster/gce/debian/node-helper.sh b/cluster/gce/debian/node-helper.sh index 58c1a04562b..b62930f0e34 100755 --- a/cluster/gce/debian/node-helper.sh +++ b/cluster/gce/debian/node-helper.sh @@ -16,12 +16,17 @@ # A library of helper functions and constant for debian os distro +function get-node-instance-metadata { + local metadata="" + metadata+="startup-script=${KUBE_TEMP}/configure-vm.sh," + metadata+="kube-env=${KUBE_TEMP}/node-kube-env.yaml," + metadata+="cluster-name=${KUBE_TEMP}/cluster-name.txt" + echo "${metadata}" +} + # $1: template name (required) function create-node-instance-template { local template_name="$1" prepare-startup-script - create-node-template "$template_name" "${scope_flags}" \ - "startup-script=${KUBE_TEMP}/configure-vm.sh" \ - "kube-env=${KUBE_TEMP}/node-kube-env.yaml" \ - "cluster-name=${KUBE_TEMP}/cluster-name.txt" + create-node-template "$template_name" "${scope_flags}" "$(get-node-instance-metadata)" } diff --git a/cluster/gce/gci/node-helper.sh b/cluster/gce/gci/node-helper.sh index 3217b4e09da..45cdfe6cf1d 100755 --- a/cluster/gce/gci/node-helper.sh +++ b/cluster/gce/gci/node-helper.sh @@ -17,16 +17,21 @@ # A library of helper functions and constant for GCI distro 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+="user-data=${KUBE_ROOT}/cluster/gce/gci/node.yaml," + metadata+="configure-sh=${KUBE_ROOT}/cluster/gce/gci/configure.sh," + metadata+="cluster-name=${KUBE_TEMP}/cluster-name.txt," + 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" + echo "${metadata}" +} + # $1: template name (required). function create-node-instance-template { local template_name="$1" ensure-gci-metadata-files - create-node-template "$template_name" "${scope_flags[*]}" \ - "kube-env=${KUBE_TEMP}/node-kube-env.yaml" \ - "user-data=${KUBE_ROOT}/cluster/gce/gci/node.yaml" \ - "configure-sh=${KUBE_ROOT}/cluster/gce/gci/configure.sh" \ - "cluster-name=${KUBE_TEMP}/cluster-name.txt" \ - "gci-update-strategy=${KUBE_TEMP}/gci-update.txt" \ - "gci-ensure-gke-docker=${KUBE_TEMP}/gci-ensure-gke-docker.txt" \ - "gci-docker-version=${KUBE_TEMP}/gci-docker-version.txt" + create-node-template "$template_name" "${scope_flags[*]}" "$(get-node-instance-metadata)" } diff --git a/cluster/gce/util.sh b/cluster/gce/util.sh index e384ca336d8..ed509660fcf 100755 --- a/cluster/gce/util.sh +++ b/cluster/gce/util.sh @@ -345,6 +345,11 @@ function detect-node-names() { --format='value(instance)')) done fi + # Add heapster node name to the list too (if it exists). + if [[ -n "${HEAPSTER_MACHINE_TYPE:-}" ]]; then + NODE_NAMES+=("${NODE_INSTANCE_PREFIX}-heapster") + fi + echo "INSTANCE_GROUPS=${INSTANCE_GROUPS[*]:-}" >&2 echo "NODE_NAMES=${NODE_NAMES[*]:-}" >&2 } @@ -533,7 +538,7 @@ function get-template-name-from-version() { # Robustly try to create an instance template. # $1: The name of the instance template. # $2: The scopes flag. -# $3 and others: Metadata entries (must all be from a file). +# $3: String of comma-separated metadata entries (must all be from a file). function create-node-template() { detect-project local template_name="$1" @@ -600,7 +605,7 @@ function create-node-template() { ${network} \ ${preemptible_minions} \ $2 \ - --metadata-from-file $(echo ${@:3} | tr ' ' ',') >&2; then + --metadata-from-file $3 >&2; then if (( attempt > 5 )); then echo -e "${color_red}Failed to create instance template $template_name ${color_norm}" >&2 exit 2 @@ -1237,21 +1242,24 @@ function create-nodes-firewall() { } } -function create-nodes-template() { - echo "Creating minions." - - # TODO(zmerlynn): Refactor setting scope flags. +function get-scope-flags() { local scope_flags= if [[ -n "${NODE_SCOPES}" ]]; then scope_flags="--scopes ${NODE_SCOPES}" else scope_flags="--no-scopes" fi + echo "${scope_flags}" +} + +function create-nodes-template() { + echo "Creating nodes." + + local scope_flags=$(get-scope-flags) write-node-env local template_name="${NODE_INSTANCE_PREFIX}-template" - create-node-instance-template $template_name } @@ -1279,7 +1287,13 @@ function set_num_migs() { function create-nodes() { local template_name="${NODE_INSTANCE_PREFIX}-template" - local instances_left=${NUM_NODES} + if [[ -z "${HEAPSTER_MACHINE_TYPE:-}" ]]; then + local -r nodes="${NUM_NODES}" + else + local -r nodes=$(( NUM_NODES - 1 )) + fi + + local instances_left=${nodes} #TODO: parallelize this loop to speed up the process for ((i=1; i<=${NUM_MIGS}; i++)); do @@ -1305,6 +1319,47 @@ function create-nodes() { --zone "${ZONE}" \ --project "${PROJECT}" || true; done + + if [[ -n "${HEAPSTER_MACHINE_TYPE:-}" ]]; then + echo "Creating a special node for heapster with machine-type ${HEAPSTER_MACHINE_TYPE}" + create-heapster-node + fi +} + +# Assumes: +# - NODE_INSTANCE_PREFIX +# - PROJECT +# - ZONE +# - HEAPSTER_MACHINE_TYPE +# - NODE_DISK_TYPE +# - NODE_DISK_SIZE +# - NODE_IMAGE_PROJECT +# - NODE_IMAGE +# - NODE_TAG +# - NETWORK +# - ENABLE_IP_ALIASES +# - IP_ALIAS_SUBNETWORK +# - IP_ALIAS_SIZE +function create-heapster-node() { + local network=$(make-gcloud-network-argument \ + "${NETWORK}" "" \ + "${ENABLE_IP_ALIASES:-}" \ + "${IP_ALIAS_SUBNETWORK:-}" \ + "${IP_ALIAS_SIZE:-}") + + gcloud compute instances \ + create "${NODE_INSTANCE_PREFIX}-heapster" \ + --project "${PROJECT}" \ + --zone "${ZONE}" \ + --machine-type="${HEAPSTER_MACHINE_TYPE}" \ + --boot-disk-type "${NODE_DISK_TYPE}" \ + --boot-disk-size "${NODE_DISK_SIZE}" \ + --image-project="${NODE_IMAGE_PROJECT}" \ + --image "${NODE_IMAGE}" \ + --tags "${NODE_TAG}" \ + ${network} \ + $(get-scope-flags) \ + --metadata-from-file "$(get-node-instance-metadata)" } # Assumes: @@ -1505,6 +1560,20 @@ function kube-down() { "${template}" fi done + + # Delete the special heapster node (if it exists). + if [[ -n "${HEAPSTER_MACHINE_TYPE:-}" ]]; then + local -r heapster_machine_name="${NODE_INSTANCE_PREFIX}-heapster" + if gcloud compute instances describe "${heapster_machine_name}" --zone "${ZONE}" --project "${PROJECT}" &>/dev/null; then + # Now we can safely delete the VM. + gcloud compute instances delete \ + --project "${PROJECT}" \ + --quiet \ + --delete-disks all \ + --zone "${ZONE}" \ + "${heapster_machine_name}" + fi + fi fi local -r REPLICA_NAME="${KUBE_REPLICA_NAME:-$(get-replica-name)}" @@ -1875,13 +1944,7 @@ function prepare-push() { if [[ "${node}" == "true" ]]; then write-node-env - # TODO(zmerlynn): Refactor setting scope flags. - local scope_flags= - if [[ -n "${NODE_SCOPES}" ]]; then - scope_flags="--scopes ${NODE_SCOPES}" - else - scope_flags="--no-scopes" - fi + local scope_flags=$(get-scope-flags) # Ugly hack: Since it is not possible to delete instance-template that is currently # being used, create a temp one, then delete the old one and recreate it once again. From b960a0da1223216ce184eeef55dd93439d61def0 Mon Sep 17 00:00:00 2001 From: Shyam Jeedigunta Date: Wed, 28 Jun 2017 16:54:21 +0200 Subject: [PATCH 106/448] Allow log-dumping only N randomly-chosen nodes in the cluster --- cluster/log-dump.sh | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/cluster/log-dump.sh b/cluster/log-dump.sh index 941df1eb5b1..8855bf54805 100755 --- a/cluster/log-dump.sh +++ b/cluster/log-dump.sh @@ -224,8 +224,19 @@ function dump_nodes() { return fi + nodes_selected_for_logs=() + if [[ -n "${LOGDUMP_ONLY_N_RANDOM_NODES:-}" ]]; then + # We randomly choose 'LOGDUMP_ONLY_N_RANDOM_NODES' many nodes for fetching logs. + for index in `shuf -i 0-$(( ${#node_names[*]} - 1 )) -n ${LOGDUMP_ONLY_N_RANDOM_NODES}` + do + nodes_selected_for_logs+=("${node_names[$index]}") + done + else + nodes_selected_for_logs=( "${node_names[@]}" ) + fi + proc=${max_scp_processes} - for node_name in "${node_names[@]}"; do + for node_name in "${nodes_selected_for_logs[@]}"; do node_dir="${report_dir}/${node_name}" mkdir -p "${node_dir}" # Save logs in the background. This speeds up things when there are From b47dc4704b19fe4e0dccb566b2128bd8226551fc Mon Sep 17 00:00:00 2001 From: Saksham Sharma Date: Tue, 27 Jun 2017 17:40:46 -0700 Subject: [PATCH 107/448] Add Google cloudkms dependency --- Godeps/Godeps.json | 4 + Godeps/LICENSES | 35 + vendor/BUILD | 1 + .../google.golang.org/api/cloudkms/v1/BUILD | 33 + .../api/cloudkms/v1/cloudkms-api.json | 1516 +++++ .../api/cloudkms/v1/cloudkms-gen.go | 5036 +++++++++++++++++ 6 files changed, 6625 insertions(+) create mode 100644 vendor/google.golang.org/api/cloudkms/v1/BUILD create mode 100644 vendor/google.golang.org/api/cloudkms/v1/cloudkms-api.json create mode 100644 vendor/google.golang.org/api/cloudkms/v1/cloudkms-gen.go diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json index 8238ba1ea3c..9b2e52a4ec2 100644 --- a/Godeps/Godeps.json +++ b/Godeps/Godeps.json @@ -2779,6 +2779,10 @@ "ImportPath": "golang.org/x/tools/container/intsets", "Rev": "2382e3994d48b1d22acc2c86bcad0a2aff028e32" }, + { + "ImportPath": "google.golang.org/api/cloudkms/v1", + "Rev": "e3824ed33c72bf7e81da0286772c34b987520914" + }, { "ImportPath": "google.golang.org/api/cloudmonitoring/v2beta2", "Rev": "e3824ed33c72bf7e81da0286772c34b987520914" diff --git a/Godeps/LICENSES b/Godeps/LICENSES index 72a219de0c1..abce3db800e 100644 --- a/Godeps/LICENSES +++ b/Godeps/LICENSES @@ -84080,6 +84080,41 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ================================================================================ +================================================================================ += vendor/google.golang.org/api/cloudkms/v1 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/cloudmonitoring/v2beta2 licensed under: = diff --git a/vendor/BUILD b/vendor/BUILD index 63adadb16e4..1d95c27006c 100644 --- a/vendor/BUILD +++ b/vendor/BUILD @@ -353,6 +353,7 @@ filegroup( "//vendor/golang.org/x/text/width:all-srcs", "//vendor/golang.org/x/time/rate:all-srcs", "//vendor/golang.org/x/tools/container/intsets:all-srcs", + "//vendor/google.golang.org/api/cloudkms/v1:all-srcs", "//vendor/google.golang.org/api/cloudmonitoring/v2beta2:all-srcs", "//vendor/google.golang.org/api/compute/v0.beta:all-srcs", "//vendor/google.golang.org/api/compute/v1:all-srcs", diff --git a/vendor/google.golang.org/api/cloudkms/v1/BUILD b/vendor/google.golang.org/api/cloudkms/v1/BUILD new file mode 100644 index 00000000000..36e0dbf0dbb --- /dev/null +++ b/vendor/google.golang.org/api/cloudkms/v1/BUILD @@ -0,0 +1,33 @@ +package(default_visibility = ["//visibility:public"]) + +licenses(["notice"]) + +load( + "@io_bazel_rules_go//go:def.bzl", + "go_library", +) + +go_library( + name = "go_default_library", + srcs = ["cloudkms-gen.go"], + tags = ["automanaged"], + deps = [ + "//vendor/golang.org/x/net/context:go_default_library", + "//vendor/golang.org/x/net/context/ctxhttp:go_default_library", + "//vendor/google.golang.org/api/gensupport:go_default_library", + "//vendor/google.golang.org/api/googleapi: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/google.golang.org/api/cloudkms/v1/cloudkms-api.json b/vendor/google.golang.org/api/cloudkms/v1/cloudkms-api.json new file mode 100644 index 00000000000..a2d9194c7d5 --- /dev/null +++ b/vendor/google.golang.org/api/cloudkms/v1/cloudkms-api.json @@ -0,0 +1,1516 @@ +{ + "ownerDomain": "google.com", + "name": "cloudkms", + "batchPath": "batch", + "title": "Google Cloud Key Management Service (KMS) API", + "ownerName": "Google", + "resources": { + "projects": { + "resources": { + "locations": { + "methods": { + "list": { + "description": "Lists information about the supported locations for this service.", + "response": { + "$ref": "ListLocationsResponse" + }, + "parameterOrder": [ + "name" + ], + "httpMethod": "GET", + "parameters": { + "filter": { + "location": "query", + "description": "The standard list filter.", + "type": "string" + }, + "name": { + "description": "The resource that owns the locations collection, if applicable.", + "required": true, + "type": "string", + "pattern": "^projects/[^/]+$", + "location": "path" + }, + "pageToken": { + "location": "query", + "description": "The standard list page token.", + "type": "string" + }, + "pageSize": { + "description": "The standard list page size.", + "format": "int32", + "type": "integer", + "location": "query" + } + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform" + ], + "flatPath": "v1/projects/{projectsId}/locations", + "path": "v1/{+name}/locations", + "id": "cloudkms.projects.locations.list" + }, + "get": { + "response": { + "$ref": "Location" + }, + "parameterOrder": [ + "name" + ], + "httpMethod": "GET", + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform" + ], + "parameters": { + "name": { + "description": "Resource name for the location.", + "required": true, + "type": "string", + "pattern": "^projects/[^/]+/locations/[^/]+$", + "location": "path" + } + }, + "flatPath": "v1/projects/{projectsId}/locations/{locationsId}", + "path": "v1/{+name}", + "id": "cloudkms.projects.locations.get", + "description": "Get information about a location." + } + }, + "resources": { + "keyRings": { + "methods": { + "list": { + "response": { + "$ref": "ListKeyRingsResponse" + }, + "parameterOrder": [ + "parent" + ], + "httpMethod": "GET", + "parameters": { + "pageToken": { + "description": "Optional pagination token, returned earlier via\nListKeyRingsResponse.next_page_token.", + "type": "string", + "location": "query" + }, + "pageSize": { + "description": "Optional limit on the number of KeyRings to include in the\nresponse. Further KeyRings can subsequently be obtained by\nincluding the ListKeyRingsResponse.next_page_token in a subsequent\nrequest. If unspecified, the server will pick an appropriate default.", + "format": "int32", + "type": "integer", + "location": "query" + }, + "parent": { + "description": "Required. The resource name of the location associated with the\nKeyRings, in the format `projects/*/locations/*`.", + "required": true, + "type": "string", + "pattern": "^projects/[^/]+/locations/[^/]+$", + "location": "path" + } + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform" + ], + "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/keyRings", + "path": "v1/{+parent}/keyRings", + "id": "cloudkms.projects.locations.keyRings.list", + "description": "Lists KeyRings." + }, + "setIamPolicy": { + "description": "Sets the access control policy on the specified resource. Replaces any\nexisting policy.", + "request": { + "$ref": "SetIamPolicyRequest" + }, + "response": { + "$ref": "Policy" + }, + "parameterOrder": [ + "resource" + ], + "httpMethod": "POST", + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform" + ], + "parameters": { + "resource": { + "description": "REQUIRED: The resource for which the policy is being specified.\nSee the operation documentation for the appropriate value for this field.", + "required": true, + "type": "string", + "pattern": "^projects/[^/]+/locations/[^/]+/keyRings/[^/]+$", + "location": "path" + } + }, + "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/keyRings/{keyRingsId}:setIamPolicy", + "path": "v1/{+resource}:setIamPolicy", + "id": "cloudkms.projects.locations.keyRings.setIamPolicy" + }, + "create": { + "httpMethod": "POST", + "parameterOrder": [ + "parent" + ], + "response": { + "$ref": "KeyRing" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform" + ], + "parameters": { + "parent": { + "description": "Required. The resource name of the location associated with the\nKeyRings, in the format `projects/*/locations/*`.", + "required": true, + "type": "string", + "pattern": "^projects/[^/]+/locations/[^/]+$", + "location": "path" + }, + "keyRingId": { + "description": "Required. It must be unique within a location and match the regular\nexpression `[a-zA-Z0-9_-]{1,63}`", + "type": "string", + "location": "query" + } + }, + "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/keyRings", + "id": "cloudkms.projects.locations.keyRings.create", + "path": "v1/{+parent}/keyRings", + "description": "Create a new KeyRing in a given Project and Location.", + "request": { + "$ref": "KeyRing" + } + }, + "getIamPolicy": { + "response": { + "$ref": "Policy" + }, + "parameterOrder": [ + "resource" + ], + "httpMethod": "GET", + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform" + ], + "parameters": { + "resource": { + "description": "REQUIRED: The resource for which the policy is being requested.\nSee the operation documentation for the appropriate value for this field.", + "required": true, + "type": "string", + "pattern": "^projects/[^/]+/locations/[^/]+/keyRings/[^/]+$", + "location": "path" + } + }, + "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/keyRings/{keyRingsId}:getIamPolicy", + "path": "v1/{+resource}:getIamPolicy", + "id": "cloudkms.projects.locations.keyRings.getIamPolicy", + "description": "Gets the access control policy for a resource.\nReturns an empty policy if the resource exists and does not have a policy\nset." + }, + "get": { + "description": "Returns metadata for a given KeyRing.", + "response": { + "$ref": "KeyRing" + }, + "parameterOrder": [ + "name" + ], + "httpMethod": "GET", + "parameters": { + "name": { + "description": "The name of the KeyRing to get.", + "required": true, + "type": "string", + "pattern": "^projects/[^/]+/locations/[^/]+/keyRings/[^/]+$", + "location": "path" + } + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform" + ], + "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/keyRings/{keyRingsId}", + "path": "v1/{+name}", + "id": "cloudkms.projects.locations.keyRings.get" + }, + "testIamPermissions": { + "request": { + "$ref": "TestIamPermissionsRequest" + }, + "description": "Returns permissions that a caller has on the specified resource.\nIf the resource does not exist, this will return an empty set of\npermissions, not a NOT_FOUND error.\n\nNote: This operation is designed to be used for building permission-aware\nUIs and command-line tools, not for authorization checking. This operation\nmay \"fail open\" without warning.", + "response": { + "$ref": "TestIamPermissionsResponse" + }, + "parameterOrder": [ + "resource" + ], + "httpMethod": "POST", + "parameters": { + "resource": { + "description": "REQUIRED: The resource for which the policy detail is being requested.\nSee the operation documentation for the appropriate value for this field.", + "required": true, + "type": "string", + "pattern": "^projects/[^/]+/locations/[^/]+/keyRings/[^/]+$", + "location": "path" + } + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform" + ], + "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/keyRings/{keyRingsId}:testIamPermissions", + "path": "v1/{+resource}:testIamPermissions", + "id": "cloudkms.projects.locations.keyRings.testIamPermissions" + } + }, + "resources": { + "cryptoKeys": { + "methods": { + "list": { + "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/keyRings/{keyRingsId}/cryptoKeys", + "path": "v1/{+parent}/cryptoKeys", + "id": "cloudkms.projects.locations.keyRings.cryptoKeys.list", + "description": "Lists CryptoKeys.", + "response": { + "$ref": "ListCryptoKeysResponse" + }, + "parameterOrder": [ + "parent" + ], + "httpMethod": "GET", + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform" + ], + "parameters": { + "pageSize": { + "description": "Optional limit on the number of CryptoKeys to include in the\nresponse. Further CryptoKeys can subsequently be obtained by\nincluding the ListCryptoKeysResponse.next_page_token in a subsequent\nrequest. If unspecified, the server will pick an appropriate default.", + "format": "int32", + "type": "integer", + "location": "query" + }, + "parent": { + "description": "Required. The resource name of the KeyRing to list, in the format\n`projects/*/locations/*/keyRings/*`.", + "required": true, + "type": "string", + "pattern": "^projects/[^/]+/locations/[^/]+/keyRings/[^/]+$", + "location": "path" + }, + "pageToken": { + "location": "query", + "description": "Optional pagination token, returned earlier via\nListCryptoKeysResponse.next_page_token.", + "type": "string" + } + } + }, + "encrypt": { + "request": { + "$ref": "EncryptRequest" + }, + "description": "Encrypt data, so that it can only be recovered by a call to Decrypt.", + "response": { + "$ref": "EncryptResponse" + }, + "parameterOrder": [ + "name" + ], + "httpMethod": "POST", + "parameters": { + "name": { + "description": "Required. The resource name of the CryptoKey or CryptoKeyVersion\nto use for encryption.\n\nIf a CryptoKey is specified, the server will use its\nprimary version.", + "required": true, + "type": "string", + "pattern": "^projects/[^/]+/locations/[^/]+/keyRings/[^/]+/cryptoKeys/.+$", + "location": "path" + } + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform" + ], + "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/keyRings/{keyRingsId}/cryptoKeys/{cryptoKeysId}:encrypt", + "path": "v1/{+name}:encrypt", + "id": "cloudkms.projects.locations.keyRings.cryptoKeys.encrypt" + }, + "create": { + "response": { + "$ref": "CryptoKey" + }, + "parameterOrder": [ + "parent" + ], + "httpMethod": "POST", + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform" + ], + "parameters": { + "parent": { + "pattern": "^projects/[^/]+/locations/[^/]+/keyRings/[^/]+$", + "location": "path", + "description": "Required. The name of the KeyRing associated with the\nCryptoKeys.", + "required": true, + "type": "string" + }, + "cryptoKeyId": { + "location": "query", + "description": "Required. It must be unique within a KeyRing and match the regular\nexpression `[a-zA-Z0-9_-]{1,63}`", + "type": "string" + } + }, + "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/keyRings/{keyRingsId}/cryptoKeys", + "path": "v1/{+parent}/cryptoKeys", + "id": "cloudkms.projects.locations.keyRings.cryptoKeys.create", + "description": "Create a new CryptoKey within a KeyRing.\n\nCryptoKey.purpose is required.", + "request": { + "$ref": "CryptoKey" + } + }, + "setIamPolicy": { + "httpMethod": "POST", + "parameterOrder": [ + "resource" + ], + "response": { + "$ref": "Policy" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform" + ], + "parameters": { + "resource": { + "pattern": "^projects/[^/]+/locations/[^/]+/keyRings/[^/]+/cryptoKeys/[^/]+$", + "location": "path", + "description": "REQUIRED: The resource for which the policy is being specified.\nSee the operation documentation for the appropriate value for this field.", + "required": true, + "type": "string" + } + }, + "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/keyRings/{keyRingsId}/cryptoKeys/{cryptoKeysId}:setIamPolicy", + "id": "cloudkms.projects.locations.keyRings.cryptoKeys.setIamPolicy", + "path": "v1/{+resource}:setIamPolicy", + "description": "Sets the access control policy on the specified resource. Replaces any\nexisting policy.", + "request": { + "$ref": "SetIamPolicyRequest" + } + }, + "updatePrimaryVersion": { + "response": { + "$ref": "CryptoKey" + }, + "parameterOrder": [ + "name" + ], + "httpMethod": "POST", + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform" + ], + "parameters": { + "name": { + "location": "path", + "description": "The resource name of the CryptoKey to update.", + "required": true, + "type": "string", + "pattern": "^projects/[^/]+/locations/[^/]+/keyRings/[^/]+/cryptoKeys/[^/]+$" + } + }, + "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/keyRings/{keyRingsId}/cryptoKeys/{cryptoKeysId}:updatePrimaryVersion", + "path": "v1/{+name}:updatePrimaryVersion", + "id": "cloudkms.projects.locations.keyRings.cryptoKeys.updatePrimaryVersion", + "description": "Update the version of a CryptoKey that will be used in Encrypt", + "request": { + "$ref": "UpdateCryptoKeyPrimaryVersionRequest" + } + }, + "getIamPolicy": { + "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/keyRings/{keyRingsId}/cryptoKeys/{cryptoKeysId}:getIamPolicy", + "path": "v1/{+resource}:getIamPolicy", + "id": "cloudkms.projects.locations.keyRings.cryptoKeys.getIamPolicy", + "description": "Gets the access control policy for a resource.\nReturns an empty policy if the resource exists and does not have a policy\nset.", + "parameterOrder": [ + "resource" + ], + "response": { + "$ref": "Policy" + }, + "httpMethod": "GET", + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform" + ], + "parameters": { + "resource": { + "pattern": "^projects/[^/]+/locations/[^/]+/keyRings/[^/]+/cryptoKeys/[^/]+$", + "location": "path", + "description": "REQUIRED: The resource for which the policy is being requested.\nSee the operation documentation for the appropriate value for this field.", + "required": true, + "type": "string" + } + } + }, + "patch": { + "response": { + "$ref": "CryptoKey" + }, + "parameterOrder": [ + "name" + ], + "httpMethod": "PATCH", + "parameters": { + "updateMask": { + "description": "Required list of fields to be updated in this request.", + "format": "google-fieldmask", + "type": "string", + "location": "query" + }, + "name": { + "pattern": "^projects/[^/]+/locations/[^/]+/keyRings/[^/]+/cryptoKeys/[^/]+$", + "location": "path", + "description": "Output only. The resource name for this CryptoKey in the format\n`projects/*/locations/*/keyRings/*/cryptoKeys/*`.", + "required": true, + "type": "string" + } + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform" + ], + "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/keyRings/{keyRingsId}/cryptoKeys/{cryptoKeysId}", + "path": "v1/{+name}", + "id": "cloudkms.projects.locations.keyRings.cryptoKeys.patch", + "request": { + "$ref": "CryptoKey" + }, + "description": "Update a CryptoKey." + }, + "get": { + "description": "Returns metadata for a given CryptoKey, as well as its\nprimary CryptoKeyVersion.", + "response": { + "$ref": "CryptoKey" + }, + "parameterOrder": [ + "name" + ], + "httpMethod": "GET", + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform" + ], + "parameters": { + "name": { + "pattern": "^projects/[^/]+/locations/[^/]+/keyRings/[^/]+/cryptoKeys/[^/]+$", + "location": "path", + "description": "The name of the CryptoKey to get.", + "required": true, + "type": "string" + } + }, + "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/keyRings/{keyRingsId}/cryptoKeys/{cryptoKeysId}", + "path": "v1/{+name}", + "id": "cloudkms.projects.locations.keyRings.cryptoKeys.get" + }, + "testIamPermissions": { + "request": { + "$ref": "TestIamPermissionsRequest" + }, + "description": "Returns permissions that a caller has on the specified resource.\nIf the resource does not exist, this will return an empty set of\npermissions, not a NOT_FOUND error.\n\nNote: This operation is designed to be used for building permission-aware\nUIs and command-line tools, not for authorization checking. This operation\nmay \"fail open\" without warning.", + "response": { + "$ref": "TestIamPermissionsResponse" + }, + "parameterOrder": [ + "resource" + ], + "httpMethod": "POST", + "parameters": { + "resource": { + "location": "path", + "description": "REQUIRED: The resource for which the policy detail is being requested.\nSee the operation documentation for the appropriate value for this field.", + "required": true, + "type": "string", + "pattern": "^projects/[^/]+/locations/[^/]+/keyRings/[^/]+/cryptoKeys/[^/]+$" + } + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform" + ], + "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/keyRings/{keyRingsId}/cryptoKeys/{cryptoKeysId}:testIamPermissions", + "path": "v1/{+resource}:testIamPermissions", + "id": "cloudkms.projects.locations.keyRings.cryptoKeys.testIamPermissions" + }, + "decrypt": { + "description": "Decrypt data that was protected by Encrypt.", + "request": { + "$ref": "DecryptRequest" + }, + "httpMethod": "POST", + "parameterOrder": [ + "name" + ], + "response": { + "$ref": "DecryptResponse" + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform" + ], + "parameters": { + "name": { + "description": "Required. The resource name of the CryptoKey to use for decryption.\nThe server will choose the appropriate version.", + "required": true, + "type": "string", + "pattern": "^projects/[^/]+/locations/[^/]+/keyRings/[^/]+/cryptoKeys/[^/]+$", + "location": "path" + } + }, + "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/keyRings/{keyRingsId}/cryptoKeys/{cryptoKeysId}:decrypt", + "id": "cloudkms.projects.locations.keyRings.cryptoKeys.decrypt", + "path": "v1/{+name}:decrypt" + } + }, + "resources": { + "cryptoKeyVersions": { + "methods": { + "list": { + "path": "v1/{+parent}/cryptoKeyVersions", + "id": "cloudkms.projects.locations.keyRings.cryptoKeys.cryptoKeyVersions.list", + "description": "Lists CryptoKeyVersions.", + "response": { + "$ref": "ListCryptoKeyVersionsResponse" + }, + "parameterOrder": [ + "parent" + ], + "httpMethod": "GET", + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform" + ], + "parameters": { + "pageToken": { + "description": "Optional pagination token, returned earlier via\nListCryptoKeyVersionsResponse.next_page_token.", + "type": "string", + "location": "query" + }, + "pageSize": { + "description": "Optional limit on the number of CryptoKeyVersions to\ninclude in the response. Further CryptoKeyVersions can\nsubsequently be obtained by including the\nListCryptoKeyVersionsResponse.next_page_token in a subsequent request.\nIf unspecified, the server will pick an appropriate default.", + "format": "int32", + "type": "integer", + "location": "query" + }, + "parent": { + "pattern": "^projects/[^/]+/locations/[^/]+/keyRings/[^/]+/cryptoKeys/[^/]+$", + "location": "path", + "description": "Required. The resource name of the CryptoKey to list, in the format\n`projects/*/locations/*/keyRings/*/cryptoKeys/*`.", + "required": true, + "type": "string" + } + }, + "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/keyRings/{keyRingsId}/cryptoKeys/{cryptoKeysId}/cryptoKeyVersions" + }, + "create": { + "response": { + "$ref": "CryptoKeyVersion" + }, + "parameterOrder": [ + "parent" + ], + "httpMethod": "POST", + "parameters": { + "parent": { + "pattern": "^projects/[^/]+/locations/[^/]+/keyRings/[^/]+/cryptoKeys/[^/]+$", + "location": "path", + "description": "Required. The name of the CryptoKey associated with\nthe CryptoKeyVersions.", + "required": true, + "type": "string" + } + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform" + ], + "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/keyRings/{keyRingsId}/cryptoKeys/{cryptoKeysId}/cryptoKeyVersions", + "path": "v1/{+parent}/cryptoKeyVersions", + "id": "cloudkms.projects.locations.keyRings.cryptoKeys.cryptoKeyVersions.create", + "request": { + "$ref": "CryptoKeyVersion" + }, + "description": "Create a new CryptoKeyVersion in a CryptoKey.\n\nThe server will assign the next sequential id. If unset,\nstate will be set to\nENABLED." + }, + "destroy": { + "httpMethod": "POST", + "parameterOrder": [ + "name" + ], + "response": { + "$ref": "CryptoKeyVersion" + }, + "parameters": { + "name": { + "pattern": "^projects/[^/]+/locations/[^/]+/keyRings/[^/]+/cryptoKeys/[^/]+/cryptoKeyVersions/[^/]+$", + "location": "path", + "description": "The resource name of the CryptoKeyVersion to destroy.", + "required": true, + "type": "string" + } + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform" + ], + "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/keyRings/{keyRingsId}/cryptoKeys/{cryptoKeysId}/cryptoKeyVersions/{cryptoKeyVersionsId}:destroy", + "id": "cloudkms.projects.locations.keyRings.cryptoKeys.cryptoKeyVersions.destroy", + "path": "v1/{+name}:destroy", + "request": { + "$ref": "DestroyCryptoKeyVersionRequest" + }, + "description": "Schedule a CryptoKeyVersion for destruction.\n\nUpon calling this method, CryptoKeyVersion.state will be set to\nDESTROY_SCHEDULED\nand destroy_time will be set to a time 24\nhours in the future, at which point the state\nwill be changed to\nDESTROYED, and the key\nmaterial will be irrevocably destroyed.\n\nBefore the destroy_time is reached,\nRestoreCryptoKeyVersion may be called to reverse the process." + }, + "restore": { + "response": { + "$ref": "CryptoKeyVersion" + }, + "parameterOrder": [ + "name" + ], + "httpMethod": "POST", + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform" + ], + "parameters": { + "name": { + "description": "The resource name of the CryptoKeyVersion to restore.", + "required": true, + "type": "string", + "pattern": "^projects/[^/]+/locations/[^/]+/keyRings/[^/]+/cryptoKeys/[^/]+/cryptoKeyVersions/[^/]+$", + "location": "path" + } + }, + "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/keyRings/{keyRingsId}/cryptoKeys/{cryptoKeysId}/cryptoKeyVersions/{cryptoKeyVersionsId}:restore", + "path": "v1/{+name}:restore", + "id": "cloudkms.projects.locations.keyRings.cryptoKeys.cryptoKeyVersions.restore", + "description": "Restore a CryptoKeyVersion in the\nDESTROY_SCHEDULED,\nstate.\n\nUpon restoration of the CryptoKeyVersion, state\nwill be set to DISABLED,\nand destroy_time will be cleared.", + "request": { + "$ref": "RestoreCryptoKeyVersionRequest" + } + }, + "patch": { + "httpMethod": "PATCH", + "parameterOrder": [ + "name" + ], + "response": { + "$ref": "CryptoKeyVersion" + }, + "parameters": { + "updateMask": { + "description": "Required list of fields to be updated in this request.", + "format": "google-fieldmask", + "type": "string", + "location": "query" + }, + "name": { + "description": "Output only. The resource name for this CryptoKeyVersion in the format\n`projects/*/locations/*/keyRings/*/cryptoKeys/*/cryptoKeyVersions/*`.", + "required": true, + "type": "string", + "pattern": "^projects/[^/]+/locations/[^/]+/keyRings/[^/]+/cryptoKeys/[^/]+/cryptoKeyVersions/[^/]+$", + "location": "path" + } + }, + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform" + ], + "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/keyRings/{keyRingsId}/cryptoKeys/{cryptoKeysId}/cryptoKeyVersions/{cryptoKeyVersionsId}", + "id": "cloudkms.projects.locations.keyRings.cryptoKeys.cryptoKeyVersions.patch", + "path": "v1/{+name}", + "request": { + "$ref": "CryptoKeyVersion" + }, + "description": "Update a CryptoKeyVersion's metadata.\n\nstate may be changed between\nENABLED and\nDISABLED using this\nmethod. See DestroyCryptoKeyVersion and RestoreCryptoKeyVersion to\nmove between other states." + }, + "get": { + "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/keyRings/{keyRingsId}/cryptoKeys/{cryptoKeysId}/cryptoKeyVersions/{cryptoKeyVersionsId}", + "path": "v1/{+name}", + "id": "cloudkms.projects.locations.keyRings.cryptoKeys.cryptoKeyVersions.get", + "description": "Returns metadata for a given CryptoKeyVersion.", + "parameterOrder": [ + "name" + ], + "response": { + "$ref": "CryptoKeyVersion" + }, + "httpMethod": "GET", + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform" + ], + "parameters": { + "name": { + "pattern": "^projects/[^/]+/locations/[^/]+/keyRings/[^/]+/cryptoKeys/[^/]+/cryptoKeyVersions/[^/]+$", + "location": "path", + "description": "The name of the CryptoKeyVersion to get.", + "required": true, + "type": "string" + } + } + } + } + } + } + } + } + } + } + } + } + } + }, + "parameters": { + "upload_protocol": { + "description": "Upload protocol for media (e.g. \"raw\", \"multipart\").", + "type": "string", + "location": "query" + }, + "prettyPrint": { + "description": "Returns response with indentations and line breaks.", + "type": "boolean", + "default": "true", + "location": "query" + }, + "uploadType": { + "location": "query", + "description": "Legacy upload protocol for media (e.g. \"media\", \"multipart\").", + "type": "string" + }, + "fields": { + "description": "Selector specifying which fields to include in a partial response.", + "type": "string", + "location": "query" + }, + "callback": { + "location": "query", + "description": "JSONP", + "type": "string" + }, + "$.xgafv": { + "description": "V1 error format.", + "type": "string", + "enumDescriptions": [ + "v1 error format", + "v2 error format" + ], + "location": "query", + "enum": [ + "1", + "2" + ] + }, + "alt": { + "enum": [ + "json", + "media", + "proto" + ], + "type": "string", + "enumDescriptions": [ + "Responses with Content-Type of application/json", + "Media download with context-dependent Content-Type", + "Responses with Content-Type of application/x-protobuf" + ], + "location": "query", + "description": "Data format for response.", + "default": "json" + }, + "key": { + "location": "query", + "description": "API key. Your API key identifies your project and provides you with API access, quota, and reports. Required unless you provide an OAuth 2.0 token.", + "type": "string" + }, + "access_token": { + "description": "OAuth access token.", + "type": "string", + "location": "query" + }, + "quotaUser": { + "description": "Available to use for quota purposes for server-side applications. Can be any arbitrary string assigned to a user, but should not exceed 40 characters.", + "type": "string", + "location": "query" + }, + "pp": { + "description": "Pretty-print response.", + "type": "boolean", + "default": "true", + "location": "query" + }, + "bearer_token": { + "description": "OAuth bearer token.", + "type": "string", + "location": "query" + }, + "oauth_token": { + "location": "query", + "description": "OAuth 2.0 token for the current user.", + "type": "string" + } + }, + "version": "v1", + "baseUrl": "https://cloudkms.googleapis.com/", + "kind": "discovery#restDescription", + "description": "Manages encryption for your cloud services the same way you do on-premise. You can generate, use, rotate, and destroy AES256 encryption keys.", + "servicePath": "", + "basePath": "", + "id": "cloudkms:v1", + "documentationLink": "https://cloud.google.com/kms/", + "revision": "20170425", + "discoveryVersion": "v1", + "version_module": "True", + "schemas": { + "Binding": { + "description": "Associates `members` with a `role`.", + "type": "object", + "properties": { + "members": { + "description": "Specifies the identities requesting access for a Cloud Platform resource.\n`members` can have the following values:\n\n* `allUsers`: A special identifier that represents anyone who is\n on the internet; with or without a Google account.\n\n* `allAuthenticatedUsers`: A special identifier that represents anyone\n who is authenticated with a Google account or a service account.\n\n* `user:{emailid}`: An email address that represents a specific Google\n account. For example, `alice@gmail.com` or `joe@example.com`.\n\n\n* `serviceAccount:{emailid}`: An email address that represents a service\n account. For example, `my-other-app@appspot.gserviceaccount.com`.\n\n* `group:{emailid}`: An email address that represents a Google group.\n For example, `admins@example.com`.\n\n* `domain:{domain}`: A Google Apps domain name that represents all the\n users of that domain. For example, `google.com` or `example.com`.\n\n", + "type": "array", + "items": { + "type": "string" + } + }, + "role": { + "description": "Role that is assigned to `members`.\nFor example, `roles/viewer`, `roles/editor`, or `roles/owner`.\nRequired", + "type": "string" + } + }, + "id": "Binding" + }, + "EncryptRequest": { + "description": "Request message for KeyManagementService.Encrypt.", + "type": "object", + "properties": { + "additionalAuthenticatedData": { + "description": "Optional data that, if specified, must also be provided during decryption\nthrough DecryptRequest.additional_authenticated_data. Must be no\nlarger than 64KiB.", + "format": "byte", + "type": "string" + }, + "plaintext": { + "description": "Required. The data to encrypt. Must be no larger than 64KiB.", + "format": "byte", + "type": "string" + } + }, + "id": "EncryptRequest" + }, + "ListCryptoKeyVersionsResponse": { + "description": "Response message for KeyManagementService.ListCryptoKeyVersions.", + "type": "object", + "properties": { + "cryptoKeyVersions": { + "description": "The list of CryptoKeyVersions.", + "type": "array", + "items": { + "$ref": "CryptoKeyVersion" + } + }, + "nextPageToken": { + "description": "A token to retrieve next page of results. Pass this value in\nListCryptoKeyVersionsRequest.page_token to retrieve the next page of\nresults.", + "type": "string" + }, + "totalSize": { + "description": "The total number of CryptoKeyVersions that matched the\nquery.", + "format": "int32", + "type": "integer" + } + }, + "id": "ListCryptoKeyVersionsResponse" + }, + "TestIamPermissionsResponse": { + "description": "Response message for `TestIamPermissions` method.", + "type": "object", + "properties": { + "permissions": { + "description": "A subset of `TestPermissionsRequest.permissions` that the caller is\nallowed.", + "type": "array", + "items": { + "type": "string" + } + } + }, + "id": "TestIamPermissionsResponse" + }, + "DestroyCryptoKeyVersionRequest": { + "description": "Request message for KeyManagementService.DestroyCryptoKeyVersion.", + "type": "object", + "properties": {}, + "id": "DestroyCryptoKeyVersionRequest" + }, + "CryptoKey": { + "description": "A CryptoKey represents a logical key that can be used for cryptographic\noperations.\n\nA CryptoKey is made up of one or more versions, which\nrepresent the actual key material used in cryptographic operations.", + "type": "object", + "properties": { + "createTime": { + "description": "Output only. The time at which this CryptoKey was created.", + "format": "google-datetime", + "type": "string" + }, + "rotationPeriod": { + "description": "next_rotation_time will be advanced by this period when the service\nautomatically rotates a key. Must be at least one day.\n\nIf rotation_period is set, next_rotation_time must also be set.", + "format": "google-duration", + "type": "string" + }, + "primary": { + "description": "Output only. A copy of the \"primary\" CryptoKeyVersion that will be used\nby Encrypt when this CryptoKey is given\nin EncryptRequest.name.\n\nThe CryptoKey's primary version can be updated via\nUpdateCryptoKeyPrimaryVersion.", + "$ref": "CryptoKeyVersion" + }, + "name": { + "description": "Output only. The resource name for this CryptoKey in the format\n`projects/*/locations/*/keyRings/*/cryptoKeys/*`.", + "type": "string" + }, + "purpose": { + "enum": [ + "CRYPTO_KEY_PURPOSE_UNSPECIFIED", + "ENCRYPT_DECRYPT" + ], + "description": "The immutable purpose of this CryptoKey. Currently, the only acceptable\npurpose is ENCRYPT_DECRYPT.", + "type": "string", + "enumDescriptions": [ + "Not specified.", + "CryptoKeys with this purpose may be used with\nEncrypt and\nDecrypt." + ] + }, + "nextRotationTime": { + "description": "At next_rotation_time, the Key Management Service will automatically:\n\n1. Create a new version of this CryptoKey.\n2. Mark the new version as primary.\n\nKey rotations performed manually via\nCreateCryptoKeyVersion and\nUpdateCryptoKeyPrimaryVersion\ndo not affect next_rotation_time.", + "format": "google-datetime", + "type": "string" + } + }, + "id": "CryptoKey" + }, + "Rule": { + "description": "A rule to be applied in a Policy.", + "type": "object", + "properties": { + "notIn": { + "description": "If one or more 'not_in' clauses are specified, the rule matches\nif the PRINCIPAL/AUTHORITY_SELECTOR is in none of the entries.\nThe format for in and not_in entries is the same as for members in a\nBinding (see google/iam/v1/policy.proto).", + "type": "array", + "items": { + "type": "string" + } + }, + "description": { + "description": "Human-readable description of the rule.", + "type": "string" + }, + "conditions": { + "description": "Additional restrictions that must be met", + "type": "array", + "items": { + "$ref": "Condition" + } + }, + "logConfig": { + "description": "The config returned to callers of tech.iam.IAM.CheckPolicy for any entries\nthat match the LOG action.", + "type": "array", + "items": { + "$ref": "LogConfig" + } + }, + "in": { + "description": "If one or more 'in' clauses are specified, the rule matches if\nthe PRINCIPAL/AUTHORITY_SELECTOR is in at least one of these entries.", + "type": "array", + "items": { + "type": "string" + } + }, + "permissions": { + "description": "A permission is a string of form '\u003cservice\u003e.\u003cresource type\u003e.\u003cverb\u003e'\n(e.g., 'storage.buckets.list'). A value of '*' matches all permissions,\nand a verb part of '*' (e.g., 'storage.buckets.*') matches all verbs.", + "type": "array", + "items": { + "type": "string" + } + }, + "action": { + "enum": [ + "NO_ACTION", + "ALLOW", + "ALLOW_WITH_LOG", + "DENY", + "DENY_WITH_LOG", + "LOG" + ], + "description": "Required", + "type": "string", + "enumDescriptions": [ + "Default no action.", + "Matching 'Entries' grant access.", + "Matching 'Entries' grant access and the caller promises to log\nthe request per the returned log_configs.", + "Matching 'Entries' deny access.", + "Matching 'Entries' deny access and the caller promises to log\nthe request per the returned log_configs.", + "Matching 'Entries' tell IAM.Check callers to generate logs." + ] + } + }, + "id": "Rule" + }, + "LogConfig": { + "description": "Specifies what kind of log the caller must write", + "type": "object", + "properties": { + "cloudAudit": { + "$ref": "CloudAuditOptions", + "description": "Cloud audit options." + }, + "counter": { + "$ref": "CounterOptions", + "description": "Counter options." + }, + "dataAccess": { + "description": "Data access options.", + "$ref": "DataAccessOptions" + } + }, + "id": "LogConfig" + }, + "SetIamPolicyRequest": { + "description": "Request message for `SetIamPolicy` method.", + "type": "object", + "properties": { + "policy": { + "$ref": "Policy", + "description": "REQUIRED: The complete policy to be applied to the `resource`. The size of\nthe policy is limited to a few 10s of KB. An empty policy is a\nvalid policy but certain Cloud Platform services (such as Projects)\nmight reject them." + }, + "updateMask": { + "description": "OPTIONAL: A FieldMask specifying which fields of the policy to modify. Only\nthe fields in the mask will be modified. If no mask is provided, the\nfollowing default mask is used:\npaths: \"bindings, etag\"\nThis field is only used by Cloud IAM.", + "format": "google-fieldmask", + "type": "string" + } + }, + "id": "SetIamPolicyRequest" + }, + "DecryptRequest": { + "description": "Request message for KeyManagementService.Decrypt.", + "type": "object", + "properties": { + "ciphertext": { + "description": "Required. The encrypted data originally returned in\nEncryptResponse.ciphertext.", + "format": "byte", + "type": "string" + }, + "additionalAuthenticatedData": { + "description": "Optional data that must match the data originally supplied in\nEncryptRequest.additional_authenticated_data.", + "format": "byte", + "type": "string" + } + }, + "id": "DecryptRequest" + }, + "Location": { + "description": "A resource that represents Google Cloud Platform location.", + "type": "object", + "properties": { + "labels": { + "description": "Cross-service attributes for the location. For example\n\n {\"cloud.googleapis.com/region\": \"us-east1\"}", + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "name": { + "description": "Resource name for the location, which may vary between implementations.\nFor example: `\"projects/example-project/locations/us-east1\"`", + "type": "string" + }, + "locationId": { + "description": "The canonical id for this location. For example: `\"us-east1\"`.", + "type": "string" + }, + "metadata": { + "description": "Service-specific metadata. For example the available capacity at the given\nlocation.", + "type": "object", + "additionalProperties": { + "description": "Properties of the object. Contains field @type with type URL.", + "type": "any" + } + } + }, + "id": "Location" + }, + "ListCryptoKeysResponse": { + "properties": { + "nextPageToken": { + "description": "A token to retrieve next page of results. Pass this value in\nListCryptoKeysRequest.page_token to retrieve the next page of results.", + "type": "string" + }, + "cryptoKeys": { + "description": "The list of CryptoKeys.", + "type": "array", + "items": { + "$ref": "CryptoKey" + } + }, + "totalSize": { + "description": "The total number of CryptoKeys that matched the query.", + "format": "int32", + "type": "integer" + } + }, + "id": "ListCryptoKeysResponse", + "description": "Response message for KeyManagementService.ListCryptoKeys.", + "type": "object" + }, + "Condition": { + "properties": { + "values": { + "description": "The objects of the condition. This is mutually exclusive with 'value'.", + "type": "array", + "items": { + "type": "string" + } + }, + "iam": { + "enumDescriptions": [ + "Default non-attribute.", + "Either principal or (if present) authority selector.", + "The principal (even if an authority selector is present), which\nmust only be used for attribution, not authorization.", + "An approver (distinct from the requester) that has authorized this\nrequest.\nWhen used with IN, the condition indicates that one of the approvers\nassociated with the request matches the specified principal, or is a\nmember of the specified group. Approvers can only grant additional\naccess, and are thus only used in a strictly positive context\n(e.g. ALLOW/IN or DENY/NOT_IN).\nSee: go/rpc-security-policy-dynamicauth.", + "What types of justifications have been supplied with this request.\nString values should match enum names from tech.iam.JustificationType,\ne.g. \"MANUAL_STRING\". It is not permitted to grant access based on\nthe *absence* of a justification, so justification conditions can only\nbe used in a \"positive\" context (e.g., ALLOW/IN or DENY/NOT_IN).\n\nMultiple justifications, e.g., a Buganizer ID and a manually-entered\nreason, are normal and supported." + ], + "enum": [ + "NO_ATTR", + "AUTHORITY", + "ATTRIBUTION", + "APPROVER", + "JUSTIFICATION_TYPE" + ], + "description": "Trusted attributes supplied by the IAM system.", + "type": "string" + }, + "op": { + "enumDescriptions": [ + "Default no-op.", + "DEPRECATED. Use IN instead.", + "DEPRECATED. Use NOT_IN instead.", + "The condition is true if the subject (or any element of it if it is\na set) matches any of the supplied values.", + "The condition is true if the subject (or every element of it if it is\na set) matches none of the supplied values.", + "Subject is discharged" + ], + "enum": [ + "NO_OP", + "EQUALS", + "NOT_EQUALS", + "IN", + "NOT_IN", + "DISCHARGED" + ], + "description": "An operator to apply the subject with.", + "type": "string" + }, + "svc": { + "description": "Trusted attributes discharged by the service.", + "type": "string" + }, + "value": { + "description": "DEPRECATED. Use 'values' instead.", + "type": "string" + }, + "sys": { + "enumDescriptions": [ + "Default non-attribute type", + "Region of the resource", + "Service name", + "Resource name", + "IP address of the caller" + ], + "enum": [ + "NO_ATTR", + "REGION", + "SERVICE", + "NAME", + "IP" + ], + "description": "Trusted attributes supplied by any service that owns resources and uses\nthe IAM system for access control.", + "type": "string" + } + }, + "id": "Condition", + "description": "A condition to be met.", + "type": "object" + }, + "CounterOptions": { + "description": "Options for counters", + "type": "object", + "properties": { + "metric": { + "description": "The metric to update.", + "type": "string" + }, + "field": { + "description": "The field value to attribute.", + "type": "string" + } + }, + "id": "CounterOptions" + }, + "AuditLogConfig": { + "description": "Provides the configuration for logging a type of permissions.\nExample:\n\n {\n \"audit_log_configs\": [\n {\n \"log_type\": \"DATA_READ\",\n \"exempted_members\": [\n \"user:foo@gmail.com\"\n ]\n },\n {\n \"log_type\": \"DATA_WRITE\",\n }\n ]\n }\n\nThis enables 'DATA_READ' and 'DATA_WRITE' logging, while exempting\nfoo@gmail.com from DATA_READ logging.", + "type": "object", + "properties": { + "exemptedMembers": { + "description": "Specifies the identities that do not cause logging for this type of\npermission.\nFollows the same format of Binding.members.", + "type": "array", + "items": { + "type": "string" + } + }, + "logType": { + "description": "The log type that this config enables.", + "type": "string", + "enumDescriptions": [ + "Default case. Should never be this.", + "Admin reads. Example: CloudIAM getIamPolicy", + "Data writes. Example: CloudSQL Users create", + "Data reads. Example: CloudSQL Users list" + ], + "enum": [ + "LOG_TYPE_UNSPECIFIED", + "ADMIN_READ", + "DATA_WRITE", + "DATA_READ" + ] + } + }, + "id": "AuditLogConfig" + }, + "DecryptResponse": { + "description": "Response message for KeyManagementService.Decrypt.", + "type": "object", + "properties": { + "plaintext": { + "description": "The decrypted data originally supplied in EncryptRequest.plaintext.", + "format": "byte", + "type": "string" + } + }, + "id": "DecryptResponse" + }, + "TestIamPermissionsRequest": { + "description": "Request message for `TestIamPermissions` method.", + "type": "object", + "properties": { + "permissions": { + "description": "The set of permissions to check for the `resource`. Permissions with\nwildcards (such as '*' or 'storage.*') are not allowed. For more\ninformation see\n[IAM Overview](https://cloud.google.com/iam/docs/overview#permissions).", + "type": "array", + "items": { + "type": "string" + } + } + }, + "id": "TestIamPermissionsRequest" + }, + "KeyRing": { + "description": "A KeyRing is a toplevel logical grouping of CryptoKeys.", + "type": "object", + "properties": { + "createTime": { + "description": "Output only. The time at which this KeyRing was created.", + "format": "google-datetime", + "type": "string" + }, + "name": { + "description": "Output only. The resource name for the KeyRing in the format\n`projects/*/locations/*/keyRings/*`.", + "type": "string" + } + }, + "id": "KeyRing" + }, + "EncryptResponse": { + "properties": { + "ciphertext": { + "description": "The encrypted data.", + "format": "byte", + "type": "string" + }, + "name": { + "description": "The resource name of the CryptoKeyVersion used in encryption.", + "type": "string" + } + }, + "id": "EncryptResponse", + "description": "Response message for KeyManagementService.Encrypt.", + "type": "object" + }, + "ListLocationsResponse": { + "properties": { + "locations": { + "description": "A list of locations that matches the specified filter in the request.", + "type": "array", + "items": { + "$ref": "Location" + } + }, + "nextPageToken": { + "description": "The standard List next-page token.", + "type": "string" + } + }, + "id": "ListLocationsResponse", + "description": "The response message for Locations.ListLocations.", + "type": "object" + }, + "Policy": { + "description": "Defines an Identity and Access Management (IAM) policy. It is used to\nspecify access control policies for Cloud Platform resources.\n\n\nA `Policy` consists of a list of `bindings`. A `Binding` binds a list of\n`members` to a `role`, where the members can be user accounts, Google groups,\nGoogle domains, and service accounts. A `role` is a named list of permissions\ndefined by IAM.\n\n**Example**\n\n {\n \"bindings\": [\n {\n \"role\": \"roles/owner\",\n \"members\": [\n \"user:mike@example.com\",\n \"group:admins@example.com\",\n \"domain:google.com\",\n \"serviceAccount:my-other-app@appspot.gserviceaccount.com\",\n ]\n },\n {\n \"role\": \"roles/viewer\",\n \"members\": [\"user:sean@example.com\"]\n }\n ]\n }\n\nFor a description of IAM and its features, see the\n[IAM developer's guide](https://cloud.google.com/iam).", + "type": "object", + "properties": { + "etag": { + "description": "`etag` is used for optimistic concurrency control as a way to help\nprevent simultaneous updates of a policy from overwriting each other.\nIt is strongly suggested that systems make use of the `etag` in the\nread-modify-write cycle to perform policy updates in order to avoid race\nconditions: An `etag` is returned in the response to `getIamPolicy`, and\nsystems are expected to put that etag in the request to `setIamPolicy` to\nensure that their change will be applied to the same version of the policy.\n\nIf no `etag` is provided in the call to `setIamPolicy`, then the existing\npolicy is overwritten blindly.", + "format": "byte", + "type": "string" + }, + "iamOwned": { + "type": "boolean" + }, + "rules": { + "description": "If more than one rule is specified, the rules are applied in the following\nmanner:\n- All matching LOG rules are always applied.\n- If any DENY/DENY_WITH_LOG rule matches, permission is denied.\n Logging will be applied if one or more matching rule requires logging.\n- Otherwise, if any ALLOW/ALLOW_WITH_LOG rule matches, permission is\n granted.\n Logging will be applied if one or more matching rule requires logging.\n- Otherwise, if no rule applies, permission is denied.", + "type": "array", + "items": { + "$ref": "Rule" + } + }, + "version": { + "description": "Version of the `Policy`. The default version is 0.", + "format": "int32", + "type": "integer" + }, + "auditConfigs": { + "description": "Specifies cloud audit logging configuration for this policy.", + "type": "array", + "items": { + "$ref": "AuditConfig" + } + }, + "bindings": { + "description": "Associates a list of `members` to a `role`.\nMultiple `bindings` must not be specified for the same `role`.\n`bindings` with no members will result in an error.", + "type": "array", + "items": { + "$ref": "Binding" + } + } + }, + "id": "Policy" + }, + "RestoreCryptoKeyVersionRequest": { + "properties": {}, + "id": "RestoreCryptoKeyVersionRequest", + "description": "Request message for KeyManagementService.RestoreCryptoKeyVersion.", + "type": "object" + }, + "UpdateCryptoKeyPrimaryVersionRequest": { + "description": "Request message for KeyManagementService.UpdateCryptoKeyPrimaryVersion.", + "type": "object", + "properties": { + "cryptoKeyVersionId": { + "description": "The id of the child CryptoKeyVersion to use as primary.", + "type": "string" + } + }, + "id": "UpdateCryptoKeyPrimaryVersionRequest" + }, + "ListKeyRingsResponse": { + "description": "Response message for KeyManagementService.ListKeyRings.", + "type": "object", + "properties": { + "nextPageToken": { + "description": "A token to retrieve next page of results. Pass this value in\nListKeyRingsRequest.page_token to retrieve the next page of results.", + "type": "string" + }, + "totalSize": { + "description": "The total number of KeyRings that matched the query.", + "format": "int32", + "type": "integer" + }, + "keyRings": { + "description": "The list of KeyRings.", + "type": "array", + "items": { + "$ref": "KeyRing" + } + } + }, + "id": "ListKeyRingsResponse" + }, + "DataAccessOptions": { + "description": "Write a Data Access (Gin) log", + "type": "object", + "properties": {}, + "id": "DataAccessOptions" + }, + "AuditConfig": { + "properties": { + "auditLogConfigs": { + "description": "The configuration for logging of each type of permission.\nNext ID: 4", + "type": "array", + "items": { + "$ref": "AuditLogConfig" + } + }, + "exemptedMembers": { + "type": "array", + "items": { + "type": "string" + } + }, + "service": { + "description": "Specifies a service that will be enabled for audit logging.\nFor example, `storage.googleapis.com`, `cloudsql.googleapis.com`.\n`allServices` is a special value that covers all services.", + "type": "string" + } + }, + "id": "AuditConfig", + "description": "Specifies the audit configuration for a service.\nThe configuration determines which permission types are logged, and what\nidentities, if any, are exempted from logging.\nAn AuditConfig must have one or more AuditLogConfigs.\n\nIf there are AuditConfigs for both `allServices` and a specific service,\nthe union of the two AuditConfigs is used for that service: the log_types\nspecified in each AuditConfig are enabled, and the exempted_members in each\nAuditConfig are exempted.\n\nExample Policy with multiple AuditConfigs:\n\n {\n \"audit_configs\": [\n {\n \"service\": \"allServices\"\n \"audit_log_configs\": [\n {\n \"log_type\": \"DATA_READ\",\n \"exempted_members\": [\n \"user:foo@gmail.com\"\n ]\n },\n {\n \"log_type\": \"DATA_WRITE\",\n },\n {\n \"log_type\": \"ADMIN_READ\",\n }\n ]\n },\n {\n \"service\": \"fooservice.googleapis.com\"\n \"audit_log_configs\": [\n {\n \"log_type\": \"DATA_READ\",\n },\n {\n \"log_type\": \"DATA_WRITE\",\n \"exempted_members\": [\n \"user:bar@gmail.com\"\n ]\n }\n ]\n }\n ]\n }\n\nFor fooservice, this policy enables DATA_READ, DATA_WRITE and ADMIN_READ\nlogging. It also exempts foo@gmail.com from DATA_READ logging, and\nbar@gmail.com from DATA_WRITE logging.", + "type": "object" + }, + "CryptoKeyVersion": { + "description": "A CryptoKeyVersion represents an individual cryptographic key, and the\nassociated key material.\n\nIt can be used for cryptographic operations either directly, or via its\nparent CryptoKey, in which case the server will choose the appropriate\nversion for the operation.", + "type": "object", + "properties": { + "destroyTime": { + "description": "Output only. The time this CryptoKeyVersion's key material is scheduled\nfor destruction. Only present if state is\nDESTROY_SCHEDULED.", + "format": "google-datetime", + "type": "string" + }, + "createTime": { + "description": "Output only. The time at which this CryptoKeyVersion was created.", + "format": "google-datetime", + "type": "string" + }, + "state": { + "enum": [ + "CRYPTO_KEY_VERSION_STATE_UNSPECIFIED", + "ENABLED", + "DISABLED", + "DESTROYED", + "DESTROY_SCHEDULED" + ], + "description": "The current state of the CryptoKeyVersion.", + "type": "string", + "enumDescriptions": [ + "Not specified.", + "This version may be used in Encrypt and\nDecrypt requests.", + "This version may not be used, but the key material is still available,\nand the version can be placed back into the ENABLED state.", + "This version is destroyed, and the key material is no longer stored.\nA version may not leave this state once entered.", + "This version is scheduled for destruction, and will be destroyed soon.\nCall\nRestoreCryptoKeyVersion\nto put it back into the DISABLED state." + ] + }, + "name": { + "description": "Output only. The resource name for this CryptoKeyVersion in the format\n`projects/*/locations/*/keyRings/*/cryptoKeys/*/cryptoKeyVersions/*`.", + "type": "string" + }, + "destroyEventTime": { + "description": "Output only. The time this CryptoKeyVersion's key material was\ndestroyed. Only present if state is\nDESTROYED.", + "format": "google-datetime", + "type": "string" + } + }, + "id": "CryptoKeyVersion" + }, + "CloudAuditOptions": { + "description": "Write a Cloud Audit log", + "type": "object", + "properties": {}, + "id": "CloudAuditOptions" + } + }, + "protocol": "rest", + "icons": { + "x16": "http://www.google.com/images/icons/product/search-16.gif", + "x32": "http://www.google.com/images/icons/product/search-32.gif" + }, + "canonicalName": "Cloud KMS", + "auth": { + "oauth2": { + "scopes": { + "https://www.googleapis.com/auth/cloud-platform": { + "description": "View and manage your data across Google Cloud Platform services" + } + } + } + }, + "rootUrl": "https://cloudkms.googleapis.com/" +} diff --git a/vendor/google.golang.org/api/cloudkms/v1/cloudkms-gen.go b/vendor/google.golang.org/api/cloudkms/v1/cloudkms-gen.go new file mode 100644 index 00000000000..2baf8313c94 --- /dev/null +++ b/vendor/google.golang.org/api/cloudkms/v1/cloudkms-gen.go @@ -0,0 +1,5036 @@ +// Package cloudkms provides access to the Google Cloud Key Management Service (KMS) API. +// +// See https://cloud.google.com/kms/ +// +// Usage example: +// +// import "google.golang.org/api/cloudkms/v1" +// ... +// cloudkmsService, err := cloudkms.New(oauthHttpClient) +package cloudkms + +import ( + "bytes" + "encoding/json" + "errors" + "fmt" + context "golang.org/x/net/context" + ctxhttp "golang.org/x/net/context/ctxhttp" + gensupport "google.golang.org/api/gensupport" + googleapi "google.golang.org/api/googleapi" + "io" + "net/http" + "net/url" + "strconv" + "strings" +) + +// Always reference these packages, just in case the auto-generated code +// below doesn't. +var _ = bytes.NewBuffer +var _ = strconv.Itoa +var _ = fmt.Sprintf +var _ = json.NewDecoder +var _ = io.Copy +var _ = url.Parse +var _ = gensupport.MarshalJSON +var _ = googleapi.Version +var _ = errors.New +var _ = strings.Replace +var _ = context.Canceled +var _ = ctxhttp.Do + +const apiId = "cloudkms:v1" +const apiName = "cloudkms" +const apiVersion = "v1" +const basePath = "https://cloudkms.googleapis.com/" + +// OAuth2 scopes used by this API. +const ( + // View and manage your data across Google Cloud Platform services + CloudPlatformScope = "https://www.googleapis.com/auth/cloud-platform" +) + +func New(client *http.Client) (*Service, error) { + if client == nil { + return nil, errors.New("client is nil") + } + s := &Service{client: client, BasePath: basePath} + s.Projects = NewProjectsService(s) + return s, nil +} + +type Service struct { + client *http.Client + BasePath string // API endpoint base URL + UserAgent string // optional additional User-Agent fragment + + Projects *ProjectsService +} + +func (s *Service) userAgent() string { + if s.UserAgent == "" { + return googleapi.UserAgent + } + return googleapi.UserAgent + " " + s.UserAgent +} + +func NewProjectsService(s *Service) *ProjectsService { + rs := &ProjectsService{s: s} + rs.Locations = NewProjectsLocationsService(s) + return rs +} + +type ProjectsService struct { + s *Service + + Locations *ProjectsLocationsService +} + +func NewProjectsLocationsService(s *Service) *ProjectsLocationsService { + rs := &ProjectsLocationsService{s: s} + rs.KeyRings = NewProjectsLocationsKeyRingsService(s) + return rs +} + +type ProjectsLocationsService struct { + s *Service + + KeyRings *ProjectsLocationsKeyRingsService +} + +func NewProjectsLocationsKeyRingsService(s *Service) *ProjectsLocationsKeyRingsService { + rs := &ProjectsLocationsKeyRingsService{s: s} + rs.CryptoKeys = NewProjectsLocationsKeyRingsCryptoKeysService(s) + return rs +} + +type ProjectsLocationsKeyRingsService struct { + s *Service + + CryptoKeys *ProjectsLocationsKeyRingsCryptoKeysService +} + +func NewProjectsLocationsKeyRingsCryptoKeysService(s *Service) *ProjectsLocationsKeyRingsCryptoKeysService { + rs := &ProjectsLocationsKeyRingsCryptoKeysService{s: s} + rs.CryptoKeyVersions = NewProjectsLocationsKeyRingsCryptoKeysCryptoKeyVersionsService(s) + return rs +} + +type ProjectsLocationsKeyRingsCryptoKeysService struct { + s *Service + + CryptoKeyVersions *ProjectsLocationsKeyRingsCryptoKeysCryptoKeyVersionsService +} + +func NewProjectsLocationsKeyRingsCryptoKeysCryptoKeyVersionsService(s *Service) *ProjectsLocationsKeyRingsCryptoKeysCryptoKeyVersionsService { + rs := &ProjectsLocationsKeyRingsCryptoKeysCryptoKeyVersionsService{s: s} + return rs +} + +type ProjectsLocationsKeyRingsCryptoKeysCryptoKeyVersionsService struct { + s *Service +} + +// AuditConfig: Specifies the audit configuration for a service. +// The configuration determines which permission types are logged, and +// what +// identities, if any, are exempted from logging. +// An AuditConfig must have one or more AuditLogConfigs. +// +// If there are AuditConfigs for both `allServices` and a specific +// service, +// the union of the two AuditConfigs is used for that service: the +// log_types +// specified in each AuditConfig are enabled, and the exempted_members +// in each +// AuditConfig are exempted. +// +// Example Policy with multiple AuditConfigs: +// +// { +// "audit_configs": [ +// { +// "service": "allServices" +// "audit_log_configs": [ +// { +// "log_type": "DATA_READ", +// "exempted_members": [ +// "user:foo@gmail.com" +// ] +// }, +// { +// "log_type": "DATA_WRITE", +// }, +// { +// "log_type": "ADMIN_READ", +// } +// ] +// }, +// { +// "service": "fooservice.googleapis.com" +// "audit_log_configs": [ +// { +// "log_type": "DATA_READ", +// }, +// { +// "log_type": "DATA_WRITE", +// "exempted_members": [ +// "user:bar@gmail.com" +// ] +// } +// ] +// } +// ] +// } +// +// For fooservice, this policy enables DATA_READ, DATA_WRITE and +// ADMIN_READ +// logging. It also exempts foo@gmail.com from DATA_READ logging, +// and +// bar@gmail.com from DATA_WRITE logging. +type AuditConfig struct { + // AuditLogConfigs: The configuration for logging of each type of + // permission. + // Next ID: 4 + AuditLogConfigs []*AuditLogConfig `json:"auditLogConfigs,omitempty"` + + ExemptedMembers []string `json:"exemptedMembers,omitempty"` + + // Service: Specifies a service that will be enabled for audit + // logging. + // For example, `storage.googleapis.com`, + // `cloudsql.googleapis.com`. + // `allServices` is a special value that covers all services. + Service string `json:"service,omitempty"` + + // ForceSendFields is a list of field names (e.g. "AuditLogConfigs") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "AuditLogConfigs") to + // include in API requests with the JSON null value. By default, fields + // with empty values are omitted from API requests. However, any field + // with an empty value appearing in NullFields will be sent to the + // server as null. It is an error if a field in this list has a + // non-empty value. This may be used to include null fields in Patch + // requests. + NullFields []string `json:"-"` +} + +func (s *AuditConfig) MarshalJSON() ([]byte, error) { + type noMethod AuditConfig + raw := noMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// AuditLogConfig: Provides the configuration for logging a type of +// permissions. +// Example: +// +// { +// "audit_log_configs": [ +// { +// "log_type": "DATA_READ", +// "exempted_members": [ +// "user:foo@gmail.com" +// ] +// }, +// { +// "log_type": "DATA_WRITE", +// } +// ] +// } +// +// This enables 'DATA_READ' and 'DATA_WRITE' logging, while +// exempting +// foo@gmail.com from DATA_READ logging. +type AuditLogConfig struct { + // ExemptedMembers: Specifies the identities that do not cause logging + // for this type of + // permission. + // Follows the same format of Binding.members. + ExemptedMembers []string `json:"exemptedMembers,omitempty"` + + // LogType: The log type that this config enables. + // + // Possible values: + // "LOG_TYPE_UNSPECIFIED" - Default case. Should never be this. + // "ADMIN_READ" - Admin reads. Example: CloudIAM getIamPolicy + // "DATA_WRITE" - Data writes. Example: CloudSQL Users create + // "DATA_READ" - Data reads. Example: CloudSQL Users list + LogType string `json:"logType,omitempty"` + + // ForceSendFields is a list of field names (e.g. "ExemptedMembers") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "ExemptedMembers") to + // include in API requests with the JSON null value. By default, fields + // with empty values are omitted from API requests. However, any field + // with an empty value appearing in NullFields will be sent to the + // server as null. It is an error if a field in this list has a + // non-empty value. This may be used to include null fields in Patch + // requests. + NullFields []string `json:"-"` +} + +func (s *AuditLogConfig) MarshalJSON() ([]byte, error) { + type noMethod AuditLogConfig + raw := noMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// Binding: Associates `members` with a `role`. +type Binding struct { + // Members: Specifies the identities requesting access for a Cloud + // Platform resource. + // `members` can have the following values: + // + // * `allUsers`: A special identifier that represents anyone who is + // on the internet; with or without a Google account. + // + // * `allAuthenticatedUsers`: A special identifier that represents + // anyone + // who is authenticated with a Google account or a service + // account. + // + // * `user:{emailid}`: An email address that represents a specific + // Google + // account. For example, `alice@gmail.com` or `joe@example.com`. + // + // + // * `serviceAccount:{emailid}`: An email address that represents a + // service + // account. For example, + // `my-other-app@appspot.gserviceaccount.com`. + // + // * `group:{emailid}`: An email address that represents a Google + // group. + // For example, `admins@example.com`. + // + // * `domain:{domain}`: A Google Apps domain name that represents all + // the + // users of that domain. For example, `google.com` or + // `example.com`. + // + // + Members []string `json:"members,omitempty"` + + // Role: Role that is assigned to `members`. + // For example, `roles/viewer`, `roles/editor`, or + // `roles/owner`. + // Required + Role string `json:"role,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Members") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Members") to include in + // API requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *Binding) MarshalJSON() ([]byte, error) { + type noMethod Binding + raw := noMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// CloudAuditOptions: Write a Cloud Audit log +type CloudAuditOptions struct { +} + +// Condition: A condition to be met. +type Condition struct { + // Iam: Trusted attributes supplied by the IAM system. + // + // Possible values: + // "NO_ATTR" - Default non-attribute. + // "AUTHORITY" - Either principal or (if present) authority selector. + // "ATTRIBUTION" - The principal (even if an authority selector is + // present), which + // must only be used for attribution, not authorization. + // "APPROVER" - An approver (distinct from the requester) that has + // authorized this + // request. + // When used with IN, the condition indicates that one of the + // approvers + // associated with the request matches the specified principal, or is + // a + // member of the specified group. Approvers can only grant + // additional + // access, and are thus only used in a strictly positive context + // (e.g. ALLOW/IN or DENY/NOT_IN). + // See: go/rpc-security-policy-dynamicauth. + // "JUSTIFICATION_TYPE" - What types of justifications have been + // supplied with this request. + // String values should match enum names from + // tech.iam.JustificationType, + // e.g. "MANUAL_STRING". It is not permitted to grant access based + // on + // the *absence* of a justification, so justification conditions can + // only + // be used in a "positive" context (e.g., ALLOW/IN or + // DENY/NOT_IN). + // + // Multiple justifications, e.g., a Buganizer ID and a + // manually-entered + // reason, are normal and supported. + Iam string `json:"iam,omitempty"` + + // Op: An operator to apply the subject with. + // + // Possible values: + // "NO_OP" - Default no-op. + // "EQUALS" - DEPRECATED. Use IN instead. + // "NOT_EQUALS" - DEPRECATED. Use NOT_IN instead. + // "IN" - The condition is true if the subject (or any element of it + // if it is + // a set) matches any of the supplied values. + // "NOT_IN" - The condition is true if the subject (or every element + // of it if it is + // a set) matches none of the supplied values. + // "DISCHARGED" - Subject is discharged + Op string `json:"op,omitempty"` + + // Svc: Trusted attributes discharged by the service. + Svc string `json:"svc,omitempty"` + + // Sys: Trusted attributes supplied by any service that owns resources + // and uses + // the IAM system for access control. + // + // Possible values: + // "NO_ATTR" - Default non-attribute type + // "REGION" - Region of the resource + // "SERVICE" - Service name + // "NAME" - Resource name + // "IP" - IP address of the caller + Sys string `json:"sys,omitempty"` + + // Value: DEPRECATED. Use 'values' instead. + Value string `json:"value,omitempty"` + + // Values: The objects of the condition. This is mutually exclusive with + // 'value'. + Values []string `json:"values,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Iam") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Iam") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *Condition) MarshalJSON() ([]byte, error) { + type noMethod Condition + raw := noMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// CounterOptions: Options for counters +type CounterOptions struct { + // Field: The field value to attribute. + Field string `json:"field,omitempty"` + + // Metric: The metric to update. + Metric string `json:"metric,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Field") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Field") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *CounterOptions) MarshalJSON() ([]byte, error) { + type noMethod CounterOptions + raw := noMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// CryptoKey: A CryptoKey represents a logical key that can be used for +// cryptographic +// operations. +// +// A CryptoKey is made up of one or more versions, which +// represent the actual key material used in cryptographic operations. +type CryptoKey struct { + // CreateTime: Output only. The time at which this CryptoKey was + // created. + CreateTime string `json:"createTime,omitempty"` + + // Name: Output only. The resource name for this CryptoKey in the + // format + // `projects/*/locations/*/keyRings/*/cryptoKeys/*`. + Name string `json:"name,omitempty"` + + // NextRotationTime: At next_rotation_time, the Key Management Service + // will automatically: + // + // 1. Create a new version of this CryptoKey. + // 2. Mark the new version as primary. + // + // Key rotations performed manually via + // CreateCryptoKeyVersion and + // UpdateCryptoKeyPrimaryVersion + // do not affect next_rotation_time. + NextRotationTime string `json:"nextRotationTime,omitempty"` + + // Primary: Output only. A copy of the "primary" CryptoKeyVersion that + // will be used + // by Encrypt when this CryptoKey is given + // in EncryptRequest.name. + // + // The CryptoKey's primary version can be updated + // via + // UpdateCryptoKeyPrimaryVersion. + Primary *CryptoKeyVersion `json:"primary,omitempty"` + + // Purpose: The immutable purpose of this CryptoKey. Currently, the only + // acceptable + // purpose is ENCRYPT_DECRYPT. + // + // Possible values: + // "CRYPTO_KEY_PURPOSE_UNSPECIFIED" - Not specified. + // "ENCRYPT_DECRYPT" - CryptoKeys with this purpose may be used + // with + // Encrypt and + // Decrypt. + Purpose string `json:"purpose,omitempty"` + + // RotationPeriod: next_rotation_time will be advanced by this period + // when the service + // automatically rotates a key. Must be at least one day. + // + // If rotation_period is set, next_rotation_time must also be set. + RotationPeriod string `json:"rotationPeriod,omitempty"` + + // ServerResponse contains the HTTP response code and headers from the + // server. + googleapi.ServerResponse `json:"-"` + + // ForceSendFields is a list of field names (e.g. "CreateTime") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "CreateTime") to include in + // API requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *CryptoKey) MarshalJSON() ([]byte, error) { + type noMethod CryptoKey + raw := noMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// CryptoKeyVersion: A CryptoKeyVersion represents an individual +// cryptographic key, and the +// associated key material. +// +// It can be used for cryptographic operations either directly, or via +// its +// parent CryptoKey, in which case the server will choose the +// appropriate +// version for the operation. +type CryptoKeyVersion struct { + // CreateTime: Output only. The time at which this CryptoKeyVersion was + // created. + CreateTime string `json:"createTime,omitempty"` + + // DestroyEventTime: Output only. The time this CryptoKeyVersion's key + // material was + // destroyed. Only present if state is + // DESTROYED. + DestroyEventTime string `json:"destroyEventTime,omitempty"` + + // DestroyTime: Output only. The time this CryptoKeyVersion's key + // material is scheduled + // for destruction. Only present if state is + // DESTROY_SCHEDULED. + DestroyTime string `json:"destroyTime,omitempty"` + + // Name: Output only. The resource name for this CryptoKeyVersion in the + // format + // `projects/*/locations/*/keyRings/*/cryptoKeys/*/cryptoKeyVersio + // ns/*`. + Name string `json:"name,omitempty"` + + // State: The current state of the CryptoKeyVersion. + // + // Possible values: + // "CRYPTO_KEY_VERSION_STATE_UNSPECIFIED" - Not specified. + // "ENABLED" - This version may be used in Encrypt and + // Decrypt requests. + // "DISABLED" - This version may not be used, but the key material is + // still available, + // and the version can be placed back into the ENABLED state. + // "DESTROYED" - This version is destroyed, and the key material is no + // longer stored. + // A version may not leave this state once entered. + // "DESTROY_SCHEDULED" - This version is scheduled for destruction, + // and will be destroyed soon. + // Call + // RestoreCryptoKeyVersion + // to put it back into the DISABLED state. + State string `json:"state,omitempty"` + + // ServerResponse contains the HTTP response code and headers from the + // server. + googleapi.ServerResponse `json:"-"` + + // ForceSendFields is a list of field names (e.g. "CreateTime") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "CreateTime") to include in + // API requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *CryptoKeyVersion) MarshalJSON() ([]byte, error) { + type noMethod CryptoKeyVersion + raw := noMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// DataAccessOptions: Write a Data Access (Gin) log +type DataAccessOptions struct { +} + +// DecryptRequest: Request message for KeyManagementService.Decrypt. +type DecryptRequest struct { + // AdditionalAuthenticatedData: Optional data that must match the data + // originally supplied in + // EncryptRequest.additional_authenticated_data. + AdditionalAuthenticatedData string `json:"additionalAuthenticatedData,omitempty"` + + // Ciphertext: Required. The encrypted data originally returned + // in + // EncryptResponse.ciphertext. + Ciphertext string `json:"ciphertext,omitempty"` + + // ForceSendFields is a list of field names (e.g. + // "AdditionalAuthenticatedData") to unconditionally include in API + // requests. By default, fields with empty values are omitted from API + // requests. However, any non-pointer, non-interface field appearing in + // ForceSendFields will be sent to the server regardless of whether the + // field is empty or not. This may be used to include empty fields in + // Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. + // "AdditionalAuthenticatedData") to include in API requests with the + // JSON null value. By default, fields with empty values are omitted + // from API requests. However, any field with an empty value appearing + // in NullFields will be sent to the server as null. It is an error if a + // field in this list has a non-empty value. This may be used to include + // null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *DecryptRequest) MarshalJSON() ([]byte, error) { + type noMethod DecryptRequest + raw := noMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// DecryptResponse: Response message for KeyManagementService.Decrypt. +type DecryptResponse struct { + // Plaintext: The decrypted data originally supplied in + // EncryptRequest.plaintext. + Plaintext string `json:"plaintext,omitempty"` + + // ServerResponse contains the HTTP response code and headers from the + // server. + googleapi.ServerResponse `json:"-"` + + // ForceSendFields is a list of field names (e.g. "Plaintext") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Plaintext") to include in + // API requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *DecryptResponse) MarshalJSON() ([]byte, error) { + type noMethod DecryptResponse + raw := noMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// DestroyCryptoKeyVersionRequest: Request message for +// KeyManagementService.DestroyCryptoKeyVersion. +type DestroyCryptoKeyVersionRequest struct { +} + +// EncryptRequest: Request message for KeyManagementService.Encrypt. +type EncryptRequest struct { + // AdditionalAuthenticatedData: Optional data that, if specified, must + // also be provided during decryption + // through DecryptRequest.additional_authenticated_data. Must be + // no + // larger than 64KiB. + AdditionalAuthenticatedData string `json:"additionalAuthenticatedData,omitempty"` + + // Plaintext: Required. The data to encrypt. Must be no larger than + // 64KiB. + Plaintext string `json:"plaintext,omitempty"` + + // ForceSendFields is a list of field names (e.g. + // "AdditionalAuthenticatedData") to unconditionally include in API + // requests. By default, fields with empty values are omitted from API + // requests. However, any non-pointer, non-interface field appearing in + // ForceSendFields will be sent to the server regardless of whether the + // field is empty or not. This may be used to include empty fields in + // Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. + // "AdditionalAuthenticatedData") to include in API requests with the + // JSON null value. By default, fields with empty values are omitted + // from API requests. However, any field with an empty value appearing + // in NullFields will be sent to the server as null. It is an error if a + // field in this list has a non-empty value. This may be used to include + // null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *EncryptRequest) MarshalJSON() ([]byte, error) { + type noMethod EncryptRequest + raw := noMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// EncryptResponse: Response message for KeyManagementService.Encrypt. +type EncryptResponse struct { + // Ciphertext: The encrypted data. + Ciphertext string `json:"ciphertext,omitempty"` + + // Name: The resource name of the CryptoKeyVersion used in encryption. + Name string `json:"name,omitempty"` + + // ServerResponse contains the HTTP response code and headers from the + // server. + googleapi.ServerResponse `json:"-"` + + // ForceSendFields is a list of field names (e.g. "Ciphertext") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Ciphertext") to include in + // API requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *EncryptResponse) MarshalJSON() ([]byte, error) { + type noMethod EncryptResponse + raw := noMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// KeyRing: A KeyRing is a toplevel logical grouping of CryptoKeys. +type KeyRing struct { + // CreateTime: Output only. The time at which this KeyRing was created. + CreateTime string `json:"createTime,omitempty"` + + // Name: Output only. The resource name for the KeyRing in the + // format + // `projects/*/locations/*/keyRings/*`. + Name string `json:"name,omitempty"` + + // ServerResponse contains the HTTP response code and headers from the + // server. + googleapi.ServerResponse `json:"-"` + + // ForceSendFields is a list of field names (e.g. "CreateTime") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "CreateTime") to include in + // API requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *KeyRing) MarshalJSON() ([]byte, error) { + type noMethod KeyRing + raw := noMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// ListCryptoKeyVersionsResponse: Response message for +// KeyManagementService.ListCryptoKeyVersions. +type ListCryptoKeyVersionsResponse struct { + // CryptoKeyVersions: The list of CryptoKeyVersions. + CryptoKeyVersions []*CryptoKeyVersion `json:"cryptoKeyVersions,omitempty"` + + // NextPageToken: A token to retrieve next page of results. Pass this + // value in + // ListCryptoKeyVersionsRequest.page_token to retrieve the next page + // of + // results. + NextPageToken string `json:"nextPageToken,omitempty"` + + // TotalSize: The total number of CryptoKeyVersions that matched + // the + // query. + TotalSize int64 `json:"totalSize,omitempty"` + + // ServerResponse contains the HTTP response code and headers from the + // server. + googleapi.ServerResponse `json:"-"` + + // ForceSendFields is a list of field names (e.g. "CryptoKeyVersions") + // to unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "CryptoKeyVersions") to + // include in API requests with the JSON null value. By default, fields + // with empty values are omitted from API requests. However, any field + // with an empty value appearing in NullFields will be sent to the + // server as null. It is an error if a field in this list has a + // non-empty value. This may be used to include null fields in Patch + // requests. + NullFields []string `json:"-"` +} + +func (s *ListCryptoKeyVersionsResponse) MarshalJSON() ([]byte, error) { + type noMethod ListCryptoKeyVersionsResponse + raw := noMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// ListCryptoKeysResponse: Response message for +// KeyManagementService.ListCryptoKeys. +type ListCryptoKeysResponse struct { + // CryptoKeys: The list of CryptoKeys. + CryptoKeys []*CryptoKey `json:"cryptoKeys,omitempty"` + + // NextPageToken: A token to retrieve next page of results. Pass this + // value in + // ListCryptoKeysRequest.page_token to retrieve the next page of + // results. + NextPageToken string `json:"nextPageToken,omitempty"` + + // TotalSize: The total number of CryptoKeys that matched the query. + TotalSize int64 `json:"totalSize,omitempty"` + + // ServerResponse contains the HTTP response code and headers from the + // server. + googleapi.ServerResponse `json:"-"` + + // ForceSendFields is a list of field names (e.g. "CryptoKeys") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "CryptoKeys") to include in + // API requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *ListCryptoKeysResponse) MarshalJSON() ([]byte, error) { + type noMethod ListCryptoKeysResponse + raw := noMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// ListKeyRingsResponse: Response message for +// KeyManagementService.ListKeyRings. +type ListKeyRingsResponse struct { + // KeyRings: The list of KeyRings. + KeyRings []*KeyRing `json:"keyRings,omitempty"` + + // NextPageToken: A token to retrieve next page of results. Pass this + // value in + // ListKeyRingsRequest.page_token to retrieve the next page of results. + NextPageToken string `json:"nextPageToken,omitempty"` + + // TotalSize: The total number of KeyRings that matched the query. + TotalSize int64 `json:"totalSize,omitempty"` + + // ServerResponse contains the HTTP response code and headers from the + // server. + googleapi.ServerResponse `json:"-"` + + // ForceSendFields is a list of field names (e.g. "KeyRings") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "KeyRings") to include in + // API requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *ListKeyRingsResponse) MarshalJSON() ([]byte, error) { + type noMethod ListKeyRingsResponse + raw := noMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// ListLocationsResponse: The response message for +// Locations.ListLocations. +type ListLocationsResponse struct { + // Locations: A list of locations that matches the specified filter in + // the request. + Locations []*Location `json:"locations,omitempty"` + + // NextPageToken: The standard List next-page token. + NextPageToken string `json:"nextPageToken,omitempty"` + + // ServerResponse contains the HTTP response code and headers from the + // server. + googleapi.ServerResponse `json:"-"` + + // ForceSendFields is a list of field names (e.g. "Locations") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Locations") to include in + // API requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *ListLocationsResponse) MarshalJSON() ([]byte, error) { + type noMethod ListLocationsResponse + raw := noMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// Location: A resource that represents Google Cloud Platform location. +type Location struct { + // Labels: Cross-service attributes for the location. For example + // + // {"cloud.googleapis.com/region": "us-east1"} + Labels map[string]string `json:"labels,omitempty"` + + // LocationId: The canonical id for this location. For example: + // "us-east1". + LocationId string `json:"locationId,omitempty"` + + // Metadata: Service-specific metadata. For example the available + // capacity at the given + // location. + Metadata googleapi.RawMessage `json:"metadata,omitempty"` + + // Name: Resource name for the location, which may vary between + // implementations. + // For example: "projects/example-project/locations/us-east1" + Name string `json:"name,omitempty"` + + // ServerResponse contains the HTTP response code and headers from the + // server. + googleapi.ServerResponse `json:"-"` + + // ForceSendFields is a list of field names (e.g. "Labels") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Labels") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *Location) MarshalJSON() ([]byte, error) { + type noMethod Location + raw := noMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// LogConfig: Specifies what kind of log the caller must write +type LogConfig struct { + // CloudAudit: Cloud audit options. + CloudAudit *CloudAuditOptions `json:"cloudAudit,omitempty"` + + // Counter: Counter options. + Counter *CounterOptions `json:"counter,omitempty"` + + // DataAccess: Data access options. + DataAccess *DataAccessOptions `json:"dataAccess,omitempty"` + + // ForceSendFields is a list of field names (e.g. "CloudAudit") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "CloudAudit") to include in + // API requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *LogConfig) MarshalJSON() ([]byte, error) { + type noMethod LogConfig + raw := noMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// Policy: Defines an Identity and Access Management (IAM) policy. It is +// used to +// specify access control policies for Cloud Platform resources. +// +// +// A `Policy` consists of a list of `bindings`. A `Binding` binds a list +// of +// `members` to a `role`, where the members can be user accounts, Google +// groups, +// Google domains, and service accounts. A `role` is a named list of +// permissions +// defined by IAM. +// +// **Example** +// +// { +// "bindings": [ +// { +// "role": "roles/owner", +// "members": [ +// "user:mike@example.com", +// "group:admins@example.com", +// "domain:google.com", +// +// "serviceAccount:my-other-app@appspot.gserviceaccount.com", +// ] +// }, +// { +// "role": "roles/viewer", +// "members": ["user:sean@example.com"] +// } +// ] +// } +// +// For a description of IAM and its features, see the +// [IAM developer's guide](https://cloud.google.com/iam). +type Policy struct { + // AuditConfigs: Specifies cloud audit logging configuration for this + // policy. + AuditConfigs []*AuditConfig `json:"auditConfigs,omitempty"` + + // Bindings: Associates a list of `members` to a `role`. + // Multiple `bindings` must not be specified for the same + // `role`. + // `bindings` with no members will result in an error. + Bindings []*Binding `json:"bindings,omitempty"` + + // Etag: `etag` is used for optimistic concurrency control as a way to + // help + // prevent simultaneous updates of a policy from overwriting each + // other. + // It is strongly suggested that systems make use of the `etag` in + // the + // read-modify-write cycle to perform policy updates in order to avoid + // race + // conditions: An `etag` is returned in the response to `getIamPolicy`, + // and + // systems are expected to put that etag in the request to + // `setIamPolicy` to + // ensure that their change will be applied to the same version of the + // policy. + // + // If no `etag` is provided in the call to `setIamPolicy`, then the + // existing + // policy is overwritten blindly. + Etag string `json:"etag,omitempty"` + + IamOwned bool `json:"iamOwned,omitempty"` + + // Rules: If more than one rule is specified, the rules are applied in + // the following + // manner: + // - All matching LOG rules are always applied. + // - If any DENY/DENY_WITH_LOG rule matches, permission is denied. + // Logging will be applied if one or more matching rule requires + // logging. + // - Otherwise, if any ALLOW/ALLOW_WITH_LOG rule matches, permission is + // granted. + // Logging will be applied if one or more matching rule requires + // logging. + // - Otherwise, if no rule applies, permission is denied. + Rules []*Rule `json:"rules,omitempty"` + + // Version: Version of the `Policy`. The default version is 0. + Version int64 `json:"version,omitempty"` + + // ServerResponse contains the HTTP response code and headers from the + // server. + googleapi.ServerResponse `json:"-"` + + // ForceSendFields is a list of field names (e.g. "AuditConfigs") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "AuditConfigs") to include + // in API requests with the JSON null value. By default, fields with + // empty values are omitted from API requests. However, any field with + // an empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *Policy) MarshalJSON() ([]byte, error) { + type noMethod Policy + raw := noMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// RestoreCryptoKeyVersionRequest: Request message for +// KeyManagementService.RestoreCryptoKeyVersion. +type RestoreCryptoKeyVersionRequest struct { +} + +// Rule: A rule to be applied in a Policy. +type Rule struct { + // Action: Required + // + // Possible values: + // "NO_ACTION" - Default no action. + // "ALLOW" - Matching 'Entries' grant access. + // "ALLOW_WITH_LOG" - Matching 'Entries' grant access and the caller + // promises to log + // the request per the returned log_configs. + // "DENY" - Matching 'Entries' deny access. + // "DENY_WITH_LOG" - Matching 'Entries' deny access and the caller + // promises to log + // the request per the returned log_configs. + // "LOG" - Matching 'Entries' tell IAM.Check callers to generate logs. + Action string `json:"action,omitempty"` + + // Conditions: Additional restrictions that must be met + Conditions []*Condition `json:"conditions,omitempty"` + + // Description: Human-readable description of the rule. + Description string `json:"description,omitempty"` + + // In: If one or more 'in' clauses are specified, the rule matches + // if + // the PRINCIPAL/AUTHORITY_SELECTOR is in at least one of these entries. + In []string `json:"in,omitempty"` + + // LogConfig: The config returned to callers of tech.iam.IAM.CheckPolicy + // for any entries + // that match the LOG action. + LogConfig []*LogConfig `json:"logConfig,omitempty"` + + // NotIn: If one or more 'not_in' clauses are specified, the rule + // matches + // if the PRINCIPAL/AUTHORITY_SELECTOR is in none of the entries. + // The format for in and not_in entries is the same as for members in + // a + // Binding (see google/iam/v1/policy.proto). + NotIn []string `json:"notIn,omitempty"` + + // Permissions: A permission is a string of form '..' + // (e.g., 'storage.buckets.list'). A value of '*' matches all + // permissions, + // and a verb part of '*' (e.g., 'storage.buckets.*') matches all verbs. + Permissions []string `json:"permissions,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Action") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Action") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *Rule) MarshalJSON() ([]byte, error) { + type noMethod Rule + raw := noMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// SetIamPolicyRequest: Request message for `SetIamPolicy` method. +type SetIamPolicyRequest struct { + // Policy: REQUIRED: The complete policy to be applied to the + // `resource`. The size of + // the policy is limited to a few 10s of KB. An empty policy is a + // valid policy but certain Cloud Platform services (such as + // Projects) + // might reject them. + Policy *Policy `json:"policy,omitempty"` + + // UpdateMask: OPTIONAL: A FieldMask specifying which fields of the + // policy to modify. Only + // the fields in the mask will be modified. If no mask is provided, + // the + // following default mask is used: + // paths: "bindings, etag" + // This field is only used by Cloud IAM. + UpdateMask string `json:"updateMask,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Policy") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Policy") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *SetIamPolicyRequest) MarshalJSON() ([]byte, error) { + type noMethod SetIamPolicyRequest + raw := noMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// TestIamPermissionsRequest: Request message for `TestIamPermissions` +// method. +type TestIamPermissionsRequest struct { + // Permissions: The set of permissions to check for the `resource`. + // Permissions with + // wildcards (such as '*' or 'storage.*') are not allowed. For + // more + // information see + // [IAM + // Overview](https://cloud.google.com/iam/docs/overview#permissions). + Permissions []string `json:"permissions,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Permissions") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Permissions") to include + // in API requests with the JSON null value. By default, fields with + // empty values are omitted from API requests. However, any field with + // an empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *TestIamPermissionsRequest) MarshalJSON() ([]byte, error) { + type noMethod TestIamPermissionsRequest + raw := noMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// TestIamPermissionsResponse: Response message for `TestIamPermissions` +// method. +type TestIamPermissionsResponse struct { + // Permissions: A subset of `TestPermissionsRequest.permissions` that + // the caller is + // allowed. + Permissions []string `json:"permissions,omitempty"` + + // ServerResponse contains the HTTP response code and headers from the + // server. + googleapi.ServerResponse `json:"-"` + + // ForceSendFields is a list of field names (e.g. "Permissions") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Permissions") to include + // in API requests with the JSON null value. By default, fields with + // empty values are omitted from API requests. However, any field with + // an empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *TestIamPermissionsResponse) MarshalJSON() ([]byte, error) { + type noMethod TestIamPermissionsResponse + raw := noMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// UpdateCryptoKeyPrimaryVersionRequest: Request message for +// KeyManagementService.UpdateCryptoKeyPrimaryVersion. +type UpdateCryptoKeyPrimaryVersionRequest struct { + // CryptoKeyVersionId: The id of the child CryptoKeyVersion to use as + // primary. + CryptoKeyVersionId string `json:"cryptoKeyVersionId,omitempty"` + + // ForceSendFields is a list of field names (e.g. "CryptoKeyVersionId") + // to unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "CryptoKeyVersionId") to + // include in API requests with the JSON null value. By default, fields + // with empty values are omitted from API requests. However, any field + // with an empty value appearing in NullFields will be sent to the + // server as null. It is an error if a field in this list has a + // non-empty value. This may be used to include null fields in Patch + // requests. + NullFields []string `json:"-"` +} + +func (s *UpdateCryptoKeyPrimaryVersionRequest) MarshalJSON() ([]byte, error) { + type noMethod UpdateCryptoKeyPrimaryVersionRequest + raw := noMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// method id "cloudkms.projects.locations.get": + +type ProjectsLocationsGetCall struct { + s *Service + name string + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header +} + +// Get: Get information about a location. +func (r *ProjectsLocationsService) Get(name string) *ProjectsLocationsGetCall { + c := &ProjectsLocationsGetCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.name = name + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *ProjectsLocationsGetCall) Fields(s ...googleapi.Field) *ProjectsLocationsGetCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// IfNoneMatch sets the optional parameter which makes the operation +// fail if the object's ETag matches the given value. This is useful for +// getting updates only after the object has changed since the last +// request. Use googleapi.IsNotModified to check whether the response +// error from Do is the result of In-None-Match. +func (c *ProjectsLocationsGetCall) IfNoneMatch(entityTag string) *ProjectsLocationsGetCall { + c.ifNoneMatch_ = entityTag + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *ProjectsLocationsGetCall) Context(ctx context.Context) *ProjectsLocationsGetCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *ProjectsLocationsGetCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *ProjectsLocationsGetCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + if c.ifNoneMatch_ != "" { + reqHeaders.Set("If-None-Match", c.ifNoneMatch_) + } + var body io.Reader = nil + c.urlParams_.Set("alt", alt) + urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}") + urls += "?" + c.urlParams_.Encode() + req, _ := http.NewRequest("GET", urls, body) + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "name": c.name, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "cloudkms.projects.locations.get" call. +// Exactly one of *Location or error will be non-nil. Any non-2xx status +// code is an error. Response headers are in either +// *Location.ServerResponse.Header or (if a response was returned at +// all) in error.(*googleapi.Error).Header. Use googleapi.IsNotModified +// to check whether the returned error was because +// http.StatusNotModified was returned. +func (c *ProjectsLocationsGetCall) Do(opts ...googleapi.CallOption) (*Location, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &Location{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := json.NewDecoder(res.Body).Decode(target); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Get information about a location.", + // "flatPath": "v1/projects/{projectsId}/locations/{locationsId}", + // "httpMethod": "GET", + // "id": "cloudkms.projects.locations.get", + // "parameterOrder": [ + // "name" + // ], + // "parameters": { + // "name": { + // "description": "Resource name for the location.", + // "location": "path", + // "pattern": "^projects/[^/]+/locations/[^/]+$", + // "required": true, + // "type": "string" + // } + // }, + // "path": "v1/{+name}", + // "response": { + // "$ref": "Location" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform" + // ] + // } + +} + +// method id "cloudkms.projects.locations.list": + +type ProjectsLocationsListCall struct { + s *Service + name string + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header +} + +// List: Lists information about the supported locations for this +// service. +func (r *ProjectsLocationsService) List(name string) *ProjectsLocationsListCall { + c := &ProjectsLocationsListCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.name = name + return c +} + +// Filter sets the optional parameter "filter": The standard list +// filter. +func (c *ProjectsLocationsListCall) Filter(filter string) *ProjectsLocationsListCall { + c.urlParams_.Set("filter", filter) + return c +} + +// PageSize sets the optional parameter "pageSize": The standard list +// page size. +func (c *ProjectsLocationsListCall) PageSize(pageSize int64) *ProjectsLocationsListCall { + c.urlParams_.Set("pageSize", fmt.Sprint(pageSize)) + return c +} + +// PageToken sets the optional parameter "pageToken": The standard list +// page token. +func (c *ProjectsLocationsListCall) PageToken(pageToken string) *ProjectsLocationsListCall { + c.urlParams_.Set("pageToken", pageToken) + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *ProjectsLocationsListCall) Fields(s ...googleapi.Field) *ProjectsLocationsListCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// IfNoneMatch sets the optional parameter which makes the operation +// fail if the object's ETag matches the given value. This is useful for +// getting updates only after the object has changed since the last +// request. Use googleapi.IsNotModified to check whether the response +// error from Do is the result of In-None-Match. +func (c *ProjectsLocationsListCall) IfNoneMatch(entityTag string) *ProjectsLocationsListCall { + c.ifNoneMatch_ = entityTag + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *ProjectsLocationsListCall) Context(ctx context.Context) *ProjectsLocationsListCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *ProjectsLocationsListCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *ProjectsLocationsListCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + if c.ifNoneMatch_ != "" { + reqHeaders.Set("If-None-Match", c.ifNoneMatch_) + } + var body io.Reader = nil + c.urlParams_.Set("alt", alt) + urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}/locations") + urls += "?" + c.urlParams_.Encode() + req, _ := http.NewRequest("GET", urls, body) + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "name": c.name, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "cloudkms.projects.locations.list" call. +// Exactly one of *ListLocationsResponse or error will be non-nil. Any +// non-2xx status code is an error. Response headers are in either +// *ListLocationsResponse.ServerResponse.Header or (if a response was +// returned at all) in error.(*googleapi.Error).Header. Use +// googleapi.IsNotModified to check whether the returned error was +// because http.StatusNotModified was returned. +func (c *ProjectsLocationsListCall) Do(opts ...googleapi.CallOption) (*ListLocationsResponse, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &ListLocationsResponse{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := json.NewDecoder(res.Body).Decode(target); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Lists information about the supported locations for this service.", + // "flatPath": "v1/projects/{projectsId}/locations", + // "httpMethod": "GET", + // "id": "cloudkms.projects.locations.list", + // "parameterOrder": [ + // "name" + // ], + // "parameters": { + // "filter": { + // "description": "The standard list filter.", + // "location": "query", + // "type": "string" + // }, + // "name": { + // "description": "The resource that owns the locations collection, if applicable.", + // "location": "path", + // "pattern": "^projects/[^/]+$", + // "required": true, + // "type": "string" + // }, + // "pageSize": { + // "description": "The standard list page size.", + // "format": "int32", + // "location": "query", + // "type": "integer" + // }, + // "pageToken": { + // "description": "The standard list page token.", + // "location": "query", + // "type": "string" + // } + // }, + // "path": "v1/{+name}/locations", + // "response": { + // "$ref": "ListLocationsResponse" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform" + // ] + // } + +} + +// Pages invokes f for each page of results. +// A non-nil error returned from f will halt the iteration. +// The provided context supersedes any context provided to the Context method. +func (c *ProjectsLocationsListCall) Pages(ctx context.Context, f func(*ListLocationsResponse) error) error { + c.ctx_ = ctx + defer c.PageToken(c.urlParams_.Get("pageToken")) // reset paging to original point + for { + x, err := c.Do() + if err != nil { + return err + } + if err := f(x); err != nil { + return err + } + if x.NextPageToken == "" { + return nil + } + c.PageToken(x.NextPageToken) + } +} + +// method id "cloudkms.projects.locations.keyRings.create": + +type ProjectsLocationsKeyRingsCreateCall struct { + s *Service + parent string + keyring *KeyRing + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// Create: Create a new KeyRing in a given Project and Location. +func (r *ProjectsLocationsKeyRingsService) Create(parent string, keyring *KeyRing) *ProjectsLocationsKeyRingsCreateCall { + c := &ProjectsLocationsKeyRingsCreateCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.parent = parent + c.keyring = keyring + return c +} + +// KeyRingId sets the optional parameter "keyRingId": Required. It must +// be unique within a location and match the regular +// expression `[a-zA-Z0-9_-]{1,63}` +func (c *ProjectsLocationsKeyRingsCreateCall) KeyRingId(keyRingId string) *ProjectsLocationsKeyRingsCreateCall { + c.urlParams_.Set("keyRingId", keyRingId) + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *ProjectsLocationsKeyRingsCreateCall) Fields(s ...googleapi.Field) *ProjectsLocationsKeyRingsCreateCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *ProjectsLocationsKeyRingsCreateCall) Context(ctx context.Context) *ProjectsLocationsKeyRingsCreateCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *ProjectsLocationsKeyRingsCreateCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *ProjectsLocationsKeyRingsCreateCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + var body io.Reader = nil + body, err := googleapi.WithoutDataWrapper.JSONReader(c.keyring) + if err != nil { + return nil, err + } + reqHeaders.Set("Content-Type", "application/json") + c.urlParams_.Set("alt", alt) + urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+parent}/keyRings") + urls += "?" + c.urlParams_.Encode() + req, _ := http.NewRequest("POST", urls, body) + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "parent": c.parent, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "cloudkms.projects.locations.keyRings.create" call. +// Exactly one of *KeyRing or error will be non-nil. Any non-2xx status +// code is an error. Response headers are in either +// *KeyRing.ServerResponse.Header or (if a response was returned at all) +// in error.(*googleapi.Error).Header. Use googleapi.IsNotModified to +// check whether the returned error was because http.StatusNotModified +// was returned. +func (c *ProjectsLocationsKeyRingsCreateCall) Do(opts ...googleapi.CallOption) (*KeyRing, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &KeyRing{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := json.NewDecoder(res.Body).Decode(target); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Create a new KeyRing in a given Project and Location.", + // "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/keyRings", + // "httpMethod": "POST", + // "id": "cloudkms.projects.locations.keyRings.create", + // "parameterOrder": [ + // "parent" + // ], + // "parameters": { + // "keyRingId": { + // "description": "Required. It must be unique within a location and match the regular\nexpression `[a-zA-Z0-9_-]{1,63}`", + // "location": "query", + // "type": "string" + // }, + // "parent": { + // "description": "Required. The resource name of the location associated with the\nKeyRings, in the format `projects/*/locations/*`.", + // "location": "path", + // "pattern": "^projects/[^/]+/locations/[^/]+$", + // "required": true, + // "type": "string" + // } + // }, + // "path": "v1/{+parent}/keyRings", + // "request": { + // "$ref": "KeyRing" + // }, + // "response": { + // "$ref": "KeyRing" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform" + // ] + // } + +} + +// method id "cloudkms.projects.locations.keyRings.get": + +type ProjectsLocationsKeyRingsGetCall struct { + s *Service + name string + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header +} + +// Get: Returns metadata for a given KeyRing. +func (r *ProjectsLocationsKeyRingsService) Get(name string) *ProjectsLocationsKeyRingsGetCall { + c := &ProjectsLocationsKeyRingsGetCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.name = name + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *ProjectsLocationsKeyRingsGetCall) Fields(s ...googleapi.Field) *ProjectsLocationsKeyRingsGetCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// IfNoneMatch sets the optional parameter which makes the operation +// fail if the object's ETag matches the given value. This is useful for +// getting updates only after the object has changed since the last +// request. Use googleapi.IsNotModified to check whether the response +// error from Do is the result of In-None-Match. +func (c *ProjectsLocationsKeyRingsGetCall) IfNoneMatch(entityTag string) *ProjectsLocationsKeyRingsGetCall { + c.ifNoneMatch_ = entityTag + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *ProjectsLocationsKeyRingsGetCall) Context(ctx context.Context) *ProjectsLocationsKeyRingsGetCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *ProjectsLocationsKeyRingsGetCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *ProjectsLocationsKeyRingsGetCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + if c.ifNoneMatch_ != "" { + reqHeaders.Set("If-None-Match", c.ifNoneMatch_) + } + var body io.Reader = nil + c.urlParams_.Set("alt", alt) + urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}") + urls += "?" + c.urlParams_.Encode() + req, _ := http.NewRequest("GET", urls, body) + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "name": c.name, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "cloudkms.projects.locations.keyRings.get" call. +// Exactly one of *KeyRing or error will be non-nil. Any non-2xx status +// code is an error. Response headers are in either +// *KeyRing.ServerResponse.Header or (if a response was returned at all) +// in error.(*googleapi.Error).Header. Use googleapi.IsNotModified to +// check whether the returned error was because http.StatusNotModified +// was returned. +func (c *ProjectsLocationsKeyRingsGetCall) Do(opts ...googleapi.CallOption) (*KeyRing, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &KeyRing{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := json.NewDecoder(res.Body).Decode(target); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Returns metadata for a given KeyRing.", + // "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/keyRings/{keyRingsId}", + // "httpMethod": "GET", + // "id": "cloudkms.projects.locations.keyRings.get", + // "parameterOrder": [ + // "name" + // ], + // "parameters": { + // "name": { + // "description": "The name of the KeyRing to get.", + // "location": "path", + // "pattern": "^projects/[^/]+/locations/[^/]+/keyRings/[^/]+$", + // "required": true, + // "type": "string" + // } + // }, + // "path": "v1/{+name}", + // "response": { + // "$ref": "KeyRing" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform" + // ] + // } + +} + +// method id "cloudkms.projects.locations.keyRings.getIamPolicy": + +type ProjectsLocationsKeyRingsGetIamPolicyCall struct { + s *Service + resource string + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header +} + +// GetIamPolicy: Gets the access control policy for a resource. +// Returns an empty policy if the resource exists and does not have a +// policy +// set. +func (r *ProjectsLocationsKeyRingsService) GetIamPolicy(resource string) *ProjectsLocationsKeyRingsGetIamPolicyCall { + c := &ProjectsLocationsKeyRingsGetIamPolicyCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.resource = resource + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *ProjectsLocationsKeyRingsGetIamPolicyCall) Fields(s ...googleapi.Field) *ProjectsLocationsKeyRingsGetIamPolicyCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// IfNoneMatch sets the optional parameter which makes the operation +// fail if the object's ETag matches the given value. This is useful for +// getting updates only after the object has changed since the last +// request. Use googleapi.IsNotModified to check whether the response +// error from Do is the result of In-None-Match. +func (c *ProjectsLocationsKeyRingsGetIamPolicyCall) IfNoneMatch(entityTag string) *ProjectsLocationsKeyRingsGetIamPolicyCall { + c.ifNoneMatch_ = entityTag + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *ProjectsLocationsKeyRingsGetIamPolicyCall) Context(ctx context.Context) *ProjectsLocationsKeyRingsGetIamPolicyCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *ProjectsLocationsKeyRingsGetIamPolicyCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *ProjectsLocationsKeyRingsGetIamPolicyCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + if c.ifNoneMatch_ != "" { + reqHeaders.Set("If-None-Match", c.ifNoneMatch_) + } + var body io.Reader = nil + c.urlParams_.Set("alt", alt) + urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+resource}:getIamPolicy") + urls += "?" + c.urlParams_.Encode() + req, _ := http.NewRequest("GET", urls, body) + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "resource": c.resource, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "cloudkms.projects.locations.keyRings.getIamPolicy" call. +// Exactly one of *Policy or error will be non-nil. Any non-2xx status +// code is an error. Response headers are in either +// *Policy.ServerResponse.Header or (if a response was returned at all) +// in error.(*googleapi.Error).Header. Use googleapi.IsNotModified to +// check whether the returned error was because http.StatusNotModified +// was returned. +func (c *ProjectsLocationsKeyRingsGetIamPolicyCall) Do(opts ...googleapi.CallOption) (*Policy, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &Policy{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := json.NewDecoder(res.Body).Decode(target); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Gets the access control policy for a resource.\nReturns an empty policy if the resource exists and does not have a policy\nset.", + // "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/keyRings/{keyRingsId}:getIamPolicy", + // "httpMethod": "GET", + // "id": "cloudkms.projects.locations.keyRings.getIamPolicy", + // "parameterOrder": [ + // "resource" + // ], + // "parameters": { + // "resource": { + // "description": "REQUIRED: The resource for which the policy is being requested.\nSee the operation documentation for the appropriate value for this field.", + // "location": "path", + // "pattern": "^projects/[^/]+/locations/[^/]+/keyRings/[^/]+$", + // "required": true, + // "type": "string" + // } + // }, + // "path": "v1/{+resource}:getIamPolicy", + // "response": { + // "$ref": "Policy" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform" + // ] + // } + +} + +// method id "cloudkms.projects.locations.keyRings.list": + +type ProjectsLocationsKeyRingsListCall struct { + s *Service + parent string + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header +} + +// List: Lists KeyRings. +func (r *ProjectsLocationsKeyRingsService) List(parent string) *ProjectsLocationsKeyRingsListCall { + c := &ProjectsLocationsKeyRingsListCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.parent = parent + return c +} + +// PageSize sets the optional parameter "pageSize": Optional limit on +// the number of KeyRings to include in the +// response. Further KeyRings can subsequently be obtained by +// including the ListKeyRingsResponse.next_page_token in a +// subsequent +// request. If unspecified, the server will pick an appropriate +// default. +func (c *ProjectsLocationsKeyRingsListCall) PageSize(pageSize int64) *ProjectsLocationsKeyRingsListCall { + c.urlParams_.Set("pageSize", fmt.Sprint(pageSize)) + return c +} + +// PageToken sets the optional parameter "pageToken": Optional +// pagination token, returned earlier +// via +// ListKeyRingsResponse.next_page_token. +func (c *ProjectsLocationsKeyRingsListCall) PageToken(pageToken string) *ProjectsLocationsKeyRingsListCall { + c.urlParams_.Set("pageToken", pageToken) + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *ProjectsLocationsKeyRingsListCall) Fields(s ...googleapi.Field) *ProjectsLocationsKeyRingsListCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// IfNoneMatch sets the optional parameter which makes the operation +// fail if the object's ETag matches the given value. This is useful for +// getting updates only after the object has changed since the last +// request. Use googleapi.IsNotModified to check whether the response +// error from Do is the result of In-None-Match. +func (c *ProjectsLocationsKeyRingsListCall) IfNoneMatch(entityTag string) *ProjectsLocationsKeyRingsListCall { + c.ifNoneMatch_ = entityTag + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *ProjectsLocationsKeyRingsListCall) Context(ctx context.Context) *ProjectsLocationsKeyRingsListCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *ProjectsLocationsKeyRingsListCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *ProjectsLocationsKeyRingsListCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + if c.ifNoneMatch_ != "" { + reqHeaders.Set("If-None-Match", c.ifNoneMatch_) + } + var body io.Reader = nil + c.urlParams_.Set("alt", alt) + urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+parent}/keyRings") + urls += "?" + c.urlParams_.Encode() + req, _ := http.NewRequest("GET", urls, body) + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "parent": c.parent, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "cloudkms.projects.locations.keyRings.list" call. +// Exactly one of *ListKeyRingsResponse or error will be non-nil. Any +// non-2xx status code is an error. Response headers are in either +// *ListKeyRingsResponse.ServerResponse.Header or (if a response was +// returned at all) in error.(*googleapi.Error).Header. Use +// googleapi.IsNotModified to check whether the returned error was +// because http.StatusNotModified was returned. +func (c *ProjectsLocationsKeyRingsListCall) Do(opts ...googleapi.CallOption) (*ListKeyRingsResponse, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &ListKeyRingsResponse{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := json.NewDecoder(res.Body).Decode(target); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Lists KeyRings.", + // "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/keyRings", + // "httpMethod": "GET", + // "id": "cloudkms.projects.locations.keyRings.list", + // "parameterOrder": [ + // "parent" + // ], + // "parameters": { + // "pageSize": { + // "description": "Optional limit on the number of KeyRings to include in the\nresponse. Further KeyRings can subsequently be obtained by\nincluding the ListKeyRingsResponse.next_page_token in a subsequent\nrequest. If unspecified, the server will pick an appropriate default.", + // "format": "int32", + // "location": "query", + // "type": "integer" + // }, + // "pageToken": { + // "description": "Optional pagination token, returned earlier via\nListKeyRingsResponse.next_page_token.", + // "location": "query", + // "type": "string" + // }, + // "parent": { + // "description": "Required. The resource name of the location associated with the\nKeyRings, in the format `projects/*/locations/*`.", + // "location": "path", + // "pattern": "^projects/[^/]+/locations/[^/]+$", + // "required": true, + // "type": "string" + // } + // }, + // "path": "v1/{+parent}/keyRings", + // "response": { + // "$ref": "ListKeyRingsResponse" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform" + // ] + // } + +} + +// Pages invokes f for each page of results. +// A non-nil error returned from f will halt the iteration. +// The provided context supersedes any context provided to the Context method. +func (c *ProjectsLocationsKeyRingsListCall) Pages(ctx context.Context, f func(*ListKeyRingsResponse) error) error { + c.ctx_ = ctx + defer c.PageToken(c.urlParams_.Get("pageToken")) // reset paging to original point + for { + x, err := c.Do() + if err != nil { + return err + } + if err := f(x); err != nil { + return err + } + if x.NextPageToken == "" { + return nil + } + c.PageToken(x.NextPageToken) + } +} + +// method id "cloudkms.projects.locations.keyRings.setIamPolicy": + +type ProjectsLocationsKeyRingsSetIamPolicyCall struct { + s *Service + resource string + setiampolicyrequest *SetIamPolicyRequest + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// SetIamPolicy: Sets the access control policy on the specified +// resource. Replaces any +// existing policy. +func (r *ProjectsLocationsKeyRingsService) SetIamPolicy(resource string, setiampolicyrequest *SetIamPolicyRequest) *ProjectsLocationsKeyRingsSetIamPolicyCall { + c := &ProjectsLocationsKeyRingsSetIamPolicyCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.resource = resource + c.setiampolicyrequest = setiampolicyrequest + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *ProjectsLocationsKeyRingsSetIamPolicyCall) Fields(s ...googleapi.Field) *ProjectsLocationsKeyRingsSetIamPolicyCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *ProjectsLocationsKeyRingsSetIamPolicyCall) Context(ctx context.Context) *ProjectsLocationsKeyRingsSetIamPolicyCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *ProjectsLocationsKeyRingsSetIamPolicyCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *ProjectsLocationsKeyRingsSetIamPolicyCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + var body io.Reader = nil + body, err := googleapi.WithoutDataWrapper.JSONReader(c.setiampolicyrequest) + if err != nil { + return nil, err + } + reqHeaders.Set("Content-Type", "application/json") + c.urlParams_.Set("alt", alt) + urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+resource}:setIamPolicy") + urls += "?" + c.urlParams_.Encode() + req, _ := http.NewRequest("POST", urls, body) + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "resource": c.resource, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "cloudkms.projects.locations.keyRings.setIamPolicy" call. +// Exactly one of *Policy or error will be non-nil. Any non-2xx status +// code is an error. Response headers are in either +// *Policy.ServerResponse.Header or (if a response was returned at all) +// in error.(*googleapi.Error).Header. Use googleapi.IsNotModified to +// check whether the returned error was because http.StatusNotModified +// was returned. +func (c *ProjectsLocationsKeyRingsSetIamPolicyCall) Do(opts ...googleapi.CallOption) (*Policy, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &Policy{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := json.NewDecoder(res.Body).Decode(target); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Sets the access control policy on the specified resource. Replaces any\nexisting policy.", + // "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/keyRings/{keyRingsId}:setIamPolicy", + // "httpMethod": "POST", + // "id": "cloudkms.projects.locations.keyRings.setIamPolicy", + // "parameterOrder": [ + // "resource" + // ], + // "parameters": { + // "resource": { + // "description": "REQUIRED: The resource for which the policy is being specified.\nSee the operation documentation for the appropriate value for this field.", + // "location": "path", + // "pattern": "^projects/[^/]+/locations/[^/]+/keyRings/[^/]+$", + // "required": true, + // "type": "string" + // } + // }, + // "path": "v1/{+resource}:setIamPolicy", + // "request": { + // "$ref": "SetIamPolicyRequest" + // }, + // "response": { + // "$ref": "Policy" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform" + // ] + // } + +} + +// method id "cloudkms.projects.locations.keyRings.testIamPermissions": + +type ProjectsLocationsKeyRingsTestIamPermissionsCall struct { + s *Service + resource string + testiampermissionsrequest *TestIamPermissionsRequest + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// TestIamPermissions: Returns permissions that a caller has on the +// specified resource. +// If the resource does not exist, this will return an empty set +// of +// permissions, not a NOT_FOUND error. +// +// Note: This operation is designed to be used for building +// permission-aware +// UIs and command-line tools, not for authorization checking. This +// operation +// may "fail open" without warning. +func (r *ProjectsLocationsKeyRingsService) TestIamPermissions(resource string, testiampermissionsrequest *TestIamPermissionsRequest) *ProjectsLocationsKeyRingsTestIamPermissionsCall { + c := &ProjectsLocationsKeyRingsTestIamPermissionsCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.resource = resource + c.testiampermissionsrequest = testiampermissionsrequest + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *ProjectsLocationsKeyRingsTestIamPermissionsCall) Fields(s ...googleapi.Field) *ProjectsLocationsKeyRingsTestIamPermissionsCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *ProjectsLocationsKeyRingsTestIamPermissionsCall) Context(ctx context.Context) *ProjectsLocationsKeyRingsTestIamPermissionsCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *ProjectsLocationsKeyRingsTestIamPermissionsCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *ProjectsLocationsKeyRingsTestIamPermissionsCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + var body io.Reader = nil + body, err := googleapi.WithoutDataWrapper.JSONReader(c.testiampermissionsrequest) + if err != nil { + return nil, err + } + reqHeaders.Set("Content-Type", "application/json") + c.urlParams_.Set("alt", alt) + urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+resource}:testIamPermissions") + urls += "?" + c.urlParams_.Encode() + req, _ := http.NewRequest("POST", urls, body) + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "resource": c.resource, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "cloudkms.projects.locations.keyRings.testIamPermissions" call. +// Exactly one of *TestIamPermissionsResponse or error will be non-nil. +// Any non-2xx status code is an error. Response headers are in either +// *TestIamPermissionsResponse.ServerResponse.Header or (if a response +// was returned at all) in error.(*googleapi.Error).Header. Use +// googleapi.IsNotModified to check whether the returned error was +// because http.StatusNotModified was returned. +func (c *ProjectsLocationsKeyRingsTestIamPermissionsCall) Do(opts ...googleapi.CallOption) (*TestIamPermissionsResponse, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &TestIamPermissionsResponse{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := json.NewDecoder(res.Body).Decode(target); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Returns permissions that a caller has on the specified resource.\nIf the resource does not exist, this will return an empty set of\npermissions, not a NOT_FOUND error.\n\nNote: This operation is designed to be used for building permission-aware\nUIs and command-line tools, not for authorization checking. This operation\nmay \"fail open\" without warning.", + // "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/keyRings/{keyRingsId}:testIamPermissions", + // "httpMethod": "POST", + // "id": "cloudkms.projects.locations.keyRings.testIamPermissions", + // "parameterOrder": [ + // "resource" + // ], + // "parameters": { + // "resource": { + // "description": "REQUIRED: The resource for which the policy detail is being requested.\nSee the operation documentation for the appropriate value for this field.", + // "location": "path", + // "pattern": "^projects/[^/]+/locations/[^/]+/keyRings/[^/]+$", + // "required": true, + // "type": "string" + // } + // }, + // "path": "v1/{+resource}:testIamPermissions", + // "request": { + // "$ref": "TestIamPermissionsRequest" + // }, + // "response": { + // "$ref": "TestIamPermissionsResponse" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform" + // ] + // } + +} + +// method id "cloudkms.projects.locations.keyRings.cryptoKeys.create": + +type ProjectsLocationsKeyRingsCryptoKeysCreateCall struct { + s *Service + parent string + cryptokey *CryptoKey + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// Create: Create a new CryptoKey within a KeyRing. +// +// CryptoKey.purpose is required. +func (r *ProjectsLocationsKeyRingsCryptoKeysService) Create(parent string, cryptokey *CryptoKey) *ProjectsLocationsKeyRingsCryptoKeysCreateCall { + c := &ProjectsLocationsKeyRingsCryptoKeysCreateCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.parent = parent + c.cryptokey = cryptokey + return c +} + +// CryptoKeyId sets the optional parameter "cryptoKeyId": Required. It +// must be unique within a KeyRing and match the regular +// expression `[a-zA-Z0-9_-]{1,63}` +func (c *ProjectsLocationsKeyRingsCryptoKeysCreateCall) CryptoKeyId(cryptoKeyId string) *ProjectsLocationsKeyRingsCryptoKeysCreateCall { + c.urlParams_.Set("cryptoKeyId", cryptoKeyId) + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *ProjectsLocationsKeyRingsCryptoKeysCreateCall) Fields(s ...googleapi.Field) *ProjectsLocationsKeyRingsCryptoKeysCreateCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *ProjectsLocationsKeyRingsCryptoKeysCreateCall) Context(ctx context.Context) *ProjectsLocationsKeyRingsCryptoKeysCreateCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *ProjectsLocationsKeyRingsCryptoKeysCreateCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *ProjectsLocationsKeyRingsCryptoKeysCreateCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + var body io.Reader = nil + body, err := googleapi.WithoutDataWrapper.JSONReader(c.cryptokey) + if err != nil { + return nil, err + } + reqHeaders.Set("Content-Type", "application/json") + c.urlParams_.Set("alt", alt) + urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+parent}/cryptoKeys") + urls += "?" + c.urlParams_.Encode() + req, _ := http.NewRequest("POST", urls, body) + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "parent": c.parent, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "cloudkms.projects.locations.keyRings.cryptoKeys.create" call. +// Exactly one of *CryptoKey or error will be non-nil. Any non-2xx +// status code is an error. Response headers are in either +// *CryptoKey.ServerResponse.Header or (if a response was returned at +// all) in error.(*googleapi.Error).Header. Use googleapi.IsNotModified +// to check whether the returned error was because +// http.StatusNotModified was returned. +func (c *ProjectsLocationsKeyRingsCryptoKeysCreateCall) Do(opts ...googleapi.CallOption) (*CryptoKey, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &CryptoKey{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := json.NewDecoder(res.Body).Decode(target); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Create a new CryptoKey within a KeyRing.\n\nCryptoKey.purpose is required.", + // "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/keyRings/{keyRingsId}/cryptoKeys", + // "httpMethod": "POST", + // "id": "cloudkms.projects.locations.keyRings.cryptoKeys.create", + // "parameterOrder": [ + // "parent" + // ], + // "parameters": { + // "cryptoKeyId": { + // "description": "Required. It must be unique within a KeyRing and match the regular\nexpression `[a-zA-Z0-9_-]{1,63}`", + // "location": "query", + // "type": "string" + // }, + // "parent": { + // "description": "Required. The name of the KeyRing associated with the\nCryptoKeys.", + // "location": "path", + // "pattern": "^projects/[^/]+/locations/[^/]+/keyRings/[^/]+$", + // "required": true, + // "type": "string" + // } + // }, + // "path": "v1/{+parent}/cryptoKeys", + // "request": { + // "$ref": "CryptoKey" + // }, + // "response": { + // "$ref": "CryptoKey" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform" + // ] + // } + +} + +// method id "cloudkms.projects.locations.keyRings.cryptoKeys.decrypt": + +type ProjectsLocationsKeyRingsCryptoKeysDecryptCall struct { + s *Service + name string + decryptrequest *DecryptRequest + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// Decrypt: Decrypt data that was protected by Encrypt. +func (r *ProjectsLocationsKeyRingsCryptoKeysService) Decrypt(name string, decryptrequest *DecryptRequest) *ProjectsLocationsKeyRingsCryptoKeysDecryptCall { + c := &ProjectsLocationsKeyRingsCryptoKeysDecryptCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.name = name + c.decryptrequest = decryptrequest + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *ProjectsLocationsKeyRingsCryptoKeysDecryptCall) Fields(s ...googleapi.Field) *ProjectsLocationsKeyRingsCryptoKeysDecryptCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *ProjectsLocationsKeyRingsCryptoKeysDecryptCall) Context(ctx context.Context) *ProjectsLocationsKeyRingsCryptoKeysDecryptCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *ProjectsLocationsKeyRingsCryptoKeysDecryptCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *ProjectsLocationsKeyRingsCryptoKeysDecryptCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + var body io.Reader = nil + body, err := googleapi.WithoutDataWrapper.JSONReader(c.decryptrequest) + if err != nil { + return nil, err + } + reqHeaders.Set("Content-Type", "application/json") + c.urlParams_.Set("alt", alt) + urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}:decrypt") + urls += "?" + c.urlParams_.Encode() + req, _ := http.NewRequest("POST", urls, body) + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "name": c.name, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "cloudkms.projects.locations.keyRings.cryptoKeys.decrypt" call. +// Exactly one of *DecryptResponse or error will be non-nil. Any non-2xx +// status code is an error. Response headers are in either +// *DecryptResponse.ServerResponse.Header or (if a response was returned +// at all) in error.(*googleapi.Error).Header. Use +// googleapi.IsNotModified to check whether the returned error was +// because http.StatusNotModified was returned. +func (c *ProjectsLocationsKeyRingsCryptoKeysDecryptCall) Do(opts ...googleapi.CallOption) (*DecryptResponse, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &DecryptResponse{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := json.NewDecoder(res.Body).Decode(target); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Decrypt data that was protected by Encrypt.", + // "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/keyRings/{keyRingsId}/cryptoKeys/{cryptoKeysId}:decrypt", + // "httpMethod": "POST", + // "id": "cloudkms.projects.locations.keyRings.cryptoKeys.decrypt", + // "parameterOrder": [ + // "name" + // ], + // "parameters": { + // "name": { + // "description": "Required. The resource name of the CryptoKey to use for decryption.\nThe server will choose the appropriate version.", + // "location": "path", + // "pattern": "^projects/[^/]+/locations/[^/]+/keyRings/[^/]+/cryptoKeys/[^/]+$", + // "required": true, + // "type": "string" + // } + // }, + // "path": "v1/{+name}:decrypt", + // "request": { + // "$ref": "DecryptRequest" + // }, + // "response": { + // "$ref": "DecryptResponse" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform" + // ] + // } + +} + +// method id "cloudkms.projects.locations.keyRings.cryptoKeys.encrypt": + +type ProjectsLocationsKeyRingsCryptoKeysEncryptCall struct { + s *Service + name string + encryptrequest *EncryptRequest + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// Encrypt: Encrypt data, so that it can only be recovered by a call to +// Decrypt. +func (r *ProjectsLocationsKeyRingsCryptoKeysService) Encrypt(name string, encryptrequest *EncryptRequest) *ProjectsLocationsKeyRingsCryptoKeysEncryptCall { + c := &ProjectsLocationsKeyRingsCryptoKeysEncryptCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.name = name + c.encryptrequest = encryptrequest + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *ProjectsLocationsKeyRingsCryptoKeysEncryptCall) Fields(s ...googleapi.Field) *ProjectsLocationsKeyRingsCryptoKeysEncryptCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *ProjectsLocationsKeyRingsCryptoKeysEncryptCall) Context(ctx context.Context) *ProjectsLocationsKeyRingsCryptoKeysEncryptCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *ProjectsLocationsKeyRingsCryptoKeysEncryptCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *ProjectsLocationsKeyRingsCryptoKeysEncryptCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + var body io.Reader = nil + body, err := googleapi.WithoutDataWrapper.JSONReader(c.encryptrequest) + if err != nil { + return nil, err + } + reqHeaders.Set("Content-Type", "application/json") + c.urlParams_.Set("alt", alt) + urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}:encrypt") + urls += "?" + c.urlParams_.Encode() + req, _ := http.NewRequest("POST", urls, body) + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "name": c.name, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "cloudkms.projects.locations.keyRings.cryptoKeys.encrypt" call. +// Exactly one of *EncryptResponse or error will be non-nil. Any non-2xx +// status code is an error. Response headers are in either +// *EncryptResponse.ServerResponse.Header or (if a response was returned +// at all) in error.(*googleapi.Error).Header. Use +// googleapi.IsNotModified to check whether the returned error was +// because http.StatusNotModified was returned. +func (c *ProjectsLocationsKeyRingsCryptoKeysEncryptCall) Do(opts ...googleapi.CallOption) (*EncryptResponse, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &EncryptResponse{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := json.NewDecoder(res.Body).Decode(target); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Encrypt data, so that it can only be recovered by a call to Decrypt.", + // "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/keyRings/{keyRingsId}/cryptoKeys/{cryptoKeysId}:encrypt", + // "httpMethod": "POST", + // "id": "cloudkms.projects.locations.keyRings.cryptoKeys.encrypt", + // "parameterOrder": [ + // "name" + // ], + // "parameters": { + // "name": { + // "description": "Required. The resource name of the CryptoKey or CryptoKeyVersion\nto use for encryption.\n\nIf a CryptoKey is specified, the server will use its\nprimary version.", + // "location": "path", + // "pattern": "^projects/[^/]+/locations/[^/]+/keyRings/[^/]+/cryptoKeys/.+$", + // "required": true, + // "type": "string" + // } + // }, + // "path": "v1/{+name}:encrypt", + // "request": { + // "$ref": "EncryptRequest" + // }, + // "response": { + // "$ref": "EncryptResponse" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform" + // ] + // } + +} + +// method id "cloudkms.projects.locations.keyRings.cryptoKeys.get": + +type ProjectsLocationsKeyRingsCryptoKeysGetCall struct { + s *Service + name string + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header +} + +// Get: Returns metadata for a given CryptoKey, as well as its +// primary CryptoKeyVersion. +func (r *ProjectsLocationsKeyRingsCryptoKeysService) Get(name string) *ProjectsLocationsKeyRingsCryptoKeysGetCall { + c := &ProjectsLocationsKeyRingsCryptoKeysGetCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.name = name + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *ProjectsLocationsKeyRingsCryptoKeysGetCall) Fields(s ...googleapi.Field) *ProjectsLocationsKeyRingsCryptoKeysGetCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// IfNoneMatch sets the optional parameter which makes the operation +// fail if the object's ETag matches the given value. This is useful for +// getting updates only after the object has changed since the last +// request. Use googleapi.IsNotModified to check whether the response +// error from Do is the result of In-None-Match. +func (c *ProjectsLocationsKeyRingsCryptoKeysGetCall) IfNoneMatch(entityTag string) *ProjectsLocationsKeyRingsCryptoKeysGetCall { + c.ifNoneMatch_ = entityTag + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *ProjectsLocationsKeyRingsCryptoKeysGetCall) Context(ctx context.Context) *ProjectsLocationsKeyRingsCryptoKeysGetCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *ProjectsLocationsKeyRingsCryptoKeysGetCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *ProjectsLocationsKeyRingsCryptoKeysGetCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + if c.ifNoneMatch_ != "" { + reqHeaders.Set("If-None-Match", c.ifNoneMatch_) + } + var body io.Reader = nil + c.urlParams_.Set("alt", alt) + urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}") + urls += "?" + c.urlParams_.Encode() + req, _ := http.NewRequest("GET", urls, body) + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "name": c.name, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "cloudkms.projects.locations.keyRings.cryptoKeys.get" call. +// Exactly one of *CryptoKey or error will be non-nil. Any non-2xx +// status code is an error. Response headers are in either +// *CryptoKey.ServerResponse.Header or (if a response was returned at +// all) in error.(*googleapi.Error).Header. Use googleapi.IsNotModified +// to check whether the returned error was because +// http.StatusNotModified was returned. +func (c *ProjectsLocationsKeyRingsCryptoKeysGetCall) Do(opts ...googleapi.CallOption) (*CryptoKey, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &CryptoKey{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := json.NewDecoder(res.Body).Decode(target); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Returns metadata for a given CryptoKey, as well as its\nprimary CryptoKeyVersion.", + // "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/keyRings/{keyRingsId}/cryptoKeys/{cryptoKeysId}", + // "httpMethod": "GET", + // "id": "cloudkms.projects.locations.keyRings.cryptoKeys.get", + // "parameterOrder": [ + // "name" + // ], + // "parameters": { + // "name": { + // "description": "The name of the CryptoKey to get.", + // "location": "path", + // "pattern": "^projects/[^/]+/locations/[^/]+/keyRings/[^/]+/cryptoKeys/[^/]+$", + // "required": true, + // "type": "string" + // } + // }, + // "path": "v1/{+name}", + // "response": { + // "$ref": "CryptoKey" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform" + // ] + // } + +} + +// method id "cloudkms.projects.locations.keyRings.cryptoKeys.getIamPolicy": + +type ProjectsLocationsKeyRingsCryptoKeysGetIamPolicyCall struct { + s *Service + resource string + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header +} + +// GetIamPolicy: Gets the access control policy for a resource. +// Returns an empty policy if the resource exists and does not have a +// policy +// set. +func (r *ProjectsLocationsKeyRingsCryptoKeysService) GetIamPolicy(resource string) *ProjectsLocationsKeyRingsCryptoKeysGetIamPolicyCall { + c := &ProjectsLocationsKeyRingsCryptoKeysGetIamPolicyCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.resource = resource + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *ProjectsLocationsKeyRingsCryptoKeysGetIamPolicyCall) Fields(s ...googleapi.Field) *ProjectsLocationsKeyRingsCryptoKeysGetIamPolicyCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// IfNoneMatch sets the optional parameter which makes the operation +// fail if the object's ETag matches the given value. This is useful for +// getting updates only after the object has changed since the last +// request. Use googleapi.IsNotModified to check whether the response +// error from Do is the result of In-None-Match. +func (c *ProjectsLocationsKeyRingsCryptoKeysGetIamPolicyCall) IfNoneMatch(entityTag string) *ProjectsLocationsKeyRingsCryptoKeysGetIamPolicyCall { + c.ifNoneMatch_ = entityTag + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *ProjectsLocationsKeyRingsCryptoKeysGetIamPolicyCall) Context(ctx context.Context) *ProjectsLocationsKeyRingsCryptoKeysGetIamPolicyCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *ProjectsLocationsKeyRingsCryptoKeysGetIamPolicyCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *ProjectsLocationsKeyRingsCryptoKeysGetIamPolicyCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + if c.ifNoneMatch_ != "" { + reqHeaders.Set("If-None-Match", c.ifNoneMatch_) + } + var body io.Reader = nil + c.urlParams_.Set("alt", alt) + urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+resource}:getIamPolicy") + urls += "?" + c.urlParams_.Encode() + req, _ := http.NewRequest("GET", urls, body) + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "resource": c.resource, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "cloudkms.projects.locations.keyRings.cryptoKeys.getIamPolicy" call. +// Exactly one of *Policy or error will be non-nil. Any non-2xx status +// code is an error. Response headers are in either +// *Policy.ServerResponse.Header or (if a response was returned at all) +// in error.(*googleapi.Error).Header. Use googleapi.IsNotModified to +// check whether the returned error was because http.StatusNotModified +// was returned. +func (c *ProjectsLocationsKeyRingsCryptoKeysGetIamPolicyCall) Do(opts ...googleapi.CallOption) (*Policy, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &Policy{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := json.NewDecoder(res.Body).Decode(target); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Gets the access control policy for a resource.\nReturns an empty policy if the resource exists and does not have a policy\nset.", + // "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/keyRings/{keyRingsId}/cryptoKeys/{cryptoKeysId}:getIamPolicy", + // "httpMethod": "GET", + // "id": "cloudkms.projects.locations.keyRings.cryptoKeys.getIamPolicy", + // "parameterOrder": [ + // "resource" + // ], + // "parameters": { + // "resource": { + // "description": "REQUIRED: The resource for which the policy is being requested.\nSee the operation documentation for the appropriate value for this field.", + // "location": "path", + // "pattern": "^projects/[^/]+/locations/[^/]+/keyRings/[^/]+/cryptoKeys/[^/]+$", + // "required": true, + // "type": "string" + // } + // }, + // "path": "v1/{+resource}:getIamPolicy", + // "response": { + // "$ref": "Policy" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform" + // ] + // } + +} + +// method id "cloudkms.projects.locations.keyRings.cryptoKeys.list": + +type ProjectsLocationsKeyRingsCryptoKeysListCall struct { + s *Service + parent string + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header +} + +// List: Lists CryptoKeys. +func (r *ProjectsLocationsKeyRingsCryptoKeysService) List(parent string) *ProjectsLocationsKeyRingsCryptoKeysListCall { + c := &ProjectsLocationsKeyRingsCryptoKeysListCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.parent = parent + return c +} + +// PageSize sets the optional parameter "pageSize": Optional limit on +// the number of CryptoKeys to include in the +// response. Further CryptoKeys can subsequently be obtained +// by +// including the ListCryptoKeysResponse.next_page_token in a +// subsequent +// request. If unspecified, the server will pick an appropriate +// default. +func (c *ProjectsLocationsKeyRingsCryptoKeysListCall) PageSize(pageSize int64) *ProjectsLocationsKeyRingsCryptoKeysListCall { + c.urlParams_.Set("pageSize", fmt.Sprint(pageSize)) + return c +} + +// PageToken sets the optional parameter "pageToken": Optional +// pagination token, returned earlier +// via +// ListCryptoKeysResponse.next_page_token. +func (c *ProjectsLocationsKeyRingsCryptoKeysListCall) PageToken(pageToken string) *ProjectsLocationsKeyRingsCryptoKeysListCall { + c.urlParams_.Set("pageToken", pageToken) + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *ProjectsLocationsKeyRingsCryptoKeysListCall) Fields(s ...googleapi.Field) *ProjectsLocationsKeyRingsCryptoKeysListCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// IfNoneMatch sets the optional parameter which makes the operation +// fail if the object's ETag matches the given value. This is useful for +// getting updates only after the object has changed since the last +// request. Use googleapi.IsNotModified to check whether the response +// error from Do is the result of In-None-Match. +func (c *ProjectsLocationsKeyRingsCryptoKeysListCall) IfNoneMatch(entityTag string) *ProjectsLocationsKeyRingsCryptoKeysListCall { + c.ifNoneMatch_ = entityTag + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *ProjectsLocationsKeyRingsCryptoKeysListCall) Context(ctx context.Context) *ProjectsLocationsKeyRingsCryptoKeysListCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *ProjectsLocationsKeyRingsCryptoKeysListCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *ProjectsLocationsKeyRingsCryptoKeysListCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + if c.ifNoneMatch_ != "" { + reqHeaders.Set("If-None-Match", c.ifNoneMatch_) + } + var body io.Reader = nil + c.urlParams_.Set("alt", alt) + urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+parent}/cryptoKeys") + urls += "?" + c.urlParams_.Encode() + req, _ := http.NewRequest("GET", urls, body) + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "parent": c.parent, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "cloudkms.projects.locations.keyRings.cryptoKeys.list" call. +// Exactly one of *ListCryptoKeysResponse or error will be non-nil. Any +// non-2xx status code is an error. Response headers are in either +// *ListCryptoKeysResponse.ServerResponse.Header or (if a response was +// returned at all) in error.(*googleapi.Error).Header. Use +// googleapi.IsNotModified to check whether the returned error was +// because http.StatusNotModified was returned. +func (c *ProjectsLocationsKeyRingsCryptoKeysListCall) Do(opts ...googleapi.CallOption) (*ListCryptoKeysResponse, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &ListCryptoKeysResponse{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := json.NewDecoder(res.Body).Decode(target); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Lists CryptoKeys.", + // "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/keyRings/{keyRingsId}/cryptoKeys", + // "httpMethod": "GET", + // "id": "cloudkms.projects.locations.keyRings.cryptoKeys.list", + // "parameterOrder": [ + // "parent" + // ], + // "parameters": { + // "pageSize": { + // "description": "Optional limit on the number of CryptoKeys to include in the\nresponse. Further CryptoKeys can subsequently be obtained by\nincluding the ListCryptoKeysResponse.next_page_token in a subsequent\nrequest. If unspecified, the server will pick an appropriate default.", + // "format": "int32", + // "location": "query", + // "type": "integer" + // }, + // "pageToken": { + // "description": "Optional pagination token, returned earlier via\nListCryptoKeysResponse.next_page_token.", + // "location": "query", + // "type": "string" + // }, + // "parent": { + // "description": "Required. The resource name of the KeyRing to list, in the format\n`projects/*/locations/*/keyRings/*`.", + // "location": "path", + // "pattern": "^projects/[^/]+/locations/[^/]+/keyRings/[^/]+$", + // "required": true, + // "type": "string" + // } + // }, + // "path": "v1/{+parent}/cryptoKeys", + // "response": { + // "$ref": "ListCryptoKeysResponse" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform" + // ] + // } + +} + +// Pages invokes f for each page of results. +// A non-nil error returned from f will halt the iteration. +// The provided context supersedes any context provided to the Context method. +func (c *ProjectsLocationsKeyRingsCryptoKeysListCall) Pages(ctx context.Context, f func(*ListCryptoKeysResponse) error) error { + c.ctx_ = ctx + defer c.PageToken(c.urlParams_.Get("pageToken")) // reset paging to original point + for { + x, err := c.Do() + if err != nil { + return err + } + if err := f(x); err != nil { + return err + } + if x.NextPageToken == "" { + return nil + } + c.PageToken(x.NextPageToken) + } +} + +// method id "cloudkms.projects.locations.keyRings.cryptoKeys.patch": + +type ProjectsLocationsKeyRingsCryptoKeysPatchCall struct { + s *Service + name string + cryptokey *CryptoKey + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// Patch: Update a CryptoKey. +func (r *ProjectsLocationsKeyRingsCryptoKeysService) Patch(name string, cryptokey *CryptoKey) *ProjectsLocationsKeyRingsCryptoKeysPatchCall { + c := &ProjectsLocationsKeyRingsCryptoKeysPatchCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.name = name + c.cryptokey = cryptokey + return c +} + +// UpdateMask sets the optional parameter "updateMask": Required list of +// fields to be updated in this request. +func (c *ProjectsLocationsKeyRingsCryptoKeysPatchCall) UpdateMask(updateMask string) *ProjectsLocationsKeyRingsCryptoKeysPatchCall { + c.urlParams_.Set("updateMask", updateMask) + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *ProjectsLocationsKeyRingsCryptoKeysPatchCall) Fields(s ...googleapi.Field) *ProjectsLocationsKeyRingsCryptoKeysPatchCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *ProjectsLocationsKeyRingsCryptoKeysPatchCall) Context(ctx context.Context) *ProjectsLocationsKeyRingsCryptoKeysPatchCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *ProjectsLocationsKeyRingsCryptoKeysPatchCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *ProjectsLocationsKeyRingsCryptoKeysPatchCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + var body io.Reader = nil + body, err := googleapi.WithoutDataWrapper.JSONReader(c.cryptokey) + if err != nil { + return nil, err + } + reqHeaders.Set("Content-Type", "application/json") + c.urlParams_.Set("alt", alt) + urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}") + urls += "?" + c.urlParams_.Encode() + req, _ := http.NewRequest("PATCH", urls, body) + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "name": c.name, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "cloudkms.projects.locations.keyRings.cryptoKeys.patch" call. +// Exactly one of *CryptoKey or error will be non-nil. Any non-2xx +// status code is an error. Response headers are in either +// *CryptoKey.ServerResponse.Header or (if a response was returned at +// all) in error.(*googleapi.Error).Header. Use googleapi.IsNotModified +// to check whether the returned error was because +// http.StatusNotModified was returned. +func (c *ProjectsLocationsKeyRingsCryptoKeysPatchCall) Do(opts ...googleapi.CallOption) (*CryptoKey, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &CryptoKey{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := json.NewDecoder(res.Body).Decode(target); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Update a CryptoKey.", + // "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/keyRings/{keyRingsId}/cryptoKeys/{cryptoKeysId}", + // "httpMethod": "PATCH", + // "id": "cloudkms.projects.locations.keyRings.cryptoKeys.patch", + // "parameterOrder": [ + // "name" + // ], + // "parameters": { + // "name": { + // "description": "Output only. The resource name for this CryptoKey in the format\n`projects/*/locations/*/keyRings/*/cryptoKeys/*`.", + // "location": "path", + // "pattern": "^projects/[^/]+/locations/[^/]+/keyRings/[^/]+/cryptoKeys/[^/]+$", + // "required": true, + // "type": "string" + // }, + // "updateMask": { + // "description": "Required list of fields to be updated in this request.", + // "format": "google-fieldmask", + // "location": "query", + // "type": "string" + // } + // }, + // "path": "v1/{+name}", + // "request": { + // "$ref": "CryptoKey" + // }, + // "response": { + // "$ref": "CryptoKey" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform" + // ] + // } + +} + +// method id "cloudkms.projects.locations.keyRings.cryptoKeys.setIamPolicy": + +type ProjectsLocationsKeyRingsCryptoKeysSetIamPolicyCall struct { + s *Service + resource string + setiampolicyrequest *SetIamPolicyRequest + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// SetIamPolicy: Sets the access control policy on the specified +// resource. Replaces any +// existing policy. +func (r *ProjectsLocationsKeyRingsCryptoKeysService) SetIamPolicy(resource string, setiampolicyrequest *SetIamPolicyRequest) *ProjectsLocationsKeyRingsCryptoKeysSetIamPolicyCall { + c := &ProjectsLocationsKeyRingsCryptoKeysSetIamPolicyCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.resource = resource + c.setiampolicyrequest = setiampolicyrequest + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *ProjectsLocationsKeyRingsCryptoKeysSetIamPolicyCall) Fields(s ...googleapi.Field) *ProjectsLocationsKeyRingsCryptoKeysSetIamPolicyCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *ProjectsLocationsKeyRingsCryptoKeysSetIamPolicyCall) Context(ctx context.Context) *ProjectsLocationsKeyRingsCryptoKeysSetIamPolicyCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *ProjectsLocationsKeyRingsCryptoKeysSetIamPolicyCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *ProjectsLocationsKeyRingsCryptoKeysSetIamPolicyCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + var body io.Reader = nil + body, err := googleapi.WithoutDataWrapper.JSONReader(c.setiampolicyrequest) + if err != nil { + return nil, err + } + reqHeaders.Set("Content-Type", "application/json") + c.urlParams_.Set("alt", alt) + urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+resource}:setIamPolicy") + urls += "?" + c.urlParams_.Encode() + req, _ := http.NewRequest("POST", urls, body) + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "resource": c.resource, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "cloudkms.projects.locations.keyRings.cryptoKeys.setIamPolicy" call. +// Exactly one of *Policy or error will be non-nil. Any non-2xx status +// code is an error. Response headers are in either +// *Policy.ServerResponse.Header or (if a response was returned at all) +// in error.(*googleapi.Error).Header. Use googleapi.IsNotModified to +// check whether the returned error was because http.StatusNotModified +// was returned. +func (c *ProjectsLocationsKeyRingsCryptoKeysSetIamPolicyCall) Do(opts ...googleapi.CallOption) (*Policy, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &Policy{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := json.NewDecoder(res.Body).Decode(target); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Sets the access control policy on the specified resource. Replaces any\nexisting policy.", + // "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/keyRings/{keyRingsId}/cryptoKeys/{cryptoKeysId}:setIamPolicy", + // "httpMethod": "POST", + // "id": "cloudkms.projects.locations.keyRings.cryptoKeys.setIamPolicy", + // "parameterOrder": [ + // "resource" + // ], + // "parameters": { + // "resource": { + // "description": "REQUIRED: The resource for which the policy is being specified.\nSee the operation documentation for the appropriate value for this field.", + // "location": "path", + // "pattern": "^projects/[^/]+/locations/[^/]+/keyRings/[^/]+/cryptoKeys/[^/]+$", + // "required": true, + // "type": "string" + // } + // }, + // "path": "v1/{+resource}:setIamPolicy", + // "request": { + // "$ref": "SetIamPolicyRequest" + // }, + // "response": { + // "$ref": "Policy" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform" + // ] + // } + +} + +// method id "cloudkms.projects.locations.keyRings.cryptoKeys.testIamPermissions": + +type ProjectsLocationsKeyRingsCryptoKeysTestIamPermissionsCall struct { + s *Service + resource string + testiampermissionsrequest *TestIamPermissionsRequest + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// TestIamPermissions: Returns permissions that a caller has on the +// specified resource. +// If the resource does not exist, this will return an empty set +// of +// permissions, not a NOT_FOUND error. +// +// Note: This operation is designed to be used for building +// permission-aware +// UIs and command-line tools, not for authorization checking. This +// operation +// may "fail open" without warning. +func (r *ProjectsLocationsKeyRingsCryptoKeysService) TestIamPermissions(resource string, testiampermissionsrequest *TestIamPermissionsRequest) *ProjectsLocationsKeyRingsCryptoKeysTestIamPermissionsCall { + c := &ProjectsLocationsKeyRingsCryptoKeysTestIamPermissionsCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.resource = resource + c.testiampermissionsrequest = testiampermissionsrequest + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *ProjectsLocationsKeyRingsCryptoKeysTestIamPermissionsCall) Fields(s ...googleapi.Field) *ProjectsLocationsKeyRingsCryptoKeysTestIamPermissionsCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *ProjectsLocationsKeyRingsCryptoKeysTestIamPermissionsCall) Context(ctx context.Context) *ProjectsLocationsKeyRingsCryptoKeysTestIamPermissionsCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *ProjectsLocationsKeyRingsCryptoKeysTestIamPermissionsCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *ProjectsLocationsKeyRingsCryptoKeysTestIamPermissionsCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + var body io.Reader = nil + body, err := googleapi.WithoutDataWrapper.JSONReader(c.testiampermissionsrequest) + if err != nil { + return nil, err + } + reqHeaders.Set("Content-Type", "application/json") + c.urlParams_.Set("alt", alt) + urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+resource}:testIamPermissions") + urls += "?" + c.urlParams_.Encode() + req, _ := http.NewRequest("POST", urls, body) + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "resource": c.resource, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "cloudkms.projects.locations.keyRings.cryptoKeys.testIamPermissions" call. +// Exactly one of *TestIamPermissionsResponse or error will be non-nil. +// Any non-2xx status code is an error. Response headers are in either +// *TestIamPermissionsResponse.ServerResponse.Header or (if a response +// was returned at all) in error.(*googleapi.Error).Header. Use +// googleapi.IsNotModified to check whether the returned error was +// because http.StatusNotModified was returned. +func (c *ProjectsLocationsKeyRingsCryptoKeysTestIamPermissionsCall) Do(opts ...googleapi.CallOption) (*TestIamPermissionsResponse, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &TestIamPermissionsResponse{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := json.NewDecoder(res.Body).Decode(target); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Returns permissions that a caller has on the specified resource.\nIf the resource does not exist, this will return an empty set of\npermissions, not a NOT_FOUND error.\n\nNote: This operation is designed to be used for building permission-aware\nUIs and command-line tools, not for authorization checking. This operation\nmay \"fail open\" without warning.", + // "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/keyRings/{keyRingsId}/cryptoKeys/{cryptoKeysId}:testIamPermissions", + // "httpMethod": "POST", + // "id": "cloudkms.projects.locations.keyRings.cryptoKeys.testIamPermissions", + // "parameterOrder": [ + // "resource" + // ], + // "parameters": { + // "resource": { + // "description": "REQUIRED: The resource for which the policy detail is being requested.\nSee the operation documentation for the appropriate value for this field.", + // "location": "path", + // "pattern": "^projects/[^/]+/locations/[^/]+/keyRings/[^/]+/cryptoKeys/[^/]+$", + // "required": true, + // "type": "string" + // } + // }, + // "path": "v1/{+resource}:testIamPermissions", + // "request": { + // "$ref": "TestIamPermissionsRequest" + // }, + // "response": { + // "$ref": "TestIamPermissionsResponse" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform" + // ] + // } + +} + +// method id "cloudkms.projects.locations.keyRings.cryptoKeys.updatePrimaryVersion": + +type ProjectsLocationsKeyRingsCryptoKeysUpdatePrimaryVersionCall struct { + s *Service + name string + updatecryptokeyprimaryversionrequest *UpdateCryptoKeyPrimaryVersionRequest + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// UpdatePrimaryVersion: Update the version of a CryptoKey that will be +// used in Encrypt +func (r *ProjectsLocationsKeyRingsCryptoKeysService) UpdatePrimaryVersion(name string, updatecryptokeyprimaryversionrequest *UpdateCryptoKeyPrimaryVersionRequest) *ProjectsLocationsKeyRingsCryptoKeysUpdatePrimaryVersionCall { + c := &ProjectsLocationsKeyRingsCryptoKeysUpdatePrimaryVersionCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.name = name + c.updatecryptokeyprimaryversionrequest = updatecryptokeyprimaryversionrequest + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *ProjectsLocationsKeyRingsCryptoKeysUpdatePrimaryVersionCall) Fields(s ...googleapi.Field) *ProjectsLocationsKeyRingsCryptoKeysUpdatePrimaryVersionCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *ProjectsLocationsKeyRingsCryptoKeysUpdatePrimaryVersionCall) Context(ctx context.Context) *ProjectsLocationsKeyRingsCryptoKeysUpdatePrimaryVersionCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *ProjectsLocationsKeyRingsCryptoKeysUpdatePrimaryVersionCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *ProjectsLocationsKeyRingsCryptoKeysUpdatePrimaryVersionCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + var body io.Reader = nil + body, err := googleapi.WithoutDataWrapper.JSONReader(c.updatecryptokeyprimaryversionrequest) + if err != nil { + return nil, err + } + reqHeaders.Set("Content-Type", "application/json") + c.urlParams_.Set("alt", alt) + urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}:updatePrimaryVersion") + urls += "?" + c.urlParams_.Encode() + req, _ := http.NewRequest("POST", urls, body) + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "name": c.name, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "cloudkms.projects.locations.keyRings.cryptoKeys.updatePrimaryVersion" call. +// Exactly one of *CryptoKey or error will be non-nil. Any non-2xx +// status code is an error. Response headers are in either +// *CryptoKey.ServerResponse.Header or (if a response was returned at +// all) in error.(*googleapi.Error).Header. Use googleapi.IsNotModified +// to check whether the returned error was because +// http.StatusNotModified was returned. +func (c *ProjectsLocationsKeyRingsCryptoKeysUpdatePrimaryVersionCall) Do(opts ...googleapi.CallOption) (*CryptoKey, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &CryptoKey{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := json.NewDecoder(res.Body).Decode(target); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Update the version of a CryptoKey that will be used in Encrypt", + // "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/keyRings/{keyRingsId}/cryptoKeys/{cryptoKeysId}:updatePrimaryVersion", + // "httpMethod": "POST", + // "id": "cloudkms.projects.locations.keyRings.cryptoKeys.updatePrimaryVersion", + // "parameterOrder": [ + // "name" + // ], + // "parameters": { + // "name": { + // "description": "The resource name of the CryptoKey to update.", + // "location": "path", + // "pattern": "^projects/[^/]+/locations/[^/]+/keyRings/[^/]+/cryptoKeys/[^/]+$", + // "required": true, + // "type": "string" + // } + // }, + // "path": "v1/{+name}:updatePrimaryVersion", + // "request": { + // "$ref": "UpdateCryptoKeyPrimaryVersionRequest" + // }, + // "response": { + // "$ref": "CryptoKey" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform" + // ] + // } + +} + +// method id "cloudkms.projects.locations.keyRings.cryptoKeys.cryptoKeyVersions.create": + +type ProjectsLocationsKeyRingsCryptoKeysCryptoKeyVersionsCreateCall struct { + s *Service + parent string + cryptokeyversion *CryptoKeyVersion + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// Create: Create a new CryptoKeyVersion in a CryptoKey. +// +// The server will assign the next sequential id. If unset, +// state will be set to +// ENABLED. +func (r *ProjectsLocationsKeyRingsCryptoKeysCryptoKeyVersionsService) Create(parent string, cryptokeyversion *CryptoKeyVersion) *ProjectsLocationsKeyRingsCryptoKeysCryptoKeyVersionsCreateCall { + c := &ProjectsLocationsKeyRingsCryptoKeysCryptoKeyVersionsCreateCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.parent = parent + c.cryptokeyversion = cryptokeyversion + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *ProjectsLocationsKeyRingsCryptoKeysCryptoKeyVersionsCreateCall) Fields(s ...googleapi.Field) *ProjectsLocationsKeyRingsCryptoKeysCryptoKeyVersionsCreateCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *ProjectsLocationsKeyRingsCryptoKeysCryptoKeyVersionsCreateCall) Context(ctx context.Context) *ProjectsLocationsKeyRingsCryptoKeysCryptoKeyVersionsCreateCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *ProjectsLocationsKeyRingsCryptoKeysCryptoKeyVersionsCreateCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *ProjectsLocationsKeyRingsCryptoKeysCryptoKeyVersionsCreateCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + var body io.Reader = nil + body, err := googleapi.WithoutDataWrapper.JSONReader(c.cryptokeyversion) + if err != nil { + return nil, err + } + reqHeaders.Set("Content-Type", "application/json") + c.urlParams_.Set("alt", alt) + urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+parent}/cryptoKeyVersions") + urls += "?" + c.urlParams_.Encode() + req, _ := http.NewRequest("POST", urls, body) + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "parent": c.parent, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "cloudkms.projects.locations.keyRings.cryptoKeys.cryptoKeyVersions.create" call. +// Exactly one of *CryptoKeyVersion or error will be non-nil. Any +// non-2xx status code is an error. Response headers are in either +// *CryptoKeyVersion.ServerResponse.Header or (if a response was +// returned at all) in error.(*googleapi.Error).Header. Use +// googleapi.IsNotModified to check whether the returned error was +// because http.StatusNotModified was returned. +func (c *ProjectsLocationsKeyRingsCryptoKeysCryptoKeyVersionsCreateCall) Do(opts ...googleapi.CallOption) (*CryptoKeyVersion, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &CryptoKeyVersion{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := json.NewDecoder(res.Body).Decode(target); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Create a new CryptoKeyVersion in a CryptoKey.\n\nThe server will assign the next sequential id. If unset,\nstate will be set to\nENABLED.", + // "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/keyRings/{keyRingsId}/cryptoKeys/{cryptoKeysId}/cryptoKeyVersions", + // "httpMethod": "POST", + // "id": "cloudkms.projects.locations.keyRings.cryptoKeys.cryptoKeyVersions.create", + // "parameterOrder": [ + // "parent" + // ], + // "parameters": { + // "parent": { + // "description": "Required. The name of the CryptoKey associated with\nthe CryptoKeyVersions.", + // "location": "path", + // "pattern": "^projects/[^/]+/locations/[^/]+/keyRings/[^/]+/cryptoKeys/[^/]+$", + // "required": true, + // "type": "string" + // } + // }, + // "path": "v1/{+parent}/cryptoKeyVersions", + // "request": { + // "$ref": "CryptoKeyVersion" + // }, + // "response": { + // "$ref": "CryptoKeyVersion" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform" + // ] + // } + +} + +// method id "cloudkms.projects.locations.keyRings.cryptoKeys.cryptoKeyVersions.destroy": + +type ProjectsLocationsKeyRingsCryptoKeysCryptoKeyVersionsDestroyCall struct { + s *Service + name string + destroycryptokeyversionrequest *DestroyCryptoKeyVersionRequest + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// Destroy: Schedule a CryptoKeyVersion for destruction. +// +// Upon calling this method, CryptoKeyVersion.state will be set +// to +// DESTROY_SCHEDULED +// and destroy_time will be set to a time 24 +// hours in the future, at which point the state +// will be changed to +// DESTROYED, and the key +// material will be irrevocably destroyed. +// +// Before the destroy_time is reached, +// RestoreCryptoKeyVersion may be called to reverse the process. +func (r *ProjectsLocationsKeyRingsCryptoKeysCryptoKeyVersionsService) Destroy(name string, destroycryptokeyversionrequest *DestroyCryptoKeyVersionRequest) *ProjectsLocationsKeyRingsCryptoKeysCryptoKeyVersionsDestroyCall { + c := &ProjectsLocationsKeyRingsCryptoKeysCryptoKeyVersionsDestroyCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.name = name + c.destroycryptokeyversionrequest = destroycryptokeyversionrequest + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *ProjectsLocationsKeyRingsCryptoKeysCryptoKeyVersionsDestroyCall) Fields(s ...googleapi.Field) *ProjectsLocationsKeyRingsCryptoKeysCryptoKeyVersionsDestroyCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *ProjectsLocationsKeyRingsCryptoKeysCryptoKeyVersionsDestroyCall) Context(ctx context.Context) *ProjectsLocationsKeyRingsCryptoKeysCryptoKeyVersionsDestroyCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *ProjectsLocationsKeyRingsCryptoKeysCryptoKeyVersionsDestroyCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *ProjectsLocationsKeyRingsCryptoKeysCryptoKeyVersionsDestroyCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + var body io.Reader = nil + body, err := googleapi.WithoutDataWrapper.JSONReader(c.destroycryptokeyversionrequest) + if err != nil { + return nil, err + } + reqHeaders.Set("Content-Type", "application/json") + c.urlParams_.Set("alt", alt) + urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}:destroy") + urls += "?" + c.urlParams_.Encode() + req, _ := http.NewRequest("POST", urls, body) + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "name": c.name, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "cloudkms.projects.locations.keyRings.cryptoKeys.cryptoKeyVersions.destroy" call. +// Exactly one of *CryptoKeyVersion or error will be non-nil. Any +// non-2xx status code is an error. Response headers are in either +// *CryptoKeyVersion.ServerResponse.Header or (if a response was +// returned at all) in error.(*googleapi.Error).Header. Use +// googleapi.IsNotModified to check whether the returned error was +// because http.StatusNotModified was returned. +func (c *ProjectsLocationsKeyRingsCryptoKeysCryptoKeyVersionsDestroyCall) Do(opts ...googleapi.CallOption) (*CryptoKeyVersion, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &CryptoKeyVersion{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := json.NewDecoder(res.Body).Decode(target); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Schedule a CryptoKeyVersion for destruction.\n\nUpon calling this method, CryptoKeyVersion.state will be set to\nDESTROY_SCHEDULED\nand destroy_time will be set to a time 24\nhours in the future, at which point the state\nwill be changed to\nDESTROYED, and the key\nmaterial will be irrevocably destroyed.\n\nBefore the destroy_time is reached,\nRestoreCryptoKeyVersion may be called to reverse the process.", + // "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/keyRings/{keyRingsId}/cryptoKeys/{cryptoKeysId}/cryptoKeyVersions/{cryptoKeyVersionsId}:destroy", + // "httpMethod": "POST", + // "id": "cloudkms.projects.locations.keyRings.cryptoKeys.cryptoKeyVersions.destroy", + // "parameterOrder": [ + // "name" + // ], + // "parameters": { + // "name": { + // "description": "The resource name of the CryptoKeyVersion to destroy.", + // "location": "path", + // "pattern": "^projects/[^/]+/locations/[^/]+/keyRings/[^/]+/cryptoKeys/[^/]+/cryptoKeyVersions/[^/]+$", + // "required": true, + // "type": "string" + // } + // }, + // "path": "v1/{+name}:destroy", + // "request": { + // "$ref": "DestroyCryptoKeyVersionRequest" + // }, + // "response": { + // "$ref": "CryptoKeyVersion" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform" + // ] + // } + +} + +// method id "cloudkms.projects.locations.keyRings.cryptoKeys.cryptoKeyVersions.get": + +type ProjectsLocationsKeyRingsCryptoKeysCryptoKeyVersionsGetCall struct { + s *Service + name string + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header +} + +// Get: Returns metadata for a given CryptoKeyVersion. +func (r *ProjectsLocationsKeyRingsCryptoKeysCryptoKeyVersionsService) Get(name string) *ProjectsLocationsKeyRingsCryptoKeysCryptoKeyVersionsGetCall { + c := &ProjectsLocationsKeyRingsCryptoKeysCryptoKeyVersionsGetCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.name = name + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *ProjectsLocationsKeyRingsCryptoKeysCryptoKeyVersionsGetCall) Fields(s ...googleapi.Field) *ProjectsLocationsKeyRingsCryptoKeysCryptoKeyVersionsGetCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// IfNoneMatch sets the optional parameter which makes the operation +// fail if the object's ETag matches the given value. This is useful for +// getting updates only after the object has changed since the last +// request. Use googleapi.IsNotModified to check whether the response +// error from Do is the result of In-None-Match. +func (c *ProjectsLocationsKeyRingsCryptoKeysCryptoKeyVersionsGetCall) IfNoneMatch(entityTag string) *ProjectsLocationsKeyRingsCryptoKeysCryptoKeyVersionsGetCall { + c.ifNoneMatch_ = entityTag + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *ProjectsLocationsKeyRingsCryptoKeysCryptoKeyVersionsGetCall) Context(ctx context.Context) *ProjectsLocationsKeyRingsCryptoKeysCryptoKeyVersionsGetCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *ProjectsLocationsKeyRingsCryptoKeysCryptoKeyVersionsGetCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *ProjectsLocationsKeyRingsCryptoKeysCryptoKeyVersionsGetCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + if c.ifNoneMatch_ != "" { + reqHeaders.Set("If-None-Match", c.ifNoneMatch_) + } + var body io.Reader = nil + c.urlParams_.Set("alt", alt) + urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}") + urls += "?" + c.urlParams_.Encode() + req, _ := http.NewRequest("GET", urls, body) + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "name": c.name, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "cloudkms.projects.locations.keyRings.cryptoKeys.cryptoKeyVersions.get" call. +// Exactly one of *CryptoKeyVersion or error will be non-nil. Any +// non-2xx status code is an error. Response headers are in either +// *CryptoKeyVersion.ServerResponse.Header or (if a response was +// returned at all) in error.(*googleapi.Error).Header. Use +// googleapi.IsNotModified to check whether the returned error was +// because http.StatusNotModified was returned. +func (c *ProjectsLocationsKeyRingsCryptoKeysCryptoKeyVersionsGetCall) Do(opts ...googleapi.CallOption) (*CryptoKeyVersion, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &CryptoKeyVersion{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := json.NewDecoder(res.Body).Decode(target); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Returns metadata for a given CryptoKeyVersion.", + // "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/keyRings/{keyRingsId}/cryptoKeys/{cryptoKeysId}/cryptoKeyVersions/{cryptoKeyVersionsId}", + // "httpMethod": "GET", + // "id": "cloudkms.projects.locations.keyRings.cryptoKeys.cryptoKeyVersions.get", + // "parameterOrder": [ + // "name" + // ], + // "parameters": { + // "name": { + // "description": "The name of the CryptoKeyVersion to get.", + // "location": "path", + // "pattern": "^projects/[^/]+/locations/[^/]+/keyRings/[^/]+/cryptoKeys/[^/]+/cryptoKeyVersions/[^/]+$", + // "required": true, + // "type": "string" + // } + // }, + // "path": "v1/{+name}", + // "response": { + // "$ref": "CryptoKeyVersion" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform" + // ] + // } + +} + +// method id "cloudkms.projects.locations.keyRings.cryptoKeys.cryptoKeyVersions.list": + +type ProjectsLocationsKeyRingsCryptoKeysCryptoKeyVersionsListCall struct { + s *Service + parent string + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header +} + +// List: Lists CryptoKeyVersions. +func (r *ProjectsLocationsKeyRingsCryptoKeysCryptoKeyVersionsService) List(parent string) *ProjectsLocationsKeyRingsCryptoKeysCryptoKeyVersionsListCall { + c := &ProjectsLocationsKeyRingsCryptoKeysCryptoKeyVersionsListCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.parent = parent + return c +} + +// PageSize sets the optional parameter "pageSize": Optional limit on +// the number of CryptoKeyVersions to +// include in the response. Further CryptoKeyVersions can +// subsequently be obtained by including +// the +// ListCryptoKeyVersionsResponse.next_page_token in a subsequent +// request. +// If unspecified, the server will pick an appropriate default. +func (c *ProjectsLocationsKeyRingsCryptoKeysCryptoKeyVersionsListCall) PageSize(pageSize int64) *ProjectsLocationsKeyRingsCryptoKeysCryptoKeyVersionsListCall { + c.urlParams_.Set("pageSize", fmt.Sprint(pageSize)) + return c +} + +// PageToken sets the optional parameter "pageToken": Optional +// pagination token, returned earlier +// via +// ListCryptoKeyVersionsResponse.next_page_token. +func (c *ProjectsLocationsKeyRingsCryptoKeysCryptoKeyVersionsListCall) PageToken(pageToken string) *ProjectsLocationsKeyRingsCryptoKeysCryptoKeyVersionsListCall { + c.urlParams_.Set("pageToken", pageToken) + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *ProjectsLocationsKeyRingsCryptoKeysCryptoKeyVersionsListCall) Fields(s ...googleapi.Field) *ProjectsLocationsKeyRingsCryptoKeysCryptoKeyVersionsListCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// IfNoneMatch sets the optional parameter which makes the operation +// fail if the object's ETag matches the given value. This is useful for +// getting updates only after the object has changed since the last +// request. Use googleapi.IsNotModified to check whether the response +// error from Do is the result of In-None-Match. +func (c *ProjectsLocationsKeyRingsCryptoKeysCryptoKeyVersionsListCall) IfNoneMatch(entityTag string) *ProjectsLocationsKeyRingsCryptoKeysCryptoKeyVersionsListCall { + c.ifNoneMatch_ = entityTag + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *ProjectsLocationsKeyRingsCryptoKeysCryptoKeyVersionsListCall) Context(ctx context.Context) *ProjectsLocationsKeyRingsCryptoKeysCryptoKeyVersionsListCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *ProjectsLocationsKeyRingsCryptoKeysCryptoKeyVersionsListCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *ProjectsLocationsKeyRingsCryptoKeysCryptoKeyVersionsListCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + if c.ifNoneMatch_ != "" { + reqHeaders.Set("If-None-Match", c.ifNoneMatch_) + } + var body io.Reader = nil + c.urlParams_.Set("alt", alt) + urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+parent}/cryptoKeyVersions") + urls += "?" + c.urlParams_.Encode() + req, _ := http.NewRequest("GET", urls, body) + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "parent": c.parent, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "cloudkms.projects.locations.keyRings.cryptoKeys.cryptoKeyVersions.list" call. +// Exactly one of *ListCryptoKeyVersionsResponse or error will be +// non-nil. Any non-2xx status code is an error. Response headers are in +// either *ListCryptoKeyVersionsResponse.ServerResponse.Header or (if a +// response was returned at all) in error.(*googleapi.Error).Header. Use +// googleapi.IsNotModified to check whether the returned error was +// because http.StatusNotModified was returned. +func (c *ProjectsLocationsKeyRingsCryptoKeysCryptoKeyVersionsListCall) Do(opts ...googleapi.CallOption) (*ListCryptoKeyVersionsResponse, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &ListCryptoKeyVersionsResponse{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := json.NewDecoder(res.Body).Decode(target); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Lists CryptoKeyVersions.", + // "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/keyRings/{keyRingsId}/cryptoKeys/{cryptoKeysId}/cryptoKeyVersions", + // "httpMethod": "GET", + // "id": "cloudkms.projects.locations.keyRings.cryptoKeys.cryptoKeyVersions.list", + // "parameterOrder": [ + // "parent" + // ], + // "parameters": { + // "pageSize": { + // "description": "Optional limit on the number of CryptoKeyVersions to\ninclude in the response. Further CryptoKeyVersions can\nsubsequently be obtained by including the\nListCryptoKeyVersionsResponse.next_page_token in a subsequent request.\nIf unspecified, the server will pick an appropriate default.", + // "format": "int32", + // "location": "query", + // "type": "integer" + // }, + // "pageToken": { + // "description": "Optional pagination token, returned earlier via\nListCryptoKeyVersionsResponse.next_page_token.", + // "location": "query", + // "type": "string" + // }, + // "parent": { + // "description": "Required. The resource name of the CryptoKey to list, in the format\n`projects/*/locations/*/keyRings/*/cryptoKeys/*`.", + // "location": "path", + // "pattern": "^projects/[^/]+/locations/[^/]+/keyRings/[^/]+/cryptoKeys/[^/]+$", + // "required": true, + // "type": "string" + // } + // }, + // "path": "v1/{+parent}/cryptoKeyVersions", + // "response": { + // "$ref": "ListCryptoKeyVersionsResponse" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform" + // ] + // } + +} + +// Pages invokes f for each page of results. +// A non-nil error returned from f will halt the iteration. +// The provided context supersedes any context provided to the Context method. +func (c *ProjectsLocationsKeyRingsCryptoKeysCryptoKeyVersionsListCall) Pages(ctx context.Context, f func(*ListCryptoKeyVersionsResponse) error) error { + c.ctx_ = ctx + defer c.PageToken(c.urlParams_.Get("pageToken")) // reset paging to original point + for { + x, err := c.Do() + if err != nil { + return err + } + if err := f(x); err != nil { + return err + } + if x.NextPageToken == "" { + return nil + } + c.PageToken(x.NextPageToken) + } +} + +// method id "cloudkms.projects.locations.keyRings.cryptoKeys.cryptoKeyVersions.patch": + +type ProjectsLocationsKeyRingsCryptoKeysCryptoKeyVersionsPatchCall struct { + s *Service + name string + cryptokeyversion *CryptoKeyVersion + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// Patch: Update a CryptoKeyVersion's metadata. +// +// state may be changed between +// ENABLED and +// DISABLED using this +// method. See DestroyCryptoKeyVersion and RestoreCryptoKeyVersion +// to +// move between other states. +func (r *ProjectsLocationsKeyRingsCryptoKeysCryptoKeyVersionsService) Patch(name string, cryptokeyversion *CryptoKeyVersion) *ProjectsLocationsKeyRingsCryptoKeysCryptoKeyVersionsPatchCall { + c := &ProjectsLocationsKeyRingsCryptoKeysCryptoKeyVersionsPatchCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.name = name + c.cryptokeyversion = cryptokeyversion + return c +} + +// UpdateMask sets the optional parameter "updateMask": Required list of +// fields to be updated in this request. +func (c *ProjectsLocationsKeyRingsCryptoKeysCryptoKeyVersionsPatchCall) UpdateMask(updateMask string) *ProjectsLocationsKeyRingsCryptoKeysCryptoKeyVersionsPatchCall { + c.urlParams_.Set("updateMask", updateMask) + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *ProjectsLocationsKeyRingsCryptoKeysCryptoKeyVersionsPatchCall) Fields(s ...googleapi.Field) *ProjectsLocationsKeyRingsCryptoKeysCryptoKeyVersionsPatchCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *ProjectsLocationsKeyRingsCryptoKeysCryptoKeyVersionsPatchCall) Context(ctx context.Context) *ProjectsLocationsKeyRingsCryptoKeysCryptoKeyVersionsPatchCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *ProjectsLocationsKeyRingsCryptoKeysCryptoKeyVersionsPatchCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *ProjectsLocationsKeyRingsCryptoKeysCryptoKeyVersionsPatchCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + var body io.Reader = nil + body, err := googleapi.WithoutDataWrapper.JSONReader(c.cryptokeyversion) + if err != nil { + return nil, err + } + reqHeaders.Set("Content-Type", "application/json") + c.urlParams_.Set("alt", alt) + urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}") + urls += "?" + c.urlParams_.Encode() + req, _ := http.NewRequest("PATCH", urls, body) + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "name": c.name, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "cloudkms.projects.locations.keyRings.cryptoKeys.cryptoKeyVersions.patch" call. +// Exactly one of *CryptoKeyVersion or error will be non-nil. Any +// non-2xx status code is an error. Response headers are in either +// *CryptoKeyVersion.ServerResponse.Header or (if a response was +// returned at all) in error.(*googleapi.Error).Header. Use +// googleapi.IsNotModified to check whether the returned error was +// because http.StatusNotModified was returned. +func (c *ProjectsLocationsKeyRingsCryptoKeysCryptoKeyVersionsPatchCall) Do(opts ...googleapi.CallOption) (*CryptoKeyVersion, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &CryptoKeyVersion{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := json.NewDecoder(res.Body).Decode(target); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Update a CryptoKeyVersion's metadata.\n\nstate may be changed between\nENABLED and\nDISABLED using this\nmethod. See DestroyCryptoKeyVersion and RestoreCryptoKeyVersion to\nmove between other states.", + // "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/keyRings/{keyRingsId}/cryptoKeys/{cryptoKeysId}/cryptoKeyVersions/{cryptoKeyVersionsId}", + // "httpMethod": "PATCH", + // "id": "cloudkms.projects.locations.keyRings.cryptoKeys.cryptoKeyVersions.patch", + // "parameterOrder": [ + // "name" + // ], + // "parameters": { + // "name": { + // "description": "Output only. The resource name for this CryptoKeyVersion in the format\n`projects/*/locations/*/keyRings/*/cryptoKeys/*/cryptoKeyVersions/*`.", + // "location": "path", + // "pattern": "^projects/[^/]+/locations/[^/]+/keyRings/[^/]+/cryptoKeys/[^/]+/cryptoKeyVersions/[^/]+$", + // "required": true, + // "type": "string" + // }, + // "updateMask": { + // "description": "Required list of fields to be updated in this request.", + // "format": "google-fieldmask", + // "location": "query", + // "type": "string" + // } + // }, + // "path": "v1/{+name}", + // "request": { + // "$ref": "CryptoKeyVersion" + // }, + // "response": { + // "$ref": "CryptoKeyVersion" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform" + // ] + // } + +} + +// method id "cloudkms.projects.locations.keyRings.cryptoKeys.cryptoKeyVersions.restore": + +type ProjectsLocationsKeyRingsCryptoKeysCryptoKeyVersionsRestoreCall struct { + s *Service + name string + restorecryptokeyversionrequest *RestoreCryptoKeyVersionRequest + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// Restore: Restore a CryptoKeyVersion in +// the +// DESTROY_SCHEDULED, +// state. +// +// Upon restoration of the CryptoKeyVersion, state +// will be set to DISABLED, +// and destroy_time will be cleared. +func (r *ProjectsLocationsKeyRingsCryptoKeysCryptoKeyVersionsService) Restore(name string, restorecryptokeyversionrequest *RestoreCryptoKeyVersionRequest) *ProjectsLocationsKeyRingsCryptoKeysCryptoKeyVersionsRestoreCall { + c := &ProjectsLocationsKeyRingsCryptoKeysCryptoKeyVersionsRestoreCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.name = name + c.restorecryptokeyversionrequest = restorecryptokeyversionrequest + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *ProjectsLocationsKeyRingsCryptoKeysCryptoKeyVersionsRestoreCall) Fields(s ...googleapi.Field) *ProjectsLocationsKeyRingsCryptoKeysCryptoKeyVersionsRestoreCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *ProjectsLocationsKeyRingsCryptoKeysCryptoKeyVersionsRestoreCall) Context(ctx context.Context) *ProjectsLocationsKeyRingsCryptoKeysCryptoKeyVersionsRestoreCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *ProjectsLocationsKeyRingsCryptoKeysCryptoKeyVersionsRestoreCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *ProjectsLocationsKeyRingsCryptoKeysCryptoKeyVersionsRestoreCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + var body io.Reader = nil + body, err := googleapi.WithoutDataWrapper.JSONReader(c.restorecryptokeyversionrequest) + if err != nil { + return nil, err + } + reqHeaders.Set("Content-Type", "application/json") + c.urlParams_.Set("alt", alt) + urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}:restore") + urls += "?" + c.urlParams_.Encode() + req, _ := http.NewRequest("POST", urls, body) + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "name": c.name, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "cloudkms.projects.locations.keyRings.cryptoKeys.cryptoKeyVersions.restore" call. +// Exactly one of *CryptoKeyVersion or error will be non-nil. Any +// non-2xx status code is an error. Response headers are in either +// *CryptoKeyVersion.ServerResponse.Header or (if a response was +// returned at all) in error.(*googleapi.Error).Header. Use +// googleapi.IsNotModified to check whether the returned error was +// because http.StatusNotModified was returned. +func (c *ProjectsLocationsKeyRingsCryptoKeysCryptoKeyVersionsRestoreCall) Do(opts ...googleapi.CallOption) (*CryptoKeyVersion, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &CryptoKeyVersion{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := json.NewDecoder(res.Body).Decode(target); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Restore a CryptoKeyVersion in the\nDESTROY_SCHEDULED,\nstate.\n\nUpon restoration of the CryptoKeyVersion, state\nwill be set to DISABLED,\nand destroy_time will be cleared.", + // "flatPath": "v1/projects/{projectsId}/locations/{locationsId}/keyRings/{keyRingsId}/cryptoKeys/{cryptoKeysId}/cryptoKeyVersions/{cryptoKeyVersionsId}:restore", + // "httpMethod": "POST", + // "id": "cloudkms.projects.locations.keyRings.cryptoKeys.cryptoKeyVersions.restore", + // "parameterOrder": [ + // "name" + // ], + // "parameters": { + // "name": { + // "description": "The resource name of the CryptoKeyVersion to restore.", + // "location": "path", + // "pattern": "^projects/[^/]+/locations/[^/]+/keyRings/[^/]+/cryptoKeys/[^/]+/cryptoKeyVersions/[^/]+$", + // "required": true, + // "type": "string" + // } + // }, + // "path": "v1/{+name}:restore", + // "request": { + // "$ref": "RestoreCryptoKeyVersionRequest" + // }, + // "response": { + // "$ref": "CryptoKeyVersion" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform" + // ] + // } + +} From b3956a689eaa7730e3fe3c1ca253a4027f9a1b9f Mon Sep 17 00:00:00 2001 From: Koonwah Chen Date: Wed, 28 Jun 2017 16:03:18 -0700 Subject: [PATCH 108/448] Add KUBE_GCE_API_ENDPOINT for GCE API endpoint config. --- cluster/common.sh | 1 + cluster/gce/config-default.sh | 3 ++- cluster/gce/gci/configure-helper.sh | 7 ++++++- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/cluster/common.sh b/cluster/common.sh index 502abfbb81c..951826cbe65 100755 --- a/cluster/common.sh +++ b/cluster/common.sh @@ -665,6 +665,7 @@ ENABLE_APISERVER_BASIC_AUDIT: $(yaml-quote ${ENABLE_APISERVER_BASIC_AUDIT:-}) ENABLE_APISERVER_ADVANCED_AUDIT: $(yaml-quote ${ENABLE_APISERVER_ADVANCED_AUDIT:-}) ENABLE_CACHE_MUTATION_DETECTOR: $(yaml-quote ${ENABLE_CACHE_MUTATION_DETECTOR:-false}) ADVANCED_AUDIT_BACKEND: $(yaml-quote ${ADVANCED_AUDIT_BACKEND:-log}) +KUBE_GCE_API_ENDPOINT: $(yaml-quote ${KUBE_GCE_API_ENDPOINT:-}) EOF if [ -n "${KUBELET_PORT:-}" ]; then cat >>$file </etc/gce.conf [global] EOF + if [[ -n "${KUBE_GCE_API_ENDPOINT:-}" ]]; then + cat <>/etc/gce.conf +api-endpoint = ${KUBE_GCE_API_ENDPOINT} +EOF + fi if [[ -n "${PROJECT_ID:-}" && -n "${TOKEN_URL:-}" && -n "${TOKEN_BODY:-}" && -n "${NODE_NETWORK:-}" ]]; then use_cloud_config="true" cat <>/etc/gce.conf @@ -1695,7 +1700,7 @@ function start-kube-addons { sed -i -e "s@__CALICO_TYPHA_CPU__@$(get-calico-typha-cpu)@g" "${typha_dep_file}" sed -i -e "s@__CALICO_TYPHA_REPLICAS__@$(get-calico-typha-replicas)@g" "${typha_dep_file}" else - # If not configured to use Calico, the set the typha replica count to 0, but only if the + # If not configured to use Calico, the set the typha replica count to 0, but only if the # addon is present. local -r typha_dep_file="${dst_dir}/calico-policy-controller/typha-deployment.yaml" if [[ -e $typha_dep_file ]]; then From 57e8461662cf943f0512e4b6d2de3aaccb9168c8 Mon Sep 17 00:00:00 2001 From: Saksham Sharma Date: Tue, 27 Jun 2017 17:28:32 -0700 Subject: [PATCH 109/448] Add Google cloudkms service to gce cloud provider --- pkg/cloudprovider/providers/gce/BUILD | 1 + pkg/cloudprovider/providers/gce/gce.go | 22 ++++++++++++++++++++-- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/pkg/cloudprovider/providers/gce/BUILD b/pkg/cloudprovider/providers/gce/BUILD index 3b97c50e768..038d2f8b6ba 100644 --- a/pkg/cloudprovider/providers/gce/BUILD +++ b/pkg/cloudprovider/providers/gce/BUILD @@ -55,6 +55,7 @@ go_library( "//vendor/github.com/prometheus/client_golang/prometheus: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/cloudkms/v1: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/google.golang.org/api/container/v1:go_default_library", diff --git a/pkg/cloudprovider/providers/gce/gce.go b/pkg/cloudprovider/providers/gce/gce.go index 90e2570a429..e56c4b3fb13 100644 --- a/pkg/cloudprovider/providers/gce/gce.go +++ b/pkg/cloudprovider/providers/gce/gce.go @@ -25,9 +25,9 @@ import ( "sync" "time" - "cloud.google.com/go/compute/metadata" + gcfg "gopkg.in/gcfg.v1" - "gopkg.in/gcfg.v1" + "cloud.google.com/go/compute/metadata" "k8s.io/apimachinery/pkg/util/sets" "k8s.io/apimachinery/pkg/util/wait" @@ -38,6 +38,7 @@ import ( "github.com/golang/glog" "golang.org/x/oauth2" "golang.org/x/oauth2/google" + cloudkms "google.golang.org/api/cloudkms/v1" computebeta "google.golang.org/api/compute/v0.beta" compute "google.golang.org/api/compute/v1" container "google.golang.org/api/container/v1" @@ -85,6 +86,7 @@ type GCECloud struct { service *compute.Service serviceBeta *computebeta.Service containerService *container.Service + cloudkmsService *cloudkms.Service clientBuilder controller.ControllerClientBuilder projectID string region string @@ -153,6 +155,16 @@ func (g *GCECloud) GetComputeService() *compute.Service { return g.service } +// Raw access to the cloudkmsService of GCE cloud. Required for encryption of etcd using Google KMS. +func (g *GCECloud) GetKMSService() *cloudkms.Service { + return g.cloudkmsService +} + +// Returns the ProjectID corresponding to the project this cloud is in. +func (g *GCECloud) GetProjectID() string { + return g.projectID +} + // newGCECloud creates a new instance of GCECloud. func newGCECloud(config io.Reader) (*GCECloud, error) { projectID, zone, err := getProjectAndZone() @@ -244,6 +256,11 @@ func CreateGCECloud(projectID, region, zone string, managedZones []string, netwo return nil, err } + cloudkmsService, err := cloudkms.New(client) + if err != nil { + return nil, err + } + if networkURL == "" { networkName, err := getNetworkNameViaAPICall(service, projectID) if err != nil { @@ -274,6 +291,7 @@ func CreateGCECloud(projectID, region, zone string, managedZones []string, netwo service: service, serviceBeta: serviceBeta, containerService: containerService, + cloudkmsService: cloudkmsService, projectID: projectID, networkProjectID: networkProjectID, onXPN: onXPN, From 90ee0c4e0bda1f37216eb8224905e0f8c5c3408f Mon Sep 17 00:00:00 2001 From: Jonathan MacMillan Date: Thu, 1 Jun 2017 12:54:57 -0700 Subject: [PATCH 110/448] [Federation] Convert the deployment controller to a sync controller. --- .../federation-controller-manager/app/BUILD | 1 - .../app/controllermanager.go | 10 - federation/pkg/federatedtypes/BUILD | 5 +- federation/pkg/federatedtypes/deployment.go | 188 +++++ federation/pkg/federatedtypes/replicaset.go | 210 +----- federation/pkg/federatedtypes/scheduling.go | 184 +++++ ...{replicaset_test.go => scheduling_test.go} | 15 +- federation/pkg/federation-controller/BUILD | 1 - .../federation-controller/deployment/BUILD | 76 -- .../deployment/deploymentcontroller.go | 649 ------------------ .../pkg/federation-controller/sync/BUILD | 3 + .../deploymentcontroller_test.go | 26 +- 12 files changed, 417 insertions(+), 951 deletions(-) create mode 100644 federation/pkg/federatedtypes/deployment.go rename federation/pkg/federatedtypes/{replicaset_test.go => scheduling_test.go} (90%) delete mode 100644 federation/pkg/federation-controller/deployment/BUILD delete mode 100644 federation/pkg/federation-controller/deployment/deploymentcontroller.go rename federation/pkg/federation-controller/{deployment => sync}/deploymentcontroller_test.go (83%) diff --git a/federation/cmd/federation-controller-manager/app/BUILD b/federation/cmd/federation-controller-manager/app/BUILD index 2be5e85b6d3..1069570bbd2 100644 --- a/federation/cmd/federation-controller-manager/app/BUILD +++ b/federation/cmd/federation-controller-manager/app/BUILD @@ -23,7 +23,6 @@ go_library( "//federation/pkg/dnsprovider/providers/google/clouddns:go_default_library", "//federation/pkg/federatedtypes:go_default_library", "//federation/pkg/federation-controller/cluster:go_default_library", - "//federation/pkg/federation-controller/deployment:go_default_library", "//federation/pkg/federation-controller/ingress:go_default_library", "//federation/pkg/federation-controller/namespace:go_default_library", "//federation/pkg/federation-controller/service:go_default_library", diff --git a/federation/cmd/federation-controller-manager/app/controllermanager.go b/federation/cmd/federation-controller-manager/app/controllermanager.go index 17b37d4004b..1f8b41ec9b8 100644 --- a/federation/cmd/federation-controller-manager/app/controllermanager.go +++ b/federation/cmd/federation-controller-manager/app/controllermanager.go @@ -37,7 +37,6 @@ import ( "k8s.io/kubernetes/federation/cmd/federation-controller-manager/app/options" "k8s.io/kubernetes/federation/pkg/federatedtypes" clustercontroller "k8s.io/kubernetes/federation/pkg/federation-controller/cluster" - deploymentcontroller "k8s.io/kubernetes/federation/pkg/federation-controller/deployment" ingresscontroller "k8s.io/kubernetes/federation/pkg/federation-controller/ingress" namespacecontroller "k8s.io/kubernetes/federation/pkg/federation-controller/namespace" servicecontroller "k8s.io/kubernetes/federation/pkg/federation-controller/service" @@ -166,15 +165,6 @@ func StartControllers(s *options.CMServer, restClientCfg *restclient.Config) err } } - if controllerEnabled(s.Controllers, serverResources, deploymentcontroller.ControllerName, deploymentcontroller.RequiredResources, true) { - glog.V(3).Infof("Loading client config for deployment controller %q", deploymentcontroller.UserAgentName) - deploymentClientset := federationclientset.NewForConfigOrDie(restclient.AddUserAgent(restClientCfg, deploymentcontroller.UserAgentName)) - deploymentController := deploymentcontroller.NewDeploymentController(deploymentClientset) - glog.V(3).Infof("Running deployment controller") - // TODO: rename s.ConcurrentReplicaSetSyncs - go deploymentController.Run(s.ConcurrentReplicaSetSyncs, wait.NeverStop) - } - if controllerEnabled(s.Controllers, serverResources, ingresscontroller.ControllerName, ingresscontroller.RequiredResources, true) { glog.V(3).Infof("Loading client config for ingress controller %q", ingresscontroller.UserAgentName) ingClientset := federationclientset.NewForConfigOrDie(restclient.AddUserAgent(restClientCfg, ingresscontroller.UserAgentName)) diff --git a/federation/pkg/federatedtypes/BUILD b/federation/pkg/federatedtypes/BUILD index 3391d597462..8e1f8e2fbce 100644 --- a/federation/pkg/federatedtypes/BUILD +++ b/federation/pkg/federatedtypes/BUILD @@ -14,6 +14,7 @@ go_library( "adapter.go", "configmap.go", "daemonset.go", + "deployment.go", "registry.go", "replicaset.go", "scheduling.go", @@ -32,6 +33,7 @@ go_library( "//vendor/github.com/golang/glog: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/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", @@ -58,7 +60,7 @@ filegroup( go_test( name = "go_default_test", - srcs = ["replicaset_test.go"], + srcs = ["scheduling_test.go"], library = ":go_default_library", tags = ["automanaged"], deps = [ @@ -66,5 +68,6 @@ go_test( "//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/runtime:go_default_library", ], ) diff --git a/federation/pkg/federatedtypes/deployment.go b/federation/pkg/federatedtypes/deployment.go new file mode 100644 index 00000000000..72a007126ae --- /dev/null +++ b/federation/pkg/federatedtypes/deployment.go @@ -0,0 +1,188 @@ +/* +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 federatedtypes + +import ( + apiv1 "k8s.io/api/core/v1" + extensionsv1 "k8s.io/api/extensions/v1beta1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + pkgruntime "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/types" + "k8s.io/apimachinery/pkg/watch" + federationclientset "k8s.io/kubernetes/federation/client/clientset_generated/federation_clientset" + fedutil "k8s.io/kubernetes/federation/pkg/federation-controller/util" + kubeclientset "k8s.io/kubernetes/pkg/client/clientset_generated/clientset" +) + +const ( + DeploymentKind = "deployment" + DeploymentControllerName = "deployments" + FedDeploymentPreferencesAnnotation = "federation.kubernetes.io/deployment-preferences" +) + +func init() { + RegisterFederatedType(DeploymentKind, DeploymentControllerName, []schema.GroupVersionResource{extensionsv1.SchemeGroupVersion.WithResource(DeploymentControllerName)}, NewDeploymentAdapter) +} + +type DeploymentAdapter struct { + *schedulingAdapter + client federationclientset.Interface +} + +func NewDeploymentAdapter(client federationclientset.Interface) FederatedTypeAdapter { + schedulingAdapter := schedulingAdapter{ + preferencesAnnotationName: FedDeploymentPreferencesAnnotation, + updateStatusFunc: func(obj pkgruntime.Object, status SchedulingStatus) error { + deployment := obj.(*extensionsv1.Deployment) + if status.Replicas != deployment.Status.Replicas || status.UpdatedReplicas != deployment.Status.UpdatedReplicas || + status.ReadyReplicas != deployment.Status.ReadyReplicas || status.AvailableReplicas != deployment.Status.AvailableReplicas { + deployment.Status = extensionsv1.DeploymentStatus{ + Replicas: status.Replicas, + UpdatedReplicas: status.UpdatedReplicas, + ReadyReplicas: status.ReadyReplicas, + AvailableReplicas: status.AvailableReplicas, + } + _, err := client.Extensions().Deployments(deployment.Namespace).UpdateStatus(deployment) + return err + } + return nil + }, + } + + return &DeploymentAdapter{&schedulingAdapter, client} +} + +func (a *DeploymentAdapter) Kind() string { + return DeploymentKind +} + +func (a *DeploymentAdapter) ObjectType() pkgruntime.Object { + return &extensionsv1.Deployment{} +} + +func (a *DeploymentAdapter) IsExpectedType(obj interface{}) bool { + _, ok := obj.(*extensionsv1.Deployment) + return ok +} + +func (a *DeploymentAdapter) Copy(obj pkgruntime.Object) pkgruntime.Object { + deployment := obj.(*extensionsv1.Deployment) + return fedutil.DeepCopyDeployment(deployment) +} + +func (a *DeploymentAdapter) Equivalent(obj1, obj2 pkgruntime.Object) bool { + deployment1 := obj1.(*extensionsv1.Deployment) + deployment2 := obj2.(*extensionsv1.Deployment) + return fedutil.DeploymentEquivalent(deployment1, deployment2) +} + +func (a *DeploymentAdapter) NamespacedName(obj pkgruntime.Object) types.NamespacedName { + deployment := obj.(*extensionsv1.Deployment) + return types.NamespacedName{Namespace: deployment.Namespace, Name: deployment.Name} +} + +func (a *DeploymentAdapter) ObjectMeta(obj pkgruntime.Object) *metav1.ObjectMeta { + return &obj.(*extensionsv1.Deployment).ObjectMeta +} + +func (a *DeploymentAdapter) FedCreate(obj pkgruntime.Object) (pkgruntime.Object, error) { + deployment := obj.(*extensionsv1.Deployment) + return a.client.Extensions().Deployments(deployment.Namespace).Create(deployment) +} + +func (a *DeploymentAdapter) FedDelete(namespacedName types.NamespacedName, options *metav1.DeleteOptions) error { + return a.client.Extensions().Deployments(namespacedName.Namespace).Delete(namespacedName.Name, options) +} + +func (a *DeploymentAdapter) FedGet(namespacedName types.NamespacedName) (pkgruntime.Object, error) { + return a.client.Extensions().Deployments(namespacedName.Namespace).Get(namespacedName.Name, metav1.GetOptions{}) +} + +func (a *DeploymentAdapter) FedList(namespace string, options metav1.ListOptions) (pkgruntime.Object, error) { + return a.client.Extensions().Deployments(namespace).List(options) +} + +func (a *DeploymentAdapter) FedUpdate(obj pkgruntime.Object) (pkgruntime.Object, error) { + deployment := obj.(*extensionsv1.Deployment) + return a.client.Extensions().Deployments(deployment.Namespace).Update(deployment) +} + +func (a *DeploymentAdapter) FedWatch(namespace string, options metav1.ListOptions) (watch.Interface, error) { + return a.client.Extensions().Deployments(namespace).Watch(options) +} + +func (a *DeploymentAdapter) ClusterCreate(client kubeclientset.Interface, obj pkgruntime.Object) (pkgruntime.Object, error) { + deployment := obj.(*extensionsv1.Deployment) + return client.Extensions().Deployments(deployment.Namespace).Create(deployment) +} + +func (a *DeploymentAdapter) ClusterDelete(client kubeclientset.Interface, nsName types.NamespacedName, options *metav1.DeleteOptions) error { + return client.Extensions().Deployments(nsName.Namespace).Delete(nsName.Name, options) +} + +func (a *DeploymentAdapter) ClusterGet(client kubeclientset.Interface, namespacedName types.NamespacedName) (pkgruntime.Object, error) { + return client.Extensions().Deployments(namespacedName.Namespace).Get(namespacedName.Name, metav1.GetOptions{}) +} + +func (a *DeploymentAdapter) ClusterList(client kubeclientset.Interface, namespace string, options metav1.ListOptions) (pkgruntime.Object, error) { + return client.Extensions().Deployments(namespace).List(options) +} + +func (a *DeploymentAdapter) ClusterUpdate(client kubeclientset.Interface, obj pkgruntime.Object) (pkgruntime.Object, error) { + deployment := obj.(*extensionsv1.Deployment) + return client.Extensions().Deployments(deployment.Namespace).Update(deployment) +} + +func (a *DeploymentAdapter) ClusterWatch(client kubeclientset.Interface, namespace string, options metav1.ListOptions) (watch.Interface, error) { + return client.Extensions().Deployments(namespace).Watch(options) +} + +func (a *DeploymentAdapter) EquivalentIgnoringSchedule(obj1, obj2 pkgruntime.Object) bool { + deployment1 := obj1.(*extensionsv1.Deployment) + deployment2 := a.Copy(obj2).(*extensionsv1.Deployment) + deployment2.Spec.Replicas = deployment1.Spec.Replicas + return fedutil.DeploymentEquivalent(deployment1, deployment2) +} + +func (a *DeploymentAdapter) NewTestObject(namespace string) pkgruntime.Object { + replicas := int32(3) + zero := int64(0) + return &extensionsv1.Deployment{ + ObjectMeta: metav1.ObjectMeta{ + GenerateName: "test-deployment-", + Namespace: namespace, + }, + Spec: extensionsv1.DeploymentSpec{ + Replicas: &replicas, + Template: apiv1.PodTemplateSpec{ + ObjectMeta: metav1.ObjectMeta{ + Labels: map[string]string{"foo": "bar"}, + }, + Spec: apiv1.PodSpec{ + TerminationGracePeriodSeconds: &zero, + Containers: []apiv1.Container{ + { + Name: "nginx", + Image: "nginx", + }, + }, + }, + }, + }, + } +} diff --git a/federation/pkg/federatedtypes/replicaset.go b/federation/pkg/federatedtypes/replicaset.go index 85f18597a78..35c53306ab0 100644 --- a/federation/pkg/federatedtypes/replicaset.go +++ b/federation/pkg/federatedtypes/replicaset.go @@ -17,12 +17,6 @@ limitations under the License. package federatedtypes import ( - "bytes" - "fmt" - "sort" - "time" - - "github.com/golang/glog" apiv1 "k8s.io/api/core/v1" extensionsv1 "k8s.io/api/extensions/v1beta1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -30,13 +24,8 @@ import ( "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/watch" - fedapi "k8s.io/kubernetes/federation/apis/federation" - fedv1beta1 "k8s.io/kubernetes/federation/apis/federation/v1beta1" federationclientset "k8s.io/kubernetes/federation/client/clientset_generated/federation_clientset" fedutil "k8s.io/kubernetes/federation/pkg/federation-controller/util" - "k8s.io/kubernetes/federation/pkg/federation-controller/util/planner" - "k8s.io/kubernetes/federation/pkg/federation-controller/util/podanalyzer" - "k8s.io/kubernetes/federation/pkg/federation-controller/util/replicapreferences" kubeclientset "k8s.io/kubernetes/pkg/client/clientset_generated/clientset" ) @@ -46,28 +35,35 @@ const ( FedReplicaSetPreferencesAnnotation = "federation.kubernetes.io/replica-set-preferences" ) -type replicaSetUserInfo struct { - scheduleResult (map[string]int64) - fedStatus *extensionsv1.ReplicaSetStatus -} - func init() { RegisterFederatedType(ReplicaSetKind, ReplicaSetControllerName, []schema.GroupVersionResource{extensionsv1.SchemeGroupVersion.WithResource(ReplicaSetControllerName)}, NewReplicaSetAdapter) } type ReplicaSetAdapter struct { - client federationclientset.Interface - defaultPlanner *planner.Planner + *schedulingAdapter + client federationclientset.Interface } func NewReplicaSetAdapter(client federationclientset.Interface) FederatedTypeAdapter { - return &ReplicaSetAdapter{ - client: client, - defaultPlanner: planner.NewPlanner(&fedapi.ReplicaAllocationPreferences{ - Clusters: map[string]fedapi.ClusterPreferences{ - "*": {Weight: 1}, - }, - })} + schedulingAdapter := schedulingAdapter{ + preferencesAnnotationName: FedReplicaSetPreferencesAnnotation, + updateStatusFunc: func(obj pkgruntime.Object, status SchedulingStatus) error { + rs := obj.(*extensionsv1.ReplicaSet) + if status.Replicas != rs.Status.Replicas || status.FullyLabeledReplicas != rs.Status.FullyLabeledReplicas || + status.ReadyReplicas != rs.Status.ReadyReplicas || status.AvailableReplicas != rs.Status.AvailableReplicas { + rs.Status = extensionsv1.ReplicaSetStatus{ + Replicas: status.Replicas, + FullyLabeledReplicas: status.Replicas, + ReadyReplicas: status.ReadyReplicas, + AvailableReplicas: status.AvailableReplicas, + } + _, err := client.Extensions().ReplicaSets(rs.Namespace).UpdateStatus(rs) + return err + } + return nil + }, + } + return &ReplicaSetAdapter{&schedulingAdapter, client} } func (a *ReplicaSetAdapter) Kind() string { @@ -92,9 +88,7 @@ func (a *ReplicaSetAdapter) Copy(obj pkgruntime.Object) pkgruntime.Object { } func (a *ReplicaSetAdapter) Equivalent(obj1, obj2 pkgruntime.Object) bool { - replicaset1 := obj1.(*extensionsv1.ReplicaSet) - replicaset2 := obj2.(*extensionsv1.ReplicaSet) - return fedutil.ObjectMetaAndSpecEquivalent(replicaset1, replicaset2) + return fedutil.ObjectMetaAndSpecEquivalent(obj1, obj2) } func (a *ReplicaSetAdapter) NamespacedName(obj pkgruntime.Object) types.NamespacedName { @@ -158,79 +152,6 @@ func (a *ReplicaSetAdapter) ClusterWatch(client kubeclientset.Interface, namespa return client.Extensions().ReplicaSets(namespace).Watch(options) } -func (a *ReplicaSetAdapter) IsSchedulingAdapter() bool { - return true -} - -func (a *ReplicaSetAdapter) GetSchedule(obj pkgruntime.Object, key string, clusters []*fedv1beta1.Cluster, informer fedutil.FederatedInformer) (*SchedulingInfo, error) { - var clusterNames []string - for _, cluster := range clusters { - clusterNames = append(clusterNames, cluster.Name) - } - - // Schedule the pods across the existing clusters. - replicaSetGetter := func(clusterName, key string) (interface{}, bool, error) { - return informer.GetTargetStore().GetByKey(clusterName, key) - } - podsGetter := func(clusterName string, replicaSet *extensionsv1.ReplicaSet) (*apiv1.PodList, error) { - clientset, err := informer.GetClientsetForCluster(clusterName) - if err != nil { - return nil, err - } - selector, err := metav1.LabelSelectorAsSelector(replicaSet.Spec.Selector) - if err != nil { - return nil, fmt.Errorf("invalid selector: %v", err) - } - return clientset.Core().Pods(replicaSet.ObjectMeta.Namespace).List(metav1.ListOptions{LabelSelector: selector.String()}) - } - current, estimatedCapacity, err := clustersReplicaState(clusterNames, key, replicaSetGetter, podsGetter) - if err != nil { - return nil, err - } - rs := obj.(*extensionsv1.ReplicaSet) - return &SchedulingInfo{ - Schedule: a.schedule(rs, clusterNames, current, estimatedCapacity), - Status: SchedulingStatus{}, - }, nil -} - -func (a *ReplicaSetAdapter) ScheduleObject(cluster *fedv1beta1.Cluster, clusterObj pkgruntime.Object, federationObjCopy pkgruntime.Object, schedulingInfo *SchedulingInfo) (pkgruntime.Object, bool, error) { - rs := federationObjCopy.(*extensionsv1.ReplicaSet) - - replicas, ok := schedulingInfo.Schedule[cluster.Name] - if !ok { - replicas = 0 - } - specReplicas := int32(replicas) - rs.Spec.Replicas = &specReplicas - - if clusterObj != nil { - clusterRs := clusterObj.(*extensionsv1.ReplicaSet) - schedulingInfo.Status.Replicas += clusterRs.Status.Replicas - schedulingInfo.Status.FullyLabeledReplicas += clusterRs.Status.FullyLabeledReplicas - schedulingInfo.Status.ReadyReplicas += clusterRs.Status.ReadyReplicas - schedulingInfo.Status.AvailableReplicas += clusterRs.Status.AvailableReplicas - } - return rs, replicas > 0, nil -} - -func (a *ReplicaSetAdapter) UpdateFederatedStatus(obj pkgruntime.Object, status SchedulingStatus) error { - rs := obj.(*extensionsv1.ReplicaSet) - - if status.Replicas != rs.Status.Replicas || status.FullyLabeledReplicas != rs.Status.FullyLabeledReplicas || - status.ReadyReplicas != rs.Status.ReadyReplicas || status.AvailableReplicas != rs.Status.AvailableReplicas { - rs.Status = extensionsv1.ReplicaSetStatus{ - Replicas: status.Replicas, - FullyLabeledReplicas: status.Replicas, - ReadyReplicas: status.ReadyReplicas, - AvailableReplicas: status.AvailableReplicas, - } - _, err := a.client.Extensions().ReplicaSets(rs.Namespace).UpdateStatus(rs) - return err - } - return nil -} - func (a *ReplicaSetAdapter) EquivalentIgnoringSchedule(obj1, obj2 pkgruntime.Object) bool { replicaset1 := obj1.(*extensionsv1.ReplicaSet) replicaset2 := a.Copy(obj2).(*extensionsv1.ReplicaSet) @@ -238,93 +159,6 @@ func (a *ReplicaSetAdapter) EquivalentIgnoringSchedule(obj1, obj2 pkgruntime.Obj return fedutil.ObjectMetaAndSpecEquivalent(replicaset1, replicaset2) } -func (a *ReplicaSetAdapter) schedule(frs *extensionsv1.ReplicaSet, clusterNames []string, - current map[string]int64, estimatedCapacity map[string]int64) map[string]int64 { - // TODO: integrate real scheduler - - plnr := a.defaultPlanner - frsPref, err := replicapreferences.GetAllocationPreferences(frs, FedReplicaSetPreferencesAnnotation) - if err != nil { - glog.Info("Invalid ReplicaSet specific preference, use default. rs: %v, err: %v", frs, err) - } - if frsPref != nil { // create a new planner if user specified a preference - plnr = planner.NewPlanner(frsPref) - } - - replicas := int64(*frs.Spec.Replicas) - scheduleResult, overflow := plnr.Plan(replicas, clusterNames, current, estimatedCapacity, - frs.Namespace+"/"+frs.Name) - // Ensure that the schedule being returned has scheduling instructions for - // all of the clusters that currently have replicas. A cluster that was in - // the previous schedule but is not in the new schedule should have zero - // replicas. - result := make(map[string]int64) - for clusterName := range current { - result[clusterName] = 0 - } - for clusterName, replicas := range scheduleResult { - result[clusterName] = replicas - } - for clusterName, replicas := range overflow { - result[clusterName] += replicas - } - if glog.V(4) { - buf := bytes.NewBufferString(fmt.Sprintf("Schedule - ReplicaSet: %s/%s\n", frs.Namespace, frs.Name)) - sort.Strings(clusterNames) - for _, clusterName := range clusterNames { - cur := current[clusterName] - target := scheduleResult[clusterName] - fmt.Fprintf(buf, "%s: current: %d target: %d", clusterName, cur, target) - if over, found := overflow[clusterName]; found { - fmt.Fprintf(buf, " overflow: %d", over) - } - if capacity, found := estimatedCapacity[clusterName]; found { - fmt.Fprintf(buf, " capacity: %d", capacity) - } - fmt.Fprintf(buf, "\n") - } - glog.V(4).Infof(buf.String()) - } - return result -} - -// clusterReplicaState returns information about the scheduling state of the pods running in the federated clusters. -func clustersReplicaState( - clusterNames []string, - replicaSetKey string, - replicaSetGetter func(clusterName string, key string) (interface{}, bool, error), - podsGetter func(clusterName string, replicaSet *extensionsv1.ReplicaSet) (*apiv1.PodList, error)) (current map[string]int64, estimatedCapacity map[string]int64, err error) { - - current = make(map[string]int64) - estimatedCapacity = make(map[string]int64) - - for _, clusterName := range clusterNames { - rsObj, exists, err := replicaSetGetter(clusterName, replicaSetKey) - if err != nil { - return nil, nil, err - } - if !exists { - continue - } - rs := rsObj.(*extensionsv1.ReplicaSet) - if int32(*rs.Spec.Replicas) == rs.Status.ReadyReplicas { - current[clusterName] = int64(rs.Status.ReadyReplicas) - } else { - pods, err := podsGetter(clusterName, rs) - if err != nil { - return nil, nil, err - } - podStatus := podanalyzer.AnalyzePods(pods, time.Now()) - current[clusterName] = int64(podStatus.RunningAndReady) // include pending as well? - unschedulable := int64(podStatus.Unschedulable) - if unschedulable > 0 { - estimatedCapacity[clusterName] = int64(*rs.Spec.Replicas) - unschedulable - } - } - } - return current, estimatedCapacity, nil -} - func (a *ReplicaSetAdapter) NewTestObject(namespace string) pkgruntime.Object { replicas := int32(3) zero := int64(0) diff --git a/federation/pkg/federatedtypes/scheduling.go b/federation/pkg/federatedtypes/scheduling.go index c5d0b93a845..7183479c295 100644 --- a/federation/pkg/federatedtypes/scheduling.go +++ b/federation/pkg/federatedtypes/scheduling.go @@ -17,15 +17,31 @@ limitations under the License. package federatedtypes import ( + "bytes" + "fmt" + "reflect" + "sort" + "time" + + apiv1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/meta" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" pkgruntime "k8s.io/apimachinery/pkg/runtime" + fedapi "k8s.io/kubernetes/federation/apis/federation" federationapi "k8s.io/kubernetes/federation/apis/federation/v1beta1" fedutil "k8s.io/kubernetes/federation/pkg/federation-controller/util" + "k8s.io/kubernetes/federation/pkg/federation-controller/util/planner" + "k8s.io/kubernetes/federation/pkg/federation-controller/util/podanalyzer" + "k8s.io/kubernetes/federation/pkg/federation-controller/util/replicapreferences" + + "github.com/golang/glog" ) // SchedulingStatus contains the status of the objects that are being // scheduled into joined clusters. type SchedulingStatus struct { Replicas int32 + UpdatedReplicas int32 FullyLabeledReplicas int32 ReadyReplicas int32 AvailableReplicas int32 @@ -49,3 +65,171 @@ type SchedulingAdapter interface { // equivalent ignoring differences due to scheduling. EquivalentIgnoringSchedule(obj1, obj2 pkgruntime.Object) bool } + +// schedulingAdapter is meant to be embedded in other type adapters that require +// workload scheduling. +type schedulingAdapter struct { + preferencesAnnotationName string + updateStatusFunc func(pkgruntime.Object, SchedulingStatus) error +} + +func (a *schedulingAdapter) IsSchedulingAdapter() bool { + return true +} + +func (a *schedulingAdapter) GetSchedule(obj pkgruntime.Object, key string, clusters []*federationapi.Cluster, informer fedutil.FederatedInformer) (*SchedulingInfo, error) { + var clusterNames []string + for _, cluster := range clusters { + clusterNames = append(clusterNames, cluster.Name) + } + + // Schedule the pods across the existing clusters. + objectGetter := func(clusterName, key string) (interface{}, bool, error) { + return informer.GetTargetStore().GetByKey(clusterName, key) + } + podsGetter := func(clusterName string, obj pkgruntime.Object) (*apiv1.PodList, error) { + clientset, err := informer.GetClientsetForCluster(clusterName) + if err != nil { + return nil, err + } + selectorObj := reflect.ValueOf(obj).Elem().FieldByName("Spec").FieldByName("Selector").Interface().(*metav1.LabelSelector) + selector, err := metav1.LabelSelectorAsSelector(selectorObj) + if err != nil { + return nil, fmt.Errorf("invalid selector: %v", err) + } + metadata, err := meta.Accessor(obj) + if err != nil { + return nil, err + } + return clientset.Core().Pods(metadata.GetNamespace()).List(metav1.ListOptions{LabelSelector: selector.String()}) + } + currentReplicasPerCluster, estimatedCapacity, err := clustersReplicaState(clusterNames, key, objectGetter, podsGetter) + if err != nil { + return nil, err + } + + fedPref, err := replicapreferences.GetAllocationPreferences(obj, a.preferencesAnnotationName) + if err != nil { + glog.Info("Invalid workload-type specific preference, using default. object: %v, err: %v", obj, err) + } + if fedPref == nil { + fedPref = &fedapi.ReplicaAllocationPreferences{ + Clusters: map[string]fedapi.ClusterPreferences{ + "*": {Weight: 1}, + }, + } + } + + plnr := planner.NewPlanner(fedPref) + + return &SchedulingInfo{ + Schedule: schedule(plnr, obj, key, clusterNames, currentReplicasPerCluster, estimatedCapacity), + Status: SchedulingStatus{}, + }, nil +} + +func (a *schedulingAdapter) ScheduleObject(cluster *federationapi.Cluster, clusterObj pkgruntime.Object, federationObjCopy pkgruntime.Object, schedulingInfo *SchedulingInfo) (pkgruntime.Object, bool, error) { + replicas, ok := schedulingInfo.Schedule[cluster.Name] + if !ok { + replicas = 0 + } + + specReplicas := int32(replicas) + reflect.ValueOf(federationObjCopy).Elem().FieldByName("Spec").FieldByName("Replicas").Set(reflect.ValueOf(&specReplicas)) + + if clusterObj != nil { + schedulingStatusVal := reflect.ValueOf(schedulingInfo).Elem().FieldByName("Status") + objStatusVal := reflect.ValueOf(clusterObj).Elem().FieldByName("Status") + for i := 0; i < schedulingStatusVal.NumField(); i++ { + schedulingStatusField := schedulingStatusVal.Field(i) + schedulingStatusFieldName := schedulingStatusVal.Type().Field(i).Name + objStatusField := objStatusVal.FieldByName(schedulingStatusFieldName) + if objStatusField.IsValid() { + current := schedulingStatusField.Int() + additional := objStatusField.Int() + schedulingStatusField.SetInt(current + additional) + } + } + } + return federationObjCopy, replicas > 0, nil +} + +func (a *schedulingAdapter) UpdateFederatedStatus(obj pkgruntime.Object, status SchedulingStatus) error { + return a.updateStatusFunc(obj, status) +} + +func schedule(planner *planner.Planner, obj pkgruntime.Object, key string, clusterNames []string, currentReplicasPerCluster map[string]int64, estimatedCapacity map[string]int64) map[string]int64 { + // TODO: integrate real scheduler + replicas := reflect.ValueOf(obj).Elem().FieldByName("Spec").FieldByName("Replicas").Elem().Int() + scheduleResult, overflow := planner.Plan(replicas, clusterNames, currentReplicasPerCluster, estimatedCapacity, key) + + // Ensure that all current clusters end up in the scheduling result. + result := make(map[string]int64) + for clusterName := range currentReplicasPerCluster { + result[clusterName] = 0 + } + + for clusterName, replicas := range scheduleResult { + result[clusterName] = replicas + } + for clusterName, replicas := range overflow { + result[clusterName] += replicas + } + + if glog.V(4) { + buf := bytes.NewBufferString(fmt.Sprintf("Schedule - %q\n", key)) + sort.Strings(clusterNames) + for _, clusterName := range clusterNames { + cur := currentReplicasPerCluster[clusterName] + target := scheduleResult[clusterName] + fmt.Fprintf(buf, "%s: current: %d target: %d", clusterName, cur, target) + if over, found := overflow[clusterName]; found { + fmt.Fprintf(buf, " overflow: %d", over) + } + if capacity, found := estimatedCapacity[clusterName]; found { + fmt.Fprintf(buf, " capacity: %d", capacity) + } + fmt.Fprintf(buf, "\n") + } + glog.V(4).Infof(buf.String()) + } + return result +} + +// clusterReplicaState returns information about the scheduling state of the pods running in the federated clusters. +func clustersReplicaState( + clusterNames []string, + key string, + objectGetter func(clusterName string, key string) (interface{}, bool, error), + podsGetter func(clusterName string, obj pkgruntime.Object) (*apiv1.PodList, error)) (currentReplicasPerCluster map[string]int64, estimatedCapacity map[string]int64, err error) { + + currentReplicasPerCluster = make(map[string]int64) + estimatedCapacity = make(map[string]int64) + + for _, clusterName := range clusterNames { + obj, exists, err := objectGetter(clusterName, key) + if err != nil { + return nil, nil, err + } + if !exists { + continue + } + replicas := reflect.ValueOf(obj).Elem().FieldByName("Spec").FieldByName("Replicas").Elem().Int() + readyReplicas := reflect.ValueOf(obj).Elem().FieldByName("Status").FieldByName("ReadyReplicas").Int() + if replicas == readyReplicas { + currentReplicasPerCluster[clusterName] = readyReplicas + } else { + pods, err := podsGetter(clusterName, obj.(pkgruntime.Object)) + if err != nil { + return nil, nil, err + } + podStatus := podanalyzer.AnalyzePods(pods, time.Now()) + currentReplicasPerCluster[clusterName] = int64(podStatus.RunningAndReady) // include pending as well? + unschedulable := int64(podStatus.Unschedulable) + if unschedulable > 0 { + estimatedCapacity[clusterName] = replicas - unschedulable + } + } + } + return currentReplicasPerCluster, estimatedCapacity, nil +} diff --git a/federation/pkg/federatedtypes/replicaset_test.go b/federation/pkg/federatedtypes/scheduling_test.go similarity index 90% rename from federation/pkg/federatedtypes/replicaset_test.go rename to federation/pkg/federatedtypes/scheduling_test.go index 271612039ba..d938e525a56 100644 --- a/federation/pkg/federatedtypes/replicaset_test.go +++ b/federation/pkg/federatedtypes/scheduling_test.go @@ -24,21 +24,22 @@ import ( apiv1 "k8s.io/api/core/v1" extensionsv1 "k8s.io/api/extensions/v1beta1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + pkgruntime "k8s.io/apimachinery/pkg/runtime" "github.com/stretchr/testify/assert" ) func TestClusterReplicaState(t *testing.T) { - uncalledPodsGetter := func(clusterName string, replicaSet *extensionsv1.ReplicaSet) (*apiv1.PodList, error) { - t.Fatal("podsGetter should not be called when replica sets are all ready.") + uncalledPodsGetter := func(clusterName string, obj pkgruntime.Object) (*apiv1.PodList, error) { + t.Fatal("podsGetter should not be called when workload objects are all ready.") return nil, nil } - podsByReplicaSet := make(map[*extensionsv1.ReplicaSet][]*apiv1.Pod) - podsGetter := func(clusterName string, replicaSet *extensionsv1.ReplicaSet) (*apiv1.PodList, error) { - pods, ok := podsByReplicaSet[replicaSet] + podsByReplicaSet := make(map[pkgruntime.Object][]*apiv1.Pod) + podsGetter := func(clusterName string, obj pkgruntime.Object) (*apiv1.PodList, error) { + pods, ok := podsByReplicaSet[obj] if !ok { - t.Fatalf("No pods found in test data for replica set named %v", replicaSet.Name) + t.Fatalf("No pods found in test data for replica set %v", obj) return nil, fmt.Errorf("Not found") } var podListPods []apiv1.Pod @@ -64,7 +65,7 @@ func TestClusterReplicaState(t *testing.T) { rs2Replicas int32 rs1ReadyReplicas int32 rs2ReadyReplicas int32 - podsGetter func(clusterName string, replicaSet *extensionsv1.ReplicaSet) (*apiv1.PodList, error) + podsGetter func(clusterName string, obj pkgruntime.Object) (*apiv1.PodList, error) pod1Phase apiv1.PodPhase pod1Condition apiv1.PodCondition pod2Phase apiv1.PodPhase diff --git a/federation/pkg/federation-controller/BUILD b/federation/pkg/federation-controller/BUILD index 310b2860242..1c5fd2d39bd 100644 --- a/federation/pkg/federation-controller/BUILD +++ b/federation/pkg/federation-controller/BUILD @@ -25,7 +25,6 @@ filegroup( srcs = [ ":package-srcs", "//federation/pkg/federation-controller/cluster:all-srcs", - "//federation/pkg/federation-controller/deployment:all-srcs", "//federation/pkg/federation-controller/ingress:all-srcs", "//federation/pkg/federation-controller/namespace:all-srcs", "//federation/pkg/federation-controller/service:all-srcs", diff --git a/federation/pkg/federation-controller/deployment/BUILD b/federation/pkg/federation-controller/deployment/BUILD deleted file mode 100644 index 207236f2eab..00000000000 --- a/federation/pkg/federation-controller/deployment/BUILD +++ /dev/null @@ -1,76 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -licenses(["notice"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", - "go_test", -) - -go_library( - name = "go_default_library", - srcs = ["deploymentcontroller.go"], - tags = ["automanaged"], - deps = [ - "//federation/apis/federation:go_default_library", - "//federation/apis/federation/v1beta1:go_default_library", - "//federation/client/clientset_generated/federation_clientset:go_default_library", - "//federation/pkg/federation-controller/util:go_default_library", - "//federation/pkg/federation-controller/util/deletionhelper:go_default_library", - "//federation/pkg/federation-controller/util/eventsink:go_default_library", - "//federation/pkg/federation-controller/util/planner:go_default_library", - "//federation/pkg/federation-controller/util/replicapreferences:go_default_library", - "//pkg/api:go_default_library", - "//pkg/client/clientset_generated/clientset:go_default_library", - "//pkg/controller:go_default_library", - "//vendor/github.com/golang/glog: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: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/tools/cache:go_default_library", - "//vendor/k8s.io/client-go/tools/record:go_default_library", - "//vendor/k8s.io/client-go/util/flowcontrol:go_default_library", - "//vendor/k8s.io/client-go/util/workqueue:go_default_library", - ], -) - -go_test( - name = "go_default_test", - srcs = ["deploymentcontroller_test.go"], - library = ":go_default_library", - tags = ["automanaged"], - deps = [ - "//federation/apis/federation/v1beta1:go_default_library", - "//federation/client/clientset_generated/federation_clientset/fake:go_default_library", - "//federation/pkg/federation-controller/util/test:go_default_library", - "//pkg/client/clientset_generated/clientset:go_default_library", - "//pkg/client/clientset_generated/clientset/fake: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/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/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/federation/pkg/federation-controller/deployment/deploymentcontroller.go b/federation/pkg/federation-controller/deployment/deploymentcontroller.go deleted file mode 100644 index ccb1e13a480..00000000000 --- a/federation/pkg/federation-controller/deployment/deploymentcontroller.go +++ /dev/null @@ -1,649 +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 deployment - -import ( - "bytes" - "fmt" - "sort" - "time" - - "github.com/golang/glog" - - apiv1 "k8s.io/api/core/v1" - clientv1 "k8s.io/api/core/v1" - extensionsv1 "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" - "k8s.io/apimachinery/pkg/runtime/schema" - "k8s.io/apimachinery/pkg/util/wait" - "k8s.io/apimachinery/pkg/watch" - "k8s.io/client-go/tools/cache" - "k8s.io/client-go/tools/record" - "k8s.io/client-go/util/flowcontrol" - "k8s.io/client-go/util/workqueue" - fed "k8s.io/kubernetes/federation/apis/federation" - fedv1 "k8s.io/kubernetes/federation/apis/federation/v1beta1" - fedclientset "k8s.io/kubernetes/federation/client/clientset_generated/federation_clientset" - fedutil "k8s.io/kubernetes/federation/pkg/federation-controller/util" - "k8s.io/kubernetes/federation/pkg/federation-controller/util/deletionhelper" - "k8s.io/kubernetes/federation/pkg/federation-controller/util/eventsink" - "k8s.io/kubernetes/federation/pkg/federation-controller/util/planner" - "k8s.io/kubernetes/federation/pkg/federation-controller/util/replicapreferences" - "k8s.io/kubernetes/pkg/api" - kubeclientset "k8s.io/kubernetes/pkg/client/clientset_generated/clientset" - "k8s.io/kubernetes/pkg/controller" -) - -const ( - FedDeploymentPreferencesAnnotation = "federation.kubernetes.io/deployment-preferences" - allClustersKey = "THE_ALL_CLUSTER_KEY" - UserAgentName = "federation-deployment-controller" - ControllerName = "deployments" -) - -var ( - RequiredResources = []schema.GroupVersionResource{extensionsv1.SchemeGroupVersion.WithResource("deployments")} - deploymentReviewDelay = 10 * time.Second - clusterAvailableDelay = 20 * time.Second - clusterUnavailableDelay = 60 * time.Second - allDeploymentReviewDelay = 2 * time.Minute - updateTimeout = 30 * time.Second -) - -type DeploymentController struct { - fedClient fedclientset.Interface - - deploymentController cache.Controller - deploymentStore cache.Store - - fedDeploymentInformer fedutil.FederatedInformer - fedPodInformer fedutil.FederatedInformer - - deploymentDeliverer *fedutil.DelayingDeliverer - clusterDeliverer *fedutil.DelayingDeliverer - deploymentWorkQueue workqueue.Interface - // For updating members of federation. - fedUpdater fedutil.FederatedUpdater - deploymentBackoff *flowcontrol.Backoff - eventRecorder record.EventRecorder - - deletionHelper *deletionhelper.DeletionHelper - - defaultPlanner *planner.Planner -} - -// NewDeploymentController returns a new deployment controller -func NewDeploymentController(federationClient fedclientset.Interface) *DeploymentController { - broadcaster := record.NewBroadcaster() - broadcaster.StartRecordingToSink(eventsink.NewFederatedEventSink(federationClient)) - recorder := broadcaster.NewRecorder(api.Scheme, clientv1.EventSource{Component: UserAgentName}) - - fdc := &DeploymentController{ - fedClient: federationClient, - deploymentDeliverer: fedutil.NewDelayingDeliverer(), - clusterDeliverer: fedutil.NewDelayingDeliverer(), - deploymentWorkQueue: workqueue.New(), - deploymentBackoff: flowcontrol.NewBackOff(5*time.Second, time.Minute), - defaultPlanner: planner.NewPlanner(&fed.ReplicaAllocationPreferences{ - Clusters: map[string]fed.ClusterPreferences{ - "*": {Weight: 1}, - }, - }), - eventRecorder: recorder, - } - - deploymentFedInformerFactory := func(cluster *fedv1.Cluster, clientset kubeclientset.Interface) (cache.Store, cache.Controller) { - return cache.NewInformer( - &cache.ListWatch{ - ListFunc: func(options metav1.ListOptions) (runtime.Object, error) { - return clientset.Extensions().Deployments(metav1.NamespaceAll).List(options) - }, - WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) { - return clientset.Extensions().Deployments(metav1.NamespaceAll).Watch(options) - }, - }, - &extensionsv1.Deployment{}, - controller.NoResyncPeriodFunc(), - fedutil.NewTriggerOnAllChanges( - func(obj runtime.Object) { fdc.deliverLocalDeployment(obj, deploymentReviewDelay) }, - ), - ) - } - clusterLifecycle := fedutil.ClusterLifecycleHandlerFuncs{ - ClusterAvailable: func(cluster *fedv1.Cluster) { - fdc.clusterDeliverer.DeliverAfter(allClustersKey, nil, clusterAvailableDelay) - }, - ClusterUnavailable: func(cluster *fedv1.Cluster, _ []interface{}) { - fdc.clusterDeliverer.DeliverAfter(allClustersKey, nil, clusterUnavailableDelay) - }, - } - fdc.fedDeploymentInformer = fedutil.NewFederatedInformer(federationClient, deploymentFedInformerFactory, &clusterLifecycle) - - podFedInformerFactory := func(cluster *fedv1.Cluster, clientset kubeclientset.Interface) (cache.Store, cache.Controller) { - return cache.NewInformer( - &cache.ListWatch{ - ListFunc: func(options metav1.ListOptions) (runtime.Object, error) { - return clientset.Core().Pods(metav1.NamespaceAll).List(options) - }, - WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) { - return clientset.Core().Pods(metav1.NamespaceAll).Watch(options) - }, - }, - &apiv1.Pod{}, - controller.NoResyncPeriodFunc(), - fedutil.NewTriggerOnAllChanges( - func(obj runtime.Object) { - fdc.clusterDeliverer.DeliverAfter(allClustersKey, nil, allDeploymentReviewDelay) - }, - ), - ) - } - fdc.fedPodInformer = fedutil.NewFederatedInformer(federationClient, podFedInformerFactory, &fedutil.ClusterLifecycleHandlerFuncs{}) - - fdc.deploymentStore, fdc.deploymentController = cache.NewInformer( - &cache.ListWatch{ - ListFunc: func(options metav1.ListOptions) (runtime.Object, error) { - return fdc.fedClient.Extensions().Deployments(metav1.NamespaceAll).List(options) - }, - WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) { - return fdc.fedClient.Extensions().Deployments(metav1.NamespaceAll).Watch(options) - }, - }, - &extensionsv1.Deployment{}, - controller.NoResyncPeriodFunc(), - fedutil.NewTriggerOnMetaAndSpecChanges( - func(obj runtime.Object) { fdc.deliverFedDeploymentObj(obj, deploymentReviewDelay) }, - ), - ) - - fdc.fedUpdater = fedutil.NewFederatedUpdater(fdc.fedDeploymentInformer, "deployment", updateTimeout, fdc.eventRecorder, - func(client kubeclientset.Interface, obj runtime.Object) error { - rs := obj.(*extensionsv1.Deployment) - _, err := client.Extensions().Deployments(rs.Namespace).Create(rs) - return err - }, - func(client kubeclientset.Interface, obj runtime.Object) error { - rs := obj.(*extensionsv1.Deployment) - _, err := client.Extensions().Deployments(rs.Namespace).Update(rs) - return err - }, - func(client kubeclientset.Interface, obj runtime.Object) error { - rs := obj.(*extensionsv1.Deployment) - orphanDependents := false - err := client.Extensions().Deployments(rs.Namespace).Delete(rs.Name, &metav1.DeleteOptions{OrphanDependents: &orphanDependents}) - return err - }) - - fdc.deletionHelper = deletionhelper.NewDeletionHelper( - fdc.updateDeployment, - // objNameFunc - func(obj runtime.Object) string { - deployment := obj.(*extensionsv1.Deployment) - return fmt.Sprintf("%s/%s", deployment.Namespace, deployment.Name) - }, - fdc.fedDeploymentInformer, - fdc.fedUpdater, - ) - - return fdc -} - -// Sends the given updated object to apiserver. -// Assumes that the given object is a deployment. -func (fdc *DeploymentController) updateDeployment(obj runtime.Object) (runtime.Object, error) { - deployment := obj.(*extensionsv1.Deployment) - return fdc.fedClient.Extensions().Deployments(deployment.Namespace).Update(deployment) -} - -func (fdc *DeploymentController) Run(workers int, stopCh <-chan struct{}) { - go fdc.deploymentController.Run(stopCh) - fdc.fedDeploymentInformer.Start() - fdc.fedPodInformer.Start() - - fdc.deploymentDeliverer.StartWithHandler(func(item *fedutil.DelayingDelivererItem) { - fdc.deploymentWorkQueue.Add(item.Key) - }) - fdc.clusterDeliverer.StartWithHandler(func(_ *fedutil.DelayingDelivererItem) { - fdc.reconcileDeploymentsOnClusterChange() - }) - - // Wait until the cluster is synced to prevent the update storm at the very beginning. - for !fdc.isSynced() { - time.Sleep(5 * time.Millisecond) - glog.V(3).Infof("Waiting for controller to sync up") - } - - for i := 0; i < workers; i++ { - go wait.Until(fdc.worker, time.Second, stopCh) - } - - fedutil.StartBackoffGC(fdc.deploymentBackoff, stopCh) - - <-stopCh - glog.Infof("Shutting down DeploymentController") - fdc.deploymentDeliverer.Stop() - fdc.clusterDeliverer.Stop() - fdc.deploymentWorkQueue.ShutDown() - fdc.fedDeploymentInformer.Stop() - fdc.fedPodInformer.Stop() -} - -func (fdc *DeploymentController) isSynced() bool { - if !fdc.fedDeploymentInformer.ClustersSynced() { - glog.V(2).Infof("Cluster list not synced") - return false - } - clustersFromDeps, err := fdc.fedDeploymentInformer.GetReadyClusters() - if err != nil { - glog.Errorf("Failed to get ready clusters: %v", err) - return false - } - if !fdc.fedDeploymentInformer.GetTargetStore().ClustersSynced(clustersFromDeps) { - return false - } - - if !fdc.fedPodInformer.ClustersSynced() { - glog.V(2).Infof("Cluster list not synced") - return false - } - clustersFromPods, err := fdc.fedPodInformer.GetReadyClusters() - if err != nil { - glog.Errorf("Failed to get ready clusters: %v", err) - return false - } - - // This also checks whether podInformer and deploymentInformer have the - // same cluster lists. - if !fdc.fedPodInformer.GetTargetStore().ClustersSynced(clustersFromDeps) { - glog.V(2).Infof("Pod informer not synced") - return false - } - if !fdc.fedPodInformer.GetTargetStore().ClustersSynced(clustersFromPods) { - glog.V(2).Infof("Pod informer not synced") - return false - } - - if !fdc.deploymentController.HasSynced() { - glog.V(2).Infof("federation deployment list not synced") - return false - } - return true -} - -func (fdc *DeploymentController) deliverLocalDeployment(obj interface{}, duration time.Duration) { - key, err := controller.KeyFunc(obj) - if err != nil { - glog.Errorf("Couldn't get key for object %v: %v", obj, err) - return - } - _, exists, err := fdc.deploymentStore.GetByKey(key) - if err != nil { - glog.Errorf("Couldn't get federation deployment %v: %v", key, err) - return - } - if exists { // ignore deployments exists only in local k8s - fdc.deliverDeploymentByKey(key, duration, false) - } -} - -func (fdc *DeploymentController) deliverFedDeploymentObj(obj interface{}, delay time.Duration) { - key, err := controller.KeyFunc(obj) - if err != nil { - glog.Errorf("Couldn't get key for object %+v: %v", obj, err) - return - } - fdc.deliverDeploymentByKey(key, delay, false) -} - -func (fdc *DeploymentController) deliverDeploymentByKey(key string, delay time.Duration, failed bool) { - if failed { - fdc.deploymentBackoff.Next(key, time.Now()) - delay = delay + fdc.deploymentBackoff.Get(key) - } else { - fdc.deploymentBackoff.Reset(key) - } - fdc.deploymentDeliverer.DeliverAfter(key, nil, delay) -} - -func (fdc *DeploymentController) worker() { - for { - item, quit := fdc.deploymentWorkQueue.Get() - if quit { - return - } - key := item.(string) - status, err := fdc.reconcileDeployment(key) - fdc.deploymentWorkQueue.Done(item) - if err != nil { - glog.Errorf("Error syncing cluster controller: %v", err) - fdc.deliverDeploymentByKey(key, 0, true) - } else { - switch status { - case statusAllOk: - break - case statusError: - fdc.deliverDeploymentByKey(key, 0, true) - case statusNeedRecheck: - fdc.deliverDeploymentByKey(key, deploymentReviewDelay, false) - case statusNotSynced: - fdc.deliverDeploymentByKey(key, clusterAvailableDelay, false) - default: - glog.Errorf("Unhandled reconciliation status: %s", status) - fdc.deliverDeploymentByKey(key, deploymentReviewDelay, false) - } - } - } -} - -type podAnalysisResult struct { - // Total number of pods created. - total int - // Number of pods that are running and ready. - runningAndReady int - // Number of pods that have been in unschedulable state for UnshedulableThreshold seconds. - unschedulable int - - // TODO: Handle other scenarios like pod waiting too long for scheduler etc. -} - -const ( - // TODO: make it configurable - unschedulableThreshold = 60 * time.Second -) - -// A function that calculates how many pods from the list are in one of -// the meaningful (from the replica set perspective) states. This function is -// a temporary workaround against the current lack of ownerRef in pods. -// TODO(perotinus): Unify this with the ReplicaSet controller. -func analyzePods(selectorv1 *metav1.LabelSelector, allPods []fedutil.FederatedObject, currentTime time.Time) (map[string]podAnalysisResult, error) { - selector, err := metav1.LabelSelectorAsSelector(selectorv1) - if err != nil { - return nil, fmt.Errorf("invalid selector: %v", err) - } - result := make(map[string]podAnalysisResult) - - for _, fedObject := range allPods { - pod, isPod := fedObject.Object.(*apiv1.Pod) - if !isPod { - return nil, fmt.Errorf("invalid arg content - not a *pod") - } - if !selector.Empty() && selector.Matches(labels.Set(pod.Labels)) { - status := result[fedObject.ClusterName] - status.total++ - for _, condition := range pod.Status.Conditions { - if pod.Status.Phase == apiv1.PodRunning { - if condition.Type == apiv1.PodReady { - status.runningAndReady++ - } - } else { - if condition.Type == apiv1.PodScheduled && - condition.Status == apiv1.ConditionFalse && - condition.Reason == apiv1.PodReasonUnschedulable && - condition.LastTransitionTime.Add(unschedulableThreshold).Before(currentTime) { - - status.unschedulable++ - } - } - } - result[fedObject.ClusterName] = status - } - } - return result, nil -} - -func (fdc *DeploymentController) schedule(fd *extensionsv1.Deployment, clusters []*fedv1.Cluster, - current map[string]int64, estimatedCapacity map[string]int64) map[string]int64 { - // TODO: integrate real scheduler - - plannerToBeUsed := fdc.defaultPlanner - fdPref, err := replicapreferences.GetAllocationPreferences(fd, FedDeploymentPreferencesAnnotation) - if err != nil { - glog.Info("Invalid Deployment specific preference, use default. deployment: %v, err: %v", fd.Name, err) - } - if fdPref != nil { // create a new planner if user specified a preference - plannerToBeUsed = planner.NewPlanner(fdPref) - } - replicas := int64(0) - if fd.Spec.Replicas != nil { - replicas = int64(*fd.Spec.Replicas) - } - var clusterNames []string - for _, cluster := range clusters { - clusterNames = append(clusterNames, cluster.Name) - } - scheduleResult, overflow := plannerToBeUsed.Plan(replicas, clusterNames, current, estimatedCapacity, - fd.Namespace+"/"+fd.Name) - // make sure the result contains all clusters that currently have some replicas. - result := make(map[string]int64) - for clusterName := range current { - result[clusterName] = 0 - } - for clusterName, replicas := range scheduleResult { - result[clusterName] = replicas - } - for clusterName, replicas := range overflow { - result[clusterName] += replicas - } - if glog.V(4) { - buf := bytes.NewBufferString(fmt.Sprintf("Schedule - Deployment: %s/%s\n", fd.Namespace, fd.Name)) - sort.Strings(clusterNames) - for _, clusterName := range clusterNames { - cur := current[clusterName] - target := scheduleResult[clusterName] - fmt.Fprintf(buf, "%s: current: %d target: %d", clusterName, cur, target) - if over, found := overflow[clusterName]; found { - fmt.Fprintf(buf, " overflow: %d", over) - } - if capacity, found := estimatedCapacity[clusterName]; found { - fmt.Fprintf(buf, " capacity: %d", capacity) - } - fmt.Fprintf(buf, "\n") - } - glog.V(4).Infof(buf.String()) - } - return result -} - -type reconciliationStatus string - -const ( - statusAllOk = reconciliationStatus("ALL_OK") - statusNeedRecheck = reconciliationStatus("RECHECK") - statusError = reconciliationStatus("ERROR") - statusNotSynced = reconciliationStatus("NOSYNC") -) - -func (fdc *DeploymentController) reconcileDeployment(key string) (reconciliationStatus, error) { - if !fdc.isSynced() { - return statusNotSynced, nil - } - - glog.V(4).Infof("Start reconcile deployment %q", key) - startTime := time.Now() - defer glog.V(4).Infof("Finished reconcile deployment %q (%v)", key, time.Now().Sub(startTime)) - - objFromStore, exists, err := fdc.deploymentStore.GetByKey(key) - if err != nil { - return statusError, err - } - if !exists { - // don't delete local deployments for now. Do not reconcile it anymore. - return statusAllOk, nil - } - obj, err := api.Scheme.DeepCopy(objFromStore) - fd, ok := obj.(*extensionsv1.Deployment) - if err != nil || !ok { - glog.Errorf("Error in retrieving obj from store: %v, %v", ok, err) - return statusError, err - } - - if fd.DeletionTimestamp != nil { - if err := fdc.delete(fd); err != nil { - glog.Errorf("Failed to delete %s: %v", fd.Name, err) - fdc.eventRecorder.Eventf(fd, api.EventTypeWarning, "DeleteFailed", - "Deployment delete failed: %v", err) - return statusError, err - } - return statusAllOk, nil - } - - glog.V(3).Infof("Ensuring delete object from underlying clusters finalizer for deployment: %s", - fd.Name) - // Add the required finalizers before creating a deployment in underlying clusters. - updatedDeploymentObj, err := fdc.deletionHelper.EnsureFinalizers(fd) - if err != nil { - glog.Errorf("Failed to ensure delete object from underlying clusters finalizer in deployment %s: %v", - fd.Name, err) - return statusError, err - } - fd = updatedDeploymentObj.(*extensionsv1.Deployment) - - glog.V(3).Infof("Syncing deployment %s in underlying clusters", fd.Name) - - clusters, err := fdc.fedDeploymentInformer.GetReadyClusters() - if err != nil { - return statusError, err - } - - // collect current status and do schedule - allPods, err := fdc.fedPodInformer.GetTargetStore().List() - if err != nil { - return statusError, err - } - podStatus, err := analyzePods(fd.Spec.Selector, allPods, time.Now()) - current := make(map[string]int64) - estimatedCapacity := make(map[string]int64) - for _, cluster := range clusters { - ldObj, exists, err := fdc.fedDeploymentInformer.GetTargetStore().GetByKey(cluster.Name, key) - if err != nil { - return statusError, err - } - if exists { - ld := ldObj.(*extensionsv1.Deployment) - current[cluster.Name] = int64(podStatus[cluster.Name].runningAndReady) // include pending as well? - unschedulable := int64(podStatus[cluster.Name].unschedulable) - if unschedulable > 0 { - estimatedCapacity[cluster.Name] = int64(*ld.Spec.Replicas) - unschedulable - } - } - } - - scheduleResult := fdc.schedule(fd, clusters, current, estimatedCapacity) - - glog.V(4).Infof("Start syncing local deployment %s: %v", key, scheduleResult) - - fedStatus := extensionsv1.DeploymentStatus{ObservedGeneration: fd.Generation} - operations := make([]fedutil.FederatedOperation, 0) - for clusterName, replicas := range scheduleResult { - - ldObj, exists, err := fdc.fedDeploymentInformer.GetTargetStore().GetByKey(clusterName, key) - if err != nil { - return statusError, err - } - - // The object can be modified. - ld := fedutil.DeepCopyDeployment(fd) - specReplicas := int32(replicas) - ld.Spec.Replicas = &specReplicas - - if !exists { - if replicas > 0 { - operations = append(operations, fedutil.FederatedOperation{ - Type: fedutil.OperationTypeAdd, - Obj: ld, - ClusterName: clusterName, - Key: key, - }) - } - } else { - // TODO: Update only one deployment at a time if update strategy is rolling update. - - currentLd := ldObj.(*extensionsv1.Deployment) - // Update existing replica set, if needed. - if !fedutil.DeploymentEquivalent(ld, currentLd) { - operations = append(operations, fedutil.FederatedOperation{ - Type: fedutil.OperationTypeUpdate, - Obj: ld, - ClusterName: clusterName, - Key: key, - }) - glog.Infof("Updating %s in %s", currentLd.Name, clusterName) - } - fedStatus.Replicas += currentLd.Status.Replicas - fedStatus.AvailableReplicas += currentLd.Status.AvailableReplicas - fedStatus.UnavailableReplicas += currentLd.Status.UnavailableReplicas - fedStatus.ReadyReplicas += currentLd.Status.ReadyReplicas - } - } - if fedStatus.Replicas != fd.Status.Replicas || - fedStatus.AvailableReplicas != fd.Status.AvailableReplicas || - fedStatus.UnavailableReplicas != fd.Status.UnavailableReplicas || - fedStatus.ReadyReplicas != fd.Status.ReadyReplicas { - fd.Status = fedStatus - _, err = fdc.fedClient.Extensions().Deployments(fd.Namespace).UpdateStatus(fd) - if err != nil { - return statusError, err - } - } - - if len(operations) == 0 { - // Everything is in order - return statusAllOk, nil - } - err = fdc.fedUpdater.Update(operations) - if err != nil { - glog.Errorf("Failed to execute updates for %s: %v", key, err) - return statusError, err - } - - // Some operations were made, reconcile after a while. - return statusNeedRecheck, nil -} - -func (fdc *DeploymentController) reconcileDeploymentsOnClusterChange() { - if !fdc.isSynced() { - fdc.clusterDeliverer.DeliverAfter(allClustersKey, nil, clusterAvailableDelay) - } - deps := fdc.deploymentStore.List() - for _, dep := range deps { - key, _ := controller.KeyFunc(dep) - fdc.deliverDeploymentByKey(key, 0, false) - } -} - -// delete deletes the given deployment or returns error if the deletion was not complete. -func (fdc *DeploymentController) delete(deployment *extensionsv1.Deployment) error { - glog.V(3).Infof("Handling deletion of deployment: %v", *deployment) - _, err := fdc.deletionHelper.HandleObjectInUnderlyingClusters(deployment) - if err != nil { - return err - } - - err = fdc.fedClient.Extensions().Deployments(deployment.Namespace).Delete(deployment.Name, nil) - if err != nil { - // Its all good if the error is not found error. That means it is deleted already and we do not have to do anything. - // This is expected when we are processing an update as a result of deployment finalizer deletion. - // The process that deleted the last finalizer is also going to delete the deployment and we do not have to do anything. - if !errors.IsNotFound(err) { - return fmt.Errorf("failed to delete deployment: %v", err) - } - } - return nil -} diff --git a/federation/pkg/federation-controller/sync/BUILD b/federation/pkg/federation-controller/sync/BUILD index 1258db9f168..8dc31c81627 100644 --- a/federation/pkg/federation-controller/sync/BUILD +++ b/federation/pkg/federation-controller/sync/BUILD @@ -44,6 +44,7 @@ go_test( name = "go_default_test", srcs = [ "controller_test.go", + "deploymentcontroller_test.go", "replicasetcontroller_test.go", ], library = ":go_default_library", @@ -62,6 +63,8 @@ go_test( "//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/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/testing:go_default_library", ], diff --git a/federation/pkg/federation-controller/deployment/deploymentcontroller_test.go b/federation/pkg/federation-controller/sync/deploymentcontroller_test.go similarity index 83% rename from federation/pkg/federation-controller/deployment/deploymentcontroller_test.go rename to federation/pkg/federation-controller/sync/deploymentcontroller_test.go index a03b05b4842..cae13c2c322 100644 --- a/federation/pkg/federation-controller/deployment/deploymentcontroller_test.go +++ b/federation/pkg/federation-controller/sync/deploymentcontroller_test.go @@ -14,13 +14,12 @@ See the License for the specific language governing permissions and limitations under the License. */ -package deployment +package sync import ( "flag" "fmt" "testing" - "time" apiv1 "k8s.io/api/core/v1" extensionsv1 "k8s.io/api/extensions/v1beta1" @@ -30,6 +29,7 @@ import ( "k8s.io/apimachinery/pkg/util/wait" fedv1 "k8s.io/kubernetes/federation/apis/federation/v1beta1" fakefedclientset "k8s.io/kubernetes/federation/client/clientset_generated/federation_clientset/fake" + "k8s.io/kubernetes/federation/pkg/federatedtypes" . "k8s.io/kubernetes/federation/pkg/federation-controller/util/test" kubeclientset "k8s.io/kubernetes/pkg/client/clientset_generated/clientset" fakekubeclientset "k8s.io/kubernetes/pkg/client/clientset_generated/clientset/fake" @@ -39,7 +39,6 @@ import ( const ( deployments = "deployments" - pods = "pods" ) func TestDeploymentController(t *testing.T) { @@ -47,11 +46,6 @@ func TestDeploymentController(t *testing.T) { flag.Set("v", "5") flag.Parse() - deploymentReviewDelay = 500 * time.Millisecond - clusterAvailableDelay = 100 * time.Millisecond - clusterUnavailableDelay = 100 * time.Millisecond - allDeploymentReviewDelay = 500 * time.Millisecond - cluster1 := NewCluster("cluster1", apiv1.ConditionTrue) cluster2 := NewCluster("cluster2", apiv1.ConditionTrue) @@ -65,18 +59,15 @@ func TestDeploymentController(t *testing.T) { cluster1Client := &fakekubeclientset.Clientset{} cluster1Watch := RegisterFakeWatch(deployments, &cluster1Client.Fake) - _ = RegisterFakeWatch(pods, &cluster1Client.Fake) - RegisterFakeList(deployments, &cluster1Client.Fake, &extensionsv1.DeploymentList{Items: []extensionsv1.Deployment{}}) cluster1CreateChan := RegisterFakeCopyOnCreate(deployments, &cluster1Client.Fake, cluster1Watch) cluster1UpdateChan := RegisterFakeCopyOnUpdate(deployments, &cluster1Client.Fake, cluster1Watch) cluster2Client := &fakekubeclientset.Clientset{} cluster2Watch := RegisterFakeWatch(deployments, &cluster2Client.Fake) - _ = RegisterFakeWatch(pods, &cluster2Client.Fake) - RegisterFakeList(deployments, &cluster2Client.Fake, &extensionsv1.DeploymentList{Items: []extensionsv1.Deployment{}}) cluster2CreateChan := RegisterFakeCopyOnCreate(deployments, &cluster2Client.Fake, cluster2Watch) - deploymentController := NewDeploymentController(fakeClient) + deploymentController := newFederationSyncController(fakeClient, federatedtypes.NewDeploymentAdapter(fakeClient)) + deploymentController.minimizeLatency() clientFactory := func(cluster *fedv1.Cluster) (kubeclientset.Interface, error) { switch cluster.Name { case cluster1.Name: @@ -87,11 +78,10 @@ func TestDeploymentController(t *testing.T) { return nil, fmt.Errorf("Unknown cluster") } } - ToFederatedInformerForTestOnly(deploymentController.fedDeploymentInformer).SetClientFactory(clientFactory) - ToFederatedInformerForTestOnly(deploymentController.fedPodInformer).SetClientFactory(clientFactory) + ToFederatedInformerForTestOnly(deploymentController.informer).SetClientFactory(clientFactory) stop := make(chan struct{}) - go deploymentController.Run(5, stop) + go deploymentController.Run(stop) // Create deployment. Expect to see it in cluster1. dep1 := newDeploymentWithReplicas("depA", 6) @@ -113,7 +103,7 @@ func TestDeploymentController(t *testing.T) { } assert.NoError(t, CheckObjectFromChan(cluster1CreateChan, checkDeployment(dep1, *dep1.Spec.Replicas))) err := WaitForStoreUpdate( - deploymentController.fedDeploymentInformer.GetTargetStore(), + deploymentController.informer.GetTargetStore(), cluster1.Name, types.NamespacedName{Namespace: dep1.Namespace, Name: dep1.Name}.String(), wait.ForeverTestTimeout) assert.Nil(t, err, "deployment should have appeared in the informer store") @@ -132,7 +122,7 @@ func TestDeploymentController(t *testing.T) { // Add new deployment with non-default replica placement preferences. dep2 := newDeploymentWithReplicas("deployment2", 9) dep2.Annotations = make(map[string]string) - dep2.Annotations[FedDeploymentPreferencesAnnotation] = `{"rebalance": true, + dep2.Annotations[federatedtypes.FedDeploymentPreferencesAnnotation] = `{"rebalance": true, "clusters": { "cluster1": {"weight": 2}, "cluster2": {"weight": 1} From f375dcf4df60f3317751512ab5f68981076bd4b2 Mon Sep 17 00:00:00 2001 From: Adam Worrall Date: Wed, 28 Jun 2017 18:06:55 -0700 Subject: [PATCH 111/448] Write output into the correct dir --- test/e2e/framework/google_compute.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/e2e/framework/google_compute.go b/test/e2e/framework/google_compute.go index 8b6fbedfe19..f741a04ec0a 100644 --- a/test/e2e/framework/google_compute.go +++ b/test/e2e/framework/google_compute.go @@ -188,7 +188,7 @@ func LogClusterImageSources() { } outputBytes, _ := json.MarshalIndent(images, "", " ") - filePath := filepath.Join(TestContext.OutputDir, "images.json") + filePath := filepath.Join(TestContext.ReportDir, "images.json") if err := ioutil.WriteFile(filePath, outputBytes, 0644); err != nil { Logf("cluster images sources, could not write to %q: %v", filePath, err) } From 00eeb7f53a8ac67d6f89543a709af16b6e43f29b Mon Sep 17 00:00:00 2001 From: Pengfei Ni Date: Thu, 29 Jun 2017 09:17:14 +0800 Subject: [PATCH 112/448] Add node e2e tests for runAsUser --- test/e2e_node/security_context_test.go | 41 ++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/test/e2e_node/security_context_test.go b/test/e2e_node/security_context_test.go index 56676d54de8..d79830f4754 100644 --- a/test/e2e_node/security_context_test.go +++ b/test/e2e_node/security_context_test.go @@ -274,4 +274,45 @@ var _ = framework.KubeDescribe("Security Context", func() { }) }) + Context("When creating a container with runAsUser", func() { + makeUserPod := func(podName, image string, command []string, userid int64) *v1.Pod { + return &v1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: podName, + }, + Spec: v1.PodSpec{ + RestartPolicy: v1.RestartPolicyNever, + Containers: []v1.Container{ + { + Image: image, + Name: podName, + Command: command, + SecurityContext: &v1.SecurityContext{ + RunAsUser: &userid, + }, + }, + }, + }, + } + } + createAndWaitUserPod := func(userid int64) { + podName := fmt.Sprintf("busybox-user-%d-%s", userid, uuid.NewUUID()) + podClient.Create(makeUserPod(podName, + "gcr.io/google_containers/busybox:1.24", + []string{"sh", "-c", fmt.Sprintf("test $(id -u) -eq %d", userid)}, + userid, + )) + + podClient.WaitForSuccess(podName, framework.PodStartTimeout) + } + + It("should run the container with uid 65534", func() { + createAndWaitUserPod(65534) + }) + + It("should run the container with uid 0", func() { + createAndWaitUserPod(0) + }) + + }) }) From 53c536b59c7121f8642c773d8bbfdf066a8012ab Mon Sep 17 00:00:00 2001 From: xiangpengzhao Date: Thu, 29 Jun 2017 10:22:57 +0800 Subject: [PATCH 113/448] Implement GetCapacity in container_manager_unsupported --- pkg/kubelet/cm/container_manager_unsupported.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pkg/kubelet/cm/container_manager_unsupported.go b/pkg/kubelet/cm/container_manager_unsupported.go index 5a1a2f76d6d..a9984b9e25d 100644 --- a/pkg/kubelet/cm/container_manager_unsupported.go +++ b/pkg/kubelet/cm/container_manager_unsupported.go @@ -64,6 +64,10 @@ func (cm *unsupportedContainerManager) GetNodeAllocatableReservation() v1.Resour return nil } +func (cm *unsupportedContainerManager) GetCapacity() v1.ResourceList { + return nil +} + func (cm *unsupportedContainerManager) NewPodContainerManager() PodContainerManager { return &unsupportedPodContainerManager{} } From e0d02f140e1e35f5f2c315fa99cff3876ddfd184 Mon Sep 17 00:00:00 2001 From: Guangya Liu Date: Wed, 28 Jun 2017 11:36:35 +0800 Subject: [PATCH 114/448] Used const variable in scheduler test. --- plugin/pkg/scheduler/core/generic_scheduler.go | 2 +- plugin/pkg/scheduler/core/generic_scheduler_test.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/plugin/pkg/scheduler/core/generic_scheduler.go b/plugin/pkg/scheduler/core/generic_scheduler.go index ea36e73bd95..68ab9b389eb 100644 --- a/plugin/pkg/scheduler/core/generic_scheduler.go +++ b/plugin/pkg/scheduler/core/generic_scheduler.go @@ -44,7 +44,7 @@ type FitError struct { var ErrNoNodesAvailable = fmt.Errorf("no nodes available to schedule pods") -const NoNodeAvailableMsg = "No nodes are available that match all of the following predicates:" +const NoNodeAvailableMsg = "No nodes are available that match all of the following predicates" // Error returns detailed information of why the pod failed to fit on each node func (f *FitError) Error() string { diff --git a/plugin/pkg/scheduler/core/generic_scheduler_test.go b/plugin/pkg/scheduler/core/generic_scheduler_test.go index 55e06bb0f6e..5255b12ff7e 100644 --- a/plugin/pkg/scheduler/core/generic_scheduler_test.go +++ b/plugin/pkg/scheduler/core/generic_scheduler_test.go @@ -410,7 +410,7 @@ func TestHumanReadableFitError(t *testing.T) { "3": []algorithm.PredicateFailureReason{algorithmpredicates.ErrNodeUnderDiskPressure}, }, } - if strings.Contains(error.Error(), "No nodes are available that match all of the following predicates") { + if strings.Contains(error.Error(), NoNodeAvailableMsg) { if strings.Contains(error.Error(), "NodeUnderDiskPressure (2)") && strings.Contains(error.Error(), "NodeUnderMemoryPressure (1)") { return } From 2e79f6c61a182343f941049f3ad17cd1954db581 Mon Sep 17 00:00:00 2001 From: allencloud Date: Fri, 23 Jun 2017 13:58:31 +0800 Subject: [PATCH 115/448] remove unused codes in loadSystemLanguage Signed-off-by: allencloud --- pkg/util/i18n/i18n.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pkg/util/i18n/i18n.go b/pkg/util/i18n/i18n.go index d0335d6fbb2..aac3a304958 100644 --- a/pkg/util/i18n/i18n.go +++ b/pkg/util/i18n/i18n.go @@ -49,12 +49,12 @@ var knownTranslations = map[string][]string{ func loadSystemLanguage() string { langStr := os.Getenv("LANG") if langStr == "" { - glog.V(3).Infof("Couldn't find the LANG environment variable, defaulting to en-US") + glog.V(3).Infof("Couldn't find the LANG environment variable, defaulting to en_US") return "default" } pieces := strings.Split(langStr, ".") - if len(pieces) == 0 { - glog.V(3).Infof("Unexpected system language (%s), defaulting to en-US", langStr) + if len(pieces) != 2 { + glog.V(3).Infof("Unexpected system language (%s), defaulting to en_US", langStr) return "default" } return pieces[0] From 6a88a03d59e96be590cf2be2056d4e19847902da Mon Sep 17 00:00:00 2001 From: Johannes Scheuermann Date: Wed, 28 Jun 2017 23:03:33 +0200 Subject: [PATCH 116/448] Set a Quobyte quota for newly created volumes --- pkg/volume/quobyte/quobyte_util.go | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/pkg/volume/quobyte/quobyte_util.go b/pkg/volume/quobyte/quobyte_util.go index cd32637c581..e094133bf48 100644 --- a/pkg/volume/quobyte/quobyte_util.go +++ b/pkg/volume/quobyte/quobyte_util.go @@ -36,7 +36,7 @@ func (manager *quobyteVolumeManager) createVolume(provisioner *quobyteVolumeProv capacity := provisioner.options.PVC.Spec.Resources.Requests[v1.ResourceName(v1.ResourceStorage)] volumeSize := int(volume.RoundUpSize(capacity.Value(), 1024*1024*1024)) // Quobyte has the concept of Volumes which doen't have a specific size (they can grow unlimited) - // to simulate a size constraint we could set here a Quota + // to simulate a size constraint we set here a Quota for logical space volumeRequest := &quobyteapi.CreateVolumeRequest{ Name: provisioner.volume, RootUserID: provisioner.user, @@ -45,7 +45,15 @@ func (manager *quobyteVolumeManager) createVolume(provisioner *quobyteVolumeProv ConfigurationName: provisioner.config, } - if _, err := manager.createQuobyteClient().CreateVolume(volumeRequest); err != nil { + quobyteClient := manager.createQuobyteClient() + volumeUUID, err := quobyteClient.CreateVolume(volumeRequest) + if err != nil { + return &v1.QuobyteVolumeSource{}, volumeSize, err + } + + // Set Quoate for Volume with specified byte size + err = quobyteClient.SetVolumeQuota(volumeUUID, capacity.Value()) + if err != nil { return &v1.QuobyteVolumeSource{}, volumeSize, err } From d462b4cbc83c71a0c2020d18023751ebc2dced31 Mon Sep 17 00:00:00 2001 From: Mike Danese Date: Wed, 28 Jun 2017 11:29:54 +0200 Subject: [PATCH 117/448] Partially revert "Do not fire InsufficientResourceError when there are intentional reasons." This partially reverts commit 2b311fefba9cc106ed1a8cebc6c61e32814fd9e5. We drop the changes to the DaemonSet controller but leave the test. By reverting the changes, we make it easier to return different values of shouldContinueRunning for intentional predicate failures, rather then lumping all intentional predicate failures together. The test should continue to pass after the fix. --- pkg/controller/daemon/daemoncontroller.go | 44 +++++++---------------- 1 file changed, 13 insertions(+), 31 deletions(-) diff --git a/pkg/controller/daemon/daemoncontroller.go b/pkg/controller/daemon/daemoncontroller.go index c45e17ab30a..5f9cc6b2867 100644 --- a/pkg/controller/daemon/daemoncontroller.go +++ b/pkg/controller/daemon/daemoncontroller.go @@ -1022,30 +1022,6 @@ func (dsc *DaemonSetsController) syncDaemonSet(key string) error { return dsc.updateDaemonSetStatus(ds, hash) } -// hasIntentionalPredicatesReasons checks if any of the given predicate failure reasons -// is intentional. -func hasIntentionalPredicatesReasons(reasons []algorithm.PredicateFailureReason) bool { - for _, r := range reasons { - switch reason := r.(type) { - case *predicates.PredicateFailureError: - switch reason { - // intentional - case - predicates.ErrNodeSelectorNotMatch, - predicates.ErrPodNotMatchHostName, - predicates.ErrNodeLabelPresenceViolated, - // this one is probably intentional since it's a workaround for not having - // pod hard anti affinity. - predicates.ErrPodNotFitsHostPorts, - // DaemonSet is expected to respect taints and tolerations - predicates.ErrTaintsTolerationsNotMatch: - return true - } - } - } - return false -} - // nodeShouldRunDaemonPod checks a set of preconditions against a (node,daemonset) and returns a // summary. Returned booleans are: // * wantToRun: @@ -1135,12 +1111,6 @@ func (dsc *DaemonSetsController) nodeShouldRunDaemonPod(node *v1.Node, ds *exten return false, false, false, err } - // Return directly if there is any intentional predicate failure reason, so that daemonset controller skips - // checking other predicate failures, such as InsufficientResourceError and unintentional errors. - if hasIntentionalPredicatesReasons(reasons) { - return false, false, false, nil - } - for _, r := range reasons { glog.V(4).Infof("DaemonSet Predicates failed on node %s for ds '%s/%s' for reason: %v", node.Name, ds.ObjectMeta.Namespace, ds.ObjectMeta.Name, r.GetReason()) switch reason := r.(type) { @@ -1149,8 +1119,20 @@ func (dsc *DaemonSetsController) nodeShouldRunDaemonPod(node *v1.Node, ds *exten shouldSchedule = false case *predicates.PredicateFailureError: var emitEvent bool + // we try to partition predicates into two partitions here: intentional on the part of the operator and not. switch reason { - // unintentional predicates reasons need to be fired out to event. + // intentional + case + predicates.ErrNodeSelectorNotMatch, + predicates.ErrPodNotMatchHostName, + predicates.ErrNodeLabelPresenceViolated, + // this one is probably intentional since it's a workaround for not having + // pod hard anti affinity. + predicates.ErrPodNotFitsHostPorts, + // DaemonSet is expected to respect taints and tolerations + predicates.ErrTaintsTolerationsNotMatch: + wantToRun, shouldSchedule, shouldContinueRunning = false, false, false + // unintentional case predicates.ErrDiskConflict, predicates.ErrVolumeZoneConflict, From 1aede99abaecf175375430dd1054dd1340553cf0 Mon Sep 17 00:00:00 2001 From: Mike Danese Date: Wed, 28 Jun 2017 11:42:49 +0200 Subject: [PATCH 118/448] fix #45780 slightly differently --- pkg/controller/daemon/daemoncontroller.go | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/pkg/controller/daemon/daemoncontroller.go b/pkg/controller/daemon/daemoncontroller.go index 5f9cc6b2867..9b154990d7f 100644 --- a/pkg/controller/daemon/daemoncontroller.go +++ b/pkg/controller/daemon/daemoncontroller.go @@ -1111,12 +1111,13 @@ func (dsc *DaemonSetsController) nodeShouldRunDaemonPod(node *v1.Node, ds *exten return false, false, false, err } + var insufficientResourceErr error + for _, r := range reasons { glog.V(4).Infof("DaemonSet Predicates failed on node %s for ds '%s/%s' for reason: %v", node.Name, ds.ObjectMeta.Namespace, ds.ObjectMeta.Name, r.GetReason()) switch reason := r.(type) { case *predicates.InsufficientResourceError: - dsc.eventRecorder.Eventf(ds, v1.EventTypeWarning, FailedPlacementReason, "failed to place pod on %q: %s", node.ObjectMeta.Name, reason.Error()) - shouldSchedule = false + insufficientResourceErr = reason case *predicates.PredicateFailureError: var emitEvent bool // we try to partition predicates into two partitions here: intentional on the part of the operator and not. @@ -1128,10 +1129,11 @@ func (dsc *DaemonSetsController) nodeShouldRunDaemonPod(node *v1.Node, ds *exten predicates.ErrNodeLabelPresenceViolated, // this one is probably intentional since it's a workaround for not having // pod hard anti affinity. - predicates.ErrPodNotFitsHostPorts, - // DaemonSet is expected to respect taints and tolerations - predicates.ErrTaintsTolerationsNotMatch: + predicates.ErrPodNotFitsHostPorts: wantToRun, shouldSchedule, shouldContinueRunning = false, false, false + case predicates.ErrTaintsTolerationsNotMatch: + // DaemonSet is expected to respect taints and tolerations + wantToRun, shouldSchedule, shouldContinueRunning = false, false, true // unintentional case predicates.ErrDiskConflict, @@ -1160,6 +1162,12 @@ func (dsc *DaemonSetsController) nodeShouldRunDaemonPod(node *v1.Node, ds *exten } } } + // only emit this event if insufficient resource is the only thing + // preventing the daemon pod from scheduling + if shouldSchedule && insufficientResourceErr != nil { + dsc.eventRecorder.Eventf(ds, v1.EventTypeWarning, FailedPlacementReason, "failed to place pod on %q: %s", node.ObjectMeta.Name, insufficientResourceErr.Error()) + shouldSchedule = false + } return } From 8e6c2ea4d055b53f5cf1886af1c7e5a224d6afd1 Mon Sep 17 00:00:00 2001 From: Mike Danese Date: Wed, 28 Jun 2017 11:27:24 +0200 Subject: [PATCH 119/448] support NoExecute and NoSchedule taints correctly in DaemonSet controller And add some unit tests. --- pkg/controller/daemon/daemoncontroller.go | 20 +++++++-- .../daemon/daemoncontroller_test.go | 43 +++++++++++++++++-- .../algorithm/predicates/predicates.go | 19 ++++++-- 3 files changed, 72 insertions(+), 10 deletions(-) diff --git a/pkg/controller/daemon/daemoncontroller.go b/pkg/controller/daemon/daemoncontroller.go index 9b154990d7f..9641cbde14c 100644 --- a/pkg/controller/daemon/daemoncontroller.go +++ b/pkg/controller/daemon/daemoncontroller.go @@ -1040,7 +1040,14 @@ func (dsc *DaemonSetsController) nodeShouldRunDaemonPod(node *v1.Node, ds *exten // Because these bools require an && of all their required conditions, we start // with all bools set to true and set a bool to false if a condition is not met. - // A bool should probably not be set to true after this line. + // A bool should probably not be set to true after this line. We can + // return early if we are: + // + // 1. return false, false, false, err + // 2. return false, false, false, nil + // + // Otherwise if a condition is not met, we should set one of these + // bools to false. wantToRun, shouldSchedule, shouldContinueRunning = true, true, true // If the daemon set specifies a node name, check that it matches with node.Name. if !(ds.Spec.Template.Spec.NodeName == "" || ds.Spec.Template.Spec.NodeName == node.Name) { @@ -1130,10 +1137,17 @@ func (dsc *DaemonSetsController) nodeShouldRunDaemonPod(node *v1.Node, ds *exten // this one is probably intentional since it's a workaround for not having // pod hard anti affinity. predicates.ErrPodNotFitsHostPorts: - wantToRun, shouldSchedule, shouldContinueRunning = false, false, false + return false, false, false, nil case predicates.ErrTaintsTolerationsNotMatch: // DaemonSet is expected to respect taints and tolerations - wantToRun, shouldSchedule, shouldContinueRunning = false, false, true + fitsNoExecute, _, err := predicates.PodToleratesNodeNoExecuteTaints(newPod, nil, nodeInfo) + if err != nil { + return false, false, false, err + } + if !fitsNoExecute { + return false, false, false, nil + } + wantToRun, shouldSchedule = false, false // unintentional case predicates.ErrDiskConflict, diff --git a/pkg/controller/daemon/daemoncontroller_test.go b/pkg/controller/daemon/daemoncontroller_test.go index 5a853ccd575..e65e40c94fb 100644 --- a/pkg/controller/daemon/daemoncontroller_test.go +++ b/pkg/controller/daemon/daemoncontroller_test.go @@ -60,6 +60,7 @@ var ( var ( noScheduleTolerations = []v1.Toleration{{Key: "dedicated", Value: "user1", Effect: "NoSchedule"}} noScheduleTaints = []v1.Taint{{Key: "dedicated", Value: "user1", Effect: "NoSchedule"}} + noExecuteTaints = []v1.Taint{{Key: "dedicated", Value: "user1", Effect: "NoExecute"}} ) var ( @@ -1079,10 +1080,46 @@ func TestDaemonKillFailedPods(t *testing.T) { } } -// DaemonSet should not launch a pod on a tainted node when the pod doesn't tolerate that taint. -func TestTaintedNodeDaemonDoesNotLaunchUntoleratePod(t *testing.T) { +// Daemonset should not remove a running pod from a node if the pod doesn't +// tolerate the nodes NoSchedule taint +func TestNoScheduleTaintedDoesntEvicitRunningIntolerantPod(t *testing.T) { for _, strategy := range updateStrategies() { - ds := newDaemonSet("untolerate") + ds := newDaemonSet("intolerant") + ds.Spec.UpdateStrategy = *strategy + manager, podControl, _ := newTestController(ds) + + node := newNode("tainted", nil) + manager.nodeStore.Add(node) + setNodeTaint(node, noScheduleTaints) + manager.podStore.Add(newPod("keep-running-me", "tainted", simpleDaemonSetLabel, ds)) + manager.dsStore.Add(ds) + + syncAndValidateDaemonSets(t, manager, ds, podControl, 0, 0) + } +} + +// Daemonset should remove a running pod from a node if the pod doesn't +// tolerate the nodes NoExecute taint +func TestNoExecuteTaintedDoesEvicitRunningIntolerantPod(t *testing.T) { + for _, strategy := range updateStrategies() { + ds := newDaemonSet("intolerant") + ds.Spec.UpdateStrategy = *strategy + manager, podControl, _ := newTestController(ds) + + node := newNode("tainted", nil) + manager.nodeStore.Add(node) + setNodeTaint(node, noExecuteTaints) + manager.podStore.Add(newPod("stop-running-me", "tainted", simpleDaemonSetLabel, ds)) + manager.dsStore.Add(ds) + + syncAndValidateDaemonSets(t, manager, ds, podControl, 0, 1) + } +} + +// DaemonSet should not launch a pod on a tainted node when the pod doesn't tolerate that taint. +func TestTaintedNodeDaemonDoesNotLaunchIntolerantPod(t *testing.T) { + for _, strategy := range updateStrategies() { + ds := newDaemonSet("intolerant") ds.Spec.UpdateStrategy = *strategy manager, podControl, _ := newTestController(ds) diff --git a/plugin/pkg/scheduler/algorithm/predicates/predicates.go b/plugin/pkg/scheduler/algorithm/predicates/predicates.go index dbb214c943d..99b7482d5cf 100644 --- a/plugin/pkg/scheduler/algorithm/predicates/predicates.go +++ b/plugin/pkg/scheduler/algorithm/predicates/predicates.go @@ -1247,15 +1247,26 @@ func (c *PodAffinityChecker) satisfiesPodsAffinityAntiAffinity(pod *v1.Pod, node // PodToleratesNodeTaints checks if a pod tolertaions can tolerate the node taints func PodToleratesNodeTaints(pod *v1.Pod, meta interface{}, nodeInfo *schedulercache.NodeInfo) (bool, []algorithm.PredicateFailureReason, error) { + return podToleratesNodeTaints(pod, nodeInfo, func(t *v1.Taint) bool { + // PodToleratesNodeTaints is only interested in NoSchedule and NoExecute taints. + return t.Effect == v1.TaintEffectNoSchedule || t.Effect == v1.TaintEffectNoExecute + }) +} + +// PodToleratesNodeNoExecuteTaints checks if a pod tolertaions can tolerate the node's NoExecute taints +func PodToleratesNodeNoExecuteTaints(pod *v1.Pod, meta interface{}, nodeInfo *schedulercache.NodeInfo) (bool, []algorithm.PredicateFailureReason, error) { + return podToleratesNodeTaints(pod, nodeInfo, func(t *v1.Taint) bool { + return t.Effect == v1.TaintEffectNoExecute + }) +} + +func podToleratesNodeTaints(pod *v1.Pod, nodeInfo *schedulercache.NodeInfo, filter func(t *v1.Taint) bool) (bool, []algorithm.PredicateFailureReason, error) { taints, err := nodeInfo.Taints() if err != nil { return false, nil, err } - if v1helper.TolerationsTolerateTaintsWithFilter(pod.Spec.Tolerations, taints, func(t *v1.Taint) bool { - // PodToleratesNodeTaints is only interested in NoSchedule and NoExecute taints. - return t.Effect == v1.TaintEffectNoSchedule || t.Effect == v1.TaintEffectNoExecute - }) { + if v1helper.TolerationsTolerateTaintsWithFilter(pod.Spec.Tolerations, taints, filter) { return true, nil, nil } return false, []algorithm.PredicateFailureReason{ErrTaintsTolerationsNotMatch}, nil From 63ccedcfa7a34ba4bed8b697a07eab9e1e14896d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20K=C5=82obuszewski?= Date: Fri, 2 Jun 2017 13:25:02 +0200 Subject: [PATCH 120/448] Update addon-resizer version Also, remove the flags that have been deprecated in the new version. --- .../cluster-monitoring/google/heapster-controller.yaml | 8 ++------ .../googleinfluxdb/heapster-controller-combined.yaml | 8 ++------ .../cluster-monitoring/influxdb/heapster-controller.yaml | 8 ++------ .../stackdriver/heapster-controller.yaml | 4 +--- .../standalone/heapster-controller.yaml | 4 +--- 5 files changed, 8 insertions(+), 24 deletions(-) diff --git a/cluster/addons/cluster-monitoring/google/heapster-controller.yaml b/cluster/addons/cluster-monitoring/google/heapster-controller.yaml index a8aeb03c0ae..57d915b95bf 100644 --- a/cluster/addons/cluster-monitoring/google/heapster-controller.yaml +++ b/cluster/addons/cluster-monitoring/google/heapster-controller.yaml @@ -78,7 +78,7 @@ spec: - name: usr-ca-certs mountPath: /usr/share/ca-certificates readOnly: true - - image: gcr.io/google_containers/addon-resizer:1.7 + - image: gcr.io/google_containers/addon-resizer:2.0 name: heapster-nanny resources: limits: @@ -102,12 +102,10 @@ spec: - --extra-cpu={{ metrics_cpu_per_node }}m - --memory={{ base_metrics_memory }} - --extra-memory={{metrics_memory_per_node}}Mi - - --threshold=5 - --deployment=heapster-v1.4.0 - --container=heapster - --poll-period=300000 - - --estimator=exponential - - image: gcr.io/google_containers/addon-resizer:1.7 + - image: gcr.io/google_containers/addon-resizer:2.0 name: eventer-nanny resources: limits: @@ -131,11 +129,9 @@ spec: - --extra-cpu=0m - --memory={{base_eventer_memory}} - --extra-memory={{eventer_memory_per_node}}Ki - - --threshold=5 - --deployment=heapster-v1.4.0 - --container=eventer - --poll-period=300000 - - --estimator=exponential volumes: - name: ssl-certs hostPath: diff --git a/cluster/addons/cluster-monitoring/googleinfluxdb/heapster-controller-combined.yaml b/cluster/addons/cluster-monitoring/googleinfluxdb/heapster-controller-combined.yaml index 71b132a5c50..82e11998ed2 100644 --- a/cluster/addons/cluster-monitoring/googleinfluxdb/heapster-controller-combined.yaml +++ b/cluster/addons/cluster-monitoring/googleinfluxdb/heapster-controller-combined.yaml @@ -79,7 +79,7 @@ spec: - name: usr-ca-certs mountPath: /usr/share/ca-certificates readOnly: true - - image: gcr.io/google_containers/addon-resizer:1.7 + - image: gcr.io/google_containers/addon-resizer:2.0 name: heapster-nanny resources: limits: @@ -103,12 +103,10 @@ spec: - --extra-cpu={{ metrics_cpu_per_node }}m - --memory={{ base_metrics_memory }} - --extra-memory={{ metrics_memory_per_node }}Mi - - --threshold=5 - --deployment=heapster-v1.4.0 - --container=heapster - --poll-period=300000 - - --estimator=exponential - - image: gcr.io/google_containers/addon-resizer:1.7 + - image: gcr.io/google_containers/addon-resizer:2.0 name: eventer-nanny resources: limits: @@ -132,11 +130,9 @@ spec: - --extra-cpu=0m - --memory={{ base_eventer_memory }} - --extra-memory={{ eventer_memory_per_node }}Ki - - --threshold=5 - --deployment=heapster-v1.4.0 - --container=eventer - --poll-period=300000 - - --estimator=exponential volumes: - name: ssl-certs hostPath: diff --git a/cluster/addons/cluster-monitoring/influxdb/heapster-controller.yaml b/cluster/addons/cluster-monitoring/influxdb/heapster-controller.yaml index 9d9d616b9f4..0b27abbc2ee 100644 --- a/cluster/addons/cluster-monitoring/influxdb/heapster-controller.yaml +++ b/cluster/addons/cluster-monitoring/influxdb/heapster-controller.yaml @@ -64,7 +64,7 @@ spec: - /eventer - --source=kubernetes:'' - --sink=influxdb:http://monitoring-influxdb:8086 - - image: gcr.io/google_containers/addon-resizer:1.7 + - image: gcr.io/google_containers/addon-resizer:2.0 name: heapster-nanny resources: limits: @@ -88,12 +88,10 @@ spec: - --extra-cpu={{ metrics_cpu_per_node }}m - --memory={{ base_metrics_memory }} - --extra-memory={{ metrics_memory_per_node }}Mi - - --threshold=5 - --deployment=heapster-v1.4.0 - --container=heapster - --poll-period=300000 - - --estimator=exponential - - image: gcr.io/google_containers/addon-resizer:1.7 + - image: gcr.io/google_containers/addon-resizer:2.0 name: eventer-nanny resources: limits: @@ -117,11 +115,9 @@ spec: - --extra-cpu=0m - --memory={{ base_eventer_memory }} - --extra-memory={{ eventer_memory_per_node }}Ki - - --threshold=5 - --deployment=heapster-v1.4.0 - --container=eventer - --poll-period=300000 - - --estimator=exponential serviceAccountName: heapster tolerations: - key: "CriticalAddonsOnly" diff --git a/cluster/addons/cluster-monitoring/stackdriver/heapster-controller.yaml b/cluster/addons/cluster-monitoring/stackdriver/heapster-controller.yaml index ed78824e7b3..90908770a07 100644 --- a/cluster/addons/cluster-monitoring/stackdriver/heapster-controller.yaml +++ b/cluster/addons/cluster-monitoring/stackdriver/heapster-controller.yaml @@ -64,7 +64,7 @@ spec: - name: usr-ca-certs mountPath: /usr/share/ca-certificates readOnly: true - - image: gcr.io/google_containers/addon-resizer:1.7 + - image: gcr.io/google_containers/addon-resizer:2.0 name: heapster-nanny resources: limits: @@ -88,11 +88,9 @@ spec: - --extra-cpu={{ metrics_cpu_per_node }}m - --memory={{ base_metrics_memory }} - --extra-memory={{metrics_memory_per_node}}Mi - - --threshold=5 - --deployment=heapster-v1.4.0 - --container=heapster - --poll-period=300000 - - --estimator=exponential volumes: - name: ssl-certs hostPath: diff --git a/cluster/addons/cluster-monitoring/standalone/heapster-controller.yaml b/cluster/addons/cluster-monitoring/standalone/heapster-controller.yaml index 79b701dae99..aa329ccb44a 100644 --- a/cluster/addons/cluster-monitoring/standalone/heapster-controller.yaml +++ b/cluster/addons/cluster-monitoring/standalone/heapster-controller.yaml @@ -55,7 +55,7 @@ spec: command: - /heapster - --source=kubernetes.summary_api:'' - - image: gcr.io/google_containers/addon-resizer:1.7 + - image: gcr.io/google_containers/addon-resizer:2.0 name: heapster-nanny resources: limits: @@ -79,11 +79,9 @@ spec: - --extra-cpu={{ metrics_cpu_per_node }}m - --memory={{ base_metrics_memory }} - --extra-memory={{ metrics_memory_per_node }}Mi - - --threshold=5 - --deployment=heapster-v1.4.0 - --container=heapster - --poll-period=300000 - - --estimator=exponential serviceAccountName: heapster tolerations: - key: "CriticalAddonsOnly" From 23a90a7679512b1c0bdffee27165c1414eb3383c Mon Sep 17 00:00:00 2001 From: FengyunPan Date: Thu, 29 Jun 2017 17:22:03 +0800 Subject: [PATCH 121/448] Fix removing finalizer for garbage collector The loop should use 'continue' not 'break', otherwise removeFinalizer() not only removes "orphaningFinalizer" from its finalizers list but also removes others. --- pkg/controller/garbagecollector/operations.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/controller/garbagecollector/operations.go b/pkg/controller/garbagecollector/operations.go index b488fb8d1a2..fcfdcd1cee6 100644 --- a/pkg/controller/garbagecollector/operations.go +++ b/pkg/controller/garbagecollector/operations.go @@ -115,7 +115,7 @@ func (gc *GarbageCollector) removeFinalizer(owner *node, targetFinalizer string) for _, f := range finalizers { if f == targetFinalizer { found = true - break + continue } newFinalizers = append(newFinalizers, f) } From 7ce5478c0ced59869da3eedbfd2b4bf95d0d9fe0 Mon Sep 17 00:00:00 2001 From: Johannes Scheuermann Date: Thu, 29 Jun 2017 12:15:22 +0200 Subject: [PATCH 122/448] Update Quobyte API repo --- Godeps/Godeps.json | 2 +- vendor/github.com/quobyte/api/BUILD | 31 ------------------------ vendor/github.com/quobyte/api/README.md | 8 +++--- vendor/github.com/quobyte/api/quobyte.go | 27 ++++++++++++++++++++- vendor/github.com/quobyte/api/types.go | 22 +++++++++++++++++ 5 files changed, 53 insertions(+), 37 deletions(-) delete mode 100644 vendor/github.com/quobyte/api/BUILD diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json index 8238ba1ea3c..f09e0f03802 100644 --- a/Godeps/Godeps.json +++ b/Godeps/Godeps.json @@ -2218,7 +2218,7 @@ }, { "ImportPath": "github.com/quobyte/api", - "Rev": "bf713b5a4333f44504fa1ce63690de45cfed6413" + "Rev": "cb10db90715b14d4784465d2fa3b915dfacc0628" }, { "ImportPath": "github.com/rackspace/gophercloud", diff --git a/vendor/github.com/quobyte/api/BUILD b/vendor/github.com/quobyte/api/BUILD deleted file mode 100644 index 84fec6cd094..00000000000 --- a/vendor/github.com/quobyte/api/BUILD +++ /dev/null @@ -1,31 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -licenses(["notice"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = [ - "quobyte.go", - "rpc_client.go", - "types.go", - ], - tags = ["automanaged"], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/vendor/github.com/quobyte/api/README.md b/vendor/github.com/quobyte/api/README.md index 7ed01f10d2c..072033b7bde 100644 --- a/vendor/github.com/quobyte/api/README.md +++ b/vendor/github.com/quobyte/api/README.md @@ -22,14 +22,14 @@ func main() { Name: "MyVolume", RootUserID: "root", RootGroupID: "root", - ConfigurationName: "base", + ConfigurationName: "BASE", } - volume_uuid, err := client.CreateVolume(req) + volumeUUID, err := client.CreateVolume(req) if err != nil { log.Fatalf("Error:", err) } - log.Printf("%s", volume_uuid) + log.Printf("%s", volumeUUID) } -``` +``` \ No newline at end of file diff --git a/vendor/github.com/quobyte/api/quobyte.go b/vendor/github.com/quobyte/api/quobyte.go index 88f7c848279..3a2a5fd17a2 100644 --- a/vendor/github.com/quobyte/api/quobyte.go +++ b/vendor/github.com/quobyte/api/quobyte.go @@ -1,7 +1,9 @@ // Package quobyte represents a golang API for the Quobyte Storage System package quobyte -import "net/http" +import ( + "net/http" +) type QuobyteClient struct { client *http.Client @@ -77,3 +79,26 @@ func (client *QuobyteClient) GetClientList(tenant string) (GetClientListResponse return response, nil } + +func (client *QuobyteClient) SetVolumeQuota(volumeUUID string, quotaSize uint64) error { + request := &setQuotaRequest{ + Quotas: []*quota{ + "a{ + Consumer: []*consumingEntity{ + &consumingEntity{ + Type: "VOLUME", + Identifier: volumeUUID, + }, + }, + Limits: []*resource{ + &resource{ + Type: "LOGICAL_DISK_SPACE", + Value: quotaSize, + }, + }, + }, + }, + } + + return client.sendRequest("setQuota", request, nil) +} diff --git a/vendor/github.com/quobyte/api/types.go b/vendor/github.com/quobyte/api/types.go index 2ed5698aa1e..c1a87d33714 100644 --- a/vendor/github.com/quobyte/api/types.go +++ b/vendor/github.com/quobyte/api/types.go @@ -32,3 +32,25 @@ type Client struct { MountedUserName string `json:"mount_user_name,omitempty"` MountedVolumeUUID string `json:"mounted_volume_uuid,omitempty"` } + +type consumingEntity struct { + Type string `json:"type,omitempty"` + Identifier string `json:"identifier,omitempty"` + TenantID string `json:"tenant_id,omitempty"` +} + +type resource struct { + Type string `json:"type,omitempty"` + Value uint64 `json:"value,omitempty"` +} + +type quota struct { + ID string `json:"id,omitempty"` + Consumer []*consumingEntity `json:"consumer,omitempty"` + Limits []*resource `json:"limits,omitempty"` + Currentusage []*resource `json:"current_usage,omitempty"` +} + +type setQuotaRequest struct { + Quotas []*quota `json:"quotas,omitempty"` +} From e631550ef3b23b2ede9774ebc6daf2e7f13f441c Mon Sep 17 00:00:00 2001 From: Johannes Scheuermann Date: Thu, 29 Jun 2017 13:12:24 +0200 Subject: [PATCH 123/448] Make the Quota creation optional --- examples/persistent-volume-provisioning/README.md | 1 + .../quobyte/quobyte-storage-class.yaml | 1 + pkg/volume/quobyte/quobyte.go | 5 ++++- pkg/volume/quobyte/quobyte_util.go | 12 +++++++----- 4 files changed, 13 insertions(+), 6 deletions(-) diff --git a/examples/persistent-volume-provisioning/README.md b/examples/persistent-volume-provisioning/README.md index 4d3f00af648..a2f4753f06c 100644 --- a/examples/persistent-volume-provisioning/README.md +++ b/examples/persistent-volume-provisioning/README.md @@ -256,6 +256,7 @@ parameters: * **group** maps all access to this group. Default is `nfsnobody`. * **quobyteConfig** use the specified configuration to create the volume. You can create a new configuration or modify an existing one with the Web console or the quobyte CLI. Default is `BASE` * **quobyteTenant** use the specified tenant ID to create/delete the volume. This Quobyte tenant has to be already present in Quobyte. For Quobyte < 1.4 use an empty string `""` as `DEFAULT` tenant. Default is `DEFAULT` +* **createQuota** if set all volumes created by this storage class will get a Quota for the specified size. The quota is set for the logical disk size (which can differ from the physical size e.q. if replication is used). Default is ``False First create Quobyte admin's Secret in the system namespace. Here the Secret is created in `kube-system`: diff --git a/examples/persistent-volume-provisioning/quobyte/quobyte-storage-class.yaml b/examples/persistent-volume-provisioning/quobyte/quobyte-storage-class.yaml index 739b94fe916..b9679d61dfb 100644 --- a/examples/persistent-volume-provisioning/quobyte/quobyte-storage-class.yaml +++ b/examples/persistent-volume-provisioning/quobyte/quobyte-storage-class.yaml @@ -12,3 +12,4 @@ parameters: group: "root" quobyteConfig: "BASE" quobyteTenant: "DEFAULT" + createQuota: "False" diff --git a/pkg/volume/quobyte/quobyte.go b/pkg/volume/quobyte/quobyte.go index 7cc98138916..5fae74de721 100644 --- a/pkg/volume/quobyte/quobyte.go +++ b/pkg/volume/quobyte/quobyte.go @@ -365,6 +365,7 @@ func (provisioner *quobyteVolumeProvisioner) Provision() (*v1.PersistentVolume, } provisioner.config = "BASE" provisioner.tenant = "DEFAULT" + createQuota := false cfg, err := parseAPIConfig(provisioner.plugin, provisioner.options.Parameters) if err != nil { @@ -382,6 +383,8 @@ func (provisioner *quobyteVolumeProvisioner) Provision() (*v1.PersistentVolume, provisioner.tenant = v case "quobyteconfig": provisioner.config = v + case "createquota": + createQuota = gostrings.ToLower(v) == "true" case "adminsecretname", "adminsecretnamespace", "quobyteapiserver": @@ -402,7 +405,7 @@ func (provisioner *quobyteVolumeProvisioner) Provision() (*v1.PersistentVolume, config: cfg, } - vol, sizeGB, err := manager.createVolume(provisioner) + vol, sizeGB, err := manager.createVolume(provisioner, createQuota) if err != nil { return nil, err } diff --git a/pkg/volume/quobyte/quobyte_util.go b/pkg/volume/quobyte/quobyte_util.go index e094133bf48..2b5db49fa23 100644 --- a/pkg/volume/quobyte/quobyte_util.go +++ b/pkg/volume/quobyte/quobyte_util.go @@ -32,7 +32,7 @@ type quobyteVolumeManager struct { config *quobyteAPIConfig } -func (manager *quobyteVolumeManager) createVolume(provisioner *quobyteVolumeProvisioner) (quobyte *v1.QuobyteVolumeSource, size int, err error) { +func (manager *quobyteVolumeManager) createVolume(provisioner *quobyteVolumeProvisioner, createQuota bool) (quobyte *v1.QuobyteVolumeSource, size int, err error) { capacity := provisioner.options.PVC.Spec.Resources.Requests[v1.ResourceName(v1.ResourceStorage)] volumeSize := int(volume.RoundUpSize(capacity.Value(), 1024*1024*1024)) // Quobyte has the concept of Volumes which doen't have a specific size (they can grow unlimited) @@ -51,10 +51,12 @@ func (manager *quobyteVolumeManager) createVolume(provisioner *quobyteVolumeProv return &v1.QuobyteVolumeSource{}, volumeSize, err } - // Set Quoate for Volume with specified byte size - err = quobyteClient.SetVolumeQuota(volumeUUID, capacity.Value()) - if err != nil { - return &v1.QuobyteVolumeSource{}, volumeSize, err + // Set Quota for Volume with specified byte size + if createQuota { + err = quobyteClient.SetVolumeQuota(volumeUUID, uint64(capacity.Value())) + if err != nil { + return &v1.QuobyteVolumeSource{}, volumeSize, err + } } glog.V(4).Infof("Created Quobyte volume %s", provisioner.volume) From 468b97a746f803ab7278e2996e275ac517639e1b Mon Sep 17 00:00:00 2001 From: FengyunPan Date: Thu, 29 Jun 2017 21:42:47 +0800 Subject: [PATCH 124/448] Update comment for garbagecollector --- pkg/controller/garbagecollector/garbagecollector_test.go | 2 +- pkg/controller/garbagecollector/graph.go | 6 +++--- pkg/controller/garbagecollector/graph_builder.go | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/pkg/controller/garbagecollector/garbagecollector_test.go b/pkg/controller/garbagecollector/garbagecollector_test.go index bfba3a314d4..994db10136e 100644 --- a/pkg/controller/garbagecollector/garbagecollector_test.go +++ b/pkg/controller/garbagecollector/garbagecollector_test.go @@ -272,7 +272,7 @@ func TestProcessEvent(t *testing.T) { var testScenarios = []struct { name string // a series of events that will be supplied to the - // GraphBuilder.eventQueue. + // GraphBuilder.graphChanges. events []event }{ { diff --git a/pkg/controller/garbagecollector/graph.go b/pkg/controller/garbagecollector/graph.go index 59b36c2ebfa..5ced32b7a97 100644 --- a/pkg/controller/garbagecollector/graph.go +++ b/pkg/controller/garbagecollector/graph.go @@ -34,8 +34,8 @@ func (s objectReference) String() string { return fmt.Sprintf("[%s/%s, namespace: %s, name: %s, uid: %s]", s.APIVersion, s.Kind, s.Namespace, s.Name, s.UID) } -// The single-threaded GraphBuilder.processEvent() is the sole writer of the -// nodes. The multi-threaded GarbageCollector.processItem() reads the nodes. +// The single-threaded GraphBuilder.processGraphChanges() is the sole writer of the +// nodes. The multi-threaded GarbageCollector.attemptToDeleteItem() reads the nodes. // WARNING: node has different locks on different fields. setters and getters // use the respective locks, so the return values of the getters can be // inconsistent. @@ -46,7 +46,7 @@ type node struct { // dependents are the nodes that have node.identity as a // metadata.ownerReference. dependents map[*node]struct{} - // this is set by processEvent() if the object has non-nil DeletionTimestamp + // this is set by processGraphChanges() if the object has non-nil DeletionTimestamp // and has the FinalizerDeleteDependents. deletingDependents bool deletingDependentsLock sync.RWMutex diff --git a/pkg/controller/garbagecollector/graph_builder.go b/pkg/controller/garbagecollector/graph_builder.go index 671db1e7c66..4f356667b4e 100644 --- a/pkg/controller/garbagecollector/graph_builder.go +++ b/pkg/controller/garbagecollector/graph_builder.go @@ -259,7 +259,7 @@ func (gb *GraphBuilder) enqueueChanges(e *event) { // addDependentToOwners adds n to owners' dependents list. If the owner does not // exist in the gb.uidToNode yet, a "virtual" node will be created to represent // the owner. The "virtual" node will be enqueued to the attemptToDelete, so that -// processItem() will verify if the owner exists according to the API server. +// attemptToDeleteItem() will verify if the owner exists according to the API server. func (gb *GraphBuilder) addDependentToOwners(n *node, owners []metav1.OwnerReference) { for _, owner := range owners { ownerNode, ok := gb.uidToNode.Read(owner.UID) From fe598e0401aa1d38b5da44087c93199f6d1c0f68 Mon Sep 17 00:00:00 2001 From: Kazuki Suda Date: Thu, 29 Jun 2017 23:12:22 +0900 Subject: [PATCH 125/448] Fix completions for --namespace to override flags Due to not using __kubectl_parse_get, __kubectl_get_namespaces doesn't support to override kubectl flags. --- pkg/kubectl/cmd/cmd.go | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/pkg/kubectl/cmd/cmd.go b/pkg/kubectl/cmd/cmd.go index 1bafc28778c..b96f10c23af 100644 --- a/pkg/kubectl/cmd/cmd.go +++ b/pkg/kubectl/cmd/cmd.go @@ -69,11 +69,7 @@ __kubectl_override_flags() __kubectl_get_namespaces() { - local template kubectl_out - template="{{ range .items }}{{ .metadata.name }} {{ end }}" - if kubectl_out=$(kubectl get -o template --template="${template}" namespace 2>/dev/null); then - COMPREPLY=( $( compgen -W "${kubectl_out[*]}" -- "$cur" ) ) - fi + __kubectl_parse_get "namespace" } __kubectl_config_get_contexts() From 4cdc5247fc0ad6405bc4ce17e5438d23e033d739 Mon Sep 17 00:00:00 2001 From: Kazuki Suda Date: Thu, 29 Jun 2017 23:26:50 +0900 Subject: [PATCH 126/448] Rename function to follow other similar functions --- pkg/kubectl/cmd/cmd.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/pkg/kubectl/cmd/cmd.go b/pkg/kubectl/cmd/cmd.go index b96f10c23af..8e2aa76ba7c 100644 --- a/pkg/kubectl/cmd/cmd.go +++ b/pkg/kubectl/cmd/cmd.go @@ -67,11 +67,6 @@ __kubectl_override_flags() done } -__kubectl_get_namespaces() -{ - __kubectl_parse_get "namespace" -} - __kubectl_config_get_contexts() { __kubectl_parse_config "contexts" @@ -115,6 +110,11 @@ __kubectl_get_resource() __kubectl_parse_get "${nouns[${#nouns[@]} -1]}" } +__kubectl_get_resource_namespace() +{ + __kubectl_parse_get "namespace" +} + __kubectl_get_resource_pod() { __kubectl_parse_get "pod" @@ -240,7 +240,7 @@ __custom_func() { var ( bash_completion_flags = map[string]string{ - "namespace": "__kubectl_get_namespaces", + "namespace": "__kubectl_get_resource_namespace", "context": "__kubectl_config_get_contexts", "cluster": "__kubectl_config_get_clusters", "user": "__kubectl_config_get_users", From c4e84e263c59f2976a7f1af8e949c7676b4b3877 Mon Sep 17 00:00:00 2001 From: Koonwah Chen Date: Thu, 29 Jun 2017 10:04:53 -0700 Subject: [PATCH 127/448] Change KUBE_GCE_API_ENDPOINT to GCE_API_ENDPOINT --- cluster/common.sh | 2 +- cluster/gce/config-default.sh | 2 +- cluster/gce/gci/configure-helper.sh | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/cluster/common.sh b/cluster/common.sh index 951826cbe65..0c793ddec6e 100755 --- a/cluster/common.sh +++ b/cluster/common.sh @@ -665,7 +665,7 @@ ENABLE_APISERVER_BASIC_AUDIT: $(yaml-quote ${ENABLE_APISERVER_BASIC_AUDIT:-}) ENABLE_APISERVER_ADVANCED_AUDIT: $(yaml-quote ${ENABLE_APISERVER_ADVANCED_AUDIT:-}) ENABLE_CACHE_MUTATION_DETECTOR: $(yaml-quote ${ENABLE_CACHE_MUTATION_DETECTOR:-false}) ADVANCED_AUDIT_BACKEND: $(yaml-quote ${ADVANCED_AUDIT_BACKEND:-log}) -KUBE_GCE_API_ENDPOINT: $(yaml-quote ${KUBE_GCE_API_ENDPOINT:-}) +GCE_API_ENDPOINT: $(yaml-quote ${GCE_API_ENDPOINT:-}) EOF if [ -n "${KUBELET_PORT:-}" ]; then cat >>$file </etc/gce.conf [global] EOF - if [[ -n "${KUBE_GCE_API_ENDPOINT:-}" ]]; then + if [[ -n "${GCE_API_ENDPOINT:-}" ]]; then cat <>/etc/gce.conf -api-endpoint = ${KUBE_GCE_API_ENDPOINT} +api-endpoint = ${GCE_API_ENDPOINT} EOF fi if [[ -n "${PROJECT_ID:-}" && -n "${TOKEN_URL:-}" && -n "${TOKEN_BODY:-}" && -n "${NODE_NETWORK:-}" ]]; then From c0621061c8b3ae6a464a77f246bc0529a7e7923b Mon Sep 17 00:00:00 2001 From: Chris Hoge Date: Thu, 29 Jun 2017 09:33:05 -0700 Subject: [PATCH 128/448] Add configuration for swift container name Fixes Issue #47966 --- cluster/openstack-heat/config-default.sh | 3 +++ cluster/openstack-heat/util.sh | 8 ++++---- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/cluster/openstack-heat/config-default.sh b/cluster/openstack-heat/config-default.sh index 66702a3e9f3..bc6fb3aa726 100644 --- a/cluster/openstack-heat/config-default.sh +++ b/cluster/openstack-heat/config-default.sh @@ -43,6 +43,9 @@ CLUSTER_IP_RANGE=${CLUSTER_IP_RANGE:-10.244.0.0/16} SWIFT_SERVER_URL=${SWIFT_SERVER_URL:-} +# The name of the object store container to use +SWIFT_OBJECT_STORE=${SWIFT_OBJECT_STORE:-kubernetes} + # Flag indicates if new image must be created. If 'false' then image with IMAGE_ID will be used. # If 'true' then new image will be created from file config-image.sh CREATE_IMAGE=${CREATE_IMAGE:-true} # use "true" for devstack diff --git a/cluster/openstack-heat/util.sh b/cluster/openstack-heat/util.sh index 66726db3e23..c81b16cc201 100644 --- a/cluster/openstack-heat/util.sh +++ b/cluster/openstack-heat/util.sh @@ -108,7 +108,7 @@ function create-stack() { # ROOT # KUBERNETES_RELEASE_TAR function upload-resources() { - swift post kubernetes --read-acl '.r:*,.rlistings' + swift post ${SWIFT_OBJECT_STORE} --read-acl '.r:*,.rlistings' locations=( "${ROOT}/../../_output/release-tars/${KUBERNETES_RELEASE_TAR}" @@ -119,11 +119,11 @@ function upload-resources() { RELEASE_TAR_PATH=$(dirname ${RELEASE_TAR_LOCATION}) echo "[INFO] Uploading ${KUBERNETES_RELEASE_TAR}" - swift upload kubernetes ${RELEASE_TAR_PATH}/${KUBERNETES_RELEASE_TAR} \ + swift upload ${SWIFT_OBJECT_STORE} ${RELEASE_TAR_PATH}/${KUBERNETES_RELEASE_TAR} \ --object-name kubernetes-server.tar.gz echo "[INFO] Uploading kubernetes-salt.tar.gz" - swift upload kubernetes ${RELEASE_TAR_PATH}/kubernetes-salt.tar.gz \ + swift upload ${SWIFT_OBJECT_STORE} ${RELEASE_TAR_PATH}/kubernetes-salt.tar.gz \ --object-name kubernetes-salt.tar.gz } @@ -196,7 +196,7 @@ function run-heat-script() { fi SWIFT_SERVER_URL=$(openstack catalog show object-store --format value | egrep -o "$rgx" | cut -d" " -f2 | head -n 1) fi - local swift_repo_url="${SWIFT_SERVER_URL}/kubernetes" + local swift_repo_url="${SWIFT_SERVER_URL}/${SWIFT_OBJECT_STORE}" if [ $CREATE_IMAGE = true ]; then echo "[INFO] Retrieve new image ID" From fee83f65d4e194d651389a4323d5a0fe3ddccc9a Mon Sep 17 00:00:00 2001 From: Jiaying Zhang Date: Wed, 21 Jun 2017 17:55:47 -0700 Subject: [PATCH 129/448] Add unit test coverage for nvidiaGPUManager initialization Part of #47750 ```release-note NONE ``` --- pkg/kubelet/gpu/nvidia/BUILD | 1 + .../gpu/nvidia/nvidia_gpu_manager_test.go | 31 +++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/pkg/kubelet/gpu/nvidia/BUILD b/pkg/kubelet/gpu/nvidia/BUILD index cb136291152..c785ddebad1 100644 --- a/pkg/kubelet/gpu/nvidia/BUILD +++ b/pkg/kubelet/gpu/nvidia/BUILD @@ -44,6 +44,7 @@ go_test( library = ":go_default_library", tags = ["automanaged"], deps = [ + "//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", diff --git a/pkg/kubelet/gpu/nvidia/nvidia_gpu_manager_test.go b/pkg/kubelet/gpu/nvidia/nvidia_gpu_manager_test.go index d8613de527c..dc7253f0940 100644 --- a/pkg/kubelet/gpu/nvidia/nvidia_gpu_manager_test.go +++ b/pkg/kubelet/gpu/nvidia/nvidia_gpu_manager_test.go @@ -17,6 +17,8 @@ limitations under the License. package nvidia import ( + "os" + "reflect" "testing" "github.com/stretchr/testify/assert" @@ -26,6 +28,7 @@ import ( 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/libdocker" ) type testActivePodsLister struct { @@ -60,6 +63,34 @@ func makeTestPod(numContainers, gpusPerContainer int) *v1.Pod { 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. + fakeDocker := libdocker.NewFakeDockerClient() + testGpuManager2, err := NewNvidiaGPUManager(podLister, fakeDocker) + 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{} From 0db5b3716538217f0f4fce860d2fa2fe4b5f09d3 Mon Sep 17 00:00:00 2001 From: Koonwah Chen Date: Thu, 29 Jun 2017 10:42:29 -0700 Subject: [PATCH 130/448] testing fixed hack/verify-gofmt.sh and hack/verify-flags-underscore.py --- hack/verify-flags/known-flags.txt | 1 + pkg/cloudprovider/providers/gce/gce.go | 12 ++++++------ 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/hack/verify-flags/known-flags.txt b/hack/verify-flags/known-flags.txt index b504324bb95..a4422ddce5e 100644 --- a/hack/verify-flags/known-flags.txt +++ b/hack/verify-flags/known-flags.txt @@ -297,6 +297,7 @@ gather-logs-sizes gather-metrics-at-teardown gather-resource-usage gather-suite-metrics-at-teardown +gce-api-endpoint gce-multizone gce-project gce-service-account diff --git a/pkg/cloudprovider/providers/gce/gce.go b/pkg/cloudprovider/providers/gce/gce.go index 4e60519daaf..c88064fab6d 100644 --- a/pkg/cloudprovider/providers/gce/gce.go +++ b/pkg/cloudprovider/providers/gce/gce.go @@ -194,16 +194,16 @@ func newGCECloud(config io.Reader) (*GCECloud, error) { projectID = cfg.Global.ProjectID } - if cfg.Global.NetworkName != "" && strings.Contains(cfg.Global.NetworkName, "/"){ + if cfg.Global.NetworkName != "" && strings.Contains(cfg.Global.NetworkName, "/") { networkURL = cfg.Global.NetworkName - }else { + } else { networkURL = gceNetworkURL(apiEndpoint, projectID, networkName) } - if cfg.Global.SubnetworkName != "" && strings.Contains(cfg.Global.SubnetworkName, "/"){ - subnetworkURL = cfg.Global.SubnetworkName - }else { - subnetworkURL = gceSubnetworkURL(apiEndpoint, cfg.Global.ProjectID, region, cfg.Global.SubnetworkName) + if cfg.Global.SubnetworkName != "" && strings.Contains(cfg.Global.SubnetworkName, "/") { + subnetworkURL = cfg.Global.SubnetworkName + } else { + subnetworkURL = gceSubnetworkURL(apiEndpoint, cfg.Global.ProjectID, region, cfg.Global.SubnetworkName) } if cfg.Global.TokenURL != "" { tokenSource = NewAltTokenSource(cfg.Global.TokenURL, cfg.Global.TokenBody) From 8469b013333baec0dc2fc43a6bfb7493fcf019e8 Mon Sep 17 00:00:00 2001 From: Aaron Crickenberger Date: Thu, 8 Jun 2017 15:41:46 -0700 Subject: [PATCH 131/448] TestLoopbackHostPort should accept IPv6 loopback host --- .../k8s.io/apiserver/pkg/server/config_selfclient_test.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/staging/src/k8s.io/apiserver/pkg/server/config_selfclient_test.go b/staging/src/k8s.io/apiserver/pkg/server/config_selfclient_test.go index d76e31f8eb7..a28e1937b68 100644 --- a/staging/src/k8s.io/apiserver/pkg/server/config_selfclient_test.go +++ b/staging/src/k8s.io/apiserver/pkg/server/config_selfclient_test.go @@ -17,7 +17,7 @@ limitations under the License. package server import ( - "strings" + "net" "testing" ) @@ -37,8 +37,8 @@ func TestLoopbackHostPort(t *testing.T) { if err != nil { t.Fatalf("unexpected error: %v", err) } - if !strings.HasPrefix(host, "127.") { - t.Fatalf("expected host to start with 127., got %q", host) + if ip := net.ParseIP(host); ip == nil || !ip.IsLoopback() { + t.Fatalf("expected host to be loopback, got %q", host) } if port != "443" { t.Fatalf("expected 443 as port, got %q", port) From 642154a7a3d695af9ae3c38df8754a0774c90407 Mon Sep 17 00:00:00 2001 From: Nick Sardo Date: Thu, 29 Jun 2017 12:05:32 -0700 Subject: [PATCH 132/448] Do not fail on error when deleting ingress --- test/e2e/framework/ingress_utils.go | 9 ++++++--- test/e2e/ingress.go | 4 ++-- test/e2e/upgrades/ingress.go | 2 +- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/test/e2e/framework/ingress_utils.go b/test/e2e/framework/ingress_utils.go index 92d0ef59f0c..64ab85b2cf8 100644 --- a/test/e2e/framework/ingress_utils.go +++ b/test/e2e/framework/ingress_utils.go @@ -882,9 +882,12 @@ func (j *IngressTestJig) GetRootCA(secretName string) (rootCA []byte) { return } -// DeleteIngress deletes the ingress resource -func (j *IngressTestJig) DeleteIngress() { - ExpectNoError(j.Client.Extensions().Ingresses(j.Ingress.Namespace).Delete(j.Ingress.Name, nil)) +// TryDeleteIngress attempts to delete the ingress resource and logs errors if they occur. +func (j *IngressTestJig) TryDeleteIngress() { + err := j.Client.Extensions().Ingresses(j.Ingress.Namespace).Delete(j.Ingress.Name, nil) + if err != nil { + Logf("Error while deleting the ingress %v/%v: %v", j.Ingress.Namespace, j.Ingress.Name, err) + } } // WaitForIngress waits till the ingress acquires an IP, then waits for its diff --git a/test/e2e/ingress.go b/test/e2e/ingress.go index b4d3e34943d..70199d04741 100644 --- a/test/e2e/ingress.go +++ b/test/e2e/ingress.go @@ -89,7 +89,7 @@ var _ = framework.KubeDescribe("Loadbalancing: L7", func() { return } By("Deleting ingress") - jig.DeleteIngress() + jig.TryDeleteIngress() By("Cleaning up cloud resources") framework.CleanupGCEIngressController(gceController) @@ -179,7 +179,7 @@ var _ = framework.KubeDescribe("Loadbalancing: L7", func() { return } By("Deleting ingress") - jig.DeleteIngress() + jig.TryDeleteIngress() }) It("should conform to Ingress spec", func() { diff --git a/test/e2e/upgrades/ingress.go b/test/e2e/upgrades/ingress.go index 1a6ace7e0d0..7ca9e3b7d13 100644 --- a/test/e2e/upgrades/ingress.go +++ b/test/e2e/upgrades/ingress.go @@ -101,7 +101,7 @@ func (t *IngressUpgradeTest) Teardown(f *framework.Framework) { } if t.jig.Ingress != nil { By("Deleting ingress") - t.jig.DeleteIngress() + t.jig.TryDeleteIngress() } else { By("No ingress created, no cleanup necessary") } From 6da0c1106369040017bf12374499e15c60f52762 Mon Sep 17 00:00:00 2001 From: Minhan Xia Date: Thu, 13 Apr 2017 15:29:13 -0700 Subject: [PATCH 133/448] add dockershim checkpoint node e2e test --- hack/verify-flags/known-flags.txt | 1 + test/e2e/framework/test_context.go | 4 +- test/e2e_node/BUILD | 2 + test/e2e_node/dockershim_checkpoint_test.go | 224 ++++++++++++++++++++ 4 files changed, 230 insertions(+), 1 deletion(-) create mode 100644 test/e2e_node/dockershim_checkpoint_test.go diff --git a/hack/verify-flags/known-flags.txt b/hack/verify-flags/known-flags.txt index 991aa53aa75..be556bddcbb 100644 --- a/hack/verify-flags/known-flags.txt +++ b/hack/verify-flags/known-flags.txt @@ -185,6 +185,7 @@ docker-exec-handler docker-password docker-server docker-username +dockershim-checkpoint-dir driver-port drop-embedded-fields dry-run diff --git a/test/e2e/framework/test_context.go b/test/e2e/framework/test_context.go index 5945867e395..5d9d01c6f8d 100644 --- a/test/e2e/framework/test_context.go +++ b/test/e2e/framework/test_context.go @@ -39,7 +39,8 @@ type TestContextType struct { CertDir string Host string // TODO: Deprecating this over time... instead just use gobindata_util.go , see #23987. - RepoRoot string + RepoRoot string + DockershimCheckpointDir string Provider string CloudConfig CloudConfig @@ -181,6 +182,7 @@ func RegisterCommonFlags() { flag.StringVar(&TestContext.ContainerRuntime, "container-runtime", "docker", "The container runtime of cluster VM instances (docker/rkt/remote).") flag.StringVar(&TestContext.ContainerRuntimeEndpoint, "container-runtime-endpoint", "", "The container runtime endpoint of cluster VM instances.") flag.StringVar(&TestContext.ImageServiceEndpoint, "image-service-endpoint", "", "The image service endpoint of cluster VM instances.") + flag.StringVar(&TestContext.DockershimCheckpointDir, "dockershim-checkpoint-dir", "/var/lib/dockershim/sandbox", "The directory for dockershim to store sandbox checkpoints.") } // Register flags specific to the cluster e2e test suite. diff --git a/test/e2e_node/BUILD b/test/e2e_node/BUILD index 0d88c27ae00..1ca164d6271 100644 --- a/test/e2e_node/BUILD +++ b/test/e2e_node/BUILD @@ -70,6 +70,7 @@ go_test( "critical_pod_test.go", "density_test.go", "disk_eviction_test.go", + "dockershim_checkpoint_test.go", "dynamic_kubelet_configuration_test.go", "e2e_node_suite_test.go", "garbage_collector_test.go", @@ -138,6 +139,7 @@ go_test( "//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/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/client-go/tools/cache:go_default_library", diff --git a/test/e2e_node/dockershim_checkpoint_test.go b/test/e2e_node/dockershim_checkpoint_test.go new file mode 100644 index 00000000000..f3738701ed1 --- /dev/null +++ b/test/e2e_node/dockershim_checkpoint_test.go @@ -0,0 +1,224 @@ +/* +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 ( + "crypto/md5" + "fmt" + "os" + "os/exec" + "path" + "regexp" + "strings" + "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" + "k8s.io/apimachinery/pkg/util/wait" + "k8s.io/kubernetes/test/e2e/framework" +) + +const ( + testCheckpoint = "checkpoint-test" + // Container GC Period is 1 minute + gcTimeout = 3 * time.Minute + testCheckpointContent = `{"version":"v1","name":"fluentd-gcp-v2.0-vmnqx","namespace":"kube-system","data":{},"checksum":1799154314}` +) + +var _ = framework.KubeDescribe("Dockershim [Serial] [Disruptive] [Feature:Docker]", func() { + f := framework.NewDefaultFramework("dockerhism-checkpoint-test") + + It("should clean up pod sandbox checkpoint after pod deletion", func() { + podName := "pod-checkpoint-no-disrupt" + runPodCheckpointTest(f, podName, func() { + checkpoints := findCheckpoints(podName) + if len(checkpoints) == 0 { + framework.Failf("No checkpoint for the pod was found") + } + }) + }) + + It("should remove dangling checkpoint file", func() { + filename := fmt.Sprintf("%x", md5.Sum([]byte(fmt.Sprintf("%s/%s", testCheckpoint, f.Namespace.Name)))) + fullpath := path.Join(framework.TestContext.DockershimCheckpointDir, filename) + + By(fmt.Sprintf("Write a file at %q", fullpath)) + err := writeFileAndSync(fullpath, []byte(testCheckpointContent)) + framework.ExpectNoError(err, "Failed to create file %q", fullpath) + + By("Check if file is removed") + Eventually(func() bool { + if _, err := os.Stat(fullpath); os.IsNotExist(err) { + return true + } + return false + }, gcTimeout, 10*time.Second).Should(BeTrue()) + + }) + + Context("When pod sandbox checkpoint is missing", func() { + It("should complete pod sandbox clean up", func() { + podName := "pod-checkpoint-missing" + runPodCheckpointTest(f, podName, func() { + checkpoints := findCheckpoints(podName) + if len(checkpoints) == 0 { + framework.Failf("No checkpoint for the pod was found") + } + By("Removing checkpoint of test pod") + for _, filename := range checkpoints { + if len(filename) == 0 { + continue + } + framework.Logf("Removing checkpiont %q", filename) + _, err := exec.Command("sudo", "rm", filename).CombinedOutput() + framework.ExpectNoError(err, "Failed to remove checkpoint file %q: %v", string(filename), err) + } + }) + }) + }) + + Context("When all containers in pod are missing", func() { + It("should complete pod sandbox clean up based on the information in sandbox checkpoint", func() { + runPodCheckpointTest(f, "pod-containers-missing", func() { + By("Gathering pod container ids") + stdout, err := exec.Command("sudo", "docker", "ps", "-q", "-f", + fmt.Sprintf("name=%s", f.Namespace.Name)).CombinedOutput() + framework.ExpectNoError(err, "Failed to run docker ps: %v", err) + lines := strings.Split(string(stdout), "\n") + ids := []string{} + for _, id := range lines { + id = cleanString(id) + if len(id) > 0 { + ids = append(ids, id) + } + } + + By("Stop and remove pod containers") + dockerStopCmd := append([]string{"docker", "stop"}, ids...) + _, err = exec.Command("sudo", dockerStopCmd...).CombinedOutput() + framework.ExpectNoError(err, "Failed to run command %v: %v", dockerStopCmd, err) + dockerRmCmd := append([]string{"docker", "rm"}, ids...) + _, err = exec.Command("sudo", dockerRmCmd...).CombinedOutput() + framework.ExpectNoError(err, "Failed to run command %v: %v", dockerRmCmd, err) + }) + }) + }) + + Context("When checkpoint file is corrupted", func() { + It("should complete pod sandbox clean up", func() { + podName := "pod-checkpoint-corrupted" + runPodCheckpointTest(f, podName, func() { + By("Corrupt checkpoint file") + checkpoints := findCheckpoints(podName) + if len(checkpoints) == 0 { + framework.Failf("No checkpoint for the pod was found") + } + for _, file := range checkpoints { + f, err := os.OpenFile(file, os.O_WRONLY|os.O_APPEND, 0644) + framework.ExpectNoError(err, "Failed to open file %q", file) + _, err = f.WriteString("blabblab") + framework.ExpectNoError(err, "Failed to write to file %q", file) + f.Sync() + f.Close() + } + }) + }) + }) +}) + +func runPodCheckpointTest(f *framework.Framework, podName string, twist func()) { + podName = podName + string(uuid.NewUUID()) + By(fmt.Sprintf("Creating test pod: %s", podName)) + f.PodClient().CreateSync(&v1.Pod{ + ObjectMeta: metav1.ObjectMeta{Name: podName}, + Spec: v1.PodSpec{ + Containers: []v1.Container{ + { + Image: framework.GetPauseImageName(f.ClientSet), + Name: "pause-container", + }, + }, + }, + }) + + By("Performing disruptive operations") + twist() + + By("Remove test pod") + f.PodClient().DeleteSync(podName, &metav1.DeleteOptions{}, framework.DefaultPodDeletionTimeout) + + By("Waiting for checkpoint to be removed") + if err := wait.PollImmediate(10*time.Second, gcTimeout, func() (bool, error) { + checkpoints := findCheckpoints(podName) + if len(checkpoints) == 0 { + return true, nil + } + framework.Logf("Checkpoint of %q still exists: %v", podName, checkpoints) + return false, nil + }); err != nil { + framework.Failf("Failed to observe checkpoint being removed within timeout: %v", err) + } +} + +// cleanString cleans up any trailing spaces and new line character for the input string +func cleanString(output string) string { + processed := strings.TrimSpace(string(output)) + regex := regexp.MustCompile(`\r?\n`) + processed = regex.ReplaceAllString(processed, "") + return processed +} + +func writeFileAndSync(path string, data []byte) error { + f, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644) + if err != nil { + return err + } + _, err = f.Write(data) + if err != nil { + return err + } + f.Sync() + if err1 := f.Close(); err == nil { + err = err1 + } + return err +} + +// findCheckpoints returns all checkpoint files containing input string +func findCheckpoints(match string) []string { + By(fmt.Sprintf("Search checkpoints containing %q", match)) + checkpoints := []string{} + stdout, err := exec.Command("sudo", "grep", "-rl", match, framework.TestContext.DockershimCheckpointDir).CombinedOutput() + if err != nil { + framework.Logf("grep from dockershim checkpoint directory returns error: %v", err) + } + if stdout == nil { + return checkpoints + } + files := strings.Split(string(stdout), "\n") + for _, file := range files { + cleaned := cleanString(file) + if len(cleaned) == 0 { + continue + } + checkpoints = append(checkpoints, cleaned) + } + return checkpoints +} From 6660726ce676282422c32813b537f97bb8fff374 Mon Sep 17 00:00:00 2001 From: ymqytw Date: Thu, 29 Jun 2017 14:49:51 -0700 Subject: [PATCH 134/448] eliminate kubectl dependency on k8s.io/kubernetes/pkg/util --- pkg/kubectl/BUILD | 1 - pkg/kubectl/proxy_server.go | 2 +- pkg/kubectl/stop.go | 4 ++-- pkg/kubectl/util/BUILD | 5 ++++- pkg/{ => kubectl}/util/umask.go | 0 pkg/util/BUILD | 1 - 6 files changed, 7 insertions(+), 6 deletions(-) rename pkg/{ => kubectl}/util/umask.go (100%) diff --git a/pkg/kubectl/BUILD b/pkg/kubectl/BUILD index 9e953c04dde..6bad6f9c8e0 100644 --- a/pkg/kubectl/BUILD +++ b/pkg/kubectl/BUILD @@ -145,7 +145,6 @@ go_library( "//pkg/kubectl/util:go_default_library", "//pkg/printers:go_default_library", "//pkg/printers/internalversion:go_default_library", - "//pkg/util:go_default_library", "//pkg/util/slice:go_default_library", "//vendor/github.com/emicklei/go-restful-swagger12:go_default_library", "//vendor/github.com/golang/glog:go_default_library", diff --git a/pkg/kubectl/proxy_server.go b/pkg/kubectl/proxy_server.go index ce60727b4b8..f1712287ee9 100644 --- a/pkg/kubectl/proxy_server.go +++ b/pkg/kubectl/proxy_server.go @@ -29,7 +29,7 @@ import ( "github.com/golang/glog" restclient "k8s.io/client-go/rest" - "k8s.io/kubernetes/pkg/util" + "k8s.io/kubernetes/pkg/kubectl/util" ) const ( diff --git a/pkg/kubectl/stop.go b/pkg/kubectl/stop.go index 86510ac02af..f104f4f1e08 100644 --- a/pkg/kubectl/stop.go +++ b/pkg/kubectl/stop.go @@ -38,7 +38,6 @@ import ( 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" - "k8s.io/kubernetes/pkg/util" ) const ( @@ -401,7 +400,8 @@ func (reaper *DeploymentReaper) Stop(namespace, name string, timeout time.Durati 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 - d.Spec.RevisionHistoryLimit = util.Int32Ptr(0) + rhl := int32(0) + d.Spec.RevisionHistoryLimit = &rhl d.Spec.Replicas = 0 d.Spec.Paused = true }) diff --git a/pkg/kubectl/util/BUILD b/pkg/kubectl/util/BUILD index f4113db90fe..5cf656bc508 100644 --- a/pkg/kubectl/util/BUILD +++ b/pkg/kubectl/util/BUILD @@ -7,7 +7,10 @@ load( go_library( name = "go_default_library", - srcs = ["util.go"], + srcs = [ + "umask.go", + "util.go", + ], tags = ["automanaged"], visibility = ["//build/visible_to:pkg_kubectl_util_CONSUMERS"], deps = [ diff --git a/pkg/util/umask.go b/pkg/kubectl/util/umask.go similarity index 100% rename from pkg/util/umask.go rename to pkg/kubectl/util/umask.go diff --git a/pkg/util/BUILD b/pkg/util/BUILD index 6dcbb4086b3..e72b6f2e2fa 100644 --- a/pkg/util/BUILD +++ b/pkg/util/BUILD @@ -13,7 +13,6 @@ go_library( srcs = [ "doc.go", "template.go", - "umask.go", "util.go", ], tags = ["automanaged"], From 2510a4737467818e501c7aeb66deb46aa5acef11 Mon Sep 17 00:00:00 2001 From: ymqytw Date: Thu, 29 Jun 2017 14:57:06 -0700 Subject: [PATCH 135/448] move crlf to kubectl/util --- pkg/kubectl/cmd/util/editor/BUILD | 2 +- pkg/kubectl/cmd/util/editor/editoptions.go | 2 +- pkg/kubectl/util/BUILD | 5 ++++- pkg/{ => kubectl}/util/crlf/BUILD | 0 pkg/{ => kubectl}/util/crlf/crlf.go | 0 pkg/util/BUILD | 1 - 6 files changed, 6 insertions(+), 4 deletions(-) rename pkg/{ => kubectl}/util/crlf/BUILD (100%) rename pkg/{ => kubectl}/util/crlf/crlf.go (100%) diff --git a/pkg/kubectl/cmd/util/editor/BUILD b/pkg/kubectl/cmd/util/editor/BUILD index 68e18edf45a..63544fd287d 100644 --- a/pkg/kubectl/cmd/util/editor/BUILD +++ b/pkg/kubectl/cmd/util/editor/BUILD @@ -21,8 +21,8 @@ go_library( "//pkg/kubectl:go_default_library", "//pkg/kubectl/cmd/util:go_default_library", "//pkg/kubectl/resource:go_default_library", + "//pkg/kubectl/util/crlf:go_default_library", "//pkg/printers:go_default_library", - "//pkg/util/crlf:go_default_library", "//pkg/util/term:go_default_library", "//vendor/github.com/evanphx/json-patch:go_default_library", "//vendor/github.com/golang/glog:go_default_library", diff --git a/pkg/kubectl/cmd/util/editor/editoptions.go b/pkg/kubectl/cmd/util/editor/editoptions.go index df4b88b631b..9353314b78f 100644 --- a/pkg/kubectl/cmd/util/editor/editoptions.go +++ b/pkg/kubectl/cmd/util/editor/editoptions.go @@ -44,8 +44,8 @@ import ( "k8s.io/kubernetes/pkg/kubectl" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" "k8s.io/kubernetes/pkg/kubectl/resource" + "k8s.io/kubernetes/pkg/kubectl/util/crlf" "k8s.io/kubernetes/pkg/printers" - "k8s.io/kubernetes/pkg/util/crlf" ) // EditOptions contains all the options for running edit cli command. diff --git a/pkg/kubectl/util/BUILD b/pkg/kubectl/util/BUILD index f4113db90fe..31049056699 100644 --- a/pkg/kubectl/util/BUILD +++ b/pkg/kubectl/util/BUILD @@ -25,7 +25,10 @@ filegroup( filegroup( name = "all-srcs", - srcs = [":package-srcs"], + srcs = [ + ":package-srcs", + "//pkg/kubectl/util/crlf:all-srcs", + ], tags = ["automanaged"], visibility = ["//build/visible_to:pkg_kubectl_util_CONSUMERS"], ) diff --git a/pkg/util/crlf/BUILD b/pkg/kubectl/util/crlf/BUILD similarity index 100% rename from pkg/util/crlf/BUILD rename to pkg/kubectl/util/crlf/BUILD diff --git a/pkg/util/crlf/crlf.go b/pkg/kubectl/util/crlf/crlf.go similarity index 100% rename from pkg/util/crlf/crlf.go rename to pkg/kubectl/util/crlf/crlf.go diff --git a/pkg/util/BUILD b/pkg/util/BUILD index 6dcbb4086b3..e7899341bda 100644 --- a/pkg/util/BUILD +++ b/pkg/util/BUILD @@ -48,7 +48,6 @@ filegroup( "//pkg/util/bandwidth:all-srcs", "//pkg/util/config:all-srcs", "//pkg/util/configz:all-srcs", - "//pkg/util/crlf:all-srcs", "//pkg/util/dbus:all-srcs", "//pkg/util/ebtables:all-srcs", "//pkg/util/env:all-srcs", From e9795e3742dd275be8c3e5b59144fe9dc810c081 Mon Sep 17 00:00:00 2001 From: "Tim St. Clair" Date: Thu, 29 Jun 2017 15:58:07 -0700 Subject: [PATCH 136/448] Cleanup lint errors in the pkg/kubelet/server/... directory --- pkg/kubelet/server/portforward/websocket.go | 1 - pkg/kubelet/server/remotecommand/httpstream.go | 4 ++-- pkg/kubelet/server/server.go | 8 +++----- pkg/kubelet/server/server_test.go | 15 --------------- pkg/kubelet/server/server_websocket_test.go | 2 +- pkg/kubelet/server/stats/summary_test.go | 7 ------- 6 files changed, 6 insertions(+), 31 deletions(-) diff --git a/pkg/kubelet/server/portforward/websocket.go b/pkg/kubelet/server/portforward/websocket.go index 22d5add067a..cb4bca04558 100644 --- a/pkg/kubelet/server/portforward/websocket.go +++ b/pkg/kubelet/server/portforward/websocket.go @@ -158,7 +158,6 @@ type websocketStreamPair struct { // request over a websocket connection type websocketStreamHandler struct { conn *wsstream.Conn - ports []int32 streamPairs []*websocketStreamPair pod string uid types.UID diff --git a/pkg/kubelet/server/remotecommand/httpstream.go b/pkg/kubelet/server/remotecommand/httpstream.go index f09b5e400b5..9d4883212d9 100644 --- a/pkg/kubelet/server/remotecommand/httpstream.go +++ b/pkg/kubelet/server/remotecommand/httpstream.go @@ -423,7 +423,7 @@ func handleResizeEvents(stream io.Reader, channel chan<- remotecommand.TerminalS } } -func v1WriteStatusFunc(stream io.WriteCloser) func(status *apierrors.StatusError) error { +func v1WriteStatusFunc(stream io.Writer) func(status *apierrors.StatusError) error { return func(status *apierrors.StatusError) error { if status.Status().Status == metav1.StatusSuccess { return nil // send error messages @@ -435,7 +435,7 @@ func v1WriteStatusFunc(stream io.WriteCloser) func(status *apierrors.StatusError // v4WriteStatusFunc returns a WriteStatusFunc that marshals a given api Status // as json in the error channel. -func v4WriteStatusFunc(stream io.WriteCloser) func(status *apierrors.StatusError) error { +func v4WriteStatusFunc(stream io.Writer) func(status *apierrors.StatusError) error { return func(status *apierrors.StatusError) error { bs, err := json.Marshal(status.Status()) if err != nil { diff --git a/pkg/kubelet/server/server.go b/pkg/kubelet/server/server.go index 0b70b89b441..63e0f11ee79 100644 --- a/pkg/kubelet/server/server.go +++ b/pkg/kubelet/server/server.go @@ -267,8 +267,7 @@ func (s *Server) InstallDefaultHandlers() { healthz.PingHealthz, healthz.NamedCheck("syncloop", s.syncLoopHealthCheck), ) - var ws *restful.WebService - ws = new(restful.WebService) + ws := new(restful.WebService) ws. Path("/pods"). Produces(restful.MIME_JSON) @@ -296,9 +295,8 @@ const pprofBasePath = "/debug/pprof/" // InstallDebuggingHandlers registers the HTTP request patterns that serve logs or run commands/containers func (s *Server) InstallDebuggingHandlers(criHandler http.Handler) { glog.Infof("Adding debug handlers to kubelet server.") - var ws *restful.WebService - ws = new(restful.WebService) + ws := new(restful.WebService) ws. Path("/run") ws.Route(ws.POST("/{podNamespace}/{podID}/{containerName}"). @@ -429,7 +427,7 @@ func (s *Server) syncLoopHealthCheck(req *http.Request) error { } enterLoopTime := s.host.LatestLoopEntryTime() if !enterLoopTime.IsZero() && time.Now().After(enterLoopTime.Add(duration)) { - return fmt.Errorf("Sync Loop took longer than expected.") + return fmt.Errorf("sync Loop took longer than expected") } return nil } diff --git a/pkg/kubelet/server/server_test.go b/pkg/kubelet/server/server_test.go index e8b96aa0a11..045a6144b38 100644 --- a/pkg/kubelet/server/server_test.go +++ b/pkg/kubelet/server/server_test.go @@ -248,21 +248,6 @@ func newServerTest() *serverTestFramework { return fw } -// encodeJSON returns obj marshalled as a JSON string, panicing on any errors -func encodeJSON(obj interface{}) string { - data, err := json.Marshal(obj) - if err != nil { - panic(err) - } - return string(data) -} - -func readResp(resp *http.Response) (string, error) { - defer resp.Body.Close() - body, err := ioutil.ReadAll(resp.Body) - return string(body), err -} - // A helper function to return the correct pod name. func getPodName(name, namespace string) string { if namespace == "" { diff --git a/pkg/kubelet/server/server_websocket_test.go b/pkg/kubelet/server/server_websocket_test.go index 080e09fb6b9..058b67d978a 100644 --- a/pkg/kubelet/server/server_websocket_test.go +++ b/pkg/kubelet/server/server_websocket_test.go @@ -172,7 +172,7 @@ func TestServeWSPortForward(t *testing.T) { } if test.containerData != "" { - channel, data, err = wsRead(ws) + _, data, err = wsRead(ws) if err != nil { t.Fatalf("%d: unexpected error reading container data: %v", i, err) } diff --git a/pkg/kubelet/server/stats/summary_test.go b/pkg/kubelet/server/stats/summary_test.go index be604aff3c4..eb39efd44c2 100644 --- a/pkg/kubelet/server/stats/summary_test.go +++ b/pkg/kubelet/server/stats/summary_test.go @@ -376,13 +376,6 @@ func checkMemoryStats(t *testing.T, label string, seed int, info v2.ContainerInf } } -func checkFsStats(t *testing.T, capacity uint64, Available uint64, inodes uint64, inodesFree uint64, fs *kubestats.FsStats) { - assert.EqualValues(t, capacity, *fs.CapacityBytes) - assert.EqualValues(t, Available, *fs.AvailableBytes) - assert.EqualValues(t, inodesFree, *fs.InodesFree) - assert.EqualValues(t, inodes, *fs.Inodes) -} - func TestCustomMetrics(t *testing.T) { spec := []v1.MetricSpec{ { From dc1ee493a29251492403e4282b5df3e897de2214 Mon Sep 17 00:00:00 2001 From: Mikhail Mazurskiy Date: Tue, 27 Jun 2017 12:58:35 +1000 Subject: [PATCH 137/448] Refactor unstructured converter --- pkg/api/unstructured_test.go | 7 +++---- .../pkg/apis/meta/v1/unstructured/unstructured.go | 4 ++-- .../pkg/conversion/unstructured/converter.go | 12 ++++++++---- .../pkg/conversion/unstructured/converter_test.go | 3 +-- .../k8s.io/apiserver/pkg/endpoints/handlers/patch.go | 4 ++-- .../k8s.io/apiserver/pkg/endpoints/handlers/rest.go | 9 ++++----- 6 files changed, 20 insertions(+), 19 deletions(-) diff --git a/pkg/api/unstructured_test.go b/pkg/api/unstructured_test.go index 72de2e329d9..1351ea861ec 100644 --- a/pkg/api/unstructured_test.go +++ b/pkg/api/unstructured_test.go @@ -97,8 +97,7 @@ func doRoundTrip(t *testing.T, group testapi.TestGroup, kind string) { return } - newUnstr := make(map[string]interface{}) - err = unstructured.DefaultConverter.ToUnstructured(item, &newUnstr) + newUnstr, err := unstructured.DefaultConverter.ToUnstructured(item) if err != nil { t.Errorf("ToUnstructured failed: %v", err) return @@ -138,8 +137,8 @@ func BenchmarkToFromUnstructured(b *testing.B) { size := len(items) b.ResetTimer() for i := 0; i < b.N; i++ { - unstr := map[string]interface{}{} - if err := unstructured.DefaultConverter.ToUnstructured(&items[i%size], &unstr); err != nil { + unstr, err := unstructured.DefaultConverter.ToUnstructured(&items[i%size]) + if err != nil { b.Fatalf("unexpected error: %v", err) } obj := v1.Pod{} diff --git a/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/unstructured.go b/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/unstructured.go index d428193738b..e6cf0934a50 100644 --- a/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/unstructured.go +++ b/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/unstructured.go @@ -482,8 +482,8 @@ func (u *Unstructured) SetInitializers(initializers *metav1.Initializers) { setNestedField(u.Object, nil, "metadata", "initializers") return } - out := make(map[string]interface{}) - if err := converter.ToUnstructured(initializers, &out); err != nil { + out, err := converter.ToUnstructured(initializers) + if err != nil { utilruntime.HandleError(fmt.Errorf("unable to retrieve initializers for object: %v", err)) } setNestedField(u.Object, out, "metadata", "initializers") diff --git a/staging/src/k8s.io/apimachinery/pkg/conversion/unstructured/converter.go b/staging/src/k8s.io/apimachinery/pkg/conversion/unstructured/converter.go index cf84a619898..8dab1dbfe93 100644 --- a/staging/src/k8s.io/apimachinery/pkg/conversion/unstructured/converter.go +++ b/staging/src/k8s.io/apimachinery/pkg/conversion/unstructured/converter.go @@ -39,7 +39,7 @@ import ( // Converter is an interface for converting between interface{} // and map[string]interface representation. type Converter interface { - ToUnstructured(obj interface{}, u *map[string]interface{}) error + ToUnstructured(obj interface{}) (map[string]interface{}, error) FromUnstructured(u map[string]interface{}, obj interface{}) error } @@ -388,12 +388,13 @@ func interfaceFromUnstructured(sv, dv reflect.Value) error { return nil } -func (c *converterImpl) ToUnstructured(obj interface{}, u *map[string]interface{}) error { +func (c *converterImpl) ToUnstructured(obj interface{}) (map[string]interface{}, error) { t := reflect.TypeOf(obj) value := reflect.ValueOf(obj) if t.Kind() != reflect.Ptr || value.IsNil() { - return fmt.Errorf("ToUnstructured requires a non-nil pointer to an object, got %v", t) + return nil, fmt.Errorf("ToUnstructured requires a non-nil pointer to an object, got %v", t) } + u := &map[string]interface{}{} err := toUnstructured(value.Elem(), reflect.ValueOf(u).Elem()) if c.mismatchDetection { newUnstr := &map[string]interface{}{} @@ -405,7 +406,10 @@ func (c *converterImpl) ToUnstructured(obj interface{}, u *map[string]interface{ glog.Fatalf("ToUnstructured mismatch for %#v, diff: %v", u, diff.ObjectReflectDiff(u, newUnstr)) } } - return err + if err != nil { + return nil, err + } + return *u, nil } func toUnstructuredViaJSON(obj interface{}, u *map[string]interface{}) error { diff --git a/staging/src/k8s.io/apimachinery/pkg/conversion/unstructured/converter_test.go b/staging/src/k8s.io/apimachinery/pkg/conversion/unstructured/converter_test.go index cbab0d1dad7..68ca9e203f5 100644 --- a/staging/src/k8s.io/apimachinery/pkg/conversion/unstructured/converter_test.go +++ b/staging/src/k8s.io/apimachinery/pkg/conversion/unstructured/converter_test.go @@ -121,8 +121,7 @@ func doRoundTrip(t *testing.T, item runtime.Object) { return } - newUnstr := make(map[string]interface{}) - err = DefaultConverter.ToUnstructured(item, &newUnstr) + newUnstr, err := DefaultConverter.ToUnstructured(item) if err != nil { t.Errorf("ToUnstructured failed: %v", err) return diff --git a/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/patch.go b/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/patch.go index 48c20e5e437..ca585e6ddf4 100644 --- a/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/patch.go +++ b/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/patch.go @@ -87,8 +87,8 @@ func strategicPatchObject( objToUpdate runtime.Object, versionedObj runtime.Object, ) error { - originalObjMap := make(map[string]interface{}) - if err := unstructured.DefaultConverter.ToUnstructured(originalObject, &originalObjMap); err != nil { + originalObjMap, err := unstructured.DefaultConverter.ToUnstructured(originalObject) + if err != nil { return err } diff --git a/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/rest.go b/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/rest.go index f238d447d32..194433ba8eb 100644 --- a/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/rest.go +++ b/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/rest.go @@ -694,8 +694,8 @@ func patchResource( return nil, err } // Capture the original object map and patch for possible retries. - originalMap := make(map[string]interface{}) - if err := unstructured.DefaultConverter.ToUnstructured(currentVersionedObject, &originalMap); err != nil { + originalMap, err := unstructured.DefaultConverter.ToUnstructured(currentVersionedObject) + if err != nil { return nil, err } if err := strategicPatchObject(codec, defaulter, currentVersionedObject, patchJS, versionedObjToUpdate, versionedObj); err != nil { @@ -734,15 +734,14 @@ func patchResource( // 3. ensure no conflicts between the two patches // 4. apply the #1 patch to the currentJS object - currentObjMap := make(map[string]interface{}) - // 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 } - if err := unstructured.DefaultConverter.ToUnstructured(currentVersionedObject, ¤tObjMap); err != nil { + currentObjMap, err := unstructured.DefaultConverter.ToUnstructured(currentVersionedObject) + if err != nil { return nil, err } From 0a1e24f31e5dc1a4f193a6d564ed06e2535b2830 Mon Sep 17 00:00:00 2001 From: Cao Shufeng Date: Fri, 30 Jun 2017 10:51:07 +0800 Subject: [PATCH 138/448] remove useless check from impersonation filter When groupsSpecified is false, that means no other groups are added rather than the service account groups. So this check doesn't make any sense. --- .../apiserver/pkg/endpoints/filters/impersonation.go | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/staging/src/k8s.io/apiserver/pkg/endpoints/filters/impersonation.go b/staging/src/k8s.io/apiserver/pkg/endpoints/filters/impersonation.go index 891b339ecce..1a2d5472478 100644 --- a/staging/src/k8s.io/apiserver/pkg/endpoints/filters/impersonation.go +++ b/staging/src/k8s.io/apiserver/pkg/endpoints/filters/impersonation.go @@ -118,18 +118,8 @@ func WithImpersonation(handler http.Handler, requestContextMapper request.Reques if !groupsSpecified && username != user.Anonymous { // When impersonating a non-anonymous user, if no groups were specified - // if neither the system:authenticated nor system:unauthenticated groups are explicitly included, // include the system:authenticated group in the impersonated user info - found := false - for _, group := range groups { - if group == user.AllAuthenticated || group == user.AllUnauthenticated { - found = true - break - } - } - if !found { - groups = append(groups, user.AllAuthenticated) - } + groups = append(groups, user.AllAuthenticated) } newUser := &user.DefaultInfo{ From f3084cd3835b0c600f0c198f3594085cb181d419 Mon Sep 17 00:00:00 2001 From: Chao Xu Date: Fri, 30 Jun 2017 03:51:28 +0200 Subject: [PATCH 139/448] Update CHANGELOG.md for v1.7.0. --- CHANGELOG.md | 1860 ++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 1653 insertions(+), 207 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3c14c8360f4..a0fb529f799 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,127 +1,142 @@ -- [v1.7.0-rc.1](#v170-rc1) - - [Downloads for v1.7.0-rc.1](#downloads-for-v170-rc1) +- [v1.7.0](#v170) + - [Downloads for v1.7.0](#downloads-for-v170) - [Client Binaries](#client-binaries) - [Server Binaries](#server-binaries) - [Node Binaries](#node-binaries) - - [Changelog since v1.7.0-beta.2](#changelog-since-v170-beta2) - - [Action Required](#action-required) - - [Other notable changes](#other-notable-changes) -- [v1.8.0-alpha.1](#v180-alpha1) - - [Downloads for v1.8.0-alpha.1](#downloads-for-v180-alpha1) + - [**Major Themes**](#major-themes) + - [**Action Required Before Upgrading**](#action-required-before-upgrading) + - [**Known Issues**](#known-issues) + - [**Deprecations**](#deprecations) + - [**Features**](#features) + - [**External Dependency Version Information**](#external-dependency-version-information) + - [**Other notable changes**](#other-notable-changes) +- [Unsorted](#unsorted) + - [Changelog since v1.7.0-rc.1](#changelog-since-v170-rc1) + - [Previous Releases Included in v1.7.0](#previous-releases-included-in-v170) +- [v1.7.0-rc.1](#v170-rc1) + - [Downloads for v1.7.0-rc.1](#downloads-for-v170-rc1) - [Client Binaries](#client-binaries-1) - [Server Binaries](#server-binaries-1) - [Node Binaries](#node-binaries-1) - - [Changelog since v1.7.0-alpha.4](#changelog-since-v170-alpha4) - - [Action Required](#action-required-1) + - [Changelog since v1.7.0-beta.2](#changelog-since-v170-beta2) + - [Action Required](#action-required) - [Other notable changes](#other-notable-changes-1) -- [v1.6.6](#v166) - - [Downloads for v1.6.6](#downloads-for-v166) +- [v1.8.0-alpha.1](#v180-alpha1) + - [Downloads for v1.8.0-alpha.1](#downloads-for-v180-alpha1) - [Client Binaries](#client-binaries-2) - [Server Binaries](#server-binaries-2) - [Node Binaries](#node-binaries-2) - - [Changelog since v1.6.5](#changelog-since-v165) - - [Action Required](#action-required-2) + - [Changelog since v1.7.0-alpha.4](#changelog-since-v170-alpha4) + - [Action Required](#action-required-1) - [Other notable changes](#other-notable-changes-2) -- [v1.7.0-beta.2](#v170-beta2) - - [Downloads for v1.7.0-beta.2](#downloads-for-v170-beta2) +- [v1.6.6](#v166) + - [Downloads for v1.6.6](#downloads-for-v166) - [Client Binaries](#client-binaries-3) - [Server Binaries](#server-binaries-3) - [Node Binaries](#node-binaries-3) - - [Changelog since v1.7.0-beta.1](#changelog-since-v170-beta1) - - [Action Required](#action-required-3) + - [Changelog since v1.6.5](#changelog-since-v165) + - [Action Required](#action-required-2) - [Other notable changes](#other-notable-changes-3) -- [v1.6.5](#v165) - - [Known Issues for v1.6.5](#known-issues-for-v165) - - [Downloads for v1.6.5](#downloads-for-v165) +- [v1.7.0-beta.2](#v170-beta2) + - [Downloads for v1.7.0-beta.2](#downloads-for-v170-beta2) - [Client Binaries](#client-binaries-4) - [Server Binaries](#server-binaries-4) - [Node Binaries](#node-binaries-4) - - [Changelog since v1.6.4](#changelog-since-v164) + - [Changelog since v1.7.0-beta.1](#changelog-since-v170-beta1) + - [Action Required](#action-required-3) - [Other notable changes](#other-notable-changes-4) -- [v1.7.0-beta.1](#v170-beta1) - - [Downloads for v1.7.0-beta.1](#downloads-for-v170-beta1) +- [v1.6.5](#v165) + - [Known Issues for v1.6.5](#known-issues-for-v165) + - [Downloads for v1.6.5](#downloads-for-v165) - [Client Binaries](#client-binaries-5) - [Server Binaries](#server-binaries-5) - [Node Binaries](#node-binaries-5) - - [Changelog since v1.7.0-alpha.4](#changelog-since-v170-alpha4-1) - - [Action Required](#action-required-4) + - [Changelog since v1.6.4](#changelog-since-v164) - [Other notable changes](#other-notable-changes-5) -- [v1.6.4](#v164) - - [Known Issues for v1.6.4](#known-issues-for-v164) - - [Downloads for v1.6.4](#downloads-for-v164) +- [v1.7.0-beta.1](#v170-beta1) + - [Downloads for v1.7.0-beta.1](#downloads-for-v170-beta1) - [Client Binaries](#client-binaries-6) - [Server Binaries](#server-binaries-6) - [Node Binaries](#node-binaries-6) - - [Changelog since v1.6.3](#changelog-since-v163) + - [Changelog since v1.7.0-alpha.4](#changelog-since-v170-alpha4-1) + - [Action Required](#action-required-4) - [Other notable changes](#other-notable-changes-6) -- [v1.7.0-alpha.4](#v170-alpha4) - - [Downloads for v1.7.0-alpha.4](#downloads-for-v170-alpha4) +- [v1.6.4](#v164) + - [Known Issues for v1.6.4](#known-issues-for-v164) + - [Downloads for v1.6.4](#downloads-for-v164) - [Client Binaries](#client-binaries-7) - [Server Binaries](#server-binaries-7) - [Node Binaries](#node-binaries-7) - - [Changelog since v1.7.0-alpha.3](#changelog-since-v170-alpha3) - - [Action Required](#action-required-5) + - [Changelog since v1.6.3](#changelog-since-v163) - [Other notable changes](#other-notable-changes-7) -- [v1.6.3](#v163) - - [Known Issues for v1.6.3](#known-issues-for-v163) - - [Downloads for v1.6.3](#downloads-for-v163) +- [v1.7.0-alpha.4](#v170-alpha4) + - [Downloads for v1.7.0-alpha.4](#downloads-for-v170-alpha4) - [Client Binaries](#client-binaries-8) - [Server Binaries](#server-binaries-8) - [Node Binaries](#node-binaries-8) - - [Changelog since v1.6.2](#changelog-since-v162) + - [Changelog since v1.7.0-alpha.3](#changelog-since-v170-alpha3) + - [Action Required](#action-required-5) - [Other notable changes](#other-notable-changes-8) -- [v1.7.0-alpha.3](#v170-alpha3) - - [Downloads for v1.7.0-alpha.3](#downloads-for-v170-alpha3) +- [v1.6.3](#v163) + - [Known Issues for v1.6.3](#known-issues-for-v163) + - [Downloads for v1.6.3](#downloads-for-v163) - [Client Binaries](#client-binaries-9) - [Server Binaries](#server-binaries-9) - [Node Binaries](#node-binaries-9) - - [Changelog since v1.7.0-alpha.2](#changelog-since-v170-alpha2) - - [Action Required](#action-required-6) + - [Changelog since v1.6.2](#changelog-since-v162) - [Other notable changes](#other-notable-changes-9) -- [v1.5.7](#v157) - - [Downloads for v1.5.7](#downloads-for-v157) +- [v1.7.0-alpha.3](#v170-alpha3) + - [Downloads for v1.7.0-alpha.3](#downloads-for-v170-alpha3) - [Client Binaries](#client-binaries-10) - [Server Binaries](#server-binaries-10) - [Node Binaries](#node-binaries-10) - - [Changelog since v1.5.6](#changelog-since-v156) + - [Changelog since v1.7.0-alpha.2](#changelog-since-v170-alpha2) + - [Action Required](#action-required-6) - [Other notable changes](#other-notable-changes-10) -- [v1.4.12](#v1412) - - [Downloads for v1.4.12](#downloads-for-v1412) +- [v1.5.7](#v157) + - [Downloads for v1.5.7](#downloads-for-v157) - [Client Binaries](#client-binaries-11) - [Server Binaries](#server-binaries-11) - [Node Binaries](#node-binaries-11) - - [Changelog since v1.4.9](#changelog-since-v149) + - [Changelog since v1.5.6](#changelog-since-v156) - [Other notable changes](#other-notable-changes-11) -- [v1.7.0-alpha.2](#v170-alpha2) - - [Downloads for v1.7.0-alpha.2](#downloads-for-v170-alpha2) +- [v1.4.12](#v1412) + - [Downloads for v1.4.12](#downloads-for-v1412) - [Client Binaries](#client-binaries-12) - [Server Binaries](#server-binaries-12) - - [Changelog since v1.7.0-alpha.1](#changelog-since-v170-alpha1) - - [Action Required](#action-required-7) + - [Node Binaries](#node-binaries-12) + - [Changelog since v1.4.9](#changelog-since-v149) - [Other notable changes](#other-notable-changes-12) -- [v1.6.2](#v162) - - [Downloads for v1.6.2](#downloads-for-v162) +- [v1.7.0-alpha.2](#v170-alpha2) + - [Downloads for v1.7.0-alpha.2](#downloads-for-v170-alpha2) - [Client Binaries](#client-binaries-13) - [Server Binaries](#server-binaries-13) - - [Changelog since v1.6.1](#changelog-since-v161) + - [Changelog since v1.7.0-alpha.1](#changelog-since-v170-alpha1) + - [Action Required](#action-required-7) - [Other notable changes](#other-notable-changes-13) -- [v1.7.0-alpha.1](#v170-alpha1) - - [Downloads for v1.7.0-alpha.1](#downloads-for-v170-alpha1) +- [v1.6.2](#v162) + - [Downloads for v1.6.2](#downloads-for-v162) - [Client Binaries](#client-binaries-14) - [Server Binaries](#server-binaries-14) - - [Changelog since v1.6.0](#changelog-since-v160) + - [Changelog since v1.6.1](#changelog-since-v161) - [Other notable changes](#other-notable-changes-14) -- [v1.6.1](#v161) - - [Downloads for v1.6.1](#downloads-for-v161) +- [v1.7.0-alpha.1](#v170-alpha1) + - [Downloads for v1.7.0-alpha.1](#downloads-for-v170-alpha1) - [Client Binaries](#client-binaries-15) - [Server Binaries](#server-binaries-15) - - [Changelog since v1.6.0](#changelog-since-v160-1) + - [Changelog since v1.6.0](#changelog-since-v160) - [Other notable changes](#other-notable-changes-15) -- [v1.6.0](#v160) - - [Downloads for v1.6.0](#downloads-for-v160) +- [v1.6.1](#v161) + - [Downloads for v1.6.1](#downloads-for-v161) - [Client Binaries](#client-binaries-16) - [Server Binaries](#server-binaries-16) + - [Changelog since v1.6.0](#changelog-since-v160-1) + - [Other notable changes](#other-notable-changes-16) +- [v1.6.0](#v160) + - [Downloads for v1.6.0](#downloads-for-v160) + - [Client Binaries](#client-binaries-17) + - [Server Binaries](#server-binaries-17) - [WARNING: etcd backup strongly recommended](#warning:-etcd-backup-strongly-recommended) - [Major updates and release themes](#major-updates-and-release-themes) - [Action Required](#action-required-8) @@ -149,7 +164,7 @@ - [Scheduling](#scheduling-1) - [Service Catalog](#service-catalog) - [Volumes](#volumes-1) - - [Deprecations](#deprecations) + - [Deprecations](#deprecations-1) - [Cluster Provisioning Scripts](#cluster-provisioning-scripts) - [kubeadm](#kubeadm-1) - [Other Deprecations](#other-deprecations) @@ -188,7 +203,7 @@ - [vSphere](#vsphere) - [Federation](#federation-2) - [kubefed](#kubefed) - - [Other Notable Changes](#other-notable-changes-16) + - [Other Notable Changes](#other-notable-changes-17) - [Garbage Collector](#garbage-collector) - [kubeadm](#kubeadm-2) - [kubectl](#kubectl-1) @@ -198,7 +213,7 @@ - [Updates to apply](#updates-to-apply) - [Updates to edit](#updates-to-edit) - [Bug fixes](#bug-fixes) - - [Other Notable Changes](#other-notable-changes-17) + - [Other Notable Changes](#other-notable-changes-18) - [Node Components](#node-components-2) - [Bug fixes](#bug-fixes-1) - [kube-controller-manager](#kube-controller-manager) @@ -211,7 +226,7 @@ - [Photon](#photon) - [rbd](#rbd) - [vSphere](#vsphere-1) - - [Other Notable Changes](#other-notable-changes-18) + - [Other Notable Changes](#other-notable-changes-19) - [Changes to Cluster Provisioning Scripts](#changes-to-cluster-provisioning-scripts) - [AWS](#aws-1) - [Juju](#juju) @@ -219,7 +234,7 @@ - [GCE](#gce-1) - [OpenStack](#openstack) - [Container Images](#container-images) - - [Other Notable Changes](#other-notable-changes-19) + - [Other Notable Changes](#other-notable-changes-20) - [Changes to Addons](#changes-to-addons) - [Dashboard](#dashboard) - [DNS](#dns) @@ -230,229 +245,229 @@ - [Fluentd](#fluentd) - [Heapster](#heapster) - [Registry](#registry) - - [External Dependency Version Information](#external-dependency-version-information) + - [External Dependency Version Information](#external-dependency-version-information-1) - [Changelog since v1.6.0-rc.1](#changelog-since-v160-rc1) - [Previous Releases Included in v1.6.0](#previous-releases-included-in-v160) - [v1.5.6](#v156) - [Downloads for v1.5.6](#downloads-for-v156) - - [Client Binaries](#client-binaries-17) - - [Server Binaries](#server-binaries-17) - - [Changelog since v1.5.5](#changelog-since-v155) - - [Other notable changes](#other-notable-changes-20) -- [v1.6.0-rc.1](#v160-rc1) - - [Downloads for v1.6.0-rc.1](#downloads-for-v160-rc1) - [Client Binaries](#client-binaries-18) - [Server Binaries](#server-binaries-18) - - [Changelog since v1.6.0-beta.4](#changelog-since-v160-beta4) + - [Changelog since v1.5.5](#changelog-since-v155) - [Other notable changes](#other-notable-changes-21) -- [v1.5.5](#v155) - - [Downloads for v1.5.5](#downloads-for-v155) +- [v1.6.0-rc.1](#v160-rc1) + - [Downloads for v1.6.0-rc.1](#downloads-for-v160-rc1) - [Client Binaries](#client-binaries-19) - [Server Binaries](#server-binaries-19) + - [Changelog since v1.6.0-beta.4](#changelog-since-v160-beta4) + - [Other notable changes](#other-notable-changes-22) +- [v1.5.5](#v155) + - [Downloads for v1.5.5](#downloads-for-v155) + - [Client Binaries](#client-binaries-20) + - [Server Binaries](#server-binaries-20) - [Changelog since v1.5.4](#changelog-since-v154) - [v1.6.0-beta.4](#v160-beta4) - [Downloads for v1.6.0-beta.4](#downloads-for-v160-beta4) - - [Client Binaries](#client-binaries-20) - - [Server Binaries](#server-binaries-20) - - [Changelog since v1.6.0-beta.3](#changelog-since-v160-beta3) - - [Other notable changes](#other-notable-changes-22) -- [v1.6.0-beta.3](#v160-beta3) - - [Downloads for v1.6.0-beta.3](#downloads-for-v160-beta3) - [Client Binaries](#client-binaries-21) - [Server Binaries](#server-binaries-21) - - [Changelog since v1.6.0-beta.2](#changelog-since-v160-beta2) + - [Changelog since v1.6.0-beta.3](#changelog-since-v160-beta3) - [Other notable changes](#other-notable-changes-23) -- [v1.6.0-beta.2](#v160-beta2) - - [Downloads for v1.6.0-beta.2](#downloads-for-v160-beta2) +- [v1.6.0-beta.3](#v160-beta3) + - [Downloads for v1.6.0-beta.3](#downloads-for-v160-beta3) - [Client Binaries](#client-binaries-22) - [Server Binaries](#server-binaries-22) - - [Changelog since v1.6.0-beta.1](#changelog-since-v160-beta1) - - [Action Required](#action-required-9) + - [Changelog since v1.6.0-beta.2](#changelog-since-v160-beta2) - [Other notable changes](#other-notable-changes-24) -- [v1.5.4](#v154) - - [Downloads for v1.5.4](#downloads-for-v154) +- [v1.6.0-beta.2](#v160-beta2) + - [Downloads for v1.6.0-beta.2](#downloads-for-v160-beta2) - [Client Binaries](#client-binaries-23) - [Server Binaries](#server-binaries-23) - - [Changelog since v1.5.3](#changelog-since-v153) + - [Changelog since v1.6.0-beta.1](#changelog-since-v160-beta1) + - [Action Required](#action-required-9) - [Other notable changes](#other-notable-changes-25) -- [v1.6.0-beta.1](#v160-beta1) - - [Downloads for v1.6.0-beta.1](#downloads-for-v160-beta1) +- [v1.5.4](#v154) + - [Downloads for v1.5.4](#downloads-for-v154) - [Client Binaries](#client-binaries-24) - [Server Binaries](#server-binaries-24) - - [Changelog since v1.6.0-alpha.3](#changelog-since-v160-alpha3) - - [Action Required](#action-required-10) + - [Changelog since v1.5.3](#changelog-since-v153) - [Other notable changes](#other-notable-changes-26) -- [v1.6.0-alpha.3](#v160-alpha3) - - [Downloads for v1.6.0-alpha.3](#downloads-for-v160-alpha3) +- [v1.6.0-beta.1](#v160-beta1) + - [Downloads for v1.6.0-beta.1](#downloads-for-v160-beta1) - [Client Binaries](#client-binaries-25) - [Server Binaries](#server-binaries-25) - - [Changelog since v1.6.0-alpha.2](#changelog-since-v160-alpha2) + - [Changelog since v1.6.0-alpha.3](#changelog-since-v160-alpha3) + - [Action Required](#action-required-10) - [Other notable changes](#other-notable-changes-27) -- [v1.4.9](#v149) - - [Downloads for v1.4.9](#downloads-for-v149) +- [v1.6.0-alpha.3](#v160-alpha3) + - [Downloads for v1.6.0-alpha.3](#downloads-for-v160-alpha3) - [Client Binaries](#client-binaries-26) - [Server Binaries](#server-binaries-26) - - [Changelog since v1.4.8](#changelog-since-v148) + - [Changelog since v1.6.0-alpha.2](#changelog-since-v160-alpha2) - [Other notable changes](#other-notable-changes-28) -- [v1.5.3](#v153) - - [Downloads for v1.5.3](#downloads-for-v153) +- [v1.4.9](#v149) + - [Downloads for v1.4.9](#downloads-for-v149) - [Client Binaries](#client-binaries-27) - [Server Binaries](#server-binaries-27) - - [Node Binaries](#node-binaries-12) - - [Changelog since v1.5.2](#changelog-since-v152) + - [Changelog since v1.4.8](#changelog-since-v148) - [Other notable changes](#other-notable-changes-29) -- [v1.6.0-alpha.2](#v160-alpha2) - - [Downloads for v1.6.0-alpha.2](#downloads-for-v160-alpha2) +- [v1.5.3](#v153) + - [Downloads for v1.5.3](#downloads-for-v153) - [Client Binaries](#client-binaries-28) - [Server Binaries](#server-binaries-28) - - [Changelog since v1.6.0-alpha.1](#changelog-since-v160-alpha1) + - [Node Binaries](#node-binaries-13) + - [Changelog since v1.5.2](#changelog-since-v152) - [Other notable changes](#other-notable-changes-30) -- [v1.6.0-alpha.1](#v160-alpha1) - - [Downloads for v1.6.0-alpha.1](#downloads-for-v160-alpha1) +- [v1.6.0-alpha.2](#v160-alpha2) + - [Downloads for v1.6.0-alpha.2](#downloads-for-v160-alpha2) - [Client Binaries](#client-binaries-29) - [Server Binaries](#server-binaries-29) - - [Changelog since v1.5.0](#changelog-since-v150) - - [Action Required](#action-required-11) + - [Changelog since v1.6.0-alpha.1](#changelog-since-v160-alpha1) - [Other notable changes](#other-notable-changes-31) -- [v1.5.2](#v152) - - [Downloads for v1.5.2](#downloads-for-v152) +- [v1.6.0-alpha.1](#v160-alpha1) + - [Downloads for v1.6.0-alpha.1](#downloads-for-v160-alpha1) - [Client Binaries](#client-binaries-30) - [Server Binaries](#server-binaries-30) - - [Changelog since v1.5.1](#changelog-since-v151) + - [Changelog since v1.5.0](#changelog-since-v150) + - [Action Required](#action-required-11) - [Other notable changes](#other-notable-changes-32) -- [v1.4.8](#v148) - - [Downloads for v1.4.8](#downloads-for-v148) +- [v1.5.2](#v152) + - [Downloads for v1.5.2](#downloads-for-v152) - [Client Binaries](#client-binaries-31) - [Server Binaries](#server-binaries-31) - - [Changelog since v1.4.7](#changelog-since-v147) + - [Changelog since v1.5.1](#changelog-since-v151) - [Other notable changes](#other-notable-changes-33) -- [v1.5.1](#v151) - - [Downloads for v1.5.1](#downloads-for-v151) +- [v1.4.8](#v148) + - [Downloads for v1.4.8](#downloads-for-v148) - [Client Binaries](#client-binaries-32) - [Server Binaries](#server-binaries-32) - - [Changelog since v1.5.0](#changelog-since-v150-1) + - [Changelog since v1.4.7](#changelog-since-v147) - [Other notable changes](#other-notable-changes-34) +- [v1.5.1](#v151) + - [Downloads for v1.5.1](#downloads-for-v151) + - [Client Binaries](#client-binaries-33) + - [Server Binaries](#server-binaries-33) + - [Changelog since v1.5.0](#changelog-since-v150-1) + - [Other notable changes](#other-notable-changes-35) - [Known Issues for v1.5.1](#known-issues-for-v151) - [v1.5.0](#v150) - [Downloads for v1.5.0](#downloads-for-v150) - - [Client Binaries](#client-binaries-33) - - [Server Binaries](#server-binaries-33) - - [Major Themes](#major-themes) - - [Features](#features) - - [Known Issues](#known-issues) + - [Client Binaries](#client-binaries-34) + - [Server Binaries](#server-binaries-34) + - [Major Themes](#major-themes-1) + - [Features](#features-1) + - [Known Issues](#known-issues-1) - [Notable Changes to Existing Behavior](#notable-changes-to-existing-behavior) - - [Deprecations](#deprecations-1) - - [Action Required Before Upgrading](#action-required-before-upgrading) - - [External Dependency Version Information](#external-dependency-version-information-1) + - [Deprecations](#deprecations-2) + - [Action Required Before Upgrading](#action-required-before-upgrading-1) + - [External Dependency Version Information](#external-dependency-version-information-2) - [Changelog since v1.5.0-beta.3](#changelog-since-v150-beta3) - - [Other notable changes](#other-notable-changes-35) + - [Other notable changes](#other-notable-changes-36) - [Previous Releases Included in v1.5.0](#previous-releases-included-in-v150) - [v1.4.7](#v147) - [Downloads for v1.4.7](#downloads-for-v147) - - [Client Binaries](#client-binaries-34) - - [Server Binaries](#server-binaries-34) - - [Changelog since v1.4.6](#changelog-since-v146) - - [Other notable changes](#other-notable-changes-36) -- [v1.5.0-beta.3](#v150-beta3) - - [Downloads for v1.5.0-beta.3](#downloads-for-v150-beta3) - [Client Binaries](#client-binaries-35) - [Server Binaries](#server-binaries-35) - - [Changelog since v1.5.0-beta.2](#changelog-since-v150-beta2) + - [Changelog since v1.4.6](#changelog-since-v146) - [Other notable changes](#other-notable-changes-37) -- [v1.5.0-beta.2](#v150-beta2) - - [Downloads for v1.5.0-beta.2](#downloads-for-v150-beta2) +- [v1.5.0-beta.3](#v150-beta3) + - [Downloads for v1.5.0-beta.3](#downloads-for-v150-beta3) - [Client Binaries](#client-binaries-36) - [Server Binaries](#server-binaries-36) - - [Changelog since v1.5.0-beta.1](#changelog-since-v150-beta1) + - [Changelog since v1.5.0-beta.2](#changelog-since-v150-beta2) - [Other notable changes](#other-notable-changes-38) -- [v1.5.0-beta.1](#v150-beta1) - - [Downloads for v1.5.0-beta.1](#downloads-for-v150-beta1) +- [v1.5.0-beta.2](#v150-beta2) + - [Downloads for v1.5.0-beta.2](#downloads-for-v150-beta2) - [Client Binaries](#client-binaries-37) - [Server Binaries](#server-binaries-37) - - [Changelog since v1.5.0-alpha.2](#changelog-since-v150-alpha2) - - [Action Required](#action-required-12) + - [Changelog since v1.5.0-beta.1](#changelog-since-v150-beta1) - [Other notable changes](#other-notable-changes-39) -- [v1.4.6](#v146) - - [Downloads for v1.4.6](#downloads-for-v146) +- [v1.5.0-beta.1](#v150-beta1) + - [Downloads for v1.5.0-beta.1](#downloads-for-v150-beta1) - [Client Binaries](#client-binaries-38) - [Server Binaries](#server-binaries-38) - - [Changelog since v1.4.5](#changelog-since-v145) + - [Changelog since v1.5.0-alpha.2](#changelog-since-v150-alpha2) + - [Action Required](#action-required-12) - [Other notable changes](#other-notable-changes-40) -- [v1.3.10](#v1310) - - [Downloads for v1.3.10](#downloads-for-v1310) +- [v1.4.6](#v146) + - [Downloads for v1.4.6](#downloads-for-v146) - [Client Binaries](#client-binaries-39) - [Server Binaries](#server-binaries-39) - - [Changelog since v1.3.9](#changelog-since-v139) + - [Changelog since v1.4.5](#changelog-since-v145) - [Other notable changes](#other-notable-changes-41) -- [v1.4.5](#v145) - - [Downloads for v1.4.5](#downloads-for-v145) +- [v1.3.10](#v1310) + - [Downloads for v1.3.10](#downloads-for-v1310) - [Client Binaries](#client-binaries-40) - [Server Binaries](#server-binaries-40) - - [Changelog since v1.4.4](#changelog-since-v144) + - [Changelog since v1.3.9](#changelog-since-v139) - [Other notable changes](#other-notable-changes-42) -- [v1.5.0-alpha.2](#v150-alpha2) - - [Downloads for v1.5.0-alpha.2](#downloads-for-v150-alpha2) +- [v1.4.5](#v145) + - [Downloads for v1.4.5](#downloads-for-v145) - [Client Binaries](#client-binaries-41) - [Server Binaries](#server-binaries-41) - - [Changelog since v1.5.0-alpha.1](#changelog-since-v150-alpha1) - - [Action Required](#action-required-13) + - [Changelog since v1.4.4](#changelog-since-v144) - [Other notable changes](#other-notable-changes-43) -- [v1.2.7](#v127) - - [Downloads for v1.2.7](#downloads-for-v127) +- [v1.5.0-alpha.2](#v150-alpha2) + - [Downloads for v1.5.0-alpha.2](#downloads-for-v150-alpha2) - [Client Binaries](#client-binaries-42) - [Server Binaries](#server-binaries-42) - - [Changelog since v1.2.6](#changelog-since-v126) + - [Changelog since v1.5.0-alpha.1](#changelog-since-v150-alpha1) + - [Action Required](#action-required-13) - [Other notable changes](#other-notable-changes-44) -- [v1.4.4](#v144) - - [Downloads for v1.4.4](#downloads-for-v144) +- [v1.2.7](#v127) + - [Downloads for v1.2.7](#downloads-for-v127) - [Client Binaries](#client-binaries-43) - [Server Binaries](#server-binaries-43) - - [Changelog since v1.4.3](#changelog-since-v143) + - [Changelog since v1.2.6](#changelog-since-v126) - [Other notable changes](#other-notable-changes-45) +- [v1.4.4](#v144) + - [Downloads for v1.4.4](#downloads-for-v144) + - [Client Binaries](#client-binaries-44) + - [Server Binaries](#server-binaries-44) + - [Changelog since v1.4.3](#changelog-since-v143) + - [Other notable changes](#other-notable-changes-46) - [v1.3.9](#v139) - [Downloads](#downloads) - [Changelog since v1.3.8](#changelog-since-v138) - - [Other notable changes](#other-notable-changes-46) + - [Other notable changes](#other-notable-changes-47) - [v1.4.3](#v143) - [Downloads](#downloads-1) - [Changelog since v1.4.2-beta.1](#changelog-since-v142-beta1) - - [Other notable changes](#other-notable-changes-47) + - [Other notable changes](#other-notable-changes-48) - [v1.4.2](#v142) - [Downloads](#downloads-2) - [Changelog since v1.4.2-beta.1](#changelog-since-v142-beta1-1) - - [Other notable changes](#other-notable-changes-48) + - [Other notable changes](#other-notable-changes-49) - [v1.5.0-alpha.1](#v150-alpha1) - [Downloads](#downloads-3) - [Changelog since v1.4.0-alpha.3](#changelog-since-v140-alpha3) - [Experimental Features](#experimental-features) - [Action Required](#action-required-14) - - [Other notable changes](#other-notable-changes-49) + - [Other notable changes](#other-notable-changes-50) - [v1.4.2-beta.1](#v142-beta1) - [Downloads](#downloads-4) - [Changelog since v1.4.1](#changelog-since-v141) - - [Other notable changes](#other-notable-changes-50) + - [Other notable changes](#other-notable-changes-51) - [v1.4.1](#v141) - [Downloads](#downloads-5) - [Changelog since v1.4.1-beta.2](#changelog-since-v141-beta2) - [v1.4.1-beta.2](#v141-beta2) - [Downloads](#downloads-6) - [Changelog since v1.4.0](#changelog-since-v140) - - [Other notable changes](#other-notable-changes-51) + - [Other notable changes](#other-notable-changes-52) - [v1.3.8](#v138) - [Downloads](#downloads-7) - [Changelog since v1.3.7](#changelog-since-v137) - - [Other notable changes](#other-notable-changes-52) + - [Other notable changes](#other-notable-changes-53) - [v1.4.0](#v140) - [Downloads](#downloads-8) - - [Major Themes](#major-themes-1) - - [Features](#features-1) - - [Known Issues](#known-issues-1) + - [Major Themes](#major-themes-2) + - [Features](#features-2) + - [Known Issues](#known-issues-2) - [Notable Changes to Existing Behavior](#notable-changes-to-existing-behavior-1) - [Deployments](#deployments) - [kubectl rolling-update: < v1.4.0 client vs >=v1.4.0 cluster](#kubectl-rolling-update:-<-v140-client-vs->=v140-cluster) - [kubectl delete: < v1.4.0 client vs >=v1.4.0 cluster](#kubectl-delete:-<-v140-client-vs->=v140-cluster) - [DELETE operation in REST API](#delete-operation-in-rest-api) - - [Action Required Before Upgrading](#action-required-before-upgrading-1) + - [Action Required Before Upgrading](#action-required-before-upgrading-2) - [optionally, remove the old secret](#optionally-remove-the-old-secret) - [Previous Releases Included in v1.4.0](#previous-releases-included-in-v140) - [v1.4.0-beta.11](#v140-beta11) @@ -461,26 +476,26 @@ - [v1.4.0-beta.10](#v140-beta10) - [Downloads](#downloads-10) - [Changelog since v1.4.0-beta.8](#changelog-since-v140-beta8) - - [Other notable changes](#other-notable-changes-53) + - [Other notable changes](#other-notable-changes-54) - [v1.4.0-beta.8](#v140-beta8) - [Downloads](#downloads-11) - [Changelog since v1.4.0-beta.7](#changelog-since-v140-beta7) - [v1.4.0-beta.7](#v140-beta7) - [Downloads](#downloads-12) - [Changelog since v1.4.0-beta.6](#changelog-since-v140-beta6) - - [Other notable changes](#other-notable-changes-54) + - [Other notable changes](#other-notable-changes-55) - [v1.4.0-beta.6](#v140-beta6) - [Downloads](#downloads-13) - [Changelog since v1.4.0-beta.5](#changelog-since-v140-beta5) - - [Other notable changes](#other-notable-changes-55) + - [Other notable changes](#other-notable-changes-56) - [v1.4.0-beta.5](#v140-beta5) - [Downloads](#downloads-14) - [Changelog since v1.4.0-beta.3](#changelog-since-v140-beta3) - - [Other notable changes](#other-notable-changes-56) + - [Other notable changes](#other-notable-changes-57) - [v1.3.7](#v137) - [Downloads](#downloads-15) - [Changelog since v1.3.6](#changelog-since-v136) - - [Other notable changes](#other-notable-changes-57) + - [Other notable changes](#other-notable-changes-58) - [v1.4.0-beta.3](#v140-beta3) - [Downloads](#downloads-16) - [Changelog since v1.4.0-beta.2](#changelog-since-v140-beta2) @@ -491,57 +506,57 @@ - [v1.4.0-beta.2](#v140-beta2) - [Downloads](#downloads-17) - [Changelog since v1.4.0-beta.1](#changelog-since-v140-beta1) - - [Other notable changes](#other-notable-changes-58) + - [Other notable changes](#other-notable-changes-59) - [v1.4.0-beta.1](#v140-beta1) - [Downloads](#downloads-18) - [Changelog since v1.4.0-alpha.3](#changelog-since-v140-alpha3-1) - [Action Required](#action-required-15) - - [Other notable changes](#other-notable-changes-59) + - [Other notable changes](#other-notable-changes-60) - [v1.3.6](#v136) - [Downloads](#downloads-19) - [Changelog since v1.3.5](#changelog-since-v135) - - [Other notable changes](#other-notable-changes-60) + - [Other notable changes](#other-notable-changes-61) - [v1.4.0-alpha.3](#v140-alpha3) - [Downloads](#downloads-20) - [Changelog since v1.4.0-alpha.2](#changelog-since-v140-alpha2) - [Action Required](#action-required-16) - - [Other notable changes](#other-notable-changes-61) + - [Other notable changes](#other-notable-changes-62) - [v1.3.5](#v135) - [Downloads](#downloads-21) - [Changelog since v1.3.4](#changelog-since-v134) - - [Other notable changes](#other-notable-changes-62) + - [Other notable changes](#other-notable-changes-63) - [v1.3.4](#v134) - [Downloads](#downloads-22) - [Changelog since v1.3.3](#changelog-since-v133) - - [Other notable changes](#other-notable-changes-63) + - [Other notable changes](#other-notable-changes-64) - [v1.4.0-alpha.2](#v140-alpha2) - [Downloads](#downloads-23) - [Changelog since v1.4.0-alpha.1](#changelog-since-v140-alpha1) - [Action Required](#action-required-17) - - [Other notable changes](#other-notable-changes-64) + - [Other notable changes](#other-notable-changes-65) - [v1.3.3](#v133) - [Downloads](#downloads-24) - [Changelog since v1.3.2](#changelog-since-v132) - - [Other notable changes](#other-notable-changes-65) - - [Known Issues](#known-issues-2) + - [Other notable changes](#other-notable-changes-66) + - [Known Issues](#known-issues-3) - [v1.3.2](#v132) - [Downloads](#downloads-25) - [Changelog since v1.3.1](#changelog-since-v131) - - [Other notable changes](#other-notable-changes-66) + - [Other notable changes](#other-notable-changes-67) - [v1.3.1](#v131) - [Downloads](#downloads-26) - [Changelog since v1.3.0](#changelog-since-v130) - - [Other notable changes](#other-notable-changes-67) + - [Other notable changes](#other-notable-changes-68) - [v1.2.6](#v126) - [Downloads](#downloads-27) - [Changelog since v1.2.5](#changelog-since-v125) - - [Other notable changes](#other-notable-changes-68) + - [Other notable changes](#other-notable-changes-69) - [v1.4.0-alpha.1](#v140-alpha1) - [Downloads](#downloads-28) - [Changelog since v1.3.0](#changelog-since-v130-1) - [Experimental Features](#experimental-features-1) - [Action Required](#action-required-18) - - [Other notable changes](#other-notable-changes-69) + - [Other notable changes](#other-notable-changes-70) - [v1.3.0](#v130) - [Downloads](#downloads-29) - [Highlights](#highlights) @@ -557,70 +572,70 @@ - [Downloads](#downloads-30) - [Changelog since v1.3.0-beta.2](#changelog-since-v130-beta2) - [Action Required](#action-required-19) - - [Other notable changes](#other-notable-changes-70) + - [Other notable changes](#other-notable-changes-71) - [v1.2.5](#v125) - [Downloads](#downloads-31) - [Changes since v1.2.4](#changes-since-v124) - - [Other notable changes](#other-notable-changes-71) + - [Other notable changes](#other-notable-changes-72) - [v1.3.0-beta.2](#v130-beta2) - [Downloads](#downloads-32) - [Changes since v1.3.0-beta.1](#changes-since-v130-beta1) - [Experimental Features](#experimental-features-2) - - [Other notable changes](#other-notable-changes-72) + - [Other notable changes](#other-notable-changes-73) - [v1.3.0-beta.1](#v130-beta1) - [Downloads](#downloads-33) - [Changes since v1.3.0-alpha.5](#changes-since-v130-alpha5) - [Action Required](#action-required-20) - - [Other notable changes](#other-notable-changes-73) + - [Other notable changes](#other-notable-changes-74) - [v1.3.0-alpha.5](#v130-alpha5) - [Downloads](#downloads-34) - [Changes since v1.3.0-alpha.4](#changes-since-v130-alpha4) - [Action Required](#action-required-21) - - [Other notable changes](#other-notable-changes-74) + - [Other notable changes](#other-notable-changes-75) - [v1.3.0-alpha.4](#v130-alpha4) - [Downloads](#downloads-35) - [Changes since v1.3.0-alpha.3](#changes-since-v130-alpha3) - [Action Required](#action-required-22) - - [Other notable changes](#other-notable-changes-75) + - [Other notable changes](#other-notable-changes-76) - [v1.2.4](#v124) - [Downloads](#downloads-36) - [Changes since v1.2.3](#changes-since-v123) - - [Other notable changes](#other-notable-changes-76) + - [Other notable changes](#other-notable-changes-77) - [v1.3.0-alpha.3](#v130-alpha3) - [Downloads](#downloads-37) - [Changes since v1.3.0-alpha.2](#changes-since-v130-alpha2) - [Action Required](#action-required-23) - - [Other notable changes](#other-notable-changes-77) + - [Other notable changes](#other-notable-changes-78) - [v1.2.3](#v123) - [Downloads](#downloads-38) - [Changes since v1.2.2](#changes-since-v122) - [Action Required](#action-required-24) - - [Other notable changes](#other-notable-changes-78) + - [Other notable changes](#other-notable-changes-79) - [v1.3.0-alpha.2](#v130-alpha2) - [Downloads](#downloads-39) - [Changes since v1.3.0-alpha.1](#changes-since-v130-alpha1) - - [Other notable changes](#other-notable-changes-79) + - [Other notable changes](#other-notable-changes-80) - [v1.2.2](#v122) - [Downloads](#downloads-40) - [Changes since v1.2.1](#changes-since-v121) - - [Other notable changes](#other-notable-changes-80) + - [Other notable changes](#other-notable-changes-81) - [v1.2.1](#v121) - [Downloads](#downloads-41) - [Changes since v1.2.0](#changes-since-v120) - - [Other notable changes](#other-notable-changes-81) + - [Other notable changes](#other-notable-changes-82) - [v1.3.0-alpha.1](#v130-alpha1) - [Downloads](#downloads-42) - [Changes since v1.2.0](#changes-since-v120-1) - [Action Required](#action-required-25) - - [Other notable changes](#other-notable-changes-82) + - [Other notable changes](#other-notable-changes-83) - [v1.2.0](#v120) - [Downloads](#downloads-43) - [Changes since v1.1.1](#changes-since-v111) - - [Major Themes](#major-themes-2) + - [Major Themes](#major-themes-3) - [Other notable improvements](#other-notable-improvements) - [Experimental Features](#experimental-features-3) - [Action required](#action-required-26) - - [Known Issues](#known-issues-3) + - [Known Issues](#known-issues-4) - [Docker Known Issues](#docker-known-issues) - [1.9.1](#191) - [Provider-specific Notes](#provider-specific-notes-1) @@ -632,6 +647,1437 @@ +# v1.7.0 + +[Documentation](https://docs.k8s.io) & [Examples](https://releases.k8s.io/release-1.7/examples) + +## Downloads for v1.7.0 + + +filename | sha256 hash +-------- | ----------- +[kubernetes.tar.gz](https://dl.k8s.io/v1.7.0/kubernetes.tar.gz) | `947f1dd9a9b6b427faac84067a30c86e83e6391eb42f09ddcc50a8694765c31a` +[kubernetes-src.tar.gz](https://dl.k8s.io/v1.7.0/kubernetes-src.tar.gz) | `d3d8b0bfc31164dd703b38d8484cfed7981cacd1e496731880afa87f8bf39aac` + +### Client Binaries + +filename | sha256 hash +-------- | ----------- +[kubernetes-client-darwin-386.tar.gz](https://dl.k8s.io/v1.7.0/kubernetes-client-darwin-386.tar.gz) | `da298e24318e57ac8a558c390117bd7e9e596b3bdf1c5960979898fefe6c5c88` +[kubernetes-client-darwin-amd64.tar.gz](https://dl.k8s.io/v1.7.0/kubernetes-client-darwin-amd64.tar.gz) | `c22f72e1592731155db5b05d0d660f1d7314288cb020f7980e2a109d9e7ba0e5` +[kubernetes-client-linux-386.tar.gz](https://dl.k8s.io/v1.7.0/kubernetes-client-linux-386.tar.gz) | `fc8e90e96360c3a2c8ec56903ab5acde1dffa4d641e1ee27b804ee6d8e824cf6` +[kubernetes-client-linux-amd64.tar.gz](https://dl.k8s.io/v1.7.0/kubernetes-client-linux-amd64.tar.gz) | `8b3ed03f8a4b3a1ec124abde01632ee6dcec9daf9376f0288fd7500b5173981c` +[kubernetes-client-linux-arm64.tar.gz](https://dl.k8s.io/v1.7.0/kubernetes-client-linux-arm64.tar.gz) | `8930c74dab9ada31e6994f0dc3fb22d41a602a2880b6b17112718ce73eac0574` +[kubernetes-client-linux-arm.tar.gz](https://dl.k8s.io/v1.7.0/kubernetes-client-linux-arm.tar.gz) | `20a6f4645cab3c0aef72f849ae90b2691605fd3f670ce36cc8aa11aef31c6edb` +[kubernetes-client-linux-ppc64le.tar.gz](https://dl.k8s.io/v1.7.0/kubernetes-client-linux-ppc64le.tar.gz) | `509e214d55e8df1906894cbdc166e791761a3b82a52bcea0de65ceca3143c8b5` +[kubernetes-client-linux-s390x.tar.gz](https://dl.k8s.io/v1.7.0/kubernetes-client-linux-s390x.tar.gz) | `fd39f47b691fc608f2ea3fed35408dd4c0b1d198605ec17363b0987b123a4702` +[kubernetes-client-windows-386.tar.gz](https://dl.k8s.io/v1.7.0/kubernetes-client-windows-386.tar.gz) | `d9b72cfeefee0cd2db5f6a388bdb9da1e33514498f4d88be1b04282db5bfbd3d` +[kubernetes-client-windows-amd64.tar.gz](https://dl.k8s.io/v1.7.0/kubernetes-client-windows-amd64.tar.gz) | `c536952bd29a7ae12c8fa148d592cc3c353dea4d0079e8497edaf8a759a16006` + +### Server Binaries + +filename | sha256 hash +-------- | ----------- +[kubernetes-server-linux-amd64.tar.gz](https://dl.k8s.io/v1.7.0/kubernetes-server-linux-amd64.tar.gz) | `175fc9360d4f26b5f60b467798d851061f01d0ca555c254ef44a8a9822cf7560` +[kubernetes-server-linux-arm64.tar.gz](https://dl.k8s.io/v1.7.0/kubernetes-server-linux-arm64.tar.gz) | `f1e039e0e2923d1ea02fd76453aa51715ca83c5c26ca1a761ace2c717b79154f` +[kubernetes-server-linux-arm.tar.gz](https://dl.k8s.io/v1.7.0/kubernetes-server-linux-arm.tar.gz) | `48dc95e5230d7a44b64b379f9cf2e1ec72b7c4c7c62f4f3e92a73076ad6376db` +[kubernetes-server-linux-ppc64le.tar.gz](https://dl.k8s.io/v1.7.0/kubernetes-server-linux-ppc64le.tar.gz) | `dc079cd18333c201cfd0f5b0e93e602d020a9e665d8c13968170a2cd89eebeb4` +[kubernetes-server-linux-s390x.tar.gz](https://dl.k8s.io/v1.7.0/kubernetes-server-linux-s390x.tar.gz) | `fe6674e7d69aeffd522e543e957897e2cb943e82d5ccd368ccb9009e1128273f` + +### Node Binaries + +filename | sha256 hash +-------- | ----------- +[kubernetes-node-linux-amd64.tar.gz](https://dl.k8s.io/v1.7.0/kubernetes-node-linux-amd64.tar.gz) | `6c6cece62bad5bfeaf4a4b14e93c9ba99c96dc82b7855a2214cdf37a65251de8` +[kubernetes-node-linux-arm64.tar.gz](https://dl.k8s.io/v1.7.0/kubernetes-node-linux-arm64.tar.gz) | `dd75dc044fb1f337b60cb4b27c9bbdca4742d8bc0a1d03d13553a1b8fc593e98` +[kubernetes-node-linux-arm.tar.gz](https://dl.k8s.io/v1.7.0/kubernetes-node-linux-arm.tar.gz) | `c5d832c93c24d77414a880d8b7c4fac9a7443305e8e5c704f637ff023ff56f94` +[kubernetes-node-linux-ppc64le.tar.gz](https://dl.k8s.io/v1.7.0/kubernetes-node-linux-ppc64le.tar.gz) | `649813a257353c5b85605869e33aeeb0c070e64e6fee18bc9c6e70472aa05677` +[kubernetes-node-linux-s390x.tar.gz](https://dl.k8s.io/v1.7.0/kubernetes-node-linux-s390x.tar.gz) | `5ca0a7e9e90b2de7aff7bbdc84f662140ce847ea46cdb78802ce75459e0cc043` +[kubernetes-node-windows-amd64.tar.gz](https://dl.k8s.io/v1.7.0/kubernetes-node-windows-amd64.tar.gz) | `4b84b0025aff1d4406f3e5cd5fa86940f594e3ec6e1d12d3ce1eea5f5b3fc55d` + +## **Major Themes** + +Kubernetes 1.7 is a milestone release that adds security, stateful application, and extensibility features motivated by widespread production use of Kubernetes. + +Security enhancements in this release include encrypted secrets (alpha), network policy for pod-to-pod communication, the node authorizer to limit Kubelet access to API resources, and Kubelet client / server TLS certificate rotation (alpha). + +Major features for stateful applications include automated updates to StatefulSets, enhanced updates for DaemonSets, a burst mode for faster StatefulSets scaling, and (alpha) support for local storage. + +Extensibility features include API aggregation (beta), CustomResourceDefinitions (beta) in favor of ThirdPartyResources, support for extensible admission controllers (alpha), pluggable cloud providers (alpha), and container runtime interface (CRI) enhancements. + +## **Action Required Before Upgrading** + +* NetworkPolicy has been promoted from extensions/v1beta1 to the new networking.k8s.io/v1 API group. The structure remains unchanged from the v1beta1 API. The net.beta.kubernetes.io/network-policy annotation on Namespaces (used to opt in to isolation) has been removed. Instead, isolation is now determined on a per-pod basis. A NetworkPolicy may target a pod for isolation by including the pod in its spec.podSelector. Targeted Pods accept the traffic specified in the respective NetworkPolicy (and nothing else). Pods not targeted by any NetworkPolicy accept all traffic by default. ([[#39164](https://github.com/kubernetes/kubernetes/pull/39164)](https://github.com/kubernetes/kubernetes/pull/39164), [[@danwinship](https://github.com/danwinship)](https://github.com/danwinship)) + + **Action Required:** When upgrading to Kubernetes 1.7 (and a [network plugin](https://kubernetes.io/docs/tasks/administer-cluster/declare-network-policy/) that supports the new NetworkPolicy v1 semantics), you should consider the following. + + The v1beta1 API used an annotation on Namespaces to activate the DefaultDeny policy for an entire Namespace. To activate default deny in the v1 API, you can create a NetworkPolicy that matches all Pods but does not allow any traffic: + + ```yaml + kind: NetworkPolicy + apiVersion: networking.k8s.io/v1 + metadata: + name: default-deny + spec: + podSelector: + ``` + + This will ensure that Pods that aren't matched by any other NetworkPolicy will continue to be fully-isolated, as they were in v1beta1. + + In Namespaces that previously did not have the "DefaultDeny" annotation, you should delete any existing NetworkPolicy objects. These had no effect in the v1beta1 API, but with v1 semantics they might cause some traffic to be unintentionally blocked. + +* `cluster/update-storage-objects.sh` now supports updating StorageClasses in etcd to storage.k8s.io/v1. You must do this prior to upgrading to 1.8. ([[#46116](https://github.com/kubernetes/kubernetes/pull/46116)](https://github.com/kubernetes/kubernetes/pull/46116), [[@ncdc](https://github.com/ncdc)](https://github.com/ncdc)) + +* PodSpecs containing parent directory references such as `..` (for example, `../bar`) in hostPath volume path or in volumeMount subpaths must be changed to the simple absolute path. Backsteps `..` are no longer allowed.([[#47290](https://github.com/kubernetes/kubernetes/pull/47290)](https://github.com/kubernetes/kubernetes/pull/47290), [[@jhorwit2](https://github.com/jhorwit2)](https://github.com/jhorwit2)). + +* Azure: Container permissions for provisioned volumes have changed to private. If you have existing Azure volumes that were created by Kubernetes v1.6.0-v1.6.5, you should change the permissions on them manually. ([[#47605](https://github.com/kubernetes/kubernetes/pull/47605)](https://github.com/kubernetes/kubernetes/pull/47605), [[@brendandburns](https://github.com/brendandburns)](https://github.com/brendandburns)) + +* GKE/GCE: New and upgraded 1.7 GCE/GKE clusters no longer have an RBAC ClusterRoleBinding that grants the cluster-admin ClusterRole to the default service account in the kube-system Namespace. ([[#46750](https://github.com/kubernetes/kubernetes/pull/46750)](https://github.com/kubernetes/kubernetes/pull/46750), [[@cjcullen](https://github.com/cjcullen)](https://github.com/cjcullen)). If this permission is still desired, run the following command to explicitly grant it, either before or after upgrading to 1.7: + ``` + kubectl create clusterrolebinding kube-system-default --serviceaccount=kube-system:default --clusterrole=cluster-admin + ``` + +* kube-controller-manager has dropped support for the `--insecure-experimental-approve-all-kubelet-csrs-for-group` flag. It is accepted in 1.7, but ignored. Instead, the csrapproving controller uses authorization checks to determine whether to approve certificate signing requests: ([[#45619](https://github.com/kubernetes/kubernetes/pull/45619)](https://github.com/kubernetes/kubernetes/pull/45619), [[@mikedanese](https://github.com/mikedanese)](https://github.com/mikedanese)) + + * Before upgrading, users must ensure their controller manager will enable the csrapproving controller, create an RBAC ClusterRole and ClusterRoleBinding to approve CSRs for the same group, then upgrade. Example roles to enable the equivalent behavior can be found in the TLS bootstrapping documentation ([https://github.com/kubernetes/kubernetes.github.io/pull/4208](https://github.com/kubernetes/kubernetes.github.io/pull/4208)). + +* The Namespace API object no longer supports the deletecollection operation. ([[#46407](https://github.com/kubernetes/kubernetes/pull/46407)](https://github.com/kubernetes/kubernetes/pull/46407), [[@liggitt](https://github.com/liggitt)](https://github.com/liggitt)) + +* `kubectl create role` and `kubectl create clusterrole` invocations must be updated to specify multiple resource names as repeated `--resource-name` arguments instead of comma-separated arguments to a single `--resource-name` argument. E.g. `--resource-name=x,y` must become `--resource-name x --resource-name y` ([[#44950](https://github.com/kubernetes/kubernetes/pull/44950)](https://github.com/kubernetes/kubernetes/pull/44950), [[@xilabao](https://github.com/xilabao)](https://github.com/xilabao)) + +* `kubectl create rolebinding` and `kubectl create clusterrolebinding` invocations must be updated to specify multiple subjects as repeated `--user`, `--group`, or `--serviceaccount` arguments instead of comma-separated arguments to a single `--user`, `--group`, or `--serviceaccount`. E.g. `--user=x,y` must become `--user x --user y` ([[#43903](https://github.com/kubernetes/kubernetes/pull/43903)](https://github.com/kubernetes/kubernetes/pull/43903), [[@xilabao](https://github.com/xilabao)](https://github.com/xilabao)) + +* The following alpha API groups were unintentionally enabled by default in previous releases, and will no longer be enabled by default in v1.8: ([[#47690](https://github.com/kubernetes/kubernetes/pull/47690)](https://github.com/kubernetes/kubernetes/pull/47690), [[@caesarxuchao](https://github.com/caesarxuchao)](https://github.com/caesarxuchao)) + + * rbac.authorization.k8s.io/v1alpha1 + + * settings.k8s.io/v1alpha1 + + * If you wish to continue using them in v1.8, please enable them explicitly using the `--runtime-config` flag on the apiserver (for example, `--runtime-config="rbac.authorization.k8s.io/v1alpha1,settings.k8s.io/v1alpha1"`) + +## **Known Issues** + +Populated via [v1.7.x known issues / FAQ accumulator](https://github.com/kubernetes/kubernetes/issues/46733) + +* The kube-apiserver discovery APIs (for example, `/apis`) return information about the API groups being served, and can change dynamically. +During server startup, prior to the server reporting healthy (via `/healthz`), not all API groups may be reported. +Wait for the server to report healthy (via `/healthz`) before depending on the information provided by the discovery APIs. +Additionally, since the information returned from the discovery APIs may change dynamically, a cache of the results should not be considered authoritative. +ETag support is planned in a future version to facilitate client caching. +([[#47977](https://github.com/kubernetes/kubernetes/pull/47977)](https://github.com/kubernetes/kubernetes/issues/47977), [[#44957](https://github.com/kubernetes/kubernetes/pull/44957)](https://github.com/kubernetes/kubernetes/issues/44957)) + +* The DaemonSet controller will evict running Pods that do not tolerate the NoSchedule taint if the taint is added to a Node. There is an open PR ([[#48189](https://github.com/kubernetes/kubernetes/pull/48189)](https://github.com/kubernetes/kubernetes/pull/48189)) to resolve this issue, but as this issue also exists in 1.6, and as we do not wish to risk release stability by merging it directly prior to a release without sufficient testing, we have decided to defer merging the PR until the next point release for each minor version ([[#48190](https://github.com/kubernetes/kubernetes/pull/48190)](https://github.com/kubernetes/kubernetes/issues/48190)). + +* Protobuf serialization does not distinguish between `[]` and `null`. +API fields previously capable of storing and returning either `[]` and `null` via JSON API requests (for example, the Endpoints `subsets` field) +can now store only `null` when created using the protobuf content-type or stored in etcd using protobuf serialization (the default in 1.6). +JSON API clients should tolerate `null` values for such fields, and treat `null` and `[]` as equivalent in meaning unless specifically documented otherwise for a particular field. ([[#44593](https://github.com/kubernetes/kubernetes/pull/44593)](https://github.com/kubernetes/kubernetes/issues/44593)) + +## **Deprecations** + +* ThirdPartyResource (Alpha) is deprecated. Please migrate to the successor, CustomResourceDefinition (Beta). ([docs PR](https://github.com/kubernetes/kubernetes.github.io/pull/4071)) ([kubernetes/features#95](https://github.com/kubernetes/features/issues/95)) + +* Swagger 1.2 spec (/swaggerapi/*) is deprecated. Please use OpenAPI instead. + +* The Namespace API object no longer supports the deletecollection operation. ([[#46407](https://github.com/kubernetes/kubernetes/pull/46407)](https://github.com/kubernetes/kubernetes/pull/46407), [[@liggitt](https://github.com/liggitt)](https://github.com/liggitt)) + +* DaemonSet’s spec.templateGeneration has been deprecated. ([[#45924](https://github.com/kubernetes/kubernetes/pull/45924)](https://github.com/kubernetes/kubernetes/pull/45924), [[@janetkuo](https://github.com/janetkuo)](https://github.com/janetkuo)) + +* In 1.7, the kube-proxy component has been converted to use a configuration file. The old flags still work in 1.7, but they are being deprecated and will be removed in a future release. Cluster administrators are advised to switch to using the configuration file, but no action is strictly necessary in 1.7. ([[#34727](https://github.com/kubernetes/kubernetes/pull/34727)](https://github.com/kubernetes/kubernetes/pull/34727), [[@ncdc](https://github.com/ncdc)](https://github.com/ncdc)) + +## **Features** + +Features for this release were tracked via the use of the [kubernetes/features](https://github.com/kubernetes/features) issues repo. Each Feature issue is owned by a Special Interest Group from [kubernetes/community](https://github.com/kubernetes/community) + +TODO: replace docs PR links with links to actual docs + +* API Machinery + + * [alpha] Add extensible external admission control ([docs PR](https://github.com/kubernetes/kubernetes.github.io/pull/4092)) ([kubernetes/features#209](https://github.com/kubernetes/features/issues/209)) + + * [beta] User-provided apiservers can be aggregated (served along with) the rest of the Kubernetes API ([docs PR](https://github.com/kubernetes/kubernetes.github.io/pull/4173)) ([kubernetes/features#263](https://github.com/kubernetes/features/issues/263)) + + * [beta] ThirdPartyResource is deprecated. Please migrate to the successor, CustomResourceDefinition. ([docs PR](https://github.com/kubernetes/kubernetes.github.io/pull/4071)) ([kubernetes/features#95](https://github.com/kubernetes/features/issues/95)) + +* Apps + + * [beta] StatefulSet supports RollingUpdate and OnDelete update strategies. ([docs PR](https://github.com/kubernetes/kubernetes.github.io/pull/4174)) ([kubernetes/features#188](https://github.com/kubernetes/features/issues/188)) + + * [beta] DaemonSet supports history and rollback. ([docs PR](https://github.com/kubernetes/kubernetes.github.io/pull/4098)) ([kubernetes/features#124](https://github.com/kubernetes/features/issues/124)) + + * [alpha] StatefulSet authors should be able to relax the ordering and parallelism policies for software that can safely support rapid, out-of-order changes. ([docs PR](https://github.com/kubernetes/kubernetes.github.io/pull/4162)) ([kubernetes/features#272](https://github.com/kubernetes/features/issues/272)) + + * [beta] PodDisruptionBudget has a new field MaxUnavailable, which allows users to specify the maximum number of disruptions that can be tolerated during eviction. ([docs PR](https://github.com/kubernetes/kubernetes.github.io/pull/4140)) ([kubernetes/features#285](https://github.com/kubernetes/features/issues/285)) + + * [beta] Deployments uses a hashing collision avoidance mechanism that ensures new rollouts will not block on hashing collisions anymore. ([kubernetes/features#287](https://github.com/kubernetes/features/issues/287)) + +* Auth + + * [alpha] Rotation of the server TLS certificate on the kubelet ([docs PR](https://github.com/kubernetes/kubernetes.github.io/pull/4208)) ([kubernetes/features#267](https://github.com/kubernetes/features/issues/267)) + + * [alpha] Rotation of the client TLS certificate on the kubelet ([docs PR](https://github.com/kubernetes/kubernetes.github.io/pull/4208)) ([kubernetes/features#266](https://github.com/kubernetes/features/issues/266)) + + * [alpha] Encrypt secrets stored in etcd ([docs PR](https://github.com/kubernetes/kubernetes.github.io/pull/4181)) ([kubernetes/features#92](https://github.com/kubernetes/features/issues/92)) + + * [beta] A new Node authorization mode and NodeRestriction admission plugin, when used in combination, limit nodes' access to specific APIs, so that they may only modify their own Node API object, only modify Pod objects bound to themselves, and only retrieve secrets and configmaps referenced by pods bound to themselves ([docs PR](https://github.com/kubernetes/kubernetes.github.io/pull/4077)) ([kubernetes/features#279](https://github.com/kubernetes/features/issues/279)) + + * [alpha] Advanced Auditing enhances the Kubernetes API audit logging capabilities through a customizable policy, pluggable audit backends, and richer audit data ([docs PR](https://github.com/kubernetes/kubernetes.github.io/pull/4101)) ([kubernetes/features#22](https://github.com/kubernetes/features/issues/22)) + +* Autoscaling + + * [alpha] HPA Status Conditions ([docs PR](https://github.com/kubernetes/kubernetes.github.io/pull/4118)) ([kubernetes/features#264](https://github.com/kubernetes/features/issues/264)) + +* Cluster Lifecycle + + * [alpha] Improved support for out-of-tree and out-of-process cloud providers, a.k.a pluggable cloud providers ([docs](https://kubernetes.io/docs/tasks/administer-cluster/running-cloud-controller)) ([kubernetes/features#88](https://github.com/kubernetes/features/issues/88)) + + * [alpha] Manual upgrades for kubeadm from v1.6 to v1.7. Automated upgrades ([kubernetes/features#296](https://github.com/kubernetes/features/issues/296)) are targeted for v1.8. ([docs PR](https://github.com/kubernetes/kubernetes.github.io/pull/3999)) (part of [kubernetes/features#11](https://github.com/kubernetes/features/issues/11)) + +* Federation + + * [alpha] The federation-apiserver now supports a SchedulingPolicy admission controller that enables policy-based control over placement of federated resources ([docs PR](https://github.com/kubernetes/kubernetes.github.io/pull/4075)) ([kubernetes/features#250](https://github.com/kubernetes/features/issues/250)) + + * [alpha] Federation ClusterSelector annotation to direct objects to federated clusters with matching labels ([docs PR](https://github.com/kubernetes/kubernetes.github.io/pull/4214)) ([kubernetes/features#74](https://github.com/kubernetes/features/issues/74)) + +* Instrumentation + + * [alpha] Introduces a lightweight monitoring component for serving the core resource metrics API used by the Horizontal Pod Autoscaler and other components ([kubernetes/features#271](https://github.com/kubernetes/features/issues/271)) + +* Network + + * [stable] NetworkPolicy promoted to GA ([docs PR](https://github.com/kubernetes/kubernetes.github.io/pull/4003)([kubernetes/features#185](https://github.com/kubernetes/features/issues/185)) + + * [stable] Source IP Preservation - change Cloud load-balancer strategy to health-checks and respond to health check only on nodes that host pods for the service ([docs PR](https://github.com/kubernetes/kubernetes.github.io/pull/4093)) ([kubernetes/features#27](https://github.com/kubernetes/features/issues/27)) + +* Node + + * [alpha] CRI validation testing, which provides a test framework and a suite of tests to validate that the CRI server implementation meets all the requirements. This allows the CRI runtime developers to verify that their runtime conforms to CRI, without needing to set up Kubernetes components or run Kubernetes end-to-end tests. ([docs](https://github.com/kubernetes/community/blob/master/contributors/devel/cri-validation.md) and [release notes](https://github.com/kubernetes-incubator/cri-tools/releases/tag/v0.1)) ([kubernetes/features#292](https://github.com/kubernetes/features/issues/292)) + + * [alpha] Adds support of container metrics in CRI ([docs PR](https://github.com/kubernetes/community/pull/742)) ([kubernetes/features#290](https://github.com/kubernetes/features/issues/290)) + + * [alpha] Integration with containerd 1.0, which supports basic pod lifecycle and image management. ([docs](https://github.com/kubernetes-incubator/cri-containerd/blob/master/README.md) and [release notes](https://github.com/kubernetes-incubator/cri-containerd/releases/tag/v0.1.0)) ([kubernetes/features#286](https://github.com/kubernetes/features/issues/286)) + +* Scheduling + + * [alpha] Support for delegating pod binding to a scheduler extender ([kubernetes/features#270](https://github.com/kubernetes/features/issues/270)) + +* Storage + + * [alpha] This feature adds capacity isolation support for local storage at node, container, and volume levels ([docs PR](https://github.com/kubernetes/kubernetes.github.io/pull/4145)) ([kubernetes/features#245](https://github.com/kubernetes/features/issues/245)) + + * [alpha] Make locally attached (non-network attached) storage available as a persistent volume source. ([docs PR](https://github.com/kubernetes/kubernetes.github.io/pull/4050)) ([kubernetes/features#121](https://github.com/kubernetes/features/issues/121)) + + * [stable] Volume plugin for StorageOS provides highly-available cluster-wide persistent volumes from local or attached node storage ([docs PR](https://github.com/kubernetes/kubernetes.github.io/pull/4095)) ([kubernetes/features#190](https://github.com/kubernetes/features/issues/190)) + + * [stable] Add support for cloudprovider metrics for storage API calls ([docs PR](https://github.com/kubernetes/kubernetes.github.io/pull/4138)) ([kubernetes/features#182](https://github.com/kubernetes/features/issues/182)) + +## **External Dependency Version Information** + +Continuous integration builds have used the following versions of external dependencies, however, this is not a strong recommendation and users should consult an appropriate installation or upgrade guide before deciding what versions of etcd, docker or rkt to use. + +* Docker versions 1.10.3, 1.11.2, 1.12.6 have been validated + + * Docker version 1.12.6 known issues + + * overlay2 driver not fully supported + + * live-restore not fully supported + + * no shared pid namespace support + + * Docker version 1.11.2 known issues + + * Kernel crash with Aufs storage driver on Debian Jessie ([[#27885](https://github.com/kubernetes/kubernetes/pull/27885)](https://github.com/kubernetes/kubernetes/issues/27885)) which can be identified by the [node problem detector](http://kubernetes.io/docs/admin/node-problem/) + + * Leaked File descriptors ([#275](https://github.com/docker/containerd/issues/275)) + + * Additional memory overhead per container ([[#21737](https://github.com/kubernetes/kubernetes/pull/21737)](https://github.com/docker/docker/issues/21737)) + + * Docker 1.10.3 contains [backports provided by RedHat](https://github.com/docker/docker/compare/v1.10.3...runcom:docker-1.10.3-stable) for known issues + +* rkt version 1.23.0+ + + * known issues with the rkt runtime are [listed in the Getting Started Guide](http://kubernetes.io/docs/getting-started-guides/rkt/notes/) + +* etcd version 3.0.17 + +* Go version: 1.8.3. [Link to announcement](https://groups.google.com/d/msg/kubernetes-dev/0XRRz6UhhTM/YODWVnuDBQAJ) + + * Kubernetes can only be compiled with Go 1.8. Support for all other versions is dropped. + +### **Other notable changes** + +* API Machinery + + * The protobuf serialization of API objects has been updated to store maps in a predictable order to ensure that the representation of that object does not change when saved into etcd. This prevents the same object from being seen as being modified, even when no values have changed. ([[#47701](https://github.com/kubernetes/kubernetes/pull/47701)](https://github.com/kubernetes/kubernetes/pull/47701), [[@smarterclayton](https://github.com/smarterclayton)](https://github.com/smarterclayton)) + + * API resource discovery now includes the singularName used to refer to the resource. ([[#43312](https://github.com/kubernetes/kubernetes/pull/43312)](https://github.com/kubernetes/kubernetes/pull/43312), [[@deads2k](https://github.com/deads2k)](https://github.com/deads2k)) + + * Enhance the garbage collection admission plugin so that a user who doesn't have delete permission of the owning object cannot modify the blockOwnerDeletion field of existing ownerReferences, or add new ownerReferences with blockOwnerDeletion=true ([[#43876](https://github.com/kubernetes/kubernetes/pull/43876)](https://github.com/kubernetes/kubernetes/pull/43876), [[@caesarxuchao](https://github.com/caesarxuchao)](https://github.com/caesarxuchao)) + + * The Kubernetes API server now exits if it encounters a networking failure (e.g. the networking interface hosting its address goes away) to allow a process manager (systemd/kubelet/etc) to react to the problem. Previously the server would log the failure and try again to bind to its configured address:port. ([[#42272](https://github.com/kubernetes/kubernetes/pull/42272)](https://github.com/kubernetes/kubernetes/pull/42272), [[@marun](https://github.com/marun)](https://github.com/marun)) + + * Exec and portforward actions over SPDY now properly handle redirects sent by the Kubelet ([[#44451](https://github.com/kubernetes/kubernetes/pull/44451)](https://github.com/kubernetes/kubernetes/pull/44451), [[@ncdc](https://github.com/ncdc)](https://github.com/ncdc)) + + * The proxy subresource APIs for nodes, services, and pods now support the HTTP PATCH method. ([[#44929](https://github.com/kubernetes/kubernetes/pull/44929)](https://github.com/kubernetes/kubernetes/pull/44929), [[@liggitt](https://github.com/liggitt)](https://github.com/liggitt)) + + * The Categories []string field on discovered API resources represents the list of group aliases (e.g. "all") that each resource belongs to. ([[#43338](https://github.com/kubernetes/kubernetes/pull/43338)](https://github.com/kubernetes/kubernetes/pull/43338), [[@fabianofranz](https://github.com/fabianofranz)](https://github.com/fabianofranz)) + + * [alpha] The Kubernetes API supports retrieving tabular output for API resources via a new mime-type application/json;as=Table;v=v1alpha1;g=meta.k8s.io. The returned object (if the server supports it) will be of type meta.k8s.io/v1alpha1 with Table, and contain column and row information related to the resource. Each row will contain information about the resource - by default it will be the object metadata, but callers can add the ?includeObject=Object query parameter and receive the full object. In the future kubectl will use this to retrieve the results of `kubectl get`. ([[#40848](https://github.com/kubernetes/kubernetes/pull/40848)](https://github.com/kubernetes/kubernetes/pull/40848), [[@smarterclayton](https://github.com/smarterclayton)](https://github.com/smarterclayton)) + + * The Prometheus metrics for the kube-apiserver for tracking incoming API requests and latencies now return the subresource label for correctly attributing the type of API call. ([[#46354](https://github.com/kubernetes/kubernetes/pull/46354)](https://github.com/kubernetes/kubernetes/pull/46354), [[@smarterclayton](https://github.com/smarterclayton)](https://github.com/smarterclayton)) + + * The behavior of some watch calls to the server when filtering on fields was incorrect. If watching objects with a filter, when an update was made that no longer matched the filter a DELETE event was correctly sent. However, the object that was returned by that delete was not the (correct) version before the update, but instead, the newer version. That meant the new object was not matched by the filter. This was a regression from behavior between cached watches on the server side and uncached watches, and thus broke downstream API clients. ([[#46223](https://github.com/kubernetes/kubernetes/pull/46223)](https://github.com/kubernetes/kubernetes/pull/46223), [[@smarterclayton](https://github.com/smarterclayton)](https://github.com/smarterclayton)) + + * OpenAPI spec is now available in protobuf binary and gzip format (with ETag support) ([[#45836](https://github.com/kubernetes/kubernetes/pull/45836)](https://github.com/kubernetes/kubernetes/pull/45836), [[@mbohlool](https://github.com/mbohlool)](https://github.com/mbohlool)) + + * Updating apiserver to return UID of the deleted resource. Clients can use this UID to verify that the resource was deleted or waiting for finalizers. ([[#45600](https://github.com/kubernetes/kubernetes/pull/45600)](https://github.com/kubernetes/kubernetes/pull/45600), [[@nikhiljindal](https://github.com/nikhiljindal)](https://github.com/nikhiljindal)) + + * Fix incorrect conflict errors applying strategic merge patches to resources. ([[#43871](https://github.com/kubernetes/kubernetes/pull/43871)](https://github.com/kubernetes/kubernetes/pull/43871), [[@liggitt](https://github.com/liggitt)](https://github.com/liggitt)) + +* Apps + + * StatefulSet has a configurable update strategy. Updates can be performed using the RollingUpdate or OnDelete strategies. OnDelete is the default behavior, and it implements the same behavior as StatefulSets in 1.6. RollingUpdate performs automated, ordered updates to Pods in a StatefulSet. ([[#46669](https://github.com/kubernetes/kubernetes/pull/46669)](https://github.com/kubernetes/kubernetes/pull/46669), [[@kow3ns](https://github.com/kow3ns)](https://github.com/kow3ns))([kubernetes/features#287](https://github.com/kubernetes/features/issues/287)). + + * StatefulSetStatus now tracks replicas, readyReplicas, currentReplicas, and updatedReplicas. The semantics of replicas is now consistent with DaemonSet and ReplicaSet, and readyReplicas has the semantics that replicas did prior to 1.7 ([[#46669](https://github.com/kubernetes/kubernetes/pull/46669)](https://github.com/kubernetes/kubernetes/pull/46669), [[@kow3ns](https://github.com/kow3ns)](https://github.com/kow3ns)). + + * DaemonSets supports history and rollback ([[#45924](https://github.com/kubernetes/kubernetes/pull/45924)](https://github.com/kubernetes/kubernetes/pull/45924), [[@janetkuo](https://github.com/janetkuo)](https://github.com/janetkuo))([kubernetes/features#124](https://github.com/kubernetes/features/issues/124)). + + * ControllerRevision type has been added for StatefulSet and DaemonSet history. Clients should not depend on the stability of this type as it may change, as necessary, in future releases to support StatefulSet and DaemonSet update and rollback. We enable this type as we do with beta features, because StatefulSet update and DaemonSet update are enabled. ([[#45867](https://github.com/kubernetes/kubernetes/pull/45867)](https://github.com/kubernetes/kubernetes/pull/45867), [[@kow3ns](https://github.com/kow3ns)](https://github.com/kow3ns)) + + * PodDisruptionBudget now uses ControllerRef to decide which controller owns a given Pod, so it doesn't get confused by controllers with overlapping selectors. ([[#45003](https://github.com/kubernetes/kubernetes/pull/45003)](https://github.com/kubernetes/kubernetes/pull/45003), [[@krmayankk](https://github.com/krmayankk)](https://github.com/krmayankk)) + + * Deployments are updated to use (1) a more stable hashing algorithm (fnv) than the previous one (adler) and (2) a hashing collision avoidance mechanism that will ensure new rollouts will not block on hashing collisions anymore. ([[#44774](https://github.com/kubernetes/kubernetes/pull/44774)](https://github.com/kubernetes/kubernetes/pull/44774), [[@kargakis](https://github.com/kargakis)](https://github.com/kargakis))([kubernetes/features#287](https://github.com/kubernetes/features/issues/287)) + + * PodDisruptionBudget now has a MaxUnavailable field. This allows users to specify the maximum number of disruptions that can be tolerated during eviction. ([[#45587](https://github.com/kubernetes/kubernetes/pull/45587)](https://github.com/kubernetes/kubernetes/pull/45587), [[@foxish](https://github.com/foxish)](https://github.com/foxish))([kubernetes/features#285](https://github.com/kubernetes/features/issues/285)) + + * Deployments and DaemonSets rollouts are considered complete when all of the desired replicas are updated and available. This change affects `kubectl rollout status` and Deployment condition. ([[#44672](https://github.com/kubernetes/kubernetes/pull/44672)](https://github.com/kubernetes/kubernetes/pull/44672), [[@kargakis](https://github.com/kargakis)](https://github.com/kargakis)) + + * Job controller now respects ControllerRef to avoid fighting over Pods. ([[#42176](https://github.com/kubernetes/kubernetes/pull/42176)](https://github.com/kubernetes/kubernetes/pull/42176), [[@enisoc](https://github.com/enisoc)](https://github.com/enisoc)) + + * CronJob controller now respects ControllerRef to avoid fighting with other controllers. ([[#42177](https://github.com/kubernetes/kubernetes/pull/42177)](https://github.com/kubernetes/kubernetes/pull/42177), [[@enisoc](https://github.com/enisoc)](https://github.com/enisoc)) + +* Auth + + * Features: + + * Azure plugin for client auth ([[#43987](https://github.com/kubernetes/kubernetes/pull/43987)](https://github.com/kubernetes/kubernetes/pull/43987), [[@cosmincojocar](https://github.com/cosmincojocar)](https://github.com/cosmincojocar)) + + * Permission to use a PodSecurityPolicy can now be granted within a single namespace by allowing the use verb on the podsecuritypolicies resource within the namespace. ([[#42360](https://github.com/kubernetes/kubernetes/pull/42360)](https://github.com/kubernetes/kubernetes/pull/42360), [[@liggitt](https://github.com/liggitt)](https://github.com/liggitt)) + + * Break the 'certificatesigningrequests' controller into a 'csrapprover' controller and 'csrsigner' controller. ([[#45514](https://github.com/kubernetes/kubernetes/pull/45514)](https://github.com/kubernetes/kubernetes/pull/45514), [[@mikedanese](https://github.com/mikedanese)](https://github.com/mikedanese)) + + * kube-apiserver: `--service-account-lookup` now defaults to true, requiring the Secret API object containing the token to exist in order for a service account token to be valid. This enables service account tokens to be revoked by deleting the Secret object containing the token. ([[#44071](https://github.com/kubernetes/kubernetes/pull/44071)](https://github.com/kubernetes/kubernetes/pull/44071), [[@liggitt](https://github.com/liggitt)](https://github.com/liggitt)) + + * `kubectl auth can-i` now supports non-resource URLs ([[#46432](https://github.com/kubernetes/kubernetes/pull/46432)](https://github.com/kubernetes/kubernetes/pull/46432), [[@CaoShuFeng](https://github.com/CaoShuFeng)](https://github.com/CaoShuFeng)) + + * Promote kubelet tls bootstrap to beta. Add a non-experimental flag to use it and deprecate the old flag. ([[#46799](https://github.com/kubernetes/kubernetes/pull/46799)](https://github.com/kubernetes/kubernetes/pull/46799), [[@mikedanese](https://github.com/mikedanese)](https://github.com/mikedanese)) + + * Add the alpha.image-policy.k8s.io/failed-open=true annotation when the image policy webhook encounters an error and fails open. ([[#46264](https://github.com/kubernetes/kubernetes/pull/46264)](https://github.com/kubernetes/kubernetes/pull/46264), [[@Q-Lee](https://github.com/Q-Lee)](https://github.com/Q-Lee)) + + * Bug fixes: + + * Make gcp auth provider not to override the Auth header if it's already exits ([[#45575](https://github.com/kubernetes/kubernetes/pull/45575)](https://github.com/kubernetes/kubernetes/pull/45575), [[@wanghaoran1988](https://github.com/wanghaoran1988)](https://github.com/wanghaoran1988)) + + * The oidc client plugin has reduce round trips and fix scopes requested ([[#45317](https://github.com/kubernetes/kubernetes/pull/45317)](https://github.com/kubernetes/kubernetes/pull/45317), [[@ericchiang](https://github.com/ericchiang)](https://github.com/ericchiang)) + + * API requests using impersonation now include the system:authenticated group in the impersonated user automatically. ([[#44076](https://github.com/kubernetes/kubernetes/pull/44076)](https://github.com/kubernetes/kubernetes/pull/44076), [[@liggitt](https://github.com/liggitt)](https://github.com/liggitt)) + + * RBAC role and rolebinding auto-reconciliation is now performed only when the RBAC authorization mode is enabled. ([[#43813](https://github.com/kubernetes/kubernetes/pull/43813)](https://github.com/kubernetes/kubernetes/pull/43813), [[@liggitt](https://github.com/liggitt)](https://github.com/liggitt)) + + * PodSecurityPolicy now recognizes pods that specify runAsNonRoot: false in their security context and does not overwrite the specified value ([[#47073](https://github.com/kubernetes/kubernetes/pull/47073)](https://github.com/kubernetes/kubernetes/pull/47073), [[@Q-Lee](https://github.com/Q-Lee)](https://github.com/Q-Lee)) + + * Tokens retrieved from Google Cloud with application default credentials will not be cached if the client fails authorization ([[#46694](https://github.com/kubernetes/kubernetes/pull/46694)](https://github.com/kubernetes/kubernetes/pull/46694), [[@matt-tyler](https://github.com/matt-tyler)](https://github.com/matt-tyler)) + +* Autoscaling + + * Cluster Autoscaler 0.6. More information available [here](https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/README.md). + +* CLI + + * Features + + * `kubectl logs` supports specifying a container name when using label selectors ([[#44282](https://github.com/kubernetes/kubernetes/pull/44282)](https://github.com/kubernetes/kubernetes/pull/44282), [[@derekwaynecarr](https://github.com/derekwaynecarr)](https://github.com/derekwaynecarr)) + + * `kubectl rollout` supports undo and history for DaemonSet ([[#46144](https://github.com/kubernetes/kubernetes/pull/46144)](https://github.com/kubernetes/kubernetes/pull/46144), [[@janetkuo](https://github.com/janetkuo)](https://github.com/janetkuo)) + + * `kubectl rollout` supports status and history for StatefulSet ([[#46669](https://github.com/kubernetes/kubernetes/pull/46669)](https://github.com/kubernetes/kubernetes/pull/46669), [[@kow3ns](https://github.com/kow3ns)](https://github.com/kow3ns)). + + * Implement `kubectl get controllerrevisions` ([[#46655](https://github.com/kubernetes/kubernetes/pull/46655)](https://github.com/kubernetes/kubernetes/pull/46655), [[@janetkuo](https://github.com/janetkuo)](https://github.com/janetkuo)) + + * `kubectl create clusterrole` supports `--non-resource-url` ([[#45809](https://github.com/kubernetes/kubernetes/pull/45809)](https://github.com/kubernetes/kubernetes/pull/45809), [[@CaoShuFeng](https://github.com/CaoShuFeng)](https://github.com/CaoShuFeng)) + + * `kubectl logs` and `kubectl attach` support specifying a wait timeout with `--pod-running-timeout` + + * ([[#41813](https://github.com/kubernetes/kubernetes/pull/41813)](https://github.com/kubernetes/kubernetes/pull/41813), [[@shiywang](https://github.com/shiywang)](https://github.com/shiywang)) + + * New commands + + * Add `kubectl config rename-context` ([[#46114](https://github.com/kubernetes/kubernetes/pull/46114)](https://github.com/kubernetes/kubernetes/pull/46114), [[@arthur0](https://github.com/arthur0)](https://github.com/arthur0)) + + * Add `kubectl apply edit-last-applied` subcommand ([[#42256](https://github.com/kubernetes/kubernetes/pull/42256)](https://github.com/kubernetes/kubernetes/pull/42256), [[@shiywang](https://github.com/shiywang)](https://github.com/shiywang)) + + * Strategic Merge Patch + + * Reference docs now display the patch type and patch merge key used by `kubectl apply` to merge and identify unique elements in arrays. + + * `kubectl edit` and `kubectl apply` will keep the ordering of elements in merged lists ([[#45980](https://github.com/kubernetes/kubernetes/pull/45980)](https://github.com/kubernetes/kubernetes/pull/45980), [[@mengqiy](https://github.com/mengqiy)](https://github.com/mengqiy)) + + * New patch directive (retainKeys) to specifying clearing fields missing from the request ([[#44597](https://github.com/kubernetes/kubernetes/pull/44597)](https://github.com/kubernetes/kubernetes/pull/44597), [[@mengqiy](https://github.com/mengqiy)](https://github.com/mengqiy)) + + * Open API now includes strategic merge patch tags (previously only in go struct tags) ([[#44121](https://github.com/kubernetes/kubernetes/pull/44121)](https://github.com/kubernetes/kubernetes/pull/44121), [[@mbohlool](https://github.com/mbohlool)](https://github.com/mbohlool)) + + * Plugins + + * Introduces the ability to extend kubectl by adding third-party plugins. Developer preview, please refer to the documentation for instructions about how to use it. ([[#37499](https://github.com/kubernetes/kubernetes/pull/37499)](https://github.com/kubernetes/kubernetes/pull/37499), [[@fabianofranz](https://github.com/fabianofranz)](https://github.com/fabianofranz)) + + * Added support for a hierarchy of kubectl plugins (a tree of plugins as children of other plugins). ([[#45981](https://github.com/kubernetes/kubernetes/pull/45981)](https://github.com/kubernetes/kubernetes/pull/45981), [[@fabianofranz](https://github.com/fabianofranz)](https://github.com/fabianofranz)) + + * Added exported env vars to kubectl plugins so that plugin developers have access to global flags, namespace, the plugin descriptor and the full path to the caller binary. + + * Enhancement + + * `kubectl auth can-i` now supports non-resource URLs ([[#46432](https://github.com/kubernetes/kubernetes/pull/46432)](https://github.com/kubernetes/kubernetes/pull/46432), [[@CaoShuFeng](https://github.com/CaoShuFeng)](https://github.com/CaoShuFeng)) + + * `kubectl set selector` and `kubectl set subject` no longer print "running in local/dry-run mode..." at the top. The output can now be piped and interpretted as yaml or json ([[#46507](https://github.com/kubernetes/kubernetes/pull/46507)](https://github.com/kubernetes/kubernetes/pull/46507), [[@bboreham](https://github.com/bboreham)](https://github.com/bboreham)) + + * When using an in-cluster client with an empty configuration, the `--namespace` flag is now honored ([[#46299](https://github.com/kubernetes/kubernetes/pull/46299)](https://github.com/kubernetes/kubernetes/pull/46299), [[@ncdc](https://github.com/ncdc)](https://github.com/ncdc)) + + * The help message for missingResourceError is now generic ([[#45582](https://github.com/kubernetes/kubernetes/pull/45582)](https://github.com/kubernetes/kubernetes/pull/45582), [[@CaoShuFeng](https://github.com/CaoShuFeng)](https://github.com/CaoShuFeng)) + + * `kubectl taint node` now supports label selectors ([[#44740](https://github.com/kubernetes/kubernetes/pull/44740)](https://github.com/kubernetes/kubernetes/pull/44740), [[@ravisantoshgudimetla](https://github.com/ravisantoshgudimetla)](https://github.com/ravisantoshgudimetla)) + + * `kubectl proxy --www` now logs a warning when the dir is invalid ([[#44952](https://github.com/kubernetes/kubernetes/pull/44952)](https://github.com/kubernetes/kubernetes/pull/44952), [[@CaoShuFeng](https://github.com/CaoShuFeng)](https://github.com/CaoShuFeng)) + + * `kubectl taint` output has been enhanced with the operation ([[#43171](https://github.com/kubernetes/kubernetes/pull/43171)](https://github.com/kubernetes/kubernetes/pull/43171), [[@ravisantoshgudimetla](https://github.com/ravisantoshgudimetla)](https://github.com/ravisantoshgudimetla)) + + * Kubectl `--user` and `--cluster` now support completion ([[#44251](https://github.com/kubernetes/kubernetes/pull/44251)](https://github.com/kubernetes/kubernetes/pull/44251), [[@superbrothers](https://github.com/superbrothers)](https://github.com/superbrothers)) + + * `kubectl config use-context` now supports completion ([[#42336](https://github.com/kubernetes/kubernetes/pull/42336)](https://github.com/kubernetes/kubernetes/pull/42336), [[@superbrothers](https://github.com/superbrothers)](https://github.com/superbrothers)) + + * `kubectl version` now supports `--output` ([[#39858](https://github.com/kubernetes/kubernetes/pull/39858)](https://github.com/kubernetes/kubernetes/pull/39858), [[@alejandroEsc](https://github.com/alejandroEsc)](https://github.com/alejandroEsc)) + + * Printing/describe + + * Print conditions of RC/RS in `kubectl describe` command. ([[#44710](https://github.com/kubernetes/kubernetes/pull/44710)](https://github.com/kubernetes/kubernetes/pull/44710), [[@xiangpengzhao](https://github.com/xiangpengzhao)](https://github.com/xiangpengzhao)) + + * Improved output on `kubectl get` and `kubectl describe` for generic objects. ([[#44222](https://github.com/kubernetes/kubernetes/pull/44222)](https://github.com/kubernetes/kubernetes/pull/44222), [[@fabianofranz](https://github.com/fabianofranz)](https://github.com/fabianofranz)) + + * In `kubectl describe`, find controllers with ControllerRef, instead of showing the original creator. ([[#42849](https://github.com/kubernetes/kubernetes/pull/42849)](https://github.com/kubernetes/kubernetes/pull/42849), [[@janetkuo](https://github.com/janetkuo)](https://github.com/janetkuo)) + + * Bug fixes + + * Fix some false negatives in detection of meaningful conflicts during strategic merge patch with maps and lists. ([[#43469](https://github.com/kubernetes/kubernetes/pull/43469)](https://github.com/kubernetes/kubernetes/pull/43469), [[@enisoc](https://github.com/enisoc)](https://github.com/enisoc)) + + * Restored the ability of kubectl running inside a pod to consume resource files specifying a different namespace than the one the pod is running in. ([[#44862](https://github.com/kubernetes/kubernetes/pull/44862)](https://github.com/kubernetes/kubernetes/pull/44862), [[@liggitt](https://github.com/liggitt)](https://github.com/liggitt)) + + * Kubectl commands run inside a pod using a kubeconfig file now use the namespace specified in the kubeconfig file, instead of using the pod namespace. If no kubeconfig file is used, or the kubeconfig does not specify a namespace, the pod namespace is still used as a fallback. ([[#44570](https://github.com/kubernetes/kubernetes/pull/44570)](https://github.com/kubernetes/kubernetes/pull/44570), [[@liggitt](https://github.com/liggitt)](https://github.com/liggitt)) + + * Fixed `kubectl cluster-info` dump to support multi-container pod. ([[#44088](https://github.com/kubernetes/kubernetes/pull/44088)](https://github.com/kubernetes/kubernetes/pull/44088), [[@xingzhou](https://github.com/xingzhou)](https://github.com/xingzhou)) + + * Kubectl will print a warning when deleting the current context ([[#42538](https://github.com/kubernetes/kubernetes/pull/42538)](https://github.com/kubernetes/kubernetes/pull/42538), [[@adohe](https://github.com/adohe)](https://github.com/adohe)) + + * Fix VolumeClaims/capacity in `kubectl describe statefulsets` output. ([[#47573](https://github.com/kubernetes/kubernetes/pull/47573)](https://github.com/kubernetes/kubernetes/pull/47573), [[@k82cn](https://github.com/k82cn)](https://github.com/k82cn)) + + * I18n + + * Add Traditional Chinese translation for kubectl ([[#46559](https://github.com/kubernetes/kubernetes/pull/46559)](https://github.com/kubernetes/kubernetes/pull/46559), [[@warmchang](https://github.com/warmchang)](https://github.com/warmchang)) + + * Add Japanese translation for kubectl ([[#46756](https://github.com/kubernetes/kubernetes/pull/46756)](https://github.com/kubernetes/kubernetes/pull/46756), [[@girikuncoro](https://github.com/girikuncoro)](https://github.com/girikuncoro)) + + * Add Simplified Chinese translation for kubectl ([[#45573](https://github.com/kubernetes/kubernetes/pull/45573)](https://github.com/kubernetes/kubernetes/pull/45573), [[@shiywang](https://github.com/shiywang)](https://github.com/shiywang)) + +* Cluster Lifecycle + + * Features: + + * kubeadm: Enable the Node Authorizer/Admission plugin in v1.7 ([[#46879](https://github.com/kubernetes/kubernetes/pull/46879)](https://github.com/kubernetes/kubernetes/pull/46879), [[@luxas](https://github.com/luxas)](https://github.com/luxas)) + + * kubeadm: Users can now pass extra parameters to etcd in a kubeadm cluster ([[#42246](https://github.com/kubernetes/kubernetes/pull/42246)](https://github.com/kubernetes/kubernetes/pull/42246), [[@jamiehannaford](https://github.com/jamiehannaford)](https://github.com/jamiehannaford)) + + * kubeadm: Make kubeadm use the new CSR approver in v1.7 ([[#46864](https://github.com/kubernetes/kubernetes/pull/46864)](https://github.com/kubernetes/kubernetes/pull/46864), [[@luxas](https://github.com/luxas)](https://github.com/luxas)) + + * kubeadm: Allow enabling multiple authorization modes at the same time ([[#42557](https://github.com/kubernetes/kubernetes/pull/42557)](https://github.com/kubernetes/kubernetes/pull/42557), [[@xilabao](https://github.com/xilabao)](https://github.com/xilabao)) + + * kubeadm: add proxy client-certs to kube-apiserver to allow it to proxy aggregated api servers ([[#43715](https://github.com/kubernetes/kubernetes/pull/43715)](https://github.com/kubernetes/kubernetes/pull/43715), [[@deads2k](https://github.com/deads2k)](https://github.com/deads2k)) + + * Action required when upgrading: + + * kubeadm: Modifications to cluster-internal resources installed by kubeadm will be overwritten when upgrading from v1.6 to v1.7. ([[#47081](https://github.com/kubernetes/kubernetes/pull/47081)](https://github.com/kubernetes/kubernetes/pull/47081), [[@luxas](https://github.com/luxas)](https://github.com/luxas)) + + * kubeadm deb/rpm packages: cAdvisor doesn't listen on `0.0.0.0:4194` without authentication/authorization because of the possible information leakage. The cAdvisor API can still be accessed via `https://{node-ip}:10250/stats/`, though. ([kubernetes/release#356](https://github.com/kubernetes/release/pull/356), [[@luxas](https://github.com/luxas)](https://github.com/luxas)) + + * Deletions: + + * cluster/ubuntu: Removed due to [deprecation](https://github.com/kubernetes/kubernetes/tree/master/cluster#cluster-configuration) and lack of maintenance. ([[#44344](https://github.com/kubernetes/kubernetes/pull/44344)](https://github.com/kubernetes/kubernetes/pull/44344), [[@mikedanese](https://github.com/mikedanese)](https://github.com/mikedanese)) + + * cluster/aws: Removed due to [deprecation](https://github.com/kubernetes/kubernetes/pull/38772) and lack of maintenance. ([[#42196](https://github.com/kubernetes/kubernetes/pull/42196)](https://github.com/kubernetes/kubernetes/pull/42196), [[@zmerlynn](https://github.com/zmerlynn)](https://github.com/zmerlynn)) + +* Federation + + * TODO: Sig-federation please find notable changes (feature & bug fix) below for your SIG and pull into this section + +* Instrumentation + + * Bumped Heapster to v1.4.0. More details about the release https://github.com/kubernetes/heapster/releases/tag/v1.4.0 + + * Fluentd manifest pod is no longer created on non-registered master when creating clusters using kube-up.sh. ([[#44721](https://github.com/kubernetes/kubernetes/pull/44721)](https://github.com/kubernetes/kubernetes/pull/44721), [[@piosz](https://github.com/piosz)](https://github.com/piosz)) + + * Stackdriver cluster logging now deploys a new component to export Kubernetes events. ([[#46700](https://github.com/kubernetes/kubernetes/pull/46700)](https://github.com/kubernetes/kubernetes/pull/46700), [[@crassirostris](https://github.com/crassirostris)](https://github.com/crassirostris)) + + * Stackdriver Logging deployment exposes metrics on node port 31337 when enabled. ([[#47402](https://github.com/kubernetes/kubernetes/pull/47402)](https://github.com/kubernetes/kubernetes/pull/47402), [[@crassirostris](https://github.com/crassirostris)](https://github.com/crassirostris)) + +* Network + + * DNS and name resolution + + * Updates kube-dns to 1.14.2 ([[#45684](https://github.com/kubernetes/kubernetes/pull/45684)](https://github.com/kubernetes/kubernetes/pull/45684), [[@bowei](https://github.com/bowei)](https://github.com/bowei)) + + * Support kube-master-url flag without kubeconfig + + * Fix concurrent R/Ws in dns.go + + * Fix confusing logging when initializing server + + * Fix printf in cmd/kube-dns/app/server.go + + * Fix version on startup and `--version` flag + + * Support specifying port number for nameserver in stubDomains + + * A new field hostAliases has been added to pod.spec to support adding entries to a Pod's /etc/hosts file. ([[#44641](https://github.com/kubernetes/kubernetes/pull/44641)](https://github.com/kubernetes/kubernetes/pull/44641), [[@rickypai](https://github.com/rickypai)](https://github.com/rickypai)) + + * Fix DNS suffix search list support in Windows kube-proxy. ([[#45642](https://github.com/kubernetes/kubernetes/pull/45642)](https://github.com/kubernetes/kubernetes/pull/45642), [[@JiangtianLi](https://github.com/JiangtianLi)](https://github.com/JiangtianLi)) + + * Kube Proxy + + * kube-proxy: ratelimit runs of iptables by sync-period flags ([[#46266](https://github.com/kubernetes/kubernetes/pull/46266)](https://github.com/kubernetes/kubernetes/pull/46266), [[@thockin](https://github.com/thockin)](https://github.com/thockin)) + + * Fixes a bug in the kubernetes-worker Juju charm code that attempted to give kube-proxy more than one api endpoint. ([[#44677](https://github.com/kubernetes/kubernetes/pull/44677)](https://github.com/kubernetes/kubernetes/pull/44677), [[@wwwtyro](https://github.com/wwwtyro)](https://github.com/wwwtyro)) + + * IP masquerade + + * ip-masq-agent is now on by default for GCE ([[#47794](https://github.com/kubernetes/kubernetes/pull/47794)](https://github.com/kubernetes/kubernetes/pull/47794), [[@dnardo](https://github.com/dnardo)](https://github.com/dnardo)) + + * Bump the memory request/limit for ip-masq-daemon. ([[#47887](https://github.com/kubernetes/kubernetes/pull/47887)](https://github.com/kubernetes/kubernetes/pull/47887), [[@dnardo](https://github.com/dnardo)](https://github.com/dnardo)) + + * Cloud provider: AWS + + * New 'service.beta.kubernetes.io/aws-load-balancer-extra-security-groups' Service annotation to specify extra Security Groups to be added to ELB created by AWS cloudprovider ([[#45268](https://github.com/kubernetes/kubernetes/pull/45268)](https://github.com/kubernetes/kubernetes/pull/45268), [[@redbaron](https://github.com/redbaron)](https://github.com/redbaron)) + + * Clean up blackhole routes when using kubenet ([[#47572](https://github.com/kubernetes/kubernetes/pull/47572)](https://github.com/kubernetes/kubernetes/pull/47572), [[@justinsb](https://github.com/justinsb)](https://github.com/justinsb)) + + * Maintain a cache of all instances, to fix problem with > 200 nodes with ELBs ([[#47410](https://github.com/kubernetes/kubernetes/pull/47410)](https://github.com/kubernetes/kubernetes/pull/47410), [[@justinsb](https://github.com/justinsb)](https://github.com/justinsb)) + + * Avoid spurious ELB listener recreation - ignore case when matching protocol ([[#47391](https://github.com/kubernetes/kubernetes/pull/47391)](https://github.com/kubernetes/kubernetes/pull/47391), [[@justinsb](https://github.com/justinsb)](https://github.com/justinsb)) + + * Allow configuration of a single security group for ELBs ([[#45500](https://github.com/kubernetes/kubernetes/pull/45500)](https://github.com/kubernetes/kubernetes/pull/45500), [[@nbutton23](https://github.com/nbutton23)](https://github.com/nbutton23)) + + * Remove check that forces loadBalancerSourceRanges to be 0.0.0.0/0. ([[#38636](https://github.com/kubernetes/kubernetes/pull/38636)](https://github.com/kubernetes/kubernetes/pull/38636), [[@dhawal55](https://github.com/dhawal55)](https://github.com/dhawal55)) + + * Cloud provider: Azure + + * Add support for UDP ports ([[#45523](https://github.com/kubernetes/kubernetes/pull/45523)](https://github.com/kubernetes/kubernetes/pull/45523), [[@colemickens](https://github.com/colemickens)](https://github.com/colemickens)) + + * Fix support for multiple loadBalancerSourceRanges ([[#45523](https://github.com/kubernetes/kubernetes/pull/45523)](https://github.com/kubernetes/kubernetes/pull/45523), [[@colemickens](https://github.com/colemickens)](https://github.com/colemickens)) + + * Support the Service spec's sessionAffinity ([[#45523](https://github.com/kubernetes/kubernetes/pull/45523)](https://github.com/kubernetes/kubernetes/pull/45523), [[@colemickens](https://github.com/colemickens)](https://github.com/colemickens)) + + * Cloud provider: GCE + + * Bump GLBC version to 0.9.5 - fixes [loss of manually modified GCLB health check settings](https://github.com/kubernetes/kubernetes/issues/47559) upon upgrade from pre-1.6.4 to either 1.6.4 or 1.6.5. ([[#47567](https://github.com/kubernetes/kubernetes/pull/47567)](https://github.com/kubernetes/kubernetes/pull/47567), [[@nicksardo](https://github.com/nicksardo)](https://github.com/nicksardo)) + + * [beta] Support creation of GCP Internal Load Balancers from Service objects ([[#46663](https://github.com/kubernetes/kubernetes/pull/46663)](https://github.com/kubernetes/kubernetes/pull/46663), [[@nicksardo](https://github.com/nicksardo)](https://github.com/nicksardo)) + + * GCE installs will now avoid IP masquerade for all RFC-1918 IP blocks, rather than just 10.0.0.0/8. This means that clusters can be created in 192.168.0.0./16 and 172.16.0.0/12 while preserving the container IPs (which would be lost before). ([[#46473](https://github.com/kubernetes/kubernetes/pull/46473)](https://github.com/kubernetes/kubernetes/pull/46473), [[@thockin](https://github.com/thockin)](https://github.com/thockin)) + + * The Calico version included in kube-up for GCE has been updated to v2.2. ([[#38169](https://github.com/kubernetes/kubernetes/pull/38169)](https://github.com/kubernetes/kubernetes/pull/38169), [[@caseydavenport](https://github.com/caseydavenport)](https://github.com/caseydavenport)) + + * Add ip-masq-agent addon to the addons folder which is used in GCE if `--non-masquerade-cidr` is set to 0/0 ([[#46038](https://github.com/kubernetes/kubernetes/pull/46038)](https://github.com/kubernetes/kubernetes/pull/46038), [[@dnardo](https://github.com/dnardo)](https://github.com/dnardo)) + + * Adds support for allocation of pod IPs via IP aliases. ([[#42147](https://github.com/kubernetes/kubernetes/pull/42147)](https://github.com/kubernetes/kubernetes/pull/42147), [[@bowei](https://github.com/bowei)](https://github.com/bowei)) + + * Cloud provider vSphere: + + * cloud provider: Filter out IPV6 node addresses. ([[#45181](https://github.com/kubernetes/kubernetes/pull/45181)](https://github.com/kubernetes/kubernetes/pull/45181), [[@BaluDontu](https://github.com/BaluDontu)](https://github.com/BaluDontu)) + + * Cloud provider OpenStack: + + * Fixes issue during LB creation where ports were incorrectly assigned to a floating IP ([[#44387](https://github.com/kubernetes/kubernetes/pull/44387)](https://github.com/kubernetes/kubernetes/pull/44387), [[@jamiehannaford](https://github.com/jamiehannaford)](https://github.com/jamiehannaford)) + + * Network policy + + * Add short name "netpol" for networkpolicies ([[#42241](https://github.com/kubernetes/kubernetes/pull/42241)](https://github.com/kubernetes/kubernetes/pull/42241), [[@xiangpengzhao](https://github.com/xiangpengzhao)](https://github.com/xiangpengzhao)) + + * ServiceController + + * Exclude nodes labeled as master from LoadBalancer / NodePort; restores documented behaviour. ([[#44745](https://github.com/kubernetes/kubernetes/pull/44745)](https://github.com/kubernetes/kubernetes/pull/44745), [[@justinsb](https://github.com/justinsb)](https://github.com/justinsb)) + + * Fix node selection logic on initial LB creation ([[#45773](https://github.com/kubernetes/kubernetes/pull/45773)](https://github.com/kubernetes/kubernetes/pull/45773), [[@justinsb](https://github.com/justinsb)](https://github.com/justinsb)) + + * Security updates + + * Update kube-dns and ip-masq-agent addons with new base images containing fixes for CVE-2016-4448, CVE-2016-9841, CVE-2016-9843, CVE-2017-1000366, CVE-2017-2616, and CVE-2017-9526. ([[#47877](https://github.com/kubernetes/kubernetes/pull/47877)](https://github.com/kubernetes/kubernetes/pull/47877), [[@ixdy](https://github.com/ixdy)](https://github.com/ixdy)) + + * Source IP preservation + + * Promotes Source IP preservation for Virtual IPs to GA. ([[#41162](https://github.com/kubernetes/kubernetes/pull/41162)](https://github.com/kubernetes/kubernetes/pull/41162), [[@MrHohn](https://github.com/MrHohn)](https://github.com/MrHohn)). Two annotations have been promoted to API fields: + + * Service.Spec.ExternalTrafficPolicy was 'service.beta.kubernetes.io/external-traffic' annotation. + + * Service.Spec.HealthCheckNodePort was 'service.beta.kubernetes.io/healthcheck-nodeport' annotation. + + * When switching from the service.beta.kubernetes.io/external-traffic annotation to the new externalTrafficPolicy field, the values change as follows: * "OnlyLocal" becomes "Local" * "Global" becomes "Cluster". ([[#46716](https://github.com/kubernetes/kubernetes/pull/46716)](https://github.com/kubernetes/kubernetes/pull/46716), [[@thockin](https://github.com/thockin)](https://github.com/thockin)) + + * Documentation + + * Documented NodePort networking for CDK. ([[#44863](https://github.com/kubernetes/kubernetes/pull/44863)](https://github.com/kubernetes/kubernetes/pull/44863), [[@chuckbutler](https://github.com/chuckbutler)](https://github.com/chuckbutler)) + +* Node + + * Features + + * Kubelet Container Runtime Interface (CRI) support + + * [GA] The Docker-CRI implementation is GA. The legacy, non-CRI Docker integration has been completely removed. + + * [beta] [CRI-O](https://github.com/kubernetes-incubator/cri-o) v1.0.0-alpha.0. It has passed all e2e tests. ([release notes](https://github.com/kubernetes-incubator/cri-o/releases/tag/v1.0.0-alpha.0)) + + * [beta] [Frakti](https://github.com/kubernetes/frakti) v1.0. It has passed all node conformance tests. ([release notes](https://github.com/kubernetes/frakti/releases/tag/v1.0)) + + * [alpha] [cri-containerd](https://github.com/kubernetes-incubator/cri-containerd) v0.1.0. It supports basic sandbox/container/image management and passes 30/36 CRI validation test. ([release notes](https://github.com/kubernetes-incubator/cri-containerd/releases/tag/v0.1.0)) + + * Support running Ubuntu image on GCE node ([[#44744](https://github.com/kubernetes/kubernetes/pull/44744)](https://github.com/kubernetes/kubernetes/pull/44744), [[@yguo0905](https://github.com/yguo0905)](https://github.com/yguo0905)) + + * Kubernetes now shares a single PID namespace among all containers in a pod when running with docker >= 1.13.1. This means processes can now signal processes in other containers in a pod, but it also means that the `kubectl exec {pod} kill 1` pattern will cause the Pod to be restarted rather than a single container. ([[#45236](https://github.com/kubernetes/kubernetes/pull/45236)](https://github.com/kubernetes/kubernetes/pull/45236), [[@verb](https://github.com/verb)](https://github.com/verb)) + + * A new field hostAliases has been added to the pod spec to support adding entries to a Pod's /etc/hosts file. ([docs PR](https://github.com/kubernetes/kubernetes.github.io/pull/4080))([[#44641](https://github.com/kubernetes/kubernetes/pull/44641)](https://github.com/kubernetes/kubernetes/pull/44641), [[@rickypai](https://github.com/rickypai)](https://github.com/rickypai)) + + * With `--feature-gates=RotateKubeletClientCertificate=true` set, the Kubelet will ([[#41912](https://github.com/kubernetes/kubernetes/pull/41912)](https://github.com/kubernetes/kubernetes/pull/41912), [[@jcbsmpsn](https://github.com/jcbsmpsn)](https://github.com/jcbsmpsn)) + + * request a client certificate from the API server during the boot cycle and pause + + * waiting for the request to be satisfied. It will continually refresh the certificate + + * Create clusters with GPUs in GCE by specifying `type=,count=` to NODE_ACCELERATORS environment variable. ([[#45130](https://github.com/kubernetes/kubernetes/pull/45130)](https://github.com/kubernetes/kubernetes/pull/45130), [[@vishh](https://github.com/vishh)](https://github.com/vishh)) + + * List of available GPUs - [https://cloud.google.com/compute/docs/gpus/#introduction](https://cloud.google.com/compute/docs/gpus/#introduction) + + * Disk Pressure triggers the deletion of terminated containers on the node. ([[#45896](https://github.com/kubernetes/kubernetes/pull/45896)](https://github.com/kubernetes/kubernetes/pull/45896), [[@dashpole](https://github.com/dashpole)](https://github.com/dashpole)) + + * Support status.hostIP in downward API ([[#42717](https://github.com/kubernetes/kubernetes/pull/42717)](https://github.com/kubernetes/kubernetes/pull/42717), [[@andrewsykim](https://github.com/andrewsykim)](https://github.com/andrewsykim)) + + * Upgrade Node Problem Detector to v0.4.1. New features added: + + * Add /dev/kmsg support for kernel log parsing. ([#112](https://github.com/kubernetes/node-problem-detector/pull/112), [[@euank](https://github.com/euank)](https://github.com/euank)) + + * Add ABRT support. ([#105](https://github.com/kubernetes/node-problem-detector/pull/105), [[@juliusmilan](https://github.com/juliusmilan)](https://github.com/juliusmilan)) + + * Add a docker image corruption problem detection in the default docker monitor config. ([#117](https://github.com/kubernetes/node-problem-detector/pull/117), [[@ajitak](https://github.com/ajitak)](https://github.com/ajitak)) + + * Upgrade CAdvisor to v0.26.1. New features added: + + * Add Docker overlay2 storage driver support. + + * Add ZFS support. + + * Add UDP metrics (collection disabled by default). + + * Bug fixes + + * Changed Kubelet default image-gc-high-threshold to 85% to resolve a conflict with default settings in docker that prevented image garbage collection from resolving low disk space situations when using devicemapper storage. ([[#40432](https://github.com/kubernetes/kubernetes/pull/40432)](https://github.com/kubernetes/kubernetes/pull/40432), [[@sjenning](https://github.com/sjenning)](https://github.com/sjenning)) + + * Mark all static pods on the Master node as critical to prevent preemption ([[#47356](https://github.com/kubernetes/kubernetes/pull/47356)](https://github.com/kubernetes/kubernetes/pull/47356), [[@dashpole](https://github.com/dashpole)](https://github.com/dashpole)) + + * Restrict active deadline seconds max allowed value to be maximum uint32 to avoid overflow ([[#46640](https://github.com/kubernetes/kubernetes/pull/46640)](https://github.com/kubernetes/kubernetes/pull/46640), [[@derekwaynecarr](https://github.com/derekwaynecarr)](https://github.com/derekwaynecarr)) + + * Fix a bug with cAdvisorPort in the KubeletConfiguration that prevented setting it to 0, which is in fact a valid option, as noted in issue [[#11710](https://github.com/kubernetes/kubernetes/pull/11710)](https://github.com/kubernetes/kubernetes/pull/11710). ([[#46876](https://github.com/kubernetes/kubernetes/pull/46876)](https://github.com/kubernetes/kubernetes/pull/46876), [[@mtaufen](https://github.com/mtaufen)](https://github.com/mtaufen)) + + * Fix a bug where container cannot run as root when SecurityContext.RunAsNonRoot is false. ([[#47009](https://github.com/kubernetes/kubernetes/pull/47009)](https://github.com/kubernetes/kubernetes/pull/47009), [[@yujuhong](https://github.com/yujuhong)](https://github.com/yujuhong)) + + * Fix the Kubelet PLEG update timestamp to better reflect the health of the component when the container runtime request hangs. ([[#45496](https://github.com/kubernetes/kubernetes/pull/45496)](https://github.com/kubernetes/kubernetes/pull/45496), [[@andyxning](https://github.com/andyxning)](https://github.com/andyxning)) + + * Avoid failing sync loop health check on container runtime errors ([[#47124](https://github.com/kubernetes/kubernetes/pull/47124)](https://github.com/kubernetes/kubernetes/pull/47124), [[@andyxning](https://github.com/andyxning)](https://github.com/andyxning)) + + * Fix a bug where Kubelet does not ignore pod manifest files starting with dots ([[#45111](https://github.com/kubernetes/kubernetes/pull/45111)](https://github.com/kubernetes/kubernetes/pull/45111), [[@dwradcliffe](https://github.com/dwradcliffe)](https://github.com/dwradcliffe)) + + * Changes/deprecations + + * Marks the Kubelet's `--master-service-namespace` flag deprecated ([[#44250](https://github.com/kubernetes/kubernetes/pull/44250)](https://github.com/kubernetes/kubernetes/pull/44250), [[@mtaufen](https://github.com/mtaufen)](https://github.com/mtaufen)) + + * Remove PodSandboxStatus.Linux.Namespaces.Network from CRI since it is not used/needed. ([[#45166](https://github.com/kubernetes/kubernetes/pull/45166)](https://github.com/kubernetes/kubernetes/pull/45166), [[@feiskyer](https://github.com/feiskyer)](https://github.com/feiskyer)) + + * Remove the `--enable-cri` flag. CRI is now the default, and the only way to integrate with Kubelet for the container runtimes.([[#45194](https://github.com/kubernetes/kubernetes/pull/45194)](https://github.com/kubernetes/kubernetes/pull/45194), [[@yujuhong](https://github.com/yujuhong)](https://github.com/yujuhong)) + + * CRI has been moved to package pkg/kubelet/apis/cri/v1alpha1/runtime as part of Kubelet API path cleanup. ([[#47113](https://github.com/kubernetes/kubernetes/pull/47113)](https://github.com/kubernetes/kubernetes/pull/47113), [[@feiskyer](https://github.com/feiskyer)](https://github.com/feiskyer)) + + * Add generic Toleration for NoExecute Taints to NodeProblemDetector, so that NPD can be scheduled to nodes with NoExecute taints by default. ([[#45883](https://github.com/kubernetes/kubernetes/pull/45883)](https://github.com/kubernetes/kubernetes/pull/45883), [[@gmarek](https://github.com/gmarek)](https://github.com/gmarek)) + +* Scheduling + + * NOTE: If you are using `AffinityInAnnotations=true` in `--feature-gates`, then the 1.7 release is your last opportunity to convert from specifying affinity/anti-affinity using the scheduler.alpha.kubernetes.io/affinity annotation on Pods, to using the Affinity field of PodSpec. Support for the alpha version of node and pod affinity (which uses the scheduler.alpha.kubernetes.io/affinity annotations on Pods) is going away **in Kubernetes 1.8** (not this release, but the next release). If you have not enabled AffinityInAnnotations=true in `--feature-gates`, then this change does not affect you. + + * Move hardPodAffinitySymmetricWeight to scheduler policy config ([[#44159](https://github.com/kubernetes/kubernetes/pull/44159)](https://github.com/kubernetes/kubernetes/pull/44159), [[@wanghaoran1988](https://github.com/wanghaoran1988)](https://github.com/wanghaoran1988)) + +* Storage + + * Features + + * The options passed to a Flexvolume plugin's mount command now contains the pod name (kubernetes.io/pod.name), namespace (kubernetes.io/pod.namespace), uid (kubernetes.io/pod.uid), and service account name (kubernetes.io/serviceAccount.name). ([[#39488](https://github.com/kubernetes/kubernetes/pull/39488)](https://github.com/kubernetes/kubernetes/pull/39488), [[@liggitt](https://github.com/liggitt)](https://github.com/liggitt)) + + * GCE and AWS dynamic provisioners extension: admins can configure zone(s) in which a persistent volume shall be created. ([[#38505](https://github.com/kubernetes/kubernetes/pull/38505)](https://github.com/kubernetes/kubernetes/pull/38505), [[@pospispa](https://github.com/pospispa)](https://github.com/pospispa)) + + * Implement API usage metrics for GCE storage. ([[#40338](https://github.com/kubernetes/kubernetes/pull/40338)](https://github.com/kubernetes/kubernetes/pull/40338), [[@gnufied](https://github.com/gnufied)](https://github.com/gnufied)) + + * Add support for emitting metrics from openstack cloudprovider about storage operations. ([[#46008](https://github.com/kubernetes/kubernetes/pull/46008)](https://github.com/kubernetes/kubernetes/pull/46008), [[@NickrenREN](https://github.com/NickrenREN)](https://github.com/NickrenREN)) + + * vSphere cloud provider: vSphere storage policy support for dynamic volume provisioning. ([[#46176](https://github.com/kubernetes/kubernetes/pull/46176)](https://github.com/kubernetes/kubernetes/pull/46176), [[@BaluDontu](https://github.com/BaluDontu)](https://github.com/BaluDontu)) + + * Support StorageClass in Azure file volume ([[#42170](https://github.com/kubernetes/kubernetes/pull/42170)](https://github.com/kubernetes/kubernetes/pull/42170), [[@rootfs](https://github.com/rootfs)](https://github.com/rootfs)) + + * Start recording cloud provider metrics for AWS ([[#43477](https://github.com/kubernetes/kubernetes/pull/43477)](https://github.com/kubernetes/kubernetes/pull/43477), [[@gnufied](https://github.com/gnufied)](https://github.com/gnufied)) + + * Support iSCSI CHAP authentication ([[#43396](https://github.com/kubernetes/kubernetes/pull/43396)](https://github.com/kubernetes/kubernetes/pull/43396), [[@rootfs](https://github.com/rootfs)](https://github.com/rootfs)) + + * Openstack cinder v1/v2/auto API support ([[#40423](https://github.com/kubernetes/kubernetes/pull/40423)](https://github.com/kubernetes/kubernetes/pull/40423), [[@mkutsevol](https://github.com/mkutsevol)](https://github.com/mkutsevol)) + + * Bug-Fixes + + * Fixes issue with Flexvolume, introduced in 1.6.0, where drivers without an attacher would fail (node indefinitely waiting for attach). A driver API addition is introduced: drivers that don't implement attach should return attach: false on init. ([[#47503](https://github.com/kubernetes/kubernetes/pull/47503)](https://github.com/kubernetes/kubernetes/pull/47503), [[@chakri-nelluri](https://github.com/chakri-nelluri)](https://github.com/chakri-nelluri)) + + * Fix dynamic provisioning of PVs with inaccurate AccessModes by refusing to provision when PVCs ask for AccessModes that can't be satisfied by the PVs' underlying volume plugin. ([[#47274](https://github.com/kubernetes/kubernetes/pull/47274)](https://github.com/kubernetes/kubernetes/pull/47274), [[@wongma7](https://github.com/wongma7)](https://github.com/wongma7)) + + * Fix pods failing to start if they specify a file as a volume subPath to mount. ([[#45623](https://github.com/kubernetes/kubernetes/pull/45623)](https://github.com/kubernetes/kubernetes/pull/45623), [[@wongma7](https://github.com/wongma7)](https://github.com/wongma7)) + + * Fix erroneous FailedSync and FailedMount events being periodically and indefinitely posted on Pods after kubelet is restarted. ([[#44781](https://github.com/kubernetes/kubernetes/pull/44781)](https://github.com/kubernetes/kubernetes/pull/44781), [[@wongma7](https://github.com/wongma7)](https://github.com/wongma7)) + + * Fix AWS EBS volumes not getting detached from node if routine to verify volumes are attached runs while the node is down ([[#46463](https://github.com/kubernetes/kubernetes/pull/46463)](https://github.com/kubernetes/kubernetes/pull/46463), [[@wongma7](https://github.com/wongma7)](https://github.com/wongma7)) + + * vSphere cloud provider: Fix volume detach on node failure. ([[#45569](https://github.com/kubernetes/kubernetes/pull/45569)](https://github.com/kubernetes/kubernetes/pull/45569), [[@divyenpatel](https://github.com/divyenpatel)](https://github.com/divyenpatel)) + + * Improves performance of Cinder volume attach/detach operations. ([[#41785](https://github.com/kubernetes/kubernetes/pull/41785)](https://github.com/kubernetes/kubernetes/pull/41785), [[@jamiehannaford](https://github.com/jamiehannaford)](https://github.com/jamiehannaford)) + + * AWS: Process disk attachments even with duplicate NodeNames ([[#47406](https://github.com/kubernetes/kubernetes/pull/47406)](https://github.com/kubernetes/kubernetes/pull/47406), [[@justinsb](https://github.com/justinsb)](https://github.com/justinsb)) + + * Fix iSCSI iSER mounting. ([[#47281](https://github.com/kubernetes/kubernetes/pull/47281)](https://github.com/kubernetes/kubernetes/pull/47281), [[@mtanino](https://github.com/mtanino)](https://github.com/mtanino)) + + * iscsi storage plugin: Fix dangling session when using multiple target portal addresses. ([[#46239](https://github.com/kubernetes/kubernetes/pull/46239)](https://github.com/kubernetes/kubernetes/pull/46239), [[@mtanino](https://github.com/mtanino)](https://github.com/mtanino)) + + * Fix log spam due to unnecessary status update when node is deleted. ([[#45923](https://github.com/kubernetes/kubernetes/pull/45923)](https://github.com/kubernetes/kubernetes/pull/45923), [[@verult](https://github.com/verult)](https://github.com/verult)) + + * Don't try to attach volume to new node if it is already attached to another node and the volume does not support multi-attach. ([[#45346](https://github.com/kubernetes/kubernetes/pull/45346)](https://github.com/kubernetes/kubernetes/pull/45346), [[@codablock](https://github.com/codablock)](https://github.com/codablock)) + + * vSphere cloud provider: Report same Node IP as both internal and external. ([[#45201](https://github.com/kubernetes/kubernetes/pull/45201)](https://github.com/kubernetes/kubernetes/pull/45201), [[@abrarshivani](https://github.com/abrarshivani)](https://github.com/abrarshivani)) + + * detach the volume when pod is terminated ([[#45286](https://github.com/kubernetes/kubernetes/pull/45286)](https://github.com/kubernetes/kubernetes/pull/45286), [[@gnufied](https://github.com/gnufied)](https://github.com/gnufied)) + + * vSphere cloud provider: Filter out IPV6 node addresses. ([[#45181](https://github.com/kubernetes/kubernetes/pull/45181)](https://github.com/kubernetes/kubernetes/pull/45181), [[@BaluDontu](https://github.com/BaluDontu)](https://github.com/BaluDontu)) + + * vSphere cloud provider: Fix fetching of VM UUID on Ubuntu 16.04 and Fedora. ([[#45311](https://github.com/kubernetes/kubernetes/pull/45311)](https://github.com/kubernetes/kubernetes/pull/45311), [[@divyenpatel](https://github.com/divyenpatel)](https://github.com/divyenpatel)) + + * Roll up volume error messages in the kubelet sync loop. ([[#44938](https://github.com/kubernetes/kubernetes/pull/44938)](https://github.com/kubernetes/kubernetes/pull/44938), [[@jayunit100](https://github.com/jayunit100)](https://github.com/jayunit100)) + + * Catch error when failed to make directory in NFS volume plugin ([[#38801](https://github.com/kubernetes/kubernetes/pull/38801)](https://github.com/kubernetes/kubernetes/pull/38801), [[@nak3](https://github.com/nak3)](https://github.com/nak3)) + + * Attention-Required when Upgrading + + * Alpha volume provisioning is removed and default storage class should be used instead. ([[#44090](https://github.com/kubernetes/kubernetes/pull/44090)](https://github.com/kubernetes/kubernetes/pull/44090), [[@NickrenREN](https://github.com/NickrenREN)](https://github.com/NickrenREN)) + + * Portworx volume driver no longer has to run on the master. ([[#45518](https://github.com/kubernetes/kubernetes/pull/45518)](https://github.com/kubernetes/kubernetes/pull/45518), [[@harsh-px](https://github.com/harsh-px)](https://github.com/harsh-px)) + + * Default behaviour in Cinder storageclass is changed. If availability is not specified, the zone is chosen by algorithm. It makes possible to spread stateful pods across many zones. ([[#44798](https://github.com/kubernetes/kubernetes/pull/44798)](https://github.com/kubernetes/kubernetes/pull/44798), [[@zetaab](https://github.com/zetaab)](https://github.com/zetaab)) + +# Unsorted + +* Update kube-dns, metadata-proxy, and fluentd-gcp, event-exporter, prometheus-to-sd, and ip-masq-agent addons with new base images containing fixes for CVE-2016-4448, CVE-2016-9841, CVE-2016-9843, CVE-2017-1000366, CVE-2017-2616, and CVE-2017-9526. ([[#47877](https://github.com/kubernetes/kubernetes/pull/47877)](https://github.com/kubernetes/kubernetes/pull/47877), [[@ixdy](https://github.com/ixdy)](https://github.com/ixdy)) + +* Bump the memory request/limit for ip-masq-daemon. ([[#47887](https://github.com/kubernetes/kubernetes/pull/47887)](https://github.com/kubernetes/kubernetes/pull/47887), [[@dnardo](https://github.com/dnardo)](https://github.com/dnardo)) + +* HostAliases is now parsed with hostAliases json keys to be in line with the feature's name. ([[#47512](https://github.com/kubernetes/kubernetes/pull/47512)](https://github.com/kubernetes/kubernetes/pull/47512), [[@rickypai](https://github.com/rickypai)](https://github.com/rickypai)) + +* ip-masq-agent is now the default for GCE ([[#47794](https://github.com/kubernetes/kubernetes/pull/47794)](https://github.com/kubernetes/kubernetes/pull/47794), [[@dnardo](https://github.com/dnardo)](https://github.com/dnardo)) + +* New 'service.beta.kubernetes.io/aws-load-balancer-extra-security-groups' Service annotation to specify extra Security Groups to be added to ELB created by AWS cloudprovider ([[#45268](https://github.com/kubernetes/kubernetes/pull/45268)](https://github.com/kubernetes/kubernetes/pull/45268), [[@redbaron](https://github.com/redbaron)](https://github.com/redbaron)) + +* AWS: clean up blackhole routes when using kubenet ([[#47572](https://github.com/kubernetes/kubernetes/pull/47572)](https://github.com/kubernetes/kubernetes/pull/47572), [[@justinsb](https://github.com/justinsb)](https://github.com/justinsb)) + +* Tokens retrieved from Google Cloud with application default credentials will not be cached if the client fails authorization ([[#46694](https://github.com/kubernetes/kubernetes/pull/46694)](https://github.com/kubernetes/kubernetes/pull/46694), [[@matt-tyler](https://github.com/matt-tyler)](https://github.com/matt-tyler)) + +* Taints support in gce/salt startup scripts. ([[#47632](https://github.com/kubernetes/kubernetes/pull/47632)](https://github.com/kubernetes/kubernetes/pull/47632), [[@mwielgus](https://github.com/mwielgus)](https://github.com/mwielgus)) + +* Fix VolumeClaims/capacity in `kubectl describe statefulsets` output. ([[#47573](https://github.com/kubernetes/kubernetes/pull/47573)](https://github.com/kubernetes/kubernetes/pull/47573), [[@k82cn](https://github.com/k82cn)](https://github.com/k82cn)) + +* The protobuf serialization of API objects has been updated to store maps in a predictable order to ensure that the representation of that object does not change when saved into etcd. This prevents the same object from being seen as being modified, even when no values have changed. ([[#47701](https://github.com/kubernetes/kubernetes/pull/47701)](https://github.com/kubernetes/kubernetes/pull/47701), [[@smarterclayton](https://github.com/smarterclayton)](https://github.com/smarterclayton)) + +* `kubectl logs` with label selector supports specifying a container name ([[#44282](https://github.com/kubernetes/kubernetes/pull/44282)](https://github.com/kubernetes/kubernetes/pull/44282), [[@derekwaynecarr](https://github.com/derekwaynecarr)](https://github.com/derekwaynecarr)) + +* Adds an approval work flow to the the certificate approver that will approve certificate signing requests from kubelets that meet all the criteria of kubelet server certificates. ([[#46884](https://github.com/kubernetes/kubernetes/pull/46884)](https://github.com/kubernetes/kubernetes/pull/46884), [[@jcbsmpsn](https://github.com/jcbsmpsn)](https://github.com/jcbsmpsn)) + +* AWS: Maintain a cache of all instances, to fix problem with > 200 nodes with ELBs ([[#47410](https://github.com/kubernetes/kubernetes/pull/47410)](https://github.com/kubernetes/kubernetes/pull/47410), [[@justinsb](https://github.com/justinsb)](https://github.com/justinsb)) + +* Bump GLBC version to 0.9.5 - fixes [loss of manually modified GCLB health check settings](https://github.com/kubernetes/kubernetes/issues/47559) upon upgrade from pre-1.6.4 to either 1.6.4 or 1.6.5. ([[#47567](https://github.com/kubernetes/kubernetes/pull/47567)](https://github.com/kubernetes/kubernetes/pull/47567), [[@nicksardo](https://github.com/nicksardo)](https://github.com/nicksardo)) + +* Update cluster-proportional-autoscaler, metadata-proxy, and fluentd-gcp addons with fixes for CVE-2016-4448, CVE-2016-8859, CVE-2016-9841, CVE-2016-9843, and CVE-2017-9526. ([[#47545](https://github.com/kubernetes/kubernetes/pull/47545)](https://github.com/kubernetes/kubernetes/pull/47545), [[@ixdy](https://github.com/ixdy)](https://github.com/ixdy)) + +* AWS: Batch DescribeInstance calls with nodeNames to 150 limit, to stay within AWS filter limits. ([[#47516](https://github.com/kubernetes/kubernetes/pull/47516)](https://github.com/kubernetes/kubernetes/pull/47516), [[@gnufied](https://github.com/gnufied)](https://github.com/gnufied)) + +* AWS: Process disk attachments even with duplicate NodeNames ([[#47406](https://github.com/kubernetes/kubernetes/pull/47406)](https://github.com/kubernetes/kubernetes/pull/47406), [[@justinsb](https://github.com/justinsb)](https://github.com/justinsb)) + +* kubefed will now configure NodeInternalIP as the federation API server endpoint when NodeExternalIP is unavailable for federation API servers exposed as NodePort services ([[#46960](https://github.com/kubernetes/kubernetes/pull/46960)](https://github.com/kubernetes/kubernetes/pull/46960), [[@lukaszo](https://github.com/lukaszo)](https://github.com/lukaszo)) + +* PodSecurityPolicy now recognizes pods that specify runAsNonRoot: false in their security context and does not overwrite the specified value ([[#47073](https://github.com/kubernetes/kubernetes/pull/47073)](https://github.com/kubernetes/kubernetes/pull/47073), [[@Q-Lee](https://github.com/Q-Lee)](https://github.com/Q-Lee)) + +* Update to kube-addon-manager:v6.4-beta.2: kubectl v1.6.4 and refreshed base images ([[#47389](https://github.com/kubernetes/kubernetes/pull/47389)](https://github.com/kubernetes/kubernetes/pull/47389), [[@ixdy](https://github.com/ixdy)](https://github.com/ixdy)) + +* Azure plugin for client auth ([[#43987](https://github.com/kubernetes/kubernetes/pull/43987)](https://github.com/kubernetes/kubernetes/pull/43987), [[@cosmincojocar](https://github.com/cosmincojocar)](https://github.com/cosmincojocar)) + +* AWS: Avoid spurious ELB listener recreation - ignore case when matching protocol ([[#47391](https://github.com/kubernetes/kubernetes/pull/47391)](https://github.com/kubernetes/kubernetes/pull/47391), [[@justinsb](https://github.com/justinsb)](https://github.com/justinsb)) + +* gce kube-up: The Node authorization mode and NodeRestriction admission controller are now enabled ([[#46796](https://github.com/kubernetes/kubernetes/pull/46796)](https://github.com/kubernetes/kubernetes/pull/46796), [[@mikedanese](https://github.com/mikedanese)](https://github.com/mikedanese)) + +* update gophercloud/gophercloud dependency for reauthentication fixes ([[#45545](https://github.com/kubernetes/kubernetes/pull/45545)](https://github.com/kubernetes/kubernetes/pull/45545), [[@stuart-warren](https://github.com/stuart-warren)](https://github.com/stuart-warren)) + +* servicecontroller: Fix node selection logic on initial LB creation ([[#45773](https://github.com/kubernetes/kubernetes/pull/45773)](https://github.com/kubernetes/kubernetes/pull/45773), [[@justinsb](https://github.com/justinsb)](https://github.com/justinsb)) + +* Fix iSCSI iSER mounting. ([[#47281](https://github.com/kubernetes/kubernetes/pull/47281)](https://github.com/kubernetes/kubernetes/pull/47281), [[@mtanino](https://github.com/mtanino)](https://github.com/mtanino)) + +* StorageOS Volume Driver ([[#42156](https://github.com/kubernetes/kubernetes/pull/42156)](https://github.com/kubernetes/kubernetes/pull/42156), [[@croomes](https://github.com/croomes)](https://github.com/croomes)) + + * [StorageOS](http://www.storageos.com/) can be used as a storage provider for Kubernetes. With StorageOS, capacity from local or attached storage is pooled across the cluster, providing converged infrastructure for cloud-native applications. + +* Make gcp auth provider not to override the Auth header if it's already exits ([[#45575](https://github.com/kubernetes/kubernetes/pull/45575)](https://github.com/kubernetes/kubernetes/pull/45575), [[@wanghaoran1988](https://github.com/wanghaoran1988)](https://github.com/wanghaoran1988)) + +* Allow pods to opt out of PodPreset mutation via an annotation on the pod. ([[#44965](https://github.com/kubernetes/kubernetes/pull/44965)](https://github.com/kubernetes/kubernetes/pull/44965), [[@jpeeler](https://github.com/jpeeler)](https://github.com/jpeeler)) + +* Add Traditional Chinese translation for kubectl ([[#46559](https://github.com/kubernetes/kubernetes/pull/46559)](https://github.com/kubernetes/kubernetes/pull/46559), [[@warmchang](https://github.com/warmchang)](https://github.com/warmchang)) + +* Remove Initializers from admission-control in kubernetes-master charm for pre-1.7 ([[#46987](https://github.com/kubernetes/kubernetes/pull/46987)](https://github.com/kubernetes/kubernetes/pull/46987), [[@Cynerva](https://github.com/Cynerva)](https://github.com/Cynerva)) + +* Added state guards to the idle_status messaging in the kubernetes-master charm to make deployment faster on initial deployment. ([[#47183](https://github.com/kubernetes/kubernetes/pull/47183)](https://github.com/kubernetes/kubernetes/pull/47183), [[@chuckbutler](https://github.com/chuckbutler)](https://github.com/chuckbutler)) + +* Bump up Node Problem Detector version to v0.4.0, which added support of parsing log from /dev/kmsg and ABRT. ([[#46743](https://github.com/kubernetes/kubernetes/pull/46743)](https://github.com/kubernetes/kubernetes/pull/46743), [[@Random-Liu](https://github.com/Random-Liu)](https://github.com/Random-Liu)) + +* Deprecated Binding objects in 1.7. ([[#47041](https://github.com/kubernetes/kubernetes/pull/47041)](https://github.com/kubernetes/kubernetes/pull/47041), [[@k82cn](https://github.com/k82cn)](https://github.com/k82cn)) + +* Add secretbox and AES-CBC encryption modes to at rest encryption. AES-CBC is considered superior to AES-GCM because it is resistant to nonce-reuse attacks, and secretbox uses Poly1305 and XSalsa20. ([[#46916](https://github.com/kubernetes/kubernetes/pull/46916)](https://github.com/kubernetes/kubernetes/pull/46916), [[@smarterclayton](https://github.com/smarterclayton)](https://github.com/smarterclayton)) + +* The HorizontalPodAutoscaler controller will now only send updates when it has new status information, reducing the number of writes caused by the controller. ([[#47078](https://github.com/kubernetes/kubernetes/pull/47078)](https://github.com/kubernetes/kubernetes/pull/47078), [[@DirectXMan12](https://github.com/DirectXMan12)](https://github.com/DirectXMan12)) + +* Added exponential backoff to Azure cloudprovider ([[#46660](https://github.com/kubernetes/kubernetes/pull/46660)](https://github.com/kubernetes/kubernetes/pull/46660), [[@jackfrancis](https://github.com/jackfrancis)](https://github.com/jackfrancis)) + +* fixed HostAlias in PodSpec to allow foo.bar hostnames instead of just foo DNS labels. ([[#46809](https://github.com/kubernetes/kubernetes/pull/46809)](https://github.com/kubernetes/kubernetes/pull/46809), [[@rickypai](https://github.com/rickypai)](https://github.com/rickypai)) + +* Implements rolling update for StatefulSets. Updates can be performed using the RollingUpdate, Paritioned, or OnDelete strategies. OnDelete implements the manual behavior from 1.6. status now tracks ([[#46669](https://github.com/kubernetes/kubernetes/pull/46669)](https://github.com/kubernetes/kubernetes/pull/46669), [[@kow3ns](https://github.com/kow3ns)](https://github.com/kow3ns)) + + * replicas, readyReplicas, currentReplicas, and updatedReplicas. The semantics of replicas is now consistent with DaemonSet and ReplicaSet, and readyReplicas has the semantics that replicas did prior to this release. + +* Add Japanese translation for kubectl ([[#46756](https://github.com/kubernetes/kubernetes/pull/46756)](https://github.com/kubernetes/kubernetes/pull/46756), [[@girikuncoro](https://github.com/girikuncoro)](https://github.com/girikuncoro)) + +* federation: Add admission controller for policy-based placement ([[#44786](https://github.com/kubernetes/kubernetes/pull/44786)](https://github.com/kubernetes/kubernetes/pull/44786), [[@tsandall](https://github.com/tsandall)](https://github.com/tsandall)) + +* Get command uses OpenAPI schema to enhance display for a resource if run with flag 'experimental-use-openapi-print-columns'. ([[#46235](https://github.com/kubernetes/kubernetes/pull/46235)](https://github.com/kubernetes/kubernetes/pull/46235), [[@droot](https://github.com/droot)](https://github.com/droot)) + + * An example command: + + * `kubectl get pods --experimental-use-openapi-print-columns` + +* add gzip compression to GET and LIST requests ([[#45666](https://github.com/kubernetes/kubernetes/pull/45666)](https://github.com/kubernetes/kubernetes/pull/45666), [[@ilackarms](https://github.com/ilackarms)](https://github.com/ilackarms)) + +* Alpha feature: allows users to set storage limit to isolate EmptyDir volumes. It enforces the limit by evicting pods that exceed their storage limits ([[#45686](https://github.com/kubernetes/kubernetes/pull/45686)](https://github.com/kubernetes/kubernetes/pull/45686), [[@jingxu97](https://github.com/jingxu97)](https://github.com/jingxu97)) + +* Adds the Categories []string field to API resources, which represents the list of group aliases (e.g. "all") that every resource belongs to. ([[#43338](https://github.com/kubernetes/kubernetes/pull/43338)](https://github.com/kubernetes/kubernetes/pull/43338), [[@fabianofranz](https://github.com/fabianofranz)](https://github.com/fabianofranz)) + +* Promote kubelet tls bootstrap to beta. Add a non-experimental flag to use it and deprecate the old flag. ([[#46799](https://github.com/kubernetes/kubernetes/pull/46799)](https://github.com/kubernetes/kubernetes/pull/46799), [[@mikedanese](https://github.com/mikedanese)](https://github.com/mikedanese)) + +* Fix disk partition discovery for brtfs ([[#46816](https://github.com/kubernetes/kubernetes/pull/46816)](https://github.com/kubernetes/kubernetes/pull/46816), [[@dashpole](https://github.com/dashpole)](https://github.com/dashpole)) + + * Add ZFS support + + * Add overlay2 storage driver support + +* [beta] Support creation of GCP Internal Load Balancers from Service objects ([[#46663](https://github.com/kubernetes/kubernetes/pull/46663)](https://github.com/kubernetes/kubernetes/pull/46663), [[@nicksardo](https://github.com/nicksardo)](https://github.com/nicksardo)) + +* Introduces status conditions to the HorizontalPodAutoscaler in autoscaling/v2alpha1, indicating the current status of a given HorizontalPodAutoscaler, and why it is or is not scaling. ([[#46550](https://github.com/kubernetes/kubernetes/pull/46550)](https://github.com/kubernetes/kubernetes/pull/46550), [[@DirectXMan12](https://github.com/DirectXMan12)](https://github.com/DirectXMan12)) + +* Support OpenAPI spec aggregation for kube-aggregator ([[#46734](https://github.com/kubernetes/kubernetes/pull/46734)](https://github.com/kubernetes/kubernetes/pull/46734), [[@mbohlool](https://github.com/mbohlool)](https://github.com/mbohlool)) + +* Implement `kubectl rollout undo` and `kubectl rollout history` for DaemonSet ([[#46144](https://github.com/kubernetes/kubernetes/pull/46144)](https://github.com/kubernetes/kubernetes/pull/46144), [[@janetkuo](https://github.com/janetkuo)](https://github.com/janetkuo)) + +* Respect PDBs during node upgrades and add test coverage to the ServiceTest upgrade test. ([[#45748](https://github.com/kubernetes/kubernetes/pull/45748)](https://github.com/kubernetes/kubernetes/pull/45748), [[@mml](https://github.com/mml)](https://github.com/mml)) + +* Add the alpha.image-policy.k8s.io/failed-open=true annotation when the image policy webhook encounters an error and fails open. ([[#46264](https://github.com/kubernetes/kubernetes/pull/46264)](https://github.com/kubernetes/kubernetes/pull/46264), [[@Q-Lee](https://github.com/Q-Lee)](https://github.com/Q-Lee)) + +* Enable kubelet csr bootstrap in GCE/GKE ([[#40760](https://github.com/kubernetes/kubernetes/pull/40760)](https://github.com/kubernetes/kubernetes/pull/40760), [[@mikedanese](https://github.com/mikedanese)](https://github.com/mikedanese)) + +* Implement Daemonset history ([[#45924](https://github.com/kubernetes/kubernetes/pull/45924)](https://github.com/kubernetes/kubernetes/pull/45924), [[@janetkuo](https://github.com/janetkuo)](https://github.com/janetkuo)) + +* When switching from the service.beta.kubernetes.io/external-traffic annotation to the new ([[#46716](https://github.com/kubernetes/kubernetes/pull/46716)](https://github.com/kubernetes/kubernetes/pull/46716), [[@thockin](https://github.com/thockin)](https://github.com/thockin)) + + * externalTrafficPolicy field, the values chnag as follows: * "OnlyLocal" becomes "Local" * "Global" becomes "Cluster". + +* Fix kubelet reset liveness probe failure count across pod restart boundaries ([[#46371](https://github.com/kubernetes/kubernetes/pull/46371)](https://github.com/kubernetes/kubernetes/pull/46371), [[@sjenning](https://github.com/sjenning)](https://github.com/sjenning)) + +* The gce metadata server can be hidden behind a proxy, hiding the kubelet's token. ([[#45565](https://github.com/kubernetes/kubernetes/pull/45565)](https://github.com/kubernetes/kubernetes/pull/45565), [[@Q-Lee](https://github.com/Q-Lee)](https://github.com/Q-Lee)) + +* AWS: Allow configuration of a single security group for ELBs ([[#45500](https://github.com/kubernetes/kubernetes/pull/45500)](https://github.com/kubernetes/kubernetes/pull/45500), [[@nbutton23](https://github.com/nbutton23)](https://github.com/nbutton23)) + +* Allow remote admission controllers to be dynamically added and removed by administrators. External admission controllers make an HTTP POST containing details of the requested action which the service can approve or reject. ([[#46388](https://github.com/kubernetes/kubernetes/pull/46388)](https://github.com/kubernetes/kubernetes/pull/46388), [[@lavalamp](https://github.com/lavalamp)](https://github.com/lavalamp)) + +* iscsi storage plugin: Fix dangling session when using multiple target portal addresses. ([[#46239](https://github.com/kubernetes/kubernetes/pull/46239)](https://github.com/kubernetes/kubernetes/pull/46239), [[@mtanino](https://github.com/mtanino)](https://github.com/mtanino)) + +* Duplicate recurring Events now include the latest event's Message string ([[#46034](https://github.com/kubernetes/kubernetes/pull/46034)](https://github.com/kubernetes/kubernetes/pull/46034), [[@kensimon](https://github.com/kensimon)](https://github.com/kensimon)) + +* With `--feature-gates=RotateKubeletClientCertificate=true` set, the kubelet will ([[#41912](https://github.com/kubernetes/kubernetes/pull/41912)](https://github.com/kubernetes/kubernetes/pull/41912), [[@jcbsmpsn](https://github.com/jcbsmpsn)](https://github.com/jcbsmpsn)) + + * request a client certificate from the API server during the boot cycle and pause + + * waiting for the request to be satisfied. It will continually refresh the certificate + + * as the certificates expiration approaches. + +* The Kubernetes API supports retrieving tabular output for API resources via a new mime-type application/json;as=Table;v=v1alpha1;g=meta.k8s.io. The returned object (if the server supports it) will be of type meta.k8s.io/v1alpha1 with Table, and contain column and row information related to the resource. Each row will contain information about the resource - by default it will be the object metadata, but callers can add the ?includeObject=Object query parameter and receive the full object. In the future kubectl will use this to retrieve the results of `kubectl get`. ([[#40848](https://github.com/kubernetes/kubernetes/pull/40848)](https://github.com/kubernetes/kubernetes/pull/40848), [[@smarterclayton](https://github.com/smarterclayton)](https://github.com/smarterclayton)) + +* `kubectl auth can-i` now supports non-resource URLs ([[#46432](https://github.com/kubernetes/kubernetes/pull/46432)](https://github.com/kubernetes/kubernetes/pull/46432), [[@CaoShuFeng](https://github.com/CaoShuFeng)](https://github.com/CaoShuFeng)) + +* Webhook added to the API server which emits structured audit log events. ([[#45919](https://github.com/kubernetes/kubernetes/pull/45919)](https://github.com/kubernetes/kubernetes/pull/45919), [[@ericchiang](https://github.com/ericchiang)](https://github.com/ericchiang)) + +* `kubectl edit` and `kubectl apply` will keep the ordering of elements in merged lists ([[#45980](https://github.com/kubernetes/kubernetes/pull/45980)](https://github.com/kubernetes/kubernetes/pull/45980), [[@mengqiy](https://github.com/mengqiy)](https://github.com/mengqiy)) + +* [Federation][kubefed]: Use StorageClassName for etcd pvc ([[#46323](https://github.com/kubernetes/kubernetes/pull/46323)](https://github.com/kubernetes/kubernetes/pull/46323), [[@marun](https://github.com/marun)](https://github.com/marun)) + +* Restrict active deadline seconds max allowed value to be maximum uint32 ([[#46640](https://github.com/kubernetes/kubernetes/pull/46640)](https://github.com/kubernetes/kubernetes/pull/46640), [[@derekwaynecarr](https://github.com/derekwaynecarr)](https://github.com/derekwaynecarr)) + +* Implement `kubectl get controllerrevisions` ([[#46655](https://github.com/kubernetes/kubernetes/pull/46655)](https://github.com/kubernetes/kubernetes/pull/46655), [[@janetkuo](https://github.com/janetkuo)](https://github.com/janetkuo)) + +* Local storage plugin ([[#44897](https://github.com/kubernetes/kubernetes/pull/44897)](https://github.com/kubernetes/kubernetes/pull/44897), [[@msau42](https://github.com/msau42)](https://github.com/msau42)) + +* With `--feature-gates=RotateKubeletServerCertificate=true` set, the kubelet will ([[#45059](https://github.com/kubernetes/kubernetes/pull/45059)](https://github.com/kubernetes/kubernetes/pull/45059), [[@jcbsmpsn](https://github.com/jcbsmpsn)](https://github.com/jcbsmpsn)) + + * request a server certificate from the API server during the boot cycle and pause + + * waiting for the request to be satisfied. It will continually refresh the certificate as + + * the certificates expiration approaches. + +* Add `kubectl config rename-context` ([[#46114](https://github.com/kubernetes/kubernetes/pull/46114)](https://github.com/kubernetes/kubernetes/pull/46114), [[@arthur0](https://github.com/arthur0)](https://github.com/arthur0)) + +* Move hardPodAffinitySymmetricWeight to scheduler policy config ([[#44159](https://github.com/kubernetes/kubernetes/pull/44159)](https://github.com/kubernetes/kubernetes/pull/44159), [[@wanghaoran1988](https://github.com/wanghaoran1988)](https://github.com/wanghaoran1988)) + +* AWS: support node port health check ([[#43585](https://github.com/kubernetes/kubernetes/pull/43585)](https://github.com/kubernetes/kubernetes/pull/43585), [[@foolusion](https://github.com/foolusion)](https://github.com/foolusion)) + +* support replaceKeys patch strategy and directive for strategic merge patch ([[#44597](https://github.com/kubernetes/kubernetes/pull/44597)](https://github.com/kubernetes/kubernetes/pull/44597), [[@mengqiy](https://github.com/mengqiy)](https://github.com/mengqiy)) + +* Prevent kubelet from setting allocatable < 0 for a resource upon initial creation. ([[#46516](https://github.com/kubernetes/kubernetes/pull/46516)](https://github.com/kubernetes/kubernetes/pull/46516), [[@derekwaynecarr](https://github.com/derekwaynecarr)](https://github.com/derekwaynecarr)) + +* add `--non-resource-url` to `kubectl create clusterrole` ([[#45809](https://github.com/kubernetes/kubernetes/pull/45809)](https://github.com/kubernetes/kubernetes/pull/45809), [[@CaoShuFeng](https://github.com/CaoShuFeng)](https://github.com/CaoShuFeng)) + +* Add `kubectl apply edit-last-applied` subcommand ([[#42256](https://github.com/kubernetes/kubernetes/pull/42256)](https://github.com/kubernetes/kubernetes/pull/42256), [[@shiywang](https://github.com/shiywang)](https://github.com/shiywang)) + +* Adding admissionregistration API group which enables dynamic registration of initializers and external admission webhooks. It is an alpha feature. ([[#46294](https://github.com/kubernetes/kubernetes/pull/46294)](https://github.com/kubernetes/kubernetes/pull/46294), [[@caesarxuchao](https://github.com/caesarxuchao)](https://github.com/caesarxuchao)) + +* Fix log spam due to unnecessary status update when node is deleted. ([[#45923](https://github.com/kubernetes/kubernetes/pull/45923)](https://github.com/kubernetes/kubernetes/pull/45923), [[@verult](https://github.com/verult)](https://github.com/verult)) + +* GCE installs will now avoid IP masquerade for all RFC-1918 IP blocks, rather than just 10.0.0.0/8. This means that clusters can ([[#46473](https://github.com/kubernetes/kubernetes/pull/46473)](https://github.com/kubernetes/kubernetes/pull/46473), [[@thockin](https://github.com/thockin)](https://github.com/thockin)) + + * be created in 192.168.0.0./16 and 172.16.0.0/12 while preserving the container IPs (which would be lost before). + +* set selector and set subject no longer print "running in local/dry-run mode..." at the top, so their output can be piped as valid yaml or json ([[#46507](https://github.com/kubernetes/kubernetes/pull/46507)](https://github.com/kubernetes/kubernetes/pull/46507), [[@bboreham](https://github.com/bboreham)](https://github.com/bboreham)) + +* ControllerRevision type added for StatefulSet and DaemonSet history. ([[#45867](https://github.com/kubernetes/kubernetes/pull/45867)](https://github.com/kubernetes/kubernetes/pull/45867), [[@kow3ns](https://github.com/kow3ns)](https://github.com/kow3ns)) + +* Bump Go version to 1.8.3 ([[#46429](https://github.com/kubernetes/kubernetes/pull/46429)](https://github.com/kubernetes/kubernetes/pull/46429), [[@wojtek-t](https://github.com/wojtek-t)](https://github.com/wojtek-t)) + +* Upgrade Elasticsearch Addon to v5.4.0 ([[#45589](https://github.com/kubernetes/kubernetes/pull/45589)](https://github.com/kubernetes/kubernetes/pull/45589), [[@it-svit](https://github.com/it-svit)](https://github.com/it-svit)) + +* PodDisruptionBudget now uses ControllerRef to decide which controller owns a given Pod, so it doesn't get confused by controllers with overlapping selectors. ([[#45003](https://github.com/kubernetes/kubernetes/pull/45003)](https://github.com/kubernetes/kubernetes/pull/45003), [[@krmayankk](https://github.com/krmayankk)](https://github.com/krmayankk)) + +* aws: Support for ELB tagging by users ([[#45932](https://github.com/kubernetes/kubernetes/pull/45932)](https://github.com/kubernetes/kubernetes/pull/45932), [[@lpabon](https://github.com/lpabon)](https://github.com/lpabon)) + +* kube-proxy: ratelimit runs of iptables by sync-period flags ([[#46266](https://github.com/kubernetes/kubernetes/pull/46266)](https://github.com/kubernetes/kubernetes/pull/46266), [[@thockin](https://github.com/thockin)](https://github.com/thockin)) + +* Deployments are updated to use (1) a more stable hashing algorithm (fnv) than the previous one (adler) and (2) a hashing collision avoidance mechanism that will ensure new rollouts will not block on hashing collisions anymore. ([[#44774](https://github.com/kubernetes/kubernetes/pull/44774)](https://github.com/kubernetes/kubernetes/pull/44774), [[@kargakis](https://github.com/kargakis)](https://github.com/kargakis)) + +* The Prometheus metrics for the kube-apiserver for tracking incoming API requests and latencies now return the subresource label for correctly attributing the type of API call. ([[#46354](https://github.com/kubernetes/kubernetes/pull/46354)](https://github.com/kubernetes/kubernetes/pull/46354), [[@smarterclayton](https://github.com/smarterclayton)](https://github.com/smarterclayton)) + +* Add Simplified Chinese translation for kubectl ([[#45573](https://github.com/kubernetes/kubernetes/pull/45573)](https://github.com/kubernetes/kubernetes/pull/45573), [[@shiywang](https://github.com/shiywang)](https://github.com/shiywang)) + +* The `--namespace` flag is now honored for in-cluster clients that have an empty configuration. ([[#46299](https://github.com/kubernetes/kubernetes/pull/46299)](https://github.com/kubernetes/kubernetes/pull/46299), [[@ncdc](https://github.com/ncdc)](https://github.com/ncdc)) + +* oidc client plugin: reduce round trips and fix scopes requested ([[#45317](https://github.com/kubernetes/kubernetes/pull/45317)](https://github.com/kubernetes/kubernetes/pull/45317), [[@ericchiang](https://github.com/ericchiang)](https://github.com/ericchiang)) + +* Fix init container status reporting when active deadline is exceeded. ([[#46305](https://github.com/kubernetes/kubernetes/pull/46305)](https://github.com/kubernetes/kubernetes/pull/46305), [[@sjenning](https://github.com/sjenning)](https://github.com/sjenning)) + +* Break the 'certificatesigningrequests' controller into a 'csrapprover' controller and 'csrsigner' controller. ([[#45514](https://github.com/kubernetes/kubernetes/pull/45514)](https://github.com/kubernetes/kubernetes/pull/45514), [[@mikedanese](https://github.com/mikedanese)](https://github.com/mikedanese)) + +* Modifies kubefed to create and the federation controller manager to use credentials associated with a service account rather than the user's credentials. ([[#42042](https://github.com/kubernetes/kubernetes/pull/42042)](https://github.com/kubernetes/kubernetes/pull/42042), [[@perotinus](https://github.com/perotinus)](https://github.com/perotinus)) + +* Adds a MaxUnavailable field to PodDisruptionBudget ([[#45587](https://github.com/kubernetes/kubernetes/pull/45587)](https://github.com/kubernetes/kubernetes/pull/45587), [[@foxish](https://github.com/foxish)](https://github.com/foxish)) + +* The behavior of some watch calls to the server when filtering on fields was incorrect. If watching objects with a filter, when an update was made that no longer matched the filter a DELETE event was correctly sent. However, the object that was returned by that delete was not the (correct) version before the update, but instead, the newer version. That meant the new object was not matched by the filter. This was a regression from behavior between cached watches on the server side and uncached watches, and thus broke downstream API clients. ([[#46223](https://github.com/kubernetes/kubernetes/pull/46223)](https://github.com/kubernetes/kubernetes/pull/46223), [[@smarterclayton](https://github.com/smarterclayton)](https://github.com/smarterclayton)) + +* `kubefed init` now supports overriding the default etcd image name with the `--etcd-image` parameter. ([[#46247](https://github.com/kubernetes/kubernetes/pull/46247)](https://github.com/kubernetes/kubernetes/pull/46247), [[@marun](https://github.com/marun)](https://github.com/marun)) + +* remove the elasticsearch template ([[#45952](https://github.com/kubernetes/kubernetes/pull/45952)](https://github.com/kubernetes/kubernetes/pull/45952), [[@harryge00](https://github.com/harryge00)](https://github.com/harryge00)) + +* Adds the CustomResourceDefinition (crd) types to the kube-apiserver. These are the successors to ThirdPartyResource. See [https://github.com/kubernetes/community/blob/master/contributors/design-proposals/thirdpartyresources.md](https://github.com/kubernetes/community/blob/master/contributors/design-proposals/thirdpartyresources.md) for more details. ([[#46055](https://github.com/kubernetes/kubernetes/pull/46055)](https://github.com/kubernetes/kubernetes/pull/46055), [[@deads2k](https://github.com/deads2k)](https://github.com/deads2k)) + +* StatefulSets now include an alpha scaling feature accessible by setting the spec.podManagementPolicy field to Parallel. The controller will not wait for pods to be ready before adding the other pods, and will replace deleted pods as needed. Since parallel scaling creates pods out of order, you cannot depend on predictable membership changes within your set. ([[#44899](https://github.com/kubernetes/kubernetes/pull/44899)](https://github.com/kubernetes/kubernetes/pull/44899), [[@smarterclayton](https://github.com/smarterclayton)](https://github.com/smarterclayton)) + +* fix kubelet event recording for selected events. ([[#46246](https://github.com/kubernetes/kubernetes/pull/46246)](https://github.com/kubernetes/kubernetes/pull/46246), [[@derekwaynecarr](https://github.com/derekwaynecarr)](https://github.com/derekwaynecarr)) + +* Moved qos to api.helpers. ([[#44906](https://github.com/kubernetes/kubernetes/pull/44906)](https://github.com/kubernetes/kubernetes/pull/44906), [[@k82cn](https://github.com/k82cn)](https://github.com/k82cn)) + +* OpenAPI spec is now available in protobuf binary and gzip format (with ETag support) ([[#45836](https://github.com/kubernetes/kubernetes/pull/45836)](https://github.com/kubernetes/kubernetes/pull/45836), [[@mbohlool](https://github.com/mbohlool)](https://github.com/mbohlool)) + +* Added support to a hierarchy of kubectl plugins (a tree of plugins as children of other plugins). ([[#45981](https://github.com/kubernetes/kubernetes/pull/45981)](https://github.com/kubernetes/kubernetes/pull/45981), [[@fabianofranz](https://github.com/fabianofranz)](https://github.com/fabianofranz)) + + * Added exported env vars to kubectl plugins so that plugin developers have access to global flags, namespace, the plugin descriptor and the full path to the caller binary. + +* Ignored mirror pods in PodPreset admission plugin. ([[#45958](https://github.com/kubernetes/kubernetes/pull/45958)](https://github.com/kubernetes/kubernetes/pull/45958), [[@k82cn](https://github.com/k82cn)](https://github.com/k82cn)) + +* Don't try to attach volume to new node if it is already attached to another node and the volume does not support multi-attach. ([[#45346](https://github.com/kubernetes/kubernetes/pull/45346)](https://github.com/kubernetes/kubernetes/pull/45346), [[@codablock](https://github.com/codablock)](https://github.com/codablock)) + +* The Calico version included in kube-up for GCE has been updated to v2.2. ([[#38169](https://github.com/kubernetes/kubernetes/pull/38169)](https://github.com/kubernetes/kubernetes/pull/38169), [[@caseydavenport](https://github.com/caseydavenport)](https://github.com/caseydavenport)) + +* Kubelet: Fix image garbage collector attempting to remove in-use images. ([[#46121](https://github.com/kubernetes/kubernetes/pull/46121)](https://github.com/kubernetes/kubernetes/pull/46121), [[@Random-Liu](https://github.com/Random-Liu)](https://github.com/Random-Liu)) + +* Add ip-masq-agent addon to the addons folder which is used in GCE if `--non-masquerade-cidr` is set to 0/0 ([[#46038](https://github.com/kubernetes/kubernetes/pull/46038)](https://github.com/kubernetes/kubernetes/pull/46038), [[@dnardo](https://github.com/dnardo)](https://github.com/dnardo)) + +* Fix serialization of EnforceNodeAllocatable ([[#44606](https://github.com/kubernetes/kubernetes/pull/44606)](https://github.com/kubernetes/kubernetes/pull/44606), [[@ivan4th](https://github.com/ivan4th)](https://github.com/ivan4th)) + +* Add `--write-config-to` flag to kube-proxy to allow users to write the default configuration settings to a file. ([[#45908](https://github.com/kubernetes/kubernetes/pull/45908)](https://github.com/kubernetes/kubernetes/pull/45908), [[@ncdc](https://github.com/ncdc)](https://github.com/ncdc)) + +* The NodeRestriction admission plugin limits the Node and Pod objects a kubelet can modify. In order to be limited by this admission plugin, kubelets must use credentials in the system:nodes group, with a username in the form system:node:. Such kubelets will only be allowed to modify their own Node API object, and only modify Pod API objects that are bound to their node. ([[#45929](https://github.com/kubernetes/kubernetes/pull/45929)](https://github.com/kubernetes/kubernetes/pull/45929), [[@liggitt](https://github.com/liggitt)](https://github.com/liggitt)) + +* vSphere cloud provider: Report same Node IP as both internal and external. ([[#45201](https://github.com/kubernetes/kubernetes/pull/45201)](https://github.com/kubernetes/kubernetes/pull/45201), [[@abrarshivani](https://github.com/abrarshivani)](https://github.com/abrarshivani)) + +* avoid concrete examples for missingResourceError ([[#45582](https://github.com/kubernetes/kubernetes/pull/45582)](https://github.com/kubernetes/kubernetes/pull/45582), [[@CaoShuFeng](https://github.com/CaoShuFeng)](https://github.com/CaoShuFeng)) + +* Fix DNS suffix search list support in Windows kube-proxy. ([[#45642](https://github.com/kubernetes/kubernetes/pull/45642)](https://github.com/kubernetes/kubernetes/pull/45642), [[@JiangtianLi](https://github.com/JiangtianLi)](https://github.com/JiangtianLi)) + +* Fix the bug where StartedAt time is not reported for exited containers. ([[#45977](https://github.com/kubernetes/kubernetes/pull/45977)](https://github.com/kubernetes/kubernetes/pull/45977), [[@yujuhong](https://github.com/yujuhong)](https://github.com/yujuhong)) + +* Update Dashboard version to 1.6.1 ([[#45953](https://github.com/kubernetes/kubernetes/pull/45953)](https://github.com/kubernetes/kubernetes/pull/45953), [[@maciaszczykm](https://github.com/maciaszczykm)](https://github.com/maciaszczykm)) + +* Examples: fixed cassandra mirror detection that assumes an FTP site will always be presented ([[#45965](https://github.com/kubernetes/kubernetes/pull/45965)](https://github.com/kubernetes/kubernetes/pull/45965), [[@pompomJuice](https://github.com/pompomJuice)](https://github.com/pompomJuice)) + +* Removes the deprecated kubelet flag `--babysit-daemons` ([[#44230](https://github.com/kubernetes/kubernetes/pull/44230)](https://github.com/kubernetes/kubernetes/pull/44230), [[@mtaufen](https://github.com/mtaufen)](https://github.com/mtaufen)) + +* [Federation] Automate configuring nameserver in cluster-dns for CoreDNS provider ([[#42895](https://github.com/kubernetes/kubernetes/pull/42895)](https://github.com/kubernetes/kubernetes/pull/42895), [[@shashidharatd](https://github.com/shashidharatd)](https://github.com/shashidharatd)) + +* Add an AEAD encrypting transformer for storing secrets encrypted at rest ([[#41939](https://github.com/kubernetes/kubernetes/pull/41939)](https://github.com/kubernetes/kubernetes/pull/41939), [[@smarterclayton](https://github.com/smarterclayton)](https://github.com/smarterclayton)) + +* Update Minio example ([[#45444](https://github.com/kubernetes/kubernetes/pull/45444)](https://github.com/kubernetes/kubernetes/pull/45444), [[@NitishT](https://github.com/NitishT)](https://github.com/NitishT)) + +* [Federation] Segregate DNS related code to separate controller ([[#45034](https://github.com/kubernetes/kubernetes/pull/45034)](https://github.com/kubernetes/kubernetes/pull/45034), [[@shashidharatd](https://github.com/shashidharatd)](https://github.com/shashidharatd)) + +* API Registration is now in beta. ([[#45247](https://github.com/kubernetes/kubernetes/pull/45247)](https://github.com/kubernetes/kubernetes/pull/45247), [[@mbohlool](https://github.com/mbohlool)](https://github.com/mbohlool)) + +* Allow kcm and scheduler to lock on ConfigMaps. ([[#45739](https://github.com/kubernetes/kubernetes/pull/45739)](https://github.com/kubernetes/kubernetes/pull/45739), [[@timothysc](https://github.com/timothysc)](https://github.com/timothysc)) + +* Fix lint failures on kubernetes-e2e charm ([[#45832](https://github.com/kubernetes/kubernetes/pull/45832)](https://github.com/kubernetes/kubernetes/pull/45832), [[@Cynerva](https://github.com/Cynerva)](https://github.com/Cynerva)) + +* Mirror pods must now indicate the nodeName they are bound to on creation. The mirror pod annotation is now treated as immutable and cannot be added to an existing pod, removed from a pod, or modified. ([[#45775](https://github.com/kubernetes/kubernetes/pull/45775)](https://github.com/kubernetes/kubernetes/pull/45775), [[@liggitt](https://github.com/liggitt)](https://github.com/liggitt)) + +* Updating apiserver to return UID of the deleted resource. Clients can use this UID to verify that the resource was deleted or waiting for finalizers. ([[#45600](https://github.com/kubernetes/kubernetes/pull/45600)](https://github.com/kubernetes/kubernetes/pull/45600), [[@nikhiljindal](https://github.com/nikhiljindal)](https://github.com/nikhiljindal)) + +* OwnerReferencesPermissionEnforcement admission plugin ignores pods/status. ([[#45747](https://github.com/kubernetes/kubernetes/pull/45747)](https://github.com/kubernetes/kubernetes/pull/45747), [[@derekwaynecarr](https://github.com/derekwaynecarr)](https://github.com/derekwaynecarr)) + +* prevent pods/status from touching ownerreferences ([[#45826](https://github.com/kubernetes/kubernetes/pull/45826)](https://github.com/kubernetes/kubernetes/pull/45826), [[@deads2k](https://github.com/deads2k)](https://github.com/deads2k)) + +* Fix lint errors in juju kubernetes master and e2e charms ([[#45494](https://github.com/kubernetes/kubernetes/pull/45494)](https://github.com/kubernetes/kubernetes/pull/45494), [[@ktsakalozos](https://github.com/ktsakalozos)](https://github.com/ktsakalozos)) + +* Ensure that autoscaling/v1 is the preferred version for API discovery when autoscaling/v2alpha1 is enabled. ([[#45741](https://github.com/kubernetes/kubernetes/pull/45741)](https://github.com/kubernetes/kubernetes/pull/45741), [[@DirectXMan12](https://github.com/DirectXMan12)](https://github.com/DirectXMan12)) + +* Promotes Source IP preservation for Virtual IPs to GA. ([[#41162](https://github.com/kubernetes/kubernetes/pull/41162)](https://github.com/kubernetes/kubernetes/pull/41162), [[@MrHohn](https://github.com/MrHohn)](https://github.com/MrHohn)) + + * Two api fields are defined correspondingly: + + * Service.Spec.ExternalTrafficPolicy <- 'service.beta.kubernetes.io/external-traffic' annotation. + + * Service.Spec.HealthCheckNodePort <- 'service.beta.kubernetes.io/healthcheck-nodeport' annotation. + +* the resource quota controller was not adding quota to be resynced at proper interval ([[#45685](https://github.com/kubernetes/kubernetes/pull/45685)](https://github.com/kubernetes/kubernetes/pull/45685), [[@derekwaynecarr](https://github.com/derekwaynecarr)](https://github.com/derekwaynecarr)) + +* fluentd will tolerate all NoExecute Taints when run in gcp configuration. ([[#45715](https://github.com/kubernetes/kubernetes/pull/45715)](https://github.com/kubernetes/kubernetes/pull/45715), [[@gmarek](https://github.com/gmarek)](https://github.com/gmarek)) + +* Added Group/Version/Kind and Action extension to OpenAPI Operations ([[#44787](https://github.com/kubernetes/kubernetes/pull/44787)](https://github.com/kubernetes/kubernetes/pull/44787), [[@mbohlool](https://github.com/mbohlool)](https://github.com/mbohlool)) + +* Updates kube-dns to 1.14.2 ([[#45684](https://github.com/kubernetes/kubernetes/pull/45684)](https://github.com/kubernetes/kubernetes/pull/45684), [[@bowei](https://github.com/bowei)](https://github.com/bowei)) + + * Support kube-master-url flag without kubeconfig + + * Fix concurrent R/Ws in dns.go + + * Fix confusing logging when initialize server + + * Fix printf in cmd/kube-dns/app/server.go + + * Fix version on startup and `--version` flag + + * Support specifying port number for nameserver in stubDomains + +* detach the volume when pod is terminated ([[#45286](https://github.com/kubernetes/kubernetes/pull/45286)](https://github.com/kubernetes/kubernetes/pull/45286), [[@gnufied](https://github.com/gnufied)](https://github.com/gnufied)) + +* Don't append :443 to registry domain in the kubernetes-worker layer registry action ([[#45550](https://github.com/kubernetes/kubernetes/pull/45550)](https://github.com/kubernetes/kubernetes/pull/45550), [[@jacekn](https://github.com/jacekn)](https://github.com/jacekn)) + +* AWS: Remove check that forces loadBalancerSourceRanges to be 0.0.0.0/0. ([[#38636](https://github.com/kubernetes/kubernetes/pull/38636)](https://github.com/kubernetes/kubernetes/pull/38636), [[@dhawal55](https://github.com/dhawal55)](https://github.com/dhawal55)) + +* azure: add support for UDP ports ([[#45523](https://github.com/kubernetes/kubernetes/pull/45523)](https://github.com/kubernetes/kubernetes/pull/45523), [[@colemickens](https://github.com/colemickens)](https://github.com/colemickens)) + + * azure: fix support for multiple loadBalancerSourceRanges + + * azure: support the Service spec's sessionAffinity + +* The fix makes scheduling go routine waiting for cache (e.g. Pod) to be synced. ([[#45453](https://github.com/kubernetes/kubernetes/pull/45453)](https://github.com/kubernetes/kubernetes/pull/45453), [[@k82cn](https://github.com/k82cn)](https://github.com/k82cn)) + +* vSphere cloud provider: Filter out IPV6 node addresses. ([[#45181](https://github.com/kubernetes/kubernetes/pull/45181)](https://github.com/kubernetes/kubernetes/pull/45181), [[@BaluDontu](https://github.com/BaluDontu)](https://github.com/BaluDontu)) + +* A small clean up to remove unnecessary functions. ([[#45018](https://github.com/kubernetes/kubernetes/pull/45018)](https://github.com/kubernetes/kubernetes/pull/45018), [[@ravisantoshgudimetla](https://github.com/ravisantoshgudimetla)](https://github.com/ravisantoshgudimetla)) + +* Removed old scheduler constructor. ([[#45472](https://github.com/kubernetes/kubernetes/pull/45472)](https://github.com/kubernetes/kubernetes/pull/45472), [[@k82cn](https://github.com/k82cn)](https://github.com/k82cn)) + +* vSphere cloud provider: Fix fetching of VM UUID on Ubuntu 16.04 and Fedora. ([[#45311](https://github.com/kubernetes/kubernetes/pull/45311)](https://github.com/kubernetes/kubernetes/pull/45311), [[@divyenpatel](https://github.com/divyenpatel)](https://github.com/divyenpatel)) + +* This fixes the overflow for priorityconfig- valid range {1, 9223372036854775806}. ([[#45122](https://github.com/kubernetes/kubernetes/pull/45122)](https://github.com/kubernetes/kubernetes/pull/45122), [[@ravisantoshgudimetla](https://github.com/ravisantoshgudimetla)](https://github.com/ravisantoshgudimetla)) + +* Bump cluster autoscaler to v0.5.4, which fixes scale down issues with pods ignoring SIGTERM. ([[#45483](https://github.com/kubernetes/kubernetes/pull/45483)](https://github.com/kubernetes/kubernetes/pull/45483), [[@mwielgus](https://github.com/mwielgus)](https://github.com/mwielgus)) + +* Remove deprecated node address type NodeLegacyHostIP. ([[#44830](https://github.com/kubernetes/kubernetes/pull/44830)](https://github.com/kubernetes/kubernetes/pull/44830), [[@NickrenREN](https://github.com/NickrenREN)](https://github.com/NickrenREN)) + +* UIDs and GIDs now use apimachinery types ([[#44714](https://github.com/kubernetes/kubernetes/pull/44714)](https://github.com/kubernetes/kubernetes/pull/44714), [[@jamiehannaford](https://github.com/jamiehannaford)](https://github.com/jamiehannaford)) + +* Enable basic auth username rotation for GCI ([[#44590](https://github.com/kubernetes/kubernetes/pull/44590)](https://github.com/kubernetes/kubernetes/pull/44590), [[@ihmccreery](https://github.com/ihmccreery)](https://github.com/ihmccreery)) + +* `kubectl taint node` based on label selector ([[#44740](https://github.com/kubernetes/kubernetes/pull/44740)](https://github.com/kubernetes/kubernetes/pull/44740), [[@ravisantoshgudimetla](https://github.com/ravisantoshgudimetla)](https://github.com/ravisantoshgudimetla)) + +* Scheduler perf modular extensions. ([[#44770](https://github.com/kubernetes/kubernetes/pull/44770)](https://github.com/kubernetes/kubernetes/pull/44770), [[@ravisantoshgudimetla](https://github.com/ravisantoshgudimetla)](https://github.com/ravisantoshgudimetla)) + +* Use Docker API Version instead of docker version ([[#44068](https://github.com/kubernetes/kubernetes/pull/44068)](https://github.com/kubernetes/kubernetes/pull/44068), [[@mkumatag](https://github.com/mkumatag)](https://github.com/mkumatag)) + +* bump(golang.org/x/oauth2): a6bd8cefa1811bd24b86f8902872e4e8225f74c4 ([[#45056](https://github.com/kubernetes/kubernetes/pull/45056)](https://github.com/kubernetes/kubernetes/pull/45056), [[@ericchiang](https://github.com/ericchiang)](https://github.com/ericchiang)) + +* apimachinery: make explicit that meta.KindToResource is only a guess ([[#45272](https://github.com/kubernetes/kubernetes/pull/45272)](https://github.com/kubernetes/kubernetes/pull/45272), [[@sttts](https://github.com/sttts)](https://github.com/sttts)) + +* Fixed misspelled http URL in the cluster-dns example ([[#45246](https://github.com/kubernetes/kubernetes/pull/45246)](https://github.com/kubernetes/kubernetes/pull/45246), [[@psiwczak](https://github.com/psiwczak)](https://github.com/psiwczak)) + +* separate discovery from the apiserver ([[#43003](https://github.com/kubernetes/kubernetes/pull/43003)](https://github.com/kubernetes/kubernetes/pull/43003), [[@deads2k](https://github.com/deads2k)](https://github.com/deads2k)) + +* Remove the `--secret-name` flag from `kubefed join`, instead generating the secret name arbitrarily. ([[#42513](https://github.com/kubernetes/kubernetes/pull/42513)](https://github.com/kubernetes/kubernetes/pull/42513), [[@perotinus](https://github.com/perotinus)](https://github.com/perotinus)) + +* Added InterPodAffinity unit test case with Namespace. ([[#45152](https://github.com/kubernetes/kubernetes/pull/45152)](https://github.com/kubernetes/kubernetes/pull/45152), [[@k82cn](https://github.com/k82cn)](https://github.com/k82cn)) + +* Use munged semantic version for side-loaded docker tag ([[#44981](https://github.com/kubernetes/kubernetes/pull/44981)](https://github.com/kubernetes/kubernetes/pull/44981), [[@ixdy](https://github.com/ixdy)](https://github.com/ixdy)) + +* Increase Dashboard's memory requests and limits ([[#44712](https://github.com/kubernetes/kubernetes/pull/44712)](https://github.com/kubernetes/kubernetes/pull/44712), [[@maciaszczykm](https://github.com/maciaszczykm)](https://github.com/maciaszczykm)) + +* Create and push a docker image for the cloud-controller-manager ([[#45154](https://github.com/kubernetes/kubernetes/pull/45154)](https://github.com/kubernetes/kubernetes/pull/45154), [[@luxas](https://github.com/luxas)](https://github.com/luxas)) + +* Align Extender's validation with prioritizers. ([[#45091](https://github.com/kubernetes/kubernetes/pull/45091)](https://github.com/kubernetes/kubernetes/pull/45091), [[@k82cn](https://github.com/k82cn)](https://github.com/k82cn)) + +* Retry calls we report config changes quickly. ([[#44959](https://github.com/kubernetes/kubernetes/pull/44959)](https://github.com/kubernetes/kubernetes/pull/44959), [[@ktsakalozos](https://github.com/ktsakalozos)](https://github.com/ktsakalozos)) + +* Added CIFS PV support for Juju Charms ([[#45117](https://github.com/kubernetes/kubernetes/pull/45117)](https://github.com/kubernetes/kubernetes/pull/45117), [[@chuckbutler](https://github.com/chuckbutler)](https://github.com/chuckbutler)) + +* add APIService conditions ([[#43301](https://github.com/kubernetes/kubernetes/pull/43301)](https://github.com/kubernetes/kubernetes/pull/43301), [[@deads2k](https://github.com/deads2k)](https://github.com/deads2k)) + +* Log warning when invalid dir passed to `kubectl proxy --www` ([[#44952](https://github.com/kubernetes/kubernetes/pull/44952)](https://github.com/kubernetes/kubernetes/pull/44952), [[@CaoShuFeng](https://github.com/CaoShuFeng)](https://github.com/CaoShuFeng)) + +* Roll up volume error messages in the kubelet sync loop. ([[#44938](https://github.com/kubernetes/kubernetes/pull/44938)](https://github.com/kubernetes/kubernetes/pull/44938), [[@jayunit100](https://github.com/jayunit100)](https://github.com/jayunit100)) + +* Introduces the ability to extend kubectl by adding third-party plugins. Developer preview, please refer to the documentation for instructions about how to use it. ([[#37499](https://github.com/kubernetes/kubernetes/pull/37499)](https://github.com/kubernetes/kubernetes/pull/37499), [[@fabianofranz](https://github.com/fabianofranz)](https://github.com/fabianofranz)) + +* Fixes juju kubernetes master: 1. Get certs from a dead leader. 2. Append tokens. ([[#43620](https://github.com/kubernetes/kubernetes/pull/43620)](https://github.com/kubernetes/kubernetes/pull/43620), [[@ktsakalozos](https://github.com/ktsakalozos)](https://github.com/ktsakalozos)) + +* Use correct option name in the kubernetes-worker layer registry action ([[#44921](https://github.com/kubernetes/kubernetes/pull/44921)](https://github.com/kubernetes/kubernetes/pull/44921), [[@jacekn](https://github.com/jacekn)](https://github.com/jacekn)) + +* Start recording cloud provider metrics for AWS ([[#43477](https://github.com/kubernetes/kubernetes/pull/43477)](https://github.com/kubernetes/kubernetes/pull/43477), [[@gnufied](https://github.com/gnufied)](https://github.com/gnufied)) + +* Add metrics to all major gce operations {latency, errors} ([[#44510](https://github.com/kubernetes/kubernetes/pull/44510)](https://github.com/kubernetes/kubernetes/pull/44510), [[@bowei](https://github.com/bowei)](https://github.com/bowei)) + + * The new metrics are: + + * cloudprovider_gce_api_request_duration_seconds{request, region, zone} + + * cloudprovider_gce_api_request_errors{request, region, zone} + + * request is the specific function that is used. + + * region is the target region (Will be "" if not applicable) + + * zone is the target zone (Will be "" if not applicable) + + * Note: this fixes some issues with the previous implementation of + + * metrics for disks: + + * Time duration tracked was of the initial API call, not the entire + + * operation. + + * Metrics label tuple would have resulted in many independent + + * histograms stored, one for each disk. (Did not aggregate well). + +* Update kubernetes-e2e charm to use snaps ([[#45044](https://github.com/kubernetes/kubernetes/pull/45044)](https://github.com/kubernetes/kubernetes/pull/45044), [[@Cynerva](https://github.com/Cynerva)](https://github.com/Cynerva)) + +* Log the error (if any) in e2e metrics gathering step ([[#45039](https://github.com/kubernetes/kubernetes/pull/45039)](https://github.com/kubernetes/kubernetes/pull/45039), [[@shyamjvs](https://github.com/shyamjvs)](https://github.com/shyamjvs)) + +* The proxy subresource APIs for nodes, services, and pods now support the HTTP PATCH method. ([[#44929](https://github.com/kubernetes/kubernetes/pull/44929)](https://github.com/kubernetes/kubernetes/pull/44929), [[@liggitt](https://github.com/liggitt)](https://github.com/liggitt)) + +* cluster-autoscaler: Fix duplicate writing of logs. ([[#45017](https://github.com/kubernetes/kubernetes/pull/45017)](https://github.com/kubernetes/kubernetes/pull/45017), [[@MaciekPytel](https://github.com/MaciekPytel)](https://github.com/MaciekPytel)) + +* CRI: Fix StopContainer timeout ([[#44970](https://github.com/kubernetes/kubernetes/pull/44970)](https://github.com/kubernetes/kubernetes/pull/44970), [[@Random-Liu](https://github.com/Random-Liu)](https://github.com/Random-Liu)) + +* Fixes a bug where pods were evicted even after images are successfully deleted. ([[#44986](https://github.com/kubernetes/kubernetes/pull/44986)](https://github.com/kubernetes/kubernetes/pull/44986), [[@dashpole](https://github.com/dashpole)](https://github.com/dashpole)) + +* Fix some false negatives in detection of meaningful conflicts during strategic merge patch with maps and lists. ([[#43469](https://github.com/kubernetes/kubernetes/pull/43469)](https://github.com/kubernetes/kubernetes/pull/43469), [[@enisoc](https://github.com/enisoc)](https://github.com/enisoc)) + +* kubernetes-master juju charm properly detects etcd-scale events and reconfigures appropriately. ([[#44967](https://github.com/kubernetes/kubernetes/pull/44967)](https://github.com/kubernetes/kubernetes/pull/44967), [[@chuckbutler](https://github.com/chuckbutler)](https://github.com/chuckbutler)) + +* Add redirect support to SpdyRoundTripper ([[#44451](https://github.com/kubernetes/kubernetes/pull/44451)](https://github.com/kubernetes/kubernetes/pull/44451), [[@ncdc](https://github.com/ncdc)](https://github.com/ncdc)) + +* Support running Ubuntu image on GCE node ([[#44744](https://github.com/kubernetes/kubernetes/pull/44744)](https://github.com/kubernetes/kubernetes/pull/44744), [[@yguo0905](https://github.com/yguo0905)](https://github.com/yguo0905)) + +* Send dns details only after cdk-addons are configured ([[#44945](https://github.com/kubernetes/kubernetes/pull/44945)](https://github.com/kubernetes/kubernetes/pull/44945), [[@ktsakalozos](https://github.com/ktsakalozos)](https://github.com/ktsakalozos)) + +* Added support to the pause action in the kubernetes-worker charm for new flag `--delete-local-data` ([[#44931](https://github.com/kubernetes/kubernetes/pull/44931)](https://github.com/kubernetes/kubernetes/pull/44931), [[@chuckbutler](https://github.com/chuckbutler)](https://github.com/chuckbutler)) + +* Upgrade go version to v1.8 ([[#41636](https://github.com/kubernetes/kubernetes/pull/41636)](https://github.com/kubernetes/kubernetes/pull/41636), [[@luxas](https://github.com/luxas)](https://github.com/luxas)) + +* Add namespace-{list, create, delete} actions to the kubernetes-master layer ([[#44277](https://github.com/kubernetes/kubernetes/pull/44277)](https://github.com/kubernetes/kubernetes/pull/44277), [[@jacekn](https://github.com/jacekn)](https://github.com/jacekn)) + +* Fix problems with scaling up the cluster when unschedulable pods have some persistent volume claims. ([[#44860](https://github.com/kubernetes/kubernetes/pull/44860)](https://github.com/kubernetes/kubernetes/pull/44860), [[@mwielgus](https://github.com/mwielgus)](https://github.com/mwielgus)) + +* Feature/hpa upscale downscale delay configurable ([[#42101](https://github.com/kubernetes/kubernetes/pull/42101)](https://github.com/kubernetes/kubernetes/pull/42101), [[@Dmitry1987](https://github.com/Dmitry1987)](https://github.com/Dmitry1987)) + +* Add short name "netpol" for networkpolicies ([[#42241](https://github.com/kubernetes/kubernetes/pull/42241)](https://github.com/kubernetes/kubernetes/pull/42241), [[@xiangpengzhao](https://github.com/xiangpengzhao)](https://github.com/xiangpengzhao)) + +* Restored the ability of kubectl running inside a pod to consume resource files specifying a different namespace than the one the pod is running in. ([[#44862](https://github.com/kubernetes/kubernetes/pull/44862)](https://github.com/kubernetes/kubernetes/pull/44862), [[@liggitt](https://github.com/liggitt)](https://github.com/liggitt)) + +* e2e: handle nil ReplicaSet in checkDeploymentRevision ([[#44859](https://github.com/kubernetes/kubernetes/pull/44859)](https://github.com/kubernetes/kubernetes/pull/44859), [[@sttts](https://github.com/sttts)](https://github.com/sttts)) + +* Fix false positive "meaningful conflict" detection for strategic merge patch with integer values. ([[#44788](https://github.com/kubernetes/kubernetes/pull/44788)](https://github.com/kubernetes/kubernetes/pull/44788), [[@enisoc](https://github.com/enisoc)](https://github.com/enisoc)) + +* Documented NodePort networking for CDK. ([[#44863](https://github.com/kubernetes/kubernetes/pull/44863)](https://github.com/kubernetes/kubernetes/pull/44863), [[@chuckbutler](https://github.com/chuckbutler)](https://github.com/chuckbutler)) + +* Deployments and DaemonSets are now considered complete once all of the new pods are up and running - affects kubectl rollout status (and ProgressDeadlineSeconds for Deployments) ([[#44672](https://github.com/kubernetes/kubernetes/pull/44672)](https://github.com/kubernetes/kubernetes/pull/44672), [[@kargakis](https://github.com/kargakis)](https://github.com/kargakis)) + +* Exclude nodes labeled as master from LoadBalancer / NodePort; restores documented behaviour. ([[#44745](https://github.com/kubernetes/kubernetes/pull/44745)](https://github.com/kubernetes/kubernetes/pull/44745), [[@justinsb](https://github.com/justinsb)](https://github.com/justinsb)) + +* Fixes issue during LB creation where ports where incorrectly assigned to a floating IP ([[#44387](https://github.com/kubernetes/kubernetes/pull/44387)](https://github.com/kubernetes/kubernetes/pull/44387), [[@jamiehannaford](https://github.com/jamiehannaford)](https://github.com/jamiehannaford)) + +* Remove redis-proxy.yaml sample, as the image is nowhere to be found. ([[#44801](https://github.com/kubernetes/kubernetes/pull/44801)](https://github.com/kubernetes/kubernetes/pull/44801), [[@klausenbusk](https://github.com/klausenbusk)](https://github.com/klausenbusk)) + +* Resolves juju vsphere hostname bug showing only a single node in a scaled node-pool. ([[#44780](https://github.com/kubernetes/kubernetes/pull/44780)](https://github.com/kubernetes/kubernetes/pull/44780), [[@chuckbutler](https://github.com/chuckbutler)](https://github.com/chuckbutler)) + +* kubectl commands run inside a pod using a kubeconfig file now use the namespace specified in the kubeconfig file, instead of using the pod namespace. If no kubeconfig file is used, or the kubeconfig does not specify a namespace, the pod namespace is still used as a fallback. ([[#44570](https://github.com/kubernetes/kubernetes/pull/44570)](https://github.com/kubernetes/kubernetes/pull/44570), [[@liggitt](https://github.com/liggitt)](https://github.com/liggitt)) + +* This adds support for CNI ConfigLists, which permit plugin chaining. ([[#42202](https://github.com/kubernetes/kubernetes/pull/42202)](https://github.com/kubernetes/kubernetes/pull/42202), [[@squeed](https://github.com/squeed)](https://github.com/squeed)) + +* API requests using impersonation now include the system:authenticated group in the impersonated user automatically. ([[#44076](https://github.com/kubernetes/kubernetes/pull/44076)](https://github.com/kubernetes/kubernetes/pull/44076), [[@liggitt](https://github.com/liggitt)](https://github.com/liggitt)) + +* Print conditions of RC/RS in `kubectl describe` command. ([[#44710](https://github.com/kubernetes/kubernetes/pull/44710)](https://github.com/kubernetes/kubernetes/pull/44710), [[@xiangpengzhao](https://github.com/xiangpengzhao)](https://github.com/xiangpengzhao)) + +* NONE ([[#44487](https://github.com/kubernetes/kubernetes/pull/44487)](https://github.com/kubernetes/kubernetes/pull/44487), [[@resouer](https://github.com/resouer)](https://github.com/resouer)) + +* cinder: Add support for the KVM virtio-scsi driver ([[#41498](https://github.com/kubernetes/kubernetes/pull/41498)](https://github.com/kubernetes/kubernetes/pull/41498), [[@mikebryant](https://github.com/mikebryant)](https://github.com/mikebryant)) + +* Disallows installation of upstream docker from PPA in the Juju kubernetes-worker charm. ([[#44681](https://github.com/kubernetes/kubernetes/pull/44681)](https://github.com/kubernetes/kubernetes/pull/44681), [[@wwwtyro](https://github.com/wwwtyro)](https://github.com/wwwtyro)) + +* Job controller now respects ControllerRef to avoid fighting over Pods. ([[#42176](https://github.com/kubernetes/kubernetes/pull/42176)](https://github.com/kubernetes/kubernetes/pull/42176), [[@enisoc](https://github.com/enisoc)](https://github.com/enisoc)) + +* CronJob controller now respects ControllerRef to avoid fighting with other controllers. ([[#42177](https://github.com/kubernetes/kubernetes/pull/42177)](https://github.com/kubernetes/kubernetes/pull/42177), [[@enisoc](https://github.com/enisoc)](https://github.com/enisoc)) + +* The hyperkube image has been slimmed down and no longer includes addon manifests and other various scripts. These were introduced for the now removed docker-multinode setup system. ([[#44555](https://github.com/kubernetes/kubernetes/pull/44555)](https://github.com/kubernetes/kubernetes/pull/44555), [[@luxas](https://github.com/luxas)](https://github.com/luxas)) + +* Refactoring reorganize taints function in kubectl to expose operations ([[#43171](https://github.com/kubernetes/kubernetes/pull/43171)](https://github.com/kubernetes/kubernetes/pull/43171), [[@ravisantoshgudimetla](https://github.com/ravisantoshgudimetla)](https://github.com/ravisantoshgudimetla)) + +* The Kubernetes API server now exits if it encounters a networking failure (e.g. the networking interface hosting its address goes away) to allow a process manager (systemd/kubelet/etc) to react to the problem. Previously the server would log the failure and try again to bind to its configured address:port. ([[#42272](https://github.com/kubernetes/kubernetes/pull/42272)](https://github.com/kubernetes/kubernetes/pull/42272), [[@marun](https://github.com/marun)](https://github.com/marun)) + +* Fixes a bug in the kubernetes-worker Juju charm code that attempted to give kube-proxy more than one api endpoint. ([[#44677](https://github.com/kubernetes/kubernetes/pull/44677)](https://github.com/kubernetes/kubernetes/pull/44677), [[@wwwtyro](https://github.com/wwwtyro)](https://github.com/wwwtyro)) + +* Fixes a missing comma in a list of strings. ([[#44678](https://github.com/kubernetes/kubernetes/pull/44678)](https://github.com/kubernetes/kubernetes/pull/44678), [[@wwwtyro](https://github.com/wwwtyro)](https://github.com/wwwtyro)) + +* Fix ceph-secret type to kubernetes.io/rbd in kubernetes-master charm ([[#44635](https://github.com/kubernetes/kubernetes/pull/44635)](https://github.com/kubernetes/kubernetes/pull/44635), [[@Cynerva](https://github.com/Cynerva)](https://github.com/Cynerva)) + +* Add support for Azure internal load balancer ([[#43510](https://github.com/kubernetes/kubernetes/pull/43510)](https://github.com/kubernetes/kubernetes/pull/43510), [[@karataliu](https://github.com/karataliu)](https://github.com/karataliu)) + +* Improved output on `kubectl get` and `kubectl describe` for generic objects. ([[#44222](https://github.com/kubernetes/kubernetes/pull/44222)](https://github.com/kubernetes/kubernetes/pull/44222), [[@fabianofranz](https://github.com/fabianofranz)](https://github.com/fabianofranz)) + +* Add Kubernetes 1.6 support to Juju charms ([[#44500](https://github.com/kubernetes/kubernetes/pull/44500)](https://github.com/kubernetes/kubernetes/pull/44500), [[@Cynerva](https://github.com/Cynerva)](https://github.com/Cynerva)) + + * Add metric collection to charms for autoscaling + + * Update kubernetes-e2e charm to fail when test suite fails + + * Update Juju charms to use snaps + + * Add registry action to the kubernetes-worker charm + + * Add support for kube-proxy cluster-cidr option to kubernetes-worker charm + + * Fix kubernetes-master charm starting services before TLS certs are saved + + * Fix kubernetes-worker charm failures in LXD + + * Fix stop hook failure on kubernetes-worker charm + + * Fix handling of juju kubernetes-worker.restart-needed state + + * Fix nagios checks in charms + +* Fixed `kubectl cluster-info dump` to support multi-container pod. ([[#44088](https://github.com/kubernetes/kubernetes/pull/44088)](https://github.com/kubernetes/kubernetes/pull/44088), [[@xingzhou](https://github.com/xingzhou)](https://github.com/xingzhou)) + +* Prints out status updates when running `kubefed init` ([[#41849](https://github.com/kubernetes/kubernetes/pull/41849)](https://github.com/kubernetes/kubernetes/pull/41849), [[@perotinus](https://github.com/perotinus)](https://github.com/perotinus)) + +* CRI: Fix kubelet failing to start when using rkt. ([[#44569](https://github.com/kubernetes/kubernetes/pull/44569)](https://github.com/kubernetes/kubernetes/pull/44569), [[@yujuhong](https://github.com/yujuhong)](https://github.com/yujuhong)) + +* Remove deprecatedPublicIPs field ([[#44519](https://github.com/kubernetes/kubernetes/pull/44519)](https://github.com/kubernetes/kubernetes/pull/44519), [[@thockin](https://github.com/thockin)](https://github.com/thockin)) + +* Remove deprecated ubuntu kube-up deployment. ([[#44344](https://github.com/kubernetes/kubernetes/pull/44344)](https://github.com/kubernetes/kubernetes/pull/44344), [[@mikedanese](https://github.com/mikedanese)](https://github.com/mikedanese)) + +* Use OS-specific libs when computing client User-Agent in kubectl, etc. ([[#44423](https://github.com/kubernetes/kubernetes/pull/44423)](https://github.com/kubernetes/kubernetes/pull/44423), [[@monopole](https://github.com/monopole)](https://github.com/monopole)) + +* kube-apiserver now drops unneeded path information if an older version of Windows kubectl sends it. ([[#44421](https://github.com/kubernetes/kubernetes/pull/44421)](https://github.com/kubernetes/kubernetes/pull/44421), [[@mml](https://github.com/mml)](https://github.com/mml)) + +* Extending the gc admission plugin so that a user who doesn't have delete permission of the *owner* cannot modify blockOwnerDeletion field of existing ownerReferences, or add new ownerReference with blockOwnerDeletion=true ([[#43876](https://github.com/kubernetes/kubernetes/pull/43876)](https://github.com/kubernetes/kubernetes/pull/43876), [[@caesarxuchao](https://github.com/caesarxuchao)](https://github.com/caesarxuchao)) + +* kube-apiserver: `--service-account-lookup` now defaults to true, requiring the Secret API object containing the token to exist in order for a service account token to be valid. This enables service account tokens to be revoked by deleting the Secret object containing the token. ([[#44071](https://github.com/kubernetes/kubernetes/pull/44071)](https://github.com/kubernetes/kubernetes/pull/44071), [[@liggitt](https://github.com/liggitt)](https://github.com/liggitt)) + +* CRI: `kubectl logs -f` now stops following when container stops, as it did pre-CRI. ([[#44406](https://github.com/kubernetes/kubernetes/pull/44406)](https://github.com/kubernetes/kubernetes/pull/44406), [[@Random-Liu](https://github.com/Random-Liu)](https://github.com/Random-Liu)) + +* Add completion support for `--user` and `--cluster` to kubectl ([[#44251](https://github.com/kubernetes/kubernetes/pull/44251)](https://github.com/kubernetes/kubernetes/pull/44251), [[@superbrothers](https://github.com/superbrothers)](https://github.com/superbrothers)) + +* dnsprovider: avoid panic if route53 fields are nil ([[#44380](https://github.com/kubernetes/kubernetes/pull/44380)](https://github.com/kubernetes/kubernetes/pull/44380), [[@justinsb](https://github.com/justinsb)](https://github.com/justinsb)) + +* In `kubectl describe`, find controllers with ControllerRef, instead of showing the original creator. ([[#42849](https://github.com/kubernetes/kubernetes/pull/42849)](https://github.com/kubernetes/kubernetes/pull/42849), [[@janetkuo](https://github.com/janetkuo)](https://github.com/janetkuo)) + +* Heat cluster operations now support environments that have multiple Swift URLs ([[#41561](https://github.com/kubernetes/kubernetes/pull/41561)](https://github.com/kubernetes/kubernetes/pull/41561), [[@jamiehannaford](https://github.com/jamiehannaford)](https://github.com/jamiehannaford)) + +* Adds support for allocation of pod IPs via IP aliases. ([[#42147](https://github.com/kubernetes/kubernetes/pull/42147)](https://github.com/kubernetes/kubernetes/pull/42147), [[@bowei](https://github.com/bowei)](https://github.com/bowei)) + +* validateClusterInfo: use clientcmdapi.NewCluster() ([[#44221](https://github.com/kubernetes/kubernetes/pull/44221)](https://github.com/kubernetes/kubernetes/pull/44221), [[@ncdc](https://github.com/ncdc)](https://github.com/ncdc)) + +* Fix corner-case with OnlyLocal Service healthchecks. ([[#44313](https://github.com/kubernetes/kubernetes/pull/44313)](https://github.com/kubernetes/kubernetes/pull/44313), [[@thockin](https://github.com/thockin)](https://github.com/thockin)) + +* Adds annotations to all Federation objects created by kubefed. ([[#42683](https://github.com/kubernetes/kubernetes/pull/42683)](https://github.com/kubernetes/kubernetes/pull/42683), [[@perotinus](https://github.com/perotinus)](https://github.com/perotinus)) + +* [Federation][Kubefed] Bug fix to enable disabling federation controllers through override args ([[#44209](https://github.com/kubernetes/kubernetes/pull/44209)](https://github.com/kubernetes/kubernetes/pull/44209), [[@irfanurrehman](https://github.com/irfanurrehman)](https://github.com/irfanurrehman)) + +* [Federation] Remove deprecated federation-apiserver-kubeconfig secret ([[#44287](https://github.com/kubernetes/kubernetes/pull/44287)](https://github.com/kubernetes/kubernetes/pull/44287), [[@shashidharatd](https://github.com/shashidharatd)](https://github.com/shashidharatd)) + +* Scheduler can recieve its policy configuration from a ConfigMap ([[#43892](https://github.com/kubernetes/kubernetes/pull/43892)](https://github.com/kubernetes/kubernetes/pull/43892), [[@bsalamat](https://github.com/bsalamat)](https://github.com/bsalamat)) + +* AWS cloud provider: fix support running the master with a different AWS account or even on a different cloud provider than the nodes. ([[#44235](https://github.com/kubernetes/kubernetes/pull/44235)](https://github.com/kubernetes/kubernetes/pull/44235), [[@mrIncompetent](https://github.com/mrIncompetent)](https://github.com/mrIncompetent)) + +* add rancher credential provider ([[#40160](https://github.com/kubernetes/kubernetes/pull/40160)](https://github.com/kubernetes/kubernetes/pull/40160), [[@wlan0](https://github.com/wlan0)](https://github.com/wlan0)) + +* Support generating Open API extensions for strategic merge patch tags in go struct tags ([[#44121](https://github.com/kubernetes/kubernetes/pull/44121)](https://github.com/kubernetes/kubernetes/pull/44121), [[@mbohlool](https://github.com/mbohlool)](https://github.com/mbohlool)) + +* Aggregated used ports at the NodeInfo level for PodFitsHostPorts predicate. ([[#42524](https://github.com/kubernetes/kubernetes/pull/42524)](https://github.com/kubernetes/kubernetes/pull/42524), [[@k82cn](https://github.com/k82cn)](https://github.com/k82cn)) + +* Catch error when failed to make directory in NFS volume plugin ([[#38801](https://github.com/kubernetes/kubernetes/pull/38801)](https://github.com/kubernetes/kubernetes/pull/38801), [[@nak3](https://github.com/nak3)](https://github.com/nak3)) + +* Support iSCSI CHAP authentication ([[#43396](https://github.com/kubernetes/kubernetes/pull/43396)](https://github.com/kubernetes/kubernetes/pull/43396), [[@rootfs](https://github.com/rootfs)](https://github.com/rootfs)) + +* Support context completion for `kubectl config use-context` ([[#42336](https://github.com/kubernetes/kubernetes/pull/42336)](https://github.com/kubernetes/kubernetes/pull/42336), [[@superbrothers](https://github.com/superbrothers)](https://github.com/superbrothers)) + +* print warning when delete current context ([[#42538](https://github.com/kubernetes/kubernetes/pull/42538)](https://github.com/kubernetes/kubernetes/pull/42538), [[@adohe](https://github.com/adohe)](https://github.com/adohe)) + +* Add node e2e tests for hostPid ([[#44119](https://github.com/kubernetes/kubernetes/pull/44119)](https://github.com/kubernetes/kubernetes/pull/44119), [[@feiskyer](https://github.com/feiskyer)](https://github.com/feiskyer)) + +* kubelet: make dockershim.sock configurable ([[#43914](https://github.com/kubernetes/kubernetes/pull/43914)](https://github.com/kubernetes/kubernetes/pull/43914), [[@ncdc](https://github.com/ncdc)](https://github.com/ncdc)) + +* Fix [broken service accounts when using dedicated service account key](https://github.com/kubernetes/kubernetes/issues/44285). ([[#44169](https://github.com/kubernetes/kubernetes/pull/44169)](https://github.com/kubernetes/kubernetes/pull/44169), [[@mikedanese](https://github.com/mikedanese)](https://github.com/mikedanese)) + +* Fix incorrect conflict errors applying strategic merge patches to resources. ([[#43871](https://github.com/kubernetes/kubernetes/pull/43871)](https://github.com/kubernetes/kubernetes/pull/43871), [[@liggitt](https://github.com/liggitt)](https://github.com/liggitt)) + +* Fix [transition between NotReady and Unreachable taints](https://github.com/kubernetes/kubernetes/issues/43444). ([[#44042](https://github.com/kubernetes/kubernetes/pull/44042)](https://github.com/kubernetes/kubernetes/pull/44042), [[@gmarek](https://github.com/gmarek)](https://github.com/gmarek)) + +* leader election lock based on scheduler name ([[#42961](https://github.com/kubernetes/kubernetes/pull/42961)](https://github.com/kubernetes/kubernetes/pull/42961), [[@wanghaoran1988](https://github.com/wanghaoran1988)](https://github.com/wanghaoran1988)) + +* [Federation] Remove FEDERATIONS_DOMAIN_MAP references ([[#43137](https://github.com/kubernetes/kubernetes/pull/43137)](https://github.com/kubernetes/kubernetes/pull/43137), [[@shashidharatd](https://github.com/shashidharatd)](https://github.com/shashidharatd)) + +* Fix for [federation failing to propagate cascading deletion](https://github.com/kubernetes/kubernetes/issues/44304). ([[#44108](https://github.com/kubernetes/kubernetes/pull/44108)](https://github.com/kubernetes/kubernetes/pull/44108), [[@csbell](https://github.com/csbell)](https://github.com/csbell)) + +* Fix bug with service nodeports that have no backends not being rejected, when they should be. This is not a regression vs v1.5 - it's a fix that didn't quite fix hard enough. ([[#43972](https://github.com/kubernetes/kubernetes/pull/43972)](https://github.com/kubernetes/kubernetes/pull/43972), [[@thockin](https://github.com/thockin)](https://github.com/thockin)) + +* Fix for [failure to delete federation controllers with finalizers](https://github.com/kubernetes/kubernetes/issues/43828). ([[#44084](https://github.com/kubernetes/kubernetes/pull/44084)](https://github.com/kubernetes/kubernetes/pull/44084), [[@nikhiljindal](https://github.com/nikhiljindal)](https://github.com/nikhiljindal)) + +* Fix container hostPid settings. ([[#44097](https://github.com/kubernetes/kubernetes/pull/44097)](https://github.com/kubernetes/kubernetes/pull/44097), [[@feiskyer](https://github.com/feiskyer)](https://github.com/feiskyer)) + +* Fixed an issue mounting the wrong secret into pods as a service account token. ([[#44102](https://github.com/kubernetes/kubernetes/pull/44102)](https://github.com/kubernetes/kubernetes/pull/44102), [[@ncdc](https://github.com/ncdc)](https://github.com/ncdc)) + +* Juju: Enable GPU mode if GPU hardware detected ([[#43467](https://github.com/kubernetes/kubernetes/pull/43467)](https://github.com/kubernetes/kubernetes/pull/43467), [[@tvansteenburgh](https://github.com/tvansteenburgh)](https://github.com/tvansteenburgh)) + +* get-kube-local.sh checks pods with option `--namespace=kube-system` ([[#42518](https://github.com/kubernetes/kubernetes/pull/42518)](https://github.com/kubernetes/kubernetes/pull/42518), [[@mtanino](https://github.com/mtanino)](https://github.com/mtanino)) + +* Using http2 in kubeapi-load-balancer to fix `kubectl exec` uses ([[#43625](https://github.com/kubernetes/kubernetes/pull/43625)](https://github.com/kubernetes/kubernetes/pull/43625), [[@mbruzek](https://github.com/mbruzek)](https://github.com/mbruzek)) + +* AWS cloud provider: allow to set KubernetesClusterID or KubernetesClusterTag in combination with VPC. ([[#42512](https://github.com/kubernetes/kubernetes/pull/42512)](https://github.com/kubernetes/kubernetes/pull/42512), [[@scheeles](https://github.com/scheeles)](https://github.com/scheeles)) + +* changed kubelet default image-gc-high-threshold to 85% to resolve a conflict with default settings in docker that prevented image garbage collection from resolving low disk space situations when using devicemapper storage. ([[#40432](https://github.com/kubernetes/kubernetes/pull/40432)](https://github.com/kubernetes/kubernetes/pull/40432), [[@sjenning](https://github.com/sjenning)](https://github.com/sjenning)) + +* When creating a container using envFrom, ([[#42083](https://github.com/kubernetes/kubernetes/pull/42083)](https://github.com/kubernetes/kubernetes/pull/42083), [[@fraenkel](https://github.com/fraenkel)](https://github.com/fraenkel)) + + * validate the name of the ConfigMap in a ConfigMapRef + + * validate the name of the Secret in a SecretRef + +* RBAC role and rolebinding auto-reconciliation is now performed only when the RBAC authorization mode is enabled. ([[#43813](https://github.com/kubernetes/kubernetes/pull/43813)](https://github.com/kubernetes/kubernetes/pull/43813), [[@liggitt](https://github.com/liggitt)](https://github.com/liggitt)) + +* Permission to use a PodSecurityPolicy can now be granted within a single namespace by allowing the use verb on the podsecuritypolicies resource within the namespace. ([[#42360](https://github.com/kubernetes/kubernetes/pull/42360)](https://github.com/kubernetes/kubernetes/pull/42360), [[@liggitt](https://github.com/liggitt)](https://github.com/liggitt)) + +* Enable audit log in local cluster ([[#42379](https://github.com/kubernetes/kubernetes/pull/42379)](https://github.com/kubernetes/kubernetes/pull/42379), [[@xilabao](https://github.com/xilabao)](https://github.com/xilabao)) + +* ActiveDeadlineSeconds is validated in workload controllers now, make sure it's not set anywhere (it shouldn't be set by default and having it set means your controller will restart the Pods at some point) ([[#38741](https://github.com/kubernetes/kubernetes/pull/38741)](https://github.com/kubernetes/kubernetes/pull/38741), [[@sandflee](https://github.com/sandflee)](https://github.com/sandflee)) + +* Azure: all clients poll duration is now 5 seconds ([[#43699](https://github.com/kubernetes/kubernetes/pull/43699)](https://github.com/kubernetes/kubernetes/pull/43699), [[@colemickens](https://github.com/colemickens)](https://github.com/colemickens)) + +* Address issue [[#39427](https://github.com/kubernetes/kubernetes/pull/39427)](https://github.com/kubernetes/kubernetes/pull/39427) by adding `--output` flag to `kubectl version` ([[#39858](https://github.com/kubernetes/kubernetes/pull/39858)](https://github.com/kubernetes/kubernetes/pull/39858), [[@alejandroEsc](https://github.com/alejandroEsc)](https://github.com/alejandroEsc)) + +* Support secure etcd cluster for centos provider. ([[#42994](https://github.com/kubernetes/kubernetes/pull/42994)](https://github.com/kubernetes/kubernetes/pull/42994), [[@Shawyeok](https://github.com/Shawyeok)](https://github.com/Shawyeok)) + +* Use Cluster Autoscaler 0.5.1, which fixes an issue in Cluster Autoscaler 0.5 where the cluster may be scaled up unnecessarily. Also the status of Cluster Autoscaler is now exposed in kube-system/cluster-autoscaler-status config map. ([[#43745](https://github.com/kubernetes/kubernetes/pull/43745)](https://github.com/kubernetes/kubernetes/pull/43745), [[@mwielgus](https://github.com/mwielgus)](https://github.com/mwielgus)) + +* Use ProviderID to address nodes in the cloudprovider ([[#42604](https://github.com/kubernetes/kubernetes/pull/42604)](https://github.com/kubernetes/kubernetes/pull/42604), [[@wlan0](https://github.com/wlan0)](https://github.com/wlan0)) + +* Openstack cinder v1/v2/auto API support ([[#40423](https://github.com/kubernetes/kubernetes/pull/40423)](https://github.com/kubernetes/kubernetes/pull/40423), [[@mkutsevol](https://github.com/mkutsevol)](https://github.com/mkutsevol)) + +* API resource discovery now includes the singularName used to refer to the resource. ([[#43312](https://github.com/kubernetes/kubernetes/pull/43312)](https://github.com/kubernetes/kubernetes/pull/43312), [[@deads2k](https://github.com/deads2k)](https://github.com/deads2k)) + +* Add the ability to lock on ConfigMaps to support HA for self hosted components ([[#42666](https://github.com/kubernetes/kubernetes/pull/42666)](https://github.com/kubernetes/kubernetes/pull/42666), [[@timothysc](https://github.com/timothysc)](https://github.com/timothysc)) + +* OpenStack clusters can now specify whether worker nodes are assigned a floating IP ([[#42638](https://github.com/kubernetes/kubernetes/pull/42638)](https://github.com/kubernetes/kubernetes/pull/42638), [[@jamiehannaford](https://github.com/jamiehannaford)](https://github.com/jamiehannaford)) + +* Add Host field to TCPSocketAction ([[#42902](https://github.com/kubernetes/kubernetes/pull/42902)](https://github.com/kubernetes/kubernetes/pull/42902), [[@louyihua](https://github.com/louyihua)](https://github.com/louyihua)) + +* Be able to specify the timeout to wait for pod for `kubectl logs` and `kubectl attach` ([[#41813](https://github.com/kubernetes/kubernetes/pull/41813)](https://github.com/kubernetes/kubernetes/pull/41813), [[@shiywang](https://github.com/shiywang)](https://github.com/shiywang)) + +* Add support for bring-your-own ip address for Services on Azure ([[#42034](https://github.com/kubernetes/kubernetes/pull/42034)](https://github.com/kubernetes/kubernetes/pull/42034), [[@brendandburns](https://github.com/brendandburns)](https://github.com/brendandburns)) + + * create configmap has a new option `--from-env-file` that populates a configmap from file which follows a key=val format for each line. ([[#38882](https://github.com/kubernetes/kubernetes/pull/38882)](https://github.com/kubernetes/kubernetes/pull/38882), [[@fraenkel](https://github.com/fraenkel)](https://github.com/fraenkel)) + + * create secret has a new option `--from-env-file` that populates a configmap from file which follows a key=val format for each line. + +* Update the signing key for percona debian and ubuntu packages ([[#41186](https://github.com/kubernetes/kubernetes/pull/41186)](https://github.com/kubernetes/kubernetes/pull/41186), [[@dixudx](https://github.com/dixudx)](https://github.com/dixudx)) + +* fc: Drop multipath.conf snippet ([[#36698](https://github.com/kubernetes/kubernetes/pull/36698)](https://github.com/kubernetes/kubernetes/pull/36698), [[@fabiand](https://github.com/fabiand)](https://github.com/fabiand)) +## Changelog since v1.7.0-rc.1 + + +### Previous Releases Included in v1.7.0 +- [v1.7.0-rc.1](https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG.md#v170-rc1) +- [v1.7.0-beta.2](https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG.md#v170-beta2) +- [v1.7.0-beta.1](https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG.md#v170-beta1) +- [v1.7.0-alpha.4](https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG.md#v170-alpha4) +- [v1.7.0-alpha.3](https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG.md#v170-alpha3) +- [v1.7.0-alpha.2](https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG.md#v170-alpha2) +- [v1.7.0-alpha.1](https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG.md#v170-alpha1) + + + # v1.7.0-rc.1 [Documentation](https://docs.k8s.io) & [Examples](https://releases.k8s.io/release-1.7/examples) From 0641386318ffbfe3819180e5896b8f8b64003021 Mon Sep 17 00:00:00 2001 From: Chao Xu Date: Fri, 30 Jun 2017 06:15:44 +0200 Subject: [PATCH 140/448] pull the release notes from k8s.io/features/release-1.7/release-notes-draft.md --- CHANGELOG.md | 2099 ++++++++++++++++++++++---------------------------- 1 file changed, 934 insertions(+), 1165 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a0fb529f799..3671e249170 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,13 +6,84 @@ - [Node Binaries](#node-binaries) - [**Major Themes**](#major-themes) - [**Action Required Before Upgrading**](#action-required-before-upgrading) + - [Network](#network) + - [Storage](#storage) + - [API Machinery](#api-machinery) + - [Controller Manager](#controller-manager) + - [kubectl (CLI)](#kubectl-cli) + - [kubeadm](#kubeadm) + - [Cloud Providers](#cloud-providers) - [**Known Issues**](#known-issues) - [**Deprecations**](#deprecations) - - [**Features**](#features) - - [**External Dependency Version Information**](#external-dependency-version-information) + - [Cluster provisioning scripts](#cluster-provisioning-scripts) + - [Client libraries](#client-libraries) + - [DaemonSet](#daemonset) + - [kube-proxy](#kube-proxy) + - [Namespace](#namespace) + - [Scheduling](#scheduling) + - [**Notable Features**](#notable-features) + - [Kubefed](#kubefed) + - [**Kubernetes API**](#kubernetes-api) + - [User Provided Extensions](#user-provided-extensions) + - [**Application Deployment**](#application-deployment) + - [StatefulSet](#statefulset) + - [DaemonSet](#daemonset-1) + - [Deployments](#deployments) + - [PodDisruptionBudget](#poddisruptionbudget) + - [**Security**](#security) + - [Admission Control](#admission-control) + - [TLS Bootstrapping](#tls-bootstrapping) + - [Audit Logging](#audit-logging) + - [Encryption at Rest](#encryption-at-rest) + - [Node Authorization](#node-authorization) + - [**Application Autoscaling**](#application-autoscaling) + - [Horizontal Pod Autoscaler](#horizontal-pod-autoscaler) + - [**Cluster Lifecycle**](#cluster-lifecycle) + - [kubeadm](#kubeadm-1) + - [Cloud Provider Support](#cloud-provider-support) + - [**Cluster Federation**](#cluster-federation) + - [Placement Policy](#placement-policy) + - [Cluster Selection](#cluster-selection) + - [**Instrumentation**](#instrumentation) + - [Core Metrics API](#core-metrics-api) + - [**Internationalization**](#internationalization) + - [**kubectl (CLI)**](#kubectl-cli-1) + - [**Networking**](#networking) + - [Network Policy](#network-policy) + - [Load Balancing](#load-balancing) + - [**Node Components**](#node-components) + - [Container Runtime Interface](#container-runtime-interface) + - [**Scheduling**](#scheduling-1) + - [Scheduler Extender](#scheduler-extender) + - [**Storage**](#storage-1) + - [Local Storage](#local-storage) + - [Volume Plugins](#volume-plugins) + - [Metrics](#metrics) - [**Other notable changes**](#other-notable-changes) -- [Unsorted](#unsorted) - - [Changelog since v1.7.0-rc.1](#changelog-since-v170-rc1) + - [Admission plugin](#admission-plugin) + - [API Machinery](#api-machinery-1) + - [Application autoscaling](#application-autoscaling-1) + - [Application Deployment](#application-deployment-1) + - [Cluster Autoscaling](#cluster-autoscaling) + - [Cloud Provider Enhancement](#cloud-provider-enhancement) + - [Cluster Provisioning](#cluster-provisioning) + - [Cluster federation](#cluster-federation-1) + - [Credential provider](#credential-provider) + - [Information for Kubernetes clients (openapi, swagger, client-go)](#information-for-kubernetes-clients-openapi-swagger-client-go) + - [Instrumentation](#instrumentation-1) + - [Internal storage layer](#internal-storage-layer) + - [Kubernetes Dashboard](#kubernetes-dashboard) + - [kube-dns](#kube-dns) + - [kube-proxy](#kube-proxy-1) + - [kube-scheduler](#kube-scheduler) + - [Storage](#storage-2) + - [Networking](#networking-1) + - [Node controller](#node-controller) + - [Node Components](#node-components-1) + - [Scheduling](#scheduling-2) + - [Security](#security-1) + - [Scalability](#scalability) + - [**External Dependency Version Information**](#external-dependency-version-information) - [Previous Releases Included in v1.7.0](#previous-releases-included-in-v170) - [v1.7.0-rc.1](#v170-rc1) - [Downloads for v1.7.0-rc.1](#downloads-for-v170-rc1) @@ -144,40 +215,40 @@ - [Cluster Autoscaler](#cluster-autoscaler) - [Deployment](#deployment) - [Federation](#federation) - - [Internal Storage Layer](#internal-storage-layer) - - [Node Components](#node-components) + - [Internal Storage Layer](#internal-storage-layer-1) + - [Node Components](#node-components-2) - [kubectl](#kubectl) - [RBAC](#rbac) - - [Scheduling](#scheduling) + - [Scheduling](#scheduling-3) - [Service](#service) - - [StatefulSet](#statefulset) + - [StatefulSet](#statefulset-1) - [Volumes](#volumes) - - [Notable Features](#notable-features) + - [Notable Features](#notable-features-1) - [Autoscaling](#autoscaling) - - [DaemonSet](#daemonset) + - [DaemonSet](#daemonset-2) - [Deployment](#deployment-1) - [Federation](#federation-1) - - [Internal Storage Layer](#internal-storage-layer-1) - - [kubeadm](#kubeadm) - - [Node Components](#node-components-1) + - [Internal Storage Layer](#internal-storage-layer-2) + - [kubeadm](#kubeadm-2) + - [Node Components](#node-components-3) - [RBAC](#rbac-1) - - [Scheduling](#scheduling-1) + - [Scheduling](#scheduling-4) - [Service Catalog](#service-catalog) - [Volumes](#volumes-1) - [Deprecations](#deprecations-1) - - [Cluster Provisioning Scripts](#cluster-provisioning-scripts) - - [kubeadm](#kubeadm-1) + - [Cluster Provisioning Scripts](#cluster-provisioning-scripts-1) + - [kubeadm](#kubeadm-3) - [Other Deprecations](#other-deprecations) - [Changes to API Resources](#changes-to-api-resources) - [ABAC](#abac) - - [Admission Control](#admission-control) + - [Admission Control](#admission-control-1) - [Authentication](#authentication) - [Authorization](#authorization) - [Autoscaling](#autoscaling-1) - [Certificates](#certificates) - [ConfigMap](#configmap) - [CronJob](#cronjob) - - [DaemonSet](#daemonset-1) + - [DaemonSet](#daemonset-3) - [Deployment](#deployment-2) - [Node](#node) - [Pod](#pod) @@ -186,7 +257,7 @@ - [ReplicaSet](#replicaset) - [Secrets](#secrets) - [Service](#service-1) - - [StatefulSet](#statefulset-1) + - [StatefulSet](#statefulset-2) - [Taints and Tolerations](#taints-and-tolerations) - [Volumes](#volumes-2) - [Changes to Major Components](#changes-to-major-components) @@ -202,10 +273,10 @@ - [GKE](#gke) - [vSphere](#vsphere) - [Federation](#federation-2) - - [kubefed](#kubefed) + - [kubefed](#kubefed-1) - [Other Notable Changes](#other-notable-changes-17) - [Garbage Collector](#garbage-collector) - - [kubeadm](#kubeadm-2) + - [kubeadm](#kubeadm-4) - [kubectl](#kubectl-1) - [New Commands](#new-commands) - [Create subcommands](#create-subcommands) @@ -214,13 +285,13 @@ - [Updates to edit](#updates-to-edit) - [Bug fixes](#bug-fixes) - [Other Notable Changes](#other-notable-changes-18) - - [Node Components](#node-components-2) + - [Node Components](#node-components-4) - [Bug fixes](#bug-fixes-1) - [kube-controller-manager](#kube-controller-manager) - - [kube-dns](#kube-dns) - - [kube-proxy](#kube-proxy) + - [kube-dns](#kube-dns-1) + - [kube-proxy](#kube-proxy-2) - [Scheduler](#scheduler) - - [Volume Plugins](#volume-plugins) + - [Volume Plugins](#volume-plugins-1) - [Azure Disk](#azure-disk) - [GlusterFS](#glusterfs) - [Photon](#photon) @@ -353,7 +424,7 @@ - [Client Binaries](#client-binaries-34) - [Server Binaries](#server-binaries-34) - [Major Themes](#major-themes-1) - - [Features](#features-1) + - [Features](#features) - [Known Issues](#known-issues-1) - [Notable Changes to Existing Behavior](#notable-changes-to-existing-behavior) - [Deprecations](#deprecations-2) @@ -460,10 +531,10 @@ - [v1.4.0](#v140) - [Downloads](#downloads-8) - [Major Themes](#major-themes-2) - - [Features](#features-2) + - [Features](#features-1) - [Known Issues](#known-issues-2) - [Notable Changes to Existing Behavior](#notable-changes-to-existing-behavior-1) - - [Deployments](#deployments) + - [Deployments](#deployments-1) - [kubectl rolling-update: < v1.4.0 client vs >=v1.4.0 cluster](#kubectl-rolling-update:-<-v140-client-vs->=v140-cluster) - [kubectl delete: < v1.4.0 client vs >=v1.4.0 cluster](#kubectl-delete:-<-v140-client-vs->=v140-cluster) - [DELETE operation in REST API](#delete-operation-in-rest-api) @@ -707,10 +778,12 @@ Extensibility features include API aggregation (beta), CustomResourceDefinitions ## **Action Required Before Upgrading** +### Network + * NetworkPolicy has been promoted from extensions/v1beta1 to the new networking.k8s.io/v1 API group. The structure remains unchanged from the v1beta1 API. The net.beta.kubernetes.io/network-policy annotation on Namespaces (used to opt in to isolation) has been removed. Instead, isolation is now determined on a per-pod basis. A NetworkPolicy may target a pod for isolation by including the pod in its spec.podSelector. Targeted Pods accept the traffic specified in the respective NetworkPolicy (and nothing else). Pods not targeted by any NetworkPolicy accept all traffic by default. ([[#39164](https://github.com/kubernetes/kubernetes/pull/39164)](https://github.com/kubernetes/kubernetes/pull/39164), [[@danwinship](https://github.com/danwinship)](https://github.com/danwinship)) **Action Required:** When upgrading to Kubernetes 1.7 (and a [network plugin](https://kubernetes.io/docs/tasks/administer-cluster/declare-network-policy/) that supports the new NetworkPolicy v1 semantics), you should consider the following. - + The v1beta1 API used an annotation on Namespaces to activate the DefaultDeny policy for an entire Namespace. To activate default deny in the v1 API, you can create a NetworkPolicy that matches all Pods but does not allow any traffic: ```yaml @@ -722,31 +795,26 @@ Extensibility features include API aggregation (beta), CustomResourceDefinitions podSelector: ``` - This will ensure that Pods that aren't matched by any other NetworkPolicy will continue to be fully-isolated, as they were in v1beta1. - + This will ensure that Pods that aren't matched by any other NetworkPolicy will continue to be fully-isolated, as they were in v1beta1. + In Namespaces that previously did not have the "DefaultDeny" annotation, you should delete any existing NetworkPolicy objects. These had no effect in the v1beta1 API, but with v1 semantics they might cause some traffic to be unintentionally blocked. -* `cluster/update-storage-objects.sh` now supports updating StorageClasses in etcd to storage.k8s.io/v1. You must do this prior to upgrading to 1.8. ([[#46116](https://github.com/kubernetes/kubernetes/pull/46116)](https://github.com/kubernetes/kubernetes/pull/46116), [[@ncdc](https://github.com/ncdc)](https://github.com/ncdc)) -* PodSpecs containing parent directory references such as `..` (for example, `../bar`) in hostPath volume path or in volumeMount subpaths must be changed to the simple absolute path. Backsteps `..` are no longer allowed.([[#47290](https://github.com/kubernetes/kubernetes/pull/47290)](https://github.com/kubernetes/kubernetes/pull/47290), [[@jhorwit2](https://github.com/jhorwit2)](https://github.com/jhorwit2)). +### Storage -* Azure: Container permissions for provisioned volumes have changed to private. If you have existing Azure volumes that were created by Kubernetes v1.6.0-v1.6.5, you should change the permissions on them manually. ([[#47605](https://github.com/kubernetes/kubernetes/pull/47605)](https://github.com/kubernetes/kubernetes/pull/47605), [[@brendandburns](https://github.com/brendandburns)](https://github.com/brendandburns)) +* Alpha volume provisioning is removed and default storage class should be used instead. ([[#44090](https://github.com/kubernetes/kubernetes/pull/44090)](https://github.com/kubernetes/kubernetes/pull/44090), [[@NickrenREN](https://github.com/NickrenREN)](https://github.com/NickrenREN)) -* GKE/GCE: New and upgraded 1.7 GCE/GKE clusters no longer have an RBAC ClusterRoleBinding that grants the cluster-admin ClusterRole to the default service account in the kube-system Namespace. ([[#46750](https://github.com/kubernetes/kubernetes/pull/46750)](https://github.com/kubernetes/kubernetes/pull/46750), [[@cjcullen](https://github.com/cjcullen)](https://github.com/cjcullen)). If this permission is still desired, run the following command to explicitly grant it, either before or after upgrading to 1.7: - ``` - kubectl create clusterrolebinding kube-system-default --serviceaccount=kube-system:default --clusterrole=cluster-admin - ``` +* Portworx volume driver no longer has to run on the master. ([[#45518](https://github.com/kubernetes/kubernetes/pull/45518)](https://github.com/kubernetes/kubernetes/pull/45518), [[@harsh-px](https://github.com/harsh-px)](https://github.com/harsh-px)) -* kube-controller-manager has dropped support for the `--insecure-experimental-approve-all-kubelet-csrs-for-group` flag. It is accepted in 1.7, but ignored. Instead, the csrapproving controller uses authorization checks to determine whether to approve certificate signing requests: ([[#45619](https://github.com/kubernetes/kubernetes/pull/45619)](https://github.com/kubernetes/kubernetes/pull/45619), [[@mikedanese](https://github.com/mikedanese)](https://github.com/mikedanese)) +* Default behavior in Cinder storageclass is changed. If availability is not specified, the zone is chosen by algorithm. It makes possible to spread stateful pods across many zones. ([[#44798](https://github.com/kubernetes/kubernetes/pull/44798)](https://github.com/kubernetes/kubernetes/pull/44798), [[@zetaab](https://github.com/zetaab)](https://github.com/zetaab)) - * Before upgrading, users must ensure their controller manager will enable the csrapproving controller, create an RBAC ClusterRole and ClusterRoleBinding to approve CSRs for the same group, then upgrade. Example roles to enable the equivalent behavior can be found in the TLS bootstrapping documentation ([https://github.com/kubernetes/kubernetes.github.io/pull/4208](https://github.com/kubernetes/kubernetes.github.io/pull/4208)). +* PodSpecs containing parent directory references such as `..` (for example, `../bar`) in hostPath volume path or in volumeMount subpaths must be changed to the simple absolute path. Backsteps `..` are no longer allowed.([[#47290](https://github.com/kubernetes/kubernetes/pull/47290)](https://github.com/kubernetes/kubernetes/pull/47290), [[@jhorwit2](https://github.com/jhorwit2)](https://github.com/jhorwit2)). + + +### API Machinery * The Namespace API object no longer supports the deletecollection operation. ([[#46407](https://github.com/kubernetes/kubernetes/pull/46407)](https://github.com/kubernetes/kubernetes/pull/46407), [[@liggitt](https://github.com/liggitt)](https://github.com/liggitt)) -* `kubectl create role` and `kubectl create clusterrole` invocations must be updated to specify multiple resource names as repeated `--resource-name` arguments instead of comma-separated arguments to a single `--resource-name` argument. E.g. `--resource-name=x,y` must become `--resource-name x --resource-name y` ([[#44950](https://github.com/kubernetes/kubernetes/pull/44950)](https://github.com/kubernetes/kubernetes/pull/44950), [[@xilabao](https://github.com/xilabao)](https://github.com/xilabao)) - -* `kubectl create rolebinding` and `kubectl create clusterrolebinding` invocations must be updated to specify multiple subjects as repeated `--user`, `--group`, or `--serviceaccount` arguments instead of comma-separated arguments to a single `--user`, `--group`, or `--serviceaccount`. E.g. `--user=x,y` must become `--user x --user y` ([[#43903](https://github.com/kubernetes/kubernetes/pull/43903)](https://github.com/kubernetes/kubernetes/pull/43903), [[@xilabao](https://github.com/xilabao)](https://github.com/xilabao)) - * The following alpha API groups were unintentionally enabled by default in previous releases, and will no longer be enabled by default in v1.8: ([[#47690](https://github.com/kubernetes/kubernetes/pull/47690)](https://github.com/kubernetes/kubernetes/pull/47690), [[@caesarxuchao](https://github.com/caesarxuchao)](https://github.com/caesarxuchao)) * rbac.authorization.k8s.io/v1alpha1 @@ -755,6 +823,38 @@ Extensibility features include API aggregation (beta), CustomResourceDefinitions * If you wish to continue using them in v1.8, please enable them explicitly using the `--runtime-config` flag on the apiserver (for example, `--runtime-config="rbac.authorization.k8s.io/v1alpha1,settings.k8s.io/v1alpha1"`) +* `cluster/update-storage-objects.sh` now supports updating StorageClasses in etcd to storage.k8s.io/v1. You must do this prior to upgrading to 1.8. ([[#46116](https://github.com/kubernetes/kubernetes/pull/46116)](https://github.com/kubernetes/kubernetes/pull/46116), [[@ncdc](https://github.com/ncdc)](https://github.com/ncdc)) + + +### Controller Manager + +* kube-controller-manager has dropped support for the `--insecure-experimental-approve-all-kubelet-csrs-for-group` flag. It is accepted in 1.7, but ignored. Instead, the csrapproving controller uses authorization checks to determine whether to approve certificate signing requests: ([[#45619](https://github.com/kubernetes/kubernetes/pull/45619)](https://github.com/kubernetes/kubernetes/pull/45619), [[@mikedanese](https://github.com/mikedanese)](https://github.com/mikedanese)) + + * Before upgrading, users must ensure their controller manager will enable the csrapproving controller, create an RBAC ClusterRole and ClusterRoleBinding to approve CSRs for the same group, then upgrade. Example roles to enable the equivalent behavior can be found in the [TLS bootstrapping](https://kubernetes.io/docs/admin/kubelet-tls-bootstrapping/) documentation. + + +### kubectl (CLI) +* `kubectl create role` and `kubectl create clusterrole` invocations must be updated to specify multiple resource names as repeated `--resource-name` arguments instead of comma-separated arguments to a single `--resource-name` argument. E.g. `--resource-name=x,y` must become `--resource-name x --resource-name y` ([[#44950](https://github.com/kubernetes/kubernetes/pull/44950)](https://github.com/kubernetes/kubernetes/pull/44950), [[@xilabao](https://github.com/xilabao)](https://github.com/xilabao)) + +* `kubectl create rolebinding` and `kubectl create clusterrolebinding` invocations must be updated to specify multiple subjects as repeated `--user`, `--group`, or `--serviceaccount` arguments instead of comma-separated arguments to a single `--user`, `--group`, or `--serviceaccount`. E.g. `--user=x,y` must become `--user x --user y` ([[#43903](https://github.com/kubernetes/kubernetes/pull/43903)](https://github.com/kubernetes/kubernetes/pull/43903), [[@xilabao](https://github.com/xilabao)](https://github.com/xilabao)) + + +### kubeadm + +* kubeadm: Modifications to cluster-internal resources installed by kubeadm will be overwritten when upgrading from v1.6 to v1.7. ([[#47081](https://github.com/kubernetes/kubernetes/pull/47081)](https://github.com/kubernetes/kubernetes/pull/47081), [[@luxas](https://github.com/luxas)](https://github.com/luxas)) + +* kubeadm deb/rpm packages: cAdvisor doesn't listen on `0.0.0.0:4194` without authentication/authorization because of the possible information leakage. The cAdvisor API can still be accessed via `https://{node-ip}:10250/stats/`, though. ([kubernetes/release#356](https://github.com/kubernetes/release/pull/356), [[@luxas](https://github.com/luxas)](https://github.com/luxas)) + + +### Cloud Providers + +* Azure: Container permissions for provisioned volumes have changed to private. If you have existing Azure volumes that were created by Kubernetes v1.6.0-v1.6.5, you should change the permissions on them manually. ([[#47605](https://github.com/kubernetes/kubernetes/pull/47605)](https://github.com/kubernetes/kubernetes/pull/47605), [[@brendandburns](https://github.com/brendandburns)](https://github.com/brendandburns)) + +* GKE/GCE: New and upgraded 1.7 GCE/GKE clusters no longer have an RBAC ClusterRoleBinding that grants the cluster-admin ClusterRole to the default service account in the kube-system Namespace. ([[#46750](https://github.com/kubernetes/kubernetes/pull/46750)](https://github.com/kubernetes/kubernetes/pull/46750), [[@cjcullen](https://github.com/cjcullen)](https://github.com/cjcullen)). If this permission is still desired, run the following command to explicitly grant it, either before or after upgrading to 1.7: + ``` + kubectl create clusterrolebinding kube-system-default --serviceaccount=kube-system:default --clusterrole=cluster-admin + ``` + ## **Known Issues** Populated via [v1.7.x known issues / FAQ accumulator](https://github.com/kubernetes/kubernetes/issues/46733) @@ -775,1137 +875,471 @@ JSON API clients should tolerate `null` values for such fields, and treat `null` ## **Deprecations** -* ThirdPartyResource (Alpha) is deprecated. Please migrate to the successor, CustomResourceDefinition (Beta). ([docs PR](https://github.com/kubernetes/kubernetes.github.io/pull/4071)) ([kubernetes/features#95](https://github.com/kubernetes/features/issues/95)) +### Cluster provisioning scripts +* cluster/ubuntu: Removed due to [deprecation](https://github.com/kubernetes/kubernetes/tree/master/cluster#cluster-configuration) and lack of maintenance. ([[#44344](https://github.com/kubernetes/kubernetes/pull/44344)](https://github.com/kubernetes/kubernetes/pull/44344), [[@mikedanese](https://github.com/mikedanese)](https://github.com/mikedanese)) -* Swagger 1.2 spec (/swaggerapi/*) is deprecated. Please use OpenAPI instead. +* cluster/aws: Removed due to [deprecation](https://github.com/kubernetes/kubernetes/pull/38772) and lack of maintenance. ([[#42196](https://github.com/kubernetes/kubernetes/pull/42196)](https://github.com/kubernetes/kubernetes/pull/42196), [[@zmerlynn](https://github.com/zmerlynn)](https://github.com/zmerlynn)) -* The Namespace API object no longer supports the deletecollection operation. ([[#46407](https://github.com/kubernetes/kubernetes/pull/46407)](https://github.com/kubernetes/kubernetes/pull/46407), [[@liggitt](https://github.com/liggitt)](https://github.com/liggitt)) +### Client libraries +* Swagger 1.2 spec (`/swaggerapi/*`) is deprecated. Please use OpenAPI instead. + +### DaemonSet * DaemonSet’s spec.templateGeneration has been deprecated. ([[#45924](https://github.com/kubernetes/kubernetes/pull/45924)](https://github.com/kubernetes/kubernetes/pull/45924), [[@janetkuo](https://github.com/janetkuo)](https://github.com/janetkuo)) +### kube-proxy * In 1.7, the kube-proxy component has been converted to use a configuration file. The old flags still work in 1.7, but they are being deprecated and will be removed in a future release. Cluster administrators are advised to switch to using the configuration file, but no action is strictly necessary in 1.7. ([[#34727](https://github.com/kubernetes/kubernetes/pull/34727)](https://github.com/kubernetes/kubernetes/pull/34727), [[@ncdc](https://github.com/ncdc)](https://github.com/ncdc)) -## **Features** +### Namespace +* The Namespace API object no longer supports the deletecollection operation. ([[#46407](https://github.com/kubernetes/kubernetes/pull/46407)](https://github.com/kubernetes/kubernetes/pull/46407), [[@liggitt](https://github.com/liggitt)](https://github.com/liggitt)) + + +### Scheduling +* If you are using `AffinityInAnnotations=true` in `--feature-gates`, then the 1.7 release is your last opportunity to convert from specifying affinity/anti-affinity using the scheduler.alpha.kubernetes.io/affinity annotation on Pods, to using the Affinity field of PodSpec. Support for the alpha version of node and pod affinity (which uses the scheduler.alpha.kubernetes.io/affinity annotations on Pods) is going away **in Kubernetes 1.8** (not this release, but the next release). If you have not enabled AffinityInAnnotations=true in `--feature-gates`, then this change does not affect you. + +## **Notable Features** Features for this release were tracked via the use of the [kubernetes/features](https://github.com/kubernetes/features) issues repo. Each Feature issue is owned by a Special Interest Group from [kubernetes/community](https://github.com/kubernetes/community) -TODO: replace docs PR links with links to actual docs +## Kubefed -* API Machinery +* Deprecate the `--secret-name` flag from `kubefed join`, instead generating the secret name arbitrarily. ([[#42513](https://github.com/kubernetes/kubernetes/pull/42513)](https://github.com/kubernetes/kubernetes/pull/42513), [[@perotinus](https://github.com/perotinus)](https://github.com/perotinus)) - * [alpha] Add extensible external admission control ([docs PR](https://github.com/kubernetes/kubernetes.github.io/pull/4092)) ([kubernetes/features#209](https://github.com/kubernetes/features/issues/209)) - * [beta] User-provided apiservers can be aggregated (served along with) the rest of the Kubernetes API ([docs PR](https://github.com/kubernetes/kubernetes.github.io/pull/4173)) ([kubernetes/features#263](https://github.com/kubernetes/features/issues/263)) +### **Kubernetes API** +#### User Provided Extensions +* [beta] ThirdPartyResource is deprecated. Please migrate to the successor, CustomResourceDefinition. For more information, see [Custom Resources](https://kubernetes.io/docs/concepts/api-extension/custom-resources/) and [Migrate a ThirdPartyResource to CustomResourceDefinition](https://kubernetes.io/docs/tasks/access-kubernetes-api/migrate-third-party-resource/). - * [beta] ThirdPartyResource is deprecated. Please migrate to the successor, CustomResourceDefinition. ([docs PR](https://github.com/kubernetes/kubernetes.github.io/pull/4071)) ([kubernetes/features#95](https://github.com/kubernetes/features/issues/95)) +* [beta] User-provided apiservers can be aggregated (served along with) the rest of the Kubernetes API. See [Extending the Kubernetes API with the aggregation layer](https://kubernetes.io/docs/concepts/api-extension/apiserver-aggregation/), [Configure the aggregation layer](https://kubernetes.io/docs/tasks/access-kubernetes-api/configure-aggregation-layer/), and [Setup an extension API server](https://kubernetes.io/docs/tasks/access-kubernetes-api/setup-extension-api-server/). -* Apps +* [alpha] Adding admissionregistration API group which enables dynamic registration of initializers and external admission webhooks. ([[#46294](https://github.com/kubernetes/kubernetes/pull/46294)](https://github.com/kubernetes/kubernetes/pull/46294), [[@caesarxuchao](https://github.com/caesarxuchao)](https://github.com/caesarxuchao)) - * [beta] StatefulSet supports RollingUpdate and OnDelete update strategies. ([docs PR](https://github.com/kubernetes/kubernetes.github.io/pull/4174)) ([kubernetes/features#188](https://github.com/kubernetes/features/issues/188)) - * [beta] DaemonSet supports history and rollback. ([docs PR](https://github.com/kubernetes/kubernetes.github.io/pull/4098)) ([kubernetes/features#124](https://github.com/kubernetes/features/issues/124)) +### **Application Deployment** +#### StatefulSet +* [beta] StatefulSet supports [RollingUpdate](https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#rolling-updates) and [OnDelete](https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#on-delete) update strategies. - * [alpha] StatefulSet authors should be able to relax the ordering and parallelism policies for software that can safely support rapid, out-of-order changes. ([docs PR](https://github.com/kubernetes/kubernetes.github.io/pull/4162)) ([kubernetes/features#272](https://github.com/kubernetes/features/issues/272)) +* [alpha] StatefulSet authors should be able to relax the [ordering](https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#orderedready-pod-management) and [parallelism](https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#parallel-pod-management) policies for software that can safely support rapid, out-of-order changes. - * [beta] PodDisruptionBudget has a new field MaxUnavailable, which allows users to specify the maximum number of disruptions that can be tolerated during eviction. ([docs PR](https://github.com/kubernetes/kubernetes.github.io/pull/4140)) ([kubernetes/features#285](https://github.com/kubernetes/features/issues/285)) +#### DaemonSet +* [beta] DaemonSet supports history and rollback. See [Performing a Rollback on a DaemonSet](https://kubernetes.io/docs/tasks/manage-daemon/rollback-daemon-set/). - * [beta] Deployments uses a hashing collision avoidance mechanism that ensures new rollouts will not block on hashing collisions anymore. ([kubernetes/features#287](https://github.com/kubernetes/features/issues/287)) +#### Deployments +* [beta] Deployments uses a hashing collision avoidance mechanism that ensures new rollouts will not block on hashing collisions anymore. ([kubernetes/features#287](https://github.com/kubernetes/features/issues/287)) -* Auth +#### PodDisruptionBudget +* [beta] PodDisruptionBudget has a new field MaxUnavailable, which allows users to specify the maximum number of disruptions that can be tolerated during eviction. For more information, see [Pod Disruptions](https://kubernetes.io/docs/concepts/workloads/pods/disruptions/) and [Specifying a Disruption Budget for your Application](https://kubernetes.io/docs/tasks/run-application/configure-pdb/). - * [alpha] Rotation of the server TLS certificate on the kubelet ([docs PR](https://github.com/kubernetes/kubernetes.github.io/pull/4208)) ([kubernetes/features#267](https://github.com/kubernetes/features/issues/267)) - * [alpha] Rotation of the client TLS certificate on the kubelet ([docs PR](https://github.com/kubernetes/kubernetes.github.io/pull/4208)) ([kubernetes/features#266](https://github.com/kubernetes/features/issues/266)) +### **Security** +#### Admission Control +* [alpha] Add [extensible external admission control](https://kubernetes.io/docs/admin/extensible-admission-controllers/). - * [alpha] Encrypt secrets stored in etcd ([docs PR](https://github.com/kubernetes/kubernetes.github.io/pull/4181)) ([kubernetes/features#92](https://github.com/kubernetes/features/issues/92)) +#### TLS Bootstrapping +* [alpha] Rotation of the server TLS certificate on the kubelet. See [TLS bootstrapping - approval controller](https://kubernetes.io/docs/admin/kubelet-tls-bootstrapping/#approval-controller). - * [beta] A new Node authorization mode and NodeRestriction admission plugin, when used in combination, limit nodes' access to specific APIs, so that they may only modify their own Node API object, only modify Pod objects bound to themselves, and only retrieve secrets and configmaps referenced by pods bound to themselves ([docs PR](https://github.com/kubernetes/kubernetes.github.io/pull/4077)) ([kubernetes/features#279](https://github.com/kubernetes/features/issues/279)) +* [alpha] Rotation of the client TLS certificate on the kubelet. See [TLS bootstrapping - kubelet configuration](https://kubernetes.io/docs/admin/kubelet-tls-bootstrapping/#kubelet-configuration). - * [alpha] Advanced Auditing enhances the Kubernetes API audit logging capabilities through a customizable policy, pluggable audit backends, and richer audit data ([docs PR](https://github.com/kubernetes/kubernetes.github.io/pull/4101)) ([kubernetes/features#22](https://github.com/kubernetes/features/issues/22)) +* [beta] [Kubelet TLS Bootstrap](https://kubernetes.io/docs/admin/kubelet-tls-bootstrapping/#kubelet-configuration) -* Autoscaling +#### Audit Logging +* [alpha] Advanced Auditing enhances the Kubernetes API [audit logging](https://kubernetes.io/docs/tasks/debug-application-cluster/audit/#audit-logs) capabilities through a customizable policy, pluggable audit backends, and richer audit data. - * [alpha] HPA Status Conditions ([docs PR](https://github.com/kubernetes/kubernetes.github.io/pull/4118)) ([kubernetes/features#264](https://github.com/kubernetes/features/issues/264)) +#### Encryption at Rest +* [alpha] Encrypt secrets stored in etcd. For more information, see [Securing a Cluster](https://kubernetes.io/docs/tasks/administer-cluster/securing-a-cluster/) and [Encrypting data at rest](https://kubernetes.io/docs/tasks/administer-cluster/encrypt-data/). -* Cluster Lifecycle +#### Node Authorization +* [beta] A new Node authorization mode and NodeRestriction admission plugin, when used in combination, limit nodes' access to specific APIs, so that they may only modify their own Node API object, only modify Pod objects bound to themselves, and only retrieve secrets and configmaps referenced by pods bound to themselves. See [Using Node Authorization](https://kubernetes.io/docs/admin/authorization/node/) for more information. - * [alpha] Improved support for out-of-tree and out-of-process cloud providers, a.k.a pluggable cloud providers ([docs](https://kubernetes.io/docs/tasks/administer-cluster/running-cloud-controller)) ([kubernetes/features#88](https://github.com/kubernetes/features/issues/88)) - * [alpha] Manual upgrades for kubeadm from v1.6 to v1.7. Automated upgrades ([kubernetes/features#296](https://github.com/kubernetes/features/issues/296)) are targeted for v1.8. ([docs PR](https://github.com/kubernetes/kubernetes.github.io/pull/3999)) (part of [kubernetes/features#11](https://github.com/kubernetes/features/issues/11)) +### **Application Autoscaling** +#### Horizontal Pod Autoscaler +* [alpha] [HPA Status Conditions](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough/#appendix-horizontal-pod-autoscaler-status-conditions). -* Federation - * [alpha] The federation-apiserver now supports a SchedulingPolicy admission controller that enables policy-based control over placement of federated resources ([docs PR](https://github.com/kubernetes/kubernetes.github.io/pull/4075)) ([kubernetes/features#250](https://github.com/kubernetes/features/issues/250)) +### **Cluster Lifecycle** +#### kubeadm +* [alpha] Manual [upgrades for kubeadm from v1.6 to v1.7](https://kubernetes.io/docs/tasks/administer-cluster/kubeadm-upgrade-1-7/). Automated upgrades ([kubernetes/features#296](https://github.com/kubernetes/features/issues/296)) are targeted for v1.8. - * [alpha] Federation ClusterSelector annotation to direct objects to federated clusters with matching labels ([docs PR](https://github.com/kubernetes/kubernetes.github.io/pull/4214)) ([kubernetes/features#74](https://github.com/kubernetes/features/issues/74)) +#### Cloud Provider Support +* [alpha] Improved support for out-of-tree and out-of-process cloud providers, a.k.a pluggable cloud providers. See [Build and Run cloud-controller-manager](https://kubernetes.io/docs/tasks/administer-cluster/running-cloud-controller) documentation. -* Instrumentation - * [alpha] Introduces a lightweight monitoring component for serving the core resource metrics API used by the Horizontal Pod Autoscaler and other components ([kubernetes/features#271](https://github.com/kubernetes/features/issues/271)) +### **Cluster Federation** +#### Placement Policy +* [alpha] The federation-apiserver now supports a SchedulingPolicy admission controller that enables policy-based control over placement of federated resources. For more information, see [Set up placement policies in Federation](https://kubernetes.io/docs/tasks/federation/set-up-placement-policies-federation/). -* Network +#### Cluster Selection +* [alpha] Federation [ClusterSelector annotation](https://kubernetes.io/docs/tasks/administer-federation/cluster/#clusterselector-annotation) to direct objects to federated clusters with matching labels. - * [stable] NetworkPolicy promoted to GA ([docs PR](https://github.com/kubernetes/kubernetes.github.io/pull/4003)([kubernetes/features#185](https://github.com/kubernetes/features/issues/185)) - * [stable] Source IP Preservation - change Cloud load-balancer strategy to health-checks and respond to health check only on nodes that host pods for the service ([docs PR](https://github.com/kubernetes/kubernetes.github.io/pull/4093)) ([kubernetes/features#27](https://github.com/kubernetes/features/issues/27)) +### **Instrumentation** +#### Core Metrics API +* [alpha] Introduces a lightweight monitoring component for serving the core resource metrics API used by the Horizontal Pod Autoscaler and other components ([kubernetes/features#271](https://github.com/kubernetes/features/issues/271)) -* Node - * [alpha] CRI validation testing, which provides a test framework and a suite of tests to validate that the CRI server implementation meets all the requirements. This allows the CRI runtime developers to verify that their runtime conforms to CRI, without needing to set up Kubernetes components or run Kubernetes end-to-end tests. ([docs](https://github.com/kubernetes/community/blob/master/contributors/devel/cri-validation.md) and [release notes](https://github.com/kubernetes-incubator/cri-tools/releases/tag/v0.1)) ([kubernetes/features#292](https://github.com/kubernetes/features/issues/292)) - - * [alpha] Adds support of container metrics in CRI ([docs PR](https://github.com/kubernetes/community/pull/742)) ([kubernetes/features#290](https://github.com/kubernetes/features/issues/290)) - - * [alpha] Integration with containerd 1.0, which supports basic pod lifecycle and image management. ([docs](https://github.com/kubernetes-incubator/cri-containerd/blob/master/README.md) and [release notes](https://github.com/kubernetes-incubator/cri-containerd/releases/tag/v0.1.0)) ([kubernetes/features#286](https://github.com/kubernetes/features/issues/286)) - -* Scheduling - - * [alpha] Support for delegating pod binding to a scheduler extender ([kubernetes/features#270](https://github.com/kubernetes/features/issues/270)) - -* Storage - - * [alpha] This feature adds capacity isolation support for local storage at node, container, and volume levels ([docs PR](https://github.com/kubernetes/kubernetes.github.io/pull/4145)) ([kubernetes/features#245](https://github.com/kubernetes/features/issues/245)) - - * [alpha] Make locally attached (non-network attached) storage available as a persistent volume source. ([docs PR](https://github.com/kubernetes/kubernetes.github.io/pull/4050)) ([kubernetes/features#121](https://github.com/kubernetes/features/issues/121)) - - * [stable] Volume plugin for StorageOS provides highly-available cluster-wide persistent volumes from local or attached node storage ([docs PR](https://github.com/kubernetes/kubernetes.github.io/pull/4095)) ([kubernetes/features#190](https://github.com/kubernetes/features/issues/190)) - - * [stable] Add support for cloudprovider metrics for storage API calls ([docs PR](https://github.com/kubernetes/kubernetes.github.io/pull/4138)) ([kubernetes/features#182](https://github.com/kubernetes/features/issues/182)) - -## **External Dependency Version Information** - -Continuous integration builds have used the following versions of external dependencies, however, this is not a strong recommendation and users should consult an appropriate installation or upgrade guide before deciding what versions of etcd, docker or rkt to use. - -* Docker versions 1.10.3, 1.11.2, 1.12.6 have been validated - - * Docker version 1.12.6 known issues - - * overlay2 driver not fully supported - - * live-restore not fully supported - - * no shared pid namespace support - - * Docker version 1.11.2 known issues - - * Kernel crash with Aufs storage driver on Debian Jessie ([[#27885](https://github.com/kubernetes/kubernetes/pull/27885)](https://github.com/kubernetes/kubernetes/issues/27885)) which can be identified by the [node problem detector](http://kubernetes.io/docs/admin/node-problem/) - - * Leaked File descriptors ([#275](https://github.com/docker/containerd/issues/275)) - - * Additional memory overhead per container ([[#21737](https://github.com/kubernetes/kubernetes/pull/21737)](https://github.com/docker/docker/issues/21737)) - - * Docker 1.10.3 contains [backports provided by RedHat](https://github.com/docker/docker/compare/v1.10.3...runcom:docker-1.10.3-stable) for known issues - -* rkt version 1.23.0+ - - * known issues with the rkt runtime are [listed in the Getting Started Guide](http://kubernetes.io/docs/getting-started-guides/rkt/notes/) - -* etcd version 3.0.17 - -* Go version: 1.8.3. [Link to announcement](https://groups.google.com/d/msg/kubernetes-dev/0XRRz6UhhTM/YODWVnuDBQAJ) - - * Kubernetes can only be compiled with Go 1.8. Support for all other versions is dropped. - -### **Other notable changes** - -* API Machinery - - * The protobuf serialization of API objects has been updated to store maps in a predictable order to ensure that the representation of that object does not change when saved into etcd. This prevents the same object from being seen as being modified, even when no values have changed. ([[#47701](https://github.com/kubernetes/kubernetes/pull/47701)](https://github.com/kubernetes/kubernetes/pull/47701), [[@smarterclayton](https://github.com/smarterclayton)](https://github.com/smarterclayton)) - - * API resource discovery now includes the singularName used to refer to the resource. ([[#43312](https://github.com/kubernetes/kubernetes/pull/43312)](https://github.com/kubernetes/kubernetes/pull/43312), [[@deads2k](https://github.com/deads2k)](https://github.com/deads2k)) - - * Enhance the garbage collection admission plugin so that a user who doesn't have delete permission of the owning object cannot modify the blockOwnerDeletion field of existing ownerReferences, or add new ownerReferences with blockOwnerDeletion=true ([[#43876](https://github.com/kubernetes/kubernetes/pull/43876)](https://github.com/kubernetes/kubernetes/pull/43876), [[@caesarxuchao](https://github.com/caesarxuchao)](https://github.com/caesarxuchao)) - - * The Kubernetes API server now exits if it encounters a networking failure (e.g. the networking interface hosting its address goes away) to allow a process manager (systemd/kubelet/etc) to react to the problem. Previously the server would log the failure and try again to bind to its configured address:port. ([[#42272](https://github.com/kubernetes/kubernetes/pull/42272)](https://github.com/kubernetes/kubernetes/pull/42272), [[@marun](https://github.com/marun)](https://github.com/marun)) - - * Exec and portforward actions over SPDY now properly handle redirects sent by the Kubelet ([[#44451](https://github.com/kubernetes/kubernetes/pull/44451)](https://github.com/kubernetes/kubernetes/pull/44451), [[@ncdc](https://github.com/ncdc)](https://github.com/ncdc)) - - * The proxy subresource APIs for nodes, services, and pods now support the HTTP PATCH method. ([[#44929](https://github.com/kubernetes/kubernetes/pull/44929)](https://github.com/kubernetes/kubernetes/pull/44929), [[@liggitt](https://github.com/liggitt)](https://github.com/liggitt)) - - * The Categories []string field on discovered API resources represents the list of group aliases (e.g. "all") that each resource belongs to. ([[#43338](https://github.com/kubernetes/kubernetes/pull/43338)](https://github.com/kubernetes/kubernetes/pull/43338), [[@fabianofranz](https://github.com/fabianofranz)](https://github.com/fabianofranz)) - - * [alpha] The Kubernetes API supports retrieving tabular output for API resources via a new mime-type application/json;as=Table;v=v1alpha1;g=meta.k8s.io. The returned object (if the server supports it) will be of type meta.k8s.io/v1alpha1 with Table, and contain column and row information related to the resource. Each row will contain information about the resource - by default it will be the object metadata, but callers can add the ?includeObject=Object query parameter and receive the full object. In the future kubectl will use this to retrieve the results of `kubectl get`. ([[#40848](https://github.com/kubernetes/kubernetes/pull/40848)](https://github.com/kubernetes/kubernetes/pull/40848), [[@smarterclayton](https://github.com/smarterclayton)](https://github.com/smarterclayton)) - - * The Prometheus metrics for the kube-apiserver for tracking incoming API requests and latencies now return the subresource label for correctly attributing the type of API call. ([[#46354](https://github.com/kubernetes/kubernetes/pull/46354)](https://github.com/kubernetes/kubernetes/pull/46354), [[@smarterclayton](https://github.com/smarterclayton)](https://github.com/smarterclayton)) - - * The behavior of some watch calls to the server when filtering on fields was incorrect. If watching objects with a filter, when an update was made that no longer matched the filter a DELETE event was correctly sent. However, the object that was returned by that delete was not the (correct) version before the update, but instead, the newer version. That meant the new object was not matched by the filter. This was a regression from behavior between cached watches on the server side and uncached watches, and thus broke downstream API clients. ([[#46223](https://github.com/kubernetes/kubernetes/pull/46223)](https://github.com/kubernetes/kubernetes/pull/46223), [[@smarterclayton](https://github.com/smarterclayton)](https://github.com/smarterclayton)) - - * OpenAPI spec is now available in protobuf binary and gzip format (with ETag support) ([[#45836](https://github.com/kubernetes/kubernetes/pull/45836)](https://github.com/kubernetes/kubernetes/pull/45836), [[@mbohlool](https://github.com/mbohlool)](https://github.com/mbohlool)) - - * Updating apiserver to return UID of the deleted resource. Clients can use this UID to verify that the resource was deleted or waiting for finalizers. ([[#45600](https://github.com/kubernetes/kubernetes/pull/45600)](https://github.com/kubernetes/kubernetes/pull/45600), [[@nikhiljindal](https://github.com/nikhiljindal)](https://github.com/nikhiljindal)) - - * Fix incorrect conflict errors applying strategic merge patches to resources. ([[#43871](https://github.com/kubernetes/kubernetes/pull/43871)](https://github.com/kubernetes/kubernetes/pull/43871), [[@liggitt](https://github.com/liggitt)](https://github.com/liggitt)) - -* Apps - - * StatefulSet has a configurable update strategy. Updates can be performed using the RollingUpdate or OnDelete strategies. OnDelete is the default behavior, and it implements the same behavior as StatefulSets in 1.6. RollingUpdate performs automated, ordered updates to Pods in a StatefulSet. ([[#46669](https://github.com/kubernetes/kubernetes/pull/46669)](https://github.com/kubernetes/kubernetes/pull/46669), [[@kow3ns](https://github.com/kow3ns)](https://github.com/kow3ns))([kubernetes/features#287](https://github.com/kubernetes/features/issues/287)). - - * StatefulSetStatus now tracks replicas, readyReplicas, currentReplicas, and updatedReplicas. The semantics of replicas is now consistent with DaemonSet and ReplicaSet, and readyReplicas has the semantics that replicas did prior to 1.7 ([[#46669](https://github.com/kubernetes/kubernetes/pull/46669)](https://github.com/kubernetes/kubernetes/pull/46669), [[@kow3ns](https://github.com/kow3ns)](https://github.com/kow3ns)). - - * DaemonSets supports history and rollback ([[#45924](https://github.com/kubernetes/kubernetes/pull/45924)](https://github.com/kubernetes/kubernetes/pull/45924), [[@janetkuo](https://github.com/janetkuo)](https://github.com/janetkuo))([kubernetes/features#124](https://github.com/kubernetes/features/issues/124)). - - * ControllerRevision type has been added for StatefulSet and DaemonSet history. Clients should not depend on the stability of this type as it may change, as necessary, in future releases to support StatefulSet and DaemonSet update and rollback. We enable this type as we do with beta features, because StatefulSet update and DaemonSet update are enabled. ([[#45867](https://github.com/kubernetes/kubernetes/pull/45867)](https://github.com/kubernetes/kubernetes/pull/45867), [[@kow3ns](https://github.com/kow3ns)](https://github.com/kow3ns)) - - * PodDisruptionBudget now uses ControllerRef to decide which controller owns a given Pod, so it doesn't get confused by controllers with overlapping selectors. ([[#45003](https://github.com/kubernetes/kubernetes/pull/45003)](https://github.com/kubernetes/kubernetes/pull/45003), [[@krmayankk](https://github.com/krmayankk)](https://github.com/krmayankk)) - - * Deployments are updated to use (1) a more stable hashing algorithm (fnv) than the previous one (adler) and (2) a hashing collision avoidance mechanism that will ensure new rollouts will not block on hashing collisions anymore. ([[#44774](https://github.com/kubernetes/kubernetes/pull/44774)](https://github.com/kubernetes/kubernetes/pull/44774), [[@kargakis](https://github.com/kargakis)](https://github.com/kargakis))([kubernetes/features#287](https://github.com/kubernetes/features/issues/287)) - - * PodDisruptionBudget now has a MaxUnavailable field. This allows users to specify the maximum number of disruptions that can be tolerated during eviction. ([[#45587](https://github.com/kubernetes/kubernetes/pull/45587)](https://github.com/kubernetes/kubernetes/pull/45587), [[@foxish](https://github.com/foxish)](https://github.com/foxish))([kubernetes/features#285](https://github.com/kubernetes/features/issues/285)) - - * Deployments and DaemonSets rollouts are considered complete when all of the desired replicas are updated and available. This change affects `kubectl rollout status` and Deployment condition. ([[#44672](https://github.com/kubernetes/kubernetes/pull/44672)](https://github.com/kubernetes/kubernetes/pull/44672), [[@kargakis](https://github.com/kargakis)](https://github.com/kargakis)) - - * Job controller now respects ControllerRef to avoid fighting over Pods. ([[#42176](https://github.com/kubernetes/kubernetes/pull/42176)](https://github.com/kubernetes/kubernetes/pull/42176), [[@enisoc](https://github.com/enisoc)](https://github.com/enisoc)) - - * CronJob controller now respects ControllerRef to avoid fighting with other controllers. ([[#42177](https://github.com/kubernetes/kubernetes/pull/42177)](https://github.com/kubernetes/kubernetes/pull/42177), [[@enisoc](https://github.com/enisoc)](https://github.com/enisoc)) - -* Auth - - * Features: - - * Azure plugin for client auth ([[#43987](https://github.com/kubernetes/kubernetes/pull/43987)](https://github.com/kubernetes/kubernetes/pull/43987), [[@cosmincojocar](https://github.com/cosmincojocar)](https://github.com/cosmincojocar)) - - * Permission to use a PodSecurityPolicy can now be granted within a single namespace by allowing the use verb on the podsecuritypolicies resource within the namespace. ([[#42360](https://github.com/kubernetes/kubernetes/pull/42360)](https://github.com/kubernetes/kubernetes/pull/42360), [[@liggitt](https://github.com/liggitt)](https://github.com/liggitt)) - - * Break the 'certificatesigningrequests' controller into a 'csrapprover' controller and 'csrsigner' controller. ([[#45514](https://github.com/kubernetes/kubernetes/pull/45514)](https://github.com/kubernetes/kubernetes/pull/45514), [[@mikedanese](https://github.com/mikedanese)](https://github.com/mikedanese)) - - * kube-apiserver: `--service-account-lookup` now defaults to true, requiring the Secret API object containing the token to exist in order for a service account token to be valid. This enables service account tokens to be revoked by deleting the Secret object containing the token. ([[#44071](https://github.com/kubernetes/kubernetes/pull/44071)](https://github.com/kubernetes/kubernetes/pull/44071), [[@liggitt](https://github.com/liggitt)](https://github.com/liggitt)) - - * `kubectl auth can-i` now supports non-resource URLs ([[#46432](https://github.com/kubernetes/kubernetes/pull/46432)](https://github.com/kubernetes/kubernetes/pull/46432), [[@CaoShuFeng](https://github.com/CaoShuFeng)](https://github.com/CaoShuFeng)) - - * Promote kubelet tls bootstrap to beta. Add a non-experimental flag to use it and deprecate the old flag. ([[#46799](https://github.com/kubernetes/kubernetes/pull/46799)](https://github.com/kubernetes/kubernetes/pull/46799), [[@mikedanese](https://github.com/mikedanese)](https://github.com/mikedanese)) - - * Add the alpha.image-policy.k8s.io/failed-open=true annotation when the image policy webhook encounters an error and fails open. ([[#46264](https://github.com/kubernetes/kubernetes/pull/46264)](https://github.com/kubernetes/kubernetes/pull/46264), [[@Q-Lee](https://github.com/Q-Lee)](https://github.com/Q-Lee)) - - * Bug fixes: - - * Make gcp auth provider not to override the Auth header if it's already exits ([[#45575](https://github.com/kubernetes/kubernetes/pull/45575)](https://github.com/kubernetes/kubernetes/pull/45575), [[@wanghaoran1988](https://github.com/wanghaoran1988)](https://github.com/wanghaoran1988)) - - * The oidc client plugin has reduce round trips and fix scopes requested ([[#45317](https://github.com/kubernetes/kubernetes/pull/45317)](https://github.com/kubernetes/kubernetes/pull/45317), [[@ericchiang](https://github.com/ericchiang)](https://github.com/ericchiang)) - - * API requests using impersonation now include the system:authenticated group in the impersonated user automatically. ([[#44076](https://github.com/kubernetes/kubernetes/pull/44076)](https://github.com/kubernetes/kubernetes/pull/44076), [[@liggitt](https://github.com/liggitt)](https://github.com/liggitt)) - - * RBAC role and rolebinding auto-reconciliation is now performed only when the RBAC authorization mode is enabled. ([[#43813](https://github.com/kubernetes/kubernetes/pull/43813)](https://github.com/kubernetes/kubernetes/pull/43813), [[@liggitt](https://github.com/liggitt)](https://github.com/liggitt)) - - * PodSecurityPolicy now recognizes pods that specify runAsNonRoot: false in their security context and does not overwrite the specified value ([[#47073](https://github.com/kubernetes/kubernetes/pull/47073)](https://github.com/kubernetes/kubernetes/pull/47073), [[@Q-Lee](https://github.com/Q-Lee)](https://github.com/Q-Lee)) - - * Tokens retrieved from Google Cloud with application default credentials will not be cached if the client fails authorization ([[#46694](https://github.com/kubernetes/kubernetes/pull/46694)](https://github.com/kubernetes/kubernetes/pull/46694), [[@matt-tyler](https://github.com/matt-tyler)](https://github.com/matt-tyler)) - -* Autoscaling - - * Cluster Autoscaler 0.6. More information available [here](https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/README.md). - -* CLI - - * Features - - * `kubectl logs` supports specifying a container name when using label selectors ([[#44282](https://github.com/kubernetes/kubernetes/pull/44282)](https://github.com/kubernetes/kubernetes/pull/44282), [[@derekwaynecarr](https://github.com/derekwaynecarr)](https://github.com/derekwaynecarr)) - - * `kubectl rollout` supports undo and history for DaemonSet ([[#46144](https://github.com/kubernetes/kubernetes/pull/46144)](https://github.com/kubernetes/kubernetes/pull/46144), [[@janetkuo](https://github.com/janetkuo)](https://github.com/janetkuo)) - - * `kubectl rollout` supports status and history for StatefulSet ([[#46669](https://github.com/kubernetes/kubernetes/pull/46669)](https://github.com/kubernetes/kubernetes/pull/46669), [[@kow3ns](https://github.com/kow3ns)](https://github.com/kow3ns)). - - * Implement `kubectl get controllerrevisions` ([[#46655](https://github.com/kubernetes/kubernetes/pull/46655)](https://github.com/kubernetes/kubernetes/pull/46655), [[@janetkuo](https://github.com/janetkuo)](https://github.com/janetkuo)) - - * `kubectl create clusterrole` supports `--non-resource-url` ([[#45809](https://github.com/kubernetes/kubernetes/pull/45809)](https://github.com/kubernetes/kubernetes/pull/45809), [[@CaoShuFeng](https://github.com/CaoShuFeng)](https://github.com/CaoShuFeng)) - - * `kubectl logs` and `kubectl attach` support specifying a wait timeout with `--pod-running-timeout` - - * ([[#41813](https://github.com/kubernetes/kubernetes/pull/41813)](https://github.com/kubernetes/kubernetes/pull/41813), [[@shiywang](https://github.com/shiywang)](https://github.com/shiywang)) - - * New commands - - * Add `kubectl config rename-context` ([[#46114](https://github.com/kubernetes/kubernetes/pull/46114)](https://github.com/kubernetes/kubernetes/pull/46114), [[@arthur0](https://github.com/arthur0)](https://github.com/arthur0)) - - * Add `kubectl apply edit-last-applied` subcommand ([[#42256](https://github.com/kubernetes/kubernetes/pull/42256)](https://github.com/kubernetes/kubernetes/pull/42256), [[@shiywang](https://github.com/shiywang)](https://github.com/shiywang)) - - * Strategic Merge Patch - - * Reference docs now display the patch type and patch merge key used by `kubectl apply` to merge and identify unique elements in arrays. - - * `kubectl edit` and `kubectl apply` will keep the ordering of elements in merged lists ([[#45980](https://github.com/kubernetes/kubernetes/pull/45980)](https://github.com/kubernetes/kubernetes/pull/45980), [[@mengqiy](https://github.com/mengqiy)](https://github.com/mengqiy)) - - * New patch directive (retainKeys) to specifying clearing fields missing from the request ([[#44597](https://github.com/kubernetes/kubernetes/pull/44597)](https://github.com/kubernetes/kubernetes/pull/44597), [[@mengqiy](https://github.com/mengqiy)](https://github.com/mengqiy)) - - * Open API now includes strategic merge patch tags (previously only in go struct tags) ([[#44121](https://github.com/kubernetes/kubernetes/pull/44121)](https://github.com/kubernetes/kubernetes/pull/44121), [[@mbohlool](https://github.com/mbohlool)](https://github.com/mbohlool)) - - * Plugins - - * Introduces the ability to extend kubectl by adding third-party plugins. Developer preview, please refer to the documentation for instructions about how to use it. ([[#37499](https://github.com/kubernetes/kubernetes/pull/37499)](https://github.com/kubernetes/kubernetes/pull/37499), [[@fabianofranz](https://github.com/fabianofranz)](https://github.com/fabianofranz)) - - * Added support for a hierarchy of kubectl plugins (a tree of plugins as children of other plugins). ([[#45981](https://github.com/kubernetes/kubernetes/pull/45981)](https://github.com/kubernetes/kubernetes/pull/45981), [[@fabianofranz](https://github.com/fabianofranz)](https://github.com/fabianofranz)) - - * Added exported env vars to kubectl plugins so that plugin developers have access to global flags, namespace, the plugin descriptor and the full path to the caller binary. - - * Enhancement - - * `kubectl auth can-i` now supports non-resource URLs ([[#46432](https://github.com/kubernetes/kubernetes/pull/46432)](https://github.com/kubernetes/kubernetes/pull/46432), [[@CaoShuFeng](https://github.com/CaoShuFeng)](https://github.com/CaoShuFeng)) - - * `kubectl set selector` and `kubectl set subject` no longer print "running in local/dry-run mode..." at the top. The output can now be piped and interpretted as yaml or json ([[#46507](https://github.com/kubernetes/kubernetes/pull/46507)](https://github.com/kubernetes/kubernetes/pull/46507), [[@bboreham](https://github.com/bboreham)](https://github.com/bboreham)) - - * When using an in-cluster client with an empty configuration, the `--namespace` flag is now honored ([[#46299](https://github.com/kubernetes/kubernetes/pull/46299)](https://github.com/kubernetes/kubernetes/pull/46299), [[@ncdc](https://github.com/ncdc)](https://github.com/ncdc)) - - * The help message for missingResourceError is now generic ([[#45582](https://github.com/kubernetes/kubernetes/pull/45582)](https://github.com/kubernetes/kubernetes/pull/45582), [[@CaoShuFeng](https://github.com/CaoShuFeng)](https://github.com/CaoShuFeng)) - - * `kubectl taint node` now supports label selectors ([[#44740](https://github.com/kubernetes/kubernetes/pull/44740)](https://github.com/kubernetes/kubernetes/pull/44740), [[@ravisantoshgudimetla](https://github.com/ravisantoshgudimetla)](https://github.com/ravisantoshgudimetla)) - - * `kubectl proxy --www` now logs a warning when the dir is invalid ([[#44952](https://github.com/kubernetes/kubernetes/pull/44952)](https://github.com/kubernetes/kubernetes/pull/44952), [[@CaoShuFeng](https://github.com/CaoShuFeng)](https://github.com/CaoShuFeng)) - - * `kubectl taint` output has been enhanced with the operation ([[#43171](https://github.com/kubernetes/kubernetes/pull/43171)](https://github.com/kubernetes/kubernetes/pull/43171), [[@ravisantoshgudimetla](https://github.com/ravisantoshgudimetla)](https://github.com/ravisantoshgudimetla)) - - * Kubectl `--user` and `--cluster` now support completion ([[#44251](https://github.com/kubernetes/kubernetes/pull/44251)](https://github.com/kubernetes/kubernetes/pull/44251), [[@superbrothers](https://github.com/superbrothers)](https://github.com/superbrothers)) - - * `kubectl config use-context` now supports completion ([[#42336](https://github.com/kubernetes/kubernetes/pull/42336)](https://github.com/kubernetes/kubernetes/pull/42336), [[@superbrothers](https://github.com/superbrothers)](https://github.com/superbrothers)) - - * `kubectl version` now supports `--output` ([[#39858](https://github.com/kubernetes/kubernetes/pull/39858)](https://github.com/kubernetes/kubernetes/pull/39858), [[@alejandroEsc](https://github.com/alejandroEsc)](https://github.com/alejandroEsc)) - - * Printing/describe - - * Print conditions of RC/RS in `kubectl describe` command. ([[#44710](https://github.com/kubernetes/kubernetes/pull/44710)](https://github.com/kubernetes/kubernetes/pull/44710), [[@xiangpengzhao](https://github.com/xiangpengzhao)](https://github.com/xiangpengzhao)) - - * Improved output on `kubectl get` and `kubectl describe` for generic objects. ([[#44222](https://github.com/kubernetes/kubernetes/pull/44222)](https://github.com/kubernetes/kubernetes/pull/44222), [[@fabianofranz](https://github.com/fabianofranz)](https://github.com/fabianofranz)) - - * In `kubectl describe`, find controllers with ControllerRef, instead of showing the original creator. ([[#42849](https://github.com/kubernetes/kubernetes/pull/42849)](https://github.com/kubernetes/kubernetes/pull/42849), [[@janetkuo](https://github.com/janetkuo)](https://github.com/janetkuo)) - - * Bug fixes - - * Fix some false negatives in detection of meaningful conflicts during strategic merge patch with maps and lists. ([[#43469](https://github.com/kubernetes/kubernetes/pull/43469)](https://github.com/kubernetes/kubernetes/pull/43469), [[@enisoc](https://github.com/enisoc)](https://github.com/enisoc)) - - * Restored the ability of kubectl running inside a pod to consume resource files specifying a different namespace than the one the pod is running in. ([[#44862](https://github.com/kubernetes/kubernetes/pull/44862)](https://github.com/kubernetes/kubernetes/pull/44862), [[@liggitt](https://github.com/liggitt)](https://github.com/liggitt)) - - * Kubectl commands run inside a pod using a kubeconfig file now use the namespace specified in the kubeconfig file, instead of using the pod namespace. If no kubeconfig file is used, or the kubeconfig does not specify a namespace, the pod namespace is still used as a fallback. ([[#44570](https://github.com/kubernetes/kubernetes/pull/44570)](https://github.com/kubernetes/kubernetes/pull/44570), [[@liggitt](https://github.com/liggitt)](https://github.com/liggitt)) - - * Fixed `kubectl cluster-info` dump to support multi-container pod. ([[#44088](https://github.com/kubernetes/kubernetes/pull/44088)](https://github.com/kubernetes/kubernetes/pull/44088), [[@xingzhou](https://github.com/xingzhou)](https://github.com/xingzhou)) - - * Kubectl will print a warning when deleting the current context ([[#42538](https://github.com/kubernetes/kubernetes/pull/42538)](https://github.com/kubernetes/kubernetes/pull/42538), [[@adohe](https://github.com/adohe)](https://github.com/adohe)) - - * Fix VolumeClaims/capacity in `kubectl describe statefulsets` output. ([[#47573](https://github.com/kubernetes/kubernetes/pull/47573)](https://github.com/kubernetes/kubernetes/pull/47573), [[@k82cn](https://github.com/k82cn)](https://github.com/k82cn)) - - * I18n - - * Add Traditional Chinese translation for kubectl ([[#46559](https://github.com/kubernetes/kubernetes/pull/46559)](https://github.com/kubernetes/kubernetes/pull/46559), [[@warmchang](https://github.com/warmchang)](https://github.com/warmchang)) - - * Add Japanese translation for kubectl ([[#46756](https://github.com/kubernetes/kubernetes/pull/46756)](https://github.com/kubernetes/kubernetes/pull/46756), [[@girikuncoro](https://github.com/girikuncoro)](https://github.com/girikuncoro)) - - * Add Simplified Chinese translation for kubectl ([[#45573](https://github.com/kubernetes/kubernetes/pull/45573)](https://github.com/kubernetes/kubernetes/pull/45573), [[@shiywang](https://github.com/shiywang)](https://github.com/shiywang)) - -* Cluster Lifecycle - - * Features: - - * kubeadm: Enable the Node Authorizer/Admission plugin in v1.7 ([[#46879](https://github.com/kubernetes/kubernetes/pull/46879)](https://github.com/kubernetes/kubernetes/pull/46879), [[@luxas](https://github.com/luxas)](https://github.com/luxas)) - - * kubeadm: Users can now pass extra parameters to etcd in a kubeadm cluster ([[#42246](https://github.com/kubernetes/kubernetes/pull/42246)](https://github.com/kubernetes/kubernetes/pull/42246), [[@jamiehannaford](https://github.com/jamiehannaford)](https://github.com/jamiehannaford)) - - * kubeadm: Make kubeadm use the new CSR approver in v1.7 ([[#46864](https://github.com/kubernetes/kubernetes/pull/46864)](https://github.com/kubernetes/kubernetes/pull/46864), [[@luxas](https://github.com/luxas)](https://github.com/luxas)) - - * kubeadm: Allow enabling multiple authorization modes at the same time ([[#42557](https://github.com/kubernetes/kubernetes/pull/42557)](https://github.com/kubernetes/kubernetes/pull/42557), [[@xilabao](https://github.com/xilabao)](https://github.com/xilabao)) - - * kubeadm: add proxy client-certs to kube-apiserver to allow it to proxy aggregated api servers ([[#43715](https://github.com/kubernetes/kubernetes/pull/43715)](https://github.com/kubernetes/kubernetes/pull/43715), [[@deads2k](https://github.com/deads2k)](https://github.com/deads2k)) - - * Action required when upgrading: - - * kubeadm: Modifications to cluster-internal resources installed by kubeadm will be overwritten when upgrading from v1.6 to v1.7. ([[#47081](https://github.com/kubernetes/kubernetes/pull/47081)](https://github.com/kubernetes/kubernetes/pull/47081), [[@luxas](https://github.com/luxas)](https://github.com/luxas)) - - * kubeadm deb/rpm packages: cAdvisor doesn't listen on `0.0.0.0:4194` without authentication/authorization because of the possible information leakage. The cAdvisor API can still be accessed via `https://{node-ip}:10250/stats/`, though. ([kubernetes/release#356](https://github.com/kubernetes/release/pull/356), [[@luxas](https://github.com/luxas)](https://github.com/luxas)) - - * Deletions: - - * cluster/ubuntu: Removed due to [deprecation](https://github.com/kubernetes/kubernetes/tree/master/cluster#cluster-configuration) and lack of maintenance. ([[#44344](https://github.com/kubernetes/kubernetes/pull/44344)](https://github.com/kubernetes/kubernetes/pull/44344), [[@mikedanese](https://github.com/mikedanese)](https://github.com/mikedanese)) - - * cluster/aws: Removed due to [deprecation](https://github.com/kubernetes/kubernetes/pull/38772) and lack of maintenance. ([[#42196](https://github.com/kubernetes/kubernetes/pull/42196)](https://github.com/kubernetes/kubernetes/pull/42196), [[@zmerlynn](https://github.com/zmerlynn)](https://github.com/zmerlynn)) - -* Federation - - * TODO: Sig-federation please find notable changes (feature & bug fix) below for your SIG and pull into this section - -* Instrumentation - - * Bumped Heapster to v1.4.0. More details about the release https://github.com/kubernetes/heapster/releases/tag/v1.4.0 - - * Fluentd manifest pod is no longer created on non-registered master when creating clusters using kube-up.sh. ([[#44721](https://github.com/kubernetes/kubernetes/pull/44721)](https://github.com/kubernetes/kubernetes/pull/44721), [[@piosz](https://github.com/piosz)](https://github.com/piosz)) - - * Stackdriver cluster logging now deploys a new component to export Kubernetes events. ([[#46700](https://github.com/kubernetes/kubernetes/pull/46700)](https://github.com/kubernetes/kubernetes/pull/46700), [[@crassirostris](https://github.com/crassirostris)](https://github.com/crassirostris)) - - * Stackdriver Logging deployment exposes metrics on node port 31337 when enabled. ([[#47402](https://github.com/kubernetes/kubernetes/pull/47402)](https://github.com/kubernetes/kubernetes/pull/47402), [[@crassirostris](https://github.com/crassirostris)](https://github.com/crassirostris)) - -* Network - - * DNS and name resolution - - * Updates kube-dns to 1.14.2 ([[#45684](https://github.com/kubernetes/kubernetes/pull/45684)](https://github.com/kubernetes/kubernetes/pull/45684), [[@bowei](https://github.com/bowei)](https://github.com/bowei)) - - * Support kube-master-url flag without kubeconfig - - * Fix concurrent R/Ws in dns.go - - * Fix confusing logging when initializing server - - * Fix printf in cmd/kube-dns/app/server.go - - * Fix version on startup and `--version` flag - - * Support specifying port number for nameserver in stubDomains - - * A new field hostAliases has been added to pod.spec to support adding entries to a Pod's /etc/hosts file. ([[#44641](https://github.com/kubernetes/kubernetes/pull/44641)](https://github.com/kubernetes/kubernetes/pull/44641), [[@rickypai](https://github.com/rickypai)](https://github.com/rickypai)) - - * Fix DNS suffix search list support in Windows kube-proxy. ([[#45642](https://github.com/kubernetes/kubernetes/pull/45642)](https://github.com/kubernetes/kubernetes/pull/45642), [[@JiangtianLi](https://github.com/JiangtianLi)](https://github.com/JiangtianLi)) - - * Kube Proxy - - * kube-proxy: ratelimit runs of iptables by sync-period flags ([[#46266](https://github.com/kubernetes/kubernetes/pull/46266)](https://github.com/kubernetes/kubernetes/pull/46266), [[@thockin](https://github.com/thockin)](https://github.com/thockin)) - - * Fixes a bug in the kubernetes-worker Juju charm code that attempted to give kube-proxy more than one api endpoint. ([[#44677](https://github.com/kubernetes/kubernetes/pull/44677)](https://github.com/kubernetes/kubernetes/pull/44677), [[@wwwtyro](https://github.com/wwwtyro)](https://github.com/wwwtyro)) - - * IP masquerade - - * ip-masq-agent is now on by default for GCE ([[#47794](https://github.com/kubernetes/kubernetes/pull/47794)](https://github.com/kubernetes/kubernetes/pull/47794), [[@dnardo](https://github.com/dnardo)](https://github.com/dnardo)) - - * Bump the memory request/limit for ip-masq-daemon. ([[#47887](https://github.com/kubernetes/kubernetes/pull/47887)](https://github.com/kubernetes/kubernetes/pull/47887), [[@dnardo](https://github.com/dnardo)](https://github.com/dnardo)) - - * Cloud provider: AWS - - * New 'service.beta.kubernetes.io/aws-load-balancer-extra-security-groups' Service annotation to specify extra Security Groups to be added to ELB created by AWS cloudprovider ([[#45268](https://github.com/kubernetes/kubernetes/pull/45268)](https://github.com/kubernetes/kubernetes/pull/45268), [[@redbaron](https://github.com/redbaron)](https://github.com/redbaron)) - - * Clean up blackhole routes when using kubenet ([[#47572](https://github.com/kubernetes/kubernetes/pull/47572)](https://github.com/kubernetes/kubernetes/pull/47572), [[@justinsb](https://github.com/justinsb)](https://github.com/justinsb)) - - * Maintain a cache of all instances, to fix problem with > 200 nodes with ELBs ([[#47410](https://github.com/kubernetes/kubernetes/pull/47410)](https://github.com/kubernetes/kubernetes/pull/47410), [[@justinsb](https://github.com/justinsb)](https://github.com/justinsb)) - - * Avoid spurious ELB listener recreation - ignore case when matching protocol ([[#47391](https://github.com/kubernetes/kubernetes/pull/47391)](https://github.com/kubernetes/kubernetes/pull/47391), [[@justinsb](https://github.com/justinsb)](https://github.com/justinsb)) - - * Allow configuration of a single security group for ELBs ([[#45500](https://github.com/kubernetes/kubernetes/pull/45500)](https://github.com/kubernetes/kubernetes/pull/45500), [[@nbutton23](https://github.com/nbutton23)](https://github.com/nbutton23)) - - * Remove check that forces loadBalancerSourceRanges to be 0.0.0.0/0. ([[#38636](https://github.com/kubernetes/kubernetes/pull/38636)](https://github.com/kubernetes/kubernetes/pull/38636), [[@dhawal55](https://github.com/dhawal55)](https://github.com/dhawal55)) - - * Cloud provider: Azure - - * Add support for UDP ports ([[#45523](https://github.com/kubernetes/kubernetes/pull/45523)](https://github.com/kubernetes/kubernetes/pull/45523), [[@colemickens](https://github.com/colemickens)](https://github.com/colemickens)) - - * Fix support for multiple loadBalancerSourceRanges ([[#45523](https://github.com/kubernetes/kubernetes/pull/45523)](https://github.com/kubernetes/kubernetes/pull/45523), [[@colemickens](https://github.com/colemickens)](https://github.com/colemickens)) - - * Support the Service spec's sessionAffinity ([[#45523](https://github.com/kubernetes/kubernetes/pull/45523)](https://github.com/kubernetes/kubernetes/pull/45523), [[@colemickens](https://github.com/colemickens)](https://github.com/colemickens)) - - * Cloud provider: GCE - - * Bump GLBC version to 0.9.5 - fixes [loss of manually modified GCLB health check settings](https://github.com/kubernetes/kubernetes/issues/47559) upon upgrade from pre-1.6.4 to either 1.6.4 or 1.6.5. ([[#47567](https://github.com/kubernetes/kubernetes/pull/47567)](https://github.com/kubernetes/kubernetes/pull/47567), [[@nicksardo](https://github.com/nicksardo)](https://github.com/nicksardo)) - - * [beta] Support creation of GCP Internal Load Balancers from Service objects ([[#46663](https://github.com/kubernetes/kubernetes/pull/46663)](https://github.com/kubernetes/kubernetes/pull/46663), [[@nicksardo](https://github.com/nicksardo)](https://github.com/nicksardo)) - - * GCE installs will now avoid IP masquerade for all RFC-1918 IP blocks, rather than just 10.0.0.0/8. This means that clusters can be created in 192.168.0.0./16 and 172.16.0.0/12 while preserving the container IPs (which would be lost before). ([[#46473](https://github.com/kubernetes/kubernetes/pull/46473)](https://github.com/kubernetes/kubernetes/pull/46473), [[@thockin](https://github.com/thockin)](https://github.com/thockin)) - - * The Calico version included in kube-up for GCE has been updated to v2.2. ([[#38169](https://github.com/kubernetes/kubernetes/pull/38169)](https://github.com/kubernetes/kubernetes/pull/38169), [[@caseydavenport](https://github.com/caseydavenport)](https://github.com/caseydavenport)) - - * Add ip-masq-agent addon to the addons folder which is used in GCE if `--non-masquerade-cidr` is set to 0/0 ([[#46038](https://github.com/kubernetes/kubernetes/pull/46038)](https://github.com/kubernetes/kubernetes/pull/46038), [[@dnardo](https://github.com/dnardo)](https://github.com/dnardo)) - - * Adds support for allocation of pod IPs via IP aliases. ([[#42147](https://github.com/kubernetes/kubernetes/pull/42147)](https://github.com/kubernetes/kubernetes/pull/42147), [[@bowei](https://github.com/bowei)](https://github.com/bowei)) - - * Cloud provider vSphere: - - * cloud provider: Filter out IPV6 node addresses. ([[#45181](https://github.com/kubernetes/kubernetes/pull/45181)](https://github.com/kubernetes/kubernetes/pull/45181), [[@BaluDontu](https://github.com/BaluDontu)](https://github.com/BaluDontu)) - - * Cloud provider OpenStack: - - * Fixes issue during LB creation where ports were incorrectly assigned to a floating IP ([[#44387](https://github.com/kubernetes/kubernetes/pull/44387)](https://github.com/kubernetes/kubernetes/pull/44387), [[@jamiehannaford](https://github.com/jamiehannaford)](https://github.com/jamiehannaford)) - - * Network policy - - * Add short name "netpol" for networkpolicies ([[#42241](https://github.com/kubernetes/kubernetes/pull/42241)](https://github.com/kubernetes/kubernetes/pull/42241), [[@xiangpengzhao](https://github.com/xiangpengzhao)](https://github.com/xiangpengzhao)) - - * ServiceController - - * Exclude nodes labeled as master from LoadBalancer / NodePort; restores documented behaviour. ([[#44745](https://github.com/kubernetes/kubernetes/pull/44745)](https://github.com/kubernetes/kubernetes/pull/44745), [[@justinsb](https://github.com/justinsb)](https://github.com/justinsb)) - - * Fix node selection logic on initial LB creation ([[#45773](https://github.com/kubernetes/kubernetes/pull/45773)](https://github.com/kubernetes/kubernetes/pull/45773), [[@justinsb](https://github.com/justinsb)](https://github.com/justinsb)) - - * Security updates - - * Update kube-dns and ip-masq-agent addons with new base images containing fixes for CVE-2016-4448, CVE-2016-9841, CVE-2016-9843, CVE-2017-1000366, CVE-2017-2616, and CVE-2017-9526. ([[#47877](https://github.com/kubernetes/kubernetes/pull/47877)](https://github.com/kubernetes/kubernetes/pull/47877), [[@ixdy](https://github.com/ixdy)](https://github.com/ixdy)) - - * Source IP preservation - - * Promotes Source IP preservation for Virtual IPs to GA. ([[#41162](https://github.com/kubernetes/kubernetes/pull/41162)](https://github.com/kubernetes/kubernetes/pull/41162), [[@MrHohn](https://github.com/MrHohn)](https://github.com/MrHohn)). Two annotations have been promoted to API fields: - - * Service.Spec.ExternalTrafficPolicy was 'service.beta.kubernetes.io/external-traffic' annotation. - - * Service.Spec.HealthCheckNodePort was 'service.beta.kubernetes.io/healthcheck-nodeport' annotation. - - * When switching from the service.beta.kubernetes.io/external-traffic annotation to the new externalTrafficPolicy field, the values change as follows: * "OnlyLocal" becomes "Local" * "Global" becomes "Cluster". ([[#46716](https://github.com/kubernetes/kubernetes/pull/46716)](https://github.com/kubernetes/kubernetes/pull/46716), [[@thockin](https://github.com/thockin)](https://github.com/thockin)) - - * Documentation - - * Documented NodePort networking for CDK. ([[#44863](https://github.com/kubernetes/kubernetes/pull/44863)](https://github.com/kubernetes/kubernetes/pull/44863), [[@chuckbutler](https://github.com/chuckbutler)](https://github.com/chuckbutler)) - -* Node - - * Features - - * Kubelet Container Runtime Interface (CRI) support - - * [GA] The Docker-CRI implementation is GA. The legacy, non-CRI Docker integration has been completely removed. - - * [beta] [CRI-O](https://github.com/kubernetes-incubator/cri-o) v1.0.0-alpha.0. It has passed all e2e tests. ([release notes](https://github.com/kubernetes-incubator/cri-o/releases/tag/v1.0.0-alpha.0)) - - * [beta] [Frakti](https://github.com/kubernetes/frakti) v1.0. It has passed all node conformance tests. ([release notes](https://github.com/kubernetes/frakti/releases/tag/v1.0)) - - * [alpha] [cri-containerd](https://github.com/kubernetes-incubator/cri-containerd) v0.1.0. It supports basic sandbox/container/image management and passes 30/36 CRI validation test. ([release notes](https://github.com/kubernetes-incubator/cri-containerd/releases/tag/v0.1.0)) - - * Support running Ubuntu image on GCE node ([[#44744](https://github.com/kubernetes/kubernetes/pull/44744)](https://github.com/kubernetes/kubernetes/pull/44744), [[@yguo0905](https://github.com/yguo0905)](https://github.com/yguo0905)) - - * Kubernetes now shares a single PID namespace among all containers in a pod when running with docker >= 1.13.1. This means processes can now signal processes in other containers in a pod, but it also means that the `kubectl exec {pod} kill 1` pattern will cause the Pod to be restarted rather than a single container. ([[#45236](https://github.com/kubernetes/kubernetes/pull/45236)](https://github.com/kubernetes/kubernetes/pull/45236), [[@verb](https://github.com/verb)](https://github.com/verb)) - - * A new field hostAliases has been added to the pod spec to support adding entries to a Pod's /etc/hosts file. ([docs PR](https://github.com/kubernetes/kubernetes.github.io/pull/4080))([[#44641](https://github.com/kubernetes/kubernetes/pull/44641)](https://github.com/kubernetes/kubernetes/pull/44641), [[@rickypai](https://github.com/rickypai)](https://github.com/rickypai)) - - * With `--feature-gates=RotateKubeletClientCertificate=true` set, the Kubelet will ([[#41912](https://github.com/kubernetes/kubernetes/pull/41912)](https://github.com/kubernetes/kubernetes/pull/41912), [[@jcbsmpsn](https://github.com/jcbsmpsn)](https://github.com/jcbsmpsn)) - - * request a client certificate from the API server during the boot cycle and pause - - * waiting for the request to be satisfied. It will continually refresh the certificate - - * Create clusters with GPUs in GCE by specifying `type=,count=` to NODE_ACCELERATORS environment variable. ([[#45130](https://github.com/kubernetes/kubernetes/pull/45130)](https://github.com/kubernetes/kubernetes/pull/45130), [[@vishh](https://github.com/vishh)](https://github.com/vishh)) - - * List of available GPUs - [https://cloud.google.com/compute/docs/gpus/#introduction](https://cloud.google.com/compute/docs/gpus/#introduction) - - * Disk Pressure triggers the deletion of terminated containers on the node. ([[#45896](https://github.com/kubernetes/kubernetes/pull/45896)](https://github.com/kubernetes/kubernetes/pull/45896), [[@dashpole](https://github.com/dashpole)](https://github.com/dashpole)) - - * Support status.hostIP in downward API ([[#42717](https://github.com/kubernetes/kubernetes/pull/42717)](https://github.com/kubernetes/kubernetes/pull/42717), [[@andrewsykim](https://github.com/andrewsykim)](https://github.com/andrewsykim)) - - * Upgrade Node Problem Detector to v0.4.1. New features added: - - * Add /dev/kmsg support for kernel log parsing. ([#112](https://github.com/kubernetes/node-problem-detector/pull/112), [[@euank](https://github.com/euank)](https://github.com/euank)) - - * Add ABRT support. ([#105](https://github.com/kubernetes/node-problem-detector/pull/105), [[@juliusmilan](https://github.com/juliusmilan)](https://github.com/juliusmilan)) - - * Add a docker image corruption problem detection in the default docker monitor config. ([#117](https://github.com/kubernetes/node-problem-detector/pull/117), [[@ajitak](https://github.com/ajitak)](https://github.com/ajitak)) - - * Upgrade CAdvisor to v0.26.1. New features added: - - * Add Docker overlay2 storage driver support. - - * Add ZFS support. - - * Add UDP metrics (collection disabled by default). - - * Bug fixes - - * Changed Kubelet default image-gc-high-threshold to 85% to resolve a conflict with default settings in docker that prevented image garbage collection from resolving low disk space situations when using devicemapper storage. ([[#40432](https://github.com/kubernetes/kubernetes/pull/40432)](https://github.com/kubernetes/kubernetes/pull/40432), [[@sjenning](https://github.com/sjenning)](https://github.com/sjenning)) - - * Mark all static pods on the Master node as critical to prevent preemption ([[#47356](https://github.com/kubernetes/kubernetes/pull/47356)](https://github.com/kubernetes/kubernetes/pull/47356), [[@dashpole](https://github.com/dashpole)](https://github.com/dashpole)) - - * Restrict active deadline seconds max allowed value to be maximum uint32 to avoid overflow ([[#46640](https://github.com/kubernetes/kubernetes/pull/46640)](https://github.com/kubernetes/kubernetes/pull/46640), [[@derekwaynecarr](https://github.com/derekwaynecarr)](https://github.com/derekwaynecarr)) - - * Fix a bug with cAdvisorPort in the KubeletConfiguration that prevented setting it to 0, which is in fact a valid option, as noted in issue [[#11710](https://github.com/kubernetes/kubernetes/pull/11710)](https://github.com/kubernetes/kubernetes/pull/11710). ([[#46876](https://github.com/kubernetes/kubernetes/pull/46876)](https://github.com/kubernetes/kubernetes/pull/46876), [[@mtaufen](https://github.com/mtaufen)](https://github.com/mtaufen)) - - * Fix a bug where container cannot run as root when SecurityContext.RunAsNonRoot is false. ([[#47009](https://github.com/kubernetes/kubernetes/pull/47009)](https://github.com/kubernetes/kubernetes/pull/47009), [[@yujuhong](https://github.com/yujuhong)](https://github.com/yujuhong)) - - * Fix the Kubelet PLEG update timestamp to better reflect the health of the component when the container runtime request hangs. ([[#45496](https://github.com/kubernetes/kubernetes/pull/45496)](https://github.com/kubernetes/kubernetes/pull/45496), [[@andyxning](https://github.com/andyxning)](https://github.com/andyxning)) - - * Avoid failing sync loop health check on container runtime errors ([[#47124](https://github.com/kubernetes/kubernetes/pull/47124)](https://github.com/kubernetes/kubernetes/pull/47124), [[@andyxning](https://github.com/andyxning)](https://github.com/andyxning)) - - * Fix a bug where Kubelet does not ignore pod manifest files starting with dots ([[#45111](https://github.com/kubernetes/kubernetes/pull/45111)](https://github.com/kubernetes/kubernetes/pull/45111), [[@dwradcliffe](https://github.com/dwradcliffe)](https://github.com/dwradcliffe)) - - * Changes/deprecations - - * Marks the Kubelet's `--master-service-namespace` flag deprecated ([[#44250](https://github.com/kubernetes/kubernetes/pull/44250)](https://github.com/kubernetes/kubernetes/pull/44250), [[@mtaufen](https://github.com/mtaufen)](https://github.com/mtaufen)) - - * Remove PodSandboxStatus.Linux.Namespaces.Network from CRI since it is not used/needed. ([[#45166](https://github.com/kubernetes/kubernetes/pull/45166)](https://github.com/kubernetes/kubernetes/pull/45166), [[@feiskyer](https://github.com/feiskyer)](https://github.com/feiskyer)) - - * Remove the `--enable-cri` flag. CRI is now the default, and the only way to integrate with Kubelet for the container runtimes.([[#45194](https://github.com/kubernetes/kubernetes/pull/45194)](https://github.com/kubernetes/kubernetes/pull/45194), [[@yujuhong](https://github.com/yujuhong)](https://github.com/yujuhong)) - - * CRI has been moved to package pkg/kubelet/apis/cri/v1alpha1/runtime as part of Kubelet API path cleanup. ([[#47113](https://github.com/kubernetes/kubernetes/pull/47113)](https://github.com/kubernetes/kubernetes/pull/47113), [[@feiskyer](https://github.com/feiskyer)](https://github.com/feiskyer)) - - * Add generic Toleration for NoExecute Taints to NodeProblemDetector, so that NPD can be scheduled to nodes with NoExecute taints by default. ([[#45883](https://github.com/kubernetes/kubernetes/pull/45883)](https://github.com/kubernetes/kubernetes/pull/45883), [[@gmarek](https://github.com/gmarek)](https://github.com/gmarek)) - -* Scheduling - - * NOTE: If you are using `AffinityInAnnotations=true` in `--feature-gates`, then the 1.7 release is your last opportunity to convert from specifying affinity/anti-affinity using the scheduler.alpha.kubernetes.io/affinity annotation on Pods, to using the Affinity field of PodSpec. Support for the alpha version of node and pod affinity (which uses the scheduler.alpha.kubernetes.io/affinity annotations on Pods) is going away **in Kubernetes 1.8** (not this release, but the next release). If you have not enabled AffinityInAnnotations=true in `--feature-gates`, then this change does not affect you. - - * Move hardPodAffinitySymmetricWeight to scheduler policy config ([[#44159](https://github.com/kubernetes/kubernetes/pull/44159)](https://github.com/kubernetes/kubernetes/pull/44159), [[@wanghaoran1988](https://github.com/wanghaoran1988)](https://github.com/wanghaoran1988)) - -* Storage - - * Features - - * The options passed to a Flexvolume plugin's mount command now contains the pod name (kubernetes.io/pod.name), namespace (kubernetes.io/pod.namespace), uid (kubernetes.io/pod.uid), and service account name (kubernetes.io/serviceAccount.name). ([[#39488](https://github.com/kubernetes/kubernetes/pull/39488)](https://github.com/kubernetes/kubernetes/pull/39488), [[@liggitt](https://github.com/liggitt)](https://github.com/liggitt)) - - * GCE and AWS dynamic provisioners extension: admins can configure zone(s) in which a persistent volume shall be created. ([[#38505](https://github.com/kubernetes/kubernetes/pull/38505)](https://github.com/kubernetes/kubernetes/pull/38505), [[@pospispa](https://github.com/pospispa)](https://github.com/pospispa)) - - * Implement API usage metrics for GCE storage. ([[#40338](https://github.com/kubernetes/kubernetes/pull/40338)](https://github.com/kubernetes/kubernetes/pull/40338), [[@gnufied](https://github.com/gnufied)](https://github.com/gnufied)) - - * Add support for emitting metrics from openstack cloudprovider about storage operations. ([[#46008](https://github.com/kubernetes/kubernetes/pull/46008)](https://github.com/kubernetes/kubernetes/pull/46008), [[@NickrenREN](https://github.com/NickrenREN)](https://github.com/NickrenREN)) - - * vSphere cloud provider: vSphere storage policy support for dynamic volume provisioning. ([[#46176](https://github.com/kubernetes/kubernetes/pull/46176)](https://github.com/kubernetes/kubernetes/pull/46176), [[@BaluDontu](https://github.com/BaluDontu)](https://github.com/BaluDontu)) - - * Support StorageClass in Azure file volume ([[#42170](https://github.com/kubernetes/kubernetes/pull/42170)](https://github.com/kubernetes/kubernetes/pull/42170), [[@rootfs](https://github.com/rootfs)](https://github.com/rootfs)) - - * Start recording cloud provider metrics for AWS ([[#43477](https://github.com/kubernetes/kubernetes/pull/43477)](https://github.com/kubernetes/kubernetes/pull/43477), [[@gnufied](https://github.com/gnufied)](https://github.com/gnufied)) - - * Support iSCSI CHAP authentication ([[#43396](https://github.com/kubernetes/kubernetes/pull/43396)](https://github.com/kubernetes/kubernetes/pull/43396), [[@rootfs](https://github.com/rootfs)](https://github.com/rootfs)) - - * Openstack cinder v1/v2/auto API support ([[#40423](https://github.com/kubernetes/kubernetes/pull/40423)](https://github.com/kubernetes/kubernetes/pull/40423), [[@mkutsevol](https://github.com/mkutsevol)](https://github.com/mkutsevol)) - - * Bug-Fixes - - * Fixes issue with Flexvolume, introduced in 1.6.0, where drivers without an attacher would fail (node indefinitely waiting for attach). A driver API addition is introduced: drivers that don't implement attach should return attach: false on init. ([[#47503](https://github.com/kubernetes/kubernetes/pull/47503)](https://github.com/kubernetes/kubernetes/pull/47503), [[@chakri-nelluri](https://github.com/chakri-nelluri)](https://github.com/chakri-nelluri)) - - * Fix dynamic provisioning of PVs with inaccurate AccessModes by refusing to provision when PVCs ask for AccessModes that can't be satisfied by the PVs' underlying volume plugin. ([[#47274](https://github.com/kubernetes/kubernetes/pull/47274)](https://github.com/kubernetes/kubernetes/pull/47274), [[@wongma7](https://github.com/wongma7)](https://github.com/wongma7)) - - * Fix pods failing to start if they specify a file as a volume subPath to mount. ([[#45623](https://github.com/kubernetes/kubernetes/pull/45623)](https://github.com/kubernetes/kubernetes/pull/45623), [[@wongma7](https://github.com/wongma7)](https://github.com/wongma7)) - - * Fix erroneous FailedSync and FailedMount events being periodically and indefinitely posted on Pods after kubelet is restarted. ([[#44781](https://github.com/kubernetes/kubernetes/pull/44781)](https://github.com/kubernetes/kubernetes/pull/44781), [[@wongma7](https://github.com/wongma7)](https://github.com/wongma7)) - - * Fix AWS EBS volumes not getting detached from node if routine to verify volumes are attached runs while the node is down ([[#46463](https://github.com/kubernetes/kubernetes/pull/46463)](https://github.com/kubernetes/kubernetes/pull/46463), [[@wongma7](https://github.com/wongma7)](https://github.com/wongma7)) - - * vSphere cloud provider: Fix volume detach on node failure. ([[#45569](https://github.com/kubernetes/kubernetes/pull/45569)](https://github.com/kubernetes/kubernetes/pull/45569), [[@divyenpatel](https://github.com/divyenpatel)](https://github.com/divyenpatel)) - - * Improves performance of Cinder volume attach/detach operations. ([[#41785](https://github.com/kubernetes/kubernetes/pull/41785)](https://github.com/kubernetes/kubernetes/pull/41785), [[@jamiehannaford](https://github.com/jamiehannaford)](https://github.com/jamiehannaford)) - - * AWS: Process disk attachments even with duplicate NodeNames ([[#47406](https://github.com/kubernetes/kubernetes/pull/47406)](https://github.com/kubernetes/kubernetes/pull/47406), [[@justinsb](https://github.com/justinsb)](https://github.com/justinsb)) - - * Fix iSCSI iSER mounting. ([[#47281](https://github.com/kubernetes/kubernetes/pull/47281)](https://github.com/kubernetes/kubernetes/pull/47281), [[@mtanino](https://github.com/mtanino)](https://github.com/mtanino)) - - * iscsi storage plugin: Fix dangling session when using multiple target portal addresses. ([[#46239](https://github.com/kubernetes/kubernetes/pull/46239)](https://github.com/kubernetes/kubernetes/pull/46239), [[@mtanino](https://github.com/mtanino)](https://github.com/mtanino)) - - * Fix log spam due to unnecessary status update when node is deleted. ([[#45923](https://github.com/kubernetes/kubernetes/pull/45923)](https://github.com/kubernetes/kubernetes/pull/45923), [[@verult](https://github.com/verult)](https://github.com/verult)) - - * Don't try to attach volume to new node if it is already attached to another node and the volume does not support multi-attach. ([[#45346](https://github.com/kubernetes/kubernetes/pull/45346)](https://github.com/kubernetes/kubernetes/pull/45346), [[@codablock](https://github.com/codablock)](https://github.com/codablock)) - - * vSphere cloud provider: Report same Node IP as both internal and external. ([[#45201](https://github.com/kubernetes/kubernetes/pull/45201)](https://github.com/kubernetes/kubernetes/pull/45201), [[@abrarshivani](https://github.com/abrarshivani)](https://github.com/abrarshivani)) - - * detach the volume when pod is terminated ([[#45286](https://github.com/kubernetes/kubernetes/pull/45286)](https://github.com/kubernetes/kubernetes/pull/45286), [[@gnufied](https://github.com/gnufied)](https://github.com/gnufied)) - - * vSphere cloud provider: Filter out IPV6 node addresses. ([[#45181](https://github.com/kubernetes/kubernetes/pull/45181)](https://github.com/kubernetes/kubernetes/pull/45181), [[@BaluDontu](https://github.com/BaluDontu)](https://github.com/BaluDontu)) - - * vSphere cloud provider: Fix fetching of VM UUID on Ubuntu 16.04 and Fedora. ([[#45311](https://github.com/kubernetes/kubernetes/pull/45311)](https://github.com/kubernetes/kubernetes/pull/45311), [[@divyenpatel](https://github.com/divyenpatel)](https://github.com/divyenpatel)) - - * Roll up volume error messages in the kubelet sync loop. ([[#44938](https://github.com/kubernetes/kubernetes/pull/44938)](https://github.com/kubernetes/kubernetes/pull/44938), [[@jayunit100](https://github.com/jayunit100)](https://github.com/jayunit100)) - - * Catch error when failed to make directory in NFS volume plugin ([[#38801](https://github.com/kubernetes/kubernetes/pull/38801)](https://github.com/kubernetes/kubernetes/pull/38801), [[@nak3](https://github.com/nak3)](https://github.com/nak3)) - - * Attention-Required when Upgrading - - * Alpha volume provisioning is removed and default storage class should be used instead. ([[#44090](https://github.com/kubernetes/kubernetes/pull/44090)](https://github.com/kubernetes/kubernetes/pull/44090), [[@NickrenREN](https://github.com/NickrenREN)](https://github.com/NickrenREN)) - - * Portworx volume driver no longer has to run on the master. ([[#45518](https://github.com/kubernetes/kubernetes/pull/45518)](https://github.com/kubernetes/kubernetes/pull/45518), [[@harsh-px](https://github.com/harsh-px)](https://github.com/harsh-px)) - - * Default behaviour in Cinder storageclass is changed. If availability is not specified, the zone is chosen by algorithm. It makes possible to spread stateful pods across many zones. ([[#44798](https://github.com/kubernetes/kubernetes/pull/44798)](https://github.com/kubernetes/kubernetes/pull/44798), [[@zetaab](https://github.com/zetaab)](https://github.com/zetaab)) - -# Unsorted - -* Update kube-dns, metadata-proxy, and fluentd-gcp, event-exporter, prometheus-to-sd, and ip-masq-agent addons with new base images containing fixes for CVE-2016-4448, CVE-2016-9841, CVE-2016-9843, CVE-2017-1000366, CVE-2017-2616, and CVE-2017-9526. ([[#47877](https://github.com/kubernetes/kubernetes/pull/47877)](https://github.com/kubernetes/kubernetes/pull/47877), [[@ixdy](https://github.com/ixdy)](https://github.com/ixdy)) - -* Bump the memory request/limit for ip-masq-daemon. ([[#47887](https://github.com/kubernetes/kubernetes/pull/47887)](https://github.com/kubernetes/kubernetes/pull/47887), [[@dnardo](https://github.com/dnardo)](https://github.com/dnardo)) - -* HostAliases is now parsed with hostAliases json keys to be in line with the feature's name. ([[#47512](https://github.com/kubernetes/kubernetes/pull/47512)](https://github.com/kubernetes/kubernetes/pull/47512), [[@rickypai](https://github.com/rickypai)](https://github.com/rickypai)) - -* ip-masq-agent is now the default for GCE ([[#47794](https://github.com/kubernetes/kubernetes/pull/47794)](https://github.com/kubernetes/kubernetes/pull/47794), [[@dnardo](https://github.com/dnardo)](https://github.com/dnardo)) - -* New 'service.beta.kubernetes.io/aws-load-balancer-extra-security-groups' Service annotation to specify extra Security Groups to be added to ELB created by AWS cloudprovider ([[#45268](https://github.com/kubernetes/kubernetes/pull/45268)](https://github.com/kubernetes/kubernetes/pull/45268), [[@redbaron](https://github.com/redbaron)](https://github.com/redbaron)) - -* AWS: clean up blackhole routes when using kubenet ([[#47572](https://github.com/kubernetes/kubernetes/pull/47572)](https://github.com/kubernetes/kubernetes/pull/47572), [[@justinsb](https://github.com/justinsb)](https://github.com/justinsb)) - -* Tokens retrieved from Google Cloud with application default credentials will not be cached if the client fails authorization ([[#46694](https://github.com/kubernetes/kubernetes/pull/46694)](https://github.com/kubernetes/kubernetes/pull/46694), [[@matt-tyler](https://github.com/matt-tyler)](https://github.com/matt-tyler)) - -* Taints support in gce/salt startup scripts. ([[#47632](https://github.com/kubernetes/kubernetes/pull/47632)](https://github.com/kubernetes/kubernetes/pull/47632), [[@mwielgus](https://github.com/mwielgus)](https://github.com/mwielgus)) - -* Fix VolumeClaims/capacity in `kubectl describe statefulsets` output. ([[#47573](https://github.com/kubernetes/kubernetes/pull/47573)](https://github.com/kubernetes/kubernetes/pull/47573), [[@k82cn](https://github.com/k82cn)](https://github.com/k82cn)) - -* The protobuf serialization of API objects has been updated to store maps in a predictable order to ensure that the representation of that object does not change when saved into etcd. This prevents the same object from being seen as being modified, even when no values have changed. ([[#47701](https://github.com/kubernetes/kubernetes/pull/47701)](https://github.com/kubernetes/kubernetes/pull/47701), [[@smarterclayton](https://github.com/smarterclayton)](https://github.com/smarterclayton)) - -* `kubectl logs` with label selector supports specifying a container name ([[#44282](https://github.com/kubernetes/kubernetes/pull/44282)](https://github.com/kubernetes/kubernetes/pull/44282), [[@derekwaynecarr](https://github.com/derekwaynecarr)](https://github.com/derekwaynecarr)) - -* Adds an approval work flow to the the certificate approver that will approve certificate signing requests from kubelets that meet all the criteria of kubelet server certificates. ([[#46884](https://github.com/kubernetes/kubernetes/pull/46884)](https://github.com/kubernetes/kubernetes/pull/46884), [[@jcbsmpsn](https://github.com/jcbsmpsn)](https://github.com/jcbsmpsn)) - -* AWS: Maintain a cache of all instances, to fix problem with > 200 nodes with ELBs ([[#47410](https://github.com/kubernetes/kubernetes/pull/47410)](https://github.com/kubernetes/kubernetes/pull/47410), [[@justinsb](https://github.com/justinsb)](https://github.com/justinsb)) - -* Bump GLBC version to 0.9.5 - fixes [loss of manually modified GCLB health check settings](https://github.com/kubernetes/kubernetes/issues/47559) upon upgrade from pre-1.6.4 to either 1.6.4 or 1.6.5. ([[#47567](https://github.com/kubernetes/kubernetes/pull/47567)](https://github.com/kubernetes/kubernetes/pull/47567), [[@nicksardo](https://github.com/nicksardo)](https://github.com/nicksardo)) - -* Update cluster-proportional-autoscaler, metadata-proxy, and fluentd-gcp addons with fixes for CVE-2016-4448, CVE-2016-8859, CVE-2016-9841, CVE-2016-9843, and CVE-2017-9526. ([[#47545](https://github.com/kubernetes/kubernetes/pull/47545)](https://github.com/kubernetes/kubernetes/pull/47545), [[@ixdy](https://github.com/ixdy)](https://github.com/ixdy)) - -* AWS: Batch DescribeInstance calls with nodeNames to 150 limit, to stay within AWS filter limits. ([[#47516](https://github.com/kubernetes/kubernetes/pull/47516)](https://github.com/kubernetes/kubernetes/pull/47516), [[@gnufied](https://github.com/gnufied)](https://github.com/gnufied)) - -* AWS: Process disk attachments even with duplicate NodeNames ([[#47406](https://github.com/kubernetes/kubernetes/pull/47406)](https://github.com/kubernetes/kubernetes/pull/47406), [[@justinsb](https://github.com/justinsb)](https://github.com/justinsb)) - -* kubefed will now configure NodeInternalIP as the federation API server endpoint when NodeExternalIP is unavailable for federation API servers exposed as NodePort services ([[#46960](https://github.com/kubernetes/kubernetes/pull/46960)](https://github.com/kubernetes/kubernetes/pull/46960), [[@lukaszo](https://github.com/lukaszo)](https://github.com/lukaszo)) - -* PodSecurityPolicy now recognizes pods that specify runAsNonRoot: false in their security context and does not overwrite the specified value ([[#47073](https://github.com/kubernetes/kubernetes/pull/47073)](https://github.com/kubernetes/kubernetes/pull/47073), [[@Q-Lee](https://github.com/Q-Lee)](https://github.com/Q-Lee)) - -* Update to kube-addon-manager:v6.4-beta.2: kubectl v1.6.4 and refreshed base images ([[#47389](https://github.com/kubernetes/kubernetes/pull/47389)](https://github.com/kubernetes/kubernetes/pull/47389), [[@ixdy](https://github.com/ixdy)](https://github.com/ixdy)) - -* Azure plugin for client auth ([[#43987](https://github.com/kubernetes/kubernetes/pull/43987)](https://github.com/kubernetes/kubernetes/pull/43987), [[@cosmincojocar](https://github.com/cosmincojocar)](https://github.com/cosmincojocar)) - -* AWS: Avoid spurious ELB listener recreation - ignore case when matching protocol ([[#47391](https://github.com/kubernetes/kubernetes/pull/47391)](https://github.com/kubernetes/kubernetes/pull/47391), [[@justinsb](https://github.com/justinsb)](https://github.com/justinsb)) - -* gce kube-up: The Node authorization mode and NodeRestriction admission controller are now enabled ([[#46796](https://github.com/kubernetes/kubernetes/pull/46796)](https://github.com/kubernetes/kubernetes/pull/46796), [[@mikedanese](https://github.com/mikedanese)](https://github.com/mikedanese)) - -* update gophercloud/gophercloud dependency for reauthentication fixes ([[#45545](https://github.com/kubernetes/kubernetes/pull/45545)](https://github.com/kubernetes/kubernetes/pull/45545), [[@stuart-warren](https://github.com/stuart-warren)](https://github.com/stuart-warren)) - -* servicecontroller: Fix node selection logic on initial LB creation ([[#45773](https://github.com/kubernetes/kubernetes/pull/45773)](https://github.com/kubernetes/kubernetes/pull/45773), [[@justinsb](https://github.com/justinsb)](https://github.com/justinsb)) - -* Fix iSCSI iSER mounting. ([[#47281](https://github.com/kubernetes/kubernetes/pull/47281)](https://github.com/kubernetes/kubernetes/pull/47281), [[@mtanino](https://github.com/mtanino)](https://github.com/mtanino)) - -* StorageOS Volume Driver ([[#42156](https://github.com/kubernetes/kubernetes/pull/42156)](https://github.com/kubernetes/kubernetes/pull/42156), [[@croomes](https://github.com/croomes)](https://github.com/croomes)) - - * [StorageOS](http://www.storageos.com/) can be used as a storage provider for Kubernetes. With StorageOS, capacity from local or attached storage is pooled across the cluster, providing converged infrastructure for cloud-native applications. - -* Make gcp auth provider not to override the Auth header if it's already exits ([[#45575](https://github.com/kubernetes/kubernetes/pull/45575)](https://github.com/kubernetes/kubernetes/pull/45575), [[@wanghaoran1988](https://github.com/wanghaoran1988)](https://github.com/wanghaoran1988)) - -* Allow pods to opt out of PodPreset mutation via an annotation on the pod. ([[#44965](https://github.com/kubernetes/kubernetes/pull/44965)](https://github.com/kubernetes/kubernetes/pull/44965), [[@jpeeler](https://github.com/jpeeler)](https://github.com/jpeeler)) +### **Internationalization** * Add Traditional Chinese translation for kubectl ([[#46559](https://github.com/kubernetes/kubernetes/pull/46559)](https://github.com/kubernetes/kubernetes/pull/46559), [[@warmchang](https://github.com/warmchang)](https://github.com/warmchang)) -* Remove Initializers from admission-control in kubernetes-master charm for pre-1.7 ([[#46987](https://github.com/kubernetes/kubernetes/pull/46987)](https://github.com/kubernetes/kubernetes/pull/46987), [[@Cynerva](https://github.com/Cynerva)](https://github.com/Cynerva)) - -* Added state guards to the idle_status messaging in the kubernetes-master charm to make deployment faster on initial deployment. ([[#47183](https://github.com/kubernetes/kubernetes/pull/47183)](https://github.com/kubernetes/kubernetes/pull/47183), [[@chuckbutler](https://github.com/chuckbutler)](https://github.com/chuckbutler)) - -* Bump up Node Problem Detector version to v0.4.0, which added support of parsing log from /dev/kmsg and ABRT. ([[#46743](https://github.com/kubernetes/kubernetes/pull/46743)](https://github.com/kubernetes/kubernetes/pull/46743), [[@Random-Liu](https://github.com/Random-Liu)](https://github.com/Random-Liu)) - -* Deprecated Binding objects in 1.7. ([[#47041](https://github.com/kubernetes/kubernetes/pull/47041)](https://github.com/kubernetes/kubernetes/pull/47041), [[@k82cn](https://github.com/k82cn)](https://github.com/k82cn)) - -* Add secretbox and AES-CBC encryption modes to at rest encryption. AES-CBC is considered superior to AES-GCM because it is resistant to nonce-reuse attacks, and secretbox uses Poly1305 and XSalsa20. ([[#46916](https://github.com/kubernetes/kubernetes/pull/46916)](https://github.com/kubernetes/kubernetes/pull/46916), [[@smarterclayton](https://github.com/smarterclayton)](https://github.com/smarterclayton)) - -* The HorizontalPodAutoscaler controller will now only send updates when it has new status information, reducing the number of writes caused by the controller. ([[#47078](https://github.com/kubernetes/kubernetes/pull/47078)](https://github.com/kubernetes/kubernetes/pull/47078), [[@DirectXMan12](https://github.com/DirectXMan12)](https://github.com/DirectXMan12)) - -* Added exponential backoff to Azure cloudprovider ([[#46660](https://github.com/kubernetes/kubernetes/pull/46660)](https://github.com/kubernetes/kubernetes/pull/46660), [[@jackfrancis](https://github.com/jackfrancis)](https://github.com/jackfrancis)) - -* fixed HostAlias in PodSpec to allow foo.bar hostnames instead of just foo DNS labels. ([[#46809](https://github.com/kubernetes/kubernetes/pull/46809)](https://github.com/kubernetes/kubernetes/pull/46809), [[@rickypai](https://github.com/rickypai)](https://github.com/rickypai)) - -* Implements rolling update for StatefulSets. Updates can be performed using the RollingUpdate, Paritioned, or OnDelete strategies. OnDelete implements the manual behavior from 1.6. status now tracks ([[#46669](https://github.com/kubernetes/kubernetes/pull/46669)](https://github.com/kubernetes/kubernetes/pull/46669), [[@kow3ns](https://github.com/kow3ns)](https://github.com/kow3ns)) - - * replicas, readyReplicas, currentReplicas, and updatedReplicas. The semantics of replicas is now consistent with DaemonSet and ReplicaSet, and readyReplicas has the semantics that replicas did prior to this release. - * Add Japanese translation for kubectl ([[#46756](https://github.com/kubernetes/kubernetes/pull/46756)](https://github.com/kubernetes/kubernetes/pull/46756), [[@girikuncoro](https://github.com/girikuncoro)](https://github.com/girikuncoro)) -* federation: Add admission controller for policy-based placement ([[#44786](https://github.com/kubernetes/kubernetes/pull/44786)](https://github.com/kubernetes/kubernetes/pull/44786), [[@tsandall](https://github.com/tsandall)](https://github.com/tsandall)) - -* Get command uses OpenAPI schema to enhance display for a resource if run with flag 'experimental-use-openapi-print-columns'. ([[#46235](https://github.com/kubernetes/kubernetes/pull/46235)](https://github.com/kubernetes/kubernetes/pull/46235), [[@droot](https://github.com/droot)](https://github.com/droot)) - - * An example command: - - * `kubectl get pods --experimental-use-openapi-print-columns` - -* add gzip compression to GET and LIST requests ([[#45666](https://github.com/kubernetes/kubernetes/pull/45666)](https://github.com/kubernetes/kubernetes/pull/45666), [[@ilackarms](https://github.com/ilackarms)](https://github.com/ilackarms)) - -* Alpha feature: allows users to set storage limit to isolate EmptyDir volumes. It enforces the limit by evicting pods that exceed their storage limits ([[#45686](https://github.com/kubernetes/kubernetes/pull/45686)](https://github.com/kubernetes/kubernetes/pull/45686), [[@jingxu97](https://github.com/jingxu97)](https://github.com/jingxu97)) - -* Adds the Categories []string field to API resources, which represents the list of group aliases (e.g. "all") that every resource belongs to. ([[#43338](https://github.com/kubernetes/kubernetes/pull/43338)](https://github.com/kubernetes/kubernetes/pull/43338), [[@fabianofranz](https://github.com/fabianofranz)](https://github.com/fabianofranz)) - -* Promote kubelet tls bootstrap to beta. Add a non-experimental flag to use it and deprecate the old flag. ([[#46799](https://github.com/kubernetes/kubernetes/pull/46799)](https://github.com/kubernetes/kubernetes/pull/46799), [[@mikedanese](https://github.com/mikedanese)](https://github.com/mikedanese)) - -* Fix disk partition discovery for brtfs ([[#46816](https://github.com/kubernetes/kubernetes/pull/46816)](https://github.com/kubernetes/kubernetes/pull/46816), [[@dashpole](https://github.com/dashpole)](https://github.com/dashpole)) - - * Add ZFS support - - * Add overlay2 storage driver support - -* [beta] Support creation of GCP Internal Load Balancers from Service objects ([[#46663](https://github.com/kubernetes/kubernetes/pull/46663)](https://github.com/kubernetes/kubernetes/pull/46663), [[@nicksardo](https://github.com/nicksardo)](https://github.com/nicksardo)) - -* Introduces status conditions to the HorizontalPodAutoscaler in autoscaling/v2alpha1, indicating the current status of a given HorizontalPodAutoscaler, and why it is or is not scaling. ([[#46550](https://github.com/kubernetes/kubernetes/pull/46550)](https://github.com/kubernetes/kubernetes/pull/46550), [[@DirectXMan12](https://github.com/DirectXMan12)](https://github.com/DirectXMan12)) - -* Support OpenAPI spec aggregation for kube-aggregator ([[#46734](https://github.com/kubernetes/kubernetes/pull/46734)](https://github.com/kubernetes/kubernetes/pull/46734), [[@mbohlool](https://github.com/mbohlool)](https://github.com/mbohlool)) - -* Implement `kubectl rollout undo` and `kubectl rollout history` for DaemonSet ([[#46144](https://github.com/kubernetes/kubernetes/pull/46144)](https://github.com/kubernetes/kubernetes/pull/46144), [[@janetkuo](https://github.com/janetkuo)](https://github.com/janetkuo)) - -* Respect PDBs during node upgrades and add test coverage to the ServiceTest upgrade test. ([[#45748](https://github.com/kubernetes/kubernetes/pull/45748)](https://github.com/kubernetes/kubernetes/pull/45748), [[@mml](https://github.com/mml)](https://github.com/mml)) - -* Add the alpha.image-policy.k8s.io/failed-open=true annotation when the image policy webhook encounters an error and fails open. ([[#46264](https://github.com/kubernetes/kubernetes/pull/46264)](https://github.com/kubernetes/kubernetes/pull/46264), [[@Q-Lee](https://github.com/Q-Lee)](https://github.com/Q-Lee)) - -* Enable kubelet csr bootstrap in GCE/GKE ([[#40760](https://github.com/kubernetes/kubernetes/pull/40760)](https://github.com/kubernetes/kubernetes/pull/40760), [[@mikedanese](https://github.com/mikedanese)](https://github.com/mikedanese)) - -* Implement Daemonset history ([[#45924](https://github.com/kubernetes/kubernetes/pull/45924)](https://github.com/kubernetes/kubernetes/pull/45924), [[@janetkuo](https://github.com/janetkuo)](https://github.com/janetkuo)) - -* When switching from the service.beta.kubernetes.io/external-traffic annotation to the new ([[#46716](https://github.com/kubernetes/kubernetes/pull/46716)](https://github.com/kubernetes/kubernetes/pull/46716), [[@thockin](https://github.com/thockin)](https://github.com/thockin)) - - * externalTrafficPolicy field, the values chnag as follows: * "OnlyLocal" becomes "Local" * "Global" becomes "Cluster". - -* Fix kubelet reset liveness probe failure count across pod restart boundaries ([[#46371](https://github.com/kubernetes/kubernetes/pull/46371)](https://github.com/kubernetes/kubernetes/pull/46371), [[@sjenning](https://github.com/sjenning)](https://github.com/sjenning)) - -* The gce metadata server can be hidden behind a proxy, hiding the kubelet's token. ([[#45565](https://github.com/kubernetes/kubernetes/pull/45565)](https://github.com/kubernetes/kubernetes/pull/45565), [[@Q-Lee](https://github.com/Q-Lee)](https://github.com/Q-Lee)) - -* AWS: Allow configuration of a single security group for ELBs ([[#45500](https://github.com/kubernetes/kubernetes/pull/45500)](https://github.com/kubernetes/kubernetes/pull/45500), [[@nbutton23](https://github.com/nbutton23)](https://github.com/nbutton23)) - -* Allow remote admission controllers to be dynamically added and removed by administrators. External admission controllers make an HTTP POST containing details of the requested action which the service can approve or reject. ([[#46388](https://github.com/kubernetes/kubernetes/pull/46388)](https://github.com/kubernetes/kubernetes/pull/46388), [[@lavalamp](https://github.com/lavalamp)](https://github.com/lavalamp)) - -* iscsi storage plugin: Fix dangling session when using multiple target portal addresses. ([[#46239](https://github.com/kubernetes/kubernetes/pull/46239)](https://github.com/kubernetes/kubernetes/pull/46239), [[@mtanino](https://github.com/mtanino)](https://github.com/mtanino)) - -* Duplicate recurring Events now include the latest event's Message string ([[#46034](https://github.com/kubernetes/kubernetes/pull/46034)](https://github.com/kubernetes/kubernetes/pull/46034), [[@kensimon](https://github.com/kensimon)](https://github.com/kensimon)) - -* With `--feature-gates=RotateKubeletClientCertificate=true` set, the kubelet will ([[#41912](https://github.com/kubernetes/kubernetes/pull/41912)](https://github.com/kubernetes/kubernetes/pull/41912), [[@jcbsmpsn](https://github.com/jcbsmpsn)](https://github.com/jcbsmpsn)) - - * request a client certificate from the API server during the boot cycle and pause - - * waiting for the request to be satisfied. It will continually refresh the certificate - - * as the certificates expiration approaches. - -* The Kubernetes API supports retrieving tabular output for API resources via a new mime-type application/json;as=Table;v=v1alpha1;g=meta.k8s.io. The returned object (if the server supports it) will be of type meta.k8s.io/v1alpha1 with Table, and contain column and row information related to the resource. Each row will contain information about the resource - by default it will be the object metadata, but callers can add the ?includeObject=Object query parameter and receive the full object. In the future kubectl will use this to retrieve the results of `kubectl get`. ([[#40848](https://github.com/kubernetes/kubernetes/pull/40848)](https://github.com/kubernetes/kubernetes/pull/40848), [[@smarterclayton](https://github.com/smarterclayton)](https://github.com/smarterclayton)) - -* `kubectl auth can-i` now supports non-resource URLs ([[#46432](https://github.com/kubernetes/kubernetes/pull/46432)](https://github.com/kubernetes/kubernetes/pull/46432), [[@CaoShuFeng](https://github.com/CaoShuFeng)](https://github.com/CaoShuFeng)) - -* Webhook added to the API server which emits structured audit log events. ([[#45919](https://github.com/kubernetes/kubernetes/pull/45919)](https://github.com/kubernetes/kubernetes/pull/45919), [[@ericchiang](https://github.com/ericchiang)](https://github.com/ericchiang)) - -* `kubectl edit` and `kubectl apply` will keep the ordering of elements in merged lists ([[#45980](https://github.com/kubernetes/kubernetes/pull/45980)](https://github.com/kubernetes/kubernetes/pull/45980), [[@mengqiy](https://github.com/mengqiy)](https://github.com/mengqiy)) - -* [Federation][kubefed]: Use StorageClassName for etcd pvc ([[#46323](https://github.com/kubernetes/kubernetes/pull/46323)](https://github.com/kubernetes/kubernetes/pull/46323), [[@marun](https://github.com/marun)](https://github.com/marun)) - -* Restrict active deadline seconds max allowed value to be maximum uint32 ([[#46640](https://github.com/kubernetes/kubernetes/pull/46640)](https://github.com/kubernetes/kubernetes/pull/46640), [[@derekwaynecarr](https://github.com/derekwaynecarr)](https://github.com/derekwaynecarr)) - -* Implement `kubectl get controllerrevisions` ([[#46655](https://github.com/kubernetes/kubernetes/pull/46655)](https://github.com/kubernetes/kubernetes/pull/46655), [[@janetkuo](https://github.com/janetkuo)](https://github.com/janetkuo)) - -* Local storage plugin ([[#44897](https://github.com/kubernetes/kubernetes/pull/44897)](https://github.com/kubernetes/kubernetes/pull/44897), [[@msau42](https://github.com/msau42)](https://github.com/msau42)) - -* With `--feature-gates=RotateKubeletServerCertificate=true` set, the kubelet will ([[#45059](https://github.com/kubernetes/kubernetes/pull/45059)](https://github.com/kubernetes/kubernetes/pull/45059), [[@jcbsmpsn](https://github.com/jcbsmpsn)](https://github.com/jcbsmpsn)) - - * request a server certificate from the API server during the boot cycle and pause - - * waiting for the request to be satisfied. It will continually refresh the certificate as - - * the certificates expiration approaches. - -* Add `kubectl config rename-context` ([[#46114](https://github.com/kubernetes/kubernetes/pull/46114)](https://github.com/kubernetes/kubernetes/pull/46114), [[@arthur0](https://github.com/arthur0)](https://github.com/arthur0)) - -* Move hardPodAffinitySymmetricWeight to scheduler policy config ([[#44159](https://github.com/kubernetes/kubernetes/pull/44159)](https://github.com/kubernetes/kubernetes/pull/44159), [[@wanghaoran1988](https://github.com/wanghaoran1988)](https://github.com/wanghaoran1988)) - -* AWS: support node port health check ([[#43585](https://github.com/kubernetes/kubernetes/pull/43585)](https://github.com/kubernetes/kubernetes/pull/43585), [[@foolusion](https://github.com/foolusion)](https://github.com/foolusion)) - -* support replaceKeys patch strategy and directive for strategic merge patch ([[#44597](https://github.com/kubernetes/kubernetes/pull/44597)](https://github.com/kubernetes/kubernetes/pull/44597), [[@mengqiy](https://github.com/mengqiy)](https://github.com/mengqiy)) - -* Prevent kubelet from setting allocatable < 0 for a resource upon initial creation. ([[#46516](https://github.com/kubernetes/kubernetes/pull/46516)](https://github.com/kubernetes/kubernetes/pull/46516), [[@derekwaynecarr](https://github.com/derekwaynecarr)](https://github.com/derekwaynecarr)) - -* add `--non-resource-url` to `kubectl create clusterrole` ([[#45809](https://github.com/kubernetes/kubernetes/pull/45809)](https://github.com/kubernetes/kubernetes/pull/45809), [[@CaoShuFeng](https://github.com/CaoShuFeng)](https://github.com/CaoShuFeng)) - -* Add `kubectl apply edit-last-applied` subcommand ([[#42256](https://github.com/kubernetes/kubernetes/pull/42256)](https://github.com/kubernetes/kubernetes/pull/42256), [[@shiywang](https://github.com/shiywang)](https://github.com/shiywang)) - -* Adding admissionregistration API group which enables dynamic registration of initializers and external admission webhooks. It is an alpha feature. ([[#46294](https://github.com/kubernetes/kubernetes/pull/46294)](https://github.com/kubernetes/kubernetes/pull/46294), [[@caesarxuchao](https://github.com/caesarxuchao)](https://github.com/caesarxuchao)) - -* Fix log spam due to unnecessary status update when node is deleted. ([[#45923](https://github.com/kubernetes/kubernetes/pull/45923)](https://github.com/kubernetes/kubernetes/pull/45923), [[@verult](https://github.com/verult)](https://github.com/verult)) - -* GCE installs will now avoid IP masquerade for all RFC-1918 IP blocks, rather than just 10.0.0.0/8. This means that clusters can ([[#46473](https://github.com/kubernetes/kubernetes/pull/46473)](https://github.com/kubernetes/kubernetes/pull/46473), [[@thockin](https://github.com/thockin)](https://github.com/thockin)) - - * be created in 192.168.0.0./16 and 172.16.0.0/12 while preserving the container IPs (which would be lost before). - -* set selector and set subject no longer print "running in local/dry-run mode..." at the top, so their output can be piped as valid yaml or json ([[#46507](https://github.com/kubernetes/kubernetes/pull/46507)](https://github.com/kubernetes/kubernetes/pull/46507), [[@bboreham](https://github.com/bboreham)](https://github.com/bboreham)) - -* ControllerRevision type added for StatefulSet and DaemonSet history. ([[#45867](https://github.com/kubernetes/kubernetes/pull/45867)](https://github.com/kubernetes/kubernetes/pull/45867), [[@kow3ns](https://github.com/kow3ns)](https://github.com/kow3ns)) - -* Bump Go version to 1.8.3 ([[#46429](https://github.com/kubernetes/kubernetes/pull/46429)](https://github.com/kubernetes/kubernetes/pull/46429), [[@wojtek-t](https://github.com/wojtek-t)](https://github.com/wojtek-t)) - -* Upgrade Elasticsearch Addon to v5.4.0 ([[#45589](https://github.com/kubernetes/kubernetes/pull/45589)](https://github.com/kubernetes/kubernetes/pull/45589), [[@it-svit](https://github.com/it-svit)](https://github.com/it-svit)) - -* PodDisruptionBudget now uses ControllerRef to decide which controller owns a given Pod, so it doesn't get confused by controllers with overlapping selectors. ([[#45003](https://github.com/kubernetes/kubernetes/pull/45003)](https://github.com/kubernetes/kubernetes/pull/45003), [[@krmayankk](https://github.com/krmayankk)](https://github.com/krmayankk)) - -* aws: Support for ELB tagging by users ([[#45932](https://github.com/kubernetes/kubernetes/pull/45932)](https://github.com/kubernetes/kubernetes/pull/45932), [[@lpabon](https://github.com/lpabon)](https://github.com/lpabon)) - -* kube-proxy: ratelimit runs of iptables by sync-period flags ([[#46266](https://github.com/kubernetes/kubernetes/pull/46266)](https://github.com/kubernetes/kubernetes/pull/46266), [[@thockin](https://github.com/thockin)](https://github.com/thockin)) - -* Deployments are updated to use (1) a more stable hashing algorithm (fnv) than the previous one (adler) and (2) a hashing collision avoidance mechanism that will ensure new rollouts will not block on hashing collisions anymore. ([[#44774](https://github.com/kubernetes/kubernetes/pull/44774)](https://github.com/kubernetes/kubernetes/pull/44774), [[@kargakis](https://github.com/kargakis)](https://github.com/kargakis)) - -* The Prometheus metrics for the kube-apiserver for tracking incoming API requests and latencies now return the subresource label for correctly attributing the type of API call. ([[#46354](https://github.com/kubernetes/kubernetes/pull/46354)](https://github.com/kubernetes/kubernetes/pull/46354), [[@smarterclayton](https://github.com/smarterclayton)](https://github.com/smarterclayton)) - * Add Simplified Chinese translation for kubectl ([[#45573](https://github.com/kubernetes/kubernetes/pull/45573)](https://github.com/kubernetes/kubernetes/pull/45573), [[@shiywang](https://github.com/shiywang)](https://github.com/shiywang)) -* The `--namespace` flag is now honored for in-cluster clients that have an empty configuration. ([[#46299](https://github.com/kubernetes/kubernetes/pull/46299)](https://github.com/kubernetes/kubernetes/pull/46299), [[@ncdc](https://github.com/ncdc)](https://github.com/ncdc)) +### **kubectl (CLI)** +* Features -* oidc client plugin: reduce round trips and fix scopes requested ([[#45317](https://github.com/kubernetes/kubernetes/pull/45317)](https://github.com/kubernetes/kubernetes/pull/45317), [[@ericchiang](https://github.com/ericchiang)](https://github.com/ericchiang)) + * `kubectl logs` supports specifying a container name when using label selectors ([[#44282](https://github.com/kubernetes/kubernetes/pull/44282)](https://github.com/kubernetes/kubernetes/pull/44282), [[@derekwaynecarr](https://github.com/derekwaynecarr)](https://github.com/derekwaynecarr)) -* Fix init container status reporting when active deadline is exceeded. ([[#46305](https://github.com/kubernetes/kubernetes/pull/46305)](https://github.com/kubernetes/kubernetes/pull/46305), [[@sjenning](https://github.com/sjenning)](https://github.com/sjenning)) + * `kubectl rollout` supports undo and history for DaemonSet ([[#46144](https://github.com/kubernetes/kubernetes/pull/46144)](https://github.com/kubernetes/kubernetes/pull/46144), [[@janetkuo](https://github.com/janetkuo)](https://github.com/janetkuo)) -* Break the 'certificatesigningrequests' controller into a 'csrapprover' controller and 'csrsigner' controller. ([[#45514](https://github.com/kubernetes/kubernetes/pull/45514)](https://github.com/kubernetes/kubernetes/pull/45514), [[@mikedanese](https://github.com/mikedanese)](https://github.com/mikedanese)) + * `kubectl rollout` supports status and history for StatefulSet ([[#46669](https://github.com/kubernetes/kubernetes/pull/46669)](https://github.com/kubernetes/kubernetes/pull/46669), [[@kow3ns](https://github.com/kow3ns)](https://github.com/kow3ns)). -* Modifies kubefed to create and the federation controller manager to use credentials associated with a service account rather than the user's credentials. ([[#42042](https://github.com/kubernetes/kubernetes/pull/42042)](https://github.com/kubernetes/kubernetes/pull/42042), [[@perotinus](https://github.com/perotinus)](https://github.com/perotinus)) + * Implement `kubectl get controllerrevisions` ([[#46655](https://github.com/kubernetes/kubernetes/pull/46655)](https://github.com/kubernetes/kubernetes/pull/46655), [[@janetkuo](https://github.com/janetkuo)](https://github.com/janetkuo)) -* Adds a MaxUnavailable field to PodDisruptionBudget ([[#45587](https://github.com/kubernetes/kubernetes/pull/45587)](https://github.com/kubernetes/kubernetes/pull/45587), [[@foxish](https://github.com/foxish)](https://github.com/foxish)) + * `kubectl create clusterrole` supports `--non-resource-url` ([[#45809](https://github.com/kubernetes/kubernetes/pull/45809)](https://github.com/kubernetes/kubernetes/pull/45809), [[@CaoShuFeng](https://github.com/CaoShuFeng)](https://github.com/CaoShuFeng)) -* The behavior of some watch calls to the server when filtering on fields was incorrect. If watching objects with a filter, when an update was made that no longer matched the filter a DELETE event was correctly sent. However, the object that was returned by that delete was not the (correct) version before the update, but instead, the newer version. That meant the new object was not matched by the filter. This was a regression from behavior between cached watches on the server side and uncached watches, and thus broke downstream API clients. ([[#46223](https://github.com/kubernetes/kubernetes/pull/46223)](https://github.com/kubernetes/kubernetes/pull/46223), [[@smarterclayton](https://github.com/smarterclayton)](https://github.com/smarterclayton)) + * `kubectl logs` and `kubectl attach` support specifying a wait timeout with `--pod-running-timeout` -* `kubefed init` now supports overriding the default etcd image name with the `--etcd-image` parameter. ([[#46247](https://github.com/kubernetes/kubernetes/pull/46247)](https://github.com/kubernetes/kubernetes/pull/46247), [[@marun](https://github.com/marun)](https://github.com/marun)) + * ([[#41813](https://github.com/kubernetes/kubernetes/pull/41813)](https://github.com/kubernetes/kubernetes/pull/41813), [[@shiywang](https://github.com/shiywang)](https://github.com/shiywang)) -* remove the elasticsearch template ([[#45952](https://github.com/kubernetes/kubernetes/pull/45952)](https://github.com/kubernetes/kubernetes/pull/45952), [[@harryge00](https://github.com/harryge00)](https://github.com/harryge00)) + * New commands -* Adds the CustomResourceDefinition (crd) types to the kube-apiserver. These are the successors to ThirdPartyResource. See [https://github.com/kubernetes/community/blob/master/contributors/design-proposals/thirdpartyresources.md](https://github.com/kubernetes/community/blob/master/contributors/design-proposals/thirdpartyresources.md) for more details. ([[#46055](https://github.com/kubernetes/kubernetes/pull/46055)](https://github.com/kubernetes/kubernetes/pull/46055), [[@deads2k](https://github.com/deads2k)](https://github.com/deads2k)) + * Add `kubectl config rename-context` ([[#46114](https://github.com/kubernetes/kubernetes/pull/46114)](https://github.com/kubernetes/kubernetes/pull/46114), [[@arthur0](https://github.com/arthur0)](https://github.com/arthur0)) -* StatefulSets now include an alpha scaling feature accessible by setting the spec.podManagementPolicy field to Parallel. The controller will not wait for pods to be ready before adding the other pods, and will replace deleted pods as needed. Since parallel scaling creates pods out of order, you cannot depend on predictable membership changes within your set. ([[#44899](https://github.com/kubernetes/kubernetes/pull/44899)](https://github.com/kubernetes/kubernetes/pull/44899), [[@smarterclayton](https://github.com/smarterclayton)](https://github.com/smarterclayton)) + * Add `kubectl apply edit-last-applied` subcommand ([[#42256](https://github.com/kubernetes/kubernetes/pull/42256)](https://github.com/kubernetes/kubernetes/pull/42256), [[@shiywang](https://github.com/shiywang)](https://github.com/shiywang)) -* fix kubelet event recording for selected events. ([[#46246](https://github.com/kubernetes/kubernetes/pull/46246)](https://github.com/kubernetes/kubernetes/pull/46246), [[@derekwaynecarr](https://github.com/derekwaynecarr)](https://github.com/derekwaynecarr)) + * Strategic Merge Patch -* Moved qos to api.helpers. ([[#44906](https://github.com/kubernetes/kubernetes/pull/44906)](https://github.com/kubernetes/kubernetes/pull/44906), [[@k82cn](https://github.com/k82cn)](https://github.com/k82cn)) + * Reference docs now display the patch type and patch merge key used by `kubectl apply` to merge and identify unique elements in arrays. -* OpenAPI spec is now available in protobuf binary and gzip format (with ETag support) ([[#45836](https://github.com/kubernetes/kubernetes/pull/45836)](https://github.com/kubernetes/kubernetes/pull/45836), [[@mbohlool](https://github.com/mbohlool)](https://github.com/mbohlool)) + * `kubectl edit` and `kubectl apply` will keep the ordering of elements in merged lists ([[#45980](https://github.com/kubernetes/kubernetes/pull/45980)](https://github.com/kubernetes/kubernetes/pull/45980), [[@mengqiy](https://github.com/mengqiy)](https://github.com/mengqiy)) -* Added support to a hierarchy of kubectl plugins (a tree of plugins as children of other plugins). ([[#45981](https://github.com/kubernetes/kubernetes/pull/45981)](https://github.com/kubernetes/kubernetes/pull/45981), [[@fabianofranz](https://github.com/fabianofranz)](https://github.com/fabianofranz)) + * New patch directive (retainKeys) to specifying clearing fields missing from the request ([[#44597](https://github.com/kubernetes/kubernetes/pull/44597)](https://github.com/kubernetes/kubernetes/pull/44597), [[@mengqiy](https://github.com/mengqiy)](https://github.com/mengqiy)) + + * Open API now includes strategic merge patch tags (previously only in go struct tags) ([[#44121](https://github.com/kubernetes/kubernetes/pull/44121)](https://github.com/kubernetes/kubernetes/pull/44121), [[@mbohlool](https://github.com/mbohlool)](https://github.com/mbohlool)) + + * Plugins + + * Introduces the ability to extend kubectl by adding third-party plugins. Developer preview, please refer to the documentation for instructions about how to use it. ([[#37499](https://github.com/kubernetes/kubernetes/pull/37499)](https://github.com/kubernetes/kubernetes/pull/37499), [[@fabianofranz](https://github.com/fabianofranz)](https://github.com/fabianofranz)) + + * Added support for a hierarchy of kubectl plugins (a tree of plugins as children of other plugins). ([[#45981](https://github.com/kubernetes/kubernetes/pull/45981)](https://github.com/kubernetes/kubernetes/pull/45981), [[@fabianofranz](https://github.com/fabianofranz)](https://github.com/fabianofranz)) + + * Added exported env vars to kubectl plugins so that plugin developers have access to global flags, namespace, the plugin descriptor and the full path to the caller binary. + + * Enhancement + + * `kubectl auth can-i` now supports non-resource URLs ([[#46432](https://github.com/kubernetes/kubernetes/pull/46432)](https://github.com/kubernetes/kubernetes/pull/46432), [[@CaoShuFeng](https://github.com/CaoShuFeng)](https://github.com/CaoShuFeng)) + + * `kubectl set selector` and `kubectl set subject` no longer print "running in local/dry-run mode..." at the top. The output can now be piped and interpretted as yaml or json ([[#46507](https://github.com/kubernetes/kubernetes/pull/46507)](https://github.com/kubernetes/kubernetes/pull/46507), [[@bboreham](https://github.com/bboreham)](https://github.com/bboreham)) + + * When using an in-cluster client with an empty configuration, the `--namespace` flag is now honored ([[#46299](https://github.com/kubernetes/kubernetes/pull/46299)](https://github.com/kubernetes/kubernetes/pull/46299), [[@ncdc](https://github.com/ncdc)](https://github.com/ncdc)) + + * The help message for missingResourceError is now generic ([[#45582](https://github.com/kubernetes/kubernetes/pull/45582)](https://github.com/kubernetes/kubernetes/pull/45582), [[@CaoShuFeng](https://github.com/CaoShuFeng)](https://github.com/CaoShuFeng)) + + * `kubectl taint node` now supports label selectors ([[#44740](https://github.com/kubernetes/kubernetes/pull/44740)](https://github.com/kubernetes/kubernetes/pull/44740), [[@ravisantoshgudimetla](https://github.com/ravisantoshgudimetla)](https://github.com/ravisantoshgudimetla)) + + * `kubectl proxy --www` now logs a warning when the dir is invalid ([[#44952](https://github.com/kubernetes/kubernetes/pull/44952)](https://github.com/kubernetes/kubernetes/pull/44952), [[@CaoShuFeng](https://github.com/CaoShuFeng)](https://github.com/CaoShuFeng)) + + * `kubectl taint` output has been enhanced with the operation ([[#43171](https://github.com/kubernetes/kubernetes/pull/43171)](https://github.com/kubernetes/kubernetes/pull/43171), [[@ravisantoshgudimetla](https://github.com/ravisantoshgudimetla)](https://github.com/ravisantoshgudimetla)) + + * kubectl `--user` and `--cluster` now support completion ([[#44251](https://github.com/kubernetes/kubernetes/pull/44251)](https://github.com/kubernetes/kubernetes/pull/44251), [[@superbrothers](https://github.com/superbrothers)](https://github.com/superbrothers)) + + * `kubectl config use-context` now supports completion ([[#42336](https://github.com/kubernetes/kubernetes/pull/42336)](https://github.com/kubernetes/kubernetes/pull/42336), [[@superbrothers](https://github.com/superbrothers)](https://github.com/superbrothers)) + + * `kubectl version` now supports `--output` ([[#39858](https://github.com/kubernetes/kubernetes/pull/39858)](https://github.com/kubernetes/kubernetes/pull/39858), [[@alejandroEsc](https://github.com/alejandroEsc)](https://github.com/alejandroEsc)) + + * `kubectl create configmap` has a new option `--from-env-file` that populates a configmap from file which follows a key=val format for each line. ([[#38882](https://github.com/kubernetes/kubernetes/pull/38882)](https://github.com/kubernetes/kubernetes/pull/38882), [[@fraenkel](https://github.com/fraenkel)](https://github.com/fraenkel)) + + * `kubectl create secret` has a new option `--from-env-file` that populates a configmap from file which follows a key=val format for each line. + + * Printing/describe + + * Print conditions of RC/RS in `kubectl describe` command. ([[#44710](https://github.com/kubernetes/kubernetes/pull/44710)](https://github.com/kubernetes/kubernetes/pull/44710), [[@xiangpengzhao](https://github.com/xiangpengzhao)](https://github.com/xiangpengzhao)) + + * Improved output on `kubectl get` and `kubectl describe` for generic objects. ([[#44222](https://github.com/kubernetes/kubernetes/pull/44222)](https://github.com/kubernetes/kubernetes/pull/44222), [[@fabianofranz](https://github.com/fabianofranz)](https://github.com/fabianofranz)) + + * In `kubectl describe`, find controllers with ControllerRef, instead of showing the original creator. ([[#42849](https://github.com/kubernetes/kubernetes/pull/42849)](https://github.com/kubernetes/kubernetes/pull/42849), [[@janetkuo](https://github.com/janetkuo)](https://github.com/janetkuo)) + + * `kubectl version` has new flag --output (=json or yaml) allowing result of the command to be parsed in either json format or yaml. ([[#39858](https://github.com/kubernetes/kubernetes/pull/39858)](https://github.com/kubernetes/kubernetes/pull/39858), [[@alejandroEsc](https://github.com/alejandroEsc)](https://github.com/alejandroEsc)) + + + * Bug fixes + + * Fix some false negatives in detection of meaningful conflicts during strategic merge patch with maps and lists. ([[#43469](https://github.com/kubernetes/kubernetes/pull/43469)](https://github.com/kubernetes/kubernetes/pull/43469), [[@enisoc](https://github.com/enisoc)](https://github.com/enisoc)) + + * Fix false positive "meaningful conflict" detection for strategic merge patch with integer values. ([[#44788](https://github.com/kubernetes/kubernetes/pull/44788)](https://github.com/kubernetes/kubernetes/pull/44788), [[@enisoc](https://github.com/enisoc)](https://github.com/enisoc)) + + * Restored the ability of kubectl running inside a pod to consume resource files specifying a different namespace than the one the pod is running in. ([[#44862](https://github.com/kubernetes/kubernetes/pull/44862)](https://github.com/kubernetes/kubernetes/pull/44862), [[@liggitt](https://github.com/liggitt)](https://github.com/liggitt)) + + * Kubectl commands run inside a pod using a kubeconfig file now use the namespace specified in the kubeconfig file, instead of using the pod namespace. If no kubeconfig file is used, or the kubeconfig does not specify a namespace, the pod namespace is still used as a fallback. ([[#44570](https://github.com/kubernetes/kubernetes/pull/44570)](https://github.com/kubernetes/kubernetes/pull/44570), [[@liggitt](https://github.com/liggitt)](https://github.com/liggitt)) + + * Fixed `kubectl cluster-info` dump to support multi-container pod. ([[#44088](https://github.com/kubernetes/kubernetes/pull/44088)](https://github.com/kubernetes/kubernetes/pull/44088), [[@xingzhou](https://github.com/xingzhou)](https://github.com/xingzhou)) + + * Kubectl will print a warning when deleting the current context ([[#42538](https://github.com/kubernetes/kubernetes/pull/42538)](https://github.com/kubernetes/kubernetes/pull/42538), [[@adohe](https://github.com/adohe)](https://github.com/adohe)) + + * Fix VolumeClaims/capacity in `kubectl describe statefulsets` output. ([[#47573](https://github.com/kubernetes/kubernetes/pull/47573)](https://github.com/kubernetes/kubernetes/pull/47573), [[@k82cn](https://github.com/k82cn)](https://github.com/k82cn)) + + * Fixed the output of kubectl taint node command with minor improvements. ([[#43171](https://github.com/kubernetes/kubernetes/pull/43171)](https://github.com/kubernetes/kubernetes/pull/43171), [[@ravisantoshgudimetla](https://github.com/ravisantoshgudimetla)](https://github.com/ravisantoshgudimetla)) + + +### **Networking** +#### Network Policy +* [stable] [NetworkPolicy](https://kubernetes.io/docs/concepts/services-networking/network-policies/) promoted to GA. + * Additionally adds short name "netpol" for networkpolicies ([[#42241](https://github.com/kubernetes/kubernetes/pull/42241)](https://github.com/kubernetes/kubernetes/pull/42241), [[@xiangpengzhao](https://github.com/xiangpengzhao)](https://github.com/xiangpengzhao)) + + +#### Load Balancing +* [stable] Source IP Preservation - change Cloud load-balancer strategy to health-checks and respond to health check only on nodes that host pods for the service. See [Create an External Load Balancer - Preserving the client source IP](https://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/#preserving-the-client-source-ip). + Two annotations have been promoted to API fields: + + * Service.Spec.ExternalTrafficPolicy was 'service.beta.kubernetes.io/external-traffic' annotation. + + * Service.Spec.HealthCheckNodePort was 'service.beta.kubernetes.io/healthcheck-nodeport' annotation. + +### **Node Components** +#### Container Runtime Interface +* [alpha] CRI validation testing, which provides a test framework and a suite of tests to validate that the CRI server implementation meets all the requirements. This allows the CRI runtime developers to verify that their runtime conforms to CRI, without needing to set up Kubernetes components or run Kubernetes end-to-end tests. ([docs](https://github.com/kubernetes/community/blob/master/contributors/devel/cri-validation.md) and [release notes](https://github.com/kubernetes-incubator/cri-tools/releases/tag/v0.1)) ([kubernetes/features#292](https://github.com/kubernetes/features/issues/292)) + +* [alpha] Adds support of container metrics in CRI ([docs PR](https://github.com/kubernetes/community/pull/742)) ([kubernetes/features#290](https://github.com/kubernetes/features/issues/290)) + +* [alpha] Integration with [containerd] (https://github.com/containerd/containerd) , which supports basic pod lifecycle and image management. ([docs](https://github.com/kubernetes-incubator/cri-containerd/blob/master/README.md) and [release notes](https://github.com/kubernetes-incubator/cri-containerd/releases/tag/v0.1.0)) ([kubernetes/features#286](https://github.com/kubernetes/features/issues/286)) + +* [GA] The Docker-CRI implementation is GA. The legacy, non-CRI Docker integration has been completely removed. + +* [beta] [CRI-O](https://github.com/kubernetes-incubator/cri-o) v1.0.0-alpha.0. It has passed all e2e tests. ([release notes](https://github.com/kubernetes-incubator/cri-o/releases/tag/v1.0.0-alpha.0)) + +* [beta] [Frakti](https://github.com/kubernetes/frakti) v1.0. It has passed all node conformance tests. ([release notes](https://github.com/kubernetes/frakti/releases/tag/v1.0)) + + + +### **Scheduling** +#### Scheduler Extender +* [alpha] Support for delegating pod binding to a scheduler extender ([kubernetes/features#270](https://github.com/kubernetes/features/issues/270)) + +### **Storage** +#### Local Storage +* [alpha] This feature adds capacity isolation support for local storage at node, container, and volume levels. See updated [Reserve Compute Resources for System Daemons](https://kubernetes.io/docs/tasks/administer-cluster/reserve-compute-resources/) documentation. + +* [alpha] Make locally attached (non-network attached) storage available as a persistent volume source. For more information, see [Storage Volumes - local](https://kubernetes.io/docs/concepts/storage/volumes/#local). + +#### Volume Plugins +* [stable] Volume plugin for StorageOS provides highly-available cluster-wide persistent volumes from local or attached node storage. See [Persistent Volumes - StorageOS](https://kubernetes.io/docs/concepts/storage/persistent-volumes/#storageos) and [Storage Volumes - StorageOS](https://kubernetes.io/docs/concepts/storage/volumes/#storageos). + +#### Metrics +* [stable] Add support for cloudprovider metrics for storage API calls. See [Controller manager metrics](https://kubernetes.io/docs/concepts/cluster-administration/controller-metrics/) for more information. + +### **Other notable changes** + +#### Admission plugin +* OwnerReferencesPermissionEnforcement admission plugin ignores pods/status. ([[#45747](https://github.com/kubernetes/kubernetes/pull/45747)](https://github.com/kubernetes/kubernetes/pull/45747), [[@derekwaynecarr](https://github.com/derekwaynecarr)](https://github.com/derekwaynecarr)) - * Added exported env vars to kubectl plugins so that plugin developers have access to global flags, namespace, the plugin descriptor and the full path to the caller binary. * Ignored mirror pods in PodPreset admission plugin. ([[#45958](https://github.com/kubernetes/kubernetes/pull/45958)](https://github.com/kubernetes/kubernetes/pull/45958), [[@k82cn](https://github.com/k82cn)](https://github.com/k82cn)) -* Don't try to attach volume to new node if it is already attached to another node and the volume does not support multi-attach. ([[#45346](https://github.com/kubernetes/kubernetes/pull/45346)](https://github.com/kubernetes/kubernetes/pull/45346), [[@codablock](https://github.com/codablock)](https://github.com/codablock)) +#### API Machinery +* The protobuf serialization of API objects has been updated to store maps in a predictable order to ensure that the representation of that object does not change when saved into etcd. This prevents the same object from being seen as being modified, even when no values have changed. ([[#47701](https://github.com/kubernetes/kubernetes/pull/47701)](https://github.com/kubernetes/kubernetes/pull/47701), [[@smarterclayton](https://github.com/smarterclayton)](https://github.com/smarterclayton)) -* The Calico version included in kube-up for GCE has been updated to v2.2. ([[#38169](https://github.com/kubernetes/kubernetes/pull/38169)](https://github.com/kubernetes/kubernetes/pull/38169), [[@caseydavenport](https://github.com/caseydavenport)](https://github.com/caseydavenport)) +* API resource discovery now includes the singularName used to refer to the resource. ([[#43312](https://github.com/kubernetes/kubernetes/pull/43312)](https://github.com/kubernetes/kubernetes/pull/43312), [[@deads2k](https://github.com/deads2k)](https://github.com/deads2k)) -* Kubelet: Fix image garbage collector attempting to remove in-use images. ([[#46121](https://github.com/kubernetes/kubernetes/pull/46121)](https://github.com/kubernetes/kubernetes/pull/46121), [[@Random-Liu](https://github.com/Random-Liu)](https://github.com/Random-Liu)) +* Enhance the garbage collection admission plugin so that a user who doesn't have delete permission of the owning object cannot modify the blockOwnerDeletion field of existing ownerReferences, or add new ownerReferences with blockOwnerDeletion=true ([[#43876](https://github.com/kubernetes/kubernetes/pull/43876)](https://github.com/kubernetes/kubernetes/pull/43876), [[@caesarxuchao](https://github.com/caesarxuchao)](https://github.com/caesarxuchao)) -* Add ip-masq-agent addon to the addons folder which is used in GCE if `--non-masquerade-cidr` is set to 0/0 ([[#46038](https://github.com/kubernetes/kubernetes/pull/46038)](https://github.com/kubernetes/kubernetes/pull/46038), [[@dnardo](https://github.com/dnardo)](https://github.com/dnardo)) - -* Fix serialization of EnforceNodeAllocatable ([[#44606](https://github.com/kubernetes/kubernetes/pull/44606)](https://github.com/kubernetes/kubernetes/pull/44606), [[@ivan4th](https://github.com/ivan4th)](https://github.com/ivan4th)) - -* Add `--write-config-to` flag to kube-proxy to allow users to write the default configuration settings to a file. ([[#45908](https://github.com/kubernetes/kubernetes/pull/45908)](https://github.com/kubernetes/kubernetes/pull/45908), [[@ncdc](https://github.com/ncdc)](https://github.com/ncdc)) - -* The NodeRestriction admission plugin limits the Node and Pod objects a kubelet can modify. In order to be limited by this admission plugin, kubelets must use credentials in the system:nodes group, with a username in the form system:node:. Such kubelets will only be allowed to modify their own Node API object, and only modify Pod API objects that are bound to their node. ([[#45929](https://github.com/kubernetes/kubernetes/pull/45929)](https://github.com/kubernetes/kubernetes/pull/45929), [[@liggitt](https://github.com/liggitt)](https://github.com/liggitt)) - -* vSphere cloud provider: Report same Node IP as both internal and external. ([[#45201](https://github.com/kubernetes/kubernetes/pull/45201)](https://github.com/kubernetes/kubernetes/pull/45201), [[@abrarshivani](https://github.com/abrarshivani)](https://github.com/abrarshivani)) - -* avoid concrete examples for missingResourceError ([[#45582](https://github.com/kubernetes/kubernetes/pull/45582)](https://github.com/kubernetes/kubernetes/pull/45582), [[@CaoShuFeng](https://github.com/CaoShuFeng)](https://github.com/CaoShuFeng)) - -* Fix DNS suffix search list support in Windows kube-proxy. ([[#45642](https://github.com/kubernetes/kubernetes/pull/45642)](https://github.com/kubernetes/kubernetes/pull/45642), [[@JiangtianLi](https://github.com/JiangtianLi)](https://github.com/JiangtianLi)) - -* Fix the bug where StartedAt time is not reported for exited containers. ([[#45977](https://github.com/kubernetes/kubernetes/pull/45977)](https://github.com/kubernetes/kubernetes/pull/45977), [[@yujuhong](https://github.com/yujuhong)](https://github.com/yujuhong)) - -* Update Dashboard version to 1.6.1 ([[#45953](https://github.com/kubernetes/kubernetes/pull/45953)](https://github.com/kubernetes/kubernetes/pull/45953), [[@maciaszczykm](https://github.com/maciaszczykm)](https://github.com/maciaszczykm)) - -* Examples: fixed cassandra mirror detection that assumes an FTP site will always be presented ([[#45965](https://github.com/kubernetes/kubernetes/pull/45965)](https://github.com/kubernetes/kubernetes/pull/45965), [[@pompomJuice](https://github.com/pompomJuice)](https://github.com/pompomJuice)) - -* Removes the deprecated kubelet flag `--babysit-daemons` ([[#44230](https://github.com/kubernetes/kubernetes/pull/44230)](https://github.com/kubernetes/kubernetes/pull/44230), [[@mtaufen](https://github.com/mtaufen)](https://github.com/mtaufen)) - -* [Federation] Automate configuring nameserver in cluster-dns for CoreDNS provider ([[#42895](https://github.com/kubernetes/kubernetes/pull/42895)](https://github.com/kubernetes/kubernetes/pull/42895), [[@shashidharatd](https://github.com/shashidharatd)](https://github.com/shashidharatd)) - -* Add an AEAD encrypting transformer for storing secrets encrypted at rest ([[#41939](https://github.com/kubernetes/kubernetes/pull/41939)](https://github.com/kubernetes/kubernetes/pull/41939), [[@smarterclayton](https://github.com/smarterclayton)](https://github.com/smarterclayton)) - -* Update Minio example ([[#45444](https://github.com/kubernetes/kubernetes/pull/45444)](https://github.com/kubernetes/kubernetes/pull/45444), [[@NitishT](https://github.com/NitishT)](https://github.com/NitishT)) - -* [Federation] Segregate DNS related code to separate controller ([[#45034](https://github.com/kubernetes/kubernetes/pull/45034)](https://github.com/kubernetes/kubernetes/pull/45034), [[@shashidharatd](https://github.com/shashidharatd)](https://github.com/shashidharatd)) - -* API Registration is now in beta. ([[#45247](https://github.com/kubernetes/kubernetes/pull/45247)](https://github.com/kubernetes/kubernetes/pull/45247), [[@mbohlool](https://github.com/mbohlool)](https://github.com/mbohlool)) - -* Allow kcm and scheduler to lock on ConfigMaps. ([[#45739](https://github.com/kubernetes/kubernetes/pull/45739)](https://github.com/kubernetes/kubernetes/pull/45739), [[@timothysc](https://github.com/timothysc)](https://github.com/timothysc)) - -* Fix lint failures on kubernetes-e2e charm ([[#45832](https://github.com/kubernetes/kubernetes/pull/45832)](https://github.com/kubernetes/kubernetes/pull/45832), [[@Cynerva](https://github.com/Cynerva)](https://github.com/Cynerva)) - -* Mirror pods must now indicate the nodeName they are bound to on creation. The mirror pod annotation is now treated as immutable and cannot be added to an existing pod, removed from a pod, or modified. ([[#45775](https://github.com/kubernetes/kubernetes/pull/45775)](https://github.com/kubernetes/kubernetes/pull/45775), [[@liggitt](https://github.com/liggitt)](https://github.com/liggitt)) - -* Updating apiserver to return UID of the deleted resource. Clients can use this UID to verify that the resource was deleted or waiting for finalizers. ([[#45600](https://github.com/kubernetes/kubernetes/pull/45600)](https://github.com/kubernetes/kubernetes/pull/45600), [[@nikhiljindal](https://github.com/nikhiljindal)](https://github.com/nikhiljindal)) - -* OwnerReferencesPermissionEnforcement admission plugin ignores pods/status. ([[#45747](https://github.com/kubernetes/kubernetes/pull/45747)](https://github.com/kubernetes/kubernetes/pull/45747), [[@derekwaynecarr](https://github.com/derekwaynecarr)](https://github.com/derekwaynecarr)) - -* prevent pods/status from touching ownerreferences ([[#45826](https://github.com/kubernetes/kubernetes/pull/45826)](https://github.com/kubernetes/kubernetes/pull/45826), [[@deads2k](https://github.com/deads2k)](https://github.com/deads2k)) - -* Fix lint errors in juju kubernetes master and e2e charms ([[#45494](https://github.com/kubernetes/kubernetes/pull/45494)](https://github.com/kubernetes/kubernetes/pull/45494), [[@ktsakalozos](https://github.com/ktsakalozos)](https://github.com/ktsakalozos)) - -* Ensure that autoscaling/v1 is the preferred version for API discovery when autoscaling/v2alpha1 is enabled. ([[#45741](https://github.com/kubernetes/kubernetes/pull/45741)](https://github.com/kubernetes/kubernetes/pull/45741), [[@DirectXMan12](https://github.com/DirectXMan12)](https://github.com/DirectXMan12)) - -* Promotes Source IP preservation for Virtual IPs to GA. ([[#41162](https://github.com/kubernetes/kubernetes/pull/41162)](https://github.com/kubernetes/kubernetes/pull/41162), [[@MrHohn](https://github.com/MrHohn)](https://github.com/MrHohn)) - - * Two api fields are defined correspondingly: - - * Service.Spec.ExternalTrafficPolicy <- 'service.beta.kubernetes.io/external-traffic' annotation. - - * Service.Spec.HealthCheckNodePort <- 'service.beta.kubernetes.io/healthcheck-nodeport' annotation. - -* the resource quota controller was not adding quota to be resynced at proper interval ([[#45685](https://github.com/kubernetes/kubernetes/pull/45685)](https://github.com/kubernetes/kubernetes/pull/45685), [[@derekwaynecarr](https://github.com/derekwaynecarr)](https://github.com/derekwaynecarr)) - -* fluentd will tolerate all NoExecute Taints when run in gcp configuration. ([[#45715](https://github.com/kubernetes/kubernetes/pull/45715)](https://github.com/kubernetes/kubernetes/pull/45715), [[@gmarek](https://github.com/gmarek)](https://github.com/gmarek)) - -* Added Group/Version/Kind and Action extension to OpenAPI Operations ([[#44787](https://github.com/kubernetes/kubernetes/pull/44787)](https://github.com/kubernetes/kubernetes/pull/44787), [[@mbohlool](https://github.com/mbohlool)](https://github.com/mbohlool)) - -* Updates kube-dns to 1.14.2 ([[#45684](https://github.com/kubernetes/kubernetes/pull/45684)](https://github.com/kubernetes/kubernetes/pull/45684), [[@bowei](https://github.com/bowei)](https://github.com/bowei)) - - * Support kube-master-url flag without kubeconfig - - * Fix concurrent R/Ws in dns.go - - * Fix confusing logging when initialize server - - * Fix printf in cmd/kube-dns/app/server.go - - * Fix version on startup and `--version` flag - - * Support specifying port number for nameserver in stubDomains - -* detach the volume when pod is terminated ([[#45286](https://github.com/kubernetes/kubernetes/pull/45286)](https://github.com/kubernetes/kubernetes/pull/45286), [[@gnufied](https://github.com/gnufied)](https://github.com/gnufied)) - -* Don't append :443 to registry domain in the kubernetes-worker layer registry action ([[#45550](https://github.com/kubernetes/kubernetes/pull/45550)](https://github.com/kubernetes/kubernetes/pull/45550), [[@jacekn](https://github.com/jacekn)](https://github.com/jacekn)) - -* AWS: Remove check that forces loadBalancerSourceRanges to be 0.0.0.0/0. ([[#38636](https://github.com/kubernetes/kubernetes/pull/38636)](https://github.com/kubernetes/kubernetes/pull/38636), [[@dhawal55](https://github.com/dhawal55)](https://github.com/dhawal55)) - -* azure: add support for UDP ports ([[#45523](https://github.com/kubernetes/kubernetes/pull/45523)](https://github.com/kubernetes/kubernetes/pull/45523), [[@colemickens](https://github.com/colemickens)](https://github.com/colemickens)) - - * azure: fix support for multiple loadBalancerSourceRanges - - * azure: support the Service spec's sessionAffinity - -* The fix makes scheduling go routine waiting for cache (e.g. Pod) to be synced. ([[#45453](https://github.com/kubernetes/kubernetes/pull/45453)](https://github.com/kubernetes/kubernetes/pull/45453), [[@k82cn](https://github.com/k82cn)](https://github.com/k82cn)) - -* vSphere cloud provider: Filter out IPV6 node addresses. ([[#45181](https://github.com/kubernetes/kubernetes/pull/45181)](https://github.com/kubernetes/kubernetes/pull/45181), [[@BaluDontu](https://github.com/BaluDontu)](https://github.com/BaluDontu)) - -* A small clean up to remove unnecessary functions. ([[#45018](https://github.com/kubernetes/kubernetes/pull/45018)](https://github.com/kubernetes/kubernetes/pull/45018), [[@ravisantoshgudimetla](https://github.com/ravisantoshgudimetla)](https://github.com/ravisantoshgudimetla)) - -* Removed old scheduler constructor. ([[#45472](https://github.com/kubernetes/kubernetes/pull/45472)](https://github.com/kubernetes/kubernetes/pull/45472), [[@k82cn](https://github.com/k82cn)](https://github.com/k82cn)) - -* vSphere cloud provider: Fix fetching of VM UUID on Ubuntu 16.04 and Fedora. ([[#45311](https://github.com/kubernetes/kubernetes/pull/45311)](https://github.com/kubernetes/kubernetes/pull/45311), [[@divyenpatel](https://github.com/divyenpatel)](https://github.com/divyenpatel)) - -* This fixes the overflow for priorityconfig- valid range {1, 9223372036854775806}. ([[#45122](https://github.com/kubernetes/kubernetes/pull/45122)](https://github.com/kubernetes/kubernetes/pull/45122), [[@ravisantoshgudimetla](https://github.com/ravisantoshgudimetla)](https://github.com/ravisantoshgudimetla)) - -* Bump cluster autoscaler to v0.5.4, which fixes scale down issues with pods ignoring SIGTERM. ([[#45483](https://github.com/kubernetes/kubernetes/pull/45483)](https://github.com/kubernetes/kubernetes/pull/45483), [[@mwielgus](https://github.com/mwielgus)](https://github.com/mwielgus)) - -* Remove deprecated node address type NodeLegacyHostIP. ([[#44830](https://github.com/kubernetes/kubernetes/pull/44830)](https://github.com/kubernetes/kubernetes/pull/44830), [[@NickrenREN](https://github.com/NickrenREN)](https://github.com/NickrenREN)) - -* UIDs and GIDs now use apimachinery types ([[#44714](https://github.com/kubernetes/kubernetes/pull/44714)](https://github.com/kubernetes/kubernetes/pull/44714), [[@jamiehannaford](https://github.com/jamiehannaford)](https://github.com/jamiehannaford)) - -* Enable basic auth username rotation for GCI ([[#44590](https://github.com/kubernetes/kubernetes/pull/44590)](https://github.com/kubernetes/kubernetes/pull/44590), [[@ihmccreery](https://github.com/ihmccreery)](https://github.com/ihmccreery)) - -* `kubectl taint node` based on label selector ([[#44740](https://github.com/kubernetes/kubernetes/pull/44740)](https://github.com/kubernetes/kubernetes/pull/44740), [[@ravisantoshgudimetla](https://github.com/ravisantoshgudimetla)](https://github.com/ravisantoshgudimetla)) - -* Scheduler perf modular extensions. ([[#44770](https://github.com/kubernetes/kubernetes/pull/44770)](https://github.com/kubernetes/kubernetes/pull/44770), [[@ravisantoshgudimetla](https://github.com/ravisantoshgudimetla)](https://github.com/ravisantoshgudimetla)) - -* Use Docker API Version instead of docker version ([[#44068](https://github.com/kubernetes/kubernetes/pull/44068)](https://github.com/kubernetes/kubernetes/pull/44068), [[@mkumatag](https://github.com/mkumatag)](https://github.com/mkumatag)) - -* bump(golang.org/x/oauth2): a6bd8cefa1811bd24b86f8902872e4e8225f74c4 ([[#45056](https://github.com/kubernetes/kubernetes/pull/45056)](https://github.com/kubernetes/kubernetes/pull/45056), [[@ericchiang](https://github.com/ericchiang)](https://github.com/ericchiang)) - -* apimachinery: make explicit that meta.KindToResource is only a guess ([[#45272](https://github.com/kubernetes/kubernetes/pull/45272)](https://github.com/kubernetes/kubernetes/pull/45272), [[@sttts](https://github.com/sttts)](https://github.com/sttts)) - -* Fixed misspelled http URL in the cluster-dns example ([[#45246](https://github.com/kubernetes/kubernetes/pull/45246)](https://github.com/kubernetes/kubernetes/pull/45246), [[@psiwczak](https://github.com/psiwczak)](https://github.com/psiwczak)) - -* separate discovery from the apiserver ([[#43003](https://github.com/kubernetes/kubernetes/pull/43003)](https://github.com/kubernetes/kubernetes/pull/43003), [[@deads2k](https://github.com/deads2k)](https://github.com/deads2k)) - -* Remove the `--secret-name` flag from `kubefed join`, instead generating the secret name arbitrarily. ([[#42513](https://github.com/kubernetes/kubernetes/pull/42513)](https://github.com/kubernetes/kubernetes/pull/42513), [[@perotinus](https://github.com/perotinus)](https://github.com/perotinus)) - -* Added InterPodAffinity unit test case with Namespace. ([[#45152](https://github.com/kubernetes/kubernetes/pull/45152)](https://github.com/kubernetes/kubernetes/pull/45152), [[@k82cn](https://github.com/k82cn)](https://github.com/k82cn)) - -* Use munged semantic version for side-loaded docker tag ([[#44981](https://github.com/kubernetes/kubernetes/pull/44981)](https://github.com/kubernetes/kubernetes/pull/44981), [[@ixdy](https://github.com/ixdy)](https://github.com/ixdy)) - -* Increase Dashboard's memory requests and limits ([[#44712](https://github.com/kubernetes/kubernetes/pull/44712)](https://github.com/kubernetes/kubernetes/pull/44712), [[@maciaszczykm](https://github.com/maciaszczykm)](https://github.com/maciaszczykm)) - -* Create and push a docker image for the cloud-controller-manager ([[#45154](https://github.com/kubernetes/kubernetes/pull/45154)](https://github.com/kubernetes/kubernetes/pull/45154), [[@luxas](https://github.com/luxas)](https://github.com/luxas)) - -* Align Extender's validation with prioritizers. ([[#45091](https://github.com/kubernetes/kubernetes/pull/45091)](https://github.com/kubernetes/kubernetes/pull/45091), [[@k82cn](https://github.com/k82cn)](https://github.com/k82cn)) - -* Retry calls we report config changes quickly. ([[#44959](https://github.com/kubernetes/kubernetes/pull/44959)](https://github.com/kubernetes/kubernetes/pull/44959), [[@ktsakalozos](https://github.com/ktsakalozos)](https://github.com/ktsakalozos)) - -* Added CIFS PV support for Juju Charms ([[#45117](https://github.com/kubernetes/kubernetes/pull/45117)](https://github.com/kubernetes/kubernetes/pull/45117), [[@chuckbutler](https://github.com/chuckbutler)](https://github.com/chuckbutler)) - -* add APIService conditions ([[#43301](https://github.com/kubernetes/kubernetes/pull/43301)](https://github.com/kubernetes/kubernetes/pull/43301), [[@deads2k](https://github.com/deads2k)](https://github.com/deads2k)) - -* Log warning when invalid dir passed to `kubectl proxy --www` ([[#44952](https://github.com/kubernetes/kubernetes/pull/44952)](https://github.com/kubernetes/kubernetes/pull/44952), [[@CaoShuFeng](https://github.com/CaoShuFeng)](https://github.com/CaoShuFeng)) - -* Roll up volume error messages in the kubelet sync loop. ([[#44938](https://github.com/kubernetes/kubernetes/pull/44938)](https://github.com/kubernetes/kubernetes/pull/44938), [[@jayunit100](https://github.com/jayunit100)](https://github.com/jayunit100)) - -* Introduces the ability to extend kubectl by adding third-party plugins. Developer preview, please refer to the documentation for instructions about how to use it. ([[#37499](https://github.com/kubernetes/kubernetes/pull/37499)](https://github.com/kubernetes/kubernetes/pull/37499), [[@fabianofranz](https://github.com/fabianofranz)](https://github.com/fabianofranz)) - -* Fixes juju kubernetes master: 1. Get certs from a dead leader. 2. Append tokens. ([[#43620](https://github.com/kubernetes/kubernetes/pull/43620)](https://github.com/kubernetes/kubernetes/pull/43620), [[@ktsakalozos](https://github.com/ktsakalozos)](https://github.com/ktsakalozos)) - -* Use correct option name in the kubernetes-worker layer registry action ([[#44921](https://github.com/kubernetes/kubernetes/pull/44921)](https://github.com/kubernetes/kubernetes/pull/44921), [[@jacekn](https://github.com/jacekn)](https://github.com/jacekn)) - -* Start recording cloud provider metrics for AWS ([[#43477](https://github.com/kubernetes/kubernetes/pull/43477)](https://github.com/kubernetes/kubernetes/pull/43477), [[@gnufied](https://github.com/gnufied)](https://github.com/gnufied)) - -* Add metrics to all major gce operations {latency, errors} ([[#44510](https://github.com/kubernetes/kubernetes/pull/44510)](https://github.com/kubernetes/kubernetes/pull/44510), [[@bowei](https://github.com/bowei)](https://github.com/bowei)) - - * The new metrics are: - - * cloudprovider_gce_api_request_duration_seconds{request, region, zone} - - * cloudprovider_gce_api_request_errors{request, region, zone} - - * request is the specific function that is used. - - * region is the target region (Will be "" if not applicable) - - * zone is the target zone (Will be "" if not applicable) - - * Note: this fixes some issues with the previous implementation of - - * metrics for disks: - - * Time duration tracked was of the initial API call, not the entire - - * operation. - - * Metrics label tuple would have resulted in many independent - - * histograms stored, one for each disk. (Did not aggregate well). - -* Update kubernetes-e2e charm to use snaps ([[#45044](https://github.com/kubernetes/kubernetes/pull/45044)](https://github.com/kubernetes/kubernetes/pull/45044), [[@Cynerva](https://github.com/Cynerva)](https://github.com/Cynerva)) - -* Log the error (if any) in e2e metrics gathering step ([[#45039](https://github.com/kubernetes/kubernetes/pull/45039)](https://github.com/kubernetes/kubernetes/pull/45039), [[@shyamjvs](https://github.com/shyamjvs)](https://github.com/shyamjvs)) +* Exec and portforward actions over SPDY now properly handle redirects sent by the Kubelet ([[#44451](https://github.com/kubernetes/kubernetes/pull/44451)](https://github.com/kubernetes/kubernetes/pull/44451), [[@ncdc](https://github.com/ncdc)](https://github.com/ncdc)) * The proxy subresource APIs for nodes, services, and pods now support the HTTP PATCH method. ([[#44929](https://github.com/kubernetes/kubernetes/pull/44929)](https://github.com/kubernetes/kubernetes/pull/44929), [[@liggitt](https://github.com/liggitt)](https://github.com/liggitt)) -* cluster-autoscaler: Fix duplicate writing of logs. ([[#45017](https://github.com/kubernetes/kubernetes/pull/45017)](https://github.com/kubernetes/kubernetes/pull/45017), [[@MaciekPytel](https://github.com/MaciekPytel)](https://github.com/MaciekPytel)) +* The Categories []string field on discovered API resources represents the list of group aliases (e.g. "all") that each resource belongs to. ([[#43338](https://github.com/kubernetes/kubernetes/pull/43338)](https://github.com/kubernetes/kubernetes/pull/43338), [[@fabianofranz](https://github.com/fabianofranz)](https://github.com/fabianofranz)) -* CRI: Fix StopContainer timeout ([[#44970](https://github.com/kubernetes/kubernetes/pull/44970)](https://github.com/kubernetes/kubernetes/pull/44970), [[@Random-Liu](https://github.com/Random-Liu)](https://github.com/Random-Liu)) +* [alpha] The Kubernetes API supports retrieving tabular output for API resources via a new mime-type application/json;as=Table;v=v1alpha1;g=meta.k8s.io. The returned object (if the server supports it) will be of type meta.k8s.io/v1alpha1 with Table, and contain column and row information related to the resource. Each row will contain information about the resource - by default it will be the object metadata, but callers can add the ?includeObject=Object query parameter and receive the full object. In the future kubectl will use this to retrieve the results of `kubectl get`. ([[#40848](https://github.com/kubernetes/kubernetes/pull/40848)](https://github.com/kubernetes/kubernetes/pull/40848), [[@smarterclayton](https://github.com/smarterclayton)](https://github.com/smarterclayton)) -* Fixes a bug where pods were evicted even after images are successfully deleted. ([[#44986](https://github.com/kubernetes/kubernetes/pull/44986)](https://github.com/kubernetes/kubernetes/pull/44986), [[@dashpole](https://github.com/dashpole)](https://github.com/dashpole)) +* The behavior of some watch calls to the server when filtering on fields was incorrect. If watching objects with a filter, when an update was made that no longer matched the filter a DELETE event was correctly sent. However, the object that was returned by that delete was not the (correct) version before the update, but instead, the newer version. That meant the new object was not matched by the filter. This was a regression from behavior between cached watches on the server side and uncached watches, and thus broke downstream API clients. ([[#46223](https://github.com/kubernetes/kubernetes/pull/46223)](https://github.com/kubernetes/kubernetes/pull/46223), [[@smarterclayton](https://github.com/smarterclayton)](https://github.com/smarterclayton)) -* Fix some false negatives in detection of meaningful conflicts during strategic merge patch with maps and lists. ([[#43469](https://github.com/kubernetes/kubernetes/pull/43469)](https://github.com/kubernetes/kubernetes/pull/43469), [[@enisoc](https://github.com/enisoc)](https://github.com/enisoc)) +* OpenAPI spec is now available in protobuf binary and gzip format (with ETag support) ([[#45836](https://github.com/kubernetes/kubernetes/pull/45836)](https://github.com/kubernetes/kubernetes/pull/45836), [[@mbohlool](https://github.com/mbohlool)](https://github.com/mbohlool)) -* kubernetes-master juju charm properly detects etcd-scale events and reconfigures appropriately. ([[#44967](https://github.com/kubernetes/kubernetes/pull/44967)](https://github.com/kubernetes/kubernetes/pull/44967), [[@chuckbutler](https://github.com/chuckbutler)](https://github.com/chuckbutler)) +* Updating apiserver to return UID of the deleted resource. Clients can use this UID to verify that the resource was deleted or waiting for finalizers. ([[#45600](https://github.com/kubernetes/kubernetes/pull/45600)](https://github.com/kubernetes/kubernetes/pull/45600), [[@nikhiljindal](https://github.com/nikhiljindal)](https://github.com/nikhiljindal)) -* Add redirect support to SpdyRoundTripper ([[#44451](https://github.com/kubernetes/kubernetes/pull/44451)](https://github.com/kubernetes/kubernetes/pull/44451), [[@ncdc](https://github.com/ncdc)](https://github.com/ncdc)) +* Fix incorrect conflict errors applying strategic merge patches to resources. ([[#43871](https://github.com/kubernetes/kubernetes/pull/43871)](https://github.com/kubernetes/kubernetes/pull/43871), [[@liggitt](https://github.com/liggitt)](https://github.com/liggitt)) -* Support running Ubuntu image on GCE node ([[#44744](https://github.com/kubernetes/kubernetes/pull/44744)](https://github.com/kubernetes/kubernetes/pull/44744), [[@yguo0905](https://github.com/yguo0905)](https://github.com/yguo0905)) +* Fix init container status reporting when active deadline is exceeded. ([[#46305](https://github.com/kubernetes/kubernetes/pull/46305)](https://github.com/kubernetes/kubernetes/pull/46305), [[@sjenning](https://github.com/sjenning)](https://github.com/sjenning)) -* Send dns details only after cdk-addons are configured ([[#44945](https://github.com/kubernetes/kubernetes/pull/44945)](https://github.com/kubernetes/kubernetes/pull/44945), [[@ktsakalozos](https://github.com/ktsakalozos)](https://github.com/ktsakalozos)) +* Moved qos to api.helpers. ([[#44906](https://github.com/kubernetes/kubernetes/pull/44906)](https://github.com/kubernetes/kubernetes/pull/44906), [[@k82cn](https://github.com/k82cn)](https://github.com/k82cn)) -* Added support to the pause action in the kubernetes-worker charm for new flag `--delete-local-data` ([[#44931](https://github.com/kubernetes/kubernetes/pull/44931)](https://github.com/kubernetes/kubernetes/pull/44931), [[@chuckbutler](https://github.com/chuckbutler)](https://github.com/chuckbutler)) +* Fix issue with the resource quota controller causing add quota to be resynced at the wrong ([[#45685](https://github.com/kubernetes/kubernetes/pull/45685)](https://github.com/kubernetes/kubernetes/pull/45685), [[@derekwaynecarr](https://github.com/derekwaynecarr)](https://github.com/derekwaynecarr)) -* Upgrade go version to v1.8 ([[#41636](https://github.com/kubernetes/kubernetes/pull/41636)](https://github.com/kubernetes/kubernetes/pull/41636), [[@luxas](https://github.com/luxas)](https://github.com/luxas)) +* Added Group/Version/Kind and Action extension to OpenAPI Operations ([[#44787](https://github.com/kubernetes/kubernetes/pull/44787)](https://github.com/kubernetes/kubernetes/pull/44787), [[@mbohlool](https://github.com/mbohlool)](https://github.com/mbohlool)) -* Add namespace-{list, create, delete} actions to the kubernetes-master layer ([[#44277](https://github.com/kubernetes/kubernetes/pull/44277)](https://github.com/kubernetes/kubernetes/pull/44277), [[@jacekn](https://github.com/jacekn)](https://github.com/jacekn)) +* Make clear that meta.KindToResource is only a guess ([[#45272](https://github.com/kubernetes/kubernetes/pull/45272)](https://github.com/kubernetes/kubernetes/pull/45272), [[@sttts](https://github.com/sttts)](https://github.com/sttts)) -* Fix problems with scaling up the cluster when unschedulable pods have some persistent volume claims. ([[#44860](https://github.com/kubernetes/kubernetes/pull/44860)](https://github.com/kubernetes/kubernetes/pull/44860), [[@mwielgus](https://github.com/mwielgus)](https://github.com/mwielgus)) +* Add APIService conditions ([[#43301](https://github.com/kubernetes/kubernetes/pull/43301)](https://github.com/kubernetes/kubernetes/pull/43301), [[@deads2k](https://github.com/deads2k)](https://github.com/deads2k)) -* Feature/hpa upscale downscale delay configurable ([[#42101](https://github.com/kubernetes/kubernetes/pull/42101)](https://github.com/kubernetes/kubernetes/pull/42101), [[@Dmitry1987](https://github.com/Dmitry1987)](https://github.com/Dmitry1987)) +* Create and push a docker image for the cloud-controller-manager ([[#45154](https://github.com/kubernetes/kubernetes/pull/45154)](https://github.com/kubernetes/kubernetes/pull/45154), [[@luxas](https://github.com/luxas)](https://github.com/luxas)) -* Add short name "netpol" for networkpolicies ([[#42241](https://github.com/kubernetes/kubernetes/pull/42241)](https://github.com/kubernetes/kubernetes/pull/42241), [[@xiangpengzhao](https://github.com/xiangpengzhao)](https://github.com/xiangpengzhao)) +* Deprecated Binding objects in 1.7. ([[#47041](https://github.com/kubernetes/kubernetes/pull/47041)](https://github.com/kubernetes/kubernetes/pull/47041), [[@k82cn](https://github.com/k82cn)](https://github.com/k82cn)) -* Restored the ability of kubectl running inside a pod to consume resource files specifying a different namespace than the one the pod is running in. ([[#44862](https://github.com/kubernetes/kubernetes/pull/44862)](https://github.com/kubernetes/kubernetes/pull/44862), [[@liggitt](https://github.com/liggitt)](https://github.com/liggitt)) +* Adds the Categories []string field to API resources, which represents the list of group aliases (e.g. "all") that every resource belongs to. ([[#43338](https://github.com/kubernetes/kubernetes/pull/43338)](https://github.com/kubernetes/kubernetes/pull/43338), [[@fabianofranz](https://github.com/fabianofranz)](https://github.com/fabianofranz)) -* e2e: handle nil ReplicaSet in checkDeploymentRevision ([[#44859](https://github.com/kubernetes/kubernetes/pull/44859)](https://github.com/kubernetes/kubernetes/pull/44859), [[@sttts](https://github.com/sttts)](https://github.com/sttts)) +* `--service-account-lookup` now defaults to true, requiring the Secret API object containing the token to exist in order for a service account token to be valid. This enables service account tokens to be revoked by deleting the Secret object containing the token. ([[#44071](https://github.com/kubernetes/kubernetes/pull/44071)](https://github.com/kubernetes/kubernetes/pull/44071), [[@liggitt](https://github.com/liggitt)](https://github.com/liggitt)) -* Fix false positive "meaningful conflict" detection for strategic merge patch with integer values. ([[#44788](https://github.com/kubernetes/kubernetes/pull/44788)](https://github.com/kubernetes/kubernetes/pull/44788), [[@enisoc](https://github.com/enisoc)](https://github.com/enisoc)) +* API Registration is now in beta. ([[#45247](https://github.com/kubernetes/kubernetes/pull/45247)](https://github.com/kubernetes/kubernetes/pull/45247), [[@mbohlool](https://github.com/mbohlool)](https://github.com/mbohlool)) -* Documented NodePort networking for CDK. ([[#44863](https://github.com/kubernetes/kubernetes/pull/44863)](https://github.com/kubernetes/kubernetes/pull/44863), [[@chuckbutler](https://github.com/chuckbutler)](https://github.com/chuckbutler)) +* The Kubernetes API server now exits if it encounters a networking failure (e.g. the networking interface hosting its address goes away) to allow a process manager (systemd/kubelet/etc) to react to the problem. Previously the server would log the failure and try again to bind to its configured address:port. ([[#42272](https://github.com/kubernetes/kubernetes/pull/42272)](https://github.com/kubernetes/kubernetes/pull/42272), [[@marun](https://github.com/marun)](https://github.com/marun)) -* Deployments and DaemonSets are now considered complete once all of the new pods are up and running - affects kubectl rollout status (and ProgressDeadlineSeconds for Deployments) ([[#44672](https://github.com/kubernetes/kubernetes/pull/44672)](https://github.com/kubernetes/kubernetes/pull/44672), [[@kargakis](https://github.com/kargakis)](https://github.com/kargakis)) +* The Prometheus metrics for the kube-apiserver for tracking incoming API requests and latencies now return the subresource label for correctly attributing the type of API call. ([[#46354](https://github.com/kubernetes/kubernetes/pull/46354)](https://github.com/kubernetes/kubernetes/pull/46354), [[@smarterclayton](https://github.com/smarterclayton)](https://github.com/smarterclayton)) -* Exclude nodes labeled as master from LoadBalancer / NodePort; restores documented behaviour. ([[#44745](https://github.com/kubernetes/kubernetes/pull/44745)](https://github.com/kubernetes/kubernetes/pull/44745), [[@justinsb](https://github.com/justinsb)](https://github.com/justinsb)) +* kube-apiserver now drops unneeded path information if an older version of Windows kubectl sends it. ([[#44421](https://github.com/kubernetes/kubernetes/pull/44421)](https://github.com/kubernetes/kubernetes/pull/44421), [[@mml](https://github.com/mml)](https://github.com/mml)) -* Fixes issue during LB creation where ports where incorrectly assigned to a floating IP ([[#44387](https://github.com/kubernetes/kubernetes/pull/44387)](https://github.com/kubernetes/kubernetes/pull/44387), [[@jamiehannaford](https://github.com/jamiehannaford)](https://github.com/jamiehannaford)) -* Remove redis-proxy.yaml sample, as the image is nowhere to be found. ([[#44801](https://github.com/kubernetes/kubernetes/pull/44801)](https://github.com/kubernetes/kubernetes/pull/44801), [[@klausenbusk](https://github.com/klausenbusk)](https://github.com/klausenbusk)) +#### Application autoscaling +* Make "upscale forbidden window" and "downscale forbidden window" duration configurable in arguments of kube-controller-manager. ([[#42101](https://github.com/kubernetes/kubernetes/pull/42101)](https://github.com/kubernetes/kubernetes/pull/42101), [[@Dmitry1987](https://github.com/Dmitry1987)](https://github.com/Dmitry1987)) -* Resolves juju vsphere hostname bug showing only a single node in a scaled node-pool. ([[#44780](https://github.com/kubernetes/kubernetes/pull/44780)](https://github.com/kubernetes/kubernetes/pull/44780), [[@chuckbutler](https://github.com/chuckbutler)](https://github.com/chuckbutler)) +#### Application Deployment +* StatefulSetStatus now tracks replicas, readyReplicas, currentReplicas, and updatedReplicas. The semantics of replicas is now consistent with DaemonSet and ReplicaSet, and readyReplicas has the semantics that replicas did prior to 1.7 ([[#46669](https://github.com/kubernetes/kubernetes/pull/46669)](https://github.com/kubernetes/kubernetes/pull/46669), [[@kow3ns](https://github.com/kow3ns)](https://github.com/kow3ns)). -* kubectl commands run inside a pod using a kubeconfig file now use the namespace specified in the kubeconfig file, instead of using the pod namespace. If no kubeconfig file is used, or the kubeconfig does not specify a namespace, the pod namespace is still used as a fallback. ([[#44570](https://github.com/kubernetes/kubernetes/pull/44570)](https://github.com/kubernetes/kubernetes/pull/44570), [[@liggitt](https://github.com/liggitt)](https://github.com/liggitt)) +* ControllerRevision type has been added for StatefulSet and DaemonSet history. Clients should not depend on the stability of this type as it may change, as necessary, in future releases to support StatefulSet and DaemonSet update and rollback. We enable this type as we do with beta features, because StatefulSet update and DaemonSet update are enabled. ([[#45867](https://github.com/kubernetes/kubernetes/pull/45867)](https://github.com/kubernetes/kubernetes/pull/45867), [[@kow3ns](https://github.com/kow3ns)](https://github.com/kow3ns)) -* This adds support for CNI ConfigLists, which permit plugin chaining. ([[#42202](https://github.com/kubernetes/kubernetes/pull/42202)](https://github.com/kubernetes/kubernetes/pull/42202), [[@squeed](https://github.com/squeed)](https://github.com/squeed)) +* PodDisruptionBudget now uses ControllerRef to decide which controller owns a given Pod, so it doesn't get confused by controllers with overlapping selectors. ([[#45003](https://github.com/kubernetes/kubernetes/pull/45003)](https://github.com/kubernetes/kubernetes/pull/45003), [[@krmayankk](https://github.com/krmayankk)](https://github.com/krmayankk)) -* API requests using impersonation now include the system:authenticated group in the impersonated user automatically. ([[#44076](https://github.com/kubernetes/kubernetes/pull/44076)](https://github.com/kubernetes/kubernetes/pull/44076), [[@liggitt](https://github.com/liggitt)](https://github.com/liggitt)) +* Deployments are updated to use (1) a more stable hashing algorithm (fnv) than the previous one (adler) and (2) a hashing collision avoidance mechanism that will ensure new rollouts will not block on hashing collisions anymore. ([[#44774](https://github.com/kubernetes/kubernetes/pull/44774)](https://github.com/kubernetes/kubernetes/pull/44774), [[@kargakis](https://github.com/kargakis)](https://github.com/kargakis))([kubernetes/features#287](https://github.com/kubernetes/features/issues/287)) -* Print conditions of RC/RS in `kubectl describe` command. ([[#44710](https://github.com/kubernetes/kubernetes/pull/44710)](https://github.com/kubernetes/kubernetes/pull/44710), [[@xiangpengzhao](https://github.com/xiangpengzhao)](https://github.com/xiangpengzhao)) - -* NONE ([[#44487](https://github.com/kubernetes/kubernetes/pull/44487)](https://github.com/kubernetes/kubernetes/pull/44487), [[@resouer](https://github.com/resouer)](https://github.com/resouer)) - -* cinder: Add support for the KVM virtio-scsi driver ([[#41498](https://github.com/kubernetes/kubernetes/pull/41498)](https://github.com/kubernetes/kubernetes/pull/41498), [[@mikebryant](https://github.com/mikebryant)](https://github.com/mikebryant)) - -* Disallows installation of upstream docker from PPA in the Juju kubernetes-worker charm. ([[#44681](https://github.com/kubernetes/kubernetes/pull/44681)](https://github.com/kubernetes/kubernetes/pull/44681), [[@wwwtyro](https://github.com/wwwtyro)](https://github.com/wwwtyro)) +* Deployments and DaemonSets rollouts are considered complete when all of the desired replicas are updated and available. This change affects `kubectl rollout status` and Deployment condition. ([[#44672](https://github.com/kubernetes/kubernetes/pull/44672)](https://github.com/kubernetes/kubernetes/pull/44672), [[@kargakis](https://github.com/kargakis)](https://github.com/kargakis)) * Job controller now respects ControllerRef to avoid fighting over Pods. ([[#42176](https://github.com/kubernetes/kubernetes/pull/42176)](https://github.com/kubernetes/kubernetes/pull/42176), [[@enisoc](https://github.com/enisoc)](https://github.com/enisoc)) * CronJob controller now respects ControllerRef to avoid fighting with other controllers. ([[#42177](https://github.com/kubernetes/kubernetes/pull/42177)](https://github.com/kubernetes/kubernetes/pull/42177), [[@enisoc](https://github.com/enisoc)](https://github.com/enisoc)) -* The hyperkube image has been slimmed down and no longer includes addon manifests and other various scripts. These were introduced for the now removed docker-multinode setup system. ([[#44555](https://github.com/kubernetes/kubernetes/pull/44555)](https://github.com/kubernetes/kubernetes/pull/44555), [[@luxas](https://github.com/luxas)](https://github.com/luxas)) +#### Cluster Autoscaling +* Cluster Autoscaler 0.6. More information available [here](https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/README.md). -* Refactoring reorganize taints function in kubectl to expose operations ([[#43171](https://github.com/kubernetes/kubernetes/pull/43171)](https://github.com/kubernetes/kubernetes/pull/43171), [[@ravisantoshgudimetla](https://github.com/ravisantoshgudimetla)](https://github.com/ravisantoshgudimetla)) +* cluster-autoscaler: Fix duplicate writing of logs. ([[#45017](https://github.com/kubernetes/kubernetes/pull/45017)](https://github.com/kubernetes/kubernetes/pull/45017), [[@MaciekPytel](https://github.com/MaciekPytel)](https://github.com/MaciekPytel)) -* The Kubernetes API server now exits if it encounters a networking failure (e.g. the networking interface hosting its address goes away) to allow a process manager (systemd/kubelet/etc) to react to the problem. Previously the server would log the failure and try again to bind to its configured address:port. ([[#42272](https://github.com/kubernetes/kubernetes/pull/42272)](https://github.com/kubernetes/kubernetes/pull/42272), [[@marun](https://github.com/marun)](https://github.com/marun)) -* Fixes a bug in the kubernetes-worker Juju charm code that attempted to give kube-proxy more than one api endpoint. ([[#44677](https://github.com/kubernetes/kubernetes/pull/44677)](https://github.com/kubernetes/kubernetes/pull/44677), [[@wwwtyro](https://github.com/wwwtyro)](https://github.com/wwwtyro)) +#### Cloud Provider Enhancement -* Fixes a missing comma in a list of strings. ([[#44678](https://github.com/kubernetes/kubernetes/pull/44678)](https://github.com/kubernetes/kubernetes/pull/44678), [[@wwwtyro](https://github.com/wwwtyro)](https://github.com/wwwtyro)) +* AWS: -* Fix ceph-secret type to kubernetes.io/rbd in kubernetes-master charm ([[#44635](https://github.com/kubernetes/kubernetes/pull/44635)](https://github.com/kubernetes/kubernetes/pull/44635), [[@Cynerva](https://github.com/Cynerva)](https://github.com/Cynerva)) + * New 'service.beta.kubernetes.io/aws-load-balancer-extra-security-groups' Service annotation to specify extra Security Groups to be added to ELB created by AWS cloudprovider ([[#45268](https://github.com/kubernetes/kubernetes/pull/45268)](https://github.com/kubernetes/kubernetes/pull/45268), [[@redbaron](https://github.com/redbaron)](https://github.com/redbaron)) -* Add support for Azure internal load balancer ([[#43510](https://github.com/kubernetes/kubernetes/pull/43510)](https://github.com/kubernetes/kubernetes/pull/43510), [[@karataliu](https://github.com/karataliu)](https://github.com/karataliu)) + * Clean up blackhole routes when using kubenet ([[#47572](https://github.com/kubernetes/kubernetes/pull/47572)](https://github.com/kubernetes/kubernetes/pull/47572), [[@justinsb](https://github.com/justinsb)](https://github.com/justinsb)) -* Improved output on `kubectl get` and `kubectl describe` for generic objects. ([[#44222](https://github.com/kubernetes/kubernetes/pull/44222)](https://github.com/kubernetes/kubernetes/pull/44222), [[@fabianofranz](https://github.com/fabianofranz)](https://github.com/fabianofranz)) + * Maintain a cache of all instances, to fix problem with > 200 nodes with ELBs ([[#47410](https://github.com/kubernetes/kubernetes/pull/47410)](https://github.com/kubernetes/kubernetes/pull/47410), [[@justinsb](https://github.com/justinsb)](https://github.com/justinsb)) -* Add Kubernetes 1.6 support to Juju charms ([[#44500](https://github.com/kubernetes/kubernetes/pull/44500)](https://github.com/kubernetes/kubernetes/pull/44500), [[@Cynerva](https://github.com/Cynerva)](https://github.com/Cynerva)) + * Avoid spurious ELB listener recreation - ignore case when matching protocol ([[#47391](https://github.com/kubernetes/kubernetes/pull/47391)](https://github.com/kubernetes/kubernetes/pull/47391), [[@justinsb](https://github.com/justinsb)](https://github.com/justinsb)) + + * Allow configuration of a single security group for ELBs ([[#45500](https://github.com/kubernetes/kubernetes/pull/45500)](https://github.com/kubernetes/kubernetes/pull/45500), [[@nbutton23](https://github.com/nbutton23)](https://github.com/nbutton23)) + + * Remove check that forces loadBalancerSourceRanges to be 0.0.0.0/0. ([[#38636](https://github.com/kubernetes/kubernetes/pull/38636)](https://github.com/kubernetes/kubernetes/pull/38636), [[@dhawal55](https://github.com/dhawal55)](https://github.com/dhawal55)) + + * Allow setting KubernetesClusterID or KubernetesClusterTag in combination with VPC. ([[#42512](https://github.com/kubernetes/kubernetes/pull/42512)](https://github.com/kubernetes/kubernetes/pull/42512), [[@scheeles](https://github.com/scheeles)](https://github.com/scheeles)) + + * Start recording cloud provider metrics for AWS ([[#43477](https://github.com/kubernetes/kubernetes/pull/43477)](https://github.com/kubernetes/kubernetes/pull/43477), [[@gnufied](https://github.com/gnufied)](https://github.com/gnufied)) + + * AWS: Batch DescribeInstance calls with nodeNames to 150 limit, to stay within AWS filter limits. ([[#47516](https://github.com/kubernetes/kubernetes/pull/47516)](https://github.com/kubernetes/kubernetes/pull/47516), [[@gnufied](https://github.com/gnufied)](https://github.com/gnufied)) + + * AWS: Process disk attachments even with duplicate NodeNames ([[#47406](https://github.com/kubernetes/kubernetes/pull/47406)](https://github.com/kubernetes/kubernetes/pull/47406), [[@justinsb](https://github.com/justinsb)](https://github.com/justinsb)) + + * Allow configuration of a single security group for ELBs ([[#45500](https://github.com/kubernetes/kubernetes/pull/45500)](https://github.com/kubernetes/kubernetes/pull/45500), [[@nbutton23](https://github.com/nbutton23)](https://github.com/nbutton23)) + + * Fix support running the master with a different AWS account or even on a different cloud provider than the nodes. ([[#44235](https://github.com/kubernetes/kubernetes/pull/44235)](https://github.com/kubernetes/kubernetes/pull/44235), [[@mrIncompetent](https://github.com/mrIncompetent)](https://github.com/mrIncompetent)) + + * Support node port health check ([[#43585](https://github.com/kubernetes/kubernetes/pull/43585)](https://github.com/kubernetes/kubernetes/pull/43585), [[@foolusion](https://github.com/foolusion)](https://github.com/foolusion)) + + * Support for ELB tagging by users ([[#45932](https://github.com/kubernetes/kubernetes/pull/45932)](https://github.com/kubernetes/kubernetes/pull/45932), [[@lpabon](https://github.com/lpabon)](https://github.com/lpabon)) + +* Azure: + + * Add support for UDP ports ([[#45523](https://github.com/kubernetes/kubernetes/pull/45523)](https://github.com/kubernetes/kubernetes/pull/45523), [[@colemickens](https://github.com/colemickens)](https://github.com/colemickens)) + + * Fix support for multiple loadBalancerSourceRanges ([[#45523](https://github.com/kubernetes/kubernetes/pull/45523)](https://github.com/kubernetes/kubernetes/pull/45523), [[@colemickens](https://github.com/colemickens)](https://github.com/colemickens)) + + * Support the Service spec's sessionAffinity ([[#45523](https://github.com/kubernetes/kubernetes/pull/45523)](https://github.com/kubernetes/kubernetes/pull/45523), [[@colemickens](https://github.com/colemickens)](https://github.com/colemickens)) + + * Added exponential backoff to Azure cloudprovider ([[#46660](https://github.com/kubernetes/kubernetes/pull/46660)](https://github.com/kubernetes/kubernetes/pull/46660), [[@jackfrancis](https://github.com/jackfrancis)](https://github.com/jackfrancis)) + + * Add support for bring-your-own ip address for Services on Azure ([[#42034](https://github.com/kubernetes/kubernetes/pull/42034)](https://github.com/kubernetes/kubernetes/pull/42034), [[@brendandburns](https://github.com/brendandburns)](https://github.com/brendandburns)) + + * Add support for Azure internal load balancer ([[#43510](https://github.com/kubernetes/kubernetes/pull/43510)](https://github.com/kubernetes/kubernetes/pull/43510), [[@karataliu](https://github.com/karataliu)](https://github.com/karataliu)) + + * Client poll duration is now 5 seconds ([[#43699](https://github.com/kubernetes/kubernetes/pull/43699)](https://github.com/kubernetes/kubernetes/pull/43699), [[@colemickens](https://github.com/colemickens)](https://github.com/colemickens)) + + * Azure plugin for client auth ([[#43987](https://github.com/kubernetes/kubernetes/pull/43987)](https://github.com/kubernetes/kubernetes/pull/43987), [[@cosmincojocar](https://github.com/cosmincojocar)](https://github.com/cosmincojocar)) + + +* GCP: + + * Bump GLBC version to 0.9.5 - fixes [loss of manually modified GCLB health check settings](https://github.com/kubernetes/kubernetes/issues/47559) upon upgrade from pre-1.6.4 to either 1.6.4 or 1.6.5. ([[#47567](https://github.com/kubernetes/kubernetes/pull/47567)](https://github.com/kubernetes/kubernetes/pull/47567), [[@nicksardo](https://github.com/nicksardo)](https://github.com/nicksardo)) + + * [beta] Support creation of GCP Internal Load Balancers from Service objects ([[#46663](https://github.com/kubernetes/kubernetes/pull/46663)](https://github.com/kubernetes/kubernetes/pull/46663), [[@nicksardo](https://github.com/nicksardo)](https://github.com/nicksardo)) + + * GCE installs will now avoid IP masquerade for all RFC-1918 IP blocks, rather than just 10.0.0.0/8. This means that clusters can be created in 192.168.0.0./16 and 172.16.0.0/12 while preserving the container IPs (which would be lost before). ([[#46473](https://github.com/kubernetes/kubernetes/pull/46473)](https://github.com/kubernetes/kubernetes/pull/46473), [[@thockin](https://github.com/thockin)](https://github.com/thockin)) + + * The Calico version included in kube-up for GCE has been updated to v2.2. ([[#38169](https://github.com/kubernetes/kubernetes/pull/38169)](https://github.com/kubernetes/kubernetes/pull/38169), [[@caseydavenport](https://github.com/caseydavenport)](https://github.com/caseydavenport)) + + * ip-masq-agent is now on by default for GCE ([[#47794](https://github.com/kubernetes/kubernetes/pull/47794)](https://github.com/kubernetes/kubernetes/pull/47794), [[@dnardo](https://github.com/dnardo)](https://github.com/dnardo)) + + * Add ip-masq-agent addon to the addons folder which is used in GCE if `--non-masquerade-cidr` is set to 0/0 ([[#46038](https://github.com/kubernetes/kubernetes/pull/46038)](https://github.com/kubernetes/kubernetes/pull/46038), [[@dnardo](https://github.com/dnardo)](https://github.com/dnardo)) + + * Enable kubelet csr bootstrap in GCE/GKE ([[#40760](https://github.com/kubernetes/kubernetes/pull/40760)](https://github.com/kubernetes/kubernetes/pull/40760), [[@mikedanese](https://github.com/mikedanese)](https://github.com/mikedanese)) + + * Adds support for allocation of pod IPs via IP aliases. ([[#42147](https://github.com/kubernetes/kubernetes/pull/42147)](https://github.com/kubernetes/kubernetes/pull/42147), [[@bowei](https://github.com/bowei)](https://github.com/bowei)) + + * gce kube-up: The Node authorization mode and NodeRestriction admission controller are now enabled ([[#46796](https://github.com/kubernetes/kubernetes/pull/46796)](https://github.com/kubernetes/kubernetes/pull/46796), [[@mikedanese](https://github.com/mikedanese)](https://github.com/mikedanese)) + + * Tokens retrieved from Google Cloud with application default credentials will not be cached if the client fails authorization ([[#46694](https://github.com/kubernetes/kubernetes/pull/46694)](https://github.com/kubernetes/kubernetes/pull/46694), [[@matt-tyler](https://github.com/matt-tyler)](https://github.com/matt-tyler)) + + * Add metrics to all major gce operations {latency, errors} ([[#44510](https://github.com/kubernetes/kubernetes/pull/44510)](https://github.com/kubernetes/kubernetes/pull/44510), [[@bowei](https://github.com/bowei)](https://github.com/bowei)) + + * The new metrics are: + + * cloudprovider_gce_api_request_duration_seconds{request, region, zone} + + * cloudprovider_gce_api_request_errors{request, region, zone} + + * request is the specific function that is used. + + * region is the target region (Will be "" if not applicable) + + * zone is the target zone (Will be "" if not applicable) + + * Note: this fixes some issues with the previous implementation of metrics for disks: + + * Time duration tracked was of the initial API call, not the entire operation. + + * Metrics label tuple would have resulted in many independent histograms stored, one for each disk. (Did not aggregate well). + + * Fluentd now tolerates all NoExecute Taints when run in gcp configuration. ([[#45715](https://github.com/kubernetes/kubernetes/pull/45715)](https://github.com/kubernetes/kubernetes/pull/45715), [[@gmarek](https://github.com/gmarek)](https://github.com/gmarek)) + + * Taints support in gce/salt startup scripts. ([[#47632](https://github.com/kubernetes/kubernetes/pull/47632)](https://github.com/kubernetes/kubernetes/pull/47632), [[@mwielgus](https://github.com/mwielgus)](https://github.com/mwielgus)) + + * GCE installs will now avoid IP masquerade for all RFC-1918 IP blocks, rather than just 10.0.0.0/8. This means that clusters can ([[#46473](https://github.com/kubernetes/kubernetes/pull/46473)](https://github.com/kubernetes/kubernetes/pull/46473), [[@thockin](https://github.com/thockin)](https://github.com/thockin)) be created in 192.168.0.0./16 and 172.16.0.0/12 while preserving the container IPs (which would be lost before). + + * Support running Ubuntu image on GCE node ([[#44744](https://github.com/kubernetes/kubernetes/pull/44744)](https://github.com/kubernetes/kubernetes/pull/44744), [[@yguo0905](https://github.com/yguo0905)](https://github.com/yguo0905)) + + * The gce metadata server can now be hidden behind a proxy, hiding the kubelet's token. ([[#45565](https://github.com/kubernetes/kubernetes/pull/45565)](https://github.com/kubernetes/kubernetes/pull/45565), [[@Q-Lee](https://github.com/Q-Lee)](https://github.com/Q-Lee)) + +* OpenStack: + + * Fix issue during LB creation where ports were incorrectly assigned to a floating IP ([[#44387](https://github.com/kubernetes/kubernetes/pull/44387)](https://github.com/kubernetes/kubernetes/pull/44387), [[@jamiehannaford](https://github.com/jamiehannaford)](https://github.com/jamiehannaford)) + + * Openstack cinder v1/v2/auto API support ([[#40423](https://github.com/kubernetes/kubernetes/pull/40423)](https://github.com/kubernetes/kubernetes/pull/40423), [[@mkutsevol](https://github.com/mkutsevol)](https://github.com/mkutsevol)) + + * OpenStack clusters can now specify whether worker nodes are assigned a floating IP ([[#42638](https://github.com/kubernetes/kubernetes/pull/42638)](https://github.com/kubernetes/kubernetes/pull/42638), [[@jamiehannaford](https://github.com/jamiehannaford)](https://github.com/jamiehannaford)) + + +* vSphere: + + * Fix volume detach on node failure. ([[#45569](https://github.com/kubernetes/kubernetes/pull/45569)](https://github.com/kubernetes/kubernetes/pull/45569), [[@divyenpatel](https://github.com/divyenpatel)](https://github.com/divyenpatel)) + + * Report same Node IP as both internal and external. ([[#45201](https://github.com/kubernetes/kubernetes/pull/45201)](https://github.com/kubernetes/kubernetes/pull/45201), [[@abrarshivani](https://github.com/abrarshivani)](https://github.com/abrarshivani)) + + * Filter out IPV6 node addresses. ([[#45181](https://github.com/kubernetes/kubernetes/pull/45181)](https://github.com/kubernetes/kubernetes/pull/45181), [[@BaluDontu](https://github.com/BaluDontu)](https://github.com/BaluDontu)) + + * Fix fetching of VM UUID on Ubuntu 16.04 and Fedora. ([[#45311](https://github.com/kubernetes/kubernetes/pull/45311)](https://github.com/kubernetes/kubernetes/pull/45311), [[@divyenpatel](https://github.com/divyenpatel)](https://github.com/divyenpatel)) + + +#### Cluster Provisioning +* Juju: + + * Add Kubernetes 1.6 support to Juju charms ([[#44500](https://github.com/kubernetes/kubernetes/pull/44500)](https://github.com/kubernetes/kubernetes/pull/44500), [[@Cynerva](https://github.com/Cynerva)](https://github.com/Cynerva)) * Add metric collection to charms for autoscaling @@ -1927,144 +1361,479 @@ Continuous integration builds have used the following versions of external depen * Fix nagios checks in charms -* Fixed `kubectl cluster-info dump` to support multi-container pod. ([[#44088](https://github.com/kubernetes/kubernetes/pull/44088)](https://github.com/kubernetes/kubernetes/pull/44088), [[@xingzhou](https://github.com/xingzhou)](https://github.com/xingzhou)) + * Enable GPU mode if GPU hardware detected ([[#43467](https://github.com/kubernetes/kubernetes/pull/43467)](https://github.com/kubernetes/kubernetes/pull/43467), [[@tvansteenburgh](https://github.com/tvansteenburgh)](https://github.com/tvansteenburgh)) -* Prints out status updates when running `kubefed init` ([[#41849](https://github.com/kubernetes/kubernetes/pull/41849)](https://github.com/kubernetes/kubernetes/pull/41849), [[@perotinus](https://github.com/perotinus)](https://github.com/perotinus)) + * Fix ceph-secret type to kubernetes.io/rbd in kubernetes-master charm ([[#44635](https://github.com/kubernetes/kubernetes/pull/44635)](https://github.com/kubernetes/kubernetes/pull/44635), [[@Cynerva](https://github.com/Cynerva)](https://github.com/Cynerva)) -* CRI: Fix kubelet failing to start when using rkt. ([[#44569](https://github.com/kubernetes/kubernetes/pull/44569)](https://github.com/kubernetes/kubernetes/pull/44569), [[@yujuhong](https://github.com/yujuhong)](https://github.com/yujuhong)) + * Disallows installation of upstream docker from PPA in the Juju kubernetes-worker charm. ([[#44681](https://github.com/kubernetes/kubernetes/pull/44681)](https://github.com/kubernetes/kubernetes/pull/44681), [[@wwwtyro](https://github.com/wwwtyro)](https://github.com/wwwtyro)) -* Remove deprecatedPublicIPs field ([[#44519](https://github.com/kubernetes/kubernetes/pull/44519)](https://github.com/kubernetes/kubernetes/pull/44519), [[@thockin](https://github.com/thockin)](https://github.com/thockin)) + * Resolves juju vsphere hostname bug showing only a single node in a scaled node-pool. ([[#44780](https://github.com/kubernetes/kubernetes/pull/44780)](https://github.com/kubernetes/kubernetes/pull/44780), [[@chuckbutler](https://github.com/chuckbutler)](https://github.com/chuckbutler)) -* Remove deprecated ubuntu kube-up deployment. ([[#44344](https://github.com/kubernetes/kubernetes/pull/44344)](https://github.com/kubernetes/kubernetes/pull/44344), [[@mikedanese](https://github.com/mikedanese)](https://github.com/mikedanese)) + * Fixes a bug in the kubernetes-worker Juju charm code that attempted to give kube-proxy more than one api endpoint. ([[#44677](https://github.com/kubernetes/kubernetes/pull/44677)](https://github.com/kubernetes/kubernetes/pull/44677), [[@wwwtyro](https://github.com/wwwtyro)](https://github.com/wwwtyro)) -* Use OS-specific libs when computing client User-Agent in kubectl, etc. ([[#44423](https://github.com/kubernetes/kubernetes/pull/44423)](https://github.com/kubernetes/kubernetes/pull/44423), [[@monopole](https://github.com/monopole)](https://github.com/monopole)) + * Added CIFS PV support for Juju Charms ([[#45117](https://github.com/kubernetes/kubernetes/pull/45117)](https://github.com/kubernetes/kubernetes/pull/45117), [[@chuckbutler](https://github.com/chuckbutler)](https://github.com/chuckbutler)) -* kube-apiserver now drops unneeded path information if an older version of Windows kubectl sends it. ([[#44421](https://github.com/kubernetes/kubernetes/pull/44421)](https://github.com/kubernetes/kubernetes/pull/44421), [[@mml](https://github.com/mml)](https://github.com/mml)) + * Fixes juju kubernetes master: 1. Get certs from a dead leader. 2. Append tokens. ([[#43620](https://github.com/kubernetes/kubernetes/pull/43620)](https://github.com/kubernetes/kubernetes/pull/43620), [[@ktsakalozos](https://github.com/ktsakalozos)](https://github.com/ktsakalozos)) -* Extending the gc admission plugin so that a user who doesn't have delete permission of the *owner* cannot modify blockOwnerDeletion field of existing ownerReferences, or add new ownerReference with blockOwnerDeletion=true ([[#43876](https://github.com/kubernetes/kubernetes/pull/43876)](https://github.com/kubernetes/kubernetes/pull/43876), [[@caesarxuchao](https://github.com/caesarxuchao)](https://github.com/caesarxuchao)) + * kubernetes-master juju charm properly detects etcd-scale events and reconfigures appropriately. ([[#44967](https://github.com/kubernetes/kubernetes/pull/44967)](https://github.com/kubernetes/kubernetes/pull/44967), [[@chuckbutler](https://github.com/chuckbutler)](https://github.com/chuckbutler)) -* kube-apiserver: `--service-account-lookup` now defaults to true, requiring the Secret API object containing the token to exist in order for a service account token to be valid. This enables service account tokens to be revoked by deleting the Secret object containing the token. ([[#44071](https://github.com/kubernetes/kubernetes/pull/44071)](https://github.com/kubernetes/kubernetes/pull/44071), [[@liggitt](https://github.com/liggitt)](https://github.com/liggitt)) + * Use correct option name in the kubernetes-worker layer registry action ([[#44921](https://github.com/kubernetes/kubernetes/pull/44921)](https://github.com/kubernetes/kubernetes/pull/44921), [[@jacekn](https://github.com/jacekn)](https://github.com/jacekn)) -* CRI: `kubectl logs -f` now stops following when container stops, as it did pre-CRI. ([[#44406](https://github.com/kubernetes/kubernetes/pull/44406)](https://github.com/kubernetes/kubernetes/pull/44406), [[@Random-Liu](https://github.com/Random-Liu)](https://github.com/Random-Liu)) + * Send dns details only after cdk-addons are configured ([[#44945](https://github.com/kubernetes/kubernetes/pull/44945)](https://github.com/kubernetes/kubernetes/pull/44945), [[@ktsakalozos](https://github.com/ktsakalozos)](https://github.com/ktsakalozos)) -* Add completion support for `--user` and `--cluster` to kubectl ([[#44251](https://github.com/kubernetes/kubernetes/pull/44251)](https://github.com/kubernetes/kubernetes/pull/44251), [[@superbrothers](https://github.com/superbrothers)](https://github.com/superbrothers)) + * Added support to the pause action in the kubernetes-worker charm for new flag `--delete-local-data` ([[#44931](https://github.com/kubernetes/kubernetes/pull/44931)](https://github.com/kubernetes/kubernetes/pull/44931), [[@chuckbutler](https://github.com/chuckbutler)](https://github.com/chuckbutler)) -* dnsprovider: avoid panic if route53 fields are nil ([[#44380](https://github.com/kubernetes/kubernetes/pull/44380)](https://github.com/kubernetes/kubernetes/pull/44380), [[@justinsb](https://github.com/justinsb)](https://github.com/justinsb)) + * Add namespace-{list, create, delete} actions to the kubernetes-master layer ([[#44277](https://github.com/kubernetes/kubernetes/pull/44277)](https://github.com/kubernetes/kubernetes/pull/44277), [[@jacekn](https://github.com/jacekn)](https://github.com/jacekn)) -* In `kubectl describe`, find controllers with ControllerRef, instead of showing the original creator. ([[#42849](https://github.com/kubernetes/kubernetes/pull/42849)](https://github.com/kubernetes/kubernetes/pull/42849), [[@janetkuo](https://github.com/janetkuo)](https://github.com/janetkuo)) + * Using http2 in kubeapi-load-balancer to fix `kubectl exec` uses ([[#43625](https://github.com/kubernetes/kubernetes/pull/43625)](https://github.com/kubernetes/kubernetes/pull/43625), [[@mbruzek](https://github.com/mbruzek)](https://github.com/mbruzek)) -* Heat cluster operations now support environments that have multiple Swift URLs ([[#41561](https://github.com/kubernetes/kubernetes/pull/41561)](https://github.com/kubernetes/kubernetes/pull/41561), [[@jamiehannaford](https://github.com/jamiehannaford)](https://github.com/jamiehannaford)) -* Adds support for allocation of pod IPs via IP aliases. ([[#42147](https://github.com/kubernetes/kubernetes/pull/42147)](https://github.com/kubernetes/kubernetes/pull/42147), [[@bowei](https://github.com/bowei)](https://github.com/bowei)) + * Don't append :443 to registry domain in the kubernetes-worker layer registry action ([[#45550](https://github.com/kubernetes/kubernetes/pull/45550)](https://github.com/kubernetes/kubernetes/pull/45550), [[@jacekn](https://github.com/jacekn)](https://github.com/jacekn)) -* validateClusterInfo: use clientcmdapi.NewCluster() ([[#44221](https://github.com/kubernetes/kubernetes/pull/44221)](https://github.com/kubernetes/kubernetes/pull/44221), [[@ncdc](https://github.com/ncdc)](https://github.com/ncdc)) +* kubeadm -* Fix corner-case with OnlyLocal Service healthchecks. ([[#44313](https://github.com/kubernetes/kubernetes/pull/44313)](https://github.com/kubernetes/kubernetes/pull/44313), [[@thockin](https://github.com/thockin)](https://github.com/thockin)) + * Enable the Node Authorizer/Admission plugin in v1.7 ([[#46879](https://github.com/kubernetes/kubernetes/pull/46879)](https://github.com/kubernetes/kubernetes/pull/46879), [[@luxas](https://github.com/luxas)](https://github.com/luxas)) -* Adds annotations to all Federation objects created by kubefed. ([[#42683](https://github.com/kubernetes/kubernetes/pull/42683)](https://github.com/kubernetes/kubernetes/pull/42683), [[@perotinus](https://github.com/perotinus)](https://github.com/perotinus)) + * Users can now pass extra parameters to etcd in a kubeadm cluster ([[#42246](https://github.com/kubernetes/kubernetes/pull/42246)](https://github.com/kubernetes/kubernetes/pull/42246), [[@jamiehannaford](https://github.com/jamiehannaford)](https://github.com/jamiehannaford)) -* [Federation][Kubefed] Bug fix to enable disabling federation controllers through override args ([[#44209](https://github.com/kubernetes/kubernetes/pull/44209)](https://github.com/kubernetes/kubernetes/pull/44209), [[@irfanurrehman](https://github.com/irfanurrehman)](https://github.com/irfanurrehman)) + * Make kubeadm use the new CSR approver in v1.7 ([[#46864](https://github.com/kubernetes/kubernetes/pull/46864)](https://github.com/kubernetes/kubernetes/pull/46864), [[@luxas](https://github.com/luxas)](https://github.com/luxas)) -* [Federation] Remove deprecated federation-apiserver-kubeconfig secret ([[#44287](https://github.com/kubernetes/kubernetes/pull/44287)](https://github.com/kubernetes/kubernetes/pull/44287), [[@shashidharatd](https://github.com/shashidharatd)](https://github.com/shashidharatd)) + * Allow enabling multiple authorization modes at the same time ([[#42557](https://github.com/kubernetes/kubernetes/pull/42557)](https://github.com/kubernetes/kubernetes/pull/42557), [[@xilabao](https://github.com/xilabao)](https://github.com/xilabao)) -* Scheduler can recieve its policy configuration from a ConfigMap ([[#43892](https://github.com/kubernetes/kubernetes/pull/43892)](https://github.com/kubernetes/kubernetes/pull/43892), [[@bsalamat](https://github.com/bsalamat)](https://github.com/bsalamat)) + * add proxy client-certs to kube-apiserver to allow it to proxy aggregated api servers ([[#43715](https://github.com/kubernetes/kubernetes/pull/43715)](https://github.com/kubernetes/kubernetes/pull/43715), [[@deads2k](https://github.com/deads2k)](https://github.com/deads2k))* CentOS provider -* AWS cloud provider: fix support running the master with a different AWS account or even on a different cloud provider than the nodes. ([[#44235](https://github.com/kubernetes/kubernetes/pull/44235)](https://github.com/kubernetes/kubernetes/pull/44235), [[@mrIncompetent](https://github.com/mrIncompetent)](https://github.com/mrIncompetent)) +* hyperkube -* add rancher credential provider ([[#40160](https://github.com/kubernetes/kubernetes/pull/40160)](https://github.com/kubernetes/kubernetes/pull/40160), [[@wlan0](https://github.com/wlan0)](https://github.com/wlan0)) - -* Support generating Open API extensions for strategic merge patch tags in go struct tags ([[#44121](https://github.com/kubernetes/kubernetes/pull/44121)](https://github.com/kubernetes/kubernetes/pull/44121), [[@mbohlool](https://github.com/mbohlool)](https://github.com/mbohlool)) - -* Aggregated used ports at the NodeInfo level for PodFitsHostPorts predicate. ([[#42524](https://github.com/kubernetes/kubernetes/pull/42524)](https://github.com/kubernetes/kubernetes/pull/42524), [[@k82cn](https://github.com/k82cn)](https://github.com/k82cn)) - -* Catch error when failed to make directory in NFS volume plugin ([[#38801](https://github.com/kubernetes/kubernetes/pull/38801)](https://github.com/kubernetes/kubernetes/pull/38801), [[@nak3](https://github.com/nak3)](https://github.com/nak3)) - -* Support iSCSI CHAP authentication ([[#43396](https://github.com/kubernetes/kubernetes/pull/43396)](https://github.com/kubernetes/kubernetes/pull/43396), [[@rootfs](https://github.com/rootfs)](https://github.com/rootfs)) - -* Support context completion for `kubectl config use-context` ([[#42336](https://github.com/kubernetes/kubernetes/pull/42336)](https://github.com/kubernetes/kubernetes/pull/42336), [[@superbrothers](https://github.com/superbrothers)](https://github.com/superbrothers)) - -* print warning when delete current context ([[#42538](https://github.com/kubernetes/kubernetes/pull/42538)](https://github.com/kubernetes/kubernetes/pull/42538), [[@adohe](https://github.com/adohe)](https://github.com/adohe)) - -* Add node e2e tests for hostPid ([[#44119](https://github.com/kubernetes/kubernetes/pull/44119)](https://github.com/kubernetes/kubernetes/pull/44119), [[@feiskyer](https://github.com/feiskyer)](https://github.com/feiskyer)) - -* kubelet: make dockershim.sock configurable ([[#43914](https://github.com/kubernetes/kubernetes/pull/43914)](https://github.com/kubernetes/kubernetes/pull/43914), [[@ncdc](https://github.com/ncdc)](https://github.com/ncdc)) - -* Fix [broken service accounts when using dedicated service account key](https://github.com/kubernetes/kubernetes/issues/44285). ([[#44169](https://github.com/kubernetes/kubernetes/pull/44169)](https://github.com/kubernetes/kubernetes/pull/44169), [[@mikedanese](https://github.com/mikedanese)](https://github.com/mikedanese)) - -* Fix incorrect conflict errors applying strategic merge patches to resources. ([[#43871](https://github.com/kubernetes/kubernetes/pull/43871)](https://github.com/kubernetes/kubernetes/pull/43871), [[@liggitt](https://github.com/liggitt)](https://github.com/liggitt)) - -* Fix [transition between NotReady and Unreachable taints](https://github.com/kubernetes/kubernetes/issues/43444). ([[#44042](https://github.com/kubernetes/kubernetes/pull/44042)](https://github.com/kubernetes/kubernetes/pull/44042), [[@gmarek](https://github.com/gmarek)](https://github.com/gmarek)) - -* leader election lock based on scheduler name ([[#42961](https://github.com/kubernetes/kubernetes/pull/42961)](https://github.com/kubernetes/kubernetes/pull/42961), [[@wanghaoran1988](https://github.com/wanghaoran1988)](https://github.com/wanghaoran1988)) - -* [Federation] Remove FEDERATIONS_DOMAIN_MAP references ([[#43137](https://github.com/kubernetes/kubernetes/pull/43137)](https://github.com/kubernetes/kubernetes/pull/43137), [[@shashidharatd](https://github.com/shashidharatd)](https://github.com/shashidharatd)) - -* Fix for [federation failing to propagate cascading deletion](https://github.com/kubernetes/kubernetes/issues/44304). ([[#44108](https://github.com/kubernetes/kubernetes/pull/44108)](https://github.com/kubernetes/kubernetes/pull/44108), [[@csbell](https://github.com/csbell)](https://github.com/csbell)) - -* Fix bug with service nodeports that have no backends not being rejected, when they should be. This is not a regression vs v1.5 - it's a fix that didn't quite fix hard enough. ([[#43972](https://github.com/kubernetes/kubernetes/pull/43972)](https://github.com/kubernetes/kubernetes/pull/43972), [[@thockin](https://github.com/thockin)](https://github.com/thockin)) - -* Fix for [failure to delete federation controllers with finalizers](https://github.com/kubernetes/kubernetes/issues/43828). ([[#44084](https://github.com/kubernetes/kubernetes/pull/44084)](https://github.com/kubernetes/kubernetes/pull/44084), [[@nikhiljindal](https://github.com/nikhiljindal)](https://github.com/nikhiljindal)) - -* Fix container hostPid settings. ([[#44097](https://github.com/kubernetes/kubernetes/pull/44097)](https://github.com/kubernetes/kubernetes/pull/44097), [[@feiskyer](https://github.com/feiskyer)](https://github.com/feiskyer)) - -* Fixed an issue mounting the wrong secret into pods as a service account token. ([[#44102](https://github.com/kubernetes/kubernetes/pull/44102)](https://github.com/kubernetes/kubernetes/pull/44102), [[@ncdc](https://github.com/ncdc)](https://github.com/ncdc)) - -* Juju: Enable GPU mode if GPU hardware detected ([[#43467](https://github.com/kubernetes/kubernetes/pull/43467)](https://github.com/kubernetes/kubernetes/pull/43467), [[@tvansteenburgh](https://github.com/tvansteenburgh)](https://github.com/tvansteenburgh)) - -* get-kube-local.sh checks pods with option `--namespace=kube-system` ([[#42518](https://github.com/kubernetes/kubernetes/pull/42518)](https://github.com/kubernetes/kubernetes/pull/42518), [[@mtanino](https://github.com/mtanino)](https://github.com/mtanino)) - -* Using http2 in kubeapi-load-balancer to fix `kubectl exec` uses ([[#43625](https://github.com/kubernetes/kubernetes/pull/43625)](https://github.com/kubernetes/kubernetes/pull/43625), [[@mbruzek](https://github.com/mbruzek)](https://github.com/mbruzek)) - -* AWS cloud provider: allow to set KubernetesClusterID or KubernetesClusterTag in combination with VPC. ([[#42512](https://github.com/kubernetes/kubernetes/pull/42512)](https://github.com/kubernetes/kubernetes/pull/42512), [[@scheeles](https://github.com/scheeles)](https://github.com/scheeles)) - -* changed kubelet default image-gc-high-threshold to 85% to resolve a conflict with default settings in docker that prevented image garbage collection from resolving low disk space situations when using devicemapper storage. ([[#40432](https://github.com/kubernetes/kubernetes/pull/40432)](https://github.com/kubernetes/kubernetes/pull/40432), [[@sjenning](https://github.com/sjenning)](https://github.com/sjenning)) - -* When creating a container using envFrom, ([[#42083](https://github.com/kubernetes/kubernetes/pull/42083)](https://github.com/kubernetes/kubernetes/pull/42083), [[@fraenkel](https://github.com/fraenkel)](https://github.com/fraenkel)) - - * validate the name of the ConfigMap in a ConfigMapRef - - * validate the name of the Secret in a SecretRef - -* RBAC role and rolebinding auto-reconciliation is now performed only when the RBAC authorization mode is enabled. ([[#43813](https://github.com/kubernetes/kubernetes/pull/43813)](https://github.com/kubernetes/kubernetes/pull/43813), [[@liggitt](https://github.com/liggitt)](https://github.com/liggitt)) - -* Permission to use a PodSecurityPolicy can now be granted within a single namespace by allowing the use verb on the podsecuritypolicies resource within the namespace. ([[#42360](https://github.com/kubernetes/kubernetes/pull/42360)](https://github.com/kubernetes/kubernetes/pull/42360), [[@liggitt](https://github.com/liggitt)](https://github.com/liggitt)) - -* Enable audit log in local cluster ([[#42379](https://github.com/kubernetes/kubernetes/pull/42379)](https://github.com/kubernetes/kubernetes/pull/42379), [[@xilabao](https://github.com/xilabao)](https://github.com/xilabao)) - -* ActiveDeadlineSeconds is validated in workload controllers now, make sure it's not set anywhere (it shouldn't be set by default and having it set means your controller will restart the Pods at some point) ([[#38741](https://github.com/kubernetes/kubernetes/pull/38741)](https://github.com/kubernetes/kubernetes/pull/38741), [[@sandflee](https://github.com/sandflee)](https://github.com/sandflee)) - -* Azure: all clients poll duration is now 5 seconds ([[#43699](https://github.com/kubernetes/kubernetes/pull/43699)](https://github.com/kubernetes/kubernetes/pull/43699), [[@colemickens](https://github.com/colemickens)](https://github.com/colemickens)) - -* Address issue [[#39427](https://github.com/kubernetes/kubernetes/pull/39427)](https://github.com/kubernetes/kubernetes/pull/39427) by adding `--output` flag to `kubectl version` ([[#39858](https://github.com/kubernetes/kubernetes/pull/39858)](https://github.com/kubernetes/kubernetes/pull/39858), [[@alejandroEsc](https://github.com/alejandroEsc)](https://github.com/alejandroEsc)) + * The hyperkube image has been slimmed down and no longer includes addon manifests and other various scripts. These were introduced for the now removed docker-multinode setup system. ([[#44555](https://github.com/kubernetes/kubernetes/pull/44555)](https://github.com/kubernetes/kubernetes/pull/44555), [[@luxas](https://github.com/luxas)](https://github.com/luxas)) * Support secure etcd cluster for centos provider. ([[#42994](https://github.com/kubernetes/kubernetes/pull/42994)](https://github.com/kubernetes/kubernetes/pull/42994), [[@Shawyeok](https://github.com/Shawyeok)](https://github.com/Shawyeok)) -* Use Cluster Autoscaler 0.5.1, which fixes an issue in Cluster Autoscaler 0.5 where the cluster may be scaled up unnecessarily. Also the status of Cluster Autoscaler is now exposed in kube-system/cluster-autoscaler-status config map. ([[#43745](https://github.com/kubernetes/kubernetes/pull/43745)](https://github.com/kubernetes/kubernetes/pull/43745), [[@mwielgus](https://github.com/mwielgus)](https://github.com/mwielgus)) +* Update to kube-addon-manager:v6.4-beta.2: kubectl v1.6.4 and refreshed base images ([[#47389](https://github.com/kubernetes/kubernetes/pull/47389)](https://github.com/kubernetes/kubernetes/pull/47389), [[@ixdy](https://github.com/ixdy)](https://github.com/ixdy)) -* Use ProviderID to address nodes in the cloudprovider ([[#42604](https://github.com/kubernetes/kubernetes/pull/42604)](https://github.com/kubernetes/kubernetes/pull/42604), [[@wlan0](https://github.com/wlan0)](https://github.com/wlan0)) +* Remove Initializers from admission-control in kubernetes-master charm for pre-1.7 ([[#46987](https://github.com/kubernetes/kubernetes/pull/46987)](https://github.com/kubernetes/kubernetes/pull/46987), [[@Cynerva](https://github.com/Cynerva)](https://github.com/Cynerva)) -* Openstack cinder v1/v2/auto API support ([[#40423](https://github.com/kubernetes/kubernetes/pull/40423)](https://github.com/kubernetes/kubernetes/pull/40423), [[@mkutsevol](https://github.com/mkutsevol)](https://github.com/mkutsevol)) +* Added state guards to the idle_status messaging in the kubernetes-master charm to make deployment faster on initial deployment. ([[#47183](https://github.com/kubernetes/kubernetes/pull/47183)](https://github.com/kubernetes/kubernetes/pull/47183), [[@chuckbutler](https://github.com/chuckbutler)](https://github.com/chuckbutler)) -* API resource discovery now includes the singularName used to refer to the resource. ([[#43312](https://github.com/kubernetes/kubernetes/pull/43312)](https://github.com/kubernetes/kubernetes/pull/43312), [[@deads2k](https://github.com/deads2k)](https://github.com/deads2k)) +#### Cluster federation +* Features: -* Add the ability to lock on ConfigMaps to support HA for self hosted components ([[#42666](https://github.com/kubernetes/kubernetes/pull/42666)](https://github.com/kubernetes/kubernetes/pull/42666), [[@timothysc](https://github.com/timothysc)](https://github.com/timothysc)) + * Adds annotations to all Federation objects created by kubefed. ([[#42683](https://github.com/kubernetes/kubernetes/pull/42683)](https://github.com/kubernetes/kubernetes/pull/42683), [[@perotinus](https://github.com/perotinus)](https://github.com/perotinus)) -* OpenStack clusters can now specify whether worker nodes are assigned a floating IP ([[#42638](https://github.com/kubernetes/kubernetes/pull/42638)](https://github.com/kubernetes/kubernetes/pull/42638), [[@jamiehannaford](https://github.com/jamiehannaford)](https://github.com/jamiehannaford)) + * Mechanism of adding `federation domain maps` to kube-dns deployment via `--federations` flag is superseded by adding/updating `federations` key in `kube-system/kube-dns` configmap. If user is using kubefed tool to join cluster federation, adding federation domain maps to kube-dns is already taken care by `kubefed join` and does not need further action. -* Add Host field to TCPSocketAction ([[#42902](https://github.com/kubernetes/kubernetes/pull/42902)](https://github.com/kubernetes/kubernetes/pull/42902), [[@louyihua](https://github.com/louyihua)](https://github.com/louyihua)) + * Prints out status updates when running `kubefed init` ([[#41849](https://github.com/kubernetes/kubernetes/pull/41849)](https://github.com/kubernetes/kubernetes/pull/41849), [[@perotinus](https://github.com/perotinus)](https://github.com/perotinus)) -* Be able to specify the timeout to wait for pod for `kubectl logs` and `kubectl attach` ([[#41813](https://github.com/kubernetes/kubernetes/pull/41813)](https://github.com/kubernetes/kubernetes/pull/41813), [[@shiywang](https://github.com/shiywang)](https://github.com/shiywang)) + * `kubefed init` now supports overriding the default etcd image name with the `--etcd-image` parameter. ([[#46247](https://github.com/kubernetes/kubernetes/pull/46247)](https://github.com/kubernetes/kubernetes/pull/46247), [[@marun](https://github.com/marun)](https://github.com/marun)) -* Add support for bring-your-own ip address for Services on Azure ([[#42034](https://github.com/kubernetes/kubernetes/pull/42034)](https://github.com/kubernetes/kubernetes/pull/42034), [[@brendandburns](https://github.com/brendandburns)](https://github.com/brendandburns)) + * kubefed will now configure NodeInternalIP as the federation API server endpoint when NodeExternalIP is unavailable for federation API servers exposed as NodePort services ([[#46960](https://github.com/kubernetes/kubernetes/pull/46960)](https://github.com/kubernetes/kubernetes/pull/46960), [[@lukaszo](https://github.com/lukaszo)](https://github.com/lukaszo)) - * create configmap has a new option `--from-env-file` that populates a configmap from file which follows a key=val format for each line. ([[#38882](https://github.com/kubernetes/kubernetes/pull/38882)](https://github.com/kubernetes/kubernetes/pull/38882), [[@fraenkel](https://github.com/fraenkel)](https://github.com/fraenkel)) + * Automate configuring nameserver in cluster-dns for CoreDNS provider ([[#42895](https://github.com/kubernetes/kubernetes/pull/42895)](https://github.com/kubernetes/kubernetes/pull/42895), [[@shashidharatd](https://github.com/shashidharatd)](https://github.com/shashidharatd)) - * create secret has a new option `--from-env-file` that populates a configmap from file which follows a key=val format for each line. + * A new controller for managing DNS records is introduced which can be optionally disabled to enable third party components to manage DNS records for federated services. ([[#450354](https://github.com/kubernetes/kubernetes/pull/450354)](https://github.com/kubernetes/kubernetes/pull/45034), [[@shashidharatd](https://github.com/shashidharatd)(https://github.com/shashidharatd)]) -* Update the signing key for percona debian and ubuntu packages ([[#41186](https://github.com/kubernetes/kubernetes/pull/41186)](https://github.com/kubernetes/kubernetes/pull/41186), [[@dixudx](https://github.com/dixudx)](https://github.com/dixudx)) + * Remove the `--secret-name` flag from `kubefed join`, instead generating the secret name arbitrarily. ([[#42513](https://github.com/kubernetes/kubernetes/pull/42513)](https://github.com/kubernetes/kubernetes/pull/42513), [[@perotinus](https://github.com/perotinus)](https://github.com/perotinus)) -* fc: Drop multipath.conf snippet ([[#36698](https://github.com/kubernetes/kubernetes/pull/36698)](https://github.com/kubernetes/kubernetes/pull/36698), [[@fabiand](https://github.com/fabiand)](https://github.com/fabiand)) -## Changelog since v1.7.0-rc.1 + * Use StorageClassName for etcd pvc ([[#46323](https://github.com/kubernetes/kubernetes/pull/46323)](https://github.com/kubernetes/kubernetes/pull/46323), [[@marun](https://github.com/marun)](https://github.com/marun)) + +* Bug fixes: + + * Allow disabling federation controllers through override args ([[#44209](https://github.com/kubernetes/kubernetes/pull/44209)](https://github.com/kubernetes/kubernetes/pull/44209), [[@irfanurrehman](https://github.com/irfanurrehman)](https://github.com/irfanurrehman)) + + * Kubefed: Use service accounts instead of the user's credentials when accessing joined clusters' API servers. ([[#42042](https://github.com/kubernetes/kubernetes/pull/42042)](https://github.com/kubernetes/kubernetes/pull/42042), [[@perotinus](https://github.com/perotinus)](https://github.com/perotinus)) + + * Avoid panic if route53 fields are nil ([[#44380](https://github.com/kubernetes/kubernetes/pull/44380)](https://github.com/kubernetes/kubernetes/pull/44380), [[@justinsb](https://github.com/justinsb)](https://github.com/justinsb)) + + +#### Credential provider +* add rancher credential provider ([[#40160](https://github.com/kubernetes/kubernetes/pull/40160)](https://github.com/kubernetes/kubernetes/pull/40160), [[@wlan0](https://github.com/wlan0)](https://github.com/wlan0)) + +#### Information for Kubernetes clients (openapi, swagger, client-go) +* Features: + + * Add Host field to TCPSocketAction ([[#42902](https://github.com/kubernetes/kubernetes/pull/42902)](https://github.com/kubernetes/kubernetes/pull/42902), [[@louyihua](https://github.com/louyihua)](https://github.com/louyihua)) + + * Add the ability to lock on ConfigMaps to support HA for self hosted components ([[#42666](https://github.com/kubernetes/kubernetes/pull/42666)](https://github.com/kubernetes/kubernetes/pull/42666), [[@timothysc](https://github.com/timothysc)](https://github.com/timothysc)) + + * validateClusterInfo: use clientcmdapi.NewCluster() ([[#44221](https://github.com/kubernetes/kubernetes/pull/44221)](https://github.com/kubernetes/kubernetes/pull/44221), [[@ncdc](https://github.com/ncdc)](https://github.com/ncdc)) + + * OpenAPI spec is now available in protobuf binary and gzip format (with ETag support) ([[#45836](https://github.com/kubernetes/kubernetes/pull/45836)](https://github.com/kubernetes/kubernetes/pull/45836), [[@mbohlool](https://github.com/mbohlool)](https://github.com/mbohlool)) + + * HostAliases is now parsed with hostAliases json keys to be in line with the feature's name. ([[#47512](https://github.com/kubernetes/kubernetes/pull/47512)](https://github.com/kubernetes/kubernetes/pull/47512), [[@rickypai](https://github.com/rickypai)](https://github.com/rickypai)) + + * Add redirect support to SpdyRoundTripper ([[#44451](https://github.com/kubernetes/kubernetes/pull/44451)](https://github.com/kubernetes/kubernetes/pull/44451), [[@ncdc](https://github.com/ncdc)](https://github.com/ncdc)) + + * Duplicate recurring Events now include the latest event's Message string ([[#46034](https://github.com/kubernetes/kubernetes/pull/46034)](https://github.com/kubernetes/kubernetes/pull/46034), [[@kensimon](https://github.com/kensimon)](https://github.com/kensimon)) + +* Bug fixes: + + * Fix serialization of EnforceNodeAllocatable ([[#44606](https://github.com/kubernetes/kubernetes/pull/44606)](https://github.com/kubernetes/kubernetes/pull/44606), [[@ivan4th](https://github.com/ivan4th)](https://github.com/ivan4th)) + + * Use OS-specific libs when computing client User-Agent in kubectl, etc. ([[#44423](https://github.com/kubernetes/kubernetes/pull/44423)](https://github.com/kubernetes/kubernetes/pull/44423), [[@monopole](https://github.com/monopole)](https://github.com/monopole)) + + +#### Instrumentation +* Bumped Heapster to v1.4.0. More details about the release https://github.com/kubernetes/heapster/releases/tag/v1.4.0 + +* Fluentd manifest pod is no longer created on non-registered master when creating clusters using kube-up.sh. ([[#44721](https://github.com/kubernetes/kubernetes/pull/44721)](https://github.com/kubernetes/kubernetes/pull/44721), [[@piosz](https://github.com/piosz)](https://github.com/piosz)) + +* Stackdriver cluster logging now deploys a new component to export Kubernetes events. ([[#46700](https://github.com/kubernetes/kubernetes/pull/46700)](https://github.com/kubernetes/kubernetes/pull/46700), [[@crassirostris](https://github.com/crassirostris)](https://github.com/crassirostris)) + +* Stackdriver Logging deployment exposes metrics on node port 31337 when enabled. ([[#47402](https://github.com/kubernetes/kubernetes/pull/47402)](https://github.com/kubernetes/kubernetes/pull/47402), [[@crassirostris](https://github.com/crassirostris)](https://github.com/crassirostris)) + +* Upgrade Elasticsearch Addon to v5.4.0 ([[#45589](https://github.com/kubernetes/kubernetes/pull/45589)](https://github.com/kubernetes/kubernetes/pull/45589), [[@it-svit](https://github.com/it-svit)](https://github.com/it-svit)) + +#### Internal storage layer +* prevent pods/status from touching ownerreferences ([[#45826](https://github.com/kubernetes/kubernetes/pull/45826)](https://github.com/kubernetes/kubernetes/pull/45826), [[@deads2k](https://github.com/deads2k)](https://github.com/deads2k)) + +* Ensure that autoscaling/v1 is the preferred version for API discovery when autoscaling/v2alpha1 is enabled. ([[#45741](https://github.com/kubernetes/kubernetes/pull/45741)](https://github.com/kubernetes/kubernetes/pull/45741), [[@DirectXMan12](https://github.com/DirectXMan12)](https://github.com/DirectXMan12)) + +* The proxy subresource APIs for nodes, services, and pods now support the HTTP PATCH method. ([[#44929](https://github.com/kubernetes/kubernetes/pull/44929)](https://github.com/kubernetes/kubernetes/pull/44929), [[@liggitt](https://github.com/liggitt)](https://github.com/liggitt)) + +* Fluentd now tolerates all NoExecute Taints when run in gcp configuration. ([[#45715](https://github.com/kubernetes/kubernetes/pull/45715)](https://github.com/kubernetes/kubernetes/pull/45715), [[@gmarek](https://github.com/gmarek)](https://github.com/gmarek)) + + +#### Kubernetes Dashboard + +* Increase Dashboard's memory requests and limits ([#44712](https://github.com/kubernetes/kubernetes/pull/44712), [@maciaszczykm](https://github.com/maciaszczykm)) + +* Update Dashboard version to 1.6.1 ([[#45953](https://github.com/kubernetes/kubernetes/pull/45953)](https://github.com/kubernetes/kubernetes/pull/45953), [[@maciaszczykm](https://github.com/maciaszczykm)](https://github.com/maciaszczykm)) + + +#### kube-dns +* Updates kube-dns to 1.14.2 ([[#45684](https://github.com/kubernetes/kubernetes/pull/45684)](https://github.com/kubernetes/kubernetes/pull/45684), [[@bowei](https://github.com/bowei)](https://github.com/bowei)) + + * Support kube-master-url flag without kubeconfig + + * Fix concurrent R/Ws in dns.go + + * Fix confusing logging when initialize server + + * Fix printf in cmd/kube-dns/app/server.go + + * Fix version on startup and `--version` flag + + * Support specifying port number for nameserver in stubDomains + +#### kube-proxy +* Features: + + * ratelimit runs of iptables by sync-period flags ([[#46266](https://github.com/kubernetes/kubernetes/pull/46266)](https://github.com/kubernetes/kubernetes/pull/46266), [[@thockin](https://github.com/thockin)](https://github.com/thockin)) + + * Log warning when invalid dir passed to `kubectl proxy --www` ([[#44952](https://github.com/kubernetes/kubernetes/pull/44952)](https://github.com/kubernetes/kubernetes/pull/44952), [[@CaoShuFeng](https://github.com/CaoShuFeng)](https://github.com/CaoShuFeng)) + + * Add `--write-config-to` flag to kube-proxy to allow users to write the default configuration settings to a file. ([[#45908](https://github.com/kubernetes/kubernetes/pull/45908)](https://github.com/kubernetes/kubernetes/pull/45908), [[@ncdc](https://github.com/ncdc)](https://github.com/ncdc)) + + * When switching from the service.beta.kubernetes.io/external-traffic annotation to the new ([[#46716](https://github.com/kubernetes/kubernetes/pull/46716)](https://github.com/kubernetes/kubernetes/pull/46716), [[@thockin](https://github.com/thockin)](https://github.com/thockin)) externalTrafficPolicy field, the values chnag as follows: * "OnlyLocal" becomes "Local" * "Global" becomes "Cluster". + + +* Bug fixes: + + * Fix corner-case with OnlyLocal Service healthchecks. ([[#44313](https://github.com/kubernetes/kubernetes/pull/44313)](https://github.com/kubernetes/kubernetes/pull/44313), [[@thockin](https://github.com/thockin)](https://github.com/thockin)) + + * Fix DNS suffix search list support in Windows kube-proxy. ([[#45642](https://github.com/kubernetes/kubernetes/pull/45642)](https://github.com/kubernetes/kubernetes/pull/45642), [[@JiangtianLi](https://github.com/JiangtianLi)](https://github.com/JiangtianLi)) + +#### kube-scheduler +* Scheduler can receive its policy configuration from a ConfigMap ([[#43892](https://github.com/kubernetes/kubernetes/pull/43892)](https://github.com/kubernetes/kubernetes/pull/43892), [[@bsalamat](https://github.com/bsalamat)](https://github.com/bsalamat)) + +* Aggregated used ports at the NodeInfo level for PodFitsHostPorts predicate. ([[#42524](https://github.com/kubernetes/kubernetes/pull/42524)](https://github.com/kubernetes/kubernetes/pull/42524), [[@k82cn](https://github.com/k82cn)](https://github.com/k82cn)) + +* leader election lock based on scheduler name ([[#42961](https://github.com/kubernetes/kubernetes/pull/42961)](https://github.com/kubernetes/kubernetes/pull/42961), [[@wanghaoran1988](https://github.com/wanghaoran1988)](https://github.com/wanghaoran1988)) + + * Fix DNS suffix search list support in Windows kube-proxy. ([[#45642](https://github.com/kubernetes/kubernetes/pull/45642)](https://github.com/kubernetes/kubernetes/pull/45642), [[@JiangtianLi](https://github.com/JiangtianLi)](https://github.com/JiangtianLi)) + +#### Storage + +* Features + + * The options passed to a Flexvolume plugin's mount command now contains the pod name (kubernetes.io/pod.name), namespace (kubernetes.io/pod.namespace), uid (kubernetes.io/pod.uid), and service account name (kubernetes.io/serviceAccount.name). ([[#39488](https://github.com/kubernetes/kubernetes/pull/39488)](https://github.com/kubernetes/kubernetes/pull/39488), [[@liggitt](https://github.com/liggitt)](https://github.com/liggitt)) + + * GCE and AWS dynamic provisioners extension: admins can configure zone(s) in which a persistent volume shall be created. ([[#38505](https://github.com/kubernetes/kubernetes/pull/38505)](https://github.com/kubernetes/kubernetes/pull/38505), [[@pospispa](https://github.com/pospispa)](https://github.com/pospispa)) + + * Implement API usage metrics for GCE storage. ([[#40338](https://github.com/kubernetes/kubernetes/pull/40338)](https://github.com/kubernetes/kubernetes/pull/40338), [[@gnufied](https://github.com/gnufied)](https://github.com/gnufied)) + + * Add support for emitting metrics from openstack cloudprovider about storage operations. ([[#46008](https://github.com/kubernetes/kubernetes/pull/46008)](https://github.com/kubernetes/kubernetes/pull/46008), [[@NickrenREN](https://github.com/NickrenREN)](https://github.com/NickrenREN)) + + * vSphere cloud provider: vSphere storage policy support for dynamic volume provisioning. ([[#46176](https://github.com/kubernetes/kubernetes/pull/46176)](https://github.com/kubernetes/kubernetes/pull/46176), [[@BaluDontu](https://github.com/BaluDontu)](https://github.com/BaluDontu)) + + * Support StorageClass in Azure file volume ([[#42170](https://github.com/kubernetes/kubernetes/pull/42170)](https://github.com/kubernetes/kubernetes/pull/42170), [[@rootfs](https://github.com/rootfs)](https://github.com/rootfs)) + + * Start recording cloud provider metrics for AWS ([[#43477](https://github.com/kubernetes/kubernetes/pull/43477)](https://github.com/kubernetes/kubernetes/pull/43477), [[@gnufied](https://github.com/gnufied)](https://github.com/gnufied)) + + * Support iSCSI CHAP authentication ([[#43396](https://github.com/kubernetes/kubernetes/pull/43396)](https://github.com/kubernetes/kubernetes/pull/43396), [[@rootfs](https://github.com/rootfs)](https://github.com/rootfs)) + + * Openstack cinder v1/v2/auto API support ([[#40423](https://github.com/kubernetes/kubernetes/pull/40423)](https://github.com/kubernetes/kubernetes/pull/40423), [[@mkutsevol](https://github.com/mkutsevol)](https://github.com/mkutsevol * cinder: Add support for the KVM virtio-scsi driver ([[#41498](https://github.com/kubernetes/kubernetes/pull/41498)](https://github.com/kubernetes/kubernetes/pull/41498), [[@mikebryant](https://github.com/mikebryant)](https://github.com/mikebryant)) + + * Alpha feature: allows users to set storage limit to isolate EmptyDir volumes. It enforces the limit by evicting pods that exceed their storage limits ([[#45686](https://github.com/kubernetes/kubernetes/pull/45686)](https://github.com/kubernetes/kubernetes/pull/45686), [[@jingxu97](https://github.com/jingxu97)](https://github.com/jingxu97)) + +* Bug fixes + + * Fixes issue with Flexvolume, introduced in 1.6.0, where drivers without an attacher would fail (node indefinitely waiting for attach). A driver API addition is introduced: drivers that don't implement attach should return attach: false on init. ([[#47503](https://github.com/kubernetes/kubernetes/pull/47503)](https://github.com/kubernetes/kubernetes/pull/47503), [[@chakri-nelluri](https://github.com/chakri-nelluri)](https://github.com/chakri-nelluri)) + + * Fix dynamic provisioning of PVs with inaccurate AccessModes by refusing to provision when PVCs ask for AccessModes that can't be satisfied by the PVs' underlying volume plugin. ([[#47274](https://github.com/kubernetes/kubernetes/pull/47274)](https://github.com/kubernetes/kubernetes/pull/47274), [[@wongma7](https://github.com/wongma7)](https://github.com/wongma7)) + + * Fix pods failing to start if they specify a file as a volume subPath to mount. ([[#45623](https://github.com/kubernetes/kubernetes/pull/45623)](https://github.com/kubernetes/kubernetes/pull/45623), [[@wongma7](https://github.com/wongma7)](https://github.com/wongma7)) + + * Fix erroneous FailedSync and FailedMount events being periodically and indefinitely posted on Pods after kubelet is restarted. ([[#44781](https://github.com/kubernetes/kubernetes/pull/44781)](https://github.com/kubernetes/kubernetes/pull/44781), [[@wongma7](https://github.com/wongma7)](https://github.com/wongma7)) + + * Fix AWS EBS volumes not getting detached from node if routine to verify volumes are attached runs while the node is down ([[#46463](https://github.com/kubernetes/kubernetes/pull/46463)](https://github.com/kubernetes/kubernetes/pull/46463), [[@wongma7](https://github.com/wongma7)](https://github.com/wongma7)) + + * Improves performance of Cinder volume attach/detach operations. ([[#41785](https://github.com/kubernetes/kubernetes/pull/41785)](https://github.com/kubernetes/kubernetes/pull/41785), [[@jamiehannaford](https://github.com/jamiehannaford)](https://github.com/jamiehannaford)) + + * Fix iSCSI iSER mounting. ([[#47281](https://github.com/kubernetes/kubernetes/pull/47281)](https://github.com/kubernetes/kubernetes/pull/47281), [[@mtanino](https://github.com/mtanino)](https://github.com/mtanino)) + + * iscsi storage plugin: Fix dangling session when using multiple target portal addresses. ([[#46239](https://github.com/kubernetes/kubernetes/pull/46239)](https://github.com/kubernetes/kubernetes/pull/46239), [[@mtanino](https://github.com/mtanino)](https://github.com/mtanino)) + + + * Fix log spam due to unnecessary status update when node is deleted. ([[#45923](https://github.com/kubernetes/kubernetes/pull/45923)](https://github.com/kubernetes/kubernetes/pull/45923), [[@verult](https://github.com/verult)](https://github.com/verult)) + + * Don't try to attach volume to new node if it is already attached to another node and the volume does not support multi-attach. ([[#45346](https://github.com/kubernetes/kubernetes/pull/45346)](https://github.com/kubernetes/kubernetes/pull/45346), [[@codablock](https://github.com/codablock)](https://github.com/codablock)) + + * detach the volume when pod is terminated ([[#45286](https://github.com/kubernetes/kubernetes/pull/45286)](https://github.com/kubernetes/kubernetes/pull/45286), [[@gnufied](https://github.com/gnufied)](https://github.com/gnufied)) + + * Roll up volume error messages in the kubelet sync loop. ([[#44938](https://github.com/kubernetes/kubernetes/pull/44938)](https://github.com/kubernetes/kubernetes/pull/44938), [[@jayunit100](https://github.com/jayunit100)](https://github.com/jayunit100)) + + * Catch error when failed to make directory in NFS volume plugin ([[#38801](https://github.com/kubernetes/kubernetes/pull/38801)](https://github.com/kubernetes/kubernetes/pull/38801), [[@nak3](https://github.com/nak3)](https://github.com/nak3)) + + + +#### Networking + +* DNS and name resolution + + * Updates kube-dns to 1.14.2 ([[#45684](https://github.com/kubernetes/kubernetes/pull/45684)](https://github.com/kubernetes/kubernetes/pull/45684), [[@bowei](https://github.com/bowei)](https://github.com/bowei)) + + * Support kube-master-url flag without kubeconfig + + * Fix concurrent R/Ws in dns.go + + * Fix confusing logging when initializing server + + * Support specifying port number for nameserver in stubDomains + + * A new field hostAliases has been added to pod.spec to support adding entries to a Pod's /etc/hosts file. ([[#44641](https://github.com/kubernetes/kubernetes/pull/44641)](https://github.com/kubernetes/kubernetes/pull/44641), [[@rickypai](https://github.com/rickypai)](https://github.com/rickypai)) + + * Fix DNS suffix search list support in Windows kube-proxy. ([[#45642](https://github.com/kubernetes/kubernetes/pull/45642)](https://github.com/kubernetes/kubernetes/pull/45642), [[@JiangtianLi](https://github.com/JiangtianLi)](https://github.com/JiangtianLi)) + +* Kube-proxy + + * ratelimit runs of iptables by sync-period flags ([[#46266](https://github.com/kubernetes/kubernetes/pull/46266)](https://github.com/kubernetes/kubernetes/pull/46266), [[@thockin](https://github.com/thockin)](https://github.com/thockin)) + + * Fix corner-case with OnlyLocal Service healthchecks. ([[#44313](https://github.com/kubernetes/kubernetes/pull/44313)](https://github.com/kubernetes/kubernetes/pull/44313), [[@thockin](https://github.com/thockin)](https://github.com/thockin)) + +* Exclude nodes labeled as master from LoadBalancer / NodePort; restores documented behaviour. ([[#44745](https://github.com/kubernetes/kubernetes/pull/44745)](https://github.com/kubernetes/kubernetes/pull/44745), [[@justinsb](https://github.com/justinsb)](https://github.com/justinsb)) + +* Adds support for CNI ConfigLists, which permit plugin chaining. ([[#42202](https://github.com/kubernetes/kubernetes/pull/42202)](https://github.com/kubernetes/kubernetes/pull/42202), [[@squeed](https://github.com/squeed)](https://github.com/squeed)) + +* Fix node selection logic on initial LB creation ([[#45773](https://github.com/kubernetes/kubernetes/pull/45773)](https://github.com/kubernetes/kubernetes/pull/45773), [[@justinsb](https://github.com/justinsb)](https://github.com/justinsb)) + +* When switching from the service.beta.kubernetes.io/external-traffic annotation to the new externalTrafficPolicy field, the values change as follows: * "OnlyLocal" becomes "Local" * "Global" becomes "Cluster". ([[#46716](https://github.com/kubernetes/kubernetes/pull/46716)](https://github.com/kubernetes/kubernetes/pull/46716), [[@thockin](https://github.com/thockin)](https://github.com/thockin)) + +* servicecontroller: Fix node selection logic on initial LB creation ([[#45773](https://github.com/kubernetes/kubernetes/pull/45773)](https://github.com/kubernetes/kubernetes/pull/45773), [[@justinsb](https://github.com/justinsb)](https://github.com/justinsb)) + +* fixed HostAlias in PodSpec to allow foo.bar hostnames instead of just foo DNS labels. ([[#46809](https://github.com/kubernetes/kubernetes/pull/46809)](https://github.com/kubernetes/kubernetes/pull/46809), [[@rickypai](https://github.com/rickypai)](https://github.com/rickypai)) + + +#### Node controller +* Bug fixes: + + * Fix [transition between NotReady and Unreachable taints](https://github.com/kubernetes/kubernetes/issues/43444). ([[#44042](https://github.com/kubernetes/kubernetes/pull/44042)](https://github.com/kubernetes/kubernetes/pull/44042), [[@gmarek](https://github.com/gmarek)](https://github.com/gmarek)) + + +#### Node Components + +* Features + + * Removes the deprecated kubelet flag `--babysit-daemons` ([[#44230](https://github.com/kubernetes/kubernetes/pull/44230)](https://github.com/kubernetes/kubernetes/pull/44230), [[@mtaufen](https://github.com/mtaufen)](https://github.com/mtaufen)) + + * make dockershim.sock configurable ([[#43914](https://github.com/kubernetes/kubernetes/pull/43914)](https://github.com/kubernetes/kubernetes/pull/43914), [[@ncdc](https://github.com/ncdc)](https://github.com/ncdc)) + + * Support running Ubuntu image on GCE node ([[#44744](https://github.com/kubernetes/kubernetes/pull/44744)](https://github.com/kubernetes/kubernetes/pull/44744), [[@yguo0905](https://github.com/yguo0905)](https://github.com/yguo0905)) + + * Kubernetes now shares a single PID namespace among all containers in a pod when running with docker >= 1.13.1. This means processes can now signal processes in other containers in a pod, but it also means that the `kubectl exec {pod} kill 1` pattern will cause the Pod to be restarted rather than a single container. ([[#45236](https://github.com/kubernetes/kubernetes/pull/45236)](https://github.com/kubernetes/kubernetes/pull/45236), [[@verb](https://github.com/verb)](https://github.com/verb)) + + * A new field hostAliases has been added to the pod spec to support [adding entries to a Pod's /etc/hosts file](https://kubernetes.io/docs/concepts/services-networking/add-entries-to-pod-etc-hosts-with-host-aliases/). ([[#44641](https://github.com/kubernetes/kubernetes/pull/44641)](https://github.com/kubernetes/kubernetes/pull/44641), [[@rickypai](https://github.com/rickypai)](https://github.com/rickypai)) + + * With `--feature-gates=RotateKubeletClientCertificate=true` set, the Kubelet will ([[#41912](https://github.com/kubernetes/kubernetes/pull/41912)](https://github.com/kubernetes/kubernetes/pull/41912), [[@jcbsmpsn](https://github.com/jcbsmpsn)](https://github.com/jcbsmpsn)) + + * request a client certificate from the API server during the boot cycle and pause + + * waiting for the request to be satisfied. It will continually refresh the certificate + + * Create clusters with GPUs in GCE by specifying `type=,count=` to NODE_ACCELERATORS environment variable. ([[#45130](https://github.com/kubernetes/kubernetes/pull/45130)](https://github.com/kubernetes/kubernetes/pull/45130), [[@vishh](https://github.com/vishh)](https://github.com/vishh)) + + * List of available GPUs - [https://cloud.google.com/compute/docs/gpus/#introduction](https://cloud.google.com/compute/docs/gpus/#introduction) + + * Disk Pressure triggers the deletion of terminated containers on the node. ([[#45896](https://github.com/kubernetes/kubernetes/pull/45896)](https://github.com/kubernetes/kubernetes/pull/45896), [[@dashpole](https://github.com/dashpole)](https://github.com/dashpole)) + + * Support status.hostIP in downward API ([[#42717](https://github.com/kubernetes/kubernetes/pull/42717)](https://github.com/kubernetes/kubernetes/pull/42717), [[@andrewsykim](https://github.com/andrewsykim)](https://github.com/andrewsykim)) + + * Upgrade Node Problem Detector to v0.4.1. New features added: + + * Add /dev/kmsg support for kernel log parsing. ([#112](https://github.com/kubernetes/node-problem-detector/pull/112), [[@euank](https://github.com/euank)](https://github.com/euank)) + + * Add ABRT support. ([#105](https://github.com/kubernetes/node-problem-detector/pull/105), [[@juliusmilan](https://github.com/juliusmilan)](https://github.com/juliusmilan)) + + * Add a docker image corruption problem detection in the default docker monitor config. ([#117](https://github.com/kubernetes/node-problem-detector/pull/117), [[@ajitak](https://github.com/ajitak)](https://github.com/ajitak)) + + * Upgrade CAdvisor to v0.26.1. New features added: + + * Add Docker overlay2 storage driver support. + + * Add ZFS support. + + * Add UDP metrics (collection disabled by default). + + * Roll up volume error messages in the kubelet sync loop. ([[#44938](https://github.com/kubernetes/kubernetes/pull/44938)](https://github.com/kubernetes/kubernetes/pull/44938), [[@jayunit100](https://github.com/jayunit100)](https://github.com/jayunit100)) + + * Allow pods to opt out of PodPreset mutation via an annotation on the pod. ([[#44965](https://github.com/kubernetes/kubernetes/pull/44965)](https://github.com/kubernetes/kubernetes/pull/44965), [[@jpeeler](https://github.com/jpeeler)](https://github.com/jpeeler)) + + * Add generic Toleration for NoExecute Taints to NodeProblemDetector, so that NPD can be scheduled to nodes with NoExecute taints by default. ([[#45883](https://github.com/kubernetes/kubernetes/pull/45883)](https://github.com/kubernetes/kubernetes/pull/45883), [[@gmarek](https://github.com/gmarek)](https://github.com/gmarek)) + + * Prevent kubelet from setting allocatable < 0 for a resource upon initial creation. ([[#46516](https://github.com/kubernetes/kubernetes/pull/46516)](https://github.com/kubernetes/kubernetes/pull/46516), [[@derekwaynecarr](https://github.com/derekwaynecarr)](https://github.com/derekwaynecarr)) + +* Bug fixes + + * Changed Kubelet default image-gc-high-threshold to 85% to resolve a conflict with default settings in docker that prevented image garbage collection from resolving low disk space situations when using devicemapper storage. ([[#40432](https://github.com/kubernetes/kubernetes/pull/40432)](https://github.com/kubernetes/kubernetes/pull/40432), [[@sjenning](https://github.com/sjenning)](https://github.com/sjenning)) + + * Mark all static pods on the Master node as critical to prevent preemption ([[#47356](https://github.com/kubernetes/kubernetes/pull/47356)](https://github.com/kubernetes/kubernetes/pull/47356), [[@dashpole](https://github.com/dashpole)](https://github.com/dashpole)) + + * Restrict active deadline seconds max allowed value to be maximum uint32 to avoid overflow ([[#46640](https://github.com/kubernetes/kubernetes/pull/46640)](https://github.com/kubernetes/kubernetes/pull/46640), [[@derekwaynecarr](https://github.com/derekwaynecarr)](https://github.com/derekwaynecarr)) + + * Fix a bug with cAdvisorPort in the KubeletConfiguration that prevented setting it to 0, which is in fact a valid option, as noted in issue [[#11710](https://github.com/kubernetes/kubernetes/pull/11710)](https://github.com/kubernetes/kubernetes/pull/11710). ([[#46876](https://github.com/kubernetes/kubernetes/pull/46876)](https://github.com/kubernetes/kubernetes/pull/46876), [[@mtaufen](https://github.com/mtaufen)](https://github.com/mtaufen)) + + * Fix a bug where container cannot run as root when SecurityContext.RunAsNonRoot is false. ([[#47009](https://github.com/kubernetes/kubernetes/pull/47009)](https://github.com/kubernetes/kubernetes/pull/47009), [[@yujuhong](https://github.com/yujuhong)](https://github.com/yujuhong)) + + * Fix the Kubelet PLEG update timestamp to better reflect the health of the component when the container runtime request hangs. ([[#45496](https://github.com/kubernetes/kubernetes/pull/45496)](https://github.com/kubernetes/kubernetes/pull/45496), [[@andyxning](https://github.com/andyxning)](https://github.com/andyxning)) + + * Avoid failing sync loop health check on container runtime errors ([[#47124](https://github.com/kubernetes/kubernetes/pull/47124)](https://github.com/kubernetes/kubernetes/pull/47124), [[@andyxning](https://github.com/andyxning)](https://github.com/andyxning)) + + * Fix a bug where Kubelet does not ignore pod manifest files starting with dots ([[#45111](https://github.com/kubernetes/kubernetes/pull/45111)](https://github.com/kubernetes/kubernetes/pull/45111), [[@dwradcliffe](https://github.com/dwradcliffe)](https://github.com/dwradcliffe)) + + * Fix kubelet reset liveness probe failure count across pod restart boundaries ([[#46371](https://github.com/kubernetes/kubernetes/pull/46371)](https://github.com/kubernetes/kubernetes/pull/46371), [[@sjenning](https://github.com/sjenning)](https://github.com/sjenning)) + + * Fix log spam due to unnecessary status update when node is deleted. ([[#45923](https://github.com/kubernetes/kubernetes/pull/45923)](https://github.com/kubernetes/kubernetes/pull/45923), [[@verult](https://github.com/verult)](https://github.com/verult)) + + * Fix kubelet event recording for selected events. ([[#46246](https://github.com/kubernetes/kubernetes/pull/46246)](https://github.com/kubernetes/kubernetes/pull/46246), [[@derekwaynecarr](https://github.com/derekwaynecarr)](https://github.com/derekwaynecarr)) + + * Fix image garbage collector attempting to remove in-use images. ([[#46121](https://github.com/kubernetes/kubernetes/pull/46121)](https://github.com/kubernetes/kubernetes/pull/46121), [[@Random-Liu](https://github.com/Random-Liu)](https://github.com/Random-Liu)) + + * Detach the volume when pod is terminated ([[#45286](https://github.com/kubernetes/kubernetes/pull/45286)](https://github.com/kubernetes/kubernetes/pull/45286), [[@gnufied](https://github.com/gnufied)](https://github.com/gnufied)) + + * CRI: Fix StopContainer timeout ([[#44970](https://github.com/kubernetes/kubernetes/pull/44970)](https://github.com/kubernetes/kubernetes/pull/44970), [[@Random-Liu](https://github.com/Random-Liu)](https://github.com/Random-Liu)) + + * CRI: Fix kubelet failing to start when using rkt. ([[#44569](https://github.com/kubernetes/kubernetes/pull/44569)](https://github.com/kubernetes/kubernetes/pull/44569), [[@yujuhong](https://github.com/yujuhong)](https://github.com/yujuhong)) + + * CRI: `kubectl logs -f` now stops following when container stops, as it did pre-CRI. ([[#44406](https://github.com/kubernetes/kubernetes/pull/44406)](https://github.com/kubernetes/kubernetes/pull/44406), [[@Random-Liu](https://github.com/Random-Liu)](https://github.com/Random-Liu)) + + * Fixes a bug where pods were evicted even after images are successfully deleted. ([[#44986](https://github.com/kubernetes/kubernetes/pull/44986)](https://github.com/kubernetes/kubernetes/pull/44986), [[@dashpole](https://github.com/dashpole)](https://github.com/dashpole)) + + * When creating a container using envFrom, ([[#42083](https://github.com/kubernetes/kubernetes/pull/42083)](https://github.com/kubernetes/kubernetes/pull/42083), [[@fraenkel](https://github.com/fraenkel)](https://github.com/fraenkel) + * validate the name of the ConfigMap in a ConfigMapRef + * validate the name of the Secret in a SecretRef + + * Fix the bug where StartedAt time is not reported for exited containers. ([[#45977](https://github.com/kubernetes/kubernetes/pull/45977)](https://github.com/kubernetes/kubernetes/pull/45977), [[@yujuhong](https://github.com/yujuhong)](https://github.com/yujuhong)) + +* Changes/deprecations + + * Marks the Kubelet's `--master-service-namespace` flag deprecated ([[#44250](https://github.com/kubernetes/kubernetes/pull/44250)](https://github.com/kubernetes/kubernetes/pull/44250), [[@mtaufen](https://github.com/mtaufen)](https://github.com/mtaufen)) + + * Remove PodSandboxStatus.Linux.Namespaces.Network from CRI since it is not used/needed. ([[#45166](https://github.com/kubernetes/kubernetes/pull/45166)](https://github.com/kubernetes/kubernetes/pull/45166), [[@feiskyer](https://github.com/feiskyer)](https://github.com/feiskyer)) + + * Remove the `--enable-cri` flag. CRI is now the default, and the only way to integrate with Kubelet for the container runtimes.([[#45194](https://github.com/kubernetes/kubernetes/pull/45194)](https://github.com/kubernetes/kubernetes/pull/45194), [[@yujuhong](https://github.com/yujuhong)](https://github.com/yujuhong)) + + * CRI has been moved to package pkg/kubelet/apis/cri/v1alpha1/runtime as part of Kubelet API path cleanup. ([[#47113](https://github.com/kubernetes/kubernetes/pull/47113)](https://github.com/kubernetes/kubernetes/pull/47113), [[@feiskyer](https://github.com/feiskyer)](https://github.com/feiskyer)) + + +#### Scheduling + +* The fix makes scheduling go routine waiting for cache (e.g. Pod) to be synced. ([[#45453](https://github.com/kubernetes/kubernetes/pull/45453)](https://github.com/kubernetes/kubernetes/pull/45453), [[@k82cn](https://github.com/k82cn)](https://github.com/k82cn)) + +* Move hardPodAffinitySymmetricWeight to scheduler policy config ([[#44159](https://github.com/kubernetes/kubernetes/pull/44159)](https://github.com/kubernetes/kubernetes/pull/44159), [[@wanghaoran1988](https://github.com/wanghaoran1988)](https://github.com/wanghaoran1988)) + +* Align Extender's validation with prioritizers. ([[#45091](https://github.com/kubernetes/kubernetes/pull/45091)](https://github.com/kubernetes/kubernetes/pull/45091), [[@k82cn](https://github.com/k82cn)](https://github.com/k82cn)) + +* Removed old scheduler constructor. ([[#45472](https://github.com/kubernetes/kubernetes/pull/45472)](https://github.com/kubernetes/kubernetes/pull/45472), [[@k82cn](https://github.com/k82cn)](https://github.com/k82cn)) + +* Fixes the overflow for priorityconfig- valid range {1, 9223372036854775806}. ([[#45122](https://github.com/kubernetes/kubernetes/pull/45122)](https://github.com/kubernetes/kubernetes/pull/45122), [[@ravisantoshgudimetla](https://github.com/ravisantoshgudimetla)](https://github.com/ravisantoshgudimetla)) + +* Move hardPodAffinitySymmetricWeight to scheduler policy config ([[#44159](https://github.com/kubernetes/kubernetes/pull/44159)](https://github.com/kubernetes/kubernetes/pull/44159), [[@wanghaoran1988](https://github.com/wanghaoran1988)](https://github.com/wanghaoran1988)) + + +#### Security +* Features: + + * Permission to use a PodSecurityPolicy can now be granted within a single namespace by allowing the use verb on the podsecuritypolicies resource within the namespace. ([[#42360](https://github.com/kubernetes/kubernetes/pull/42360)](https://github.com/kubernetes/kubernetes/pull/42360), [[@liggitt](https://github.com/liggitt)](https://github.com/liggitt)) + + * Break the 'certificatesigningrequests' controller into a 'csrapprover' controller and 'csrsigner' controller. ([[#45514](https://github.com/kubernetes/kubernetes/pull/45514)](https://github.com/kubernetes/kubernetes/pull/45514), [[@mikedanese](https://github.com/mikedanese)](https://github.com/mikedanese)) + + * `kubectl auth can-i` now supports non-resource URLs ([[#46432](https://github.com/kubernetes/kubernetes/pull/46432)](https://github.com/kubernetes/kubernetes/pull/46432), [[@CaoShuFeng](https://github.com/CaoShuFeng)](https://github.com/CaoShuFeng)) + + * Promote kubelet tls bootstrap to beta. Add a non-experimental flag to use it and deprecate the old flag. ([[#46799](https://github.com/kubernetes/kubernetes/pull/46799)](https://github.com/kubernetes/kubernetes/pull/46799), [[@mikedanese](https://github.com/mikedanese)](https://github.com/mikedanese)) + + * Add the alpha.image-policy.k8s.io/failed-open=true annotation when the image policy webhook encounters an error and fails open. ([[#46264](https://github.com/kubernetes/kubernetes/pull/46264)](https://github.com/kubernetes/kubernetes/pull/46264), [[@Q-Lee](https://github.com/Q-Lee)](https://github.com/Q-Lee)) + + * Add an AEAD encrypting transformer for storing secrets encrypted at rest ([[#41939](https://github.com/kubernetes/kubernetes/pull/41939)](https://github.com/kubernetes/kubernetes/pull/41939), [[@smarterclayton](https://github.com/smarterclayton)](https://github.com/smarterclayton)) + + * Add secretbox and AES-CBC encryption modes to at rest encryption. AES-CBC is considered superior to AES-GCM because it is resistant to nonce-reuse attacks, and secretbox uses Poly1305 and XSalsa20. ([[#46916](https://github.com/kubernetes/kubernetes/pull/46916)](https://github.com/kubernetes/kubernetes/pull/46916), [[@smarterclayton](https://github.com/smarterclayton)](https://github.com/smarterclayton)) + +* Bug fixes: + + * Make gcp auth provider not to override the Auth header if it's already exits ([[#45575](https://github.com/kubernetes/kubernetes/pull/45575)](https://github.com/kubernetes/kubernetes/pull/45575), [[@wanghaoran1988](https://github.com/wanghaoran1988)](https://github.com/wanghaoran1988)) + + * The oidc client plugin has reduce round trips and fix scopes requested ([[#45317](https://github.com/kubernetes/kubernetes/pull/45317)](https://github.com/kubernetes/kubernetes/pull/45317), [[@ericchiang](https://github.com/ericchiang)](https://github.com/ericchiang)) + + * API requests using impersonation now include the system:authenticated group in the impersonated user automatically. ([[#44076](https://github.com/kubernetes/kubernetes/pull/44076)](https://github.com/kubernetes/kubernetes/pull/44076), [[@liggitt](https://github.com/liggitt)](https://github.com/liggitt)) + + * RBAC role and rolebinding auto-reconciliation is now performed only when the RBAC authorization mode is enabled. ([[#43813](https://github.com/kubernetes/kubernetes/pull/43813)](https://github.com/kubernetes/kubernetes/pull/43813), [[@liggitt](https://github.com/liggitt)](https://github.com/liggitt)) + + * PodSecurityPolicy now recognizes pods that specify runAsNonRoot: false in their security context and does not overwrite the specified value ([[#47073](https://github.com/kubernetes/kubernetes/pull/47073)](https://github.com/kubernetes/kubernetes/pull/47073), [[@Q-Lee](https://github.com/Q-Lee)](https://github.com/Q-Lee)) + + * Tokens retrieved from Google Cloud with application default credentials will not be cached if the client fails authorization ([[#46694](https://github.com/kubernetes/kubernetes/pull/46694)](https://github.com/kubernetes/kubernetes/pull/46694), [[@matt-tyler](https://github.com/matt-tyler)](https://github.com/matt-tyler)) + + * Update kube-dns, metadata-proxy, and fluentd-gcp, event-exporter, prometheus-to-sd, and ip-masq-agent addons with new base images containing fixes for CVE-2016-4448, CVE-2016-9841, CVE-2016-9843, CVE-2017-1000366, CVE-2017-2616, and CVE-2017-9526. ([[#47877](https://github.com/kubernetes/kubernetes/pull/47877)](https://github.com/kubernetes/kubernetes/pull/47877), [[@ixdy](https://github.com/ixdy)](https://github.com/ixdy)) + + * Fixed an issue mounting the wrong secret into pods as a service account token. ([[#44102](https://github.com/kubernetes/kubernetes/pull/44102)](https://github.com/kubernetes/kubernetes/pull/44102), [[@ncdc](https://github.com/ncdc)](https://github.com/ncdc)) + +#### Scalability + +* The HorizontalPodAutoscaler controller will now only send updates when it has new status information, reducing the number of writes caused by the controller. ([[#47078](https://github.com/kubernetes/kubernetes/pull/47078)](https://github.com/kubernetes/kubernetes/pull/47078), [[@DirectXMan12](https://github.com/DirectXMan12)](https://github.com/DirectXMan12)) + + +## **External Dependency Version Information** + +Continuous integration builds have used the following versions of external dependencies, however, this is not a strong recommendation and users should consult an appropriate installation or upgrade guide before deciding what versions of etcd, docker or rkt to use. + +* Docker versions 1.10.3, 1.11.2, 1.12.6 have been validated + + * Docker version 1.12.6 known issues + + * overlay2 driver not fully supported + + * live-restore not fully supported + + * no shared pid namespace support + + * Docker version 1.11.2 known issues + + * Kernel crash with Aufs storage driver on Debian Jessie ([[#27885](https://github.com/kubernetes/kubernetes/pull/27885)](https://github.com/kubernetes/kubernetes/issues/27885)) which can be identified by the [node problem detector](https://kubernetes.io/docs/tasks/debug-application-cluster/monitor-node-health/) + + * Leaked File descriptors ([#275](https://github.com/docker/containerd/issues/275)) + + * Additional memory overhead per container ([[#21737](https://github.com/kubernetes/kubernetes/pull/21737)](https://github.com/docker/docker/issues/21737)) + + * Docker 1.10.3 contains [backports provided by RedHat](https://github.com/docker/docker/compare/v1.10.3...runcom:docker-1.10.3-stable) for known issues + +* For issues with Docker 1.13.X please see the [1.13.X tracking issue](https://github.com/kubernetes/kubernetes/issues/42926) + +* rkt version 1.23.0+ + + * known issues with the rkt runtime are [listed in the Getting Started Guide](https://kubernetes.io/docs/getting-started-guides/rkt/notes/) + +* etcd version 3.0.17 + +* Go version: 1.8.3. [Link to announcement](https://groups.google.com/d/msg/kubernetes-dev/0XRRz6UhhTM/YODWVnuDBQAJ) + + * Kubernetes can only be compiled with Go 1.8. Support for all other versions is dropped. ### Previous Releases Included in v1.7.0 From 17a0f17118fbd3c527a9e0a7a939e2211a6b1ef9 Mon Sep 17 00:00:00 2001 From: liujun137 Date: Fri, 30 Jun 2017 14:49:09 +0800 Subject: [PATCH 141/448] Remove duplicated line from ceph-secret-admin.yaml --- .../persistent-volume-provisioning/rbd/ceph-secret-admin.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/examples/persistent-volume-provisioning/rbd/ceph-secret-admin.yaml b/examples/persistent-volume-provisioning/rbd/ceph-secret-admin.yaml index f86d975f7f7..894a9df6b4a 100644 --- a/examples/persistent-volume-provisioning/rbd/ceph-secret-admin.yaml +++ b/examples/persistent-volume-provisioning/rbd/ceph-secret-admin.yaml @@ -6,4 +6,3 @@ type: "kubernetes.io/rbd" data: #Please note this value is base64 encoded. key: QVFEQ1pMdFhPUnQrSmhBQUFYaERWNHJsZ3BsMmNjcDR6RFZST0E9PQ== -type: kubernetes.io/rbd From ba3e49b56d88f5c9934e7c32922e1ad2684ab4b9 Mon Sep 17 00:00:00 2001 From: Dong Liu Date: Fri, 30 Jun 2017 15:09:39 +0800 Subject: [PATCH 142/448] Fix share name generation in azure file provisioner. --- pkg/volume/azure_file/azure_provision.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pkg/volume/azure_file/azure_provision.go b/pkg/volume/azure_file/azure_provision.go index 1020b60cc84..12bd0a1008e 100644 --- a/pkg/volume/azure_file/azure_provision.go +++ b/pkg/volume/azure_file/azure_provision.go @@ -134,7 +134,9 @@ var _ volume.Provisioner = &azureFileProvisioner{} func (a *azureFileProvisioner) Provision() (*v1.PersistentVolume, error) { var sku, location, account string - name := volume.GenerateVolumeName(a.options.ClusterName, a.options.PVName, 75) + // File share name has a length limit of 63, and it cannot contain two consecutive '-'s. + name := volume.GenerateVolumeName(a.options.ClusterName, a.options.PVName, 63) + name = strings.Replace(name, "--", "-", -1) capacity := a.options.PVC.Spec.Resources.Requests[v1.ResourceName(v1.ResourceStorage)] requestBytes := capacity.Value() requestGB := int(volume.RoundUpSize(requestBytes, 1024*1024*1024)) From d93aa71fd3ed46dfe9dd0235976c647578e1d65b Mon Sep 17 00:00:00 2001 From: xiangpengzhao Date: Fri, 30 Jun 2017 16:24:21 +0800 Subject: [PATCH 143/448] Fix broken mardown format in v1.7 CHANGELOG --- CHANGELOG.md | 628 +++++++++++++++++++++++++-------------------------- 1 file changed, 310 insertions(+), 318 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3671e249170..44729a1878d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -780,7 +780,7 @@ Extensibility features include API aggregation (beta), CustomResourceDefinitions ### Network -* NetworkPolicy has been promoted from extensions/v1beta1 to the new networking.k8s.io/v1 API group. The structure remains unchanged from the v1beta1 API. The net.beta.kubernetes.io/network-policy annotation on Namespaces (used to opt in to isolation) has been removed. Instead, isolation is now determined on a per-pod basis. A NetworkPolicy may target a pod for isolation by including the pod in its spec.podSelector. Targeted Pods accept the traffic specified in the respective NetworkPolicy (and nothing else). Pods not targeted by any NetworkPolicy accept all traffic by default. ([[#39164](https://github.com/kubernetes/kubernetes/pull/39164)](https://github.com/kubernetes/kubernetes/pull/39164), [[@danwinship](https://github.com/danwinship)](https://github.com/danwinship)) +* NetworkPolicy has been promoted from extensions/v1beta1 to the new networking.k8s.io/v1 API group. The structure remains unchanged from the v1beta1 API. The net.beta.kubernetes.io/network-policy annotation on Namespaces (used to opt in to isolation) has been removed. Instead, isolation is now determined on a per-pod basis. A NetworkPolicy may target a pod for isolation by including the pod in its spec.podSelector. Targeted Pods accept the traffic specified in the respective NetworkPolicy (and nothing else). Pods not targeted by any NetworkPolicy accept all traffic by default. ([#39164](https://github.com/kubernetes/kubernetes/pull/39164), [@danwinship](https://github.com/danwinship)) **Action Required:** When upgrading to Kubernetes 1.7 (and a [network plugin](https://kubernetes.io/docs/tasks/administer-cluster/declare-network-policy/) that supports the new NetworkPolicy v1 semantics), you should consider the following. @@ -802,20 +802,20 @@ Extensibility features include API aggregation (beta), CustomResourceDefinitions ### Storage -* Alpha volume provisioning is removed and default storage class should be used instead. ([[#44090](https://github.com/kubernetes/kubernetes/pull/44090)](https://github.com/kubernetes/kubernetes/pull/44090), [[@NickrenREN](https://github.com/NickrenREN)](https://github.com/NickrenREN)) +* Alpha volume provisioning is removed and default storage class should be used instead. ([#44090](https://github.com/kubernetes/kubernetes/pull/44090), [@NickrenREN](https://github.com/NickrenREN)) -* Portworx volume driver no longer has to run on the master. ([[#45518](https://github.com/kubernetes/kubernetes/pull/45518)](https://github.com/kubernetes/kubernetes/pull/45518), [[@harsh-px](https://github.com/harsh-px)](https://github.com/harsh-px)) +* Portworx volume driver no longer has to run on the master. ([#45518](https://github.com/kubernetes/kubernetes/pull/45518), [@harsh-px](https://github.com/harsh-px)) -* Default behavior in Cinder storageclass is changed. If availability is not specified, the zone is chosen by algorithm. It makes possible to spread stateful pods across many zones. ([[#44798](https://github.com/kubernetes/kubernetes/pull/44798)](https://github.com/kubernetes/kubernetes/pull/44798), [[@zetaab](https://github.com/zetaab)](https://github.com/zetaab)) +* Default behavior in Cinder storageclass is changed. If availability is not specified, the zone is chosen by algorithm. It makes possible to spread stateful pods across many zones. ([#44798](https://github.com/kubernetes/kubernetes/pull/44798), [@zetaab](https://github.com/zetaab)) -* PodSpecs containing parent directory references such as `..` (for example, `../bar`) in hostPath volume path or in volumeMount subpaths must be changed to the simple absolute path. Backsteps `..` are no longer allowed.([[#47290](https://github.com/kubernetes/kubernetes/pull/47290)](https://github.com/kubernetes/kubernetes/pull/47290), [[@jhorwit2](https://github.com/jhorwit2)](https://github.com/jhorwit2)). +* PodSpecs containing parent directory references such as `..` (for example, `../bar`) in hostPath volume path or in volumeMount subpaths must be changed to the simple absolute path. Backsteps `..` are no longer allowed.([#47290](https://github.com/kubernetes/kubernetes/pull/47290), [@jhorwit2](https://github.com/jhorwit2)). ### API Machinery -* The Namespace API object no longer supports the deletecollection operation. ([[#46407](https://github.com/kubernetes/kubernetes/pull/46407)](https://github.com/kubernetes/kubernetes/pull/46407), [[@liggitt](https://github.com/liggitt)](https://github.com/liggitt)) +* The Namespace API object no longer supports the deletecollection operation. ([#46407](https://github.com/kubernetes/kubernetes/pull/46407), [@liggitt](https://github.com/liggitt)) -* The following alpha API groups were unintentionally enabled by default in previous releases, and will no longer be enabled by default in v1.8: ([[#47690](https://github.com/kubernetes/kubernetes/pull/47690)](https://github.com/kubernetes/kubernetes/pull/47690), [[@caesarxuchao](https://github.com/caesarxuchao)](https://github.com/caesarxuchao)) +* The following alpha API groups were unintentionally enabled by default in previous releases, and will no longer be enabled by default in v1.8: ([#47690](https://github.com/kubernetes/kubernetes/pull/47690), [@caesarxuchao](https://github.com/caesarxuchao)) * rbac.authorization.k8s.io/v1alpha1 @@ -823,34 +823,34 @@ Extensibility features include API aggregation (beta), CustomResourceDefinitions * If you wish to continue using them in v1.8, please enable them explicitly using the `--runtime-config` flag on the apiserver (for example, `--runtime-config="rbac.authorization.k8s.io/v1alpha1,settings.k8s.io/v1alpha1"`) -* `cluster/update-storage-objects.sh` now supports updating StorageClasses in etcd to storage.k8s.io/v1. You must do this prior to upgrading to 1.8. ([[#46116](https://github.com/kubernetes/kubernetes/pull/46116)](https://github.com/kubernetes/kubernetes/pull/46116), [[@ncdc](https://github.com/ncdc)](https://github.com/ncdc)) +* `cluster/update-storage-objects.sh` now supports updating StorageClasses in etcd to storage.k8s.io/v1. You must do this prior to upgrading to 1.8. ([#46116](https://github.com/kubernetes/kubernetes/pull/46116), [@ncdc](https://github.com/ncdc)) ### Controller Manager -* kube-controller-manager has dropped support for the `--insecure-experimental-approve-all-kubelet-csrs-for-group` flag. It is accepted in 1.7, but ignored. Instead, the csrapproving controller uses authorization checks to determine whether to approve certificate signing requests: ([[#45619](https://github.com/kubernetes/kubernetes/pull/45619)](https://github.com/kubernetes/kubernetes/pull/45619), [[@mikedanese](https://github.com/mikedanese)](https://github.com/mikedanese)) +* kube-controller-manager has dropped support for the `--insecure-experimental-approve-all-kubelet-csrs-for-group` flag. It is accepted in 1.7, but ignored. Instead, the csrapproving controller uses authorization checks to determine whether to approve certificate signing requests: ([#45619](https://github.com/kubernetes/kubernetes/pull/45619), [@mikedanese](https://github.com/mikedanese)) * Before upgrading, users must ensure their controller manager will enable the csrapproving controller, create an RBAC ClusterRole and ClusterRoleBinding to approve CSRs for the same group, then upgrade. Example roles to enable the equivalent behavior can be found in the [TLS bootstrapping](https://kubernetes.io/docs/admin/kubelet-tls-bootstrapping/) documentation. ### kubectl (CLI) -* `kubectl create role` and `kubectl create clusterrole` invocations must be updated to specify multiple resource names as repeated `--resource-name` arguments instead of comma-separated arguments to a single `--resource-name` argument. E.g. `--resource-name=x,y` must become `--resource-name x --resource-name y` ([[#44950](https://github.com/kubernetes/kubernetes/pull/44950)](https://github.com/kubernetes/kubernetes/pull/44950), [[@xilabao](https://github.com/xilabao)](https://github.com/xilabao)) +* `kubectl create role` and `kubectl create clusterrole` invocations must be updated to specify multiple resource names as repeated `--resource-name` arguments instead of comma-separated arguments to a single `--resource-name` argument. E.g. `--resource-name=x,y` must become `--resource-name x --resource-name y` ([#44950](https://github.com/kubernetes/kubernetes/pull/44950), [@xilabao](https://github.com/xilabao)) -* `kubectl create rolebinding` and `kubectl create clusterrolebinding` invocations must be updated to specify multiple subjects as repeated `--user`, `--group`, or `--serviceaccount` arguments instead of comma-separated arguments to a single `--user`, `--group`, or `--serviceaccount`. E.g. `--user=x,y` must become `--user x --user y` ([[#43903](https://github.com/kubernetes/kubernetes/pull/43903)](https://github.com/kubernetes/kubernetes/pull/43903), [[@xilabao](https://github.com/xilabao)](https://github.com/xilabao)) +* `kubectl create rolebinding` and `kubectl create clusterrolebinding` invocations must be updated to specify multiple subjects as repeated `--user`, `--group`, or `--serviceaccount` arguments instead of comma-separated arguments to a single `--user`, `--group`, or `--serviceaccount`. E.g. `--user=x,y` must become `--user x --user y` ([#43903](https://github.com/kubernetes/kubernetes/pull/43903), [@xilabao](https://github.com/xilabao)) ### kubeadm -* kubeadm: Modifications to cluster-internal resources installed by kubeadm will be overwritten when upgrading from v1.6 to v1.7. ([[#47081](https://github.com/kubernetes/kubernetes/pull/47081)](https://github.com/kubernetes/kubernetes/pull/47081), [[@luxas](https://github.com/luxas)](https://github.com/luxas)) +* kubeadm: Modifications to cluster-internal resources installed by kubeadm will be overwritten when upgrading from v1.6 to v1.7. ([#47081](https://github.com/kubernetes/kubernetes/pull/47081), [@luxas](https://github.com/luxas)) -* kubeadm deb/rpm packages: cAdvisor doesn't listen on `0.0.0.0:4194` without authentication/authorization because of the possible information leakage. The cAdvisor API can still be accessed via `https://{node-ip}:10250/stats/`, though. ([kubernetes/release#356](https://github.com/kubernetes/release/pull/356), [[@luxas](https://github.com/luxas)](https://github.com/luxas)) +* kubeadm deb/rpm packages: cAdvisor doesn't listen on `0.0.0.0:4194` without authentication/authorization because of the possible information leakage. The cAdvisor API can still be accessed via `https://{node-ip}:10250/stats/`, though. ([kubernetes/release#356](https://github.com/kubernetes/release/pull/356), [@luxas](https://github.com/luxas)) ### Cloud Providers -* Azure: Container permissions for provisioned volumes have changed to private. If you have existing Azure volumes that were created by Kubernetes v1.6.0-v1.6.5, you should change the permissions on them manually. ([[#47605](https://github.com/kubernetes/kubernetes/pull/47605)](https://github.com/kubernetes/kubernetes/pull/47605), [[@brendandburns](https://github.com/brendandburns)](https://github.com/brendandburns)) +* Azure: Container permissions for provisioned volumes have changed to private. If you have existing Azure volumes that were created by Kubernetes v1.6.0-v1.6.5, you should change the permissions on them manually. ([#47605](https://github.com/kubernetes/kubernetes/pull/47605), [@brendandburns](https://github.com/brendandburns)) -* GKE/GCE: New and upgraded 1.7 GCE/GKE clusters no longer have an RBAC ClusterRoleBinding that grants the cluster-admin ClusterRole to the default service account in the kube-system Namespace. ([[#46750](https://github.com/kubernetes/kubernetes/pull/46750)](https://github.com/kubernetes/kubernetes/pull/46750), [[@cjcullen](https://github.com/cjcullen)](https://github.com/cjcullen)). If this permission is still desired, run the following command to explicitly grant it, either before or after upgrading to 1.7: +* GKE/GCE: New and upgraded 1.7 GCE/GKE clusters no longer have an RBAC ClusterRoleBinding that grants the cluster-admin ClusterRole to the default service account in the kube-system Namespace. ([#46750](https://github.com/kubernetes/kubernetes/pull/46750), [@cjcullen](https://github.com/cjcullen)). If this permission is still desired, run the following command to explicitly grant it, either before or after upgrading to 1.7: ``` kubectl create clusterrolebinding kube-system-default --serviceaccount=kube-system:default --clusterrole=cluster-admin ``` @@ -864,34 +864,34 @@ During server startup, prior to the server reporting healthy (via `/healthz`), n Wait for the server to report healthy (via `/healthz`) before depending on the information provided by the discovery APIs. Additionally, since the information returned from the discovery APIs may change dynamically, a cache of the results should not be considered authoritative. ETag support is planned in a future version to facilitate client caching. -([[#47977](https://github.com/kubernetes/kubernetes/pull/47977)](https://github.com/kubernetes/kubernetes/issues/47977), [[#44957](https://github.com/kubernetes/kubernetes/pull/44957)](https://github.com/kubernetes/kubernetes/issues/44957)) +([#47977](https://github.com/kubernetes/kubernetes/pull/47977), [#44957](https://github.com/kubernetes/kubernetes/pull/44957)) -* The DaemonSet controller will evict running Pods that do not tolerate the NoSchedule taint if the taint is added to a Node. There is an open PR ([[#48189](https://github.com/kubernetes/kubernetes/pull/48189)](https://github.com/kubernetes/kubernetes/pull/48189)) to resolve this issue, but as this issue also exists in 1.6, and as we do not wish to risk release stability by merging it directly prior to a release without sufficient testing, we have decided to defer merging the PR until the next point release for each minor version ([[#48190](https://github.com/kubernetes/kubernetes/pull/48190)](https://github.com/kubernetes/kubernetes/issues/48190)). +* The DaemonSet controller will evict running Pods that do not tolerate the NoSchedule taint if the taint is added to a Node. There is an open PR ([#48189](https://github.com/kubernetes/kubernetes/pull/48189)) to resolve this issue, but as this issue also exists in 1.6, and as we do not wish to risk release stability by merging it directly prior to a release without sufficient testing, we have decided to defer merging the PR until the next point release for each minor version ([#48190](https://github.com/kubernetes/kubernetes/pull/48190)). * Protobuf serialization does not distinguish between `[]` and `null`. API fields previously capable of storing and returning either `[]` and `null` via JSON API requests (for example, the Endpoints `subsets` field) can now store only `null` when created using the protobuf content-type or stored in etcd using protobuf serialization (the default in 1.6). -JSON API clients should tolerate `null` values for such fields, and treat `null` and `[]` as equivalent in meaning unless specifically documented otherwise for a particular field. ([[#44593](https://github.com/kubernetes/kubernetes/pull/44593)](https://github.com/kubernetes/kubernetes/issues/44593)) +JSON API clients should tolerate `null` values for such fields, and treat `null` and `[]` as equivalent in meaning unless specifically documented otherwise for a particular field. ([#44593](https://github.com/kubernetes/kubernetes/pull/44593)) ## **Deprecations** ### Cluster provisioning scripts -* cluster/ubuntu: Removed due to [deprecation](https://github.com/kubernetes/kubernetes/tree/master/cluster#cluster-configuration) and lack of maintenance. ([[#44344](https://github.com/kubernetes/kubernetes/pull/44344)](https://github.com/kubernetes/kubernetes/pull/44344), [[@mikedanese](https://github.com/mikedanese)](https://github.com/mikedanese)) +* cluster/ubuntu: Removed due to [deprecation](https://github.com/kubernetes/kubernetes/tree/master/cluster#cluster-configuration) and lack of maintenance. ([#44344](https://github.com/kubernetes/kubernetes/pull/44344), [@mikedanese](https://github.com/mikedanese)) -* cluster/aws: Removed due to [deprecation](https://github.com/kubernetes/kubernetes/pull/38772) and lack of maintenance. ([[#42196](https://github.com/kubernetes/kubernetes/pull/42196)](https://github.com/kubernetes/kubernetes/pull/42196), [[@zmerlynn](https://github.com/zmerlynn)](https://github.com/zmerlynn)) +* cluster/aws: Removed due to [deprecation](https://github.com/kubernetes/kubernetes/pull/38772) and lack of maintenance. ([#42196](https://github.com/kubernetes/kubernetes/pull/42196), [@zmerlynn](https://github.com/zmerlynn)) ### Client libraries * Swagger 1.2 spec (`/swaggerapi/*`) is deprecated. Please use OpenAPI instead. ### DaemonSet -* DaemonSet’s spec.templateGeneration has been deprecated. ([[#45924](https://github.com/kubernetes/kubernetes/pull/45924)](https://github.com/kubernetes/kubernetes/pull/45924), [[@janetkuo](https://github.com/janetkuo)](https://github.com/janetkuo)) +* DaemonSet’s spec.templateGeneration has been deprecated. ([#45924](https://github.com/kubernetes/kubernetes/pull/45924), [@janetkuo](https://github.com/janetkuo)) ### kube-proxy -* In 1.7, the kube-proxy component has been converted to use a configuration file. The old flags still work in 1.7, but they are being deprecated and will be removed in a future release. Cluster administrators are advised to switch to using the configuration file, but no action is strictly necessary in 1.7. ([[#34727](https://github.com/kubernetes/kubernetes/pull/34727)](https://github.com/kubernetes/kubernetes/pull/34727), [[@ncdc](https://github.com/ncdc)](https://github.com/ncdc)) +* In 1.7, the kube-proxy component has been converted to use a configuration file. The old flags still work in 1.7, but they are being deprecated and will be removed in a future release. Cluster administrators are advised to switch to using the configuration file, but no action is strictly necessary in 1.7. ([#34727](https://github.com/kubernetes/kubernetes/pull/34727), [@ncdc](https://github.com/ncdc)) ### Namespace -* The Namespace API object no longer supports the deletecollection operation. ([[#46407](https://github.com/kubernetes/kubernetes/pull/46407)](https://github.com/kubernetes/kubernetes/pull/46407), [[@liggitt](https://github.com/liggitt)](https://github.com/liggitt)) +* The Namespace API object no longer supports the deletecollection operation. ([#46407](https://github.com/kubernetes/kubernetes/pull/46407), [@liggitt](https://github.com/liggitt)) ### Scheduling @@ -903,7 +903,7 @@ Features for this release were tracked via the use of the [kubernetes/features]( ## Kubefed -* Deprecate the `--secret-name` flag from `kubefed join`, instead generating the secret name arbitrarily. ([[#42513](https://github.com/kubernetes/kubernetes/pull/42513)](https://github.com/kubernetes/kubernetes/pull/42513), [[@perotinus](https://github.com/perotinus)](https://github.com/perotinus)) +* Deprecate the `--secret-name` flag from `kubefed join`, instead generating the secret name arbitrarily. ([#42513](https://github.com/kubernetes/kubernetes/pull/42513), [@perotinus](https://github.com/perotinus)) ### **Kubernetes API** @@ -912,7 +912,7 @@ Features for this release were tracked via the use of the [kubernetes/features]( * [beta] User-provided apiservers can be aggregated (served along with) the rest of the Kubernetes API. See [Extending the Kubernetes API with the aggregation layer](https://kubernetes.io/docs/concepts/api-extension/apiserver-aggregation/), [Configure the aggregation layer](https://kubernetes.io/docs/tasks/access-kubernetes-api/configure-aggregation-layer/), and [Setup an extension API server](https://kubernetes.io/docs/tasks/access-kubernetes-api/setup-extension-api-server/). -* [alpha] Adding admissionregistration API group which enables dynamic registration of initializers and external admission webhooks. ([[#46294](https://github.com/kubernetes/kubernetes/pull/46294)](https://github.com/kubernetes/kubernetes/pull/46294), [[@caesarxuchao](https://github.com/caesarxuchao)](https://github.com/caesarxuchao)) +* [alpha] Adding admissionregistration API group which enables dynamic registration of initializers and external admission webhooks. ([#46294](https://github.com/kubernetes/kubernetes/pull/46294), [@caesarxuchao](https://github.com/caesarxuchao)) ### **Application Deployment** @@ -980,113 +980,113 @@ Features for this release were tracked via the use of the [kubernetes/features]( ### **Internationalization** -* Add Traditional Chinese translation for kubectl ([[#46559](https://github.com/kubernetes/kubernetes/pull/46559)](https://github.com/kubernetes/kubernetes/pull/46559), [[@warmchang](https://github.com/warmchang)](https://github.com/warmchang)) +* Add Traditional Chinese translation for kubectl ([#46559](https://github.com/kubernetes/kubernetes/pull/46559), [@warmchang](https://github.com/warmchang)) -* Add Japanese translation for kubectl ([[#46756](https://github.com/kubernetes/kubernetes/pull/46756)](https://github.com/kubernetes/kubernetes/pull/46756), [[@girikuncoro](https://github.com/girikuncoro)](https://github.com/girikuncoro)) +* Add Japanese translation for kubectl ([#46756](https://github.com/kubernetes/kubernetes/pull/46756), [@girikuncoro](https://github.com/girikuncoro)) -* Add Simplified Chinese translation for kubectl ([[#45573](https://github.com/kubernetes/kubernetes/pull/45573)](https://github.com/kubernetes/kubernetes/pull/45573), [[@shiywang](https://github.com/shiywang)](https://github.com/shiywang)) +* Add Simplified Chinese translation for kubectl ([#45573](https://github.com/kubernetes/kubernetes/pull/45573), [@shiywang](https://github.com/shiywang)) ### **kubectl (CLI)** * Features - * `kubectl logs` supports specifying a container name when using label selectors ([[#44282](https://github.com/kubernetes/kubernetes/pull/44282)](https://github.com/kubernetes/kubernetes/pull/44282), [[@derekwaynecarr](https://github.com/derekwaynecarr)](https://github.com/derekwaynecarr)) + * `kubectl logs` supports specifying a container name when using label selectors ([#44282](https://github.com/kubernetes/kubernetes/pull/44282), [@derekwaynecarr](https://github.com/derekwaynecarr)) - * `kubectl rollout` supports undo and history for DaemonSet ([[#46144](https://github.com/kubernetes/kubernetes/pull/46144)](https://github.com/kubernetes/kubernetes/pull/46144), [[@janetkuo](https://github.com/janetkuo)](https://github.com/janetkuo)) + * `kubectl rollout` supports undo and history for DaemonSet ([#46144](https://github.com/kubernetes/kubernetes/pull/46144), [@janetkuo](https://github.com/janetkuo)) - * `kubectl rollout` supports status and history for StatefulSet ([[#46669](https://github.com/kubernetes/kubernetes/pull/46669)](https://github.com/kubernetes/kubernetes/pull/46669), [[@kow3ns](https://github.com/kow3ns)](https://github.com/kow3ns)). + * `kubectl rollout` supports status and history for StatefulSet ([#46669](https://github.com/kubernetes/kubernetes/pull/46669), [@kow3ns](https://github.com/kow3ns)). - * Implement `kubectl get controllerrevisions` ([[#46655](https://github.com/kubernetes/kubernetes/pull/46655)](https://github.com/kubernetes/kubernetes/pull/46655), [[@janetkuo](https://github.com/janetkuo)](https://github.com/janetkuo)) + * Implement `kubectl get controllerrevisions` ([#46655](https://github.com/kubernetes/kubernetes/pull/46655), [@janetkuo](https://github.com/janetkuo)) - * `kubectl create clusterrole` supports `--non-resource-url` ([[#45809](https://github.com/kubernetes/kubernetes/pull/45809)](https://github.com/kubernetes/kubernetes/pull/45809), [[@CaoShuFeng](https://github.com/CaoShuFeng)](https://github.com/CaoShuFeng)) + * `kubectl create clusterrole` supports `--non-resource-url` ([#45809](https://github.com/kubernetes/kubernetes/pull/45809), [@CaoShuFeng](https://github.com/CaoShuFeng)) * `kubectl logs` and `kubectl attach` support specifying a wait timeout with `--pod-running-timeout` - * ([[#41813](https://github.com/kubernetes/kubernetes/pull/41813)](https://github.com/kubernetes/kubernetes/pull/41813), [[@shiywang](https://github.com/shiywang)](https://github.com/shiywang)) + * ([#41813](https://github.com/kubernetes/kubernetes/pull/41813), [@shiywang](https://github.com/shiywang)) * New commands - * Add `kubectl config rename-context` ([[#46114](https://github.com/kubernetes/kubernetes/pull/46114)](https://github.com/kubernetes/kubernetes/pull/46114), [[@arthur0](https://github.com/arthur0)](https://github.com/arthur0)) + * Add `kubectl config rename-context` ([#46114](https://github.com/kubernetes/kubernetes/pull/46114), [@arthur0](https://github.com/arthur0)) - * Add `kubectl apply edit-last-applied` subcommand ([[#42256](https://github.com/kubernetes/kubernetes/pull/42256)](https://github.com/kubernetes/kubernetes/pull/42256), [[@shiywang](https://github.com/shiywang)](https://github.com/shiywang)) + * Add `kubectl apply edit-last-applied` subcommand ([#42256](https://github.com/kubernetes/kubernetes/pull/42256), [@shiywang](https://github.com/shiywang)) * Strategic Merge Patch * Reference docs now display the patch type and patch merge key used by `kubectl apply` to merge and identify unique elements in arrays. - * `kubectl edit` and `kubectl apply` will keep the ordering of elements in merged lists ([[#45980](https://github.com/kubernetes/kubernetes/pull/45980)](https://github.com/kubernetes/kubernetes/pull/45980), [[@mengqiy](https://github.com/mengqiy)](https://github.com/mengqiy)) + * `kubectl edit` and `kubectl apply` will keep the ordering of elements in merged lists ([#45980](https://github.com/kubernetes/kubernetes/pull/45980), [@mengqiy](https://github.com/mengqiy)) - * New patch directive (retainKeys) to specifying clearing fields missing from the request ([[#44597](https://github.com/kubernetes/kubernetes/pull/44597)](https://github.com/kubernetes/kubernetes/pull/44597), [[@mengqiy](https://github.com/mengqiy)](https://github.com/mengqiy)) + * New patch directive (retainKeys) to specifying clearing fields missing from the request ([#44597](https://github.com/kubernetes/kubernetes/pull/44597), [@mengqiy](https://github.com/mengqiy)) - * Open API now includes strategic merge patch tags (previously only in go struct tags) ([[#44121](https://github.com/kubernetes/kubernetes/pull/44121)](https://github.com/kubernetes/kubernetes/pull/44121), [[@mbohlool](https://github.com/mbohlool)](https://github.com/mbohlool)) + * Open API now includes strategic merge patch tags (previously only in go struct tags) ([#44121](https://github.com/kubernetes/kubernetes/pull/44121), [@mbohlool](https://github.com/mbohlool)) * Plugins - * Introduces the ability to extend kubectl by adding third-party plugins. Developer preview, please refer to the documentation for instructions about how to use it. ([[#37499](https://github.com/kubernetes/kubernetes/pull/37499)](https://github.com/kubernetes/kubernetes/pull/37499), [[@fabianofranz](https://github.com/fabianofranz)](https://github.com/fabianofranz)) + * Introduces the ability to extend kubectl by adding third-party plugins. Developer preview, please refer to the documentation for instructions about how to use it. ([#37499](https://github.com/kubernetes/kubernetes/pull/37499), [@fabianofranz](https://github.com/fabianofranz)) - * Added support for a hierarchy of kubectl plugins (a tree of plugins as children of other plugins). ([[#45981](https://github.com/kubernetes/kubernetes/pull/45981)](https://github.com/kubernetes/kubernetes/pull/45981), [[@fabianofranz](https://github.com/fabianofranz)](https://github.com/fabianofranz)) + * Added support for a hierarchy of kubectl plugins (a tree of plugins as children of other plugins). ([#45981](https://github.com/kubernetes/kubernetes/pull/45981), [@fabianofranz](https://github.com/fabianofranz)) * Added exported env vars to kubectl plugins so that plugin developers have access to global flags, namespace, the plugin descriptor and the full path to the caller binary. * Enhancement - * `kubectl auth can-i` now supports non-resource URLs ([[#46432](https://github.com/kubernetes/kubernetes/pull/46432)](https://github.com/kubernetes/kubernetes/pull/46432), [[@CaoShuFeng](https://github.com/CaoShuFeng)](https://github.com/CaoShuFeng)) + * `kubectl auth can-i` now supports non-resource URLs ([#46432](https://github.com/kubernetes/kubernetes/pull/46432), [@CaoShuFeng](https://github.com/CaoShuFeng)) - * `kubectl set selector` and `kubectl set subject` no longer print "running in local/dry-run mode..." at the top. The output can now be piped and interpretted as yaml or json ([[#46507](https://github.com/kubernetes/kubernetes/pull/46507)](https://github.com/kubernetes/kubernetes/pull/46507), [[@bboreham](https://github.com/bboreham)](https://github.com/bboreham)) + * `kubectl set selector` and `kubectl set subject` no longer print "running in local/dry-run mode..." at the top. The output can now be piped and interpretted as yaml or json ([#46507](https://github.com/kubernetes/kubernetes/pull/46507), [@bboreham](https://github.com/bboreham)) - * When using an in-cluster client with an empty configuration, the `--namespace` flag is now honored ([[#46299](https://github.com/kubernetes/kubernetes/pull/46299)](https://github.com/kubernetes/kubernetes/pull/46299), [[@ncdc](https://github.com/ncdc)](https://github.com/ncdc)) + * When using an in-cluster client with an empty configuration, the `--namespace` flag is now honored ([#46299](https://github.com/kubernetes/kubernetes/pull/46299), [@ncdc](https://github.com/ncdc)) - * The help message for missingResourceError is now generic ([[#45582](https://github.com/kubernetes/kubernetes/pull/45582)](https://github.com/kubernetes/kubernetes/pull/45582), [[@CaoShuFeng](https://github.com/CaoShuFeng)](https://github.com/CaoShuFeng)) + * The help message for missingResourceError is now generic ([#45582](https://github.com/kubernetes/kubernetes/pull/45582), [@CaoShuFeng](https://github.com/CaoShuFeng)) - * `kubectl taint node` now supports label selectors ([[#44740](https://github.com/kubernetes/kubernetes/pull/44740)](https://github.com/kubernetes/kubernetes/pull/44740), [[@ravisantoshgudimetla](https://github.com/ravisantoshgudimetla)](https://github.com/ravisantoshgudimetla)) + * `kubectl taint node` now supports label selectors ([#44740](https://github.com/kubernetes/kubernetes/pull/44740), [@ravisantoshgudimetla](https://github.com/ravisantoshgudimetla)) - * `kubectl proxy --www` now logs a warning when the dir is invalid ([[#44952](https://github.com/kubernetes/kubernetes/pull/44952)](https://github.com/kubernetes/kubernetes/pull/44952), [[@CaoShuFeng](https://github.com/CaoShuFeng)](https://github.com/CaoShuFeng)) + * `kubectl proxy --www` now logs a warning when the dir is invalid ([#44952](https://github.com/kubernetes/kubernetes/pull/44952), [@CaoShuFeng](https://github.com/CaoShuFeng)) - * `kubectl taint` output has been enhanced with the operation ([[#43171](https://github.com/kubernetes/kubernetes/pull/43171)](https://github.com/kubernetes/kubernetes/pull/43171), [[@ravisantoshgudimetla](https://github.com/ravisantoshgudimetla)](https://github.com/ravisantoshgudimetla)) + * `kubectl taint` output has been enhanced with the operation ([#43171](https://github.com/kubernetes/kubernetes/pull/43171), [@ravisantoshgudimetla](https://github.com/ravisantoshgudimetla)) - * kubectl `--user` and `--cluster` now support completion ([[#44251](https://github.com/kubernetes/kubernetes/pull/44251)](https://github.com/kubernetes/kubernetes/pull/44251), [[@superbrothers](https://github.com/superbrothers)](https://github.com/superbrothers)) + * kubectl `--user` and `--cluster` now support completion ([#44251](https://github.com/kubernetes/kubernetes/pull/44251), [@superbrothers](https://github.com/superbrothers)) - * `kubectl config use-context` now supports completion ([[#42336](https://github.com/kubernetes/kubernetes/pull/42336)](https://github.com/kubernetes/kubernetes/pull/42336), [[@superbrothers](https://github.com/superbrothers)](https://github.com/superbrothers)) + * `kubectl config use-context` now supports completion ([#42336](https://github.com/kubernetes/kubernetes/pull/42336), [@superbrothers](https://github.com/superbrothers)) - * `kubectl version` now supports `--output` ([[#39858](https://github.com/kubernetes/kubernetes/pull/39858)](https://github.com/kubernetes/kubernetes/pull/39858), [[@alejandroEsc](https://github.com/alejandroEsc)](https://github.com/alejandroEsc)) + * `kubectl version` now supports `--output` ([#39858](https://github.com/kubernetes/kubernetes/pull/39858), [@alejandroEsc](https://github.com/alejandroEsc)) - * `kubectl create configmap` has a new option `--from-env-file` that populates a configmap from file which follows a key=val format for each line. ([[#38882](https://github.com/kubernetes/kubernetes/pull/38882)](https://github.com/kubernetes/kubernetes/pull/38882), [[@fraenkel](https://github.com/fraenkel)](https://github.com/fraenkel)) + * `kubectl create configmap` has a new option `--from-env-file` that populates a configmap from file which follows a key=val format for each line. ([#38882](https://github.com/kubernetes/kubernetes/pull/38882), [@fraenkel](https://github.com/fraenkel)) * `kubectl create secret` has a new option `--from-env-file` that populates a configmap from file which follows a key=val format for each line. * Printing/describe - * Print conditions of RC/RS in `kubectl describe` command. ([[#44710](https://github.com/kubernetes/kubernetes/pull/44710)](https://github.com/kubernetes/kubernetes/pull/44710), [[@xiangpengzhao](https://github.com/xiangpengzhao)](https://github.com/xiangpengzhao)) + * Print conditions of RC/RS in `kubectl describe` command. ([#44710](https://github.com/kubernetes/kubernetes/pull/44710), [@xiangpengzhao](https://github.com/xiangpengzhao)) - * Improved output on `kubectl get` and `kubectl describe` for generic objects. ([[#44222](https://github.com/kubernetes/kubernetes/pull/44222)](https://github.com/kubernetes/kubernetes/pull/44222), [[@fabianofranz](https://github.com/fabianofranz)](https://github.com/fabianofranz)) + * Improved output on `kubectl get` and `kubectl describe` for generic objects. ([#44222](https://github.com/kubernetes/kubernetes/pull/44222), [@fabianofranz](https://github.com/fabianofranz)) - * In `kubectl describe`, find controllers with ControllerRef, instead of showing the original creator. ([[#42849](https://github.com/kubernetes/kubernetes/pull/42849)](https://github.com/kubernetes/kubernetes/pull/42849), [[@janetkuo](https://github.com/janetkuo)](https://github.com/janetkuo)) + * In `kubectl describe`, find controllers with ControllerRef, instead of showing the original creator. ([#42849](https://github.com/kubernetes/kubernetes/pull/42849), [@janetkuo](https://github.com/janetkuo)) - * `kubectl version` has new flag --output (=json or yaml) allowing result of the command to be parsed in either json format or yaml. ([[#39858](https://github.com/kubernetes/kubernetes/pull/39858)](https://github.com/kubernetes/kubernetes/pull/39858), [[@alejandroEsc](https://github.com/alejandroEsc)](https://github.com/alejandroEsc)) + * `kubectl version` has new flag --output (=json or yaml) allowing result of the command to be parsed in either json format or yaml. ([#39858](https://github.com/kubernetes/kubernetes/pull/39858), [@alejandroEsc](https://github.com/alejandroEsc)) * Bug fixes - * Fix some false negatives in detection of meaningful conflicts during strategic merge patch with maps and lists. ([[#43469](https://github.com/kubernetes/kubernetes/pull/43469)](https://github.com/kubernetes/kubernetes/pull/43469), [[@enisoc](https://github.com/enisoc)](https://github.com/enisoc)) + * Fix some false negatives in detection of meaningful conflicts during strategic merge patch with maps and lists. ([#43469](https://github.com/kubernetes/kubernetes/pull/43469), [@enisoc](https://github.com/enisoc)) - * Fix false positive "meaningful conflict" detection for strategic merge patch with integer values. ([[#44788](https://github.com/kubernetes/kubernetes/pull/44788)](https://github.com/kubernetes/kubernetes/pull/44788), [[@enisoc](https://github.com/enisoc)](https://github.com/enisoc)) + * Fix false positive "meaningful conflict" detection for strategic merge patch with integer values. ([#44788](https://github.com/kubernetes/kubernetes/pull/44788), [@enisoc](https://github.com/enisoc)) - * Restored the ability of kubectl running inside a pod to consume resource files specifying a different namespace than the one the pod is running in. ([[#44862](https://github.com/kubernetes/kubernetes/pull/44862)](https://github.com/kubernetes/kubernetes/pull/44862), [[@liggitt](https://github.com/liggitt)](https://github.com/liggitt)) + * Restored the ability of kubectl running inside a pod to consume resource files specifying a different namespace than the one the pod is running in. ([#44862](https://github.com/kubernetes/kubernetes/pull/44862), [@liggitt](https://github.com/liggitt)) - * Kubectl commands run inside a pod using a kubeconfig file now use the namespace specified in the kubeconfig file, instead of using the pod namespace. If no kubeconfig file is used, or the kubeconfig does not specify a namespace, the pod namespace is still used as a fallback. ([[#44570](https://github.com/kubernetes/kubernetes/pull/44570)](https://github.com/kubernetes/kubernetes/pull/44570), [[@liggitt](https://github.com/liggitt)](https://github.com/liggitt)) + * Kubectl commands run inside a pod using a kubeconfig file now use the namespace specified in the kubeconfig file, instead of using the pod namespace. If no kubeconfig file is used, or the kubeconfig does not specify a namespace, the pod namespace is still used as a fallback. ([#44570](https://github.com/kubernetes/kubernetes/pull/44570), [@liggitt](https://github.com/liggitt)) - * Fixed `kubectl cluster-info` dump to support multi-container pod. ([[#44088](https://github.com/kubernetes/kubernetes/pull/44088)](https://github.com/kubernetes/kubernetes/pull/44088), [[@xingzhou](https://github.com/xingzhou)](https://github.com/xingzhou)) + * Fixed `kubectl cluster-info` dump to support multi-container pod. ([#44088](https://github.com/kubernetes/kubernetes/pull/44088), [@xingzhou](https://github.com/xingzhou)) - * Kubectl will print a warning when deleting the current context ([[#42538](https://github.com/kubernetes/kubernetes/pull/42538)](https://github.com/kubernetes/kubernetes/pull/42538), [[@adohe](https://github.com/adohe)](https://github.com/adohe)) + * Kubectl will print a warning when deleting the current context ([#42538](https://github.com/kubernetes/kubernetes/pull/42538), [@adohe](https://github.com/adohe)) - * Fix VolumeClaims/capacity in `kubectl describe statefulsets` output. ([[#47573](https://github.com/kubernetes/kubernetes/pull/47573)](https://github.com/kubernetes/kubernetes/pull/47573), [[@k82cn](https://github.com/k82cn)](https://github.com/k82cn)) + * Fix VolumeClaims/capacity in `kubectl describe statefulsets` output. ([#47573](https://github.com/kubernetes/kubernetes/pull/47573), [@k82cn](https://github.com/k82cn)) - * Fixed the output of kubectl taint node command with minor improvements. ([[#43171](https://github.com/kubernetes/kubernetes/pull/43171)](https://github.com/kubernetes/kubernetes/pull/43171), [[@ravisantoshgudimetla](https://github.com/ravisantoshgudimetla)](https://github.com/ravisantoshgudimetla)) + * Fixed the output of kubectl taint node command with minor improvements. ([#43171](https://github.com/kubernetes/kubernetes/pull/43171), [@ravisantoshgudimetla](https://github.com/ravisantoshgudimetla)) ### **Networking** #### Network Policy * [stable] [NetworkPolicy](https://kubernetes.io/docs/concepts/services-networking/network-policies/) promoted to GA. - * Additionally adds short name "netpol" for networkpolicies ([[#42241](https://github.com/kubernetes/kubernetes/pull/42241)](https://github.com/kubernetes/kubernetes/pull/42241), [[@xiangpengzhao](https://github.com/xiangpengzhao)](https://github.com/xiangpengzhao)) + * Additionally adds short name "netpol" for networkpolicies ([#42241](https://github.com/kubernetes/kubernetes/pull/42241), [@xiangpengzhao](https://github.com/xiangpengzhao)) #### Load Balancing @@ -1132,161 +1132,161 @@ Features for this release were tracked via the use of the [kubernetes/features]( ### **Other notable changes** #### Admission plugin -* OwnerReferencesPermissionEnforcement admission plugin ignores pods/status. ([[#45747](https://github.com/kubernetes/kubernetes/pull/45747)](https://github.com/kubernetes/kubernetes/pull/45747), [[@derekwaynecarr](https://github.com/derekwaynecarr)](https://github.com/derekwaynecarr)) +* OwnerReferencesPermissionEnforcement admission plugin ignores pods/status. ([#45747](https://github.com/kubernetes/kubernetes/pull/45747), [@derekwaynecarr](https://github.com/derekwaynecarr)) -* Ignored mirror pods in PodPreset admission plugin. ([[#45958](https://github.com/kubernetes/kubernetes/pull/45958)](https://github.com/kubernetes/kubernetes/pull/45958), [[@k82cn](https://github.com/k82cn)](https://github.com/k82cn)) +* Ignored mirror pods in PodPreset admission plugin. ([#45958](https://github.com/kubernetes/kubernetes/pull/45958), [@k82cn](https://github.com/k82cn)) #### API Machinery -* The protobuf serialization of API objects has been updated to store maps in a predictable order to ensure that the representation of that object does not change when saved into etcd. This prevents the same object from being seen as being modified, even when no values have changed. ([[#47701](https://github.com/kubernetes/kubernetes/pull/47701)](https://github.com/kubernetes/kubernetes/pull/47701), [[@smarterclayton](https://github.com/smarterclayton)](https://github.com/smarterclayton)) +* The protobuf serialization of API objects has been updated to store maps in a predictable order to ensure that the representation of that object does not change when saved into etcd. This prevents the same object from being seen as being modified, even when no values have changed. ([#47701](https://github.com/kubernetes/kubernetes/pull/47701), [@smarterclayton](https://github.com/smarterclayton)) -* API resource discovery now includes the singularName used to refer to the resource. ([[#43312](https://github.com/kubernetes/kubernetes/pull/43312)](https://github.com/kubernetes/kubernetes/pull/43312), [[@deads2k](https://github.com/deads2k)](https://github.com/deads2k)) +* API resource discovery now includes the singularName used to refer to the resource. ([#43312](https://github.com/kubernetes/kubernetes/pull/43312), [@deads2k](https://github.com/deads2k)) -* Enhance the garbage collection admission plugin so that a user who doesn't have delete permission of the owning object cannot modify the blockOwnerDeletion field of existing ownerReferences, or add new ownerReferences with blockOwnerDeletion=true ([[#43876](https://github.com/kubernetes/kubernetes/pull/43876)](https://github.com/kubernetes/kubernetes/pull/43876), [[@caesarxuchao](https://github.com/caesarxuchao)](https://github.com/caesarxuchao)) +* Enhance the garbage collection admission plugin so that a user who doesn't have delete permission of the owning object cannot modify the blockOwnerDeletion field of existing ownerReferences, or add new ownerReferences with blockOwnerDeletion=true ([#43876](https://github.com/kubernetes/kubernetes/pull/43876), [@caesarxuchao](https://github.com/caesarxuchao)) -* Exec and portforward actions over SPDY now properly handle redirects sent by the Kubelet ([[#44451](https://github.com/kubernetes/kubernetes/pull/44451)](https://github.com/kubernetes/kubernetes/pull/44451), [[@ncdc](https://github.com/ncdc)](https://github.com/ncdc)) +* Exec and portforward actions over SPDY now properly handle redirects sent by the Kubelet ([#44451](https://github.com/kubernetes/kubernetes/pull/44451), [@ncdc](https://github.com/ncdc)) -* The proxy subresource APIs for nodes, services, and pods now support the HTTP PATCH method. ([[#44929](https://github.com/kubernetes/kubernetes/pull/44929)](https://github.com/kubernetes/kubernetes/pull/44929), [[@liggitt](https://github.com/liggitt)](https://github.com/liggitt)) +* The proxy subresource APIs for nodes, services, and pods now support the HTTP PATCH method. ([#44929](https://github.com/kubernetes/kubernetes/pull/44929), [@liggitt](https://github.com/liggitt)) -* The Categories []string field on discovered API resources represents the list of group aliases (e.g. "all") that each resource belongs to. ([[#43338](https://github.com/kubernetes/kubernetes/pull/43338)](https://github.com/kubernetes/kubernetes/pull/43338), [[@fabianofranz](https://github.com/fabianofranz)](https://github.com/fabianofranz)) +* The Categories []string field on discovered API resources represents the list of group aliases (e.g. "all") that each resource belongs to. ([#43338](https://github.com/kubernetes/kubernetes/pull/43338), [@fabianofranz](https://github.com/fabianofranz)) -* [alpha] The Kubernetes API supports retrieving tabular output for API resources via a new mime-type application/json;as=Table;v=v1alpha1;g=meta.k8s.io. The returned object (if the server supports it) will be of type meta.k8s.io/v1alpha1 with Table, and contain column and row information related to the resource. Each row will contain information about the resource - by default it will be the object metadata, but callers can add the ?includeObject=Object query parameter and receive the full object. In the future kubectl will use this to retrieve the results of `kubectl get`. ([[#40848](https://github.com/kubernetes/kubernetes/pull/40848)](https://github.com/kubernetes/kubernetes/pull/40848), [[@smarterclayton](https://github.com/smarterclayton)](https://github.com/smarterclayton)) +* [alpha] The Kubernetes API supports retrieving tabular output for API resources via a new mime-type application/json;as=Table;v=v1alpha1;g=meta.k8s.io. The returned object (if the server supports it) will be of type meta.k8s.io/v1alpha1 with Table, and contain column and row information related to the resource. Each row will contain information about the resource - by default it will be the object metadata, but callers can add the ?includeObject=Object query parameter and receive the full object. In the future kubectl will use this to retrieve the results of `kubectl get`. ([#40848](https://github.com/kubernetes/kubernetes/pull/40848), [@smarterclayton](https://github.com/smarterclayton)) -* The behavior of some watch calls to the server when filtering on fields was incorrect. If watching objects with a filter, when an update was made that no longer matched the filter a DELETE event was correctly sent. However, the object that was returned by that delete was not the (correct) version before the update, but instead, the newer version. That meant the new object was not matched by the filter. This was a regression from behavior between cached watches on the server side and uncached watches, and thus broke downstream API clients. ([[#46223](https://github.com/kubernetes/kubernetes/pull/46223)](https://github.com/kubernetes/kubernetes/pull/46223), [[@smarterclayton](https://github.com/smarterclayton)](https://github.com/smarterclayton)) +* The behavior of some watch calls to the server when filtering on fields was incorrect. If watching objects with a filter, when an update was made that no longer matched the filter a DELETE event was correctly sent. However, the object that was returned by that delete was not the (correct) version before the update, but instead, the newer version. That meant the new object was not matched by the filter. This was a regression from behavior between cached watches on the server side and uncached watches, and thus broke downstream API clients. ([#46223](https://github.com/kubernetes/kubernetes/pull/46223), [@smarterclayton](https://github.com/smarterclayton)) -* OpenAPI spec is now available in protobuf binary and gzip format (with ETag support) ([[#45836](https://github.com/kubernetes/kubernetes/pull/45836)](https://github.com/kubernetes/kubernetes/pull/45836), [[@mbohlool](https://github.com/mbohlool)](https://github.com/mbohlool)) +* OpenAPI spec is now available in protobuf binary and gzip format (with ETag support) ([#45836](https://github.com/kubernetes/kubernetes/pull/45836), [@mbohlool](https://github.com/mbohlool)) -* Updating apiserver to return UID of the deleted resource. Clients can use this UID to verify that the resource was deleted or waiting for finalizers. ([[#45600](https://github.com/kubernetes/kubernetes/pull/45600)](https://github.com/kubernetes/kubernetes/pull/45600), [[@nikhiljindal](https://github.com/nikhiljindal)](https://github.com/nikhiljindal)) +* Updating apiserver to return UID of the deleted resource. Clients can use this UID to verify that the resource was deleted or waiting for finalizers. ([#45600](https://github.com/kubernetes/kubernetes/pull/45600), [@nikhiljindal](https://github.com/nikhiljindal)) -* Fix incorrect conflict errors applying strategic merge patches to resources. ([[#43871](https://github.com/kubernetes/kubernetes/pull/43871)](https://github.com/kubernetes/kubernetes/pull/43871), [[@liggitt](https://github.com/liggitt)](https://github.com/liggitt)) +* Fix incorrect conflict errors applying strategic merge patches to resources. ([#43871](https://github.com/kubernetes/kubernetes/pull/43871), [@liggitt](https://github.com/liggitt)) -* Fix init container status reporting when active deadline is exceeded. ([[#46305](https://github.com/kubernetes/kubernetes/pull/46305)](https://github.com/kubernetes/kubernetes/pull/46305), [[@sjenning](https://github.com/sjenning)](https://github.com/sjenning)) +* Fix init container status reporting when active deadline is exceeded. ([#46305](https://github.com/kubernetes/kubernetes/pull/46305), [@sjenning](https://github.com/sjenning)) -* Moved qos to api.helpers. ([[#44906](https://github.com/kubernetes/kubernetes/pull/44906)](https://github.com/kubernetes/kubernetes/pull/44906), [[@k82cn](https://github.com/k82cn)](https://github.com/k82cn)) +* Moved qos to api.helpers. ([#44906](https://github.com/kubernetes/kubernetes/pull/44906), [@k82cn](https://github.com/k82cn)) -* Fix issue with the resource quota controller causing add quota to be resynced at the wrong ([[#45685](https://github.com/kubernetes/kubernetes/pull/45685)](https://github.com/kubernetes/kubernetes/pull/45685), [[@derekwaynecarr](https://github.com/derekwaynecarr)](https://github.com/derekwaynecarr)) +* Fix issue with the resource quota controller causing add quota to be resynced at the wrong ([#45685](https://github.com/kubernetes/kubernetes/pull/45685), [@derekwaynecarr](https://github.com/derekwaynecarr)) -* Added Group/Version/Kind and Action extension to OpenAPI Operations ([[#44787](https://github.com/kubernetes/kubernetes/pull/44787)](https://github.com/kubernetes/kubernetes/pull/44787), [[@mbohlool](https://github.com/mbohlool)](https://github.com/mbohlool)) +* Added Group/Version/Kind and Action extension to OpenAPI Operations ([#44787](https://github.com/kubernetes/kubernetes/pull/44787), [@mbohlool](https://github.com/mbohlool)) -* Make clear that meta.KindToResource is only a guess ([[#45272](https://github.com/kubernetes/kubernetes/pull/45272)](https://github.com/kubernetes/kubernetes/pull/45272), [[@sttts](https://github.com/sttts)](https://github.com/sttts)) +* Make clear that meta.KindToResource is only a guess ([#45272](https://github.com/kubernetes/kubernetes/pull/45272), [@sttts](https://github.com/sttts)) -* Add APIService conditions ([[#43301](https://github.com/kubernetes/kubernetes/pull/43301)](https://github.com/kubernetes/kubernetes/pull/43301), [[@deads2k](https://github.com/deads2k)](https://github.com/deads2k)) +* Add APIService conditions ([#43301](https://github.com/kubernetes/kubernetes/pull/43301), [@deads2k](https://github.com/deads2k)) -* Create and push a docker image for the cloud-controller-manager ([[#45154](https://github.com/kubernetes/kubernetes/pull/45154)](https://github.com/kubernetes/kubernetes/pull/45154), [[@luxas](https://github.com/luxas)](https://github.com/luxas)) +* Create and push a docker image for the cloud-controller-manager ([#45154](https://github.com/kubernetes/kubernetes/pull/45154), [@luxas](https://github.com/luxas)) -* Deprecated Binding objects in 1.7. ([[#47041](https://github.com/kubernetes/kubernetes/pull/47041)](https://github.com/kubernetes/kubernetes/pull/47041), [[@k82cn](https://github.com/k82cn)](https://github.com/k82cn)) +* Deprecated Binding objects in 1.7. ([#47041](https://github.com/kubernetes/kubernetes/pull/47041), [@k82cn](https://github.com/k82cn)) -* Adds the Categories []string field to API resources, which represents the list of group aliases (e.g. "all") that every resource belongs to. ([[#43338](https://github.com/kubernetes/kubernetes/pull/43338)](https://github.com/kubernetes/kubernetes/pull/43338), [[@fabianofranz](https://github.com/fabianofranz)](https://github.com/fabianofranz)) +* Adds the Categories []string field to API resources, which represents the list of group aliases (e.g. "all") that every resource belongs to. ([#43338](https://github.com/kubernetes/kubernetes/pull/43338), [@fabianofranz](https://github.com/fabianofranz)) -* `--service-account-lookup` now defaults to true, requiring the Secret API object containing the token to exist in order for a service account token to be valid. This enables service account tokens to be revoked by deleting the Secret object containing the token. ([[#44071](https://github.com/kubernetes/kubernetes/pull/44071)](https://github.com/kubernetes/kubernetes/pull/44071), [[@liggitt](https://github.com/liggitt)](https://github.com/liggitt)) +* `--service-account-lookup` now defaults to true, requiring the Secret API object containing the token to exist in order for a service account token to be valid. This enables service account tokens to be revoked by deleting the Secret object containing the token. ([#44071](https://github.com/kubernetes/kubernetes/pull/44071), [@liggitt](https://github.com/liggitt)) -* API Registration is now in beta. ([[#45247](https://github.com/kubernetes/kubernetes/pull/45247)](https://github.com/kubernetes/kubernetes/pull/45247), [[@mbohlool](https://github.com/mbohlool)](https://github.com/mbohlool)) +* API Registration is now in beta. ([#45247](https://github.com/kubernetes/kubernetes/pull/45247), [@mbohlool](https://github.com/mbohlool)) -* The Kubernetes API server now exits if it encounters a networking failure (e.g. the networking interface hosting its address goes away) to allow a process manager (systemd/kubelet/etc) to react to the problem. Previously the server would log the failure and try again to bind to its configured address:port. ([[#42272](https://github.com/kubernetes/kubernetes/pull/42272)](https://github.com/kubernetes/kubernetes/pull/42272), [[@marun](https://github.com/marun)](https://github.com/marun)) +* The Kubernetes API server now exits if it encounters a networking failure (e.g. the networking interface hosting its address goes away) to allow a process manager (systemd/kubelet/etc) to react to the problem. Previously the server would log the failure and try again to bind to its configured address:port. ([#42272](https://github.com/kubernetes/kubernetes/pull/42272), [@marun](https://github.com/marun)) -* The Prometheus metrics for the kube-apiserver for tracking incoming API requests and latencies now return the subresource label for correctly attributing the type of API call. ([[#46354](https://github.com/kubernetes/kubernetes/pull/46354)](https://github.com/kubernetes/kubernetes/pull/46354), [[@smarterclayton](https://github.com/smarterclayton)](https://github.com/smarterclayton)) +* The Prometheus metrics for the kube-apiserver for tracking incoming API requests and latencies now return the subresource label for correctly attributing the type of API call. ([#46354](https://github.com/kubernetes/kubernetes/pull/46354), [@smarterclayton](https://github.com/smarterclayton)) -* kube-apiserver now drops unneeded path information if an older version of Windows kubectl sends it. ([[#44421](https://github.com/kubernetes/kubernetes/pull/44421)](https://github.com/kubernetes/kubernetes/pull/44421), [[@mml](https://github.com/mml)](https://github.com/mml)) +* kube-apiserver now drops unneeded path information if an older version of Windows kubectl sends it. ([#44421](https://github.com/kubernetes/kubernetes/pull/44421), [@mml](https://github.com/mml)) #### Application autoscaling -* Make "upscale forbidden window" and "downscale forbidden window" duration configurable in arguments of kube-controller-manager. ([[#42101](https://github.com/kubernetes/kubernetes/pull/42101)](https://github.com/kubernetes/kubernetes/pull/42101), [[@Dmitry1987](https://github.com/Dmitry1987)](https://github.com/Dmitry1987)) +* Make "upscale forbidden window" and "downscale forbidden window" duration configurable in arguments of kube-controller-manager. ([#42101](https://github.com/kubernetes/kubernetes/pull/42101), [@Dmitry1987](https://github.com/Dmitry1987)) #### Application Deployment -* StatefulSetStatus now tracks replicas, readyReplicas, currentReplicas, and updatedReplicas. The semantics of replicas is now consistent with DaemonSet and ReplicaSet, and readyReplicas has the semantics that replicas did prior to 1.7 ([[#46669](https://github.com/kubernetes/kubernetes/pull/46669)](https://github.com/kubernetes/kubernetes/pull/46669), [[@kow3ns](https://github.com/kow3ns)](https://github.com/kow3ns)). +* StatefulSetStatus now tracks replicas, readyReplicas, currentReplicas, and updatedReplicas. The semantics of replicas is now consistent with DaemonSet and ReplicaSet, and readyReplicas has the semantics that replicas did prior to 1.7 ([#46669](https://github.com/kubernetes/kubernetes/pull/46669), [@kow3ns](https://github.com/kow3ns)). -* ControllerRevision type has been added for StatefulSet and DaemonSet history. Clients should not depend on the stability of this type as it may change, as necessary, in future releases to support StatefulSet and DaemonSet update and rollback. We enable this type as we do with beta features, because StatefulSet update and DaemonSet update are enabled. ([[#45867](https://github.com/kubernetes/kubernetes/pull/45867)](https://github.com/kubernetes/kubernetes/pull/45867), [[@kow3ns](https://github.com/kow3ns)](https://github.com/kow3ns)) +* ControllerRevision type has been added for StatefulSet and DaemonSet history. Clients should not depend on the stability of this type as it may change, as necessary, in future releases to support StatefulSet and DaemonSet update and rollback. We enable this type as we do with beta features, because StatefulSet update and DaemonSet update are enabled. ([#45867](https://github.com/kubernetes/kubernetes/pull/45867), [@kow3ns](https://github.com/kow3ns)) -* PodDisruptionBudget now uses ControllerRef to decide which controller owns a given Pod, so it doesn't get confused by controllers with overlapping selectors. ([[#45003](https://github.com/kubernetes/kubernetes/pull/45003)](https://github.com/kubernetes/kubernetes/pull/45003), [[@krmayankk](https://github.com/krmayankk)](https://github.com/krmayankk)) +* PodDisruptionBudget now uses ControllerRef to decide which controller owns a given Pod, so it doesn't get confused by controllers with overlapping selectors. ([#45003](https://github.com/kubernetes/kubernetes/pull/45003), [@krmayankk](https://github.com/krmayankk)) -* Deployments are updated to use (1) a more stable hashing algorithm (fnv) than the previous one (adler) and (2) a hashing collision avoidance mechanism that will ensure new rollouts will not block on hashing collisions anymore. ([[#44774](https://github.com/kubernetes/kubernetes/pull/44774)](https://github.com/kubernetes/kubernetes/pull/44774), [[@kargakis](https://github.com/kargakis)](https://github.com/kargakis))([kubernetes/features#287](https://github.com/kubernetes/features/issues/287)) +* Deployments are updated to use (1) a more stable hashing algorithm (fnv) than the previous one (adler) and (2) a hashing collision avoidance mechanism that will ensure new rollouts will not block on hashing collisions anymore. ([#44774](https://github.com/kubernetes/kubernetes/pull/44774), [@kargakis](https://github.com/kargakis))([kubernetes/features#287](https://github.com/kubernetes/features/issues/287)) -* Deployments and DaemonSets rollouts are considered complete when all of the desired replicas are updated and available. This change affects `kubectl rollout status` and Deployment condition. ([[#44672](https://github.com/kubernetes/kubernetes/pull/44672)](https://github.com/kubernetes/kubernetes/pull/44672), [[@kargakis](https://github.com/kargakis)](https://github.com/kargakis)) +* Deployments and DaemonSets rollouts are considered complete when all of the desired replicas are updated and available. This change affects `kubectl rollout status` and Deployment condition. ([#44672](https://github.com/kubernetes/kubernetes/pull/44672), [@kargakis](https://github.com/kargakis)) -* Job controller now respects ControllerRef to avoid fighting over Pods. ([[#42176](https://github.com/kubernetes/kubernetes/pull/42176)](https://github.com/kubernetes/kubernetes/pull/42176), [[@enisoc](https://github.com/enisoc)](https://github.com/enisoc)) +* Job controller now respects ControllerRef to avoid fighting over Pods. ([#42176](https://github.com/kubernetes/kubernetes/pull/42176), [@enisoc](https://github.com/enisoc)) -* CronJob controller now respects ControllerRef to avoid fighting with other controllers. ([[#42177](https://github.com/kubernetes/kubernetes/pull/42177)](https://github.com/kubernetes/kubernetes/pull/42177), [[@enisoc](https://github.com/enisoc)](https://github.com/enisoc)) +* CronJob controller now respects ControllerRef to avoid fighting with other controllers. ([#42177](https://github.com/kubernetes/kubernetes/pull/42177), [@enisoc](https://github.com/enisoc)) #### Cluster Autoscaling * Cluster Autoscaler 0.6. More information available [here](https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/README.md). -* cluster-autoscaler: Fix duplicate writing of logs. ([[#45017](https://github.com/kubernetes/kubernetes/pull/45017)](https://github.com/kubernetes/kubernetes/pull/45017), [[@MaciekPytel](https://github.com/MaciekPytel)](https://github.com/MaciekPytel)) +* cluster-autoscaler: Fix duplicate writing of logs. ([#45017](https://github.com/kubernetes/kubernetes/pull/45017), [@MaciekPytel](https://github.com/MaciekPytel)) #### Cloud Provider Enhancement * AWS: - * New 'service.beta.kubernetes.io/aws-load-balancer-extra-security-groups' Service annotation to specify extra Security Groups to be added to ELB created by AWS cloudprovider ([[#45268](https://github.com/kubernetes/kubernetes/pull/45268)](https://github.com/kubernetes/kubernetes/pull/45268), [[@redbaron](https://github.com/redbaron)](https://github.com/redbaron)) + * New 'service.beta.kubernetes.io/aws-load-balancer-extra-security-groups' Service annotation to specify extra Security Groups to be added to ELB created by AWS cloudprovider ([#45268](https://github.com/kubernetes/kubernetes/pull/45268), [@redbaron](https://github.com/redbaron)) - * Clean up blackhole routes when using kubenet ([[#47572](https://github.com/kubernetes/kubernetes/pull/47572)](https://github.com/kubernetes/kubernetes/pull/47572), [[@justinsb](https://github.com/justinsb)](https://github.com/justinsb)) + * Clean up blackhole routes when using kubenet ([#47572](https://github.com/kubernetes/kubernetes/pull/47572), [@justinsb](https://github.com/justinsb)) - * Maintain a cache of all instances, to fix problem with > 200 nodes with ELBs ([[#47410](https://github.com/kubernetes/kubernetes/pull/47410)](https://github.com/kubernetes/kubernetes/pull/47410), [[@justinsb](https://github.com/justinsb)](https://github.com/justinsb)) + * Maintain a cache of all instances, to fix problem with > 200 nodes with ELBs ([#47410](https://github.com/kubernetes/kubernetes/pull/47410), [@justinsb](https://github.com/justinsb)) - * Avoid spurious ELB listener recreation - ignore case when matching protocol ([[#47391](https://github.com/kubernetes/kubernetes/pull/47391)](https://github.com/kubernetes/kubernetes/pull/47391), [[@justinsb](https://github.com/justinsb)](https://github.com/justinsb)) + * Avoid spurious ELB listener recreation - ignore case when matching protocol ([#47391](https://github.com/kubernetes/kubernetes/pull/47391), [@justinsb](https://github.com/justinsb)) - * Allow configuration of a single security group for ELBs ([[#45500](https://github.com/kubernetes/kubernetes/pull/45500)](https://github.com/kubernetes/kubernetes/pull/45500), [[@nbutton23](https://github.com/nbutton23)](https://github.com/nbutton23)) + * Allow configuration of a single security group for ELBs ([#45500](https://github.com/kubernetes/kubernetes/pull/45500), [@nbutton23](https://github.com/nbutton23)) - * Remove check that forces loadBalancerSourceRanges to be 0.0.0.0/0. ([[#38636](https://github.com/kubernetes/kubernetes/pull/38636)](https://github.com/kubernetes/kubernetes/pull/38636), [[@dhawal55](https://github.com/dhawal55)](https://github.com/dhawal55)) + * Remove check that forces loadBalancerSourceRanges to be 0.0.0.0/0. ([#38636](https://github.com/kubernetes/kubernetes/pull/38636), [@dhawal55](https://github.com/dhawal55)) - * Allow setting KubernetesClusterID or KubernetesClusterTag in combination with VPC. ([[#42512](https://github.com/kubernetes/kubernetes/pull/42512)](https://github.com/kubernetes/kubernetes/pull/42512), [[@scheeles](https://github.com/scheeles)](https://github.com/scheeles)) + * Allow setting KubernetesClusterID or KubernetesClusterTag in combination with VPC. ([#42512](https://github.com/kubernetes/kubernetes/pull/42512), [@scheeles](https://github.com/scheeles)) - * Start recording cloud provider metrics for AWS ([[#43477](https://github.com/kubernetes/kubernetes/pull/43477)](https://github.com/kubernetes/kubernetes/pull/43477), [[@gnufied](https://github.com/gnufied)](https://github.com/gnufied)) + * Start recording cloud provider metrics for AWS ([#43477](https://github.com/kubernetes/kubernetes/pull/43477), [@gnufied](https://github.com/gnufied)) - * AWS: Batch DescribeInstance calls with nodeNames to 150 limit, to stay within AWS filter limits. ([[#47516](https://github.com/kubernetes/kubernetes/pull/47516)](https://github.com/kubernetes/kubernetes/pull/47516), [[@gnufied](https://github.com/gnufied)](https://github.com/gnufied)) + * AWS: Batch DescribeInstance calls with nodeNames to 150 limit, to stay within AWS filter limits. ([#47516](https://github.com/kubernetes/kubernetes/pull/47516), [@gnufied](https://github.com/gnufied)) - * AWS: Process disk attachments even with duplicate NodeNames ([[#47406](https://github.com/kubernetes/kubernetes/pull/47406)](https://github.com/kubernetes/kubernetes/pull/47406), [[@justinsb](https://github.com/justinsb)](https://github.com/justinsb)) + * AWS: Process disk attachments even with duplicate NodeNames ([#47406](https://github.com/kubernetes/kubernetes/pull/47406), [@justinsb](https://github.com/justinsb)) - * Allow configuration of a single security group for ELBs ([[#45500](https://github.com/kubernetes/kubernetes/pull/45500)](https://github.com/kubernetes/kubernetes/pull/45500), [[@nbutton23](https://github.com/nbutton23)](https://github.com/nbutton23)) + * Allow configuration of a single security group for ELBs ([#45500](https://github.com/kubernetes/kubernetes/pull/45500), [@nbutton23](https://github.com/nbutton23)) - * Fix support running the master with a different AWS account or even on a different cloud provider than the nodes. ([[#44235](https://github.com/kubernetes/kubernetes/pull/44235)](https://github.com/kubernetes/kubernetes/pull/44235), [[@mrIncompetent](https://github.com/mrIncompetent)](https://github.com/mrIncompetent)) + * Fix support running the master with a different AWS account or even on a different cloud provider than the nodes. ([#44235](https://github.com/kubernetes/kubernetes/pull/44235), [@mrIncompetent](https://github.com/mrIncompetent)) - * Support node port health check ([[#43585](https://github.com/kubernetes/kubernetes/pull/43585)](https://github.com/kubernetes/kubernetes/pull/43585), [[@foolusion](https://github.com/foolusion)](https://github.com/foolusion)) + * Support node port health check ([#43585](https://github.com/kubernetes/kubernetes/pull/43585), [@foolusion](https://github.com/foolusion)) - * Support for ELB tagging by users ([[#45932](https://github.com/kubernetes/kubernetes/pull/45932)](https://github.com/kubernetes/kubernetes/pull/45932), [[@lpabon](https://github.com/lpabon)](https://github.com/lpabon)) + * Support for ELB tagging by users ([#45932](https://github.com/kubernetes/kubernetes/pull/45932), [@lpabon](https://github.com/lpabon)) * Azure: - * Add support for UDP ports ([[#45523](https://github.com/kubernetes/kubernetes/pull/45523)](https://github.com/kubernetes/kubernetes/pull/45523), [[@colemickens](https://github.com/colemickens)](https://github.com/colemickens)) + * Add support for UDP ports ([#45523](https://github.com/kubernetes/kubernetes/pull/45523), [@colemickens](https://github.com/colemickens)) - * Fix support for multiple loadBalancerSourceRanges ([[#45523](https://github.com/kubernetes/kubernetes/pull/45523)](https://github.com/kubernetes/kubernetes/pull/45523), [[@colemickens](https://github.com/colemickens)](https://github.com/colemickens)) + * Fix support for multiple loadBalancerSourceRanges ([#45523](https://github.com/kubernetes/kubernetes/pull/45523), [@colemickens](https://github.com/colemickens)) - * Support the Service spec's sessionAffinity ([[#45523](https://github.com/kubernetes/kubernetes/pull/45523)](https://github.com/kubernetes/kubernetes/pull/45523), [[@colemickens](https://github.com/colemickens)](https://github.com/colemickens)) + * Support the Service spec's sessionAffinity ([#45523](https://github.com/kubernetes/kubernetes/pull/45523), [@colemickens](https://github.com/colemickens)) - * Added exponential backoff to Azure cloudprovider ([[#46660](https://github.com/kubernetes/kubernetes/pull/46660)](https://github.com/kubernetes/kubernetes/pull/46660), [[@jackfrancis](https://github.com/jackfrancis)](https://github.com/jackfrancis)) + * Added exponential backoff to Azure cloudprovider ([#46660](https://github.com/kubernetes/kubernetes/pull/46660), [@jackfrancis](https://github.com/jackfrancis)) - * Add support for bring-your-own ip address for Services on Azure ([[#42034](https://github.com/kubernetes/kubernetes/pull/42034)](https://github.com/kubernetes/kubernetes/pull/42034), [[@brendandburns](https://github.com/brendandburns)](https://github.com/brendandburns)) + * Add support for bring-your-own ip address for Services on Azure ([#42034](https://github.com/kubernetes/kubernetes/pull/42034), [@brendandburns](https://github.com/brendandburns)) - * Add support for Azure internal load balancer ([[#43510](https://github.com/kubernetes/kubernetes/pull/43510)](https://github.com/kubernetes/kubernetes/pull/43510), [[@karataliu](https://github.com/karataliu)](https://github.com/karataliu)) + * Add support for Azure internal load balancer ([#43510](https://github.com/kubernetes/kubernetes/pull/43510), [@karataliu](https://github.com/karataliu)) - * Client poll duration is now 5 seconds ([[#43699](https://github.com/kubernetes/kubernetes/pull/43699)](https://github.com/kubernetes/kubernetes/pull/43699), [[@colemickens](https://github.com/colemickens)](https://github.com/colemickens)) + * Client poll duration is now 5 seconds ([#43699](https://github.com/kubernetes/kubernetes/pull/43699), [@colemickens](https://github.com/colemickens)) - * Azure plugin for client auth ([[#43987](https://github.com/kubernetes/kubernetes/pull/43987)](https://github.com/kubernetes/kubernetes/pull/43987), [[@cosmincojocar](https://github.com/cosmincojocar)](https://github.com/cosmincojocar)) + * Azure plugin for client auth ([#43987](https://github.com/kubernetes/kubernetes/pull/43987), [@cosmincojocar](https://github.com/cosmincojocar)) * GCP: - * Bump GLBC version to 0.9.5 - fixes [loss of manually modified GCLB health check settings](https://github.com/kubernetes/kubernetes/issues/47559) upon upgrade from pre-1.6.4 to either 1.6.4 or 1.6.5. ([[#47567](https://github.com/kubernetes/kubernetes/pull/47567)](https://github.com/kubernetes/kubernetes/pull/47567), [[@nicksardo](https://github.com/nicksardo)](https://github.com/nicksardo)) + * Bump GLBC version to 0.9.5 - fixes [loss of manually modified GCLB health check settings](https://github.com/kubernetes/kubernetes/issues/47559) upon upgrade from pre-1.6.4 to either 1.6.4 or 1.6.5. ([#47567](https://github.com/kubernetes/kubernetes/pull/47567), [@nicksardo](https://github.com/nicksardo)) - * [beta] Support creation of GCP Internal Load Balancers from Service objects ([[#46663](https://github.com/kubernetes/kubernetes/pull/46663)](https://github.com/kubernetes/kubernetes/pull/46663), [[@nicksardo](https://github.com/nicksardo)](https://github.com/nicksardo)) + * [beta] Support creation of GCP Internal Load Balancers from Service objects ([#46663](https://github.com/kubernetes/kubernetes/pull/46663), [@nicksardo](https://github.com/nicksardo)) - * GCE installs will now avoid IP masquerade for all RFC-1918 IP blocks, rather than just 10.0.0.0/8. This means that clusters can be created in 192.168.0.0./16 and 172.16.0.0/12 while preserving the container IPs (which would be lost before). ([[#46473](https://github.com/kubernetes/kubernetes/pull/46473)](https://github.com/kubernetes/kubernetes/pull/46473), [[@thockin](https://github.com/thockin)](https://github.com/thockin)) + * GCE installs will now avoid IP masquerade for all RFC-1918 IP blocks, rather than just 10.0.0.0/8. This means that clusters can be created in 192.168.0.0./16 and 172.16.0.0/12 while preserving the container IPs (which would be lost before). ([#46473](https://github.com/kubernetes/kubernetes/pull/46473), [@thockin](https://github.com/thockin)) - * The Calico version included in kube-up for GCE has been updated to v2.2. ([[#38169](https://github.com/kubernetes/kubernetes/pull/38169)](https://github.com/kubernetes/kubernetes/pull/38169), [[@caseydavenport](https://github.com/caseydavenport)](https://github.com/caseydavenport)) + * The Calico version included in kube-up for GCE has been updated to v2.2. ([#38169](https://github.com/kubernetes/kubernetes/pull/38169), [@caseydavenport](https://github.com/caseydavenport)) - * ip-masq-agent is now on by default for GCE ([[#47794](https://github.com/kubernetes/kubernetes/pull/47794)](https://github.com/kubernetes/kubernetes/pull/47794), [[@dnardo](https://github.com/dnardo)](https://github.com/dnardo)) + * ip-masq-agent is now on by default for GCE ([#47794](https://github.com/kubernetes/kubernetes/pull/47794), [@dnardo](https://github.com/dnardo)) - * Add ip-masq-agent addon to the addons folder which is used in GCE if `--non-masquerade-cidr` is set to 0/0 ([[#46038](https://github.com/kubernetes/kubernetes/pull/46038)](https://github.com/kubernetes/kubernetes/pull/46038), [[@dnardo](https://github.com/dnardo)](https://github.com/dnardo)) + * Add ip-masq-agent addon to the addons folder which is used in GCE if `--non-masquerade-cidr` is set to 0/0 ([#46038](https://github.com/kubernetes/kubernetes/pull/46038), [@dnardo](https://github.com/dnardo)) - * Enable kubelet csr bootstrap in GCE/GKE ([[#40760](https://github.com/kubernetes/kubernetes/pull/40760)](https://github.com/kubernetes/kubernetes/pull/40760), [[@mikedanese](https://github.com/mikedanese)](https://github.com/mikedanese)) + * Enable kubelet csr bootstrap in GCE/GKE ([#40760](https://github.com/kubernetes/kubernetes/pull/40760), [@mikedanese](https://github.com/mikedanese)) - * Adds support for allocation of pod IPs via IP aliases. ([[#42147](https://github.com/kubernetes/kubernetes/pull/42147)](https://github.com/kubernetes/kubernetes/pull/42147), [[@bowei](https://github.com/bowei)](https://github.com/bowei)) + * Adds support for allocation of pod IPs via IP aliases. ([#42147](https://github.com/kubernetes/kubernetes/pull/42147), [@bowei](https://github.com/bowei)) - * gce kube-up: The Node authorization mode and NodeRestriction admission controller are now enabled ([[#46796](https://github.com/kubernetes/kubernetes/pull/46796)](https://github.com/kubernetes/kubernetes/pull/46796), [[@mikedanese](https://github.com/mikedanese)](https://github.com/mikedanese)) + * gce kube-up: The Node authorization mode and NodeRestriction admission controller are now enabled ([#46796](https://github.com/kubernetes/kubernetes/pull/46796), [@mikedanese](https://github.com/mikedanese)) - * Tokens retrieved from Google Cloud with application default credentials will not be cached if the client fails authorization ([[#46694](https://github.com/kubernetes/kubernetes/pull/46694)](https://github.com/kubernetes/kubernetes/pull/46694), [[@matt-tyler](https://github.com/matt-tyler)](https://github.com/matt-tyler)) + * Tokens retrieved from Google Cloud with application default credentials will not be cached if the client fails authorization ([#46694](https://github.com/kubernetes/kubernetes/pull/46694), [@matt-tyler](https://github.com/matt-tyler)) - * Add metrics to all major gce operations {latency, errors} ([[#44510](https://github.com/kubernetes/kubernetes/pull/44510)](https://github.com/kubernetes/kubernetes/pull/44510), [[@bowei](https://github.com/bowei)](https://github.com/bowei)) + * Add metrics to all major gce operations {latency, errors} ([#44510](https://github.com/kubernetes/kubernetes/pull/44510), [@bowei](https://github.com/bowei)) * The new metrics are: @@ -1306,40 +1306,40 @@ Features for this release were tracked via the use of the [kubernetes/features]( * Metrics label tuple would have resulted in many independent histograms stored, one for each disk. (Did not aggregate well). - * Fluentd now tolerates all NoExecute Taints when run in gcp configuration. ([[#45715](https://github.com/kubernetes/kubernetes/pull/45715)](https://github.com/kubernetes/kubernetes/pull/45715), [[@gmarek](https://github.com/gmarek)](https://github.com/gmarek)) + * Fluentd now tolerates all NoExecute Taints when run in gcp configuration. ([#45715](https://github.com/kubernetes/kubernetes/pull/45715), [@gmarek](https://github.com/gmarek)) - * Taints support in gce/salt startup scripts. ([[#47632](https://github.com/kubernetes/kubernetes/pull/47632)](https://github.com/kubernetes/kubernetes/pull/47632), [[@mwielgus](https://github.com/mwielgus)](https://github.com/mwielgus)) + * Taints support in gce/salt startup scripts. ([#47632](https://github.com/kubernetes/kubernetes/pull/47632), [@mwielgus](https://github.com/mwielgus)) - * GCE installs will now avoid IP masquerade for all RFC-1918 IP blocks, rather than just 10.0.0.0/8. This means that clusters can ([[#46473](https://github.com/kubernetes/kubernetes/pull/46473)](https://github.com/kubernetes/kubernetes/pull/46473), [[@thockin](https://github.com/thockin)](https://github.com/thockin)) be created in 192.168.0.0./16 and 172.16.0.0/12 while preserving the container IPs (which would be lost before). + * GCE installs will now avoid IP masquerade for all RFC-1918 IP blocks, rather than just 10.0.0.0/8. This means that clusters can ([#46473](https://github.com/kubernetes/kubernetes/pull/46473), [@thockin](https://github.com/thockin)) be created in 192.168.0.0./16 and 172.16.0.0/12 while preserving the container IPs (which would be lost before). - * Support running Ubuntu image on GCE node ([[#44744](https://github.com/kubernetes/kubernetes/pull/44744)](https://github.com/kubernetes/kubernetes/pull/44744), [[@yguo0905](https://github.com/yguo0905)](https://github.com/yguo0905)) + * Support running Ubuntu image on GCE node ([#44744](https://github.com/kubernetes/kubernetes/pull/44744), [@yguo0905](https://github.com/yguo0905)) - * The gce metadata server can now be hidden behind a proxy, hiding the kubelet's token. ([[#45565](https://github.com/kubernetes/kubernetes/pull/45565)](https://github.com/kubernetes/kubernetes/pull/45565), [[@Q-Lee](https://github.com/Q-Lee)](https://github.com/Q-Lee)) + * The gce metadata server can now be hidden behind a proxy, hiding the kubelet's token. ([#45565](https://github.com/kubernetes/kubernetes/pull/45565), [@Q-Lee](https://github.com/Q-Lee)) * OpenStack: - * Fix issue during LB creation where ports were incorrectly assigned to a floating IP ([[#44387](https://github.com/kubernetes/kubernetes/pull/44387)](https://github.com/kubernetes/kubernetes/pull/44387), [[@jamiehannaford](https://github.com/jamiehannaford)](https://github.com/jamiehannaford)) + * Fix issue during LB creation where ports were incorrectly assigned to a floating IP ([#44387](https://github.com/kubernetes/kubernetes/pull/44387), [@jamiehannaford](https://github.com/jamiehannaford)) - * Openstack cinder v1/v2/auto API support ([[#40423](https://github.com/kubernetes/kubernetes/pull/40423)](https://github.com/kubernetes/kubernetes/pull/40423), [[@mkutsevol](https://github.com/mkutsevol)](https://github.com/mkutsevol)) + * Openstack cinder v1/v2/auto API support ([#40423](https://github.com/kubernetes/kubernetes/pull/40423), [@mkutsevol](https://github.com/mkutsevol)) - * OpenStack clusters can now specify whether worker nodes are assigned a floating IP ([[#42638](https://github.com/kubernetes/kubernetes/pull/42638)](https://github.com/kubernetes/kubernetes/pull/42638), [[@jamiehannaford](https://github.com/jamiehannaford)](https://github.com/jamiehannaford)) + * OpenStack clusters can now specify whether worker nodes are assigned a floating IP ([#42638](https://github.com/kubernetes/kubernetes/pull/42638), [@jamiehannaford](https://github.com/jamiehannaford)) * vSphere: - * Fix volume detach on node failure. ([[#45569](https://github.com/kubernetes/kubernetes/pull/45569)](https://github.com/kubernetes/kubernetes/pull/45569), [[@divyenpatel](https://github.com/divyenpatel)](https://github.com/divyenpatel)) + * Fix volume detach on node failure. ([#45569](https://github.com/kubernetes/kubernetes/pull/45569), [@divyenpatel](https://github.com/divyenpatel)) - * Report same Node IP as both internal and external. ([[#45201](https://github.com/kubernetes/kubernetes/pull/45201)](https://github.com/kubernetes/kubernetes/pull/45201), [[@abrarshivani](https://github.com/abrarshivani)](https://github.com/abrarshivani)) + * Report same Node IP as both internal and external. ([#45201](https://github.com/kubernetes/kubernetes/pull/45201), [@abrarshivani](https://github.com/abrarshivani)) - * Filter out IPV6 node addresses. ([[#45181](https://github.com/kubernetes/kubernetes/pull/45181)](https://github.com/kubernetes/kubernetes/pull/45181), [[@BaluDontu](https://github.com/BaluDontu)](https://github.com/BaluDontu)) + * Filter out IPV6 node addresses. ([#45181](https://github.com/kubernetes/kubernetes/pull/45181), [@BaluDontu](https://github.com/BaluDontu)) - * Fix fetching of VM UUID on Ubuntu 16.04 and Fedora. ([[#45311](https://github.com/kubernetes/kubernetes/pull/45311)](https://github.com/kubernetes/kubernetes/pull/45311), [[@divyenpatel](https://github.com/divyenpatel)](https://github.com/divyenpatel)) + * Fix fetching of VM UUID on Ubuntu 16.04 and Fedora. ([#45311](https://github.com/kubernetes/kubernetes/pull/45311), [@divyenpatel](https://github.com/divyenpatel)) #### Cluster Provisioning * Juju: - * Add Kubernetes 1.6 support to Juju charms ([[#44500](https://github.com/kubernetes/kubernetes/pull/44500)](https://github.com/kubernetes/kubernetes/pull/44500), [[@Cynerva](https://github.com/Cynerva)](https://github.com/Cynerva)) + * Add Kubernetes 1.6 support to Juju charms ([#44500](https://github.com/kubernetes/kubernetes/pull/44500), [@Cynerva](https://github.com/Cynerva)) * Add metric collection to charms for autoscaling @@ -1361,146 +1361,146 @@ Features for this release were tracked via the use of the [kubernetes/features]( * Fix nagios checks in charms - * Enable GPU mode if GPU hardware detected ([[#43467](https://github.com/kubernetes/kubernetes/pull/43467)](https://github.com/kubernetes/kubernetes/pull/43467), [[@tvansteenburgh](https://github.com/tvansteenburgh)](https://github.com/tvansteenburgh)) + * Enable GPU mode if GPU hardware detected ([#43467](https://github.com/kubernetes/kubernetes/pull/43467), [@tvansteenburgh](https://github.com/tvansteenburgh)) - * Fix ceph-secret type to kubernetes.io/rbd in kubernetes-master charm ([[#44635](https://github.com/kubernetes/kubernetes/pull/44635)](https://github.com/kubernetes/kubernetes/pull/44635), [[@Cynerva](https://github.com/Cynerva)](https://github.com/Cynerva)) + * Fix ceph-secret type to kubernetes.io/rbd in kubernetes-master charm ([#44635](https://github.com/kubernetes/kubernetes/pull/44635), [@Cynerva](https://github.com/Cynerva)) - * Disallows installation of upstream docker from PPA in the Juju kubernetes-worker charm. ([[#44681](https://github.com/kubernetes/kubernetes/pull/44681)](https://github.com/kubernetes/kubernetes/pull/44681), [[@wwwtyro](https://github.com/wwwtyro)](https://github.com/wwwtyro)) + * Disallows installation of upstream docker from PPA in the Juju kubernetes-worker charm. ([#44681](https://github.com/kubernetes/kubernetes/pull/44681), [@wwwtyro](https://github.com/wwwtyro)) - * Resolves juju vsphere hostname bug showing only a single node in a scaled node-pool. ([[#44780](https://github.com/kubernetes/kubernetes/pull/44780)](https://github.com/kubernetes/kubernetes/pull/44780), [[@chuckbutler](https://github.com/chuckbutler)](https://github.com/chuckbutler)) + * Resolves juju vsphere hostname bug showing only a single node in a scaled node-pool. ([#44780](https://github.com/kubernetes/kubernetes/pull/44780), [@chuckbutler](https://github.com/chuckbutler)) - * Fixes a bug in the kubernetes-worker Juju charm code that attempted to give kube-proxy more than one api endpoint. ([[#44677](https://github.com/kubernetes/kubernetes/pull/44677)](https://github.com/kubernetes/kubernetes/pull/44677), [[@wwwtyro](https://github.com/wwwtyro)](https://github.com/wwwtyro)) + * Fixes a bug in the kubernetes-worker Juju charm code that attempted to give kube-proxy more than one api endpoint. ([#44677](https://github.com/kubernetes/kubernetes/pull/44677), [@wwwtyro](https://github.com/wwwtyro)) - * Added CIFS PV support for Juju Charms ([[#45117](https://github.com/kubernetes/kubernetes/pull/45117)](https://github.com/kubernetes/kubernetes/pull/45117), [[@chuckbutler](https://github.com/chuckbutler)](https://github.com/chuckbutler)) + * Added CIFS PV support for Juju Charms ([#45117](https://github.com/kubernetes/kubernetes/pull/45117), [@chuckbutler](https://github.com/chuckbutler)) - * Fixes juju kubernetes master: 1. Get certs from a dead leader. 2. Append tokens. ([[#43620](https://github.com/kubernetes/kubernetes/pull/43620)](https://github.com/kubernetes/kubernetes/pull/43620), [[@ktsakalozos](https://github.com/ktsakalozos)](https://github.com/ktsakalozos)) + * Fixes juju kubernetes master: 1. Get certs from a dead leader. 2. Append tokens. ([#43620](https://github.com/kubernetes/kubernetes/pull/43620), [@ktsakalozos](https://github.com/ktsakalozos)) - * kubernetes-master juju charm properly detects etcd-scale events and reconfigures appropriately. ([[#44967](https://github.com/kubernetes/kubernetes/pull/44967)](https://github.com/kubernetes/kubernetes/pull/44967), [[@chuckbutler](https://github.com/chuckbutler)](https://github.com/chuckbutler)) + * kubernetes-master juju charm properly detects etcd-scale events and reconfigures appropriately. ([#44967](https://github.com/kubernetes/kubernetes/pull/44967), [@chuckbutler](https://github.com/chuckbutler)) - * Use correct option name in the kubernetes-worker layer registry action ([[#44921](https://github.com/kubernetes/kubernetes/pull/44921)](https://github.com/kubernetes/kubernetes/pull/44921), [[@jacekn](https://github.com/jacekn)](https://github.com/jacekn)) + * Use correct option name in the kubernetes-worker layer registry action ([#44921](https://github.com/kubernetes/kubernetes/pull/44921), [@jacekn](https://github.com/jacekn)) - * Send dns details only after cdk-addons are configured ([[#44945](https://github.com/kubernetes/kubernetes/pull/44945)](https://github.com/kubernetes/kubernetes/pull/44945), [[@ktsakalozos](https://github.com/ktsakalozos)](https://github.com/ktsakalozos)) + * Send dns details only after cdk-addons are configured ([#44945](https://github.com/kubernetes/kubernetes/pull/44945), [@ktsakalozos](https://github.com/ktsakalozos)) - * Added support to the pause action in the kubernetes-worker charm for new flag `--delete-local-data` ([[#44931](https://github.com/kubernetes/kubernetes/pull/44931)](https://github.com/kubernetes/kubernetes/pull/44931), [[@chuckbutler](https://github.com/chuckbutler)](https://github.com/chuckbutler)) + * Added support to the pause action in the kubernetes-worker charm for new flag `--delete-local-data` ([#44931](https://github.com/kubernetes/kubernetes/pull/44931), [@chuckbutler](https://github.com/chuckbutler)) - * Add namespace-{list, create, delete} actions to the kubernetes-master layer ([[#44277](https://github.com/kubernetes/kubernetes/pull/44277)](https://github.com/kubernetes/kubernetes/pull/44277), [[@jacekn](https://github.com/jacekn)](https://github.com/jacekn)) + * Add namespace-{list, create, delete} actions to the kubernetes-master layer ([#44277](https://github.com/kubernetes/kubernetes/pull/44277), [@jacekn](https://github.com/jacekn)) - * Using http2 in kubeapi-load-balancer to fix `kubectl exec` uses ([[#43625](https://github.com/kubernetes/kubernetes/pull/43625)](https://github.com/kubernetes/kubernetes/pull/43625), [[@mbruzek](https://github.com/mbruzek)](https://github.com/mbruzek)) + * Using http2 in kubeapi-load-balancer to fix `kubectl exec` uses ([#43625](https://github.com/kubernetes/kubernetes/pull/43625), [@mbruzek](https://github.com/mbruzek)) - * Don't append :443 to registry domain in the kubernetes-worker layer registry action ([[#45550](https://github.com/kubernetes/kubernetes/pull/45550)](https://github.com/kubernetes/kubernetes/pull/45550), [[@jacekn](https://github.com/jacekn)](https://github.com/jacekn)) + * Don't append :443 to registry domain in the kubernetes-worker layer registry action ([#45550](https://github.com/kubernetes/kubernetes/pull/45550), [@jacekn](https://github.com/jacekn)) * kubeadm - * Enable the Node Authorizer/Admission plugin in v1.7 ([[#46879](https://github.com/kubernetes/kubernetes/pull/46879)](https://github.com/kubernetes/kubernetes/pull/46879), [[@luxas](https://github.com/luxas)](https://github.com/luxas)) + * Enable the Node Authorizer/Admission plugin in v1.7 ([#46879](https://github.com/kubernetes/kubernetes/pull/46879), [@luxas](https://github.com/luxas)) - * Users can now pass extra parameters to etcd in a kubeadm cluster ([[#42246](https://github.com/kubernetes/kubernetes/pull/42246)](https://github.com/kubernetes/kubernetes/pull/42246), [[@jamiehannaford](https://github.com/jamiehannaford)](https://github.com/jamiehannaford)) + * Users can now pass extra parameters to etcd in a kubeadm cluster ([#42246](https://github.com/kubernetes/kubernetes/pull/42246), [@jamiehannaford](https://github.com/jamiehannaford)) - * Make kubeadm use the new CSR approver in v1.7 ([[#46864](https://github.com/kubernetes/kubernetes/pull/46864)](https://github.com/kubernetes/kubernetes/pull/46864), [[@luxas](https://github.com/luxas)](https://github.com/luxas)) + * Make kubeadm use the new CSR approver in v1.7 ([#46864](https://github.com/kubernetes/kubernetes/pull/46864), [@luxas](https://github.com/luxas)) - * Allow enabling multiple authorization modes at the same time ([[#42557](https://github.com/kubernetes/kubernetes/pull/42557)](https://github.com/kubernetes/kubernetes/pull/42557), [[@xilabao](https://github.com/xilabao)](https://github.com/xilabao)) + * Allow enabling multiple authorization modes at the same time ([#42557](https://github.com/kubernetes/kubernetes/pull/42557), [@xilabao](https://github.com/xilabao)) - * add proxy client-certs to kube-apiserver to allow it to proxy aggregated api servers ([[#43715](https://github.com/kubernetes/kubernetes/pull/43715)](https://github.com/kubernetes/kubernetes/pull/43715), [[@deads2k](https://github.com/deads2k)](https://github.com/deads2k))* CentOS provider + * add proxy client-certs to kube-apiserver to allow it to proxy aggregated api servers ([#43715](https://github.com/kubernetes/kubernetes/pull/43715), [@deads2k](https://github.com/deads2k))* CentOS provider * hyperkube - * The hyperkube image has been slimmed down and no longer includes addon manifests and other various scripts. These were introduced for the now removed docker-multinode setup system. ([[#44555](https://github.com/kubernetes/kubernetes/pull/44555)](https://github.com/kubernetes/kubernetes/pull/44555), [[@luxas](https://github.com/luxas)](https://github.com/luxas)) + * The hyperkube image has been slimmed down and no longer includes addon manifests and other various scripts. These were introduced for the now removed docker-multinode setup system. ([#44555](https://github.com/kubernetes/kubernetes/pull/44555), [@luxas](https://github.com/luxas)) -* Support secure etcd cluster for centos provider. ([[#42994](https://github.com/kubernetes/kubernetes/pull/42994)](https://github.com/kubernetes/kubernetes/pull/42994), [[@Shawyeok](https://github.com/Shawyeok)](https://github.com/Shawyeok)) +* Support secure etcd cluster for centos provider. ([#42994](https://github.com/kubernetes/kubernetes/pull/42994), [@Shawyeok](https://github.com/Shawyeok)) -* Update to kube-addon-manager:v6.4-beta.2: kubectl v1.6.4 and refreshed base images ([[#47389](https://github.com/kubernetes/kubernetes/pull/47389)](https://github.com/kubernetes/kubernetes/pull/47389), [[@ixdy](https://github.com/ixdy)](https://github.com/ixdy)) +* Update to kube-addon-manager:v6.4-beta.2: kubectl v1.6.4 and refreshed base images ([#47389](https://github.com/kubernetes/kubernetes/pull/47389), [@ixdy](https://github.com/ixdy)) -* Remove Initializers from admission-control in kubernetes-master charm for pre-1.7 ([[#46987](https://github.com/kubernetes/kubernetes/pull/46987)](https://github.com/kubernetes/kubernetes/pull/46987), [[@Cynerva](https://github.com/Cynerva)](https://github.com/Cynerva)) +* Remove Initializers from admission-control in kubernetes-master charm for pre-1.7 ([#46987](https://github.com/kubernetes/kubernetes/pull/46987), [@Cynerva](https://github.com/Cynerva)) -* Added state guards to the idle_status messaging in the kubernetes-master charm to make deployment faster on initial deployment. ([[#47183](https://github.com/kubernetes/kubernetes/pull/47183)](https://github.com/kubernetes/kubernetes/pull/47183), [[@chuckbutler](https://github.com/chuckbutler)](https://github.com/chuckbutler)) +* Added state guards to the idle_status messaging in the kubernetes-master charm to make deployment faster on initial deployment. ([#47183](https://github.com/kubernetes/kubernetes/pull/47183), [@chuckbutler](https://github.com/chuckbutler)) #### Cluster federation * Features: - * Adds annotations to all Federation objects created by kubefed. ([[#42683](https://github.com/kubernetes/kubernetes/pull/42683)](https://github.com/kubernetes/kubernetes/pull/42683), [[@perotinus](https://github.com/perotinus)](https://github.com/perotinus)) + * Adds annotations to all Federation objects created by kubefed. ([#42683](https://github.com/kubernetes/kubernetes/pull/42683), [@perotinus](https://github.com/perotinus)) * Mechanism of adding `federation domain maps` to kube-dns deployment via `--federations` flag is superseded by adding/updating `federations` key in `kube-system/kube-dns` configmap. If user is using kubefed tool to join cluster federation, adding federation domain maps to kube-dns is already taken care by `kubefed join` and does not need further action. - * Prints out status updates when running `kubefed init` ([[#41849](https://github.com/kubernetes/kubernetes/pull/41849)](https://github.com/kubernetes/kubernetes/pull/41849), [[@perotinus](https://github.com/perotinus)](https://github.com/perotinus)) + * Prints out status updates when running `kubefed init` ([#41849](https://github.com/kubernetes/kubernetes/pull/41849), [@perotinus](https://github.com/perotinus)) - * `kubefed init` now supports overriding the default etcd image name with the `--etcd-image` parameter. ([[#46247](https://github.com/kubernetes/kubernetes/pull/46247)](https://github.com/kubernetes/kubernetes/pull/46247), [[@marun](https://github.com/marun)](https://github.com/marun)) + * `kubefed init` now supports overriding the default etcd image name with the `--etcd-image` parameter. ([#46247](https://github.com/kubernetes/kubernetes/pull/46247), [@marun](https://github.com/marun)) - * kubefed will now configure NodeInternalIP as the federation API server endpoint when NodeExternalIP is unavailable for federation API servers exposed as NodePort services ([[#46960](https://github.com/kubernetes/kubernetes/pull/46960)](https://github.com/kubernetes/kubernetes/pull/46960), [[@lukaszo](https://github.com/lukaszo)](https://github.com/lukaszo)) + * kubefed will now configure NodeInternalIP as the federation API server endpoint when NodeExternalIP is unavailable for federation API servers exposed as NodePort services ([#46960](https://github.com/kubernetes/kubernetes/pull/46960), [@lukaszo](https://github.com/lukaszo)) - * Automate configuring nameserver in cluster-dns for CoreDNS provider ([[#42895](https://github.com/kubernetes/kubernetes/pull/42895)](https://github.com/kubernetes/kubernetes/pull/42895), [[@shashidharatd](https://github.com/shashidharatd)](https://github.com/shashidharatd)) + * Automate configuring nameserver in cluster-dns for CoreDNS provider ([#42895](https://github.com/kubernetes/kubernetes/pull/42895), [@shashidharatd](https://github.com/shashidharatd)) - * A new controller for managing DNS records is introduced which can be optionally disabled to enable third party components to manage DNS records for federated services. ([[#450354](https://github.com/kubernetes/kubernetes/pull/450354)](https://github.com/kubernetes/kubernetes/pull/45034), [[@shashidharatd](https://github.com/shashidharatd)(https://github.com/shashidharatd)]) + * A new controller for managing DNS records is introduced which can be optionally disabled to enable third party components to manage DNS records for federated services. ([#450354](https://github.com/kubernetes/kubernetes/pull/450354), [@shashidharatd](https://github.com/shashidharatd)(https://github.com/shashidharatd)]) - * Remove the `--secret-name` flag from `kubefed join`, instead generating the secret name arbitrarily. ([[#42513](https://github.com/kubernetes/kubernetes/pull/42513)](https://github.com/kubernetes/kubernetes/pull/42513), [[@perotinus](https://github.com/perotinus)](https://github.com/perotinus)) + * Remove the `--secret-name` flag from `kubefed join`, instead generating the secret name arbitrarily. ([#42513](https://github.com/kubernetes/kubernetes/pull/42513), [@perotinus](https://github.com/perotinus)) - * Use StorageClassName for etcd pvc ([[#46323](https://github.com/kubernetes/kubernetes/pull/46323)](https://github.com/kubernetes/kubernetes/pull/46323), [[@marun](https://github.com/marun)](https://github.com/marun)) + * Use StorageClassName for etcd pvc ([#46323](https://github.com/kubernetes/kubernetes/pull/46323), [@marun](https://github.com/marun)) * Bug fixes: - * Allow disabling federation controllers through override args ([[#44209](https://github.com/kubernetes/kubernetes/pull/44209)](https://github.com/kubernetes/kubernetes/pull/44209), [[@irfanurrehman](https://github.com/irfanurrehman)](https://github.com/irfanurrehman)) + * Allow disabling federation controllers through override args ([#44209](https://github.com/kubernetes/kubernetes/pull/44209), [@irfanurrehman](https://github.com/irfanurrehman)) - * Kubefed: Use service accounts instead of the user's credentials when accessing joined clusters' API servers. ([[#42042](https://github.com/kubernetes/kubernetes/pull/42042)](https://github.com/kubernetes/kubernetes/pull/42042), [[@perotinus](https://github.com/perotinus)](https://github.com/perotinus)) + * Kubefed: Use service accounts instead of the user's credentials when accessing joined clusters' API servers. ([#42042](https://github.com/kubernetes/kubernetes/pull/42042), [@perotinus](https://github.com/perotinus)) - * Avoid panic if route53 fields are nil ([[#44380](https://github.com/kubernetes/kubernetes/pull/44380)](https://github.com/kubernetes/kubernetes/pull/44380), [[@justinsb](https://github.com/justinsb)](https://github.com/justinsb)) + * Avoid panic if route53 fields are nil ([#44380](https://github.com/kubernetes/kubernetes/pull/44380), [@justinsb](https://github.com/justinsb)) #### Credential provider -* add rancher credential provider ([[#40160](https://github.com/kubernetes/kubernetes/pull/40160)](https://github.com/kubernetes/kubernetes/pull/40160), [[@wlan0](https://github.com/wlan0)](https://github.com/wlan0)) +* add rancher credential provider ([#40160](https://github.com/kubernetes/kubernetes/pull/40160), [@wlan0](https://github.com/wlan0)) #### Information for Kubernetes clients (openapi, swagger, client-go) * Features: - * Add Host field to TCPSocketAction ([[#42902](https://github.com/kubernetes/kubernetes/pull/42902)](https://github.com/kubernetes/kubernetes/pull/42902), [[@louyihua](https://github.com/louyihua)](https://github.com/louyihua)) + * Add Host field to TCPSocketAction ([#42902](https://github.com/kubernetes/kubernetes/pull/42902), [@louyihua](https://github.com/louyihua)) - * Add the ability to lock on ConfigMaps to support HA for self hosted components ([[#42666](https://github.com/kubernetes/kubernetes/pull/42666)](https://github.com/kubernetes/kubernetes/pull/42666), [[@timothysc](https://github.com/timothysc)](https://github.com/timothysc)) + * Add the ability to lock on ConfigMaps to support HA for self hosted components ([#42666](https://github.com/kubernetes/kubernetes/pull/42666), [@timothysc](https://github.com/timothysc)) - * validateClusterInfo: use clientcmdapi.NewCluster() ([[#44221](https://github.com/kubernetes/kubernetes/pull/44221)](https://github.com/kubernetes/kubernetes/pull/44221), [[@ncdc](https://github.com/ncdc)](https://github.com/ncdc)) + * validateClusterInfo: use clientcmdapi.NewCluster() ([#44221](https://github.com/kubernetes/kubernetes/pull/44221), [@ncdc](https://github.com/ncdc)) - * OpenAPI spec is now available in protobuf binary and gzip format (with ETag support) ([[#45836](https://github.com/kubernetes/kubernetes/pull/45836)](https://github.com/kubernetes/kubernetes/pull/45836), [[@mbohlool](https://github.com/mbohlool)](https://github.com/mbohlool)) + * OpenAPI spec is now available in protobuf binary and gzip format (with ETag support) ([#45836](https://github.com/kubernetes/kubernetes/pull/45836), [@mbohlool](https://github.com/mbohlool)) - * HostAliases is now parsed with hostAliases json keys to be in line with the feature's name. ([[#47512](https://github.com/kubernetes/kubernetes/pull/47512)](https://github.com/kubernetes/kubernetes/pull/47512), [[@rickypai](https://github.com/rickypai)](https://github.com/rickypai)) + * HostAliases is now parsed with hostAliases json keys to be in line with the feature's name. ([#47512](https://github.com/kubernetes/kubernetes/pull/47512), [@rickypai](https://github.com/rickypai)) - * Add redirect support to SpdyRoundTripper ([[#44451](https://github.com/kubernetes/kubernetes/pull/44451)](https://github.com/kubernetes/kubernetes/pull/44451), [[@ncdc](https://github.com/ncdc)](https://github.com/ncdc)) + * Add redirect support to SpdyRoundTripper ([#44451](https://github.com/kubernetes/kubernetes/pull/44451), [@ncdc](https://github.com/ncdc)) - * Duplicate recurring Events now include the latest event's Message string ([[#46034](https://github.com/kubernetes/kubernetes/pull/46034)](https://github.com/kubernetes/kubernetes/pull/46034), [[@kensimon](https://github.com/kensimon)](https://github.com/kensimon)) + * Duplicate recurring Events now include the latest event's Message string ([#46034](https://github.com/kubernetes/kubernetes/pull/46034), [@kensimon](https://github.com/kensimon)) * Bug fixes: - * Fix serialization of EnforceNodeAllocatable ([[#44606](https://github.com/kubernetes/kubernetes/pull/44606)](https://github.com/kubernetes/kubernetes/pull/44606), [[@ivan4th](https://github.com/ivan4th)](https://github.com/ivan4th)) + * Fix serialization of EnforceNodeAllocatable ([#44606](https://github.com/kubernetes/kubernetes/pull/44606), [@ivan4th](https://github.com/ivan4th)) - * Use OS-specific libs when computing client User-Agent in kubectl, etc. ([[#44423](https://github.com/kubernetes/kubernetes/pull/44423)](https://github.com/kubernetes/kubernetes/pull/44423), [[@monopole](https://github.com/monopole)](https://github.com/monopole)) + * Use OS-specific libs when computing client User-Agent in kubectl, etc. ([#44423](https://github.com/kubernetes/kubernetes/pull/44423), [@monopole](https://github.com/monopole)) #### Instrumentation * Bumped Heapster to v1.4.0. More details about the release https://github.com/kubernetes/heapster/releases/tag/v1.4.0 -* Fluentd manifest pod is no longer created on non-registered master when creating clusters using kube-up.sh. ([[#44721](https://github.com/kubernetes/kubernetes/pull/44721)](https://github.com/kubernetes/kubernetes/pull/44721), [[@piosz](https://github.com/piosz)](https://github.com/piosz)) +* Fluentd manifest pod is no longer created on non-registered master when creating clusters using kube-up.sh. ([#44721](https://github.com/kubernetes/kubernetes/pull/44721), [@piosz](https://github.com/piosz)) -* Stackdriver cluster logging now deploys a new component to export Kubernetes events. ([[#46700](https://github.com/kubernetes/kubernetes/pull/46700)](https://github.com/kubernetes/kubernetes/pull/46700), [[@crassirostris](https://github.com/crassirostris)](https://github.com/crassirostris)) +* Stackdriver cluster logging now deploys a new component to export Kubernetes events. ([#46700](https://github.com/kubernetes/kubernetes/pull/46700), [@crassirostris](https://github.com/crassirostris)) -* Stackdriver Logging deployment exposes metrics on node port 31337 when enabled. ([[#47402](https://github.com/kubernetes/kubernetes/pull/47402)](https://github.com/kubernetes/kubernetes/pull/47402), [[@crassirostris](https://github.com/crassirostris)](https://github.com/crassirostris)) +* Stackdriver Logging deployment exposes metrics on node port 31337 when enabled. ([#47402](https://github.com/kubernetes/kubernetes/pull/47402), [@crassirostris](https://github.com/crassirostris)) -* Upgrade Elasticsearch Addon to v5.4.0 ([[#45589](https://github.com/kubernetes/kubernetes/pull/45589)](https://github.com/kubernetes/kubernetes/pull/45589), [[@it-svit](https://github.com/it-svit)](https://github.com/it-svit)) +* Upgrade Elasticsearch Addon to v5.4.0 ([#45589](https://github.com/kubernetes/kubernetes/pull/45589), [@it-svit](https://github.com/it-svit)) #### Internal storage layer -* prevent pods/status from touching ownerreferences ([[#45826](https://github.com/kubernetes/kubernetes/pull/45826)](https://github.com/kubernetes/kubernetes/pull/45826), [[@deads2k](https://github.com/deads2k)](https://github.com/deads2k)) +* prevent pods/status from touching ownerreferences ([#45826](https://github.com/kubernetes/kubernetes/pull/45826), [@deads2k](https://github.com/deads2k)) -* Ensure that autoscaling/v1 is the preferred version for API discovery when autoscaling/v2alpha1 is enabled. ([[#45741](https://github.com/kubernetes/kubernetes/pull/45741)](https://github.com/kubernetes/kubernetes/pull/45741), [[@DirectXMan12](https://github.com/DirectXMan12)](https://github.com/DirectXMan12)) +* Ensure that autoscaling/v1 is the preferred version for API discovery when autoscaling/v2alpha1 is enabled. ([#45741](https://github.com/kubernetes/kubernetes/pull/45741), [@DirectXMan12](https://github.com/DirectXMan12)) -* The proxy subresource APIs for nodes, services, and pods now support the HTTP PATCH method. ([[#44929](https://github.com/kubernetes/kubernetes/pull/44929)](https://github.com/kubernetes/kubernetes/pull/44929), [[@liggitt](https://github.com/liggitt)](https://github.com/liggitt)) +* The proxy subresource APIs for nodes, services, and pods now support the HTTP PATCH method. ([#44929](https://github.com/kubernetes/kubernetes/pull/44929), [@liggitt](https://github.com/liggitt)) -* Fluentd now tolerates all NoExecute Taints when run in gcp configuration. ([[#45715](https://github.com/kubernetes/kubernetes/pull/45715)](https://github.com/kubernetes/kubernetes/pull/45715), [[@gmarek](https://github.com/gmarek)](https://github.com/gmarek)) +* Fluentd now tolerates all NoExecute Taints when run in gcp configuration. ([#45715](https://github.com/kubernetes/kubernetes/pull/45715), [@gmarek](https://github.com/gmarek)) #### Kubernetes Dashboard * Increase Dashboard's memory requests and limits ([#44712](https://github.com/kubernetes/kubernetes/pull/44712), [@maciaszczykm](https://github.com/maciaszczykm)) -* Update Dashboard version to 1.6.1 ([[#45953](https://github.com/kubernetes/kubernetes/pull/45953)](https://github.com/kubernetes/kubernetes/pull/45953), [[@maciaszczykm](https://github.com/maciaszczykm)](https://github.com/maciaszczykm)) +* Update Dashboard version to 1.6.1 ([#45953](https://github.com/kubernetes/kubernetes/pull/45953), [@maciaszczykm](https://github.com/maciaszczykm)) #### kube-dns -* Updates kube-dns to 1.14.2 ([[#45684](https://github.com/kubernetes/kubernetes/pull/45684)](https://github.com/kubernetes/kubernetes/pull/45684), [[@bowei](https://github.com/bowei)](https://github.com/bowei)) +* Updates kube-dns to 1.14.2 ([#45684](https://github.com/kubernetes/kubernetes/pull/45684), [@bowei](https://github.com/bowei)) * Support kube-master-url flag without kubeconfig @@ -1517,82 +1517,82 @@ Features for this release were tracked via the use of the [kubernetes/features]( #### kube-proxy * Features: - * ratelimit runs of iptables by sync-period flags ([[#46266](https://github.com/kubernetes/kubernetes/pull/46266)](https://github.com/kubernetes/kubernetes/pull/46266), [[@thockin](https://github.com/thockin)](https://github.com/thockin)) + * ratelimit runs of iptables by sync-period flags ([#46266](https://github.com/kubernetes/kubernetes/pull/46266), [@thockin](https://github.com/thockin)) - * Log warning when invalid dir passed to `kubectl proxy --www` ([[#44952](https://github.com/kubernetes/kubernetes/pull/44952)](https://github.com/kubernetes/kubernetes/pull/44952), [[@CaoShuFeng](https://github.com/CaoShuFeng)](https://github.com/CaoShuFeng)) + * Log warning when invalid dir passed to `kubectl proxy --www` ([#44952](https://github.com/kubernetes/kubernetes/pull/44952), [@CaoShuFeng](https://github.com/CaoShuFeng)) - * Add `--write-config-to` flag to kube-proxy to allow users to write the default configuration settings to a file. ([[#45908](https://github.com/kubernetes/kubernetes/pull/45908)](https://github.com/kubernetes/kubernetes/pull/45908), [[@ncdc](https://github.com/ncdc)](https://github.com/ncdc)) + * Add `--write-config-to` flag to kube-proxy to allow users to write the default configuration settings to a file. ([#45908](https://github.com/kubernetes/kubernetes/pull/45908), [@ncdc](https://github.com/ncdc)) - * When switching from the service.beta.kubernetes.io/external-traffic annotation to the new ([[#46716](https://github.com/kubernetes/kubernetes/pull/46716)](https://github.com/kubernetes/kubernetes/pull/46716), [[@thockin](https://github.com/thockin)](https://github.com/thockin)) externalTrafficPolicy field, the values chnag as follows: * "OnlyLocal" becomes "Local" * "Global" becomes "Cluster". + * When switching from the service.beta.kubernetes.io/external-traffic annotation to the new ([#46716](https://github.com/kubernetes/kubernetes/pull/46716), [@thockin](https://github.com/thockin)) externalTrafficPolicy field, the values chnag as follows: * "OnlyLocal" becomes "Local" * "Global" becomes "Cluster". * Bug fixes: - * Fix corner-case with OnlyLocal Service healthchecks. ([[#44313](https://github.com/kubernetes/kubernetes/pull/44313)](https://github.com/kubernetes/kubernetes/pull/44313), [[@thockin](https://github.com/thockin)](https://github.com/thockin)) + * Fix corner-case with OnlyLocal Service healthchecks. ([#44313](https://github.com/kubernetes/kubernetes/pull/44313), [@thockin](https://github.com/thockin)) - * Fix DNS suffix search list support in Windows kube-proxy. ([[#45642](https://github.com/kubernetes/kubernetes/pull/45642)](https://github.com/kubernetes/kubernetes/pull/45642), [[@JiangtianLi](https://github.com/JiangtianLi)](https://github.com/JiangtianLi)) + * Fix DNS suffix search list support in Windows kube-proxy. ([#45642](https://github.com/kubernetes/kubernetes/pull/45642), [@JiangtianLi](https://github.com/JiangtianLi)) #### kube-scheduler -* Scheduler can receive its policy configuration from a ConfigMap ([[#43892](https://github.com/kubernetes/kubernetes/pull/43892)](https://github.com/kubernetes/kubernetes/pull/43892), [[@bsalamat](https://github.com/bsalamat)](https://github.com/bsalamat)) +* Scheduler can receive its policy configuration from a ConfigMap ([#43892](https://github.com/kubernetes/kubernetes/pull/43892), [@bsalamat](https://github.com/bsalamat)) -* Aggregated used ports at the NodeInfo level for PodFitsHostPorts predicate. ([[#42524](https://github.com/kubernetes/kubernetes/pull/42524)](https://github.com/kubernetes/kubernetes/pull/42524), [[@k82cn](https://github.com/k82cn)](https://github.com/k82cn)) +* Aggregated used ports at the NodeInfo level for PodFitsHostPorts predicate. ([#42524](https://github.com/kubernetes/kubernetes/pull/42524), [@k82cn](https://github.com/k82cn)) -* leader election lock based on scheduler name ([[#42961](https://github.com/kubernetes/kubernetes/pull/42961)](https://github.com/kubernetes/kubernetes/pull/42961), [[@wanghaoran1988](https://github.com/wanghaoran1988)](https://github.com/wanghaoran1988)) +* leader election lock based on scheduler name ([#42961](https://github.com/kubernetes/kubernetes/pull/42961), [@wanghaoran1988](https://github.com/wanghaoran1988)) - * Fix DNS suffix search list support in Windows kube-proxy. ([[#45642](https://github.com/kubernetes/kubernetes/pull/45642)](https://github.com/kubernetes/kubernetes/pull/45642), [[@JiangtianLi](https://github.com/JiangtianLi)](https://github.com/JiangtianLi)) + * Fix DNS suffix search list support in Windows kube-proxy. ([#45642](https://github.com/kubernetes/kubernetes/pull/45642), [@JiangtianLi](https://github.com/JiangtianLi)) #### Storage * Features - * The options passed to a Flexvolume plugin's mount command now contains the pod name (kubernetes.io/pod.name), namespace (kubernetes.io/pod.namespace), uid (kubernetes.io/pod.uid), and service account name (kubernetes.io/serviceAccount.name). ([[#39488](https://github.com/kubernetes/kubernetes/pull/39488)](https://github.com/kubernetes/kubernetes/pull/39488), [[@liggitt](https://github.com/liggitt)](https://github.com/liggitt)) + * The options passed to a Flexvolume plugin's mount command now contains the pod name (kubernetes.io/pod.name), namespace (kubernetes.io/pod.namespace), uid (kubernetes.io/pod.uid), and service account name (kubernetes.io/serviceAccount.name). ([#39488](https://github.com/kubernetes/kubernetes/pull/39488), [@liggitt](https://github.com/liggitt)) - * GCE and AWS dynamic provisioners extension: admins can configure zone(s) in which a persistent volume shall be created. ([[#38505](https://github.com/kubernetes/kubernetes/pull/38505)](https://github.com/kubernetes/kubernetes/pull/38505), [[@pospispa](https://github.com/pospispa)](https://github.com/pospispa)) + * GCE and AWS dynamic provisioners extension: admins can configure zone(s) in which a persistent volume shall be created. ([#38505](https://github.com/kubernetes/kubernetes/pull/38505), [@pospispa](https://github.com/pospispa)) - * Implement API usage metrics for GCE storage. ([[#40338](https://github.com/kubernetes/kubernetes/pull/40338)](https://github.com/kubernetes/kubernetes/pull/40338), [[@gnufied](https://github.com/gnufied)](https://github.com/gnufied)) + * Implement API usage metrics for GCE storage. ([#40338](https://github.com/kubernetes/kubernetes/pull/40338), [@gnufied](https://github.com/gnufied)) - * Add support for emitting metrics from openstack cloudprovider about storage operations. ([[#46008](https://github.com/kubernetes/kubernetes/pull/46008)](https://github.com/kubernetes/kubernetes/pull/46008), [[@NickrenREN](https://github.com/NickrenREN)](https://github.com/NickrenREN)) + * Add support for emitting metrics from openstack cloudprovider about storage operations. ([#46008](https://github.com/kubernetes/kubernetes/pull/46008), [@NickrenREN](https://github.com/NickrenREN)) - * vSphere cloud provider: vSphere storage policy support for dynamic volume provisioning. ([[#46176](https://github.com/kubernetes/kubernetes/pull/46176)](https://github.com/kubernetes/kubernetes/pull/46176), [[@BaluDontu](https://github.com/BaluDontu)](https://github.com/BaluDontu)) + * vSphere cloud provider: vSphere storage policy support for dynamic volume provisioning. ([#46176](https://github.com/kubernetes/kubernetes/pull/46176), [@BaluDontu](https://github.com/BaluDontu)) - * Support StorageClass in Azure file volume ([[#42170](https://github.com/kubernetes/kubernetes/pull/42170)](https://github.com/kubernetes/kubernetes/pull/42170), [[@rootfs](https://github.com/rootfs)](https://github.com/rootfs)) + * Support StorageClass in Azure file volume ([#42170](https://github.com/kubernetes/kubernetes/pull/42170), [@rootfs](https://github.com/rootfs)) - * Start recording cloud provider metrics for AWS ([[#43477](https://github.com/kubernetes/kubernetes/pull/43477)](https://github.com/kubernetes/kubernetes/pull/43477), [[@gnufied](https://github.com/gnufied)](https://github.com/gnufied)) + * Start recording cloud provider metrics for AWS ([#43477](https://github.com/kubernetes/kubernetes/pull/43477), [@gnufied](https://github.com/gnufied)) - * Support iSCSI CHAP authentication ([[#43396](https://github.com/kubernetes/kubernetes/pull/43396)](https://github.com/kubernetes/kubernetes/pull/43396), [[@rootfs](https://github.com/rootfs)](https://github.com/rootfs)) + * Support iSCSI CHAP authentication ([#43396](https://github.com/kubernetes/kubernetes/pull/43396), [@rootfs](https://github.com/rootfs)) - * Openstack cinder v1/v2/auto API support ([[#40423](https://github.com/kubernetes/kubernetes/pull/40423)](https://github.com/kubernetes/kubernetes/pull/40423), [[@mkutsevol](https://github.com/mkutsevol)](https://github.com/mkutsevol * cinder: Add support for the KVM virtio-scsi driver ([[#41498](https://github.com/kubernetes/kubernetes/pull/41498)](https://github.com/kubernetes/kubernetes/pull/41498), [[@mikebryant](https://github.com/mikebryant)](https://github.com/mikebryant)) + * Openstack cinder v1/v2/auto API support ([#40423](https://github.com/kubernetes/kubernetes/pull/40423), [@mkutsevol](https://github.com/mkutsevol)](https://github.com/kubernetes/kubernetes/pull/41498), [@mikebryant](https://github.com/mikebryant)) - * Alpha feature: allows users to set storage limit to isolate EmptyDir volumes. It enforces the limit by evicting pods that exceed their storage limits ([[#45686](https://github.com/kubernetes/kubernetes/pull/45686)](https://github.com/kubernetes/kubernetes/pull/45686), [[@jingxu97](https://github.com/jingxu97)](https://github.com/jingxu97)) + * Alpha feature: allows users to set storage limit to isolate EmptyDir volumes. It enforces the limit by evicting pods that exceed their storage limits ([#45686](https://github.com/kubernetes/kubernetes/pull/45686), [@jingxu97](https://github.com/jingxu97)) * Bug fixes - * Fixes issue with Flexvolume, introduced in 1.6.0, where drivers without an attacher would fail (node indefinitely waiting for attach). A driver API addition is introduced: drivers that don't implement attach should return attach: false on init. ([[#47503](https://github.com/kubernetes/kubernetes/pull/47503)](https://github.com/kubernetes/kubernetes/pull/47503), [[@chakri-nelluri](https://github.com/chakri-nelluri)](https://github.com/chakri-nelluri)) + * Fixes issue with Flexvolume, introduced in 1.6.0, where drivers without an attacher would fail (node indefinitely waiting for attach). A driver API addition is introduced: drivers that don't implement attach should return attach: false on init. ([#47503](https://github.com/kubernetes/kubernetes/pull/47503), [@chakri-nelluri](https://github.com/chakri-nelluri)) - * Fix dynamic provisioning of PVs with inaccurate AccessModes by refusing to provision when PVCs ask for AccessModes that can't be satisfied by the PVs' underlying volume plugin. ([[#47274](https://github.com/kubernetes/kubernetes/pull/47274)](https://github.com/kubernetes/kubernetes/pull/47274), [[@wongma7](https://github.com/wongma7)](https://github.com/wongma7)) + * Fix dynamic provisioning of PVs with inaccurate AccessModes by refusing to provision when PVCs ask for AccessModes that can't be satisfied by the PVs' underlying volume plugin. ([#47274](https://github.com/kubernetes/kubernetes/pull/47274), [@wongma7](https://github.com/wongma7)) - * Fix pods failing to start if they specify a file as a volume subPath to mount. ([[#45623](https://github.com/kubernetes/kubernetes/pull/45623)](https://github.com/kubernetes/kubernetes/pull/45623), [[@wongma7](https://github.com/wongma7)](https://github.com/wongma7)) + * Fix pods failing to start if they specify a file as a volume subPath to mount. ([#45623](https://github.com/kubernetes/kubernetes/pull/45623), [@wongma7](https://github.com/wongma7)) - * Fix erroneous FailedSync and FailedMount events being periodically and indefinitely posted on Pods after kubelet is restarted. ([[#44781](https://github.com/kubernetes/kubernetes/pull/44781)](https://github.com/kubernetes/kubernetes/pull/44781), [[@wongma7](https://github.com/wongma7)](https://github.com/wongma7)) + * Fix erroneous FailedSync and FailedMount events being periodically and indefinitely posted on Pods after kubelet is restarted. ([#44781](https://github.com/kubernetes/kubernetes/pull/44781), [@wongma7](https://github.com/wongma7)) - * Fix AWS EBS volumes not getting detached from node if routine to verify volumes are attached runs while the node is down ([[#46463](https://github.com/kubernetes/kubernetes/pull/46463)](https://github.com/kubernetes/kubernetes/pull/46463), [[@wongma7](https://github.com/wongma7)](https://github.com/wongma7)) + * Fix AWS EBS volumes not getting detached from node if routine to verify volumes are attached runs while the node is down ([#46463](https://github.com/kubernetes/kubernetes/pull/46463), [@wongma7](https://github.com/wongma7)) - * Improves performance of Cinder volume attach/detach operations. ([[#41785](https://github.com/kubernetes/kubernetes/pull/41785)](https://github.com/kubernetes/kubernetes/pull/41785), [[@jamiehannaford](https://github.com/jamiehannaford)](https://github.com/jamiehannaford)) + * Improves performance of Cinder volume attach/detach operations. ([#41785](https://github.com/kubernetes/kubernetes/pull/41785), [@jamiehannaford](https://github.com/jamiehannaford)) - * Fix iSCSI iSER mounting. ([[#47281](https://github.com/kubernetes/kubernetes/pull/47281)](https://github.com/kubernetes/kubernetes/pull/47281), [[@mtanino](https://github.com/mtanino)](https://github.com/mtanino)) + * Fix iSCSI iSER mounting. ([#47281](https://github.com/kubernetes/kubernetes/pull/47281), [@mtanino](https://github.com/mtanino)) - * iscsi storage plugin: Fix dangling session when using multiple target portal addresses. ([[#46239](https://github.com/kubernetes/kubernetes/pull/46239)](https://github.com/kubernetes/kubernetes/pull/46239), [[@mtanino](https://github.com/mtanino)](https://github.com/mtanino)) + * iscsi storage plugin: Fix dangling session when using multiple target portal addresses. ([#46239](https://github.com/kubernetes/kubernetes/pull/46239), [@mtanino](https://github.com/mtanino)) - * Fix log spam due to unnecessary status update when node is deleted. ([[#45923](https://github.com/kubernetes/kubernetes/pull/45923)](https://github.com/kubernetes/kubernetes/pull/45923), [[@verult](https://github.com/verult)](https://github.com/verult)) + * Fix log spam due to unnecessary status update when node is deleted. ([#45923](https://github.com/kubernetes/kubernetes/pull/45923), [@verult](https://github.com/verult)) - * Don't try to attach volume to new node if it is already attached to another node and the volume does not support multi-attach. ([[#45346](https://github.com/kubernetes/kubernetes/pull/45346)](https://github.com/kubernetes/kubernetes/pull/45346), [[@codablock](https://github.com/codablock)](https://github.com/codablock)) + * Don't try to attach volume to new node if it is already attached to another node and the volume does not support multi-attach. ([#45346](https://github.com/kubernetes/kubernetes/pull/45346), [@codablock](https://github.com/codablock)) - * detach the volume when pod is terminated ([[#45286](https://github.com/kubernetes/kubernetes/pull/45286)](https://github.com/kubernetes/kubernetes/pull/45286), [[@gnufied](https://github.com/gnufied)](https://github.com/gnufied)) + * detach the volume when pod is terminated ([#45286](https://github.com/kubernetes/kubernetes/pull/45286), [@gnufied](https://github.com/gnufied)) - * Roll up volume error messages in the kubelet sync loop. ([[#44938](https://github.com/kubernetes/kubernetes/pull/44938)](https://github.com/kubernetes/kubernetes/pull/44938), [[@jayunit100](https://github.com/jayunit100)](https://github.com/jayunit100)) + * Roll up volume error messages in the kubelet sync loop. ([#44938](https://github.com/kubernetes/kubernetes/pull/44938), [@jayunit100](https://github.com/jayunit100)) - * Catch error when failed to make directory in NFS volume plugin ([[#38801](https://github.com/kubernetes/kubernetes/pull/38801)](https://github.com/kubernetes/kubernetes/pull/38801), [[@nak3](https://github.com/nak3)](https://github.com/nak3)) + * Catch error when failed to make directory in NFS volume plugin ([#38801](https://github.com/kubernetes/kubernetes/pull/38801), [@nak3](https://github.com/nak3)) @@ -1600,7 +1600,7 @@ Features for this release were tracked via the use of the [kubernetes/features]( * DNS and name resolution - * Updates kube-dns to 1.14.2 ([[#45684](https://github.com/kubernetes/kubernetes/pull/45684)](https://github.com/kubernetes/kubernetes/pull/45684), [[@bowei](https://github.com/bowei)](https://github.com/bowei)) + * Updates kube-dns to 1.14.2 ([#45684](https://github.com/kubernetes/kubernetes/pull/45684), [@bowei](https://github.com/bowei)) * Support kube-master-url flag without kubeconfig @@ -1610,70 +1610,70 @@ Features for this release were tracked via the use of the [kubernetes/features]( * Support specifying port number for nameserver in stubDomains - * A new field hostAliases has been added to pod.spec to support adding entries to a Pod's /etc/hosts file. ([[#44641](https://github.com/kubernetes/kubernetes/pull/44641)](https://github.com/kubernetes/kubernetes/pull/44641), [[@rickypai](https://github.com/rickypai)](https://github.com/rickypai)) + * A new field hostAliases has been added to pod.spec to support adding entries to a Pod's /etc/hosts file. ([#44641](https://github.com/kubernetes/kubernetes/pull/44641), [@rickypai](https://github.com/rickypai)) - * Fix DNS suffix search list support in Windows kube-proxy. ([[#45642](https://github.com/kubernetes/kubernetes/pull/45642)](https://github.com/kubernetes/kubernetes/pull/45642), [[@JiangtianLi](https://github.com/JiangtianLi)](https://github.com/JiangtianLi)) + * Fix DNS suffix search list support in Windows kube-proxy. ([#45642](https://github.com/kubernetes/kubernetes/pull/45642), [@JiangtianLi](https://github.com/JiangtianLi)) * Kube-proxy - * ratelimit runs of iptables by sync-period flags ([[#46266](https://github.com/kubernetes/kubernetes/pull/46266)](https://github.com/kubernetes/kubernetes/pull/46266), [[@thockin](https://github.com/thockin)](https://github.com/thockin)) + * ratelimit runs of iptables by sync-period flags ([#46266](https://github.com/kubernetes/kubernetes/pull/46266), [@thockin](https://github.com/thockin)) - * Fix corner-case with OnlyLocal Service healthchecks. ([[#44313](https://github.com/kubernetes/kubernetes/pull/44313)](https://github.com/kubernetes/kubernetes/pull/44313), [[@thockin](https://github.com/thockin)](https://github.com/thockin)) + * Fix corner-case with OnlyLocal Service healthchecks. ([#44313](https://github.com/kubernetes/kubernetes/pull/44313), [@thockin](https://github.com/thockin)) -* Exclude nodes labeled as master from LoadBalancer / NodePort; restores documented behaviour. ([[#44745](https://github.com/kubernetes/kubernetes/pull/44745)](https://github.com/kubernetes/kubernetes/pull/44745), [[@justinsb](https://github.com/justinsb)](https://github.com/justinsb)) +* Exclude nodes labeled as master from LoadBalancer / NodePort; restores documented behaviour. ([#44745](https://github.com/kubernetes/kubernetes/pull/44745), [@justinsb](https://github.com/justinsb)) -* Adds support for CNI ConfigLists, which permit plugin chaining. ([[#42202](https://github.com/kubernetes/kubernetes/pull/42202)](https://github.com/kubernetes/kubernetes/pull/42202), [[@squeed](https://github.com/squeed)](https://github.com/squeed)) +* Adds support for CNI ConfigLists, which permit plugin chaining. ([#42202](https://github.com/kubernetes/kubernetes/pull/42202), [@squeed](https://github.com/squeed)) -* Fix node selection logic on initial LB creation ([[#45773](https://github.com/kubernetes/kubernetes/pull/45773)](https://github.com/kubernetes/kubernetes/pull/45773), [[@justinsb](https://github.com/justinsb)](https://github.com/justinsb)) +* Fix node selection logic on initial LB creation ([#45773](https://github.com/kubernetes/kubernetes/pull/45773), [@justinsb](https://github.com/justinsb)) -* When switching from the service.beta.kubernetes.io/external-traffic annotation to the new externalTrafficPolicy field, the values change as follows: * "OnlyLocal" becomes "Local" * "Global" becomes "Cluster". ([[#46716](https://github.com/kubernetes/kubernetes/pull/46716)](https://github.com/kubernetes/kubernetes/pull/46716), [[@thockin](https://github.com/thockin)](https://github.com/thockin)) +* When switching from the service.beta.kubernetes.io/external-traffic annotation to the new externalTrafficPolicy field, the values change as follows: * "OnlyLocal" becomes "Local" * "Global" becomes "Cluster". ([#46716](https://github.com/kubernetes/kubernetes/pull/46716), [@thockin](https://github.com/thockin)) -* servicecontroller: Fix node selection logic on initial LB creation ([[#45773](https://github.com/kubernetes/kubernetes/pull/45773)](https://github.com/kubernetes/kubernetes/pull/45773), [[@justinsb](https://github.com/justinsb)](https://github.com/justinsb)) +* servicecontroller: Fix node selection logic on initial LB creation ([#45773](https://github.com/kubernetes/kubernetes/pull/45773), [@justinsb](https://github.com/justinsb)) -* fixed HostAlias in PodSpec to allow foo.bar hostnames instead of just foo DNS labels. ([[#46809](https://github.com/kubernetes/kubernetes/pull/46809)](https://github.com/kubernetes/kubernetes/pull/46809), [[@rickypai](https://github.com/rickypai)](https://github.com/rickypai)) +* fixed HostAlias in PodSpec to allow foo.bar hostnames instead of just foo DNS labels. ([#46809](https://github.com/kubernetes/kubernetes/pull/46809), [@rickypai](https://github.com/rickypai)) #### Node controller * Bug fixes: - * Fix [transition between NotReady and Unreachable taints](https://github.com/kubernetes/kubernetes/issues/43444). ([[#44042](https://github.com/kubernetes/kubernetes/pull/44042)](https://github.com/kubernetes/kubernetes/pull/44042), [[@gmarek](https://github.com/gmarek)](https://github.com/gmarek)) + * Fix [transition between NotReady and Unreachable taints](https://github.com/kubernetes/kubernetes/issues/43444). ([#44042](https://github.com/kubernetes/kubernetes/pull/44042), [@gmarek](https://github.com/gmarek)) #### Node Components * Features - * Removes the deprecated kubelet flag `--babysit-daemons` ([[#44230](https://github.com/kubernetes/kubernetes/pull/44230)](https://github.com/kubernetes/kubernetes/pull/44230), [[@mtaufen](https://github.com/mtaufen)](https://github.com/mtaufen)) + * Removes the deprecated kubelet flag `--babysit-daemons` ([#44230](https://github.com/kubernetes/kubernetes/pull/44230), [@mtaufen](https://github.com/mtaufen)) - * make dockershim.sock configurable ([[#43914](https://github.com/kubernetes/kubernetes/pull/43914)](https://github.com/kubernetes/kubernetes/pull/43914), [[@ncdc](https://github.com/ncdc)](https://github.com/ncdc)) + * make dockershim.sock configurable ([#43914](https://github.com/kubernetes/kubernetes/pull/43914), [@ncdc](https://github.com/ncdc)) - * Support running Ubuntu image on GCE node ([[#44744](https://github.com/kubernetes/kubernetes/pull/44744)](https://github.com/kubernetes/kubernetes/pull/44744), [[@yguo0905](https://github.com/yguo0905)](https://github.com/yguo0905)) + * Support running Ubuntu image on GCE node ([#44744](https://github.com/kubernetes/kubernetes/pull/44744), [@yguo0905](https://github.com/yguo0905)) - * Kubernetes now shares a single PID namespace among all containers in a pod when running with docker >= 1.13.1. This means processes can now signal processes in other containers in a pod, but it also means that the `kubectl exec {pod} kill 1` pattern will cause the Pod to be restarted rather than a single container. ([[#45236](https://github.com/kubernetes/kubernetes/pull/45236)](https://github.com/kubernetes/kubernetes/pull/45236), [[@verb](https://github.com/verb)](https://github.com/verb)) + * Kubernetes now shares a single PID namespace among all containers in a pod when running with docker >= 1.13.1. This means processes can now signal processes in other containers in a pod, but it also means that the `kubectl exec {pod} kill 1` pattern will cause the Pod to be restarted rather than a single container. ([#45236](https://github.com/kubernetes/kubernetes/pull/45236), [@verb](https://github.com/verb)) - * A new field hostAliases has been added to the pod spec to support [adding entries to a Pod's /etc/hosts file](https://kubernetes.io/docs/concepts/services-networking/add-entries-to-pod-etc-hosts-with-host-aliases/). ([[#44641](https://github.com/kubernetes/kubernetes/pull/44641)](https://github.com/kubernetes/kubernetes/pull/44641), [[@rickypai](https://github.com/rickypai)](https://github.com/rickypai)) + * A new field hostAliases has been added to the pod spec to support [adding entries to a Pod's /etc/hosts file](https://kubernetes.io/docs/concepts/services-networking/add-entries-to-pod-etc-hosts-with-host-aliases/). ([#44641](https://github.com/kubernetes/kubernetes/pull/44641), [@rickypai](https://github.com/rickypai)) - * With `--feature-gates=RotateKubeletClientCertificate=true` set, the Kubelet will ([[#41912](https://github.com/kubernetes/kubernetes/pull/41912)](https://github.com/kubernetes/kubernetes/pull/41912), [[@jcbsmpsn](https://github.com/jcbsmpsn)](https://github.com/jcbsmpsn)) + * With `--feature-gates=RotateKubeletClientCertificate=true` set, the Kubelet will ([#41912](https://github.com/kubernetes/kubernetes/pull/41912), [@jcbsmpsn](https://github.com/jcbsmpsn)) * request a client certificate from the API server during the boot cycle and pause * waiting for the request to be satisfied. It will continually refresh the certificate - * Create clusters with GPUs in GCE by specifying `type=,count=` to NODE_ACCELERATORS environment variable. ([[#45130](https://github.com/kubernetes/kubernetes/pull/45130)](https://github.com/kubernetes/kubernetes/pull/45130), [[@vishh](https://github.com/vishh)](https://github.com/vishh)) + * Create clusters with GPUs in GCE by specifying `type=,count=` to NODE_ACCELERATORS environment variable. ([#45130](https://github.com/kubernetes/kubernetes/pull/45130), [@vishh](https://github.com/vishh)) * List of available GPUs - [https://cloud.google.com/compute/docs/gpus/#introduction](https://cloud.google.com/compute/docs/gpus/#introduction) - * Disk Pressure triggers the deletion of terminated containers on the node. ([[#45896](https://github.com/kubernetes/kubernetes/pull/45896)](https://github.com/kubernetes/kubernetes/pull/45896), [[@dashpole](https://github.com/dashpole)](https://github.com/dashpole)) + * Disk Pressure triggers the deletion of terminated containers on the node. ([#45896](https://github.com/kubernetes/kubernetes/pull/45896), [@dashpole](https://github.com/dashpole)) - * Support status.hostIP in downward API ([[#42717](https://github.com/kubernetes/kubernetes/pull/42717)](https://github.com/kubernetes/kubernetes/pull/42717), [[@andrewsykim](https://github.com/andrewsykim)](https://github.com/andrewsykim)) + * Support status.hostIP in downward API ([#42717](https://github.com/kubernetes/kubernetes/pull/42717), [@andrewsykim](https://github.com/andrewsykim)) * Upgrade Node Problem Detector to v0.4.1. New features added: - * Add /dev/kmsg support for kernel log parsing. ([#112](https://github.com/kubernetes/node-problem-detector/pull/112), [[@euank](https://github.com/euank)](https://github.com/euank)) + * Add /dev/kmsg support for kernel log parsing. ([#112](https://github.com/kubernetes/node-problem-detector/pull/112), [@euank](https://github.com/euank)) - * Add ABRT support. ([#105](https://github.com/kubernetes/node-problem-detector/pull/105), [[@juliusmilan](https://github.com/juliusmilan)](https://github.com/juliusmilan)) + * Add ABRT support. ([#105](https://github.com/kubernetes/node-problem-detector/pull/105), [@juliusmilan](https://github.com/juliusmilan)) - * Add a docker image corruption problem detection in the default docker monitor config. ([#117](https://github.com/kubernetes/node-problem-detector/pull/117), [[@ajitak](https://github.com/ajitak)](https://github.com/ajitak)) + * Add a docker image corruption problem detection in the default docker monitor config. ([#117](https://github.com/kubernetes/node-problem-detector/pull/117), [@ajitak](https://github.com/ajitak)) * Upgrade CAdvisor to v0.26.1. New features added: @@ -1683,120 +1683,120 @@ Features for this release were tracked via the use of the [kubernetes/features]( * Add UDP metrics (collection disabled by default). - * Roll up volume error messages in the kubelet sync loop. ([[#44938](https://github.com/kubernetes/kubernetes/pull/44938)](https://github.com/kubernetes/kubernetes/pull/44938), [[@jayunit100](https://github.com/jayunit100)](https://github.com/jayunit100)) + * Roll up volume error messages in the kubelet sync loop. ([#44938](https://github.com/kubernetes/kubernetes/pull/44938), [@jayunit100](https://github.com/jayunit100)) - * Allow pods to opt out of PodPreset mutation via an annotation on the pod. ([[#44965](https://github.com/kubernetes/kubernetes/pull/44965)](https://github.com/kubernetes/kubernetes/pull/44965), [[@jpeeler](https://github.com/jpeeler)](https://github.com/jpeeler)) + * Allow pods to opt out of PodPreset mutation via an annotation on the pod. ([#44965](https://github.com/kubernetes/kubernetes/pull/44965), [@jpeeler](https://github.com/jpeeler)) - * Add generic Toleration for NoExecute Taints to NodeProblemDetector, so that NPD can be scheduled to nodes with NoExecute taints by default. ([[#45883](https://github.com/kubernetes/kubernetes/pull/45883)](https://github.com/kubernetes/kubernetes/pull/45883), [[@gmarek](https://github.com/gmarek)](https://github.com/gmarek)) + * Add generic Toleration for NoExecute Taints to NodeProblemDetector, so that NPD can be scheduled to nodes with NoExecute taints by default. ([#45883](https://github.com/kubernetes/kubernetes/pull/45883), [@gmarek](https://github.com/gmarek)) - * Prevent kubelet from setting allocatable < 0 for a resource upon initial creation. ([[#46516](https://github.com/kubernetes/kubernetes/pull/46516)](https://github.com/kubernetes/kubernetes/pull/46516), [[@derekwaynecarr](https://github.com/derekwaynecarr)](https://github.com/derekwaynecarr)) + * Prevent kubelet from setting allocatable < 0 for a resource upon initial creation. ([#46516](https://github.com/kubernetes/kubernetes/pull/46516), [@derekwaynecarr](https://github.com/derekwaynecarr)) * Bug fixes - * Changed Kubelet default image-gc-high-threshold to 85% to resolve a conflict with default settings in docker that prevented image garbage collection from resolving low disk space situations when using devicemapper storage. ([[#40432](https://github.com/kubernetes/kubernetes/pull/40432)](https://github.com/kubernetes/kubernetes/pull/40432), [[@sjenning](https://github.com/sjenning)](https://github.com/sjenning)) + * Changed Kubelet default image-gc-high-threshold to 85% to resolve a conflict with default settings in docker that prevented image garbage collection from resolving low disk space situations when using devicemapper storage. ([#40432](https://github.com/kubernetes/kubernetes/pull/40432), [@sjenning](https://github.com/sjenning)) - * Mark all static pods on the Master node as critical to prevent preemption ([[#47356](https://github.com/kubernetes/kubernetes/pull/47356)](https://github.com/kubernetes/kubernetes/pull/47356), [[@dashpole](https://github.com/dashpole)](https://github.com/dashpole)) + * Mark all static pods on the Master node as critical to prevent preemption ([#47356](https://github.com/kubernetes/kubernetes/pull/47356), [@dashpole](https://github.com/dashpole)) - * Restrict active deadline seconds max allowed value to be maximum uint32 to avoid overflow ([[#46640](https://github.com/kubernetes/kubernetes/pull/46640)](https://github.com/kubernetes/kubernetes/pull/46640), [[@derekwaynecarr](https://github.com/derekwaynecarr)](https://github.com/derekwaynecarr)) + * Restrict active deadline seconds max allowed value to be maximum uint32 to avoid overflow ([#46640](https://github.com/kubernetes/kubernetes/pull/46640), [@derekwaynecarr](https://github.com/derekwaynecarr)) - * Fix a bug with cAdvisorPort in the KubeletConfiguration that prevented setting it to 0, which is in fact a valid option, as noted in issue [[#11710](https://github.com/kubernetes/kubernetes/pull/11710)](https://github.com/kubernetes/kubernetes/pull/11710). ([[#46876](https://github.com/kubernetes/kubernetes/pull/46876)](https://github.com/kubernetes/kubernetes/pull/46876), [[@mtaufen](https://github.com/mtaufen)](https://github.com/mtaufen)) + * Fix a bug with cAdvisorPort in the KubeletConfiguration that prevented setting it to 0, which is in fact a valid option, as noted in issue [#11710](https://github.com/kubernetes/kubernetes/pull/11710). ([#46876](https://github.com/kubernetes/kubernetes/pull/46876), [@mtaufen](https://github.com/mtaufen)) - * Fix a bug where container cannot run as root when SecurityContext.RunAsNonRoot is false. ([[#47009](https://github.com/kubernetes/kubernetes/pull/47009)](https://github.com/kubernetes/kubernetes/pull/47009), [[@yujuhong](https://github.com/yujuhong)](https://github.com/yujuhong)) + * Fix a bug where container cannot run as root when SecurityContext.RunAsNonRoot is false. ([#47009](https://github.com/kubernetes/kubernetes/pull/47009), [@yujuhong](https://github.com/yujuhong)) - * Fix the Kubelet PLEG update timestamp to better reflect the health of the component when the container runtime request hangs. ([[#45496](https://github.com/kubernetes/kubernetes/pull/45496)](https://github.com/kubernetes/kubernetes/pull/45496), [[@andyxning](https://github.com/andyxning)](https://github.com/andyxning)) + * Fix the Kubelet PLEG update timestamp to better reflect the health of the component when the container runtime request hangs. ([#45496](https://github.com/kubernetes/kubernetes/pull/45496), [@andyxning](https://github.com/andyxning)) - * Avoid failing sync loop health check on container runtime errors ([[#47124](https://github.com/kubernetes/kubernetes/pull/47124)](https://github.com/kubernetes/kubernetes/pull/47124), [[@andyxning](https://github.com/andyxning)](https://github.com/andyxning)) + * Avoid failing sync loop health check on container runtime errors ([#47124](https://github.com/kubernetes/kubernetes/pull/47124), [@andyxning](https://github.com/andyxning)) - * Fix a bug where Kubelet does not ignore pod manifest files starting with dots ([[#45111](https://github.com/kubernetes/kubernetes/pull/45111)](https://github.com/kubernetes/kubernetes/pull/45111), [[@dwradcliffe](https://github.com/dwradcliffe)](https://github.com/dwradcliffe)) + * Fix a bug where Kubelet does not ignore pod manifest files starting with dots ([#45111](https://github.com/kubernetes/kubernetes/pull/45111), [@dwradcliffe](https://github.com/dwradcliffe)) - * Fix kubelet reset liveness probe failure count across pod restart boundaries ([[#46371](https://github.com/kubernetes/kubernetes/pull/46371)](https://github.com/kubernetes/kubernetes/pull/46371), [[@sjenning](https://github.com/sjenning)](https://github.com/sjenning)) + * Fix kubelet reset liveness probe failure count across pod restart boundaries ([#46371](https://github.com/kubernetes/kubernetes/pull/46371), [@sjenning](https://github.com/sjenning)) - * Fix log spam due to unnecessary status update when node is deleted. ([[#45923](https://github.com/kubernetes/kubernetes/pull/45923)](https://github.com/kubernetes/kubernetes/pull/45923), [[@verult](https://github.com/verult)](https://github.com/verult)) + * Fix log spam due to unnecessary status update when node is deleted. ([#45923](https://github.com/kubernetes/kubernetes/pull/45923), [@verult](https://github.com/verult)) - * Fix kubelet event recording for selected events. ([[#46246](https://github.com/kubernetes/kubernetes/pull/46246)](https://github.com/kubernetes/kubernetes/pull/46246), [[@derekwaynecarr](https://github.com/derekwaynecarr)](https://github.com/derekwaynecarr)) + * Fix kubelet event recording for selected events. ([#46246](https://github.com/kubernetes/kubernetes/pull/46246), [@derekwaynecarr](https://github.com/derekwaynecarr)) - * Fix image garbage collector attempting to remove in-use images. ([[#46121](https://github.com/kubernetes/kubernetes/pull/46121)](https://github.com/kubernetes/kubernetes/pull/46121), [[@Random-Liu](https://github.com/Random-Liu)](https://github.com/Random-Liu)) + * Fix image garbage collector attempting to remove in-use images. ([#46121](https://github.com/kubernetes/kubernetes/pull/46121), [@Random-Liu](https://github.com/Random-Liu)) - * Detach the volume when pod is terminated ([[#45286](https://github.com/kubernetes/kubernetes/pull/45286)](https://github.com/kubernetes/kubernetes/pull/45286), [[@gnufied](https://github.com/gnufied)](https://github.com/gnufied)) + * Detach the volume when pod is terminated ([#45286](https://github.com/kubernetes/kubernetes/pull/45286), [@gnufied](https://github.com/gnufied)) - * CRI: Fix StopContainer timeout ([[#44970](https://github.com/kubernetes/kubernetes/pull/44970)](https://github.com/kubernetes/kubernetes/pull/44970), [[@Random-Liu](https://github.com/Random-Liu)](https://github.com/Random-Liu)) + * CRI: Fix StopContainer timeout ([#44970](https://github.com/kubernetes/kubernetes/pull/44970), [@Random-Liu](https://github.com/Random-Liu)) - * CRI: Fix kubelet failing to start when using rkt. ([[#44569](https://github.com/kubernetes/kubernetes/pull/44569)](https://github.com/kubernetes/kubernetes/pull/44569), [[@yujuhong](https://github.com/yujuhong)](https://github.com/yujuhong)) + * CRI: Fix kubelet failing to start when using rkt. ([#44569](https://github.com/kubernetes/kubernetes/pull/44569), [@yujuhong](https://github.com/yujuhong)) - * CRI: `kubectl logs -f` now stops following when container stops, as it did pre-CRI. ([[#44406](https://github.com/kubernetes/kubernetes/pull/44406)](https://github.com/kubernetes/kubernetes/pull/44406), [[@Random-Liu](https://github.com/Random-Liu)](https://github.com/Random-Liu)) + * CRI: `kubectl logs -f` now stops following when container stops, as it did pre-CRI. ([#44406](https://github.com/kubernetes/kubernetes/pull/44406), [@Random-Liu](https://github.com/Random-Liu)) - * Fixes a bug where pods were evicted even after images are successfully deleted. ([[#44986](https://github.com/kubernetes/kubernetes/pull/44986)](https://github.com/kubernetes/kubernetes/pull/44986), [[@dashpole](https://github.com/dashpole)](https://github.com/dashpole)) + * Fixes a bug where pods were evicted even after images are successfully deleted. ([#44986](https://github.com/kubernetes/kubernetes/pull/44986), [@dashpole](https://github.com/dashpole)) - * When creating a container using envFrom, ([[#42083](https://github.com/kubernetes/kubernetes/pull/42083)](https://github.com/kubernetes/kubernetes/pull/42083), [[@fraenkel](https://github.com/fraenkel)](https://github.com/fraenkel) + * When creating a container using envFrom, ([#42083](https://github.com/kubernetes/kubernetes/pull/42083), [@fraenkel](https://github.com/fraenkel) * validate the name of the ConfigMap in a ConfigMapRef * validate the name of the Secret in a SecretRef - * Fix the bug where StartedAt time is not reported for exited containers. ([[#45977](https://github.com/kubernetes/kubernetes/pull/45977)](https://github.com/kubernetes/kubernetes/pull/45977), [[@yujuhong](https://github.com/yujuhong)](https://github.com/yujuhong)) + * Fix the bug where StartedAt time is not reported for exited containers. ([#45977](https://github.com/kubernetes/kubernetes/pull/45977), [@yujuhong](https://github.com/yujuhong)) * Changes/deprecations - * Marks the Kubelet's `--master-service-namespace` flag deprecated ([[#44250](https://github.com/kubernetes/kubernetes/pull/44250)](https://github.com/kubernetes/kubernetes/pull/44250), [[@mtaufen](https://github.com/mtaufen)](https://github.com/mtaufen)) + * Marks the Kubelet's `--master-service-namespace` flag deprecated ([#44250](https://github.com/kubernetes/kubernetes/pull/44250), [@mtaufen](https://github.com/mtaufen)) - * Remove PodSandboxStatus.Linux.Namespaces.Network from CRI since it is not used/needed. ([[#45166](https://github.com/kubernetes/kubernetes/pull/45166)](https://github.com/kubernetes/kubernetes/pull/45166), [[@feiskyer](https://github.com/feiskyer)](https://github.com/feiskyer)) + * Remove PodSandboxStatus.Linux.Namespaces.Network from CRI since it is not used/needed. ([#45166](https://github.com/kubernetes/kubernetes/pull/45166), [@feiskyer](https://github.com/feiskyer)) - * Remove the `--enable-cri` flag. CRI is now the default, and the only way to integrate with Kubelet for the container runtimes.([[#45194](https://github.com/kubernetes/kubernetes/pull/45194)](https://github.com/kubernetes/kubernetes/pull/45194), [[@yujuhong](https://github.com/yujuhong)](https://github.com/yujuhong)) + * Remove the `--enable-cri` flag. CRI is now the default, and the only way to integrate with Kubelet for the container runtimes.([#45194](https://github.com/kubernetes/kubernetes/pull/45194), [@yujuhong](https://github.com/yujuhong)) - * CRI has been moved to package pkg/kubelet/apis/cri/v1alpha1/runtime as part of Kubelet API path cleanup. ([[#47113](https://github.com/kubernetes/kubernetes/pull/47113)](https://github.com/kubernetes/kubernetes/pull/47113), [[@feiskyer](https://github.com/feiskyer)](https://github.com/feiskyer)) + * CRI has been moved to package pkg/kubelet/apis/cri/v1alpha1/runtime as part of Kubelet API path cleanup. ([#47113](https://github.com/kubernetes/kubernetes/pull/47113), [@feiskyer](https://github.com/feiskyer)) #### Scheduling -* The fix makes scheduling go routine waiting for cache (e.g. Pod) to be synced. ([[#45453](https://github.com/kubernetes/kubernetes/pull/45453)](https://github.com/kubernetes/kubernetes/pull/45453), [[@k82cn](https://github.com/k82cn)](https://github.com/k82cn)) +* The fix makes scheduling go routine waiting for cache (e.g. Pod) to be synced. ([#45453](https://github.com/kubernetes/kubernetes/pull/45453), [@k82cn](https://github.com/k82cn)) -* Move hardPodAffinitySymmetricWeight to scheduler policy config ([[#44159](https://github.com/kubernetes/kubernetes/pull/44159)](https://github.com/kubernetes/kubernetes/pull/44159), [[@wanghaoran1988](https://github.com/wanghaoran1988)](https://github.com/wanghaoran1988)) +* Move hardPodAffinitySymmetricWeight to scheduler policy config ([#44159](https://github.com/kubernetes/kubernetes/pull/44159), [@wanghaoran1988](https://github.com/wanghaoran1988)) -* Align Extender's validation with prioritizers. ([[#45091](https://github.com/kubernetes/kubernetes/pull/45091)](https://github.com/kubernetes/kubernetes/pull/45091), [[@k82cn](https://github.com/k82cn)](https://github.com/k82cn)) +* Align Extender's validation with prioritizers. ([#45091](https://github.com/kubernetes/kubernetes/pull/45091), [@k82cn](https://github.com/k82cn)) -* Removed old scheduler constructor. ([[#45472](https://github.com/kubernetes/kubernetes/pull/45472)](https://github.com/kubernetes/kubernetes/pull/45472), [[@k82cn](https://github.com/k82cn)](https://github.com/k82cn)) +* Removed old scheduler constructor. ([#45472](https://github.com/kubernetes/kubernetes/pull/45472), [@k82cn](https://github.com/k82cn)) -* Fixes the overflow for priorityconfig- valid range {1, 9223372036854775806}. ([[#45122](https://github.com/kubernetes/kubernetes/pull/45122)](https://github.com/kubernetes/kubernetes/pull/45122), [[@ravisantoshgudimetla](https://github.com/ravisantoshgudimetla)](https://github.com/ravisantoshgudimetla)) +* Fixes the overflow for priorityconfig- valid range {1, 9223372036854775806}. ([#45122](https://github.com/kubernetes/kubernetes/pull/45122), [@ravisantoshgudimetla](https://github.com/ravisantoshgudimetla)) -* Move hardPodAffinitySymmetricWeight to scheduler policy config ([[#44159](https://github.com/kubernetes/kubernetes/pull/44159)](https://github.com/kubernetes/kubernetes/pull/44159), [[@wanghaoran1988](https://github.com/wanghaoran1988)](https://github.com/wanghaoran1988)) +* Move hardPodAffinitySymmetricWeight to scheduler policy config ([#44159](https://github.com/kubernetes/kubernetes/pull/44159), [@wanghaoran1988](https://github.com/wanghaoran1988)) #### Security * Features: - * Permission to use a PodSecurityPolicy can now be granted within a single namespace by allowing the use verb on the podsecuritypolicies resource within the namespace. ([[#42360](https://github.com/kubernetes/kubernetes/pull/42360)](https://github.com/kubernetes/kubernetes/pull/42360), [[@liggitt](https://github.com/liggitt)](https://github.com/liggitt)) + * Permission to use a PodSecurityPolicy can now be granted within a single namespace by allowing the use verb on the podsecuritypolicies resource within the namespace. ([#42360](https://github.com/kubernetes/kubernetes/pull/42360), [@liggitt](https://github.com/liggitt)) - * Break the 'certificatesigningrequests' controller into a 'csrapprover' controller and 'csrsigner' controller. ([[#45514](https://github.com/kubernetes/kubernetes/pull/45514)](https://github.com/kubernetes/kubernetes/pull/45514), [[@mikedanese](https://github.com/mikedanese)](https://github.com/mikedanese)) + * Break the 'certificatesigningrequests' controller into a 'csrapprover' controller and 'csrsigner' controller. ([#45514](https://github.com/kubernetes/kubernetes/pull/45514), [@mikedanese](https://github.com/mikedanese)) - * `kubectl auth can-i` now supports non-resource URLs ([[#46432](https://github.com/kubernetes/kubernetes/pull/46432)](https://github.com/kubernetes/kubernetes/pull/46432), [[@CaoShuFeng](https://github.com/CaoShuFeng)](https://github.com/CaoShuFeng)) + * `kubectl auth can-i` now supports non-resource URLs ([#46432](https://github.com/kubernetes/kubernetes/pull/46432), [@CaoShuFeng](https://github.com/CaoShuFeng)) - * Promote kubelet tls bootstrap to beta. Add a non-experimental flag to use it and deprecate the old flag. ([[#46799](https://github.com/kubernetes/kubernetes/pull/46799)](https://github.com/kubernetes/kubernetes/pull/46799), [[@mikedanese](https://github.com/mikedanese)](https://github.com/mikedanese)) + * Promote kubelet tls bootstrap to beta. Add a non-experimental flag to use it and deprecate the old flag. ([#46799](https://github.com/kubernetes/kubernetes/pull/46799), [@mikedanese](https://github.com/mikedanese)) - * Add the alpha.image-policy.k8s.io/failed-open=true annotation when the image policy webhook encounters an error and fails open. ([[#46264](https://github.com/kubernetes/kubernetes/pull/46264)](https://github.com/kubernetes/kubernetes/pull/46264), [[@Q-Lee](https://github.com/Q-Lee)](https://github.com/Q-Lee)) + * Add the alpha.image-policy.k8s.io/failed-open=true annotation when the image policy webhook encounters an error and fails open. ([#46264](https://github.com/kubernetes/kubernetes/pull/46264), [@Q-Lee](https://github.com/Q-Lee)) - * Add an AEAD encrypting transformer for storing secrets encrypted at rest ([[#41939](https://github.com/kubernetes/kubernetes/pull/41939)](https://github.com/kubernetes/kubernetes/pull/41939), [[@smarterclayton](https://github.com/smarterclayton)](https://github.com/smarterclayton)) + * Add an AEAD encrypting transformer for storing secrets encrypted at rest ([#41939](https://github.com/kubernetes/kubernetes/pull/41939), [@smarterclayton](https://github.com/smarterclayton)) - * Add secretbox and AES-CBC encryption modes to at rest encryption. AES-CBC is considered superior to AES-GCM because it is resistant to nonce-reuse attacks, and secretbox uses Poly1305 and XSalsa20. ([[#46916](https://github.com/kubernetes/kubernetes/pull/46916)](https://github.com/kubernetes/kubernetes/pull/46916), [[@smarterclayton](https://github.com/smarterclayton)](https://github.com/smarterclayton)) + * Add secretbox and AES-CBC encryption modes to at rest encryption. AES-CBC is considered superior to AES-GCM because it is resistant to nonce-reuse attacks, and secretbox uses Poly1305 and XSalsa20. ([#46916](https://github.com/kubernetes/kubernetes/pull/46916), [@smarterclayton](https://github.com/smarterclayton)) * Bug fixes: - * Make gcp auth provider not to override the Auth header if it's already exits ([[#45575](https://github.com/kubernetes/kubernetes/pull/45575)](https://github.com/kubernetes/kubernetes/pull/45575), [[@wanghaoran1988](https://github.com/wanghaoran1988)](https://github.com/wanghaoran1988)) + * Make gcp auth provider not to override the Auth header if it's already exits ([#45575](https://github.com/kubernetes/kubernetes/pull/45575), [@wanghaoran1988](https://github.com/wanghaoran1988)) - * The oidc client plugin has reduce round trips and fix scopes requested ([[#45317](https://github.com/kubernetes/kubernetes/pull/45317)](https://github.com/kubernetes/kubernetes/pull/45317), [[@ericchiang](https://github.com/ericchiang)](https://github.com/ericchiang)) + * The oidc client plugin has reduce round trips and fix scopes requested ([#45317](https://github.com/kubernetes/kubernetes/pull/45317), [@ericchiang](https://github.com/ericchiang)) - * API requests using impersonation now include the system:authenticated group in the impersonated user automatically. ([[#44076](https://github.com/kubernetes/kubernetes/pull/44076)](https://github.com/kubernetes/kubernetes/pull/44076), [[@liggitt](https://github.com/liggitt)](https://github.com/liggitt)) + * API requests using impersonation now include the system:authenticated group in the impersonated user automatically. ([#44076](https://github.com/kubernetes/kubernetes/pull/44076), [@liggitt](https://github.com/liggitt)) - * RBAC role and rolebinding auto-reconciliation is now performed only when the RBAC authorization mode is enabled. ([[#43813](https://github.com/kubernetes/kubernetes/pull/43813)](https://github.com/kubernetes/kubernetes/pull/43813), [[@liggitt](https://github.com/liggitt)](https://github.com/liggitt)) + * RBAC role and rolebinding auto-reconciliation is now performed only when the RBAC authorization mode is enabled. ([#43813](https://github.com/kubernetes/kubernetes/pull/43813), [@liggitt](https://github.com/liggitt)) - * PodSecurityPolicy now recognizes pods that specify runAsNonRoot: false in their security context and does not overwrite the specified value ([[#47073](https://github.com/kubernetes/kubernetes/pull/47073)](https://github.com/kubernetes/kubernetes/pull/47073), [[@Q-Lee](https://github.com/Q-Lee)](https://github.com/Q-Lee)) + * PodSecurityPolicy now recognizes pods that specify runAsNonRoot: false in their security context and does not overwrite the specified value ([#47073](https://github.com/kubernetes/kubernetes/pull/47073), [@Q-Lee](https://github.com/Q-Lee)) - * Tokens retrieved from Google Cloud with application default credentials will not be cached if the client fails authorization ([[#46694](https://github.com/kubernetes/kubernetes/pull/46694)](https://github.com/kubernetes/kubernetes/pull/46694), [[@matt-tyler](https://github.com/matt-tyler)](https://github.com/matt-tyler)) + * Tokens retrieved from Google Cloud with application default credentials will not be cached if the client fails authorization ([#46694](https://github.com/kubernetes/kubernetes/pull/46694), [@matt-tyler](https://github.com/matt-tyler)) - * Update kube-dns, metadata-proxy, and fluentd-gcp, event-exporter, prometheus-to-sd, and ip-masq-agent addons with new base images containing fixes for CVE-2016-4448, CVE-2016-9841, CVE-2016-9843, CVE-2017-1000366, CVE-2017-2616, and CVE-2017-9526. ([[#47877](https://github.com/kubernetes/kubernetes/pull/47877)](https://github.com/kubernetes/kubernetes/pull/47877), [[@ixdy](https://github.com/ixdy)](https://github.com/ixdy)) + * Update kube-dns, metadata-proxy, and fluentd-gcp, event-exporter, prometheus-to-sd, and ip-masq-agent addons with new base images containing fixes for CVE-2016-4448, CVE-2016-9841, CVE-2016-9843, CVE-2017-1000366, CVE-2017-2616, and CVE-2017-9526. ([#47877](https://github.com/kubernetes/kubernetes/pull/47877), [@ixdy](https://github.com/ixdy)) - * Fixed an issue mounting the wrong secret into pods as a service account token. ([[#44102](https://github.com/kubernetes/kubernetes/pull/44102)](https://github.com/kubernetes/kubernetes/pull/44102), [[@ncdc](https://github.com/ncdc)](https://github.com/ncdc)) + * Fixed an issue mounting the wrong secret into pods as a service account token. ([#44102](https://github.com/kubernetes/kubernetes/pull/44102), [@ncdc](https://github.com/ncdc)) #### Scalability -* The HorizontalPodAutoscaler controller will now only send updates when it has new status information, reducing the number of writes caused by the controller. ([[#47078](https://github.com/kubernetes/kubernetes/pull/47078)](https://github.com/kubernetes/kubernetes/pull/47078), [[@DirectXMan12](https://github.com/DirectXMan12)](https://github.com/DirectXMan12)) +* The HorizontalPodAutoscaler controller will now only send updates when it has new status information, reducing the number of writes caused by the controller. ([#47078](https://github.com/kubernetes/kubernetes/pull/47078), [@DirectXMan12](https://github.com/DirectXMan12)) ## **External Dependency Version Information** @@ -1815,11 +1815,11 @@ Continuous integration builds have used the following versions of external depen * Docker version 1.11.2 known issues - * Kernel crash with Aufs storage driver on Debian Jessie ([[#27885](https://github.com/kubernetes/kubernetes/pull/27885)](https://github.com/kubernetes/kubernetes/issues/27885)) which can be identified by the [node problem detector](https://kubernetes.io/docs/tasks/debug-application-cluster/monitor-node-health/) + * Kernel crash with Aufs storage driver on Debian Jessie ([#27885](https://github.com/kubernetes/kubernetes/pull/27885)) which can be identified by the [node problem detector](https://kubernetes.io/docs/tasks/debug-application-cluster/monitor-node-health/) * Leaked File descriptors ([#275](https://github.com/docker/containerd/issues/275)) - * Additional memory overhead per container ([[#21737](https://github.com/kubernetes/kubernetes/pull/21737)](https://github.com/docker/docker/issues/21737)) + * Additional memory overhead per container ([#21737](https://github.com/kubernetes/kubernetes/pull/21737)) * Docker 1.10.3 contains [backports provided by RedHat](https://github.com/docker/docker/compare/v1.10.3...runcom:docker-1.10.3-stable) for known issues @@ -2152,7 +2152,6 @@ filename | sha256 hash * The Prometheus metrics for the kube-apiserver for tracking incoming API requests and latencies now return the `subresource` label for correctly attributing the type of API call. ([#46354](https://github.com/kubernetes/kubernetes/pull/46354), [@smarterclayton](https://github.com/smarterclayton)) * Add Simplified Chinese translation for kubectl ([#45573](https://github.com/kubernetes/kubernetes/pull/45573), [@shiywang](https://github.com/shiywang)) * The --namespace flag is now honored for in-cluster clients that have an empty configuration. ([#46299](https://github.com/kubernetes/kubernetes/pull/46299), [@ncdc](https://github.com/ncdc)) -* NONE ([#45317](https://github.com/kubernetes/kubernetes/pull/45317), [@ericchiang](https://github.com/ericchiang)) * Fix init container status reporting when active deadline is exceeded. ([#46305](https://github.com/kubernetes/kubernetes/pull/46305), [@sjenning](https://github.com/sjenning)) * Improves performance of Cinder volume attach/detach operations ([#41785](https://github.com/kubernetes/kubernetes/pull/41785), [@jamiehannaford](https://github.com/jamiehannaford)) * GCE and AWS dynamic provisioners extension: admins can configure zone(s) in which a persistent volume shall be created. ([#38505](https://github.com/kubernetes/kubernetes/pull/38505), [@pospispa](https://github.com/pospispa)) @@ -2610,7 +2609,6 @@ filename | sha256 hash * The Prometheus metrics for the kube-apiserver for tracking incoming API requests and latencies now return the `subresource` label for correctly attributing the type of API call. ([#46354](https://github.com/kubernetes/kubernetes/pull/46354), [@smarterclayton](https://github.com/smarterclayton)) * Add Simplified Chinese translation for kubectl ([#45573](https://github.com/kubernetes/kubernetes/pull/45573), [@shiywang](https://github.com/shiywang)) * The --namespace flag is now honored for in-cluster clients that have an empty configuration. ([#46299](https://github.com/kubernetes/kubernetes/pull/46299), [@ncdc](https://github.com/ncdc)) -* NONE ([#45317](https://github.com/kubernetes/kubernetes/pull/45317), [@ericchiang](https://github.com/ericchiang)) * Fix init container status reporting when active deadline is exceeded. ([#46305](https://github.com/kubernetes/kubernetes/pull/46305), [@sjenning](https://github.com/sjenning)) * Improves performance of Cinder volume attach/detach operations ([#41785](https://github.com/kubernetes/kubernetes/pull/41785), [@jamiehannaford](https://github.com/jamiehannaford)) * GCE and AWS dynamic provisioners extension: admins can configure zone(s) in which a persistent volume shall be created. ([#38505](https://github.com/kubernetes/kubernetes/pull/38505), [@pospispa](https://github.com/pospispa)) @@ -3039,7 +3037,6 @@ filename | sha256 hash * This adds support for CNI ConfigLists, which permit plugin chaining. ([#42202](https://github.com/kubernetes/kubernetes/pull/42202), [@squeed](https://github.com/squeed)) * API requests using impersonation now include the `system:authenticated` group in the impersonated user automatically. ([#44076](https://github.com/kubernetes/kubernetes/pull/44076), [@liggitt](https://github.com/liggitt)) * Print conditions of RC/RS in 'kubectl describe' command. ([#44710](https://github.com/kubernetes/kubernetes/pull/44710), [@xiangpengzhao](https://github.com/xiangpengzhao)) -* `NONE` ([#44487](https://github.com/kubernetes/kubernetes/pull/44487), [@resouer](https://github.com/resouer)) * cinder: Add support for the KVM virtio-scsi driver ([#41498](https://github.com/kubernetes/kubernetes/pull/41498), [@mikebryant](https://github.com/mikebryant)) * Disallows installation of upstream docker from PPA in the Juju kubernetes-worker charm. ([#44681](https://github.com/kubernetes/kubernetes/pull/44681), [@wwwtyro](https://github.com/wwwtyro)) * Fluentd manifest pod is no longer created on non-registered master when creating clusters using kube-up.sh. ([#44721](https://github.com/kubernetes/kubernetes/pull/44721), [@piosz](https://github.com/piosz)) @@ -3158,7 +3155,6 @@ filename | sha256 hash * - gcr.io/google-containers/etcd-empty-dir-cleanup * - gcr.io/google-containers/kube-dnsmasq-amd64 * Check if pathExists before performing Unmount ([#39311](https://github.com/kubernetes/kubernetes/pull/39311), [@rkouj](https://github.com/rkouj)) -* NONE ([#39768](https://github.com/kubernetes/kubernetes/pull/39768), [@rkouj](https://github.com/rkouj)) * Unmount operation should not fail if volume is already unmounted ([#38547](https://github.com/kubernetes/kubernetes/pull/38547), [@rkouj](https://github.com/rkouj)) * Updates base image used for `kube-addon-manager` to latest `python:2.7-slim` and embedded `kubectl` to `v1.3.10`. No functionality changes expected. ([#42842](https://github.com/kubernetes/kubernetes/pull/42842), [@ixdy](https://github.com/ixdy)) * list-resources: don't fail if the grep fails to match any resources ([#41933](https://github.com/kubernetes/kubernetes/pull/41933), [@ixdy](https://github.com/ixdy)) @@ -5370,7 +5366,6 @@ filename | sha256 hash * PodSecurityPolicy resource is now enabled by default in the extensions API group. ([#39743](https://github.com/kubernetes/kubernetes/pull/39743), [@pweil-](https://github.com/pweil-)) * add --controllers to controller manager ([#39740](https://github.com/kubernetes/kubernetes/pull/39740), [@deads2k](https://github.com/deads2k)) * proxy/iptables: don't sync proxy rules if services map didn't change ([#38996](https://github.com/kubernetes/kubernetes/pull/38996), [@dcbw](https://github.com/dcbw)) -* NONE ([#39768](https://github.com/kubernetes/kubernetes/pull/39768), [@rkouj](https://github.com/rkouj)) * Update amd64 kube-proxy base image to debian-iptables-amd64:v5 ([#39725](https://github.com/kubernetes/kubernetes/pull/39725), [@ixdy](https://github.com/ixdy)) * Update dashboard version to v1.5.1 ([#39662](https://github.com/kubernetes/kubernetes/pull/39662), [@rf232](https://github.com/rf232)) * Fix kubectl get -f -o so it prints all items in the file ([#39038](https://github.com/kubernetes/kubernetes/pull/39038), [@ncdc](https://github.com/ncdc)) @@ -6839,10 +6834,8 @@ binary | sha256 hash * Move push-ci-build.sh to kubernetes/release repo ([#32444](https://github.com/kubernetes/kubernetes/pull/32444), [@david-mcmahon](https://github.com/david-mcmahon)) * vendor: update github.com/coreos/go-oidc client package ([#31564](https://github.com/kubernetes/kubernetes/pull/31564), [@ericchiang](https://github.com/ericchiang)) * Fixed an issue that caused a credential error when deploying federation control plane onto a GKE cluster. ([#31747](https://github.com/kubernetes/kubernetes/pull/31747), [@madhusudancs](https://github.com/madhusudancs)) -* NONE ([#32229](https://github.com/kubernetes/kubernetes/pull/32229), [@errordeveloper](https://github.com/errordeveloper)) * Error if a contextName is provided but not found in the kubeconfig. ([#31767](https://github.com/kubernetes/kubernetes/pull/31767), [@asalkeld](https://github.com/asalkeld)) * Use a Deployment for kube-dns ([#32018](https://github.com/kubernetes/kubernetes/pull/32018), [@MrHohn](https://github.com/MrHohn)) -* NONE ([#32067](https://github.com/kubernetes/kubernetes/pull/32067), [@erikh](https://github.com/erikh)) * Support graceful termination in kube-dns ([#31894](https://github.com/kubernetes/kubernetes/pull/31894), [@MrHohn](https://github.com/MrHohn)) * When prompting for passwords, don't echo to the terminal ([#31586](https://github.com/kubernetes/kubernetes/pull/31586), [@brendandburns](https://github.com/brendandburns)) * add group prefix matching for kubectl usage ([#32140](https://github.com/kubernetes/kubernetes/pull/32140), [@deads2k](https://github.com/deads2k)) @@ -7523,7 +7516,6 @@ binary | sha256 hash * allow group impersonation ([#30803](https://github.com/kubernetes/kubernetes/pull/30803), [@deads2k](https://github.com/deads2k)) * Always return command output for exec probes and kubelet RunInContainer ([#30731](https://github.com/kubernetes/kubernetes/pull/30731), [@ncdc](https://github.com/ncdc)) * Enable the garbage collector by default ([#30480](https://github.com/kubernetes/kubernetes/pull/30480), [@caesarxuchao](https://github.com/caesarxuchao)) -* NONE ([#30599](https://github.com/kubernetes/kubernetes/pull/30599), [@therc](https://github.com/therc)) * use valid_resources to replace kubectl.PossibleResourceTypes ([#30955](https://github.com/kubernetes/kubernetes/pull/30955), [@lojies](https://github.com/lojies)) * oidc auth provider: don't trim issuer URL ([#30944](https://github.com/kubernetes/kubernetes/pull/30944), [@ericchiang](https://github.com/ericchiang)) * Add a short `-n` for `kubectl --namespace` ([#30630](https://github.com/kubernetes/kubernetes/pull/30630), [@silasbw](https://github.com/silasbw)) From f67d143d6a784f5cb0afca8829ecb71228a3520c Mon Sep 17 00:00:00 2001 From: Maciej Pytel Date: Thu, 29 Jun 2017 18:52:59 +0200 Subject: [PATCH 144/448] Added scale-down-to-0 e2e for cluster autoscaler --- test/e2e/autoscaling/BUILD | 1 + .../autoscaling/cluster_size_autoscaling.go | 46 +++++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/test/e2e/autoscaling/BUILD b/test/e2e/autoscaling/BUILD index b53160c6cd3..0159ea9909c 100644 --- a/test/e2e/autoscaling/BUILD +++ b/test/e2e/autoscaling/BUILD @@ -17,6 +17,7 @@ go_library( ], tags = ["automanaged"], deps = [ + "//pkg/api:go_default_library", "//pkg/client/clientset_generated/clientset:go_default_library", "//test/e2e/common:go_default_library", "//test/e2e/framework:go_default_library", diff --git a/test/e2e/autoscaling/cluster_size_autoscaling.go b/test/e2e/autoscaling/cluster_size_autoscaling.go index fb78e979141..f480cffddca 100644 --- a/test/e2e/autoscaling/cluster_size_autoscaling.go +++ b/test/e2e/autoscaling/cluster_size_autoscaling.go @@ -39,6 +39,7 @@ import ( "k8s.io/apimachinery/pkg/util/sets" "k8s.io/apimachinery/pkg/util/uuid" "k8s.io/apimachinery/pkg/util/wait" + "k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/client/clientset_generated/clientset" "k8s.io/kubernetes/test/e2e/framework" "k8s.io/kubernetes/test/e2e/scheduling" @@ -589,6 +590,51 @@ var _ = framework.KubeDescribe("Cluster size autoscaling [Slow]", func() { framework.ExpectNoError(waitForAllCaPodsReadyInNamespace(f, c)) }) + It("Should be able to scale a node group down to 0[Feature:ClusterSizeAutoscalingScaleDown]", func() { + framework.SkipUnlessAtLeast(len(originalSizes), 2, "At least 2 node groups are needed for scale-to-0 tests") + By("Find smallest node group and manually scale it to a single node") + minMig := "" + minSize := nodeCount + for mig, size := range originalSizes { + if size <= minSize { + minMig = mig + minSize = size + } + } + err := framework.ResizeGroup(minMig, int32(1)) + framework.ExpectNoError(err) + framework.ExpectNoError(framework.WaitForClusterSize(c, nodeCount-minSize+1, resizeTimeout)) + + By("Make the single node unschedulable") + allNodes, err := f.ClientSet.Core().Nodes().List(metav1.ListOptions{FieldSelector: fields.Set{ + "spec.unschedulable": "false", + }.AsSelector().String()}) + framework.ExpectNoError(err) + ngNodes, err := framework.GetGroupNodes(minMig) + framework.ExpectNoError(err) + By(fmt.Sprintf("Target nodes for scale-down: %s", ngNodes)) + Expect(len(ngNodes) == 1).To(BeTrue()) + node, err := f.ClientSet.Core().Nodes().Get(ngNodes[0], metav1.GetOptions{}) + framework.ExpectNoError(err) + makeNodeUnschedulable(f.ClientSet, node) + + By("Manually drain the single node") + podOpts := metav1.ListOptions{FieldSelector: fields.OneTermEqualSelector(api.PodHostField, node.Name).String()} + pods, err := c.Core().Pods(metav1.NamespaceAll).List(podOpts) + framework.ExpectNoError(err) + for _, pod := range pods.Items { + err = f.ClientSet.Core().Pods(pod.Namespace).Delete(pod.Name, metav1.NewDeleteOptions(0)) + framework.ExpectNoError(err) + } + + By("The node should be removed") + framework.ExpectNoError(WaitForClusterSizeFunc(f.ClientSet, + func(size int) bool { return size < len(allNodes.Items) }, scaleDownTimeout)) + minSize, err = framework.GroupSize(minMig) + framework.ExpectNoError(err) + Expect(minSize).Should(Equal(0)) + }) + It("Shouldn't perform scale up operation and should list unhealthy status if most of the cluster is broken[Feature:ClusterSizeAutoscalingScaleUp]", func() { clusterSize := nodeCount for clusterSize < unhealthyClusterThreshold+1 { From 82dff5fbd082a6b99daa6e75f8bac6cb75fb5a3c Mon Sep 17 00:00:00 2001 From: sakeven Date: Fri, 30 Jun 2017 18:33:17 +0800 Subject: [PATCH 145/448] HTTPExtender: shoud close resp.Body even when StatusCode not ok Signed-off-by: sakeven --- plugin/pkg/scheduler/core/extender.go | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/plugin/pkg/scheduler/core/extender.go b/plugin/pkg/scheduler/core/extender.go index 6c24cf00cd3..898ef4f4525 100644 --- a/plugin/pkg/scheduler/core/extender.go +++ b/plugin/pkg/scheduler/core/extender.go @@ -20,8 +20,8 @@ import ( "bytes" "encoding/json" "fmt" - "io/ioutil" "net/http" + "strings" "time" "k8s.io/api/core/v1" @@ -229,7 +229,7 @@ func (h *HTTPExtender) send(action string, args interface{}, result interface{}) return err } - url := h.extenderURL + "/" + action + url := strings.TrimRight(h.extenderURL, "/") + "/" + action req, err := http.NewRequest("POST", url, bytes.NewReader(out)) if err != nil { @@ -242,19 +242,11 @@ func (h *HTTPExtender) send(action string, args interface{}, result interface{}) if err != nil { return err } + 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) } - defer resp.Body.Close() - body, err := ioutil.ReadAll(resp.Body) - if err != nil { - return err - } - - if err := json.Unmarshal(body, result); err != nil { - return err - } - return nil + return json.NewDecoder(resp.Body).Decode(result) } From 3e09d8c98505cc1c4c233f8393f3ab5c8bb06143 Mon Sep 17 00:00:00 2001 From: duan-yue Date: Fri, 30 Jun 2017 20:56:19 +0800 Subject: [PATCH 146/448] remove redundant alias --- cmd/kube-controller-manager/app/extensions.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/kube-controller-manager/app/extensions.go b/cmd/kube-controller-manager/app/extensions.go index f1b65440799..7e9be6a87e3 100644 --- a/cmd/kube-controller-manager/app/extensions.go +++ b/cmd/kube-controller-manager/app/extensions.go @@ -24,7 +24,7 @@ import ( "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/kubernetes/pkg/controller/daemon" "k8s.io/kubernetes/pkg/controller/deployment" - replicaset "k8s.io/kubernetes/pkg/controller/replicaset" + "k8s.io/kubernetes/pkg/controller/replicaset" ) func startDaemonSetController(ctx ControllerContext) (bool, error) { From 19ca6ca9f2cbb0056766e46a6a0c69c40d990287 Mon Sep 17 00:00:00 2001 From: Manjunath A Kumatagi Date: Fri, 30 Jun 2017 18:43:55 +0530 Subject: [PATCH 147/448] Fix review comments - luxas, ixdy --- test/images/BUILD | 6 +++--- test/images/Makefile | 2 +- test/images/clusterapi-tester/NAME | 1 - test/images/clusterapi-tester/VERSION | 2 +- .../{nvidia-cuda => cuda-vector-add}/BASEIMAGE | 0 .../{nvidia-cuda => cuda-vector-add}/Dockerfile | 0 .../{nvidia-cuda => cuda-vector-add}/README.md | 0 test/images/cuda-vector-add/VERSION | 1 + test/images/dnsutils/NAME | 1 - test/images/dnsutils/VERSION | 2 +- test/images/entrypoint-tester/NAME | 1 - test/images/entrypoint-tester/VERSION | 2 +- test/images/fakegitserver/NAME | 1 - test/images/fakegitserver/VERSION | 2 +- test/images/goproxy/NAME | 1 - test/images/goproxy/VERSION | 2 +- test/images/hostexec/NAME | 1 - test/images/hostexec/VERSION | 2 +- test/images/image-util.sh | 14 ++------------ test/images/iperf/NAME | 1 - test/images/iperf/VERSION | 2 +- test/images/jessie-dnsutils/NAME | 1 - test/images/jessie-dnsutils/VERSION | 2 +- test/images/logs-generator/NAME | 1 - test/images/logs-generator/VERSION | 2 +- test/images/mount-tester-user/BASEIMAGE | 5 ----- test/images/mount-tester-user/NAME | 1 - test/images/mount-tester-user/VERSION | 1 - test/images/mount-tester/NAME | 1 - test/images/mount-tester/VERSION | 1 - test/images/mounttest-user/BASEIMAGE | 5 +++++ .../Dockerfile | 0 test/images/mounttest-user/VERSION | 1 + test/images/{mount-tester => mounttest}/BUILD | 12 ++++++------ test/images/{mount-tester => mounttest}/Dockerfile | 0 test/images/{mount-tester => mounttest}/Makefile | 0 test/images/mounttest/VERSION | 1 + test/images/{mount-tester => mounttest}/mt.go | 0 test/images/n-way-http/NAME | 1 - test/images/n-way-http/VERSION | 2 +- test/images/net/NAME | 1 - test/images/net/VERSION | 2 +- test/images/netexec/NAME | 1 - test/images/netexec/VERSION | 2 +- test/images/{network-tester => nettest}/BUILD | 12 ++++++------ test/images/{network-tester => nettest}/Dockerfile | 0 test/images/{network-tester => nettest}/Makefile | 0 test/images/nettest/VERSION | 1 + test/images/{network-tester => nettest}/nettest.go | 0 test/images/{network-tester => nettest}/rc.json | 0 .../{network-tester => nettest}/service.json | 0 .../{network-tester => nettest}/slow-pod.json | 0 .../{network-tester => nettest}/slow-rc.json | 0 test/images/network-tester/NAME | 1 - test/images/network-tester/VERSION | 1 - test/images/no-snat-test-proxy/NAME | 1 - test/images/no-snat-test-proxy/VERSION | 2 +- test/images/no-snat-test/NAME | 1 - test/images/no-snat-test/VERSION | 2 +- test/images/nvidia-cuda/NAME | 1 - test/images/nvidia-cuda/VERSION | 1 - test/images/port-forward-tester/NAME | 1 - test/images/port-forward-tester/VERSION | 2 +- test/images/porter/NAME | 1 - test/images/porter/VERSION | 2 +- test/images/redis/NAME | 1 - test/images/redis/VERSION | 2 +- test/images/resource-consumer/NAME | 1 - test/images/resource-consumer/VERSION | 2 +- test/images/resource-consumer/controller/NAME | 1 - test/images/resource-consumer/controller/VERSION | 2 +- .../{serve_hostname => serve-hostname}/BASEIMAGE | 0 .../{serve_hostname => serve-hostname}/BUILD | 12 ++++++------ .../{serve_hostname => serve-hostname}/Dockerfile | 0 .../{serve_hostname => serve-hostname}/Makefile | 0 .../{serve_hostname => serve-hostname}/README.md | 0 test/images/serve-hostname/VERSION | 1 + .../serve_hostname.go | 0 test/images/serve_hostname/NAME | 1 - test/images/serve_hostname/VERSION | 1 - 80 files changed, 53 insertions(+), 87 deletions(-) delete mode 100644 test/images/clusterapi-tester/NAME rename test/images/{nvidia-cuda => cuda-vector-add}/BASEIMAGE (100%) rename test/images/{nvidia-cuda => cuda-vector-add}/Dockerfile (100%) rename test/images/{nvidia-cuda => cuda-vector-add}/README.md (100%) create mode 100644 test/images/cuda-vector-add/VERSION delete mode 100644 test/images/dnsutils/NAME delete mode 100644 test/images/entrypoint-tester/NAME delete mode 100644 test/images/fakegitserver/NAME delete mode 100644 test/images/goproxy/NAME delete mode 100644 test/images/hostexec/NAME delete mode 100644 test/images/iperf/NAME delete mode 100644 test/images/jessie-dnsutils/NAME delete mode 100644 test/images/logs-generator/NAME delete mode 100644 test/images/mount-tester-user/BASEIMAGE delete mode 100644 test/images/mount-tester-user/NAME delete mode 100644 test/images/mount-tester-user/VERSION delete mode 100644 test/images/mount-tester/NAME delete mode 100644 test/images/mount-tester/VERSION create mode 100644 test/images/mounttest-user/BASEIMAGE rename test/images/{mount-tester-user => mounttest-user}/Dockerfile (100%) create mode 100644 test/images/mounttest-user/VERSION rename test/images/{mount-tester => mounttest}/BUILD (95%) rename test/images/{mount-tester => mounttest}/Dockerfile (100%) rename test/images/{mount-tester => mounttest}/Makefile (100%) create mode 100644 test/images/mounttest/VERSION rename test/images/{mount-tester => mounttest}/mt.go (100%) delete mode 100644 test/images/n-way-http/NAME delete mode 100644 test/images/net/NAME delete mode 100644 test/images/netexec/NAME rename test/images/{network-tester => nettest}/BUILD (96%) rename test/images/{network-tester => nettest}/Dockerfile (100%) rename test/images/{network-tester => nettest}/Makefile (100%) create mode 100644 test/images/nettest/VERSION rename test/images/{network-tester => nettest}/nettest.go (100%) rename test/images/{network-tester => nettest}/rc.json (100%) rename test/images/{network-tester => nettest}/service.json (100%) rename test/images/{network-tester => nettest}/slow-pod.json (100%) rename test/images/{network-tester => nettest}/slow-rc.json (100%) delete mode 100644 test/images/network-tester/NAME delete mode 100644 test/images/network-tester/VERSION delete mode 100644 test/images/no-snat-test-proxy/NAME delete mode 100644 test/images/no-snat-test/NAME delete mode 100644 test/images/nvidia-cuda/NAME delete mode 100644 test/images/nvidia-cuda/VERSION delete mode 100644 test/images/port-forward-tester/NAME delete mode 100644 test/images/porter/NAME delete mode 100644 test/images/redis/NAME delete mode 100644 test/images/resource-consumer/NAME delete mode 100644 test/images/resource-consumer/controller/NAME rename test/images/{serve_hostname => serve-hostname}/BASEIMAGE (100%) rename test/images/{serve_hostname => serve-hostname}/BUILD (95%) rename test/images/{serve_hostname => serve-hostname}/Dockerfile (100%) rename test/images/{serve_hostname => serve-hostname}/Makefile (100%) rename test/images/{serve_hostname => serve-hostname}/README.md (100%) create mode 100644 test/images/serve-hostname/VERSION rename test/images/{serve_hostname => serve-hostname}/serve_hostname.go (100%) delete mode 100644 test/images/serve_hostname/NAME delete mode 100644 test/images/serve_hostname/VERSION diff --git a/test/images/BUILD b/test/images/BUILD index 4424ecf83c1..009d86244a1 100644 --- a/test/images/BUILD +++ b/test/images/BUILD @@ -23,17 +23,17 @@ filegroup( "//test/images/fakegitserver:all-srcs", "//test/images/goproxy:all-srcs", "//test/images/logs-generator:all-srcs", - "//test/images/mount-tester:all-srcs", + "//test/images/mounttest:all-srcs", "//test/images/n-way-http:all-srcs", "//test/images/net:all-srcs", "//test/images/netexec:all-srcs", - "//test/images/network-tester:all-srcs", + "//test/images/nettest:all-srcs", "//test/images/no-snat-test:all-srcs", "//test/images/no-snat-test-proxy:all-srcs", "//test/images/port-forward-tester:all-srcs", "//test/images/porter:all-srcs", "//test/images/resource-consumer:all-srcs", - "//test/images/serve_hostname:all-srcs", + "//test/images/serve-hostname:all-srcs", ], tags = ["automanaged"], ) diff --git a/test/images/Makefile b/test/images/Makefile index 9d5aeb5ebc5..450b17beb7c 100644 --- a/test/images/Makefile +++ b/test/images/Makefile @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -REGISTRY ?= gcr.io/k8s-e2e-images +REGISTRY ?= gcr.io/kubernetes-e2e-test-images GOARM=7 QEMUVERSION=v2.7.0 GOLANG_VERSION=1.8.3 diff --git a/test/images/clusterapi-tester/NAME b/test/images/clusterapi-tester/NAME deleted file mode 100644 index 97185c48995..00000000000 --- a/test/images/clusterapi-tester/NAME +++ /dev/null @@ -1 +0,0 @@ -clusterapi-tester diff --git a/test/images/clusterapi-tester/VERSION b/test/images/clusterapi-tester/VERSION index 9459d4ba2a0..d3827e75a5c 100644 --- a/test/images/clusterapi-tester/VERSION +++ b/test/images/clusterapi-tester/VERSION @@ -1 +1 @@ -1.1 +1.0 diff --git a/test/images/nvidia-cuda/BASEIMAGE b/test/images/cuda-vector-add/BASEIMAGE similarity index 100% rename from test/images/nvidia-cuda/BASEIMAGE rename to test/images/cuda-vector-add/BASEIMAGE diff --git a/test/images/nvidia-cuda/Dockerfile b/test/images/cuda-vector-add/Dockerfile similarity index 100% rename from test/images/nvidia-cuda/Dockerfile rename to test/images/cuda-vector-add/Dockerfile diff --git a/test/images/nvidia-cuda/README.md b/test/images/cuda-vector-add/README.md similarity index 100% rename from test/images/nvidia-cuda/README.md rename to test/images/cuda-vector-add/README.md diff --git a/test/images/cuda-vector-add/VERSION b/test/images/cuda-vector-add/VERSION new file mode 100644 index 00000000000..d3827e75a5c --- /dev/null +++ b/test/images/cuda-vector-add/VERSION @@ -0,0 +1 @@ +1.0 diff --git a/test/images/dnsutils/NAME b/test/images/dnsutils/NAME deleted file mode 100644 index bca3eb0f23f..00000000000 --- a/test/images/dnsutils/NAME +++ /dev/null @@ -1 +0,0 @@ -dnsutils diff --git a/test/images/dnsutils/VERSION b/test/images/dnsutils/VERSION index 9459d4ba2a0..d3827e75a5c 100644 --- a/test/images/dnsutils/VERSION +++ b/test/images/dnsutils/VERSION @@ -1 +1 @@ -1.1 +1.0 diff --git a/test/images/entrypoint-tester/NAME b/test/images/entrypoint-tester/NAME deleted file mode 100644 index e2d8e243c18..00000000000 --- a/test/images/entrypoint-tester/NAME +++ /dev/null @@ -1 +0,0 @@ -ep diff --git a/test/images/entrypoint-tester/VERSION b/test/images/entrypoint-tester/VERSION index 3b04cfb60da..d3827e75a5c 100644 --- a/test/images/entrypoint-tester/VERSION +++ b/test/images/entrypoint-tester/VERSION @@ -1 +1 @@ -0.2 +1.0 diff --git a/test/images/fakegitserver/NAME b/test/images/fakegitserver/NAME deleted file mode 100644 index 1f1e4b248bf..00000000000 --- a/test/images/fakegitserver/NAME +++ /dev/null @@ -1 +0,0 @@ -fakegitserver diff --git a/test/images/fakegitserver/VERSION b/test/images/fakegitserver/VERSION index 3b04cfb60da..d3827e75a5c 100644 --- a/test/images/fakegitserver/VERSION +++ b/test/images/fakegitserver/VERSION @@ -1 +1 @@ -0.2 +1.0 diff --git a/test/images/goproxy/NAME b/test/images/goproxy/NAME deleted file mode 100644 index 663e1754bde..00000000000 --- a/test/images/goproxy/NAME +++ /dev/null @@ -1 +0,0 @@ -goproxy diff --git a/test/images/goproxy/VERSION b/test/images/goproxy/VERSION index 3b04cfb60da..d3827e75a5c 100644 --- a/test/images/goproxy/VERSION +++ b/test/images/goproxy/VERSION @@ -1 +1 @@ -0.2 +1.0 diff --git a/test/images/hostexec/NAME b/test/images/hostexec/NAME deleted file mode 100644 index 0d7e9c73d9d..00000000000 --- a/test/images/hostexec/NAME +++ /dev/null @@ -1 +0,0 @@ -hostexec diff --git a/test/images/hostexec/VERSION b/test/images/hostexec/VERSION index 7e32cd56983..d3827e75a5c 100644 --- a/test/images/hostexec/VERSION +++ b/test/images/hostexec/VERSION @@ -1 +1 @@ -1.3 +1.0 diff --git a/test/images/image-util.sh b/test/images/image-util.sh index 96ccaddfe4a..d9ff9e31e08 100755 --- a/test/images/image-util.sh +++ b/test/images/image-util.sh @@ -63,8 +63,6 @@ build() { pushd ${temp_dir} # image tag TAG=$( Date: Fri, 30 Jun 2017 09:19:44 -0400 Subject: [PATCH 148/448] don't accept delete tokens that are waiting to be reaped --- pkg/serviceaccount/jwt.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/pkg/serviceaccount/jwt.go b/pkg/serviceaccount/jwt.go index 9135df00785..83efe5be0aa 100644 --- a/pkg/serviceaccount/jwt.go +++ b/pkg/serviceaccount/jwt.go @@ -290,6 +290,10 @@ func (j *jwtTokenAuthenticator) AuthenticateToken(token string) (user.Info, bool glog.V(4).Infof("Could not retrieve token %s/%s for service account %s/%s: %v", namespace, secretName, namespace, serviceAccountName, err) return nil, false, errors.New("Token has been invalidated") } + if secret.DeletionTimestamp != nil { + glog.V(4).Infof("Token is deleted and awaiting removal: %s/%s for service account %s/%s", namespace, secretName, namespace, serviceAccountName) + return nil, false, errors.New("Token has been invalidated") + } if bytes.Compare(secret.Data[v1.ServiceAccountTokenKey], []byte(token)) != 0 { glog.V(4).Infof("Token contents no longer matches %s/%s for service account %s/%s", namespace, secretName, namespace, serviceAccountName) return nil, false, errors.New("Token does not match server's copy") @@ -301,6 +305,10 @@ func (j *jwtTokenAuthenticator) AuthenticateToken(token string) (user.Info, bool glog.V(4).Infof("Could not retrieve service account %s/%s: %v", namespace, serviceAccountName, err) return nil, false, err } + if serviceAccount.DeletionTimestamp != nil { + glog.V(4).Infof("Service account has been deleted %s/%s", namespace, serviceAccountName) + return nil, false, fmt.Errorf("ServiceAccount %s/%s has been deleted", namespace, serviceAccountName) + } if string(serviceAccount.UID) != serviceAccountUID { glog.V(4).Infof("Service account UID no longer matches %s/%s: %q != %q", namespace, serviceAccountName, string(serviceAccount.UID), serviceAccountUID) return nil, false, fmt.Errorf("ServiceAccount UID (%s) does not match claim (%s)", serviceAccount.UID, serviceAccountUID) From 5f0c16b5d0d7e33984314d12e155d8b497c12a0d Mon Sep 17 00:00:00 2001 From: Manjunath A Kumatagi Date: Fri, 30 Jun 2017 19:42:55 +0530 Subject: [PATCH 149/448] Fix verify-golint --- hack/.linted_packages | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hack/.linted_packages b/hack/.linted_packages index a04fb93796e..fa3ca90f21d 100644 --- a/hack/.linted_packages +++ b/hack/.linted_packages @@ -463,14 +463,14 @@ test/images/entrypoint-tester test/images/fakegitserver test/images/goproxy test/images/logs-generator -test/images/mount-tester +test/images/mounttest test/images/n-way-http test/images/net test/images/net/common test/images/port-forward-tester test/images/porter test/images/resource-consumer/consume-cpu -test/images/serve_hostname +test/images/serve-hostname test/integration/apiserver test/integration/client test/integration/configmap From d10cf91cf480903f51dcc940c6093e51c7e45dd4 Mon Sep 17 00:00:00 2001 From: Aleksandra Malinowska Date: Fri, 30 Jun 2017 14:15:17 +0200 Subject: [PATCH 150/448] Fix issue with not waiting for nodes to be fully schedulable during test cleanup --- .../autoscaling/cluster_size_autoscaling.go | 37 ++++++++++++++++--- 1 file changed, 31 insertions(+), 6 deletions(-) diff --git a/test/e2e/autoscaling/cluster_size_autoscaling.go b/test/e2e/autoscaling/cluster_size_autoscaling.go index fb78e979141..12d9dea148a 100644 --- a/test/e2e/autoscaling/cluster_size_autoscaling.go +++ b/test/e2e/autoscaling/cluster_size_autoscaling.go @@ -59,11 +59,14 @@ const ( nodesRecoverTimeout = 5 * time.Minute rcCreationRetryTimeout = 4 * time.Minute rcCreationRetryDelay = 20 * time.Second + makeSchedulableTimeout = 10 * time.Minute + makeSchedulableDelay = 20 * time.Second gkeEndpoint = "https://test-container.sandbox.googleapis.com" gkeUpdateTimeout = 15 * time.Minute disabledTaint = "DisabledForAutoscalingTest" + criticalAddonsOnlyTaint = "CriticalAddonsOnly" newNodesForScaledownTests = 2 unhealthyClusterThreshold = 4 @@ -126,9 +129,22 @@ var _ = framework.KubeDescribe("Cluster size autoscaling [Slow]", func() { framework.ExpectNoError(framework.WaitForClusterSize(c, expectedNodes, scaleDownTimeout)) nodes, err := c.Core().Nodes().List(metav1.ListOptions{}) framework.ExpectNoError(err) - for _, n := range nodes.Items { - framework.ExpectNoError(makeNodeSchedulable(c, &n)) + + s := time.Now() + makeSchedulableLoop: + for start := time.Now(); time.Since(start) < makeSchedulableTimeout; time.Sleep(makeSchedulableDelay) { + for _, n := range nodes.Items { + err = makeNodeSchedulable(c, &n, true) + switch err.(type) { + case CriticalAddonsOnlyError: + continue makeSchedulableLoop + default: + framework.ExpectNoError(err) + } + } + break } + glog.Infof("Made nodes schedulable again in %v", time.Now().Sub(s).String()) }) It("shouldn't increase cluster size if pending pod is too large [Feature:ClusterSizeAutoscalingScaleUp]", func() { @@ -574,7 +590,7 @@ var _ = framework.KubeDescribe("Cluster size autoscaling [Slow]", func() { err = makeNodeUnschedulable(f.ClientSet, &node) defer func(n v1.Node) { - makeNodeSchedulable(f.ClientSet, &n) + makeNodeSchedulable(f.ClientSet, &n, false) }(node) framework.ExpectNoError(err) } @@ -1012,7 +1028,13 @@ func makeNodeUnschedulable(c clientset.Interface, node *v1.Node) error { return fmt.Errorf("Failed to taint node in allowed number of retries") } -func makeNodeSchedulable(c clientset.Interface, node *v1.Node) error { +type CriticalAddonsOnlyError struct{} + +func (_ CriticalAddonsOnlyError) Error() string { + return fmt.Sprintf("CriticalAddonsOnly taint found on node") +} + +func makeNodeSchedulable(c clientset.Interface, node *v1.Node, failOnCriticalAddonsOnly bool) error { By(fmt.Sprintf("Remove taint from node %s", node.Name)) for j := 0; j < 3; j++ { freshNode, err := c.Core().Nodes().Get(node.Name, metav1.GetOptions{}) @@ -1021,6 +1043,9 @@ func makeNodeSchedulable(c clientset.Interface, node *v1.Node) error { } newTaints := make([]v1.Taint, 0) for _, taint := range freshNode.Spec.Taints { + if failOnCriticalAddonsOnly && taint.Key == criticalAddonsOnlyTaint { + return CriticalAddonsOnlyError{} + } if taint.Key != disabledTaint { newTaints = append(newTaints, taint) } @@ -1143,7 +1168,7 @@ func runReplicatedPodOnEachNode(f *framework.Framework, nodes []v1.Node, namespa err := makeNodeUnschedulable(f.ClientSet, &node) defer func(n v1.Node) { - makeNodeSchedulable(f.ClientSet, &n) + makeNodeSchedulable(f.ClientSet, &n, false) }(node) if err != nil { @@ -1169,7 +1194,7 @@ func runReplicatedPodOnEachNode(f *framework.Framework, nodes []v1.Node, namespa return err } for i, node := range nodes { - err = makeNodeSchedulable(f.ClientSet, &node) + err = makeNodeSchedulable(f.ClientSet, &node, false) if err != nil { return err } From c1a76fbb57f66a9fec48dae0dfc658ac5c20661e Mon Sep 17 00:00:00 2001 From: Shyam Jeedigunta Date: Thu, 29 Jun 2017 16:13:05 +0200 Subject: [PATCH 151/448] Make cluster IP range an argument to ginkgo to fix firewall test --- hack/ginkgo-e2e.sh | 1 + hack/verify-flags/known-flags.txt | 1 + test/e2e/firewall.go | 2 +- test/e2e/framework/firewall_util.go | 11 +---------- test/e2e/framework/test_context.go | 2 ++ 5 files changed, 6 insertions(+), 11 deletions(-) diff --git a/hack/ginkgo-e2e.sh b/hack/ginkgo-e2e.sh index bb52e3702bb..d892786debc 100755 --- a/hack/ginkgo-e2e.sh +++ b/hack/ginkgo-e2e.sh @@ -157,6 +157,7 @@ export PATH=$(dirname "${e2e_test}"):"${PATH}" ${MASTER_OS_DISTRIBUTION:+"--master-os-distro=${MASTER_OS_DISTRIBUTION}"} \ ${NODE_OS_DISTRIBUTION:+"--node-os-distro=${NODE_OS_DISTRIBUTION}"} \ ${NUM_NODES:+"--num-nodes=${NUM_NODES}"} \ + ${CLUSTER_IP_RANGE:+"--cluster-ip-range=${CLUSTER_IP_RANGE}"} \ ${E2E_CLEAN_START:+"--clean-start=true"} \ ${E2E_MIN_STARTUP_PODS:+"--minStartupPods=${E2E_MIN_STARTUP_PODS}"} \ ${E2E_REPORT_DIR:+"--report-dir=${E2E_REPORT_DIR}"} \ diff --git a/hack/verify-flags/known-flags.txt b/hack/verify-flags/known-flags.txt index 991aa53aa75..2a347472e22 100644 --- a/hack/verify-flags/known-flags.txt +++ b/hack/verify-flags/known-flags.txt @@ -105,6 +105,7 @@ cluster-context cluster-dns cluster-domain cluster-ip +cluster-ip-range cluster-monitor-period cluster-name cluster-signing-cert-file diff --git a/test/e2e/firewall.go b/test/e2e/firewall.go index 8586cccdc61..56d8cf381c3 100644 --- a/test/e2e/firewall.go +++ b/test/e2e/firewall.go @@ -160,7 +160,7 @@ var _ = framework.KubeDescribe("Firewall rule", func() { } By("Checking if e2e firewall rules are correct") - for _, expFw := range framework.GetE2eFirewalls(cloudConfig.MasterName, cloudConfig.MasterTag, cloudConfig.NodeTag, cloudConfig.Network) { + for _, expFw := range framework.GetE2eFirewalls(cloudConfig.MasterName, cloudConfig.MasterTag, cloudConfig.NodeTag, cloudConfig.Network, cloudConfig.ClusterIPRange) { fw, err := gceCloud.GetFirewall(expFw.Name) Expect(err).NotTo(HaveOccurred()) Expect(framework.VerifyFirewallRule(fw, expFw, cloudConfig.Network, false)).NotTo(HaveOccurred()) diff --git a/test/e2e/framework/firewall_util.go b/test/e2e/framework/firewall_util.go index 9de9dd89f5f..e6e4e1651c8 100644 --- a/test/e2e/framework/firewall_util.go +++ b/test/e2e/framework/firewall_util.go @@ -141,21 +141,12 @@ func GetClusterName(instancePrefix string) string { return instancePrefix } -// GetClusterIpRange returns the CLUSTER_IP_RANGE env we set for e2e cluster. -// -// Warning: this MUST be consistent with the CLUSTER_IP_RANGE set in -// gce/config-test.sh. -func GetClusterIpRange() string { - return "10.100.0.0/14" -} - // GetE2eFirewalls returns all firewall rules we create for an e2e cluster. // From cluster/gce/util.sh, all firewall rules should be consistent with the ones created by startup scripts. -func GetE2eFirewalls(masterName, masterTag, nodeTag, network string) []*compute.Firewall { +func GetE2eFirewalls(masterName, masterTag, nodeTag, network, clusterIpRange string) []*compute.Firewall { instancePrefix, err := GetInstancePrefix(masterName) Expect(err).NotTo(HaveOccurred()) clusterName := GetClusterName(instancePrefix) - clusterIpRange := GetClusterIpRange() fws := []*compute.Firewall{} fws = append(fws, &compute.Firewall{ diff --git a/test/e2e/framework/test_context.go b/test/e2e/framework/test_context.go index 5945867e395..651efec15a1 100644 --- a/test/e2e/framework/test_context.go +++ b/test/e2e/framework/test_context.go @@ -140,6 +140,7 @@ type CloudConfig struct { MasterName string NodeInstanceGroup string // comma-delimited list of groups' names NumNodes int + ClusterIPRange string ClusterTag string Network string ConfigFile string // for azure and openstack @@ -212,6 +213,7 @@ func RegisterClusterFlags() { flag.StringVar(&cloudConfig.NodeInstanceGroup, "node-instance-group", "", "Name of the managed instance group for nodes. Valid only for gce, gke or aws. If there is more than one group: comma separated list of groups.") flag.StringVar(&cloudConfig.Network, "network", "e2e", "The cloud provider network for this e2e cluster.") flag.IntVar(&cloudConfig.NumNodes, "num-nodes", -1, "Number of nodes in the cluster") + flag.StringVar(&cloudConfig.ClusterIPRange, "cluster-ip-range", "10.100.0.0/14", "A CIDR notation IP range from which to assign IPs in the cluster.") flag.StringVar(&cloudConfig.NodeTag, "node-tag", "", "Network tags used on node instances. Valid only for gce, gke") flag.StringVar(&cloudConfig.MasterTag, "master-tag", "", "Network tags used on master instances. Valid only for gce, gke") From f4fc98ae0138e6388961f7e7b2731492cd350012 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucas=20K=C3=A4ldstr=C3=B6m?= Date: Fri, 30 Jun 2017 17:46:34 +0300 Subject: [PATCH 152/448] kubeadm: Remove old feature gates and unused functions --- cmd/kubeadm/app/constants/constants.go | 8 +-- cmd/kubeadm/app/master/BUILD | 1 - cmd/kubeadm/app/master/manifests.go | 60 +++------------------- cmd/kubeadm/app/master/manifests_test.go | 65 +----------------------- 4 files changed, 8 insertions(+), 126 deletions(-) diff --git a/cmd/kubeadm/app/constants/constants.go b/cmd/kubeadm/app/constants/constants.go index 4b91728140b..461c11ea271 100644 --- a/cmd/kubeadm/app/constants/constants.go +++ b/cmd/kubeadm/app/constants/constants.go @@ -107,11 +107,5 @@ var ( DefaultTokenUsages = []string{"signing", "authentication"} // MinimumControlPlaneVersion specifies the minimum control plane version kubeadm can deploy - MinimumControlPlaneVersion = version.MustParseSemantic("v1.6.0") - - // MinimumCSRSARApproverVersion specifies the minimum kubernetes version that can be used for enabling the new-in-v1.7 CSR approver based on a SubjectAccessReview - MinimumCSRSARApproverVersion = version.MustParseSemantic("v1.7.0-beta.0") - - // MinimumAPIAggregationVersion specifies the minimum kubernetes version that can be used enabling the API aggregation in the apiserver and the front proxy flags - MinimumAPIAggregationVersion = version.MustParseSemantic("v1.7.0-alpha.1") + MinimumControlPlaneVersion = version.MustParseSemantic("v1.7.0") ) diff --git a/cmd/kubeadm/app/master/BUILD b/cmd/kubeadm/app/master/BUILD index e7db78a80e2..c8d7f970017 100644 --- a/cmd/kubeadm/app/master/BUILD +++ b/cmd/kubeadm/app/master/BUILD @@ -22,7 +22,6 @@ go_library( "//cmd/kubeadm/app/constants:go_default_library", "//cmd/kubeadm/app/images:go_default_library", "//cmd/kubeadm/app/util/kubeconfig:go_default_library", - "//pkg/bootstrap/api:go_default_library", "//pkg/kubeapiserver/authorizer/modes:go_default_library", "//pkg/kubectl/cmd/util:go_default_library", "//pkg/kubelet/types:go_default_library", diff --git a/cmd/kubeadm/app/master/manifests.go b/cmd/kubeadm/app/master/manifests.go index f047b8c082b..10a33797ea0 100644 --- a/cmd/kubeadm/app/master/manifests.go +++ b/cmd/kubeadm/app/master/manifests.go @@ -34,7 +34,6 @@ import ( kubeadmapiext "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1" kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants" "k8s.io/kubernetes/cmd/kubeadm/app/images" - bootstrapapi "k8s.io/kubernetes/pkg/bootstrap/api" authzmodes "k8s.io/kubernetes/pkg/kubeapiserver/authorizer/modes" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" kubetypes "k8s.io/kubernetes/pkg/kubelet/types" @@ -48,14 +47,9 @@ const ( defaultv17AdmissionControl = "Initializers,NamespaceLifecycle,LimitRanger,ServiceAccount,PersistentVolumeLabel,DefaultStorageClass,DefaultTolerationSeconds,NodeRestriction,ResourceQuota" etcd = "etcd" - apiServer = "apiserver" - controllerManager = "controller-manager" - scheduler = "scheduler" - proxy = "proxy" kubeAPIServer = "kube-apiserver" kubeControllerManager = "kube-controller-manager" kubeScheduler = "kube-scheduler" - kubeProxy = "kube-proxy" ) // WriteStaticPodManifests builds manifest objects based on user provided configuration and then dumps it to disk @@ -313,22 +307,7 @@ func componentPod(container api.Container, volumes ...api.Volume) api.Pod { } } -func getComponentBaseCommand(component string) []string { - if kubeadmapi.GlobalEnvParams.HyperkubeImage != "" { - return []string{"/hyperkube", component} - } - - return []string{"kube-" + component} -} - func getAPIServerCommand(cfg *kubeadmapi.MasterConfiguration, selfHosted bool, k8sVersion *version.Version) []string { - var command []string - - // self-hosted apiserver needs to wait on a lock - if selfHosted { - command = []string{"/usr/bin/flock", "--exclusive", "--timeout=30", "/var/lock/api-server.lock"} - } - defaultArguments := map[string]string{ "insecure-port": "0", "admission-control": defaultv17AdmissionControl, @@ -350,14 +329,11 @@ func getAPIServerCommand(cfg *kubeadmapi.MasterConfiguration, selfHosted bool, k "requestheader-extra-headers-prefix": "X-Remote-Extra-", "requestheader-client-ca-file": filepath.Join(cfg.CertificatesDir, kubeadmconstants.FrontProxyCACertName), "requestheader-allowed-names": "front-proxy-client", - } - if k8sVersion.AtLeast(kubeadmconstants.MinimumAPIAggregationVersion) { - // add options which allow the kube-apiserver to act as a front-proxy to aggregated API servers - defaultArguments["proxy-client-cert-file"] = filepath.Join(cfg.CertificatesDir, kubeadmconstants.FrontProxyClientCertName) - defaultArguments["proxy-client-key-file"] = filepath.Join(cfg.CertificatesDir, kubeadmconstants.FrontProxyClientKeyName) + "proxy-client-cert-file": filepath.Join(cfg.CertificatesDir, kubeadmconstants.FrontProxyClientCertName), + "proxy-client-key-file": filepath.Join(cfg.CertificatesDir, kubeadmconstants.FrontProxyClientKeyName), } - command = getComponentBaseCommand(apiServer) + command := []string{"kube-apiserver"} command = append(command, getExtraParameters(cfg.APIServerExtraArgs, defaultArguments)...) command = append(command, getAuthzParameters(cfg.AuthorizationModes)...) @@ -397,28 +373,18 @@ func getAPIServerCommand(cfg *kubeadmapi.MasterConfiguration, selfHosted bool, k } func getEtcdCommand(cfg *kubeadmapi.MasterConfiguration) []string { - var command []string - defaultArguments := map[string]string{ "listen-client-urls": "http://127.0.0.1:2379", "advertise-client-urls": "http://127.0.0.1:2379", "data-dir": cfg.Etcd.DataDir, } - command = append(command, "etcd") + command := []string{"etcd"} command = append(command, getExtraParameters(cfg.Etcd.ExtraArgs, defaultArguments)...) - return command } func getControllerManagerCommand(cfg *kubeadmapi.MasterConfiguration, selfHosted bool, k8sVersion *version.Version) []string { - var command []string - - // self-hosted controller-manager needs to wait on a lock - if selfHosted { - command = []string{"/usr/bin/flock", "--exclusive", "--timeout=30", "/var/lock/controller-manager.lock"} - } - defaultArguments := map[string]string{ "address": "127.0.0.1", "leader-elect": "true", @@ -430,13 +396,8 @@ func getControllerManagerCommand(cfg *kubeadmapi.MasterConfiguration, selfHosted "use-service-account-credentials": "true", "controllers": "*,bootstrapsigner,tokencleaner", } - if k8sVersion.LessThan(kubeadmconstants.MinimumCSRSARApproverVersion) { - // enable the former CSR group approver for v1.6 clusters. - // TODO(luxas): Remove this once we're targeting v1.8 at HEAD - defaultArguments["insecure-experimental-approve-all-kubelet-csrs-for-group"] = bootstrapapi.BootstrapGroup - } - command = getComponentBaseCommand(controllerManager) + command := []string{"kube-controller-manager"} command = append(command, getExtraParameters(cfg.ControllerManagerExtraArgs, defaultArguments)...) if cfg.CloudProvider != "" { @@ -453,27 +414,18 @@ func getControllerManagerCommand(cfg *kubeadmapi.MasterConfiguration, selfHosted if cfg.Networking.PodSubnet != "" { command = append(command, "--allocate-node-cidrs=true", "--cluster-cidr="+cfg.Networking.PodSubnet) } - return command } func getSchedulerCommand(cfg *kubeadmapi.MasterConfiguration, selfHosted bool) []string { - var command []string - - // self-hosted apiserver needs to wait on a lock - if selfHosted { - command = []string{"/usr/bin/flock", "--exclusive", "--timeout=30", "/var/lock/api-server.lock"} - } - defaultArguments := map[string]string{ "address": "127.0.0.1", "leader-elect": "true", "kubeconfig": filepath.Join(kubeadmapi.GlobalEnvParams.KubernetesDir, kubeadmconstants.SchedulerKubeConfigFileName), } - command = getComponentBaseCommand(scheduler) + command := []string{"kube-scheduler"} command = append(command, getExtraParameters(cfg.SchedulerExtraArgs, defaultArguments)...) - return command } diff --git a/cmd/kubeadm/app/master/manifests_test.go b/cmd/kubeadm/app/master/manifests_test.go index 2ff66df5402..c2b29af2cdb 100644 --- a/cmd/kubeadm/app/master/manifests_test.go +++ b/cmd/kubeadm/app/master/manifests_test.go @@ -478,35 +478,6 @@ func TestComponentPod(t *testing.T) { } } -func TestGetComponentBaseCommand(t *testing.T) { - var tests = []struct { - c string - expected []string - }{ - { - c: "foo", - expected: []string{"kube-foo", "--v=2"}, - }, - { - c: "bar", - expected: []string{"kube-bar", "--v=2"}, - }, - } - - for _, rt := range tests { - actual := getComponentBaseCommand(rt.c) - for i := range actual { - if actual[i] != rt.expected[i] { - t.Errorf( - "failed getComponentBaseCommand:\n\texpected: %s\n\t actual: %s", - rt.expected[i], - actual[i], - ) - } - } - } -} - func TestGetAPIServerCommand(t *testing.T) { var tests = []struct { cfg *kubeadmapi.MasterConfiguration @@ -567,9 +538,9 @@ func TestGetAPIServerCommand(t *testing.T) { "--secure-port=123", "--allow-privileged=true", "--kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname", + "--experimental-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", - "--experimental-bootstrap-token-auth=true", "--requestheader-username-headers=X-Remote-User", "--requestheader-group-headers=X-Remote-Group", "--requestheader-extra-headers-prefix=X-Remote-Extra-", @@ -726,25 +697,6 @@ func TestGetControllerManagerCommand(t *testing.T) { "--controllers=*,bootstrapsigner,tokencleaner", }, }, - { - cfg: &kubeadmapi.MasterConfiguration{ - CertificatesDir: testCertsDir, - KubernetesVersion: "v1.6.4", - }, - expected: []string{ - "kube-controller-manager", - "--address=127.0.0.1", - "--leader-elect=true", - "--kubeconfig=" + kubeadmapi.GlobalEnvParams.KubernetesDir + "/controller-manager.conf", - "--root-ca-file=" + testCertsDir + "/ca.crt", - "--service-account-private-key-file=" + testCertsDir + "/sa.key", - "--cluster-signing-cert-file=" + testCertsDir + "/ca.crt", - "--cluster-signing-key-file=" + testCertsDir + "/ca.key", - "--use-service-account-credentials=true", - "--controllers=*,bootstrapsigner,tokencleaner", - "--insecure-experimental-approve-all-kubelet-csrs-for-group=system:bootstrappers", - }, - }, { cfg: &kubeadmapi.MasterConfiguration{ CloudProvider: "foo", @@ -998,18 +950,3 @@ func TestGetExtraParameters(t *testing.T) { } } } - -func TestVersionCompare(t *testing.T) { - versions := []string{ - "v1.7.0-alpha.1", - "v1.7.0-beta.0", - "v1.7.0-rc.0", - "v1.7.0", - "v1.7.1", - } - for _, v := range versions { - if !version.MustParseSemantic(v).AtLeast(kubeadmconstants.MinimumAPIAggregationVersion) { - t.Errorf("err") - } - } -} From 643afd3ffcc51c4694ffcfd9dab654253d590259 Mon Sep 17 00:00:00 2001 From: FengyunPan Date: Fri, 30 Jun 2017 18:55:53 +0800 Subject: [PATCH 153/448] Fix deleting empty monitors Fix #48094 When create-monitor of cloud-config is false, pool has not monitor and can not delete empty monitor. --- .../providers/openstack/openstack_loadbalancer.go | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/pkg/cloudprovider/providers/openstack/openstack_loadbalancer.go b/pkg/cloudprovider/providers/openstack/openstack_loadbalancer.go index 413e7750288..0de9803008a 100644 --- a/pkg/cloudprovider/providers/openstack/openstack_loadbalancer.go +++ b/pkg/cloudprovider/providers/openstack/openstack_loadbalancer.go @@ -763,9 +763,13 @@ func (lbaas *LbaasV2) EnsureLoadBalancer(clusterName string, apiService *v1.Serv } waitLoadbalancerActiveProvisioningStatus(lbaas.network, loadbalancer.ID) monitorID = monitor.ID + } else if lbaas.opts.CreateMonitor == false { + glog.V(4).Infof("Do not create monitor for pool %s when create-monitor is false", pool.ID) } - glog.V(4).Infof("Monitor for pool %s: %s", pool.ID, monitorID) + if monitorID != "" { + glog.V(4).Infof("Monitor for pool %s: %s", pool.ID, monitorID) + } } // All remaining listeners are obsolete, delete @@ -1106,7 +1110,10 @@ func (lbaas *LbaasV2) EnsureLoadBalancerDeleted(clusterName string, service *v1. return fmt.Errorf("Error getting pool for listener %s: %v", listener.ID, err) } poolIDs = append(poolIDs, pool.ID) - monitorIDs = append(monitorIDs, pool.MonitorID) + // If create-monitor of cloud-config is false, pool has not monitor. + if pool.MonitorID != "" { + monitorIDs = append(monitorIDs, pool.MonitorID) + } } // get all members associated with each poolIDs From 5b8ad3f7c5f1e00261b481036955adff03022440 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Tue, 6 Jun 2017 10:27:35 -0500 Subject: [PATCH 154/448] kubelet: remove unused bandwidth shaping teardown code Since v1.5 and the removal of --configure-cbr0: 0800df74abab11ba43ac53b345653e4b814ed77b "Remove the legacy networking mode --configure-cbr0" kubelet hasn't done any shaping operations internally. They have all been delegated to network plugins like kubenet or external CNI plugins. But some shaping code was still left in kubelet, so remove it now that it's unused. --- pkg/kubelet/BUILD | 2 - pkg/kubelet/kubelet.go | 27 ------- pkg/kubelet/kubelet_network.go | 47 ----------- pkg/kubelet/kubelet_network_test.go | 80 ------------------- pkg/kubelet/kubelet_pods.go | 6 -- .../network/kubenet/kubenet_linux_test.go | 2 +- 6 files changed, 1 insertion(+), 163 deletions(-) diff --git a/pkg/kubelet/BUILD b/pkg/kubelet/BUILD index 9880249c4e3..2f9d71700e0 100644 --- a/pkg/kubelet/BUILD +++ b/pkg/kubelet/BUILD @@ -96,7 +96,6 @@ go_library( "//pkg/security/apparmor:go_default_library", "//pkg/securitycontext:go_default_library", "//pkg/util:go_default_library", - "//pkg/util/bandwidth:go_default_library", "//pkg/util/dbus:go_default_library", "//pkg/util/exec:go_default_library", "//pkg/util/io:go_default_library", @@ -201,7 +200,6 @@ go_test( "//pkg/kubelet/util/queue:go_default_library", "//pkg/kubelet/util/sliceutils:go_default_library", "//pkg/kubelet/volumemanager:go_default_library", - "//pkg/util/bandwidth:go_default_library", "//pkg/util/mount:go_default_library", "//pkg/version:go_default_library", "//pkg/volume:go_default_library", diff --git a/pkg/kubelet/kubelet.go b/pkg/kubelet/kubelet.go index bdbf2aaddaf..b969f7830b9 100644 --- a/pkg/kubelet/kubelet.go +++ b/pkg/kubelet/kubelet.go @@ -102,7 +102,6 @@ import ( "k8s.io/kubernetes/pkg/kubelet/util/sliceutils" "k8s.io/kubernetes/pkg/kubelet/volumemanager" "k8s.io/kubernetes/pkg/security/apparmor" - "k8s.io/kubernetes/pkg/util/bandwidth" utildbus "k8s.io/kubernetes/pkg/util/dbus" utilexec "k8s.io/kubernetes/pkg/util/exec" kubeio "k8s.io/kubernetes/pkg/util/io" @@ -1027,10 +1026,6 @@ type Kubelet struct { // clusterDomain and clusterDNS. resolverConfig string - // Optionally shape the bandwidth of a pod - // TODO: remove when kubenet plugin is ready - shaper bandwidth.BandwidthShaper - // Information about the ports which are opened by daemons on Node running this Kubelet server. daemonEndpoints *v1.NodeDaemonEndpoints @@ -1632,28 +1627,6 @@ func (kl *Kubelet) syncPod(o syncPodOptions) error { return err } - // early successful exit if pod is not bandwidth-constrained - if !kl.shapingEnabled() { - return nil - } - - // Update the traffic shaping for the pod's ingress and egress limits - ingress, egress, err := bandwidth.ExtractPodBandwidthResources(pod.Annotations) - if err != nil { - return err - } - if egress != nil || ingress != nil { - if kubecontainer.IsHostNetworkPod(pod) { - kl.recorder.Event(pod, v1.EventTypeWarning, events.HostNetworkNotSupported, "Bandwidth shaping is not currently supported on the host network") - } else if kl.shaper != nil { - if len(apiPodStatus.PodIP) > 0 { - err = kl.shaper.ReconcileCIDR(fmt.Sprintf("%s/32", apiPodStatus.PodIP), egress, ingress) - } - } else { - kl.recorder.Event(pod, v1.EventTypeWarning, events.UndefinedShaper, "Pod requests bandwidth shaping, but the shaper is undefined") - } - } - return nil } diff --git a/pkg/kubelet/kubelet_network.go b/pkg/kubelet/kubelet_network.go index 5ac13653ac5..8d8b7472eb3 100644 --- a/pkg/kubelet/kubelet_network.go +++ b/pkg/kubelet/kubelet_network.go @@ -25,10 +25,8 @@ import ( "github.com/golang/glog" "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/util/sets" "k8s.io/kubernetes/pkg/apis/componentconfig" "k8s.io/kubernetes/pkg/kubelet/network" - "k8s.io/kubernetes/pkg/util/bandwidth" utiliptables "k8s.io/kubernetes/pkg/util/iptables" ) @@ -244,51 +242,6 @@ func (kl *Kubelet) parseResolvConf(reader io.Reader) (nameservers []string, sear return nameservers, searches, nil } -// cleanupBandwidthLimits updates the status of bandwidth-limited containers -// and ensures that only the appropriate CIDRs are active on the node. -func (kl *Kubelet) cleanupBandwidthLimits(allPods []*v1.Pod) error { - if kl.shaper == nil { - return nil - } - currentCIDRs, err := kl.shaper.GetCIDRs() - if err != nil { - return err - } - possibleCIDRs := sets.String{} - for ix := range allPods { - pod := allPods[ix] - ingress, egress, err := bandwidth.ExtractPodBandwidthResources(pod.Annotations) - if err != nil { - return err - } - if ingress == nil && egress == nil { - glog.V(8).Infof("Not a bandwidth limited container...") - continue - } - status, found := kl.statusManager.GetPodStatus(pod.UID) - if !found { - // TODO(random-liu): Cleanup status get functions. (issue #20477) - s, err := kl.containerRuntime.GetPodStatus(pod.UID, pod.Name, pod.Namespace) - if err != nil { - return err - } - status = kl.generateAPIPodStatus(pod, s) - } - if status.Phase == v1.PodRunning { - possibleCIDRs.Insert(fmt.Sprintf("%s/32", status.PodIP)) - } - } - for _, cidr := range currentCIDRs { - if !possibleCIDRs.Has(cidr) { - glog.V(2).Infof("Removing CIDR: %s (%v)", cidr, possibleCIDRs) - if err := kl.shaper.Reset(cidr); err != nil { - return err - } - } - } - return nil -} - // syncNetworkStatus updates the network state func (kl *Kubelet) syncNetworkStatus() { // For cri integration, network state will be updated in updateRuntimeUp, diff --git a/pkg/kubelet/kubelet_network_test.go b/pkg/kubelet/kubelet_network_test.go index dc68b882681..5de1c582eda 100644 --- a/pkg/kubelet/kubelet_network_test.go +++ b/pkg/kubelet/kubelet_network_test.go @@ -26,7 +26,6 @@ import ( "github.com/stretchr/testify/require" "k8s.io/api/core/v1" "k8s.io/client-go/tools/record" - "k8s.io/kubernetes/pkg/util/bandwidth" ) func TestNodeIPParam(t *testing.T) { @@ -184,85 +183,6 @@ func TestComposeDNSSearch(t *testing.T) { } } -func TestCleanupBandwidthLimits(t *testing.T) { - testPod := func(name, ingress string) *v1.Pod { - pod := podWithUidNameNs("", name, "") - - if len(ingress) != 0 { - pod.Annotations["kubernetes.io/ingress-bandwidth"] = ingress - } - - return pod - } - - // TODO(random-liu): We removed the test case for pod status not cached here. We should add a higher - // layer status getter function and test that function instead. - tests := []struct { - status *v1.PodStatus - pods []*v1.Pod - inputCIDRs []string - expectResetCIDRs []string - name string - }{ - { - status: &v1.PodStatus{ - PodIP: "1.2.3.4", - Phase: v1.PodRunning, - }, - pods: []*v1.Pod{ - testPod("foo", "10M"), - testPod("bar", ""), - }, - inputCIDRs: []string{"1.2.3.4/32", "2.3.4.5/32", "5.6.7.8/32"}, - expectResetCIDRs: []string{"2.3.4.5/32", "5.6.7.8/32"}, - name: "pod running", - }, - { - status: &v1.PodStatus{ - PodIP: "1.2.3.4", - Phase: v1.PodFailed, - }, - pods: []*v1.Pod{ - testPod("foo", "10M"), - testPod("bar", ""), - }, - inputCIDRs: []string{"1.2.3.4/32", "2.3.4.5/32", "5.6.7.8/32"}, - expectResetCIDRs: []string{"1.2.3.4/32", "2.3.4.5/32", "5.6.7.8/32"}, - name: "pod not running", - }, - { - status: &v1.PodStatus{ - PodIP: "1.2.3.4", - Phase: v1.PodFailed, - }, - pods: []*v1.Pod{ - testPod("foo", ""), - testPod("bar", ""), - }, - inputCIDRs: []string{"1.2.3.4/32", "2.3.4.5/32", "5.6.7.8/32"}, - expectResetCIDRs: []string{"1.2.3.4/32", "2.3.4.5/32", "5.6.7.8/32"}, - name: "no bandwidth limits", - }, - } - for _, test := range tests { - shaper := &bandwidth.FakeShaper{ - CIDRs: test.inputCIDRs, - } - - testKube := newTestKubelet(t, false /* controllerAttachDetachEnabled */) - defer testKube.Cleanup() - testKube.kubelet.shaper = shaper - - for _, pod := range test.pods { - testKube.kubelet.statusManager.SetPodStatus(pod, *test.status) - } - - err := testKube.kubelet.cleanupBandwidthLimits(test.pods) - assert.NoError(t, err, "test [%s]", test.name) - assert.EqualValues(t, test.expectResetCIDRs, shaper.ResetCIDRs, "test[%s]", test.name) - } -} - func TestGetIPTablesMark(t *testing.T) { tests := []struct { bit int diff --git a/pkg/kubelet/kubelet_pods.go b/pkg/kubelet/kubelet_pods.go index 2784b433f1c..e0faebf4574 100644 --- a/pkg/kubelet/kubelet_pods.go +++ b/pkg/kubelet/kubelet_pods.go @@ -893,12 +893,6 @@ func (kl *Kubelet) HandlePodCleanups() error { // Remove any orphaned mirror pods. kl.podManager.DeleteOrphanedMirrorPods() - // Clear out any old bandwidth rules - err = kl.cleanupBandwidthLimits(allPods) - if err != nil { - glog.Errorf("Failed cleaning up bandwidth limits: %v", err) - } - // Remove any cgroups in the hierarchy for pods that are no longer running. if kl.cgroupsPerQOS { kl.cleanupOrphanedPodCgroups(cgroupPods, activePods) diff --git a/pkg/kubelet/network/kubenet/kubenet_linux_test.go b/pkg/kubelet/network/kubenet/kubenet_linux_test.go index c3fad8ca3f2..2e5f5a42dfb 100644 --- a/pkg/kubelet/network/kubenet/kubenet_linux_test.go +++ b/pkg/kubelet/network/kubenet/kubenet_linux_test.go @@ -125,7 +125,7 @@ func TestGetPodNetworkStatus(t *testing.T) { } } -// TestTeardownBeforeSetUp tests that a `TearDown` call does call +// TestTeardownCallsShaper tests that a `TearDown` call does call // `shaper.Reset` func TestTeardownCallsShaper(t *testing.T) { fexec := &exec.FakeExec{ From 36a54bd5a41edcee515d4629b285b4080201d023 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Tue, 6 Jun 2017 11:34:11 -0500 Subject: [PATCH 155/448] kubelet: remove NET_PLUGIN_CAPABILITY_SHAPING This was effectively unused with v1.5 and later when kubelet stopped doing internal shaping and delegated all shaping to plugins. --- pkg/kubelet/kubelet_network.go | 19 ------------------- pkg/kubelet/network/kubenet/kubenet_linux.go | 2 +- pkg/kubelet/network/plugins.go | 6 ------ 3 files changed, 1 insertion(+), 26 deletions(-) diff --git a/pkg/kubelet/kubelet_network.go b/pkg/kubelet/kubelet_network.go index 8d8b7472eb3..4e1a971bae5 100644 --- a/pkg/kubelet/kubelet_network.go +++ b/pkg/kubelet/kubelet_network.go @@ -280,25 +280,6 @@ func (kl *Kubelet) updatePodCIDR(cidr string) { kl.runtimeState.setPodCIDR(cidr) } -// shapingEnabled returns whether traffic shaping is enabled. -func (kl *Kubelet) shapingEnabled() bool { - // Disable shaping if a network plugin is defined and supports shaping - if kl.networkPlugin != nil && kl.networkPlugin.Capabilities().Has(network.NET_PLUGIN_CAPABILITY_SHAPING) { - return false - } - // This is not strictly true but we need to figure out how to handle - // bandwidth shaping anyway. If the kubelet doesn't have a networkPlugin, - // it could mean: - // a. the kubelet is responsible for bandwidth shaping - // b. the kubelet is using cri, and the cri has a network plugin - // Today, the only plugin that understands bandwidth shaping is kubenet, and - // it doesn't support bandwidth shaping when invoked through cri, so it - // effectively boils down to letting the kubelet decide how to handle - // shaping annotations. The combination of (cri + network plugin that - // handles bandwidth shaping) may not work because of this. - return true -} - // syncNetworkUtil ensures the network utility are present on host. // Network util includes: // 1. In nat table, KUBE-MARK-DROP rule to mark connections for dropping diff --git a/pkg/kubelet/network/kubenet/kubenet_linux.go b/pkg/kubelet/network/kubenet/kubenet_linux.go index 55a769f71a0..50a83dae828 100644 --- a/pkg/kubelet/network/kubenet/kubenet_linux.go +++ b/pkg/kubelet/network/kubenet/kubenet_linux.go @@ -304,7 +304,7 @@ func (plugin *kubenetNetworkPlugin) Name() string { } func (plugin *kubenetNetworkPlugin) Capabilities() utilsets.Int { - return utilsets.NewInt(network.NET_PLUGIN_CAPABILITY_SHAPING) + return utilsets.NewInt() } // setup sets up networking through CNI using the given ns/name and sandbox ID. diff --git a/pkg/kubelet/network/plugins.go b/pkg/kubelet/network/plugins.go index 78b11550c87..53856f78a3c 100644 --- a/pkg/kubelet/network/plugins.go +++ b/pkg/kubelet/network/plugins.go @@ -43,12 +43,6 @@ const DefaultPluginName = "kubernetes.io/no-op" const NET_PLUGIN_EVENT_POD_CIDR_CHANGE = "pod-cidr-change" const NET_PLUGIN_EVENT_POD_CIDR_CHANGE_DETAIL_CIDR = "pod-cidr" -// Plugin capabilities -const ( - // Indicates the plugin handles Kubernetes bandwidth shaping annotations internally - NET_PLUGIN_CAPABILITY_SHAPING int = 1 -) - // Plugin is an interface to network plugins for the kubelet type NetworkPlugin interface { // Init initializes the plugin. This will be called exactly once From cd34d8f80d2e1ae3fbea0cc2b4d33de149d281da Mon Sep 17 00:00:00 2001 From: Konstantinos Tsakalozos Date: Fri, 30 Jun 2017 20:24:35 +0300 Subject: [PATCH 156/448] Ensure get_password is accessing a file that exists. --- .../layers/kubernetes-master/reactive/kubernetes_master.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cluster/juju/layers/kubernetes-master/reactive/kubernetes_master.py b/cluster/juju/layers/kubernetes-master/reactive/kubernetes_master.py index cd21be31c08..0bc39a58404 100644 --- a/cluster/juju/layers/kubernetes-master/reactive/kubernetes_master.py +++ b/cluster/juju/layers/kubernetes-master/reactive/kubernetes_master.py @@ -920,9 +920,9 @@ def setup_tokens(token, username, user): def get_password(csv_fname, user): '''Get the password of user within the csv file provided.''' root_cdk = '/root/cdk' - if not os.path.isdir(root_cdk): - return None tokens_fname = os.path.join(root_cdk, csv_fname) + if not os.path.isfile(tokens_fname): + return None with open(tokens_fname, 'r') as stream: for line in stream: record = line.split(',') From 74fde1893edc0c456e785a441e267d2e1c3bc129 Mon Sep 17 00:00:00 2001 From: Johannes Scheuermann Date: Fri, 30 Jun 2017 20:41:34 +0200 Subject: [PATCH 157/448] Add bazel build file --- vendor/github.com/quobyte/api/BUILD | 31 +++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 vendor/github.com/quobyte/api/BUILD diff --git a/vendor/github.com/quobyte/api/BUILD b/vendor/github.com/quobyte/api/BUILD new file mode 100644 index 00000000000..84fec6cd094 --- /dev/null +++ b/vendor/github.com/quobyte/api/BUILD @@ -0,0 +1,31 @@ +package(default_visibility = ["//visibility:public"]) + +licenses(["notice"]) + +load( + "@io_bazel_rules_go//go:def.bzl", + "go_library", +) + +go_library( + name = "go_default_library", + srcs = [ + "quobyte.go", + "rpc_client.go", + "types.go", + ], + tags = ["automanaged"], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], +) From 2ee08591b07c18d93367aba202a54f5d03ce11b0 Mon Sep 17 00:00:00 2001 From: Matt Liggett Date: Thu, 29 Jun 2017 13:59:29 -0700 Subject: [PATCH 158/448] Return a slightly more verbose error when "go get" fails. --- hack/e2e.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/hack/e2e.go b/hack/e2e.go index 889754a6681..bc58a0ad8cf 100644 --- a/hack/e2e.go +++ b/hack/e2e.go @@ -144,8 +144,9 @@ func (t tester) getKubetest(get bool, old time.Duration) (string, error) { return "", fmt.Errorf("Cannot install kubetest until $GOPATH is set") } log.Print("Updating kubetest binary...") - if err = t.wait("go", "get", "-u", "k8s.io/test-infra/kubetest"); err != nil { - return "", err // Could not upgrade + cmd := []string{"go", "get", "-u", "k8s.io/test-infra/kubetest"} + if err = t.wait(cmd[0], cmd[1:]...); err != nil { + return "", fmt.Errorf("%s: %v", strings.Join(cmd, " "), err) // Could not upgrade } if p, err = t.lookKubetest(); err != nil { return "", err // Cannot find kubetest From 7b6727f7f7e09ddedd37b42d4a4b6ee433413ef1 Mon Sep 17 00:00:00 2001 From: Faraaz Khan Date: Thu, 29 Jun 2017 05:15:49 +0000 Subject: [PATCH 159/448] allow heapster clusterrole to see deployments --- plugin/pkg/auth/authorizer/rbac/bootstrappolicy/policy.go | 1 + .../rbac/bootstrappolicy/testdata/cluster-roles.yaml | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/plugin/pkg/auth/authorizer/rbac/bootstrappolicy/policy.go b/plugin/pkg/auth/authorizer/rbac/bootstrappolicy/policy.go index 1697ad680d9..e2693416b39 100644 --- a/plugin/pkg/auth/authorizer/rbac/bootstrappolicy/policy.go +++ b/plugin/pkg/auth/authorizer/rbac/bootstrappolicy/policy.go @@ -243,6 +243,7 @@ func ClusterRoles() []rbac.ClusterRole { 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(), }, }, { diff --git a/plugin/pkg/auth/authorizer/rbac/bootstrappolicy/testdata/cluster-roles.yaml b/plugin/pkg/auth/authorizer/rbac/bootstrappolicy/testdata/cluster-roles.yaml index d5c47f0fa6d..939d68ac457 100644 --- a/plugin/pkg/auth/authorizer/rbac/bootstrappolicy/testdata/cluster-roles.yaml +++ b/plugin/pkg/auth/authorizer/rbac/bootstrappolicy/testdata/cluster-roles.yaml @@ -404,6 +404,14 @@ items: - get - list - watch + - apiGroups: + - extensions + resources: + - deployments + verbs: + - get + - list + - watch - apiVersion: rbac.authorization.k8s.io/v1beta1 kind: ClusterRole metadata: From 36621847863748dbad34079befef317c6a93d841 Mon Sep 17 00:00:00 2001 From: Clayton Coleman Date: Sun, 25 Jun 2017 14:42:22 -0500 Subject: [PATCH 160/448] meta.EachListItem should support runtime.Unstructured Allows callers to iterate over that construct. --- .../k8s.io/apimachinery/pkg/api/meta/help.go | 3 ++ .../apis/meta/v1/unstructured/unstructured.go | 33 +++++++++++++++++++ .../apimachinery/pkg/runtime/interfaces.go | 8 +++-- 3 files changed, 42 insertions(+), 2 deletions(-) diff --git a/staging/src/k8s.io/apimachinery/pkg/api/meta/help.go b/staging/src/k8s.io/apimachinery/pkg/api/meta/help.go index 9e0fb152ade..c70b3d2b6c7 100644 --- a/staging/src/k8s.io/apimachinery/pkg/api/meta/help.go +++ b/staging/src/k8s.io/apimachinery/pkg/api/meta/help.go @@ -67,6 +67,9 @@ func GetItemsPtr(list runtime.Object) (interface{}, error) { // EachListItem invokes fn on each runtime.Object in the list. Any error immediately terminates // the loop. func EachListItem(obj runtime.Object, fn func(runtime.Object) error) error { + if unstructured, ok := obj.(runtime.Unstructured); ok { + return unstructured.EachListItem(fn) + } // TODO: Change to an interface call? itemsPtr, err := GetItemsPtr(obj) if err != nil { diff --git a/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/unstructured.go b/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/unstructured.go index e6cf0934a50..5d1aeb0bcb9 100644 --- a/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/unstructured.go +++ b/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/unstructured.go @@ -69,6 +69,39 @@ func (obj *Unstructured) IsList() bool { } func (obj *UnstructuredList) IsList() bool { return true } +func (obj *Unstructured) EachListItem(fn func(runtime.Object) error) error { + if obj.Object == nil { + return fmt.Errorf("content is not a list") + } + field, ok := obj.Object["items"] + if !ok { + return fmt.Errorf("content is not a list") + } + items, ok := field.([]interface{}) + if !ok { + return nil + } + for _, item := range items { + child, ok := item.(map[string]interface{}) + if !ok { + return fmt.Errorf("items member is not an object") + } + if err := fn(&Unstructured{Object: child}); err != nil { + return err + } + } + return nil +} + +func (obj *UnstructuredList) EachListItem(fn func(runtime.Object) error) error { + for i := range obj.Items { + if err := fn(&obj.Items[i]); err != nil { + return err + } + } + return nil +} + func (obj *Unstructured) UnstructuredContent() map[string]interface{} { if obj.Object == nil { obj.Object = make(map[string]interface{}) diff --git a/staging/src/k8s.io/apimachinery/pkg/runtime/interfaces.go b/staging/src/k8s.io/apimachinery/pkg/runtime/interfaces.go index fcb18ba111f..281f8d23c7c 100644 --- a/staging/src/k8s.io/apimachinery/pkg/runtime/interfaces.go +++ b/staging/src/k8s.io/apimachinery/pkg/runtime/interfaces.go @@ -242,10 +242,14 @@ type Unstructured interface { // IsUnstructuredObject is a marker interface to allow objects that can be serialized but not introspected // to bypass conversion. IsUnstructuredObject() - // IsList returns true if this type is a list or matches the list convention - has an array called "items". - IsList() bool // UnstructuredContent returns a non-nil, mutable map of the contents of this object. Values may be // []interface{}, map[string]interface{}, or any primitive type. Contents are typically serialized to // and from JSON. UnstructuredContent() map[string]interface{} + // IsList returns true if this type is a list or matches the list convention - has an array called "items". + IsList() bool + // EachListItem should pass a single item out of the list as an Object to the provided function. Any + // error should terminate the iteration. If IsList() returns false, this method should return an error + // instead of calling the provided function. + EachListItem(func(Object) error) error } From dd04125b2c6150a51892e281013b46c8d9c72466 Mon Sep 17 00:00:00 2001 From: Matt Liggett Date: Tue, 13 Jun 2017 17:18:23 -0700 Subject: [PATCH 161/448] Add testing manifests for (node upgrade) etcd test. --- .../statefulset/etcd/pdb.yaml | 11 ++ .../statefulset/etcd/service.yaml | 18 ++ .../statefulset/etcd/statefulset.yaml | 178 ++++++++++++++++++ .../statefulset/etcd/tester.yaml | 24 +++ 4 files changed, 231 insertions(+) create mode 100644 test/e2e/testing-manifests/statefulset/etcd/pdb.yaml create mode 100644 test/e2e/testing-manifests/statefulset/etcd/service.yaml create mode 100644 test/e2e/testing-manifests/statefulset/etcd/statefulset.yaml create mode 100644 test/e2e/testing-manifests/statefulset/etcd/tester.yaml diff --git a/test/e2e/testing-manifests/statefulset/etcd/pdb.yaml b/test/e2e/testing-manifests/statefulset/etcd/pdb.yaml new file mode 100644 index 00000000000..64d68aac7c0 --- /dev/null +++ b/test/e2e/testing-manifests/statefulset/etcd/pdb.yaml @@ -0,0 +1,11 @@ +apiVersion: policy/v1beta1 +kind: PodDisruptionBudget +metadata: + name: etcd-pdb + labels: + pdb: etcd +spec: + minAvailable: 2 + selector: + matchLabels: + app: etcd diff --git a/test/e2e/testing-manifests/statefulset/etcd/service.yaml b/test/e2e/testing-manifests/statefulset/etcd/service.yaml new file mode 100644 index 00000000000..3932f04f42b --- /dev/null +++ b/test/e2e/testing-manifests/statefulset/etcd/service.yaml @@ -0,0 +1,18 @@ +apiVersion: v1 +kind: Service +metadata: + annotations: + service.alpha.kubernetes.io/tolerate-unready-endpoints: "true" +metadata: + name: etcd + labels: + app: etcd +spec: + ports: + - port: 2380 + name: etcd-server + - port: 2379 + name: etcd-client + clusterIP: None + selector: + app: etcd diff --git a/test/e2e/testing-manifests/statefulset/etcd/statefulset.yaml b/test/e2e/testing-manifests/statefulset/etcd/statefulset.yaml new file mode 100644 index 00000000000..c7800cd4e8f --- /dev/null +++ b/test/e2e/testing-manifests/statefulset/etcd/statefulset.yaml @@ -0,0 +1,178 @@ +apiVersion: apps/v1beta1 +kind: StatefulSet +metadata: + name: etcd + labels: + app: etcd +spec: + serviceName: etcd + replicas: 3 + template: + metadata: + name: etcd + labels: + app: etcd + spec: + containers: + - name: etcd + image: gcr.io/google_containers/etcd-amd64:2.2.5 + imagePullPolicy: Always + ports: + - containerPort: 2380 + name: peer + - containerPort: 2379 + name: client + resources: + requests: + cpu: 100m + memory: 512Mi + env: + - name: INITIAL_CLUSTER_SIZE + value: "3" + - name: SET_NAME + value: etcd + volumeMounts: + - name: datadir + mountPath: /var/run/etcd + lifecycle: + preStop: + exec: + command: + - "/bin/sh" + - "-ec" + - | + EPS="" + for i in $(seq 0 $((${INITIAL_CLUSTER_SIZE} - 1))); do + EPS="${EPS}${EPS:+,}http://${SET_NAME}-${i}.${SET_NAME}:2379" + done + + HOSTNAME=$(hostname) + + member_hash() { + etcdctl member list | grep http://${HOSTNAME}.${SET_NAME}:2380 | cut -d':' -f1 | cut -d'[' -f1 + } + + echo "Removing ${HOSTNAME} from etcd cluster" + + ETCDCTL_ENDPOINT=${EPS} etcdctl member remove $(member_hash) + if [ $? -eq 0 ]; then + # Remove everything otherwise the cluster will no longer scale-up + rm -rf /var/run/etcd/* + fi + command: + - "/bin/sh" + - "-ec" + - | + HOSTNAME=$(hostname) + + # store member id into PVC for later member replacement + collect_member() { + while ! etcdctl member list &>/dev/null; do sleep 1; done + etcdctl member list | grep http://${HOSTNAME}.${SET_NAME}:2380 | cut -d':' -f1 | cut -d'[' -f1 > /var/run/etcd/member_id + exit 0 + } + + eps() { + EPS="" + for i in $(seq 0 $((${INITIAL_CLUSTER_SIZE} - 1))); do + EPS="${EPS}${EPS:+,}http://${SET_NAME}-${i}.${SET_NAME}:2379" + done + echo ${EPS} + } + + member_hash() { + etcdctl member list | grep http://${HOSTNAME}.${SET_NAME}:2380 | cut -d':' -f1 | cut -d'[' -f1 + } + + # re-joining after failure? + if [ -e /var/run/etcd/default.etcd ]; then + echo "Re-joining etcd member" + member_id=$(cat /var/run/etcd/member_id) + + # re-join member + ETCDCTL_ENDPOINT=$(eps) etcdctl member update ${member_id} http://${HOSTNAME}.${SET_NAME}:2380 + exec etcd --name ${HOSTNAME} \ + --listen-peer-urls http://${HOSTNAME}.${SET_NAME}:2380 \ + --listen-client-urls http://${HOSTNAME}.${SET_NAME}:2379,http://127.0.0.1:2379 \ + --advertise-client-urls http://${HOSTNAME}.${SET_NAME}:2379 \ + --data-dir /var/run/etcd/default.etcd + fi + + # etcd-SET_ID + SET_ID=${HOSTNAME:5:${#HOSTNAME}} + + # adding a new member to existing cluster (assuming all initial pods are available) + if [ "${SET_ID}" -ge ${INITIAL_CLUSTER_SIZE} ]; then + export ETCDCTL_ENDPOINT=$(eps) + + # member already added? + MEMBER_HASH=$(member_hash) + if [ -n "${MEMBER_HASH}" ]; then + # the member hash exists but for some reason etcd failed + # as the datadir has not be created, we can remove the member + # and retrieve new hash + etcdctl member remove ${MEMBER_HASH} + fi + + echo "Adding new member" + etcdctl member add ${HOSTNAME} http://${HOSTNAME}.${SET_NAME}:2380 | grep "^ETCD_" > /var/run/etcd/new_member_envs + + if [ $? -ne 0 ]; then + echo "Exiting" + rm -f /var/run/etcd/new_member_envs + exit 1 + fi + + cat /var/run/etcd/new_member_envs + source /var/run/etcd/new_member_envs + + collect_member & + + exec etcd --name ${HOSTNAME} \ + --listen-peer-urls http://${HOSTNAME}.${SET_NAME}:2380 \ + --listen-client-urls http://${HOSTNAME}.${SET_NAME}:2379,http://127.0.0.1:2379 \ + --advertise-client-urls http://${HOSTNAME}.${SET_NAME}:2379 \ + --data-dir /var/run/etcd/default.etcd \ + --initial-advertise-peer-urls http://${HOSTNAME}.${SET_NAME}:2380 \ + --initial-cluster ${ETCD_INITIAL_CLUSTER} \ + --initial-cluster-state ${ETCD_INITIAL_CLUSTER_STATE} + fi + + for i in $(seq 0 $((${INITIAL_CLUSTER_SIZE} - 1))); do + while true; do + echo "Waiting for ${SET_NAME}-${i}.${SET_NAME} to come up" + ping -W 1 -c 1 ${SET_NAME}-${i}.${SET_NAME} > /dev/null && break + sleep 1s + done + done + + PEERS="" + for i in $(seq 0 $((${INITIAL_CLUSTER_SIZE} - 1))); do + PEERS="${PEERS}${PEERS:+,}${SET_NAME}-${i}=http://${SET_NAME}-${i}.${SET_NAME}:2380" + done + + collect_member & + + # join member + exec etcd --name ${HOSTNAME} \ + --initial-advertise-peer-urls http://${HOSTNAME}.${SET_NAME}:2380 \ + --listen-peer-urls http://${HOSTNAME}.${SET_NAME}:2380 \ + --listen-client-urls http://${HOSTNAME}.${SET_NAME}:2379,http://127.0.0.1:2379 \ + --advertise-client-urls http://${HOSTNAME}.${SET_NAME}:2379 \ + --initial-cluster-token etcd-cluster-1 \ + --initial-cluster ${PEERS} \ + --initial-cluster-state new \ + --data-dir /var/run/etcd/default.etcd + volumeClaimTemplates: + - metadata: + name: datadir + annotations: + volume.alpha.kubernetes.io/storage-class: anything + spec: + accessModes: + - "ReadWriteOnce" + resources: + requests: + # upstream recommended max is 700M + storage: 1Gi + diff --git a/test/e2e/testing-manifests/statefulset/etcd/tester.yaml b/test/e2e/testing-manifests/statefulset/etcd/tester.yaml new file mode 100644 index 00000000000..c5ea0b90c14 --- /dev/null +++ b/test/e2e/testing-manifests/statefulset/etcd/tester.yaml @@ -0,0 +1,24 @@ +apiVersion: apps/v1beta1 +kind: Deployment +metadata: + name: etcd-test-server +spec: + replicas: 3 + template: + metadata: + labels: + app: test-server + spec: + containers: + - name: test-server + image: gcr.io/google-containers/etcd-statefulset-e2e-test:0.0 + imagePullPolicy: Always + ports: + - containerPort: 8080 + readinessProbe: + httpGet: + path: /healthz + port: 8080 + initialDelaySeconds: 2 + periodSeconds: 2 + From 8f7a26dfbe5d502eb0f17aa7ed249bec79cc4a47 Mon Sep 17 00:00:00 2001 From: Matt Liggett Date: Thu, 29 Jun 2017 17:03:25 -0700 Subject: [PATCH 162/448] Add (node upgrade) etcd test. --- test/e2e/upgrades/etcd.go | 199 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 199 insertions(+) create mode 100644 test/e2e/upgrades/etcd.go diff --git a/test/e2e/upgrades/etcd.go b/test/e2e/upgrades/etcd.go new file mode 100644 index 00000000000..aea9e08ec64 --- /dev/null +++ b/test/e2e/upgrades/etcd.go @@ -0,0 +1,199 @@ +/* +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 upgrades + +import ( + "encoding/json" + "fmt" + "io/ioutil" + "net/http" + "path/filepath" + "sync" + "time" + + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/wait" + "k8s.io/kubernetes/pkg/util/version" + "k8s.io/kubernetes/test/e2e/framework" +) + +const manifestPath = "test/e2e/testing-manifests/statefulset/etcd" + +type EtcdUpgradeTest struct { + ip string + successfulWrites int + ssTester *framework.StatefulSetTester +} + +func (EtcdUpgradeTest) Name() string { return "etcd-upgrade" } + +func (EtcdUpgradeTest) Skip(upgCtx UpgradeContext) bool { + minVersion := version.MustParseSemantic("1.6.0") + for _, vCtx := range upgCtx.Versions { + if vCtx.Version.LessThan(minVersion) { + return true + } + } + return false +} + +func kubectlCreate(ns, file string) { + path := filepath.Join(framework.TestContext.RepoRoot, manifestPath, file) + framework.RunKubectlOrDie("create", "-f", path, fmt.Sprintf("--namespace=%s", ns)) +} + +func (t *EtcdUpgradeTest) Setup(f *framework.Framework) { + ns := f.Namespace.Name + statefulsetPoll := 30 * time.Second + statefulsetTimeout := 10 * time.Minute + t.ssTester = framework.NewStatefulSetTester(f.ClientSet) + + By("Creating a PDB") + kubectlCreate(ns, "pdb.yaml") + + By("Creating an etcd StatefulSet") + t.ssTester.CreateStatefulSet(manifestPath, ns) + + By("Creating an etcd--test-server deployment") + kubectlCreate(ns, "tester.yaml") + + By("Getting the ingress IPs from the services") + err := wait.PollImmediate(statefulsetPoll, statefulsetTimeout, func() (bool, error) { + if t.ip = t.getServiceIP(f, ns, "test-server"); t.ip == "" { + return false, nil + } + if _, err := t.listUsers(); err != nil { + framework.Logf("Service endpoint is up but isn't responding") + return false, nil + } + return true, nil + }) + Expect(err).NotTo(HaveOccurred()) + framework.Logf("Service endpoint is up") + + By("Adding 2 dummy users") + Expect(t.addUser("Alice")).NotTo(HaveOccurred()) + Expect(t.addUser("Bob")).NotTo(HaveOccurred()) + t.successfulWrites = 2 + + By("Verifying that the users exist") + users, err := t.listUsers() + Expect(err).NotTo(HaveOccurred()) + Expect(len(users)).To(Equal(2)) +} + +func (t *EtcdUpgradeTest) listUsers() ([]string, error) { + r, err := http.Get(fmt.Sprintf("http://%s:8080/list", t.ip)) + if err != nil { + return nil, err + } + defer r.Body.Close() + if r.StatusCode != http.StatusOK { + b, err := ioutil.ReadAll(r.Body) + if err != nil { + return nil, err + } + return nil, fmt.Errorf(string(b)) + } + var names []string + if err := json.NewDecoder(r.Body).Decode(&names); err != nil { + return nil, err + } + return names, nil +} + +func (t *EtcdUpgradeTest) addUser(name string) error { + val := map[string][]string{"name": {name}} + r, err := http.PostForm(fmt.Sprintf("http://%s:8080/add", t.ip), val) + if err != nil { + return err + } + defer r.Body.Close() + if r.StatusCode != http.StatusOK { + b, err := ioutil.ReadAll(r.Body) + if err != nil { + return err + } + return fmt.Errorf(string(b)) + } + return nil +} + +func (t *EtcdUpgradeTest) getServiceIP(f *framework.Framework, ns, svcName string) string { + svc, err := f.ClientSet.CoreV1().Services(ns).Get(svcName, metav1.GetOptions{}) + Expect(err).NotTo(HaveOccurred()) + ingress := svc.Status.LoadBalancer.Ingress + if len(ingress) == 0 { + return "" + } + return ingress[0].IP +} + +func (t *EtcdUpgradeTest) Test(f *framework.Framework, done <-chan struct{}, upgrade UpgradeType) { + By("Continuously polling the database during upgrade.") + var ( + success, failures, writeAttempts, lastUserCount int + mu sync.Mutex + errors = map[string]int{} + ) + // Write loop. + go wait.Until(func() { + writeAttempts++ + if err := t.addUser(fmt.Sprintf("user-%d", writeAttempts)); err != nil { + framework.Logf("Unable to add user: %v", err) + mu.Lock() + errors[err.Error()]++ + mu.Unlock() + return + } + t.successfulWrites++ + }, 10*time.Millisecond, done) + // Read loop. + wait.Until(func() { + users, err := t.listUsers() + if err != nil { + framework.Logf("Could not retrieve users: %v", err) + failures++ + mu.Lock() + errors[err.Error()]++ + mu.Unlock() + return + } + success++ + lastUserCount = len(users) + }, 10*time.Millisecond, done) + framework.Logf("got %d users; want >=%d", lastUserCount, t.successfulWrites) + + Expect(lastUserCount >= t.successfulWrites).To(BeTrue()) + ratio := float64(success) / float64(success+failures) + framework.Logf("Successful gets %d/%d=%v", success, success+failures, ratio) + ratio = float64(t.successfulWrites) / float64(writeAttempts) + framework.Logf("Successful writes %d/%d=%v", t.successfulWrites, writeAttempts, ratio) + framework.Logf("Errors: %v", errors) + // TODO(maisem): tweak this value once we have a few test runs. + Expect(ratio > 0.75).To(BeTrue()) +} + +// Teardown does one final check of the data's availability. +func (t *EtcdUpgradeTest) Teardown(f *framework.Framework) { + users, err := t.listUsers() + Expect(err).NotTo(HaveOccurred()) + Expect(len(users) >= t.successfulWrites).To(BeTrue()) +} From f0ce897277bdb1f0a630f9c894d1049d1d689c0b Mon Sep 17 00:00:00 2001 From: ymqytw Date: Thu, 29 Jun 2017 15:14:52 -0700 Subject: [PATCH 163/448] move term to kubectl/util --- pkg/kubectl/cmd/BUILD | 4 ++-- pkg/kubectl/cmd/exec.go | 2 +- pkg/kubectl/cmd/exec_test.go | 2 +- pkg/kubectl/cmd/templates/BUILD | 2 +- pkg/kubectl/cmd/templates/templater.go | 2 +- pkg/kubectl/cmd/util/editor/BUILD | 2 +- pkg/kubectl/cmd/util/editor/editor.go | 2 +- pkg/kubectl/util/BUILD | 1 + pkg/{ => kubectl}/util/term/BUILD | 0 pkg/{ => kubectl}/util/term/resize.go | 0 pkg/{ => kubectl}/util/term/resizeevents.go | 0 pkg/{ => kubectl}/util/term/resizeevents_windows.go | 0 pkg/{ => kubectl}/util/term/setsize.go | 0 pkg/{ => kubectl}/util/term/setsize_unsupported.go | 0 pkg/{ => kubectl}/util/term/term.go | 0 pkg/{ => kubectl}/util/term/term_writer.go | 0 pkg/{ => kubectl}/util/term/term_writer_test.go | 0 pkg/kubelet/dockershim/BUILD | 2 +- pkg/kubelet/dockershim/exec.go | 4 ++-- pkg/kubelet/rkt/BUILD | 2 +- pkg/kubelet/rkt/rkt.go | 4 ++-- pkg/util/BUILD | 1 - 22 files changed, 15 insertions(+), 15 deletions(-) rename pkg/{ => kubectl}/util/term/BUILD (100%) rename pkg/{ => kubectl}/util/term/resize.go (100%) rename pkg/{ => kubectl}/util/term/resizeevents.go (100%) rename pkg/{ => kubectl}/util/term/resizeevents_windows.go (100%) rename pkg/{ => kubectl}/util/term/setsize.go (100%) rename pkg/{ => kubectl}/util/term/setsize_unsupported.go (100%) rename pkg/{ => kubectl}/util/term/term.go (100%) rename pkg/{ => kubectl}/util/term/term_writer.go (100%) rename pkg/{ => kubectl}/util/term/term_writer_test.go (100%) diff --git a/pkg/kubectl/cmd/BUILD b/pkg/kubectl/cmd/BUILD index aabaeec1885..c2198c2973d 100644 --- a/pkg/kubectl/cmd/BUILD +++ b/pkg/kubectl/cmd/BUILD @@ -94,6 +94,7 @@ go_library( "//pkg/kubectl/plugins:go_default_library", "//pkg/kubectl/resource:go_default_library", "//pkg/kubectl/util:go_default_library", + "//pkg/kubectl/util/term:go_default_library", "//pkg/kubelet/types:go_default_library", "//pkg/printers:go_default_library", "//pkg/printers/internalversion:go_default_library", @@ -101,7 +102,6 @@ go_library( "//pkg/util/i18n:go_default_library", "//pkg/util/interrupt:go_default_library", "//pkg/util/taints:go_default_library", - "//pkg/util/term:go_default_library", "//pkg/version:go_default_library", "//vendor/github.com/daviddengcn/go-colortext:go_default_library", "//vendor/github.com/docker/distribution/reference:go_default_library", @@ -214,11 +214,11 @@ go_test( "//pkg/kubectl/cmd/util/openapi:go_default_library", "//pkg/kubectl/plugins:go_default_library", "//pkg/kubectl/resource:go_default_library", + "//pkg/kubectl/util/term:go_default_library", "//pkg/printers:go_default_library", "//pkg/printers/internalversion:go_default_library", "//pkg/util/i18n:go_default_library", "//pkg/util/strings:go_default_library", - "//pkg/util/term:go_default_library", "//vendor/github.com/go-openapi/spec:go_default_library", "//vendor/github.com/spf13/cobra:go_default_library", "//vendor/github.com/stretchr/testify/assert:go_default_library", diff --git a/pkg/kubectl/cmd/exec.go b/pkg/kubectl/cmd/exec.go index 84d76f1a332..3ca48d9a689 100644 --- a/pkg/kubectl/cmd/exec.go +++ b/pkg/kubectl/cmd/exec.go @@ -32,9 +32,9 @@ 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/util/term" "k8s.io/kubernetes/pkg/util/i18n" "k8s.io/kubernetes/pkg/util/interrupt" - "k8s.io/kubernetes/pkg/util/term" ) var ( diff --git a/pkg/kubectl/cmd/exec_test.go b/pkg/kubectl/cmd/exec_test.go index 8d72c724bc4..6c57bbd80c0 100644 --- a/pkg/kubectl/cmd/exec_test.go +++ b/pkg/kubectl/cmd/exec_test.go @@ -35,7 +35,7 @@ import ( "k8s.io/client-go/tools/remotecommand" "k8s.io/kubernetes/pkg/api" cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing" - "k8s.io/kubernetes/pkg/util/term" + "k8s.io/kubernetes/pkg/kubectl/util/term" ) type fakeRemoteExecutor struct { diff --git a/pkg/kubectl/cmd/templates/BUILD b/pkg/kubectl/cmd/templates/BUILD index 4ee1ce4ab0f..7255c533561 100644 --- a/pkg/kubectl/cmd/templates/BUILD +++ b/pkg/kubectl/cmd/templates/BUILD @@ -19,7 +19,7 @@ go_library( "//build/visible_to:pkg_kubectl_cmd_templates_CONSUMERS", ], deps = [ - "//pkg/util/term:go_default_library", + "//pkg/kubectl/util/term:go_default_library", "//vendor/github.com/MakeNowJust/heredoc:go_default_library", "//vendor/github.com/russross/blackfriday:go_default_library", "//vendor/github.com/spf13/cobra:go_default_library", diff --git a/pkg/kubectl/cmd/templates/templater.go b/pkg/kubectl/cmd/templates/templater.go index 30c128ef3b2..27b76dc42b7 100644 --- a/pkg/kubectl/cmd/templates/templater.go +++ b/pkg/kubectl/cmd/templates/templater.go @@ -23,7 +23,7 @@ import ( "text/template" "unicode" - "k8s.io/kubernetes/pkg/util/term" + "k8s.io/kubernetes/pkg/kubectl/util/term" "github.com/spf13/cobra" flag "github.com/spf13/pflag" diff --git a/pkg/kubectl/cmd/util/editor/BUILD b/pkg/kubectl/cmd/util/editor/BUILD index 63544fd287d..328f1f3e55a 100644 --- a/pkg/kubectl/cmd/util/editor/BUILD +++ b/pkg/kubectl/cmd/util/editor/BUILD @@ -22,8 +22,8 @@ go_library( "//pkg/kubectl/cmd/util:go_default_library", "//pkg/kubectl/resource:go_default_library", "//pkg/kubectl/util/crlf:go_default_library", + "//pkg/kubectl/util/term:go_default_library", "//pkg/printers:go_default_library", - "//pkg/util/term:go_default_library", "//vendor/github.com/evanphx/json-patch:go_default_library", "//vendor/github.com/golang/glog:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", diff --git a/pkg/kubectl/cmd/util/editor/editor.go b/pkg/kubectl/cmd/util/editor/editor.go index 9f53ee7c758..a53e8c0970a 100644 --- a/pkg/kubectl/cmd/util/editor/editor.go +++ b/pkg/kubectl/cmd/util/editor/editor.go @@ -29,7 +29,7 @@ import ( "github.com/golang/glog" - "k8s.io/kubernetes/pkg/util/term" + "k8s.io/kubernetes/pkg/kubectl/util/term" ) const ( diff --git a/pkg/kubectl/util/BUILD b/pkg/kubectl/util/BUILD index 7742aac0725..fb4b1fdac61 100644 --- a/pkg/kubectl/util/BUILD +++ b/pkg/kubectl/util/BUILD @@ -31,6 +31,7 @@ filegroup( srcs = [ ":package-srcs", "//pkg/kubectl/util/crlf:all-srcs", + "//pkg/kubectl/util/term:all-srcs", ], tags = ["automanaged"], visibility = ["//build/visible_to:pkg_kubectl_util_CONSUMERS"], diff --git a/pkg/util/term/BUILD b/pkg/kubectl/util/term/BUILD similarity index 100% rename from pkg/util/term/BUILD rename to pkg/kubectl/util/term/BUILD diff --git a/pkg/util/term/resize.go b/pkg/kubectl/util/term/resize.go similarity index 100% rename from pkg/util/term/resize.go rename to pkg/kubectl/util/term/resize.go diff --git a/pkg/util/term/resizeevents.go b/pkg/kubectl/util/term/resizeevents.go similarity index 100% rename from pkg/util/term/resizeevents.go rename to pkg/kubectl/util/term/resizeevents.go diff --git a/pkg/util/term/resizeevents_windows.go b/pkg/kubectl/util/term/resizeevents_windows.go similarity index 100% rename from pkg/util/term/resizeevents_windows.go rename to pkg/kubectl/util/term/resizeevents_windows.go diff --git a/pkg/util/term/setsize.go b/pkg/kubectl/util/term/setsize.go similarity index 100% rename from pkg/util/term/setsize.go rename to pkg/kubectl/util/term/setsize.go diff --git a/pkg/util/term/setsize_unsupported.go b/pkg/kubectl/util/term/setsize_unsupported.go similarity index 100% rename from pkg/util/term/setsize_unsupported.go rename to pkg/kubectl/util/term/setsize_unsupported.go diff --git a/pkg/util/term/term.go b/pkg/kubectl/util/term/term.go similarity index 100% rename from pkg/util/term/term.go rename to pkg/kubectl/util/term/term.go diff --git a/pkg/util/term/term_writer.go b/pkg/kubectl/util/term/term_writer.go similarity index 100% rename from pkg/util/term/term_writer.go rename to pkg/kubectl/util/term/term_writer.go diff --git a/pkg/util/term/term_writer_test.go b/pkg/kubectl/util/term/term_writer_test.go similarity index 100% rename from pkg/util/term/term_writer_test.go rename to pkg/kubectl/util/term/term_writer_test.go diff --git a/pkg/kubelet/dockershim/BUILD b/pkg/kubelet/dockershim/BUILD index 915b6b8485d..a2b81a5ecc7 100644 --- a/pkg/kubelet/dockershim/BUILD +++ b/pkg/kubelet/dockershim/BUILD @@ -53,9 +53,9 @@ go_library( "//pkg/security/apparmor:go_default_library", "//pkg/util/exec:go_default_library", "//pkg/util/hash:go_default_library", - "//pkg/util/term:go_default_library", "//vendor/github.com/blang/semver:go_default_library", "//vendor/github.com/docker/docker/pkg/jsonmessage:go_default_library", + "//vendor/github.com/docker/docker/pkg/term:go_default_library", "//vendor/github.com/docker/engine-api/types:go_default_library", "//vendor/github.com/docker/engine-api/types/container:go_default_library", "//vendor/github.com/docker/engine-api/types/filters:go_default_library", diff --git a/pkg/kubelet/dockershim/exec.go b/pkg/kubelet/dockershim/exec.go index 1d73a8a8d5c..2855af3b0e7 100644 --- a/pkg/kubelet/dockershim/exec.go +++ b/pkg/kubelet/dockershim/exec.go @@ -23,13 +23,13 @@ import ( "os/exec" "time" + "github.com/docker/docker/pkg/term" dockertypes "github.com/docker/engine-api/types" "github.com/golang/glog" "k8s.io/client-go/tools/remotecommand" kubecontainer "k8s.io/kubernetes/pkg/kubelet/container" utilexec "k8s.io/kubernetes/pkg/util/exec" - "k8s.io/kubernetes/pkg/util/term" "k8s.io/kubernetes/pkg/kubelet/dockershim/libdocker" ) @@ -89,7 +89,7 @@ func (*NsenterExecHandler) ExecInContainer(client libdocker.Interface, container defer stdout.Close() kubecontainer.HandleResizing(resize, func(size remotecommand.TerminalSize) { - term.SetSize(p.Fd(), size) + term.SetWinsize(p.Fd(), &term.Winsize{Height: size.Height, Width: size.Width}) }) if stdin != nil { diff --git a/pkg/kubelet/rkt/BUILD b/pkg/kubelet/rkt/BUILD index 35abb2b2b73..f80e2c6c830 100644 --- a/pkg/kubelet/rkt/BUILD +++ b/pkg/kubelet/rkt/BUILD @@ -39,13 +39,13 @@ go_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/pkg/term:go_default_library", "//vendor/github.com/docker/engine-api/types:go_default_library", "//vendor/github.com/golang/glog:go_default_library", "//vendor/golang.org/x/net/context:go_default_library", diff --git a/pkg/kubelet/rkt/rkt.go b/pkg/kubelet/rkt/rkt.go index 8a1ff5e9e79..e4481e37d9a 100644 --- a/pkg/kubelet/rkt/rkt.go +++ b/pkg/kubelet/rkt/rkt.go @@ -38,6 +38,7 @@ import ( appctypes "github.com/appc/spec/schema/types" "github.com/coreos/go-systemd/unit" rktapi "github.com/coreos/rkt/api/v1alpha" + "github.com/docker/docker/pkg/term" "github.com/golang/glog" "golang.org/x/net/context" "google.golang.org/grpc" @@ -65,7 +66,6 @@ import ( utilexec "k8s.io/kubernetes/pkg/util/exec" "k8s.io/kubernetes/pkg/util/selinux" utilstrings "k8s.io/kubernetes/pkg/util/strings" - "k8s.io/kubernetes/pkg/util/term" ) const ( @@ -2175,7 +2175,7 @@ func (r *Runtime) ExecInContainer(containerID kubecontainer.ContainerID, cmd []s defer stdout.Close() kubecontainer.HandleResizing(resize, func(size remotecommand.TerminalSize) { - term.SetSize(p.Fd(), size) + term.SetWinsize(p.Fd(), &term.Winsize{Height: size.Height, Width: size.Width}) }) if stdin != nil { diff --git a/pkg/util/BUILD b/pkg/util/BUILD index 4d03d9cde70..c7048bed481 100644 --- a/pkg/util/BUILD +++ b/pkg/util/BUILD @@ -90,7 +90,6 @@ filegroup( "//pkg/util/system:all-srcs", "//pkg/util/tail:all-srcs", "//pkg/util/taints:all-srcs", - "//pkg/util/term:all-srcs", "//pkg/util/threading:all-srcs", "//pkg/util/tolerations:all-srcs", "//pkg/util/uuid:all-srcs", From 0c7f3c1963ffc4ab2b66a4ddee4ba74f2c187c60 Mon Sep 17 00:00:00 2001 From: Michelle Au Date: Fri, 30 Jun 2017 15:40:01 -0700 Subject: [PATCH 164/448] Add local volume bug to known issues --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 44729a1878d..3a6369a4869 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -873,6 +873,8 @@ API fields previously capable of storing and returning either `[]` and `null` vi can now store only `null` when created using the protobuf content-type or stored in etcd using protobuf serialization (the default in 1.6). JSON API clients should tolerate `null` values for such fields, and treat `null` and `[]` as equivalent in meaning unless specifically documented otherwise for a particular field. ([#44593](https://github.com/kubernetes/kubernetes/pull/44593)) +* Local volume source paths that are directories and not mount points fail to unmount. A fix is in process ([#48331](https://github.com/kubernetes/kubernetes/issues/48331)). + ## **Deprecations** ### Cluster provisioning scripts From 5bbb16381eedf6e986f3a38ac4d993580dff61fe Mon Sep 17 00:00:00 2001 From: Matt Liggett Date: Fri, 30 Jun 2017 15:42:16 -0700 Subject: [PATCH 165/448] update-bazel --- test/e2e/upgrades/BUILD | 1 + 1 file changed, 1 insertion(+) diff --git a/test/e2e/upgrades/BUILD b/test/e2e/upgrades/BUILD index 1b0cc573751..98082c71864 100644 --- a/test/e2e/upgrades/BUILD +++ b/test/e2e/upgrades/BUILD @@ -14,6 +14,7 @@ go_library( "configmaps.go", "daemonsets.go", "deployments.go", + "etcd.go", "horizontal_pod_autoscalers.go", "ingress.go", "job.go", From 7541496a4fa84b2da7d263083c689c764153075d Mon Sep 17 00:00:00 2001 From: Klaus Ma Date: Sun, 4 Jun 2017 19:02:46 +0800 Subject: [PATCH 166/448] Updated OWNERS_ALIASES for scheduler, and added scheduler integration test owners. --- OWNERS_ALIASES | 4 +++- plugin/pkg/scheduler/OWNERS | 12 ++---------- test/e2e/scheduling/OWNERS | 1 - test/integration/scheduler/OWNERS | 4 ++++ 4 files changed, 9 insertions(+), 12 deletions(-) create mode 100644 test/integration/scheduler/OWNERS diff --git a/OWNERS_ALIASES b/OWNERS_ALIASES index 6ac605625af..745a906d50b 100644 --- a/OWNERS_ALIASES +++ b/OWNERS_ALIASES @@ -3,11 +3,13 @@ aliases: - davidopp - timothysc - wojtek-t + - k82cn sig-scheduling: - davidopp + - bsalamat - timothysc - wojtek-t - - k82cn + - k82cn - jayunit100 sig-cli-maintainers: - adohe diff --git a/plugin/pkg/scheduler/OWNERS b/plugin/pkg/scheduler/OWNERS index 7b17cd0f2ee..d2792efd526 100644 --- a/plugin/pkg/scheduler/OWNERS +++ b/plugin/pkg/scheduler/OWNERS @@ -1,12 +1,4 @@ approvers: -- davidopp -- timothysc -- wojtek-t -- k82cn +- sig-scheduling-maintainers reviewers: -- davidopp -- bsalamat -- timothysc -- wojtek-t -- k82cn -- jayunit100 +- sig-scheduling diff --git a/test/e2e/scheduling/OWNERS b/test/e2e/scheduling/OWNERS index 731daf5f7e0..d2792efd526 100644 --- a/test/e2e/scheduling/OWNERS +++ b/test/e2e/scheduling/OWNERS @@ -1,5 +1,4 @@ approvers: - sig-scheduling-maintainers -- k82cn reviewers: - sig-scheduling diff --git a/test/integration/scheduler/OWNERS b/test/integration/scheduler/OWNERS new file mode 100644 index 00000000000..d2792efd526 --- /dev/null +++ b/test/integration/scheduler/OWNERS @@ -0,0 +1,4 @@ +approvers: +- sig-scheduling-maintainers +reviewers: +- sig-scheduling From 8dac9639e4a9aa84f7223e5781dc79de6099e5b6 Mon Sep 17 00:00:00 2001 From: ymqytw Date: Thu, 29 Jun 2017 16:07:31 -0700 Subject: [PATCH 167/448] split util/slice --- hack/.linted_packages | 1 + pkg/kubectl/BUILD | 2 +- pkg/kubectl/history.go | 2 +- pkg/kubectl/rollback.go | 2 +- pkg/kubectl/util/BUILD | 1 + pkg/kubectl/util/slice/BUILD | 35 ++++++++++++++++++++++++++++ pkg/kubectl/util/slice/slice.go | 32 +++++++++++++++++++++++++ pkg/kubectl/util/slice/slice_test.go | 31 ++++++++++++++++++++++++ pkg/util/slice/slice.go | 11 --------- pkg/util/slice/slice_test.go | 9 ------- 10 files changed, 103 insertions(+), 23 deletions(-) create mode 100644 pkg/kubectl/util/slice/BUILD create mode 100644 pkg/kubectl/util/slice/slice.go create mode 100644 pkg/kubectl/util/slice/slice_test.go diff --git a/hack/.linted_packages b/hack/.linted_packages index 38be9e2ea27..9bb55acef13 100644 --- a/hack/.linted_packages +++ b/hack/.linted_packages @@ -278,6 +278,7 @@ pkg/util/rand pkg/util/runtime pkg/util/sets pkg/util/sets/types +pkg/util/slice pkg/util/tail pkg/util/validation pkg/util/validation/field diff --git a/pkg/kubectl/BUILD b/pkg/kubectl/BUILD index 6bad6f9c8e0..ae9d0ebf358 100644 --- a/pkg/kubectl/BUILD +++ b/pkg/kubectl/BUILD @@ -143,9 +143,9 @@ go_library( "//pkg/credentialprovider:go_default_library", "//pkg/kubectl/resource:go_default_library", "//pkg/kubectl/util:go_default_library", + "//pkg/kubectl/util/slice:go_default_library", "//pkg/printers:go_default_library", "//pkg/printers/internalversion:go_default_library", - "//pkg/util/slice:go_default_library", "//vendor/github.com/emicklei/go-restful-swagger12:go_default_library", "//vendor/github.com/golang/glog:go_default_library", "//vendor/github.com/spf13/cobra:go_default_library", diff --git a/pkg/kubectl/history.go b/pkg/kubectl/history.go index aca1963eaf7..8f07a40bee2 100644 --- a/pkg/kubectl/history.go +++ b/pkg/kubectl/history.go @@ -39,8 +39,8 @@ import ( clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" "k8s.io/kubernetes/pkg/controller" deploymentutil "k8s.io/kubernetes/pkg/controller/deployment/util" + sliceutil "k8s.io/kubernetes/pkg/kubectl/util/slice" printersinternal "k8s.io/kubernetes/pkg/printers/internalversion" - sliceutil "k8s.io/kubernetes/pkg/util/slice" ) const ( diff --git a/pkg/kubectl/rollback.go b/pkg/kubectl/rollback.go index ded384b2b52..ee9594db648 100644 --- a/pkg/kubectl/rollback.go +++ b/pkg/kubectl/rollback.go @@ -39,8 +39,8 @@ import ( clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" "k8s.io/kubernetes/pkg/controller/daemon" deploymentutil "k8s.io/kubernetes/pkg/controller/deployment/util" + sliceutil "k8s.io/kubernetes/pkg/kubectl/util/slice" printersinternal "k8s.io/kubernetes/pkg/printers/internalversion" - sliceutil "k8s.io/kubernetes/pkg/util/slice" ) const ( diff --git a/pkg/kubectl/util/BUILD b/pkg/kubectl/util/BUILD index fb4b1fdac61..aa82e750aaf 100644 --- a/pkg/kubectl/util/BUILD +++ b/pkg/kubectl/util/BUILD @@ -31,6 +31,7 @@ filegroup( srcs = [ ":package-srcs", "//pkg/kubectl/util/crlf:all-srcs", + "//pkg/kubectl/util/slice:all-srcs", "//pkg/kubectl/util/term:all-srcs", ], tags = ["automanaged"], diff --git a/pkg/kubectl/util/slice/BUILD b/pkg/kubectl/util/slice/BUILD new file mode 100644 index 00000000000..35cb2024d50 --- /dev/null +++ b/pkg/kubectl/util/slice/BUILD @@ -0,0 +1,35 @@ +package(default_visibility = ["//visibility:public"]) + +licenses(["notice"]) + +load( + "@io_bazel_rules_go//go:def.bzl", + "go_library", + "go_test", +) + +go_library( + name = "go_default_library", + srcs = ["slice.go"], + tags = ["automanaged"], +) + +go_test( + name = "go_default_test", + srcs = ["slice_test.go"], + library = ":go_default_library", + tags = ["automanaged"], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], +) diff --git a/pkg/kubectl/util/slice/slice.go b/pkg/kubectl/util/slice/slice.go new file mode 100644 index 00000000000..6885c4888db --- /dev/null +++ b/pkg/kubectl/util/slice/slice.go @@ -0,0 +1,32 @@ +/* +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 slice + +import ( + "sort" +) + +// Int64Slice attaches the methods of Interface to []int64, +// sorting in increasing order. +type Int64Slice []int64 + +func (p Int64Slice) Len() int { return len(p) } +func (p Int64Slice) Less(i, j int) bool { return p[i] < p[j] } +func (p Int64Slice) Swap(i, j int) { p[i], p[j] = p[j], p[i] } + +// Sorts []int64 in increasing order +func SortInts64(a []int64) { sort.Sort(Int64Slice(a)) } diff --git a/pkg/kubectl/util/slice/slice_test.go b/pkg/kubectl/util/slice/slice_test.go new file mode 100644 index 00000000000..7e3bec6e277 --- /dev/null +++ b/pkg/kubectl/util/slice/slice_test.go @@ -0,0 +1,31 @@ +/* +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 slice + +import ( + "reflect" + "testing" +) + +func TestSortInts64(t *testing.T) { + src := []int64{10, 1, 2, 3, 4, 5, 6} + expected := []int64{1, 2, 3, 4, 5, 6, 10} + SortInts64(src) + if !reflect.DeepEqual(src, expected) { + t.Errorf("func Ints64 didnt sort correctly, %v !- %v", src, expected) + } +} diff --git a/pkg/util/slice/slice.go b/pkg/util/slice/slice.go index 205b597c404..b408dbae841 100644 --- a/pkg/util/slice/slice.go +++ b/pkg/util/slice/slice.go @@ -68,14 +68,3 @@ func ContainsString(slice []string, s string, modifier func(s string) string) bo } return false } - -// Int64Slice attaches the methods of Interface to []int64, -// sorting in increasing order. -type Int64Slice []int64 - -func (p Int64Slice) Len() int { return len(p) } -func (p Int64Slice) Less(i, j int) bool { return p[i] < p[j] } -func (p Int64Slice) Swap(i, j int) { p[i], p[j] = p[j], p[i] } - -// Sorts []int64 in increasing order -func SortInts64(a []int64) { sort.Sort(Int64Slice(a)) } diff --git a/pkg/util/slice/slice_test.go b/pkg/util/slice/slice_test.go index 1c02f420411..437c8ecee55 100644 --- a/pkg/util/slice/slice_test.go +++ b/pkg/util/slice/slice_test.go @@ -89,12 +89,3 @@ func TestShuffleStrings(t *testing.T) { } } } - -func TestSortInts64(t *testing.T) { - src := []int64{10, 1, 2, 3, 4, 5, 6} - expected := []int64{1, 2, 3, 4, 5, 6, 10} - SortInts64(src) - if !reflect.DeepEqual(src, expected) { - t.Errorf("func Ints64 didnt sort correctly, %v !- %v", src, expected) - } -} From ddfa04eaac359376e3cc4e033e3c55eae183e3da Mon Sep 17 00:00:00 2001 From: Klaus Ma Date: Sat, 1 Jul 2017 14:00:31 +0800 Subject: [PATCH 168/448] Added case on 'terminated-but-not-yet-deleted' for Admit. --- pkg/kubelet/kubelet_pods.go | 3 +-- pkg/kubelet/kubelet_test.go | 11 +++++++++++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/pkg/kubelet/kubelet_pods.go b/pkg/kubelet/kubelet_pods.go index 2784b433f1c..7e38fcf3f51 100644 --- a/pkg/kubelet/kubelet_pods.go +++ b/pkg/kubelet/kubelet_pods.go @@ -729,9 +729,8 @@ func (kl *Kubelet) getPullSecretsForPod(pod *v1.Pod) []v1.Secret { return pullSecrets } -// Returns true if pod is in the terminated state ("Failed" or "Succeeded"). +// podIsTerminated returns true if pod is in the terminated state ("Failed" or "Succeeded"). func (kl *Kubelet) podIsTerminated(pod *v1.Pod) bool { - var status v1.PodStatus // Check the cached pod status which was set after the last sync. status, ok := kl.statusManager.GetPodStatus(pod.UID) if !ok { diff --git a/pkg/kubelet/kubelet_test.go b/pkg/kubelet/kubelet_test.go index f698fca9288..bf355f3d044 100644 --- a/pkg/kubelet/kubelet_test.go +++ b/pkg/kubelet/kubelet_test.go @@ -1249,10 +1249,21 @@ func TestFilterOutTerminatedPods(t *testing.T) { defer testKubelet.Cleanup() kubelet := testKubelet.kubelet pods := newTestPods(5) + now := metav1.NewTime(time.Now()) pods[0].Status.Phase = v1.PodFailed pods[1].Status.Phase = v1.PodSucceeded + // The pod is terminating, should not filter out. pods[2].Status.Phase = v1.PodRunning + pods[2].DeletionTimestamp = &now + pods[2].Status.ContainerStatuses = []v1.ContainerStatus{ + {State: v1.ContainerState{ + Running: &v1.ContainerStateRunning{ + StartedAt: now, + }, + }}, + } pods[3].Status.Phase = v1.PodPending + pods[4].Status.Phase = v1.PodRunning expected := []*v1.Pod{pods[2], pods[3], pods[4]} kubelet.podManager.SetPods(pods) From c73b535d164eba11e93b99a02a8b1a54c0746526 Mon Sep 17 00:00:00 2001 From: Deyuan Deng Date: Mon, 8 May 2017 09:42:11 +0800 Subject: [PATCH 169/448] Fix kubectl describe for controllerRef --- pkg/printers/internalversion/describe.go | 15 ++- pkg/printers/internalversion/describe_test.go | 95 +++++++++++++++++++ 2 files changed, 105 insertions(+), 5 deletions(-) diff --git a/pkg/printers/internalversion/describe.go b/pkg/printers/internalversion/describe.go index 677018dd9fc..a32413f0463 100644 --- a/pkg/printers/internalversion/describe.go +++ b/pkg/printers/internalversion/describe.go @@ -1421,7 +1421,7 @@ func (d *ReplicationControllerDescriber) Describe(namespace, name string, descri return "", err } - running, waiting, succeeded, failed, err := getPodStatusForController(pc, labels.SelectorFromSet(controller.Spec.Selector)) + running, waiting, succeeded, failed, err := getPodStatusForController(pc, labels.SelectorFromSet(controller.Spec.Selector), controller.UID) if err != nil { return "", err } @@ -1498,7 +1498,7 @@ func (d *ReplicaSetDescriber) Describe(namespace, name string, describerSettings return "", err } - running, waiting, succeeded, failed, getPodErr := getPodStatusForController(pc, selector) + running, waiting, succeeded, failed, getPodErr := getPodStatusForController(pc, selector, rs.UID) var events *api.EventList if describerSettings.ShowEvents { @@ -1698,7 +1698,7 @@ func (d *DaemonSetDescriber) Describe(namespace, name string, describerSettings if err != nil { return "", err } - running, waiting, succeeded, failed, err := getPodStatusForController(pc, selector) + running, waiting, succeeded, failed, err := getPodStatusForController(pc, selector, daemon.UID) if err != nil { return "", err } @@ -2452,7 +2452,7 @@ func (p *StatefulSetDescriber) Describe(namespace, name string, describerSetting return "", err } - running, waiting, succeeded, failed, err := getPodStatusForController(pc, selector) + running, waiting, succeeded, failed, err := getPodStatusForController(pc, selector, ps.UID) if err != nil { return "", err } @@ -2837,13 +2837,18 @@ func printReplicaSetsByLabels(matchingRSs []*versionedextension.ReplicaSet) stri return list } -func getPodStatusForController(c coreclient.PodInterface, selector labels.Selector) (running, waiting, succeeded, failed int, err error) { +func getPodStatusForController(c coreclient.PodInterface, selector labels.Selector, uid types.UID) (running, waiting, succeeded, failed int, err error) { options := metav1.ListOptions{LabelSelector: selector.String()} rcPods, err := c.List(options) if err != nil { return } for _, pod := range rcPods.Items { + controllerRef := controller.GetControllerOf(&pod) + // Skip pods that are orphans or owned by other controllers. + if controllerRef == nil || controllerRef.UID != uid { + continue + } switch pod.Status.Phase { case api.PodRunning: running++ diff --git a/pkg/printers/internalversion/describe_test.go b/pkg/printers/internalversion/describe_test.go index 7e028755813..f1c67dde9f8 100644 --- a/pkg/printers/internalversion/describe_test.go +++ b/pkg/printers/internalversion/describe_test.go @@ -1492,3 +1492,98 @@ func TestDescribeResourceQuota(t *testing.T) { } } } + +// boolPtr returns a pointer to a bool +func boolPtr(b bool) *bool { + o := b + return &o +} + +func TestControllerRef(t *testing.T) { + f := fake.NewSimpleClientset( + &api.ReplicationController{ + ObjectMeta: metav1.ObjectMeta{ + Name: "bar", + Namespace: "foo", + UID: "123456", + }, + TypeMeta: metav1.TypeMeta{ + Kind: "ReplicationController", + }, + Spec: api.ReplicationControllerSpec{ + Replicas: 1, + Selector: map[string]string{"abc": "xyz"}, + Template: &api.PodTemplateSpec{ + Spec: api.PodSpec{ + Containers: []api.Container{ + {Image: "mytest-image:latest"}, + }, + }, + }, + }, + }, + &api.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: "barpod", + Namespace: "foo", + Labels: map[string]string{"abc": "xyz"}, + OwnerReferences: []metav1.OwnerReference{{Name: "bar", UID: "123456", Controller: boolPtr(true)}}, + }, + TypeMeta: metav1.TypeMeta{ + Kind: "Pod", + }, + Spec: api.PodSpec{ + Containers: []api.Container{ + {Image: "mytest-image:latest"}, + }, + }, + Status: api.PodStatus{ + Phase: api.PodRunning, + }, + }, + &api.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: "orphan", + Namespace: "foo", + Labels: map[string]string{"abc": "xyz"}, + }, + TypeMeta: metav1.TypeMeta{ + Kind: "Pod", + }, + Spec: api.PodSpec{ + Containers: []api.Container{ + {Image: "mytest-image:latest"}, + }, + }, + Status: api.PodStatus{ + Phase: api.PodRunning, + }, + }, + &api.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: "buzpod", + Namespace: "foo", + Labels: map[string]string{"abc": "xyz"}, + OwnerReferences: []metav1.OwnerReference{{Name: "buz", UID: "654321", Controller: boolPtr(true)}}, + }, + TypeMeta: metav1.TypeMeta{ + Kind: "Pod", + }, + Spec: api.PodSpec{ + Containers: []api.Container{ + {Image: "mytest-image:latest"}, + }, + }, + Status: api.PodStatus{ + Phase: api.PodRunning, + }, + }) + d := ReplicationControllerDescriber{f} + out, err := d.Describe("foo", "bar", printers.DescriberSettings{ShowEvents: false}) + if err != nil { + t.Errorf("unexpected error: %v", err) + } + if !strings.Contains(out, "1 Running") { + t.Errorf("unexpected out: %s", out) + } +} From 4eee8ea1195876fbe3ee46edc1930afe0cd0cda8 Mon Sep 17 00:00:00 2001 From: Kazuki Suda Date: Sat, 1 Jul 2017 21:44:14 +0900 Subject: [PATCH 170/448] Support completion for kubectl config delete-cluster --- pkg/kubectl/cmd/cmd.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pkg/kubectl/cmd/cmd.go b/pkg/kubectl/cmd/cmd.go index 1bafc28778c..086065b3fe7 100644 --- a/pkg/kubectl/cmd/cmd.go +++ b/pkg/kubectl/cmd/cmd.go @@ -190,6 +190,10 @@ __custom_func() { __kubectl_config_get_contexts return ;; + kubectl_config_delete-cluster) + __kubectl_config_get_clusters + return + ;; *) ;; esac From 9f37efcf7e078de3f3c2282dd72101088e7ac461 Mon Sep 17 00:00:00 2001 From: JulienBalestra Date: Sat, 17 Jun 2017 12:43:15 +0200 Subject: [PATCH 171/448] Provide a way to setup the limit NO files for rkt Pods --- pkg/kubelet/rkt/BUILD | 1 + pkg/kubelet/rkt/rkt.go | 24 +++++++++++++++++ pkg/kubelet/rkt/rkt_test.go | 51 +++++++++++++++++++++++++++++++++++++ 3 files changed, 76 insertions(+) diff --git a/pkg/kubelet/rkt/BUILD b/pkg/kubelet/rkt/BUILD index f80e2c6c830..a3422c8eea4 100644 --- a/pkg/kubelet/rkt/BUILD +++ b/pkg/kubelet/rkt/BUILD @@ -82,6 +82,7 @@ go_test( "//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", diff --git a/pkg/kubelet/rkt/rkt.go b/pkg/kubelet/rkt/rkt.go index e4481e37d9a..6138e4d36ca 100644 --- a/pkg/kubelet/rkt/rkt.go +++ b/pkg/kubelet/rkt/rkt.go @@ -95,6 +95,8 @@ const ( k8sRktRestartCountAnno = "rkt.kubernetes.io/restart-count" k8sRktTerminationMessagePathAnno = "rkt.kubernetes.io/termination-message-path" + k8sRktLimitNoFileAnno = "systemd-unit-option.rkt.kubernetes.io/LimitNOFILE" + // TODO(euank): This has significant security concerns as a stage1 image is // effectively root. // Furthermore, this (using an annotation) is a hack to pass an extra @@ -1148,6 +1150,23 @@ func constructSyslogIdentifier(generateName string, podName string) string { 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. @@ -1235,6 +1254,11 @@ func (r *Runtime) preparePod(pod *v1.Pod, podIP string, pullSecrets []v1.Secret, 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)) diff --git a/pkg/kubelet/rkt/rkt_test.go b/pkg/kubelet/rkt/rkt_test.go index 4adc84ae72a..18092169b6a 100644 --- a/pkg/kubelet/rkt/rkt_test.go +++ b/pkg/kubelet/rkt/rkt_test.go @@ -28,6 +28,7 @@ import ( 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" @@ -2075,3 +2076,53 @@ func TestGetPodSystemdServiceFiles(t *testing.T) { } } } + +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)) + } + } +} From 36271f985d41fd3d0e9cd59e6f23105cf96283bb Mon Sep 17 00:00:00 2001 From: Nikhita Raghunath Date: Sun, 2 Jul 2017 03:53:35 +0530 Subject: [PATCH 172/448] Add Cleanup section to apiextensions client-go --- .../apiextensions-apiserver/examples/client-go/README.md | 8 +++++++- .../apiextensions-apiserver/examples/client-go/main.go | 2 +- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/README.md b/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/README.md index 4468e616ba7..3ac247f4a1f 100644 --- a/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/README.md +++ b/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/README.md @@ -43,4 +43,10 @@ type User struct { Name string `json:"name"` Password string `json:"password"` } -``` \ No newline at end of file +``` + +## Cleanup + +Successfully running this program will clean the created artifacts. If you terminate the program without completing, you can clean up the created CustomResourceDefinition with: + + kubectl delete crd examples.cr.client-go.k8s.io diff --git a/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/main.go b/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/main.go index 9ed7c2f012b..2d50a83d52b 100644 --- a/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/main.go +++ b/staging/src/k8s.io/apiextensions-apiserver/examples/client-go/main.go @@ -110,7 +110,7 @@ func main() { } fmt.Print("PROCESSED\n") - // Fetch a list of our TPRs + // Fetch a list of our CRs exampleList := crv1.ExampleList{} err = exampleClient.Get().Resource(crv1.ExampleResourcePlural).Do().Into(&exampleList) if err != nil { From 549360cf91ff30f433982fc86a4cf1cc87a6c96f Mon Sep 17 00:00:00 2001 From: Klaus Ma Date: Wed, 28 Jun 2017 20:32:38 +0800 Subject: [PATCH 173/448] Checked container spec when killing container. --- .../kuberuntime/kuberuntime_container.go | 11 ++++-- .../kuberuntime/kuberuntime_container_test.go | 35 +++++++++++++++++++ 2 files changed, 44 insertions(+), 2 deletions(-) diff --git a/pkg/kubelet/kuberuntime/kuberuntime_container.go b/pkg/kubelet/kuberuntime/kuberuntime_container.go index 27b5b55e864..c3eaf657ec9 100644 --- a/pkg/kubelet/kuberuntime/kuberuntime_container.go +++ b/pkg/kubelet/kuberuntime/kuberuntime_container.go @@ -155,7 +155,10 @@ func (m *kubeGenericRuntimeManager) startContainer(podSandboxID string, podSandb msg, handlerErr := m.runner.Run(kubeContainerID, pod, container, container.Lifecycle.PostStart) if handlerErr != nil { m.recordContainerEvent(pod, container, kubeContainerID.ID, v1.EventTypeWarning, events.FailedPostStartHook, msg) - m.killContainer(pod, kubeContainerID, container.Name, "FailedPostStartHook", nil) + if err := m.killContainer(pod, kubeContainerID, container.Name, "FailedPostStartHook", nil); err != nil { + glog.Errorf("Failed to kill container %q(id=%q) in pod %q: %v, %v", + container.Name, kubeContainerID.String(), format.Pod(pod), ErrPostStartHook, err) + } return msg, ErrPostStartHook } } @@ -547,7 +550,10 @@ func (m *kubeGenericRuntimeManager) restoreSpecsFromContainerLabels(containerID func (m *kubeGenericRuntimeManager) killContainer(pod *v1.Pod, containerID kubecontainer.ContainerID, containerName string, reason string, gracePeriodOverride *int64) error { var containerSpec *v1.Container if pod != nil { - containerSpec = kubecontainer.GetContainerSpec(pod, containerName) + if containerSpec = kubecontainer.GetContainerSpec(pod, containerName); containerSpec == nil { + return fmt.Errorf("failed to get containerSpec %q(id=%q) in pod %q when killing container for reason %q", + containerName, containerID.String(), format.Pod(pod), reason) + } } else { // Restore necessary information if one of the specs is nil. restoredPod, restoredContainer, err := m.restoreSpecsFromContainerLabels(containerID) @@ -556,6 +562,7 @@ func (m *kubeGenericRuntimeManager) killContainer(pod *v1.Pod, containerID kubec } pod, containerSpec = restoredPod, restoredContainer } + // From this point , pod and container must be non-nil. gracePeriod := int64(minimumGracePeriodInSeconds) switch { diff --git a/pkg/kubelet/kuberuntime/kuberuntime_container_test.go b/pkg/kubelet/kuberuntime/kuberuntime_container_test.go index c6bfbd10b79..6152a1974e4 100644 --- a/pkg/kubelet/kuberuntime/kuberuntime_container_test.go +++ b/pkg/kubelet/kuberuntime/kuberuntime_container_test.go @@ -69,6 +69,41 @@ func TestRemoveContainer(t *testing.T) { assert.Empty(t, containers) } +// TestKillContainer tests killing the container in a Pod. +func TestKillContainer(t *testing.T) { + _, _, m, _ := createTestRuntimeManager() + + tests := []struct { + caseName string + pod *v1.Pod + containerID kubecontainer.ContainerID + containerName string + reason string + gracePeriodOverride int64 + succeed bool + }{ + { + caseName: "Failed to find container in pods, expect to return error", + pod: &v1.Pod{ + ObjectMeta: metav1.ObjectMeta{UID: "pod1_id", Name: "pod1", Namespace: "default"}, + Spec: v1.PodSpec{Containers: []v1.Container{{Name: "empty_container"}}}, + }, + containerID: kubecontainer.ContainerID{Type: "docker", ID: "not_exist_container_id"}, + containerName: "not_exist_container", + reason: "unknown reason", + gracePeriodOverride: 0, + succeed: false, + }, + } + + for _, test := range tests { + err := m.killContainer(test.pod, test.containerID, test.containerName, test.reason, &test.gracePeriodOverride) + if test.succeed != (err == nil) { + t.Errorf("%s: expected %v, got %v (%v)", test.caseName, test.succeed, (err == nil), err) + } + } +} + // TestToKubeContainerStatus tests the converting the CRI container status to // the internal type (i.e., toKubeContainerStatus()) for containers in // different states. From 5fa4668e9f7627ff75f4c4ad7a41654b8910d375 Mon Sep 17 00:00:00 2001 From: zhangxiaoyu-zidif Date: Sun, 2 Jul 2017 12:11:33 +0800 Subject: [PATCH 174/448] fix style of yaml and text --- CHANGELOG.md | 132 +++++++++++++++++++++++++++------------------------ 1 file changed, 70 insertions(+), 62 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 44729a1878d..43af6c00fd3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2000,37 +2000,41 @@ filename | sha256 hash * Support updating storageclasses in etcd to storage.k8s.io/v1. You must do this prior to upgrading to 1.8. ([#46116](https://github.com/kubernetes/kubernetes/pull/46116), [@ncdc](https://github.com/ncdc)) * The namespace API object no longer supports the deletecollection operation. ([#46407](https://github.com/kubernetes/kubernetes/pull/46407), [@liggitt](https://github.com/liggitt)) * NetworkPolicy has been moved from `extensions/v1beta1` to the new ([#39164](https://github.com/kubernetes/kubernetes/pull/39164), [@danwinship](https://github.com/danwinship)) - * `networking.k8s.io/v1` API group. The structure remains unchanged from - * the beta1 API. - * The `net.beta.kubernetes.io/network-policy` annotation on Namespaces - * to opt in to isolation has been removed. Instead, isolation is now - * determined at a per-pod level, with pods being isolated if there is - * any NetworkPolicy whose spec.podSelector targets them. Pods that are - * targeted by NetworkPolicies accept traffic that is accepted by any of - * the NetworkPolicies (and nothing else), and pods that are not targeted - * by any NetworkPolicy accept all traffic by default. - * Action Required: - * When upgrading to Kubernetes 1.7 (and a network plugin that supports - * the new NetworkPolicy v1 semantics), to ensure full behavioral - * compatibility with v1beta1: - * 1. In Namespaces that previously had the "DefaultDeny" annotation, - * you can create equivalent v1 semantics by creating a - * NetworkPolicy that matches all pods but does not allow any - * traffic: - * kind: NetworkPolicy - * apiVersion: networking.k8s.io/v1 - * metadata: - * name: default-deny - * spec: - * podSelector: - * This will ensure that pods that aren't matched by any other - * NetworkPolicy will continue to be fully-isolated, as they were - * before. - * 2. In Namespaces that previously did not have the "DefaultDeny" - * annotation, you should delete any existing NetworkPolicy - * objects. These would have had no effect before, but with v1 - * semantics they might cause some traffic to be blocked that you - * didn't intend to be blocked. + `networking.k8s.io/v1` API group. The structure remains unchanged from + the beta1 API. + The `net.beta.kubernetes.io/network-policy` annotation on Namespaces + to opt in to isolation has been removed. Instead, isolation is now + determined at a per-pod level, with pods being isolated if there is + any NetworkPolicy whose spec.podSelector targets them. Pods that are + targeted by NetworkPolicies accept traffic that is accepted by any of + the NetworkPolicies (and nothing else), and pods that are not targeted + by any NetworkPolicy accept all traffic by default. + Action Required: + When upgrading to Kubernetes 1.7 (and a network plugin that supports + the new NetworkPolicy v1 semantics), to ensure full behavioral + compatibility with v1beta1: + 1. In Namespaces that previously had the "DefaultDeny" annotation, + you can create equivalent v1 semantics by creating a + NetworkPolicy that matches all pods but does not allow any + traffic: + + ```yaml + kind: NetworkPolicy + apiVersion: networking.k8s.io/v1 + metadata: + name: default-deny + spec: + podSelector: + ``` + + This will ensure that pods that aren't matched by any other + NetworkPolicy will continue to be fully-isolated, as they were + before. + 2. In Namespaces that previously did not have the "DefaultDeny" + annotation, you should delete any existing NetworkPolicy + objects. These would have had no effect before, but with v1 + semantics they might cause some traffic to be blocked that you + didn't intend to be blocked. ### Other notable changes @@ -2493,37 +2497,41 @@ filename | sha256 hash * Support updating storageclasses in etcd to storage.k8s.io/v1. You must do this prior to upgrading to 1.8. ([#46116](https://github.com/kubernetes/kubernetes/pull/46116), [@ncdc](https://github.com/ncdc)) * The namespace API object no longer supports the deletecollection operation. ([#46407](https://github.com/kubernetes/kubernetes/pull/46407), [@liggitt](https://github.com/liggitt)) * NetworkPolicy has been moved from `extensions/v1beta1` to the new ([#39164](https://github.com/kubernetes/kubernetes/pull/39164), [@danwinship](https://github.com/danwinship)) - * `networking.k8s.io/v1` API group. The structure remains unchanged from - * the beta1 API. - * The `net.beta.kubernetes.io/network-policy` annotation on Namespaces - * to opt in to isolation has been removed. Instead, isolation is now - * determined at a per-pod level, with pods being isolated if there is - * any NetworkPolicy whose spec.podSelector targets them. Pods that are - * targeted by NetworkPolicies accept traffic that is accepted by any of - * the NetworkPolicies (and nothing else), and pods that are not targeted - * by any NetworkPolicy accept all traffic by default. - * Action Required: - * When upgrading to Kubernetes 1.7 (and a network plugin that supports - * the new NetworkPolicy v1 semantics), to ensure full behavioral - * compatibility with v1beta1: - * 1. In Namespaces that previously had the "DefaultDeny" annotation, - * you can create equivalent v1 semantics by creating a - * NetworkPolicy that matches all pods but does not allow any - * traffic: - * kind: NetworkPolicy - * apiVersion: networking.k8s.io/v1 - * metadata: - * name: default-deny - * spec: - * podSelector: - * This will ensure that pods that aren't matched by any other - * NetworkPolicy will continue to be fully-isolated, as they were - * before. - * 2. In Namespaces that previously did not have the "DefaultDeny" - * annotation, you should delete any existing NetworkPolicy - * objects. These would have had no effect before, but with v1 - * semantics they might cause some traffic to be blocked that you - * didn't intend to be blocked. + `networking.k8s.io/v1` API group. The structure remains unchanged from + the beta1 API. + The `net.beta.kubernetes.io/network-policy` annotation on Namespaces + to opt in to isolation has been removed. Instead, isolation is now + determined at a per-pod level, with pods being isolated if there is + any NetworkPolicy whose spec.podSelector targets them. Pods that are + targeted by NetworkPolicies accept traffic that is accepted by any of + the NetworkPolicies (and nothing else), and pods that are not targeted + by any NetworkPolicy accept all traffic by default. + Action Required: + When upgrading to Kubernetes 1.7 (and a network plugin that supports + the new NetworkPolicy v1 semantics), to ensure full behavioral + compatibility with v1beta1: + 1. In Namespaces that previously had the "DefaultDeny" annotation, + you can create equivalent v1 semantics by creating a + NetworkPolicy that matches all pods but does not allow any + traffic: + + ```yaml + kind: NetworkPolicy + apiVersion: networking.k8s.io/v1 + metadata: + name: default-deny + spec: + podSelector: + ``` + + This will ensure that pods that aren't matched by any other + NetworkPolicy will continue to be fully-isolated, as they were + before. + 2. In Namespaces that previously did not have the "DefaultDeny" + annotation, you should delete any existing NetworkPolicy + objects. These would have had no effect before, but with v1 + semantics they might cause some traffic to be blocked that you + didn't intend to be blocked. ### Other notable changes From 8eb3a66d3fb76a38eb53465045915bedfdaa7f52 Mon Sep 17 00:00:00 2001 From: Klaus Ma Date: Sun, 2 Jul 2017 21:25:48 +0800 Subject: [PATCH 175/448] Group and order imported packages. --- plugin/pkg/scheduler/scheduler.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/plugin/pkg/scheduler/scheduler.go b/plugin/pkg/scheduler/scheduler.go index 9105f79a98d..289709e1269 100644 --- a/plugin/pkg/scheduler/scheduler.go +++ b/plugin/pkg/scheduler/scheduler.go @@ -17,6 +17,7 @@ limitations under the License. package scheduler import ( + "fmt" "time" "k8s.io/api/core/v1" @@ -36,8 +37,6 @@ import ( "k8s.io/kubernetes/plugin/pkg/scheduler/schedulercache" "k8s.io/kubernetes/plugin/pkg/scheduler/util" - "fmt" - "github.com/golang/glog" ) From 4675f9703d7c9799d2151e7bf22c24b9d8bdf58b Mon Sep 17 00:00:00 2001 From: Klaus Ma Date: Mon, 3 Jul 2017 09:53:45 +0800 Subject: [PATCH 176/448] Updated comments of func in testapi. --- pkg/api/testapi/testapi.go | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/pkg/api/testapi/testapi.go b/pkg/api/testapi/testapi.go index 3a08f575bf9..ebb42a4cb18 100644 --- a/pkg/api/testapi/testapi.go +++ b/pkg/api/testapi/testapi.go @@ -432,7 +432,7 @@ func (g TestGroup) SelfLink(resource, name string) string { } } -// Returns the appropriate path for the given prefix (watch, proxy, redirect, etc), resource, namespace and 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 { @@ -462,7 +462,7 @@ func (g TestGroup) ResourcePathWithPrefix(prefix, resource, namespace, name stri return path } -// Returns the appropriate path for the given resource, namespace and name. +// 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 { @@ -480,6 +480,7 @@ func (g TestGroup) SubResourcePath(resource, namespace, name, sub string) string return path } +// RESTMapper returns RESTMapper in api.Registry. func (g TestGroup) RESTMapper() meta.RESTMapper { return api.Registry.RESTMapper() } @@ -494,7 +495,7 @@ func ExternalGroupVersions() schema.GroupVersions { return versions } -// Get codec based on runtime.Object +// GetCodecForObject gets codec based on runtime.Object func GetCodecForObject(obj runtime.Object) (runtime.Codec, error) { kinds, _, err := api.Scheme.ObjectKinds(obj) if err != nil { @@ -522,6 +523,7 @@ func GetCodecForObject(obj runtime.Object) (runtime.Codec, error) { 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} } From b851614adfe2b39941d518485480ff527fa4f0c1 Mon Sep 17 00:00:00 2001 From: Clayton Coleman Date: Sat, 1 Jul 2017 23:50:40 -0400 Subject: [PATCH 177/448] GuaranteedUpdate must write if stored data is not canonical An optimization added to the GuaranteedUpdate loop changed the comparison of the current objects serialization against the stored data, instead comparing to the in memory object, which defeated the mechanism we use to migrate stored data. This commit preserves that optimization but correctly verifies the in memory serialization against the on disk serialization by fetching the latest serialized data. Since most updates are not no-ops, this should not regress the performance of the normal path. --- .../apiserver/pkg/storage/etcd3/store.go | 18 +++++++++ .../apiserver/pkg/storage/etcd3/store_test.go | 40 ++++++++++++++++++- 2 files changed, 56 insertions(+), 2 deletions(-) diff --git a/staging/src/k8s.io/apiserver/pkg/storage/etcd3/store.go b/staging/src/k8s.io/apiserver/pkg/storage/etcd3/store.go index 210b67084c4..708018cd49b 100644 --- a/staging/src/k8s.io/apiserver/pkg/storage/etcd3/store.go +++ b/staging/src/k8s.io/apiserver/pkg/storage/etcd3/store.go @@ -264,11 +264,13 @@ func (s *store) GuaranteedUpdate( key = path.Join(s.pathPrefix, key) var origState *objState + var mustCheckData bool if len(suggestion) == 1 && suggestion[0] != nil { origState, err = s.getStateFromObject(suggestion[0]) if err != nil { return err } + mustCheckData = true } else { getResp, err := s.client.KV.Get(ctx, key, s.getOps...) if err != nil { @@ -297,6 +299,21 @@ func (s *store) GuaranteedUpdate( return err } if !origState.stale && bytes.Equal(data, origState.data) { + // if we skipped the original Get in this loop, we must refresh from + // etcd in order to be sure the data in the store is equivalent to + // our desired serialization + if mustCheckData { + getResp, err := s.client.KV.Get(ctx, key, s.getOps...) + if err != nil { + return err + } + origState, err = s.getState(getResp, key, v, ignoreNotFound) + if err != nil { + return err + } + mustCheckData = false + continue + } return decode(s.codec, s.versioner, origState.data, out, origState.rev) } @@ -330,6 +347,7 @@ func (s *store) GuaranteedUpdate( return err } trace.Step("Retry value restored") + mustCheckData = false continue } putResp := txnResp.Responses[0].GetResponsePut() diff --git a/staging/src/k8s.io/apiserver/pkg/storage/etcd3/store_test.go b/staging/src/k8s.io/apiserver/pkg/storage/etcd3/store_test.go index cc1d76c7789..ed9c3bf3c86 100644 --- a/staging/src/k8s.io/apiserver/pkg/storage/etcd3/store_test.go +++ b/staging/src/k8s.io/apiserver/pkg/storage/etcd3/store_test.go @@ -20,6 +20,7 @@ import ( "bytes" "fmt" "reflect" + "strconv" "sync" "testing" @@ -459,6 +460,41 @@ func TestGuaranteedUpdateWithTTL(t *testing.T) { testCheckEventType(t, watch.Deleted, w) } +func TestGuaranteedUpdateChecksStoredData(t *testing.T) { + ctx, store, cluster := testSetup(t) + defer cluster.Terminate(t) + + input := &example.Pod{ObjectMeta: metav1.ObjectMeta{Name: "foo"}} + key := "/somekey" + + // serialize input into etcd with data that would be normalized by a write - in this case, leading + // and trailing whitespace + codec := codecs.LegacyCodec(examplev1.SchemeGroupVersion) + data, err := runtime.Encode(codec, input) + if err != nil { + t.Fatal(err) + } + resp, err := store.client.Put(ctx, key, "test! "+string(data)+" ") + if err != nil { + t.Fatal(err) + } + + // this update should write the canonical value to etcd because the new serialization differs + // from the stored serialization + input.ResourceVersion = strconv.FormatInt(resp.Header.Revision, 10) + out := &example.Pod{} + err = store.GuaranteedUpdate(ctx, key, out, true, nil, + func(_ runtime.Object, _ storage.ResponseMeta) (runtime.Object, *uint64, error) { + return input, nil, nil + }, input) + if err != nil { + t.Fatalf("Update failed: %v", err) + } + if out.ResourceVersion == strconv.FormatInt(resp.Header.Revision, 10) { + t.Errorf("guaranteed update should have updated the serialized data, got %#v", out) + } +} + func TestGuaranteedUpdateWithConflict(t *testing.T) { ctx, store, cluster := testSetup(t) defer cluster.Terminate(t) @@ -569,10 +605,10 @@ func TestTransformationFailure(t *testing.T) { }); !storage.IsInternalError(err) { t.Errorf("Unexpected error: %v", err) } - // GuaranteedUpdate with suggestion should not return an error if we don't change the object + // GuaranteedUpdate with suggestion should return an error if we don't change the object if err := store.GuaranteedUpdate(ctx, preset[1].key, &example.Pod{}, false, nil, func(input runtime.Object, res storage.ResponseMeta) (output runtime.Object, ttl *uint64, err error) { return input, nil, nil - }, preset[1].obj); err != nil { + }, preset[1].obj); err == nil { t.Errorf("Unexpected error: %v", err) } From 37f9e1302509486a22e2d0bebfb6f8053c00d03f Mon Sep 17 00:00:00 2001 From: Xing Zhou Date: Fri, 9 Jun 2017 11:28:25 +0800 Subject: [PATCH 178/448] Remove useless error --- pkg/api/v1/resource/helpers.go | 2 +- pkg/kubelet/cm/helpers_linux.go | 5 +---- pkg/kubelet/cm/qos_container_manager_linux.go | 11 ++--------- 3 files changed, 4 insertions(+), 14 deletions(-) diff --git a/pkg/api/v1/resource/helpers.go b/pkg/api/v1/resource/helpers.go index 081f0f56d21..e97879d2830 100644 --- a/pkg/api/v1/resource/helpers.go +++ b/pkg/api/v1/resource/helpers.go @@ -27,7 +27,7 @@ import ( // PodRequestsAndLimits returns a dictionary of all defined resources summed up for all // containers of the pod. -func PodRequestsAndLimits(pod *v1.Pod) (reqs map[v1.ResourceName]resource.Quantity, limits map[v1.ResourceName]resource.Quantity, err error) { +func PodRequestsAndLimits(pod *v1.Pod) (reqs map[v1.ResourceName]resource.Quantity, limits map[v1.ResourceName]resource.Quantity) { reqs, limits = map[v1.ResourceName]resource.Quantity{}, map[v1.ResourceName]resource.Quantity{} for _, container := range pod.Spec.Containers { for name, quantity := range container.Resources.Requests { diff --git a/pkg/kubelet/cm/helpers_linux.go b/pkg/kubelet/cm/helpers_linux.go index 0d415728058..39f445a9431 100644 --- a/pkg/kubelet/cm/helpers_linux.go +++ b/pkg/kubelet/cm/helpers_linux.go @@ -86,10 +86,7 @@ func MilliCPUToShares(milliCPU int64) int64 { // ResourceConfigForPod takes the input pod and outputs the cgroup resource config. func ResourceConfigForPod(pod *v1.Pod) *ResourceConfig { // sum requests and limits. - reqs, limits, err := resource.PodRequestsAndLimits(pod) - if err != nil { - return &ResourceConfig{} - } + reqs, limits := resource.PodRequestsAndLimits(pod) cpuRequests := int64(0) cpuLimits := int64(0) diff --git a/pkg/kubelet/cm/qos_container_manager_linux.go b/pkg/kubelet/cm/qos_container_manager_linux.go index 80aebbc1912..aeb92f5a0ed 100644 --- a/pkg/kubelet/cm/qos_container_manager_linux.go +++ b/pkg/kubelet/cm/qos_container_manager_linux.go @@ -148,10 +148,7 @@ func (m *qosContainerManagerImpl) setCPUCgroupConfig(configs map[v1.PodQOSClass] // we only care about the burstable qos tier continue } - req, _, err := resource.PodRequestsAndLimits(pod) - if err != nil { - return err - } + req, _ := resource.PodRequestsAndLimits(pod) if request, found := req[v1.ResourceCPU]; found { burstablePodCPURequest += request.MilliValue() } @@ -188,11 +185,7 @@ func (m *qosContainerManagerImpl) setMemoryReserve(configs map[v1.PodQOSClass]*C // limits are not set for Best Effort pods continue } - req, _, err := resource.PodRequestsAndLimits(pod) - if err != nil { - glog.V(2).Infof("[Container Manager] Pod resource requests/limits could not be determined. Not setting QOS memory limts.") - return - } + req, _ := resource.PodRequestsAndLimits(pod) if request, found := req[v1.ResourceMemory]; found { podMemoryRequest += request.Value() } From ca5581edcc6a7ddecad485bfcfbda962f22171a4 Mon Sep 17 00:00:00 2001 From: Karol Wychowaniec Date: Tue, 27 Jun 2017 11:40:42 +0200 Subject: [PATCH 179/448] Pass cluster name to Heapster with Stackdriver sink. --- .../cluster-monitoring/stackdriver/heapster-controller.yaml | 2 +- cluster/common.sh | 1 + cluster/gce/container-linux/configure-helper.sh | 3 +++ cluster/gce/gci/configure-helper.sh | 3 +++ 4 files changed, 8 insertions(+), 1 deletion(-) diff --git a/cluster/addons/cluster-monitoring/stackdriver/heapster-controller.yaml b/cluster/addons/cluster-monitoring/stackdriver/heapster-controller.yaml index 90908770a07..c34f5ef1afa 100644 --- a/cluster/addons/cluster-monitoring/stackdriver/heapster-controller.yaml +++ b/cluster/addons/cluster-monitoring/stackdriver/heapster-controller.yaml @@ -55,7 +55,7 @@ spec: command: - /heapster - --source=kubernetes.summary_api:'' - - --sink=stackdriver + - --sink=stackdriver:?cluster_name={{ cluster_name }} # TODO: add --disable_export when it's merged into Heapster release volumeMounts: - name: ssl-certs diff --git a/cluster/common.sh b/cluster/common.sh index 0bcc69685f0..3dfe7b10fe7 100755 --- a/cluster/common.sh +++ b/cluster/common.sh @@ -605,6 +605,7 @@ function build-kube-env { rm -f ${file} cat >$file < Date: Tue, 20 Jun 2017 16:57:12 +0800 Subject: [PATCH 180/448] add validate for advanced audit policy This change checks group name and non-resrouce URLs format for audit policy. --- .../apiserver/pkg/apis/audit/validation/BUILD | 1 + .../pkg/apis/audit/validation/validation.go | 42 +++++++++++++++++++ .../apis/audit/validation/validation_test.go | 30 ++++++++++++- 3 files changed, 72 insertions(+), 1 deletion(-) diff --git a/staging/src/k8s.io/apiserver/pkg/apis/audit/validation/BUILD b/staging/src/k8s.io/apiserver/pkg/apis/audit/validation/BUILD index 63cbc6bacd8..d6d26735cf6 100644 --- a/staging/src/k8s.io/apiserver/pkg/apis/audit/validation/BUILD +++ b/staging/src/k8s.io/apiserver/pkg/apis/audit/validation/BUILD @@ -21,6 +21,7 @@ go_library( srcs = ["validation.go"], tags = ["automanaged"], deps = [ + "//vendor/k8s.io/apimachinery/pkg/api/validation:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library", "//vendor/k8s.io/apiserver/pkg/apis/audit:go_default_library", ], diff --git a/staging/src/k8s.io/apiserver/pkg/apis/audit/validation/validation.go b/staging/src/k8s.io/apiserver/pkg/apis/audit/validation/validation.go index 2ceead05f4b..80b73f851cb 100644 --- a/staging/src/k8s.io/apiserver/pkg/apis/audit/validation/validation.go +++ b/staging/src/k8s.io/apiserver/pkg/apis/audit/validation/validation.go @@ -17,6 +17,9 @@ limitations under the License. package validation import ( + "strings" + + "k8s.io/apimachinery/pkg/api/validation" "k8s.io/apimachinery/pkg/util/validation/field" "k8s.io/apiserver/pkg/apis/audit" ) @@ -33,6 +36,8 @@ func ValidatePolicy(policy *audit.Policy) field.ErrorList { func validatePolicyRule(rule audit.PolicyRule, fldPath *field.Path) field.ErrorList { var allErrs field.ErrorList allErrs = append(allErrs, validateLevel(rule.Level, fldPath.Child("level"))...) + allErrs = append(allErrs, validateNonResourceURLs(rule.NonResourceURLs, fldPath.Child("nonResourceURLs"))...) + allErrs = append(allErrs, validateResources(rule.Resources, fldPath.Child("resources"))...) if len(rule.NonResourceURLs) > 0 { if len(rule.Resources) > 0 || len(rule.Namespaces) > 0 { @@ -60,3 +65,40 @@ func validateLevel(level audit.Level, fldPath *field.Path) field.ErrorList { return field.ErrorList{field.NotSupported(fldPath, level, validLevels)} } } + +func validateNonResourceURLs(urls []string, fldPath *field.Path) field.ErrorList { + var allErrs field.ErrorList + for i, url := range urls { + if url == "*" { + continue + } + + if !strings.HasPrefix(url, "/") { + allErrs = append(allErrs, field.Invalid(fldPath.Index(i), url, "non-resource URL rules must begin with a '/' character")) + } + + if url != "" && strings.ContainsRune(url[:len(url)-1], '*') { + allErrs = append(allErrs, field.Invalid(fldPath.Index(i), url, "non-resource URL wildcards '*' must be the final character of the rule")) + } + } + return allErrs +} + +func validateResources(groupResources []audit.GroupResources, fldPath *field.Path) field.ErrorList { + var allErrs field.ErrorList + for _, groupResource := range groupResources { + // The empty string represents the core API group. + if len(groupResource.Group) == 0 { + continue + } + + // Group names must be lower case and be valid DNS subdomains. + // reference: https://github.com/kubernetes/community/blob/master/contributors/devel/api-conventions.md + // an error is returned for group name like rbac.authorization.k8s.io/v1beta1 + // rbac.authorization.k8s.io is the valid one + if msgs := validation.NameIsDNSSubdomain(groupResource.Group, false); len(msgs) != 0 { + allErrs = append(allErrs, field.Invalid(fldPath.Child("group"), groupResource.Group, strings.Join(msgs, ","))) + } + } + return allErrs +} diff --git a/staging/src/k8s.io/apiserver/pkg/apis/audit/validation/validation_test.go b/staging/src/k8s.io/apiserver/pkg/apis/audit/validation/validation_test.go index 07e354bc7bf..99692157791 100644 --- a/staging/src/k8s.io/apiserver/pkg/apis/audit/validation/validation_test.go +++ b/staging/src/k8s.io/apiserver/pkg/apis/audit/validation/validation_test.go @@ -32,7 +32,7 @@ func TestValidatePolicy(t *testing.T) { }, { // Specific request Level: audit.LevelRequestResponse, Verbs: []string{"get"}, - Resources: []audit.GroupResources{{Resources: []string{"secrets"}}}, + Resources: []audit.GroupResources{{Group: "rbac.authorization.k8s.io", Resources: []string{"roles", "rolebindings"}}}, Namespaces: []string{"kube-system"}, }, { // Some non-resource URLs Level: audit.LevelMetadata, @@ -41,6 +41,7 @@ func TestValidatePolicy(t *testing.T) { "/logs*", "/healthz*", "/metrics", + "*", }, }, } @@ -73,6 +74,33 @@ func TestValidatePolicy(t *testing.T) { Level: audit.LevelMetadata, Resources: []audit.GroupResources{{Resources: []string{"secrets"}}}, NonResourceURLs: []string{"/logs*"}, + }, { // invalid group name + Level: audit.LevelMetadata, + Resources: []audit.GroupResources{{Group: "rbac.authorization.k8s.io/v1beta1", Resources: []string{"roles"}}}, + }, { // invalid non-resource URLs + Level: audit.LevelMetadata, + NonResourceURLs: []string{ + "logs", + "/healthz*", + }, + }, { // empty non-resource URLs + Level: audit.LevelMetadata, + NonResourceURLs: []string{ + "", + "/healthz*", + }, + }, { // invalid non-resource URLs with multi "*" + Level: audit.LevelMetadata, + NonResourceURLs: []string{ + "/logs/*/*", + "/metrics", + }, + }, { // invalid non-resrouce URLs with "*" not in the end + Level: audit.LevelMetadata, + NonResourceURLs: []string{ + "/logs/*.log", + "/metrics", + }, }, } errorCases := []audit.Policy{} From b6abcacb38d5da7c70ea9f3e6f673c8beeb90092 Mon Sep 17 00:00:00 2001 From: Cao Shufeng Date: Fri, 30 Jun 2017 16:22:08 +0800 Subject: [PATCH 181/448] update events' ResponseStatus at Metadata level ResponseStatus is populated in MetadataLevel, so we also update it in MetadataLevel. --- staging/src/k8s.io/apiserver/pkg/apis/audit/types.go | 4 ++-- staging/src/k8s.io/apiserver/pkg/audit/request.go | 6 ++++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/staging/src/k8s.io/apiserver/pkg/apis/audit/types.go b/staging/src/k8s.io/apiserver/pkg/apis/audit/types.go index 0ca857678ce..8e8770d0084 100644 --- a/staging/src/k8s.io/apiserver/pkg/apis/audit/types.go +++ b/staging/src/k8s.io/apiserver/pkg/apis/audit/types.go @@ -100,8 +100,8 @@ type Event struct { // +optional ObjectRef *ObjectReference // The response status, populated even when the ResponseObject is not a Status type. - // For successful responses, this will only include the Code and StatusSuccess. - // For non-status type error responses, this will be auto-populated with the error Message. + // For successful responses, this will only include the Code. For non-status type + // error responses, this will be auto-populated with the error Message. // +optional ResponseStatus *metav1.Status diff --git a/staging/src/k8s.io/apiserver/pkg/audit/request.go b/staging/src/k8s.io/apiserver/pkg/audit/request.go index 4118d468af8..0a1c088a7ce 100644 --- a/staging/src/k8s.io/apiserver/pkg/audit/request.go +++ b/staging/src/k8s.io/apiserver/pkg/audit/request.go @@ -170,14 +170,16 @@ func LogRequestPatch(ae *audit.Event, patch []byte) { // LogResponseObject fills in the response object into an audit event. The passed runtime.Object // will be converted to the given gv. func LogResponseObject(ae *audit.Event, obj runtime.Object, gv schema.GroupVersion, s runtime.NegotiatedSerializer) { - if ae == nil || ae.Level.Less(audit.LevelRequestResponse) { + if ae == nil || ae.Level.Less(audit.LevelMetadata) { return } - if status, ok := obj.(*metav1.Status); ok { ae.ResponseStatus = status } + if ae.Level.Less(audit.LevelRequestResponse) { + return + } // TODO(audit): hook into the serializer to avoid double conversion var err error ae.ResponseObject, err = encodeObject(obj, gv, s) From 625192b3a22ef2618385e50847406be570bf54c7 Mon Sep 17 00:00:00 2001 From: Mik Vyatskov Date: Thu, 29 Jun 2017 13:45:10 +0200 Subject: [PATCH 182/448] Covert Stackdriver Logging load tests to soak tests --- test/e2e/cluster-logging/BUILD | 2 +- test/e2e/cluster-logging/sd.go | 20 +-- test/e2e/cluster-logging/sd_events.go | 16 +- test/e2e/cluster-logging/sd_load.go | 125 -------------- test/e2e/cluster-logging/sd_soak.go | 90 ++++++++++ test/e2e/cluster-logging/sd_utils.go | 227 +++++++++++++++----------- test/e2e/cluster-logging/utils.go | 5 + 7 files changed, 250 insertions(+), 235 deletions(-) delete mode 100644 test/e2e/cluster-logging/sd_load.go create mode 100644 test/e2e/cluster-logging/sd_soak.go diff --git a/test/e2e/cluster-logging/BUILD b/test/e2e/cluster-logging/BUILD index 5bfc9351ce7..0e99935a4d5 100644 --- a/test/e2e/cluster-logging/BUILD +++ b/test/e2e/cluster-logging/BUILD @@ -14,7 +14,7 @@ go_library( "es_utils.go", "sd.go", "sd_events.go", - "sd_load.go", + "sd_soak.go", "sd_utils.go", "utils.go", ], diff --git a/test/e2e/cluster-logging/sd.go b/test/e2e/cluster-logging/sd.go index f30f9777739..65a8ac66c14 100644 --- a/test/e2e/cluster-logging/sd.go +++ b/test/e2e/cluster-logging/sd.go @@ -26,24 +26,24 @@ import ( . "github.com/onsi/ginkgo" ) -var _ = framework.KubeDescribe("Cluster level logging using GCL", func() { - f := framework.NewDefaultFramework("gcl-logging") +var _ = framework.KubeDescribe("Cluster level logging implemented by Stackdriver", func() { + f := framework.NewDefaultFramework("sd-logging") BeforeEach(func() { framework.SkipUnlessProviderIs("gce", "gke") }) - It("should check that logs from containers are ingested in GCL", func() { + It("should ingest logs from applications", func() { podName := "synthlogger" - gclLogsProvider, err := newGclLogsProvider(f) - framework.ExpectNoError(err, "Failed to create GCL logs provider") + sdLogsProvider, err := newSdLogsProvider(f) + framework.ExpectNoError(err, "Failed to create Stackdriver logs provider") - err = gclLogsProvider.Init() - defer gclLogsProvider.Cleanup() - framework.ExpectNoError(err, "Failed to init GCL logs provider") + err = sdLogsProvider.Init() + defer sdLogsProvider.Cleanup() + framework.ExpectNoError(err, "Failed to init Stackdriver logs provider") - err = ensureSingleFluentdOnEachNode(f, gclLogsProvider.FluentdApplicationName()) + err = ensureSingleFluentdOnEachNode(f, sdLogsProvider.FluentdApplicationName()) framework.ExpectNoError(err, "Fluentd deployed incorrectly") By("Running synthetic logger") @@ -54,7 +54,7 @@ var _ = framework.KubeDescribe("Cluster level logging using GCL", func() { By("Waiting for logs to ingest") config := &loggingTestConfig{ - LogsProvider: gclLogsProvider, + LogsProvider: sdLogsProvider, Pods: []*loggingPod{pod}, IngestionTimeout: 10 * time.Minute, MaxAllowedLostFraction: 0, diff --git a/test/e2e/cluster-logging/sd_events.go b/test/e2e/cluster-logging/sd_events.go index 913ab18e12e..2c81b3887c9 100644 --- a/test/e2e/cluster-logging/sd_events.go +++ b/test/e2e/cluster-logging/sd_events.go @@ -40,26 +40,26 @@ const ( eventCreationInterval = 10 * time.Second ) -var _ = framework.KubeDescribe("Cluster level logging using GCL", func() { - f := framework.NewDefaultFramework("gcl-logging-events") +var _ = framework.KubeDescribe("Cluster level logging implemented by Stackdriver", func() { + f := framework.NewDefaultFramework("sd-logging-events") BeforeEach(func() { framework.SkipUnlessProviderIs("gce", "gke") }) It("should ingest events", func() { - gclLogsProvider, err := newGclLogsProvider(f) - framework.ExpectNoError(err, "Failed to create GCL logs provider") + sdLogsProvider, err := newSdLogsProvider(f) + framework.ExpectNoError(err, "Failed to create Stackdriver logs provider") - err = gclLogsProvider.Init() - defer gclLogsProvider.Cleanup() - framework.ExpectNoError(err, "Failed to init GCL logs provider") + err = sdLogsProvider.Init() + defer sdLogsProvider.Cleanup() + framework.ExpectNoError(err, "Failed to init Stackdriver logs provider") stopCh := make(chan struct{}) successCh := make(chan struct{}) go func() { wait.Poll(eventPollingInterval, eventsIngestionTimeout, func() (bool, error) { - events := gclLogsProvider.ReadEvents() + events := sdLogsProvider.ReadEvents() if len(events) > 0 { framework.Logf("Some events are ingested, sample event: %v", events[0]) close(successCh) diff --git a/test/e2e/cluster-logging/sd_load.go b/test/e2e/cluster-logging/sd_load.go deleted file mode 100644 index c6ff8f4103a..00000000000 --- a/test/e2e/cluster-logging/sd_load.go +++ /dev/null @@ -1,125 +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 - -import ( - "fmt" - "time" - - meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/kubernetes/test/e2e/framework" - - . "github.com/onsi/ginkgo" -) - -const ( - loadTestMaxAllowedLostFraction = 0.01 - loadTestMaxAllowedFluentdRestarts = 1 -) - -var _ = framework.KubeDescribe("Cluster level logging using GCL [Feature:StackdriverLogging]", func() { - f := framework.NewDefaultFramework("gcl-logging-load") - - It("should create a constant load with long-living pods and ensure logs delivery", func() { - gclLogsProvider, err := newGclLogsProvider(f) - framework.ExpectNoError(err, "Failed to create GCL logs provider") - - err = gclLogsProvider.Init() - defer gclLogsProvider.Cleanup() - framework.ExpectNoError(err, "Failed to init GCL logs provider") - - nodes := framework.GetReadySchedulableNodesOrDie(f.ClientSet).Items - nodeCount := len(nodes) - podCount := 30 * nodeCount - loggingDuration := 10 * time.Minute - linesPerSecond := 1000 * nodeCount - linesPerPod := linesPerSecond * int(loggingDuration.Seconds()) / podCount - ingestionTimeout := 20 * time.Minute - - By("Running logs generator pods") - pods := []*loggingPod{} - for podIdx := 0; podIdx < podCount; podIdx++ { - node := nodes[podIdx%len(nodes)] - podName := fmt.Sprintf("logs-generator-%d-%d", linesPerPod, podIdx) - pods = append(pods, createLoggingPod(f, podName, node.Name, linesPerPod, loggingDuration)) - - defer f.PodClient().Delete(podName, &meta_v1.DeleteOptions{}) - } - - By("Waiting for all log lines to be ingested") - config := &loggingTestConfig{ - LogsProvider: gclLogsProvider, - Pods: pods, - IngestionTimeout: ingestionTimeout, - MaxAllowedLostFraction: loadTestMaxAllowedLostFraction, - MaxAllowedFluentdRestarts: loadTestMaxAllowedFluentdRestarts, - } - err = waitForFullLogsIngestion(f, config) - if err != nil { - framework.Failf("Failed to ingest logs: %v", err) - } else { - framework.Logf("Successfully ingested all logs") - } - }) - - It("should create a constant load with short-living pods and ensure logs delivery", func() { - gclLogsProvider, err := newGclLogsProvider(f) - framework.ExpectNoError(err, "Failed to create GCL logs provider") - - err = gclLogsProvider.Init() - defer gclLogsProvider.Cleanup() - framework.ExpectNoError(err, "Failed to init GCL logs provider") - - nodes := framework.GetReadySchedulableNodesOrDie(f.ClientSet).Items - maxPodCount := 10 - jobDuration := 1 * time.Minute - linesPerPodPerSecond := 100 - testDuration := 10 * time.Minute - ingestionTimeout := 20 * time.Minute - - podRunDelay := time.Duration(int64(jobDuration) / int64(maxPodCount)) - podRunCount := int(testDuration.Seconds())/int(podRunDelay.Seconds()) - 1 - linesPerPod := linesPerPodPerSecond * int(jobDuration.Seconds()) - - By("Running short-living pods") - pods := []*loggingPod{} - for runIdx := 0; runIdx < podRunCount; runIdx++ { - for nodeIdx, node := range nodes { - podName := fmt.Sprintf("job-logs-generator-%d-%d-%d-%d", maxPodCount, linesPerPod, runIdx, nodeIdx) - pods = append(pods, createLoggingPod(f, podName, node.Name, linesPerPod, jobDuration)) - - defer f.PodClient().Delete(podName, &meta_v1.DeleteOptions{}) - } - time.Sleep(podRunDelay) - } - - By("Waiting for all log lines to be ingested") - config := &loggingTestConfig{ - LogsProvider: gclLogsProvider, - Pods: pods, - IngestionTimeout: ingestionTimeout, - MaxAllowedLostFraction: loadTestMaxAllowedLostFraction, - MaxAllowedFluentdRestarts: loadTestMaxAllowedFluentdRestarts, - } - err = waitForFullLogsIngestion(f, config) - if err != nil { - framework.Failf("Failed to ingest logs: %v", err) - } else { - framework.Logf("Successfully ingested all logs") - } - }) -}) diff --git a/test/e2e/cluster-logging/sd_soak.go b/test/e2e/cluster-logging/sd_soak.go new file mode 100644 index 00000000000..3d8f9485a79 --- /dev/null +++ b/test/e2e/cluster-logging/sd_soak.go @@ -0,0 +1,90 @@ +/* +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 + +import ( + "fmt" + "math" + "time" + + meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/kubernetes/test/e2e/framework" + + . "github.com/onsi/ginkgo" +) + +const ( + // maxAllowedLostFraction is the fraction of lost logs considered acceptable. + maxAllowedLostFraction = 0.01 + // maxAllowedRestartsPerHour is the number of fluentd container restarts + // considered acceptable. Once per hour is fine for now, as long as it + // doesn't loose too much logs. + maxAllowedRestartsPerHour = 1.0 +) + +var _ = framework.KubeDescribe("Cluster level logging implemented by Stackdriver [Feature:StackdriverLogging] [Soak]", func() { + f := framework.NewDefaultFramework("sd-logging-load") + + It("should ingest logs from applications running for a prolonged amount of time", func() { + sdLogsProvider, err := newSdLogsProvider(f) + framework.ExpectNoError(err, "Failed to create Stackdriver logs provider") + + err = sdLogsProvider.Init() + defer sdLogsProvider.Cleanup() + framework.ExpectNoError(err, "Failed to init Stackdriver logs provider") + + nodes := framework.GetReadySchedulableNodesOrDie(f.ClientSet).Items + maxPodCount := 10 + jobDuration := 1 * time.Hour + linesPerPodPerSecond := 100 + testDuration := 21 * time.Hour + ingestionTimeout := testDuration + 30*time.Minute + allowedRestarts := int(math.Ceil(float64(testDuration) / + float64(time.Hour) * maxAllowedRestartsPerHour)) + + podRunDelay := time.Duration(int64(jobDuration) / int64(maxPodCount)) + podRunCount := int(testDuration.Seconds())/int(podRunDelay.Seconds()) - 1 + linesPerPod := linesPerPodPerSecond * int(jobDuration.Seconds()) + + By("Running short-living pods") + pods := []*loggingPod{} + for runIdx := 0; runIdx < podRunCount; runIdx++ { + for nodeIdx, node := range nodes { + podName := fmt.Sprintf("job-logs-generator-%d-%d-%d-%d", maxPodCount, linesPerPod, runIdx, nodeIdx) + pods = append(pods, createLoggingPod(f, podName, node.Name, linesPerPod, jobDuration)) + + defer f.PodClient().Delete(podName, &meta_v1.DeleteOptions{}) + } + time.Sleep(podRunDelay) + } + + By("Waiting for all log lines to be ingested") + config := &loggingTestConfig{ + LogsProvider: sdLogsProvider, + Pods: pods, + IngestionTimeout: ingestionTimeout, + MaxAllowedLostFraction: maxAllowedLostFraction, + MaxAllowedFluentdRestarts: allowedRestarts, + } + err = waitForFullLogsIngestion(f, config) + if err != nil { + framework.Failf("Failed to ingest logs: %v", err) + } else { + framework.Logf("Successfully ingested all logs") + } + }) +}) diff --git a/test/e2e/cluster-logging/sd_utils.go b/test/e2e/cluster-logging/sd_utils.go index d64d9a293c1..f5be7191f1f 100644 --- a/test/e2e/cluster-logging/sd_utils.go +++ b/test/e2e/cluster-logging/sd_utils.go @@ -28,14 +28,14 @@ import ( "golang.org/x/net/context" "golang.org/x/oauth2/google" - gcl "google.golang.org/api/logging/v2beta1" + sd "google.golang.org/api/logging/v2beta1" pubsub "google.golang.org/api/pubsub/v1" ) const ( - // The amount of time to wait before considering - // Stackdriver Logging sink operational - sinkInitialDelay = 1 * time.Minute + // The amount of time to wait for Stackdriver Logging + // sink to become operational + sinkStartupTimeout = 10 * time.Minute // The limit on the number of messages to pull from PubSub maxPullLogMessages = 100 * 1000 @@ -44,26 +44,26 @@ const ( maxCacheSize = 10 * 1000 // PubSub topic with log entries polling interval - gclLoggingPollInterval = 100 * time.Millisecond + sdLoggingPollInterval = 100 * time.Millisecond ) -type gclLogsProvider struct { - GclService *gcl.Service +type sdLogsProvider struct { + SdService *sd.Service PubsubService *pubsub.Service Framework *framework.Framework Topic *pubsub.Topic Subscription *pubsub.Subscription - LogSink *gcl.LogSink + LogSink *sd.LogSink LogEntryCache map[string]chan logEntry EventCache chan map[string]interface{} CacheMutex *sync.Mutex PollingStopChannel chan struct{} } -func newGclLogsProvider(f *framework.Framework) (*gclLogsProvider, error) { +func newSdLogsProvider(f *framework.Framework) (*sdLogsProvider, error) { ctx := context.Background() - hc, err := google.DefaultClient(ctx, gcl.CloudPlatformScope) - gclService, err := gcl.New(hc) + hc, err := google.DefaultClient(ctx, sd.CloudPlatformScope) + sdService, err := sd.New(hc) if err != nil { return nil, err } @@ -73,8 +73,8 @@ func newGclLogsProvider(f *framework.Framework) (*gclLogsProvider, error) { return nil, err } - provider := &gclLogsProvider{ - GclService: gclService, + provider := &sdLogsProvider{ + SdService: sdService, PubsubService: pubsubService, Framework: f, LogEntryCache: map[string]chan logEntry{}, @@ -85,131 +85,144 @@ func newGclLogsProvider(f *framework.Framework) (*gclLogsProvider, error) { return provider, nil } -func (gclLogsProvider *gclLogsProvider) Init() error { +func (sdLogsProvider *sdLogsProvider) Init() error { projectId := framework.TestContext.CloudConfig.ProjectID - nsName := gclLogsProvider.Framework.Namespace.Name + nsName := sdLogsProvider.Framework.Namespace.Name - topic, err := gclLogsProvider.createPubSubTopic(projectId, nsName) + topic, err := sdLogsProvider.createPubSubTopic(projectId, nsName) if err != nil { return fmt.Errorf("failed to create PubSub topic: %v", err) } - gclLogsProvider.Topic = topic + sdLogsProvider.Topic = topic - subs, err := gclLogsProvider.createPubSubSubscription(projectId, nsName, topic.Name) + subs, err := sdLogsProvider.createPubSubSubscription(projectId, nsName, topic.Name) if err != nil { return fmt.Errorf("failed to create PubSub subscription: %v", err) } - gclLogsProvider.Subscription = subs + sdLogsProvider.Subscription = subs - logSink, err := gclLogsProvider.createGclLogSink(projectId, nsName, nsName, topic.Name) + logSink, err := sdLogsProvider.createSink(projectId, nsName, nsName, topic.Name) if err != nil { return fmt.Errorf("failed to create Stackdriver Logging sink: %v", err) } - gclLogsProvider.LogSink = logSink + sdLogsProvider.LogSink = logSink - if err = gclLogsProvider.authorizeGclLogSink(); err != nil { + if err = sdLogsProvider.authorizeSink(); err != nil { return fmt.Errorf("failed to authorize log sink: %v", err) } - framework.Logf("Waiting for log sink to become operational") - // TODO: Replace with something more intelligent - time.Sleep(sinkInitialDelay) + if err = sdLogsProvider.waitSinkInit(); err != nil { + return fmt.Errorf("failed to wait for sink to become operational: %v", err) + } - go gclLogsProvider.pollLogs() + go sdLogsProvider.pollLogs() return nil } -func (gclLogsProvider *gclLogsProvider) createPubSubTopic(projectId, topicName string) (*pubsub.Topic, error) { +func (sdLogsProvider *sdLogsProvider) createPubSubTopic(projectId, topicName string) (*pubsub.Topic, error) { topicFullName := fmt.Sprintf("projects/%s/topics/%s", projectId, topicName) topic := &pubsub.Topic{ Name: topicFullName, } - return gclLogsProvider.PubsubService.Projects.Topics.Create(topicFullName, topic).Do() + return sdLogsProvider.PubsubService.Projects.Topics.Create(topicFullName, topic).Do() } -func (gclLogsProvider *gclLogsProvider) createPubSubSubscription(projectId, subsName, topicName string) (*pubsub.Subscription, error) { +func (sdLogsProvider *sdLogsProvider) createPubSubSubscription(projectId, subsName, topicName string) (*pubsub.Subscription, error) { subsFullName := fmt.Sprintf("projects/%s/subscriptions/%s", projectId, subsName) subs := &pubsub.Subscription{ Name: subsFullName, Topic: topicName, } - return gclLogsProvider.PubsubService.Projects.Subscriptions.Create(subsFullName, subs).Do() + return sdLogsProvider.PubsubService.Projects.Subscriptions.Create(subsFullName, subs).Do() } -func (gclLogsProvider *gclLogsProvider) createGclLogSink(projectId, nsName, sinkName, topicName string) (*gcl.LogSink, error) { +func (sdLogsProvider *sdLogsProvider) createSink(projectId, nsName, sinkName, topicName string) (*sd.LogSink, error) { projectDst := fmt.Sprintf("projects/%s", projectId) filter := fmt.Sprintf("(resource.type=\"gke_cluster\" AND jsonPayload.kind=\"Event\" AND jsonPayload.metadata.namespace=\"%s\") OR "+ "(resource.type=\"container\" AND resource.labels.namespace_id=\"%s\")", nsName, nsName) framework.Logf("Using the following filter for entries: %s", filter) - sink := &gcl.LogSink{ + sink := &sd.LogSink{ Name: sinkName, Destination: fmt.Sprintf("pubsub.googleapis.com/%s", topicName), Filter: filter, } - return gclLogsProvider.GclService.Projects.Sinks.Create(projectDst, sink).Do() + return sdLogsProvider.SdService.Projects.Sinks.Create(projectDst, sink).Do() } -func (gclLogsProvider *gclLogsProvider) authorizeGclLogSink() error { - topicsService := gclLogsProvider.PubsubService.Projects.Topics - policy, err := topicsService.GetIamPolicy(gclLogsProvider.Topic.Name).Do() +func (sdLogsProvider *sdLogsProvider) authorizeSink() error { + topicsService := sdLogsProvider.PubsubService.Projects.Topics + policy, err := topicsService.GetIamPolicy(sdLogsProvider.Topic.Name).Do() if err != nil { return err } binding := &pubsub.Binding{ Role: "roles/pubsub.publisher", - Members: []string{gclLogsProvider.LogSink.WriterIdentity}, + Members: []string{sdLogsProvider.LogSink.WriterIdentity}, } policy.Bindings = append(policy.Bindings, binding) req := &pubsub.SetIamPolicyRequest{Policy: policy} - if _, err = topicsService.SetIamPolicy(gclLogsProvider.Topic.Name, req).Do(); err != nil { + if _, err = topicsService.SetIamPolicy(sdLogsProvider.Topic.Name, req).Do(); err != nil { return err } return nil } -func (gclLogsProvider *gclLogsProvider) pollLogs() { - wait.PollUntil(gclLoggingPollInterval, func() (bool, error) { - subsName := gclLogsProvider.Subscription.Name - subsService := gclLogsProvider.PubsubService.Projects.Subscriptions - req := &pubsub.PullRequest{ - ReturnImmediately: true, - MaxMessages: maxPullLogMessages, - } - resp, err := subsService.Pull(subsName, req).Do() +func (sdLogsProvider *sdLogsProvider) waitSinkInit() error { + framework.Logf("Waiting for log sink to become operational") + return wait.Poll(1*time.Second, sinkStartupTimeout, func() (bool, error) { + err := publish(sdLogsProvider.PubsubService, sdLogsProvider.Topic, "embrace eternity") if err != nil { - framework.Logf("Failed to pull messaged from PubSub due to %v", err) + framework.Logf("Failed to push message to PubSub due to %v", err) + } + + messages, err := pullAndAck(sdLogsProvider.PubsubService, sdLogsProvider.Subscription) + if err != nil { + framework.Logf("Failed to pull messages from PubSub due to %v", err) + return false, nil + } + if len(messages) > 0 { + framework.Logf("Sink %s is operational", sdLogsProvider.LogSink.Name) + return true, nil + } + + return false, nil + }) +} + +func (sdLogsProvider *sdLogsProvider) pollLogs() { + wait.PollUntil(sdLoggingPollInterval, func() (bool, error) { + messages, err := pullAndAck(sdLogsProvider.PubsubService, sdLogsProvider.Subscription) + if err != nil { + framework.Logf("Failed to pull messages from PubSub due to %v", err) return false, nil } - ids := []string{} - for _, msg := range resp.ReceivedMessages { - ids = append(ids, msg.AckId) - + for _, msg := range messages { logEntryEncoded, err := base64.StdEncoding.DecodeString(msg.Message.Data) if err != nil { framework.Logf("Got a message from pubsub that is not base64-encoded: %s", msg.Message.Data) continue } - var gclLogEntry gcl.LogEntry - if err := json.Unmarshal(logEntryEncoded, &gclLogEntry); err != nil { + var sdLogEntry sd.LogEntry + if err := json.Unmarshal(logEntryEncoded, &sdLogEntry); err != nil { framework.Logf("Failed to decode a pubsub message '%s': %v", logEntryEncoded, err) continue } - switch gclLogEntry.Resource.Type { + switch sdLogEntry.Resource.Type { case "container": - podName := gclLogEntry.Resource.Labels["pod_id"] - ch := gclLogsProvider.getCacheChannel(podName) - ch <- logEntry{Payload: gclLogEntry.TextPayload} + podName := sdLogEntry.Resource.Labels["pod_id"] + ch := sdLogsProvider.getCacheChannel(podName) + ch <- logEntry{Payload: sdLogEntry.TextPayload} break case "gke_cluster": - jsonPayloadRaw, err := gclLogEntry.JsonPayload.MarshalJSON() + jsonPayloadRaw, err := sdLogEntry.JsonPayload.MarshalJSON() if err != nil { - framework.Logf("Failed to get jsonPayload from LogEntry %v", gclLogEntry) + framework.Logf("Failed to get jsonPayload from LogEntry %v", sdLogEntry) break } var eventObject map[string]interface{} @@ -218,55 +231,48 @@ func (gclLogsProvider *gclLogsProvider) pollLogs() { framework.Logf("Failed to deserialize jsonPayload as json object %s", string(jsonPayloadRaw[:])) break } - gclLogsProvider.EventCache <- eventObject + sdLogsProvider.EventCache <- eventObject break default: - framework.Logf("Received LogEntry with unexpected resource type: %s", gclLogEntry.Resource.Type) + framework.Logf("Received LogEntry with unexpected resource type: %s", sdLogEntry.Resource.Type) break } } - if len(ids) > 0 { - ackReq := &pubsub.AcknowledgeRequest{AckIds: ids} - if _, err = subsService.Acknowledge(subsName, ackReq).Do(); err != nil { - framework.Logf("Failed to ack: %v", err) - } - } - return false, nil - }, gclLogsProvider.PollingStopChannel) + }, sdLogsProvider.PollingStopChannel) } -func (gclLogsProvider *gclLogsProvider) Cleanup() { - gclLogsProvider.PollingStopChannel <- struct{}{} +func (sdLogsProvider *sdLogsProvider) Cleanup() { + sdLogsProvider.PollingStopChannel <- struct{}{} - if gclLogsProvider.LogSink != nil { + if sdLogsProvider.LogSink != nil { projectId := framework.TestContext.CloudConfig.ProjectID - sinkNameId := fmt.Sprintf("projects/%s/sinks/%s", projectId, gclLogsProvider.LogSink.Name) - sinksService := gclLogsProvider.GclService.Projects.Sinks + sinkNameId := fmt.Sprintf("projects/%s/sinks/%s", projectId, sdLogsProvider.LogSink.Name) + sinksService := sdLogsProvider.SdService.Projects.Sinks if _, err := sinksService.Delete(sinkNameId).Do(); err != nil { framework.Logf("Failed to delete LogSink: %v", err) } } - if gclLogsProvider.Subscription != nil { - subsService := gclLogsProvider.PubsubService.Projects.Subscriptions - if _, err := subsService.Delete(gclLogsProvider.Subscription.Name).Do(); err != nil { + if sdLogsProvider.Subscription != nil { + subsService := sdLogsProvider.PubsubService.Projects.Subscriptions + if _, err := subsService.Delete(sdLogsProvider.Subscription.Name).Do(); err != nil { framework.Logf("Failed to delete PubSub subscription: %v", err) } } - if gclLogsProvider.Topic != nil { - topicsService := gclLogsProvider.PubsubService.Projects.Topics - if _, err := topicsService.Delete(gclLogsProvider.Topic.Name).Do(); err != nil { + if sdLogsProvider.Topic != nil { + topicsService := sdLogsProvider.PubsubService.Projects.Topics + if _, err := topicsService.Delete(sdLogsProvider.Topic.Name).Do(); err != nil { framework.Logf("Failed to delete PubSub topic: %v", err) } } } -func (gclLogsProvider *gclLogsProvider) ReadEntries(pod *loggingPod) []logEntry { +func (sdLogsProvider *sdLogsProvider) ReadEntries(pod *loggingPod) []logEntry { var entries []logEntry - ch := gclLogsProvider.getCacheChannel(pod.Name) + ch := sdLogsProvider.getCacheChannel(pod.Name) polling_loop: for { select { @@ -279,16 +285,16 @@ polling_loop: return entries } -func (logsProvider *gclLogsProvider) FluentdApplicationName() string { +func (logsProvider *sdLogsProvider) FluentdApplicationName() string { return "fluentd-gcp" } -func (gclLogsProvider *gclLogsProvider) ReadEvents() []map[string]interface{} { +func (sdLogsProvider *sdLogsProvider) ReadEvents() []map[string]interface{} { var events []map[string]interface{} polling_loop: for { select { - case event := <-gclLogsProvider.EventCache: + case event := <-sdLogsProvider.EventCache: events = append(events, event) default: break polling_loop @@ -297,15 +303,54 @@ polling_loop: return events } -func (gclLogsProvider *gclLogsProvider) getCacheChannel(podName string) chan logEntry { - gclLogsProvider.CacheMutex.Lock() - defer gclLogsProvider.CacheMutex.Unlock() +func (sdLogsProvider *sdLogsProvider) getCacheChannel(podName string) chan logEntry { + sdLogsProvider.CacheMutex.Lock() + defer sdLogsProvider.CacheMutex.Unlock() - if ch, ok := gclLogsProvider.LogEntryCache[podName]; ok { + if ch, ok := sdLogsProvider.LogEntryCache[podName]; ok { return ch } newCh := make(chan logEntry, maxCacheSize) - gclLogsProvider.LogEntryCache[podName] = newCh + sdLogsProvider.LogEntryCache[podName] = newCh return newCh } + +func pullAndAck(service *pubsub.Service, subs *pubsub.Subscription) ([]*pubsub.ReceivedMessage, error) { + subsService := service.Projects.Subscriptions + req := &pubsub.PullRequest{ + ReturnImmediately: true, + MaxMessages: maxPullLogMessages, + } + + resp, err := subsService.Pull(subs.Name, req).Do() + if err != nil { + return nil, err + } + + var ids []string + for _, msg := range resp.ReceivedMessages { + ids = append(ids, msg.AckId) + } + if len(ids) > 0 { + ackReq := &pubsub.AcknowledgeRequest{AckIds: ids} + if _, err = subsService.Acknowledge(subs.Name, ackReq).Do(); err != nil { + framework.Logf("Failed to ack poll: %v", err) + } + } + + return resp.ReceivedMessages, nil +} + +func publish(service *pubsub.Service, topic *pubsub.Topic, msg string) error { + topicsService := service.Projects.Topics + req := &pubsub.PublishRequest{ + Messages: []*pubsub.PubsubMessage{ + { + Data: base64.StdEncoding.EncodeToString([]byte(msg)), + }, + }, + } + _, err := topicsService.Publish(topic.Name, req).Do() + return err +} diff --git a/test/e2e/cluster-logging/utils.go b/test/e2e/cluster-logging/utils.go index 7cc0a5dc826..01190acd2ef 100644 --- a/test/e2e/cluster-logging/utils.go +++ b/test/e2e/cluster-logging/utils.go @@ -213,6 +213,11 @@ func waitForFullLogsIngestion(f *framework.Framework, config *loggingTestConfig) if totalMissing > 0 { framework.Logf("After %v still missing %d lines, %.2f%% of total number of lines", config.IngestionTimeout, totalMissing, lostFraction*100) + for podIdx, missing := range missingByPod { + if missing != 0 { + framework.Logf("Still missing %d lines for pod %v", missing, config.Pods[podIdx]) + } + } } if lostFraction > config.MaxAllowedLostFraction { From e2571a853a78dfbe098a5e49609cd0f4210632ca Mon Sep 17 00:00:00 2001 From: Konstantinos Tsakalozos Date: Mon, 3 Jul 2017 17:45:40 +0300 Subject: [PATCH 183/448] Non leaders should overwrite any local copies of keys they have with what the leader has. --- .../kubernetes-master/reactive/kubernetes_master.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/cluster/juju/layers/kubernetes-master/reactive/kubernetes_master.py b/cluster/juju/layers/kubernetes-master/reactive/kubernetes_master.py index 0bc39a58404..ea78246e0a6 100644 --- a/cluster/juju/layers/kubernetes-master/reactive/kubernetes_master.py +++ b/cluster/juju/layers/kubernetes-master/reactive/kubernetes_master.py @@ -247,7 +247,9 @@ def setup_non_leader_authentication(): known_tokens = '/root/cdk/known_tokens.csv' keys = [service_key, basic_auth, known_tokens] - if not get_keys_from_leader(keys): + # The source of truth for non-leaders is the leader. + # Therefore we overwrite_local with whatever the leader has. + if not get_keys_from_leader(keys, overwrite_local=True): # the keys were not retrieved. Non-leaders have to retry. return @@ -268,7 +270,7 @@ def setup_non_leader_authentication(): set_state('authentication.setup') -def get_keys_from_leader(keys): +def get_keys_from_leader(keys, overwrite_local=False): """ Gets the broadcasted keys from the leader and stores them in the corresponding files. @@ -285,7 +287,7 @@ def get_keys_from_leader(keys): for k in keys: # If the path does not exist, assume we need it - if not os.path.exists(k): + if not os.path.exists(k) or overwrite_local: # Fetch data from leadership broadcast contents = charms.leadership.leader_get(k) # Default to logging the warning and wait for leader data to be set From c21b305fe9b111923a36312ab9caa78153819792 Mon Sep 17 00:00:00 2001 From: George Kraft Date: Mon, 3 Jul 2017 09:44:22 -0500 Subject: [PATCH 184/448] Fix kubernetes charms not restarting services after snap upgrades --- .../juju/layers/kubernetes-master/reactive/kubernetes_master.py | 1 + .../juju/layers/kubernetes-worker/reactive/kubernetes_worker.py | 1 + 2 files changed, 2 insertions(+) diff --git a/cluster/juju/layers/kubernetes-master/reactive/kubernetes_master.py b/cluster/juju/layers/kubernetes-master/reactive/kubernetes_master.py index 0bc39a58404..20d7758e39b 100644 --- a/cluster/juju/layers/kubernetes-master/reactive/kubernetes_master.py +++ b/cluster/juju/layers/kubernetes-master/reactive/kubernetes_master.py @@ -155,6 +155,7 @@ def install_snaps(): hookenv.status_set('maintenance', 'Installing cdk-addons snap') snap.install('cdk-addons', channel=channel) set_state('kubernetes-master.snaps.installed') + remove_state('kubernetes-master.components.started') @when('config.changed.channel') diff --git a/cluster/juju/layers/kubernetes-worker/reactive/kubernetes_worker.py b/cluster/juju/layers/kubernetes-worker/reactive/kubernetes_worker.py index a4f02046164..4dba0c0ff6e 100644 --- a/cluster/juju/layers/kubernetes-worker/reactive/kubernetes_worker.py +++ b/cluster/juju/layers/kubernetes-worker/reactive/kubernetes_worker.py @@ -149,6 +149,7 @@ def install_snaps(): hookenv.status_set('maintenance', 'Installing kube-proxy snap') snap.install('kube-proxy', channel=channel, classic=True) set_state('kubernetes-worker.snaps.installed') + set_state('kubernetes-worker.restart-needed') remove_state('kubernetes-worker.snaps.upgrade-needed') remove_state('kubernetes-worker.snaps.upgrade-specified') From cea934bcbc9edb4d8a84a5918988b39d522251b0 Mon Sep 17 00:00:00 2001 From: Konstantinos Tsakalozos Date: Mon, 3 Jul 2017 18:22:20 +0300 Subject: [PATCH 185/448] Fix: namespace-create have kubectl in path --- .../juju/layers/kubernetes-master/actions/namespace-create | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/cluster/juju/layers/kubernetes-master/actions/namespace-create b/cluster/juju/layers/kubernetes-master/actions/namespace-create index 56a6f5c8e40..63ba89d8e5a 100755 --- a/cluster/juju/layers/kubernetes-master/actions/namespace-create +++ b/cluster/juju/layers/kubernetes-master/actions/namespace-create @@ -1,5 +1,5 @@ #!/usr/bin/env python3 - +import os from yaml import safe_load as load from charmhelpers.core.hookenv import ( action_get, @@ -11,6 +11,9 @@ from charms.templating.jinja2 import render from subprocess import check_output +os.environ['PATH'] += os.pathsep + os.path.join(os.sep, 'snap', 'bin') + + def kubectl(args): cmd = ['kubectl'] + args return check_output(cmd) From 3ee458d2463447e9bf4d56bdc33c59a3d22a671c Mon Sep 17 00:00:00 2001 From: deads2k Date: Tue, 27 Jun 2017 16:40:14 -0400 Subject: [PATCH 186/448] remove tpr API access --- api/openapi-spec/swagger.json | 710 -------- api/swagger-spec/extensions_v1beta1.json | 682 -------- cmd/kube-apiserver/app/aggregator.go | 8 +- cmd/kube-apiserver/app/server.go | 2 +- .../extensions/v1beta1/definitions.html | 157 -- .../extensions/v1beta1/operations.html | 1525 ++--------------- hack/.linted_packages | 1 - hack/make-rules/test-cmd-util.sh | 162 -- pkg/master/thirdparty/BUILD | 5 - .../thirdparty/tprregistration_controller.go | 88 +- .../tprregistration_controller_test.go | 77 +- pkg/registry/extensions/rest/BUILD | 4 - .../extensions/rest/storage_extensions.go | 37 - test/e2e/BUILD | 1 - test/e2e/third-party.go | 186 -- test/integration/BUILD | 1 - .../etcd/etcd_storage_path_test.go | 5 +- test/integration/thirdparty/BUILD | 52 - test/integration/thirdparty/client-go_test.go | 109 -- .../integration/thirdparty/thirdparty_test.go | 284 --- 20 files changed, 153 insertions(+), 3943 deletions(-) delete mode 100644 test/e2e/third-party.go delete mode 100644 test/integration/thirdparty/BUILD delete mode 100644 test/integration/thirdparty/client-go_test.go delete mode 100644 test/integration/thirdparty/thirdparty_test.go diff --git a/api/openapi-spec/swagger.json b/api/openapi-spec/swagger.json index 04fc9ec271a..af0a6b5149f 100644 --- a/api/openapi-spec/swagger.json +++ b/api/openapi-spec/swagger.json @@ -33551,450 +33551,6 @@ } ] }, - "/apis/extensions/v1beta1/thirdpartyresources": { - "get": { - "description": "list or watch objects of kind ThirdPartyResource", - "consumes": [ - "*/*" - ], - "produces": [ - "application/json", - "application/yaml", - "application/vnd.kubernetes.protobuf", - "application/json;stream=watch", - "application/vnd.kubernetes.protobuf;stream=watch" - ], - "schemes": [ - "https" - ], - "tags": [ - "extensions_v1beta1" - ], - "operationId": "listExtensionsV1beta1ThirdPartyResource", - "parameters": [ - { - "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": "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.", - "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.extensions.v1beta1.ThirdPartyResourceList" - } - }, - "401": { - "description": "Unauthorized" - } - }, - "x-kubernetes-action": "list", - "x-kubernetes-group-version-kind": { - "group": "extensions", - "version": "v1beta1", - "kind": "ThirdPartyResource" - } - }, - "post": { - "description": "create a ThirdPartyResource", - "consumes": [ - "*/*" - ], - "produces": [ - "application/json", - "application/yaml", - "application/vnd.kubernetes.protobuf" - ], - "schemes": [ - "https" - ], - "tags": [ - "extensions_v1beta1" - ], - "operationId": "createExtensionsV1beta1ThirdPartyResource", - "parameters": [ - { - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/io.k8s.api.extensions.v1beta1.ThirdPartyResource" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/io.k8s.api.extensions.v1beta1.ThirdPartyResource" - } - }, - "401": { - "description": "Unauthorized" - } - }, - "x-kubernetes-action": "post", - "x-kubernetes-group-version-kind": { - "group": "extensions", - "version": "v1beta1", - "kind": "ThirdPartyResource" - } - }, - "delete": { - "description": "delete collection of ThirdPartyResource", - "consumes": [ - "*/*" - ], - "produces": [ - "application/json", - "application/yaml", - "application/vnd.kubernetes.protobuf" - ], - "schemes": [ - "https" - ], - "tags": [ - "extensions_v1beta1" - ], - "operationId": "deleteExtensionsV1beta1CollectionThirdPartyResource", - "parameters": [ - { - "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": "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.", - "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": "extensions", - "version": "v1beta1", - "kind": "ThirdPartyResource" - } - }, - "parameters": [ - { - "uniqueItems": true, - "type": "string", - "description": "If 'true', then the output is pretty printed.", - "name": "pretty", - "in": "query" - } - ] - }, - "/apis/extensions/v1beta1/thirdpartyresources/{name}": { - "get": { - "description": "read the specified ThirdPartyResource", - "consumes": [ - "*/*" - ], - "produces": [ - "application/json", - "application/yaml", - "application/vnd.kubernetes.protobuf" - ], - "schemes": [ - "https" - ], - "tags": [ - "extensions_v1beta1" - ], - "operationId": "readExtensionsV1beta1ThirdPartyResource", - "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.extensions.v1beta1.ThirdPartyResource" - } - }, - "401": { - "description": "Unauthorized" - } - }, - "x-kubernetes-action": "get", - "x-kubernetes-group-version-kind": { - "group": "extensions", - "version": "v1beta1", - "kind": "ThirdPartyResource" - } - }, - "put": { - "description": "replace the specified ThirdPartyResource", - "consumes": [ - "*/*" - ], - "produces": [ - "application/json", - "application/yaml", - "application/vnd.kubernetes.protobuf" - ], - "schemes": [ - "https" - ], - "tags": [ - "extensions_v1beta1" - ], - "operationId": "replaceExtensionsV1beta1ThirdPartyResource", - "parameters": [ - { - "name": "body", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/io.k8s.api.extensions.v1beta1.ThirdPartyResource" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/io.k8s.api.extensions.v1beta1.ThirdPartyResource" - } - }, - "401": { - "description": "Unauthorized" - } - }, - "x-kubernetes-action": "put", - "x-kubernetes-group-version-kind": { - "group": "extensions", - "version": "v1beta1", - "kind": "ThirdPartyResource" - } - }, - "delete": { - "description": "delete a ThirdPartyResource", - "consumes": [ - "*/*" - ], - "produces": [ - "application/json", - "application/yaml", - "application/vnd.kubernetes.protobuf" - ], - "schemes": [ - "https" - ], - "tags": [ - "extensions_v1beta1" - ], - "operationId": "deleteExtensionsV1beta1ThirdPartyResource", - "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.", - "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": "extensions", - "version": "v1beta1", - "kind": "ThirdPartyResource" - } - }, - "patch": { - "description": "partially update the specified ThirdPartyResource", - "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": [ - "extensions_v1beta1" - ], - "operationId": "patchExtensionsV1beta1ThirdPartyResource", - "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.extensions.v1beta1.ThirdPartyResource" - } - }, - "401": { - "description": "Unauthorized" - } - }, - "x-kubernetes-action": "patch", - "x-kubernetes-group-version-kind": { - "group": "extensions", - "version": "v1beta1", - "kind": "ThirdPartyResource" - } - }, - "parameters": [ - { - "uniqueItems": true, - "type": "string", - "description": "name of the ThirdPartyResource", - "name": "name", - "in": "path", - "required": true - }, - { - "uniqueItems": true, - "type": "string", - "description": "If 'true', then the output is pretty printed.", - "name": "pretty", - "in": "query" - } - ] - }, "/apis/extensions/v1beta1/watch/daemonsets": { "get": { "description": "watch individual changes to a list of DaemonSet", @@ -35653,194 +35209,6 @@ } ] }, - "/apis/extensions/v1beta1/watch/thirdpartyresources": { - "get": { - "description": "watch individual changes to a list of ThirdPartyResource", - "consumes": [ - "*/*" - ], - "produces": [ - "application/json", - "application/yaml", - "application/vnd.kubernetes.protobuf", - "application/json;stream=watch", - "application/vnd.kubernetes.protobuf;stream=watch" - ], - "schemes": [ - "https" - ], - "tags": [ - "extensions_v1beta1" - ], - "operationId": "watchExtensionsV1beta1ThirdPartyResourceList", - "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": "extensions", - "version": "v1beta1", - "kind": "ThirdPartyResource" - } - }, - "parameters": [ - { - "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": "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.", - "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/extensions/v1beta1/watch/thirdpartyresources/{name}": { - "get": { - "description": "watch changes to an object of kind ThirdPartyResource", - "consumes": [ - "*/*" - ], - "produces": [ - "application/json", - "application/yaml", - "application/vnd.kubernetes.protobuf", - "application/json;stream=watch", - "application/vnd.kubernetes.protobuf;stream=watch" - ], - "schemes": [ - "https" - ], - "tags": [ - "extensions_v1beta1" - ], - "operationId": "watchExtensionsV1beta1ThirdPartyResource", - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.WatchEvent" - } - }, - "401": { - "description": "Unauthorized" - } - }, - "x-kubernetes-action": "watch", - "x-kubernetes-group-version-kind": { - "group": "extensions", - "version": "v1beta1", - "kind": "ThirdPartyResource" - } - }, - "parameters": [ - { - "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": "string", - "description": "name of the ThirdPartyResource", - "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.", - "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/networking.k8s.io/": { "get": { "description": "get information of a group", @@ -52779,15 +52147,6 @@ } } }, - "io.k8s.api.extensions.v1beta1.APIVersion": { - "description": "An APIVersion represents a single concrete version of an object model.", - "properties": { - "name": { - "description": "Name of this version (e.g. 'v1').", - "type": "string" - } - } - }, "io.k8s.api.extensions.v1beta1.DaemonSet": { "description": "DaemonSet represents the configuration of a daemon set.", "properties": { @@ -54008,75 +53367,6 @@ } } }, - "io.k8s.api.extensions.v1beta1.ThirdPartyResource": { - "description": "A ThirdPartyResource is a generic representation of a resource, it is used by add-ons and plugins to add new resource types to the API. It consists of one or more Versions of the api.", - "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 the description of this object.", - "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" - }, - "versions": { - "description": "Versions are versions for this third party object", - "type": "array", - "items": { - "$ref": "#/definitions/io.k8s.api.extensions.v1beta1.APIVersion" - } - } - }, - "x-kubernetes-group-version-kind": [ - { - "group": "extensions", - "version": "v1beta1", - "kind": "ThirdPartyResource" - } - ] - }, - "io.k8s.api.extensions.v1beta1.ThirdPartyResourceList": { - "description": "ThirdPartyResourceList is a list of ThirdPartyResources.", - "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 ThirdPartyResources.", - "type": "array", - "items": { - "$ref": "#/definitions/io.k8s.api.extensions.v1beta1.ThirdPartyResource" - } - }, - "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": "extensions", - "version": "v1beta1", - "kind": "ThirdPartyResourceList" - } - ] - }, "io.k8s.api.networking.v1.NetworkPolicy": { "description": "NetworkPolicy describes what network traffic is allowed for a set of Pods", "properties": { diff --git a/api/swagger-spec/extensions_v1beta1.json b/api/swagger-spec/extensions_v1beta1.json index 4c0f72665c5..31dd2aa0dd3 100644 --- a/api/swagger-spec/extensions_v1beta1.json +++ b/api/swagger-spec/extensions_v1beta1.json @@ -6144,621 +6144,6 @@ } ] }, - { - "path": "/apis/extensions/v1beta1/thirdpartyresources", - "description": "API at /apis/extensions/v1beta1", - "operations": [ - { - "type": "v1beta1.ThirdPartyResourceList", - "method": "GET", - "summary": "list or watch objects of kind ThirdPartyResource", - "nickname": "listThirdPartyResource", - "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.", - "required": false, - "allowMultiple": false - } - ], - "responseMessages": [ - { - "code": 200, - "message": "OK", - "responseModel": "v1beta1.ThirdPartyResourceList" - } - ], - "produces": [ - "application/json", - "application/yaml", - "application/vnd.kubernetes.protobuf", - "application/json;stream=watch", - "application/vnd.kubernetes.protobuf;stream=watch" - ], - "consumes": [ - "*/*" - ] - }, - { - "type": "v1beta1.ThirdPartyResource", - "method": "POST", - "summary": "create a ThirdPartyResource", - "nickname": "createThirdPartyResource", - "parameters": [ - { - "type": "string", - "paramType": "query", - "name": "pretty", - "description": "If 'true', then the output is pretty printed.", - "required": false, - "allowMultiple": false - }, - { - "type": "v1beta1.ThirdPartyResource", - "paramType": "body", - "name": "body", - "description": "", - "required": true, - "allowMultiple": false - } - ], - "responseMessages": [ - { - "code": 200, - "message": "OK", - "responseModel": "v1beta1.ThirdPartyResource" - } - ], - "produces": [ - "application/json", - "application/yaml", - "application/vnd.kubernetes.protobuf" - ], - "consumes": [ - "*/*" - ] - }, - { - "type": "v1.Status", - "method": "DELETE", - "summary": "delete collection of ThirdPartyResource", - "nickname": "deletecollectionThirdPartyResource", - "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.", - "required": false, - "allowMultiple": false - } - ], - "responseMessages": [ - { - "code": 200, - "message": "OK", - "responseModel": "v1.Status" - } - ], - "produces": [ - "application/json", - "application/yaml", - "application/vnd.kubernetes.protobuf" - ], - "consumes": [ - "*/*" - ] - } - ] - }, - { - "path": "/apis/extensions/v1beta1/watch/thirdpartyresources", - "description": "API at /apis/extensions/v1beta1", - "operations": [ - { - "type": "v1.WatchEvent", - "method": "GET", - "summary": "watch individual changes to a list of ThirdPartyResource", - "nickname": "watchThirdPartyResourceList", - "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.", - "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/extensions/v1beta1/thirdpartyresources/{name}", - "description": "API at /apis/extensions/v1beta1", - "operations": [ - { - "type": "v1beta1.ThirdPartyResource", - "method": "GET", - "summary": "read the specified ThirdPartyResource", - "nickname": "readThirdPartyResource", - "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 ThirdPartyResource", - "required": true, - "allowMultiple": false - } - ], - "responseMessages": [ - { - "code": 200, - "message": "OK", - "responseModel": "v1beta1.ThirdPartyResource" - } - ], - "produces": [ - "application/json", - "application/yaml", - "application/vnd.kubernetes.protobuf" - ], - "consumes": [ - "*/*" - ] - }, - { - "type": "v1beta1.ThirdPartyResource", - "method": "PUT", - "summary": "replace the specified ThirdPartyResource", - "nickname": "replaceThirdPartyResource", - "parameters": [ - { - "type": "string", - "paramType": "query", - "name": "pretty", - "description": "If 'true', then the output is pretty printed.", - "required": false, - "allowMultiple": false - }, - { - "type": "v1beta1.ThirdPartyResource", - "paramType": "body", - "name": "body", - "description": "", - "required": true, - "allowMultiple": false - }, - { - "type": "string", - "paramType": "path", - "name": "name", - "description": "name of the ThirdPartyResource", - "required": true, - "allowMultiple": false - } - ], - "responseMessages": [ - { - "code": 200, - "message": "OK", - "responseModel": "v1beta1.ThirdPartyResource" - } - ], - "produces": [ - "application/json", - "application/yaml", - "application/vnd.kubernetes.protobuf" - ], - "consumes": [ - "*/*" - ] - }, - { - "type": "v1beta1.ThirdPartyResource", - "method": "PATCH", - "summary": "partially update the specified ThirdPartyResource", - "nickname": "patchThirdPartyResource", - "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 ThirdPartyResource", - "required": true, - "allowMultiple": false - } - ], - "responseMessages": [ - { - "code": 200, - "message": "OK", - "responseModel": "v1beta1.ThirdPartyResource" - } - ], - "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 ThirdPartyResource", - "nickname": "deleteThirdPartyResource", - "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.", - "required": false, - "allowMultiple": false - }, - { - "type": "string", - "paramType": "path", - "name": "name", - "description": "name of the ThirdPartyResource", - "required": true, - "allowMultiple": false - } - ], - "responseMessages": [ - { - "code": 200, - "message": "OK", - "responseModel": "v1.Status" - } - ], - "produces": [ - "application/json", - "application/yaml", - "application/vnd.kubernetes.protobuf" - ], - "consumes": [ - "*/*" - ] - } - ] - }, - { - "path": "/apis/extensions/v1beta1/watch/thirdpartyresources/{name}", - "description": "API at /apis/extensions/v1beta1", - "operations": [ - { - "type": "v1.WatchEvent", - "method": "GET", - "summary": "watch changes to an object of kind ThirdPartyResource", - "nickname": "watchThirdPartyResource", - "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.", - "required": false, - "allowMultiple": false - }, - { - "type": "string", - "paramType": "path", - "name": "name", - "description": "name of the ThirdPartyResource", - "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/extensions/v1beta1", "description": "API at /apis/extensions/v1beta1", @@ -10300,73 +9685,6 @@ } } }, - "v1beta1.ThirdPartyResourceList": { - "id": "v1beta1.ThirdPartyResourceList", - "description": "ThirdPartyResourceList is a list of ThirdPartyResources.", - "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." - }, - "items": { - "type": "array", - "items": { - "$ref": "v1beta1.ThirdPartyResource" - }, - "description": "Items is the list of ThirdPartyResources." - } - } - }, - "v1beta1.ThirdPartyResource": { - "id": "v1beta1.ThirdPartyResource", - "description": "A ThirdPartyResource is a generic representation of a resource, it is used by add-ons and plugins to add new resource types to the API. It consists of one or more Versions of the api.", - "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 metadata" - }, - "description": { - "type": "string", - "description": "Description is the description of this object." - }, - "versions": { - "type": "array", - "items": { - "$ref": "v1beta1.APIVersion" - }, - "description": "Versions are versions for this third party object" - } - } - }, - "v1beta1.APIVersion": { - "id": "v1beta1.APIVersion", - "description": "An APIVersion represents a single concrete version of an object model.", - "properties": { - "name": { - "type": "string", - "description": "Name of this version (e.g. 'v1')." - } - } - }, "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.", diff --git a/cmd/kube-apiserver/app/aggregator.go b/cmd/kube-apiserver/app/aggregator.go index e146d98c9b9..de77ef2e911 100644 --- a/cmd/kube-apiserver/app/aggregator.go +++ b/cmd/kube-apiserver/app/aggregator.go @@ -41,7 +41,6 @@ import ( apiregistrationclient "k8s.io/kube-aggregator/pkg/client/clientset_generated/internalclientset/typed/apiregistration/internalversion" "k8s.io/kube-aggregator/pkg/controllers/autoregister" "k8s.io/kubernetes/cmd/kube-apiserver/app/options" - informers "k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion" "k8s.io/kubernetes/pkg/master/thirdparty" ) @@ -85,7 +84,7 @@ func createAggregatorConfig(kubeAPIServerConfig genericapiserver.Config, command return aggregatorConfig, nil } -func createAggregatorServer(aggregatorConfig *aggregatorapiserver.Config, delegateAPIServer genericapiserver.DelegationTarget, kubeInformers informers.SharedInformerFactory, apiExtensionInformers apiextensionsinformers.SharedInformerFactory) (*aggregatorapiserver.APIAggregator, error) { +func createAggregatorServer(aggregatorConfig *aggregatorapiserver.Config, delegateAPIServer genericapiserver.DelegationTarget, apiExtensionInformers apiextensionsinformers.SharedInformerFactory) (*aggregatorapiserver.APIAggregator, error) { aggregatorServer, err := aggregatorConfig.Complete().NewWithDelegate(delegateAPIServer) if err != nil { return nil, err @@ -98,14 +97,13 @@ func createAggregatorServer(aggregatorConfig *aggregatorapiserver.Config, delega } autoRegistrationController := autoregister.NewAutoRegisterController(aggregatorServer.APIRegistrationInformers.Apiregistration().InternalVersion().APIServices(), apiRegistrationClient) apiServices := apiServicesToRegister(delegateAPIServer, autoRegistrationController) - tprRegistrationController := thirdparty.NewAutoRegistrationController( - kubeInformers.Extensions().InternalVersion().ThirdPartyResources(), + crdRegistrationController := thirdparty.NewAutoRegistrationController( apiExtensionInformers.Apiextensions().InternalVersion().CustomResourceDefinitions(), autoRegistrationController) aggregatorServer.GenericAPIServer.AddPostStartHook("kube-apiserver-autoregistration", func(context genericapiserver.PostStartHookContext) error { go autoRegistrationController.Run(5, context.StopCh) - go tprRegistrationController.Run(5, context.StopCh) + go crdRegistrationController.Run(5, context.StopCh) return nil }) aggregatorServer.GenericAPIServer.AddHealthzChecks(healthz.NamedCheck("autoregister-completion", func(r *http.Request) error { diff --git a/cmd/kube-apiserver/app/server.go b/cmd/kube-apiserver/app/server.go index 9c101c706c5..48dd9316b04 100644 --- a/cmd/kube-apiserver/app/server.go +++ b/cmd/kube-apiserver/app/server.go @@ -161,7 +161,7 @@ func Run(runOptions *options.ServerRunOptions, stopCh <-chan struct{}) error { } aggregatorConfig.ProxyTransport = proxyTransport aggregatorConfig.ServiceResolver = serviceResolver - aggregatorServer, err := createAggregatorServer(aggregatorConfig, kubeAPIServer.GenericAPIServer, sharedInformers, apiExtensionsServer.Informers) + 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 return err diff --git a/docs/api-reference/extensions/v1beta1/definitions.html b/docs/api-reference/extensions/v1beta1/definitions.html index 9b95b7fa0f7..ad065bdb75a 100755 --- a/docs/api-reference/extensions/v1beta1/definitions.html +++ b/docs/api-reference/extensions/v1beta1/definitions.html @@ -382,12 +382,6 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }

v1beta1.Scale

  • -

    v1beta1.ThirdPartyResource

    -
  • -
  • -

    v1beta1.ThirdPartyResourceList

    -
  • -
  • v1beta1.DaemonSetList

  • @@ -3252,40 +3246,6 @@ When an object is created, the system will populate this list with the current s - -
    -

    v1beta1.APIVersion

    -
    -

    An APIVersion represents a single concrete version of an object model.

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

    name

    Name of this version (e.g. v1).

    false

    string

    -

    v1beta1.SupplementalGroupsStrategyOptions

    @@ -5817,68 +5777,6 @@ Examples:
    -
    -
    -

    v1beta1.ThirdPartyResource

    -
    -

    A ThirdPartyResource is a generic representation of a resource, it is used by add-ons and plugins to add new resource types to the API. It consists of one or more Versions of the api.

    -
    - ------- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    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 metadata

    false

    v1.ObjectMeta

    description

    Description is the description of this object.

    false

    string

    versions

    Versions are versions for this third party object

    false

    v1beta1.APIVersion array

    -

    v1.DeletionPropagation

    @@ -8152,61 +8050,6 @@ Both these may change in the future. Incoming requests are matched against the h -
    -
    -

    v1beta1.ThirdPartyResourceList

    -
    -

    ThirdPartyResourceList is a list of ThirdPartyResources.

    -
    - ------- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    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.

    false

    v1.ListMeta

    items

    Items is the list of ThirdPartyResources.

    true

    v1beta1.ThirdPartyResource array

    -

    v1.AzureDataDiskCachingMode

    diff --git a/docs/api-reference/extensions/v1beta1/operations.html b/docs/api-reference/extensions/v1beta1/operations.html index d51388f77f6..acd272ffe73 100755 --- a/docs/api-reference/extensions/v1beta1/operations.html +++ b/docs/api-reference/extensions/v1beta1/operations.html @@ -9886,10 +9886,10 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
    -

    list or watch objects of kind ThirdPartyResource

    +

    watch individual changes to a list of DaemonSet

    -
    GET /apis/extensions/v1beta1/thirdpartyresources
    +
    GET /apis/extensions/v1beta1/watch/daemonsets
    @@ -9993,7 +9993,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }

    200

    success

    -

    v1beta1.ThirdPartyResourceList

    +

    v1.WatchEvent

    @@ -10043,10 +10043,10 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
    -

    delete collection of ThirdPartyResource

    +

    watch individual changes to a list of Deployment

    -
    DELETE /apis/extensions/v1beta1/thirdpartyresources
    +
    GET /apis/extensions/v1beta1/watch/deployments
    @@ -10150,7 +10150,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }

    200

    success

    -

    v1.Status

    +

    v1.WatchEvent

    @@ -10179,6 +10179,12 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
  • application/vnd.kubernetes.protobuf

  • +
  • +

    application/json;stream=watch

    +
  • +
  • +

    application/vnd.kubernetes.protobuf;stream=watch

    +
  • @@ -10194,10 +10200,10 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
    -

    create a ThirdPartyResource

    +

    watch individual changes to a list of Ingress

    -
    POST /apis/extensions/v1beta1/thirdpartyresources
    +
    GET /apis/extensions/v1beta1/watch/ingresses
    @@ -10231,11 +10237,51 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; } -

    BodyParameter

    -

    body

    +

    QueryParameter

    +

    labelSelector

    +

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

    +

    false

    +

    string

    -

    true

    -

    v1beta1.ThirdPartyResource

    + + +

    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.

    +

    false

    +

    integer (int32)

    @@ -10261,7 +10307,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }

    200

    success

    -

    v1beta1.ThirdPartyResource

    +

    v1.WatchEvent

    @@ -10290,6 +10336,12 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
  • application/vnd.kubernetes.protobuf

  • +
  • +

    application/json;stream=watch

    +
  • +
  • +

    application/vnd.kubernetes.protobuf;stream=watch

    +
  • @@ -10305,991 +10357,6 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
    -

    read the specified ThirdPartyResource

    -
    -
    -
    GET /apis/extensions/v1beta1/thirdpartyresources/{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 ThirdPartyResource

    true

    string

    - -
    -
    -

    Responses

    - ----- - - - - - - - - - - - - - - -
    HTTP CodeDescriptionSchema

    200

    success

    v1beta1.ThirdPartyResource

    - -
    -
    -

    Consumes

    -
    -
      -
    • -

      /

      -
    • -
    -
    -
    -
    -

    Produces

    -
    -
      -
    • -

      application/json

      -
    • -
    • -

      application/yaml

      -
    • -
    • -

      application/vnd.kubernetes.protobuf

      -
    • -
    -
    -
    -
    -

    Tags

    -
    -
      -
    • -

      apisextensionsv1beta1

      -
    • -
    -
    -
    -
    -
    -

    replace the specified ThirdPartyResource

    -
    -
    -
    PUT /apis/extensions/v1beta1/thirdpartyresources/{name}
    -
    -
    -
    -

    Parameters

    - -------- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    TypeNameDescriptionRequiredSchemaDefault

    QueryParameter

    pretty

    If true, then the output is pretty printed.

    false

    string

    BodyParameter

    body

    true

    v1beta1.ThirdPartyResource

    PathParameter

    name

    name of the ThirdPartyResource

    true

    string

    - -
    -
    -

    Responses

    - ----- - - - - - - - - - - - - - - -
    HTTP CodeDescriptionSchema

    200

    success

    v1beta1.ThirdPartyResource

    - -
    -
    -

    Consumes

    -
    -
      -
    • -

      /

      -
    • -
    -
    -
    -
    -

    Produces

    -
    -
      -
    • -

      application/json

      -
    • -
    • -

      application/yaml

      -
    • -
    • -

      application/vnd.kubernetes.protobuf

      -
    • -
    -
    -
    -
    -

    Tags

    -
    -
      -
    • -

      apisextensionsv1beta1

      -
    • -
    -
    -
    -
    -
    -

    delete a ThirdPartyResource

    -
    -
    -
    DELETE /apis/extensions/v1beta1/thirdpartyresources/{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.

    false

    string

    PathParameter

    name

    name of the ThirdPartyResource

    true

    string

    - -
    -
    -

    Responses

    - ----- - - - - - - - - - - - - - - -
    HTTP CodeDescriptionSchema

    200

    success

    v1.Status

    - -
    -
    -

    Consumes

    -
    -
      -
    • -

      /

      -
    • -
    -
    -
    -
    -

    Produces

    -
    -
      -
    • -

      application/json

      -
    • -
    • -

      application/yaml

      -
    • -
    • -

      application/vnd.kubernetes.protobuf

      -
    • -
    -
    -
    -
    -

    Tags

    -
    -
      -
    • -

      apisextensionsv1beta1

      -
    • -
    -
    -
    -
    -
    -

    partially update the specified ThirdPartyResource

    -
    -
    -
    PATCH /apis/extensions/v1beta1/thirdpartyresources/{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 ThirdPartyResource

    true

    string

    - -
    -
    -

    Responses

    - ----- - - - - - - - - - - - - - - -
    HTTP CodeDescriptionSchema

    200

    success

    v1beta1.ThirdPartyResource

    - -
    -
    -

    Consumes

    -
    -
      -
    • -

      application/json-patch+json

      -
    • -
    • -

      application/merge-patch+json

      -
    • -
    • -

      application/strategic-merge-patch+json

      -
    • -
    -
    -
    -
    -

    Produces

    -
    -
      -
    • -

      application/json

      -
    • -
    • -

      application/yaml

      -
    • -
    • -

      application/vnd.kubernetes.protobuf

      -
    • -
    -
    -
    -
    -

    Tags

    -
    -
      -
    • -

      apisextensionsv1beta1

      -
    • -
    -
    -
    -
    -
    -

    watch individual changes to a list of DaemonSet

    -
    -
    -
    GET /apis/extensions/v1beta1/watch/daemonsets
    -
    -
    -
    -

    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.

    false

    integer (int32)

    - -
    -
    -

    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

    -
    -
      -
    • -

      apisextensionsv1beta1

      -
    • -
    -
    -
    -
    -
    -

    watch individual changes to a list of Deployment

    -
    -
    -
    GET /apis/extensions/v1beta1/watch/deployments
    -
    -
    -
    -

    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.

    false

    integer (int32)

    - -
    -
    -

    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

    -
    -
      -
    • -

      apisextensionsv1beta1

      -
    • -
    -
    -
    -
    -
    -

    watch individual changes to a list of Ingress

    -
    -
    -
    GET /apis/extensions/v1beta1/watch/ingresses
    -
    -
    -
    -

    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.

    false

    integer (int32)

    - -
    -
    -

    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

    -
    -
      -
    • -

      apisextensionsv1beta1

      -
    • -
    -
    -
    -
    -

    watch individual changes to a list of DaemonSet

    @@ -11297,7 +10364,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
    -

    Parameters

    +

    Parameters

    @@ -11387,7 +10454,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
    -

    Responses

    +

    Responses

    @@ -11412,7 +10479,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
    -

    Consumes

    +

    Consumes

    • @@ -11422,7 +10489,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
    -

    Produces

    +

    Produces

    • @@ -11444,7 +10511,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
    -

    Tags

    +

    Tags

    • @@ -11462,7 +10529,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
    -

    Parameters

    +

    Parameters

    @@ -11560,7 +10627,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
    -

    Responses

    +

    Responses

    @@ -11585,7 +10652,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
    -

    Consumes

    +

    Consumes

    • @@ -11595,7 +10662,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
    -

    Produces

    +

    Produces

    • @@ -11617,7 +10684,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
    -

    Tags

    +

    Tags

    • @@ -11635,7 +10702,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
    -

    Parameters

    +

    Parameters

    @@ -11725,7 +10792,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
    -

    Responses

    +

    Responses

    @@ -11750,7 +10817,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
    -

    Consumes

    +

    Consumes

    • @@ -11760,7 +10827,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
    -

    Produces

    +

    Produces

    • @@ -11782,7 +10849,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
    -

    Tags

    +

    Tags

    • @@ -11800,7 +10867,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
    -

    Parameters

    +

    Parameters

    @@ -11898,7 +10965,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
    -

    Responses

    +

    Responses

    @@ -11923,7 +10990,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
    -

    Consumes

    +

    Consumes

    • @@ -11933,7 +11000,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
    -

    Produces

    +

    Produces

    • @@ -11955,7 +11022,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
    -

    Tags

    +

    Tags

    • @@ -11973,7 +11040,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
    -

    Parameters

    +

    Parameters

    @@ -12063,7 +11130,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
    -

    Responses

    +

    Responses

    @@ -12088,7 +11155,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
    -

    Consumes

    +

    Consumes

    • @@ -12098,7 +11165,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
    -

    Produces

    +

    Produces

    • @@ -12120,7 +11187,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
    -

    Tags

    +

    Tags

    • @@ -12138,7 +11205,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
    -

    Parameters

    +

    Parameters

    @@ -12236,7 +11303,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
    -

    Responses

    +

    Responses

    @@ -12261,7 +11328,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
    -

    Consumes

    +

    Consumes

    • @@ -12271,7 +11338,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
    -

    Produces

    +

    Produces

    • @@ -12293,7 +11360,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
    -

    Tags

    +

    Tags

    • @@ -12311,7 +11378,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
    -

    Parameters

    +

    Parameters

    @@ -12401,7 +11468,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
    -

    Responses

    +

    Responses

    @@ -12426,7 +11493,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
    -

    Consumes

    +

    Consumes

    • @@ -12436,7 +11503,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
    -

    Produces

    +

    Produces

    • @@ -12458,7 +11525,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
    -

    Tags

    +

    Tags

    • @@ -12476,7 +11543,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
    -

    Parameters

    +

    Parameters

    @@ -12574,7 +11641,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
    -

    Responses

    +

    Responses

    @@ -12599,7 +11666,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
    -

    Consumes

    +

    Consumes

    • @@ -12609,7 +11676,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
    -

    Produces

    +

    Produces

    • @@ -12631,7 +11698,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
    -

    Tags

    +

    Tags

    • @@ -12649,7 +11716,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
    -

    Parameters

    +

    Parameters

    @@ -12739,7 +11806,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
    -

    Responses

    +

    Responses

    @@ -12764,7 +11831,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
    -

    Consumes

    +

    Consumes

    • @@ -12774,7 +11841,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
    -

    Produces

    +

    Produces

    • @@ -12796,7 +11863,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
    -

    Tags

    +

    Tags

    • @@ -12814,7 +11881,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
    -

    Parameters

    +

    Parameters

    @@ -12912,7 +11979,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
    -

    Responses

    +

    Responses

    @@ -12937,7 +12004,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
    -

    Consumes

    +

    Consumes

    • @@ -12947,7 +12014,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
    -

    Produces

    +

    Produces

    • @@ -12969,7 +12036,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
    -

    Tags

    +

    Tags

    • @@ -12987,7 +12054,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
    -

    Parameters

    +

    Parameters

    @@ -13069,7 +12136,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
    -

    Responses

    +

    Responses

    @@ -13094,7 +12161,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
    -

    Consumes

    +

    Consumes

    • @@ -13104,7 +12171,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
    -

    Produces

    +

    Produces

    • @@ -13126,7 +12193,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
    -

    Tags

    +

    Tags

    • @@ -13144,7 +12211,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
    -

    Parameters

    +

    Parameters

    @@ -13226,7 +12293,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
    -

    Responses

    +

    Responses

    @@ -13251,7 +12318,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
    -

    Consumes

    +

    Consumes

    • @@ -13261,7 +12328,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
    -

    Produces

    +

    Produces

    • @@ -13283,7 +12350,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
    -

    Tags

    +

    Tags

    • @@ -13301,7 +12368,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
    -

    Parameters

    +

    Parameters

    @@ -13391,7 +12458,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
    -

    Responses

    +

    Responses

    @@ -13416,7 +12483,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
    -

    Consumes

    +

    Consumes

    • @@ -13426,7 +12493,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
    -

    Produces

    +

    Produces

    • @@ -13448,7 +12515,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
    -

    Tags

    +

    Tags

    • @@ -13466,7 +12533,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
    -

    Parameters

    +

    Parameters

    @@ -13548,7 +12615,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
    -

    Responses

    +

    Responses

    @@ -13573,7 +12640,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
    -

    Consumes

    +

    Consumes

    • @@ -13583,7 +12650,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
    -

    Produces

    +

    Produces

    • @@ -13605,329 +12672,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
    -

    Tags

    -
    -
      -
    • -

      apisextensionsv1beta1

      -
    • -
    -
    -
    - -
    -

    watch individual changes to a list of ThirdPartyResource

    -
    -
    -
    GET /apis/extensions/v1beta1/watch/thirdpartyresources
    -
    -
    -
    -

    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.

    false

    integer (int32)

    - -
    -
    -

    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

    -
    -
      -
    • -

      apisextensionsv1beta1

      -
    • -
    -
    -
    -
    -
    -

    watch changes to an object of kind ThirdPartyResource

    -
    -
    -
    GET /apis/extensions/v1beta1/watch/thirdpartyresources/{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.

    false

    integer (int32)

    PathParameter

    name

    name of the ThirdPartyResource

    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

    +

    Tags

    • diff --git a/hack/.linted_packages b/hack/.linted_packages index 8b59a161dea..5d70e1f9ffe 100644 --- a/hack/.linted_packages +++ b/hack/.linted_packages @@ -498,7 +498,6 @@ test/integration/quota test/integration/secrets test/integration/serviceaccount test/integration/storageclasses -test/integration/thirdparty test/integration/ttlcontroller test/soak/cauldron test/soak/serve_hostnames diff --git a/hack/make-rules/test-cmd-util.sh b/hack/make-rules/test-cmd-util.sh index fc34fe9e6c0..639ceffe5cd 100644 --- a/hack/make-rules/test-cmd-util.sh +++ b/hack/make-rules/test-cmd-util.sh @@ -1492,161 +1492,6 @@ __EOF__ set +o errexit } -run_tpr_tests() { - set -o nounset - set -o errexit - - create_and_use_new_namespace - kube::log::status "Testing kubectl tpr" - kubectl "${kube_flags[@]}" create -f - "${kube_flags[@]}" << __EOF__ -{ - "kind": "ThirdPartyResource", - "apiVersion": "extensions/v1beta1", - "metadata": { - "name": "foo.company.com" - }, - "versions": [ - { - "name": "v1" - } - ] -} -__EOF__ - - # Post-Condition: assertion object exist - kube::test::get_object_assert thirdpartyresources "{{range.items}}{{$id_field}}:{{end}}" 'foo.company.com:' - - kubectl "${kube_flags[@]}" create -f - "${kube_flags[@]}" << __EOF__ -{ - "kind": "ThirdPartyResource", - "apiVersion": "extensions/v1beta1", - "metadata": { - "name": "bar.company.com" - }, - "versions": [ - { - "name": "v1" - } - ] -} -__EOF__ - - # Post-Condition: assertion object exist - kube::test::get_object_assert thirdpartyresources "{{range.items}}{{$id_field}}:{{end}}" 'bar.company.com:foo.company.com:' - - run_non_native_resource_tests - - # teardown - kubectl delete thirdpartyresources/foo.company.com "${kube_flags[@]}" - kubectl delete thirdpartyresources/bar.company.com "${kube_flags[@]}" - - set +o nounset - set +o errexit -} - -run_tpr_migration_tests() { - set -o nounset - set -o errexit - - kube::log::status "Testing kubectl tpr migration" - local i tries - create_and_use_new_namespace - - # Create CRD first. This is sort of backwards so we can create a marker below. - kubectl "${kube_flags_with_token[@]}" create -f - << __EOF__ -{ - "kind": "CustomResourceDefinition", - "apiVersion": "apiextensions.k8s.io/v1beta1", - "metadata": { - "name": "foos.company.crd" - }, - "spec": { - "group": "company.crd", - "version": "v1", - "names": { - "plural": "foos", - "kind": "Foo" - } - } -} -__EOF__ - # Wait for API to become available. - tries=0 - until kubectl "${kube_flags[@]}" get foos.company.crd || [ $tries -gt 10 ]; do - tries=$((tries+1)) - sleep ${tries} - done - kube::test::get_object_assert foos.company.crd '{{len .items}}' '0' - - # Create a marker that only exists in CRD so we know when CRD is active vs. TPR. - kubectl "${kube_flags[@]}" create -f - << __EOF__ -{ - "kind": "Foo", - "apiVersion": "company.crd/v1", - "metadata": { - "name": "crd-marker" - }, - "testValue": "only exists in CRD" -} -__EOF__ - kube::test::get_object_assert foos.company.crd '{{len .items}}' '1' - - # Now create a TPR that sits in front of the CRD and hides it. - kubectl "${kube_flags[@]}" create -f - << __EOF__ -{ - "kind": "ThirdPartyResource", - "apiVersion": "extensions/v1beta1", - "metadata": { - "name": "foo.company.crd" - }, - "versions": [ - { - "name": "v1" - } - ] -} -__EOF__ - # The marker should disappear. - kube::test::wait_object_assert foos.company.crd '{{len .items}}' '0' - - # Add some items to the TPR. - for i in {1..10}; do - kubectl "${kube_flags[@]}" create -f - << __EOF__ -{ - "kind": "Foo", - "apiVersion": "company.crd/v1", - "metadata": { - "name": "tpr-${i}" - }, - "testValue": "migrate-${i}" -} -__EOF__ - done - kube::test::get_object_assert foos.company.crd '{{len .items}}' '10' - - # Delete the TPR and wait for the CRD to take over. - kubectl "${kube_flags[@]}" delete thirdpartyresource/foo.company.crd - tries=0 - until kubectl "${kube_flags[@]}" get foos.company.crd/crd-marker || [ $tries -gt 10 ]; do - tries=$((tries+1)) - sleep ${tries} - done - kube::test::get_object_assert foos.company.crd/crd-marker '{{.testValue}}' 'only exists in CRD' - - # Check if the TPR items were migrated to CRD. - kube::test::get_object_assert foos.company.crd '{{len .items}}' '11' - for i in {1..10}; do - kube::test::get_object_assert foos.company.crd/tpr-${i} '{{.testValue}}' "migrate-${i}" - done - - # teardown - kubectl delete customresourcedefinitions/foos.company.crd "${kube_flags_with_token[@]}" - - set +o nounset - set +o errexit -} - - kube::util::non_native_resources() { local times local wait @@ -4455,13 +4300,6 @@ runTests() { record_command run_crd_tests fi - if kube::test::if_supports_resource "${thirdpartyresources}" ; then - record_command run_tpr_tests - if kube::test::if_supports_resource "${customresourcedefinitions}" ; then - record_command run_tpr_migration_tests - fi - fi - ################# # Run cmd w img # ################# diff --git a/pkg/master/thirdparty/BUILD b/pkg/master/thirdparty/BUILD index 2e2a14bd5ff..2ba97ed38a0 100644 --- a/pkg/master/thirdparty/BUILD +++ b/pkg/master/thirdparty/BUILD @@ -18,8 +18,6 @@ go_library( deps = [ "//pkg/api:go_default_library", "//pkg/apis/extensions:go_default_library", - "//pkg/client/informers/informers_generated/internalversion/extensions/internalversion:go_default_library", - "//pkg/client/listers/extensions/internalversion:go_default_library", "//pkg/controller:go_default_library", "//pkg/registry/extensions/rest:go_default_library", "//pkg/registry/extensions/thirdpartyresourcedata:go_default_library", @@ -75,14 +73,11 @@ go_test( library = ":go_default_library", tags = ["automanaged"], deps = [ - "//pkg/apis/extensions:go_default_library", - "//pkg/client/listers/extensions/internalversion:go_default_library", "//vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions:go_default_library", "//vendor/k8s.io/apiextensions-apiserver/pkg/client/listers/apiextensions/internalversion: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/tools/cache:go_default_library", - "//vendor/k8s.io/client-go/util/workqueue:go_default_library", "//vendor/k8s.io/kube-aggregator/pkg/apis/apiregistration:go_default_library", ], ) diff --git a/pkg/master/thirdparty/tprregistration_controller.go b/pkg/master/thirdparty/tprregistration_controller.go index 6e0bcc3fac5..bfaa0421661 100644 --- a/pkg/master/thirdparty/tprregistration_controller.go +++ b/pkg/master/thirdparty/tprregistration_controller.go @@ -33,11 +33,7 @@ import ( "k8s.io/client-go/tools/cache" "k8s.io/client-go/util/workqueue" "k8s.io/kube-aggregator/pkg/apis/apiregistration" - "k8s.io/kubernetes/pkg/apis/extensions" - informers "k8s.io/kubernetes/pkg/client/informers/informers_generated/internalversion/extensions/internalversion" - listers "k8s.io/kubernetes/pkg/client/listers/extensions/internalversion" "k8s.io/kubernetes/pkg/controller" - "k8s.io/kubernetes/pkg/registry/extensions/thirdpartyresourcedata" ) // AutoAPIServiceRegistration is an interface which callers can re-declare locally and properly cast to for @@ -49,9 +45,7 @@ type AutoAPIServiceRegistration interface { RemoveAPIServiceToSync(name string) } -type tprRegistrationController struct { - tprLister listers.ThirdPartyResourceLister - tprSynced cache.InformerSynced +type crdRegistrationController struct { crdLister crdlisters.CustomResourceDefinitionLister crdSynced cache.InformerSynced @@ -68,44 +62,15 @@ type tprRegistrationController struct { // controller so they automatically stay in sync. // In order to stay sane with both TPR and CRD present, we have a single controller that manages both. When choosing whether to have an // APIService, we simply iterate through both. -func NewAutoRegistrationController(tprInformer informers.ThirdPartyResourceInformer, crdinformer crdinformers.CustomResourceDefinitionInformer, apiServiceRegistration AutoAPIServiceRegistration) *tprRegistrationController { - c := &tprRegistrationController{ - tprLister: tprInformer.Lister(), - tprSynced: tprInformer.Informer().HasSynced, +func NewAutoRegistrationController(crdinformer crdinformers.CustomResourceDefinitionInformer, apiServiceRegistration AutoAPIServiceRegistration) *crdRegistrationController { + c := &crdRegistrationController{ crdLister: crdinformer.Lister(), crdSynced: crdinformer.Informer().HasSynced, apiServiceRegistration: apiServiceRegistration, - queue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "tpr-autoregister"), + queue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "crd-autoregister"), } c.syncHandler = c.handleVersionUpdate - tprInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ - AddFunc: func(obj interface{}) { - cast := obj.(*extensions.ThirdPartyResource) - c.enqueueTPR(cast) - }, - UpdateFunc: func(_, obj interface{}) { - cast := obj.(*extensions.ThirdPartyResource) - c.enqueueTPR(cast) - }, - DeleteFunc: func(obj interface{}) { - cast, ok := obj.(*extensions.ThirdPartyResource) - if !ok { - tombstone, ok := obj.(cache.DeletedFinalStateUnknown) - if !ok { - glog.V(2).Infof("Couldn't get object from tombstone %#v", obj) - return - } - cast, ok = tombstone.Obj.(*extensions.ThirdPartyResource) - if !ok { - glog.V(2).Infof("Tombstone contained unexpected object: %#v", obj) - return - } - } - c.enqueueTPR(cast) - }, - }) - crdinformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ AddFunc: func(obj interface{}) { cast := obj.(*apiextensions.CustomResourceDefinition) @@ -136,16 +101,16 @@ func NewAutoRegistrationController(tprInformer informers.ThirdPartyResourceInfor return c } -func (c *tprRegistrationController) Run(threadiness int, stopCh <-chan struct{}) { +func (c *crdRegistrationController) Run(threadiness int, stopCh <-chan struct{}) { defer utilruntime.HandleCrash() // make sure the work queue is shutdown which will trigger workers to end defer c.queue.ShutDown() - glog.Infof("Starting tpr-autoregister controller") - defer glog.Infof("Shutting down tpr-autoregister controller") + glog.Infof("Starting crd-autoregister controller") + defer glog.Infof("Shutting down crd-autoregister controller") // wait for your secondary caches to fill before starting your work - if !controller.WaitForCacheSync("tpr-autoregister", stopCh, c.tprSynced) { + if !controller.WaitForCacheSync("crd-autoregister", stopCh, c.crdSynced) { return } @@ -160,7 +125,7 @@ func (c *tprRegistrationController) Run(threadiness int, stopCh <-chan struct{}) <-stopCh } -func (c *tprRegistrationController) runWorker() { +func (c *crdRegistrationController) runWorker() { // hot loop until we're told to stop. processNextWorkItem will automatically wait until there's work // available, so we don't worry about secondary waits for c.processNextWorkItem() { @@ -168,7 +133,7 @@ func (c *tprRegistrationController) runWorker() { } // processNextWorkItem deals with one key off the queue. It returns false when it's time to quit. -func (c *tprRegistrationController) processNextWorkItem() bool { +func (c *crdRegistrationController) processNextWorkItem() bool { // pull the next work item from queue. It should be a key we use to lookup something in a cache key, quit := c.queue.Get() if quit { @@ -198,43 +163,14 @@ func (c *tprRegistrationController) processNextWorkItem() bool { return true } -func (c *tprRegistrationController) enqueueTPR(tpr *extensions.ThirdPartyResource) { - _, group, err := thirdpartyresourcedata.ExtractApiGroupAndKind(tpr) - if err != nil { - utilruntime.HandleError(err) - return - } - for _, version := range tpr.Versions { - c.queue.Add(schema.GroupVersion{Group: group, Version: version.Name}) - } -} - -func (c *tprRegistrationController) enqueueCRD(crd *apiextensions.CustomResourceDefinition) { +func (c *crdRegistrationController) enqueueCRD(crd *apiextensions.CustomResourceDefinition) { c.queue.Add(schema.GroupVersion{Group: crd.Spec.Group, Version: crd.Spec.Version}) } -func (c *tprRegistrationController) handleVersionUpdate(groupVersion schema.GroupVersion) error { +func (c *crdRegistrationController) handleVersionUpdate(groupVersion schema.GroupVersion) error { found := false apiServiceName := groupVersion.Version + "." + groupVersion.Group - // check all TPRs. There shouldn't that many, but if we have problems later we can index them - tprs, err := c.tprLister.List(labels.Everything()) - if err != nil { - return err - } - for _, tpr := range tprs { - _, group, err := thirdpartyresourcedata.ExtractApiGroupAndKind(tpr) - if err != nil { - return err - } - for _, version := range tpr.Versions { - if version.Name == groupVersion.Version && group == groupVersion.Group { - found = true - break - } - } - } - // check all CRDs. There shouldn't that many, but if we have problems later we can index them crds, err := c.crdLister.List(labels.Everything()) if err != nil { diff --git a/pkg/master/thirdparty/tprregistration_controller_test.go b/pkg/master/thirdparty/tprregistration_controller_test.go index 97c6e28ec2f..b4573a5fa30 100644 --- a/pkg/master/thirdparty/tprregistration_controller_test.go +++ b/pkg/master/thirdparty/tprregistration_controller_test.go @@ -25,87 +25,18 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/client-go/tools/cache" - "k8s.io/client-go/util/workqueue" "k8s.io/kube-aggregator/pkg/apis/apiregistration" - "k8s.io/kubernetes/pkg/apis/extensions" - listers "k8s.io/kubernetes/pkg/client/listers/extensions/internalversion" ) -func TestEnqueue(t *testing.T) { - c := tprRegistrationController{ - queue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "tpr-autoregister"), - } - - tpr := &extensions.ThirdPartyResource{ - ObjectMeta: metav1.ObjectMeta{Name: "resource.group.example.com"}, - Versions: []extensions.APIVersion{ - {Name: "v1alpha1"}, - {Name: "v1"}, - }, - } - c.enqueueTPR(tpr) - - first, _ := c.queue.Get() - expectedFirst := schema.GroupVersion{Group: "group.example.com", Version: "v1alpha1"} - if first != expectedFirst { - t.Errorf("expected %v, got %v", expectedFirst, first) - } - - second, _ := c.queue.Get() - expectedSecond := schema.GroupVersion{Group: "group.example.com", Version: "v1"} - if second != expectedSecond { - t.Errorf("expected %v, got %v", expectedSecond, second) - } -} - func TestHandleVersionUpdate(t *testing.T) { tests := []struct { name string - startingTPRs []*extensions.ThirdPartyResource startingCRDs []*apiextensions.CustomResourceDefinition version schema.GroupVersion expectedAdded []*apiregistration.APIService expectedRemoved []string }{ - { - name: "simple add tpr", - startingTPRs: []*extensions.ThirdPartyResource{ - { - ObjectMeta: metav1.ObjectMeta{Name: "resource.group.com"}, - Versions: []extensions.APIVersion{ - {Name: "v1"}, - }, - }, - }, - version: schema.GroupVersion{Group: "group.com", Version: "v1"}, - - expectedAdded: []*apiregistration.APIService{ - { - ObjectMeta: metav1.ObjectMeta{Name: "v1.group.com"}, - Spec: apiregistration.APIServiceSpec{ - Group: "group.com", - Version: "v1", - GroupPriorityMinimum: 1000, - VersionPriority: 100, - }, - }, - }, - }, - { - name: "simple remove tpr", - startingTPRs: []*extensions.ThirdPartyResource{ - { - ObjectMeta: metav1.ObjectMeta{Name: "resource.group.com"}, - Versions: []extensions.APIVersion{ - {Name: "v1"}, - }, - }, - }, - version: schema.GroupVersion{Group: "group.com", Version: "v2"}, - - expectedRemoved: []string{"v2.group.com"}, - }, { name: "simple add crd", startingCRDs: []*apiextensions.CustomResourceDefinition{ @@ -148,18 +79,12 @@ func TestHandleVersionUpdate(t *testing.T) { for _, test := range tests { registration := &fakeAPIServiceRegistration{} - tprCache := cache.NewIndexer(cache.DeletionHandlingMetaNamespaceKeyFunc, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}) - tprLister := listers.NewThirdPartyResourceLister(tprCache) crdCache := cache.NewIndexer(cache.DeletionHandlingMetaNamespaceKeyFunc, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}) crdLister := crdlisters.NewCustomResourceDefinitionLister(crdCache) - c := tprRegistrationController{ - tprLister: tprLister, + c := crdRegistrationController{ crdLister: crdLister, apiServiceRegistration: registration, } - for i := range test.startingTPRs { - tprCache.Add(test.startingTPRs[i]) - } for i := range test.startingCRDs { crdCache.Add(test.startingCRDs[i]) } diff --git a/pkg/registry/extensions/rest/BUILD b/pkg/registry/extensions/rest/BUILD index 2b21c5dc1de..6904731a9b4 100644 --- a/pkg/registry/extensions/rest/BUILD +++ b/pkg/registry/extensions/rest/BUILD @@ -39,15 +39,11 @@ go_library( "//pkg/registry/extensions/networkpolicy/storage:go_default_library", "//pkg/registry/extensions/podsecuritypolicy/storage:go_default_library", "//pkg/registry/extensions/replicaset/storage:go_default_library", - "//pkg/registry/extensions/thirdpartyresource/storage:go_default_library", "//pkg/registry/extensions/thirdpartyresourcedata:go_default_library", - "//vendor/github.com/golang/glog: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/runtime: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/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/pkg/registry/extensions/rest/storage_extensions.go b/pkg/registry/extensions/rest/storage_extensions.go index f674e94e920..a593921b48a 100644 --- a/pkg/registry/extensions/rest/storage_extensions.go +++ b/pkg/registry/extensions/rest/storage_extensions.go @@ -17,21 +17,13 @@ limitations under the License. package rest import ( - "fmt" - "time" - - "github.com/golang/glog" - extensionsapiv1beta1 "k8s.io/api/extensions/v1beta1" - 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" serverstorage "k8s.io/apiserver/pkg/server/storage" "k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/apis/extensions" - extensionsclient "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/internalversion" expcontrollerstore "k8s.io/kubernetes/pkg/registry/extensions/controller/storage" daemonstore "k8s.io/kubernetes/pkg/registry/extensions/daemonset/storage" deploymentstore "k8s.io/kubernetes/pkg/registry/extensions/deployment/storage" @@ -39,7 +31,6 @@ import ( networkpolicystore "k8s.io/kubernetes/pkg/registry/extensions/networkpolicy/storage" pspstore "k8s.io/kubernetes/pkg/registry/extensions/podsecuritypolicy/storage" replicasetstore "k8s.io/kubernetes/pkg/registry/extensions/replicaset/storage" - thirdpartyresourcestore "k8s.io/kubernetes/pkg/registry/extensions/thirdpartyresource/storage" ) type RESTStorageProvider struct { @@ -70,11 +61,6 @@ func (p RESTStorageProvider) v1beta1Storage(apiResourceConfigSource serverstorag storage["replicationcontrollers"] = controllerStorage.ReplicationController storage["replicationcontrollers/scale"] = controllerStorage.Scale - if apiResourceConfigSource.ResourceEnabled(version.WithResource("thirdpartyresources")) { - thirdPartyResourceStorage := thirdpartyresourcestore.NewREST(restOptionsGetter) - storage["thirdpartyresources"] = thirdPartyResourceStorage - } - if apiResourceConfigSource.ResourceEnabled(version.WithResource("daemonsets")) { daemonSetStorage, daemonSetStatusStorage := daemonstore.NewREST(restOptionsGetter) storage["daemonsets"] = daemonSetStorage @@ -110,29 +96,6 @@ func (p RESTStorageProvider) v1beta1Storage(apiResourceConfigSource serverstorag return storage } -func (p RESTStorageProvider) PostStartHook() (string, genericapiserver.PostStartHookFunc, error) { - return "extensions/third-party-resources", p.postStartHookFunc, nil -} -func (p RESTStorageProvider) postStartHookFunc(hookContext genericapiserver.PostStartHookContext) error { - clientset, err := extensionsclient.NewForConfig(hookContext.LoopbackClientConfig) - if err != nil { - utilruntime.HandleError(fmt.Errorf("unable to initialize client: %v", err)) - return nil - } - - thirdPartyControl := ThirdPartyController{ - master: p.ResourceInterface, - client: clientset, - } - go wait.Forever(func() { - if err := thirdPartyControl.SyncResources(); err != nil { - glog.Warningf("third party resource sync failed: %v", err) - } - }, 10*time.Second) - - return nil -} - func (p RESTStorageProvider) GroupName() string { return extensions.GroupName } diff --git a/test/e2e/BUILD b/test/e2e/BUILD index 126d2e3670c..ae5d48ecf08 100644 --- a/test/e2e/BUILD +++ b/test/e2e/BUILD @@ -104,7 +104,6 @@ go_library( "serviceloadbalancers.go", "ssh.go", "stackdriver_monitoring.go", - "third-party.go", "ubernetes_lite.go", "util_iperf.go", ], diff --git a/test/e2e/third-party.go b/test/e2e/third-party.go deleted file mode 100644 index 91e25c136a1..00000000000 --- a/test/e2e/third-party.go +++ /dev/null @@ -1,186 +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 - -import ( - "encoding/json" - "fmt" - "net/http" - "time" - - extensions "k8s.io/api/extensions/v1beta1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/util/wait" - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/test/e2e/framework" - - . "github.com/onsi/ginkgo" -) - -var data = `{ - "kind": "Foo", - "apiVersion": "company.com/v1", - "metadata": { - "name": "bazz" - }, - "someField": "hello world", - "otherField": 1 -}` - -type Foo struct { - metav1.TypeMeta `json:",inline"` - metav1.ObjectMeta `json:"metadata,omitempty" description:"standard object metadata"` - - SomeField string `json:"someField"` - OtherField int `json:"otherField"` -} - -type FooList struct { - metav1.TypeMeta `json:",inline"` - metav1.ListMeta `json:"metadata,omitempty" description:"standard list metadata; see https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata"` - - Items []Foo `json:"items"` -} - -// This test is marked flaky pending namespace controller observing dynamic creation of new third party types. -var _ = Describe("ThirdParty resources [Flaky] [Disruptive]", func() { - - f := framework.NewDefaultFramework("thirdparty") - - rsrc := &extensions.ThirdPartyResource{ - ObjectMeta: metav1.ObjectMeta{ - Name: "foo.company.com", - }, - Versions: []extensions.APIVersion{ - {Name: "v1"}, - }, - } - - Context("Simple Third Party", func() { - It("creating/deleting thirdparty objects works [Conformance]", func() { - defer func() { - if err := f.ClientSet.Extensions().ThirdPartyResources().Delete(rsrc.Name, nil); err != nil { - framework.Failf("failed to delete third party resource: %v", err) - } - }() - if _, err := f.ClientSet.Extensions().ThirdPartyResources().Create(rsrc); err != nil { - framework.Failf("failed to create third party resource: %v", err) - } - - wait.Poll(time.Second*30, time.Minute*5, func() (bool, error) { - data, err := f.ClientSet.Extensions().RESTClient().Get().AbsPath("/apis/company.com/v1/foos").DoRaw() - if err != nil { - return false, err - } - meta := metav1.TypeMeta{} - if err := json.Unmarshal(data, &meta); err != nil { - return false, err - } - if meta.Kind == "FooList" { - return true, nil - } - status := metav1.Status{} - if err := runtime.DecodeInto(api.Codecs.LegacyCodec(api.Registry.EnabledVersions()...), data, &status); err != nil { - return false, err - } - if status.Code != http.StatusNotFound { - return false, fmt.Errorf("Unexpected status: %v", status) - } - return false, nil - }) - - data, err := f.ClientSet.Extensions().RESTClient().Get().AbsPath("/apis/company.com/v1/foos").DoRaw() - if err != nil { - framework.Failf("failed to list with no objects: %v", err) - } - list := FooList{} - if err := json.Unmarshal(data, &list); err != nil { - framework.Failf("failed to decode: %#v", err) - } - if len(list.Items) != 0 { - framework.Failf("unexpected object before create: %v", list) - } - foo := &Foo{ - TypeMeta: metav1.TypeMeta{ - Kind: "Foo", - }, - ObjectMeta: metav1.ObjectMeta{ - Name: "foo", - }, - SomeField: "bar", - OtherField: 10, - } - bodyData, err := json.Marshal(foo) - if err != nil { - framework.Failf("failed to marshal: %v", err) - } - if _, err := f.ClientSet.Extensions().RESTClient().Post().AbsPath("/apis/company.com/v1/namespaces/default/foos").Body(bodyData).DoRaw(); err != nil { - framework.Failf("failed to create: %v", err) - } - - data, err = f.ClientSet.Extensions().RESTClient().Get().AbsPath("/apis/company.com/v1/namespaces/default/foos/foo").DoRaw() - if err != nil { - framework.Failf("failed to get object: %v", err) - } - out := Foo{} - if err := json.Unmarshal(data, &out); err != nil { - framework.Failf("failed to decode: %#v", err) - } - if out.Name != foo.Name || out.SomeField != foo.SomeField || out.OtherField != foo.OtherField { - framework.Failf("expected:\n%#v\nsaw:\n%#v\n%s\n", foo, &out, string(data)) - } - - data, err = f.ClientSet.Extensions().RESTClient().Get().AbsPath("/apis/company.com/v1/foos").DoRaw() - if err != nil { - framework.Failf("failed to list with no objects: %v", err) - } - if err := json.Unmarshal(data, &list); err != nil { - framework.Failf("failed to decode: %#v", err) - } - if len(list.Items) != 1 { - framework.Failf("unexpected object too few or too many: %v", list) - } - if list.Items[0].Name != foo.Name || list.Items[0].SomeField != foo.SomeField || list.Items[0].OtherField != foo.OtherField { - framework.Failf("expected: %#v, saw in list: %#v", foo, list.Items[0]) - } - - // Need to manually do the serialization because otherwise the - // Content-Type header is set to protobuf, the thirdparty codec in - // the API server side only accepts JSON. - deleteOptionsData, err := json.Marshal(metav1.NewDeleteOptions(10)) - framework.ExpectNoError(err) - if _, err := f.ClientSet.Core().RESTClient().Delete(). - AbsPath("/apis/company.com/v1/namespaces/default/foos/foo"). - Body(deleteOptionsData). - DoRaw(); err != nil { - framework.Failf("failed to delete: %v", err) - } - - data, err = f.ClientSet.Extensions().RESTClient().Get().AbsPath("/apis/company.com/v1/foos").DoRaw() - if err != nil { - framework.Failf("failed to list with no objects: %v", err) - } - if err := json.Unmarshal(data, &list); err != nil { - framework.Failf("failed to decode: %#v", err) - } - if len(list.Items) != 0 { - framework.Failf("unexpected object after delete: %v", list) - } - }) - }) -}) diff --git a/test/integration/BUILD b/test/integration/BUILD index d465c6510c0..9b8b639d26e 100644 --- a/test/integration/BUILD +++ b/test/integration/BUILD @@ -60,7 +60,6 @@ filegroup( "//test/integration/secrets:all-srcs", "//test/integration/serviceaccount:all-srcs", "//test/integration/storageclasses:all-srcs", - "//test/integration/thirdparty:all-srcs", "//test/integration/ttlcontroller:all-srcs", "//test/integration/volume:all-srcs", ], diff --git a/test/integration/etcd/etcd_storage_path_test.go b/test/integration/etcd/etcd_storage_path_test.go index fd494e3d58a..f6be745a12d 100644 --- a/test/integration/etcd/etcd_storage_path_test.go +++ b/test/integration/etcd/etcd_storage_path_test.go @@ -197,10 +197,6 @@ var etcdStorageData = map[schema.GroupVersionResource]struct { stub: `{"metadata": {"name": "psp1"}, "spec": {"fsGroup": {"rule": "RunAsAny"}, "privileged": true, "runAsUser": {"rule": "RunAsAny"}, "seLinux": {"rule": "MustRunAs"}, "supplementalGroups": {"rule": "RunAsAny"}}}`, expectedEtcdPath: "/registry/podsecuritypolicy/psp1", }, - gvr("extensions", "v1beta1", "thirdpartyresources"): { - stub: `{"description": "third party", "metadata": {"name": "kind.domain.tld"}, "versions": [{"name": "v3"}]}`, - expectedEtcdPath: "/registry/thirdpartyresources/kind.domain.tld", - }, gvr("extensions", "v1beta1", "ingresses"): { stub: `{"metadata": {"name": "ingress1"}, "spec": {"backend": {"serviceName": "service", "servicePort": 5000}}}`, expectedEtcdPath: "/registry/ingress/etcdstoragepathtestnamespace/ingress1", @@ -372,6 +368,7 @@ var ephemeralWhiteList = createEphemeralWhiteList( gvr("extensions", "v1beta1", "replicationcontrollerdummies"), // not stored in etcd gvr("extensions", "v1beta1", "scales"), // not stored in etcd, part of kapiv1.ReplicationController gvr("extensions", "v1beta1", "thirdpartyresourcedatas"), // we cannot create this + gvr("extensions", "v1beta1", "thirdpartyresources"), // these have been removed from the API server, but kept for the client // -- // k8s.io/kubernetes/pkg/apis/imagepolicy/v1alpha1 diff --git a/test/integration/thirdparty/BUILD b/test/integration/thirdparty/BUILD deleted file mode 100644 index 036c8b72dbe..00000000000 --- a/test/integration/thirdparty/BUILD +++ /dev/null @@ -1,52 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -licenses(["notice"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_test", -) - -go_test( - name = "go_default_test", - srcs = [ - "client-go_test.go", - "thirdparty_test.go", - ], - tags = [ - "automanaged", - "integration", - ], - deps = [ - "//pkg/api:go_default_library", - "//pkg/client/clientset_generated/clientset:go_default_library", - "//test/integration/framework: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/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/diff:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library", - "//vendor/k8s.io/client-go/examples/third-party-resources-deprecated/apis/tpr/v1:go_default_library", - "//vendor/k8s.io/client-go/examples/third-party-resources-deprecated/client:go_default_library", - "//vendor/k8s.io/client-go/examples/third-party-resources-deprecated/controller: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/test/integration/thirdparty/client-go_test.go b/test/integration/thirdparty/client-go_test.go deleted file mode 100644 index 7dc616f9c7b..00000000000 --- a/test/integration/thirdparty/client-go_test.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 thirdparty - -import ( - "context" - "testing" - - apiv1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/runtime/serializer" - "k8s.io/client-go/kubernetes" - "k8s.io/client-go/rest" - "k8s.io/kubernetes/test/integration/framework" - - exampletprv1 "k8s.io/client-go/examples/third-party-resources-deprecated/apis/tpr/v1" - exampleclient "k8s.io/client-go/examples/third-party-resources-deprecated/client" - examplecontroller "k8s.io/client-go/examples/third-party-resources-deprecated/controller" -) - -func TestClientGoThirdPartyResourceExample(t *testing.T) { - _, s, closeFn := framework.RunAMaster(framework.NewIntegrationTestMasterConfig()) - defer closeFn() - - scheme := runtime.NewScheme() - if err := exampletprv1.AddToScheme(scheme); err != nil { - t.Fatalf("unexpected error: %v", err) - } - - config := &rest.Config{Host: s.URL, ContentConfig: rest.ContentConfig{ - NegotiatedSerializer: serializer.DirectCodecFactory{CodecFactory: serializer.NewCodecFactory(scheme)}, - }} - clientset, err := kubernetes.NewForConfig(config) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - - t.Logf("Creating TPR %q", exampletprv1.ExampleResourcePlural) - if err := exampleclient.CreateTPR(clientset); err != nil { - t.Fatalf("unexpected error creating the ThirdPartyResource: %v", err) - } - - exampleClient, exampleScheme, err := exampleclient.NewClient(config) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - - t.Logf("Waiting for TPR %q to show up", exampletprv1.ExampleResourcePlural) - if err := exampleclient.WaitForExampleResource(exampleClient); err != nil { - t.Fatalf("TPR examples did not show up: %v", err) - } - t.Logf("TPR %q is active", exampletprv1.ExampleResourcePlural) - - t.Logf("Starting a controller on instances of TPR %q", exampletprv1.ExampleResourcePlural) - controller := examplecontroller.ExampleController{ - ExampleClient: exampleClient, - ExampleScheme: exampleScheme, - } - - ctx, cancelFunc := context.WithCancel(context.Background()) - defer cancelFunc() - go controller.Run(ctx) - - // Create an instance of our TPR - t.Logf("Creating instance of TPR %q", exampletprv1.ExampleResourcePlural) - example := &exampletprv1.Example{ - ObjectMeta: metav1.ObjectMeta{ - Name: "example1", - }, - Spec: exampletprv1.ExampleSpec{ - Foo: "hello", - Bar: true, - }, - Status: exampletprv1.ExampleStatus{ - State: exampletprv1.ExampleStateCreated, - Message: "Created, not processed yet", - }, - } - var result exampletprv1.Example - err = exampleClient.Post(). - Resource(exampletprv1.ExampleResourcePlural). - Namespace(apiv1.NamespaceDefault). - Body(example). - Do().Into(&result) - if err != nil { - t.Fatalf("Failed to create an instance of TPR: %v", err) - } - - t.Logf("Waiting for TPR %q instance to be processed", exampletprv1.ExampleResourcePlural) - if err := exampleclient.WaitForExampleInstanceProcessed(exampleClient, "example1"); err != nil { - t.Fatalf("TPR example was not processed correctly: %v", err) - } - t.Logf("TPR %q instance is processed", exampletprv1.ExampleResourcePlural) -} diff --git a/test/integration/thirdparty/thirdparty_test.go b/test/integration/thirdparty/thirdparty_test.go deleted file mode 100644 index f6dcb6c5911..00000000000 --- a/test/integration/thirdparty/thirdparty_test.go +++ /dev/null @@ -1,284 +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 thirdparty - -// This file contains tests for the storage classes API resource. - -import ( - "encoding/json" - "reflect" - "sort" - "sync" - "testing" - "time" - - extensions "k8s.io/api/extensions/v1beta1" - 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/diff" - "k8s.io/apimachinery/pkg/util/wait" - restclient "k8s.io/client-go/rest" - "k8s.io/kubernetes/pkg/api" - "k8s.io/kubernetes/pkg/client/clientset_generated/clientset" - "k8s.io/kubernetes/test/integration/framework" -) - -func TestThirdPartyDiscovery(t *testing.T) { - group := "company.com" - version := "v1" - - _, s, closeFn := framework.RunAMaster(framework.NewIntegrationTestMasterConfig()) - defer closeFn() - clientConfig := &restclient.Config{Host: s.URL, ContentConfig: restclient.ContentConfig{NegotiatedSerializer: api.Codecs}} - client := clientset.NewForConfigOrDie(clientConfig) - - // install thirdparty resource - once := sync.Once{} - deleteFoo := installThirdParty(t, client, clientConfig, - &extensions.ThirdPartyResource{ - ObjectMeta: metav1.ObjectMeta{Name: "foo.company.com"}, - Versions: []extensions.APIVersion{{Name: version}}, - }, group, version, "foos", - ) - defer once.Do(deleteFoo) - - // check whether it shows up in discovery properly - resources, err := client.Discovery().ServerResourcesForGroupVersion("company.com/" + version) - if err != nil { - t.Fatal(err) - } - if len(resources.APIResources) != 1 { - t.Fatalf("Expected exactly the resource \"foos\" in group version %v/%v via discovery, got: %v", group, version, resources.APIResources) - } - r := resources.APIResources[0] - if r.Name != "foos" { - t.Fatalf("Expected exactly the resource \"foos\" in group version %v/%v via discovery, got: %v", group, version, r) - } - sort.Strings(r.Verbs) - expectedVerbs := []string{"create", "delete", "deletecollection", "get", "list", "patch", "update", "watch"} - if !reflect.DeepEqual([]string(r.Verbs), expectedVerbs) { - t.Fatalf("Unexpected verbs for resource \"foos\" in group version %v/%v via discovery: expected=%v got=%v", group, version, expectedVerbs, r.Verbs) - } - - // delete - once.Do(deleteFoo) - - // check whether resource is also gone from discovery - resources, err = client.Discovery().ServerResourcesForGroupVersion(group + "/" + version) - if err == nil { - for _, r := range resources.APIResources { - if r.Name == "foos" { - t.Fatalf("unexpected resource \"foos\" in group version %v/%v after deletion", group, version) - } - } - } -} - -// TODO these tests will eventually be runnable in a single test -func TestThirdPartyDelete(t *testing.T) { - _, s, closeFn := framework.RunAMaster(framework.NewIntegrationTestMasterConfig()) - defer closeFn() - - clientConfig := &restclient.Config{Host: s.URL, ContentConfig: restclient.ContentConfig{NegotiatedSerializer: api.Codecs}} - client := clientset.NewForConfigOrDie(clientConfig) - - DoTestInstallThirdPartyAPIDelete(t, client, clientConfig) -} - -func TestThirdPartyMultiple(t *testing.T) { - _, s, closeFn := framework.RunAMaster(framework.NewIntegrationTestMasterConfig()) - defer closeFn() - - clientConfig := &restclient.Config{Host: s.URL, ContentConfig: restclient.ContentConfig{NegotiatedSerializer: api.Codecs}} - client := clientset.NewForConfigOrDie(clientConfig) - - DoTestInstallMultipleAPIs(t, client, clientConfig) -} - -// TODO make multiple versions work. they've been broken -var versionsToTest = []string{"v1"} - -type Foo struct { - metav1.TypeMeta `json:",inline"` - metav1.ObjectMeta `json:"metadata,omitempty" description:"standard object metadata"` - - SomeField string `json:"someField"` - OtherField int `json:"otherField"` -} - -type FooList struct { - metav1.TypeMeta `json:",inline"` - metav1.ListMeta `json:"metadata,omitempty" description:"standard list metadata; see https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata"` - - Items []Foo `json:"items"` -} - -// installThirdParty installs a third party resource and returns a defer func -func installThirdParty(t *testing.T, client clientset.Interface, clientConfig *restclient.Config, tpr *extensions.ThirdPartyResource, group, version, resource string) func() { - var err error - _, err = client.Extensions().ThirdPartyResources().Create(tpr) - if err != nil { - t.Fatal(err) - } - - fooClientConfig := *clientConfig - fooClientConfig.APIPath = "apis" - fooClientConfig.GroupVersion = &schema.GroupVersion{Group: group, Version: version} - fooClient, err := restclient.RESTClientFor(&fooClientConfig) - if err != nil { - t.Fatal(err) - } - - err = wait.Poll(100*time.Millisecond, 60*time.Second, func() (bool, error) { - _, err := fooClient.Get().Namespace("default").Resource(resource).DoRaw() - if err == nil { - return true, nil - } - if apierrors.IsNotFound(err) { - return false, nil - } - - return false, err - }) - if err != nil { - t.Fatal(err) - } - - return func() { - client.Extensions().ThirdPartyResources().Delete(tpr.Name, nil) - err = wait.Poll(100*time.Millisecond, 60*time.Second, func() (bool, error) { - _, err := fooClient.Get().Namespace("default").Resource(resource).DoRaw() - if apierrors.IsNotFound(err) { - return true, nil - } - - return false, err - }) - if err != nil { - t.Fatal(err) - } - } -} - -func DoTestInstallMultipleAPIs(t *testing.T, client clientset.Interface, clientConfig *restclient.Config) { - group := "company.com" - version := "v1" - - deleteFoo := installThirdParty(t, client, clientConfig, - &extensions.ThirdPartyResource{ - ObjectMeta: metav1.ObjectMeta{Name: "foo.company.com"}, - Versions: []extensions.APIVersion{{Name: version}}, - }, group, version, "foos", - ) - defer deleteFoo() - - // TODO make multiple resources in one version work - // deleteBar = installThirdParty(t, client, clientConfig, - // &extensions.ThirdPartyResource{ - // ObjectMeta: metav1.ObjectMeta{Name: "bar.company.com"}, - // Versions: []extensions.APIVersion{{Name: version}}, - // }, group, version, "bars", - // ) - // defer deleteBar() -} - -func DoTestInstallThirdPartyAPIDelete(t *testing.T, client clientset.Interface, clientConfig *restclient.Config) { - for _, version := range versionsToTest { - testInstallThirdPartyAPIDeleteVersion(t, client, clientConfig, version) - } -} - -func testInstallThirdPartyAPIDeleteVersion(t *testing.T, client clientset.Interface, clientConfig *restclient.Config, version string) { - group := "company.com" - - deleteFoo := installThirdParty(t, client, clientConfig, - &extensions.ThirdPartyResource{ - ObjectMeta: metav1.ObjectMeta{Name: "foo.company.com"}, - Versions: []extensions.APIVersion{{Name: version}}, - }, group, version, "foos", - ) - defer deleteFoo() - - fooClientConfig := *clientConfig - fooClientConfig.APIPath = "apis" - fooClientConfig.GroupVersion = &schema.GroupVersion{Group: group, Version: version} - fooClient, err := restclient.RESTClientFor(&fooClientConfig) - if err != nil { - t.Fatal(err) - } - - expectedObj := Foo{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test", - Namespace: "default", - }, - TypeMeta: metav1.TypeMeta{ - Kind: "Foo", - }, - SomeField: "test field", - OtherField: 10, - } - objBytes, err := json.Marshal(&expectedObj) - if err != nil { - t.Fatal(err) - } - - if _, err := fooClient.Post().Namespace("default").Resource("foos").Body(objBytes).DoRaw(); err != nil { - t.Fatal(err) - } - - apiBytes, err := fooClient.Get().Namespace("default").Resource("foos").Name("test").DoRaw() - if err != nil { - t.Fatal(err) - } - item := Foo{} - err = json.Unmarshal(apiBytes, &item) - if err != nil { - t.Fatal(err) - } - - // Fill in fields set by the apiserver - item.SelfLink = expectedObj.SelfLink - item.ResourceVersion = expectedObj.ResourceVersion - item.Namespace = expectedObj.Namespace - item.UID = expectedObj.UID - item.CreationTimestamp = expectedObj.CreationTimestamp - if !reflect.DeepEqual(item, expectedObj) { - t.Fatalf("expected:\n%v\n", diff.ObjectGoPrintSideBySide(expectedObj, item)) - } - - listBytes, err := fooClient.Get().Namespace("default").Resource("foos").DoRaw() - if err != nil { - t.Fatal(err) - } - list := FooList{} - err = json.Unmarshal(listBytes, &list) - if err != nil { - t.Fatal(err) - } - if len(list.Items) != 1 { - t.Fatalf("wrong item: %v", list) - } - - if _, err := fooClient.Delete().Namespace("default").Resource("foos").Name("test").DoRaw(); err != nil { - t.Fatal(err) - } - if _, err := fooClient.Get().Namespace("default").Resource("foos").Name("test").DoRaw(); !apierrors.IsNotFound(err) { - t.Fatal(err) - } -} From 312fb1e1fa198f4715598feac659f5eeffd05032 Mon Sep 17 00:00:00 2001 From: deads2k Date: Fri, 30 Jun 2017 14:13:29 -0400 Subject: [PATCH 187/448] allow a deletestrategy to opt-out of GC --- pkg/registry/core/event/BUILD | 1 + pkg/registry/core/event/strategy.go | 5 + .../pkg/registry/generic/registry/BUILD | 1 + .../pkg/registry/generic/registry/store.go | 137 +++++++++--------- .../apiserver/pkg/registry/rest/delete.go | 3 + 5 files changed, 79 insertions(+), 68 deletions(-) diff --git a/pkg/registry/core/event/BUILD b/pkg/registry/core/event/BUILD index 91c0da283d7..4a9fd1b4daa 100644 --- a/pkg/registry/core/event/BUILD +++ b/pkg/registry/core/event/BUILD @@ -24,6 +24,7 @@ go_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", "//vendor/k8s.io/apiserver/pkg/storage/names:go_default_library", ], diff --git a/pkg/registry/core/event/strategy.go b/pkg/registry/core/event/strategy.go index 77ea252b482..e70518af04b 100644 --- a/pkg/registry/core/event/strategy.go +++ b/pkg/registry/core/event/strategy.go @@ -25,6 +25,7 @@ import ( "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" "k8s.io/apiserver/pkg/storage/names" "k8s.io/kubernetes/pkg/api" @@ -40,6 +41,10 @@ type eventStrategy struct { // Event objects via the REST API. var Strategy = eventStrategy{api.Scheme, names.SimpleNameGenerator} +func (eventStrategy) DefaultGarbageCollectionPolicy() rest.GarbageCollectionPolicy { + return rest.Unsupported +} + func (eventStrategy) NamespaceScoped() bool { return true } diff --git a/staging/src/k8s.io/apiserver/pkg/registry/generic/registry/BUILD b/staging/src/k8s.io/apiserver/pkg/registry/generic/registry/BUILD index 15a507c6638..75242efe182 100644 --- a/staging/src/k8s.io/apiserver/pkg/registry/generic/registry/BUILD +++ b/staging/src/k8s.io/apiserver/pkg/registry/generic/registry/BUILD @@ -68,6 +68,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/util/runtime: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/watch:go_default_library", "//vendor/k8s.io/apiserver/pkg/endpoints/request:go_default_library", diff --git a/staging/src/k8s.io/apiserver/pkg/registry/generic/registry/store.go b/staging/src/k8s.io/apiserver/pkg/registry/generic/registry/store.go index 2dcea903a0a..ad8c552a713 100644 --- a/staging/src/k8s.io/apiserver/pkg/registry/generic/registry/store.go +++ b/staging/src/k8s.io/apiserver/pkg/registry/generic/registry/store.go @@ -34,6 +34,7 @@ import ( "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" utilruntime "k8s.io/apimachinery/pkg/util/runtime" + "k8s.io/apimachinery/pkg/util/sets" "k8s.io/apimachinery/pkg/util/validation/field" "k8s.io/apimachinery/pkg/watch" genericapirequest "k8s.io/apiserver/pkg/endpoints/request" @@ -628,120 +629,120 @@ var ( errEmptiedFinalizers = fmt.Errorf("emptied finalizers") ) -// shouldUpdateFinalizerOrphanDependents returns if the finalizers need to be +// shouldOrphanDependents returns true if the finalizer for orphaning should be set // updated for FinalizerOrphanDependents. In the order of highest to lowest // priority, there are three factors affect whether to add/remove the // FinalizerOrphanDependents: options, existing finalizers of the object, // and e.DeleteStrategy.DefaultGarbageCollectionPolicy. -func shouldUpdateFinalizerOrphanDependents(e *Store, accessor metav1.Object, options *metav1.DeleteOptions) (shouldUpdate bool, shouldOrphan bool) { - shouldOrphan = false - // Get default orphan policy from this REST object type +func shouldOrphanDependents(e *Store, accessor metav1.Object, options *metav1.DeleteOptions) bool { if gcStrategy, ok := e.DeleteStrategy.(rest.GarbageCollectionDeleteStrategy); ok { - if gcStrategy.DefaultGarbageCollectionPolicy() == rest.OrphanDependents { - shouldOrphan = true + if gcStrategy.DefaultGarbageCollectionPolicy() == rest.Unsupported { + // return false to indicate that we should NOT orphan + return false } } - // If a finalizer is set in the object, it overrides the default - hasOrphanFinalizer := false - finalizers := accessor.GetFinalizers() - for _, f := range finalizers { - // validation should make sure the two cases won't be true at the same - // time. - switch f { - case metav1.FinalizerOrphanDependents: - shouldOrphan = true - hasOrphanFinalizer = true - break - case metav1.FinalizerDeleteDependents: - shouldOrphan = false - break - } - } - - // If an explicit policy was set at deletion time, that overrides both + // An explicit policy was set at deletion time, that overrides everything if options != nil && options.OrphanDependents != nil { - shouldOrphan = *options.OrphanDependents + return *options.OrphanDependents } if options != nil && options.PropagationPolicy != nil { switch *options.PropagationPolicy { case metav1.DeletePropagationOrphan: - shouldOrphan = true + return true case metav1.DeletePropagationBackground, metav1.DeletePropagationForeground: - shouldOrphan = false + return false } } - shouldUpdate = shouldOrphan != hasOrphanFinalizer - return shouldUpdate, shouldOrphan + // If a finalizer is set in the object, it overrides the default + // validation should make sure the two cases won't be true at the same time. + finalizers := accessor.GetFinalizers() + for _, f := range finalizers { + switch f { + case metav1.FinalizerOrphanDependents: + return true + case metav1.FinalizerDeleteDependents: + return false + } + } + + // Get default orphan policy from this REST object type if it exists + if gcStrategy, ok := e.DeleteStrategy.(rest.GarbageCollectionDeleteStrategy); ok { + if gcStrategy.DefaultGarbageCollectionPolicy() == rest.OrphanDependents { + return true + } + } + return false } -// shouldUpdateFinalizerDeleteDependents returns if the finalizers need to be +// shouldDeleteDependents returns true if the finalizer for foreground deletion should be set // updated for FinalizerDeleteDependents. In the order of highest to lowest // priority, there are three factors affect whether to add/remove the // FinalizerDeleteDependents: options, existing finalizers of the object, and // e.DeleteStrategy.DefaultGarbageCollectionPolicy. -func shouldUpdateFinalizerDeleteDependents(e *Store, accessor metav1.Object, options *metav1.DeleteOptions) (shouldUpdate bool, shouldDeleteDependentInForeground bool) { - // default to false - shouldDeleteDependentInForeground = false - - // If a finalizer is set in the object, it overrides the default - hasFinalizerDeleteDependents := false - finalizers := accessor.GetFinalizers() - for _, f := range finalizers { - // validation has made sure the two cases won't be true at the same - // time. - switch f { - case metav1.FinalizerDeleteDependents: - shouldDeleteDependentInForeground = true - hasFinalizerDeleteDependents = true - break - case metav1.FinalizerOrphanDependents: - shouldDeleteDependentInForeground = false - break - } +func shouldDeleteDependents(e *Store, accessor metav1.Object, options *metav1.DeleteOptions) bool { + // Get default orphan policy from this REST object type + if gcStrategy, ok := e.DeleteStrategy.(rest.GarbageCollectionDeleteStrategy); ok && gcStrategy.DefaultGarbageCollectionPolicy() == rest.Unsupported { + // return false to indicate that we should NOT delete in foreground + return false } // If an explicit policy was set at deletion time, that overrides both if options != nil && options.OrphanDependents != nil { - shouldDeleteDependentInForeground = false + return false } if options != nil && options.PropagationPolicy != nil { switch *options.PropagationPolicy { case metav1.DeletePropagationForeground: - shouldDeleteDependentInForeground = true + return true case metav1.DeletePropagationBackground, metav1.DeletePropagationOrphan: - shouldDeleteDependentInForeground = false + return false } } - shouldUpdate = shouldDeleteDependentInForeground != hasFinalizerDeleteDependents - return shouldUpdate, shouldDeleteDependentInForeground -} - -// shouldUpdateFinalizers returns if we need to update the finalizers of the -// object, and the desired list of finalizers. -func shouldUpdateFinalizers(e *Store, accessor metav1.Object, options *metav1.DeleteOptions) (shouldUpdate bool, newFinalizers []string) { - shouldUpdate1, shouldOrphan := shouldUpdateFinalizerOrphanDependents(e, accessor, options) - shouldUpdate2, shouldDeleteDependentInForeground := shouldUpdateFinalizerDeleteDependents(e, accessor, options) - oldFinalizers := accessor.GetFinalizers() - if !shouldUpdate1 && !shouldUpdate2 { - return false, oldFinalizers + // If a finalizer is set in the object, it overrides the default + // validation has made sure the two cases won't be true at the same time. + finalizers := accessor.GetFinalizers() + for _, f := range finalizers { + switch f { + case metav1.FinalizerDeleteDependents: + return true + case metav1.FinalizerOrphanDependents: + return false + } } + return false +} + +// deletionFinalizers returns the deletion finalizers we should set on the object and a bool indicate they did or +// did not change. +func deletionFinalizers(e *Store, accessor metav1.Object, options *metav1.DeleteOptions) (bool, []string) { + shouldOrphan := shouldOrphanDependents(e, accessor, options) + shouldDeleteDependentInForeground := shouldDeleteDependents(e, accessor, options) + newFinalizers := []string{} + // first remove both finalizers, add them back if needed. - for _, f := range oldFinalizers { + for _, f := range accessor.GetFinalizers() { if f == metav1.FinalizerOrphanDependents || f == metav1.FinalizerDeleteDependents { continue } newFinalizers = append(newFinalizers, f) } + if shouldOrphan { newFinalizers = append(newFinalizers, metav1.FinalizerOrphanDependents) } if shouldDeleteDependentInForeground { newFinalizers = append(newFinalizers, metav1.FinalizerDeleteDependents) } + + oldFinalizerSet := sets.NewString(accessor.GetFinalizers()...) + newFinalizersSet := sets.NewString(newFinalizers...) + if oldFinalizerSet.Equal(newFinalizersSet) { + return false, accessor.GetFinalizers() + } return true, newFinalizers } @@ -871,8 +872,8 @@ func (e *Store) updateForGracefulDeletionAndFinalizers(ctx genericapirequest.Con if err != nil { return nil, err } - shouldUpdate, newFinalizers := shouldUpdateFinalizers(e, existingAccessor, options) - if shouldUpdate { + needsUpdate, newFinalizers := deletionFinalizers(e, existingAccessor, options) + if needsUpdate { existingAccessor.SetFinalizers(newFinalizers) } @@ -964,7 +965,7 @@ func (e *Store) Delete(ctx genericapirequest.Context, name string, options *meta // Handle combinations of graceful deletion and finalization by issuing // the correct updates. if e.EnableGarbageCollection { - shouldUpdateFinalizers, _ := shouldUpdateFinalizers(e, accessor, options) + shouldUpdateFinalizers, _ := deletionFinalizers(e, accessor, options) // TODO: remove the check, because we support no-op updates now. if graceful || pendingFinalizers || shouldUpdateFinalizers { err, ignoreNotFound, deleteImmediately, out, lastExisting = e.updateForGracefulDeletionAndFinalizers(ctx, name, key, options, preconditions, obj) diff --git a/staging/src/k8s.io/apiserver/pkg/registry/rest/delete.go b/staging/src/k8s.io/apiserver/pkg/registry/rest/delete.go index ad407e3ec8b..80e08fb192a 100644 --- a/staging/src/k8s.io/apiserver/pkg/registry/rest/delete.go +++ b/staging/src/k8s.io/apiserver/pkg/registry/rest/delete.go @@ -39,6 +39,9 @@ type GarbageCollectionPolicy string const ( DeleteDependents GarbageCollectionPolicy = "DeleteDependents" OrphanDependents GarbageCollectionPolicy = "OrphanDependents" + // Unsupported means that the resource knows that it cannot be GC'd, so the finalizers + // should never be set in storage. + Unsupported GarbageCollectionPolicy = "Unsupported" ) // GarbageCollectionDeleteStrategy must be implemented by the registry that wants to From 9b43bd4a5b234d528ebc0fd059ae69eedced8c7f Mon Sep 17 00:00:00 2001 From: deads2k Date: Mon, 3 Jul 2017 14:34:03 -0400 Subject: [PATCH 188/448] make the panic handler first --- staging/src/k8s.io/apiserver/pkg/server/config.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/staging/src/k8s.io/apiserver/pkg/server/config.go b/staging/src/k8s.io/apiserver/pkg/server/config.go index a95edc01908..9b4b7b69894 100644 --- a/staging/src/k8s.io/apiserver/pkg/server/config.go +++ b/staging/src/k8s.io/apiserver/pkg/server/config.go @@ -476,11 +476,11 @@ func DefaultBuildHandlerChain(apiHandler http.Handler, c *Config) http.Handler { } handler = genericapifilters.WithAuthentication(handler, c.RequestContextMapper, c.Authenticator, genericapifilters.Unauthorized(c.SupportsBasicAuth)) handler = genericfilters.WithCORS(handler, c.CorsAllowedOriginList, nil, nil, nil, "true") - handler = genericfilters.WithPanicRecovery(handler) handler = genericfilters.WithTimeoutForNonLongRunningRequests(handler, c.RequestContextMapper, c.LongRunningFunc) handler = genericfilters.WithMaxInFlightLimit(handler, c.MaxRequestsInFlight, c.MaxMutatingRequestsInFlight, c.RequestContextMapper, c.LongRunningFunc) handler = genericapifilters.WithRequestInfo(handler, NewRequestInfoResolver(c), c.RequestContextMapper) handler = apirequest.WithRequestContext(handler, c.RequestContextMapper) + handler = genericfilters.WithPanicRecovery(handler) return handler } From f0e08818d8f3f98fd0b791e9127ae59cb7e36d35 Mon Sep 17 00:00:00 2001 From: George Kraft Date: Mon, 3 Jul 2017 13:29:31 -0500 Subject: [PATCH 189/448] Fix charms leaving services running after unit removal --- .../kubernetes-master/reactive/kubernetes_master.py | 11 +++++++++++ .../kubernetes-worker/reactive/kubernetes_worker.py | 9 +++------ 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/cluster/juju/layers/kubernetes-master/reactive/kubernetes_master.py b/cluster/juju/layers/kubernetes-master/reactive/kubernetes_master.py index ea78246e0a6..cb47d85d7f4 100644 --- a/cluster/juju/layers/kubernetes-master/reactive/kubernetes_master.py +++ b/cluster/juju/layers/kubernetes-master/reactive/kubernetes_master.py @@ -45,6 +45,7 @@ from charms.kubernetes.flagmanager import FlagManager from charmhelpers.core import hookenv from charmhelpers.core import host from charmhelpers.core import unitdata +from charmhelpers.core.host import service_stop from charmhelpers.core.templating import render from charmhelpers.fetch import apt_install from charmhelpers.contrib.charmsupport import nrpe @@ -694,6 +695,16 @@ def disable_gpu_mode(): remove_state('kubernetes-master.gpu.enabled') +@hook('stop') +def shutdown(): + """ Stop the kubernetes master services + + """ + service_stop('snap.kube-apiserver.daemon') + service_stop('snap.kube-controller-manager.daemon') + service_stop('snap.kube-scheduler.daemon') + + def arch(): '''Return the package architecture as a string. Raise an exception if the architecture is not supported by kubernetes.''' diff --git a/cluster/juju/layers/kubernetes-worker/reactive/kubernetes_worker.py b/cluster/juju/layers/kubernetes-worker/reactive/kubernetes_worker.py index a4f02046164..6aa919dea38 100644 --- a/cluster/juju/layers/kubernetes-worker/reactive/kubernetes_worker.py +++ b/cluster/juju/layers/kubernetes-worker/reactive/kubernetes_worker.py @@ -157,15 +157,12 @@ def install_snaps(): def shutdown(): ''' When this unit is destroyed: - delete the current node - - stop the kubelet service - - stop the kube-proxy service - - remove the 'kubernetes-worker.cni-plugins.installed' state + - stop the worker services ''' if os.path.isfile(kubeconfig_path): kubectl('delete', 'node', gethostname()) - service_stop('kubelet') - service_stop('kube-proxy') - remove_state('kubernetes-worker.cni-plugins.installed') + service_stop('snap.kubelet.daemon') + service_stop('snap.kube-proxy.daemon') @when('docker.available') From 05fbc7a7f8da41e8ba56a27d13548cc06c574643 Mon Sep 17 00:00:00 2001 From: Rye Terrell Date: Mon, 3 Jul 2017 21:58:54 -0500 Subject: [PATCH 190/448] configure kube-proxy to run with unset conntrack param when in lxc --- cluster/juju/layers/kubernetes-worker/layer.yaml | 1 + .../layers/kubernetes-worker/reactive/kubernetes_worker.py | 3 +++ 2 files changed, 4 insertions(+) diff --git a/cluster/juju/layers/kubernetes-worker/layer.yaml b/cluster/juju/layers/kubernetes-worker/layer.yaml index 73678fa8b87..5cfc04020de 100644 --- a/cluster/juju/layers/kubernetes-worker/layer.yaml +++ b/cluster/juju/layers/kubernetes-worker/layer.yaml @@ -22,6 +22,7 @@ options: - 'ceph-common' - 'nfs-common' - 'socat' + - 'virt-what' tls-client: ca_certificate_path: '/root/cdk/ca.crt' server_certificate_path: '/root/cdk/server.crt' diff --git a/cluster/juju/layers/kubernetes-worker/reactive/kubernetes_worker.py b/cluster/juju/layers/kubernetes-worker/reactive/kubernetes_worker.py index 4dba0c0ff6e..df315dcce16 100644 --- a/cluster/juju/layers/kubernetes-worker/reactive/kubernetes_worker.py +++ b/cluster/juju/layers/kubernetes-worker/reactive/kubernetes_worker.py @@ -485,6 +485,9 @@ def configure_worker_services(api_servers, dns, cluster_cidr): kube_proxy_opts.add('v', '0') kube_proxy_opts.add('master', random.choice(api_servers), strict=True) + if b'lxc' in check_output('virt-what', shell=True): + kube_proxy_opts.add('conntrack-max-per-core', '0') + cmd = ['snap', 'set', 'kubelet'] + kubelet_opts.to_s().split(' ') check_call(cmd) cmd = ['snap', 'set', 'kube-proxy'] + kube_proxy_opts.to_s().split(' ') From 016f1cfd8f287186cc56874384d922fe9e849b8e Mon Sep 17 00:00:00 2001 From: xiangpengzhao Date: Mon, 3 Jul 2017 11:48:56 +0800 Subject: [PATCH 191/448] Remove unused sub-pkgs in pkg/util --- hack/.linted_packages | 14 +------------- hack/verify-generated-protobuf.sh | 2 +- pkg/util/BUILD | 11 ----------- pkg/util/errors/BUILD | 27 --------------------------- pkg/util/errors/doc.go | 21 --------------------- pkg/util/framer/BUILD | 27 --------------------------- pkg/util/framer/doc.go | 21 --------------------- pkg/util/intstr/BUILD | 27 --------------------------- pkg/util/intstr/doc.go | 21 --------------------- pkg/util/json/BUILD | 27 --------------------------- pkg/util/json/doc.go | 21 --------------------- pkg/util/net/BUILD | 11 ----------- pkg/util/net/doc.go | 21 --------------------- pkg/util/rand/BUILD | 27 --------------------------- pkg/util/rand/doc.go | 21 --------------------- pkg/util/runtime/BUILD | 27 --------------------------- pkg/util/runtime/doc.go | 21 --------------------- pkg/util/sets/BUILD | 30 ------------------------------ pkg/util/sets/doc.go | 21 --------------------- pkg/util/sets/types/BUILD | 27 --------------------------- pkg/util/sets/types/doc.go | 21 --------------------- pkg/util/uuid/BUILD | 27 --------------------------- pkg/util/uuid/doc.go | 19 ------------------- pkg/util/validation/BUILD | 30 ------------------------------ pkg/util/validation/doc.go | 21 --------------------- pkg/util/validation/field/BUILD | 27 --------------------------- pkg/util/validation/field/doc.go | 21 --------------------- pkg/util/wait/BUILD | 27 --------------------------- pkg/util/wait/doc.go | 21 --------------------- pkg/util/yaml/BUILD | 27 --------------------------- pkg/util/yaml/doc.go | 21 --------------------- 31 files changed, 2 insertions(+), 685 deletions(-) delete mode 100644 pkg/util/errors/BUILD delete mode 100644 pkg/util/errors/doc.go delete mode 100644 pkg/util/framer/BUILD delete mode 100644 pkg/util/framer/doc.go delete mode 100644 pkg/util/intstr/BUILD delete mode 100644 pkg/util/intstr/doc.go delete mode 100644 pkg/util/json/BUILD delete mode 100644 pkg/util/json/doc.go delete mode 100644 pkg/util/net/doc.go delete mode 100644 pkg/util/rand/BUILD delete mode 100644 pkg/util/rand/doc.go delete mode 100644 pkg/util/runtime/BUILD delete mode 100644 pkg/util/runtime/doc.go delete mode 100644 pkg/util/sets/BUILD delete mode 100644 pkg/util/sets/doc.go delete mode 100644 pkg/util/sets/types/BUILD delete mode 100644 pkg/util/sets/types/doc.go delete mode 100644 pkg/util/uuid/BUILD delete mode 100644 pkg/util/uuid/doc.go delete mode 100644 pkg/util/validation/BUILD delete mode 100644 pkg/util/validation/doc.go delete mode 100644 pkg/util/validation/field/BUILD delete mode 100644 pkg/util/validation/field/doc.go delete mode 100644 pkg/util/wait/BUILD delete mode 100644 pkg/util/wait/doc.go delete mode 100644 pkg/util/yaml/BUILD delete mode 100644 pkg/util/yaml/doc.go diff --git a/hack/.linted_packages b/hack/.linted_packages index 9bb55acef13..e9879688cca 100644 --- a/hack/.linted_packages +++ b/hack/.linted_packages @@ -258,33 +258,21 @@ pkg/security/podsecuritypolicy/sysctl pkg/serviceaccount pkg/types pkg/util/async -pkg/util/errors pkg/util/flock -pkg/util/framer pkg/util/goroutinemap pkg/util/hash pkg/util/i18n pkg/util/interrupt -pkg/util/intstr pkg/util/io -pkg/util/json pkg/util/limitwriter pkg/util/logs pkg/util/maps pkg/util/metrics -pkg/util/net +pkg/util/net/sets pkg/util/netsh -pkg/util/rand -pkg/util/runtime -pkg/util/sets -pkg/util/sets/types pkg/util/slice pkg/util/tail -pkg/util/validation -pkg/util/validation/field pkg/util/version -pkg/util/wait -pkg/util/yaml pkg/version/prometheus pkg/volume pkg/volume/downwardapi diff --git a/hack/verify-generated-protobuf.sh b/hack/verify-generated-protobuf.sh index de0b4dbbb96..c05ecf4e595 100755 --- a/hack/verify-generated-protobuf.sh +++ b/hack/verify-generated-protobuf.sh @@ -23,7 +23,7 @@ source "${KUBE_ROOT}/hack/lib/init.sh" kube::golang::setup_env -APIROOTS=${APIROOTS:-pkg/api pkg/apis pkg/runtime pkg/util/intstr pkg/watch staging/src/k8s.io/apimachinery/pkg/api staging/src/k8s.io/apimachinery/pkg/apis staging/src/k8s.io/apiserver/pkg staging/src/k8s.io/api staging/src/k8s.io/metrics/pkg/apis} +APIROOTS=${APIROOTS:-pkg/api pkg/apis pkg/runtime pkg/watch staging/src/k8s.io/apimachinery/pkg/api staging/src/k8s.io/apimachinery/pkg/apis staging/src/k8s.io/apiserver/pkg staging/src/k8s.io/api staging/src/k8s.io/metrics/pkg/apis} _tmp="${KUBE_ROOT}/_tmp" cleanup() { diff --git a/pkg/util/BUILD b/pkg/util/BUILD index c7048bed481..18d0fedf534 100644 --- a/pkg/util/BUILD +++ b/pkg/util/BUILD @@ -50,20 +50,16 @@ filegroup( "//pkg/util/dbus:all-srcs", "//pkg/util/ebtables:all-srcs", "//pkg/util/env:all-srcs", - "//pkg/util/errors:all-srcs", "//pkg/util/exec:all-srcs", "//pkg/util/flock:all-srcs", - "//pkg/util/framer:all-srcs", "//pkg/util/goroutinemap:all-srcs", "//pkg/util/hash:all-srcs", "//pkg/util/i18n:all-srcs", "//pkg/util/initsystem:all-srcs", "//pkg/util/interrupt:all-srcs", - "//pkg/util/intstr:all-srcs", "//pkg/util/io:all-srcs", "//pkg/util/ipconfig:all-srcs", "//pkg/util/iptables:all-srcs", - "//pkg/util/json:all-srcs", "//pkg/util/keymutex:all-srcs", "//pkg/util/labels:all-srcs", "//pkg/util/limitwriter:all-srcs", @@ -77,13 +73,10 @@ filegroup( "//pkg/util/oom:all-srcs", "//pkg/util/parsers:all-srcs", "//pkg/util/procfs:all-srcs", - "//pkg/util/rand:all-srcs", "//pkg/util/removeall:all-srcs", "//pkg/util/resourcecontainer:all-srcs", "//pkg/util/rlimit:all-srcs", - "//pkg/util/runtime:all-srcs", "//pkg/util/selinux:all-srcs", - "//pkg/util/sets:all-srcs", "//pkg/util/slice:all-srcs", "//pkg/util/strings:all-srcs", "//pkg/util/sysctl:all-srcs", @@ -92,12 +85,8 @@ filegroup( "//pkg/util/taints:all-srcs", "//pkg/util/threading:all-srcs", "//pkg/util/tolerations:all-srcs", - "//pkg/util/uuid:all-srcs", - "//pkg/util/validation:all-srcs", "//pkg/util/version:all-srcs", - "//pkg/util/wait:all-srcs", "//pkg/util/workqueue/prometheus:all-srcs", - "//pkg/util/yaml:all-srcs", ], tags = ["automanaged"], ) diff --git a/pkg/util/errors/BUILD b/pkg/util/errors/BUILD deleted file mode 100644 index deefdcef3c1..00000000000 --- a/pkg/util/errors/BUILD +++ /dev/null @@ -1,27 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -licenses(["notice"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = ["doc.go"], - tags = ["automanaged"], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/pkg/util/errors/doc.go b/pkg/util/errors/doc.go deleted file mode 100644 index 38d261613cd..00000000000 --- a/pkg/util/errors/doc.go +++ /dev/null @@ -1,21 +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 errors only exists until heapster rebases -// TODO genericapiserver remove this empty package. Godep fails without this because heapster relies -// on this package. This will allow us to start splitting packages, but will force -// heapster to update on their next kube rebase. -package errors diff --git a/pkg/util/framer/BUILD b/pkg/util/framer/BUILD deleted file mode 100644 index deefdcef3c1..00000000000 --- a/pkg/util/framer/BUILD +++ /dev/null @@ -1,27 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -licenses(["notice"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = ["doc.go"], - tags = ["automanaged"], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/pkg/util/framer/doc.go b/pkg/util/framer/doc.go deleted file mode 100644 index 168acea0901..00000000000 --- a/pkg/util/framer/doc.go +++ /dev/null @@ -1,21 +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 framer only exists until heapster rebases -// TODO genericapiserver remove this empty package. Godep fails without this because heapster relies -// on this package. This will allow us to start splitting packages, but will force -// heapster to update on their next kube rebase. -package framer diff --git a/pkg/util/intstr/BUILD b/pkg/util/intstr/BUILD deleted file mode 100644 index deefdcef3c1..00000000000 --- a/pkg/util/intstr/BUILD +++ /dev/null @@ -1,27 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -licenses(["notice"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = ["doc.go"], - tags = ["automanaged"], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/pkg/util/intstr/doc.go b/pkg/util/intstr/doc.go deleted file mode 100644 index e5221d4697a..00000000000 --- a/pkg/util/intstr/doc.go +++ /dev/null @@ -1,21 +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 intstr only exists until heapster rebases -// TODO genericapiserver remove this empty package. Godep fails without this because heapster relies -// on this package. This will allow us to start splitting packages, but will force -// heapster to update on their next kube rebase. -package intstr diff --git a/pkg/util/json/BUILD b/pkg/util/json/BUILD deleted file mode 100644 index deefdcef3c1..00000000000 --- a/pkg/util/json/BUILD +++ /dev/null @@ -1,27 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -licenses(["notice"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = ["doc.go"], - tags = ["automanaged"], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/pkg/util/json/doc.go b/pkg/util/json/doc.go deleted file mode 100644 index a7c3c015172..00000000000 --- a/pkg/util/json/doc.go +++ /dev/null @@ -1,21 +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 json only exists until heapster rebases -// TODO genericapiserver remove this empty package. Godep fails without this because heapster relies -// on this package. This will allow us to start splitting packages, but will force -// heapster to update on their next kube rebase. -package json diff --git a/pkg/util/net/BUILD b/pkg/util/net/BUILD index 3ee4e871b0e..0c027b3bd46 100644 --- a/pkg/util/net/BUILD +++ b/pkg/util/net/BUILD @@ -2,17 +2,6 @@ package(default_visibility = ["//visibility:public"]) licenses(["notice"]) -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = ["doc.go"], - tags = ["automanaged"], -) - filegroup( name = "package-srcs", srcs = glob(["**"]), diff --git a/pkg/util/net/doc.go b/pkg/util/net/doc.go deleted file mode 100644 index 61bf9e38aa4..00000000000 --- a/pkg/util/net/doc.go +++ /dev/null @@ -1,21 +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 net only exists until heapster rebases -// TODO genericapiserver remove this empty package. Godep fails without this because heapster relies -// on this package. This will allow us to start splitting packages, but will force -// heapster to update on their next kube rebase. -package net diff --git a/pkg/util/rand/BUILD b/pkg/util/rand/BUILD deleted file mode 100644 index deefdcef3c1..00000000000 --- a/pkg/util/rand/BUILD +++ /dev/null @@ -1,27 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -licenses(["notice"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = ["doc.go"], - tags = ["automanaged"], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/pkg/util/rand/doc.go b/pkg/util/rand/doc.go deleted file mode 100644 index 7ba225434da..00000000000 --- a/pkg/util/rand/doc.go +++ /dev/null @@ -1,21 +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 rand needed for godep. -// TODO genericapiserver remove this empty package. Godep fails without this because heapster relies -// on this package. This will allow us to start splitting packages, but will force -// heapster to update on their next kube rebase. -package rand diff --git a/pkg/util/runtime/BUILD b/pkg/util/runtime/BUILD deleted file mode 100644 index deefdcef3c1..00000000000 --- a/pkg/util/runtime/BUILD +++ /dev/null @@ -1,27 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -licenses(["notice"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = ["doc.go"], - tags = ["automanaged"], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/pkg/util/runtime/doc.go b/pkg/util/runtime/doc.go deleted file mode 100644 index d9aeba6c9c5..00000000000 --- a/pkg/util/runtime/doc.go +++ /dev/null @@ -1,21 +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 runtime only exists until heapster rebases -// TODO genericapiserver remove this empty package. Godep fails without this because heapster relies -// on this package. This will allow us to start splitting packages, but will force -// heapster to update on their next kube rebase. -package runtime diff --git a/pkg/util/sets/BUILD b/pkg/util/sets/BUILD deleted file mode 100644 index 9d385a0f239..00000000000 --- a/pkg/util/sets/BUILD +++ /dev/null @@ -1,30 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -licenses(["notice"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = ["doc.go"], - tags = ["automanaged"], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [ - ":package-srcs", - "//pkg/util/sets/types:all-srcs", - ], - tags = ["automanaged"], -) diff --git a/pkg/util/sets/doc.go b/pkg/util/sets/doc.go deleted file mode 100644 index 5fe6f4f9eb1..00000000000 --- a/pkg/util/sets/doc.go +++ /dev/null @@ -1,21 +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 sets only exists until heapster rebases -// TODO genericapiserver remove this empty package. Godep fails without this because heapster relies -// on this package. This will allow us to start splitting packages, but will force -// heapster to update on their next kube rebase. -package sets diff --git a/pkg/util/sets/types/BUILD b/pkg/util/sets/types/BUILD deleted file mode 100644 index deefdcef3c1..00000000000 --- a/pkg/util/sets/types/BUILD +++ /dev/null @@ -1,27 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -licenses(["notice"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = ["doc.go"], - tags = ["automanaged"], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/pkg/util/sets/types/doc.go b/pkg/util/sets/types/doc.go deleted file mode 100644 index 5fe6f4f9eb1..00000000000 --- a/pkg/util/sets/types/doc.go +++ /dev/null @@ -1,21 +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 sets only exists until heapster rebases -// TODO genericapiserver remove this empty package. Godep fails without this because heapster relies -// on this package. This will allow us to start splitting packages, but will force -// heapster to update on their next kube rebase. -package sets diff --git a/pkg/util/uuid/BUILD b/pkg/util/uuid/BUILD deleted file mode 100644 index deefdcef3c1..00000000000 --- a/pkg/util/uuid/BUILD +++ /dev/null @@ -1,27 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -licenses(["notice"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = ["doc.go"], - tags = ["automanaged"], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/pkg/util/uuid/doc.go b/pkg/util/uuid/doc.go deleted file mode 100644 index 51afc2e6e15..00000000000 --- a/pkg/util/uuid/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. -*/ - -// uuid contains uuid generation helpers. -// WARNING: this will go away when all godeps which vendor us are ported to the new package. -package uuid diff --git a/pkg/util/validation/BUILD b/pkg/util/validation/BUILD deleted file mode 100644 index e67c7910f31..00000000000 --- a/pkg/util/validation/BUILD +++ /dev/null @@ -1,30 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -licenses(["notice"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = ["doc.go"], - tags = ["automanaged"], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [ - ":package-srcs", - "//pkg/util/validation/field:all-srcs", - ], - tags = ["automanaged"], -) diff --git a/pkg/util/validation/doc.go b/pkg/util/validation/doc.go deleted file mode 100644 index 345315c02d2..00000000000 --- a/pkg/util/validation/doc.go +++ /dev/null @@ -1,21 +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 validation only exists until heapster rebases -// TODO genericapiserver remove this empty package. Godep fails without this because heapster relies -// on this package. This will allow us to start splitting packages, but will force -// heapster to update on their next kube rebase. -package validation diff --git a/pkg/util/validation/field/BUILD b/pkg/util/validation/field/BUILD deleted file mode 100644 index deefdcef3c1..00000000000 --- a/pkg/util/validation/field/BUILD +++ /dev/null @@ -1,27 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -licenses(["notice"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = ["doc.go"], - tags = ["automanaged"], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/pkg/util/validation/field/doc.go b/pkg/util/validation/field/doc.go deleted file mode 100644 index 0421cbda632..00000000000 --- a/pkg/util/validation/field/doc.go +++ /dev/null @@ -1,21 +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 field only exists until heapster rebases -// TODO genericapiserver remove this empty package. Godep fails without this because heapster relies -// on this package. This will allow us to start splitting packages, but will force -// heapster to update on their next kube rebase. -package field diff --git a/pkg/util/wait/BUILD b/pkg/util/wait/BUILD deleted file mode 100644 index deefdcef3c1..00000000000 --- a/pkg/util/wait/BUILD +++ /dev/null @@ -1,27 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -licenses(["notice"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = ["doc.go"], - tags = ["automanaged"], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/pkg/util/wait/doc.go b/pkg/util/wait/doc.go deleted file mode 100644 index 748c3a18305..00000000000 --- a/pkg/util/wait/doc.go +++ /dev/null @@ -1,21 +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 wait only exists until heapster rebases -// TODO genericapiserver remove this empty package. Godep fails without this because heapster relies -// on this package. This will allow us to start splitting packages, but will force -// heapster to update on their next kube rebase. -package wait diff --git a/pkg/util/yaml/BUILD b/pkg/util/yaml/BUILD deleted file mode 100644 index deefdcef3c1..00000000000 --- a/pkg/util/yaml/BUILD +++ /dev/null @@ -1,27 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -licenses(["notice"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = ["doc.go"], - tags = ["automanaged"], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/pkg/util/yaml/doc.go b/pkg/util/yaml/doc.go deleted file mode 100644 index f046b9b4dfe..00000000000 --- a/pkg/util/yaml/doc.go +++ /dev/null @@ -1,21 +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 yaml only exists until heapster rebases -// TODO genericapiserver remove this empty package. Godep fails without this because heapster relies -// on this package. This will allow us to start splitting packages, but will force -// heapster to update on their next kube rebase. -package yaml From 6cfbd9329adfff68389ca28cd7f13273d48072ce Mon Sep 17 00:00:00 2001 From: xiangpengzhao Date: Tue, 4 Jul 2017 11:56:34 +0800 Subject: [PATCH 192/448] Fix lint errors of pkg/util/net/sets/ipnet.go --- pkg/util/net/sets/ipnet.go | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/pkg/util/net/sets/ipnet.go b/pkg/util/net/sets/ipnet.go index 5b6fe933f1c..90ad58c6354 100644 --- a/pkg/util/net/sets/ipnet.go +++ b/pkg/util/net/sets/ipnet.go @@ -21,8 +21,10 @@ import ( "strings" ) +// IPNet maps string to net.IPNet. type IPNet map[string]*net.IPNet +// ParseIPNets parses string slice to IPNet. func ParseIPNets(specs ...string) (IPNet, error) { ipnetset := make(IPNet) for _, spec := range specs { @@ -96,9 +98,9 @@ func (s IPNet) StringSlice() []string { } // IsSuperset returns true if and only if s1 is a superset of s2. -func (s1 IPNet) IsSuperset(s2 IPNet) bool { +func (s IPNet) IsSuperset(s2 IPNet) bool { for k := range s2 { - _, found := s1[k] + _, found := s[k] if !found { return false } @@ -109,8 +111,8 @@ func (s1 IPNet) IsSuperset(s2 IPNet) bool { // 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 IPNet) Equal(s2 IPNet) bool { - return len(s1) == len(s2) && s1.IsSuperset(s2) +func (s IPNet) Equal(s2 IPNet) bool { + return len(s) == len(s2) && s.IsSuperset(s2) } // Len returns the size of the set. From afafb3f231c66d4baefc1fae980f651b465cd422 Mon Sep 17 00:00:00 2001 From: Cosmin Cojocar Date: Tue, 4 Jul 2017 08:56:40 +0200 Subject: [PATCH 193/448] Use the azure certificate password when decoding the certificate --- pkg/cloudprovider/providers/azure/azure.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/cloudprovider/providers/azure/azure.go b/pkg/cloudprovider/providers/azure/azure.go index 21e20566bc1..83dab01a084 100644 --- a/pkg/cloudprovider/providers/azure/azure.go +++ b/pkg/cloudprovider/providers/azure/azure.go @@ -159,7 +159,7 @@ func newServicePrincipalToken(az *Cloud) (*azure.ServicePrincipalToken, error) { if err != nil { return nil, fmt.Errorf("reading the client certificate from file %s: %v", az.AADClientCertPath, err) } - certificate, privateKey, err := decodePkcs12(certData, az.AADClientSecret) + certificate, privateKey, err := decodePkcs12(certData, az.AADClientCertPassword) if err != nil { return nil, fmt.Errorf("decoding the client certificate: %v", err) } From 3d6479f7216dcb61e56ab6dd53fad7176930645d Mon Sep 17 00:00:00 2001 From: Shiyang Wang Date: Tue, 13 Jun 2017 08:24:40 +0800 Subject: [PATCH 194/448] Fix 401/403 apiserver errors do not return 'Status' objects --- .../apiserver/pkg/endpoints/filters/BUILD | 5 + .../pkg/endpoints/filters/authentication.go | 39 +++-- .../pkg/endpoints/filters/authorization.go | 5 +- .../pkg/endpoints/filters/impersonation.go | 7 +- .../endpoints/filters/impersonation_test.go | 4 +- .../endpoints/handlers/responsewriters/BUILD | 4 + .../handlers/responsewriters/errors.go | 19 ++- .../handlers/responsewriters/errors_test.go | 23 +-- .../src/k8s.io/apiserver/pkg/server/config.go | 6 +- test/integration/master/BUILD | 7 + test/integration/master/master_test.go | 135 ++++++++++++++---- 11 files changed, 187 insertions(+), 67 deletions(-) diff --git a/staging/src/k8s.io/apiserver/pkg/endpoints/filters/BUILD b/staging/src/k8s.io/apiserver/pkg/endpoints/filters/BUILD index e1f01128710..2dcc5badfdc 100644 --- a/staging/src/k8s.io/apiserver/pkg/endpoints/filters/BUILD +++ b/staging/src/k8s.io/apiserver/pkg/endpoints/filters/BUILD @@ -23,6 +23,8 @@ go_test( deps = [ "//vendor/k8s.io/api/authentication/v1:go_default_library", "//vendor/k8s.io/api/batch/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/sets:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library", "//vendor/k8s.io/apiserver/pkg/apis/audit:go_default_library", @@ -54,7 +56,10 @@ go_library( "//vendor/github.com/prometheus/client_golang/prometheus: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/runtime:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/net:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/runtime:go_default_library", "//vendor/k8s.io/apiserver/pkg/apis/audit:go_default_library", diff --git a/staging/src/k8s.io/apiserver/pkg/endpoints/filters/authentication.go b/staging/src/k8s.io/apiserver/pkg/endpoints/filters/authentication.go index 17bc44f7b76..a53db72137d 100644 --- a/staging/src/k8s.io/apiserver/pkg/endpoints/filters/authentication.go +++ b/staging/src/k8s.io/apiserver/pkg/endpoints/filters/authentication.go @@ -17,13 +17,19 @@ limitations under the License. package filters import ( + "errors" "net/http" "strings" "github.com/golang/glog" "github.com/prometheus/client_golang/prometheus" + apierrors "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apiserver/pkg/authentication/authenticator" + "k8s.io/apiserver/pkg/endpoints/handlers/responsewriters" + "k8s.io/apiserver/pkg/endpoints/request" genericapirequest "k8s.io/apiserver/pkg/endpoints/request" ) @@ -76,22 +82,25 @@ func WithAuthentication(handler http.Handler, mapper genericapirequest.RequestCo ) } -func Unauthorized(supportsBasicAuth bool) http.HandlerFunc { - if supportsBasicAuth { - return unauthorizedBasicAuth - } - return unauthorized -} +func Unauthorized(requestContextMapper request.RequestContextMapper, 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 + } + requestInfo, found := request.RequestInfoFrom(ctx) + if !found { + responsewriters.InternalError(w, req, errors.New("no RequestInfo found in the context")) + return + } -// unauthorizedBasicAuth serves an unauthorized message to clients. -func unauthorizedBasicAuth(w http.ResponseWriter, req *http.Request) { - w.Header().Set("WWW-Authenticate", `Basic realm="kubernetes-master"`) - http.Error(w, "Unauthorized", http.StatusUnauthorized) -} - -// unauthorized serves an unauthorized message to clients. -func unauthorized(w http.ResponseWriter, req *http.Request) { - http.Error(w, "Unauthorized", http.StatusUnauthorized) + gv := schema.GroupVersion{Group: requestInfo.APIGroup, Version: requestInfo.APIVersion} + responsewriters.ErrorNegotiated(ctx, apierrors.NewUnauthorized("Unauthorized"), s, gv, w, req) + }) } // compressUsername maps all possible usernames onto a small set of categories diff --git a/staging/src/k8s.io/apiserver/pkg/endpoints/filters/authorization.go b/staging/src/k8s.io/apiserver/pkg/endpoints/filters/authorization.go index 90599fe3e9a..d244257a04d 100644 --- a/staging/src/k8s.io/apiserver/pkg/endpoints/filters/authorization.go +++ b/staging/src/k8s.io/apiserver/pkg/endpoints/filters/authorization.go @@ -22,13 +22,14 @@ import ( "github.com/golang/glog" + "k8s.io/apimachinery/pkg/runtime" "k8s.io/apiserver/pkg/authorization/authorizer" "k8s.io/apiserver/pkg/endpoints/handlers/responsewriters" "k8s.io/apiserver/pkg/endpoints/request" ) // 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) http.Handler { +func WithAuthorization(handler http.Handler, requestContextMapper request.RequestContextMapper, a authorizer.Authorizer, s runtime.NegotiatedSerializer) http.Handler { if a == nil { glog.Warningf("Authorization is disabled") return handler @@ -56,7 +57,7 @@ func WithAuthorization(handler http.Handler, requestContextMapper request.Reques } glog.V(4).Infof("Forbidden: %#v, Reason: %q", req.RequestURI, reason) - responsewriters.Forbidden(attributes, w, req, reason) + responsewriters.Forbidden(ctx, attributes, w, req, reason, s) }) } diff --git a/staging/src/k8s.io/apiserver/pkg/endpoints/filters/impersonation.go b/staging/src/k8s.io/apiserver/pkg/endpoints/filters/impersonation.go index 891b339ecce..cc4f16bb27b 100644 --- a/staging/src/k8s.io/apiserver/pkg/endpoints/filters/impersonation.go +++ b/staging/src/k8s.io/apiserver/pkg/endpoints/filters/impersonation.go @@ -26,6 +26,7 @@ import ( authenticationv1 "k8s.io/api/authentication/v1" "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/runtime" "k8s.io/apiserver/pkg/authentication/serviceaccount" "k8s.io/apiserver/pkg/authentication/user" "k8s.io/apiserver/pkg/authorization/authorizer" @@ -35,7 +36,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) http.Handler { +func WithImpersonation(handler http.Handler, requestContextMapper request.RequestContextMapper, 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 { @@ -104,14 +105,14 @@ func WithImpersonation(handler http.Handler, requestContextMapper request.Reques default: glog.V(4).Infof("unknown impersonation request type: %v", impersonationRequest) - responsewriters.Forbidden(actingAsAttributes, w, req, fmt.Sprintf("unknown impersonation request type: %v", impersonationRequest)) + responsewriters.Forbidden(ctx, actingAsAttributes, w, req, fmt.Sprintf("unknown impersonation request type: %v", impersonationRequest), s) return } allowed, reason, err := a.Authorize(actingAsAttributes) if err != nil || !allowed { glog.V(4).Infof("Forbidden: %#v, Reason: %s, Error: %v", req.RequestURI, reason, err) - responsewriters.Forbidden(actingAsAttributes, w, req, reason) + responsewriters.Forbidden(ctx, actingAsAttributes, w, req, reason, s) return } } diff --git a/staging/src/k8s.io/apiserver/pkg/endpoints/filters/impersonation_test.go b/staging/src/k8s.io/apiserver/pkg/endpoints/filters/impersonation_test.go index 1c9adb61bc0..d43776507ed 100644 --- a/staging/src/k8s.io/apiserver/pkg/endpoints/filters/impersonation_test.go +++ b/staging/src/k8s.io/apiserver/pkg/endpoints/filters/impersonation_test.go @@ -26,6 +26,8 @@ import ( "testing" authenticationapi "k8s.io/api/authentication/v1" + "k8s.io/apimachinery/pkg/runtime" + serializer "k8s.io/apimachinery/pkg/runtime/serializer" "k8s.io/apiserver/pkg/authentication/user" "k8s.io/apiserver/pkg/authorization/authorizer" "k8s.io/apiserver/pkg/endpoints/request" @@ -356,7 +358,7 @@ func TestImpersonationFilter(t *testing.T) { delegate.ServeHTTP(w, req) }) - }(WithImpersonation(doNothingHandler, requestContextMapper, impersonateAuthorizer{})) + }(WithImpersonation(doNothingHandler, requestContextMapper, impersonateAuthorizer{}, serializer.NewCodecFactory(runtime.NewScheme()))) handler = request.WithRequestContext(handler, requestContextMapper) server := httptest.NewServer(handler) diff --git a/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/responsewriters/BUILD b/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/responsewriters/BUILD index f4ccbeab32c..47986c453c2 100644 --- a/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/responsewriters/BUILD +++ b/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/responsewriters/BUILD @@ -19,9 +19,12 @@ go_test( 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/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/apiserver/pkg/authentication/user:go_default_library", "//vendor/k8s.io/apiserver/pkg/authorization/authorizer:go_default_library", + "//vendor/k8s.io/apiserver/pkg/endpoints/request:go_default_library", ], ) @@ -35,6 +38,7 @@ go_library( ], tags = ["automanaged"], 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/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", diff --git a/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/responsewriters/errors.go b/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/responsewriters/errors.go index 5c6c9bf7561..6a2d226c05a 100644 --- a/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/responsewriters/errors.go +++ b/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/responsewriters/errors.go @@ -21,8 +21,12 @@ import ( "net/http" "strings" - "k8s.io/apimachinery/pkg/util/runtime" + apierrors "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/runtime" + "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. @@ -37,17 +41,20 @@ func BadGatewayError(w http.ResponseWriter, req *http.Request) { } // Forbidden renders a simple forbidden error -func Forbidden(attributes authorizer.Attributes, w http.ResponseWriter, req *http.Request, reason string) { +func Forbidden(ctx request.Context, attributes authorizer.Attributes, w http.ResponseWriter, req *http.Request, reason string, s runtime.NegotiatedSerializer) { msg := sanitizer.Replace(forbiddenMessage(attributes)) - w.Header().Set("Content-Type", "text/plain") w.Header().Set("X-Content-Type-Options", "nosniff") w.WriteHeader(http.StatusForbidden) + var errMsg string if len(reason) == 0 { - fmt.Fprintf(w, "%s", msg) + errMsg = fmt.Sprintf("%s", msg) } else { - fmt.Fprintf(w, "%s: %q", msg, reason) + errMsg = fmt.Sprintf("%s: %q", msg, reason) } + 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) } func forbiddenMessage(attributes authorizer.Attributes) string { @@ -81,7 +88,7 @@ func InternalError(w http.ResponseWriter, req *http.Request, err error) { w.Header().Set("X-Content-Type-Options", "nosniff") w.WriteHeader(http.StatusInternalServerError) fmt.Fprintf(w, "Internal Server Error: %q: %v", sanitizer.Replace(req.RequestURI), err) - runtime.HandleError(err) + utilruntime.HandleError(err) } // NotFound renders a simple not found error. diff --git a/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/responsewriters/errors_test.go b/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/responsewriters/errors_test.go index 31f45d1e10c..9af22c73f3a 100644 --- a/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/responsewriters/errors_test.go +++ b/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/responsewriters/errors_test.go @@ -22,8 +22,11 @@ import ( "net/http/httptest" "testing" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/serializer" "k8s.io/apiserver/pkg/authentication/user" "k8s.io/apiserver/pkg/authorization/authorizer" + "k8s.io/apiserver/pkg/endpoints/request" ) func TestErrors(t *testing.T) { @@ -64,18 +67,20 @@ func TestForbidden(t *testing.T) { attributes authorizer.Attributes reason string }{ - {`User "NAME" cannot GET path "/whatever".`, - authorizer.AttributesRecord{User: u, Verb: "GET", Path: "/whatever"}, ""}, - {`User "NAME" cannot GET path "/<script>".`, - authorizer.AttributesRecord{User: u, Verb: "GET", Path: "/