mirror of
https://github.com/ceph/ceph-csi.git
synced 2025-06-14 02:43:36 +00:00
vendor updates
This commit is contained in:
7
vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/BUILD
generated
vendored
7
vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/BUILD
generated
vendored
@ -30,7 +30,6 @@ go_library(
|
||||
"//pkg/apis/extensions:go_default_library",
|
||||
"//pkg/client/clientset_generated/internalclientset:go_default_library",
|
||||
"//pkg/client/clientset_generated/internalclientset/typed/core/internalversion:go_default_library",
|
||||
"//pkg/client/unversioned:go_default_library",
|
||||
"//pkg/controller:go_default_library",
|
||||
"//pkg/kubectl:go_default_library",
|
||||
"//pkg/kubectl/categories:go_default_library",
|
||||
@ -40,6 +39,7 @@ go_library(
|
||||
"//pkg/kubectl/plugins:go_default_library",
|
||||
"//pkg/kubectl/resource:go_default_library",
|
||||
"//pkg/kubectl/scheme:go_default_library",
|
||||
"//pkg/kubectl/util/transport:go_default_library",
|
||||
"//pkg/kubectl/validation:go_default_library",
|
||||
"//pkg/printers:go_default_library",
|
||||
"//pkg/printers/internalversion:go_default_library",
|
||||
@ -53,6 +53,7 @@ go_library(
|
||||
"//vendor/k8s.io/api/apps/v1beta1:go_default_library",
|
||||
"//vendor/k8s.io/api/apps/v1beta2:go_default_library",
|
||||
"//vendor/k8s.io/api/batch/v1:go_default_library",
|
||||
"//vendor/k8s.io/api/batch/v1beta1:go_default_library",
|
||||
"//vendor/k8s.io/api/batch/v2alpha1:go_default_library",
|
||||
"//vendor/k8s.io/api/core/v1:go_default_library",
|
||||
"//vendor/k8s.io/api/extensions/v1beta1:go_default_library",
|
||||
@ -76,6 +77,7 @@ go_library(
|
||||
"//vendor/k8s.io/client-go/dynamic:go_default_library",
|
||||
"//vendor/k8s.io/client-go/kubernetes:go_default_library",
|
||||
"//vendor/k8s.io/client-go/rest:go_default_library",
|
||||
"//vendor/k8s.io/client-go/scale:go_default_library",
|
||||
"//vendor/k8s.io/client-go/tools/clientcmd:go_default_library",
|
||||
"//vendor/k8s.io/client-go/util/homedir:go_default_library",
|
||||
"//vendor/k8s.io/utils/exec:go_default_library",
|
||||
@ -94,8 +96,7 @@ go_test(
|
||||
data = [
|
||||
"//api/swagger-spec",
|
||||
],
|
||||
importpath = "k8s.io/kubernetes/pkg/kubectl/cmd/util",
|
||||
library = ":go_default_library",
|
||||
embed = [":go_default_library"],
|
||||
visibility = [
|
||||
"//build/visible_to:COMMON_testing",
|
||||
],
|
||||
|
20
vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/clientcache.go
generated
vendored
20
vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/clientcache.go
generated
vendored
@ -24,8 +24,8 @@ import (
|
||||
"k8s.io/client-go/kubernetes"
|
||||
restclient "k8s.io/client-go/rest"
|
||||
"k8s.io/client-go/tools/clientcmd"
|
||||
"k8s.io/kubernetes/pkg/api/legacyscheme"
|
||||
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
|
||||
oldclient "k8s.io/kubernetes/pkg/client/unversioned"
|
||||
"k8s.io/kubernetes/pkg/version"
|
||||
)
|
||||
|
||||
@ -150,7 +150,7 @@ func (c *ClientCache) clientConfigForVersion(requiredVersion *schema.GroupVersio
|
||||
}
|
||||
|
||||
// TODO this isn't what we want. Each clientset should be setting defaults as it sees fit.
|
||||
oldclient.SetKubernetesDefaults(&config)
|
||||
setKubernetesDefaults(&config)
|
||||
|
||||
if requiredVersion != nil {
|
||||
c.configs[*requiredVersion] = copyConfig(&config)
|
||||
@ -165,6 +165,22 @@ func (c *ClientCache) clientConfigForVersion(requiredVersion *schema.GroupVersio
|
||||
return copyConfig(&config), nil
|
||||
}
|
||||
|
||||
// setKubernetesDefaults sets default values on the provided client config for accessing the
|
||||
// Kubernetes API or returns an error if any of the defaults are impossible or invalid.
|
||||
func setKubernetesDefaults(config *restclient.Config) error {
|
||||
if config.APIPath == "" {
|
||||
config.APIPath = "/api"
|
||||
}
|
||||
// TODO chase down uses and tolerate nil
|
||||
if config.GroupVersion == nil {
|
||||
config.GroupVersion = &schema.GroupVersion{}
|
||||
}
|
||||
if config.NegotiatedSerializer == nil {
|
||||
config.NegotiatedSerializer = legacyscheme.Codecs
|
||||
}
|
||||
return restclient.SetKubernetesDefaults(config)
|
||||
}
|
||||
|
||||
func copyConfig(in *restclient.Config) *restclient.Config {
|
||||
configCopy := *in
|
||||
copyGroupVersion := *configCopy.GroupVersion
|
||||
|
3
vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/editor/BUILD
generated
vendored
3
vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/editor/BUILD
generated
vendored
@ -42,8 +42,7 @@ go_library(
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["editor_test.go"],
|
||||
importpath = "k8s.io/kubernetes/pkg/kubectl/cmd/util/editor",
|
||||
library = ":go_default_library",
|
||||
embed = [":go_default_library"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
|
27
vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/editor/editoptions.go
generated
vendored
27
vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/editor/editoptions.go
generated
vendored
@ -60,10 +60,8 @@ type EditOptions struct {
|
||||
|
||||
cmdutil.ValidateOptions
|
||||
|
||||
Mapper meta.RESTMapper
|
||||
ResourceMapper *resource.Mapper
|
||||
OriginalResult *resource.Result
|
||||
Encoder runtime.Encoder
|
||||
|
||||
EditMode EditMode
|
||||
|
||||
@ -107,7 +105,6 @@ func (o *EditOptions) Complete(f cmdutil.Factory, out, errOut io.Writer, args []
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
mapper, _ := f.Object()
|
||||
b := f.NewBuilder().
|
||||
Unstructured()
|
||||
if o.EditMode == NormalEditMode || o.EditMode == ApplyEditMode {
|
||||
@ -138,9 +135,7 @@ func (o *EditOptions) Complete(f cmdutil.Factory, out, errOut io.Writer, args []
|
||||
Do()
|
||||
}
|
||||
|
||||
o.Mapper = mapper
|
||||
o.CmdNamespace = cmdNamespace
|
||||
o.Encoder = f.JSONEncoder()
|
||||
o.f = f
|
||||
|
||||
// Set up writer
|
||||
@ -397,25 +392,25 @@ func (o *EditOptions) visitToApplyEditPatch(originalInfos []*resource.Info, patc
|
||||
return fmt.Errorf("no original object found for %#v", info.Object)
|
||||
}
|
||||
|
||||
originalJS, err := encodeToJson(o.Encoder, originalInfo.Object)
|
||||
originalJS, err := encodeToJson(cmdutil.InternalVersionJSONEncoder(), originalInfo.Object)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
editedJS, err := encodeToJson(o.Encoder, info.Object)
|
||||
editedJS, err := encodeToJson(cmdutil.InternalVersionJSONEncoder(), info.Object)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if reflect.DeepEqual(originalJS, editedJS) {
|
||||
o.f.PrintSuccess(o.Mapper, false, o.Out, info.Mapping.Resource, info.Name, false, "skipped")
|
||||
cmdutil.PrintSuccess(false, o.Out, info.Object, false, "skipped")
|
||||
return nil
|
||||
} else {
|
||||
err := o.annotationPatch(info)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
o.f.PrintSuccess(o.Mapper, false, o.Out, info.Mapping.Resource, info.Name, false, "edited")
|
||||
cmdutil.PrintSuccess(false, o.Out, info.Object, false, "edited")
|
||||
return nil
|
||||
}
|
||||
})
|
||||
@ -423,7 +418,7 @@ func (o *EditOptions) visitToApplyEditPatch(originalInfos []*resource.Info, patc
|
||||
}
|
||||
|
||||
func (o *EditOptions) annotationPatch(update *resource.Info) error {
|
||||
patch, _, patchType, err := GetApplyPatch(update.Object, o.Encoder)
|
||||
patch, _, patchType, err := GetApplyPatch(update.Object, cmdutil.InternalVersionJSONEncoder())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -522,19 +517,19 @@ func (o *EditOptions) visitToPatch(originalInfos []*resource.Info, patchVisitor
|
||||
return fmt.Errorf("no original object found for %#v", info.Object)
|
||||
}
|
||||
|
||||
originalJS, err := encodeToJson(o.Encoder, originalInfo.Object)
|
||||
originalJS, err := encodeToJson(cmdutil.InternalVersionJSONEncoder(), originalInfo.Object)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
editedJS, err := encodeToJson(o.Encoder, info.Object)
|
||||
editedJS, err := encodeToJson(cmdutil.InternalVersionJSONEncoder(), info.Object)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if reflect.DeepEqual(originalJS, editedJS) {
|
||||
// no edit, so just skip it.
|
||||
o.f.PrintSuccess(o.Mapper, false, o.Out, info.Mapping.Resource, info.Name, false, "skipped")
|
||||
cmdutil.PrintSuccess(false, o.Out, info.Object, false, "skipped")
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -588,7 +583,7 @@ func (o *EditOptions) visitToPatch(originalInfos []*resource.Info, patchVisitor
|
||||
return nil
|
||||
}
|
||||
info.Refresh(patched, true)
|
||||
o.f.PrintSuccess(o.Mapper, false, o.Out, info.Mapping.Resource, info.Name, false, "edited")
|
||||
cmdutil.PrintSuccess(false, o.Out, info.Object, false, "edited")
|
||||
return nil
|
||||
})
|
||||
return err
|
||||
@ -599,7 +594,7 @@ func (o *EditOptions) visitToCreate(createVisitor resource.Visitor) error {
|
||||
if err := resource.CreateAndRefresh(info); err != nil {
|
||||
return err
|
||||
}
|
||||
o.f.PrintSuccess(o.Mapper, false, o.Out, info.Mapping.Resource, info.Name, false, "created")
|
||||
cmdutil.PrintSuccess(false, o.Out, info.Object, false, "created")
|
||||
return nil
|
||||
})
|
||||
return err
|
||||
@ -610,7 +605,7 @@ func (o *EditOptions) visitAnnotation(annotationVisitor resource.Visitor) error
|
||||
err := annotationVisitor.Visit(func(info *resource.Info, incomingErr error) error {
|
||||
// put configuration annotation in "updates"
|
||||
if o.ApplyAnnotation {
|
||||
if err := kubectl.CreateOrUpdateAnnotation(true, info, o.Encoder); err != nil {
|
||||
if err := kubectl.CreateOrUpdateAnnotation(true, info, cmdutil.InternalVersionJSONEncoder()); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
3
vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/env/BUILD
generated
vendored
3
vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/env/BUILD
generated
vendored
@ -37,6 +37,5 @@ filegroup(
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["env_parse_test.go"],
|
||||
importpath = "k8s.io/kubernetes/pkg/kubectl/cmd/util/env",
|
||||
library = ":go_default_library",
|
||||
embed = [":go_default_library"],
|
||||
)
|
||||
|
4
vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/env/env_resolve.go
generated
vendored
4
vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/env/env_resolve.go
generated
vendored
@ -46,7 +46,7 @@ func getSecretRefValue(client kubernetes.Interface, namespace string, store *Res
|
||||
secret, ok := store.SecretStore[secretSelector.Name]
|
||||
if !ok {
|
||||
var err error
|
||||
secret, err = client.Core().Secrets(namespace).Get(secretSelector.Name, metav1.GetOptions{})
|
||||
secret, err = client.CoreV1().Secrets(namespace).Get(secretSelector.Name, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
@ -64,7 +64,7 @@ func getConfigMapRefValue(client kubernetes.Interface, namespace string, store *
|
||||
configMap, ok := store.ConfigMapStore[configMapSelector.Name]
|
||||
if !ok {
|
||||
var err error
|
||||
configMap, err = client.Core().ConfigMaps(namespace).Get(configMapSelector.Name, metav1.GetOptions{})
|
||||
configMap, err = client.CoreV1().ConfigMaps(namespace).Get(configMapSelector.Name, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
62
vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/factory.go
generated
vendored
62
vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/factory.go
generated
vendored
@ -18,7 +18,6 @@ package util
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
@ -60,10 +59,10 @@ var (
|
||||
|
||||
// Factory provides abstractions that allow the Kubectl command to be extended across multiple types
|
||||
// of resources and different API sets.
|
||||
// The rings are here for a reason. In order for composers to be able to provide alternative factory implementations
|
||||
// The rings are here for a reason. In order for composers to be able to provide alternative factory implementations
|
||||
// they need to provide low level pieces of *certain* functions so that when the factory calls back into itself
|
||||
// it uses the custom version of the function. Rather than try to enumerate everything that someone would want to override
|
||||
// we split the factory into rings, where each ring can depend on methods an earlier ring, but cannot depend
|
||||
// it uses the custom version of the function. Rather than try to enumerate everything that someone would want to override
|
||||
// we split the factory into rings, where each ring can depend on methods in an earlier ring, but cannot depend
|
||||
// upon peer methods in its own ring.
|
||||
// TODO: make the functions interfaces
|
||||
// TODO: pass the various interfaces on the factory directly into the command constructors (so the
|
||||
@ -103,18 +102,6 @@ type ClientAccessFactory interface {
|
||||
// just directions to the server. People use this to build RESTMappers on top of
|
||||
BareClientConfig() (*restclient.Config, error)
|
||||
|
||||
// TODO remove. This should be rolled into `ClientSet`
|
||||
ClientSetForVersion(requiredVersion *schema.GroupVersion) (internalclientset.Interface, error)
|
||||
// TODO remove. This should be rolled into `ClientConfig`
|
||||
ClientConfigForVersion(requiredVersion *schema.GroupVersion) (*restclient.Config, error)
|
||||
|
||||
// Returns interfaces for decoding objects - if toInternal is set, decoded objects will be converted
|
||||
// into their internal form (if possible). Eventually the internal form will be removed as an option,
|
||||
// and only versioned objects will be returned.
|
||||
Decoder(toInternal bool) runtime.Decoder
|
||||
// Returns an encoder capable of encoding a provided object into JSON in the default desired version.
|
||||
JSONEncoder() runtime.Encoder
|
||||
|
||||
// UpdatePodSpecForObject will call the provided function on the pod spec this object supports,
|
||||
// return false if no pod spec is supported, or return an error.
|
||||
UpdatePodSpecForObject(obj runtime.Object, fn func(*v1.PodSpec) error) (bool, error)
|
||||
@ -146,14 +133,12 @@ type ClientAccessFactory interface {
|
||||
// SuggestedPodTemplateResources returns a list of resource types that declare a pod template
|
||||
SuggestedPodTemplateResources() []schema.GroupResource
|
||||
|
||||
// Returns a Printer for formatting objects of the given type or an error.
|
||||
Printer(mapping *meta.RESTMapping, options printers.PrintOptions) (printers.ResourcePrinter, error)
|
||||
// Pauser marks the object in the info as paused. Currently supported only for Deployments.
|
||||
// Returns the patched object in bytes and any error that occured during the encoding or
|
||||
// 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 occured during the encoding or
|
||||
// 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)
|
||||
|
||||
@ -177,12 +162,9 @@ type ClientAccessFactory interface {
|
||||
// can range over in order to determine if the user has specified an editor
|
||||
// of their choice.
|
||||
EditorEnvs() []string
|
||||
|
||||
// PrintObjectSpecificMessage prints object-specific messages on the provided writer
|
||||
PrintObjectSpecificMessage(obj runtime.Object, out io.Writer)
|
||||
}
|
||||
|
||||
// ObjectMappingFactory holds the second level of factory methods. These functions depend upon ClientAccessFactory methods.
|
||||
// ObjectMappingFactory holds the second level of factory methods. These functions depend upon ClientAccessFactory methods.
|
||||
// Generally they provide object typing and functions that build requests based on the negotiated clients.
|
||||
type ObjectMappingFactory interface {
|
||||
// Returns interfaces for dealing with arbitrary runtime.Objects.
|
||||
@ -220,31 +202,13 @@ type ObjectMappingFactory interface {
|
||||
|
||||
// Returns a schema that can validate objects stored on disk.
|
||||
Validator(validate bool) (validation.Schema, error)
|
||||
// OpenAPISchema returns the schema openapi schema definiton
|
||||
// OpenAPISchema returns the schema openapi schema definition
|
||||
OpenAPISchema() (openapi.Resources, error)
|
||||
}
|
||||
|
||||
// BuilderFactory holds the second level of factory methods. These functions depend upon ObjectMappingFactory and ClientAccessFactory methods.
|
||||
// BuilderFactory holds the third level of factory methods. These functions depend upon ObjectMappingFactory and ClientAccessFactory methods.
|
||||
// Generally they depend upon client mapper functions
|
||||
type BuilderFactory interface {
|
||||
// PrinterForCommand returns the default printer for the command. It requires that certain options
|
||||
// are declared on the command (see AddPrinterFlags). Returns a printer, or an error if a printer
|
||||
// could not be found.
|
||||
PrinterForOptions(options *printers.PrintOptions) (printers.ResourcePrinter, error)
|
||||
// PrinterForMapping returns a printer suitable for displaying the provided resource type.
|
||||
// Requires that printer flags have been added to cmd (see AddPrinterFlags).
|
||||
// Returns a printer, true if the printer is generic (is not internal), or
|
||||
// an error if a printer could not be found.
|
||||
PrinterForMapping(options *printers.PrintOptions, mapping *meta.RESTMapping) (printers.ResourcePrinter, error)
|
||||
// PrintObject prints an api object given command line flags to modify the output format
|
||||
PrintObject(cmd *cobra.Command, isLocal bool, mapper meta.RESTMapper, obj runtime.Object, out io.Writer) error
|
||||
// PrintResourceInfoForCommand receives a *cobra.Command and a *resource.Info and
|
||||
// attempts to print an info object based on the specified output format. If the
|
||||
// object passed is non-generic, it attempts to print the object using a HumanReadablePrinter.
|
||||
// Requires that printer flags have been added to cmd (see AddPrinterFlags).
|
||||
PrintResourceInfoForCommand(cmd *cobra.Command, info *resource.Info, out io.Writer) error
|
||||
// PrintSuccess prints message after finishing mutating operations
|
||||
PrintSuccess(mapper meta.RESTMapper, shortOutput bool, out io.Writer, resource, name string, dryRun bool, operation string)
|
||||
// NewBuilder returns an object that assists in loading objects from both disk and the server
|
||||
// and which implements the common patterns for CLI interactions with generic resources.
|
||||
NewBuilder() *resource.Builder
|
||||
@ -254,16 +218,6 @@ type BuilderFactory interface {
|
||||
PluginRunner() plugins.PluginRunner
|
||||
}
|
||||
|
||||
func getGroupVersionKinds(gvks []schema.GroupVersionKind, group string) []schema.GroupVersionKind {
|
||||
result := []schema.GroupVersionKind{}
|
||||
for ix := range gvks {
|
||||
if gvks[ix].Group == group {
|
||||
result = append(result, gvks[ix])
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
type factory struct {
|
||||
ClientAccessFactory
|
||||
ObjectMappingFactory
|
||||
|
108
vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/factory_builder.go
generated
vendored
108
vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/factory_builder.go
generated
vendored
@ -19,18 +19,11 @@ limitations under the License.
|
||||
package util
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"k8s.io/apimachinery/pkg/api/meta"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/kubernetes/pkg/kubectl/plugins"
|
||||
"k8s.io/kubernetes/pkg/kubectl/resource"
|
||||
"k8s.io/kubernetes/pkg/printers"
|
||||
)
|
||||
|
||||
type ring2Factory struct {
|
||||
@ -47,105 +40,6 @@ func NewBuilderFactory(clientAccessFactory ClientAccessFactory, objectMappingFac
|
||||
return f
|
||||
}
|
||||
|
||||
func (f *ring2Factory) PrinterForOptions(options *printers.PrintOptions) (printers.ResourcePrinter, error) {
|
||||
var mapper meta.RESTMapper
|
||||
var typer runtime.ObjectTyper
|
||||
|
||||
mapper, typer = f.objectMappingFactory.Object()
|
||||
|
||||
// TODO: used by the custom column implementation and the name implementation, break this dependency
|
||||
decoders := []runtime.Decoder{f.clientAccessFactory.Decoder(true), unstructured.UnstructuredJSONScheme}
|
||||
encoder := f.clientAccessFactory.JSONEncoder()
|
||||
return PrinterForOptions(mapper, typer, encoder, decoders, options)
|
||||
}
|
||||
|
||||
func (f *ring2Factory) PrinterForMapping(options *printers.PrintOptions, mapping *meta.RESTMapping) (printers.ResourcePrinter, error) {
|
||||
printer, err := f.PrinterForOptions(options)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Make sure we output versioned data for generic printers
|
||||
if printer.IsGeneric() {
|
||||
if mapping == nil {
|
||||
return nil, fmt.Errorf("no serialization format found")
|
||||
}
|
||||
version := mapping.GroupVersionKind.GroupVersion()
|
||||
if version.Empty() {
|
||||
return nil, fmt.Errorf("no serialization format found")
|
||||
}
|
||||
|
||||
printer = printers.NewVersionedPrinter(printer, mapping.ObjectConvertor, version, mapping.GroupVersionKind.GroupVersion())
|
||||
|
||||
}
|
||||
|
||||
return printer, nil
|
||||
}
|
||||
|
||||
func (f *ring2Factory) PrintSuccess(mapper meta.RESTMapper, shortOutput bool, out io.Writer, resource, name string, dryRun bool, operation string) {
|
||||
resource, _ = mapper.ResourceSingularizer(resource)
|
||||
dryRunMsg := ""
|
||||
if dryRun {
|
||||
dryRunMsg = " (dry run)"
|
||||
}
|
||||
if shortOutput {
|
||||
// -o name: prints resource/name
|
||||
if len(resource) > 0 {
|
||||
fmt.Fprintf(out, "%s/%s\n", resource, name)
|
||||
} else {
|
||||
fmt.Fprintf(out, "%s\n", name)
|
||||
}
|
||||
} else {
|
||||
// understandable output by default
|
||||
if len(resource) > 0 {
|
||||
fmt.Fprintf(out, "%s \"%s\" %s%s\n", resource, name, operation, dryRunMsg)
|
||||
} else {
|
||||
fmt.Fprintf(out, "\"%s\" %s%s\n", name, operation, dryRunMsg)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (f *ring2Factory) PrintObject(cmd *cobra.Command, isLocal bool, mapper meta.RESTMapper, obj runtime.Object, out io.Writer) error {
|
||||
// try to get a typed object
|
||||
_, typer := f.objectMappingFactory.Object()
|
||||
gvks, _, err := typer.ObjectKinds(obj)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Prefer the existing external version if specified
|
||||
var preferredVersion []string
|
||||
if gvks[0].Version != "" && gvks[0].Version != runtime.APIVersionInternal {
|
||||
preferredVersion = []string{gvks[0].Version}
|
||||
}
|
||||
|
||||
mapping, err := mapper.RESTMapping(gvks[0].GroupKind(), preferredVersion...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
printer, err := f.PrinterForMapping(ExtractCmdPrintOptions(cmd, false), mapping)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return printer.PrintObj(obj, out)
|
||||
}
|
||||
|
||||
func (f *ring2Factory) PrintResourceInfoForCommand(cmd *cobra.Command, info *resource.Info, out io.Writer) error {
|
||||
printOpts := ExtractCmdPrintOptions(cmd, false)
|
||||
printer, err := f.PrinterForOptions(printOpts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !printer.IsGeneric() {
|
||||
printer, err = f.PrinterForMapping(printOpts, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return printer.PrintObj(info.Object, out)
|
||||
}
|
||||
|
||||
// NewBuilder returns a new resource builder for structured api objects.
|
||||
func (f *ring2Factory) NewBuilder() *resource.Builder {
|
||||
clientMapperFunc := resource.ClientMapperFunc(f.objectMappingFactory.ClientForMapping)
|
||||
@ -160,7 +54,7 @@ func (f *ring2Factory) NewBuilder() *resource.Builder {
|
||||
RESTMapper: mapper,
|
||||
ObjectTyper: typer,
|
||||
ClientMapper: clientMapperFunc,
|
||||
Decoder: f.clientAccessFactory.Decoder(true),
|
||||
Decoder: InternalVersionDecoder(),
|
||||
},
|
||||
&resource.Mapper{
|
||||
RESTMapper: mapper,
|
||||
|
93
vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/factory_client_access.go
generated
vendored
93
vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/factory_client_access.go
generated
vendored
@ -23,6 +23,7 @@ import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
@ -38,6 +39,7 @@ import (
|
||||
appsv1beta1 "k8s.io/api/apps/v1beta1"
|
||||
appsv1beta2 "k8s.io/api/apps/v1beta2"
|
||||
batchv1 "k8s.io/api/batch/v1"
|
||||
batchv1beta1 "k8s.io/api/batch/v1beta1"
|
||||
batchv2alpha1 "k8s.io/api/batch/v2alpha1"
|
||||
extensionsv1beta1 "k8s.io/api/extensions/v1beta1"
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
@ -58,8 +60,7 @@ import (
|
||||
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
|
||||
"k8s.io/kubernetes/pkg/kubectl"
|
||||
"k8s.io/kubernetes/pkg/kubectl/resource"
|
||||
"k8s.io/kubernetes/pkg/printers"
|
||||
printersinternal "k8s.io/kubernetes/pkg/printers/internalversion"
|
||||
"k8s.io/kubernetes/pkg/kubectl/util/transport"
|
||||
)
|
||||
|
||||
type ring0Factory struct {
|
||||
@ -108,7 +109,15 @@ func (f *discoveryFactory) DiscoveryClient() (discovery.CachedDiscoveryInterface
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cfg.CacheDir = f.cacheDir
|
||||
if f.cacheDir != "" {
|
||||
wt := cfg.WrapTransport
|
||||
cfg.WrapTransport = func(rt http.RoundTripper) http.RoundTripper {
|
||||
if wt != nil {
|
||||
rt = wt(rt)
|
||||
}
|
||||
return transport.NewCacheRoundTripper(f.cacheDir, rt)
|
||||
}
|
||||
}
|
||||
|
||||
discoveryClient, err := discovery.NewDiscoveryClientForConfig(cfg)
|
||||
if err != nil {
|
||||
@ -194,10 +203,6 @@ func (f *ring0Factory) ClientSet() (internalclientset.Interface, error) {
|
||||
return f.clientCache.ClientSetForVersion(nil)
|
||||
}
|
||||
|
||||
func (f *ring0Factory) ClientSetForVersion(requiredVersion *schema.GroupVersion) (internalclientset.Interface, error) {
|
||||
return f.clientCache.ClientSetForVersion(requiredVersion)
|
||||
}
|
||||
|
||||
func (f *ring0Factory) ClientConfig() (*restclient.Config, error) {
|
||||
return f.clientCache.ClientConfigForVersion(nil)
|
||||
}
|
||||
@ -205,10 +210,6 @@ func (f *ring0Factory) BareClientConfig() (*restclient.Config, error) {
|
||||
return f.clientConfig.ClientConfig()
|
||||
}
|
||||
|
||||
func (f *ring0Factory) ClientConfigForVersion(requiredVersion *schema.GroupVersion) (*restclient.Config, error) {
|
||||
return f.clientCache.ClientConfigForVersion(nil)
|
||||
}
|
||||
|
||||
func (f *ring0Factory) RESTClient() (*restclient.RESTClient, error) {
|
||||
clientConfig, err := f.clientCache.ClientConfigForVersion(nil)
|
||||
if err != nil {
|
||||
@ -217,20 +218,6 @@ func (f *ring0Factory) RESTClient() (*restclient.RESTClient, error) {
|
||||
return restclient.RESTClientFor(clientConfig)
|
||||
}
|
||||
|
||||
func (f *ring0Factory) Decoder(toInternal bool) runtime.Decoder {
|
||||
var decoder runtime.Decoder
|
||||
if toInternal {
|
||||
decoder = legacyscheme.Codecs.UniversalDecoder()
|
||||
} else {
|
||||
decoder = legacyscheme.Codecs.UniversalDeserializer()
|
||||
}
|
||||
return decoder
|
||||
}
|
||||
|
||||
func (f *ring0Factory) JSONEncoder() runtime.Encoder {
|
||||
return legacyscheme.Codecs.LegacyCodec(legacyscheme.Registry.EnabledVersions()...)
|
||||
}
|
||||
|
||||
func (f *ring0Factory) UpdatePodSpecForObject(obj runtime.Object, fn func(*v1.PodSpec) error) (bool, error) {
|
||||
// TODO: replace with a swagger schema based approach (identify pod template via schema introspection)
|
||||
switch t := obj.(type) {
|
||||
@ -275,6 +262,11 @@ func (f *ring0Factory) UpdatePodSpecForObject(obj runtime.Object, fn func(*v1.Po
|
||||
// Job
|
||||
case *batchv1.Job:
|
||||
return true, fn(&t.Spec.Template.Spec)
|
||||
// CronJob
|
||||
case *batchv1beta1.CronJob:
|
||||
return true, fn(&t.Spec.JobTemplate.Spec.Template.Spec)
|
||||
case *batchv2alpha1.CronJob:
|
||||
return true, fn(&t.Spec.JobTemplate.Spec.Template.Spec)
|
||||
default:
|
||||
return false, fmt.Errorf("the object is not a pod or does not have a pod template")
|
||||
}
|
||||
@ -425,12 +417,6 @@ func (f *ring0Factory) SuggestedPodTemplateResources() []schema.GroupResource {
|
||||
}
|
||||
}
|
||||
|
||||
func (f *ring0Factory) Printer(mapping *meta.RESTMapping, options printers.PrintOptions) (printers.ResourcePrinter, error) {
|
||||
p := printers.NewHumanReadablePrinter(f.JSONEncoder(), f.Decoder(true), options)
|
||||
printersinternal.AddHandlers(p)
|
||||
return p, nil
|
||||
}
|
||||
|
||||
func (f *ring0Factory) Pauser(info *resource.Info) ([]byte, error) {
|
||||
switch obj := info.Object.(type) {
|
||||
case *extensions.Deployment:
|
||||
@ -438,7 +424,7 @@ func (f *ring0Factory) Pauser(info *resource.Info) ([]byte, error) {
|
||||
return nil, errors.New("is already paused")
|
||||
}
|
||||
obj.Spec.Paused = true
|
||||
return runtime.Encode(f.JSONEncoder(), info.Object)
|
||||
return runtime.Encode(InternalVersionJSONEncoder(), info.Object)
|
||||
default:
|
||||
return nil, fmt.Errorf("pausing is not supported")
|
||||
}
|
||||
@ -455,7 +441,7 @@ func (f *ring0Factory) Resumer(info *resource.Info) ([]byte, error) {
|
||||
return nil, errors.New("is not paused")
|
||||
}
|
||||
obj.Spec.Paused = false
|
||||
return runtime.Encode(f.JSONEncoder(), info.Object)
|
||||
return runtime.Encode(InternalVersionJSONEncoder(), info.Object)
|
||||
default:
|
||||
return nil, fmt.Errorf("resuming is not supported")
|
||||
}
|
||||
@ -538,10 +524,6 @@ func DefaultGenerators(cmdName string) map[string]kubectl.Generator {
|
||||
CronJobV2Alpha1GeneratorName: kubectl.CronJobV2Alpha1{},
|
||||
CronJobV1Beta1GeneratorName: kubectl.CronJobV1Beta1{},
|
||||
}
|
||||
case "autoscale":
|
||||
generator = map[string]kubectl.Generator{
|
||||
HorizontalPodAutoscalerV1GeneratorName: kubectl.HorizontalPodAutoscalerV1{},
|
||||
}
|
||||
case "namespace":
|
||||
generator = map[string]kubectl.Generator{
|
||||
NamespaceV1GeneratorName: kubectl.NamespaceGeneratorV1{},
|
||||
@ -665,34 +647,6 @@ func (f *ring0Factory) EditorEnvs() []string {
|
||||
return []string{"KUBE_EDITOR", "EDITOR"}
|
||||
}
|
||||
|
||||
func (f *ring0Factory) PrintObjectSpecificMessage(obj runtime.Object, out io.Writer) {
|
||||
switch obj := obj.(type) {
|
||||
case *api.Service:
|
||||
if obj.Spec.Type == api.ServiceTypeNodePort {
|
||||
msg := fmt.Sprintf(
|
||||
`You have exposed your service on an external port on all nodes in your
|
||||
cluster. If you want to expose this service to the external internet, you may
|
||||
need to set up firewall rules for the service port(s) (%s) to serve traffic.
|
||||
|
||||
See http://kubernetes.io/docs/user-guide/services-firewalls for more details.
|
||||
`,
|
||||
makePortsString(obj.Spec.Ports, true))
|
||||
out.Write([]byte(msg))
|
||||
}
|
||||
|
||||
if _, ok := obj.Annotations[api.AnnotationLoadBalancerSourceRangesKey]; ok {
|
||||
msg := fmt.Sprintf(
|
||||
`You are using service annotation [service.beta.kubernetes.io/load-balancer-source-ranges].
|
||||
It has been promoted to field [loadBalancerSourceRanges] in service spec. This annotation will be deprecated in the future.
|
||||
Please use the loadBalancerSourceRanges field instead.
|
||||
|
||||
See http://kubernetes.io/docs/user-guide/services-firewalls for more details.
|
||||
`)
|
||||
out.Write([]byte(msg))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// overlyCautiousIllegalFileCharacters matches characters that *might* not be supported. Windows is really restrictive, so this is really restrictive
|
||||
var overlyCautiousIllegalFileCharacters = regexp.MustCompile(`[^(\w/\.)]`)
|
||||
|
||||
@ -705,3 +659,12 @@ func computeDiscoverCacheDir(parentDir, host string) string {
|
||||
|
||||
return filepath.Join(parentDir, safeHost)
|
||||
}
|
||||
|
||||
// this method exists to help us find the points still relying on internal types.
|
||||
func InternalVersionDecoder() runtime.Decoder {
|
||||
return legacyscheme.Codecs.UniversalDecoder()
|
||||
}
|
||||
|
||||
func InternalVersionJSONEncoder() runtime.Encoder {
|
||||
return legacyscheme.Codecs.LegacyCodec(legacyscheme.Registry.EnabledVersions()...)
|
||||
}
|
||||
|
43
vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/factory_object_mapping.go
generated
vendored
43
vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/factory_object_mapping.go
generated
vendored
@ -37,12 +37,12 @@ import (
|
||||
"k8s.io/client-go/discovery"
|
||||
"k8s.io/client-go/dynamic"
|
||||
restclient "k8s.io/client-go/rest"
|
||||
scaleclient "k8s.io/client-go/scale"
|
||||
"k8s.io/kubernetes/pkg/api/legacyscheme"
|
||||
"k8s.io/kubernetes/pkg/apis/apps"
|
||||
"k8s.io/kubernetes/pkg/apis/batch"
|
||||
api "k8s.io/kubernetes/pkg/apis/core"
|
||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
||||
client "k8s.io/kubernetes/pkg/client/unversioned"
|
||||
"k8s.io/kubernetes/pkg/controller"
|
||||
"k8s.io/kubernetes/pkg/kubectl"
|
||||
"k8s.io/kubernetes/pkg/kubectl/categories"
|
||||
@ -131,7 +131,7 @@ func (f *ring1Factory) ClientForMapping(mapping *meta.RESTMapping) (resource.RES
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := client.SetKubernetesDefaults(cfg); err != nil {
|
||||
if err := setKubernetesDefaults(cfg); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
gvk := mapping.GroupVersionKind
|
||||
@ -165,9 +165,7 @@ func (f *ring1Factory) UnstructuredClientForMapping(mapping *meta.RESTMapping) (
|
||||
}
|
||||
|
||||
func (f *ring1Factory) Describer(mapping *meta.RESTMapping) (printers.Describer, error) {
|
||||
mappingVersion := mapping.GroupVersionKind.GroupVersion()
|
||||
|
||||
clientset, err := f.clientAccessFactory.ClientSetForVersion(&mappingVersion)
|
||||
clientset, err := f.clientAccessFactory.ClientSet()
|
||||
if err != nil {
|
||||
// if we can't make a client for this group/version, go generic if possible
|
||||
if genericDescriber, genericErr := genericDescriber(f.clientAccessFactory, mapping); genericErr == nil {
|
||||
@ -218,7 +216,7 @@ func genericDescriber(clientAccessFactory ClientAccessFactory, mapping *meta.RES
|
||||
}
|
||||
|
||||
func (f *ring1Factory) LogsForObject(object, options runtime.Object, timeout time.Duration) (*restclient.Request, error) {
|
||||
clientset, err := f.clientAccessFactory.ClientSetForVersion(nil)
|
||||
clientset, err := f.clientAccessFactory.ClientSet()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -281,17 +279,31 @@ func (f *ring1Factory) LogsForObject(object, options runtime.Object, timeout tim
|
||||
}
|
||||
|
||||
func (f *ring1Factory) Scaler(mapping *meta.RESTMapping) (kubectl.Scaler, error) {
|
||||
mappingVersion := mapping.GroupVersionKind.GroupVersion()
|
||||
clientset, err := f.clientAccessFactory.ClientSetForVersion(&mappingVersion)
|
||||
clientset, err := f.clientAccessFactory.ClientSet()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return kubectl.ScalerFor(mapping.GroupVersionKind.GroupKind(), clientset)
|
||||
|
||||
// create scales getter
|
||||
// TODO(p0lyn0mial): put scalesGetter to a factory
|
||||
discoClient, err := f.clientAccessFactory.DiscoveryClient()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
restClient, err := f.clientAccessFactory.RESTClient()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
mapper, _ := f.Object()
|
||||
resolver := scaleclient.NewDiscoveryScaleKindResolver(discoClient)
|
||||
scalesGetter := scaleclient.New(restClient, mapper, dynamic.LegacyAPIPathResolverFunc, resolver)
|
||||
gvk := mapping.GroupVersionKind.GroupVersion().WithResource(mapping.Resource)
|
||||
|
||||
return kubectl.ScalerFor(mapping.GroupVersionKind.GroupKind(), clientset.Batch(), scalesGetter, gvk.GroupResource()), nil
|
||||
}
|
||||
|
||||
func (f *ring1Factory) Reaper(mapping *meta.RESTMapping) (kubectl.Reaper, error) {
|
||||
mappingVersion := mapping.GroupVersionKind.GroupVersion()
|
||||
clientset, clientsetErr := f.clientAccessFactory.ClientSetForVersion(&mappingVersion)
|
||||
clientset, clientsetErr := f.clientAccessFactory.ClientSet()
|
||||
reaper, reaperErr := kubectl.ReaperFor(mapping.GroupVersionKind.GroupKind(), clientset)
|
||||
|
||||
if kubectl.IsNoSuchReaperError(reaperErr) {
|
||||
@ -350,7 +362,7 @@ func (f *ring1Factory) ApproximatePodTemplateForObject(object runtime.Object) (*
|
||||
}
|
||||
|
||||
func (f *ring1Factory) AttachablePodForObject(object runtime.Object, timeout time.Duration) (*api.Pod, error) {
|
||||
clientset, err := f.clientAccessFactory.ClientSetForVersion(nil)
|
||||
clientset, err := f.clientAccessFactory.ClientSet()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -386,6 +398,13 @@ func (f *ring1Factory) AttachablePodForObject(object runtime.Object, timeout tim
|
||||
return nil, fmt.Errorf("invalid label selector: %v", err)
|
||||
}
|
||||
|
||||
case *api.Service:
|
||||
namespace = t.Namespace
|
||||
if t.Spec.Selector == nil || len(t.Spec.Selector) == 0 {
|
||||
return nil, fmt.Errorf("invalid service '%s': Service is defined without a selector", t.Name)
|
||||
}
|
||||
selector = labels.SelectorFromSet(t.Spec.Selector)
|
||||
|
||||
case *api.Pod:
|
||||
return t, nil
|
||||
|
||||
|
2
vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/factory_object_mapping_test.go
generated
vendored
2
vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/factory_object_mapping_test.go
generated
vendored
@ -40,7 +40,7 @@ type fakeClientAccessFactory struct {
|
||||
fakeClientset *fake.Clientset
|
||||
}
|
||||
|
||||
func (f *fakeClientAccessFactory) ClientSetForVersion(requiredVersion *schema.GroupVersion) (internalclientset.Interface, error) {
|
||||
func (f *fakeClientAccessFactory) ClientSet() (internalclientset.Interface, error) {
|
||||
return f.fakeClientset, nil
|
||||
}
|
||||
|
||||
|
36
vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/factory_test.go
generated
vendored
36
vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/factory_test.go
generated
vendored
@ -17,7 +17,6 @@ limitations under the License.
|
||||
package util
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
@ -418,41 +417,6 @@ func TestGetFirstPod(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestPrintObjectSpecificMessage(t *testing.T) {
|
||||
f := NewFactory(nil)
|
||||
tests := []struct {
|
||||
obj runtime.Object
|
||||
expectOutput bool
|
||||
}{
|
||||
{
|
||||
obj: &api.Service{},
|
||||
expectOutput: false,
|
||||
},
|
||||
{
|
||||
obj: &api.Pod{},
|
||||
expectOutput: false,
|
||||
},
|
||||
{
|
||||
obj: &api.Service{Spec: api.ServiceSpec{Type: api.ServiceTypeLoadBalancer}},
|
||||
expectOutput: false,
|
||||
},
|
||||
{
|
||||
obj: &api.Service{Spec: api.ServiceSpec{Type: api.ServiceTypeNodePort}},
|
||||
expectOutput: true,
|
||||
},
|
||||
}
|
||||
for _, test := range tests {
|
||||
buff := &bytes.Buffer{}
|
||||
f.PrintObjectSpecificMessage(test.obj, buff)
|
||||
if test.expectOutput && buff.Len() == 0 {
|
||||
t.Errorf("Expected output, saw none for %v", test.obj)
|
||||
}
|
||||
if !test.expectOutput && buff.Len() > 0 {
|
||||
t.Errorf("Expected no output, saw %s for %v", buff.String(), test.obj)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestMakePortsString(t *testing.T) {
|
||||
tests := []struct {
|
||||
ports []api.ServicePort
|
||||
|
8
vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/helpers.go
generated
vendored
8
vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/helpers.go
generated
vendored
@ -401,7 +401,7 @@ func AddValidateFlags(cmd *cobra.Command) {
|
||||
}
|
||||
|
||||
func AddValidateOptionFlags(cmd *cobra.Command, options *ValidateOptions) {
|
||||
cmd.Flags().BoolVar(&options.EnableValidation, "validate", true, "If true, use a schema to validate the input before sending it")
|
||||
cmd.Flags().BoolVar(&options.EnableValidation, "validate", options.EnableValidation, "If true, use a schema to validate the input before sending it")
|
||||
}
|
||||
|
||||
func AddFilenameOptionFlags(cmd *cobra.Command, options *resource.FilenameOptions, usage string) {
|
||||
@ -427,7 +427,7 @@ func AddApplyAnnotationFlags(cmd *cobra.Command) {
|
||||
}
|
||||
|
||||
func AddApplyAnnotationVarFlags(cmd *cobra.Command, applyAnnotation *bool) {
|
||||
cmd.Flags().BoolVar(applyAnnotation, ApplyAnnotationsFlag, false, "If true, the configuration of current object will be saved in its annotation. Otherwise, the annotation will be unchanged. This flag is useful when you want to perform kubectl apply on this object in the future.")
|
||||
cmd.Flags().BoolVar(applyAnnotation, ApplyAnnotationsFlag, *applyAnnotation, "If true, the configuration of current object will be saved in its annotation. Otherwise, the annotation will be unchanged. This flag is useful when you want to perform kubectl apply on this object in the future.")
|
||||
}
|
||||
|
||||
// AddGeneratorFlags adds flags common to resource generation commands
|
||||
@ -524,7 +524,7 @@ func AddRecordFlag(cmd *cobra.Command) {
|
||||
}
|
||||
|
||||
func AddRecordVarFlag(cmd *cobra.Command, record *bool) {
|
||||
cmd.Flags().BoolVar(record, "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.")
|
||||
cmd.Flags().BoolVar(record, "record", *record, "Record current kubectl command in the resource annotation. If set to false, do not record the command. If set to true, record the command. If not set, default to updating the existing annotation value only if one already exists.")
|
||||
}
|
||||
|
||||
func GetRecordFlag(cmd *cobra.Command) bool {
|
||||
@ -601,7 +601,7 @@ func AddInclude3rdPartyFlags(cmd *cobra.Command) {
|
||||
}
|
||||
|
||||
func AddInclude3rdPartyVarFlags(cmd *cobra.Command, include3rdParty *bool) {
|
||||
cmd.Flags().BoolVar(include3rdParty, "include-extended-apis", true, "If true, include definitions of new APIs via calls to the API server. [default true]")
|
||||
cmd.Flags().BoolVar(include3rdParty, "include-extended-apis", *include3rdParty, "If true, include definitions of new APIs via calls to the API server. [default true]")
|
||||
cmd.Flags().MarkDeprecated("include-extended-apis", "No longer required.")
|
||||
}
|
||||
|
||||
|
1
vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi/BUILD
generated
vendored
1
vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi/BUILD
generated
vendored
@ -33,7 +33,6 @@ go_test(
|
||||
"openapi_test.go",
|
||||
],
|
||||
data = ["//api/openapi-spec:swagger-spec"],
|
||||
importpath = "k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi_test",
|
||||
deps = [
|
||||
":go_default_library",
|
||||
"//pkg/kubectl/cmd/util/openapi/testing:go_default_library",
|
||||
|
73
vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi/openapi.go
generated
vendored
73
vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi/openapi.go
generated
vendored
@ -56,9 +56,11 @@ func NewOpenAPIData(doc *openapi_v2.Document) (Resources, error) {
|
||||
if model == nil {
|
||||
panic("ListModels returns a model that can't be looked-up.")
|
||||
}
|
||||
gvk := parseGroupVersionKind(model)
|
||||
if len(gvk.Kind) > 0 {
|
||||
resources[gvk] = modelName
|
||||
gvkList := parseGroupVersionKind(model)
|
||||
for _, gvk := range gvkList {
|
||||
if len(gvk.Kind) > 0 {
|
||||
resources[gvk] = modelName
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -77,48 +79,49 @@ func (d *document) LookupResource(gvk schema.GroupVersionKind) proto.Schema {
|
||||
}
|
||||
|
||||
// Get and parse GroupVersionKind from the extension. Returns empty if it doesn't have one.
|
||||
func parseGroupVersionKind(s proto.Schema) schema.GroupVersionKind {
|
||||
func parseGroupVersionKind(s proto.Schema) []schema.GroupVersionKind {
|
||||
extensions := s.GetExtensions()
|
||||
|
||||
gvkListResult := []schema.GroupVersionKind{}
|
||||
|
||||
// Get the extensions
|
||||
gvkExtension, ok := extensions[groupVersionKindExtensionKey]
|
||||
if !ok {
|
||||
return schema.GroupVersionKind{}
|
||||
return []schema.GroupVersionKind{}
|
||||
}
|
||||
|
||||
// gvk extension must be a list of 1 element.
|
||||
// gvk extension must be a list of at least 1 element.
|
||||
gvkList, ok := gvkExtension.([]interface{})
|
||||
if !ok {
|
||||
return schema.GroupVersionKind{}
|
||||
}
|
||||
if len(gvkList) != 1 {
|
||||
return schema.GroupVersionKind{}
|
||||
|
||||
}
|
||||
gvk := gvkList[0]
|
||||
|
||||
// gvk extension list must be a map with group, version, and
|
||||
// kind fields
|
||||
gvkMap, ok := gvk.(map[interface{}]interface{})
|
||||
if !ok {
|
||||
return schema.GroupVersionKind{}
|
||||
}
|
||||
group, ok := gvkMap["group"].(string)
|
||||
if !ok {
|
||||
return schema.GroupVersionKind{}
|
||||
}
|
||||
version, ok := gvkMap["version"].(string)
|
||||
if !ok {
|
||||
return schema.GroupVersionKind{}
|
||||
}
|
||||
kind, ok := gvkMap["kind"].(string)
|
||||
if !ok {
|
||||
return schema.GroupVersionKind{}
|
||||
return []schema.GroupVersionKind{}
|
||||
}
|
||||
|
||||
return schema.GroupVersionKind{
|
||||
Group: group,
|
||||
Version: version,
|
||||
Kind: kind,
|
||||
for _, gvk := range gvkList {
|
||||
// gvk extension list must be a map with group, version, and
|
||||
// kind fields
|
||||
gvkMap, ok := gvk.(map[interface{}]interface{})
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
group, ok := gvkMap["group"].(string)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
version, ok := gvkMap["version"].(string)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
kind, ok := gvkMap["kind"].(string)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
gvkListResult = append(gvkListResult, schema.GroupVersionKind{
|
||||
Group: group,
|
||||
Version: version,
|
||||
Kind: kind,
|
||||
})
|
||||
}
|
||||
|
||||
return gvkListResult
|
||||
}
|
||||
|
3
vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi/validation/BUILD
generated
vendored
3
vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi/validation/BUILD
generated
vendored
@ -27,8 +27,7 @@ go_test(
|
||||
"validation_test.go",
|
||||
],
|
||||
data = ["//api/openapi-spec:swagger-spec"],
|
||||
importpath = "k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi/validation",
|
||||
library = ":go_default_library",
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//pkg/api/testapi:go_default_library",
|
||||
"//pkg/kubectl/cmd/util/openapi:go_default_library",
|
||||
|
88
vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/printing.go
generated
vendored
88
vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/printing.go
generated
vendored
@ -18,16 +18,20 @@ package util
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"strings"
|
||||
|
||||
"k8s.io/apimachinery/pkg/api/meta"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/kubernetes/pkg/kubectl"
|
||||
"k8s.io/kubernetes/pkg/kubectl/cmd/templates"
|
||||
kubectlscheme "k8s.io/kubernetes/pkg/kubectl/scheme"
|
||||
"k8s.io/kubernetes/pkg/printers"
|
||||
printersinternal "k8s.io/kubernetes/pkg/printers/internalversion"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/kubernetes/pkg/api/legacyscheme"
|
||||
)
|
||||
|
||||
// AddPrinterFlags adds printing related flags to a command (e.g. output format, no headers, template path)
|
||||
@ -48,7 +52,8 @@ func AddNonDeprecatedPrinterFlags(cmd *cobra.Command) {
|
||||
cmd.Flags().String("template", "", "Template string or path to template file to use when -o=go-template, -o=go-template-file. The template format is golang templates [http://golang.org/pkg/text/template/#pkg-overview].")
|
||||
cmd.MarkFlagFilename("template")
|
||||
cmd.Flags().String("sort-by", "", "If non-empty, sort list types using this field specification. The field specification is expressed as a JSONPath expression (e.g. '{.metadata.name}'). The field in the API resource specified by this JSONPath expression must be an integer or a string.")
|
||||
cmd.Flags().BoolP("show-all", "a", false, "When printing, show all resources (default hide terminated pods.)")
|
||||
cmd.Flags().BoolP("show-all", "a", true, "When printing, show all resources (default hide terminated pods.)")
|
||||
cmd.Flags().MarkDeprecated("show-all", "will be removed in an upcoming release")
|
||||
}
|
||||
|
||||
// AddOutputFlagsForMutation adds output related flags to a command. Used by mutations only.
|
||||
@ -58,7 +63,7 @@ func AddOutputFlagsForMutation(cmd *cobra.Command) {
|
||||
|
||||
// AddOutputVarFlagsForMutation adds output related flags to a command. Used by mutations only.
|
||||
func AddOutputVarFlagsForMutation(cmd *cobra.Command, output *string) {
|
||||
cmd.Flags().StringVarP(output, "output", "o", "", "Output mode. Use \"-o name\" for shorter output (resource/name).")
|
||||
cmd.Flags().StringVarP(output, "output", "o", *output, "Output mode. Use \"-o name\" for shorter output (resource/name).")
|
||||
}
|
||||
|
||||
// AddOutputFlags adds output related flags to a command.
|
||||
@ -81,11 +86,59 @@ func ValidateOutputArgs(cmd *cobra.Command) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// PrintSuccess prints a success message and can do a "-o name" as "shortOutput"
|
||||
// TODO this should really just be a printer. It's got just about the exact same signature.
|
||||
func PrintSuccess(shortOutput bool, out io.Writer, obj runtime.Object, dryRun bool, operation string) {
|
||||
dryRunMsg := ""
|
||||
if dryRun {
|
||||
dryRunMsg = " (dry run)"
|
||||
}
|
||||
|
||||
// match name printer format
|
||||
name := "<unknown>"
|
||||
if acc, err := meta.Accessor(obj); err == nil {
|
||||
if n := acc.GetName(); len(n) > 0 {
|
||||
name = n
|
||||
}
|
||||
}
|
||||
|
||||
// legacy scheme to be sure we work ok with internal types.
|
||||
// TODO internal types aren't supposed to exist here
|
||||
groupKind := printers.GetObjectGroupKind(obj, legacyscheme.Scheme)
|
||||
kindString := fmt.Sprintf("%s.%s", strings.ToLower(groupKind.Kind), groupKind.Group)
|
||||
if len(groupKind.Group) == 0 {
|
||||
kindString = strings.ToLower(groupKind.Kind)
|
||||
}
|
||||
|
||||
if shortOutput {
|
||||
// -o name: prints resource/name
|
||||
fmt.Fprintf(out, "%s/%s\n", kindString, name)
|
||||
return
|
||||
}
|
||||
|
||||
// understandable output by default
|
||||
fmt.Fprintf(out, "%s \"%s\" %s%s\n", kindString, name, operation, dryRunMsg)
|
||||
}
|
||||
|
||||
// PrintObject prints a single object based on the default command options
|
||||
// TODO this should go away once commands can embed the PrintOptions instead
|
||||
func PrintObject(cmd *cobra.Command, obj runtime.Object, out io.Writer) error {
|
||||
printer, err := PrinterForOptions(ExtractCmdPrintOptions(cmd, false))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return printer.PrintObj(obj, out)
|
||||
}
|
||||
|
||||
// PrinterForOptions returns the printer for the outputOptions (if given) or
|
||||
// returns the default printer for the command. Requires that printer flags have
|
||||
// been added to cmd (see AddPrinterFlags).
|
||||
func PrinterForOptions(mapper meta.RESTMapper, typer runtime.ObjectTyper, encoder runtime.Encoder, decoders []runtime.Decoder, options *printers.PrintOptions) (printers.ResourcePrinter, error) {
|
||||
printer, err := printers.GetStandardPrinter(mapper, typer, encoder, decoders, *options)
|
||||
// returns the default printer for the command.
|
||||
// TODO this should become a function on the PrintOptions struct
|
||||
func PrinterForOptions(options *printers.PrintOptions) (printers.ResourcePrinter, error) {
|
||||
// TODO: used by the custom column implementation and the name implementation, break this dependency
|
||||
decoders := []runtime.Decoder{kubectlscheme.Codecs.UniversalDecoder(), unstructured.UnstructuredJSONScheme}
|
||||
encoder := kubectlscheme.Codecs.LegacyCodec(kubectlscheme.Registry.EnabledVersions()...)
|
||||
|
||||
printer, err := printers.GetStandardPrinter(kubectlscheme.Scheme, encoder, decoders, *options)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -93,11 +146,18 @@ func PrinterForOptions(mapper meta.RESTMapper, typer runtime.ObjectTyper, encode
|
||||
// we try to convert to HumanReadablePrinter, if return ok, it must be no generic
|
||||
// we execute AddHandlers() here before maybeWrapSortingPrinter so that we don't
|
||||
// need to convert to delegatePrinter again then invoke AddHandlers()
|
||||
if humanReadablePrinter, ok := printer.(*printers.HumanReadablePrinter); ok {
|
||||
// TODO this looks highly questionable. human readable printers are baked into code. This can just live in the definition of the handler itself
|
||||
// TODO or be registered there
|
||||
if humanReadablePrinter, ok := printer.(printers.PrintHandler); ok {
|
||||
printersinternal.AddHandlers(humanReadablePrinter)
|
||||
}
|
||||
|
||||
return maybeWrapSortingPrinter(printer, *options), nil
|
||||
printer = maybeWrapSortingPrinter(printer, *options)
|
||||
|
||||
// wrap the printer in a versioning printer that understands when to convert and when not to convert
|
||||
printer = printers.NewVersionedPrinter(printer, legacyscheme.Scheme, legacyscheme.Scheme, kubectlscheme.Versions...)
|
||||
|
||||
return printer, nil
|
||||
}
|
||||
|
||||
// ExtractCmdPrintOptions parses printer specific commandline args and
|
||||
@ -223,3 +283,15 @@ func ValidResourceTypeList(f ClientAccessFactory) string {
|
||||
|
||||
`)
|
||||
}
|
||||
|
||||
// Retrieve a list of handled resources from printer as valid args
|
||||
// TODO: This function implementation should be replaced with a real implementation from the discovery service.
|
||||
func ValidArgList(f ClientAccessFactory) []string {
|
||||
validArgs := []string{}
|
||||
|
||||
humanReadablePrinter := printers.NewHumanReadablePrinter(nil, nil, printers.PrintOptions{})
|
||||
printersinternal.AddHandlers(humanReadablePrinter)
|
||||
validArgs = humanReadablePrinter.HandledResources()
|
||||
|
||||
return validArgs
|
||||
}
|
||||
|
42
vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/shortcut_restmapper.go
generated
vendored
42
vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/shortcut_restmapper.go
generated
vendored
@ -22,6 +22,7 @@ import (
|
||||
"github.com/golang/glog"
|
||||
|
||||
"k8s.io/apimachinery/pkg/api/meta"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/client-go/discovery"
|
||||
"k8s.io/kubernetes/pkg/kubectl"
|
||||
@ -72,7 +73,7 @@ func (e shortcutExpander) RESTMappings(gk schema.GroupKind, versions ...string)
|
||||
// First the list of potential resources will be taken from the API server.
|
||||
// Next we will append the hardcoded list of resources - to be backward compatible with old servers.
|
||||
// NOTE that the list is ordered by group priority.
|
||||
func (e shortcutExpander) getShortcutMappings() ([]kubectl.ResourceShortcuts, error) {
|
||||
func (e shortcutExpander) getShortcutMappings() ([]*metav1.APIResourceList, []kubectl.ResourceShortcuts, error) {
|
||||
res := []kubectl.ResourceShortcuts{}
|
||||
// get server resources
|
||||
// This can return an error *and* the results it was able to find. We don't need to fail on the error.
|
||||
@ -81,13 +82,13 @@ func (e shortcutExpander) getShortcutMappings() ([]kubectl.ResourceShortcuts, er
|
||||
glog.V(1).Infof("Error loading discovery information: %v", err)
|
||||
}
|
||||
for _, apiResources := range apiResList {
|
||||
gv, err := schema.ParseGroupVersion(apiResources.GroupVersion)
|
||||
if err != nil {
|
||||
glog.V(1).Infof("Unable to parse groupversion = %s due to = %s", apiResources.GroupVersion, err.Error())
|
||||
continue
|
||||
}
|
||||
for _, apiRes := range apiResources.APIResources {
|
||||
for _, shortName := range apiRes.ShortNames {
|
||||
gv, err := schema.ParseGroupVersion(apiResources.GroupVersion)
|
||||
if err != nil {
|
||||
glog.V(1).Infof("Unable to parse groupversion = %s due to = %s", apiResources.GroupVersion, err.Error())
|
||||
continue
|
||||
}
|
||||
rs := kubectl.ResourceShortcuts{
|
||||
ShortForm: schema.GroupResource{Group: gv.Group, Resource: shortName},
|
||||
LongForm: schema.GroupResource{Group: gv.Group, Resource: apiRes.Name},
|
||||
@ -99,7 +100,7 @@ func (e shortcutExpander) getShortcutMappings() ([]kubectl.ResourceShortcuts, er
|
||||
|
||||
// append hardcoded short forms at the end of the list
|
||||
res = append(res, kubectl.ResourcesShortcutStatic...)
|
||||
return res, nil
|
||||
return apiResList, res, nil
|
||||
}
|
||||
|
||||
// expandResourceShortcut will return the expanded version of resource
|
||||
@ -108,13 +109,33 @@ func (e shortcutExpander) getShortcutMappings() ([]kubectl.ResourceShortcuts, er
|
||||
// Lastly we will return resource unmodified.
|
||||
func (e shortcutExpander) expandResourceShortcut(resource schema.GroupVersionResource) schema.GroupVersionResource {
|
||||
// get the shortcut mappings and return on first match.
|
||||
if resources, err := e.getShortcutMappings(); err == nil {
|
||||
for _, item := range resources {
|
||||
if allResources, shortcutResources, err := e.getShortcutMappings(); err == nil {
|
||||
// avoid expanding if there's an exact match to a full resource name
|
||||
for _, apiResources := range allResources {
|
||||
gv, err := schema.ParseGroupVersion(apiResources.GroupVersion)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
if len(resource.Group) != 0 && resource.Group != gv.Group {
|
||||
continue
|
||||
}
|
||||
for _, apiRes := range apiResources.APIResources {
|
||||
if resource.Resource == apiRes.Name {
|
||||
return resource
|
||||
}
|
||||
if resource.Resource == apiRes.SingularName {
|
||||
return resource
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for _, item := range shortcutResources {
|
||||
if len(resource.Group) != 0 && resource.Group != item.ShortForm.Group {
|
||||
continue
|
||||
}
|
||||
if resource.Resource == item.ShortForm.Resource {
|
||||
resource.Resource = item.LongForm.Resource
|
||||
resource.Group = item.LongForm.Group
|
||||
return resource
|
||||
}
|
||||
}
|
||||
@ -123,12 +144,13 @@ func (e shortcutExpander) expandResourceShortcut(resource schema.GroupVersionRes
|
||||
if len(resource.Group) == 0 {
|
||||
return resource
|
||||
}
|
||||
for _, item := range resources {
|
||||
for _, item := range shortcutResources {
|
||||
if !strings.HasPrefix(item.ShortForm.Group, resource.Group) {
|
||||
continue
|
||||
}
|
||||
if resource.Resource == item.ShortForm.Resource {
|
||||
resource.Resource = item.LongForm.Resource
|
||||
resource.Group = item.LongForm.Group
|
||||
return resource
|
||||
}
|
||||
}
|
||||
|
57
vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/shortcut_restmapper_test.go
generated
vendored
57
vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/shortcut_restmapper_test.go
generated
vendored
@ -46,7 +46,7 @@ func TestReplaceAliases(t *testing.T) {
|
||||
{
|
||||
name: "hpa-priority",
|
||||
arg: "hpa",
|
||||
expected: schema.GroupVersionResource{Resource: "superhorizontalpodautoscalers"},
|
||||
expected: schema.GroupVersionResource{Resource: "superhorizontalpodautoscalers", Group: "autoscaling"},
|
||||
srvRes: []*metav1.APIResourceList{
|
||||
{
|
||||
GroupVersion: "autoscaling/v1",
|
||||
@ -68,6 +68,61 @@ func TestReplaceAliases(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "resource-override",
|
||||
arg: "dpl",
|
||||
expected: schema.GroupVersionResource{Resource: "deployments", Group: "foo"},
|
||||
srvRes: []*metav1.APIResourceList{
|
||||
{
|
||||
GroupVersion: "foo/v1",
|
||||
APIResources: []metav1.APIResource{
|
||||
{
|
||||
Name: "deployments",
|
||||
ShortNames: []string{"dpl"},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
GroupVersion: "extension/v1beta1",
|
||||
APIResources: []metav1.APIResource{
|
||||
{
|
||||
Name: "deployments",
|
||||
ShortNames: []string{"deploy"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "resource-match-preferred",
|
||||
arg: "pods",
|
||||
expected: schema.GroupVersionResource{Resource: "pods", Group: ""},
|
||||
srvRes: []*metav1.APIResourceList{
|
||||
{
|
||||
GroupVersion: "v1",
|
||||
APIResources: []metav1.APIResource{{Name: "pods", SingularName: "pod"}},
|
||||
},
|
||||
{
|
||||
GroupVersion: "acme.com/v1",
|
||||
APIResources: []metav1.APIResource{{Name: "poddlers", ShortNames: []string{"pods", "pod"}}},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "resource-match-singular-preferred",
|
||||
arg: "pod",
|
||||
expected: schema.GroupVersionResource{Resource: "pod", Group: ""},
|
||||
srvRes: []*metav1.APIResourceList{
|
||||
{
|
||||
GroupVersion: "v1",
|
||||
APIResources: []metav1.APIResource{{Name: "pods", SingularName: "pod"}},
|
||||
},
|
||||
{
|
||||
GroupVersion: "acme.com/v1",
|
||||
APIResources: []metav1.APIResource{{Name: "poddlers", ShortNames: []string{"pods", "pod"}}},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
ds := &fakeDiscoveryClient{}
|
||||
|
Reference in New Issue
Block a user