status command retrieves release status
This commit is contained in:
		
							parent
							
								
									efe5a2e56b
								
							
						
					
					
						commit
						579fa4c765
					
				| 
						 | 
					@ -134,6 +134,7 @@ COMMANDS:
 | 
				
			||||||
     charts  sync charts from state file (helm upgrade --install)
 | 
					     charts  sync charts from state file (helm upgrade --install)
 | 
				
			||||||
     diff    diff charts from state file against env (helm diff)
 | 
					     diff    diff charts from state file against env (helm diff)
 | 
				
			||||||
     sync    sync all resources from state file (repos, charts and local chart deps)
 | 
					     sync    sync all resources from state file (repos, charts and local chart deps)
 | 
				
			||||||
 | 
					     status  retrieve status of releases in state file
 | 
				
			||||||
     delete  delete charts from state file (helm delete)
 | 
					     delete  delete charts from state file (helm delete)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
GLOBAL OPTIONS:
 | 
					GLOBAL OPTIONS:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -59,6 +59,14 @@ func (helm *execer) SyncRelease(name, chart string, flags ...string) error {
 | 
				
			||||||
	return err
 | 
						return err
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (helm *execer) ReleaseStatus(name string) error {
 | 
				
			||||||
 | 
						out, err := helm.exec(append([]string{"status", name})...)
 | 
				
			||||||
 | 
						if helm.writer != nil {
 | 
				
			||||||
 | 
							helm.writer.Write(out)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return err
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (helm *execer) DecryptSecret(name string) (string, error) {
 | 
					func (helm *execer) DecryptSecret(name string) (string, error) {
 | 
				
			||||||
	out, err := helm.exec(append([]string{"secrets", "dec", name})...)
 | 
						out, err := helm.exec(append([]string{"secrets", "dec", name})...)
 | 
				
			||||||
	helm.write(out)
 | 
						helm.write(out)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -155,6 +155,16 @@ func Test_DeleteRelease(t *testing.T) {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func Test_ReleaseStatus(t *testing.T) {
 | 
				
			||||||
 | 
						var buffer bytes.Buffer
 | 
				
			||||||
 | 
						helm := MockExecer(&buffer, "dev")
 | 
				
			||||||
 | 
						helm.ReleaseStatus("myRelease")
 | 
				
			||||||
 | 
						expected := "exec: helm status myRelease --kube-context dev\n"
 | 
				
			||||||
 | 
						if buffer.String() != expected {
 | 
				
			||||||
 | 
							t.Errorf("helmexec.ReleaseStatus()\nactual = %v\nexpect = %v", buffer.String(), expected)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func Test_exec(t *testing.T) {
 | 
					func Test_exec(t *testing.T) {
 | 
				
			||||||
	var buffer bytes.Buffer
 | 
						var buffer bytes.Buffer
 | 
				
			||||||
	helm := MockExecer(&buffer, "")
 | 
						helm := MockExecer(&buffer, "")
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -9,6 +9,7 @@ type Interface interface {
 | 
				
			||||||
	UpdateDeps(chart string) error
 | 
						UpdateDeps(chart string) error
 | 
				
			||||||
	SyncRelease(name, chart string, flags ...string) error
 | 
						SyncRelease(name, chart string, flags ...string) error
 | 
				
			||||||
	DiffRelease(name, chart string, flags ...string) error
 | 
						DiffRelease(name, chart string, flags ...string) error
 | 
				
			||||||
 | 
						ReleaseStatus(name string) error
 | 
				
			||||||
	DeleteRelease(name string) error
 | 
						DeleteRelease(name string) error
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	DecryptSecret(name string) (string, error)
 | 
						DecryptSecret(name string) (string, error)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										32
									
								
								main.go
								
								
								
								
							
							
						
						
									
										32
									
								
								main.go
								
								
								
								
							| 
						 | 
					@ -218,6 +218,38 @@ func main() {
 | 
				
			||||||
				return clean(state, errs)
 | 
									return clean(state, errs)
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								Name:  "status",
 | 
				
			||||||
 | 
								Usage: "retrieve status of releases in state file",
 | 
				
			||||||
 | 
								Flags: []cli.Flag{
 | 
				
			||||||
 | 
									cli.IntFlag{
 | 
				
			||||||
 | 
										Name:  "concurrency",
 | 
				
			||||||
 | 
										Value: 0,
 | 
				
			||||||
 | 
										Usage: "maximum number of concurrent helm processes to run, 0 is unlimited",
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
									cli.StringFlag{
 | 
				
			||||||
 | 
										Name:  "args",
 | 
				
			||||||
 | 
										Value: "",
 | 
				
			||||||
 | 
										Usage: "pass args to helm exec",
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								Action: func(c *cli.Context) error {
 | 
				
			||||||
 | 
									state, helm, err := before(c)
 | 
				
			||||||
 | 
									if err != nil {
 | 
				
			||||||
 | 
										return err
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									workers := c.Int("concurrency")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									args := c.String("args")
 | 
				
			||||||
 | 
									if len(args) > 0 {
 | 
				
			||||||
 | 
										helm.SetExtraArgs(strings.Split(args, " ")...)
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									errs := state.ReleaseStatuses(helm, workers)
 | 
				
			||||||
 | 
									return clean(state, errs)
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			Name:  "delete",
 | 
								Name:  "delete",
 | 
				
			||||||
			Usage: "delete charts from state file (helm delete)",
 | 
								Usage: "delete charts from state file (helm delete)",
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -298,6 +298,49 @@ func (state *HelmState) DiffReleases(helm helmexec.Interface, additionalValues [
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (state *HelmState) ReleaseStatuses(helm helmexec.Interface, workerLimit int) []error {
 | 
				
			||||||
 | 
						var errs []error
 | 
				
			||||||
 | 
						jobQueue := make(chan ReleaseSpec)
 | 
				
			||||||
 | 
						doneQueue := make(chan bool)
 | 
				
			||||||
 | 
						errQueue := make(chan error)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if workerLimit < 1 {
 | 
				
			||||||
 | 
							workerLimit = len(state.Releases)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						for w := 1; w <= workerLimit; w++ {
 | 
				
			||||||
 | 
							go func() {
 | 
				
			||||||
 | 
								for release := range jobQueue {
 | 
				
			||||||
 | 
									if err := helm.ReleaseStatus(release.Name); err != nil {
 | 
				
			||||||
 | 
										errQueue <- err
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									doneQueue <- true
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}()
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						go func() {
 | 
				
			||||||
 | 
							for _, release := range state.Releases {
 | 
				
			||||||
 | 
								jobQueue <- release
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							close(jobQueue)
 | 
				
			||||||
 | 
						}()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for i := 0; i < len(state.Releases); {
 | 
				
			||||||
 | 
							select {
 | 
				
			||||||
 | 
							case err := <-errQueue:
 | 
				
			||||||
 | 
								errs = append(errs, err)
 | 
				
			||||||
 | 
							case <-doneQueue:
 | 
				
			||||||
 | 
								i++
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if len(errs) != 0 {
 | 
				
			||||||
 | 
							return errs
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// DeleteReleases wrapper for executing helm delete on the releases
 | 
					// DeleteReleases wrapper for executing helm delete on the releases
 | 
				
			||||||
func (state *HelmState) DeleteReleases(helm helmexec.Interface) []error {
 | 
					func (state *HelmState) DeleteReleases(helm helmexec.Interface) []error {
 | 
				
			||||||
	var wg sync.WaitGroup
 | 
						var wg sync.WaitGroup
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -468,8 +468,9 @@ func Test_normalizeChart(t *testing.T) {
 | 
				
			||||||
// mocking helmexec.Interface
 | 
					// mocking helmexec.Interface
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type mockHelmExec struct {
 | 
					type mockHelmExec struct {
 | 
				
			||||||
	charts []string
 | 
						charts   []string
 | 
				
			||||||
	repo   []string
 | 
						repo     []string
 | 
				
			||||||
 | 
						releases []string
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (helm *mockHelmExec) UpdateDeps(chart string) error {
 | 
					func (helm *mockHelmExec) UpdateDeps(chart string) error {
 | 
				
			||||||
| 
						 | 
					@ -496,6 +497,13 @@ func (helm *mockHelmExec) SyncRelease(name, chart string, flags ...string) error
 | 
				
			||||||
func (helm *mockHelmExec) DiffRelease(name, chart string, flags ...string) error {
 | 
					func (helm *mockHelmExec) DiffRelease(name, chart string, flags ...string) error {
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					func (helm *mockHelmExec) ReleaseStatus(release string) error {
 | 
				
			||||||
 | 
						if strings.Contains(release, "error") {
 | 
				
			||||||
 | 
							return errors.New("error")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						helm.releases = append(helm.releases, release)
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
func (helm *mockHelmExec) DeleteRelease(name string) error {
 | 
					func (helm *mockHelmExec) DeleteRelease(name string) error {
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -591,3 +599,50 @@ func TestHelmState_UpdateDeps(t *testing.T) {
 | 
				
			||||||
		t.Errorf("HelmState.UpdateDeps() - no errors, but got: %v", len(errs))
 | 
							t.Errorf("HelmState.UpdateDeps() - no errors, but got: %v", len(errs))
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestHelmState_ReleaseStatuses(t *testing.T) {
 | 
				
			||||||
 | 
						tests := []struct {
 | 
				
			||||||
 | 
							name     string
 | 
				
			||||||
 | 
							releases []ReleaseSpec
 | 
				
			||||||
 | 
							helm     *mockHelmExec
 | 
				
			||||||
 | 
							want     []string
 | 
				
			||||||
 | 
							wantErr  bool
 | 
				
			||||||
 | 
						}{
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								name: "happy path",
 | 
				
			||||||
 | 
								releases: []ReleaseSpec{
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										Name: "releaseA",
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								helm: &mockHelmExec{},
 | 
				
			||||||
 | 
								want: []string{"releaseA"},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								name: "happy path",
 | 
				
			||||||
 | 
								releases: []ReleaseSpec{
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										Name: "error",
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								helm:    &mockHelmExec{},
 | 
				
			||||||
 | 
								wantErr: true,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						for _, tt := range tests {
 | 
				
			||||||
 | 
							i := func(t *testing.T) {
 | 
				
			||||||
 | 
								state := &HelmState{
 | 
				
			||||||
 | 
									Releases: tt.releases,
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								errs := state.ReleaseStatuses(tt.helm, 1)
 | 
				
			||||||
 | 
								if (errs != nil) != tt.wantErr {
 | 
				
			||||||
 | 
									t.Errorf("ReleaseStatuses() for %s error = %v, wantErr %v", tt.name, errs, tt.wantErr)
 | 
				
			||||||
 | 
									return
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if !reflect.DeepEqual(tt.helm.releases, tt.want) {
 | 
				
			||||||
 | 
									t.Errorf("HelmState.ReleaseStatuses() for [%s] = %v, want %v", tt.name, tt.helm.releases, tt.want)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							t.Run(tt.name, i)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue