From 3f11c309c98cb4b6ca649cba373904f413bd7388 Mon Sep 17 00:00:00 2001 From: khanhtc1202 Date: Fri, 8 Jan 2021 14:29:34 +0900 Subject: [PATCH 1/3] QuickSync strategy planner --- pkg/app/piped/planner/lambda/BUILD.bazel | 5 +- pkg/app/piped/planner/lambda/lambda.go | 65 +++++++++++++++++++++ pkg/app/piped/planner/lambda/pipeline.go | 73 ++++++++++++++++++++++++ 3 files changed, 142 insertions(+), 1 deletion(-) create mode 100644 pkg/app/piped/planner/lambda/pipeline.go diff --git a/pkg/app/piped/planner/lambda/BUILD.bazel b/pkg/app/piped/planner/lambda/BUILD.bazel index ac252b3480..5a127a3917 100644 --- a/pkg/app/piped/planner/lambda/BUILD.bazel +++ b/pkg/app/piped/planner/lambda/BUILD.bazel @@ -2,7 +2,10 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library") go_library( name = "go_default_library", - srcs = ["lambda.go"], + srcs = [ + "lambda.go", + "pipeline.go", + ], importpath = "github.com/pipe-cd/pipe/pkg/app/piped/planner/lambda", visibility = ["//visibility:public"], deps = [ diff --git a/pkg/app/piped/planner/lambda/lambda.go b/pkg/app/piped/planner/lambda/lambda.go index d533e78c1d..df26b0d1b9 100644 --- a/pkg/app/piped/planner/lambda/lambda.go +++ b/pkg/app/piped/planner/lambda/lambda.go @@ -16,11 +16,18 @@ package lambda import ( "context" + "fmt" + "io/ioutil" + "time" + "go.uber.org/zap" + + provider "github.com/pipe-cd/pipe/pkg/app/piped/cloudprovider/lambda" "github.com/pipe-cd/pipe/pkg/app/piped/planner" "github.com/pipe-cd/pipe/pkg/model" ) +// Planner plans the deployment pipeline for Lambda application. type Planner struct { } @@ -33,6 +40,64 @@ func Register(r registerer) { r.Register(model.ApplicationKind_LAMBDA, &Planner{}) } +// Plan decides which pipeline should be used for the given input. func (p *Planner) Plan(ctx context.Context, in planner.Input) (out planner.Output, err error) { + ds, err := in.TargetDSP.Get(ctx, ioutil.Discard) + if err != nil { + err = fmt.Errorf("error while preparing deploy source data (%v)", err) + return + } + + cfg := ds.DeploymentConfig.LambdaDeploymentSpec + if cfg == nil { + err = fmt.Errorf("missing LambdaDeploymentSpec in deployment configuration") + return + } + + // Determine application version from the manifest + if version, err := determineVersion(ds.AppDir, cfg.Input.FunctionManifestFile); err == nil { + out.Version = version + } else { + out.Version = "unknown" + in.Logger.Warn("unable to determine target version", zap.Error(err)) + } + + // If the deployment was triggered by forcing via web UI, + // we rely on the user's decision. + switch in.Deployment.Trigger.SyncStrategy { + case model.SyncStrategy_QUICK_SYNC: + out.Stages = buildQuickSyncPipeline(cfg.Input.AutoRollback, time.Now()) + out.Summary = fmt.Sprintf("Quick sync to deploy image %s and configure all traffic to it (forced via web)", out.Version) + return + case model.SyncStrategy_PIPELINE: + err = fmt.Errorf("Pipeline sync for lambda application is not yet implemented") + return + } + + // If this is the first time to deploy this application or it was unable to retrieve last successful commit, + // we perform the quick sync strategy. + if in.MostRecentSuccessfulCommitHash == "" { + out.Stages = buildQuickSyncPipeline(cfg.Input.AutoRollback, time.Now()) + out.Summary = fmt.Sprintf("Quick sync to deploy image %s and configure all traffic to it (it seems this is the first deployment)", out.Version) + return + } + + // When no pipeline was configured, perform the quick sync. + if cfg.Pipeline == nil || len(cfg.Pipeline.Stages) == 0 { + out.Stages = buildQuickSyncPipeline(cfg.Input.AutoRollback, time.Now()) + out.Summary = fmt.Sprintf("Quick sync to deploy image %s and configure all traffic to it (pipeline was not configured)", out.Version) + return + } + + err = fmt.Errorf("Currently only QUICK_SYNC strategy deployement is supported") return } + +func determineVersion(appDir, functionManifestFile string) (string, error) { + fm, err := provider.LoadFunctionManifest(appDir, functionManifestFile) + if err != nil { + return "", err + } + + return provider.FindImageTag(fm) +} diff --git a/pkg/app/piped/planner/lambda/pipeline.go b/pkg/app/piped/planner/lambda/pipeline.go new file mode 100644 index 0000000000..88057a0f61 --- /dev/null +++ b/pkg/app/piped/planner/lambda/pipeline.go @@ -0,0 +1,73 @@ +// Copyright 2021 The PipeCD Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package lambda + +import ( + "fmt" + "time" + + "github.com/pipe-cd/pipe/pkg/app/piped/planner" + "github.com/pipe-cd/pipe/pkg/config" + "github.com/pipe-cd/pipe/pkg/model" +) + +func buildQuickSyncPipeline(autoRollback bool, now time.Time) []*model.PipelineStage { + var ( + preStageID = "" + stage, _ = planner.GetPredefinedStage(planner.PredefinedStageLambdaSync) + stages = []config.PipelineStage{stage} + out = make([]*model.PipelineStage, 0, len(stages)) + ) + + for i, s := range stages { + id := s.Id + if id == "" { + id = fmt.Sprintf("stage-%d", i) + } + stage := &model.PipelineStage{ + Id: id, + Name: s.Name.String(), + Desc: s.Desc, + Index: int32(i), + Predefined: true, + Visible: true, + Status: model.StageStatus_STAGE_NOT_STARTED_YET, + Metadata: planner.MakeInitialStageMetadata(s), + CreatedAt: now.Unix(), + UpdatedAt: now.Unix(), + } + if preStageID != "" { + stage.Requires = []string{preStageID} + } + preStageID = id + out = append(out, stage) + } + + if autoRollback { + s, _ := planner.GetPredefinedStage(planner.PredefinedStageRollback) + out = append(out, &model.PipelineStage{ + Id: s.Id, + Name: s.Name.String(), + Desc: s.Desc, + Predefined: true, + Visible: false, + Status: model.StageStatus_STAGE_NOT_STARTED_YET, + CreatedAt: now.Unix(), + UpdatedAt: now.Unix(), + }) + } + + return out +} From 4ac21823416ebb76d1e3e0f17f1c2bfb2657e227 Mon Sep 17 00:00:00 2001 From: khanhtc1202 Date: Fri, 8 Jan 2021 14:32:21 +0900 Subject: [PATCH 2/3] Run make gazelle --- pkg/app/piped/executor/lambda/BUILD.bazel | 2 +- pkg/app/piped/planner/lambda/BUILD.bazel | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/pkg/app/piped/executor/lambda/BUILD.bazel b/pkg/app/piped/executor/lambda/BUILD.bazel index 671ffd7ea5..cc243422b3 100644 --- a/pkg/app/piped/executor/lambda/BUILD.bazel +++ b/pkg/app/piped/executor/lambda/BUILD.bazel @@ -3,8 +3,8 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library") go_library( name = "go_default_library", srcs = [ - "lambda.go", "deploy.go", + "lambda.go", ], importpath = "github.com/pipe-cd/pipe/pkg/app/piped/executor/lambda", visibility = ["//visibility:public"], diff --git a/pkg/app/piped/planner/lambda/BUILD.bazel b/pkg/app/piped/planner/lambda/BUILD.bazel index 5a127a3917..c79ad7369e 100644 --- a/pkg/app/piped/planner/lambda/BUILD.bazel +++ b/pkg/app/piped/planner/lambda/BUILD.bazel @@ -9,7 +9,10 @@ go_library( importpath = "github.com/pipe-cd/pipe/pkg/app/piped/planner/lambda", visibility = ["//visibility:public"], deps = [ + "//pkg/app/piped/cloudprovider/lambda:go_default_library", "//pkg/app/piped/planner:go_default_library", + "//pkg/config:go_default_library", "//pkg/model:go_default_library", + "@org_uber_go_zap//:go_default_library", ], ) From 415fbd7a3cedc98e2f8d2fe7dee7c031a09a3f28 Mon Sep 17 00:00:00 2001 From: khanhtc1202 Date: Fri, 8 Jan 2021 14:34:37 +0900 Subject: [PATCH 3/3] Go lint --- pkg/app/piped/planner/lambda/lambda.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/app/piped/planner/lambda/lambda.go b/pkg/app/piped/planner/lambda/lambda.go index df26b0d1b9..3677d10aeb 100644 --- a/pkg/app/piped/planner/lambda/lambda.go +++ b/pkg/app/piped/planner/lambda/lambda.go @@ -70,7 +70,7 @@ func (p *Planner) Plan(ctx context.Context, in planner.Input) (out planner.Outpu out.Summary = fmt.Sprintf("Quick sync to deploy image %s and configure all traffic to it (forced via web)", out.Version) return case model.SyncStrategy_PIPELINE: - err = fmt.Errorf("Pipeline sync for lambda application is not yet implemented") + err = fmt.Errorf("pipeline sync for lambda application is not yet implemented") return } @@ -89,7 +89,7 @@ func (p *Planner) Plan(ctx context.Context, in planner.Input) (out planner.Outpu return } - err = fmt.Errorf("Currently only QUICK_SYNC strategy deployement is supported") + err = fmt.Errorf("currently only QUICK_SYNC strategy deployement is supported") return }