From c9479990b3ba9675f795cd7218fde356926979ca Mon Sep 17 00:00:00 2001 From: Roman Mohr Date: Tue, 8 Jan 2019 09:32:53 +0100 Subject: [PATCH] Add Custom Resource support to "kubectl autoscale" Generalize the autoscsale command to simply let the dynamic client check if a scale subresource is registered for the supplied type. This allows using the autoscale command for built in types as well as custom resources. --- pkg/kubectl/cmd/autoscale/BUILD | 2 +- pkg/kubectl/cmd/autoscale/autoscale.go | 19 +++-- pkg/kubectl/polymorphichelpers/BUILD | 2 - .../polymorphichelpers/canbeautoscaled.go | 42 ----------- .../canbeautoscaled_test.go | 72 ------------------- pkg/kubectl/polymorphichelpers/interface.go | 6 -- 6 files changed, 13 insertions(+), 130 deletions(-) delete mode 100644 pkg/kubectl/polymorphichelpers/canbeautoscaled.go delete mode 100644 pkg/kubectl/polymorphichelpers/canbeautoscaled_test.go diff --git a/pkg/kubectl/cmd/autoscale/BUILD b/pkg/kubectl/cmd/autoscale/BUILD index fdb1dce6c24..f5b62322f6d 100644 --- a/pkg/kubectl/cmd/autoscale/BUILD +++ b/pkg/kubectl/cmd/autoscale/BUILD @@ -10,7 +10,6 @@ go_library( "//pkg/kubectl/cmd/util:go_default_library", "//pkg/kubectl/generate:go_default_library", "//pkg/kubectl/generate/versioned:go_default_library", - "//pkg/kubectl/polymorphichelpers:go_default_library", "//pkg/kubectl/scheme:go_default_library", "//pkg/kubectl/util/i18n:go_default_library", "//pkg/kubectl/util/templates:go_default_library", @@ -20,6 +19,7 @@ go_library( "//staging/src/k8s.io/cli-runtime/pkg/genericclioptions/printers:go_default_library", "//staging/src/k8s.io/cli-runtime/pkg/genericclioptions/resource:go_default_library", "//staging/src/k8s.io/client-go/kubernetes/typed/autoscaling/v1:go_default_library", + "//staging/src/k8s.io/client-go/scale:go_default_library", "//vendor/github.com/spf13/cobra:go_default_library", "//vendor/k8s.io/klog:go_default_library", ], diff --git a/pkg/kubectl/cmd/autoscale/autoscale.go b/pkg/kubectl/cmd/autoscale/autoscale.go index d26a52b5592..7c1cbbd46d4 100644 --- a/pkg/kubectl/cmd/autoscale/autoscale.go +++ b/pkg/kubectl/cmd/autoscale/autoscale.go @@ -28,11 +28,11 @@ import ( "k8s.io/cli-runtime/pkg/genericclioptions/printers" "k8s.io/cli-runtime/pkg/genericclioptions/resource" autoscalingv1client "k8s.io/client-go/kubernetes/typed/autoscaling/v1" + "k8s.io/client-go/scale" "k8s.io/kubernetes/pkg/kubectl" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" "k8s.io/kubernetes/pkg/kubectl/generate" generateversioned "k8s.io/kubernetes/pkg/kubectl/generate/versioned" - "k8s.io/kubernetes/pkg/kubectl/polymorphichelpers" "k8s.io/kubernetes/pkg/kubectl/scheme" "k8s.io/kubernetes/pkg/kubectl/util/i18n" "k8s.io/kubernetes/pkg/kubectl/util/templates" @@ -74,10 +74,10 @@ type AutoscaleOptions struct { namespace string dryRun bool builder *resource.Builder - canBeAutoscaled polymorphichelpers.CanBeAutoscaledFunc generatorFunc func(string, *meta.RESTMapping) (generate.StructuredGenerator, error) - HPAClient autoscalingv1client.HorizontalPodAutoscalersGetter + HPAClient autoscalingv1client.HorizontalPodAutoscalersGetter + scaleKindResolver scale.ScaleKindResolver genericclioptions.IOStreams } @@ -133,7 +133,11 @@ func (o *AutoscaleOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args o.dryRun = cmdutil.GetFlagBool(cmd, "dry-run") o.createAnnotation = cmdutil.GetFlagBool(cmd, cmdutil.ApplyAnnotationsFlag) o.builder = f.NewBuilder() - o.canBeAutoscaled = polymorphichelpers.CanBeAutoscaledFn + discoveryClient, err := f.ToDiscoveryClient() + if err != nil { + return err + } + o.scaleKindResolver = scale.NewDiscoveryScaleKindResolver(discoveryClient) o.args = args o.RecordFlags.Complete(cmd) @@ -196,7 +200,7 @@ func (o *AutoscaleOptions) Validate() error { func (o *AutoscaleOptions) Run() error { r := o.builder. - WithScheme(scheme.Scheme, scheme.Scheme.PrioritizedVersionsAllGroups()...). + Unstructured(). ContinueOnError(). NamespaceParam(o.namespace).DefaultNamespace(). FilenameParam(o.enforceNamespace, o.FilenameOptions). @@ -214,8 +218,9 @@ func (o *AutoscaleOptions) Run() error { } mapping := info.ResourceMapping() - if err := o.canBeAutoscaled(mapping.GroupVersionKind.GroupKind()); err != nil { - return err + gvr := mapping.GroupVersionKind.GroupVersion().WithResource(mapping.Resource.Resource) + if _, err := o.scaleKindResolver.ScaleForResource(gvr); err != nil { + return fmt.Errorf("cannot autoscale a %v: %v", mapping.GroupVersionKind.Kind, err) } generator, err := o.generatorFunc(info.Name, mapping) diff --git a/pkg/kubectl/polymorphichelpers/BUILD b/pkg/kubectl/polymorphichelpers/BUILD index 235416ff41f..cbf43e685c2 100644 --- a/pkg/kubectl/polymorphichelpers/BUILD +++ b/pkg/kubectl/polymorphichelpers/BUILD @@ -4,7 +4,6 @@ go_library( name = "go_default_library", srcs = [ "attachablepodforobject.go", - "canbeautoscaled.go", "canbeexposed.go", "helpers.go", "historyviewer.go", @@ -51,7 +50,6 @@ go_library( go_test( name = "go_default_test", srcs = [ - "canbeautoscaled_test.go", "canbeexposed_test.go", "helpers_test.go", "logsforobject_test.go", diff --git a/pkg/kubectl/polymorphichelpers/canbeautoscaled.go b/pkg/kubectl/polymorphichelpers/canbeautoscaled.go deleted file mode 100644 index c91e816f7d2..00000000000 --- a/pkg/kubectl/polymorphichelpers/canbeautoscaled.go +++ /dev/null @@ -1,42 +0,0 @@ -/* -Copyright 2018 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package polymorphichelpers - -import ( - "fmt" - - appsv1 "k8s.io/api/apps/v1" - corev1 "k8s.io/api/core/v1" - extensionsv1beta1 "k8s.io/api/extensions/v1beta1" - "k8s.io/apimachinery/pkg/runtime/schema" -) - -func canBeAutoscaled(kind schema.GroupKind) error { - switch kind { - case - corev1.SchemeGroupVersion.WithKind("ReplicationController").GroupKind(), - appsv1.SchemeGroupVersion.WithKind("Deployment").GroupKind(), - appsv1.SchemeGroupVersion.WithKind("ReplicaSet").GroupKind(), - appsv1.SchemeGroupVersion.WithKind("StatefulSet").GroupKind(), - extensionsv1beta1.SchemeGroupVersion.WithKind("Deployment").GroupKind(), - extensionsv1beta1.SchemeGroupVersion.WithKind("ReplicaSet").GroupKind(): - // nothing to do here - default: - return fmt.Errorf("cannot autoscale a %v", kind) - } - return nil -} diff --git a/pkg/kubectl/polymorphichelpers/canbeautoscaled_test.go b/pkg/kubectl/polymorphichelpers/canbeautoscaled_test.go deleted file mode 100644 index b1e1fc92f0e..00000000000 --- a/pkg/kubectl/polymorphichelpers/canbeautoscaled_test.go +++ /dev/null @@ -1,72 +0,0 @@ -/* -Copyright 2018 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package polymorphichelpers - -import ( - "testing" - - appsv1 "k8s.io/api/apps/v1" - corev1 "k8s.io/api/core/v1" - extensionsv1beta1 "k8s.io/api/extensions/v1beta1" - "k8s.io/apimachinery/pkg/runtime/schema" -) - -func TestCanBeAutoscaled(t *testing.T) { - tests := []struct { - kind schema.GroupKind - expectErr bool - }{ - { - kind: corev1.SchemeGroupVersion.WithKind("ReplicationController").GroupKind(), - expectErr: false, - }, - { - kind: appsv1.SchemeGroupVersion.WithKind("Deployment").GroupKind(), - expectErr: false, - }, - { - kind: appsv1.SchemeGroupVersion.WithKind("StatefulSet").GroupKind(), - expectErr: false, - }, - { - kind: extensionsv1beta1.SchemeGroupVersion.WithKind("ReplicaSet").GroupKind(), - expectErr: false, - }, - { - kind: corev1.SchemeGroupVersion.WithKind("Node").GroupKind(), - expectErr: true, - }, - { - kind: corev1.SchemeGroupVersion.WithKind("Service").GroupKind(), - expectErr: true, - }, - { - kind: corev1.SchemeGroupVersion.WithKind("Pod").GroupKind(), - expectErr: true, - }, - } - - for _, test := range tests { - err := canBeAutoscaled(test.kind) - if test.expectErr && err == nil { - t.Error("unexpected non-error") - } - if !test.expectErr && err != nil { - t.Errorf("unexpected error: %v", err) - } - } -} diff --git a/pkg/kubectl/polymorphichelpers/interface.go b/pkg/kubectl/polymorphichelpers/interface.go index 816bf91427c..8e043388b53 100644 --- a/pkg/kubectl/polymorphichelpers/interface.go +++ b/pkg/kubectl/polymorphichelpers/interface.go @@ -79,12 +79,6 @@ type PortsForObjectFunc func(object runtime.Object) ([]string, error) // PortsForObjectFn gives a way to easily override the function for unit testing if needed var PortsForObjectFn PortsForObjectFunc = portsForObject -// CanBeAutoscaledFunc checks whether the kind of resources could be autoscaled -type CanBeAutoscaledFunc func(kind schema.GroupKind) error - -// CanBeAutoscaledFn gives a way to easily override the function for unit testing if needed -var CanBeAutoscaledFn CanBeAutoscaledFunc = canBeAutoscaled - // CanBeExposedFunc is a function type that can tell you whether a given GroupKind is capable of being exposed type CanBeExposedFunc func(kind schema.GroupKind) error