Skip to content

Commit a8ccb0f

Browse files
Display an external version of the object for --output
Use the version of the API the RESTMapper prefers (currently)
1 parent 179213f commit a8ccb0f

File tree

4 files changed

+55
-37
lines changed

4 files changed

+55
-37
lines changed

pkg/kubectl/cmd/cmd.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ Find more information at https://github.com/GoogleCloudPlatform/kubernetes.`,
8484
cmds.PersistentFlags().StringP("server", "s", "", "Kubernetes apiserver to connect to")
8585
cmds.PersistentFlags().StringP("auth-path", "a", os.Getenv("HOME")+"/.kubernetes_auth", "Path to the auth info file. If missing, prompt the user. Only used if using https.")
8686
cmds.PersistentFlags().Bool("match-server-version", false, "Require server version to match client version")
87-
cmds.PersistentFlags().String("api-version", latest.Version, "The version of the API to use against the server (used for viewing resources only)")
87+
cmds.PersistentFlags().String("api-version", latest.Version, "The version of the API to use against the server")
8888
cmds.PersistentFlags().String("certificate-authority", "", "Path to a certificate file for the certificate authority")
8989
cmds.PersistentFlags().String("client-certificate", "", "Path to a client certificate for TLS.")
9090
cmds.PersistentFlags().String("client-key", "", "Path to a client key file for TLS.")

pkg/kubectl/cmd/get.go

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ limitations under the License.
1717
package cmd
1818

1919
import (
20+
"fmt"
2021
"io"
2122

2223
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl"
@@ -33,7 +34,8 @@ func (f *Factory) NewCmdGet(out io.Writer) *cobra.Command {
3334
Possible resources include pods (po), replication controllers (rc), services
3435
(se) or minions (mi).
3536
36-
If you specify a Go template, you can use any field defined in pkg/api/types.go.
37+
If you specify a Go template, you can use any fields defined for the API version
38+
you are connecting to the server with.
3739
3840
Examples:
3941
$ kubectl get pods
@@ -54,16 +56,27 @@ Examples:
5456
client, err := f.Client(cmd, mapping)
5557
checkErr(err)
5658

57-
obj, err := kubectl.NewRESTHelper(client, mapping).Get(namespace, name, labels)
58-
checkErr(err)
59-
6059
outputFormat := getFlagString(cmd, "output")
6160
templateFile := getFlagString(cmd, "template")
6261
defaultPrinter, err := f.Printer(cmd, mapping, getFlagBool(cmd, "no-headers"))
6362
checkErr(err)
6463

65-
err = kubectl.Print(out, obj, outputFormat, templateFile, defaultPrinter)
64+
printer, versioned, err := kubectl.GetPrinter(outputFormat, templateFile, defaultPrinter)
65+
checkErr(err)
66+
67+
obj, err := kubectl.NewRESTHelper(client, mapping).Get(namespace, name, labels)
6668
checkErr(err)
69+
70+
if versioned {
71+
// TODO Add an --output-version lock which can ensure that regardless of the
72+
// server version, the client output stays the same.
73+
obj, err = mapping.ObjectConvertor.ConvertToVersion(obj, mapping.APIVersion)
74+
checkErr(err)
75+
}
76+
77+
if err := printer.PrintObj(obj, out); err != nil {
78+
checkErr(fmt.Errorf("Unable to output the provided object: %v", err))
79+
}
6780
},
6881
}
6982
cmd.Flags().StringP("output", "o", "", "Output format: json|yaml|template|templatefile")

pkg/kubectl/resource_printer.go

Lines changed: 15 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -34,20 +34,10 @@ import (
3434
"gopkg.in/v1/yaml"
3535
)
3636

37-
// Print outputs a runtime.Object to an io.Writer in the given format
38-
func Print(w io.Writer, obj runtime.Object, format string, templateFile string, defaultPrinter ResourcePrinter) error {
39-
printer, err := getPrinter(format, templateFile, defaultPrinter)
40-
if err != nil {
41-
return err
42-
}
43-
44-
if err := printer.PrintObj(obj, w); err != nil {
45-
return fmt.Errorf("Failed to print: %v\nRaw received object:\n%#v", err, obj)
46-
}
47-
return nil
48-
}
49-
50-
func getPrinter(format, templateFile string, defaultPrinter ResourcePrinter) (ResourcePrinter, error) {
37+
// GetPrinter returns a resource printer and a bool indicating whether the object must be
38+
// versioned for the given format.
39+
func GetPrinter(format, templateFile string, defaultPrinter ResourcePrinter) (ResourcePrinter, bool, error) {
40+
versioned := true
5141
var printer ResourcePrinter
5242
switch format {
5343
case "json":
@@ -57,11 +47,11 @@ func getPrinter(format, templateFile string, defaultPrinter ResourcePrinter) (Re
5747
case "template":
5848
var data []byte
5949
if len(templateFile) == 0 {
60-
return printer, fmt.Errorf("template format specified but no template given")
50+
return nil, false, fmt.Errorf("template format specified but no template given")
6151
}
6252
tmpl, err := template.New("output").Parse(templateFile)
6353
if err != nil {
64-
return printer, fmt.Errorf("Error parsing template %s, %v\n", string(data), err)
54+
return nil, false, fmt.Errorf("Error parsing template %s, %v\n", string(data), err)
6555
}
6656
printer = &TemplatePrinter{
6757
Template: tmpl,
@@ -72,27 +62,30 @@ func getPrinter(format, templateFile string, defaultPrinter ResourcePrinter) (Re
7262
var err error
7363
data, err = ioutil.ReadFile(templateFile)
7464
if err != nil {
75-
return printer, fmt.Errorf("Error reading template %s, %v\n", templateFile, err)
65+
return nil, false, fmt.Errorf("Error reading template %s, %v\n", templateFile, err)
7666
}
7767
} else {
78-
return printer, fmt.Errorf("templatefile format specified but no template file given")
68+
return nil, false, fmt.Errorf("templatefile format specified but no template file given")
7969
}
8070
tmpl, err := template.New("output").Parse(string(data))
8171
if err != nil {
82-
return printer, fmt.Errorf("Error parsing template %s, %v\n", string(data), err)
72+
return nil, false, fmt.Errorf("Error parsing template %s, %v\n", string(data), err)
8373
}
8474
printer = &TemplatePrinter{
8575
Template: tmpl,
8676
}
87-
default:
77+
case "":
8878
printer = defaultPrinter
79+
versioned = false
80+
default:
81+
return nil, false, fmt.Errorf("output format %q not recognized", format)
8982
}
90-
return printer, nil
83+
return printer, versioned, nil
9184
}
9285

9386
// ResourcePrinter is an interface that knows how to print API resources.
9487
type ResourcePrinter interface {
95-
// Print receives an arbitrary JSON body, formats it and prints it to a writer.
88+
// Print receives an arbitrary object, formats it and prints it to a writer.
9689
PrintObj(runtime.Object, io.Writer) error
9790
}
9891

pkg/kubectl/resource_printer_test.go

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -54,9 +54,14 @@ func TestJSONPrinter(t *testing.T) {
5454

5555
func TestPrintJSON(t *testing.T) {
5656
buf := bytes.NewBuffer([]byte{})
57-
if err := Print(buf, &api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo"}}, "json", "", nil); err != nil {
57+
printer, versioned, err := GetPrinter("json", "", nil)
58+
if err != nil {
5859
t.Errorf("unexpected error: %#v", err)
5960
}
61+
if !versioned {
62+
t.Errorf("printer should be versioned")
63+
}
64+
printer.PrintObj(&api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo"}}, buf)
6065
obj := map[string]interface{}{}
6166
if err := json.Unmarshal(buf.Bytes(), &obj); err != nil {
6267
t.Errorf("unexpected error: %#v\n%s", err, buf.String())
@@ -65,9 +70,14 @@ func TestPrintJSON(t *testing.T) {
6570

6671
func TestPrintYAML(t *testing.T) {
6772
buf := bytes.NewBuffer([]byte{})
68-
if err := Print(buf, &api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo"}}, "yaml", "", nil); err != nil {
73+
printer, versioned, err := GetPrinter("yaml", "", nil)
74+
if err != nil {
6975
t.Errorf("unexpected error: %#v", err)
7076
}
77+
if !versioned {
78+
t.Errorf("printer should be versioned")
79+
}
80+
printer.PrintObj(&api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo"}}, buf)
7181
obj := map[string]interface{}{}
7282
if err := yaml.Unmarshal(buf.Bytes(), &obj); err != nil {
7383
t.Errorf("unexpected error: %#v\n%s", err, buf.String())
@@ -76,31 +86,33 @@ func TestPrintYAML(t *testing.T) {
7686

7787
func TestPrintTemplate(t *testing.T) {
7888
buf := bytes.NewBuffer([]byte{})
79-
if err := Print(buf, &api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo"}}, "template", "{{ .Name }}", nil); err != nil {
89+
printer, versioned, err := GetPrinter("template", "{{ .Name }}", nil)
90+
if err != nil {
8091
t.Errorf("unexpected error: %#v", err)
8192
}
93+
if !versioned {
94+
t.Errorf("printer should be versioned")
95+
}
96+
printer.PrintObj(&api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo"}}, buf)
8297
if buf.String() != "foo" {
8398
t.Errorf("unexpected output: %s", buf.String())
8499
}
85100
}
86101

87102
func TestPrintEmptyTemplate(t *testing.T) {
88-
buf := bytes.NewBuffer([]byte{})
89-
if err := Print(buf, &api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo"}}, "template", "", nil); err == nil {
103+
if _, _, err := GetPrinter("template", "", nil); err == nil {
90104
t.Errorf("unexpected non-error")
91105
}
92106
}
93107

94108
func TestPrintBadTemplate(t *testing.T) {
95-
buf := bytes.NewBuffer([]byte{})
96-
if err := Print(buf, &api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo"}}, "template", "{{ .Name", nil); err == nil {
109+
if _, _, err := GetPrinter("template", "{{ .Name", nil); err == nil {
97110
t.Errorf("unexpected non-error")
98111
}
99112
}
100113

101114
func TestPrintBadTemplateFile(t *testing.T) {
102-
buf := bytes.NewBuffer([]byte{})
103-
if err := Print(buf, &api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo"}}, "templatefile", "", nil); err == nil {
115+
if _, _, err := GetPrinter("templatefile", "", nil); err == nil {
104116
t.Errorf("unexpected non-error")
105117
}
106118
}

0 commit comments

Comments
 (0)