move Pauser and Resumer from the factory

pull/8/head
juanvallejo 2018-05-21 17:56:56 -04:00
parent 5f5e3a59c0
commit fb0794976a
15 changed files with 182 additions and 70 deletions

View File

@ -30,6 +30,7 @@ import (
"k8s.io/kubernetes/pkg/kubectl/genericclioptions" "k8s.io/kubernetes/pkg/kubectl/genericclioptions"
"k8s.io/kubernetes/pkg/kubectl/genericclioptions/printers" "k8s.io/kubernetes/pkg/kubectl/genericclioptions/printers"
"k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource" "k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource"
"k8s.io/kubernetes/pkg/kubectl/polymorphichelpers"
"k8s.io/kubernetes/pkg/kubectl/scheme" "k8s.io/kubernetes/pkg/kubectl/scheme"
"k8s.io/kubernetes/pkg/kubectl/util/i18n" "k8s.io/kubernetes/pkg/kubectl/util/i18n"
) )
@ -41,7 +42,7 @@ type PauseConfig struct {
PrintFlags *genericclioptions.PrintFlags PrintFlags *genericclioptions.PrintFlags
ToPrinter func(string) (printers.ResourcePrinter, error) ToPrinter func(string) (printers.ResourcePrinter, error)
Pauser func(info *resource.Info) ([]byte, error) Pauser polymorphichelpers.ObjectPauserFunc
Infos []*resource.Info Infos []*resource.Info
genericclioptions.IOStreams genericclioptions.IOStreams
@ -101,7 +102,7 @@ func (o *PauseConfig) CompletePause(f cmdutil.Factory, cmd *cobra.Command, args
return cmdutil.UsageErrorf(cmd, "%s", cmd.Use) return cmdutil.UsageErrorf(cmd, "%s", cmd.Use)
} }
o.Pauser = f.Pauser o.Pauser = polymorphichelpers.ObjectPauserFn
cmdNamespace, enforceNamespace, err := f.DefaultNamespace() cmdNamespace, enforceNamespace, err := f.DefaultNamespace()
if err != nil { if err != nil {
@ -136,7 +137,7 @@ func (o *PauseConfig) CompletePause(f cmdutil.Factory, cmd *cobra.Command, args
func (o PauseConfig) RunPause() error { func (o PauseConfig) RunPause() error {
allErrs := []error{} allErrs := []error{}
for _, patch := range set.CalculatePatches(o.Infos, cmdutil.InternalVersionJSONEncoder(), o.Pauser) { for _, patch := range set.CalculatePatches(o.Infos, cmdutil.InternalVersionJSONEncoder(), set.PatchFn(o.Pauser)) {
info := patch.Info info := patch.Info
if patch.Err != nil { if patch.Err != nil {
resourceString := info.Mapping.Resource.Resource resourceString := info.Mapping.Resource.Resource

View File

@ -30,6 +30,7 @@ import (
"k8s.io/kubernetes/pkg/kubectl/genericclioptions" "k8s.io/kubernetes/pkg/kubectl/genericclioptions"
"k8s.io/kubernetes/pkg/kubectl/genericclioptions/printers" "k8s.io/kubernetes/pkg/kubectl/genericclioptions/printers"
"k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource" "k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource"
"k8s.io/kubernetes/pkg/kubectl/polymorphichelpers"
"k8s.io/kubernetes/pkg/kubectl/scheme" "k8s.io/kubernetes/pkg/kubectl/scheme"
"k8s.io/kubernetes/pkg/kubectl/util/i18n" "k8s.io/kubernetes/pkg/kubectl/util/i18n"
) )
@ -41,7 +42,7 @@ type ResumeConfig struct {
PrintFlags *genericclioptions.PrintFlags PrintFlags *genericclioptions.PrintFlags
ToPrinter func(string) (printers.ResourcePrinter, error) ToPrinter func(string) (printers.ResourcePrinter, error)
Resumer func(object *resource.Info) ([]byte, error) Resumer polymorphichelpers.ObjectResumerFunc
Infos []*resource.Info Infos []*resource.Info
genericclioptions.IOStreams genericclioptions.IOStreams
@ -99,7 +100,7 @@ func (o *ResumeConfig) CompleteResume(f cmdutil.Factory, cmd *cobra.Command, arg
return cmdutil.UsageErrorf(cmd, "%s", cmd.Use) return cmdutil.UsageErrorf(cmd, "%s", cmd.Use)
} }
o.Resumer = f.Resumer o.Resumer = polymorphichelpers.ObjectResumerFn
cmdNamespace, enforceNamespace, err := f.DefaultNamespace() cmdNamespace, enforceNamespace, err := f.DefaultNamespace()
if err != nil { if err != nil {
@ -140,7 +141,7 @@ func (o *ResumeConfig) CompleteResume(f cmdutil.Factory, cmd *cobra.Command, arg
func (o ResumeConfig) RunResume() error { func (o ResumeConfig) RunResume() error {
allErrs := []error{} allErrs := []error{}
for _, patch := range set.CalculatePatches(o.Infos, cmdutil.InternalVersionJSONEncoder(), o.Resumer) { for _, patch := range set.CalculatePatches(o.Infos, cmdutil.InternalVersionJSONEncoder(), set.PatchFn(o.Resumer)) {
info := patch.Info info := patch.Info
if patch.Err != nil { if patch.Err != nil {

View File

@ -118,16 +118,16 @@ type Patch struct {
Patch []byte Patch []byte
} }
// patchFn is a function type that accepts an info object and returns a byte slice. // PatchFn is a function type that accepts an info object and returns a byte slice.
// Implementations of patchFn should update the object and return it encoded. // Implementations of PatchFn should update the object and return it encoded.
type patchFn func(*resource.Info) ([]byte, error) type PatchFn func(runtime.Object) ([]byte, error)
// CalculatePatch calls the mutation function on the provided info object, and generates a strategic merge patch for // CalculatePatch calls the mutation function on the provided info object, and generates a strategic merge patch for
// the changes in the object. Encoder must be able to encode the info into the appropriate destination type. // the changes in the object. Encoder must be able to encode the info into the appropriate destination type.
// This function returns whether the mutation function made any change in the original object. // This function returns whether the mutation function made any change in the original object.
func CalculatePatch(patch *Patch, encoder runtime.Encoder, mutateFn patchFn) bool { func CalculatePatch(patch *Patch, encoder runtime.Encoder, mutateFn PatchFn) bool {
patch.Before, patch.Err = runtime.Encode(encoder, patch.Info.Object) patch.Before, patch.Err = runtime.Encode(encoder, patch.Info.Object)
patch.After, patch.Err = mutateFn(patch.Info) patch.After, patch.Err = mutateFn(patch.Info.Object)
if patch.Err != nil { if patch.Err != nil {
return true return true
} }
@ -141,7 +141,7 @@ func CalculatePatch(patch *Patch, encoder runtime.Encoder, mutateFn patchFn) boo
// CalculatePatches calculates patches on each provided info object. If the provided mutateFn // CalculatePatches calculates patches on each provided info object. If the provided mutateFn
// makes no change in an object, the object is not included in the final list of patches. // makes no change in an object, the object is not included in the final list of patches.
func CalculatePatches(infos []*resource.Info, encoder runtime.Encoder, mutateFn patchFn) []*Patch { func CalculatePatches(infos []*resource.Info, encoder runtime.Encoder, mutateFn PatchFn) []*Patch {
var patches []*Patch var patches []*Patch
for _, info := range infos { for _, info := range infos {
patch := &Patch{Info: info} patch := &Patch{Info: info}

View File

@ -26,6 +26,7 @@ import (
"github.com/spf13/cobra" "github.com/spf13/cobra"
"k8s.io/api/core/v1" "k8s.io/api/core/v1"
meta "k8s.io/apimachinery/pkg/api/meta"
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/types"
utilerrors "k8s.io/apimachinery/pkg/util/errors" utilerrors "k8s.io/apimachinery/pkg/util/errors"
@ -323,12 +324,53 @@ func (o *EnvOptions) RunEnv() error {
if err != nil { if err != nil {
return err return err
} }
patches := CalculatePatches(infos, scheme.DefaultJSONEncoder(), func(info *resource.Info) ([]byte, error) { patches := CalculatePatches(infos, scheme.DefaultJSONEncoder(), func(obj runtime.Object) ([]byte, error) {
_, err := o.updatePodSpecForObject(info.Object, func(spec *v1.PodSpec) error { _, err := o.updatePodSpecForObject(obj, func(spec *v1.PodSpec) error {
resolutionErrorsEncountered := false resolutionErrorsEncountered := false
containers, _ := selectContainers(spec.Containers, o.ContainerSelector) containers, _ := selectContainers(spec.Containers, o.ContainerSelector)
objName, err := meta.NewAccessor().Name(obj)
if err != nil {
return err
}
gvks, _, err := scheme.Scheme.ObjectKinds(obj)
if err != nil {
return err
}
objKind := obj.GetObjectKind().GroupVersionKind().Kind
if len(objKind) == 0 {
for _, gvk := range gvks {
if len(gvk.Kind) == 0 {
continue
}
if len(gvk.Version) == 0 || gvk.Version == runtime.APIVersionInternal {
continue
}
objKind = gvk.Kind
break
}
}
if len(containers) == 0 { if len(containers) == 0 {
fmt.Fprintf(o.ErrOut, "warning: %s/%s does not have any containers matching %q\n", info.Mapping.Resource, info.Name, o.ContainerSelector) if gvks, _, err := scheme.Scheme.ObjectKinds(obj); err == nil {
objKind := obj.GetObjectKind().GroupVersionKind().Kind
if len(objKind) == 0 {
for _, gvk := range gvks {
if len(gvk.Kind) == 0 {
continue
}
if len(gvk.Version) == 0 || gvk.Version == runtime.APIVersionInternal {
continue
}
objKind = gvk.Kind
break
}
}
fmt.Fprintf(o.ErrOut, "warning: %s/%s does not have any containers matching %q\n", objKind, objName, o.ContainerSelector)
}
return nil return nil
} }
for _, c := range containers { for _, c := range containers {
@ -343,7 +385,7 @@ func (o *EnvOptions) RunEnv() error {
resolveErrors := map[string][]string{} resolveErrors := map[string][]string{}
store := envutil.NewResourceStore() store := envutil.NewResourceStore()
fmt.Fprintf(o.Out, "# %s %s, container %s\n", info.Mapping.Resource, info.Name, c.Name) fmt.Fprintf(o.Out, "# %s %s, container %s\n", objKind, objName, c.Name)
for _, env := range c.Env { for _, env := range c.Env {
// Print the simple value // Print the simple value
if env.ValueFrom == nil { if env.ValueFrom == nil {
@ -357,7 +399,7 @@ func (o *EnvOptions) RunEnv() error {
continue continue
} }
value, err := envutil.GetEnvVarRefValue(o.clientset, o.namespace, store, env.ValueFrom, info.Object, c) value, err := envutil.GetEnvVarRefValue(o.clientset, o.namespace, store, env.ValueFrom, obj, c)
// Print the resolved value // Print the resolved value
if err == nil { if err == nil {
fmt.Fprintf(o.Out, "%s=%s\n", env.Name, value) fmt.Fprintf(o.Out, "%s=%s\n", env.Name, value)
@ -390,7 +432,7 @@ func (o *EnvOptions) RunEnv() error {
}) })
if err == nil { if err == nil {
return runtime.Encode(scheme.DefaultJSONEncoder(), info.Object) return runtime.Encode(scheme.DefaultJSONEncoder(), obj)
} }
return nil, err return nil, err
}) })

View File

@ -210,9 +210,9 @@ func (o *SetImageOptions) Validate() error {
func (o *SetImageOptions) Run() error { func (o *SetImageOptions) Run() error {
allErrs := []error{} allErrs := []error{}
patches := CalculatePatches(o.Infos, scheme.DefaultJSONEncoder(), func(info *resource.Info) ([]byte, error) { patches := CalculatePatches(o.Infos, scheme.DefaultJSONEncoder(), func(obj runtime.Object) ([]byte, error) {
transformed := false transformed := false
_, err := o.UpdatePodSpecForObject(info.Object, func(spec *v1.PodSpec) error { _, err := o.UpdatePodSpecForObject(obj, func(spec *v1.PodSpec) error {
for name, image := range o.ContainerImages { for name, image := range o.ContainerImages {
var ( var (
containerFound bool containerFound bool
@ -255,11 +255,11 @@ func (o *SetImageOptions) Run() error {
return nil, nil return nil, nil
} }
// record this change (for rollout history) // record this change (for rollout history)
if err := o.Recorder.Record(info.Object); err != nil { if err := o.Recorder.Record(obj); err != nil {
glog.V(4).Infof("error recording current command: %v", err) glog.V(4).Infof("error recording current command: %v", err)
} }
return runtime.Encode(scheme.DefaultJSONEncoder(), info.Object) return runtime.Encode(scheme.DefaultJSONEncoder(), obj)
}) })
for _, patch := range patches { for _, patch := range patches {

View File

@ -222,9 +222,9 @@ func (o *SetResourcesOptions) Validate() error {
func (o *SetResourcesOptions) Run() error { func (o *SetResourcesOptions) Run() error {
allErrs := []error{} allErrs := []error{}
patches := CalculatePatches(o.Infos, scheme.DefaultJSONEncoder(), func(info *resource.Info) ([]byte, error) { patches := CalculatePatches(o.Infos, scheme.DefaultJSONEncoder(), func(obj runtime.Object) ([]byte, error) {
transformed := false transformed := false
_, err := o.UpdatePodSpecForObject(info.Object, func(spec *v1.PodSpec) error { _, err := o.UpdatePodSpecForObject(obj, func(spec *v1.PodSpec) error {
containers, _ := selectContainers(spec.Containers, o.ContainerSelector) containers, _ := selectContainers(spec.Containers, o.ContainerSelector)
if len(containers) != 0 { if len(containers) != 0 {
for i := range containers { for i := range containers {
@ -255,11 +255,11 @@ func (o *SetResourcesOptions) Run() error {
return nil, nil return nil, nil
} }
// record this change (for rollout history) // record this change (for rollout history)
if err := o.Recorder.Record(info.Object); err != nil { if err := o.Recorder.Record(obj); err != nil {
glog.V(4).Infof("error recording current command: %v", err) glog.V(4).Infof("error recording current command: %v", err)
} }
return runtime.Encode(scheme.DefaultJSONEncoder(), info.Object) return runtime.Encode(scheme.DefaultJSONEncoder(), obj)
}) })
for _, patch := range patches { for _, patch := range patches {

View File

@ -200,7 +200,7 @@ func (o *SetSelectorOptions) RunSelector() error {
return r.Visit(func(info *resource.Info, err error) error { return r.Visit(func(info *resource.Info, err error) error {
patch := &Patch{Info: info} patch := &Patch{Info: info}
CalculatePatch(patch, scheme.DefaultJSONEncoder(), func(info *resource.Info) ([]byte, error) { CalculatePatch(patch, scheme.DefaultJSONEncoder(), func(obj runtime.Object) ([]byte, error) {
selectErr := updateSelectorForObject(info.Object, *o.selector) selectErr := updateSelectorForObject(info.Object, *o.selector)
if selectErr != nil { if selectErr != nil {
return nil, selectErr return nil, selectErr

View File

@ -173,8 +173,8 @@ func (o *SetServiceAccountOptions) Complete(f cmdutil.Factory, cmd *cobra.Comman
// Run creates and applies the patch either locally or calling apiserver. // Run creates and applies the patch either locally or calling apiserver.
func (o *SetServiceAccountOptions) Run() error { func (o *SetServiceAccountOptions) Run() error {
patchErrs := []error{} patchErrs := []error{}
patchFn := func(info *resource.Info) ([]byte, error) { patchFn := func(obj runtime.Object) ([]byte, error) {
_, err := o.updatePodSpecForObject(info.Object, func(podSpec *v1.PodSpec) error { _, err := o.updatePodSpecForObject(obj, func(podSpec *v1.PodSpec) error {
podSpec.ServiceAccountName = o.serviceAccountName podSpec.ServiceAccountName = o.serviceAccountName
return nil return nil
}) })
@ -182,11 +182,11 @@ func (o *SetServiceAccountOptions) Run() error {
return nil, err return nil, err
} }
// record this change (for rollout history) // record this change (for rollout history)
if err := o.Recorder.Record(info.Object); err != nil { if err := o.Recorder.Record(obj); err != nil {
glog.V(4).Infof("error recording current command: %v", err) glog.V(4).Infof("error recording current command: %v", err)
} }
return runtime.Encode(scheme.DefaultJSONEncoder(), info.Object) return runtime.Encode(scheme.DefaultJSONEncoder(), obj)
} }
patches := CalculatePatches(o.infos, scheme.DefaultJSONEncoder(), patchFn) patches := CalculatePatches(o.infos, scheme.DefaultJSONEncoder(), patchFn)

View File

@ -194,7 +194,7 @@ func (o *SubjectOptions) Validate() error {
} }
func (o *SubjectOptions) Run(fn updateSubjects) error { func (o *SubjectOptions) Run(fn updateSubjects) error {
patches := CalculatePatches(o.Infos, scheme.DefaultJSONEncoder(), func(info *resource.Info) ([]byte, error) { patches := CalculatePatches(o.Infos, scheme.DefaultJSONEncoder(), func(obj runtime.Object) ([]byte, error) {
subjects := []rbacv1.Subject{} subjects := []rbacv1.Subject{}
for _, user := range sets.NewString(o.Users...).List() { for _, user := range sets.NewString(o.Users...).List() {
subject := rbacv1.Subject{ subject := rbacv1.Subject{
@ -227,10 +227,10 @@ func (o *SubjectOptions) Run(fn updateSubjects) error {
subjects = append(subjects, subject) subjects = append(subjects, subject)
} }
transformed, err := updateSubjectForObject(info.Object, subjects, fn) transformed, err := updateSubjectForObject(obj, subjects, fn)
if transformed && err == nil { if transformed && err == nil {
// TODO: switch UpdatePodSpecForObject to work on v1.PodSpec // TODO: switch UpdatePodSpecForObject to work on v1.PodSpec
return runtime.Encode(scheme.DefaultJSONEncoder(), info.Object) return runtime.Encode(scheme.DefaultJSONEncoder(), obj)
} }
return nil, err return nil, err
}) })

View File

@ -92,15 +92,6 @@ type ClientAccessFactory interface {
// SuggestedPodTemplateResources returns a list of resource types that declare a pod template // SuggestedPodTemplateResources returns a list of resource types that declare a pod template
SuggestedPodTemplateResources() []schema.GroupResource SuggestedPodTemplateResources() []schema.GroupResource
// Pauser marks the object in the info as paused. Currently supported only for Deployments.
// Returns the patched object in bytes and any error that occurred during the encoding or
// in case the object is already paused.
Pauser(info *resource.Info) ([]byte, error)
// Resumer resumes a paused object inside the info. Currently supported only for Deployments.
// Returns the patched object in bytes and any error that occurred during the encoding or
// in case the object is already resumed.
Resumer(info *resource.Info) ([]byte, error)
// Returns the default namespace to use in cases where no // Returns the default namespace to use in cases where no
// other namespace is specified and whether the namespace was // other namespace is specified and whether the namespace was
// overridden. // overridden.

View File

@ -19,7 +19,6 @@ limitations under the License.
package util package util
import ( import (
"errors"
"fmt" "fmt"
"io" "io"
"os" "os"
@ -218,32 +217,6 @@ func (f *ring0Factory) SuggestedPodTemplateResources() []schema.GroupResource {
} }
} }
func (f *ring0Factory) Pauser(info *resource.Info) ([]byte, error) {
switch obj := info.Object.(type) {
case *extensions.Deployment:
if obj.Spec.Paused {
return nil, errors.New("is already paused")
}
obj.Spec.Paused = true
return runtime.Encode(InternalVersionJSONEncoder(), info.Object)
default:
return nil, fmt.Errorf("pausing is not supported")
}
}
func (f *ring0Factory) Resumer(info *resource.Info) ([]byte, error) {
switch obj := info.Object.(type) {
case *extensions.Deployment:
if !obj.Spec.Paused {
return nil, errors.New("is not paused")
}
obj.Spec.Paused = false
return runtime.Encode(InternalVersionJSONEncoder(), info.Object)
default:
return nil, fmt.Errorf("resuming is not supported")
}
}
func (f *ring0Factory) DefaultNamespace() (string, bool, error) { func (f *ring0Factory) DefaultNamespace() (string, bool, error) {
return f.clientGetter.ToRawKubeConfigLoader().Namespace() return f.clientGetter.ToRawKubeConfigLoader().Namespace()
} }

View File

@ -10,6 +10,8 @@ go_library(
"historyviewer.go", "historyviewer.go",
"interface.go", "interface.go",
"logsforobject.go", "logsforobject.go",
"objectpauser.go",
"objectresumer.go",
"portsforobject.go", "portsforobject.go",
"statusviewer.go", "statusviewer.go",
"updatepodspec.go", "updatepodspec.go",
@ -17,6 +19,7 @@ go_library(
importpath = "k8s.io/kubernetes/pkg/kubectl/polymorphichelpers", importpath = "k8s.io/kubernetes/pkg/kubectl/polymorphichelpers",
visibility = ["//visibility:public"], visibility = ["//visibility:public"],
deps = [ deps = [
"//pkg/api/legacyscheme:go_default_library",
"//pkg/apis/apps:go_default_library", "//pkg/apis/apps:go_default_library",
"//pkg/apis/batch:go_default_library", "//pkg/apis/batch:go_default_library",
"//pkg/apis/core:go_default_library", "//pkg/apis/core:go_default_library",
@ -37,6 +40,7 @@ go_library(
"//vendor/k8s.io/api/extensions/v1beta1:go_default_library", "//vendor/k8s.io/api/extensions/v1beta1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/labels: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:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",

View File

@ -77,3 +77,19 @@ type CanBeExposedFunc func(kind schema.GroupKind) error
// CanBeExposedFn gives a way to easily override the function for unit testing if needed // CanBeExposedFn gives a way to easily override the function for unit testing if needed
var CanBeExposedFn CanBeExposedFunc = canBeExposed var CanBeExposedFn CanBeExposedFunc = canBeExposed
// ObjectPauserFunc is a function type that marks the object in a given info as paused.
type ObjectPauserFunc func(runtime.Object) ([]byte, error)
// ObjectPauserFn gives a way to easily override the function for unit testing if needed.
// Returns the patched object in bytes and any error that occurred during the encoding or
// in case the object is already paused.
var ObjectPauserFn ObjectPauserFunc = defaultObjectPauser
// ObjectResumerFunc is a function type that marks the object in a given info as resumed.
type ObjectResumerFunc func(runtime.Object) ([]byte, error)
// ObjectResumerFn gives a way to easily override the function for unit testing if needed.
// Returns the patched object in bytes and any error that occurred during the encoding or
// in case the object is already resumed.
var ObjectResumerFn ObjectResumerFunc = defaultObjectResumer

View File

@ -0,0 +1,46 @@
/*
Copyright 2018 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package polymorphichelpers
import (
"errors"
"fmt"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/kubernetes/pkg/api/legacyscheme"
"k8s.io/kubernetes/pkg/apis/extensions"
)
// Currently only supports Deployments.
func defaultObjectPauser(obj runtime.Object) ([]byte, error) {
switch obj := obj.(type) {
case *extensions.Deployment:
if obj.Spec.Paused {
return nil, errors.New("is already paused")
}
obj.Spec.Paused = true
return runtime.Encode(internalVersionJSONEncoder(), obj)
default:
return nil, fmt.Errorf("pausing is not supported")
}
}
func internalVersionJSONEncoder() runtime.Encoder {
encoder := legacyscheme.Codecs.LegacyCodec(legacyscheme.Scheme.PrioritizedVersionsAllGroups()...)
return unstructured.JSONFallbackEncoder{Encoder: encoder}
}

View File

@ -0,0 +1,38 @@
/*
Copyright 2018 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package polymorphichelpers
import (
"errors"
"fmt"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/kubernetes/pkg/apis/extensions"
)
func defaultObjectResumer(obj runtime.Object) ([]byte, error) {
switch obj := obj.(type) {
case *extensions.Deployment:
if !obj.Spec.Paused {
return nil, errors.New("is not paused")
}
obj.Spec.Paused = false
return runtime.Encode(internalVersionJSONEncoder(), obj)
default:
return nil, fmt.Errorf("resuming is not supported")
}
}