From 9940951f70b3135d81580b0fe83d513492069fc9 Mon Sep 17 00:00:00 2001 From: Alexander Forbes-Reed Date: Tue, 14 Sep 2021 10:18:33 +0100 Subject: [PATCH] Remove all web references from cdep --- cmd/cdep/README.md | 17 --- cmd/cdep/main.go | 1 - tools/cdep/app/update_web.go | 237 ------------------------------ tools/cdep/cdep.go | 3 - tools/cdep/commands/update_web.go | 118 --------------- tools/cdep/parsers/parse_web.go | 49 ------ tools/cdep/web_types.go | 41 ------ 7 files changed, 466 deletions(-) delete mode 100644 tools/cdep/app/update_web.go delete mode 100644 tools/cdep/commands/update_web.go delete mode 100644 tools/cdep/parsers/parse_web.go delete mode 100644 tools/cdep/web_types.go diff --git a/cmd/cdep/README.md b/cmd/cdep/README.md index 8fbcee1..0c294c9 100644 --- a/cmd/cdep/README.md +++ b/cmd/cdep/README.md @@ -28,23 +28,6 @@ Or with some flags - `--prod`: work on prod, where `nonprod` is the default - `--branch {name}` (`-b`): define a branch to use, where `master` is the default -### update-web - -A CLI tool to deploy web applications on a specific system/environment. - -`cdep update-web {type} {env|all} {...apps} ` - -For example: - -- `cdep uw cf all website` -- `cdep uw cf all website -b new-ppc-landing` -- `cdep uw cf prod website --prod` - -Flags are: - -- `--prod`: work on the prod system, where `nonprod` is the default -- `--branch {name}` (`-b`): define a branch to use, where `master` is the default - ### update-default Specifically for fast forwarding the default commit on an environment, or all of them. diff --git a/cmd/cdep/main.go b/cmd/cdep/main.go index 741085d..c203506 100644 --- a/cmd/cdep/main.go +++ b/cmd/cdep/main.go @@ -12,7 +12,6 @@ import ( func main() { rootCmd.AddCommand(cmd.VersionCmd) rootCmd.AddCommand(cmd.UpdateCmd) - rootCmd.AddCommand(cmd.UpdateWebCmd) rootCmd.AddCommand(cmd.UpdateDefaultCmd) if err := rootCmd.Execute(); err != nil { diff --git a/tools/cdep/app/update_web.go b/tools/cdep/app/update_web.go deleted file mode 100644 index f38907e..0000000 --- a/tools/cdep/app/update_web.go +++ /dev/null @@ -1,237 +0,0 @@ -package app - -import ( - "context" - "fmt" - "io/ioutil" - "os" - "strings" - "time" - - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/awserr" - "github.com/aws/aws-sdk-go/aws/session" - "github.com/aws/aws-sdk-go/service/cloudfront" - "github.com/aws/aws-sdk-go/service/s3" - "github.com/cuvva/cuvva-public-go/lib/cher" - "github.com/cuvva/cuvva-public-go/lib/ptr" - "github.com/cuvva/cuvva-public-go/tools/cdep" - "github.com/cuvva/cuvva-public-go/tools/cdep/git" - "github.com/cuvva/cuvva-public-go/tools/cdep/parsers" - "github.com/hashicorp/go-tfe" - log "github.com/sirupsen/logrus" -) - -const ( - TERRAFORM_TOKEN_ENV = "CUVVA_TERRAFORM_TOKEN" -) - -var ( - distributions = map[string]map[string]string{ - "prod": { - "website": "E2YSXQ43EF8JNW", - }, - "nonprod": { - "website": "E1XTHIBWUL0BQ", - }, - } - - workspaces = map[string]string{ - "prod": "ws-aknKczrco9TGXn6o", - } -) - -func (a App) UpdateWeb(ctx context.Context, req *parsers.Params, overruleChecks []string) error { - if req.Environment == "prod" && req.Branch != cdep.DefaultBranch { - return cher.New("invalid_operation", nil) - } - - if len(req.Items) != 1 { - return cher.New("too_many_apps", nil) - } - - log.Info("creating aws sessions") - - profileName := "nonprod" - - if req.System == "prod" { - profileName = "root" - } - - awsSession, err := session.NewSessionWithOptions(session.Options{ - Profile: profileName, - }) - if err != nil { - return err - } - - var tf *tfe.Client - webDeploymentBucket := fmt.Sprintf("cuvva-web-deployments-%s", req.System) - app := req.Items[0] - cfClient := cloudfront.New(awsSession) - s3Client := s3.New(awsSession) - - distributionID, err := getDistributionID(app, req.System) - if err != nil { - return err - } - - log.Info("getting latest commit hash") - - latestHash, err := git.GetLatestCommitHash(ctx, req.Branch) - if err != nil { - return err - } - - // Due to the "cuvva-cloudfront-sites" bucket existing in root, we'll only do this - // check on production deploys for now - if req.System == "prod" { - log.Info("ensuring latest commit hash has been deployed") - - cfSitesClient := s3.New(awsSession) - ensuredFileKey := fmt.Sprintf("%s/%s/index", app, latestHash) - _, err = cfSitesClient.HeadObjectWithContext(ctx, &s3.HeadObjectInput{ - Bucket: aws.String("cuvva-cloudfront-sites"), - Key: &ensuredFileKey, - }) - if err != nil { - // Can't use s3.ErrCodeNoSuchKey it is not returned by the API, relies on - // https://github.com/aws/aws-sdk-go/issues/1208 - if aerr, ok := err.(awserr.Error); ok && aerr.Code() == "NotFound" { - return cher.New("web_deployment_not_found", nil) - } - - return err - } - } - - log.Info("fetching s3 deployment file") - - deployFileResp, err := s3Client.GetObjectWithContext(ctx, &s3.GetObjectInput{ - Bucket: &webDeploymentBucket, - Key: aws.String(app), - }) - if err != nil { - return err - } - - deployFileBytes, err := ioutil.ReadAll(deployFileResp.Body) - if err != nil { - return err - } - - currentIdentifier := strings.TrimSpace(string(deployFileBytes)) - - log.Info("getting cloudfront distribution config") - - distOutput, err := cfClient.GetDistributionConfigWithContext(ctx, &cloudfront.GetDistributionConfigInput{ - Id: &distributionID, - }) - if err != nil { - return err - } - if len(distOutput.DistributionConfig.Origins.Items) != 1 { - return cher.New("incorrect_origin_count", nil) - } - - existingOriginPath := distOutput.DistributionConfig.Origins.Items[0].OriginPath - if strings.HasSuffix(*existingOriginPath, latestHash) && latestHash == currentIdentifier { - return cher.New("nothing_changed", nil) - } - - if a.DryRun { - log.Info("Dry run only, stopping now") - log.Infof("current identifier: (%s), proposed identifier: (%s)\n", currentIdentifier, latestHash) - return nil - } - - if req.System == "prod" { - log.Info("locking terraform workspace") - - token := os.Getenv(TERRAFORM_TOKEN_ENV) - if token == "" { - return cher.New("terraform_token_not_found", nil) - } - - tf, err = tfe.NewClient(&tfe.Config{ - Token: token, - }) - if err != nil { - return err - } - - _, err = tf.Workspaces.Lock(ctx, workspaces[req.System], tfe.WorkspaceLockOptions{ - Reason: ptr.String("cdep web deployment"), - }) - if err != nil { - return err - } - } - - log.Info("updating s3 deployment file") - - _, err = s3Client.PutObjectWithContext(ctx, &s3.PutObjectInput{ - Bucket: &webDeploymentBucket, - Key: aws.String(app), - ContentType: aws.String("text/plain"), - Body: strings.NewReader(latestHash), - }) - if err != nil { - return err - } - - log.Info("updating cloudfront distribution config") - - originPath := fmt.Sprintf("/%s/%s", app, latestHash) - distOutput.DistributionConfig.Origins.Items[0].OriginPath = &originPath - - _, err = cfClient.UpdateDistributionWithContext(ctx, &cloudfront.UpdateDistributionInput{ - Id: &distributionID, - IfMatch: distOutput.ETag, - DistributionConfig: distOutput.DistributionConfig, - }) - if err != nil { - return err - } - - if req.System == "prod" { - log.Info("unlocking terraform workspace") - - if _, err := tf.Workspaces.Unlock(ctx, workspaces[req.System]); err != nil { - return err - } - } - - log.Info("creating cloudfront invalidation") - - callerRef := fmt.Sprintf("cdep:update-web:%d", time.Now().Unix()) - _, err = cfClient.CreateInvalidationWithContext(ctx, &cloudfront.CreateInvalidationInput{ - DistributionId: &distributionID, - InvalidationBatch: &cloudfront.InvalidationBatch{ - CallerReference: &callerRef, - Paths: &cloudfront.Paths{ - Quantity: aws.Int64(1), - Items: []*string{aws.String("/*")}, - }, - }, - }) - if err != nil { - return err - } - - return nil -} - -func getDistributionID(app, system string) (string, error) { - apps, ok := distributions[system] - if !ok { - return "", cher.New("unknown_distribution_system", nil) - } - - distID, ok := apps[app] - if !ok { - return "", cher.New("unknown_distribution_app", nil) - } - - return distID, nil -} diff --git a/tools/cdep/cdep.go b/tools/cdep/cdep.go index 684a516..0d0241a 100644 --- a/tools/cdep/cdep.go +++ b/tools/cdep/cdep.go @@ -14,9 +14,6 @@ var ErrorCodeMapping = map[string]string{ "unknown_system": "You've provided a system that does not exist.", "unknown_type": "You're trying to update something this tool cannot handle.", "working_copy_dirty": "Your config repo working copy is dirty, please clean it up and try again.", - "too_many_apps": "You can only specify one application for web updates", - "web_deployment_not_found": "The commit hash discovered has not been pushed to s3 yet", - "terraform_token_not_found": "No Terraform token found. Please generate one on Terraform (https://app.terraform.io/app/settings/tokens) and put it into the environment variable \"CUVVA_TERRAFORM_TOKEN\".", } var OverruleChecks = map[string]string{ diff --git a/tools/cdep/commands/update_web.go b/tools/cdep/commands/update_web.go deleted file mode 100644 index efde304..0000000 --- a/tools/cdep/commands/update_web.go +++ /dev/null @@ -1,118 +0,0 @@ -package commands - -import ( - "context" - "fmt" - "strings" - - "github.com/cuvva/cuvva-public-go/lib/cher" - "github.com/cuvva/cuvva-public-go/tools/cdep" - "github.com/cuvva/cuvva-public-go/tools/cdep/app" - "github.com/cuvva/cuvva-public-go/tools/cdep/parsers" - "github.com/spf13/cobra" -) - -func init() { - UpdateWebCmd.Flags().StringP("branch", "b", cdep.DefaultBranch, "Branch to deploy") - UpdateWebCmd.Flags().BoolP("prod", "", false, "Work on prod") - UpdateWebCmd.Flags().BoolP("dry-run", "", false, "Dry run only?") - UpdateWebCmd.Flags().StringSliceP("overrule-checks", "", []string{}, "Overrule checks the tool does") - - UpdateWebCmd.Flags().MarkHidden("overrule-checks") - - var envs string - types := strings.Join(cdep.ListWebTypes(), ", ") - - for _, env := range cdep.ListEnvironments("*") { - envs = fmt.Sprintf("%s - %s\n", envs, env) - } - - UpdateWebCmd.SetHelpTemplate(fmt.Sprintf(helpTemplateUpdateWeb, types, envs)) -} - -// UpdateWebCmd is the initiator for the update command -var UpdateWebCmd = &cobra.Command{ - Use: "update-web [type] [env] [services ...]", - Short: "Update the deployment identifier for web applications ", - Long: "Please read the README.md file", - Example: strings.Join([]string{ - "update-web cloudfront all website", - "uw cf prod website --prod", - "uw cf prod website -b new-landing-page --prod", - }, "\n"), - Aliases: []string{"uw"}, - Args: updateWebArgs, - RunE: func(cmd *cobra.Command, args []string) error { - ctx := context.Background() - - branch, err := cmd.Flags().GetString("branch") - if err != nil { - return err - } - - useProd, err := cmd.Flags().GetBool("prod") - if err != nil { - return err - } - - dryRun, err := cmd.Flags().GetBool("dry-run") - if err != nil { - return nil - } - - params, err := parsers.ParseWeb(args, branch, useProd) - if err != nil { - return err - } - - a := &app.App{ - DryRun: dryRun, - } - - overruleChecks, err := cmd.Flags().GetStringSlice("overrule-checks") - if err != nil { - return err - } - - return a.UpdateWeb(ctx, params, overruleChecks) - }, -} - -func updateWebArgs(cmd *cobra.Command, args []string) error { - system := "nonprod" - if useProd, err := cmd.Flags().GetBool("prod"); err == nil && useProd { - system = "prod" - } - - switch len(args) { - case 1: - if _, err := cdep.ParseWebTypeArg(args[0]); err != nil { - return err - } - case 2: - if err := cdep.ValidateSystemEnvironment(system, args[1]); err != nil { - return err - } - } - - switch true { - case len(args) == 0: - return cher.New("missing_type", cher.M{"allowed": cdep.ListWebTypes()}) - case len(args) == 1: - return cher.New("missing_environment", cher.M{"allowed": cdep.ListEnvironments(system)}) - case len(args) == 2: - return cher.New("missing_app", nil) - case len(args) >= 3: - return nil - default: - return cher.New("unknown_arguments", nil) - } -} - -const helpTemplateUpdateWeb = `{{with (or .Long .Short)}}{{. | trimTrailingWhitespaces}} - -{{end}}{{if or .Runnable .HasSubCommands}}{{.UsageString}}{{end}} -Allowed types: %s - -Allowed environments: -%s` diff --git a/tools/cdep/parsers/parse_web.go b/tools/cdep/parsers/parse_web.go deleted file mode 100644 index 859326d..0000000 --- a/tools/cdep/parsers/parse_web.go +++ /dev/null @@ -1,49 +0,0 @@ -package parsers - -import ( - "errors" - - "github.com/cuvva/cuvva-public-go/tools/cdep" -) - -func ParseWeb(args []string, branch string, prodSys bool) (*Params, error) { - if len(args) < 2 { - return nil, errors.New("missing arguments") - } - - // default to nonprod - system := "nonprod" - - if prodSys { - system = "prod" - } - - t, err := cdep.ParseWebTypeArg(args[0]) - if err != nil { - return nil, err - } - - err = cdep.ValidateSystem(system) - if err != nil { - return nil, err - } - - err = cdep.ValidateSystemEnvironment(system, args[1]) - if err != nil { - return nil, err - } - - itemSet := []string{} - - if len(args) > 2 { - itemSet = append(itemSet, args[2:]...) - } - - return &Params{ - Type: t, - System: system, - Environment: args[1], - Branch: branch, - Items: itemSet, - }, nil -} diff --git a/tools/cdep/web_types.go b/tools/cdep/web_types.go deleted file mode 100644 index f4459be..0000000 --- a/tools/cdep/web_types.go +++ /dev/null @@ -1,41 +0,0 @@ -package cdep - -import ( - "sort" - - "github.com/cuvva/cuvva-public-go/lib/cher" -) - -var WebTypes = map[string]struct{}{ - "cloudfront": {}, - "cf": {}, -} - -func ParseWebTypeArg(in string) (string, error) { - if _, ok := WebTypes[in]; !ok { - return "", cher.New("unknown_type", cher.M{ - "type": in, - "allowed": ListWebTypes(), - }) - } - - switch in { - case "cloudfront", "cf": - return "cloudfront", nil - default: - return "", cher.New("impossible", nil) - } -} - -// ListWebTypes returns a set of allowed web types -func ListWebTypes() []string { - allowed := []string{} - - for t := range WebTypes { - allowed = append(allowed, t) - } - - sort.Strings(allowed) - - return allowed -}