Repository: FairwindsOps/pluto (go)

Issue:
Allow filtering non-deprecated versions from yaml and json output
Currently, the show-all flag doesn't affect the yaml or json output. This should probably be the case.

Pull request description:
Clarify exit codes. Allow filtering of json and yaml output by -A flag
I made the exit code `2` indicate a deprecation, and `1` indicate an error.

Fixes #49

Patch:
diff --git a/README.md b/README.md
index 592c469..40930cb 100644
--- a/README.md
+++ b/README.md
@@ -114,7 +114,9 @@ Deployment   apps/v1              false        n/a             RELEASE-NAME-helm
 
 ### CI Pipelines
 
-Pluto will exit with a non-zero code if there are any deprecations detected. This can be used in a CI pipeline to make sure no deprecated versions are introduced into your code.
+Pluto will exit with a code of `2` if there are any deprecations detected. This can be used in a CI pipeline to make sure no deprecated versions are introduced into your code.
+
+An exit code of `1` indicates an error.
 
 ### Target Versions
 
diff --git a/cmd/root.go b/cmd/root.go
index e7786e6..4cd8087 100644
--- a/cmd/root.go
+++ b/cmd/root.go
@@ -82,12 +82,12 @@ var rootCmd = &cobra.Command{
 		c, _ := utf8.DecodeRuneInString(targetVersion)
 		if c != 'v' {
 			fmt.Printf("Your --target-version must begin with a 'v'. Got '%s'\n", targetVersion)
-			os.Exit(2)
+			os.Exit(1)
 		}
 
 		if !semver.IsValid(targetVersion) {
 			fmt.Printf("You must pass a valid semver to --target-version. Got '%s'\n", targetVersion)
-			os.Exit(2)
+			os.Exit(1)
 		}
 	},
 }
diff --git a/pkg/api/output.go b/pkg/api/output.go
index 510da15..16bc1dc 100644
--- a/pkg/api/output.go
+++ b/pkg/api/output.go
@@ -17,11 +17,12 @@ func DisplayOutput(outputs []*Output, outputFormat string, showNonDeprecated boo
 		fmt.Println("There were no apiVersions found that match our records.")
 		return nil
 	}
