mirror of https://github.com/linkerd/linkerd2.git
Add support for json output in inject and uninject commands (#12600)
We add support for the `--output/-o` flag in `linkerd inject` and `linkerd uninject` commands. The supported output formats are yaml (default) and json. Kubectl is able to accept both of these formats which means that `linkerd inject` and `linkerd uninject` output can be piped into kubectl regardless of which output format is used. Signed-off-by: Alex Leong <alex@buoyant.io>
This commit is contained in:
parent
46c315034b
commit
10b1a7af6a
|
|
@ -42,8 +42,8 @@ type resourceTransformerInject struct {
|
|||
closeWaitTimeout time.Duration
|
||||
}
|
||||
|
||||
func runInjectCmd(inputs []io.Reader, errWriter, outWriter io.Writer, transformer *resourceTransformerInject) int {
|
||||
return transformInput(inputs, errWriter, outWriter, transformer)
|
||||
func runInjectCmd(inputs []io.Reader, errWriter, outWriter io.Writer, transformer *resourceTransformerInject, output string) int {
|
||||
return transformInput(inputs, errWriter, outWriter, transformer, output)
|
||||
}
|
||||
|
||||
func newCmdInject() *cobra.Command {
|
||||
|
|
@ -56,6 +56,7 @@ func newCmdInject() *cobra.Command {
|
|||
injectFlags, injectFlagSet := makeInjectFlags(defaults)
|
||||
var manualOption, enableDebugSidecar bool
|
||||
var closeWaitTimeout time.Duration
|
||||
var output string
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "inject [flags] CONFIG-FILE",
|
||||
|
|
@ -109,7 +110,7 @@ sub-folders, or coming from stdin.`,
|
|||
enableDebugSidecar: enableDebugSidecar,
|
||||
closeWaitTimeout: closeWaitTimeout,
|
||||
}
|
||||
exitCode := uninjectAndInject(in, stderr, stdout, transformer)
|
||||
exitCode := uninjectAndInject(in, stderr, stdout, transformer, output)
|
||||
os.Exit(exitCode)
|
||||
return nil
|
||||
},
|
||||
|
|
@ -132,18 +133,20 @@ sub-folders, or coming from stdin.`,
|
|||
&closeWaitTimeout, "close-wait-timeout", closeWaitTimeout,
|
||||
"Sets nf_conntrack_tcp_timeout_close_wait")
|
||||
|
||||
cmd.Flags().StringVarP(&output, "output", "o", "yaml", "Output format, one of: json|yaml")
|
||||
|
||||
cmd.Flags().AddFlagSet(proxyFlagSet)
|
||||
cmd.Flags().AddFlagSet(injectFlagSet)
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
func uninjectAndInject(inputs []io.Reader, errWriter, outWriter io.Writer, transformer *resourceTransformerInject) int {
|
||||
func uninjectAndInject(inputs []io.Reader, errWriter, outWriter io.Writer, transformer *resourceTransformerInject, output string) int {
|
||||
var out bytes.Buffer
|
||||
if exitCode := runUninjectSilentCmd(inputs, errWriter, &out, transformer.values); exitCode != 0 {
|
||||
if exitCode := runUninjectSilentCmd(inputs, errWriter, &out, transformer.values, "yaml"); exitCode != 0 {
|
||||
return exitCode
|
||||
}
|
||||
return runInjectCmd([]io.Reader{&out}, errWriter, outWriter, transformer)
|
||||
return runInjectCmd([]io.Reader{&out}, errWriter, outWriter, transformer, output)
|
||||
}
|
||||
|
||||
func (rt resourceTransformerInject) transform(bytes []byte) ([]byte, []inject.Report, error) {
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ func testUninjectAndInject(t *testing.T, tc testCase) {
|
|||
allowNsInject: true,
|
||||
}
|
||||
|
||||
if exitCode := uninjectAndInject([]io.Reader{read}, report, output, transformer); exitCode != 0 {
|
||||
if exitCode := uninjectAndInject([]io.Reader{read}, report, output, transformer, "yaml"); exitCode != 0 {
|
||||
t.Errorf("Unexpected error injecting YAML: %v", report)
|
||||
}
|
||||
if err := testDataDiffer.DiffTestYAML(tc.goldenFileName, output.String()); err != nil {
|
||||
|
|
@ -432,7 +432,7 @@ func testInjectCmd(t *testing.T, tc injectCmd) {
|
|||
injectProxy: tc.injectProxy,
|
||||
values: testConfig,
|
||||
}
|
||||
exitCode := runInjectCmd([]io.Reader{in}, errBuffer, outBuffer, transformer)
|
||||
exitCode := runInjectCmd([]io.Reader{in}, errBuffer, outBuffer, transformer, "yaml")
|
||||
if exitCode != tc.exitCode {
|
||||
t.Fatalf("Expected exit code to be %d but got: %d", tc.exitCode, exitCode)
|
||||
}
|
||||
|
|
@ -538,7 +538,7 @@ func testInjectFilePath(t *testing.T, tc injectFilePath) {
|
|||
injectProxy: true,
|
||||
values: values,
|
||||
}
|
||||
if exitCode := runInjectCmd(in, errBuf, actual, transformer); exitCode != 0 {
|
||||
if exitCode := runInjectCmd(in, errBuf, actual, transformer, "yaml"); exitCode != 0 {
|
||||
t.Fatal("Unexpected error. Exit code from runInjectCmd: ", exitCode)
|
||||
}
|
||||
if err := testDataDiffer.DiffTestYAML(tc.expectedFile, actual.String()); err != nil {
|
||||
|
|
@ -565,7 +565,7 @@ func testReadFromFolder(t *testing.T, resourceFolder string, expectedFolder stri
|
|||
injectProxy: true,
|
||||
values: values,
|
||||
}
|
||||
if exitCode := runInjectCmd(in, errBuf, actual, transformer); exitCode != 0 {
|
||||
if exitCode := runInjectCmd(in, errBuf, actual, transformer, "yaml"); exitCode != 0 {
|
||||
t.Fatal("Unexpected error. Exit code from runInjectCmd: ", exitCode)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -26,12 +26,12 @@ type resourceTransformer interface {
|
|||
}
|
||||
|
||||
// Returns the integer representation of os.Exit code; 0 on success and 1 on failure.
|
||||
func transformInput(inputs []io.Reader, errWriter, outWriter io.Writer, rt resourceTransformer) int {
|
||||
func transformInput(inputs []io.Reader, errWriter, outWriter io.Writer, rt resourceTransformer, format string) int {
|
||||
postInjectBuf := &bytes.Buffer{}
|
||||
reportBuf := &bytes.Buffer{}
|
||||
|
||||
for _, input := range inputs {
|
||||
errs := processYAML(input, postInjectBuf, reportBuf, rt)
|
||||
errs := processYAML(input, postInjectBuf, reportBuf, rt, format)
|
||||
if len(errs) > 0 {
|
||||
fmt.Fprintf(errWriter, "Error transforming resources:\n%v", concatErrors(errs, "\n"))
|
||||
return 1
|
||||
|
|
@ -51,7 +51,7 @@ func transformInput(inputs []io.Reader, errWriter, outWriter io.Writer, rt resou
|
|||
}
|
||||
|
||||
// processYAML takes an input stream of YAML, outputting injected/uninjected YAML to out.
|
||||
func processYAML(in io.Reader, out io.Writer, report io.Writer, rt resourceTransformer) []error {
|
||||
func processYAML(in io.Reader, out io.Writer, report io.Writer, rt resourceTransformer, format string) []error {
|
||||
reader := yamlDecoder.NewYAMLReader(bufio.NewReaderSize(in, 4096))
|
||||
|
||||
reports := []inject.Report{}
|
||||
|
|
@ -86,9 +86,26 @@ func processYAML(in io.Reader, out io.Writer, report io.Writer, rt resourceTrans
|
|||
}
|
||||
reports = append(reports, irs...)
|
||||
|
||||
// If the format is set to json, we need to convert the yaml to json
|
||||
if format == "json" {
|
||||
result, err = yaml.YAMLToJSON(result)
|
||||
if err != nil {
|
||||
errs = append(errs, err)
|
||||
}
|
||||
} else if format == "yaml" {
|
||||
// result is already in yaml format: noop.
|
||||
} else {
|
||||
errs = append(errs, fmt.Errorf("unsupported format %s", format))
|
||||
}
|
||||
|
||||
if len(errs) == 0 {
|
||||
out.Write(result)
|
||||
out.Write([]byte("---\n"))
|
||||
if format == "yaml" {
|
||||
out.Write([]byte("---\n"))
|
||||
}
|
||||
if format == "json" {
|
||||
out.Write([]byte("\n"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -18,15 +18,17 @@ type resourceTransformerUninjectSilent struct {
|
|||
values *linkerd2.Values
|
||||
}
|
||||
|
||||
func runUninjectCmd(inputs []io.Reader, errWriter, outWriter io.Writer, values *linkerd2.Values) int {
|
||||
return transformInput(inputs, errWriter, outWriter, resourceTransformerUninject{values})
|
||||
func runUninjectCmd(inputs []io.Reader, errWriter, outWriter io.Writer, values *linkerd2.Values, output string) int {
|
||||
return transformInput(inputs, errWriter, outWriter, resourceTransformerUninject{values}, output)
|
||||
}
|
||||
|
||||
func runUninjectSilentCmd(inputs []io.Reader, errWriter, outWriter io.Writer, values *linkerd2.Values) int {
|
||||
return transformInput(inputs, errWriter, outWriter, resourceTransformerUninjectSilent{values})
|
||||
func runUninjectSilentCmd(inputs []io.Reader, errWriter, outWriter io.Writer, values *linkerd2.Values, output string) int {
|
||||
return transformInput(inputs, errWriter, outWriter, resourceTransformerUninjectSilent{values}, output)
|
||||
}
|
||||
|
||||
func newCmdUninject() *cobra.Command {
|
||||
var output string
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "uninject [flags] CONFIG-FILE",
|
||||
Short: "Remove the Linkerd proxy from a Kubernetes config",
|
||||
|
|
@ -53,12 +55,14 @@ sub-folders, or coming from stdin.`,
|
|||
return err
|
||||
}
|
||||
|
||||
exitCode := runUninjectCmd(in, os.Stderr, os.Stdout, nil)
|
||||
exitCode := runUninjectCmd(in, os.Stderr, os.Stdout, nil, output)
|
||||
os.Exit(exitCode)
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
cmd.Flags().StringVarP(&output, "output", "o", "yaml", "Output format, one of: json|yaml")
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -116,7 +116,7 @@ func TestUninjectYAML(t *testing.T) {
|
|||
output := new(bytes.Buffer)
|
||||
report := new(bytes.Buffer)
|
||||
|
||||
exitCode := runUninjectCmd(read, report, output, values)
|
||||
exitCode := runUninjectCmd(read, report, output, values, "yaml")
|
||||
if exitCode != 0 {
|
||||
t.Errorf("Failed to uninject %s", tc.inputFileName)
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue