Merge pull request #70 from cmeury/status-command
status command retrieves release status
This commit is contained in:
commit
44241f675f
|
|
@ -134,6 +134,7 @@ COMMANDS:
|
|||
charts sync charts from state file (helm upgrade --install)
|
||||
diff diff charts from state file against env (helm diff)
|
||||
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)
|
||||
|
||||
GLOBAL OPTIONS:
|
||||
|
|
|
|||
|
|
@ -59,6 +59,14 @@ func (helm *execer) SyncRelease(name, chart string, flags ...string) error {
|
|||
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) {
|
||||
out, err := helm.exec(append([]string{"secrets", "dec", name})...)
|
||||
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) {
|
||||
var buffer bytes.Buffer
|
||||
helm := MockExecer(&buffer, "")
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ type Interface interface {
|
|||
UpdateDeps(chart string) error
|
||||
SyncRelease(name, chart string, flags ...string) error
|
||||
DiffRelease(name, chart string, flags ...string) error
|
||||
ReleaseStatus(name string) error
|
||||
DeleteRelease(name string) error
|
||||
|
||||
DecryptSecret(name string) (string, error)
|
||||
|
|
|
|||
32
main.go
32
main.go
|
|
@ -218,6 +218,38 @@ func main() {
|
|||
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",
|
||||
Usage: "delete charts from state file (helm delete)",
|
||||
|
|
|
|||
|
|
@ -298,6 +298,49 @@ func (state *HelmState) DiffReleases(helm helmexec.Interface, additionalValues [
|
|||
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
|
||||
func (state *HelmState) DeleteReleases(helm helmexec.Interface) []error {
|
||||
var wg sync.WaitGroup
|
||||
|
|
|
|||
|
|
@ -468,8 +468,9 @@ func Test_normalizeChart(t *testing.T) {
|
|||
// mocking helmexec.Interface
|
||||
|
||||
type mockHelmExec struct {
|
||||
charts []string
|
||||
repo []string
|
||||
charts []string
|
||||
repo []string
|
||||
releases []string
|
||||
}
|
||||
|
||||
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 {
|
||||
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 {
|
||||
return nil
|
||||
}
|
||||
|
|
@ -591,3 +599,50 @@ func TestHelmState_UpdateDeps(t *testing.T) {
|
|||
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