mirror of https://github.com/k3s-io/k3s
simplify resource builder usage
parent
54cf942a05
commit
b8aa7baa7d
|
@ -102,6 +102,7 @@ go_library(
|
|||
"//vendor/github.com/renstrom/dedent:go_default_library",
|
||||
"//vendor/github.com/spf13/cobra:go_default_library",
|
||||
"//vendor/github.com/spf13/pflag:go_default_library",
|
||||
"//vendor/k8s.io/api/autoscaling/v1:go_default_library",
|
||||
"//vendor/k8s.io/api/core/v1:go_default_library",
|
||||
"//vendor/k8s.io/api/policy/v1beta1:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library",
|
||||
|
@ -129,7 +130,9 @@ go_library(
|
|||
"//vendor/k8s.io/apimachinery/pkg/watch:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/util/flag:go_default_library",
|
||||
"//vendor/k8s.io/client-go/discovery:go_default_library",
|
||||
"//vendor/k8s.io/client-go/dynamic:go_default_library",
|
||||
"//vendor/k8s.io/client-go/kubernetes:go_default_library",
|
||||
"//vendor/k8s.io/client-go/kubernetes/typed/autoscaling/v1:go_default_library",
|
||||
"//vendor/k8s.io/client-go/kubernetes/typed/core/v1:go_default_library",
|
||||
"//vendor/k8s.io/client-go/rest:go_default_library",
|
||||
"//vendor/k8s.io/client-go/scale:go_default_library",
|
||||
|
|
|
@ -38,6 +38,7 @@ import (
|
|||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
"k8s.io/apimachinery/pkg/util/strategicpatch"
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
"k8s.io/client-go/dynamic"
|
||||
scaleclient "k8s.io/client-go/scale"
|
||||
oapi "k8s.io/kube-openapi/pkg/util/proto"
|
||||
api "k8s.io/kubernetes/pkg/apis/core"
|
||||
|
@ -285,8 +286,13 @@ func (o *ApplyOptions) Run(f cmdutil.Factory, cmd *cobra.Command) error {
|
|||
return err
|
||||
}
|
||||
|
||||
mapper, err := f.RESTMapper()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if o.Prune {
|
||||
o.PruneResources, err = parsePruneResources(r.Mapper().RESTMapper, o.PruneWhitelist)
|
||||
o.PruneResources, err = parsePruneResources(mapper, o.PruneWhitelist)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -297,7 +303,6 @@ func (o *ApplyOptions) Run(f cmdutil.Factory, cmd *cobra.Command) error {
|
|||
|
||||
encoder := scheme.DefaultJSONEncoder()
|
||||
deserializer := scheme.Codecs.UniversalDeserializer()
|
||||
mapper := r.Mapper().RESTMapper
|
||||
|
||||
visitedUids := sets.NewString()
|
||||
visitedNamespaces := sets.NewString()
|
||||
|
@ -382,12 +387,16 @@ func (o *ApplyOptions) Run(f cmdutil.Factory, cmd *cobra.Command) error {
|
|||
return err
|
||||
}
|
||||
helper := resource.NewHelper(info.Client, info.Mapping)
|
||||
dynamicClient, err := f.DynamicClient()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
patcher := &patcher{
|
||||
encoder: encoder,
|
||||
decoder: deserializer,
|
||||
mapping: info.Mapping,
|
||||
helper: helper,
|
||||
clientFunc: f.UnstructuredClientForMapping,
|
||||
dynamicClient: dynamicClient,
|
||||
clientsetFunc: f.ClientSet,
|
||||
overwrite: o.Overwrite,
|
||||
backOff: clockwork.NewRealClock(),
|
||||
|
@ -470,9 +479,14 @@ func (o *ApplyOptions) Run(f cmdutil.Factory, cmd *cobra.Command) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
dynamicClient, err := f.DynamicClient()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
p := pruner{
|
||||
mapper: mapper,
|
||||
clientFunc: f.UnstructuredClientForMapping,
|
||||
dynamicClient: dynamicClient,
|
||||
clientsetFunc: f.ClientSet,
|
||||
|
||||
labelSelector: o.Selector,
|
||||
|
@ -560,7 +574,7 @@ func getRESTMappings(mapper meta.RESTMapper, pruneResources *[]pruneResource) (n
|
|||
|
||||
type pruner struct {
|
||||
mapper meta.RESTMapper
|
||||
clientFunc resource.ClientMapperFunc
|
||||
dynamicClient dynamic.DynamicInterface
|
||||
clientsetFunc func() (internalclientset.Interface, error)
|
||||
|
||||
visitedUids sets.String
|
||||
|
@ -577,24 +591,17 @@ type pruner struct {
|
|||
}
|
||||
|
||||
func (p *pruner) prune(f cmdutil.Factory, namespace string, mapping *meta.RESTMapping, includeUninitialized bool) error {
|
||||
c, err := p.clientFunc(mapping)
|
||||
objList, err := p.dynamicClient.Resource(mapping.GroupVersionKind.GroupVersion().WithResource(mapping.Resource)).
|
||||
Namespace(namespace).
|
||||
List(metav1.ListOptions{
|
||||
LabelSelector: p.labelSelector,
|
||||
FieldSelector: p.fieldSelector,
|
||||
IncludeUninitialized: includeUninitialized,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
objList, err := resource.NewHelper(c, mapping).List(
|
||||
namespace,
|
||||
mapping.GroupVersionKind.Version,
|
||||
false,
|
||||
&metav1.ListOptions{
|
||||
LabelSelector: p.labelSelector,
|
||||
FieldSelector: p.fieldSelector,
|
||||
IncludeUninitialized: includeUninitialized,
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
objs, err := meta.ExtractList(objList)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -635,20 +642,12 @@ func (p *pruner) prune(f cmdutil.Factory, namespace string, mapping *meta.RESTMa
|
|||
}
|
||||
|
||||
func (p *pruner) delete(namespace, name string, mapping *meta.RESTMapping, scaleClient scaleclient.ScalesGetter) error {
|
||||
c, err := p.clientFunc(mapping)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return runDelete(namespace, name, mapping, c, nil, p.cascade, p.gracePeriod, p.clientsetFunc, scaleClient)
|
||||
return runDelete(namespace, name, mapping, p.dynamicClient, p.cascade, p.gracePeriod, p.clientsetFunc, scaleClient)
|
||||
}
|
||||
|
||||
func runDelete(namespace, name string, mapping *meta.RESTMapping, c resource.RESTClient, helper *resource.Helper, cascade bool, gracePeriod int, clientsetFunc func() (internalclientset.Interface, error), scaleClient scaleclient.ScalesGetter) error {
|
||||
func runDelete(namespace, name string, mapping *meta.RESTMapping, c dynamic.DynamicInterface, cascade bool, gracePeriod int, clientsetFunc func() (internalclientset.Interface, error), scaleClient scaleclient.ScalesGetter) error {
|
||||
if !cascade {
|
||||
if helper == nil {
|
||||
helper = resource.NewHelper(c, mapping)
|
||||
}
|
||||
return helper.Delete(namespace, name)
|
||||
return c.Resource(mapping.GroupVersionKind.GroupVersion().WithResource(mapping.Resource)).Namespace(namespace).Delete(name, nil)
|
||||
}
|
||||
cs, err := clientsetFunc()
|
||||
if err != nil {
|
||||
|
@ -659,7 +658,7 @@ func runDelete(namespace, name string, mapping *meta.RESTMapping, c resource.RES
|
|||
if _, ok := err.(*kubectl.NoSuchReaperError); !ok {
|
||||
return err
|
||||
}
|
||||
return resource.NewHelper(c, mapping).Delete(namespace, name)
|
||||
return c.Resource(mapping.GroupVersionKind.GroupVersion().WithResource(mapping.Resource)).Namespace(namespace).Delete(name, nil)
|
||||
}
|
||||
var options *metav1.DeleteOptions
|
||||
if gracePeriod >= 0 {
|
||||
|
@ -672,11 +671,7 @@ func runDelete(namespace, name string, mapping *meta.RESTMapping, c resource.RES
|
|||
}
|
||||
|
||||
func (p *patcher) delete(namespace, name string) error {
|
||||
c, err := p.clientFunc(p.mapping)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return runDelete(namespace, name, p.mapping, c, p.helper, p.cascade, p.gracePeriod, p.clientsetFunc, p.scaleClient)
|
||||
return runDelete(namespace, name, p.mapping, p.dynamicClient, p.cascade, p.gracePeriod, p.clientsetFunc, p.scaleClient)
|
||||
}
|
||||
|
||||
type patcher struct {
|
||||
|
@ -685,7 +680,7 @@ type patcher struct {
|
|||
|
||||
mapping *meta.RESTMapping
|
||||
helper *resource.Helper
|
||||
clientFunc resource.ClientMapperFunc
|
||||
dynamicClient dynamic.DynamicInterface
|
||||
clientsetFunc func() (internalclientset.Interface, error)
|
||||
|
||||
overwrite bool
|
||||
|
|
|
@ -146,7 +146,7 @@ func (p *AttachOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, argsIn [
|
|||
}
|
||||
|
||||
builder := f.NewBuilder().
|
||||
Internal(legacyscheme.Scheme).
|
||||
WithScheme(legacyscheme.Scheme).
|
||||
NamespaceParam(namespace).DefaultNamespace()
|
||||
|
||||
switch len(argsIn) {
|
||||
|
|
|
@ -96,7 +96,7 @@ func (o *ReconcileOptions) Complete(cmd *cobra.Command, f cmdutil.Factory, args
|
|||
}
|
||||
|
||||
r := f.NewBuilder().
|
||||
Internal(legacyscheme.Scheme).
|
||||
WithScheme(legacyscheme.Scheme).
|
||||
ContinueOnError().
|
||||
NamespaceParam(namespace).DefaultNamespace().
|
||||
FilenameParam(enforceNamespace, options).
|
||||
|
|
|
@ -22,8 +22,10 @@ import (
|
|||
"github.com/golang/glog"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
autoscalingv1 "k8s.io/api/autoscaling/v1"
|
||||
"k8s.io/apimachinery/pkg/api/meta"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
autoscalingv1client "k8s.io/client-go/kubernetes/typed/autoscaling/v1"
|
||||
"k8s.io/kubernetes/pkg/api/legacyscheme"
|
||||
"k8s.io/kubernetes/pkg/kubectl"
|
||||
"k8s.io/kubernetes/pkg/kubectl/cmd/templates"
|
||||
|
@ -70,11 +72,11 @@ type AutoscaleOptions struct {
|
|||
namespace string
|
||||
dryRun bool
|
||||
builder *resource.Builder
|
||||
mapper meta.RESTMapper
|
||||
canBeAutoscaled func(kind schema.GroupKind) error
|
||||
clientForMapping func(mapping *meta.RESTMapping) (resource.RESTClient, error)
|
||||
generatorFunc func(string, *meta.RESTMapping) (kubectl.StructuredGenerator, error)
|
||||
|
||||
HPAClient autoscalingv1client.HorizontalPodAutoscalersGetter
|
||||
|
||||
genericclioptions.IOStreams
|
||||
}
|
||||
|
||||
|
@ -132,12 +134,6 @@ func (o *AutoscaleOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args
|
|||
o.createAnnotation = cmdutil.GetFlagBool(cmd, cmdutil.ApplyAnnotationsFlag)
|
||||
o.builder = f.NewBuilder()
|
||||
o.canBeAutoscaled = f.CanBeAutoscaled
|
||||
o.mapper, err = f.RESTMapper()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
o.clientForMapping = f.ClientForMapping
|
||||
o.args = args
|
||||
o.RecordFlags.Complete(f.Command(cmd, false))
|
||||
|
||||
|
@ -146,6 +142,12 @@ func (o *AutoscaleOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args
|
|||
return err
|
||||
}
|
||||
|
||||
kubeClient, err := f.KubernetesClientSet()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
o.HPAClient = kubeClient.AutoscalingV1()
|
||||
|
||||
// get the generator
|
||||
o.generatorFunc = func(name string, mapping *meta.RESTMapping) (kubectl.StructuredGenerator, error) {
|
||||
switch o.Generator {
|
||||
|
@ -199,7 +201,7 @@ func (o *AutoscaleOptions) Validate() error {
|
|||
|
||||
func (o *AutoscaleOptions) Run() error {
|
||||
r := o.builder.
|
||||
Internal(legacyscheme.Scheme).
|
||||
WithScheme(legacyscheme.Scheme).
|
||||
ContinueOnError().
|
||||
NamespaceParam(o.namespace).DefaultNamespace().
|
||||
FilenameParam(o.enforceNamespace, o.FilenameOptions).
|
||||
|
@ -231,20 +233,14 @@ func (o *AutoscaleOptions) Run() error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
hpa, ok := object.(*autoscalingv1.HorizontalPodAutoscaler)
|
||||
if !ok {
|
||||
return fmt.Errorf("generator made %T, not autoscalingv1.HorizontalPodAutoscaler", object)
|
||||
}
|
||||
|
||||
resourceMapper := &resource.Mapper{
|
||||
RESTMapper: o.mapper,
|
||||
ClientMapper: resource.ClientMapperFunc(o.clientForMapping),
|
||||
Decoder: cmdutil.InternalVersionDecoder(),
|
||||
}
|
||||
hpa, err := resourceMapper.InfoForObject(object, legacyscheme.Scheme, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := o.Recorder.Record(hpa.Object); err != nil {
|
||||
if err := o.Recorder.Record(hpa); err != nil {
|
||||
glog.V(4).Infof("error recording current command: %v", err)
|
||||
}
|
||||
object = hpa.Object
|
||||
|
||||
if o.dryRun {
|
||||
count++
|
||||
|
@ -253,14 +249,14 @@ func (o *AutoscaleOptions) Run() error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return printer.PrintObj(cmdutil.AsDefaultVersionedOrOriginal(hpa.Object, hpa.Mapping), o.Out)
|
||||
return printer.PrintObj(hpa, o.Out)
|
||||
}
|
||||
|
||||
if err := kubectl.CreateOrUpdateAnnotation(o.createAnnotation, hpa.Object, cmdutil.InternalVersionJSONEncoder()); err != nil {
|
||||
if err := kubectl.CreateOrUpdateAnnotation(o.createAnnotation, hpa, cmdutil.InternalVersionJSONEncoder()); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = resource.NewHelper(hpa.Client, hpa.Mapping).Create(o.namespace, false, object)
|
||||
actualHPA, err := o.HPAClient.HorizontalPodAutoscalers(o.namespace).Create(hpa)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -270,7 +266,7 @@ func (o *AutoscaleOptions) Run() error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return printer.PrintObj(cmdutil.AsDefaultVersionedOrOriginal(info.Object, hpa.Mapping), o.Out)
|
||||
return printer.PrintObj(actualHPA, o.Out)
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
|
@ -204,7 +204,7 @@ func (o *CertificateOptions) RunCertificateDeny(force bool) error {
|
|||
func (options *CertificateOptions) modifyCertificateCondition(builder *resource.Builder, clientSet internalclientset.Interface, force bool, modify func(csr *certificates.CertificateSigningRequest) (*certificates.CertificateSigningRequest, bool)) error {
|
||||
var found int
|
||||
r := builder.
|
||||
Internal(legacyscheme.Scheme).
|
||||
WithScheme(legacyscheme.Scheme).
|
||||
ContinueOnError().
|
||||
FilenameParam(false, &options.FilenameOptions).
|
||||
ResourceNames("certificatesigningrequest", options.csrNames...).
|
||||
|
|
|
@ -96,7 +96,7 @@ func (o *ClusterInfoOptions) Run() error {
|
|||
|
||||
// TODO use generalized labels once they are implemented (#341)
|
||||
b := o.Builder.
|
||||
Internal(legacyscheme.Scheme).
|
||||
WithScheme(legacyscheme.Scheme).
|
||||
NamespaceParam(o.Namespace).DefaultNamespace().
|
||||
LabelSelectorParam("kubernetes.io/cluster-service=true").
|
||||
ResourceTypeOrNameArgs(false, []string{"services"}...).
|
||||
|
|
|
@ -129,7 +129,7 @@ func (o *ConvertOptions) Complete(f cmdutil.Factory, cmd *cobra.Command) (err er
|
|||
|
||||
// build the builder
|
||||
o.builder = f.NewBuilder().
|
||||
Internal(scheme.Scheme).
|
||||
WithScheme(scheme.Scheme).
|
||||
LocalParam(o.local)
|
||||
if !o.local {
|
||||
schema, err := f.Validator(cmdutil.GetFlagBool(cmd, "validate"))
|
||||
|
|
|
@ -41,6 +41,7 @@ go_library(
|
|||
"//vendor/k8s.io/api/rbac/v1: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/runtime:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library",
|
||||
|
|
|
@ -29,6 +29,7 @@ import (
|
|||
|
||||
"github.com/golang/glog"
|
||||
"k8s.io/apimachinery/pkg/api/meta"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
kruntime "k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/kubernetes/pkg/api/legacyscheme"
|
||||
|
@ -404,29 +405,29 @@ func RunCreateSubcommand(f cmdutil.Factory, options *CreateSubcommandOptions) er
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
client, err := f.ClientForMapping(mapping)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
resourceMapper := &resource.Mapper{
|
||||
RESTMapper: mapper,
|
||||
ClientMapper: resource.ClientMapperFunc(f.ClientForMapping),
|
||||
}
|
||||
info, err := resourceMapper.InfoForObject(obj, legacyscheme.Scheme, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := kubectl.CreateOrUpdateAnnotation(options.CreateAnnotation, info.Object, cmdutil.InternalVersionJSONEncoder()); err != nil {
|
||||
|
||||
if err := kubectl.CreateOrUpdateAnnotation(options.CreateAnnotation, obj, cmdutil.InternalVersionJSONEncoder()); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
obj, err = resource.NewHelper(client, mapping).Create(namespace, false, info.Object)
|
||||
asUnstructured := &unstructured.Unstructured{}
|
||||
if err := legacyscheme.Scheme.Convert(obj, asUnstructured, nil); err != nil {
|
||||
return err
|
||||
}
|
||||
dynamicClient, err := f.DynamicClient()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if mapping.Scope.Name() == meta.RESTScopeNameRoot {
|
||||
namespace = ""
|
||||
}
|
||||
actualObject, err := dynamicClient.Resource(mapping.GroupVersionKind.GroupVersion().WithResource(mapping.Resource)).Namespace(namespace).Create(asUnstructured)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// ensure we pass a versioned object to the printer
|
||||
obj = cmdutil.AsDefaultVersionedOrOriginal(info.Object, info.Mapping)
|
||||
obj = actualObject
|
||||
} else {
|
||||
if meta, err := meta.Accessor(obj); err == nil && nsOverriden {
|
||||
meta.SetNamespace(namespace)
|
||||
|
|
|
@ -17,41 +17,16 @@ limitations under the License.
|
|||
package create
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
"k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/client-go/rest/fake"
|
||||
"k8s.io/kubernetes/pkg/api/legacyscheme"
|
||||
cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing"
|
||||
"k8s.io/kubernetes/pkg/kubectl/genericclioptions"
|
||||
"k8s.io/kubernetes/pkg/kubectl/scheme"
|
||||
)
|
||||
|
||||
func TestCreateQuota(t *testing.T) {
|
||||
resourceQuotaObject := &v1.ResourceQuota{}
|
||||
resourceQuotaObject.Name = "my-quota"
|
||||
tf := cmdtesting.NewTestFactory()
|
||||
defer tf.Cleanup()
|
||||
|
||||
codec := legacyscheme.Codecs.LegacyCodec(scheme.Versions...)
|
||||
ns := legacyscheme.Codecs
|
||||
|
||||
tf.Client = &fake.RESTClient{
|
||||
GroupVersion: schema.GroupVersion{Version: "v1"},
|
||||
NegotiatedSerializer: ns,
|
||||
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
|
||||
switch p, m := req.URL.Path, req.Method; {
|
||||
case p == "/namespaces/test/resourcequotas" && m == "POST":
|
||||
return &http.Response{StatusCode: 201, Header: defaultHeader(), Body: objBody(codec, resourceQuotaObject)}, nil
|
||||
default:
|
||||
t.Fatalf("unexpected request: %#v\n%#v", req.URL, req)
|
||||
return nil, nil
|
||||
}
|
||||
}),
|
||||
}
|
||||
tf.Namespace = "test"
|
||||
|
||||
tests := map[string]struct {
|
||||
flags []string
|
||||
|
@ -75,6 +50,12 @@ func TestCreateQuota(t *testing.T) {
|
|||
},
|
||||
}
|
||||
for name, test := range tests {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
tf := cmdtesting.NewTestFactory()
|
||||
defer tf.Cleanup()
|
||||
|
||||
tf.Namespace = "test"
|
||||
|
||||
ioStreams, _, buf, _ := genericclioptions.NewTestIOStreams()
|
||||
cmd := NewCmdCreateQuota(tf, ioStreams)
|
||||
cmd.Flags().Parse(test.flags)
|
||||
|
@ -84,5 +65,6 @@ func TestCreateQuota(t *testing.T) {
|
|||
if buf.String() != test.expectedOutput {
|
||||
t.Errorf("%s: expected output: %s, but got: %s", name, test.expectedOutput, buf.String())
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -174,7 +174,11 @@ func (o *DeleteOptions) Complete(f cmdutil.Factory, out, errOut io.Writer, args
|
|||
return err
|
||||
}
|
||||
o.Result = r
|
||||
o.Mapper = r.Mapper().RESTMapper
|
||||
|
||||
o.Mapper, err = f.RESTMapper()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Set up writer
|
||||
o.Out = out
|
||||
|
|
|
@ -282,7 +282,7 @@ func (o *DrainOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []st
|
|||
}
|
||||
|
||||
builder := f.NewBuilder().
|
||||
Internal(legacyscheme.Scheme).
|
||||
WithScheme(legacyscheme.Scheme).
|
||||
NamespaceParam(o.Namespace).DefaultNamespace().
|
||||
ResourceNames("nodes", args...).
|
||||
SingleResourceType().
|
||||
|
|
|
@ -32,7 +32,7 @@ import (
|
|||
|
||||
yaml "gopkg.in/yaml.v2"
|
||||
|
||||
"k8s.io/apimachinery/pkg/api/meta"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apimachinery/pkg/util/diff"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
"k8s.io/client-go/rest/fake"
|
||||
|
@ -211,12 +211,12 @@ func TestEdit(t *testing.T) {
|
|||
tf := cmdtesting.NewTestFactory()
|
||||
defer tf.Cleanup()
|
||||
|
||||
tf.UnstructuredClientForMappingFunc = func(mapping *meta.RESTMapping) (resource.RESTClient, error) {
|
||||
tf.UnstructuredClientForMappingFunc = func(gv schema.GroupVersion) (resource.RESTClient, error) {
|
||||
versionedAPIPath := ""
|
||||
if mapping.GroupVersionKind.Group == "" {
|
||||
versionedAPIPath = "/api/" + mapping.GroupVersionKind.Version
|
||||
if gv.Group == "" {
|
||||
versionedAPIPath = "/api/" + gv.Version
|
||||
} else {
|
||||
versionedAPIPath = "/apis/" + mapping.GroupVersionKind.Group + "/" + mapping.GroupVersionKind.Version
|
||||
versionedAPIPath = "/apis/" + gv.Group + "/" + gv.Version
|
||||
}
|
||||
return &fake.RESTClient{
|
||||
VersionedAPIPath: versionedAPIPath,
|
||||
|
|
|
@ -24,9 +24,12 @@ import (
|
|||
"github.com/spf13/cobra"
|
||||
|
||||
"k8s.io/apimachinery/pkg/api/meta"
|
||||
"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"
|
||||
"k8s.io/kubernetes/pkg/kubectl"
|
||||
"k8s.io/kubernetes/pkg/kubectl/cmd/templates"
|
||||
|
@ -97,6 +100,7 @@ type ExposeServiceOptions struct {
|
|||
Namespace string
|
||||
Mapper meta.RESTMapper
|
||||
|
||||
DynamicClient dynamic.DynamicInterface
|
||||
Builder *resource.Builder
|
||||
|
||||
Recorder genericclioptions.Recorder
|
||||
|
@ -180,6 +184,11 @@ func (o *ExposeServiceOptions) Complete(f cmdutil.Factory, cmd *cobra.Command) e
|
|||
return err
|
||||
}
|
||||
|
||||
o.DynamicClient, err = f.DynamicClient()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
o.Generators = f.Generators
|
||||
o.Builder = f.NewBuilder()
|
||||
o.CanBeExposed = f.CanBeExposed
|
||||
|
@ -203,7 +212,7 @@ func (o *ExposeServiceOptions) Complete(f cmdutil.Factory, cmd *cobra.Command) e
|
|||
|
||||
func (o *ExposeServiceOptions) RunExpose(cmd *cobra.Command, args []string) error {
|
||||
r := o.Builder.
|
||||
Internal(legacyscheme.Scheme).
|
||||
WithScheme(legacyscheme.Scheme).
|
||||
ContinueOnError().
|
||||
NamespaceParam(o.Namespace).DefaultNamespace().
|
||||
FilenameParam(o.EnforceNamespace, &o.FilenameOptions).
|
||||
|
@ -313,33 +322,36 @@ func (o *ExposeServiceOptions) RunExpose(cmd *cobra.Command, args []string) erro
|
|||
}
|
||||
}
|
||||
|
||||
resourceMapper := &resource.Mapper{
|
||||
RESTMapper: o.Mapper,
|
||||
ClientMapper: resource.ClientMapperFunc(o.ClientForMapping),
|
||||
Decoder: cmdutil.InternalVersionDecoder(),
|
||||
}
|
||||
info, err = resourceMapper.InfoForObject(object, legacyscheme.Scheme, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := o.Recorder.Record(object); err != nil {
|
||||
glog.V(4).Infof("error recording current command: %v", err)
|
||||
}
|
||||
info.Refresh(object, true)
|
||||
|
||||
if o.DryRun {
|
||||
return o.PrintObj(object, o.Out)
|
||||
}
|
||||
if err := kubectl.CreateOrUpdateAnnotation(cmdutil.GetFlagBool(cmd, cmdutil.ApplyAnnotationsFlag), info.Object, cmdutil.InternalVersionJSONEncoder()); err != nil {
|
||||
if err := kubectl.CreateOrUpdateAnnotation(cmdutil.GetFlagBool(cmd, cmdutil.ApplyAnnotationsFlag), object, cmdutil.InternalVersionJSONEncoder()); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
asUnstructured := &unstructured.Unstructured{}
|
||||
if err := legacyscheme.Scheme.Convert(object, asUnstructured, nil); err != nil {
|
||||
return err
|
||||
}
|
||||
gvks, _, err := unstructuredscheme.NewUnstructuredObjectTyper().ObjectKinds(asUnstructured)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
objMapping, err := o.Mapper.RESTMapping(gvks[0].GroupKind(), gvks[0].Version)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Serialize the object with the annotation applied.
|
||||
object, err = resource.NewHelper(info.Client, info.Mapping).Create(o.Namespace, false, object)
|
||||
actualObject, err := o.DynamicClient.Resource(objMapping.GroupVersionKind.GroupVersion().WithResource(objMapping.Resource)).Namespace(o.Namespace).Create(asUnstructured)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return o.PrintObj(cmdutil.AsDefaultVersionedOrOriginal(info.Object, info.Mapping), o.Out)
|
||||
return o.PrintObj(actualObject, o.Out)
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
|
@ -480,8 +480,6 @@ func TestRunExposeService(t *testing.T) {
|
|||
switch p, m := req.URL.Path, req.Method; {
|
||||
case p == test.calls[m] && m == "GET":
|
||||
return &http.Response{StatusCode: test.status, Header: defaultHeader(), Body: objBody(codec, test.input)}, nil
|
||||
case p == test.calls[m] && m == "POST":
|
||||
return &http.Response{StatusCode: test.status, Header: defaultHeader(), Body: objBody(codec, test.output)}, nil
|
||||
default:
|
||||
t.Fatalf("unexpected request: %#v\n%#v", req.URL, req)
|
||||
return nil, nil
|
||||
|
|
|
@ -202,7 +202,7 @@ func (o *LogsOptions) Complete(f cmdutil.Factory, out io.Writer, cmd *cobra.Comm
|
|||
|
||||
if o.Object == nil {
|
||||
builder := f.NewBuilder().
|
||||
Internal(legacyscheme.Scheme).
|
||||
WithScheme(legacyscheme.Scheme).
|
||||
NamespaceParam(o.Namespace).DefaultNamespace().
|
||||
SingleResourceType()
|
||||
if o.ResourceArg != "" {
|
||||
|
|
|
@ -180,7 +180,7 @@ func (o *PortForwardOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, arg
|
|||
}
|
||||
|
||||
builder := f.NewBuilder().
|
||||
Internal(legacyscheme.Scheme).
|
||||
WithScheme(legacyscheme.Scheme).
|
||||
ContinueOnError().
|
||||
NamespaceParam(o.Namespace).DefaultNamespace()
|
||||
|
||||
|
|
|
@ -82,7 +82,7 @@ func RunHistory(f cmdutil.Factory, cmd *cobra.Command, out io.Writer, args []str
|
|||
}
|
||||
|
||||
r := f.NewBuilder().
|
||||
Internal(legacyscheme.Scheme).
|
||||
WithScheme(legacyscheme.Scheme).
|
||||
NamespaceParam(cmdNamespace).DefaultNamespace().
|
||||
FilenameParam(enforceNamespace, options).
|
||||
ResourceTypeOrNameArgs(true, args...).
|
||||
|
|
|
@ -111,7 +111,7 @@ func (o *PauseConfig) CompletePause(f cmdutil.Factory, cmd *cobra.Command, args
|
|||
}
|
||||
|
||||
r := f.NewBuilder().
|
||||
Internal(legacyscheme.Scheme).
|
||||
WithScheme(legacyscheme.Scheme).
|
||||
NamespaceParam(cmdNamespace).DefaultNamespace().
|
||||
FilenameParam(enforceNamespace, &o.FilenameOptions).
|
||||
ResourceTypeOrNameArgs(true, args...).
|
||||
|
|
|
@ -119,7 +119,7 @@ func (o *ResumeConfig) CompleteResume(f cmdutil.Factory, cmd *cobra.Command, arg
|
|||
}
|
||||
|
||||
r := f.NewBuilder().
|
||||
Internal(legacyscheme.Scheme).
|
||||
WithScheme(legacyscheme.Scheme).
|
||||
NamespaceParam(cmdNamespace).DefaultNamespace().
|
||||
FilenameParam(enforceNamespace, &o.FilenameOptions).
|
||||
ResourceTypeOrNameArgs(true, args...).
|
||||
|
|
|
@ -124,7 +124,7 @@ func (o *RolloutStatusOptions) Validate(cmd *cobra.Command, args []string) error
|
|||
|
||||
func (o *RolloutStatusOptions) Run() error {
|
||||
r := o.Builder.
|
||||
Internal(legacyscheme.Scheme).
|
||||
WithScheme(legacyscheme.Scheme).
|
||||
NamespaceParam(o.Namespace).DefaultNamespace().
|
||||
FilenameParam(o.EnforceNamespace, o.FilenameOptions).
|
||||
ResourceTypeOrNameArgs(true, o.BuilderArgs...).
|
||||
|
|
|
@ -127,7 +127,7 @@ func (o *UndoOptions) CompleteUndo(f cmdutil.Factory, cmd *cobra.Command, out io
|
|||
}
|
||||
|
||||
r := f.NewBuilder().
|
||||
Internal(legacyscheme.Scheme).
|
||||
WithScheme(legacyscheme.Scheme).
|
||||
NamespaceParam(cmdNamespace).DefaultNamespace().
|
||||
FilenameParam(enforceNamespace, &o.FilenameOptions).
|
||||
ResourceTypeOrNameArgs(true, args...).
|
||||
|
|
|
@ -20,6 +20,7 @@ import (
|
|||
"fmt"
|
||||
"io"
|
||||
|
||||
"k8s.io/client-go/dynamic"
|
||||
"k8s.io/kubernetes/pkg/printers"
|
||||
|
||||
"github.com/docker/distribution/reference"
|
||||
|
@ -40,6 +41,7 @@ import (
|
|||
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
|
||||
"k8s.io/kubernetes/pkg/kubectl/genericclioptions"
|
||||
"k8s.io/kubernetes/pkg/kubectl/resource"
|
||||
"k8s.io/kubernetes/pkg/kubectl/scheme"
|
||||
"k8s.io/kubernetes/pkg/kubectl/util/i18n"
|
||||
"k8s.io/kubernetes/pkg/util/interrupt"
|
||||
uexec "k8s.io/utils/exec"
|
||||
|
@ -90,9 +92,7 @@ var (
|
|||
)
|
||||
|
||||
type RunObject struct {
|
||||
Versioned runtime.Object
|
||||
Object runtime.Object
|
||||
Kind string
|
||||
Mapping *meta.RESTMapping
|
||||
}
|
||||
|
||||
|
@ -107,6 +107,8 @@ type RunOptions struct {
|
|||
PrintObj func(runtime.Object) error
|
||||
Recorder genericclioptions.Recorder
|
||||
|
||||
DynamicClient dynamic.DynamicInterface
|
||||
|
||||
ArgsLenAtDash int
|
||||
Attach bool
|
||||
Expose bool
|
||||
|
@ -197,6 +199,11 @@ func (o *RunOptions) Complete(f cmdutil.Factory, cmd *cobra.Command) error {
|
|||
return err
|
||||
}
|
||||
|
||||
o.DynamicClient, err = f.DynamicClient()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
o.ArgsLenAtDash = cmd.ArgsLenAtDash()
|
||||
o.DryRun = cmdutil.GetFlagBool(cmd, "dry-run")
|
||||
o.Expose = cmdutil.GetFlagBool(cmd, "expose")
|
||||
|
@ -438,7 +445,7 @@ func (o *RunOptions) Run(f cmdutil.Factory, cmd *cobra.Command, args []string) e
|
|||
|
||||
}
|
||||
if runObject != nil {
|
||||
if err := o.PrintObj(runObject.Versioned); err != nil {
|
||||
if err := o.PrintObj(runObject.Object); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
@ -458,7 +465,7 @@ func (o *RunOptions) removeCreatedObjects(f cmdutil.Factory, createdObjects []*R
|
|||
return err
|
||||
}
|
||||
r := f.NewBuilder().
|
||||
Internal(legacyscheme.Scheme).
|
||||
WithScheme(legacyscheme.Scheme).
|
||||
ContinueOnError().
|
||||
NamespaceParam(namespace).DefaultNamespace().
|
||||
ResourceNames(obj.Mapping.Resource.Resource+"."+obj.Mapping.Resource.Group, name).
|
||||
|
@ -620,7 +627,7 @@ func (o *RunOptions) generateService(f cmdutil.Factory, cmd *cobra.Command, serv
|
|||
return nil, err
|
||||
}
|
||||
|
||||
if err := o.PrintObj(runObject.Versioned); err != nil {
|
||||
if err := o.PrintObj(runObject.Object); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// separate yaml objects
|
||||
|
@ -648,60 +655,45 @@ func (o *RunOptions) createGeneratedObject(f cmdutil.Factory, cmd *cobra.Command
|
|||
return nil, err
|
||||
}
|
||||
// run has compiled knowledge of the thing is is creating
|
||||
groupVersionKinds, _, err := legacyscheme.Scheme.ObjectKinds(obj)
|
||||
gvks, _, err := scheme.Scheme.ObjectKinds(obj)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
mapping, err := mapper.RESTMapping(gvks[0].GroupKind(), gvks[0].Version)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
groupVersionKind := groupVersionKinds[0]
|
||||
|
||||
if len(overrides) > 0 {
|
||||
codec := runtime.NewCodec(cmdutil.InternalVersionJSONEncoder(), cmdutil.InternalVersionDecoder())
|
||||
codec := runtime.NewCodec(scheme.DefaultJSONEncoder(), scheme.Codecs.UniversalDecoder(scheme.Registry.RegisteredGroupVersions()...))
|
||||
obj, err = cmdutil.Merge(codec, obj, overrides)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
mapping, err := mapper.RESTMapping(groupVersionKind.GroupKind(), groupVersionKind.Version)
|
||||
if err != nil {
|
||||
if err := o.Recorder.Record(obj); err != nil {
|
||||
glog.V(4).Infof("error recording current command: %v", err)
|
||||
}
|
||||
|
||||
actualObj := obj
|
||||
if !o.DryRun {
|
||||
if err := kubectl.CreateOrUpdateAnnotation(cmdutil.GetFlagBool(cmd, cmdutil.ApplyAnnotationsFlag), obj, scheme.DefaultJSONEncoder()); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
client, err := f.ClientForMapping(mapping)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := o.Recorder.Record(obj); err != nil {
|
||||
glog.V(4).Infof("error recording current command: %v", err)
|
||||
}
|
||||
|
||||
versioned := obj
|
||||
if !o.DryRun {
|
||||
resourceMapper := &resource.Mapper{
|
||||
RESTMapper: mapper,
|
||||
ClientMapper: resource.ClientMapperFunc(f.ClientForMapping),
|
||||
Decoder: cmdutil.InternalVersionDecoder(),
|
||||
}
|
||||
info, err := resourceMapper.InfoForObject(obj, legacyscheme.Scheme, nil)
|
||||
actualObj, err = resource.NewHelper(client, mapping).Create(namespace, false, obj)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := kubectl.CreateOrUpdateAnnotation(cmdutil.GetFlagBool(cmd, cmdutil.ApplyAnnotationsFlag), info.Object, cmdutil.InternalVersionJSONEncoder()); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
actualObj = cmdutil.AsDefaultVersionedOrOriginal(actualObj, mapping)
|
||||
|
||||
obj, err = resource.NewHelper(client, mapping).Create(namespace, false, info.Object)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
versioned = cmdutil.AsDefaultVersionedOrOriginal(info.Object, info.Mapping)
|
||||
}
|
||||
return &RunObject{
|
||||
Versioned: versioned,
|
||||
Object: obj,
|
||||
Kind: groupVersionKind.Kind,
|
||||
Object: actualObj,
|
||||
Mapping: mapping,
|
||||
}, nil
|
||||
}
|
||||
|
|
|
@ -33,7 +33,6 @@ go_library(
|
|||
"//vendor/github.com/spf13/cobra:go_default_library",
|
||||
"//vendor/k8s.io/api/core/v1:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/types:go_default_library",
|
||||
|
|
|
@ -241,7 +241,7 @@ func (o *EnvOptions) RunEnv() error {
|
|||
|
||||
if len(o.From) != 0 {
|
||||
b := o.builder().
|
||||
Internal(legacyscheme.Scheme).
|
||||
WithScheme(legacyscheme.Scheme).
|
||||
LocalParam(o.Local).
|
||||
ContinueOnError().
|
||||
NamespaceParam(o.namespace).DefaultNamespace().
|
||||
|
@ -309,7 +309,7 @@ func (o *EnvOptions) RunEnv() error {
|
|||
}
|
||||
|
||||
b := o.builder().
|
||||
Internal(legacyscheme.Scheme).
|
||||
WithScheme(legacyscheme.Scheme).
|
||||
LocalParam(o.Local).
|
||||
ContinueOnError().
|
||||
NamespaceParam(o.namespace).DefaultNamespace().
|
||||
|
|
|
@ -161,7 +161,7 @@ func (o *SetImageOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args [
|
|||
|
||||
includeUninitialized := cmdutil.ShouldIncludeUninitialized(cmd, false)
|
||||
builder := f.NewBuilder().
|
||||
Internal(legacyscheme.Scheme).
|
||||
WithScheme(legacyscheme.Scheme).
|
||||
LocalParam(o.Local).
|
||||
ContinueOnError().
|
||||
NamespaceParam(cmdNamespace).DefaultNamespace().
|
||||
|
|
|
@ -173,7 +173,7 @@ func (o *SetResourcesOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, ar
|
|||
|
||||
includeUninitialized := cmdutil.ShouldIncludeUninitialized(cmd, false)
|
||||
builder := f.NewBuilder().
|
||||
Internal(legacyscheme.Scheme).
|
||||
WithScheme(legacyscheme.Scheme).
|
||||
LocalParam(o.Local).
|
||||
ContinueOnError().
|
||||
NamespaceParam(cmdNamespace).DefaultNamespace().
|
||||
|
|
|
@ -146,7 +146,7 @@ func (o *SetSelectorOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, arg
|
|||
|
||||
includeUninitialized := cmdutil.ShouldIncludeUninitialized(cmd, false)
|
||||
o.builder = f.NewBuilder().
|
||||
Internal(legacyscheme.Scheme).
|
||||
WithScheme(legacyscheme.Scheme).
|
||||
LocalParam(o.local).
|
||||
ContinueOnError().
|
||||
NamespaceParam(cmdNamespace).DefaultNamespace().
|
||||
|
|
|
@ -152,7 +152,7 @@ func (o *SetServiceAccountOptions) Complete(f cmdutil.Factory, cmd *cobra.Comman
|
|||
resources := args[:len(args)-1]
|
||||
includeUninitialized := cmdutil.ShouldIncludeUninitialized(cmd, false)
|
||||
builder := f.NewBuilder().
|
||||
Internal(legacyscheme.Scheme).
|
||||
WithScheme(legacyscheme.Scheme).
|
||||
LocalParam(o.local).
|
||||
ContinueOnError().
|
||||
NamespaceParam(cmdNamespace).DefaultNamespace().
|
||||
|
|
|
@ -138,7 +138,7 @@ func (o *SubjectOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []
|
|||
|
||||
includeUninitialized := cmdutil.ShouldIncludeUninitialized(cmd, false)
|
||||
builder := f.NewBuilder().
|
||||
Internal(legacyscheme.Scheme).
|
||||
WithScheme(legacyscheme.Scheme).
|
||||
LocalParam(o.Local).
|
||||
ContinueOnError().
|
||||
NamespaceParam(o.namespace).DefaultNamespace().
|
||||
|
|
|
@ -172,7 +172,7 @@ func (o *TaintOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []st
|
|||
return cmdutil.UsageErrorf(cmd, err.Error())
|
||||
}
|
||||
o.builder = f.NewBuilder().
|
||||
Internal(legacyscheme.Scheme).
|
||||
WithScheme(legacyscheme.Scheme).
|
||||
ContinueOnError().
|
||||
NamespaceParam(namespace).DefaultNamespace()
|
||||
if o.selector != "" {
|
||||
|
|
|
@ -24,11 +24,12 @@ go_library(
|
|||
"//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/api/meta/testrestmapper: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/runtime:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library",
|
||||
"//vendor/k8s.io/client-go/discovery:go_default_library",
|
||||
"//vendor/k8s.io/client-go/dynamic:go_default_library",
|
||||
"//vendor/k8s.io/client-go/dynamic/fake: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/rest/fake:go_default_library",
|
||||
|
|
|
@ -30,11 +30,12 @@ import (
|
|||
"k8s.io/apimachinery/pkg/api/meta"
|
||||
"k8s.io/apimachinery/pkg/api/meta/testrestmapper"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apimachinery/pkg/runtime/serializer"
|
||||
"k8s.io/client-go/discovery"
|
||||
"k8s.io/client-go/dynamic"
|
||||
fakedynamic "k8s.io/client-go/dynamic/fake"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
restclient "k8s.io/client-go/rest"
|
||||
"k8s.io/client-go/rest/fake"
|
||||
|
@ -241,10 +242,11 @@ type TestFactory struct {
|
|||
Namespace string
|
||||
ClientConfigVal *restclient.Config
|
||||
CommandVal string
|
||||
FakeDynamicClient *fakedynamic.FakeDynamicClient
|
||||
|
||||
tempConfigFile *os.File
|
||||
|
||||
UnstructuredClientForMappingFunc func(mapping *meta.RESTMapping) (resource.RESTClient, error)
|
||||
UnstructuredClientForMappingFunc resource.FakeClientFunc
|
||||
OpenAPISchemaFunc func() (openapi.Resources, error)
|
||||
}
|
||||
|
||||
|
@ -254,6 +256,7 @@ func NewTestFactory() *TestFactory {
|
|||
config, configFile := defaultFakeClientConfig()
|
||||
return &TestFactory{
|
||||
Factory: cmdutil.NewFactory(config),
|
||||
FakeDynamicClient: fakedynamic.NewSimpleDynamicClient(legacyscheme.Scheme),
|
||||
tempConfigFile: configFile,
|
||||
}
|
||||
}
|
||||
|
@ -309,7 +312,7 @@ func (f *TestFactory) ClientForMapping(mapping *meta.RESTMapping) (resource.REST
|
|||
|
||||
func (f *TestFactory) UnstructuredClientForMapping(mapping *meta.RESTMapping) (resource.RESTClient, error) {
|
||||
if f.UnstructuredClientForMappingFunc != nil {
|
||||
return f.UnstructuredClientForMappingFunc(mapping)
|
||||
return f.UnstructuredClientForMappingFunc(mapping.GroupVersionKind.GroupVersion())
|
||||
}
|
||||
return f.UnstructuredClient, nil
|
||||
}
|
||||
|
@ -340,17 +343,17 @@ func (f *TestFactory) Command(*cobra.Command, bool) string {
|
|||
func (f *TestFactory) NewBuilder() *resource.Builder {
|
||||
mapper, err := f.RESTMapper()
|
||||
|
||||
return resource.NewBuilder(
|
||||
&resource.Mapper{
|
||||
RESTMapper: mapper,
|
||||
ClientMapper: resource.ClientMapperFunc(f.ClientForMapping),
|
||||
Decoder: cmdutil.InternalVersionDecoder(),
|
||||
},
|
||||
&resource.Mapper{
|
||||
RESTMapper: mapper,
|
||||
ClientMapper: resource.ClientMapperFunc(f.UnstructuredClientForMapping),
|
||||
Decoder: unstructured.UnstructuredJSONScheme,
|
||||
return resource.NewFakeBuilder(
|
||||
func(version schema.GroupVersion) (resource.RESTClient, error) {
|
||||
if f.UnstructuredClientForMappingFunc != nil {
|
||||
return f.UnstructuredClientForMappingFunc(version)
|
||||
}
|
||||
if f.UnstructuredClient != nil {
|
||||
return f.UnstructuredClient, nil
|
||||
}
|
||||
return f.Client, nil
|
||||
},
|
||||
mapper,
|
||||
f.CategoryExpander(),
|
||||
).AddError(err)
|
||||
}
|
||||
|
@ -402,6 +405,13 @@ func (f *TestFactory) ClientSet() (internalclientset.Interface, error) {
|
|||
return clientset, nil
|
||||
}
|
||||
|
||||
func (f *TestFactory) DynamicClient() (dynamic.DynamicInterface, error) {
|
||||
if f.FakeDynamicClient != nil {
|
||||
return f.FakeDynamicClient, nil
|
||||
}
|
||||
return f.Factory.DynamicClient()
|
||||
}
|
||||
|
||||
func (f *TestFactory) RESTClient() (*restclient.RESTClient, error) {
|
||||
// Swap out the HTTP client out of the client with the fake's version.
|
||||
fakeClient := f.Client.(*fake.RESTClient)
|
||||
|
|
|
@ -66,7 +66,6 @@ type EditOptions struct {
|
|||
|
||||
cmdutil.ValidateOptions
|
||||
|
||||
ResourceMapper *resource.Mapper
|
||||
OriginalResult *resource.Result
|
||||
|
||||
EditMode EditMode
|
||||
|
|
|
@ -33,6 +33,7 @@ import (
|
|||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apimachinery/pkg/watch"
|
||||
"k8s.io/client-go/discovery"
|
||||
"k8s.io/client-go/dynamic"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
restclient "k8s.io/client-go/rest"
|
||||
scaleclient "k8s.io/client-go/scale"
|
||||
|
@ -92,6 +93,9 @@ type ClientAccessFactory interface {
|
|||
// ClientSet gives you back an internal, generated clientset
|
||||
ClientSet() (internalclientset.Interface, error)
|
||||
|
||||
// DynamicClient returns a dynamic client ready for use
|
||||
DynamicClient() (dynamic.DynamicInterface, error)
|
||||
|
||||
// KubernetesClientSet gives you back an external clientset
|
||||
KubernetesClientSet() (*kubernetes.Clientset, error)
|
||||
|
||||
|
|
|
@ -22,7 +22,6 @@ import (
|
|||
"os"
|
||||
|
||||
"k8s.io/apimachinery/pkg/api/meta"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/client-go/dynamic"
|
||||
scaleclient "k8s.io/client-go/scale"
|
||||
"k8s.io/kubernetes/pkg/kubectl"
|
||||
|
@ -46,24 +45,12 @@ func NewBuilderFactory(clientAccessFactory ClientAccessFactory, objectMappingFac
|
|||
|
||||
// NewBuilder returns a new resource builder for structured api objects.
|
||||
func (f *ring2Factory) NewBuilder() *resource.Builder {
|
||||
clientMapperFunc := resource.ClientMapperFunc(f.objectMappingFactory.ClientForMapping)
|
||||
mapper, mapperErr := f.objectMappingFactory.RESTMapper()
|
||||
|
||||
unstructuredClientMapperFunc := resource.ClientMapperFunc(f.objectMappingFactory.UnstructuredClientForMapping)
|
||||
|
||||
categoryExpander := f.objectMappingFactory.CategoryExpander()
|
||||
|
||||
return resource.NewBuilder(
|
||||
&resource.Mapper{
|
||||
RESTMapper: mapper,
|
||||
ClientMapper: clientMapperFunc,
|
||||
Decoder: InternalVersionDecoder(),
|
||||
},
|
||||
&resource.Mapper{
|
||||
RESTMapper: mapper,
|
||||
ClientMapper: unstructuredClientMapperFunc,
|
||||
Decoder: unstructured.UnstructuredJSONScheme,
|
||||
},
|
||||
f.clientAccessFactory.ClientConfig,
|
||||
mapper,
|
||||
categoryExpander,
|
||||
).AddError(mapperErr)
|
||||
}
|
||||
|
|
|
@ -52,6 +52,7 @@ import (
|
|||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
utilflag "k8s.io/apiserver/pkg/util/flag"
|
||||
"k8s.io/client-go/discovery"
|
||||
"k8s.io/client-go/dynamic"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
restclient "k8s.io/client-go/rest"
|
||||
"k8s.io/client-go/tools/clientcmd"
|
||||
|
@ -199,6 +200,13 @@ func (f *ring0Factory) ClientSet() (internalclientset.Interface, error) {
|
|||
return internalclientset.NewForConfig(clientConfig)
|
||||
}
|
||||
|
||||
func (f *ring0Factory) DynamicClient() (dynamic.DynamicInterface, error) {
|
||||
clientConfig, err := f.ClientConfig()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dynamic.NewForConfig(clientConfig)
|
||||
}
|
||||
func (f *ring0Factory) checkMatchingServerVersion() error {
|
||||
f.checkServerVersion.Do(func() {
|
||||
if !f.requireMatchedServerVersion {
|
||||
|
|
|
@ -25,7 +25,6 @@ import (
|
|||
|
||||
"k8s.io/api/core/v1"
|
||||
apiequality "k8s.io/apimachinery/pkg/api/equality"
|
||||
"k8s.io/apimachinery/pkg/api/meta"
|
||||
"k8s.io/apimachinery/pkg/api/meta/testrestmapper"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
|
@ -36,7 +35,6 @@ import (
|
|||
manualfake "k8s.io/client-go/rest/fake"
|
||||
testcore "k8s.io/client-go/testing"
|
||||
"k8s.io/kubernetes/pkg/api/legacyscheme"
|
||||
"k8s.io/kubernetes/pkg/api/testapi"
|
||||
api "k8s.io/kubernetes/pkg/apis/core"
|
||||
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/fake"
|
||||
"k8s.io/kubernetes/pkg/controller"
|
||||
|
@ -442,10 +440,10 @@ func TestMakePortsString(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func fakeClient() resource.ClientMapper {
|
||||
return resource.ClientMapperFunc(func(*meta.RESTMapping) (resource.RESTClient, error) {
|
||||
func fakeClient() resource.FakeClientFunc {
|
||||
return func(version schema.GroupVersion) (resource.RESTClient, error) {
|
||||
return &manualfake.RESTClient{}, nil
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestDiscoveryReplaceAliases(t *testing.T) {
|
||||
|
@ -473,15 +471,7 @@ func TestDiscoveryReplaceAliases(t *testing.T) {
|
|||
|
||||
ds := &fakeDiscoveryClient{}
|
||||
mapper := NewShortcutExpander(testrestmapper.TestOnlyStaticRESTMapper(legacyscheme.Registry, legacyscheme.Scheme), ds)
|
||||
b := resource.NewBuilder(
|
||||
&resource.Mapper{
|
||||
RESTMapper: mapper,
|
||||
ClientMapper: fakeClient(),
|
||||
Decoder: testapi.Default.Codec(),
|
||||
},
|
||||
nil,
|
||||
categories.LegacyCategoryExpander,
|
||||
)
|
||||
b := resource.NewFakeBuilder(fakeClient(), mapper, categories.LegacyCategoryExpander)
|
||||
|
||||
for _, test := range tests {
|
||||
replaced := b.ReplaceAliases(test.arg)
|
||||
|
|
|
@ -8,6 +8,7 @@ go_library(
|
|||
name = "go_default_library",
|
||||
srcs = [
|
||||
"builder.go",
|
||||
"client.go",
|
||||
"doc.go",
|
||||
"helper.go",
|
||||
"interfaces.go",
|
||||
|
@ -29,16 +30,19 @@ go_library(
|
|||
"//vendor/k8s.io/apimachinery/pkg/api/errors: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/apis/meta/v1/unstructured/unstructuredscheme:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/fields:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/labels:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/types:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/util/errors:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/util/yaml:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/watch:go_default_library",
|
||||
"//vendor/k8s.io/client-go/dynamic:go_default_library",
|
||||
"//vendor/k8s.io/client-go/rest:go_default_library",
|
||||
],
|
||||
)
|
||||
|
@ -56,10 +60,10 @@ go_test(
|
|||
],
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//pkg/api/legacyscheme:go_default_library",
|
||||
"//pkg/apis/core/install:go_default_library",
|
||||
"//pkg/kubectl/categories:go_default_library",
|
||||
"//pkg/kubectl/scheme:go_default_library",
|
||||
"//vendor/github.com/davecgh/go-spew/spew:go_default_library",
|
||||
"//vendor/github.com/ghodss/yaml:go_default_library",
|
||||
"//vendor/github.com/stretchr/testify/assert:go_default_library",
|
||||
"//vendor/k8s.io/api/core/v1:go_default_library",
|
||||
|
|
|
@ -26,10 +26,12 @@ import (
|
|||
|
||||
"k8s.io/apimachinery/pkg/api/meta"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/unstructuredscheme"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apimachinery/pkg/runtime/serializer"
|
||||
utilerrors "k8s.io/apimachinery/pkg/util/errors"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
"k8s.io/kubernetes/pkg/kubectl/categories"
|
||||
|
@ -48,14 +50,22 @@ type Builder struct {
|
|||
categoryExpander categories.CategoryExpander
|
||||
|
||||
// mapper is set explicitly by resource builders
|
||||
mapper *Mapper
|
||||
internal *Mapper
|
||||
unstructured *Mapper
|
||||
mapper *mapper
|
||||
internal *mapper
|
||||
unstructured *mapper
|
||||
|
||||
// clientConfigFn is a function to produce a client, *if* you need one
|
||||
clientConfigFn ClientConfigFunc
|
||||
|
||||
restMapper meta.RESTMapper
|
||||
|
||||
// objectTyper is statically determinant per-command invocation based on your internal or unstructured choice
|
||||
// it does not ever need to rely upon discovery.
|
||||
objectTyper runtime.ObjectTyper
|
||||
|
||||
// codecFactory describes which codecs you want to use
|
||||
codecFactory *serializer.CodecFactory
|
||||
|
||||
// local indicates that we cannot make server calls
|
||||
local bool
|
||||
|
||||
|
@ -96,6 +106,9 @@ type Builder struct {
|
|||
export bool
|
||||
|
||||
schema validation.Schema
|
||||
|
||||
// fakeClientFn is used for testing
|
||||
fakeClientFn FakeClientFunc
|
||||
}
|
||||
|
||||
var missingResourceError = fmt.Errorf(`You must provide one or more resources by argument or filename.
|
||||
|
@ -128,13 +141,22 @@ type resourceTuple struct {
|
|||
Name string
|
||||
}
|
||||
|
||||
type FakeClientFunc func(version schema.GroupVersion) (RESTClient, error)
|
||||
|
||||
func NewFakeBuilder(fakeClientFn FakeClientFunc, restMapper meta.RESTMapper, categoryExpander categories.CategoryExpander) *Builder {
|
||||
ret := NewBuilder(nil, restMapper, categoryExpander)
|
||||
ret.fakeClientFn = fakeClientFn
|
||||
return ret
|
||||
}
|
||||
|
||||
// NewBuilder creates a builder that operates on generic objects. At least one of
|
||||
// internal or unstructured must be specified.
|
||||
// TODO: Add versioned client (although versioned is still lossy)
|
||||
func NewBuilder(internal, unstructured *Mapper, categoryExpander categories.CategoryExpander) *Builder {
|
||||
// TODO remove internal and unstructured mapper and instead have them set the negotiated serializer for use in the client
|
||||
func NewBuilder(clientConfigFn ClientConfigFunc, restMapper meta.RESTMapper, categoryExpander categories.CategoryExpander) *Builder {
|
||||
return &Builder{
|
||||
internal: internal,
|
||||
unstructured: unstructured,
|
||||
clientConfigFn: clientConfigFn,
|
||||
restMapper: restMapper,
|
||||
categoryExpander: categoryExpander,
|
||||
requireObject: true,
|
||||
}
|
||||
|
@ -194,39 +216,39 @@ func (b *Builder) FilenameParam(enforceNamespace bool, filenameOptions *Filename
|
|||
// reads and then writes an object. Use this mode in preference to Internal unless you
|
||||
// are working with Go types directly.
|
||||
func (b *Builder) Unstructured() *Builder {
|
||||
if b.unstructured == nil {
|
||||
b.errs = append(b.errs, fmt.Errorf("no unstructured mapper provided"))
|
||||
return b
|
||||
}
|
||||
if b.mapper != nil && b.mapper != b.unstructured {
|
||||
if b.mapper != nil {
|
||||
b.errs = append(b.errs, fmt.Errorf("another mapper was already selected, cannot use unstructured types"))
|
||||
return b
|
||||
}
|
||||
b.mapper = b.unstructured
|
||||
b.mapper.localFn = b.isLocal
|
||||
|
||||
b.objectTyper = unstructuredscheme.NewUnstructuredObjectTyper()
|
||||
b.mapper = &mapper{
|
||||
localFn: b.isLocal,
|
||||
restMapper: b.restMapper,
|
||||
clientFn: b.getClient,
|
||||
decoder: unstructured.UnstructuredJSONScheme,
|
||||
}
|
||||
|
||||
return b
|
||||
}
|
||||
|
||||
// Internal updates the builder so that it will convert objects off the wire
|
||||
// into the internal form if necessary. Using internal types is lossy - fields added
|
||||
// to the server will not be seen by the client code and may result in failure. Only
|
||||
// use this mode when working offline, or when generating patches to send to the server.
|
||||
// Use Unstructured if you are reading an object and performing a POST or PUT.
|
||||
func (b *Builder) Internal(typer runtime.ObjectTyper) *Builder {
|
||||
if b.internal == nil {
|
||||
b.errs = append(b.errs, fmt.Errorf("no internal mapper provided"))
|
||||
return b
|
||||
}
|
||||
if b.mapper != nil && b.mapper != b.internal {
|
||||
// WithScheme uses the scheme to manage typing, conversion (optional), and decoding. If decodingVersions
|
||||
// is empty, then you can end up with internal types. You have been warned.
|
||||
func (b *Builder) WithScheme(scheme *runtime.Scheme, decodingVersions ...schema.GroupVersion) *Builder {
|
||||
if b.mapper != nil {
|
||||
b.errs = append(b.errs, fmt.Errorf("another mapper was already selected, cannot use internal types"))
|
||||
return b
|
||||
}
|
||||
b.mapper = b.internal
|
||||
b.mapper.localFn = b.isLocal
|
||||
b.objectTyper = scheme
|
||||
codecFactory := serializer.NewCodecFactory(scheme)
|
||||
b.codecFactory = &codecFactory
|
||||
|
||||
b.mapper = &mapper{
|
||||
localFn: b.isLocal,
|
||||
restMapper: b.restMapper,
|
||||
clientFn: b.getClient,
|
||||
decoder: b.codecFactory.UniversalDecoder(decodingVersions...),
|
||||
}
|
||||
|
||||
b.objectTyper = typer
|
||||
return b
|
||||
}
|
||||
|
||||
|
@ -241,9 +263,6 @@ func (b *Builder) LocalParam(local bool) *Builder {
|
|||
// Local will avoid asking the server for results.
|
||||
func (b *Builder) Local() *Builder {
|
||||
b.local = true
|
||||
mapper := *b.mapper
|
||||
mapper.ClientMapper = DisabledClientForMapping{ClientMapper: mapper.ClientMapper}
|
||||
b.mapper = &mapper
|
||||
return b
|
||||
}
|
||||
|
||||
|
@ -252,7 +271,7 @@ func (b *Builder) isLocal() bool {
|
|||
}
|
||||
|
||||
// Mapper returns a copy of the current mapper.
|
||||
func (b *Builder) Mapper() *Mapper {
|
||||
func (b *Builder) Mapper() *mapper {
|
||||
mapper := *b.mapper
|
||||
return &mapper
|
||||
}
|
||||
|
@ -636,13 +655,13 @@ func (b *Builder) mappingFor(resourceOrKindArg string) (*meta.RESTMapping, error
|
|||
fullySpecifiedGVR, groupResource := schema.ParseResourceArg(resourceOrKindArg)
|
||||
gvk := schema.GroupVersionKind{}
|
||||
if fullySpecifiedGVR != nil {
|
||||
gvk, _ = b.mapper.RESTMapper.KindFor(*fullySpecifiedGVR)
|
||||
gvk, _ = b.mapper.restMapper.KindFor(*fullySpecifiedGVR)
|
||||
}
|
||||
if gvk.Empty() {
|
||||
gvk, _ = b.mapper.RESTMapper.KindFor(groupResource.WithVersion(""))
|
||||
gvk, _ = b.mapper.restMapper.KindFor(groupResource.WithVersion(""))
|
||||
}
|
||||
if !gvk.Empty() {
|
||||
return b.mapper.RESTMapper.RESTMapping(gvk.GroupKind(), gvk.Version)
|
||||
return b.mapper.restMapper.RESTMapping(gvk.GroupKind(), gvk.Version)
|
||||
}
|
||||
|
||||
fullySpecifiedGVK, groupKind := schema.ParseKindArg(resourceOrKindArg)
|
||||
|
@ -652,12 +671,12 @@ func (b *Builder) mappingFor(resourceOrKindArg string) (*meta.RESTMapping, error
|
|||
}
|
||||
|
||||
if !fullySpecifiedGVK.Empty() {
|
||||
if mapping, err := b.mapper.RESTMapper.RESTMapping(fullySpecifiedGVK.GroupKind(), fullySpecifiedGVK.Version); err == nil {
|
||||
if mapping, err := b.mapper.restMapper.RESTMapping(fullySpecifiedGVK.GroupKind(), fullySpecifiedGVK.Version); err == nil {
|
||||
return mapping, nil
|
||||
}
|
||||
}
|
||||
|
||||
mapping, err := b.mapper.RESTMapper.RESTMapping(groupKind, gvk.Version)
|
||||
mapping, err := b.mapper.restMapper.RESTMapping(groupKind, gvk.Version)
|
||||
if err != nil {
|
||||
// if we error out here, it is because we could not match a resource or a kind
|
||||
// for the given argument. To maintain consistency with previous behavior,
|
||||
|
@ -782,7 +801,7 @@ func (b *Builder) visitBySelector() *Result {
|
|||
|
||||
visitors := []Visitor{}
|
||||
for _, mapping := range mappings {
|
||||
client, err := b.mapper.ClientMapper.ClientForMapping(mapping)
|
||||
client, err := b.getClient(mapping.GroupVersionKind.GroupVersion())
|
||||
if err != nil {
|
||||
result.err = err
|
||||
return result
|
||||
|
@ -803,6 +822,18 @@ func (b *Builder) visitBySelector() *Result {
|
|||
return result
|
||||
}
|
||||
|
||||
func (b *Builder) getClient(gv schema.GroupVersion) (RESTClient, error) {
|
||||
if b.fakeClientFn != nil {
|
||||
return b.fakeClientFn(gv)
|
||||
}
|
||||
|
||||
if b.codecFactory != nil {
|
||||
return b.clientConfigFn.clientForGroupVersion(gv, b.codecFactory)
|
||||
}
|
||||
|
||||
return b.clientConfigFn.unstructuredClientForGroupVersion(gv)
|
||||
}
|
||||
|
||||
func (b *Builder) visitByResource() *Result {
|
||||
// if b.singleItemImplied is false, this could be by default, so double-check length
|
||||
// of resourceTuples to determine if in fact it is singleItemImplied or not
|
||||
|
@ -832,7 +863,7 @@ func (b *Builder) visitByResource() *Result {
|
|||
if _, ok := clients[s]; ok {
|
||||
continue
|
||||
}
|
||||
client, err := b.mapper.ClientMapper.ClientForMapping(mapping)
|
||||
client, err := b.getClient(mapping.GroupVersionKind.GroupVersion())
|
||||
if err != nil {
|
||||
result.err = err
|
||||
return result
|
||||
|
@ -910,7 +941,7 @@ func (b *Builder) visitByName() *Result {
|
|||
}
|
||||
mapping := mappings[0]
|
||||
|
||||
client, err := b.mapper.ClientMapper.ClientForMapping(mapping)
|
||||
client, err := b.getClient(mapping.GroupVersionKind.GroupVersion())
|
||||
if err != nil {
|
||||
result.err = err
|
||||
return result
|
||||
|
|
|
@ -47,11 +47,11 @@ import (
|
|||
"k8s.io/client-go/rest/fake"
|
||||
restclientwatch "k8s.io/client-go/rest/watch"
|
||||
utiltesting "k8s.io/client-go/util/testing"
|
||||
"k8s.io/kubernetes/pkg/api/legacyscheme"
|
||||
"k8s.io/kubernetes/pkg/kubectl/categories"
|
||||
"k8s.io/kubernetes/pkg/kubectl/scheme"
|
||||
|
||||
// install the pod scheme into the legacy scheme for test typer resolution
|
||||
"github.com/davecgh/go-spew/spew"
|
||||
_ "k8s.io/kubernetes/pkg/apis/core/install"
|
||||
)
|
||||
|
||||
|
@ -76,14 +76,14 @@ func watchBody(events ...watch.Event) string {
|
|||
return buf.String()
|
||||
}
|
||||
|
||||
func fakeClient() ClientMapper {
|
||||
return ClientMapperFunc(func(*meta.RESTMapping) (RESTClient, error) {
|
||||
func fakeClient() FakeClientFunc {
|
||||
return func(version schema.GroupVersion) (RESTClient, error) {
|
||||
return &fake.RESTClient{}, nil
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func fakeClientWith(testName string, t *testing.T, data map[string]string) ClientMapper {
|
||||
return ClientMapperFunc(func(*meta.RESTMapping) (RESTClient, error) {
|
||||
func fakeClientWith(testName string, t *testing.T, data map[string]string) FakeClientFunc {
|
||||
return func(version schema.GroupVersion) (RESTClient, error) {
|
||||
return &fake.RESTClient{
|
||||
GroupVersion: corev1GV,
|
||||
NegotiatedSerializer: serializer.DirectCodecFactory{CodecFactory: scheme.Codecs},
|
||||
|
@ -106,7 +106,7 @@ func fakeClientWith(testName string, t *testing.T, data map[string]string) Clien
|
|||
}, nil
|
||||
}),
|
||||
}, nil
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func testData() (*v1.PodList, *v1.ServiceList) {
|
||||
|
@ -272,16 +272,9 @@ func newDefaultBuilder() *Builder {
|
|||
return newDefaultBuilderWith(fakeClient())
|
||||
}
|
||||
|
||||
func newDefaultBuilderWith(client ClientMapper) *Builder {
|
||||
return NewBuilder(
|
||||
&Mapper{
|
||||
RESTMapper: restmapper,
|
||||
ClientMapper: client,
|
||||
Decoder: corev1Codec,
|
||||
},
|
||||
nil,
|
||||
categories.LegacyCategoryExpander,
|
||||
).Internal(legacyscheme.Scheme)
|
||||
func newDefaultBuilderWith(fakeClientFn FakeClientFunc) *Builder {
|
||||
return NewFakeBuilder(fakeClientFn, restmapper, categories.LegacyCategoryExpander).
|
||||
WithScheme(scheme.Scheme, scheme.Registry.RegisteredGroupVersions()...)
|
||||
}
|
||||
|
||||
func TestPathBuilderAndVersionedObjectNotDefaulted(t *testing.T) {
|
||||
|
@ -407,11 +400,11 @@ func TestPathBuilderWithMultiple(t *testing.T) {
|
|||
switch test.object.(type) {
|
||||
case *v1.Pod:
|
||||
if _, ok := v.Object.(*v1.Pod); !ok || v.Name != test.expectedNames[i] || v.Namespace != "test" {
|
||||
t.Errorf("unexpected info: %#v", v)
|
||||
t.Errorf("unexpected info: %v", spew.Sdump(v.Object))
|
||||
}
|
||||
case *v1.ReplicationController:
|
||||
if _, ok := v.Object.(*v1.ReplicationController); !ok || v.Name != test.expectedNames[i] || v.Namespace != "test" {
|
||||
t.Errorf("unexpected info: %#v", v)
|
||||
t.Errorf("unexpected info: %v", spew.Sdump(v.Object))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
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 resource
|
||||
|
||||
import (
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/client-go/dynamic"
|
||||
"k8s.io/client-go/rest"
|
||||
)
|
||||
|
||||
// TODO require negotiatedSerializer. leaving it optional lets us plumb current behavior and deal with the difference after major plumbing is complete
|
||||
func (clientConfigFn ClientConfigFunc) clientForGroupVersion(gv schema.GroupVersion, negotiatedSerializer runtime.NegotiatedSerializer) (RESTClient, error) {
|
||||
cfg, err := clientConfigFn()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if negotiatedSerializer != nil {
|
||||
cfg.ContentConfig.NegotiatedSerializer = negotiatedSerializer
|
||||
}
|
||||
cfg.GroupVersion = &gv
|
||||
if len(gv.Group) == 0 {
|
||||
cfg.APIPath = "/api"
|
||||
} else {
|
||||
cfg.APIPath = "/apis"
|
||||
}
|
||||
|
||||
return rest.RESTClientFor(cfg)
|
||||
}
|
||||
|
||||
func (clientConfigFn ClientConfigFunc) unstructuredClientForGroupVersion(gv schema.GroupVersion) (RESTClient, error) {
|
||||
cfg, err := clientConfigFn()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.ContentConfig = dynamic.ContentConfig()
|
||||
cfg.GroupVersion = &gv
|
||||
if len(gv.Group) == 0 {
|
||||
cfg.APIPath = "/api"
|
||||
} else {
|
||||
cfg.APIPath = "/apis"
|
||||
}
|
||||
|
||||
return rest.RESTClientFor(cfg)
|
||||
}
|
|
@ -17,38 +17,24 @@ limitations under the License.
|
|||
package resource
|
||||
|
||||
import (
|
||||
"k8s.io/apimachinery/pkg/api/meta"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
client "k8s.io/client-go/rest"
|
||||
"k8s.io/client-go/rest"
|
||||
)
|
||||
|
||||
type RESTMapperFunc func() (meta.RESTMapper, error)
|
||||
type ClientConfigFunc func() (*rest.Config, error)
|
||||
|
||||
// RESTClient is a client helper for dealing with RESTful resources
|
||||
// in a generic way.
|
||||
type RESTClient interface {
|
||||
Get() *client.Request
|
||||
Post() *client.Request
|
||||
Patch(types.PatchType) *client.Request
|
||||
Delete() *client.Request
|
||||
Put() *client.Request
|
||||
}
|
||||
|
||||
// ClientMapper abstracts retrieving a Client for mapped objects.
|
||||
type ClientMapper interface {
|
||||
ClientForMapping(mapping *meta.RESTMapping) (RESTClient, error)
|
||||
}
|
||||
|
||||
// ClientMapperFunc implements ClientMapper for a function
|
||||
type ClientMapperFunc func(mapping *meta.RESTMapping) (RESTClient, error)
|
||||
|
||||
// ClientForMapping implements ClientMapper
|
||||
func (f ClientMapperFunc) ClientForMapping(mapping *meta.RESTMapping) (RESTClient, error) {
|
||||
return f(mapping)
|
||||
Get() *rest.Request
|
||||
Post() *rest.Request
|
||||
Patch(types.PatchType) *rest.Request
|
||||
Delete() *rest.Request
|
||||
Put() *rest.Request
|
||||
}
|
||||
|
||||
// RequestTransform is a function that is given a chance to modify the outgoing request.
|
||||
type RequestTransform func(*client.Request)
|
||||
type RequestTransform func(*rest.Request)
|
||||
|
||||
// NewClientWithOptions wraps the provided RESTClient and invokes each transform on each
|
||||
// newly created request.
|
||||
|
@ -61,26 +47,26 @@ type clientOptions struct {
|
|||
transforms []RequestTransform
|
||||
}
|
||||
|
||||
func (c *clientOptions) modify(req *client.Request) *client.Request {
|
||||
func (c *clientOptions) modify(req *rest.Request) *rest.Request {
|
||||
for _, transform := range c.transforms {
|
||||
transform(req)
|
||||
}
|
||||
return req
|
||||
}
|
||||
|
||||
func (c *clientOptions) Get() *client.Request {
|
||||
func (c *clientOptions) Get() *rest.Request {
|
||||
return c.modify(c.c.Get())
|
||||
}
|
||||
|
||||
func (c *clientOptions) Post() *client.Request {
|
||||
func (c *clientOptions) Post() *rest.Request {
|
||||
return c.modify(c.c.Post())
|
||||
}
|
||||
func (c *clientOptions) Patch(t types.PatchType) *client.Request {
|
||||
func (c *clientOptions) Patch(t types.PatchType) *rest.Request {
|
||||
return c.modify(c.c.Patch(t))
|
||||
}
|
||||
func (c *clientOptions) Delete() *client.Request {
|
||||
func (c *clientOptions) Delete() *rest.Request {
|
||||
return c.modify(c.c.Delete())
|
||||
}
|
||||
func (c *clientOptions) Put() *client.Request {
|
||||
func (c *clientOptions) Put() *rest.Request {
|
||||
return c.modify(c.c.Put())
|
||||
}
|
||||
|
|
|
@ -27,20 +27,20 @@ import (
|
|||
|
||||
// Mapper is a convenience struct for holding references to the interfaces
|
||||
// needed to create Info for arbitrary objects.
|
||||
type Mapper struct {
|
||||
type mapper struct {
|
||||
// localFn indicates the call can't make server requests
|
||||
localFn func() bool
|
||||
|
||||
RESTMapper meta.RESTMapper
|
||||
ClientMapper ClientMapper
|
||||
Decoder runtime.Decoder
|
||||
restMapper meta.RESTMapper
|
||||
clientFn func(version schema.GroupVersion) (RESTClient, error)
|
||||
decoder runtime.Decoder
|
||||
}
|
||||
|
||||
// InfoForData creates an Info object for the given data. An error is returned
|
||||
// if any of the decoding or client lookup steps fail. Name and namespace will be
|
||||
// set into Info if the mapping's MetadataAccessor can retrieve them.
|
||||
func (m *Mapper) InfoForData(data []byte, source string) (*Info, error) {
|
||||
obj, gvk, err := m.Decoder.Decode(data, nil, nil)
|
||||
func (m *mapper) infoForData(data []byte, source string) (*Info, error) {
|
||||
obj, gvk, err := m.decoder.Decode(data, nil, nil)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to decode %q: %v", source, err)
|
||||
}
|
||||
|
@ -59,13 +59,13 @@ func (m *Mapper) InfoForData(data []byte, source string) (*Info, error) {
|
|||
}
|
||||
|
||||
if m.localFn == nil || !m.localFn() {
|
||||
mapping, err := m.RESTMapper.RESTMapping(gvk.GroupKind(), gvk.Version)
|
||||
mapping, err := m.restMapper.RESTMapping(gvk.GroupKind(), gvk.Version)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to recognize %q: %v", source, err)
|
||||
}
|
||||
ret.Mapping = mapping
|
||||
|
||||
client, err := m.ClientMapper.ClientForMapping(mapping)
|
||||
client, err := m.clientFn(gvk.GroupVersion())
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to connect to a server to handle %q: %v", mapping.Resource, err)
|
||||
}
|
||||
|
@ -78,7 +78,7 @@ func (m *Mapper) InfoForData(data []byte, source string) (*Info, error) {
|
|||
// InfoForObject creates an Info object for the given Object. An error is returned
|
||||
// if the object cannot be introspected. Name and namespace will be set into Info
|
||||
// if the mapping's MetadataAccessor can retrieve them.
|
||||
func (m *Mapper) InfoForObject(obj runtime.Object, typer runtime.ObjectTyper, preferredGVKs []schema.GroupVersionKind) (*Info, error) {
|
||||
func (m *mapper) infoForObject(obj runtime.Object, typer runtime.ObjectTyper, preferredGVKs []schema.GroupVersionKind) (*Info, error) {
|
||||
groupVersionKinds, _, err := typer.ObjectKinds(obj)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to get type info from the object %q: %v", reflect.TypeOf(obj), err)
|
||||
|
@ -101,13 +101,13 @@ func (m *Mapper) InfoForObject(obj runtime.Object, typer runtime.ObjectTyper, pr
|
|||
}
|
||||
|
||||
if m.localFn == nil || !m.localFn() {
|
||||
mapping, err := m.RESTMapper.RESTMapping(gvk.GroupKind(), gvk.Version)
|
||||
mapping, err := m.restMapper.RESTMapping(gvk.GroupKind(), gvk.Version)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to recognize %v", err)
|
||||
}
|
||||
ret.Mapping = mapping
|
||||
|
||||
client, err := m.ClientMapper.ClientForMapping(mapping)
|
||||
client, err := m.clientFn(gvk.GroupVersion())
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to connect to a server to handle %q: %v", mapping.Resource, err)
|
||||
}
|
||||
|
@ -152,13 +152,3 @@ func preferredObjectKind(possibilities []schema.GroupVersionKind, preferences []
|
|||
// Just pick the first
|
||||
return possibilities[0]
|
||||
}
|
||||
|
||||
// DisabledClientForMapping allows callers to avoid allowing remote calls when handling
|
||||
// resources.
|
||||
type DisabledClientForMapping struct {
|
||||
ClientMapper
|
||||
}
|
||||
|
||||
func (f DisabledClientForMapping) ClientForMapping(mapping *meta.RESTMapping) (RESTClient, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
|
|
@ -42,7 +42,7 @@ type Result struct {
|
|||
singleItemImplied bool
|
||||
targetsSingleItems bool
|
||||
|
||||
mapper *Mapper
|
||||
mapper *mapper
|
||||
ignoreErrors []utilerrors.Matcher
|
||||
|
||||
// populated by a call to Infos
|
||||
|
@ -77,7 +77,7 @@ func (r *Result) IgnoreErrors(fns ...ErrMatchFunc) *Result {
|
|||
}
|
||||
|
||||
// Mapper returns a copy of the builder's mapper.
|
||||
func (r *Result) Mapper() *Mapper {
|
||||
func (r *Result) Mapper() *mapper {
|
||||
return r.mapper
|
||||
}
|
||||
|
||||
|
|
|
@ -372,12 +372,12 @@ func (v ContinueOnErrorVisitor) Visit(fn VisitorFunc) error {
|
|||
type FlattenListVisitor struct {
|
||||
visitor Visitor
|
||||
typer runtime.ObjectTyper
|
||||
mapper *Mapper
|
||||
mapper *mapper
|
||||
}
|
||||
|
||||
// NewFlattenListVisitor creates a visitor that will expand list style runtime.Objects
|
||||
// into individual items and then visit them individually.
|
||||
func NewFlattenListVisitor(v Visitor, typer runtime.ObjectTyper, mapper *Mapper) Visitor {
|
||||
func NewFlattenListVisitor(v Visitor, typer runtime.ObjectTyper, mapper *mapper) Visitor {
|
||||
return FlattenListVisitor{v, typer, mapper}
|
||||
}
|
||||
|
||||
|
@ -393,7 +393,7 @@ func (v FlattenListVisitor) Visit(fn VisitorFunc) error {
|
|||
if err != nil {
|
||||
return fn(info, nil)
|
||||
}
|
||||
if errs := runtime.DecodeList(items, v.mapper.Decoder); len(errs) > 0 {
|
||||
if errs := runtime.DecodeList(items, v.mapper.decoder); len(errs) > 0 {
|
||||
return utilerrors.NewAggregate(errs)
|
||||
}
|
||||
|
||||
|
@ -404,7 +404,7 @@ func (v FlattenListVisitor) Visit(fn VisitorFunc) error {
|
|||
}
|
||||
|
||||
for i := range items {
|
||||
item, err := v.mapper.InfoForObject(items[i], v.typer, preferredGVKs)
|
||||
item, err := v.mapper.infoForObject(items[i], v.typer, preferredGVKs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -433,7 +433,7 @@ func ignoreFile(path string, extensions []string) bool {
|
|||
}
|
||||
|
||||
// FileVisitorForSTDIN return a special FileVisitor just for STDIN
|
||||
func FileVisitorForSTDIN(mapper *Mapper, schema validation.Schema) Visitor {
|
||||
func FileVisitorForSTDIN(mapper *mapper, schema validation.Schema) Visitor {
|
||||
return &FileVisitor{
|
||||
Path: constSTDINstr,
|
||||
StreamVisitor: NewStreamVisitor(nil, mapper, constSTDINstr, schema),
|
||||
|
@ -443,7 +443,7 @@ func FileVisitorForSTDIN(mapper *Mapper, schema validation.Schema) Visitor {
|
|||
// ExpandPathsToFileVisitors will return a slice of FileVisitors that will handle files from the provided path.
|
||||
// After FileVisitors open the files, they will pass an io.Reader to a StreamVisitor to do the reading. (stdin
|
||||
// is also taken care of). Paths argument also accepts a single file, and will return a single visitor
|
||||
func ExpandPathsToFileVisitors(mapper *Mapper, paths string, recursive bool, extensions []string, schema validation.Schema) ([]Visitor, error) {
|
||||
func ExpandPathsToFileVisitors(mapper *mapper, paths string, recursive bool, extensions []string, schema validation.Schema) ([]Visitor, error) {
|
||||
var visitors []Visitor
|
||||
err := filepath.Walk(paths, func(path string, fi os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
|
@ -510,17 +510,17 @@ func (v *FileVisitor) Visit(fn VisitorFunc) error {
|
|||
// a stream decoder method on runtime.Codec to properly handle this.
|
||||
type StreamVisitor struct {
|
||||
io.Reader
|
||||
*Mapper
|
||||
*mapper
|
||||
|
||||
Source string
|
||||
Schema validation.Schema
|
||||
}
|
||||
|
||||
// NewStreamVisitor is a helper function that is useful when we want to change the fields of the struct but keep calls the same.
|
||||
func NewStreamVisitor(r io.Reader, mapper *Mapper, source string, schema validation.Schema) *StreamVisitor {
|
||||
func NewStreamVisitor(r io.Reader, mapper *mapper, source string, schema validation.Schema) *StreamVisitor {
|
||||
return &StreamVisitor{
|
||||
Reader: r,
|
||||
Mapper: mapper,
|
||||
mapper: mapper,
|
||||
Source: source,
|
||||
Schema: schema,
|
||||
}
|
||||
|
@ -545,7 +545,7 @@ func (v *StreamVisitor) Visit(fn VisitorFunc) error {
|
|||
if err := ValidateSchema(ext.Raw, v.Schema); err != nil {
|
||||
return fmt.Errorf("error validating %q: %v", v.Source, err)
|
||||
}
|
||||
info, err := v.InfoForData(ext.Raw, v.Source)
|
||||
info, err := v.infoForData(ext.Raw, v.Source)
|
||||
if err != nil {
|
||||
if fnErr := fn(info, err); fnErr != nil {
|
||||
return fnErr
|
||||
|
|
Loading…
Reference in New Issue