Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

don't show duplicate deployed releases (#63). add release name to the name output for helm (#67) #69

Merged
merged 10 commits into from
Apr 29, 2020
5 changes: 0 additions & 5 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,11 +65,6 @@ func init() {
pflag.CommandLine.AddGoFlagSet(flag.CommandLine)
}

// Checker is an interface to find versions
type Checker interface {
FindVersions() error
}

var rootCmd = &cobra.Command{
Use: "pluto",
Short: "pluto",
Expand Down
5 changes: 5 additions & 0 deletions codecov.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,8 @@ coverage:
precision: 2
round: down
range: "30...70"

ignore:
- "e2e"
- "img"
- "**/**/testdata"
1 change: 1 addition & 0 deletions e2e/test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,6 @@ cp /pluto/pluto /usr/local/bin/pluto

cd /pluto/e2e
mkdir -p /tmp/test-results
helm delete -n kube-system hostpath-provisioner || true
venom run tests/* --log debug --output-dir=/tmp/test-results --strict
exit $?
24 changes: 12 additions & 12 deletions e2e/tests/01_helm-detect-3.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,36 +12,36 @@ testcases:
- script: pluto detect-helm --helm-version=3 -A -t v1.16.0
assertions:
- result.code ShouldEqual 3
- result.systemout ShouldContainSubstring "NAME KIND VERSION REPLACEMENT REMOVED DEPRECATED"
- result.systemout ShouldContainSubstring "test-helm3chart-v1beta1 Deployment extensions/v1beta1 apps/v1 true true"
- result.systemout ShouldContainSubstring "test-helm3chart Deployment apps/v1 false false"
- result.systemout ShouldContainSubstring "NAME KIND VERSION REPLACEMENT REMOVED DEPRECATED"
- result.systemout ShouldContainSubstring "test/test-helm3chart-v1beta1 Deployment extensions/v1beta1 apps/v1 true true"
- result.systemout ShouldContainSubstring "test/test-helm3chart Deployment apps/v1 false false"

- name: helm detect
steps:
- script: pluto detect-helm --helm-version=3 -t v1.16.0
assertions:
- result.code ShouldEqual 3
- result.systemout ShouldContainSubstring "NAME KIND VERSION REPLACEMENT REMOVED DEPRECATED"
- result.systemout ShouldContainSubstring "test-helm3chart-v1beta1 Deployment extensions/v1beta1 apps/v1 true true"
- result.systemout ShouldNotContainSubstring "test-helm3chart Deployment apps/v1 false false"
- result.systemout ShouldContainSubstring "NAME KIND VERSION REPLACEMENT REMOVED DEPRECATED"
- result.systemout ShouldContainSubstring "test/test-helm3chart-v1beta1 Deployment extensions/v1beta1 apps/v1 true true"
- result.systemout ShouldNotContainSubstring "test/test-helm3chart Deployment apps/v1 false false"

- name: helm detect ignore deprecations
steps:
- script: pluto detect-helm --helm-version=3 --ignore-deprecations -t v1.15.0
assertions:
- result.code ShouldEqual 0
- result.systemout ShouldContainSubstring "NAME KIND VERSION REPLACEMENT REMOVED DEPRECATED "
- result.systemout ShouldContainSubstring "test-helm3chart-v1beta1 Deployment extensions/v1beta1 apps/v1 false true"
- result.systemout ShouldNotContainSubstring "test-helm3chart Deployment apps/v1 false false"
- result.systemout ShouldContainSubstring "NAME KIND VERSION REPLACEMENT REMOVED DEPRECATED"
- result.systemout ShouldContainSubstring "test/test-helm3chart-v1beta1 Deployment extensions/v1beta1 apps/v1 false true"
- result.systemout ShouldNotContainSubstring "test/test-helm3chart Deployment apps/v1 false false"

- name: helm detect show all ignore removals
steps:
- script: pluto detect-helm --helm-version=3 -A --ignore-removals --ignore-deprecations -t v1.16.0
assertions:
- result.code ShouldEqual 0
- result.systemout ShouldContainSubstring "NAME KIND VERSION REPLACEMENT REMOVED DEPRECATED "
- result.systemout ShouldContainSubstring "test-helm3chart-v1beta1 Deployment extensions/v1beta1 apps/v1 true true "
- result.systemout ShouldContainSubstring "test-helm3chart Deployment apps/v1 false false "
- result.systemout ShouldContainSubstring "NAME KIND VERSION REPLACEMENT REMOVED DEPRECATED"
- result.systemout ShouldContainSubstring "test/test-helm3chart-v1beta1 Deployment extensions/v1beta1 apps/v1 true true"
- result.systemout ShouldContainSubstring "test/test-helm3chart Deployment apps/v1 false false"

- name: cleanup
steps:
Expand Down
12 changes: 6 additions & 6 deletions e2e/tests/02_helm-detect-2.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,18 @@ testcases:
- script: pluto detect-helm --helm-version=2 -A -t v1.15.0
assertions:
- result.code ShouldEqual 2
- result.systemout ShouldContainSubstring "NAME KIND VERSION REPLACEMENT REMOVED DEPRECATED"
- result.systemout ShouldContainSubstring "invincible-zebu-metrics-server Deployment extensions/v1beta1 apps/v1 false true"
- result.systemout ShouldContainSubstring "lunging-bat-metrics-server Deployment apps/v1 false false"
- result.systemout ShouldContainSubstring "NAME KIND VERSION REPLACEMENT REMOVED DEPRECATED "
- result.systemout ShouldContainSubstring "invincible-zebu/invincible-zebu-metrics-server Deployment extensions/v1beta1 apps/v1 false true"
- result.systemout ShouldContainSubstring "lunging-bat/lunging-bat-metrics-server Deployment apps/v1 false false"

- name: helm2 detect in-cluster
steps:
- script: pluto detect-helm --helm-version=2 -t v1.16.0
assertions:
- result.code ShouldEqual 3
- result.systemout ShouldContainSubstring "NAME KIND VERSION REPLACEMENT REMOVED DEPRECATED"
- result.systemout ShouldContainSubstring "invincible-zebu-metrics-server Deployment extensions/v1beta1 apps/v1 true true"
- result.systemout ShouldNotContainSubstring "lunging-bat-metrics-server Deployment apps/v1 false false"
- result.systemout ShouldContainSubstring "NAME KIND VERSION REPLACEMENT REMOVED DEPRECATED"
- result.systemout ShouldContainSubstring "invincible-zebu/invincible-zebu-metrics-server Deployment extensions/v1beta1 apps/v1 true true"
- result.systemout ShouldNotContainSubstring "lunging-bat/lunging-bat-metrics-server Deployment apps/v1 false false"
- name: cleanup
steps:
- script: kubectl delete ns helm-system
3 changes: 0 additions & 3 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -667,9 +667,6 @@ gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
helm.sh/helm v1.2.1 h1:Jrn7kKQqQ/hnFWZEX+9pMFvYqFexkzrBnGqYBmIph7c=
helm.sh/helm v2.16.5+incompatible h1:cWIBFS2bwUEgWSIggw4gvwdWFH0BLE54X7/3WszxjWc=
helm.sh/helm v2.16.5+incompatible/go.mod h1:0Xbc6ErzwWH9qC55X1+hE3ZwhM3atbhCm/NbFZw5i+4=
helm.sh/helm v2.16.6+incompatible h1:bpHl8mnkfGRx3CL/kfolSVU99U7P71G8ynHlumMJVTE=
helm.sh/helm v2.16.6+incompatible/go.mod h1:0Xbc6ErzwWH9qC55X1+hE3ZwhM3atbhCm/NbFZw5i+4=
helm.sh/helm/v3 v3.1.2 h1:VpNzaNv2DX4aRnOCcV7v5Of+XT2SZrJ8iOQ25AGKOos=
Expand Down
93 changes: 76 additions & 17 deletions pkg/helm/helm.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
package helm

import (
"encoding/json"
"fmt"

helmstoragev2 "helm.sh/helm/pkg/storage"
Expand All @@ -27,16 +28,25 @@ import (

// Helm represents all current releases that we can find in the cluster
type Helm struct {
CurrentReleases []*Release
Outputs []*api.Output
Version string
Kube *kube
Releases []*Release
Outputs []*api.Output
Version string
Kube *kube
}

// Release is a single version of a chart release
type Release struct {
Name string `json:"metadata.name" yaml:"metadata.name"`
Manifest string `json:"manifest,omitempty"`
Name string `json:"name"`
Chart *Chart `json:"chart"`
Manifest string `json:"manifest"`
}

type Chart struct {
sudermanjr marked this conversation as resolved.
Show resolved Hide resolved
Metadata *ChartMeta `json:"metadata"`
}

type ChartMeta struct {
Name string `json:"name"`
Version string `json:"version"`
}

// NewHelm returns a basic helm struct with the version of helm requested
Expand All @@ -53,18 +63,17 @@ func (h *Helm) FindVersions() error {

switch h.Version {
case "2":
err = h.getManifestsVersionTwo()
err = h.getReleasesVersionTwo()
case "3":
err = h.getManifestsVersionThree()
err = h.getReleasesVersionThree()
default:
err = fmt.Errorf("helm version either not specified or incorrect (use 2 or 3)")
}

return err
}

// getManifestsVersionTwo retrieves helm 2 manifests from ConfigMaps
func (h *Helm) getManifestsVersionTwo() error {
// getReleasesVersionTwo retrieves helm 2 releases from ConfigMaps
func (h *Helm) getReleasesVersionTwo() error {
if h.Version != "2" {
return fmt.Errorf("helm 2 function called without helm 2 version set")
}
Expand All @@ -75,17 +84,27 @@ func (h *Helm) getManifestsVersionTwo() error {
return err
}
for _, release := range list {
outList, err := checkForAPIVersion([]byte(release.Manifest))
deployed, err := helmClient.Deployed(release.Name)
if err != nil {
return fmt.Errorf("error parsing helm release '%s'\n %w", release.Name, err)
return fmt.Errorf("error determining most recent deployed for '%s'\n %w", release.Name, err)
}
h.Outputs = append(h.Outputs, outList...)
if release.Version != deployed.Version {
continue
}
rel, err := helmToRelease(release)
if err != nil {
return fmt.Errorf("error converting helm release '%s' to internal object\n %w", release.Name, err)
}
h.Releases = append(h.Releases, rel)
}
if err := h.findVersions(); err != nil {
return err
}
return nil
}

// getManifestsVersionThree retrieves helm 3 manifests from Secrets
func (h *Helm) getManifestsVersionThree() error {
// getReleasesVersionThree retrieves helm 3 releases from Secrets
func (h *Helm) getReleasesVersionThree() error {
if h.Version != "3" {
return fmt.Errorf("helm 3 function called without helm 3 version set")
}
Expand All @@ -96,11 +115,36 @@ func (h *Helm) getManifestsVersionThree() error {
return err
}
for _, release := range list {
deployed, err := helmClient.Deployed(release.Name)
if err != nil {
return fmt.Errorf("error determining most recent deployed for '%s'\n %w", release.Name, err)
}
if release.Version != deployed.Version {
continue
}
rel, err := helmToRelease(release)
if err != nil {
return fmt.Errorf("error converting helm release '%s' to internal object\n %w", release.Name, err)
}
h.Releases = append(h.Releases, rel)
}
if err := h.findVersions(); err != nil {
return err
}
return nil
}

func (h *Helm) findVersions() error {
for _, release := range h.Releases {
outList, err := checkForAPIVersion([]byte(release.Manifest))
if err != nil {
return fmt.Errorf("error parsing release '%s'\n %w", release.Name, err)
}
for _, out := range outList {
out.Name = release.Name + "/" + out.Name
}
h.Outputs = append(h.Outputs, outList...)

}
return nil
}
Expand All @@ -116,3 +160,18 @@ func checkForAPIVersion(manifest []byte) ([]*api.Output, error) {
}
return outputs, nil
}

func helmToRelease(helmRelease interface{}) (*Release, error) {
jsonRel, err := json.Marshal(helmRelease)
if err != nil {
return nil, fmt.Errorf("error marshaling release to json")
}
return marshalToRelease(jsonRel)
}

// marshalToRelease marshals release data into the Pluto Release type so we have a common type regardless of helm version
func marshalToRelease(jsonRel []byte) (*Release, error) {
var ret = new(Release)
err := json.Unmarshal(jsonRel, ret)
return ret, err
}
12 changes: 6 additions & 6 deletions pkg/helm/helm_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ var (
}
wantOutput = []*api.Output{
{
Name: "helmtest-helmchartest-v1beta1",
Name: "helmtest/helmtest-helmchartest-v1beta1",
APIVersion: &api.Version{
Name: "extensions/v1beta1",
Kind: "Deployment",
Expand All @@ -69,7 +69,7 @@ var (
},
},
{
Name: "helmtest-helmchartest",
Name: "helmtest/helmtest-helmchartest",
APIVersion: &api.Version{
Name: "apps/v1",
Kind: "Deployment",
Expand Down Expand Up @@ -161,7 +161,7 @@ func TestHelm_getManifestsVersionTwo(t *testing.T) {
}
}
t.Run(tt.name, func(t *testing.T) {
err := h.getManifestsVersionTwo()
err := h.getReleasesVersionTwo()
if tt.wantErr {
assert.EqualError(t, err, tt.errMessage)
return
Expand Down Expand Up @@ -204,7 +204,7 @@ func TestHelm_getManifestsVersionThree(t *testing.T) {
}
}
t.Run(tt.name, func(t *testing.T) {
err := h.getManifestsVersionThree()
err := h.getReleasesVersionThree()
if tt.wantErr {
assert.EqualError(t, err, tt.errMessage)
return
Expand Down Expand Up @@ -247,9 +247,9 @@ func TestHelm_getManifest_badClient(t *testing.T) {
var err error
switch tt.helmVersion {
case "2":
err = h.getManifestsVersionTwo()
err = h.getReleasesVersionTwo()
case "3":
err = h.getManifestsVersionThree()
err = h.getReleasesVersionThree()
}
if tt.wantErr {
assert.Error(t, err)
Expand Down