Unverified Commit b143093a authored by Kubernetes Submit Queue's avatar Kubernetes Submit Queue Committed by GitHub

Merge pull request #64111 from juanvallejo/jvallejo/move-more-helpers

Automatic merge from submit-queue. If you want to cherry-pick this change to another branch, please follow the instructions <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md">here</a>. Move CanBeExposed helper from factory_client_access **Release note**: ```release-note NONE ``` Moves additional helpers from the "factory_client_access". Continues work from https://github.com/kubernetes/kubernetes/pull/63984 and https://github.com/kubernetes/kubernetes/pull/63884 Moves CanBeExposed from factory_client_access. cc @soltysh
parents 65a81933 b6db6237
......@@ -27,7 +27,6 @@ import (
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/unstructuredscheme"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/util/validation"
"k8s.io/client-go/dynamic"
"k8s.io/kubernetes/pkg/api/legacyscheme"
......@@ -92,7 +91,7 @@ type ExposeServiceOptions struct {
EnforceNamespace bool
Generators func(string) map[string]kubectl.Generator
CanBeExposed func(kind schema.GroupKind) error
CanBeExposed polymorphichelpers.CanBeExposedFunc
ClientForMapping func(*meta.RESTMapping) (resource.RESTClient, error)
MapBasedSelectorForObject func(runtime.Object) (string, error)
PortsForObject polymorphichelpers.PortsForObjectFunc
......@@ -191,7 +190,7 @@ func (o *ExposeServiceOptions) Complete(f cmdutil.Factory, cmd *cobra.Command) e
o.Generators = f.Generators
o.Builder = f.NewBuilder()
o.CanBeExposed = f.CanBeExposed
o.CanBeExposed = polymorphichelpers.CanBeExposedFn
o.ClientForMapping = f.ClientForMapping
o.MapBasedSelectorForObject = f.MapBasedSelectorForObject
o.PortsForObject = polymorphichelpers.PortsForObjectFn
......
......@@ -30,6 +30,7 @@ import (
"k8s.io/kubernetes/pkg/kubectl/genericclioptions"
"k8s.io/kubernetes/pkg/kubectl/genericclioptions/printers"
"k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource"
"k8s.io/kubernetes/pkg/kubectl/polymorphichelpers"
"k8s.io/kubernetes/pkg/kubectl/scheme"
"k8s.io/kubernetes/pkg/kubectl/util/i18n"
)
......@@ -41,7 +42,7 @@ type PauseConfig struct {
PrintFlags *genericclioptions.PrintFlags
ToPrinter func(string) (printers.ResourcePrinter, error)
Pauser func(info *resource.Info) ([]byte, error)
Pauser polymorphichelpers.ObjectPauserFunc
Infos []*resource.Info
genericclioptions.IOStreams
......@@ -101,7 +102,7 @@ func (o *PauseConfig) CompletePause(f cmdutil.Factory, cmd *cobra.Command, args
return cmdutil.UsageErrorf(cmd, "%s", cmd.Use)
}
o.Pauser = f.Pauser
o.Pauser = polymorphichelpers.ObjectPauserFn
cmdNamespace, enforceNamespace, err := f.DefaultNamespace()
if err != nil {
......@@ -136,7 +137,7 @@ func (o *PauseConfig) CompletePause(f cmdutil.Factory, cmd *cobra.Command, args
func (o PauseConfig) RunPause() error {
allErrs := []error{}
for _, patch := range set.CalculatePatches(o.Infos, cmdutil.InternalVersionJSONEncoder(), o.Pauser) {
for _, patch := range set.CalculatePatches(o.Infos, cmdutil.InternalVersionJSONEncoder(), set.PatchFn(o.Pauser)) {
info := patch.Info
if patch.Err != nil {
resourceString := info.Mapping.Resource.Resource
......
......@@ -30,6 +30,7 @@ import (
"k8s.io/kubernetes/pkg/kubectl/genericclioptions"
"k8s.io/kubernetes/pkg/kubectl/genericclioptions/printers"
"k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource"
"k8s.io/kubernetes/pkg/kubectl/polymorphichelpers"
"k8s.io/kubernetes/pkg/kubectl/scheme"
"k8s.io/kubernetes/pkg/kubectl/util/i18n"
)
......@@ -41,7 +42,7 @@ type ResumeConfig struct {
PrintFlags *genericclioptions.PrintFlags
ToPrinter func(string) (printers.ResourcePrinter, error)
Resumer func(object *resource.Info) ([]byte, error)
Resumer polymorphichelpers.ObjectResumerFunc
Infos []*resource.Info
genericclioptions.IOStreams
......@@ -99,7 +100,7 @@ func (o *ResumeConfig) CompleteResume(f cmdutil.Factory, cmd *cobra.Command, arg
return cmdutil.UsageErrorf(cmd, "%s", cmd.Use)
}
o.Resumer = f.Resumer
o.Resumer = polymorphichelpers.ObjectResumerFn
cmdNamespace, enforceNamespace, err := f.DefaultNamespace()
if err != nil {
......@@ -140,7 +141,7 @@ func (o *ResumeConfig) CompleteResume(f cmdutil.Factory, cmd *cobra.Command, arg
func (o ResumeConfig) RunResume() error {
allErrs := []error{}
for _, patch := range set.CalculatePatches(o.Infos, cmdutil.InternalVersionJSONEncoder(), o.Resumer) {
for _, patch := range set.CalculatePatches(o.Infos, cmdutil.InternalVersionJSONEncoder(), set.PatchFn(o.Resumer)) {
info := patch.Info
if patch.Err != nil {
......
......@@ -20,6 +20,7 @@ import (
"io"
"github.com/spf13/cobra"
"k8s.io/kubernetes/pkg/kubectl/polymorphichelpers"
utilerrors "k8s.io/apimachinery/pkg/util/errors"
"k8s.io/kubernetes/pkg/api/legacyscheme"
......@@ -139,7 +140,7 @@ func (o *UndoOptions) CompleteUndo(f cmdutil.Factory, cmd *cobra.Command, out io
if err != nil {
return err
}
rollbacker, err := f.Rollbacker(info.ResourceMapping())
rollbacker, err := polymorphichelpers.RollbackerFn(f, info.ResourceMapping())
if err != nil {
return err
}
......
......@@ -118,16 +118,16 @@ type Patch struct {
Patch []byte
}
// patchFn is a function type that accepts an info object and returns a byte slice.
// Implementations of patchFn should update the object and return it encoded.
type patchFn func(*resource.Info) ([]byte, error)
// PatchFn is a function type that accepts an info object and returns a byte slice.
// Implementations of PatchFn should update the object and return it encoded.
type PatchFn func(runtime.Object) ([]byte, error)
// CalculatePatch calls the mutation function on the provided info object, and generates a strategic merge patch for
// the changes in the object. Encoder must be able to encode the info into the appropriate destination type.
// This function returns whether the mutation function made any change in the original object.
func CalculatePatch(patch *Patch, encoder runtime.Encoder, mutateFn patchFn) bool {
func CalculatePatch(patch *Patch, encoder runtime.Encoder, mutateFn PatchFn) bool {
patch.Before, patch.Err = runtime.Encode(encoder, patch.Info.Object)
patch.After, patch.Err = mutateFn(patch.Info)
patch.After, patch.Err = mutateFn(patch.Info.Object)
if patch.Err != nil {
return true
}
......@@ -141,7 +141,7 @@ func CalculatePatch(patch *Patch, encoder runtime.Encoder, mutateFn patchFn) boo
// CalculatePatches calculates patches on each provided info object. If the provided mutateFn
// makes no change in an object, the object is not included in the final list of patches.
func CalculatePatches(infos []*resource.Info, encoder runtime.Encoder, mutateFn patchFn) []*Patch {
func CalculatePatches(infos []*resource.Info, encoder runtime.Encoder, mutateFn PatchFn) []*Patch {
var patches []*Patch
for _, info := range infos {
patch := &Patch{Info: info}
......
......@@ -26,6 +26,7 @@ import (
"github.com/spf13/cobra"
"k8s.io/api/core/v1"
meta "k8s.io/apimachinery/pkg/api/meta"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/types"
utilerrors "k8s.io/apimachinery/pkg/util/errors"
......@@ -323,12 +324,53 @@ func (o *EnvOptions) RunEnv() error {
if err != nil {
return err
}
patches := CalculatePatches(infos, scheme.DefaultJSONEncoder(), func(info *resource.Info) ([]byte, error) {
_, err := o.updatePodSpecForObject(info.Object, func(spec *v1.PodSpec) error {
patches := CalculatePatches(infos, scheme.DefaultJSONEncoder(), func(obj runtime.Object) ([]byte, error) {
_, err := o.updatePodSpecForObject(obj, func(spec *v1.PodSpec) error {
resolutionErrorsEncountered := false
containers, _ := selectContainers(spec.Containers, o.ContainerSelector)
objName, err := meta.NewAccessor().Name(obj)
if err != nil {
return err
}
gvks, _, err := scheme.Scheme.ObjectKinds(obj)
if err != nil {
return err
}
objKind := obj.GetObjectKind().GroupVersionKind().Kind
if len(objKind) == 0 {
for _, gvk := range gvks {
if len(gvk.Kind) == 0 {
continue
}
if len(gvk.Version) == 0 || gvk.Version == runtime.APIVersionInternal {
continue
}
objKind = gvk.Kind
break
}
}
if len(containers) == 0 {
fmt.Fprintf(o.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
}
for _, c := range containers {
......@@ -343,7 +385,7 @@ func (o *EnvOptions) RunEnv() error {
resolveErrors := map[string][]string{}
store := envutil.NewResourceStore()
fmt.Fprintf(o.Out, "# %s %s, container %s\n", info.Mapping.Resource, info.Name, c.Name)
fmt.Fprintf(o.Out, "# %s %s, container %s\n", objKind, objName, c.Name)
for _, env := range c.Env {
// Print the simple value
if env.ValueFrom == nil {
......@@ -357,7 +399,7 @@ func (o *EnvOptions) RunEnv() error {
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
if err == nil {
fmt.Fprintf(o.Out, "%s=%s\n", env.Name, value)
......@@ -390,7 +432,7 @@ func (o *EnvOptions) RunEnv() error {
})
if err == nil {
return runtime.Encode(scheme.DefaultJSONEncoder(), info.Object)
return runtime.Encode(scheme.DefaultJSONEncoder(), obj)
}
return nil, err
})
......
......@@ -210,9 +210,9 @@ func (o *SetImageOptions) Validate() error {
func (o *SetImageOptions) Run() 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
_, err := o.UpdatePodSpecForObject(info.Object, func(spec *v1.PodSpec) error {
_, err := o.UpdatePodSpecForObject(obj, func(spec *v1.PodSpec) error {
for name, image := range o.ContainerImages {
var (
containerFound bool
......@@ -255,11 +255,11 @@ func (o *SetImageOptions) Run() error {
return nil, nil
}
// 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)
}
return runtime.Encode(scheme.DefaultJSONEncoder(), info.Object)
return runtime.Encode(scheme.DefaultJSONEncoder(), obj)
})
for _, patch := range patches {
......
......@@ -222,9 +222,9 @@ func (o *SetResourcesOptions) Validate() error {
func (o *SetResourcesOptions) Run() 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
_, err := o.UpdatePodSpecForObject(info.Object, func(spec *v1.PodSpec) error {
_, err := o.UpdatePodSpecForObject(obj, func(spec *v1.PodSpec) error {
containers, _ := selectContainers(spec.Containers, o.ContainerSelector)
if len(containers) != 0 {
for i := range containers {
......@@ -255,11 +255,11 @@ func (o *SetResourcesOptions) Run() error {
return nil, nil
}
// 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)
}
return runtime.Encode(scheme.DefaultJSONEncoder(), info.Object)
return runtime.Encode(scheme.DefaultJSONEncoder(), obj)
})
for _, patch := range patches {
......
......@@ -201,7 +201,7 @@ func (o *SetSelectorOptions) RunSelector() error {
return r.Visit(func(info *resource.Info, err error) error {
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)
if selectErr != nil {
return nil, selectErr
......
......@@ -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.
func (o *SetServiceAccountOptions) Run() error {
patchErrs := []error{}
patchFn := func(info *resource.Info) ([]byte, error) {
_, err := o.updatePodSpecForObject(info.Object, func(podSpec *v1.PodSpec) error {
patchFn := func(obj runtime.Object) ([]byte, error) {
_, err := o.updatePodSpecForObject(obj, func(podSpec *v1.PodSpec) error {
podSpec.ServiceAccountName = o.serviceAccountName
return nil
})
......@@ -182,11 +182,11 @@ func (o *SetServiceAccountOptions) Run() error {
return nil, err
}
// 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)
}
return runtime.Encode(scheme.DefaultJSONEncoder(), info.Object)
return runtime.Encode(scheme.DefaultJSONEncoder(), obj)
}
patches := CalculatePatches(o.infos, scheme.DefaultJSONEncoder(), patchFn)
......
......@@ -194,7 +194,7 @@ func (o *SubjectOptions) Validate() 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{}
for _, user := range sets.NewString(o.Users...).List() {
subject := rbacv1.Subject{
......@@ -227,10 +227,10 @@ func (o *SubjectOptions) Run(fn updateSubjects) error {
subjects = append(subjects, subject)
}
transformed, err := updateSubjectForObject(info.Object, subjects, fn)
transformed, err := updateSubjectForObject(obj, subjects, fn)
if transformed && err == nil {
// TODO: switch UpdatePodSpecForObject to work on v1.PodSpec
return runtime.Encode(scheme.DefaultJSONEncoder(), info.Object)
return runtime.Encode(scheme.DefaultJSONEncoder(), obj)
}
return nil, err
})
......
......@@ -16,7 +16,6 @@ go_library(
visibility = ["//build/visible_to:pkg_kubectl_cmd_util_CONSUMERS"],
deps = [
"//pkg/api/legacyscheme:go_default_library",
"//pkg/apis/apps:go_default_library",
"//pkg/apis/core:go_default_library",
"//pkg/apis/extensions:go_default_library",
"//pkg/client/clientset_generated/internalclientset:go_default_library",
......
......@@ -86,23 +86,12 @@ type ClientAccessFactory interface {
// SuggestedPodTemplateResources returns a list of resource types that declare a pod template
SuggestedPodTemplateResources() []schema.GroupResource
// Pauser marks the object in the info as paused. Currently supported only for Deployments.
// Returns the patched object in bytes and any error that occurred during the encoding or
// in case the object is already paused.
Pauser(info *resource.Info) ([]byte, error)
// Resumer resumes a paused object inside the info. Currently supported only for Deployments.
// Returns the patched object in bytes and any error that occurred during the encoding or
// in case the object is already resumed.
Resumer(info *resource.Info) ([]byte, error)
// Returns the default namespace to use in cases where no
// other namespace is specified and whether the namespace was
// overridden.
DefaultNamespace() (string, bool, error)
// Generators returns the generators for the provided command
Generators(cmdName string) map[string]kubectl.Generator
// Check whether the kind of resources could be exposed
CanBeExposed(kind schema.GroupKind) error
}
// ObjectMappingFactory holds the second level of factory methods. These functions depend upon ClientAccessFactory methods.
......@@ -116,9 +105,6 @@ type ObjectMappingFactory interface {
// Returns a Describer for displaying the specified RESTMapping type or an error.
Describer(mapping *meta.RESTMapping) (printers.Describer, error)
// Returns a Rollbacker for changing the rollback version of the specified RESTMapping type or an error
Rollbacker(mapping *meta.RESTMapping) (kubectl.Rollbacker, error)
// Returns a schema that can validate objects stored on disk.
Validator(validate bool) (validation.Schema, error)
// OpenAPISchema returns the schema openapi schema definition
......
......@@ -19,7 +19,6 @@ limitations under the License.
package util
import (
"errors"
"fmt"
"io"
......@@ -41,7 +40,6 @@ import (
restclient "k8s.io/client-go/rest"
"k8s.io/client-go/tools/clientcmd"
"k8s.io/kubernetes/pkg/api/legacyscheme"
"k8s.io/kubernetes/pkg/apis/apps"
api "k8s.io/kubernetes/pkg/apis/core"
"k8s.io/kubernetes/pkg/apis/extensions"
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
......@@ -182,32 +180,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) {
return f.clientGetter.ToRawKubeConfigLoader().Namespace()
}
......@@ -422,17 +394,6 @@ func (f *ring0Factory) Generators(cmdName string) map[string]kubectl.Generator {
return DefaultGenerators(cmdName)
}
func (f *ring0Factory) CanBeExposed(kind schema.GroupKind) error {
switch kind {
case api.Kind("ReplicationController"), api.Kind("Service"), api.Kind("Pod"),
extensions.Kind("Deployment"), apps.Kind("Deployment"), extensions.Kind("ReplicaSet"), apps.Kind("ReplicaSet"):
// nothing to do here
default:
return fmt.Errorf("cannot expose a %s", kind)
}
return nil
}
// this method exists to help us find the points still relying on internal types.
func InternalVersionDecoder() runtime.Decoder {
return legacyscheme.Codecs.UniversalDecoder()
......
......@@ -26,7 +26,6 @@ import (
"k8s.io/client-go/dynamic"
restclient "k8s.io/client-go/rest"
api "k8s.io/kubernetes/pkg/apis/core"
"k8s.io/kubernetes/pkg/kubectl"
"k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi"
openapivalidation "k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi/validation"
"k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource"
......@@ -132,14 +131,6 @@ func genericDescriber(clientAccessFactory ClientAccessFactory, mapping *meta.RES
return printersinternal.GenericDescriberFor(mapping, dynamicClient, eventsClient), nil
}
func (f *ring1Factory) Rollbacker(mapping *meta.RESTMapping) (kubectl.Rollbacker, error) {
external, err := f.clientAccessFactory.KubernetesClientSet()
if err != nil {
return nil, err
}
return kubectl.RollbackerFor(mapping.GroupVersionKind.GroupKind(), external)
}
func (f *ring1Factory) Validator(validate bool) (validation.Schema, error) {
if !validate {
return validation.NullSchema{}, nil
......
......@@ -21,7 +21,6 @@ import (
"testing"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/util/sets"
api "k8s.io/kubernetes/pkg/apis/core"
"k8s.io/kubernetes/pkg/kubectl"
......@@ -66,33 +65,6 @@ func TestProtocolsForObject(t *testing.T) {
}
}
func TestCanBeExposed(t *testing.T) {
factory := NewFactory(genericclioptions.NewTestConfigFlags())
tests := []struct {
kind schema.GroupKind
expectErr bool
}{
{
kind: api.Kind("ReplicationController"),
expectErr: false,
},
{
kind: api.Kind("Node"),
expectErr: true,
},
}
for _, test := range tests {
err := factory.CanBeExposed(test.kind)
if test.expectErr && err == nil {
t.Error("unexpected non-error")
}
if !test.expectErr && err != nil {
t.Errorf("unexpected error: %v", err)
}
}
}
func TestMakePortsString(t *testing.T) {
tests := []struct {
ports []api.ServicePort
......
......@@ -5,17 +5,22 @@ go_library(
srcs = [
"attachablepodforobject.go",
"canbeautoscaled.go",
"canbeexposed.go",
"helpers.go",
"historyviewer.go",
"interface.go",
"logsforobject.go",
"objectpauser.go",
"objectresumer.go",
"portsforobject.go",
"rollbacker.go",
"statusviewer.go",
"updatepodspec.go",
],
importpath = "k8s.io/kubernetes/pkg/kubectl/polymorphichelpers",
visibility = ["//visibility:public"],
deps = [
"//pkg/api/legacyscheme:go_default_library",
"//pkg/apis/apps:go_default_library",
"//pkg/apis/batch:go_default_library",
"//pkg/apis/core:go_default_library",
......@@ -36,6 +41,7 @@ go_library(
"//vendor/k8s.io/api/extensions/v1beta1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/labels:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
......@@ -48,6 +54,7 @@ go_library(
go_test(
name = "go_default_test",
srcs = [
"canbeexposed_test.go",
"helpers_test.go",
"logsforobject_test.go",
"portsforobject_test.go",
......
/*
Copyright 2018 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package polymorphichelpers
import (
"fmt"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/kubernetes/pkg/apis/apps"
api "k8s.io/kubernetes/pkg/apis/core"
"k8s.io/kubernetes/pkg/apis/extensions"
)
// Check whether the kind of resources could be exposed
func canBeExposed(kind schema.GroupKind) error {
switch kind {
case api.Kind("ReplicationController"), api.Kind("Service"), api.Kind("Pod"),
extensions.Kind("Deployment"), apps.Kind("Deployment"), extensions.Kind("ReplicaSet"), apps.Kind("ReplicaSet"):
// nothing to do here
default:
return fmt.Errorf("cannot expose a %s", kind)
}
return nil
}
/*
Copyright 2018 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package polymorphichelpers
import (
"testing"
"k8s.io/apimachinery/pkg/runtime/schema"
api "k8s.io/kubernetes/pkg/apis/core"
)
func TestCanBeExposed(t *testing.T) {
tests := []struct {
kind schema.GroupKind
expectErr bool
}{
{
kind: api.Kind("ReplicationController"),
expectErr: false,
},
{
kind: api.Kind("Node"),
expectErr: true,
},
}
for _, test := range tests {
err := canBeExposed(test.kind)
if test.expectErr && err == nil {
t.Error("unexpected non-error")
}
if !test.expectErr && err != nil {
t.Errorf("unexpected error: %v", err)
}
}
}
......@@ -71,3 +71,31 @@ type CanBeAutoscaledFunc func(kind schema.GroupKind) error
// CanBeAutoscaledFn gives a way to easily override the function for unit testing if needed
var CanBeAutoscaledFn CanBeAutoscaledFunc = canBeAutoscaled
// CanBeExposedFunc is a function type that can tell you whether a given GroupKind is capable of being exposed
type CanBeExposedFunc func(kind schema.GroupKind) error
// CanBeExposedFn gives a way to easily override the function for unit testing if needed
var CanBeExposedFn CanBeExposedFunc = canBeExposed
// ObjectPauserFunc is a function type that marks the object in a given info as paused.
type ObjectPauserFunc func(runtime.Object) ([]byte, error)
// ObjectPauserFn gives a way to easily override the function for unit testing if needed.
// Returns the patched object in bytes and any error that occurred during the encoding or
// in case the object is already paused.
var ObjectPauserFn ObjectPauserFunc = defaultObjectPauser
// ObjectResumerFunc is a function type that marks the object in a given info as resumed.
type ObjectResumerFunc func(runtime.Object) ([]byte, error)
// ObjectResumerFn gives a way to easily override the function for unit testing if needed.
// Returns the patched object in bytes and any error that occurred during the encoding or
// in case the object is already resumed.
var ObjectResumerFn ObjectResumerFunc = defaultObjectResumer
// RollbackerFunc gives a way to change the rollback version of the specified RESTMapping type
type RollbackerFunc func(restClientGetter genericclioptions.RESTClientGetter, mapping *meta.RESTMapping) (kubectl.Rollbacker, error)
// RollbackerFn gives a way to easily override the function for unit testing if needed
var RollbackerFn RollbackerFunc = rollbacker
/*
Copyright 2018 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES 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}
}
/*
Copyright 2018 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES 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")
}
}
/*
Copyright 2018 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package polymorphichelpers
import (
"k8s.io/apimachinery/pkg/api/meta"
"k8s.io/client-go/kubernetes"
"k8s.io/kubernetes/pkg/kubectl"
"k8s.io/kubernetes/pkg/kubectl/genericclioptions"
)
// Returns a Rollbacker for changing the rollback version of the specified RESTMapping type or an error
func rollbacker(restClientGetter genericclioptions.RESTClientGetter, mapping *meta.RESTMapping) (kubectl.Rollbacker, error) {
clientConfig, err := restClientGetter.ToRESTConfig()
if err != nil {
return nil, err
}
external, err := kubernetes.NewForConfig(clientConfig)
if err != nil {
return nil, err
}
return kubectl.RollbackerFor(mapping.GroupVersionKind.GroupKind(), external)
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment