From cfbabbb6147b6b7e804e1a311c6c9a79c4962ea8 Mon Sep 17 00:00:00 2001 From: Felix Moehler Date: Wed, 8 Nov 2023 11:13:38 +0100 Subject: [PATCH 1/6] add global flags to bosh deploy command --- cmd/cmd.go | 2 +- cmd/deploy.go | 49 +++++++++++++++++++++++++++++++++++++++++++++- cmd/deploy_test.go | 21 +++++++++++++++++++- 3 files changed, 69 insertions(+), 3 deletions(-) diff --git a/cmd/cmd.go b/cmd/cmd.go index 636c2ba51..3a0f5f158 100644 --- a/cmd/cmd.go +++ b/cmd/cmd.go @@ -337,7 +337,7 @@ func (c Cmd) Execute() (cmdErr error) { case *DeployOpts: director, deployment := c.directorAndDeployment() releaseManager := c.releaseManager(director) - return NewDeployCmd(deps.UI, deployment, releaseManager).Run(*opts) + return NewDeployCmd(deps.UI, deployment, releaseManager, director).Run(*opts) case *StartOpts: return NewStartCmd(deps.UI, c.deployment()).Run(*opts) diff --git a/cmd/deploy.go b/cmd/deploy.go index 7171fba9c..260b584a7 100644 --- a/cmd/deploy.go +++ b/cmd/deploy.go @@ -2,6 +2,7 @@ package cmd import ( bosherr "github.com/cloudfoundry/bosh-utils/errors" + "gopkg.in/yaml.v3" . "github.com/cloudfoundry/bosh-cli/v7/cmd/opts" boshdir "github.com/cloudfoundry/bosh-cli/v7/director" @@ -13,6 +14,7 @@ type DeployCmd struct { ui boshui.UI deployment boshdir.Deployment releaseUploader ReleaseUploader + director boshdir.Director } type ReleaseUploader interface { @@ -20,17 +22,36 @@ type ReleaseUploader interface { UploadReleasesWithFix([]byte) ([]byte, error) } +type Conf struct { + Flags []string `yaml:"flags"` + IncludeDeployments []string `yaml:"include"` +} + func NewDeployCmd( ui boshui.UI, deployment boshdir.Deployment, releaseUploader ReleaseUploader, + director boshdir.Director, ) DeployCmd { - return DeployCmd{ui, deployment, releaseUploader} + return DeployCmd{ui, deployment, releaseUploader, director} } func (c DeployCmd) Run(opts DeployOpts) error { tpl := boshtpl.NewTemplate(opts.Args.Manifest.Bytes) + configs, _ := c.director.ListConfigs(1, boshdir.ConfigsFilter{Type: "deploy"}) + + for _, config := range configs { + var conf Conf + + yaml.Unmarshal([]byte(config.Content), &conf) + if conf.IncludeDeployments == nil || includeContains(conf.IncludeDeployments, c.deployment.Name()) { + c.ui.PrintLinef("Using deployment flags from config of type '%s' (name: '%s')", config.Type, config.Name) + + opts = setFlags(conf.Flags, opts) + } + } + bytes, err := tpl.Evaluate(opts.VarFlags.AsVariables(), opts.OpsFlags.AsOp(), boshtpl.EvaluateOpts{}) if err != nil { return bosherr.WrapErrorf(err, "Evaluating manifest") @@ -77,6 +98,32 @@ func (c DeployCmd) Run(opts DeployOpts) error { return c.deployment.Update(bytes, updateOpts) } +func setFlags(flags []string, opts DeployOpts) DeployOpts { + for j := range flags { + switch flags[j] { + case "fix-releases": + opts.FixReleases = true + case "fix": + opts.Fix = true + case "recreate": + opts.Recreate = true + case "recreate-persistent-disks": + opts.RecreatePersistentDisks = true + } + } + + return opts +} + +func includeContains(slice []string, value string) bool { + for _, item := range slice { + if item == value { + return true + } + } + return false +} + func (c DeployCmd) checkDeploymentName(bytes []byte) error { manifest, err := boshdir.NewManifestFromBytes(bytes) if err != nil { diff --git a/cmd/deploy_test.go b/cmd/deploy_test.go index f01b7fc48..7863d6f64 100644 --- a/cmd/deploy_test.go +++ b/cmd/deploy_test.go @@ -21,6 +21,7 @@ var _ = Describe("DeployCmd", func() { ui *fakeui.FakeUI deployment *fakedir.FakeDeployment releaseUploader *fakecmd.FakeReleaseUploader + director *fakedir.FakeDirector command DeployCmd ) @@ -34,7 +35,9 @@ var _ = Describe("DeployCmd", func() { UploadReleasesStub: func(bytes []byte) ([]byte, error) { return bytes, nil }, } - command = NewDeployCmd(ui, deployment, releaseUploader) + director = &fakedir.FakeDirector{} + + command = NewDeployCmd(ui, deployment, releaseUploader, director) }) Describe("Run", func() { @@ -281,5 +284,21 @@ releases: Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("fake-err")) }) + + It("overrides the opts with the flags from configs of type deploy", func() { + configs := []boshdir.Config{{"1", "default", "deploy", "0000", "", "flags:\n - fix", true}} + + director.ListConfigsReturns(configs, nil) + + err := act() + Expect(err).ToNot(HaveOccurred()) + Expect(deployment.UpdateCallCount()).To(Equal(1)) + + _, updateOpts := deployment.UpdateArgsForCall(0) + + Expect(updateOpts).To(Equal(boshdir.UpdateOpts{ + Fix: true, + })) + }) }) }) From 55961e4b1feb77b02284e6428a753afc0971171b Mon Sep 17 00:00:00 2001 From: Felix Moehler Date: Thu, 9 Nov 2023 13:25:46 +0100 Subject: [PATCH 2/6] add excluding of deployments and tests --- cmd/deploy.go | 22 ++++++++++++--- cmd/deploy_test.go | 70 +++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 87 insertions(+), 5 deletions(-) diff --git a/cmd/deploy.go b/cmd/deploy.go index 260b584a7..3cc2ea89a 100644 --- a/cmd/deploy.go +++ b/cmd/deploy.go @@ -25,6 +25,7 @@ type ReleaseUploader interface { type Conf struct { Flags []string `yaml:"flags"` IncludeDeployments []string `yaml:"include"` + ExcludeDeployments []string `yaml:"exclude"` } func NewDeployCmd( @@ -45,10 +46,23 @@ func (c DeployCmd) Run(opts DeployOpts) error { var conf Conf yaml.Unmarshal([]byte(config.Content), &conf) - if conf.IncludeDeployments == nil || includeContains(conf.IncludeDeployments, c.deployment.Name()) { - c.ui.PrintLinef("Using deployment flags from config of type '%s' (name: '%s')", config.Type, config.Name) - opts = setFlags(conf.Flags, opts) + deploymentIncluded := containsDeployment(conf.IncludeDeployments, c.deployment.Name()) + deploymentExcluded := containsDeployment(conf.ExcludeDeployments, c.deployment.Name()) + + if conf.ExcludeDeployments != nil && + conf.IncludeDeployments != nil { + c.ui.PrintLinef("Ignoring deployment flags from config of type '%s' (name: '%s'). Please use only 'include'- OR 'exclude'-property in the config.", config.Type, config.Name) + } else { + if (conf.IncludeDeployments == nil && conf.ExcludeDeployments == nil) || + deploymentIncluded || + (!deploymentExcluded && conf.ExcludeDeployments != nil) { + c.ui.PrintLinef("!!!!!!!") + c.ui.PrintLinef("Using deployment flags from config of type '%s' (name: '%s')", config.Type, config.Name) + c.ui.PrintLinef("!!!!!!!") + + opts = setFlags(conf.Flags, opts) + } } } @@ -115,7 +129,7 @@ func setFlags(flags []string, opts DeployOpts) DeployOpts { return opts } -func includeContains(slice []string, value string) bool { +func containsDeployment(slice []string, value string) bool { for _, item := range slice { if item == value { return true diff --git a/cmd/deploy_test.go b/cmd/deploy_test.go index 7863d6f64..c4df4300d 100644 --- a/cmd/deploy_test.go +++ b/cmd/deploy_test.go @@ -285,7 +285,7 @@ releases: Expect(err.Error()).To(ContainSubstring("fake-err")) }) - It("overrides the opts with the flags from configs of type deploy", func() { + It("overwrites the opts with the flags from configs of type deploy", func() { configs := []boshdir.Config{{"1", "default", "deploy", "0000", "", "flags:\n - fix", true}} director.ListConfigsReturns(configs, nil) @@ -300,5 +300,73 @@ releases: Fix: true, })) }) + + It("overwrites the opts with the flags from configs of type deploy if the deployment is included", func() { + configs := []boshdir.Config{{"1", "default", "deploy", "0000", "", "flags:\n - fix\ninclude:\n - dep", true}} + + director.ListConfigsReturns(configs, nil) + deployment.NameReturns("dep") + + err := act() + Expect(err).ToNot(HaveOccurred()) + Expect(deployment.UpdateCallCount()).To(Equal(1)) + + _, updateOpts := deployment.UpdateArgsForCall(0) + + Expect(updateOpts).To(Equal(boshdir.UpdateOpts{ + Fix: true, + })) + }) + + It("does not overwrite the opts with the flags from configs of type deploy if the deployment is not included", func() { + configs := []boshdir.Config{{"1", "default", "deploy", "0000", "", "flags:\n - fix\ninclude:\n - foo", true}} + + director.ListConfigsReturns(configs, nil) + deployment.NameReturns("dep") + + err := act() + Expect(err).ToNot(HaveOccurred()) + Expect(deployment.UpdateCallCount()).To(Equal(1)) + + _, updateOpts := deployment.UpdateArgsForCall(0) + + Expect(updateOpts).To(Equal(boshdir.UpdateOpts{ + Fix: false, + })) + }) + + It("does not overwrite the opts with the flags from configs of type deploy if the deployment is excluded", func() { + configs := []boshdir.Config{{"1", "default", "deploy", "0000", "", "flags:\n - fix\nexclude:\n - dep", true}} + + director.ListConfigsReturns(configs, nil) + deployment.NameReturns("dep") + + err := act() + Expect(err).ToNot(HaveOccurred()) + Expect(deployment.UpdateCallCount()).To(Equal(1)) + + _, updateOpts := deployment.UpdateArgsForCall(0) + + Expect(updateOpts).To(Equal(boshdir.UpdateOpts{ + Fix: false, + })) + }) + + It("overwrites the opts with the flags from configs of type deploy if the deployment is not excluded", func() { + configs := []boshdir.Config{{"1", "default", "deploy", "0000", "", "flags:\n - fix\nexclude:\n - foo", true}} + + director.ListConfigsReturns(configs, nil) + deployment.NameReturns("dep") + + err := act() + Expect(err).ToNot(HaveOccurred()) + Expect(deployment.UpdateCallCount()).To(Equal(1)) + + _, updateOpts := deployment.UpdateArgsForCall(0) + + Expect(updateOpts).To(Equal(boshdir.UpdateOpts{ + Fix: true, + })) + }) }) }) From f80c9e4279f7085fc409cdc9f24b7b453383aeec Mon Sep 17 00:00:00 2001 From: Felix Moehler Date: Thu, 23 Nov 2023 10:17:38 +0100 Subject: [PATCH 3/6] color the cli output in case deployment flags are used --- cmd/deploy.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/cmd/deploy.go b/cmd/deploy.go index 3cc2ea89a..47ddd01f6 100644 --- a/cmd/deploy.go +++ b/cmd/deploy.go @@ -57,9 +57,7 @@ func (c DeployCmd) Run(opts DeployOpts) error { if (conf.IncludeDeployments == nil && conf.ExcludeDeployments == nil) || deploymentIncluded || (!deploymentExcluded && conf.ExcludeDeployments != nil) { - c.ui.PrintLinef("!!!!!!!") - c.ui.PrintLinef("Using deployment flags from config of type '%s' (name: '%s')", config.Type, config.Name) - c.ui.PrintLinef("!!!!!!!") + c.ui.ErrorLinef("Using deployment flags from config of type '%s' (name: '%s')", config.Type, config.Name) opts = setFlags(conf.Flags, opts) } From d7ae88a15ceb0179f8125384ea9c106b8bd1b140 Mon Sep 17 00:00:00 2001 From: Felix Moehler Date: Thu, 23 Nov 2023 10:19:37 +0100 Subject: [PATCH 4/6] rename the search function --- cmd/deploy.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cmd/deploy.go b/cmd/deploy.go index 47ddd01f6..b2f76636f 100644 --- a/cmd/deploy.go +++ b/cmd/deploy.go @@ -47,8 +47,8 @@ func (c DeployCmd) Run(opts DeployOpts) error { yaml.Unmarshal([]byte(config.Content), &conf) - deploymentIncluded := containsDeployment(conf.IncludeDeployments, c.deployment.Name()) - deploymentExcluded := containsDeployment(conf.ExcludeDeployments, c.deployment.Name()) + deploymentIncluded := applies(conf.IncludeDeployments, c.deployment.Name()) + deploymentExcluded := applies(conf.ExcludeDeployments, c.deployment.Name()) if conf.ExcludeDeployments != nil && conf.IncludeDeployments != nil { @@ -127,7 +127,7 @@ func setFlags(flags []string, opts DeployOpts) DeployOpts { return opts } -func containsDeployment(slice []string, value string) bool { +func applies(slice []string, value string) bool { for _, item := range slice { if item == value { return true From 958d4aa3578341992a7a648a378ea342c1f9479c Mon Sep 17 00:00:00 2001 From: Felix Moehler Date: Thu, 23 Nov 2023 17:00:47 +0100 Subject: [PATCH 5/6] fix issues --- cmd/deploy.go | 5 ++++- cmd/deploy_test.go | 48 ++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 48 insertions(+), 5 deletions(-) diff --git a/cmd/deploy.go b/cmd/deploy.go index b2f76636f..c1f05494c 100644 --- a/cmd/deploy.go +++ b/cmd/deploy.go @@ -45,7 +45,10 @@ func (c DeployCmd) Run(opts DeployOpts) error { for _, config := range configs { var conf Conf - yaml.Unmarshal([]byte(config.Content), &conf) + err := yaml.Unmarshal([]byte(config.Content), &conf) + if err != nil { + return err + } deploymentIncluded := applies(conf.IncludeDeployments, c.deployment.Name()) deploymentExcluded := applies(conf.ExcludeDeployments, c.deployment.Name()) diff --git a/cmd/deploy_test.go b/cmd/deploy_test.go index c4df4300d..a6916939f 100644 --- a/cmd/deploy_test.go +++ b/cmd/deploy_test.go @@ -302,7 +302,17 @@ releases: }) It("overwrites the opts with the flags from configs of type deploy if the deployment is included", func() { - configs := []boshdir.Config{{"1", "default", "deploy", "0000", "", "flags:\n - fix\ninclude:\n - dep", true}} + configs := []boshdir.Config{ + { + ID: "1", + Name: "default", + Type: "deploy", + CreatedAt: "0000", + Team: "", + Content: "flags:\n - fix\ninclude:\n - dep", + Current: true, + }, + } director.ListConfigsReturns(configs, nil) deployment.NameReturns("dep") @@ -319,7 +329,17 @@ releases: }) It("does not overwrite the opts with the flags from configs of type deploy if the deployment is not included", func() { - configs := []boshdir.Config{{"1", "default", "deploy", "0000", "", "flags:\n - fix\ninclude:\n - foo", true}} + configs := []boshdir.Config{ + { + ID: "1", + Name: "default", + Type: "deploy", + CreatedAt: "0000", + Team: "", + Content: "flags:\n - fix\ninclude:\n - foo", + Current: true, + }, + } director.ListConfigsReturns(configs, nil) deployment.NameReturns("dep") @@ -336,7 +356,17 @@ releases: }) It("does not overwrite the opts with the flags from configs of type deploy if the deployment is excluded", func() { - configs := []boshdir.Config{{"1", "default", "deploy", "0000", "", "flags:\n - fix\nexclude:\n - dep", true}} + configs := []boshdir.Config{ + { + ID: "1", + Name: "default", + Type: "deploy", + CreatedAt: "0000", + Team: "", + Content: "flags:\n - fix\nexclude:\n - dep", + Current: true, + }, + } director.ListConfigsReturns(configs, nil) deployment.NameReturns("dep") @@ -353,7 +383,17 @@ releases: }) It("overwrites the opts with the flags from configs of type deploy if the deployment is not excluded", func() { - configs := []boshdir.Config{{"1", "default", "deploy", "0000", "", "flags:\n - fix\nexclude:\n - foo", true}} + configs := []boshdir.Config{ + { + ID: "1", + Name: "default", + Type: "deploy", + CreatedAt: "0000", + Team: "", + Content: "flags:\n - fix\nexclude:\n - foo", + Current: true, + }, + } director.ListConfigsReturns(configs, nil) deployment.NameReturns("dep") From 1a8d04da825b66969c0d0aaac7e4f730dae41e2e Mon Sep 17 00:00:00 2001 From: Felix Moehler Date: Thu, 23 Nov 2023 17:31:41 +0100 Subject: [PATCH 6/6] fix some more issues --- cmd/deploy_test.go | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/cmd/deploy_test.go b/cmd/deploy_test.go index a6916939f..99e5890d9 100644 --- a/cmd/deploy_test.go +++ b/cmd/deploy_test.go @@ -286,7 +286,16 @@ releases: }) It("overwrites the opts with the flags from configs of type deploy", func() { - configs := []boshdir.Config{{"1", "default", "deploy", "0000", "", "flags:\n - fix", true}} + configs := []boshdir.Config{ + { + ID: "1", + Name: "default", Type: "deploy", + CreatedAt: "0000", + Team: "", + Content: "flags:\n - fix", + Current: true, + }, + } director.ListConfigsReturns(configs, nil)