mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-23 11:50:44 +00:00
update -o name format to kind.group/name
This commit is contained in:
parent
76e6da25fa
commit
765f9ec68b
@ -1460,7 +1460,7 @@ run_kubectl_get_tests() {
|
||||
kube::test::if_has_string "${output_message}" 'valid-pod' # pod details
|
||||
output_message=$(kubectl get pods/valid-pod -o name -w --request-timeout=1 "${kube_flags[@]}")
|
||||
kube::test::if_has_not_string "${output_message}" 'STATUS' # no headers
|
||||
kube::test::if_has_string "${output_message}" 'pods/valid-pod' # resource name
|
||||
kube::test::if_has_string "${output_message}" 'pod/valid-pod' # resource name
|
||||
output_message=$(kubectl get pods/valid-pod -o yaml -w --request-timeout=1 "${kube_flags[@]}")
|
||||
kube::test::if_has_not_string "${output_message}" 'STATUS' # no headers
|
||||
kube::test::if_has_string "${output_message}" 'name: valid-pod' # yaml
|
||||
@ -1574,6 +1574,33 @@ __EOF__
|
||||
# Post-Condition: assertion object exist
|
||||
kube::test::get_object_assert customresourcedefinitions "{{range.items}}{{$id_field}}:{{end}}" 'bars.company.com:foos.company.com:'
|
||||
|
||||
# This test ensures that the name printer is able to output a resource
|
||||
# in the proper "kind.group/resource_name" format, and that the
|
||||
# resource builder is able to resolve a GVK when a kind.group pair is given.
|
||||
kubectl "${kube_flags_with_token[@]}" create -f - << __EOF__
|
||||
{
|
||||
"kind": "CustomResourceDefinition",
|
||||
"apiVersion": "apiextensions.k8s.io/v1beta1",
|
||||
"metadata": {
|
||||
"name": "resources.mygroup.example.com"
|
||||
},
|
||||
"spec": {
|
||||
"group": "mygroup.example.com",
|
||||
"version": "v1alpha1",
|
||||
"scope": "Namespaced",
|
||||
"names": {
|
||||
"plural": "resources",
|
||||
"singular": "resource",
|
||||
"kind": "Kind",
|
||||
"listKind": "KindList"
|
||||
}
|
||||
}
|
||||
}
|
||||
__EOF__
|
||||
|
||||
# Post-Condition: assertion crd with non-matching kind and resource exists
|
||||
kube::test::get_object_assert customresourcedefinitions "{{range.items}}{{$id_field}}:{{end}}" 'bars.company.com:foos.company.com:resources.mygroup.example.com:'
|
||||
|
||||
run_non_native_resource_tests
|
||||
|
||||
# teardown
|
||||
@ -1621,6 +1648,28 @@ run_non_native_resource_tests() {
|
||||
# Test that we can list this new CustomResource (bars)
|
||||
kube::test::get_object_assert bars "{{range.items}}{{$id_field}}:{{end}}" ''
|
||||
|
||||
# Test that we can list this new CustomResource (resources)
|
||||
kube::test::get_object_assert resources "{{range.items}}{{$id_field}}:{{end}}" ''
|
||||
|
||||
# Test that we can create a new resource of type Kind
|
||||
kubectl "${kube_flags[@]}" create -f hack/testdata/CRD/resource.yaml "${kube_flags[@]}"
|
||||
|
||||
# Test that -o name returns kind.group/resourcename
|
||||
output_message=$(kubectl "${kube_flags[@]}" get resource/myobj -o name)
|
||||
kube::test::if_has_string "${output_message}" 'kind.mygroup.example.com/myobj'
|
||||
|
||||
output_message=$(kubectl "${kube_flags[@]}" get resources/myobj -o name)
|
||||
kube::test::if_has_string "${output_message}" 'kind.mygroup.example.com/myobj'
|
||||
|
||||
output_message=$(kubectl "${kube_flags[@]}" get kind.mygroup.example.com/myobj -o name)
|
||||
kube::test::if_has_string "${output_message}" 'kind.mygroup.example.com/myobj'
|
||||
|
||||
# Delete the resource with cascade.
|
||||
kubectl "${kube_flags[@]}" delete resources myobj --cascade=true
|
||||
|
||||
# Make sure it's gone
|
||||
kube::test::get_object_assert resources "{{range.items}}{{$id_field}}:{{end}}" ''
|
||||
|
||||
# Test that we can create a new resource of type Foo
|
||||
kubectl "${kube_flags[@]}" create -f hack/testdata/CRD/foo.yaml "${kube_flags[@]}"
|
||||
|
||||
@ -1649,7 +1698,7 @@ run_non_native_resource_tests() {
|
||||
kubectl "${kube_flags[@]}" get foos -o "go-template={{range .items}}{{.someField}}{{end}}" --allow-missing-template-keys=false
|
||||
kubectl "${kube_flags[@]}" get foos/test -o "go-template={{.someField}}" --allow-missing-template-keys=false
|
||||
output_message=$(kubectl "${kube_flags[@]}" get foos/test -o name)
|
||||
kube::test::if_has_string "${output_message}" 'foos/test'
|
||||
kube::test::if_has_string "${output_message}" 'foo.company.com/test'
|
||||
|
||||
# Test patching
|
||||
kube::log::status "Testing CustomResource patching"
|
||||
@ -1732,7 +1781,7 @@ run_non_native_resource_tests() {
|
||||
# Stop the watcher and the patch loop.
|
||||
kill -9 ${watch_pid}
|
||||
kill -9 ${patch_pid}
|
||||
kube::test::if_has_string "${watch_output}" 'bars/test'
|
||||
kube::test::if_has_string "${watch_output}" 'bar.company.com/test'
|
||||
|
||||
# Delete the resource without cascade.
|
||||
kubectl "${kube_flags[@]}" delete bars test --cascade=false
|
||||
|
6
hack/testdata/CRD/resource.yaml
vendored
Normal file
6
hack/testdata/CRD/resource.yaml
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
apiVersion: mygroup.example.com/v1alpha1
|
||||
kind: Kind
|
||||
metadata:
|
||||
name: myobj
|
||||
spec:
|
||||
key: value
|
@ -287,7 +287,7 @@ func (o *LabelOptions) RunLabel(f cmdutil.Factory, cmd *cobra.Command) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
if o.outputFormat != "" {
|
||||
if len(o.outputFormat) > 0 {
|
||||
return f.PrintObject(cmd, o.local, r.Mapper().RESTMapper, outputObj, o.out)
|
||||
}
|
||||
f.PrintSuccess(false, o.out, info.Mapping.Resource, info.Name, o.dryrun, dataChangeMsg)
|
||||
|
@ -64,8 +64,8 @@ func TestSetEnvLocal(t *testing.T) {
|
||||
cmd.SetOutput(buf)
|
||||
cmd.Flags().Set("output", "name")
|
||||
cmd.Flags().Set("local", "true")
|
||||
mapper, typer := f.Object()
|
||||
tf.Printer = &printers.NamePrinter{Decoders: []runtime.Decoder{codec}, Typer: typer, Mapper: mapper}
|
||||
_, typer := f.Object()
|
||||
tf.Printer = &printers.NamePrinter{Decoders: []runtime.Decoder{codec}, Typer: typer}
|
||||
|
||||
opts := EnvOptions{FilenameOptions: resource.FilenameOptions{
|
||||
Filenames: []string{"../../../../examples/storage/cassandra/cassandra-controller.yaml"}},
|
||||
@ -78,7 +78,7 @@ func TestSetEnvLocal(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
if !strings.Contains(buf.String(), "replicationcontrollers/cassandra") {
|
||||
if !strings.Contains(buf.String(), "replicationcontroller/cassandra") {
|
||||
t.Errorf("did not set env: %s", buf.String())
|
||||
}
|
||||
}
|
||||
@ -101,8 +101,8 @@ func TestSetMultiResourcesEnvLocal(t *testing.T) {
|
||||
cmd.SetOutput(buf)
|
||||
cmd.Flags().Set("output", "name")
|
||||
cmd.Flags().Set("local", "true")
|
||||
mapper, typer := f.Object()
|
||||
tf.Printer = &printers.NamePrinter{Decoders: []runtime.Decoder{codec}, Typer: typer, Mapper: mapper}
|
||||
_, typer := f.Object()
|
||||
tf.Printer = &printers.NamePrinter{Decoders: []runtime.Decoder{codec}, Typer: typer}
|
||||
|
||||
opts := EnvOptions{FilenameOptions: resource.FilenameOptions{
|
||||
Filenames: []string{"../../../../test/fixtures/pkg/kubectl/cmd/set/multi-resource-yaml.yaml"}},
|
||||
@ -116,7 +116,7 @@ func TestSetMultiResourcesEnvLocal(t *testing.T) {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
|
||||
expectedOut := "replicationcontrollers/first-rc\nreplicationcontrollers/second-rc\n"
|
||||
expectedOut := "replicationcontroller/first-rc\nreplicationcontroller/second-rc\n"
|
||||
if buf.String() != expectedOut {
|
||||
t.Errorf("expected out:\n%s\nbut got:\n%s", expectedOut, buf.String())
|
||||
}
|
||||
|
@ -63,8 +63,8 @@ func TestImageLocal(t *testing.T) {
|
||||
cmd.SetOutput(buf)
|
||||
cmd.Flags().Set("output", "name")
|
||||
cmd.Flags().Set("local", "true")
|
||||
mapper, typer := f.Object()
|
||||
tf.Printer = &printers.NamePrinter{Decoders: []runtime.Decoder{codec}, Typer: typer, Mapper: mapper}
|
||||
_, typer := f.Object()
|
||||
tf.Printer = &printers.NamePrinter{Decoders: []runtime.Decoder{codec}, Typer: typer}
|
||||
|
||||
opts := ImageOptions{FilenameOptions: resource.FilenameOptions{
|
||||
Filenames: []string{"../../../../examples/storage/cassandra/cassandra-controller.yaml"}},
|
||||
@ -80,7 +80,7 @@ func TestImageLocal(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
if !strings.Contains(buf.String(), "replicationcontrollers/cassandra") {
|
||||
if !strings.Contains(buf.String(), "replicationcontroller/cassandra") {
|
||||
t.Errorf("did not set image: %s", buf.String())
|
||||
}
|
||||
}
|
||||
@ -166,8 +166,8 @@ func TestSetMultiResourcesImageLocal(t *testing.T) {
|
||||
cmd.SetOutput(buf)
|
||||
cmd.Flags().Set("output", "name")
|
||||
cmd.Flags().Set("local", "true")
|
||||
mapper, typer := f.Object()
|
||||
tf.Printer = &printers.NamePrinter{Decoders: []runtime.Decoder{codec}, Typer: typer, Mapper: mapper}
|
||||
_, typer := f.Object()
|
||||
tf.Printer = &printers.NamePrinter{Decoders: []runtime.Decoder{codec}, Typer: typer}
|
||||
|
||||
opts := ImageOptions{FilenameOptions: resource.FilenameOptions{
|
||||
Filenames: []string{"../../../../test/fixtures/pkg/kubectl/cmd/set/multi-resource-yaml.yaml"}},
|
||||
@ -183,7 +183,7 @@ func TestSetMultiResourcesImageLocal(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
expectedOut := "replicationcontrollers/first-rc\nreplicationcontrollers/second-rc\n"
|
||||
expectedOut := "replicationcontroller/first-rc\nreplicationcontroller/second-rc\n"
|
||||
if buf.String() != expectedOut {
|
||||
t.Errorf("expected out:\n%s\nbut got:\n%s", expectedOut, buf.String())
|
||||
}
|
||||
|
@ -63,8 +63,8 @@ func TestResourcesLocal(t *testing.T) {
|
||||
cmd.SetOutput(buf)
|
||||
cmd.Flags().Set("output", "name")
|
||||
cmd.Flags().Set("local", "true")
|
||||
mapper, typer := f.Object()
|
||||
tf.Printer = &printers.NamePrinter{Decoders: []runtime.Decoder{codec}, Typer: typer, Mapper: mapper}
|
||||
_, typer := f.Object()
|
||||
tf.Printer = &printers.NamePrinter{Decoders: []runtime.Decoder{codec}, Typer: typer}
|
||||
|
||||
opts := ResourcesOptions{FilenameOptions: resource.FilenameOptions{
|
||||
Filenames: []string{"../../../../examples/storage/cassandra/cassandra-controller.yaml"}},
|
||||
@ -84,7 +84,7 @@ func TestResourcesLocal(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
if !strings.Contains(buf.String(), "replicationcontrollers/cassandra") {
|
||||
if !strings.Contains(buf.String(), "replicationcontroller/cassandra") {
|
||||
t.Errorf("did not set resources: %s", buf.String())
|
||||
}
|
||||
}
|
||||
@ -107,8 +107,8 @@ func TestSetMultiResourcesLimitsLocal(t *testing.T) {
|
||||
cmd.SetOutput(buf)
|
||||
cmd.Flags().Set("output", "name")
|
||||
cmd.Flags().Set("local", "true")
|
||||
mapper, typer := f.Object()
|
||||
tf.Printer = &printers.NamePrinter{Decoders: []runtime.Decoder{codec}, Typer: typer, Mapper: mapper}
|
||||
_, typer := f.Object()
|
||||
tf.Printer = &printers.NamePrinter{Decoders: []runtime.Decoder{codec}, Typer: typer}
|
||||
|
||||
opts := ResourcesOptions{FilenameOptions: resource.FilenameOptions{
|
||||
Filenames: []string{"../../../../test/fixtures/pkg/kubectl/cmd/set/multi-resource-yaml.yaml"}},
|
||||
@ -128,7 +128,7 @@ func TestSetMultiResourcesLimitsLocal(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
expectedOut := "replicationcontrollers/first-rc\nreplicationcontrollers/second-rc\n"
|
||||
expectedOut := "replicationcontroller/first-rc\nreplicationcontroller/second-rc\n"
|
||||
if buf.String() != expectedOut {
|
||||
t.Errorf("expected out:\n%s\nbut got:\n%s", expectedOut, buf.String())
|
||||
}
|
||||
@ -448,8 +448,8 @@ func TestSetResourcesRemote(t *testing.T) {
|
||||
testapi.Default = testapi.Groups[input.testAPIGroup]
|
||||
f, tf, _, ns := cmdtesting.NewAPIFactory()
|
||||
codec := scheme.Codecs.CodecForVersions(scheme.Codecs.LegacyCodec(groupVersion), scheme.Codecs.UniversalDecoder(groupVersion), groupVersion, groupVersion)
|
||||
mapper, typer := f.Object()
|
||||
tf.Printer = &printers.NamePrinter{Decoders: []runtime.Decoder{testapi.Default.Codec()}, Typer: typer, Mapper: mapper}
|
||||
_, typer := f.Object()
|
||||
tf.Printer = &printers.NamePrinter{Decoders: []runtime.Decoder{testapi.Default.Codec()}, Typer: typer}
|
||||
tf.Namespace = "test"
|
||||
tf.CategoryExpander = categories.LegacyCategoryExpander
|
||||
tf.Client = &fake.RESTClient{
|
||||
|
@ -335,11 +335,11 @@ func TestSelectorTest(t *testing.T) {
|
||||
cmd.Flags().Set("local", "true")
|
||||
cmd.Flags().Set("filename", "../../../../examples/storage/cassandra/cassandra-service.yaml")
|
||||
|
||||
mapper, typer := f.Object()
|
||||
tf.Printer = &printers.NamePrinter{Decoders: []runtime.Decoder{codec}, Typer: typer, Mapper: mapper}
|
||||
_, typer := f.Object()
|
||||
tf.Printer = &printers.NamePrinter{Decoders: []runtime.Decoder{codec}, Typer: typer}
|
||||
cmd.Run(cmd, []string{"environment=qa"})
|
||||
|
||||
if !strings.Contains(buf.String(), "services/cassandra") {
|
||||
if !strings.Contains(buf.String(), "service/cassandra") {
|
||||
t.Errorf("did not set selector: %s", buf.String())
|
||||
}
|
||||
}
|
||||
|
@ -116,8 +116,8 @@ func TestSetServiceAccountMultiLocal(t *testing.T) {
|
||||
cmd.SetOutput(buf)
|
||||
cmd.Flags().Set("output", "name")
|
||||
cmd.Flags().Set("local", "true")
|
||||
mapper, typer := f.Object()
|
||||
tf.Printer = &printers.NamePrinter{Decoders: []runtime.Decoder{codec}, Typer: typer, Mapper: mapper}
|
||||
_, typer := f.Object()
|
||||
tf.Printer = &printers.NamePrinter{Decoders: []runtime.Decoder{codec}, Typer: typer}
|
||||
opts := serviceAccountConfig{fileNameOptions: resource.FilenameOptions{
|
||||
Filenames: []string{"../../../../test/fixtures/pkg/kubectl/cmd/set/multi-resource-yaml.yaml"}},
|
||||
out: buf,
|
||||
@ -130,7 +130,7 @@ func TestSetServiceAccountMultiLocal(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
expectedOut := "replicationcontrollers/first-rc\nreplicationcontrollers/second-rc\n"
|
||||
expectedOut := "replicationcontroller/first-rc\nreplicationcontroller/second-rc\n"
|
||||
if buf.String() != expectedOut {
|
||||
t.Errorf("expected out:\n%s\nbut got:\n%s", expectedOut, buf.String())
|
||||
}
|
||||
|
@ -48,15 +48,12 @@ func NewBuilderFactory(clientAccessFactory ClientAccessFactory, objectMappingFac
|
||||
}
|
||||
|
||||
func (f *ring2Factory) PrinterForOptions(options *printers.PrintOptions) (printers.ResourcePrinter, error) {
|
||||
var mapper meta.RESTMapper
|
||||
var typer runtime.ObjectTyper
|
||||
|
||||
mapper, typer = f.objectMappingFactory.Object()
|
||||
_, 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)
|
||||
return printerForOptions(typer, encoder, decoders, options)
|
||||
}
|
||||
|
||||
func (f *ring2Factory) PrinterForMapping(options *printers.PrintOptions, mapping *meta.RESTMapping) (printers.ResourcePrinter, error) {
|
||||
|
@ -20,7 +20,6 @@ import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"k8s.io/apimachinery/pkg/api/meta"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/kubernetes/pkg/kubectl"
|
||||
"k8s.io/kubernetes/pkg/kubectl/cmd/templates"
|
||||
@ -84,8 +83,8 @@ func ValidateOutputArgs(cmd *cobra.Command) error {
|
||||
// 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)
|
||||
func printerForOptions(typer runtime.ObjectTyper, encoder runtime.Encoder, decoders []runtime.Decoder, options *printers.PrintOptions) (printers.ResourcePrinter, error) {
|
||||
printer, err := printers.GetStandardPrinter(typer, encoder, decoders, *options)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -598,10 +598,27 @@ func (b *Builder) SingleResourceType() *Builder {
|
||||
return b
|
||||
}
|
||||
|
||||
// mappingFor returns the RESTMapping for the Kind referenced by the resource.
|
||||
// prefers a fully specified GroupVersionResource match. If we don't have one match on GroupResource
|
||||
func (b *Builder) mappingFor(resourceArg string) (*meta.RESTMapping, error) {
|
||||
fullySpecifiedGVR, groupResource := schema.ParseResourceArg(resourceArg)
|
||||
// mappingFor returns the RESTMapping for the Kind given, or the Kind referenced by the resource.
|
||||
// prefers a fully specified GroupVersionKind match. If we don't have one, match on a fully specified
|
||||
// GroupVersionResource, or fallback to a match on GroupResource.
|
||||
func (b *Builder) mappingFor(resourceOrKindArg string) (*meta.RESTMapping, error) {
|
||||
fullySpecifiedGVK, groupKind := schema.ParseKindArg(resourceOrKindArg)
|
||||
if fullySpecifiedGVK == nil {
|
||||
gvk := groupKind.WithVersion("")
|
||||
fullySpecifiedGVK = &gvk
|
||||
}
|
||||
|
||||
if !fullySpecifiedGVK.Empty() {
|
||||
if mapping, err := b.mapper.RESTMapping(fullySpecifiedGVK.GroupKind(), fullySpecifiedGVK.Version); err == nil {
|
||||
return mapping, nil
|
||||
} else {
|
||||
if mapping, err := b.mapper.RESTMapping(groupKind, ""); err == nil {
|
||||
return mapping, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fullySpecifiedGVR, groupResource := schema.ParseResourceArg(resourceOrKindArg)
|
||||
gvk := schema.GroupVersionKind{}
|
||||
if fullySpecifiedGVR != nil {
|
||||
gvk, _ = b.mapper.KindFor(*fullySpecifiedGVR)
|
||||
|
@ -26,6 +26,7 @@ go_library(
|
||||
"//vendor/github.com/ghodss/yaml: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/v1beta1:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/labels:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
||||
|
@ -108,7 +108,7 @@ func TestPrintDefault(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, test := range printerTests {
|
||||
printer, err := printers.GetStandardPrinter(nil, nil, legacyscheme.Codecs.LegacyCodec(legacyscheme.Registry.EnabledVersions()...), []runtime.Decoder{legacyscheme.Codecs.UniversalDecoder(), unstructured.UnstructuredJSONScheme}, printers.PrintOptions{AllowMissingKeys: false})
|
||||
printer, err := printers.GetStandardPrinter(nil, legacyscheme.Codecs.LegacyCodec(legacyscheme.Registry.EnabledVersions()...), []runtime.Decoder{legacyscheme.Codecs.UniversalDecoder(), unstructured.UnstructuredJSONScheme}, printers.PrintOptions{AllowMissingKeys: false})
|
||||
if err != nil {
|
||||
t.Errorf("in %s, unexpected error: %#v", test.Name, err)
|
||||
}
|
||||
@ -278,12 +278,12 @@ func TestPrinter(t *testing.T) {
|
||||
{"test jsonpath", &printers.PrintOptions{OutputFormatType: "jsonpath", OutputFormatArgument: "{.metadata.name}", AllowMissingKeys: true}, podTest, []schema.GroupVersion{v1.SchemeGroupVersion}, "foo"},
|
||||
{"test jsonpath list", &printers.PrintOptions{OutputFormatType: "jsonpath", OutputFormatArgument: "{.items[*].metadata.name}", AllowMissingKeys: true}, podListTest, []schema.GroupVersion{v1.SchemeGroupVersion}, "foo bar"},
|
||||
{"test jsonpath empty list", &printers.PrintOptions{OutputFormatType: "jsonpath", OutputFormatArgument: "{.items[*].metadata.name}", AllowMissingKeys: true}, emptyListTest, []schema.GroupVersion{v1.SchemeGroupVersion}, ""},
|
||||
{"test name", &printers.PrintOptions{OutputFormatType: "name", AllowMissingKeys: true}, podTest, []schema.GroupVersion{v1.SchemeGroupVersion}, "pods/foo\n"},
|
||||
{"test name", &printers.PrintOptions{OutputFormatType: "name", AllowMissingKeys: true}, podTest, []schema.GroupVersion{v1.SchemeGroupVersion}, "pod/foo\n"},
|
||||
{"emits versioned objects", &printers.PrintOptions{OutputFormatType: "template", OutputFormatArgument: "{{.kind}}", AllowMissingKeys: true}, testapi, []schema.GroupVersion{v1.SchemeGroupVersion}, "Pod"},
|
||||
}
|
||||
for _, test := range printerTests {
|
||||
buf := bytes.NewBuffer([]byte{})
|
||||
printer, err := printers.GetStandardPrinter(legacyscheme.Registry.RESTMapper(legacyscheme.Registry.EnabledVersions()...), legacyscheme.Scheme, legacyscheme.Codecs.LegacyCodec(legacyscheme.Registry.EnabledVersions()...), []runtime.Decoder{legacyscheme.Codecs.UniversalDecoder(), unstructured.UnstructuredJSONScheme}, *test.PrintOpts)
|
||||
printer, err := printers.GetStandardPrinter(legacyscheme.Scheme, legacyscheme.Codecs.LegacyCodec(legacyscheme.Registry.EnabledVersions()...), []runtime.Decoder{legacyscheme.Codecs.UniversalDecoder(), unstructured.UnstructuredJSONScheme}, *test.PrintOpts)
|
||||
if err != nil {
|
||||
t.Errorf("in %s, unexpected error: %#v", test.Name, err)
|
||||
}
|
||||
@ -313,7 +313,7 @@ func TestBadPrinter(t *testing.T) {
|
||||
{"unknown format", &printers.PrintOptions{OutputFormatType: "anUnknownFormat", OutputFormatArgument: "", AllowMissingKeys: false}, fmt.Errorf("output format \"anUnknownFormat\" not recognized")},
|
||||
}
|
||||
for _, test := range badPrinterTests {
|
||||
_, err := printers.GetStandardPrinter(legacyscheme.Registry.RESTMapper(legacyscheme.Registry.EnabledVersions()...), legacyscheme.Scheme, legacyscheme.Codecs.LegacyCodec(legacyscheme.Registry.EnabledVersions()...), []runtime.Decoder{legacyscheme.Codecs.UniversalDecoder(), unstructured.UnstructuredJSONScheme}, *test.PrintOpts)
|
||||
_, err := printers.GetStandardPrinter(legacyscheme.Scheme, legacyscheme.Codecs.LegacyCodec(legacyscheme.Registry.EnabledVersions()...), []runtime.Decoder{legacyscheme.Codecs.UniversalDecoder(), unstructured.UnstructuredJSONScheme}, *test.PrintOpts)
|
||||
if err == nil || err.Error() != test.Error.Error() {
|
||||
t.Errorf("in %s, expect %s, got %s", test.Name, test.Error, err)
|
||||
}
|
||||
@ -489,7 +489,7 @@ func TestNamePrinter(t *testing.T) {
|
||||
Name: "foo",
|
||||
},
|
||||
},
|
||||
"pods/foo\n"},
|
||||
"pod/foo\n"},
|
||||
"List": {
|
||||
&v1.List{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
@ -504,10 +504,10 @@ func TestNamePrinter(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
"pods/foo\npods/bar\n"},
|
||||
"pod/foo\npod/bar\n"},
|
||||
}
|
||||
printOpts := &printers.PrintOptions{OutputFormatType: "name", AllowMissingKeys: false}
|
||||
printer, _ := printers.GetStandardPrinter(legacyscheme.Registry.RESTMapper(legacyscheme.Registry.EnabledVersions()...), legacyscheme.Scheme, legacyscheme.Codecs.LegacyCodec(legacyscheme.Registry.EnabledVersions()...), []runtime.Decoder{legacyscheme.Codecs.UniversalDecoder(), unstructured.UnstructuredJSONScheme}, *printOpts)
|
||||
printer, _ := printers.GetStandardPrinter(legacyscheme.Scheme, legacyscheme.Codecs.LegacyCodec(legacyscheme.Registry.EnabledVersions()...), []runtime.Decoder{legacyscheme.Codecs.UniversalDecoder(), unstructured.UnstructuredJSONScheme}, *printOpts)
|
||||
for name, item := range tests {
|
||||
buff := &bytes.Buffer{}
|
||||
err := printer.PrintObj(item.obj, buff)
|
||||
@ -682,7 +682,6 @@ func TestPrinters(t *testing.T) {
|
||||
"name": &printers.NamePrinter{
|
||||
Typer: legacyscheme.Scheme,
|
||||
Decoders: []runtime.Decoder{legacyscheme.Codecs.UniversalDecoder(), unstructured.UnstructuredJSONScheme},
|
||||
Mapper: legacyscheme.Registry.RESTMapper(legacyscheme.Registry.EnabledVersions()...),
|
||||
},
|
||||
}
|
||||
AddHandlers((allPrinters["humanReadable"]).(*printers.HumanReadablePrinter))
|
||||
@ -2819,7 +2818,7 @@ func TestAllowMissingKeys(t *testing.T) {
|
||||
}
|
||||
for _, test := range tests {
|
||||
buf := bytes.NewBuffer([]byte{})
|
||||
printer, err := printers.GetStandardPrinter(legacyscheme.Registry.RESTMapper(legacyscheme.Registry.EnabledVersions()...), legacyscheme.Scheme, legacyscheme.Codecs.LegacyCodec(legacyscheme.Registry.EnabledVersions()...), []runtime.Decoder{legacyscheme.Codecs.UniversalDecoder(), unstructured.UnstructuredJSONScheme}, *test.PrintOpts)
|
||||
printer, err := printers.GetStandardPrinter(legacyscheme.Scheme, legacyscheme.Codecs.LegacyCodec(legacyscheme.Registry.EnabledVersions()...), []runtime.Decoder{legacyscheme.Codecs.UniversalDecoder(), unstructured.UnstructuredJSONScheme}, *test.PrintOpts)
|
||||
if err != nil {
|
||||
t.Errorf("in %s, unexpected error: %#v", test.Name, err)
|
||||
}
|
||||
|
@ -19,8 +19,10 @@ package printers
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"strings"
|
||||
|
||||
"k8s.io/apimachinery/pkg/api/meta"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
utilerrors "k8s.io/apimachinery/pkg/util/errors"
|
||||
)
|
||||
@ -29,7 +31,6 @@ import (
|
||||
type NamePrinter struct {
|
||||
Decoders []runtime.Decoder
|
||||
Typer runtime.ObjectTyper
|
||||
Mapper meta.RESTMapper
|
||||
}
|
||||
|
||||
func (p *NamePrinter) AfterPrint(w io.Writer, res string) error {
|
||||
@ -64,18 +65,27 @@ func (p *NamePrinter) PrintObj(obj runtime.Object, w io.Writer) error {
|
||||
|
||||
groupVersionKind := obj.GetObjectKind().GroupVersionKind()
|
||||
if len(groupVersionKind.Kind) > 0 {
|
||||
if mappings, err := p.Mapper.RESTMappings(groupVersionKind.GroupKind(), groupVersionKind.Version); err == nil && len(mappings) > 0 {
|
||||
fmt.Fprintf(w, "%s/%s\n", mappings[0].Resource, name)
|
||||
return nil
|
||||
}
|
||||
kind := groupVersionKind.Kind
|
||||
group := groupVersionKind.Group
|
||||
return printObj(w, name, group, kind)
|
||||
}
|
||||
|
||||
if gvks, _, err := p.Typer.ObjectKinds(obj); err == nil {
|
||||
for _, gvk := range gvks {
|
||||
if mappings, err := p.Mapper.RESTMappings(gvk.GroupKind(), gvk.Version); err == nil && len(mappings) > 0 {
|
||||
fmt.Fprintf(w, "%s/%s\n", mappings[0].Resource, name)
|
||||
return nil
|
||||
if len(gvk.Kind) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
return printObj(w, name, gvk.Group, gvk.Kind)
|
||||
}
|
||||
}
|
||||
|
||||
if uns, ok := obj.(*unstructured.Unstructured); ok {
|
||||
group := uns.GroupVersionKind().Group
|
||||
kind := uns.GroupVersionKind().Kind
|
||||
|
||||
if len(kind) > 0 {
|
||||
return printObj(w, name, group, kind)
|
||||
}
|
||||
}
|
||||
|
||||
@ -83,6 +93,20 @@ func (p *NamePrinter) PrintObj(obj runtime.Object, w io.Writer) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func printObj(w io.Writer, name, group, kind string) error {
|
||||
if len(kind) == 0 {
|
||||
return fmt.Errorf("missing kind for resource with name %v", name)
|
||||
}
|
||||
|
||||
if len(group) == 0 {
|
||||
fmt.Fprintf(w, "%s/%s\n", strings.ToLower(kind), name)
|
||||
return nil
|
||||
}
|
||||
|
||||
fmt.Fprintf(w, "%s.%s/%s\n", strings.ToLower(kind), group, name)
|
||||
return nil
|
||||
}
|
||||
|
||||
// TODO: implement HandledResources()
|
||||
func (p *NamePrinter) HandledResources() []string {
|
||||
return []string{}
|
||||
|
@ -21,7 +21,6 @@ import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
|
||||
"k8s.io/apimachinery/pkg/api/meta"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
)
|
||||
|
||||
@ -29,7 +28,7 @@ import (
|
||||
// a printer or an error. The printer is agnostic to schema versions, so you must
|
||||
// send arguments to PrintObj in the version you wish them to be shown using a
|
||||
// VersionedPrinter (typically when generic is true).
|
||||
func GetStandardPrinter(mapper meta.RESTMapper, typer runtime.ObjectTyper, encoder runtime.Encoder, decoders []runtime.Decoder, options PrintOptions) (ResourcePrinter, error) {
|
||||
func GetStandardPrinter(typer runtime.ObjectTyper, encoder runtime.Encoder, decoders []runtime.Decoder, options PrintOptions) (ResourcePrinter, error) {
|
||||
format, formatArgument, allowMissingTemplateKeys := options.OutputFormatType, options.OutputFormatArgument, options.AllowMissingKeys
|
||||
|
||||
var printer ResourcePrinter
|
||||
@ -45,7 +44,6 @@ func GetStandardPrinter(mapper meta.RESTMapper, typer runtime.ObjectTyper, encod
|
||||
printer = &NamePrinter{
|
||||
Typer: typer,
|
||||
Decoders: decoders,
|
||||
Mapper: mapper,
|
||||
}
|
||||
|
||||
case "template", "go-template":
|
||||
|
@ -36,6 +36,21 @@ func ParseResourceArg(arg string) (*GroupVersionResource, GroupResource) {
|
||||
return gvr, ParseGroupResource(arg)
|
||||
}
|
||||
|
||||
// ParseKindArg takes the common style of string which may be either `Kind.group.com` or `Kind.version.group.com`
|
||||
// and parses it out into both possibilities. This code takes no responsibility for knowing which representation was intended
|
||||
// but with a knowledge of all GroupKinds, calling code can take a very good guess. If there are only two segments, then
|
||||
// `*GroupVersionResource` is nil.
|
||||
// `Kind.group.com` -> `group=com, version=group, kind=Kind` and `group=group.com, kind=Kind`
|
||||
func ParseKindArg(arg string) (*GroupVersionKind, GroupKind) {
|
||||
var gvk *GroupVersionKind
|
||||
if strings.Count(arg, ".") >= 2 {
|
||||
s := strings.SplitN(arg, ".", 3)
|
||||
gvk = &GroupVersionKind{Group: s[2], Version: s[1], Kind: s[0]}
|
||||
}
|
||||
|
||||
return gvk, ParseGroupKind(arg)
|
||||
}
|
||||
|
||||
// GroupResource specifies a Group and a Resource, but does not force a version. This is useful for identifying
|
||||
// concepts during lookup stages without having partially valid types
|
||||
type GroupResource struct {
|
||||
@ -58,6 +73,15 @@ func (gr *GroupResource) String() string {
|
||||
return gr.Resource + "." + gr.Group
|
||||
}
|
||||
|
||||
func ParseGroupKind(gk string) GroupKind {
|
||||
i := strings.Index(gk, ".")
|
||||
if i == -1 {
|
||||
return GroupKind{Kind: gk}
|
||||
}
|
||||
|
||||
return GroupKind{Group: gk[i+1:], Kind: gk[:i]}
|
||||
}
|
||||
|
||||
// ParseGroupResource turns "resource.group" string into a GroupResource struct. Empty strings are allowed
|
||||
// for each field.
|
||||
func ParseGroupResource(gr string) GroupResource {
|
||||
|
@ -18,6 +18,7 @@ package discovery
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"k8s.io/apimachinery/pkg/api/meta"
|
||||
@ -108,6 +109,7 @@ func NewRESTMapper(groupResources []*APIGroupResources, versionInterfaces meta.V
|
||||
plural := gv.WithResource(resource.Name)
|
||||
singular := gv.WithResource(resource.SingularName)
|
||||
versionMapper.AddSpecific(gv.WithKind(resource.Kind), plural, singular, scope)
|
||||
versionMapper.AddSpecific(gv.WithKind(strings.ToLower(resource.Kind)), plural, singular, scope)
|
||||
// TODO this is producing unsafe guesses that don't actually work, but it matches previous behavior
|
||||
versionMapper.Add(gv.WithKind(resource.Kind+"List"), scope)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user