From 9a8d3ee4fb261bfa231aa76748667f45aa3afe9d Mon Sep 17 00:00:00 2001 From: Ilya Lesikov Date: Wed, 1 Jun 2022 14:21:26 +0300 Subject: [PATCH] feat: deploy in multiple stages; improve 3way merge * Resource deployment now can happen in multiple stages. * 3-way merge improved for install/upgrade/uninstall/rollback: resources deployed in previous non-successful releases accounted for in merge. Signed-off-by: Ilya Lesikov --- cmd/werf/bundle/apply/apply.go | 1 + cmd/werf/bundle/render/render.go | 1 + cmd/werf/converge/converge.go | 3 + cmd/werf/dismiss/dismiss.go | 1 + cmd/werf/helm/helm.go | 8 ++- cmd/werf/helm/install.go | 2 + cmd/werf/helm/template.go | 2 + cmd/werf/helm/upgrade.go | 2 + cmd/werf/render/render.go | 2 + pkg/buildah/native_linux.go | 2 +- .../stage_builder/dockerfile_stage_builder.go | 1 - pkg/deploy/helm/annotations.go | 2 + pkg/deploy/helm/chart_extender/bundle_test.go | 5 +- pkg/deploy/helm/stages_splitter.go | 57 +++++++++++++++++++ 14 files changed, 82 insertions(+), 7 deletions(-) create mode 100644 pkg/deploy/helm/stages_splitter.go diff --git a/cmd/werf/bundle/apply/apply.go b/cmd/werf/bundle/apply/apply.go index e4b7e6d732..f55b1a90c2 100644 --- a/cmd/werf/bundle/apply/apply.go +++ b/cmd/werf/bundle/apply/apply.go @@ -216,6 +216,7 @@ func runApply() error { } helmUpgradeCmd, _ := helm_v3.NewUpgradeCmd(actionConfig, logboek.Context(ctx).OutStream(), helm_v3.UpgradeCmdOptions{ + StagesSplitter: helm.StagesSplitter{}, ChainPostRenderer: bundle.ChainPostRenderer, ValueOpts: &values.Options{ ValueFiles: common.GetValues(&commonCmdData), diff --git a/cmd/werf/bundle/render/render.go b/cmd/werf/bundle/render/render.go index ecf7cb2a20..5d3566e8f8 100644 --- a/cmd/werf/bundle/render/render.go +++ b/cmd/werf/bundle/render/render.go @@ -225,6 +225,7 @@ func runRender(ctx context.Context) error { } helmTemplateCmd, _ := helm_v3.NewTemplateCmd(actionConfig, output, helm_v3.TemplateCmdOptions{ + StagesSplitter: helm.StagesSplitter{}, ChainPostRenderer: bundle.ChainPostRenderer, ValueOpts: &values.Options{ ValueFiles: common.GetValues(&commonCmdData), diff --git a/cmd/werf/converge/converge.go b/cmd/werf/converge/converge.go index 21d82a4ed6..4d4ee84891 100644 --- a/cmd/werf/converge/converge.go +++ b/cmd/werf/converge/converge.go @@ -23,6 +23,7 @@ import ( "github.com/werf/werf/pkg/build" "github.com/werf/werf/pkg/config/deploy_params" "github.com/werf/werf/pkg/container_backend" + "github.com/werf/werf/pkg/deploy/helm" "github.com/werf/werf/pkg/deploy/helm/chart_extender" "github.com/werf/werf/pkg/deploy/helm/chart_extender/helpers" "github.com/werf/werf/pkg/deploy/helm/command_helpers" @@ -446,6 +447,7 @@ func run(ctx context.Context, containerBackend container_backend.ContainerBacken } helmUpgradeCmd, _ := helm_v3.NewUpgradeCmd(actionConfig, logboek.OutStream(), helm_v3.UpgradeCmdOptions{ + StagesSplitter: helm.StagesSplitter{}, ChainPostRenderer: wc.ChainPostRenderer, ValueOpts: valueOpts, CreateNamespace: common.NewBool(true), @@ -525,6 +527,7 @@ func migrateHelm2ToHelm3(ctx context.Context, releaseName, namespace string, mai } helmTemplateCmd, _ := helm_v3.NewTemplateCmd(actionConfig, ioutil.Discard, helm_v3.TemplateCmdOptions{ + StagesSplitter: helm.StagesSplitter{}, ChainPostRenderer: chainPostRenderer, ValueOpts: valueOpts, Validate: common.NewBool(true), diff --git a/cmd/werf/dismiss/dismiss.go b/cmd/werf/dismiss/dismiss.go index d3d760f219..ec2563c237 100644 --- a/cmd/werf/dismiss/dismiss.go +++ b/cmd/werf/dismiss/dismiss.go @@ -229,6 +229,7 @@ func runDismiss(ctx context.Context) error { } helmUninstallCmd := helm_v3.NewUninstallCmd(actionConfig, logboek.Context(ctx).OutStream(), helm_v3.UninstallCmdOptions{ + StagesSplitter: helm.StagesSplitter{}, DeleteNamespace: &cmdData.WithNamespace, DeleteHooks: &cmdData.WithHooks, }) diff --git a/cmd/werf/helm/helm.go b/cmd/werf/helm/helm.go index 551d7b92d6..b07f29cf03 100644 --- a/cmd/werf/helm/helm.go +++ b/cmd/werf/helm/helm.go @@ -65,7 +65,9 @@ func NewCmd() *cobra.Command { common.SetupInsecureHelmDependencies(&_commonCmdData, cmd) cmd.AddCommand( - helm_v3.NewUninstallCmd(actionConfig, os.Stdout, helm_v3.UninstallCmdOptions{}), + helm_v3.NewUninstallCmd(actionConfig, os.Stdout, helm_v3.UninstallCmdOptions{ + StagesSplitter: helm.StagesSplitter{}, + }), helm_v3.NewDependencyCmd(actionConfig, os.Stdout), helm_v3.NewGetCmd(actionConfig, os.Stdout), helm_v3.NewHistoryCmd(actionConfig, os.Stdout), @@ -73,7 +75,9 @@ func NewCmd() *cobra.Command { helm_v3.NewListCmd(actionConfig, os.Stdout), NewTemplateCmd(actionConfig, wc), helm_v3.NewRepoCmd(os.Stdout), - helm_v3.NewRollbackCmd(actionConfig, os.Stdout), + helm_v3.NewRollbackCmd(actionConfig, os.Stdout, helm_v3.RollbackCmdOptions{ + StagesSplitter: helm.StagesSplitter{}, + }), NewInstallCmd(actionConfig, wc), NewUpgradeCmd(actionConfig, wc), helm_v3.NewCreateCmd(os.Stdout), diff --git a/cmd/werf/helm/install.go b/cmd/werf/helm/install.go index 8e55372d45..e955ca2628 100644 --- a/cmd/werf/helm/install.go +++ b/cmd/werf/helm/install.go @@ -9,6 +9,7 @@ import ( "helm.sh/helm/v3/pkg/action" "github.com/werf/werf/cmd/werf/common" + "github.com/werf/werf/pkg/deploy/helm" "github.com/werf/werf/pkg/deploy/helm/chart_extender" "github.com/werf/werf/pkg/deploy/helm/command_helpers" "github.com/werf/werf/pkg/deploy/lock_manager" @@ -18,6 +19,7 @@ var installCmdData common.CmdData func NewInstallCmd(actionConfig *action.Configuration, wc *chart_extender.WerfChartStub) *cobra.Command { cmd, helmAction := helm_v3.NewInstallCmd(actionConfig, os.Stdout, helm_v3.InstallCmdOptions{ + StagesSplitter: helm.StagesSplitter{}, ChainPostRenderer: wc.ChainPostRenderer, }) SetupRenderRelatedWerfChartParams(cmd, &installCmdData) diff --git a/cmd/werf/helm/template.go b/cmd/werf/helm/template.go index 84b665fd3d..d92f32f2d0 100644 --- a/cmd/werf/helm/template.go +++ b/cmd/werf/helm/template.go @@ -9,6 +9,7 @@ import ( "helm.sh/helm/v3/pkg/action" "github.com/werf/werf/cmd/werf/common" + "github.com/werf/werf/pkg/deploy/helm" "github.com/werf/werf/pkg/deploy/helm/chart_extender" ) @@ -16,6 +17,7 @@ var templateCmdData common.CmdData func NewTemplateCmd(actionConfig *action.Configuration, wc *chart_extender.WerfChartStub) *cobra.Command { cmd, _ := helm_v3.NewTemplateCmd(actionConfig, os.Stdout, helm_v3.TemplateCmdOptions{ + StagesSplitter: helm.StagesSplitter{}, ChainPostRenderer: wc.ChainPostRenderer, }) SetupRenderRelatedWerfChartParams(cmd, &templateCmdData) diff --git a/cmd/werf/helm/upgrade.go b/cmd/werf/helm/upgrade.go index d73cf14d0b..fc6b290115 100644 --- a/cmd/werf/helm/upgrade.go +++ b/cmd/werf/helm/upgrade.go @@ -9,6 +9,7 @@ import ( "helm.sh/helm/v3/pkg/action" "github.com/werf/werf/cmd/werf/common" + "github.com/werf/werf/pkg/deploy/helm" "github.com/werf/werf/pkg/deploy/helm/chart_extender" "github.com/werf/werf/pkg/deploy/helm/command_helpers" "github.com/werf/werf/pkg/deploy/lock_manager" @@ -18,6 +19,7 @@ var upgradeCmdData common.CmdData func NewUpgradeCmd(actionConfig *action.Configuration, wc *chart_extender.WerfChartStub) *cobra.Command { cmd, _ := helm_v3.NewUpgradeCmd(actionConfig, os.Stdout, helm_v3.UpgradeCmdOptions{ + StagesSplitter: helm.StagesSplitter{}, ChainPostRenderer: wc.ChainPostRenderer, }) SetupRenderRelatedWerfChartParams(cmd, &upgradeCmdData) diff --git a/cmd/werf/render/render.go b/cmd/werf/render/render.go index 2607fa5e0d..ac5acbe345 100644 --- a/cmd/werf/render/render.go +++ b/cmd/werf/render/render.go @@ -18,6 +18,7 @@ import ( "github.com/werf/werf/cmd/werf/common" "github.com/werf/werf/pkg/build" "github.com/werf/werf/pkg/config/deploy_params" + "github.com/werf/werf/pkg/deploy/helm" "github.com/werf/werf/pkg/deploy/helm/chart_extender" "github.com/werf/werf/pkg/deploy/helm/chart_extender/helpers" "github.com/werf/werf/pkg/deploy/secrets_manager" @@ -412,6 +413,7 @@ func runRender(ctx context.Context) error { } templateOpts := helm_v3.TemplateCmdOptions{ + StagesSplitter: helm.StagesSplitter{}, ChainPostRenderer: wc.ChainPostRenderer, ValueOpts: &values.Options{ ValueFiles: common.GetValues(&commonCmdData), diff --git a/pkg/buildah/native_linux.go b/pkg/buildah/native_linux.go index 54acd36a7f..1c67e5dffb 100644 --- a/pkg/buildah/native_linux.go +++ b/pkg/buildah/native_linux.go @@ -355,7 +355,7 @@ func (b *NativeBuildah) Rm(ctx context.Context, ref string, opts RmOpts) error { func (b *NativeBuildah) Rmi(ctx context.Context, ref string, opts RmiOpts) error { _, rmiErrors := b.Runtime.RemoveImages(ctx, []string{ref}, &libimage.RemoveImagesOptions{ Force: opts.Force, - //Filters: []string{"readonly=false", "intermediate=false", "dangling=true"}, + // Filters: []string{"readonly=false", "intermediate=false", "dangling=true"}, }) var multiErr *multierror.Error diff --git a/pkg/container_backend/stage_builder/dockerfile_stage_builder.go b/pkg/container_backend/stage_builder/dockerfile_stage_builder.go index 67ca1116fc..3655f4ee9e 100644 --- a/pkg/container_backend/stage_builder/dockerfile_stage_builder.go +++ b/pkg/container_backend/stage_builder/dockerfile_stage_builder.go @@ -6,7 +6,6 @@ import ( "os" "github.com/werf/logboek" - "github.com/werf/werf/pkg/container_backend" ) diff --git a/pkg/deploy/helm/annotations.go b/pkg/deploy/helm/annotations.go index 8740dec4f6..6becab0636 100644 --- a/pkg/deploy/helm/annotations.go +++ b/pkg/deploy/helm/annotations.go @@ -19,4 +19,6 @@ const ( ShowEventsAnnoName = "werf.io/show-service-messages" ReplicasOnCreationAnnoName = "werf.io/replicas-on-creation" + + StageWeightAnnoName = "werf.io/weight" ) diff --git a/pkg/deploy/helm/chart_extender/bundle_test.go b/pkg/deploy/helm/chart_extender/bundle_test.go index 973f281c4e..735b70ba1e 100644 --- a/pkg/deploy/helm/chart_extender/bundle_test.go +++ b/pkg/deploy/helm/chart_extender/bundle_test.go @@ -7,11 +7,10 @@ import ( . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" - "github.com/werf/werf/pkg/deploy/secrets_manager" - helm_v3 "helm.sh/helm/v3/cmd/helm" - "helm.sh/helm/v3/pkg/chart" + + "github.com/werf/werf/pkg/deploy/secrets_manager" ) var _ = Describe("Bundle", func() { diff --git a/pkg/deploy/helm/stages_splitter.go b/pkg/deploy/helm/stages_splitter.go new file mode 100644 index 0000000000..71a3c4d2c3 --- /dev/null +++ b/pkg/deploy/helm/stages_splitter.go @@ -0,0 +1,57 @@ +package helm + +import ( + "fmt" + "sort" + "strconv" + + "helm.sh/helm/v3/pkg/kube" + "helm.sh/helm/v3/pkg/phasemanagers/stages" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/cli-runtime/pkg/resource" +) + +type StagesSplitter struct{} + +func (s StagesSplitter) Split(resources kube.ResourceList) (stages.SortedStageList, error) { + var stageList stages.SortedStageList + if err := resources.Visit(func(res *resource.Info, err error) error { + if err != nil { + return err + } + + unstructuredObj := unstructured.Unstructured{} + unstructuredObj.Object, err = runtime.DefaultUnstructuredConverter.ToUnstructured(res.Object) + if err != nil { + return fmt.Errorf("error converting object to unstructured type: %w", err) + } + + var weight int + if w, ok := unstructuredObj.GetAnnotations()[StageWeightAnnoName]; ok { + weight, err = strconv.Atoi(w) + if err != nil { + return fmt.Errorf("error parsing annotation \"%s: %s\" — value should be an integer: %w", StageWeightAnnoName, w, err) + } + } + + stage := stageList.StageByWeight(weight) + + if stage == nil { + stage = &stages.Stage{ + Weight: weight, + } + stageList = append(stageList, stage) + } + + stage.DesiredResources.Append(res) + + return nil + }); err != nil { + return nil, fmt.Errorf("error visiting resources list: %w", err) + } + + sort.Sort(stageList) + + return stageList, nil +}