+	usableOutputs := filterNonDeprecated(outputs, targetVersion, showNonDeprecated)
 	var err error
 	var outData []byte
 	switch outputFormat {
 	case "tabular":
-		t, err := tabOut(outputs, showNonDeprecated, targetVersion)
+		t, err := tabOut(usableOutputs, targetVersion)
 		if err != nil {
 			return err
 		}
@@ -31,13 +32,13 @@ func DisplayOutput(outputs []*Output, outputFormat string, showNonDeprecated boo
 		}
 		return nil
 	case "json":
-		outData, err = json.Marshal(outputs)
+		outData, err = json.Marshal(usableOutputs)
 		if err != nil {
 			return err
 		}
 		fmt.Println(string(outData))
 	case "yaml":
-		outData, err = yaml.Marshal(outputs)
+		outData, err = yaml.Marshal(usableOutputs)
 		if err != nil {
 			return err
 		}
@@ -48,21 +49,27 @@ func DisplayOutput(outputs []*Output, outputFormat string, showNonDeprecated boo
 	return nil
 }
 
-func tabOut(outputs []*Output, showNonDeprecated bool, targetVersion string) (*tabwriter.Writer, error) {
+func filterNonDeprecated(outputs []*Output, targetVersion string, showNonDeprecated bool) []*Output {
 	var usableOutputs []*Output
-	w := new(tabwriter.Writer)
-	w.Init(os.Stdout, 0, 15, 2, padChar, 0)
 
 	if showNonDeprecated {
 		usableOutputs = outputs
 	} else {
+
 		for _, output := range outputs {
 			if output.APIVersion.IsDeprecatedIn(targetVersion) {
 				usableOutputs = append(usableOutputs, output)
 			}
 		}
 	}
-	if len(usableOutputs) == 0 {
+	return usableOutputs
+}
+
+func tabOut(outputs []*Output, targetVersion string) (*tabwriter.Writer, error) {
+	w := new(tabwriter.Writer)
+	w.Init(os.Stdout, 0, 15, 2, padChar, 0)
+
+	if len(outputs) == 0 {
 		_, err := fmt.Fprintln(w, "APIVersions were found, but none were deprecated. Try --show-all.")
 		if err != nil {
 			return nil, err
@@ -73,7 +80,7 @@ func tabOut(outputs []*Output, showNonDeprecated bool, targetVersion string) (*t
 	if err != nil {
 		return nil, err
 	}
-	for _, output := range usableOutputs {
+	for _, output := range outputs {
 		kind := output.APIVersion.Kind
 		deprecated := fmt.Sprintf("%t", output.APIVersion.IsDeprecatedIn(targetVersion))
 		version := output.APIVersion.Name
@@ -99,7 +106,7 @@ func GetReturnCode(outputs []*Output, ignoreErrors bool, targetVersion string) i
 	}
 	for _, output := range outputs {
 		if output.APIVersion.IsDeprecatedIn(targetVersion) {
-			return 1
+			return 2
 		}
 	}
 	return 0


Test patch:
diff --git a/e2e/tests/00_static_files.yaml b/e2e/tests/00_static_files.yaml
index 2a678cf..c2c7f8b 100644
--- a/e2e/tests/00_static_files.yaml
+++ b/e2e/tests/00_static_files.yaml
@@ -5,7 +5,7 @@ testcases:
   steps:
   - script: pluto detect-files -d assets/ -A
     assertions:
-    - result.code ShouldEqual 1
+    - result.code ShouldEqual 2
     - result.systemout ShouldContainSubstring "KIND         VERSION              DEPRECATED   DEPRECATED IN   RESOURCE NAME"
     - result.systemout ShouldContainSubstring "Deployment   extensions/v1beta1   true         v1.16.0         utilities"
     - result.systemout ShouldContainSubstring "Deployment   apps/v1              false        n/a             utilities"
@@ -14,7 +14,7 @@ testcases:
   steps:
   - script: pluto detect-files -d assets/
     assertions:
-    - result.code ShouldEqual 1
+    - result.code ShouldEqual 2
     - result.systemout ShouldContainSubstring "KIND         VERSION              DEPRECATED   DEPRECATED IN   RESOURCE NAME"
     - result.systemout ShouldContainSubstring "Deployment   extensions/v1beta1   true         v1.16.0         utilities"
     - result.systemout ShouldNotContainSubstring "Deployment   apps/v1              false        n/a             utilities"
@@ -23,7 +23,7 @@ testcases:
   steps:
   - script: helm template assets/helm3chart | pluto detect -A -
     assertions:
-    - result.code ShouldEqual 1
+    - result.code ShouldEqual 2
     - result.systemout ShouldContainSubstring "KIND         VERSION              DEPRECATED   DEPRECATED IN   RESOURCE NAME"
     - result.systemout ShouldContainSubstring "Deployment   extensions/v1beta1   true         v1.16.0         RELEASE-NAME-helm3chart-v1beta1"
     - result.systemout ShouldContainSubstring "Deployment   apps/v1              false        n/a             RELEASE-NAME-helm3chart"
@@ -32,7 +32,7 @@ testcases:
   steps:
   - script: helm template assets/helm3chart | pluto detect -
     assertions:
-    - result.code ShouldEqual 1
+    - result.code ShouldEqual 2
     - result.systemout ShouldContainSubstring "KIND         VERSION              DEPRECATED   DEPRECATED IN   RESOURCE NAME"
     - result.systemout ShouldContainSubstring "Deployment   extensions/v1beta1   true         v1.16.0         RELEASE-NAME-helm3chart-v1beta1"
     - result.systemout ShouldNotContainSubstring "Deployment   apps/v1              false        n/a             RELEASE-NAME-helm3chart"
@@ -58,3 +58,17 @@ testcases:
     assertions:
     - result.code ShouldEqual 0
     - result.systemout ShouldContainSubstring "APIVersions were found, but none were deprecated. Try --show-all."
+
+- name: static files show all json
+  steps:
+  - script: pluto detect-files -d assets/ -A -ojson
+    assertions:
+    - result.code ShouldEqual 2
+    - result.systemout ShouldEqual '[{"file":"utilities","api":{"version":"extensions/v1beta1","kind":"Deployment","deprecated-in":"v1.16.0"}},{"file":"utilities","api":{"version":"apps/v1","kind":"Deployment"}}]'
+
+- name: static files json
+  steps:
+  - script: pluto detect-files -d assets/ -ojson
+    assertions:
+    - result.code ShouldEqual 2
+    - result.systemout ShouldEqual '[{"file":"utilities","api":{"version":"extensions/v1beta1","kind":"Deployment","deprecated-in":"v1.16.0"}}]'
diff --git a/e2e/tests/01_helm-detect-3.yaml b/e2e/tests/01_helm-detect-3.yaml
index 94526e8..3dfc6fa 100644
--- a/e2e/tests/01_helm-detect-3.yaml
+++ b/e2e/tests/01_helm-detect-3.yaml
@@ -11,7 +11,7 @@ testcases:
   steps:
   - script: pluto detect-helm --helm-version=3 -A
     assertions:
-    - result.code ShouldEqual 1
+    - result.code ShouldEqual 2
     - result.systemout ShouldContainSubstring "KIND         VERSION              DEPRECATED   DEPRECATED IN   RESOURCE NAME"
     - result.systemout ShouldContainSubstring "Deployment   extensions/v1beta1   true         v1.16.0         test-helm3chart-v1beta1"
     - result.systemout ShouldContainSubstring "Deployment   apps/v1              false        n/a             test-helm3chart"
@@ -20,7 +20,7 @@ testcases:
   steps:
   - script: pluto detect-helm --helm-version=3
     assertions:
-    - result.code ShouldEqual 1
+    - result.code ShouldEqual 2
     - result.systemout ShouldContainSubstring "KIND         VERSION              DEPRECATED   DEPRECATED IN   RESOURCE NAME"
     - result.systemout ShouldContainSubstring "Deployment   extensions/v1beta1   true         v1.16.0         test-helm3chart-v1beta1"
     - result.systemout ShouldNotContainSubstring "Deployment   apps/v1              false        n/a             test-helm3chart"
diff --git a/e2e/tests/02_helm-detect-2.yaml b/e2e/tests/02_helm-detect-2.yaml
index abfde6c..4a2d2c5 100644
--- a/e2e/tests/02_helm-detect-2.yaml
+++ b/e2e/tests/02_helm-detect-2.yaml
@@ -13,7 +13,7 @@ testcases:
   steps:
   - script: pluto detect-helm --helm-version=2 -A
     assertions:
-    - result.code ShouldEqual 1
+    - result.code ShouldEqual 2
     - result.systemout ShouldContainSubstring "KIND         VERSION              DEPRECATED   DEPRECATED IN   RESOURCE NAME"
     - result.systemout ShouldContainSubstring "Deployment   extensions/v1beta1   true         v1.16.0         invincible-zebu-metrics-server"
     - result.systemout ShouldContainSubstring "Deployment   apps/v1              false        n/a             lunging-bat-metrics-server"
@@ -22,7 +22,7 @@ testcases:
   steps:
   - script: pluto detect-helm --helm-version=2
     assertions:
-    - result.code ShouldEqual 1
+    - result.code ShouldEqual 2
     - result.systemout ShouldContainSubstring "KIND         VERSION              DEPRECATED   DEPRECATED IN   RESOURCE NAME"
     - result.systemout ShouldContainSubstring "Deployment   extensions/v1beta1   true         v1.16.0         invincible-zebu-metrics-server"
     - result.systemout ShouldNotContainSubstring "Deployment   apps/v1              false        n/a             lunging-bat-metrics-server"
diff --git a/e2e/tests/03-cli-validation.yaml b/e2e/tests/03-cli-validation.yaml
index 87e4c43..285e6c9 100644
--- a/e2e/tests/03-cli-validation.yaml
+++ b/e2e/tests/03-cli-validation.yaml
@@ -5,11 +5,11 @@ testcases:
   steps:
   - script: pluto detect-files -d assets/deprecated116 -t "foo"
     assertions:
-    - result.code ShouldEqual 2
+    - result.code ShouldEqual 1
     - result.systemout ShouldEqual "Your --target-version must begin with a 'v'. Got 'foo'"
 - name: Pass bad semver starting with v
   steps:
   - script: pluto detect-files -d assets/deprecated116 -t "vfoo"
     assertions:
-    - result.code ShouldEqual 2
+    - result.code ShouldEqual 1
     - result.systemout ShouldEqual "You must pass a valid semver to --target-version. Got 'vfoo'"
diff --git a/pkg/api/output_test.go b/pkg/api/output_test.go
index 84aac1c..818dac4 100644
--- a/pkg/api/output_test.go
+++ b/pkg/api/output_test.go
@@ -60,20 +60,25 @@ func ExampleDisplayOutput() {
 }
 
 func ExampleDisplayOutput_json() {
-	_ = DisplayOutput([]*Output{testOutput1}, "json", true, targetVersion116)
+	_ = DisplayOutput([]*Output{testOutput1, testOutput2}, "json", true, targetVersion116)
 
 	// Output:
-	// [{"file":"some name one","api":{"version":"apps/v1","kind":"Deployment"}}]
+	// [{"file":"some name one","api":{"version":"apps/v1","kind":"Deployment"}},{"file":"some name two","api":{"version":"extensions/v1beta1","kind":"Deployment","deprecated-in":"v1.16.0"}}]
 }
 
 func ExampleDisplayOutput_yaml() {
-	_ = DisplayOutput([]*Output{testOutput1}, "yaml", true, targetVersion116)
+	_ = DisplayOutput([]*Output{testOutput1, testOutput2}, "yaml", true, targetVersion116)
 
 	// Output:
 	// - file: some name one
 	//   api:
 	//     version: apps/v1
 	//     kind: Deployment
+	// - file: some name two
+	//   api:
+	//     version: extensions/v1beta1
+	//     kind: Deployment
+	//     deprecated-in: v1.16.0
 }
 
 func ExampleDisplayOutput_noOutput() {
@@ -124,7 +129,7 @@ func TestGetReturnCode(t *testing.T) {
 				},
 				ignoreErrors: false,
 			},
-			want: 1,
+			want: 2,
 		},
 		{
 			name: "version is deprecated ignore errors",