diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index c042706f..1bddb31a 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -12,4 +12,4 @@ jobs: go-version: '1.23' cache-dependency-path: ./go.mod - name: Run Tests - run: go test -v ./... + run: make test diff --git a/cmd/identify_dbaas.go b/cmd/identify_dbaas.go index 772747ac..83620c32 100644 --- a/cmd/identify_dbaas.go +++ b/cmd/identify_dbaas.go @@ -4,7 +4,7 @@ import ( "fmt" "github.com/spf13/cobra" - generator "github.com/uselagoon/build-deploy-tool/internal/generator" + "github.com/uselagoon/build-deploy-tool/internal/identify" ) // this is an intermediate helper command while transitioning from bash to go @@ -14,11 +14,11 @@ var dbaasIdentify = &cobra.Command{ Aliases: []string{"db", "d"}, Short: "Identify if any dbaas consumers are created", RunE: func(cmd *cobra.Command, args []string) error { - generator, err := generator.GenerateInput(*rootCmd, false) + generator, err := GenerateInput(*rootCmd, false) if err != nil { return err } - dbaasConsumers, err := IdentifyDBaaSConsumers(generator) + dbaasConsumers, err := identify.IdentifyDBaaSConsumers(generator) if err != nil { return err } @@ -28,19 +28,3 @@ var dbaasIdentify = &cobra.Command{ return nil }, } - -func IdentifyDBaaSConsumers(g generator.GeneratorInput) ([]string, error) { - lagoonBuild, err := generator.NewGenerator( - g, - ) - if err != nil { - return nil, err - } - ret := []string{} - for _, svc := range lagoonBuild.BuildValues.Services { - if svc.IsDBaaS || svc.IsSingle { - ret = append(ret, fmt.Sprintf("%s:%s", svc.Name, svc.Type)) - } - } - return ret, nil -} diff --git a/cmd/identify_feature.go b/cmd/identify_feature.go index c04ff2fa..fb9f2dbf 100644 --- a/cmd/identify_feature.go +++ b/cmd/identify_feature.go @@ -14,7 +14,7 @@ var featureFlagIdentify = &cobra.Command{ Aliases: []string{"f"}, Short: "Identify if a feature flag has been enabled", RunE: func(cmd *cobra.Command, args []string) error { - generator, err := generator.GenerateInput(*rootCmd, false) + generator, err := GenerateInput(*rootCmd, false) if err != nil { return err } diff --git a/cmd/identify_feature_test.go b/cmd/identify_feature_test.go index 7868ffe0..ba09efe0 100644 --- a/cmd/identify_feature_test.go +++ b/cmd/identify_feature_test.go @@ -4,6 +4,7 @@ import ( "os" "testing" + "github.com/uselagoon/build-deploy-tool/internal/generator" "github.com/uselagoon/build-deploy-tool/internal/helpers" "github.com/uselagoon/build-deploy-tool/internal/lagoon" "github.com/uselagoon/build-deploy-tool/internal/testdata" @@ -14,13 +15,12 @@ import ( func TestIdentifyFeatureFlag(t *testing.T) { tests := []struct { - name string - args testdata.TestData - templatePath string - varName string - vars []helpers.EnvironmentVariable - want string - wantErr bool + name string + args testdata.TestData + varName string + vars []helpers.EnvironmentVariable + want string + wantErr bool }{ { name: "test1 check if flag is defined in lagoon project variables", @@ -39,8 +39,7 @@ func TestIdentifyFeatureFlag(t *testing.T) { }, }, }, true), - templatePath: "testoutput", - want: "enabled", + want: "enabled", }, { name: "test2 check if flag is defined in lagoon environment variables", @@ -59,8 +58,7 @@ func TestIdentifyFeatureFlag(t *testing.T) { }, }, }, true), - templatePath: "testoutput", - want: "enabled", + want: "enabled", }, { name: "test3 check if force flag is defined in build variables", @@ -72,7 +70,6 @@ func TestIdentifyFeatureFlag(t *testing.T) { Branch: "main", LagoonYAML: "internal/testdata/node/lagoon.yml", }, true), - templatePath: "testoutput", vars: []helpers.EnvironmentVariable{ { Name: "LAGOON_FEATURE_FLAG_FORCE_ROOTLESS_WORKLOAD", @@ -91,7 +88,6 @@ func TestIdentifyFeatureFlag(t *testing.T) { Branch: "main", LagoonYAML: "internal/testdata/node/lagoon.yml", }, true), - templatePath: "testoutput", vars: []helpers.EnvironmentVariable{ { Name: "LAGOON_FEATURE_FLAG_FORCE_ROOTLESS_WORKLOAD", @@ -163,8 +159,11 @@ func TestIdentifyFeatureFlag(t *testing.T) { t.Run(tt.name, func(t *testing.T) { helpers.UnsetEnvVars(tt.vars) //unset variables before running tests // set the environment variables from args - savedTemplates := tt.templatePath - generator, err := testdata.SetupEnvironment(*rootCmd, savedTemplates, tt.args) + savedTemplates, err := os.MkdirTemp("", "testoutput") + if err != nil { + t.Errorf("%v", err) + } + generator, err := testdata.SetupEnvironment(generator.GeneratorInput{}, savedTemplates, tt.args) if err != nil { t.Errorf("%v", err) } diff --git a/cmd/identify_imagebuild.go b/cmd/identify_imagebuild.go index 3aa6f427..8494febf 100644 --- a/cmd/identify_imagebuild.go +++ b/cmd/identify_imagebuild.go @@ -13,7 +13,7 @@ var imageBuildIdentify = &cobra.Command{ Aliases: []string{"image-build", "img-build", "ib"}, Short: "Identify the configuration for building images for a Lagoon build", RunE: func(cmd *cobra.Command, args []string) error { - gen, err := generator.GenerateInput(*rootCmd, false) + gen, err := GenerateInput(*rootCmd, false) if err != nil { return err } diff --git a/cmd/identify_imagebuild_test.go b/cmd/identify_imagebuild_test.go index 4c713f5e..d3113dbe 100644 --- a/cmd/identify_imagebuild_test.go +++ b/cmd/identify_imagebuild_test.go @@ -819,15 +819,13 @@ func TestImageBuildConfigurationIdentification(t *testing.T) { } } // set the environment variables from args - savedTemplates := "testoutput" - generator, err := testdata.SetupEnvironment(*rootCmd, savedTemplates, tt.args) + savedTemplates, err := os.MkdirTemp("", "testoutput") if err != nil { t.Errorf("%v", err) } - - err = os.MkdirAll(savedTemplates, 0755) + generator, err := testdata.SetupEnvironment(generator.GeneratorInput{}, savedTemplates, tt.args) if err != nil { - t.Errorf("couldn't create directory %v: %v", savedTemplates, err) + t.Errorf("%v", err) } defer os.RemoveAll(savedTemplates) diff --git a/cmd/identify_ingress.go b/cmd/identify_ingress.go index e21dc3f0..8e728ec6 100644 --- a/cmd/identify_ingress.go +++ b/cmd/identify_ingress.go @@ -19,7 +19,7 @@ var primaryIngressIdentify = &cobra.Command{ Aliases: []string{"pi"}, Short: "Identify the primary ingress for a specific environment", RunE: func(cmd *cobra.Command, args []string) error { - generator, err := generator.GenerateInput(*rootCmd, false) + generator, err := GenerateInput(*rootCmd, false) if err != nil { return err } @@ -37,7 +37,7 @@ var ingressIdentify = &cobra.Command{ Aliases: []string{"i"}, Short: "Identify all ingress for a specific environment", RunE: func(cmd *cobra.Command, args []string) error { - generator, err := generator.GenerateInput(*rootCmd, false) + generator, err := GenerateInput(*rootCmd, false) if err != nil { return err } @@ -73,7 +73,7 @@ var autogenIngressIdentify = &cobra.Command{ Aliases: []string{"ci"}, Short: "Identify all created ingress object names for a specific environment", RunE: func(cmd *cobra.Command, args []string) error { - generator, err := generator.GenerateInput(*rootCmd, false) + generator, err := GenerateInput(*rootCmd, false) if err != nil { return err } diff --git a/cmd/identify_ingress_test.go b/cmd/identify_ingress_test.go index 5346abd9..4ebaa2d4 100644 --- a/cmd/identify_ingress_test.go +++ b/cmd/identify_ingress_test.go @@ -2,9 +2,11 @@ package cmd import ( "encoding/json" + "os" "reflect" "testing" + "github.com/uselagoon/build-deploy-tool/internal/generator" "github.com/uselagoon/build-deploy-tool/internal/helpers" "github.com/uselagoon/build-deploy-tool/internal/lagoon" "github.com/uselagoon/build-deploy-tool/internal/testdata" @@ -15,13 +17,12 @@ import ( func TestIdentifyRoute(t *testing.T) { tests := []struct { - name string - args testdata.TestData - templatePath string - want string - wantJSON string - wantRemain []string - wantautoGen []string + name string + args testdata.TestData + want string + wantJSON string + wantRemain []string + wantautoGen []string }{ { name: "test1 check LAGOON_FASTLY_SERVICE_IDS with secret no values", @@ -39,11 +40,10 @@ func TestIdentifyRoute(t *testing.T) { }, }, }, true), - templatePath: "testoutput", - want: "https://example.com", - wantRemain: []string{"https://node-example-project-main.example.com", "https://example.com"}, - wantautoGen: []string{"https://node-example-project-main.example.com"}, - wantJSON: `{"primary":"https://example.com","secondary":["https://node-example-project-main.example.com","https://example.com"],"autogenerated":["https://node-example-project-main.example.com"]}`, + want: "https://example.com", + wantRemain: []string{"https://node-example-project-main.example.com", "https://example.com"}, + wantautoGen: []string{"https://node-example-project-main.example.com"}, + wantJSON: `{"primary":"https://example.com","secondary":["https://node-example-project-main.example.com","https://example.com"],"autogenerated":["https://node-example-project-main.example.com"]}`, }, { name: "test2 check LAGOON_FASTLY_SERVICE_IDS no secret and no values", @@ -61,11 +61,10 @@ func TestIdentifyRoute(t *testing.T) { }, }, }, true), - templatePath: "testoutput", - want: "https://example.com", - wantRemain: []string{"https://node-example-project-main.example.com", "https://example.com"}, - wantautoGen: []string{"https://node-example-project-main.example.com"}, - wantJSON: `{"primary":"https://example.com","secondary":["https://node-example-project-main.example.com","https://example.com"],"autogenerated":["https://node-example-project-main.example.com"]}`, + want: "https://example.com", + wantRemain: []string{"https://node-example-project-main.example.com", "https://example.com"}, + wantautoGen: []string{"https://node-example-project-main.example.com"}, + wantJSON: `{"primary":"https://example.com","secondary":["https://node-example-project-main.example.com","https://example.com"],"autogenerated":["https://node-example-project-main.example.com"]}`, }, { name: "test3 check LAGOON_FASTLY_SERVICE_ID no secret and no values", @@ -83,11 +82,10 @@ func TestIdentifyRoute(t *testing.T) { }, }, }, true), - templatePath: "testoutput", - want: "https://example.com", - wantRemain: []string{"https://node-example-project-main.example.com", "https://example.com"}, - wantautoGen: []string{"https://node-example-project-main.example.com"}, - wantJSON: `{"primary":"https://example.com","secondary":["https://node-example-project-main.example.com","https://example.com"],"autogenerated":["https://node-example-project-main.example.com"]}`, + want: "https://example.com", + wantRemain: []string{"https://node-example-project-main.example.com", "https://example.com"}, + wantautoGen: []string{"https://node-example-project-main.example.com"}, + wantJSON: `{"primary":"https://example.com","secondary":["https://node-example-project-main.example.com","https://example.com"],"autogenerated":["https://node-example-project-main.example.com"]}`, }, { name: "test4 check no fastly and no values", @@ -98,11 +96,10 @@ func TestIdentifyRoute(t *testing.T) { Branch: "main", LagoonYAML: "internal/testdata/node/lagoon.yml", }, true), - templatePath: "testoutput", - want: "https://example.com", - wantRemain: []string{"https://node-example-project-main.example.com", "https://example.com"}, - wantautoGen: []string{"https://node-example-project-main.example.com"}, - wantJSON: `{"primary":"https://example.com","secondary":["https://node-example-project-main.example.com","https://example.com"],"autogenerated":["https://node-example-project-main.example.com"]}`, + want: "https://example.com", + wantRemain: []string{"https://node-example-project-main.example.com", "https://example.com"}, + wantautoGen: []string{"https://node-example-project-main.example.com"}, + wantJSON: `{"primary":"https://example.com","secondary":["https://node-example-project-main.example.com","https://example.com"],"autogenerated":["https://node-example-project-main.example.com"]}`, }, { name: "test5 multiproject1 no values", @@ -113,11 +110,10 @@ func TestIdentifyRoute(t *testing.T) { Branch: "multiproject", LagoonYAML: "internal/testdata/node/lagoon.polysite.yml", }, true), - templatePath: "testoutput", - want: "https://multiproject1.com", - wantRemain: []string{"https://node-multiproject1-multiproject.example.com", "https://multiproject1.com"}, - wantautoGen: []string{"https://node-multiproject1-multiproject.example.com"}, - wantJSON: `{"primary":"https://multiproject1.com","secondary":["https://node-multiproject1-multiproject.example.com","https://multiproject1.com"],"autogenerated":["https://node-multiproject1-multiproject.example.com"]}`, + want: "https://multiproject1.com", + wantRemain: []string{"https://node-multiproject1-multiproject.example.com", "https://multiproject1.com"}, + wantautoGen: []string{"https://node-multiproject1-multiproject.example.com"}, + wantJSON: `{"primary":"https://multiproject1.com","secondary":["https://node-multiproject1-multiproject.example.com","https://multiproject1.com"],"autogenerated":["https://node-multiproject1-multiproject.example.com"]}`, }, { name: "test6 multiproject2 no values", @@ -128,11 +124,10 @@ func TestIdentifyRoute(t *testing.T) { Branch: "multiproject", LagoonYAML: "internal/testdata/node/lagoon.polysite.yml", }, true), - templatePath: "testoutput", - want: "https://multiproject2.com", - wantRemain: []string{"https://node-multiproject2-multiproject.example.com", "https://multiproject2.com"}, - wantautoGen: []string{"https://node-multiproject2-multiproject.example.com"}, - wantJSON: `{"primary":"https://multiproject2.com","secondary":["https://node-multiproject2-multiproject.example.com","https://multiproject2.com"],"autogenerated":["https://node-multiproject2-multiproject.example.com"]}`, + want: "https://multiproject2.com", + wantRemain: []string{"https://node-multiproject2-multiproject.example.com", "https://multiproject2.com"}, + wantautoGen: []string{"https://node-multiproject2-multiproject.example.com"}, + wantJSON: `{"primary":"https://multiproject2.com","secondary":["https://node-multiproject2-multiproject.example.com","https://multiproject2.com"],"autogenerated":["https://node-multiproject2-multiproject.example.com"]}`, }, { name: "test7 multidomain no values", @@ -143,11 +138,10 @@ func TestIdentifyRoute(t *testing.T) { Branch: "tworoutes", LagoonYAML: "internal/testdata/node/lagoon.yml", }, true), - templatePath: "testoutput", - want: "https://example.com", - wantRemain: []string{"https://node-example-project-tworoutes.example.com", "https://example.com", "https://www.example.com"}, - wantautoGen: []string{"https://node-example-project-tworoutes.example.com"}, - wantJSON: `{"primary":"https://example.com","secondary":["https://node-example-project-tworoutes.example.com","https://example.com","https://www.example.com"],"autogenerated":["https://node-example-project-tworoutes.example.com"]}`, + want: "https://example.com", + wantRemain: []string{"https://node-example-project-tworoutes.example.com", "https://example.com", "https://www.example.com"}, + wantautoGen: []string{"https://node-example-project-tworoutes.example.com"}, + wantJSON: `{"primary":"https://example.com","secondary":["https://node-example-project-tworoutes.example.com","https://example.com","https://www.example.com"],"autogenerated":["https://node-example-project-tworoutes.example.com"]}`, }, { name: "test8 multidomain no values", @@ -158,11 +152,10 @@ func TestIdentifyRoute(t *testing.T) { Branch: "branch/routes", LagoonYAML: "internal/testdata/node/lagoon.yml", }, true), - templatePath: "testoutput", - want: "https://customdomain-will-be-main-domain.com", - wantRemain: []string{"https://node-example-project-branch-routes.example.com", "https://customdomain-will-be-main-domain.com", "https://customdomain-will-be-not-be-main-domain.com"}, - wantautoGen: []string{"https://node-example-project-branch-routes.example.com"}, - wantJSON: `{"primary":"https://customdomain-will-be-main-domain.com","secondary":["https://node-example-project-branch-routes.example.com","https://customdomain-will-be-main-domain.com","https://customdomain-will-be-not-be-main-domain.com"],"autogenerated":["https://node-example-project-branch-routes.example.com"]}`, + want: "https://customdomain-will-be-main-domain.com", + wantRemain: []string{"https://node-example-project-branch-routes.example.com", "https://customdomain-will-be-main-domain.com", "https://customdomain-will-be-not-be-main-domain.com"}, + wantautoGen: []string{"https://node-example-project-branch-routes.example.com"}, + wantJSON: `{"primary":"https://customdomain-will-be-main-domain.com","secondary":["https://node-example-project-branch-routes.example.com","https://customdomain-will-be-main-domain.com","https://customdomain-will-be-not-be-main-domain.com"],"autogenerated":["https://node-example-project-branch-routes.example.com"]}`, }, { name: "test9 active no values", @@ -175,11 +168,10 @@ func TestIdentifyRoute(t *testing.T) { StandbyEnvironment: "main-sb", LagoonYAML: "internal/testdata/node/lagoon.activestandby.yml", }, true), - templatePath: "testoutput", - want: "https://active.example.com", - wantRemain: []string{"https://node-example-project-main.example.com", "https://main.example.com", "https://active.example.com"}, - wantautoGen: []string{"https://node-example-project-main.example.com"}, - wantJSON: `{"primary":"https://active.example.com","secondary":["https://node-example-project-main.example.com","https://main.example.com","https://active.example.com"],"autogenerated":["https://node-example-project-main.example.com"]}`, + want: "https://active.example.com", + wantRemain: []string{"https://node-example-project-main.example.com", "https://main.example.com", "https://active.example.com"}, + wantautoGen: []string{"https://node-example-project-main.example.com"}, + wantJSON: `{"primary":"https://active.example.com","secondary":["https://node-example-project-main.example.com","https://main.example.com","https://active.example.com"],"autogenerated":["https://node-example-project-main.example.com"]}`, }, { name: "test10 standby no values", @@ -192,11 +184,10 @@ func TestIdentifyRoute(t *testing.T) { StandbyEnvironment: "main-sb", LagoonYAML: "internal/testdata/node/lagoon.activestandby.yml", }, true), - templatePath: "testoutput", - want: "https://standby.example.com", - wantRemain: []string{"https://node-example-project-main-sb.example.com", "https://main-sb.example.com", "https://standby.example.com"}, - wantautoGen: []string{"https://node-example-project-main-sb.example.com"}, - wantJSON: `{"primary":"https://standby.example.com","secondary":["https://node-example-project-main-sb.example.com","https://main-sb.example.com","https://standby.example.com"],"autogenerated":["https://node-example-project-main-sb.example.com"]}`, + want: "https://standby.example.com", + wantRemain: []string{"https://node-example-project-main-sb.example.com", "https://main-sb.example.com", "https://standby.example.com"}, + wantautoGen: []string{"https://node-example-project-main-sb.example.com"}, + wantJSON: `{"primary":"https://standby.example.com","secondary":["https://node-example-project-main-sb.example.com","https://main-sb.example.com","https://standby.example.com"],"autogenerated":["https://node-example-project-main-sb.example.com"]}`, }, { name: "test11 no custom ingress", @@ -207,11 +198,10 @@ func TestIdentifyRoute(t *testing.T) { Branch: "no-ingress", LagoonYAML: "internal/testdata/node/lagoon.yml", }, true), - templatePath: "testoutput", - want: "https://node-example-project-no-ingress.example.com", - wantRemain: []string{"https://node-example-project-no-ingress.example.com"}, - wantautoGen: []string{"https://node-example-project-no-ingress.example.com"}, - wantJSON: `{"primary":"https://node-example-project-no-ingress.example.com","secondary":["https://node-example-project-no-ingress.example.com"],"autogenerated":["https://node-example-project-no-ingress.example.com"]}`, + want: "https://node-example-project-no-ingress.example.com", + wantRemain: []string{"https://node-example-project-no-ingress.example.com"}, + wantautoGen: []string{"https://node-example-project-no-ingress.example.com"}, + wantJSON: `{"primary":"https://node-example-project-no-ingress.example.com","secondary":["https://node-example-project-no-ingress.example.com"],"autogenerated":["https://node-example-project-no-ingress.example.com"]}`, }, { name: "test12 no custom ingress", @@ -222,8 +212,7 @@ func TestIdentifyRoute(t *testing.T) { Branch: "no-ingress", LagoonYAML: "internal/testdata/node/lagoon.autogen-prefixes-1.yml", }, true), - templatePath: "testoutput", - want: "https://node-example-project-no-ingress.example.com", + want: "https://node-example-project-no-ingress.example.com", wantRemain: []string{ "https://node-example-project-no-ingress.example.com", "https://www.node-example-project-no-ingress.example.com", @@ -249,11 +238,10 @@ func TestIdentifyRoute(t *testing.T) { Branch: "main", LagoonYAML: "internal/testdata/node/lagoon.autogen-1.yml", }, true), - templatePath: "testoutput", - want: "https://example.com", - wantRemain: []string{"https://example.com"}, - wantautoGen: []string{}, - wantJSON: `{"primary":"https://example.com","secondary":["https://example.com"],"autogenerated":[]}`, + want: "https://example.com", + wantRemain: []string{"https://example.com"}, + wantautoGen: []string{}, + wantJSON: `{"primary":"https://example.com","secondary":["https://example.com"],"autogenerated":[]}`, }, { name: "test14 only autogenerated route", @@ -264,11 +252,10 @@ func TestIdentifyRoute(t *testing.T) { Branch: "notmain", LagoonYAML: "internal/testdata/node/lagoon.yml", }, true), - templatePath: "testoutput", - want: "https://node-example-project-notmain.example.com", - wantRemain: []string{"https://node-example-project-notmain.example.com"}, - wantautoGen: []string{"https://node-example-project-notmain.example.com"}, - wantJSON: `{"primary":"https://node-example-project-notmain.example.com","secondary":["https://node-example-project-notmain.example.com"],"autogenerated":["https://node-example-project-notmain.example.com"]}`, + want: "https://node-example-project-notmain.example.com", + wantRemain: []string{"https://node-example-project-notmain.example.com"}, + wantautoGen: []string{"https://node-example-project-notmain.example.com"}, + wantJSON: `{"primary":"https://node-example-project-notmain.example.com","secondary":["https://node-example-project-notmain.example.com"],"autogenerated":["https://node-example-project-notmain.example.com"]}`, }, { name: "test15 only autogenerated route complex", @@ -287,11 +274,10 @@ func TestIdentifyRoute(t *testing.T) { }, }, }, false), - templatePath: "testoutput", - want: "https://nginx-sales-customer-support-develop.ex1.example-web.com", - wantRemain: []string{"https://nginx-sales-customer-support-develop.ex1.example-web.com"}, - wantautoGen: []string{"https://nginx-sales-customer-support-develop.ex1.example-web.com"}, - wantJSON: `{"primary":"https://nginx-sales-customer-support-develop.ex1.example-web.com","secondary":["https://nginx-sales-customer-support-develop.ex1.example-web.com"],"autogenerated":["https://nginx-sales-customer-support-develop.ex1.example-web.com"]}`, + want: "https://nginx-sales-customer-support-develop.ex1.example-web.com", + wantRemain: []string{"https://nginx-sales-customer-support-develop.ex1.example-web.com"}, + wantautoGen: []string{"https://nginx-sales-customer-support-develop.ex1.example-web.com"}, + wantJSON: `{"primary":"https://nginx-sales-customer-support-develop.ex1.example-web.com","secondary":["https://nginx-sales-customer-support-develop.ex1.example-web.com"],"autogenerated":["https://nginx-sales-customer-support-develop.ex1.example-web.com"]}`, }, { name: "test16 autogenerated routes where lagoon.name of service does not match service names", @@ -310,11 +296,10 @@ func TestIdentifyRoute(t *testing.T) { }, }, }, false), - templatePath: "testoutput", - want: "https://nginx-php.feature-migration.content-example-com.example.com", - wantRemain: []string{"https://nginx-php.feature-migration.content-example-com.example.com"}, - wantautoGen: []string{"https://nginx-php.feature-migration.content-example-com.example.com"}, - wantJSON: `{"primary":"https://nginx-php.feature-migration.content-example-com.example.com","secondary":["https://nginx-php.feature-migration.content-example-com.example.com"],"autogenerated":["https://nginx-php.feature-migration.content-example-com.example.com"]}`, + want: "https://nginx-php.feature-migration.content-example-com.example.com", + wantRemain: []string{"https://nginx-php.feature-migration.content-example-com.example.com"}, + wantautoGen: []string{"https://nginx-php.feature-migration.content-example-com.example.com"}, + wantJSON: `{"primary":"https://nginx-php.feature-migration.content-example-com.example.com","secondary":["https://nginx-php.feature-migration.content-example-com.example.com"],"autogenerated":["https://nginx-php.feature-migration.content-example-com.example.com"]}`, }, { name: "test17 autogenerated routes with multiple routeable services", @@ -325,11 +310,10 @@ func TestIdentifyRoute(t *testing.T) { Branch: "main", LagoonYAML: "internal/testdata/complex/lagoon.small-2.yml", }, true), - templatePath: "testoutput", - want: "https://nginx-example-project-main.example.com", - wantRemain: []string{"https://nginx-example-project-main.example.com", "https://varnish-example-project-main.example.com"}, - wantautoGen: []string{"https://nginx-example-project-main.example.com", "https://varnish-example-project-main.example.com"}, - wantJSON: `{"primary":"https://nginx-example-project-main.example.com","secondary":["https://nginx-example-project-main.example.com","https://varnish-example-project-main.example.com"],"autogenerated":["https://nginx-example-project-main.example.com","https://varnish-example-project-main.example.com"]}`, + want: "https://nginx-example-project-main.example.com", + wantRemain: []string{"https://nginx-example-project-main.example.com", "https://varnish-example-project-main.example.com"}, + wantautoGen: []string{"https://nginx-example-project-main.example.com", "https://varnish-example-project-main.example.com"}, + wantJSON: `{"primary":"https://nginx-example-project-main.example.com","secondary":["https://nginx-example-project-main.example.com","https://varnish-example-project-main.example.com"],"autogenerated":["https://nginx-example-project-main.example.com","https://varnish-example-project-main.example.com"]}`, }, { name: "test18 autogenerated routes with wildcard and altnames", @@ -340,19 +324,21 @@ func TestIdentifyRoute(t *testing.T) { Branch: "main", LagoonYAML: "internal/testdata/complex/lagoon.complex-2.yml", }, true), - templatePath: "testoutput", - want: "https://wild.example.com", - wantRemain: []string{"https://nginx-example-project-main.example.com", "https://wild.example.com", "https://alt.example.com", "https://www.example.com", "https://en.example.com"}, - wantautoGen: []string{"https://nginx-example-project-main.example.com"}, - wantJSON: `{"primary":"https://wild.example.com","secondary":["https://nginx-example-project-main.example.com","https://wild.example.com","https://alt.example.com","https://www.example.com","https://en.example.com"],"autogenerated":["https://nginx-example-project-main.example.com"]}`, + want: "https://wild.example.com", + wantRemain: []string{"https://nginx-example-project-main.example.com", "https://wild.example.com", "https://alt.example.com", "https://www.example.com", "https://en.example.com"}, + wantautoGen: []string{"https://nginx-example-project-main.example.com"}, + wantJSON: `{"primary":"https://wild.example.com","secondary":["https://nginx-example-project-main.example.com","https://wild.example.com","https://alt.example.com","https://www.example.com","https://en.example.com"],"autogenerated":["https://nginx-example-project-main.example.com"]}`, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { helpers.UnsetEnvVars(nil) //unset variables before running tests // set the environment variables from args - savedTemplates := tt.templatePath - generator, err := testdata.SetupEnvironment(*rootCmd, savedTemplates, tt.args) + savedTemplates, err := os.MkdirTemp("", "testoutput") + if err != nil { + t.Errorf("%v", err) + } + generator, err := testdata.SetupEnvironment(generator.GeneratorInput{}, savedTemplates, tt.args) if err != nil { t.Errorf("%v", err) } @@ -383,6 +369,10 @@ func TestIdentifyRoute(t *testing.T) { if string(retJSON) != tt.wantJSON { t.Errorf("returned autogen %v doesn't match want %v", string(retJSON), tt.wantJSON) } + t.Cleanup(func() { + helpers.UnsetEnvVars(nil) + helpers.UnsetEnvVars(tt.args.BuildPodVariables) + }) }) } } @@ -406,10 +396,9 @@ func TestCreatedIngressIdentification(t *testing.T) { Branch: "main", LagoonYAML: "internal/testdata/node/lagoon.autogen-1.yml", }, true), - templatePath: "testoutput", - wantRemain: []string{"example.com"}, - wantautoGen: []string{}, - wantJSON: `{"primary":"","secondary":["example.com"],"autogenerated":[]}`, + wantRemain: []string{"example.com"}, + wantautoGen: []string{}, + wantJSON: `{"primary":"","secondary":["example.com"],"autogenerated":[]}`, }, { name: "test14 only autogenerated route", @@ -420,10 +409,9 @@ func TestCreatedIngressIdentification(t *testing.T) { Branch: "notmain", LagoonYAML: "internal/testdata/node/lagoon.yml", }, true), - templatePath: "testoutput", - wantRemain: []string{}, - wantautoGen: []string{"node"}, - wantJSON: `{"primary":"","secondary":[],"autogenerated":["node"]}`, + wantRemain: []string{}, + wantautoGen: []string{"node"}, + wantJSON: `{"primary":"","secondary":[],"autogenerated":["node"]}`, }, { name: "test15 only autogenerated route complex", @@ -442,10 +430,9 @@ func TestCreatedIngressIdentification(t *testing.T) { }, }, }, false), - templatePath: "testoutput", - wantRemain: []string{}, - wantautoGen: []string{"nginx"}, - wantJSON: `{"primary":"","secondary":[],"autogenerated":["nginx"]}`, + wantRemain: []string{}, + wantautoGen: []string{"nginx"}, + wantJSON: `{"primary":"","secondary":[],"autogenerated":["nginx"]}`, }, { name: "test16 autogenerated routes where lagoon.name of service does not match service names", @@ -464,10 +451,9 @@ func TestCreatedIngressIdentification(t *testing.T) { }, }, }, false), - templatePath: "testoutput", - wantRemain: []string{}, - wantautoGen: []string{"nginx-php"}, - wantJSON: `{"primary":"","secondary":[],"autogenerated":["nginx-php"]}`, + wantRemain: []string{}, + wantautoGen: []string{"nginx-php"}, + wantJSON: `{"primary":"","secondary":[],"autogenerated":["nginx-php"]}`, }, { name: "test17 autogenerated routes with multiple routeable services", @@ -478,10 +464,9 @@ func TestCreatedIngressIdentification(t *testing.T) { Branch: "main", LagoonYAML: "internal/testdata/complex/lagoon.small-2.yml", }, true), - templatePath: "testoutput", - wantRemain: []string{}, - wantautoGen: []string{"nginx", "varnish"}, - wantJSON: `{"primary":"","secondary":[],"autogenerated":["nginx","varnish"]}`, + wantRemain: []string{}, + wantautoGen: []string{"nginx", "varnish"}, + wantJSON: `{"primary":"","secondary":[],"autogenerated":["nginx","varnish"]}`, }, { name: "test18 autogenerated routes with wildcard and altnames", @@ -492,17 +477,16 @@ func TestCreatedIngressIdentification(t *testing.T) { Branch: "main", LagoonYAML: "internal/testdata/complex/lagoon.complex-2.yml", }, true), - templatePath: "testoutput", - wantRemain: []string{"wildcard-wild.example.com", "alt.example.com"}, - wantautoGen: []string{"nginx"}, - wantJSON: `{"primary":"","secondary":["wildcard-wild.example.com","alt.example.com"],"autogenerated":["nginx"]}`, + wantRemain: []string{"wildcard-wild.example.com", "alt.example.com"}, + wantautoGen: []string{"nginx"}, + wantJSON: `{"primary":"","secondary":["wildcard-wild.example.com","alt.example.com"],"autogenerated":["nginx"]}`, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { // set the environment variables from args savedTemplates := tt.templatePath - generator, err := testdata.SetupEnvironment(*rootCmd, savedTemplates, tt.args) + generator, err := testdata.SetupEnvironment(generator.GeneratorInput{}, savedTemplates, tt.args) if err != nil { t.Errorf("%v", err) } diff --git a/cmd/identify_lagoonservices.go b/cmd/identify_lagoonservices.go index a81e7c85..20a4542f 100644 --- a/cmd/identify_lagoonservices.go +++ b/cmd/identify_lagoonservices.go @@ -1,28 +1,19 @@ package cmd import ( - "encoding/base64" "encoding/json" "fmt" "github.com/spf13/cobra" - generator "github.com/uselagoon/build-deploy-tool/internal/generator" - servicestemplates "github.com/uselagoon/build-deploy-tool/internal/templating" + "github.com/uselagoon/build-deploy-tool/internal/collector" + "github.com/uselagoon/build-deploy-tool/internal/helpers" + "github.com/uselagoon/build-deploy-tool/internal/identify" + "github.com/uselagoon/build-deploy-tool/internal/k8s" ) -type identifyServices struct { - Name string `json:"name"` - Type string `json:"type"` - Containers []containers `json:"containers,omitempty"` -} - -type containers struct { - Name string `json:"name"` - Ports []ports `json:"ports,omitempty"` -} - -type ports struct { - Port int32 `json:"port"` +type LagoonServices struct { + Services []identify.EnvironmentService `json:"services"` + Volumes []identify.EnvironmentVolume `json:"volumes"` } var lagoonServiceIdentify = &cobra.Command{ @@ -30,73 +21,44 @@ var lagoonServiceIdentify = &cobra.Command{ Aliases: []string{"ls"}, Short: "Identify the lagoon services for a Lagoon build", RunE: func(cmd *cobra.Command, args []string) error { - gen, err := generator.GenerateInput(*rootCmd, true) + gen, err := GenerateInput(*rootCmd, false) if err != nil { return err } + client, err := k8s.NewClient() + if err != nil { + return err + } + // create a collector + col := collector.NewCollector(client) images, err := rootCmd.PersistentFlags().GetString("images") if err != nil { return fmt.Errorf("error reading images flag: %v", err) } - var imageRefs struct { - Images map[string]string `json:"images"` + imageRefs, err := loadImagesFromFile(images) + if err != nil { + return err } - imagesStr, err := base64.StdEncoding.DecodeString(images) + namespace := helpers.GetEnv("NAMESPACE", "", false) + namespace, err = helpers.GetNamespace(namespace, "/var/run/secrets/kubernetes.io/serviceaccount/namespace") if err != nil { - return fmt.Errorf("error decoding images payload: %v", err) + return err } - if err := json.Unmarshal(imagesStr, &imageRefs); err != nil { - return fmt.Errorf("error unmarshalling images payload: %v", err) + if namespace == "" { + return fmt.Errorf("unable to detect namespace") } + gen.Namespace = namespace gen.ImageReferences = imageRefs.Images - out, err := LagoonServiceTemplateIdentification(gen) + services, _, _, _, _, _, _, _, err := identify.GetCurrentState(col, gen) if err != nil { return err } - fmt.Println(out) + servs, _ := json.Marshal(services) + fmt.Println(string(servs)) return nil }, } -// LagoonServiceTemplateIdentification takes the output of the generator and returns a JSON payload that contains information -// about the services that lagoon will be deploying (this will be kubernetes `kind: deployment`, but lagoon calls them services ¯\_(ツ)_/¯) -// this command can be used to identify services that are deployed by the build, so that services that may remain in the environment can be identified -// and eventually removed -func LagoonServiceTemplateIdentification(g generator.GeneratorInput) ([]identifyServices, error) { - - lServices := []identifyServices{} - lagoonBuild, err := generator.NewGenerator( - g, - ) - if err != nil { - return nil, err - } - - deployments, err := servicestemplates.GenerateDeploymentTemplate(*lagoonBuild.BuildValues) - if err != nil { - return nil, fmt.Errorf("couldn't generate template: %v", err) - } - for _, d := range deployments { - dcs := []containers{} - for _, dc := range d.Spec.Template.Spec.Containers { - dcp := []ports{} - for _, p := range dc.Ports { - dcp = append(dcp, ports{Port: p.ContainerPort}) - } - dcs = append(dcs, containers{ - Name: dc.Name, - Ports: dcp, - }) - } - lServices = append(lServices, identifyServices{ - Name: d.Name, - Type: d.ObjectMeta.Labels["lagoon.sh/service-type"], - Containers: dcs, - }) - } - return lServices, nil -} - func init() { identifyCmd.AddCommand(lagoonServiceIdentify) } diff --git a/cmd/identify_native_cronjobs.go b/cmd/identify_native_cronjobs.go index cbc4c633..3dd861b8 100644 --- a/cmd/identify_native_cronjobs.go +++ b/cmd/identify_native_cronjobs.go @@ -13,7 +13,7 @@ var nativeCronjobsIdentify = &cobra.Command{ Aliases: []string{"nc"}, Short: "Identify any native cronjobs for a specific environment", RunE: func(cmd *cobra.Command, args []string) error { - generator, err := generator.GenerateInput(*rootCmd, false) + generator, err := GenerateInput(*rootCmd, false) if err != nil { return err } diff --git a/cmd/identify_native_cronjobs_test.go b/cmd/identify_native_cronjobs_test.go index e6040cdf..3e916ea1 100644 --- a/cmd/identify_native_cronjobs_test.go +++ b/cmd/identify_native_cronjobs_test.go @@ -5,6 +5,7 @@ import ( "testing" "github.com/uselagoon/build-deploy-tool/internal/dbaasclient" + "github.com/uselagoon/build-deploy-tool/internal/generator" "github.com/uselagoon/build-deploy-tool/internal/helpers" "github.com/uselagoon/build-deploy-tool/internal/lagoon" "github.com/uselagoon/build-deploy-tool/internal/testdata" @@ -15,10 +16,9 @@ import ( func TestIdentifyNativeCronjobs(t *testing.T) { tests := []struct { - name string - args testdata.TestData - templatePath string - want string + name string + args testdata.TestData + want string }{ { name: "test1 basic deployment", @@ -29,8 +29,7 @@ func TestIdentifyNativeCronjobs(t *testing.T) { Branch: "main", LagoonYAML: "internal/testdata/node/lagoon.yml", }, true), - templatePath: "testoutput", - want: "[]", + want: "[]", }, { name: "test2a nginx-php deployment", @@ -41,8 +40,7 @@ func TestIdentifyNativeCronjobs(t *testing.T) { Branch: "main", LagoonYAML: "internal/testdata/complex/lagoon.yml", }, true), - templatePath: "testoutput", - want: `["cronjob-cli-drush-cron2"]`, + want: `["cronjob-cli-drush-cron2"]`, }, { name: "test2b nginx-php deployment - rootless", @@ -60,23 +58,20 @@ func TestIdentifyNativeCronjobs(t *testing.T) { }, }, }, true), - templatePath: "testoutput", - want: `["cronjob-cli-drush-cron2"]`, + want: `["cronjob-cli-drush-cron2"]`, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { helpers.UnsetEnvVars(nil) //unset variables before running tests // set the environment variables from args - savedTemplates := tt.templatePath - generator, err := testdata.SetupEnvironment(*rootCmd, savedTemplates, tt.args) + savedTemplates, err := os.MkdirTemp("", "testoutput") if err != nil { t.Errorf("%v", err) } - - err = os.MkdirAll(savedTemplates, 0755) + generator, err := testdata.SetupEnvironment(generator.GeneratorInput{}, savedTemplates, tt.args) if err != nil { - t.Errorf("couldn't create directory %v: %v", savedTemplates, err) + t.Errorf("%v", err) } defer os.RemoveAll(savedTemplates) diff --git a/cmd/root.go b/cmd/root.go index e3988677..f53fd678 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -21,6 +21,8 @@ import ( "os" "github.com/spf13/cobra" + "github.com/uselagoon/build-deploy-tool/internal/dbaasclient" + "github.com/uselagoon/build-deploy-tool/internal/generator" ) // rootCmd represents the base command when called without any subcommands @@ -67,6 +69,13 @@ var collectCmd = &cobra.Command{ Long: `Collect resource information for Lagoon builds`, } +var runCmd = &cobra.Command{ + Use: "run", + Aliases: []string{"r"}, + Short: "Run a process", + Long: `Run a process`, +} + // Execute adds all child commands to the root command and sets flags appropriately. // This is called by main.main(). It only needs to happen once to the rootCmd. func Execute() { @@ -169,3 +178,129 @@ func init() { // initConfig reads in config file and ENV variables if set. func initConfig() { } + +// helper function that reads flag overrides and returns a generated input dataset +// this is called from within the main environment setup helper function +func GenerateInput(rootCmd cobra.Command, debug bool) (generator.GeneratorInput, error) { + lagoonYAML, err := rootCmd.PersistentFlags().GetString("lagoon-yml") + if err != nil { + return generator.GeneratorInput{}, fmt.Errorf("error reading lagoon-yml flag: %v", err) + } + lagoonYAMLOverride, err := rootCmd.PersistentFlags().GetString("lagoon-yml-override") + if err != nil { + return generator.GeneratorInput{}, fmt.Errorf("error reading lagoon-yml-override flag: %v", err) + } + lagoonVersion, err := rootCmd.PersistentFlags().GetString("lagoon-version") + if err != nil { + return generator.GeneratorInput{}, fmt.Errorf("error reading lagoon-version flag: %v", err) + } + projectName, err := rootCmd.PersistentFlags().GetString("project-name") + if err != nil { + return generator.GeneratorInput{}, fmt.Errorf("error reading project-name flag: %v", err) + } + environmentName, err := rootCmd.PersistentFlags().GetString("environment-name") + if err != nil { + return generator.GeneratorInput{}, fmt.Errorf("error reading environment-name flag: %v", err) + } + environmentType, err := rootCmd.PersistentFlags().GetString("environment-type") + if err != nil { + return generator.GeneratorInput{}, fmt.Errorf("error reading environment-type flag: %v", err) + } + activeEnvironment, err := rootCmd.PersistentFlags().GetString("active-environment") + if err != nil { + return generator.GeneratorInput{}, fmt.Errorf("error reading active-environment flag: %v", err) + } + standbyEnvironment, err := rootCmd.PersistentFlags().GetString("standby-environment") + if err != nil { + return generator.GeneratorInput{}, fmt.Errorf("error reading standby-environment flag: %v", err) + } + projectVariables, err := rootCmd.PersistentFlags().GetString("project-variables") + if err != nil { + return generator.GeneratorInput{}, fmt.Errorf("error reading project-variables flag: %v", err) + } + environmentVariables, err := rootCmd.PersistentFlags().GetString("environment-variables") + if err != nil { + return generator.GeneratorInput{}, fmt.Errorf("error reading environment-variables flag: %v", err) + } + buildType, err := rootCmd.PersistentFlags().GetString("build-type") + if err != nil { + return generator.GeneratorInput{}, fmt.Errorf("error reading build-type flag: %v", err) + } + branch, err := rootCmd.PersistentFlags().GetString("branch") + if err != nil { + return generator.GeneratorInput{}, fmt.Errorf("error reading branch flag: %v", err) + } + prNumber, err := rootCmd.PersistentFlags().GetString("pullrequest-number") + if err != nil { + return generator.GeneratorInput{}, fmt.Errorf("error reading pullrequest-number flag: %v", err) + } + prTitle, err := rootCmd.PersistentFlags().GetString("pullrequest-title") + if err != nil { + return generator.GeneratorInput{}, fmt.Errorf("error reading pullrequest-title flag: %v", err) + } + prHeadBranch, err := rootCmd.PersistentFlags().GetString("pullrequest-head-branch") + if err != nil { + return generator.GeneratorInput{}, fmt.Errorf("error reading pullrequest-head-branch flag: %v", err) + } + prBaseBranch, err := rootCmd.PersistentFlags().GetString("pullrequest-base-branch") + if err != nil { + return generator.GeneratorInput{}, fmt.Errorf("error reading pullrequest-base-branch flag: %v", err) + } + monitoringContact, err := rootCmd.PersistentFlags().GetString("monitoring-config") + if err != nil { + return generator.GeneratorInput{}, fmt.Errorf("error reading monitoring-config flag: %v", err) + } + monitoringStatusPageID, err := rootCmd.PersistentFlags().GetString("monitoring-status-page-id") + if err != nil { + return generator.GeneratorInput{}, fmt.Errorf("error reading monitoring-status-page-id flag: %v", err) + } + fastlyCacheNoCache, err := rootCmd.PersistentFlags().GetString("fastly-cache-no-cache-id") + if err != nil { + return generator.GeneratorInput{}, fmt.Errorf("error reading fastly-cache-no-cache-id flag: %v", err) + } + ignoreMissingEnvFiles, err := rootCmd.PersistentFlags().GetBool("ignore-missing-env-files") + if err != nil { + return generator.GeneratorInput{}, fmt.Errorf("error reading ignore-missing-env-files flag: %v", err) + } + ignoreNonStringKeyErrors, err := rootCmd.PersistentFlags().GetBool("ignore-non-string-key-errors") + if err != nil { + return generator.GeneratorInput{}, fmt.Errorf("error reading ignore-non-string-key-errors flag: %v", err) + } + savedTemplates, err := rootCmd.PersistentFlags().GetString("saved-templates-path") + if err != nil { + return generator.GeneratorInput{}, fmt.Errorf("error reading saved-templates-path flag: %v", err) + } + defaultBackupSchedule, err := rootCmd.PersistentFlags().GetString("default-backup-schedule") + if err != nil { + return generator.GeneratorInput{}, fmt.Errorf("error reading default-backup-schedule flag: %v", err) + } + // create a dbaas client with the default configuration + dbaas := dbaasclient.NewClient(dbaasclient.Client{}) + return generator.GeneratorInput{ + Debug: debug, + LagoonYAML: lagoonYAML, + LagoonYAMLOverride: lagoonYAMLOverride, + LagoonVersion: lagoonVersion, + ProjectName: projectName, + EnvironmentName: environmentName, + EnvironmentType: environmentType, + ActiveEnvironment: activeEnvironment, + StandbyEnvironment: standbyEnvironment, + ProjectVariables: projectVariables, + EnvironmentVariables: environmentVariables, + BuildType: buildType, + Branch: branch, + PRNumber: prNumber, + PRTitle: prTitle, + PRHeadBranch: prHeadBranch, + PRBaseBranch: prBaseBranch, + MonitoringContact: monitoringContact, + MonitoringStatusPageID: monitoringStatusPageID, + FastlyCacheNoCache: fastlyCacheNoCache, + SavedTemplatesPath: savedTemplates, + IgnoreMissingEnvFiles: ignoreMissingEnvFiles, + IgnoreNonStringKeyErrors: ignoreNonStringKeyErrors, + DBaaSClient: dbaas, + DefaultBackupSchedule: defaultBackupSchedule, + }, nil +} diff --git a/cmd/run_cleanup.go b/cmd/run_cleanup.go new file mode 100644 index 00000000..9a1f4f02 --- /dev/null +++ b/cmd/run_cleanup.go @@ -0,0 +1,61 @@ +package cmd + +import ( + "fmt" + + "github.com/spf13/cobra" + "github.com/uselagoon/build-deploy-tool/internal/cleanup" + "github.com/uselagoon/build-deploy-tool/internal/collector" + "github.com/uselagoon/build-deploy-tool/internal/helpers" + "github.com/uselagoon/build-deploy-tool/internal/k8s" +) + +var cleanupCmd = &cobra.Command{ + Use: "cleanup", + Aliases: []string{"clean", "cu", "c"}, + Short: "Cleanup old services", + RunE: func(cmd *cobra.Command, args []string) error { + deleteServices, err := cmd.Flags().GetBool("delete") + if err != nil { + return fmt.Errorf("error reading domain flag: %v", err) + } + client, err := k8s.NewClient() + if err != nil { + return err + } + // create a collector + col := collector.NewCollector(client) + gen, err := GenerateInput(*rootCmd, false) + if err != nil { + return err + } + images, err := rootCmd.PersistentFlags().GetString("images") + if err != nil { + return fmt.Errorf("error reading images flag: %v", err) + } + imageRefs, err := loadImagesFromFile(images) + if err != nil { + return err + } + namespace := helpers.GetEnv("NAMESPACE", "", false) + namespace, err = helpers.GetNamespace(namespace, "/var/run/secrets/kubernetes.io/serviceaccount/namespace") + if err != nil { + return err + } + if namespace == "" { + return fmt.Errorf("unable to detect namespace") + } + gen.Namespace = namespace + gen.ImageReferences = imageRefs.Images + _, _, _, _, _, _, err = cleanup.RunCleanup(col, gen, deleteServices) + if err != nil { + return err + } + return nil + }, +} + +func init() { + runCmd.AddCommand(cleanupCmd) + cleanupCmd.Flags().Bool("delete", false, "flag to actually delete services") +} diff --git a/cmd/run_hooks.go b/cmd/run_hooks.go index c56150a4..7970bf61 100644 --- a/cmd/run_hooks.go +++ b/cmd/run_hooks.go @@ -8,12 +8,6 @@ import ( "github.com/uselagoon/build-deploy-tool/internal/hooks" ) -var runCmd = &cobra.Command{ - Use: "run", - Aliases: []string{"r"}, - Short: "Run commands", -} - var runHookCmd = &cobra.Command{ Use: "hooks", Aliases: []string{"hook", "h"}, diff --git a/cmd/tasks_run.go b/cmd/tasks_run.go index b54df377..4d3c7671 100644 --- a/cmd/tasks_run.go +++ b/cmd/tasks_run.go @@ -51,7 +51,7 @@ var tasksPreRun = &cobra.Command{ Aliases: []string{"pre"}, Short: "Will run pre rollout tasks defined in .lagoon.yml", RunE: func(cmd *cobra.Command, args []string) error { - generator, err := generator.GenerateInput(*rootCmd, true) + generator, err := GenerateInput(*rootCmd, true) if err != nil { return err } @@ -82,7 +82,7 @@ var tasksPostRun = &cobra.Command{ Aliases: []string{"post"}, Short: "Will run post rollout tasks defined in .lagoon.yml", RunE: func(cmd *cobra.Command, args []string) error { - generator, err := generator.GenerateInput(*rootCmd, true) + generator, err := GenerateInput(*rootCmd, true) if err != nil { return err } diff --git a/cmd/template_autogen_ingress.go b/cmd/template_autogen_ingress.go index 2ff61697..be1445fe 100644 --- a/cmd/template_autogen_ingress.go +++ b/cmd/template_autogen_ingress.go @@ -14,7 +14,7 @@ var autogenRouteGeneration = &cobra.Command{ Aliases: []string{"autogen-ingress", "autogen", "ai"}, Short: "Generate the autogenerated ingress templates for a Lagoon build", RunE: func(cmd *cobra.Command, args []string) error { - generator, err := generator.GenerateInput(*rootCmd, true) + generator, err := GenerateInput(*rootCmd, true) if err != nil { return err } diff --git a/cmd/template_autogen_ingress_test.go b/cmd/template_autogen_ingress_test.go index 2f1e646e..b04e2857 100644 --- a/cmd/template_autogen_ingress_test.go +++ b/cmd/template_autogen_ingress_test.go @@ -8,6 +8,7 @@ import ( "testing" "github.com/andreyvit/diff" + "github.com/uselagoon/build-deploy-tool/internal/generator" "github.com/uselagoon/build-deploy-tool/internal/helpers" "github.com/uselagoon/build-deploy-tool/internal/lagoon" "github.com/uselagoon/build-deploy-tool/internal/testdata" @@ -18,13 +19,12 @@ import ( func TestAutogeneratedIngressGeneration(t *testing.T) { tests := []struct { - name string - description string - args testdata.TestData - templatePath string - wantErr bool - emptyDir bool // if no templates are generated, then there will be a .gitkeep file in there - want string + name string + description string + args testdata.TestData + wantErr bool + emptyDir bool // if no templates are generated, then there will be a .gitkeep file in there + want string }{ { name: "test1 autogenerated route", @@ -35,8 +35,7 @@ func TestAutogeneratedIngressGeneration(t *testing.T) { Branch: "main", LagoonYAML: "internal/testdata/node/lagoon.yml", }, true), - templatePath: "testoutput", - want: "internal/testdata/node/autogen-templates/ingress-1", + want: "internal/testdata/node/autogen-templates/ingress-1", }, { name: "test2 no autogenerated routes but allow pullrequests", @@ -53,8 +52,7 @@ func TestAutogeneratedIngressGeneration(t *testing.T) { EnvironmentType: "development", LagoonYAML: "internal/testdata/node/lagoon.autogen-1.yml", }, true), - templatePath: "testoutput", - want: "internal/testdata/node/autogen-templates/ingress-2", + want: "internal/testdata/node/autogen-templates/ingress-2", }, { name: "test3 autogenerated route but no pullrequests", @@ -71,9 +69,8 @@ func TestAutogeneratedIngressGeneration(t *testing.T) { EnvironmentType: "development", LagoonYAML: "internal/testdata/node/lagoon.autogen-2.yml", }, true), - templatePath: "testoutput", - emptyDir: true, - want: "", + emptyDir: true, + want: "", }, { name: "test4 autogenerated route no service in pattern", @@ -91,8 +88,7 @@ func TestAutogeneratedIngressGeneration(t *testing.T) { }, }, }, false), - templatePath: "testoutput", - want: "internal/testdata/node/autogen-templates/ingress-3", + want: "internal/testdata/node/autogen-templates/ingress-3", }, { name: "test5 autogenerated route short url", @@ -110,8 +106,7 @@ func TestAutogeneratedIngressGeneration(t *testing.T) { }, }, }, false), - templatePath: "testoutput", - want: "internal/testdata/node/autogen-templates/ingress-4", + want: "internal/testdata/node/autogen-templates/ingress-4", }, { name: "test6 autogenerated routes but disabled by service label", @@ -122,9 +117,8 @@ func TestAutogeneratedIngressGeneration(t *testing.T) { Branch: "main", LagoonYAML: "internal/testdata/node/lagoon.autogen-3.yml", }, true), - templatePath: "testoutput", - emptyDir: true, - want: "", + emptyDir: true, + want: "", }, { name: "test7 no autogenerated routes but enabled by service label", @@ -135,8 +129,7 @@ func TestAutogeneratedIngressGeneration(t *testing.T) { Branch: "main", LagoonYAML: "internal/testdata/node/lagoon.autogen-4.yml", }, true), - templatePath: "testoutput", - want: "internal/testdata/node/autogen-templates/ingress-5", + want: "internal/testdata/node/autogen-templates/ingress-5", }, { name: "test8 autogenerated routes with fastly", @@ -159,8 +152,7 @@ func TestAutogeneratedIngressGeneration(t *testing.T) { }, }, }, true), - templatePath: "testoutput", - want: "internal/testdata/node/autogen-templates/ingress-6", + want: "internal/testdata/node/autogen-templates/ingress-6", }, { name: "test9 autogenerated routes with fastly specific domain", @@ -183,8 +175,7 @@ func TestAutogeneratedIngressGeneration(t *testing.T) { }, }, }, true), - templatePath: "testoutput", - want: "internal/testdata/node/autogen-templates/ingress-7", + want: "internal/testdata/node/autogen-templates/ingress-7", }, { name: "test11 autogenerated route development environment", @@ -196,8 +187,7 @@ func TestAutogeneratedIngressGeneration(t *testing.T) { EnvironmentType: "development", LagoonYAML: "internal/testdata/node/lagoon.yml", }, true), - templatePath: "testoutput", - want: "internal/testdata/node/autogen-templates/ingress-9", + want: "internal/testdata/node/autogen-templates/ingress-9", }, { name: "test12 autogenerated route development environment - no insecure redirect", @@ -209,8 +199,7 @@ func TestAutogeneratedIngressGeneration(t *testing.T) { EnvironmentType: "development", LagoonYAML: "internal/testdata/node/lagoon.autogen-5.yml", }, true), - templatePath: "testoutput", - want: "internal/testdata/node/autogen-templates/ingress-10", + want: "internal/testdata/node/autogen-templates/ingress-10", }, { name: "test-development-service-type-override-a", @@ -232,10 +221,9 @@ func TestAutogeneratedIngressGeneration(t *testing.T) { }, }, }, true), - templatePath: "testoutput", - emptyDir: true, - want: "", - wantErr: true, + emptyDir: true, + want: "", + wantErr: true, }, { name: "test-development-service-type-override-b", @@ -257,8 +245,7 @@ func TestAutogeneratedIngressGeneration(t *testing.T) { }, }, }, true), - templatePath: "testoutput", - want: "internal/testdata/node/autogen-templates/test-development-service-type-override", + want: "internal/testdata/node/autogen-templates/test-development-service-type-override", }, { name: "test14 autogenerated route development no service type override", @@ -270,9 +257,8 @@ func TestAutogeneratedIngressGeneration(t *testing.T) { EnvironmentType: "development", LagoonYAML: "internal/testdata/node/lagoon.autogen-6.yml", }, true), - templatePath: "testoutput", - emptyDir: true, - want: "", + emptyDir: true, + want: "", }, { name: "test15 autogenerated route development service type override", @@ -284,8 +270,7 @@ func TestAutogeneratedIngressGeneration(t *testing.T) { EnvironmentType: "development", LagoonYAML: "internal/testdata/nginxphp/lagoon.yml", }, true), - templatePath: "testoutput", - want: "internal/testdata/nginxphp/autogen-templates/ingress-1", + want: "internal/testdata/nginxphp/autogen-templates/ingress-1", }, { name: "test16 autogenerated route development service name override", @@ -297,8 +282,7 @@ func TestAutogeneratedIngressGeneration(t *testing.T) { EnvironmentType: "development", LagoonYAML: "internal/testdata/nginxphp/lagoon.servicename.yml", }, true), - templatePath: "testoutput", - want: "internal/testdata/nginxphp/autogen-templates/ingress-2", + want: "internal/testdata/nginxphp/autogen-templates/ingress-2", }, { name: "test17 autogenerated route development service type override", @@ -317,8 +301,7 @@ func TestAutogeneratedIngressGeneration(t *testing.T) { }, }, }, false), - templatePath: "testoutput", - want: "internal/testdata/complex/autogen-templates/ingress-1", + want: "internal/testdata/complex/autogen-templates/ingress-1", }, { name: "test18 autogenerated route tls-acme disabled", @@ -330,8 +313,7 @@ func TestAutogeneratedIngressGeneration(t *testing.T) { EnvironmentType: "production", LagoonYAML: "internal/testdata/node/lagoon.autogen-7.yml", }, true), - templatePath: "testoutput", - want: "internal/testdata/node/autogen-templates/ingress-12", + want: "internal/testdata/node/autogen-templates/ingress-12", }, { name: "test19 autogenerated routes but tls-acme disabled by service label", @@ -343,8 +325,7 @@ func TestAutogeneratedIngressGeneration(t *testing.T) { EnvironmentType: "production", LagoonYAML: "internal/testdata/node/lagoon.autogen-8.yml", }, true), - templatePath: "testoutput", - want: "internal/testdata/node/autogen-templates/ingress-13", + want: "internal/testdata/node/autogen-templates/ingress-13", }, { name: "test20 autogenerated routes where lagoon.name of service does not match service names", @@ -363,8 +344,7 @@ func TestAutogeneratedIngressGeneration(t *testing.T) { }, }, }, false), - templatePath: "testoutput", - want: "internal/testdata/complex/autogen-templates/ingress-2", + want: "internal/testdata/complex/autogen-templates/ingress-2", }, { name: "test21 autogenerated routes where docker-compose env_file has missing file references", @@ -383,8 +363,7 @@ func TestAutogeneratedIngressGeneration(t *testing.T) { }, }, }, false), - templatePath: "testoutput", - want: "internal/testdata/complex/autogen-templates/ingress-3", + want: "internal/testdata/complex/autogen-templates/ingress-3", }, { name: "test22 autogenerated routes where should truncate long dns", @@ -408,8 +387,7 @@ func TestAutogeneratedIngressGeneration(t *testing.T) { }, }, }, false), - templatePath: "testoutput", - want: "internal/testdata/nginxphp/autogen-templates/ingress-3", + want: "internal/testdata/nginxphp/autogen-templates/ingress-3", }, { name: "test23 autogenerated routes with fastly service, should be no fastly annotations on autogenerated route", @@ -427,8 +405,7 @@ func TestAutogeneratedIngressGeneration(t *testing.T) { }, }, }, true), - templatePath: "testoutput", - want: "internal/testdata/node/autogen-templates/ingress-14", + want: "internal/testdata/node/autogen-templates/ingress-14", }, { name: "test24 autogenerated routes with 'string true enabled' with fastly service, should be no fastly annotations on autogenerated route", @@ -446,8 +423,7 @@ func TestAutogeneratedIngressGeneration(t *testing.T) { }, }, }, true), - templatePath: "testoutput", - want: "internal/testdata/node/autogen-templates/ingress-14", + want: "internal/testdata/node/autogen-templates/ingress-14", }, { name: "test25 autogenerated routes enabled globally but disabled by environment", @@ -465,9 +441,8 @@ func TestAutogeneratedIngressGeneration(t *testing.T) { }, }, }, true), - templatePath: "testoutput", - emptyDir: true, - want: "", + emptyDir: true, + want: "", }, { name: "test26 polysite autogenerated routes enabled globally but disabled by environment", @@ -485,9 +460,8 @@ func TestAutogeneratedIngressGeneration(t *testing.T) { }, }, }, true), - templatePath: "testoutput", - emptyDir: true, - want: "", + emptyDir: true, + want: "", }, { name: "test27 autogenerated routes longbranch", @@ -498,8 +472,7 @@ func TestAutogeneratedIngressGeneration(t *testing.T) { Branch: "feature/skycms-10626-update-permissions-by-term", LagoonYAML: "internal/testdata/basic/lagoon.nginx.yml", }, true), - templatePath: "testoutput", - want: "internal/testdata/basic/autogen-templates/ingress-1", + want: "internal/testdata/basic/autogen-templates/ingress-1", }, { name: "test28 autogenerated route unidler request verification disable", @@ -510,8 +483,7 @@ func TestAutogeneratedIngressGeneration(t *testing.T) { Branch: "main", LagoonYAML: "internal/testdata/node/lagoon.unidler.yml", }, true), - templatePath: "testdata/output", - want: "internal/testdata/node/autogen-templates/ingress-15", + want: "internal/testdata/node/autogen-templates/ingress-15", }, { name: "test29-autogenerated-pathroutes", @@ -522,8 +494,7 @@ func TestAutogeneratedIngressGeneration(t *testing.T) { Branch: "main", LagoonYAML: "internal/testdata/basic/lagoon.pathroutes.yml", }, true), - templatePath: "testdata/output", - want: "internal/testdata/basic/autogen-templates/test29-autogenerated-pathroutes", + want: "internal/testdata/basic/autogen-templates/test29-autogenerated-pathroutes", }, { name: "test29b-autogenerated-pathroutes", @@ -535,8 +506,7 @@ func TestAutogeneratedIngressGeneration(t *testing.T) { Branch: "main", LagoonYAML: "internal/testdata/basic/lagoon.pathroutes-2.yml", }, true), - templatePath: "testdata/output", - want: "internal/testdata/basic/autogen-templates/test29-autogenerated-pathroutes", + want: "internal/testdata/basic/autogen-templates/test29-autogenerated-pathroutes", }, { name: "test29c-autogenerated-pathroutes-compose-ports", @@ -548,25 +518,21 @@ func TestAutogeneratedIngressGeneration(t *testing.T) { Branch: "main", LagoonYAML: "internal/testdata/basic/lagoon.pathroutes-3.yml", }, true), - templatePath: "testdata/output", - want: "internal/testdata/basic/autogen-templates/test29-autogenerated-pathroutes", + want: "internal/testdata/basic/autogen-templates/test29-autogenerated-pathroutes", }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { helpers.UnsetEnvVars(nil) //unset variables before running tests // set the environment variables from args - savedTemplates := tt.templatePath - generator, err := testdata.SetupEnvironment(*rootCmd, savedTemplates, tt.args) + savedTemplates, err := os.MkdirTemp("", "testoutput") if err != nil { t.Errorf("%v", err) } - - err = os.MkdirAll(savedTemplates, 0755) + generator, err := testdata.SetupEnvironment(generator.GeneratorInput{}, savedTemplates, tt.args) if err != nil { - t.Errorf("couldn't create directory %v: %v", savedTemplates, err) + t.Errorf("%v", err) } - defer os.RemoveAll(savedTemplates) if err := AutogeneratedIngressGeneration(generator); (err != nil) != tt.wantErr { diff --git a/cmd/template_backups.go b/cmd/template_backups.go index 264e1917..e4bf2461 100644 --- a/cmd/template_backups.go +++ b/cmd/template_backups.go @@ -24,7 +24,7 @@ var backupGeneration = &cobra.Command{ if err != nil { return fmt.Errorf("error reading domain flag: %v", err) } - generator, err := generator.GenerateInput(*rootCmd, true) + generator, err := GenerateInput(*rootCmd, true) if err != nil { return err } diff --git a/cmd/template_backups_test.go b/cmd/template_backups_test.go index bf834780..22087e04 100644 --- a/cmd/template_backups_test.go +++ b/cmd/template_backups_test.go @@ -8,6 +8,7 @@ import ( "github.com/andreyvit/diff" "github.com/uselagoon/build-deploy-tool/internal/dbaasclient" + "github.com/uselagoon/build-deploy-tool/internal/generator" "github.com/uselagoon/build-deploy-tool/internal/helpers" "github.com/uselagoon/build-deploy-tool/internal/lagoon" "github.com/uselagoon/build-deploy-tool/internal/testdata" @@ -18,13 +19,12 @@ import ( func TestBackupTemplateGeneration(t *testing.T) { tests := []struct { - name string - description string - args testdata.TestData - templatePath string - want string - emptyDir bool // if no templates are generated, then there will be a .gitkeep file in there - wantErr bool + name string + description string + args testdata.TestData + want string + emptyDir bool // if no templates are generated, then there will be a .gitkeep file in there + wantErr bool }{ { name: "test1 - change the image registry used for prebackup pods", @@ -42,8 +42,7 @@ func TestBackupTemplateGeneration(t *testing.T) { }, }, }, true), - templatePath: "testoutput", - want: "internal/testdata/complex/backup-templates/backup-1", + want: "internal/testdata/complex/backup-templates/backup-1", }, { name: "test2 - custom dev only schedule but global config change enabled", @@ -67,8 +66,7 @@ func TestBackupTemplateGeneration(t *testing.T) { }, }, }, true), - templatePath: "testoutput", - want: "internal/testdata/node/backup-templates/backup-1", + want: "internal/testdata/node/backup-templates/backup-1", }, { name: "test3 - custom dev only schedule but global config change not configured (use defaults)", @@ -87,8 +85,7 @@ func TestBackupTemplateGeneration(t *testing.T) { }, }, }, true), - templatePath: "testoutput", - want: "internal/testdata/node/backup-templates/backup-2", + want: "internal/testdata/node/backup-templates/backup-2", }, { name: "test4 - custom schedule and custom backup keys", @@ -117,8 +114,7 @@ func TestBackupTemplateGeneration(t *testing.T) { {Name: "LAGOON_BACKUP_PR_SCHEDULE", Value: "3,33 12 * * *", Scope: "build"}, }, }, true), - templatePath: "testoutput", - want: "internal/testdata/node/backup-templates/backup-3", + want: "internal/testdata/node/backup-templates/backup-3", }, { name: "test5 - custom schedule and custom restore keys", @@ -147,8 +143,7 @@ func TestBackupTemplateGeneration(t *testing.T) { {Name: "LAGOON_BACKUP_PR_SCHEDULE", Value: "3,33 12 * * *", Scope: "build"}, }, }, true), - templatePath: "testoutput", - want: "internal/testdata/node/backup-templates/backup-4", + want: "internal/testdata/node/backup-templates/backup-4", }, { name: "test6 - generic backup", @@ -160,8 +155,7 @@ func TestBackupTemplateGeneration(t *testing.T) { EnvironmentType: "production", LagoonYAML: "internal/testdata/node/lagoon.yml", }, true), - templatePath: "testoutput", - want: "internal/testdata/node/backup-templates/backup-5", + want: "internal/testdata/node/backup-templates/backup-5", }, { name: "test7 - changed default backup schedule", @@ -174,8 +168,7 @@ func TestBackupTemplateGeneration(t *testing.T) { DefaultBackupSchedule: "M */6 * * *", LagoonYAML: "internal/testdata/node/lagoon.yml", }, true), - templatePath: "testoutput", - want: "internal/testdata/node/backup-templates/backup-6", + want: "internal/testdata/node/backup-templates/backup-6", }, { name: "test8 - change the image registry used for prebackup pods k8upv2", @@ -199,8 +192,7 @@ func TestBackupTemplateGeneration(t *testing.T) { }, }, }, true), - templatePath: "testoutput", - want: "internal/testdata/complex/backup-templates/backup-2", + want: "internal/testdata/complex/backup-templates/backup-2", }, { name: "test9 - nothing to backup so no schedule", @@ -224,9 +216,8 @@ func TestBackupTemplateGeneration(t *testing.T) { }, }, }, true), - templatePath: "testdata/output", - emptyDir: true, - want: "internal/testdata/node/backup-templates/backup-7", + emptyDir: true, + want: "internal/testdata/node/backup-templates/backup-7", }, { name: "test10 - generic backup with random check prune feature flags", args: testdata.GetSeedData( @@ -249,8 +240,7 @@ func TestBackupTemplateGeneration(t *testing.T) { }, }, }, true), - templatePath: "testdata/output", - want: "internal/testdata/node/backup-templates/backup-8", + want: "internal/testdata/node/backup-templates/backup-8", }, { name: "test11 - custom prod schedule", @@ -270,8 +260,7 @@ func TestBackupTemplateGeneration(t *testing.T) { {Name: "LAGOON_BACKUP_PROD_SCHEDULE", Value: "2,21 22 * * *", Scope: "build"}, }, }, true), - templatePath: "testoutput", - want: "internal/testdata/node/backup-templates/backup-9", + want: "internal/testdata/node/backup-templates/backup-9", }, { name: "test-generic-backup-rootless-workloads", @@ -297,8 +286,7 @@ func TestBackupTemplateGeneration(t *testing.T) { }, }, }, true), - templatePath: "testoutput", - want: "internal/testdata/node/backup-templates/test-generic-backup-rootless-workloads", + want: "internal/testdata/node/backup-templates/test-generic-backup-rootless-workloads", }, { name: "test-generic-backup-rootless-workloads-onrootmismatch", @@ -329,8 +317,7 @@ func TestBackupTemplateGeneration(t *testing.T) { }, }, }, true), - templatePath: "testoutput", - want: "internal/testdata/node/backup-templates/test-generic-backup-rootless-workloads-onrootmismatch", + want: "internal/testdata/node/backup-templates/test-generic-backup-rootless-workloads-onrootmismatch", }, { name: "schedules-with-additional-volumes", @@ -348,8 +335,7 @@ func TestBackupTemplateGeneration(t *testing.T) { }, }, }, true), - templatePath: "testoutput", - want: "internal/testdata/basic/backup-templates/schedules-with-additional-volumes", + want: "internal/testdata/basic/backup-templates/schedules-with-additional-volumes", }, { name: "no-schedules-with-additional-volumes-with-no-backups", @@ -367,23 +353,21 @@ func TestBackupTemplateGeneration(t *testing.T) { }, }, }, true), - templatePath: "testoutput", - emptyDir: true, - want: "internal/testdata/basic/backup-templates/schedules-with-additional-volumes-no-backup", + emptyDir: true, + want: "internal/testdata/basic/backup-templates/schedules-with-additional-volumes-no-backup", }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { helpers.UnsetEnvVars(nil) //unset variables before running tests // set the environment variables from args - savedTemplates := tt.templatePath - generator, err := testdata.SetupEnvironment(*rootCmd, savedTemplates, tt.args) + savedTemplates, err := os.MkdirTemp("", "testoutput") if err != nil { t.Errorf("%v", err) } - err = os.MkdirAll(savedTemplates, 0755) + generator, err := testdata.SetupEnvironment(generator.GeneratorInput{}, savedTemplates, tt.args) if err != nil { - t.Errorf("couldn't create directory %v: %v", savedTemplates, err) + t.Errorf("%v", err) } defer os.RemoveAll(savedTemplates) diff --git a/cmd/template_dbaas.go b/cmd/template_dbaas.go index 9b34a2da..29e4170e 100644 --- a/cmd/template_dbaas.go +++ b/cmd/template_dbaas.go @@ -14,7 +14,7 @@ var dbaasGeneration = &cobra.Command{ Aliases: []string{"db"}, Short: "Generate the DBaaS templates for a Lagoon build", RunE: func(cmd *cobra.Command, args []string) error { - generator, err := generator.GenerateInput(*rootCmd, true) + generator, err := GenerateInput(*rootCmd, true) if err != nil { return err } diff --git a/cmd/template_dbaas_test.go b/cmd/template_dbaas_test.go index aa8bbc37..f11814b5 100644 --- a/cmd/template_dbaas_test.go +++ b/cmd/template_dbaas_test.go @@ -9,6 +9,7 @@ import ( "github.com/andreyvit/diff" "github.com/uselagoon/build-deploy-tool/internal/dbaasclient" + "github.com/uselagoon/build-deploy-tool/internal/generator" "github.com/uselagoon/build-deploy-tool/internal/helpers" "github.com/uselagoon/build-deploy-tool/internal/lagoon" "github.com/uselagoon/build-deploy-tool/internal/testdata" @@ -19,12 +20,11 @@ import ( func TestDBaaSTemplateGeneration(t *testing.T) { tests := []struct { - name string - args testdata.TestData - templatePath string - want string - emptyDir bool // if no templates are generated, then there will be a .gitkeep file in there - wantErr bool + name string + args testdata.TestData + want string + emptyDir bool // if no templates are generated, then there will be a .gitkeep file in there + wantErr bool }{ { name: "test1 - mariadb-dbaas", @@ -35,8 +35,7 @@ func TestDBaaSTemplateGeneration(t *testing.T) { Branch: "main", LagoonYAML: "internal/testdata/complex/lagoon.yml", }, true), - templatePath: "testoutput", - want: "internal/testdata/complex/dbaas-templates/dbaas-1", + want: "internal/testdata/complex/dbaas-templates/dbaas-1", }, { name: "test2 - mariadb-single to mariadb-dbaas (using mariadb-shared to mariadb-dbaas conversion)", @@ -50,8 +49,7 @@ func TestDBaaSTemplateGeneration(t *testing.T) { {Name: "LAGOON_SERVICE_TYPES", Value: "mariadb:mariadb-shared", Scope: "build"}, }, }, true), - templatePath: "testdata/output", - want: "internal/testdata/complex/dbaas-templates/dbaas-2", + want: "internal/testdata/complex/dbaas-templates/dbaas-2", }, { name: "test3 - multiple mariadb", @@ -62,8 +60,7 @@ func TestDBaaSTemplateGeneration(t *testing.T) { Branch: "main", LagoonYAML: "internal/testdata/complex/lagoon.multidb.yml", }, true), - templatePath: "testdata/output", - want: "internal/testdata/complex/dbaas-templates/dbaas-3", + want: "internal/testdata/complex/dbaas-templates/dbaas-3", }, { name: "test4 - mongo", @@ -74,8 +71,7 @@ func TestDBaaSTemplateGeneration(t *testing.T) { Branch: "main", LagoonYAML: "internal/testdata/node/lagoon.mongo.yml", }, true), - templatePath: "testdata/output", - want: "internal/testdata/node/dbaas-templates/dbaas-1", + want: "internal/testdata/node/dbaas-templates/dbaas-1", }, { name: "test5 - mongo override (the mongo should not generate because it has a mongodb-single override)", @@ -89,8 +85,7 @@ func TestDBaaSTemplateGeneration(t *testing.T) { {Name: "LAGOON_SERVICE_TYPES", Value: "mongo:mongodb-single", Scope: "build"}, }, }, true), - templatePath: "testdata/output", - want: "internal/testdata/node/dbaas-templates/dbaas-2", + want: "internal/testdata/node/dbaas-templates/dbaas-2", }, { name: "test6 - postgres", @@ -104,8 +99,7 @@ func TestDBaaSTemplateGeneration(t *testing.T) { {Name: "LAGOON_DBAAS_ENVIRONMENT_TYPES", Value: "postgres-15:production-postgres,mongo-4:production-mongo", Scope: "build"}, }, }, true), - templatePath: "testdata/output", - want: "internal/testdata/complex/dbaas-templates/dbaas-4", + want: "internal/testdata/complex/dbaas-templates/dbaas-4", }, { name: "test7 - basic - no dbaas", @@ -116,23 +110,21 @@ func TestDBaaSTemplateGeneration(t *testing.T) { Branch: "main", LagoonYAML: "internal/testdata/basic/lagoon.yml", }, true), - templatePath: "testdata/output", - emptyDir: true, - want: "internal/testdata/basic/dbaas-templates/dbaas-1", + emptyDir: true, + want: "internal/testdata/basic/dbaas-templates/dbaas-1", }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { helpers.UnsetEnvVars(nil) //unset variables before running tests // set the environment variables from args - savedTemplates := tt.templatePath - generator, err := testdata.SetupEnvironment(*rootCmd, savedTemplates, tt.args) + savedTemplates, err := os.MkdirTemp("", "testoutput") if err != nil { t.Errorf("%v", err) } - err = os.MkdirAll(savedTemplates, 0755) + generator, err := testdata.SetupEnvironment(generator.GeneratorInput{}, savedTemplates, tt.args) if err != nil { - t.Errorf("couldn't create directory %v: %v", savedTemplates, err) + t.Errorf("%v", err) } defer os.RemoveAll(savedTemplates) @@ -142,7 +134,6 @@ func TestDBaaSTemplateGeneration(t *testing.T) { if err != nil { t.Errorf("%v", err) } - defer os.RemoveAll(savedTemplates) if err := DBaaSTemplateGeneration(generator); (err != nil) != tt.wantErr { t.Errorf("DBaaSTemplateGeneration() error = %v, wantErr %v", err, tt.wantErr) diff --git a/cmd/template_ingress.go b/cmd/template_ingress.go index 311cf09c..12988a31 100644 --- a/cmd/template_ingress.go +++ b/cmd/template_ingress.go @@ -14,7 +14,7 @@ var routeGeneration = &cobra.Command{ Aliases: []string{"i"}, Short: "Generate the ingress templates for a Lagoon build", RunE: func(cmd *cobra.Command, args []string) error { - generator, err := generator.GenerateInput(*rootCmd, true) + generator, err := GenerateInput(*rootCmd, true) if err != nil { return err } diff --git a/cmd/template_ingress_test.go b/cmd/template_ingress_test.go index 7d9864cf..1d9b58c6 100644 --- a/cmd/template_ingress_test.go +++ b/cmd/template_ingress_test.go @@ -9,6 +9,7 @@ import ( "testing" "github.com/andreyvit/diff" + "github.com/uselagoon/build-deploy-tool/internal/generator" "github.com/uselagoon/build-deploy-tool/internal/helpers" "github.com/uselagoon/build-deploy-tool/internal/lagoon" "github.com/uselagoon/build-deploy-tool/internal/testdata" @@ -19,12 +20,11 @@ import ( func TestTemplateRoutes(t *testing.T) { tests := []struct { - name string - args testdata.TestData - templatePath string - want string - wantErr bool - wantErrMsg string + name string + args testdata.TestData + want string + wantErr bool + wantErrMsg string }{ { name: "test2 check LAGOON_FASTLY_SERVICE_IDS no secret and no values", @@ -42,8 +42,7 @@ func TestTemplateRoutes(t *testing.T) { }, }, }, true), - templatePath: "testoutput", - want: "internal/testdata/node/ingress-templates/ingress-2", + want: "internal/testdata/node/ingress-templates/ingress-2", }, { name: "test3 check LAGOON_FASTLY_SERVICE_ID no secret and no values", @@ -61,8 +60,7 @@ func TestTemplateRoutes(t *testing.T) { }, }, }, true), - templatePath: "testoutput", - want: "internal/testdata/node/ingress-templates/ingress-3", + want: "internal/testdata/node/ingress-templates/ingress-3", }, { name: "test4 check no fastly and no values", @@ -73,8 +71,7 @@ func TestTemplateRoutes(t *testing.T) { Branch: "main", LagoonYAML: "internal/testdata/node/lagoon.yml", }, true), - templatePath: "testoutput", - want: "internal/testdata/node/ingress-templates/ingress-4", + want: "internal/testdata/node/ingress-templates/ingress-4", }, { name: "test5 multiproject1 no values", @@ -85,8 +82,7 @@ func TestTemplateRoutes(t *testing.T) { Branch: "multiproject", LagoonYAML: "internal/testdata/node/lagoon.polysite.yml", }, true), - templatePath: "testoutput", - want: "internal/testdata/node/ingress-templates/ingress-5", + want: "internal/testdata/node/ingress-templates/ingress-5", }, { name: "test6 multiproject2 no values", @@ -97,8 +93,7 @@ func TestTemplateRoutes(t *testing.T) { Branch: "multiproject", LagoonYAML: "internal/testdata/node/lagoon.polysite.yml", }, true), - templatePath: "testoutput", - want: "internal/testdata/node/ingress-templates/ingress-6", + want: "internal/testdata/node/ingress-templates/ingress-6", }, { name: "test7 multidomain no values", @@ -109,8 +104,7 @@ func TestTemplateRoutes(t *testing.T) { Branch: "tworoutes", LagoonYAML: "internal/testdata/node/lagoon.yml", }, true), - templatePath: "testoutput", - want: "internal/testdata/node/ingress-templates/ingress-7", + want: "internal/testdata/node/ingress-templates/ingress-7", }, { name: "test8 multidomain no values", @@ -121,8 +115,7 @@ func TestTemplateRoutes(t *testing.T) { Branch: "branch/routes", LagoonYAML: "internal/testdata/node/lagoon.yml", }, true), - templatePath: "testoutput", - want: "internal/testdata/node/ingress-templates/ingress-8", + want: "internal/testdata/node/ingress-templates/ingress-8", }, { name: "test9 active no values", @@ -135,8 +128,7 @@ func TestTemplateRoutes(t *testing.T) { StandbyEnvironment: "main-sb", LagoonYAML: "internal/testdata/node/lagoon.activestandby.yml", }, true), - templatePath: "testoutput", - want: "internal/testdata/node/ingress-templates/ingress-9", + want: "internal/testdata/node/ingress-templates/ingress-9", }, { name: "test10 standby no values", @@ -149,8 +141,7 @@ func TestTemplateRoutes(t *testing.T) { StandbyEnvironment: "main-sb", LagoonYAML: "internal/testdata/node/lagoon.activestandby.yml", }, true), - templatePath: "testoutput", - want: "internal/testdata/node/ingress-templates/ingress-10", + want: "internal/testdata/node/ingress-templates/ingress-10", }, { name: "test11 standby no values", @@ -161,8 +152,7 @@ func TestTemplateRoutes(t *testing.T) { Branch: "production", LagoonYAML: "internal/testdata/complex/lagoon.yml", }, true), - templatePath: "testoutput", - want: "internal/testdata/complex/ingress-templates/ingress-1", + want: "internal/testdata/complex/ingress-templates/ingress-1", }, { name: "test12 check LAGOON_ROUTES_JSON generates ingress", @@ -185,8 +175,7 @@ func TestTemplateRoutes(t *testing.T) { }, }, }, true), - templatePath: "testoutput", - want: "internal/testdata/node/ingress-templates/ingress-11", + want: "internal/testdata/node/ingress-templates/ingress-11", }, { name: "test13 ingress class from default flag", @@ -198,8 +187,7 @@ func TestTemplateRoutes(t *testing.T) { IngressClass: "nginx", LagoonYAML: "internal/testdata/node/lagoon.yml", }, true), - templatePath: "testoutput", - want: "internal/testdata/node/ingress-templates/ingress-12", + want: "internal/testdata/node/ingress-templates/ingress-12", }, { name: "test14 ingress class from lagoon.yml should overwrite default and featureflag variable", @@ -210,7 +198,7 @@ func TestTemplateRoutes(t *testing.T) { Branch: "ingressclass", IngressClass: "nginx", LagoonYAML: "internal/testdata/node/lagoon.yml", - }, true), templatePath: "testoutput", + }, true), want: "internal/testdata/node/ingress-templates/ingress-13", }, { @@ -230,8 +218,7 @@ func TestTemplateRoutes(t *testing.T) { }, }, }, true), - templatePath: "testoutput", - want: "internal/testdata/node/ingress-templates/ingress-14", + want: "internal/testdata/node/ingress-templates/ingress-14", }, { name: "test15b ingress class from lagoon api environment scope", @@ -256,8 +243,7 @@ func TestTemplateRoutes(t *testing.T) { }, }, }, true), - templatePath: "testoutput", - want: "internal/testdata/node/ingress-templates/ingress-15", + want: "internal/testdata/node/ingress-templates/ingress-15", }, { name: "test16 hsts basic", @@ -275,8 +261,7 @@ func TestTemplateRoutes(t *testing.T) { }, }, }, true), - templatePath: "testoutput", - want: "internal/testdata/node/ingress-templates/ingress-16", + want: "internal/testdata/node/ingress-templates/ingress-16", }, { name: "test17 hsts advanced", @@ -294,8 +279,7 @@ func TestTemplateRoutes(t *testing.T) { }, }, }, true), - templatePath: "testoutput", - want: "internal/testdata/node/ingress-templates/ingress-17", + want: "internal/testdata/node/ingress-templates/ingress-17", }, { name: "test18 check first route has monitoring only", @@ -306,8 +290,7 @@ func TestTemplateRoutes(t *testing.T) { Branch: "tworoutes", LagoonYAML: "internal/testdata/node/lagoon.yml", }, true), - templatePath: "testoutput", - want: "internal/testdata/node/ingress-templates/ingress-18", + want: "internal/testdata/node/ingress-templates/ingress-18", }, { name: "test19 pullrequest routes", @@ -324,8 +307,7 @@ func TestTemplateRoutes(t *testing.T) { EnvironmentType: "development", LagoonYAML: "internal/testdata/node/lagoon.yml", }, true), - templatePath: "testoutput", - want: "internal/testdata/node/ingress-templates/ingress-19", + want: "internal/testdata/node/ingress-templates/ingress-19", }, { name: "test20 pullrequest routes polysite", @@ -342,8 +324,7 @@ func TestTemplateRoutes(t *testing.T) { EnvironmentType: "development", LagoonYAML: "internal/testdata/node/lagoon.polysite-pr.yml", }, true), - templatePath: "testoutput", - want: "internal/testdata/node/ingress-templates/ingress-20", + want: "internal/testdata/node/ingress-templates/ingress-20", }, { name: "test21 alternative names", @@ -354,8 +335,7 @@ func TestTemplateRoutes(t *testing.T) { Branch: "alternativename", LagoonYAML: "internal/testdata/node/lagoon.yml", }, true), - templatePath: "testoutput", - want: "internal/testdata/node/ingress-templates/ingress-21", + want: "internal/testdata/node/ingress-templates/ingress-21", }, { name: "test22 check wildcard", @@ -366,8 +346,7 @@ func TestTemplateRoutes(t *testing.T) { Branch: "wildcard", LagoonYAML: "internal/testdata/node/lagoon.yml", }, true), - templatePath: "testoutput", - want: "internal/testdata/node/ingress-templates/ingress-22", + want: "internal/testdata/node/ingress-templates/ingress-22", }, { name: "test23 exceed route quota", @@ -385,9 +364,8 @@ func TestTemplateRoutes(t *testing.T) { }, }, }, true), - templatePath: "testdata/output", - wantErr: true, - wantErrMsg: "this environment requests 2 custom routes, this would exceed the route quota of 1", + wantErr: true, + wantErrMsg: "this environment requests 2 custom routes, this would exceed the route quota of 1", }, { name: "test24 unidler request verification disable", @@ -398,8 +376,7 @@ func TestTemplateRoutes(t *testing.T) { Branch: "main", LagoonYAML: "internal/testdata/node/lagoon.unidler.yml", }, true), - templatePath: "testdata/output", - want: "internal/testdata/node/ingress-templates/ingress-23", + want: "internal/testdata/node/ingress-templates/ingress-23", }, { name: "test25-pathroutes", @@ -410,8 +387,7 @@ func TestTemplateRoutes(t *testing.T) { Branch: "main", LagoonYAML: "internal/testdata/basic/lagoon.pathroutes.yml", }, true), - templatePath: "testdata/output", - want: "internal/testdata/basic/ingress-templates/test25-pathroutes", + want: "internal/testdata/basic/ingress-templates/test25-pathroutes", }, { name: "test25 check wildcard LAGOON_ROUTES_JSON", @@ -429,25 +405,21 @@ func TestTemplateRoutes(t *testing.T) { }, }, }, true), - templatePath: "testoutput", - want: "internal/testdata/node/ingress-templates/ingress-24", + want: "internal/testdata/node/ingress-templates/ingress-24", }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { helpers.UnsetEnvVars(nil) //unset variables before running tests // set the environment variables from args - savedTemplates := tt.templatePath - generator, err := testdata.SetupEnvironment(*rootCmd, savedTemplates, tt.args) + savedTemplates, err := os.MkdirTemp("", "testoutput") if err != nil { t.Errorf("%v", err) } - - err = os.MkdirAll(savedTemplates, 0755) + generator, err := testdata.SetupEnvironment(generator.GeneratorInput{}, savedTemplates, tt.args) if err != nil { - t.Errorf("couldn't create directory %v: %v", savedTemplates, err) + t.Errorf("%v", err) } - defer os.RemoveAll(savedTemplates) if err := IngressTemplateGeneration(generator); (err != nil) != tt.wantErr { diff --git a/cmd/template_lagoonenv.go b/cmd/template_lagoonenv.go index c4de96e8..86198da9 100644 --- a/cmd/template_lagoonenv.go +++ b/cmd/template_lagoonenv.go @@ -19,7 +19,7 @@ var lagoonEnvGeneration = &cobra.Command{ Aliases: []string{"le"}, Short: "Generate the lagoon-env secret template for a Lagoon build", RunE: func(cmd *cobra.Command, args []string) error { - generator, err := generator.GenerateInput(*rootCmd, false) + generator, err := GenerateInput(*rootCmd, false) if err != nil { return err } diff --git a/cmd/template_lagoonenv_test.go b/cmd/template_lagoonenv_test.go index 841d1401..8d503b93 100644 --- a/cmd/template_lagoonenv_test.go +++ b/cmd/template_lagoonenv_test.go @@ -8,6 +8,7 @@ import ( "github.com/andreyvit/diff" "github.com/uselagoon/build-deploy-tool/internal/dbaasclient" + "github.com/uselagoon/build-deploy-tool/internal/generator" "github.com/uselagoon/build-deploy-tool/internal/helpers" "github.com/uselagoon/build-deploy-tool/internal/lagoon" "github.com/uselagoon/build-deploy-tool/internal/testdata" @@ -20,7 +21,6 @@ func TestLagoonEnvTemplateGeneration(t *testing.T) { secretName string args testdata.TestData configMapVars map[string]string - templatePath string want string dbaasCreds string vars []helpers.EnvironmentVariable @@ -79,9 +79,8 @@ func TestLagoonEnvTemplateGeneration(t *testing.T) { }, }, }, true), - templatePath: "testoutput", - secretName: "lagoon-env", - want: "internal/testdata/basic/secret-templates/test-basic-deployment-lagoon-env", + secretName: "lagoon-env", + want: "internal/testdata/basic/secret-templates/test-basic-deployment-lagoon-env", }, { name: "test-basic-deployment-mariadbcreds-lagoon-env", @@ -137,10 +136,9 @@ func TestLagoonEnvTemplateGeneration(t *testing.T) { }, }, }, true), - dbaasCreds: "internal/testdata/basic/basic-mariadb-creds.json", - templatePath: "testoutput", - secretName: "lagoon-env", - want: "internal/testdata/basic/secret-templates/test-basic-deployment-mariadbcreds-lagoon-env", + dbaasCreds: "internal/testdata/basic/basic-mariadb-creds.json", + secretName: "lagoon-env", + want: "internal/testdata/basic/secret-templates/test-basic-deployment-mariadbcreds-lagoon-env", }, { name: "lagoon-env-with-configmap-vars", @@ -203,9 +201,8 @@ func TestLagoonEnvTemplateGeneration(t *testing.T) { "MY_SPECIAL_VARIABLE3": "myspecialvariable3", "MY_SPECIAL_VARIABLE4": "myspecialvariable4", }, - templatePath: "testoutput", - secretName: "lagoon-env", - want: "internal/testdata/basic/secret-templates/lagoon-env-with-configmap-vars", + secretName: "lagoon-env", + want: "internal/testdata/basic/secret-templates/lagoon-env-with-configmap-vars", }, { name: "lagoon-platform-env-with-configmap-vars", @@ -269,9 +266,8 @@ func TestLagoonEnvTemplateGeneration(t *testing.T) { "MY_SPECIAL_VARIABLE3": "myspecialvariable3", "MY_SPECIAL_VARIABLE4": "myspecialvariable4", }, - templatePath: "testoutput", - secretName: "lagoon-platform-env", - want: "internal/testdata/basic/secret-templates/lagoon-platform-env-with-configmap-vars", + secretName: "lagoon-platform-env", + want: "internal/testdata/basic/secret-templates/lagoon-platform-env-with-configmap-vars", }, } for _, tt := range tests { @@ -284,17 +280,14 @@ func TestLagoonEnvTemplateGeneration(t *testing.T) { } } // set the environment variables from args - savedTemplates := tt.templatePath - generator, err := testdata.SetupEnvironment(*rootCmd, savedTemplates, tt.args) + savedTemplates, err := os.MkdirTemp("", "testoutput") if err != nil { t.Errorf("%v", err) } - - err = os.MkdirAll(savedTemplates, 0755) + generator, err := testdata.SetupEnvironment(generator.GeneratorInput{}, savedTemplates, tt.args) if err != nil { - t.Errorf("couldn't create directory %v: %v", savedTemplates, err) + t.Errorf("%v", err) } - defer os.RemoveAll(savedTemplates) ts := dbaasclient.TestDBaaSHTTPServer() diff --git a/cmd/template_lagoonservices.go b/cmd/template_lagoonservices.go index a4e00b81..ca0e6d34 100644 --- a/cmd/template_lagoonservices.go +++ b/cmd/template_lagoonservices.go @@ -20,7 +20,7 @@ var lagoonServiceGeneration = &cobra.Command{ Aliases: []string{"ls"}, Short: "Generate the lagoon service templates for a Lagoon build", RunE: func(cmd *cobra.Command, args []string) error { - gen, err := generator.GenerateInput(*rootCmd, true) + gen, err := GenerateInput(*rootCmd, true) if err != nil { return err } diff --git a/cmd/template_lagoonservices_test.go b/cmd/template_lagoonservices_test.go index 482a7a39..179932d8 100644 --- a/cmd/template_lagoonservices_test.go +++ b/cmd/template_lagoonservices_test.go @@ -8,6 +8,7 @@ import ( "github.com/andreyvit/diff" "github.com/uselagoon/build-deploy-tool/internal/dbaasclient" + "github.com/uselagoon/build-deploy-tool/internal/generator" "github.com/uselagoon/build-deploy-tool/internal/helpers" "github.com/uselagoon/build-deploy-tool/internal/lagoon" "github.com/uselagoon/build-deploy-tool/internal/testdata" @@ -18,13 +19,12 @@ import ( func TestTemplateLagoonServices(t *testing.T) { tests := []struct { - name string - description string - args testdata.TestData - templatePath string - want string - imageData string - vars []helpers.EnvironmentVariable + name string + description string + args testdata.TestData + want string + imageData string + vars []helpers.EnvironmentVariable }{ { name: "test1-basic-deployment", @@ -66,8 +66,7 @@ func TestTemplateLagoonServices(t *testing.T) { }, }, }, true), - templatePath: "testoutput", - want: "internal/testdata/basic/service-templates/test1-basic-deployment", + want: "internal/testdata/basic/service-templates/test1-basic-deployment", }, { name: "test2-nginx-php", @@ -86,8 +85,7 @@ func TestTemplateLagoonServices(t *testing.T) { "varnish": "harbor.example/example-project/main/varnish@sha256:b2001babafaa8128fe89aa8fd11832cade59931d14c3de5b3ca32e2a010fbaa8", }, }, true), - templatePath: "testoutput", - want: "internal/testdata/complex/service-templates/test2-nginx-php", + want: "internal/testdata/complex/service-templates/test2-nginx-php", }, { name: "test2a-nginx-php", @@ -99,9 +97,8 @@ func TestTemplateLagoonServices(t *testing.T) { Branch: "main", LagoonYAML: "internal/testdata/complex/lagoon.varnish.yml", }, true), - imageData: "internal/testdata/complex/images-service1.yaml", - templatePath: "testoutput", - want: "internal/testdata/complex/service-templates/test2-nginx-php", + imageData: "internal/testdata/complex/images-service1.yaml", + want: "internal/testdata/complex/service-templates/test2-nginx-php", }, { name: "test2b-nginx-php", @@ -127,8 +124,7 @@ func TestTemplateLagoonServices(t *testing.T) { }, }, }, true), - templatePath: "testoutput", - want: "internal/testdata/complex/service-templates/test2b-nginx-php", + want: "internal/testdata/complex/service-templates/test2b-nginx-php", }, { name: "test2c-nginx-php", @@ -169,8 +165,7 @@ func TestTemplateLagoonServices(t *testing.T) { }, }, }, true), - templatePath: "testoutput", - want: "internal/testdata/complex/service-templates/test2c-nginx-php", + want: "internal/testdata/complex/service-templates/test2c-nginx-php", }, { name: "test2d-nginx-php", @@ -210,8 +205,7 @@ func TestTemplateLagoonServices(t *testing.T) { }, }, }, true), - templatePath: "testoutput", - want: "internal/testdata/complex/service-templates/test2d-nginx-php", + want: "internal/testdata/complex/service-templates/test2d-nginx-php", }, { name: "test3-funky-pvcs", @@ -235,8 +229,7 @@ func TestTemplateLagoonServices(t *testing.T) { }, }, }, true), - templatePath: "testoutput", - want: "internal/testdata/basic/service-templates/test3-funky-pvcs", + want: "internal/testdata/basic/service-templates/test3-funky-pvcs", }, { name: "test4-basic-worker", @@ -259,8 +252,7 @@ func TestTemplateLagoonServices(t *testing.T) { }, }, }, true), - templatePath: "testoutput", - want: "internal/testdata/basic/service-templates/test4-basic-worker", + want: "internal/testdata/basic/service-templates/test4-basic-worker", }, { name: "test5-basic-promote", @@ -276,8 +268,7 @@ func TestTemplateLagoonServices(t *testing.T) { "node": "harbor.example/example-project/main/node@sha256:b2001babafaa8128fe89aa8fd11832cade59931d14c3de5b3ca32e2a010fbaa8", }, }, true), - templatePath: "testoutput", - want: "internal/testdata/basic/service-templates/test5-basic-promote", + want: "internal/testdata/basic/service-templates/test5-basic-promote", }, { name: "test6-basic-networkpolicy", @@ -304,8 +295,7 @@ func TestTemplateLagoonServices(t *testing.T) { }, }, }, true), - templatePath: "testoutput", - want: "internal/testdata/basic/service-templates/test6-basic-networkpolicy", + want: "internal/testdata/basic/service-templates/test6-basic-networkpolicy", }, { name: "test7-basic-dynamic-secrets", @@ -322,8 +312,7 @@ func TestTemplateLagoonServices(t *testing.T) { DynamicSecrets: []string{"insights-token"}, DynamicDBaaSSecrets: []string{"mariadb-dbaas-a4hs12h3"}, }, true), - templatePath: "testoutput", - want: "internal/testdata/basic/service-templates/test7-basic-dynamic-secrets", + want: "internal/testdata/basic/service-templates/test7-basic-dynamic-secrets", }, { name: "test8-multiple-services", @@ -344,8 +333,7 @@ func TestTemplateLagoonServices(t *testing.T) { "solr-8": "harbor.example/example-project/main/solr-8@sha256:b2001babafaa8128fe89aa8fd11832cade59931d14c3de5b3ca32e2a010fbaa8", }, }, true), - templatePath: "testoutput", - want: "internal/testdata/complex/service-templates/test8-multiple-services", + want: "internal/testdata/complex/service-templates/test8-multiple-services", }, { name: "test9-meta-dbaas-types", @@ -375,8 +363,7 @@ func TestTemplateLagoonServices(t *testing.T) { }, }, }, true), - templatePath: "testoutput", - want: "internal/testdata/complex/service-templates/test9-meta-dbaas-types", + want: "internal/testdata/complex/service-templates/test9-meta-dbaas-types", }, { name: "test10-basic-no-native-cronjobs", @@ -391,8 +378,7 @@ func TestTemplateLagoonServices(t *testing.T) { "node": "harbor.example/example-project/main/node@sha256:b2001babafaa8128fe89aa8fd11832cade59931d14c3de5b3ca32e2a010fbaa8", }, }, true), - templatePath: "testoutput", - want: "internal/testdata/basic/service-templates/test10-basic-no-native-cronjobs", + want: "internal/testdata/basic/service-templates/test10-basic-no-native-cronjobs", }, { name: "test11-basic-polysite-cronjobs", @@ -407,8 +393,7 @@ func TestTemplateLagoonServices(t *testing.T) { "node": "harbor.example/example-project/main/node@sha256:b2001babafaa8128fe89aa8fd11832cade59931d14c3de5b3ca32e2a010fbaa8", }, }, true), - templatePath: "testoutput", - want: "internal/testdata/basic/service-templates/test11-basic-polysite-cronjobs", + want: "internal/testdata/basic/service-templates/test11-basic-polysite-cronjobs", }, { name: "test12-basic-persistent-custom-volumes", @@ -424,8 +409,7 @@ func TestTemplateLagoonServices(t *testing.T) { "node": "harbor.example/example-project/main/node@sha256:b2001babafaa8128fe89aa8fd11832cade59931d14c3de5b3ca32e2a010fbaa8", }, }, true), - templatePath: "testoutput", - want: "internal/testdata/basic/service-templates/test12-basic-persistent-custom-volumes", + want: "internal/testdata/basic/service-templates/test12-basic-persistent-custom-volumes", }, { name: "test13-basic-custom-volumes", @@ -441,8 +425,7 @@ func TestTemplateLagoonServices(t *testing.T) { "node": "harbor.example/example-project/main/node@sha256:b2001babafaa8128fe89aa8fd11832cade59931d14c3de5b3ca32e2a010fbaa8", }, }, true), - templatePath: "testoutput", - want: "internal/testdata/basic/service-templates/test13-basic-custom-volumes", + want: "internal/testdata/basic/service-templates/test13-basic-custom-volumes", }, { name: "test14-complex-custom-volumes", @@ -462,8 +445,7 @@ func TestTemplateLagoonServices(t *testing.T) { "mariadb": "harbor.example/example-project/main/mariadb@sha256:b2001babafaa8128fe89aa8fd11832cade59931d14c3de5b3ca32e2a010fbaa8", }, }, true), - templatePath: "testoutput", - want: "internal/testdata/complex/service-templates/test14-complex-custom-volumes", + want: "internal/testdata/complex/service-templates/test14-complex-custom-volumes", }, { name: "test15-basic-custom-volume-no-backup", @@ -479,8 +461,7 @@ func TestTemplateLagoonServices(t *testing.T) { "node": "harbor.example/example-project/main/node@sha256:b2001babafaa8128fe89aa8fd11832cade59931d14c3de5b3ca32e2a010fbaa8", }, }, true), - templatePath: "testoutput", - want: "internal/testdata/basic/service-templates/test15-basic-custom-volume-no-backup", + want: "internal/testdata/basic/service-templates/test15-basic-custom-volume-no-backup", }, { name: "test-basic-spot-affinity", @@ -518,8 +499,7 @@ func TestTemplateLagoonServices(t *testing.T) { }, }, }, true), - templatePath: "testoutput", - want: "internal/testdata/basic/service-templates/test-basic-spot-affinity", + want: "internal/testdata/basic/service-templates/test-basic-spot-affinity", }, { name: "test-basic-persistent-name", @@ -534,8 +514,7 @@ func TestTemplateLagoonServices(t *testing.T) { "basic": "harbor.example/example-project/main/basic@sha256:b2001babafaa8128fe89aa8fd11832cade59931d14c3de5b3ca32e2a010fbaa8", }, }, true), - templatePath: "testoutput", - want: "internal/testdata/basic/service-templates/test-basic-persistent-name", + want: "internal/testdata/basic/service-templates/test-basic-persistent-name", }, { name: "test-basic-persistent-names", @@ -551,8 +530,7 @@ func TestTemplateLagoonServices(t *testing.T) { "basic2": "harbor.example/example-project/main/basic2@sha256:b2001babafaa8128fe89aa8fd11832cade59931d14c3de5b3ca32e2a010fbaa8", }, }, true), - templatePath: "testoutput", - want: "internal/testdata/basic/service-templates/test-basic-persistent-names", + want: "internal/testdata/basic/service-templates/test-basic-persistent-names", }, { name: "test-complex-persistent-names", @@ -580,8 +558,7 @@ func TestTemplateLagoonServices(t *testing.T) { "queue-worker-priority-medium": "harbor.example/example-project/main/queue-worker-priority-medium@sha256:b2001babafaa8128fe89aa8fd11832cade59931d14c3de5b3ca32e2a010fbaa8", }, }, true), - templatePath: "testoutput", - want: "internal/testdata/complex/service-templates/test-complex-persistent-names", + want: "internal/testdata/complex/service-templates/test-complex-persistent-names", }, { name: "test-redis-persistent-k8upv2", @@ -602,8 +579,7 @@ func TestTemplateLagoonServices(t *testing.T) { }, }, }, true), - templatePath: "testoutput", - want: "internal/testdata/complex/service-templates/test-redis-persistent-k8upv2", + want: "internal/testdata/complex/service-templates/test-redis-persistent-k8upv2", }, { name: "test-basic-single-k8upv2", @@ -624,8 +600,7 @@ func TestTemplateLagoonServices(t *testing.T) { }, }, }, true), - templatePath: "testoutput", - want: "internal/testdata/basic/service-templates/test-basic-single-k8upv2", + want: "internal/testdata/basic/service-templates/test-basic-single-k8upv2", }, { name: "test-basic-external-service", @@ -640,8 +615,7 @@ func TestTemplateLagoonServices(t *testing.T) { "basic1": "harbor.example/example-project/main/basic1@sha256:b2001babafaa8128fe89aa8fd11832cade59931d14c3de5b3ca32e2a010fbaa8", }, }, true), - templatePath: "testoutput", - want: "internal/testdata/basic/service-templates/test-basic-external-service", + want: "internal/testdata/basic/service-templates/test-basic-external-service", }, { name: "test-basic-external-service-environment", @@ -656,8 +630,7 @@ func TestTemplateLagoonServices(t *testing.T) { "basic1": "harbor.example/example-project/stage/basic1@sha256:b2001babafaa8128fe89aa8fd11832cade59931d14c3de5b3ca32e2a010fbaa8", }, }, true), - templatePath: "testoutput", - want: "internal/testdata/basic/service-templates/test-basic-external-service-environment", + want: "internal/testdata/basic/service-templates/test-basic-external-service-environment", }, } for _, tt := range tests { @@ -670,17 +643,14 @@ func TestTemplateLagoonServices(t *testing.T) { } } // set the environment variables from args - savedTemplates := tt.templatePath - generator, err := testdata.SetupEnvironment(*rootCmd, savedTemplates, tt.args) + savedTemplates, err := os.MkdirTemp("", "testoutput") if err != nil { t.Errorf("%v", err) } - - err = os.MkdirAll(savedTemplates, 0755) + generator, err := testdata.SetupEnvironment(generator.GeneratorInput{}, savedTemplates, tt.args) if err != nil { - t.Errorf("couldn't create directory %v: %v", savedTemplates, err) + t.Errorf("%v", err) } - defer os.RemoveAll(savedTemplates) ts := dbaasclient.TestDBaaSHTTPServer() diff --git a/go.mod b/go.mod index b21fbaf1..dd8f9e01 100644 --- a/go.mod +++ b/go.mod @@ -21,7 +21,7 @@ require ( github.com/k8up-io/k8up/v2 v2.11.3 github.com/robfig/cron/v3 v3.0.1 github.com/spf13/cobra v1.8.1 - github.com/uselagoon/machinery v0.0.31 + github.com/uselagoon/machinery v0.0.34 github.com/vshn/k8up v1.99.99 gopkg.in/yaml.v2 v2.4.0 gopkg.in/yaml.v3 v3.0.1 diff --git a/go.sum b/go.sum index a2fda292..692f4c03 100644 --- a/go.sum +++ b/go.sum @@ -802,8 +802,8 @@ github.com/ultraware/funlen v0.0.2/go.mod h1:Dp4UiAus7Wdb9KUZsYWZEWiRzGuM2kXM1lP github.com/ultraware/whitespace v0.0.4/go.mod h1:aVMh/gQve5Maj9hQ/hg+F75lr/X5A89uZnzAmWSineA= github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI= -github.com/uselagoon/machinery v0.0.31 h1:SkJ+muPBb9Q5vNI0bgXxZai6jN103iSj3e3d3DcZlc4= -github.com/uselagoon/machinery v0.0.31/go.mod h1:RsHzIMOam3hiA4CKR12yANgzdTGy6tz4D19umjMzZyw= +github.com/uselagoon/machinery v0.0.34 h1:5DsvXEyMeXmzQhjt11YH7+kZJueabovrwKTv0x7jQV8= +github.com/uselagoon/machinery v0.0.34/go.mod h1:G0ujppuNR0BrtAnlmH8xDb9TDfayb4A36aeo0DYg7fQ= github.com/uudashr/gocognit v0.0.0-20190926065955-1655d0de0517/go.mod h1:j44Ayx2KW4+oB6SWMv8KsmHzZrOInQav7D3cQMJ5JUM= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/fasthttp v1.2.0/go.mod h1:4vX61m6KN+xDduDNwXrhIAVZaZaZiQ1luJk8LWSxF3s= diff --git a/internal/cleanup/cleanup.go b/internal/cleanup/cleanup.go new file mode 100644 index 00000000..dcb6cb21 --- /dev/null +++ b/internal/cleanup/cleanup.go @@ -0,0 +1,138 @@ +package cleanup + +import ( + "context" + "fmt" + + "github.com/uselagoon/build-deploy-tool/internal/collector" + "github.com/uselagoon/build-deploy-tool/internal/generator" + "github.com/uselagoon/build-deploy-tool/internal/identify" + client "sigs.k8s.io/controller-runtime/pkg/client" +) + +func RunCleanup(c *collector.Collector, gen generator.GeneratorInput, performDeletion bool) ([]string, []string, []string, []string, []string, []string, error) { + _, mariadbDelete, mongodbDelete, postgresqlDelete, depDelete, volDelete, servDelete, state, err := identify.GetCurrentState(c, gen) + if err != nil { + return nil, nil, nil, nil, nil, nil, err + } + if len(mariadbDelete) > 0 || len(mongodbDelete) > 0 || len(postgresqlDelete) > 0 || len(depDelete) > 0 || len(volDelete) > 0 || len(servDelete) > 0 { + fmt.Println(`>> Lagoon detected services or volumes that have been removed from the docker-compose file`) + if !performDeletion { + fmt.Println(`> If you no longer need these services, you can instruct Lagoon to remove it from the environment by setting the following variable + 'LAGOON_FEATURE_FLAG_CLEANUP_REMOVED_LAGOON_SERVICES=enabled' as a GLOBAL scoped variable to this environment or project. + Removing unused resources will result in the services and any data they had being deleted. + Ensure your application is no longer configured to use these resources before removing them. + If you're not sure, contact your support team with a link to this build.`) + } else { + fmt.Println(`> The flag 'LAGOON_FEATURE_FLAG_CLEANUP_REMOVED_LAGOON_SERVICES' is enabled. + Resources that were removed from the docker-compose file will now be removed from the environment. + The services and any data they had will be deleted. + You should remove this variable if you don't want services to be removed automatically in the future.`) + } + fmt.Println(`> Future releases of Lagoon may remove services automatically, you should ensure that your services are up always up to date if you see this warning."`) + + var mariaDBToDelete, mongoDBToDelete, postgresToDelete, volumesToDelete, servicesToDelete, deploymentsToDelete []string + ctx := context.Background() + for _, i := range depDelete { + deploymentsToDelete = append(deploymentsToDelete, i.Name) + if performDeletion { + fmt.Printf(">> Removing deployment %s\n", i.Name) + if err := c.Client.Delete(ctx, &i); err != nil { + return nil, nil, nil, nil, nil, nil, err + } + } else { + fmt.Printf(">> Would remove deployment %s\n", i.Name) + } + } + for _, i := range volDelete { + volumesToDelete = append(volumesToDelete, i.Name) + if performDeletion { + fmt.Printf(">> Removing volume %s\n", i.Name) + if err := c.Client.Delete(ctx, &i); err != nil { + return nil, nil, nil, nil, nil, nil, err + } + } else { + fmt.Printf(">> Would remove volume %s\n", i.Name) + } + } + for _, i := range servDelete { + servicesToDelete = append(servicesToDelete, i.Name) + if performDeletion { + fmt.Printf(">> Removing service %s\n", i.Name) + if err := c.Client.Delete(ctx, &i); err != nil { + return nil, nil, nil, nil, nil, nil, err + } + } else { + fmt.Printf(">> Would remove service %s\n", i.Name) + } + } + for _, i := range mariadbDelete { + mariaDBToDelete = append(mariaDBToDelete, i.Name) + if performDeletion { + fmt.Printf(">> Removing mariadb consumer %s\n", i.Name) + if err := c.Client.Delete(ctx, &i); err != nil { + return nil, nil, nil, nil, nil, nil, err + } + err := removePreBackupPod(ctx, c.Client, state, i.Name) + if err != nil { + return nil, nil, nil, nil, nil, nil, err + } + } else { + fmt.Printf(">> Would remove mariadb consumer %s and associated components\n", i.Name) + } + } + for _, i := range mongodbDelete { + mongoDBToDelete = append(mongoDBToDelete, i.Name) + if performDeletion { + fmt.Printf(">> Removing mongodb consumer %s\n", i.Name) + if err := c.Client.Delete(ctx, &i); err != nil { + return nil, nil, nil, nil, nil, nil, err + } + err := removePreBackupPod(ctx, c.Client, state, i.Name) + if err != nil { + return nil, nil, nil, nil, nil, nil, err + } + } else { + fmt.Printf(">> Would remove mongodb consumer %s and associated components\n", i.Name) + } + } + for _, i := range postgresqlDelete { + postgresToDelete = append(postgresToDelete, i.Name) + if performDeletion { + fmt.Printf(">> Removing postgresql consumer %s\n", i.Name) + if err := c.Client.Delete(ctx, &i); err != nil { + return nil, nil, nil, nil, nil, nil, err + } + err := removePreBackupPod(ctx, c.Client, state, i.Name) + if err != nil { + return nil, nil, nil, nil, nil, nil, err + } + } else { + fmt.Printf(">> Would remove postgresql consumer %s and associated components\n", i.Name) + } + } + return mariaDBToDelete, mongoDBToDelete, postgresToDelete, deploymentsToDelete, volumesToDelete, servicesToDelete, nil + } else { + return nil, nil, nil, nil, nil, nil, nil + } +} + +func removePreBackupPod(ctx context.Context, c client.Client, state *collector.LagoonEnvState, name string) error { + for _, pbp := range state.PreBackupPodsV1.Items { + if pbp.Name == fmt.Sprintf("%s-prebackuppod", name) { + fmt.Printf(">> Removing mariadb prebackuppod %s\n", name) + if err := c.Delete(ctx, &pbp); err != nil { + return err + } + } + } + for _, pbp := range state.PreBackupPodsV1Alpha1.Items { + if pbp.Name == fmt.Sprintf("%s-prebackuppod", name) { + fmt.Printf(">> Removing mariadb prebackuppod %s\n", name) + if err := c.Delete(ctx, &pbp); err != nil { + return err + } + } + } + return nil +} diff --git a/internal/cleanup/cleanup_test.go b/internal/cleanup/cleanup_test.go new file mode 100644 index 00000000..9b4653a1 --- /dev/null +++ b/internal/cleanup/cleanup_test.go @@ -0,0 +1,290 @@ +package cleanup + +import ( + "context" + "os" + "reflect" + "testing" + + "github.com/uselagoon/build-deploy-tool/internal/collector" + "github.com/uselagoon/build-deploy-tool/internal/dbaasclient" + "github.com/uselagoon/build-deploy-tool/internal/generator" + "github.com/uselagoon/build-deploy-tool/internal/helpers" + "github.com/uselagoon/build-deploy-tool/internal/k8s" + "github.com/uselagoon/build-deploy-tool/internal/testdata" + + // changes the testing to source from root so paths to test resources must be defined from repo root + _ "github.com/uselagoon/build-deploy-tool/internal/testing" +) + +func TestRunCleanup(t *testing.T) { + tests := []struct { + name string + namespace string + args testdata.TestData + deleteServices bool + wantErr bool + seedDir string + wantMariaDB []string + wantPsqlDB []string + wantMongoDB []string + wantDep []string + wantVol []string + wantServ []string + }{ + { + name: "basic deployment", + args: testdata.GetSeedData( + testdata.TestData{ + ProjectName: "example-project", + EnvironmentName: "main", + Branch: "main", + LagoonYAML: "internal/testdata/basic/lagoon.yml", + ImageReferences: map[string]string{ + "node": "harbor.example/example-project/main/node@sha256:b2001babafaa8128fe89aa8fd11832cade59931d14c3de5b3ca32e2a010fbaa8", + }, + }, true), + deleteServices: true, + namespace: "example-project-main", + seedDir: "internal/testdata/basic/cleanup-seed/basic-deployment", + wantMariaDB: []string{"mariadb"}, + wantDep: []string{"basic"}, + wantServ: []string{"basic"}, + }, + { + name: "multivolumes", + args: testdata.GetSeedData( + testdata.TestData{ + ProjectName: "example-project", + EnvironmentName: "main", + Branch: "main", + LagoonYAML: "internal/testdata/basic/lagoon.multiple-volumes.yml", + ImageReferences: map[string]string{ + "node": "harbor.example/example-project/main/node@sha256:b2001babafaa8128fe89aa8fd11832cade59931d14c3de5b3ca32e2a010fbaa8", + }, + }, true), + deleteServices: false, + namespace: "example-project-main", + seedDir: "internal/testdata/basic/service-templates/test12-basic-persistent-custom-volumes", + wantMariaDB: nil, + wantDep: []string{"node"}, + wantServ: []string{"node"}, + }, + { + name: "complex-singles", + args: testdata.GetSeedData( + testdata.TestData{ + ProjectName: "example-project", + EnvironmentName: "main", + Branch: "main", + LagoonYAML: "internal/testdata/complex/lagoon.services.yml", + ImageReferences: map[string]string{ + "web": "harbor.example/example-project/main/web@sha256:b2001babafaa8128fe89aa8fd11832cade59931d14c3de5b3ca32e2a010fbaa8", + "mariadb-10-5": "harbor.example/example-project/main/mariadb-10-5@sha256:b2001babafaa8128fe89aa8fd11832cade59931d14c3de5b3ca32e2a010fbaa8", + "postgres-11": "harbor.example/example-project/main/postgres-11@sha256:b2001babafaa8128fe89aa8fd11832cade59931d14c3de5b3ca32e2a010fbaa8", + "opensearch-2": "harbor.example/example-project/main/opensearch-2@sha256:b2001babafaa8128fe89aa8fd11832cade59931d14c3de5b3ca32e2a010fbaa8", + "redis-6": "harbor.example/example-project/main/redis-6@sha256:b2001babafaa8128fe89aa8fd11832cade59931d14c3de5b3ca32e2a010fbaa8", + "redis-7": "harbor.example/example-project/main/redis-7@sha256:b2001babafaa8128fe89aa8fd11832cade59931d14c3de5b3ca32e2a010fbaa8", + "solr-8": "harbor.example/example-project/main/solr-8@sha256:b2001babafaa8128fe89aa8fd11832cade59931d14c3de5b3ca32e2a010fbaa8", + }, + }, true), + deleteServices: false, + namespace: "example-project-main", + seedDir: "internal/testdata/complex/service-templates/test8-multiple-services", + wantMariaDB: nil, + wantDep: []string{"mariadb-10-5", "opensearch-2", "postgres-11", "redis-6", "redis-7", "solr-8", "web"}, + wantServ: []string{"mariadb-10-5", "opensearch-2", "postgres-11", "redis-6", "redis-7", "solr-8", "web"}, + }, + { + name: "complex-nginx", + args: testdata.GetSeedData( + testdata.TestData{ + ProjectName: "example-project", + EnvironmentName: "main", + Branch: "main", + LagoonYAML: "internal/testdata/complex/lagoon.varnish.yml", + ImageReferences: map[string]string{ + "nginx": "harbor.example/example-project/main/nginx@sha256:b2001babafaa8128fe89aa8fd11832cade59931d14c3de5b3ca32e2a010fbaa8", + "php": "harbor.example/example-project/main/php@sha256:b2001babafaa8128fe89aa8fd11832cade59931d14c3de5b3ca32e2a010fbaa8", + "cli": "harbor.example/example-project/main/cli@sha256:b2001babafaa8128fe89aa8fd11832cade59931d14c3de5b3ca32e2a010fbaa8", + "redis": "harbor.example/example-project/main/redis@sha256:b2001babafaa8128fe89aa8fd11832cade59931d14c3de5b3ca32e2a010fbaa8", + "varnish": "harbor.example/example-project/main/varnish@sha256:b2001babafaa8128fe89aa8fd11832cade59931d14c3de5b3ca32e2a010fbaa8", + }, + }, true), + deleteServices: false, + namespace: "example-project-main", + seedDir: "internal/testdata/complex/service-templates/test2-nginx-php", + wantMariaDB: nil, + wantDep: []string{"nginx-php", "cli", "redis", "varnish"}, + wantServ: []string{"nginx-php", "redis", "varnish"}, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + helpers.UnsetEnvVars(nil) //unset variables before running tests + // set the environment variables from args + savedTemplates := "testoutput" + generator, err := testdata.SetupEnvironment(generator.GeneratorInput{}, savedTemplates, tt.args) + if err != nil { + t.Errorf("%v", err) + } + + err = os.MkdirAll(savedTemplates, 0755) + if err != nil { + t.Errorf("couldn't create directory %v: %v", savedTemplates, err) + } + + defer os.RemoveAll(savedTemplates) + + ts := dbaasclient.TestDBaaSHTTPServer() + defer ts.Close() + err = os.Setenv("DBAAS_OPERATOR_HTTP", ts.URL) + if err != nil { + t.Errorf("%v", err) + } + + client, err := k8s.NewFakeClient(tt.namespace) + if err != nil { + t.Errorf("error creating fake client") + } + err = k8s.SeedFakeData(client, tt.namespace, tt.seedDir) + if err != nil { + t.Errorf("error seeding fake data: %v", err) + } + col := collector.NewCollector(client) + beforeState, _ := col.Collect(context.Background(), tt.namespace) + want := false + for _, i2 := range tt.wantDep { + for _, i1 := range beforeState.Deployments.Items { + if i1.Name == i2 { + want = true + } + } + if !want { + t.Errorf("RunCleanup() deployment %v should exist", i2) + } + want = false + } + for _, i2 := range tt.wantVol { + for _, i1 := range beforeState.PVCs.Items { + if i1.Name == i2 { + want = true + } + } + if !want { + t.Errorf("RunCleanup() pvc %v should exist", i2) + } + want = false + } + for _, i2 := range tt.wantServ { + for _, i1 := range beforeState.Services.Items { + if i1.Name == i2 { + want = true + } + } + if !want { + t.Errorf("RunCleanup() service %v should exist", i2) + } + want = false + } + for _, i2 := range tt.wantMariaDB { + for _, i1 := range beforeState.MariaDBConsumers.Items { + if i1.Name == i2 { + want = true + } + } + if !want { + t.Errorf("RunCleanup() mariadb consumer %v should exist", i2) + } + want = false + } + for _, i2 := range tt.wantMongoDB { + for _, i1 := range beforeState.MongoDBConsumers.Items { + if i1.Name == i2 { + want = true + } + } + if !want { + t.Errorf("RunCleanup() mongodb consumer %v should exist", i2) + } + want = false + } + for _, i2 := range tt.wantPsqlDB { + for _, i1 := range beforeState.PostgreSQLConsumers.Items { + if i1.Name == i2 { + want = true + } + } + if !want { + t.Errorf("RunCleanup() mariadb consumer %v should exist", i2) + } + want = false + } + mdb, mongdb, psqdb, dep, vol, serv, err := RunCleanup(col, generator, tt.deleteServices) + if (err != nil) != tt.wantErr { + t.Errorf("RunCleanup() error = %v, wantErr %v", err, tt.wantErr) + } + if mdb != nil && tt.wantMariaDB != nil && !reflect.DeepEqual(tt.wantMariaDB, mdb) { + t.Errorf("RunCleanup() %v, wantMariaDB %v", mdb, tt.wantMariaDB) + } + if mongdb != nil && tt.wantMongoDB != nil && !reflect.DeepEqual(tt.wantMongoDB, mongdb) { + t.Errorf("RunCleanup() %v, wantMongoDB %v", mongdb, tt.wantMongoDB) + } + if psqdb != nil && tt.wantPsqlDB != nil && !reflect.DeepEqual(tt.wantPsqlDB, psqdb) { + t.Errorf("RunCleanup() %v, wantPsqlDB %v", psqdb, tt.wantPsqlDB) + } + if dep != nil && tt.wantDep != nil && !reflect.DeepEqual(tt.wantDep, dep) { + t.Errorf("RunCleanup() %v, wantDep %v", dep, tt.wantDep) + } + if serv != nil && tt.wantServ != nil && !reflect.DeepEqual(tt.wantServ, serv) { + t.Errorf("RunCleanup()%v, wantServ %v", serv, tt.wantServ) + } + if vol != nil && tt.wantVol != nil && !reflect.DeepEqual(tt.wantVol, vol) { + t.Errorf("RunCleanup() %v, wantVol %v", vol, tt.wantVol) + } + afterState, _ := col.Collect(context.Background(), tt.namespace) + for _, i1 := range afterState.Deployments.Items { + for _, i2 := range dep { + if i1.Name == i2 { + t.Errorf("RunCleanup() deployment %v shouldn't exist", i2) + } + } + } + for _, i1 := range afterState.PVCs.Items { + for _, i2 := range dep { + if i1.Name == i2 { + t.Errorf("RunCleanup() pvc %v shouldn't exist", i2) + } + } + } + for _, i1 := range afterState.Services.Items { + for _, i2 := range dep { + if i1.Name == i2 { + t.Errorf("RunCleanup() service %v shouldn't exist", i2) + } + } + } + for _, i1 := range afterState.MariaDBConsumers.Items { + for _, i2 := range dep { + if i1.Name == i2 { + t.Errorf("RunCleanup() mariadb consumer %v shouldn't exist", i2) + } + } + } + for _, i1 := range afterState.MongoDBConsumers.Items { + for _, i2 := range dep { + if i1.Name == i2 { + t.Errorf("RunCleanup() mongodb consumer %v shouldn't exist", i2) + } + } + } + for _, i1 := range afterState.PostgreSQLConsumers.Items { + for _, i2 := range dep { + if i1.Name == i2 { + t.Errorf("RunCleanup() postgres consumer %v shouldn't exist", i2) + } + } + } + }) + } +} diff --git a/internal/collector/pvcs.go b/internal/collector/pvcs.go index 65859abf..bbd3fb02 100644 --- a/internal/collector/pvcs.go +++ b/internal/collector/pvcs.go @@ -10,7 +10,7 @@ import ( ) func (c *Collector) CollectPVCs(ctx context.Context, namespace string) (*corev1.PersistentVolumeClaimList, error) { - labelRequirements1, _ := labels.NewRequirement("lagoon.sh/service", selection.Exists, nil) + labelRequirements1, _ := labels.NewRequirement("lagoon.sh/template", selection.Exists, nil) listOption := (&client.ListOptions{}).ApplyOptions([]client.ListOption{ client.InNamespace(namespace), client.MatchingLabelsSelector{ diff --git a/internal/collector/testdata/json-result/result-2.json b/internal/collector/testdata/json-result/result-2.json index fd4f4913..10b8768b 100644 --- a/internal/collector/testdata/json-result/result-2.json +++ b/internal/collector/testdata/json-result/result-2.json @@ -367,6 +367,84 @@ "pvcs": { "metadata": {}, "items": [ + { + "kind": "PersistentVolumeClaim", + "apiVersion": "v1", + "metadata": { + "name": "custom-config", + "namespace": "example-project-main", + "resourceVersion": "1", + "creationTimestamp": null, + "labels": { + "app.kubernetes.io/instance": "custom-config", + "app.kubernetes.io/managed-by": "build-deploy-tool", + "app.kubernetes.io/name": "config", + "lagoon.sh/buildType": "branch", + "lagoon.sh/environment": "main", + "lagoon.sh/environmentType": "production", + "lagoon.sh/project": "example-project", + "lagoon.sh/service-type": "additional-volume", + "lagoon.sh/template": "additional-volume-0.1.0" + }, + "annotations": { + "k8up.io/backup": "true", + "k8up.syn.tools/backup": "true", + "lagoon.sh/branch": "main", + "lagoon.sh/version": "v2.7.x" + } + }, + "spec": { + "accessModes": [ + "ReadWriteMany" + ], + "resources": { + "requests": { + "storage": "5Gi" + } + }, + "storageClassName": "bulk" + }, + "status": {} + }, + { + "kind": "PersistentVolumeClaim", + "apiVersion": "v1", + "metadata": { + "name": "custom-files", + "namespace": "example-project-main", + "resourceVersion": "1", + "creationTimestamp": null, + "labels": { + "app.kubernetes.io/instance": "custom-files", + "app.kubernetes.io/managed-by": "build-deploy-tool", + "app.kubernetes.io/name": "files", + "lagoon.sh/buildType": "branch", + "lagoon.sh/environment": "main", + "lagoon.sh/environmentType": "production", + "lagoon.sh/project": "example-project", + "lagoon.sh/service-type": "additional-volume", + "lagoon.sh/template": "additional-volume-0.1.0" + }, + "annotations": { + "k8up.io/backup": "true", + "k8up.syn.tools/backup": "true", + "lagoon.sh/branch": "main", + "lagoon.sh/version": "v2.7.x" + } + }, + "spec": { + "accessModes": [ + "ReadWriteMany" + ], + "resources": { + "requests": { + "storage": "10Gi" + } + }, + "storageClassName": "bulk" + }, + "status": {} + }, { "kind": "PersistentVolumeClaim", "apiVersion": "v1", diff --git a/internal/generator/helpers_generator.go b/internal/generator/helpers_generator.go index dbcc52a3..4915c25f 100644 --- a/internal/generator/helpers_generator.go +++ b/internal/generator/helpers_generator.go @@ -10,138 +10,10 @@ import ( "github.com/distribution/reference" - "github.com/spf13/cobra" - "github.com/uselagoon/build-deploy-tool/internal/dbaasclient" "github.com/uselagoon/build-deploy-tool/internal/lagoon" "k8s.io/apimachinery/pkg/api/resource" ) -// helper function that reads flag overrides and returns a generated input dataset -// this is called from within the main environment setup helper function -func GenerateInput(rootCmd cobra.Command, debug bool) (GeneratorInput, error) { - lagoonYAML, err := rootCmd.PersistentFlags().GetString("lagoon-yml") - if err != nil { - return GeneratorInput{}, fmt.Errorf("error reading lagoon-yml flag: %v", err) - } - lagoonYAMLOverride, err := rootCmd.PersistentFlags().GetString("lagoon-yml-override") - if err != nil { - return GeneratorInput{}, fmt.Errorf("error reading lagoon-yml-override flag: %v", err) - } - lagoonVersion, err := rootCmd.PersistentFlags().GetString("lagoon-version") - if err != nil { - return GeneratorInput{}, fmt.Errorf("error reading lagoon-version flag: %v", err) - } - projectName, err := rootCmd.PersistentFlags().GetString("project-name") - if err != nil { - return GeneratorInput{}, fmt.Errorf("error reading project-name flag: %v", err) - } - environmentName, err := rootCmd.PersistentFlags().GetString("environment-name") - if err != nil { - return GeneratorInput{}, fmt.Errorf("error reading environment-name flag: %v", err) - } - environmentType, err := rootCmd.PersistentFlags().GetString("environment-type") - if err != nil { - return GeneratorInput{}, fmt.Errorf("error reading environment-type flag: %v", err) - } - activeEnvironment, err := rootCmd.PersistentFlags().GetString("active-environment") - if err != nil { - return GeneratorInput{}, fmt.Errorf("error reading active-environment flag: %v", err) - } - standbyEnvironment, err := rootCmd.PersistentFlags().GetString("standby-environment") - if err != nil { - return GeneratorInput{}, fmt.Errorf("error reading standby-environment flag: %v", err) - } - projectVariables, err := rootCmd.PersistentFlags().GetString("project-variables") - if err != nil { - return GeneratorInput{}, fmt.Errorf("error reading project-variables flag: %v", err) - } - environmentVariables, err := rootCmd.PersistentFlags().GetString("environment-variables") - if err != nil { - return GeneratorInput{}, fmt.Errorf("error reading environment-variables flag: %v", err) - } - buildType, err := rootCmd.PersistentFlags().GetString("build-type") - if err != nil { - return GeneratorInput{}, fmt.Errorf("error reading build-type flag: %v", err) - } - branch, err := rootCmd.PersistentFlags().GetString("branch") - if err != nil { - return GeneratorInput{}, fmt.Errorf("error reading branch flag: %v", err) - } - prNumber, err := rootCmd.PersistentFlags().GetString("pullrequest-number") - if err != nil { - return GeneratorInput{}, fmt.Errorf("error reading pullrequest-number flag: %v", err) - } - prTitle, err := rootCmd.PersistentFlags().GetString("pullrequest-title") - if err != nil { - return GeneratorInput{}, fmt.Errorf("error reading pullrequest-title flag: %v", err) - } - prHeadBranch, err := rootCmd.PersistentFlags().GetString("pullrequest-head-branch") - if err != nil { - return GeneratorInput{}, fmt.Errorf("error reading pullrequest-head-branch flag: %v", err) - } - prBaseBranch, err := rootCmd.PersistentFlags().GetString("pullrequest-base-branch") - if err != nil { - return GeneratorInput{}, fmt.Errorf("error reading pullrequest-base-branch flag: %v", err) - } - monitoringContact, err := rootCmd.PersistentFlags().GetString("monitoring-config") - if err != nil { - return GeneratorInput{}, fmt.Errorf("error reading monitoring-config flag: %v", err) - } - monitoringStatusPageID, err := rootCmd.PersistentFlags().GetString("monitoring-status-page-id") - if err != nil { - return GeneratorInput{}, fmt.Errorf("error reading monitoring-status-page-id flag: %v", err) - } - fastlyCacheNoCache, err := rootCmd.PersistentFlags().GetString("fastly-cache-no-cache-id") - if err != nil { - return GeneratorInput{}, fmt.Errorf("error reading fastly-cache-no-cache-id flag: %v", err) - } - ignoreMissingEnvFiles, err := rootCmd.PersistentFlags().GetBool("ignore-missing-env-files") - if err != nil { - return GeneratorInput{}, fmt.Errorf("error reading ignore-missing-env-files flag: %v", err) - } - ignoreNonStringKeyErrors, err := rootCmd.PersistentFlags().GetBool("ignore-non-string-key-errors") - if err != nil { - return GeneratorInput{}, fmt.Errorf("error reading ignore-non-string-key-errors flag: %v", err) - } - savedTemplates, err := rootCmd.PersistentFlags().GetString("saved-templates-path") - if err != nil { - return GeneratorInput{}, fmt.Errorf("error reading saved-templates-path flag: %v", err) - } - defaultBackupSchedule, err := rootCmd.PersistentFlags().GetString("default-backup-schedule") - if err != nil { - return GeneratorInput{}, fmt.Errorf("error reading default-backup-schedule flag: %v", err) - } - // create a dbaas client with the default configuration - dbaas := dbaasclient.NewClient(dbaasclient.Client{}) - return GeneratorInput{ - Debug: debug, - LagoonYAML: lagoonYAML, - LagoonYAMLOverride: lagoonYAMLOverride, - LagoonVersion: lagoonVersion, - ProjectName: projectName, - EnvironmentName: environmentName, - EnvironmentType: environmentType, - ActiveEnvironment: activeEnvironment, - StandbyEnvironment: standbyEnvironment, - ProjectVariables: projectVariables, - EnvironmentVariables: environmentVariables, - BuildType: buildType, - Branch: branch, - PRNumber: prNumber, - PRTitle: prTitle, - PRHeadBranch: prHeadBranch, - PRBaseBranch: prBaseBranch, - MonitoringContact: monitoringContact, - MonitoringStatusPageID: monitoringStatusPageID, - FastlyCacheNoCache: fastlyCacheNoCache, - SavedTemplatesPath: savedTemplates, - IgnoreMissingEnvFiles: ignoreMissingEnvFiles, - IgnoreNonStringKeyErrors: ignoreNonStringKeyErrors, - DBaaSClient: dbaas, - DefaultBackupSchedule: defaultBackupSchedule, - }, nil -} - // checks the provided environment variables looking for feature flag based variables func CheckFeatureFlag(key string, envVariables []lagoon.EnvironmentVariable, debug bool) string { // check for force value diff --git a/internal/identify/identify_dbaas.go b/internal/identify/identify_dbaas.go new file mode 100644 index 00000000..88760156 --- /dev/null +++ b/internal/identify/identify_dbaas.go @@ -0,0 +1,23 @@ +package identify + +import ( + "fmt" + + "github.com/uselagoon/build-deploy-tool/internal/generator" +) + +func IdentifyDBaaSConsumers(g generator.GeneratorInput) ([]string, error) { + lagoonBuild, err := generator.NewGenerator( + g, + ) + if err != nil { + return nil, err + } + ret := []string{} + for _, svc := range lagoonBuild.BuildValues.Services { + if svc.IsDBaaS || svc.IsSingle { + ret = append(ret, fmt.Sprintf("%s:%s", svc.Name, svc.Type)) + } + } + return ret, nil +} diff --git a/cmd/identify_dbaas_test.go b/internal/identify/identify_dbaas_test.go similarity index 95% rename from cmd/identify_dbaas_test.go rename to internal/identify/identify_dbaas_test.go index 808d505f..be565408 100644 --- a/cmd/identify_dbaas_test.go +++ b/internal/identify/identify_dbaas_test.go @@ -1,4 +1,4 @@ -package cmd +package identify import ( "os" @@ -6,6 +6,7 @@ import ( "testing" "github.com/uselagoon/build-deploy-tool/internal/dbaasclient" + "github.com/uselagoon/build-deploy-tool/internal/generator" "github.com/uselagoon/build-deploy-tool/internal/helpers" "github.com/uselagoon/build-deploy-tool/internal/lagoon" "github.com/uselagoon/build-deploy-tool/internal/testdata" @@ -105,7 +106,7 @@ func TestIdentifyDBaaSConsumers(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { savedTemplates := tt.templatePath - generator, err := testdata.SetupEnvironment(*rootCmd, savedTemplates, tt.args) + generator, err := testdata.SetupEnvironment(generator.GeneratorInput{}, savedTemplates, tt.args) if err != nil { t.Errorf("%v", err) } diff --git a/internal/identify/identify_lagoonservices.go b/internal/identify/identify_lagoonservices.go new file mode 100644 index 00000000..6859ff31 --- /dev/null +++ b/internal/identify/identify_lagoonservices.go @@ -0,0 +1,146 @@ +package identify + +import ( + "fmt" + + "github.com/uselagoon/build-deploy-tool/internal/generator" + servicestemplates "github.com/uselagoon/build-deploy-tool/internal/templating" +) + +type IdentifyServices struct { + Deployments []string `json:"deployments,omitempty"` + Volumes []string `json:"volumes,omitempty"` + Services []string `json:"services,omitempty"` +} + +// eventually replace with https://github.com/uselagoon/machinery/pull/99 +type LagoonServices struct { + Services []EnvironmentService `json:"services,omitempty"` + Volumes []EnvironmentVolume `json:"volumes,omitempty"` + // Services []schema.EnvironmentService `json:"services,omitempty"` + // Volumes []schema.EnvironmentVolume `json:"volumes,omitempty"` +} + +// eventually replace with https://github.com/uselagoon/machinery/pull/99 +type EnvironmentService struct { + ID int `json:"id,omitempty"` + Name string `json:"name,omitempty"` + Type string `json:"type,omitempty"` + Updated string `json:"updated,omitempty"` + Containers []ServiceContainer `json:"containers,omitempty"` + Created string `json:"created,omitempty"` + Abandoned bool `json:"abandoned,omitempty"` // no longer tracked in the docker-compose file +} + +// eventually replace with https://github.com/uselagoon/machinery/pull/99 +type ServiceContainer struct { + Name string `json:"name,omitempty"` + Volumes []VolumeMount `json:"volumes,omitempty"` + Ports []ContainerPort `json:"ports,omitempty"` +} + +// eventually replace with https://github.com/uselagoon/machinery/pull/99 +type EnvironmentVolume struct { + Name string `json:"name,omitempty"` + StorageType string `json:"storageType,omitempty"` + Type string `json:"type,omitempty"` + Size string `json:"size,omitempty"` + Abandoned bool `json:"abandoned,omitempty"` // no longer tracked in the docker-compose file +} + +// eventually replace with https://github.com/uselagoon/machinery/pull/99 +type VolumeMount struct { + Name string `json:"name,omitempty"` + Path string `json:"path,omitempty"` +} + +// eventually replace with https://github.com/uselagoon/machinery/pull/99 +type ContainerPort struct { + Name string `json:"name,omitempty"` + Port int `json:"port,omitempty"` +} + +// LagoonServiceTemplateIdentification takes the output of the generator and returns a JSON payload that contains information +// about the services that lagoon will be deploying (this will be kubernetes `kind: deployment`, but lagoon calls them services ¯\_(ツ)_/¯) +// this command can be used to identify services that are deployed by the build, so that services that may remain in the environment can be identified +// and eventually removed +func LagoonServiceTemplateIdentification(g generator.GeneratorInput) (*IdentifyServices, *LagoonServices, error) { + servicesData := IdentifyServices{} + lagoonBuild, err := generator.NewGenerator( + g, + ) + if err != nil { + return nil, nil, err + } + + lagoonServices := &LagoonServices{} + pvcs, err := servicestemplates.GeneratePVCTemplate(*lagoonBuild.BuildValues) + if err != nil { + return nil, nil, fmt.Errorf("couldn't identify volumes: %v", err) + } + for _, pvc := range pvcs { + servicesData.Volumes = append(servicesData.Volumes, pvc.Name) + size := pvc.Spec.Resources.Requests.Storage + storeType := "block" + if pvc.Spec.StorageClassName != nil { + switch *pvc.Spec.StorageClassName { + case "bulk": + storeType = "bulk" + } + } + kubevol := EnvironmentVolume{ + Name: pvc.Name, + StorageType: storeType, + Type: pvc.Labels["lagoon.sh/service-type"], + Size: size().String(), + } + lagoonServices.Volumes = append(lagoonServices.Volumes, kubevol) + } + deployments, err := servicestemplates.GenerateDeploymentTemplate(*lagoonBuild.BuildValues) + if err != nil { + return nil, nil, fmt.Errorf("couldn't identify deployments: %v", err) + } + for _, d := range deployments { + servicesData.Deployments = append(servicesData.Deployments, d.Name) + containers := []ServiceContainer{} + for _, c := range d.Spec.Template.Spec.Containers { + volumes := []VolumeMount{} + for _, v := range c.VolumeMounts { + for _, vo := range lagoonServices.Volumes { + if vo.Name == v.Name { + volumes = append(volumes, VolumeMount{ + Name: v.Name, + Path: v.MountPath, + }) + } + } + } + ports := []ContainerPort{} + for _, p := range c.Ports { + ports = append(ports, ContainerPort{ + Name: p.Name, + Port: int(p.ContainerPort), + }) + } + containers = append(containers, ServiceContainer{ + Name: c.Name, + Volumes: volumes, + Ports: ports, + }) + } + service := EnvironmentService{ + Name: d.Name, + Type: d.Labels["lagoon.sh/service-type"], + Containers: containers, + } + lagoonServices.Services = append(lagoonServices.Services, service) + } + services, err := servicestemplates.GenerateServiceTemplate(*lagoonBuild.BuildValues) + if err != nil { + return nil, nil, fmt.Errorf("couldn't identify services: %v", err) + } + for _, service := range services { + servicesData.Services = append(servicesData.Services, service.Name) + } + return &servicesData, lagoonServices, nil +} diff --git a/cmd/identify_lagoonservices_test.go b/internal/identify/identify_lagoonservices_test.go similarity index 65% rename from cmd/identify_lagoonservices_test.go rename to internal/identify/identify_lagoonservices_test.go index 59521a60..220869f0 100644 --- a/cmd/identify_lagoonservices_test.go +++ b/internal/identify/identify_lagoonservices_test.go @@ -1,11 +1,14 @@ -package cmd +package identify import ( + "encoding/json" "os" "reflect" "testing" + "github.com/andreyvit/diff" "github.com/uselagoon/build-deploy-tool/internal/dbaasclient" + "github.com/uselagoon/build-deploy-tool/internal/generator" "github.com/uselagoon/build-deploy-tool/internal/helpers" "github.com/uselagoon/build-deploy-tool/internal/lagoon" "github.com/uselagoon/build-deploy-tool/internal/testdata" @@ -19,7 +22,7 @@ func TestIdentifyLagoonServices(t *testing.T) { name string description string args testdata.TestData - want []identifyServices + want *IdentifyServices }{ { name: "test1 basic deployment", @@ -33,20 +36,12 @@ func TestIdentifyLagoonServices(t *testing.T) { "node": "harbor.example/example-project/main/node@sha256:b2001babafaa8128fe89aa8fd11832cade59931d14c3de5b3ca32e2a010fbaa8", }, }, true), - want: []identifyServices{ - { - Name: "node", - Type: "basic", - Containers: []containers{ - { - Name: "basic", - Ports: []ports{ - {Port: 1234}, - {Port: 8191}, - {Port: 9001}, - }, - }, - }, + want: &IdentifyServices{ + Deployments: []string{ + "node", + }, + Services: []string{ + "node", }, }, }, @@ -66,59 +61,20 @@ func TestIdentifyLagoonServices(t *testing.T) { "varnish": "harbor.example/example-project/main/varnish@sha256:b2001babafaa8128fe89aa8fd11832cade59931d14c3de5b3ca32e2a010fbaa8", }, }, true), - want: []identifyServices{ - { - Name: "cli", - Type: "cli-persistent", - Containers: []containers{ - { - Name: "cli", - Ports: []ports{}, - }, - }, + want: &IdentifyServices{ + Deployments: []string{ + "cli", + "redis", + "varnish", + "nginx-php", }, - { - Name: "redis", - Type: "redis", - Containers: []containers{ - { - Name: "redis", - Ports: []ports{ - {Port: 6379}, - }, - }, - }, + Volumes: []string{ + "nginx-php", }, - { - Name: "varnish", - Type: "varnish", - Containers: []containers{ - { - Name: "varnish", - Ports: []ports{ - {Port: 8080}, - {Port: 6082}, - }, - }, - }, - }, - { - Name: "nginx-php", - Type: "nginx-php-persistent", - Containers: []containers{ - { - Name: "nginx", - Ports: []ports{ - {Port: 8080}, - }, - }, - { - Name: "php", - Ports: []ports{ - {Port: 9000}, - }, - }, - }, + Services: []string{ + "redis", + "varnish", + "nginx-php", }, }, }, @@ -145,59 +101,20 @@ func TestIdentifyLagoonServices(t *testing.T) { }, }, }, true), - want: []identifyServices{ - { - Name: "cli", - Type: "cli-persistent", - Containers: []containers{ - { - Name: "cli", - Ports: []ports{}, - }, - }, + want: &IdentifyServices{ + Deployments: []string{ + "cli", + "redis", + "varnish", + "nginx-php", }, - { - Name: "redis", - Type: "redis", - Containers: []containers{ - { - Name: "redis", - Ports: []ports{ - {Port: 6379}, - }, - }, - }, + Volumes: []string{ + "nginx-php", }, - { - Name: "varnish", - Type: "varnish", - Containers: []containers{ - { - Name: "varnish", - Ports: []ports{ - {Port: 8080}, - {Port: 6082}, - }, - }, - }, - }, - { - Name: "nginx-php", - Type: "nginx-php-persistent", - Containers: []containers{ - { - Name: "nginx", - Ports: []ports{ - {Port: 8080}, - }, - }, - { - Name: "php", - Ports: []ports{ - {Port: 9000}, - }, - }, - }, + Services: []string{ + "redis", + "varnish", + "nginx-php", }, }, }, @@ -223,44 +140,19 @@ func TestIdentifyLagoonServices(t *testing.T) { }, }, }, true), - want: []identifyServices{ - { - Name: "lnd", - Type: "basic-persistent", - Containers: []containers{ - { - Name: "basic", - Ports: []ports{ - {Port: 8080}, - {Port: 10009}, - }, - }, - }, + want: &IdentifyServices{ + Deployments: []string{ + "lnd", + "thunderhub", + "tor", }, - { - Name: "thunderhub", - Type: "basic-persistent", - Containers: []containers{ - { - Name: "basic", - Ports: []ports{ - {Port: 3000}, - }, - }, - }, + Volumes: []string{ + "lnd", }, - { - Name: "tor", - Type: "basic", - Containers: []containers{ - { - Name: "basic", - Ports: []ports{ - {Port: 9050}, - {Port: 9051}, - }, - }, - }, + Services: []string{ + "lnd", + "thunderhub", + "tor", }, }, }, @@ -285,25 +177,52 @@ func TestIdentifyLagoonServices(t *testing.T) { }, }, }, true), - want: []identifyServices{ - { - Name: "lnd", - Type: "basic-persistent", - Containers: []containers{ - {Name: "basic", - Ports: []ports{ - {Port: 8080}, - {Port: 10009}, - }}, - }, + want: &IdentifyServices{ + Deployments: []string{ + "lnd", + "tor", + }, + Volumes: []string{ + "lnd", }, - { - Name: "tor", - Type: "worker-persistent", - Containers: []containers{ - {Name: "worker", - Ports: []ports{}}, + Services: []string{ + "lnd", + }, + }, + }, + + { + name: "test5-complex-custom-volumes", + args: testdata.GetSeedData( + testdata.TestData{ + ProjectName: "example-project", + EnvironmentName: "main", + Branch: "main", + BuildType: "branch", + LagoonYAML: "internal/testdata/complex/lagoon.multiple-volumes.yml", + ImageReferences: map[string]string{ + "nginx": "harbor.example/example-project/main/nginx@sha256:b2001babafaa8128fe89aa8fd11832cade59931d14c3de5b3ca32e2a010fbaa8", + "php": "harbor.example/example-project/main/php@sha256:b2001babafaa8128fe89aa8fd11832cade59931d14c3de5b3ca32e2a010fbaa8", + "cli": "harbor.example/example-project/main/cli@sha256:b2001babafaa8128fe89aa8fd11832cade59931d14c3de5b3ca32e2a010fbaa8", + "nginx2": "harbor.example/example-project/main/nginx2@sha256:b2001babafaa8128fe89aa8fd11832cade59931d14c3de5b3ca32e2a010fbaa8", + "php2": "harbor.example/example-project/main/php2@sha256:b2001babafaa8128fe89aa8fd11832cade59931d14c3de5b3ca32e2a010fbaa8", + "mariadb": "harbor.example/example-project/main/mariadb@sha256:b2001babafaa8128fe89aa8fd11832cade59931d14c3de5b3ca32e2a010fbaa8", }, + }, true), + want: &IdentifyServices{ + Deployments: []string{ + "cli", + "mariadb", + "nginx", + }, + Volumes: []string{ + "mariadb", + "nginx", + "custom-files", + }, + Services: []string{ + "mariadb", + "nginx", }, }, }, @@ -313,7 +232,7 @@ func TestIdentifyLagoonServices(t *testing.T) { helpers.UnsetEnvVars(nil) //unset variables before running tests // set the environment variables from args savedTemplates := "testoutput" - generator, err := testdata.SetupEnvironment(*rootCmd, savedTemplates, tt.args) + generator, err := testdata.SetupEnvironment(generator.GeneratorInput{}, savedTemplates, tt.args) if err != nil { t.Errorf("%v", err) } @@ -332,12 +251,14 @@ func TestIdentifyLagoonServices(t *testing.T) { t.Errorf("%v", err) } - out, err := LagoonServiceTemplateIdentification(generator) + out, _, err := LagoonServiceTemplateIdentification(generator) if err != nil { t.Errorf("%v", err) } if !reflect.DeepEqual(out, tt.want) { - t.Errorf("returned output %v doesn't match want %v", out, tt.want) + r1, _ := json.MarshalIndent(out, "", " ") + s1, _ := json.MarshalIndent(tt.want, "", " ") + t.Errorf("LagoonServiceTemplateIdentification() = \n%v", diff.LineDiff(string(r1), string(s1))) } t.Cleanup(func() { helpers.UnsetEnvVars(nil) diff --git a/internal/identify/identify_state.go b/internal/identify/identify_state.go new file mode 100644 index 00000000..eb773706 --- /dev/null +++ b/internal/identify/identify_state.go @@ -0,0 +1,252 @@ +package identify + +import ( + "context" + "strings" + + mariadbv1 "github.com/amazeeio/dbaas-operator/apis/mariadb/v1" + mongodbv1 "github.com/amazeeio/dbaas-operator/apis/mongodb/v1" + postgresv1 "github.com/amazeeio/dbaas-operator/apis/postgres/v1" + "github.com/uselagoon/build-deploy-tool/internal/collector" + "github.com/uselagoon/build-deploy-tool/internal/generator" + appsv1 "k8s.io/api/apps/v1" + corev1 "k8s.io/api/core/v1" +) + +func GetCurrentState(c *collector.Collector, gen generator.GeneratorInput) ( + LagoonServices, + []mariadbv1.MariaDBConsumer, + []mongodbv1.MongoDBConsumer, + []postgresv1.PostgreSQLConsumer, + []appsv1.Deployment, + []corev1.PersistentVolumeClaim, + []corev1.Service, + *collector.LagoonEnvState, + error, +) { + lagoonServices := LagoonServices{ + Services: []EnvironmentService{}, + Volumes: []EnvironmentVolume{}, + } + out, currentServices, err := LagoonServiceTemplateIdentification(gen) + if err != nil { + return lagoonServices, nil, nil, nil, nil, nil, nil, nil, err + } + + dbaas, err := IdentifyDBaaSConsumers(gen) + if err != nil { + return lagoonServices, nil, nil, nil, nil, nil, nil, nil, err + } + + state, err := c.Collect(context.Background(), gen.Namespace) + if err != nil { + return lagoonServices, nil, nil, nil, nil, nil, nil, nil, err + } + + // add any dbaas that should exist to the current services + for _, prov := range dbaas { + sp := strings.Split(prov, ":") + currentServices.Services = append(currentServices.Services, EnvironmentService{ + Name: sp[0], + Type: sp[1], + }) + } + + mariadbMatch := false + var mariadbDelete []mariadbv1.MariaDBConsumer + for _, exist := range state.MariaDBConsumers.Items { + service := EnvironmentService{ + Name: exist.Name, + Type: "mariadb-dbaas", + } + for _, prov := range dbaas { + sp := strings.Split(prov, ":") + if strings.Contains(sp[1], "mariadb-dbaas") { + if exist.Name == sp[0] { + mariadbMatch = true + continue + } + } + } + if !mariadbMatch { + service.Abandoned = true + mariadbDelete = append(mariadbDelete, exist) + } + mariadbMatch = false + lagoonServices.Services = append(lagoonServices.Services, service) + } + + mongodbMatch := false + var mongodbDelete []mongodbv1.MongoDBConsumer + for _, exist := range state.MongoDBConsumers.Items { + service := EnvironmentService{ + Name: exist.Name, + Type: "mongodb-dbaas", + } + for _, prov := range dbaas { + sp := strings.Split(prov, ":") + if strings.Contains(sp[1], "mongodb-dbaas") { + if exist.Name == sp[0] { + mongodbMatch = true + continue + } + } + } + if !mongodbMatch { + service.Abandoned = true + mongodbDelete = append(mongodbDelete, exist) + } + mongodbMatch = false + lagoonServices.Services = append(lagoonServices.Services, service) + } + + postgresqlMatch := false + var postgresqlDelete []postgresv1.PostgreSQLConsumer + for _, exist := range state.PostgreSQLConsumers.Items { + service := EnvironmentService{ + Name: exist.Name, + Type: "postgres-dbaas", + } + for _, prov := range dbaas { + sp := strings.Split(prov, ":") + if strings.Contains(sp[1], "postgres-dbaas") { + if exist.Name == sp[0] { + postgresqlMatch = true + continue + } + } + } + if !postgresqlMatch { + service.Abandoned = true + postgresqlDelete = append(postgresqlDelete, exist) + } + postgresqlMatch = false + lagoonServices.Services = append(lagoonServices.Services, service) + } + + volMatch := false + var volDelete []corev1.PersistentVolumeClaim + for _, exist := range state.PVCs.Items { + size := exist.Spec.Resources.Requests.Storage + storeType := "block" + if exist.Spec.StorageClassName != nil { + switch *exist.Spec.StorageClassName { + case "bulk": + storeType = "bulk" + } + } + kubevol := EnvironmentVolume{ + Name: exist.Name, + StorageType: storeType, + Type: exist.Labels["lagoon.sh/service-type"], + Size: size().String(), + } + for _, prov := range out.Volumes { + if exist.Name == prov { + volMatch = true + continue + } + } + if !volMatch { + kubevol.Abandoned = true + volDelete = append(volDelete, exist) + } + volMatch = false + lagoonServices.Volumes = append(lagoonServices.Volumes, kubevol) + } + + servMatch := false + var servDelete []corev1.Service + for _, exist := range state.Services.Items { + for _, prov := range out.Services { + if exist.Name == prov { + servMatch = true + continue + } + } + if !servMatch { + servDelete = append(servDelete, exist) + } + servMatch = false + } + + depMatch := false + var depDelete []appsv1.Deployment + for _, exist := range state.Deployments.Items { + containers := []ServiceContainer{} + for _, c := range exist.Spec.Template.Spec.Containers { + volumes := []VolumeMount{} + for _, v := range c.VolumeMounts { + for _, vo := range lagoonServices.Volumes { + if vo.Name == v.Name { + volumes = append(volumes, VolumeMount{ + Name: v.Name, + Path: v.MountPath, + }) + } + } + } + ports := []ContainerPort{} + for _, p := range c.Ports { + ports = append(ports, ContainerPort{ + Name: p.Name, + Port: int(p.ContainerPort), + }) + } + containers = append(containers, ServiceContainer{ + Name: c.Name, + Volumes: volumes, + Ports: ports, + }) + } + service := EnvironmentService{ + Name: exist.Name, + Type: exist.Labels["lagoon.sh/service-type"], + Containers: containers, + } + for _, prov := range out.Deployments { + if exist.Name == prov { + depMatch = true + continue + } + } + if !depMatch { + service.Abandoned = true + depDelete = append(depDelete, exist) + } + depMatch = false + lagoonServices.Services = append(lagoonServices.Services, service) + } + + for _, svc := range currentServices.Services { + if !serviceExists(lagoonServices.Services, svc.Name) { + lagoonServices.Services = append(lagoonServices.Services, svc) + } + } + + for _, vol := range currentServices.Volumes { + if !volumeExists(lagoonServices.Volumes, vol.Name) { + lagoonServices.Volumes = append(lagoonServices.Volumes, vol) + } + } + + return lagoonServices, mariadbDelete, mongodbDelete, postgresqlDelete, depDelete, volDelete, servDelete, state, nil +} + +func serviceExists(services []EnvironmentService, serviceName string) bool { + for _, svc := range services { + if svc.Name == serviceName { + return true + } + } + return false +} + +func volumeExists(volumes []EnvironmentVolume, volumeName string) bool { + for _, vol := range volumes { + if vol.Name == volumeName { + return true + } + } + return false +} diff --git a/internal/identify/identify_state_test.go b/internal/identify/identify_state_test.go new file mode 100644 index 00000000..bbd7ac00 --- /dev/null +++ b/internal/identify/identify_state_test.go @@ -0,0 +1,543 @@ +package identify + +import ( + "encoding/json" + "os" + "reflect" + "testing" + + "github.com/andreyvit/diff" + "github.com/uselagoon/build-deploy-tool/internal/collector" + "github.com/uselagoon/build-deploy-tool/internal/dbaasclient" + "github.com/uselagoon/build-deploy-tool/internal/generator" + "github.com/uselagoon/build-deploy-tool/internal/helpers" + "github.com/uselagoon/build-deploy-tool/internal/k8s" + "github.com/uselagoon/build-deploy-tool/internal/testdata" + + // changes the testing to source from root so paths to test resources must be defined from repo root + _ "github.com/uselagoon/build-deploy-tool/internal/testing" +) + +func TestGetCurrentState(t *testing.T) { + tests := []struct { + name string + namespace string + args testdata.TestData + deleteServices bool + wantErr bool + seedDir string + wantServices LagoonServices + }{ + { + name: "basic-deployment", + args: testdata.GetSeedData( + testdata.TestData{ + ProjectName: "example-project", + EnvironmentName: "main", + Branch: "main", + LagoonYAML: "internal/testdata/basic/lagoon.yml", + ImageReferences: map[string]string{ + "node": "harbor.example/example-project/main/node@sha256:b2001babafaa8128fe89aa8fd11832cade59931d14c3de5b3ca32e2a010fbaa8", + }, + }, true), + deleteServices: true, + namespace: "example-project-main", + seedDir: "internal/testdata/basic/cleanup-seed/basic-deployment", + wantServices: LagoonServices{ + Services: []EnvironmentService{ + { + Name: "mariadb", + Type: "mariadb-dbaas", + Abandoned: true, + }, + { + Name: "basic", + Type: "basic", + Abandoned: true, + Containers: []ServiceContainer{ + { + Name: "basic", + Ports: []ContainerPort{ + { + Name: "tcp-1234", + Port: 1234, + }, + { + Name: "tcp-8191", + Port: 8191, + }, + { + Name: "udp-9001", + Port: 9001, + }, + }, + }, + }, + }, + { + Name: "node", + Type: "basic", + Containers: []ServiceContainer{ + { + Name: "basic", + Ports: []ContainerPort{ + { + Name: "tcp-1234", + Port: 1234, + }, + { + Name: "tcp-8191", + Port: 8191, + }, + { + Name: "udp-9001", + Port: 9001, + }, + }, + }, + }, + }, + }, + }, + }, + { + name: "multivolumes", + args: testdata.GetSeedData( + testdata.TestData{ + ProjectName: "example-project", + EnvironmentName: "main", + Branch: "main", + LagoonYAML: "internal/testdata/basic/lagoon.multiple-volumes.yml", + ImageReferences: map[string]string{ + "node": "harbor.example/example-project/main/node@sha256:b2001babafaa8128fe89aa8fd11832cade59931d14c3de5b3ca32e2a010fbaa8", + }, + }, true), + deleteServices: false, + namespace: "example-project-main", + seedDir: "internal/testdata/basic/service-templates/test12-basic-persistent-custom-volumes", + wantServices: LagoonServices{ + Services: []EnvironmentService{ + { + Name: "node", + Type: "basic-persistent", + Containers: []ServiceContainer{ + { + Name: "basic", + Volumes: []VolumeMount{ + { + Name: "custom-config", + Path: "/config", + }, + { + Name: "custom-files", + Path: "/app/files/", + }, + { + Name: "node", + Path: "/data", + }, + }, + Ports: []ContainerPort{ + { + Name: "http", + Port: 3000, + }, + }, + }, + }, + }, + }, + Volumes: []EnvironmentVolume{ + { + Name: "custom-config", + StorageType: "bulk", + Type: "additional-volume", + Size: "5Gi", + }, + { + Name: "custom-files", + StorageType: "bulk", + Type: "additional-volume", + Size: "10Gi", + }, + { + Name: "node", + StorageType: "bulk", + Type: "basic-persistent", + Size: "5Gi", + }, + }, + }, + }, + { + name: "complex-singles", + args: testdata.GetSeedData( + testdata.TestData{ + ProjectName: "example-project", + EnvironmentName: "main", + Branch: "main", + LagoonYAML: "internal/testdata/complex/lagoon.services.yml", + ImageReferences: map[string]string{ + "web": "harbor.example/example-project/main/web@sha256:b2001babafaa8128fe89aa8fd11832cade59931d14c3de5b3ca32e2a010fbaa8", + "mariadb-10-5": "harbor.example/example-project/main/mariadb-10-5@sha256:b2001babafaa8128fe89aa8fd11832cade59931d14c3de5b3ca32e2a010fbaa8", + "postgres-11": "harbor.example/example-project/main/postgres-11@sha256:b2001babafaa8128fe89aa8fd11832cade59931d14c3de5b3ca32e2a010fbaa8", + "opensearch-2": "harbor.example/example-project/main/opensearch-2@sha256:b2001babafaa8128fe89aa8fd11832cade59931d14c3de5b3ca32e2a010fbaa8", + "redis-6": "harbor.example/example-project/main/redis-6@sha256:b2001babafaa8128fe89aa8fd11832cade59931d14c3de5b3ca32e2a010fbaa8", + "redis-7": "harbor.example/example-project/main/redis-7@sha256:b2001babafaa8128fe89aa8fd11832cade59931d14c3de5b3ca32e2a010fbaa8", + "solr-8": "harbor.example/example-project/main/solr-8@sha256:b2001babafaa8128fe89aa8fd11832cade59931d14c3de5b3ca32e2a010fbaa8", + }, + }, true), + deleteServices: false, + namespace: "example-project-main", + seedDir: "internal/testdata/complex/service-templates/test8-multiple-services", + wantServices: LagoonServices{ + Services: []EnvironmentService{ + { + Name: "mariadb-10-5", + Type: "mariadb-single", + Containers: []ServiceContainer{ + { + Name: "mariadb-single", + Volumes: []VolumeMount{ + { + Name: "mariadb-10-5", + Path: "/var/lib/mysql", + }, + }, + Ports: []ContainerPort{ + { + Name: "3306-tcp", + Port: 3306, + }, + }, + }, + }, + }, + { + Name: "opensearch-2", + Type: "opensearch-persistent", + Containers: []ServiceContainer{ + { + Name: "opensearch", + Volumes: []VolumeMount{ + { + Name: "opensearch-2", + Path: "/usr/share/opensearch/data", + }, + }, + Ports: []ContainerPort{ + { + Name: "9200-tcp", + Port: 9200, + }, + }, + }, + }, + }, + { + Name: "postgres-11", + Type: "postgres-single", + Containers: []ServiceContainer{ + { + Name: "postgres-single", + Volumes: []VolumeMount{ + { + Name: "postgres-11", + Path: "/var/lib/postgresql/data", + }, + }, + Ports: []ContainerPort{ + { + Name: "5432-tcp", + Port: 5432, + }, + }, + }, + }, + }, + { + Name: "redis-6", + Type: "redis", + Containers: []ServiceContainer{ + { + Name: "redis", + Ports: []ContainerPort{ + { + Name: "6379-tcp", + Port: 6379, + }, + }, + }, + }, + }, + { + Name: "redis-7", + Type: "redis", + Containers: []ServiceContainer{ + { + Name: "redis", + Ports: []ContainerPort{ + { + Name: "6379-tcp", + Port: 6379, + }, + }, + }, + }, + }, + { + Name: "solr-8", + Type: "solr-php-persistent", + Containers: []ServiceContainer{ + { + Name: "solr", + Volumes: []VolumeMount{ + { + Name: "solr-8", + Path: "/var/solr", + }, + }, + Ports: []ContainerPort{ + { + Name: "8983-tcp", + Port: 8983, + }, + }, + }, + }, + }, + { + Name: "web", + Type: "basic-persistent", + Containers: []ServiceContainer{ + { + Name: "basic", + Volumes: []VolumeMount{ + { + Name: "web", + Path: "/app/files", + }, + }, + Ports: []ContainerPort{ + { + Name: "http", + Port: 3000, + }, + }, + }, + }, + }, + { + Name: "mariadb-10-11", + Type: "mariadb-dbaas", + }, + { + Name: "postgres-15", + Type: "postgres-dbaas", + }, + { + Name: "mongo-4", + Type: "mongodb-dbaas", + }, + }, + Volumes: []EnvironmentVolume{ + { + Name: "mariadb-10-5", + StorageType: "block", + Type: "mariadb-single", + Size: "100Mi", + }, + { + Name: "opensearch-2", + StorageType: "block", + Type: "opensearch-persistent", + Size: "100Mi", + }, + { + Name: "postgres-11", + StorageType: "block", + Type: "postgres-single", + Size: "100Mi", + }, + { + Name: "solr-8", + StorageType: "block", + Type: "solr-php-persistent", + Size: "100Mi", + }, + { + Name: "web", + StorageType: "bulk", + Type: "basic-persistent", + Size: "10Mi", + }, + }, + }, + }, + { + name: "complex-nginx", + args: testdata.GetSeedData( + testdata.TestData{ + ProjectName: "example-project", + EnvironmentName: "main", + Branch: "main", + LagoonYAML: "internal/testdata/complex/lagoon.varnish.yml", + ImageReferences: map[string]string{ + "nginx": "harbor.example/example-project/main/nginx@sha256:b2001babafaa8128fe89aa8fd11832cade59931d14c3de5b3ca32e2a010fbaa8", + "php": "harbor.example/example-project/main/php@sha256:b2001babafaa8128fe89aa8fd11832cade59931d14c3de5b3ca32e2a010fbaa8", + "cli": "harbor.example/example-project/main/cli@sha256:b2001babafaa8128fe89aa8fd11832cade59931d14c3de5b3ca32e2a010fbaa8", + "redis": "harbor.example/example-project/main/redis@sha256:b2001babafaa8128fe89aa8fd11832cade59931d14c3de5b3ca32e2a010fbaa8", + "varnish": "harbor.example/example-project/main/varnish@sha256:b2001babafaa8128fe89aa8fd11832cade59931d14c3de5b3ca32e2a010fbaa8", + }, + }, true), + deleteServices: false, + namespace: "example-project-main", + seedDir: "internal/testdata/complex/service-templates/test2-nginx-php", + wantServices: LagoonServices{ + Services: []EnvironmentService{ + { + Name: "cli", + Type: "cli-persistent", + Containers: []ServiceContainer{ + { + Name: "cli", + Volumes: []VolumeMount{ + { + Name: "nginx-php", + Path: "/app/docroot/sites/default/files/", + }, + }, + }, + }, + }, + { + Name: "nginx-php", + Type: "nginx-php-persistent", + Containers: []ServiceContainer{ + { + Name: "nginx", + Volumes: []VolumeMount{ + { + Name: "nginx-php", + Path: "/app/docroot/sites/default/files/", + }, + }, + Ports: []ContainerPort{ + { + Name: "http", + Port: 8080, + }, + }, + }, + { + Name: "php", + Volumes: []VolumeMount{ + { + Name: "nginx-php", + Path: "/app/docroot/sites/default/files/", + }, + }, + Ports: []ContainerPort{ + { + Name: "php", + Port: 9000, + }, + }, + }, + }, + }, + { + Name: "redis", + Type: "redis", + Containers: []ServiceContainer{ + { + Name: "redis", + Ports: []ContainerPort{ + { + Name: "6379-tcp", + Port: 6379, + }, + }, + }, + }, + }, + { + Name: "varnish", + Type: "varnish", + Containers: []ServiceContainer{ + { + Name: "varnish", + Ports: []ContainerPort{ + { + Name: "http", + Port: 8080, + }, + { + Name: "controlport", + Port: 6082, + }, + }, + }, + }, + }, + { + Name: "mariadb", + Type: "mariadb-dbaas", + }, + }, + Volumes: []EnvironmentVolume{ + { + Name: "nginx-php", + StorageType: "bulk", + Type: "nginx-php-persistent", + Size: "5Gi", + }, + }, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + helpers.UnsetEnvVars(nil) //unset variables before running tests + // set the environment variables from args + savedTemplates := "testoutput" + generator, err := testdata.SetupEnvironment(generator.GeneratorInput{}, savedTemplates, tt.args) + if err != nil { + t.Errorf("%v", err) + } + + err = os.MkdirAll(savedTemplates, 0755) + if err != nil { + t.Errorf("couldn't create directory %v: %v", savedTemplates, err) + } + + defer os.RemoveAll(savedTemplates) + + ts := dbaasclient.TestDBaaSHTTPServer() + defer ts.Close() + err = os.Setenv("DBAAS_OPERATOR_HTTP", ts.URL) + if err != nil { + t.Errorf("%v", err) + } + + client, err := k8s.NewFakeClient(tt.namespace) + if err != nil { + t.Errorf("error creating fake client") + } + err = k8s.SeedFakeData(client, tt.namespace, tt.seedDir) + if err != nil { + t.Errorf("error seeding fake data: %v", err) + } + col := collector.NewCollector(client) + lagoonServices, _, _, _, _, _, _, _, err := GetCurrentState(col, generator) + if err != nil { + t.Errorf("GetCurrentState() %v ", err) + } + r1, _ := json.MarshalIndent(lagoonServices, "", " ") + s1, _ := json.MarshalIndent(tt.wantServices, "", " ") + if !reflect.DeepEqual(r1, s1) { + t.Errorf("GetCurrentState() = \n%v", diff.LineDiff(string(s1), string(r1))) + } + }) + } +} diff --git a/internal/testdata/basic/cleanup-seed/basic-deployment/cronjob-cronjob-basic-env.yaml b/internal/testdata/basic/cleanup-seed/basic-deployment/cronjob-cronjob-basic-env.yaml new file mode 100644 index 00000000..17cc237b --- /dev/null +++ b/internal/testdata/basic/cleanup-seed/basic-deployment/cronjob-cronjob-basic-env.yaml @@ -0,0 +1,90 @@ +--- +apiVersion: batch/v1 +kind: CronJob +metadata: + annotations: + lagoon.sh/branch: main + lagoon.sh/version: v2.7.x + creationTimestamp: null + labels: + app.kubernetes.io/instance: cronjob-basic + app.kubernetes.io/managed-by: build-deploy-tool + app.kubernetes.io/name: cronjob-basic + lagoon.sh/buildType: branch + lagoon.sh/environment: main + lagoon.sh/environmentType: production + lagoon.sh/project: example-project + lagoon.sh/service: basic + lagoon.sh/service-type: basic + lagoon.sh/template: basic-0.1.0 + name: cronjob-basic-env +spec: + concurrencyPolicy: Forbid + failedJobsHistoryLimit: 1 + jobTemplate: + metadata: + creationTimestamp: null + spec: + template: + metadata: + annotations: + lagoon.sh/branch: main + lagoon.sh/configMapSha: abcdefg1234567890 + lagoon.sh/version: v2.7.x + creationTimestamp: null + labels: + app.kubernetes.io/instance: cronjob-basic + app.kubernetes.io/managed-by: build-deploy-tool + app.kubernetes.io/name: cronjob-basic + lagoon.sh/buildType: branch + lagoon.sh/environment: main + lagoon.sh/environmentType: production + lagoon.sh/project: example-project + lagoon.sh/service: basic + lagoon.sh/service-type: basic + lagoon.sh/template: basic-0.1.0 + spec: + containers: + - command: + - /lagoon/cronjob.sh + - env + env: + - name: LAGOON_GIT_SHA + value: "0000000000000000000000000000000000000000" + - name: SERVICE_NAME + value: basic + envFrom: + - configMapRef: + name: lagoon-env + image: harbor.example/example-project/main/basic@sha256:b2001babafaa8128fe89aa8fd11832cade59931d14c3de5b3ca32e2a010fbaa8 + imagePullPolicy: Always + name: cronjob-basic-env + resources: + requests: + cpu: 10m + memory: 10Mi + securityContext: {} + volumeMounts: + - mountPath: /var/run/secrets/lagoon/sshkey/ + name: lagoon-sshkey + readOnly: true + dnsConfig: + options: + - name: timeout + value: "60" + - name: attempts + value: "10" + enableServiceLinks: false + imagePullSecrets: + - name: lagoon-internal-registry-secret + priorityClassName: lagoon-priority-production + restartPolicy: Never + volumes: + - name: lagoon-sshkey + secret: + defaultMode: 420 + secretName: lagoon-sshkey + schedule: 18,48 * * * * + startingDeadlineSeconds: 240 + successfulJobsHistoryLimit: 0 +status: {} diff --git a/internal/testdata/basic/cleanup-seed/basic-deployment/deployment-basic.yaml b/internal/testdata/basic/cleanup-seed/basic-deployment/deployment-basic.yaml new file mode 100644 index 00000000..f036a7e4 --- /dev/null +++ b/internal/testdata/basic/cleanup-seed/basic-deployment/deployment-basic.yaml @@ -0,0 +1,93 @@ +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + annotations: + lagoon.sh/branch: main + lagoon.sh/version: v2.7.x + creationTimestamp: null + labels: + app.kubernetes.io/instance: basic + app.kubernetes.io/managed-by: build-deploy-tool + app.kubernetes.io/name: basic + lagoon.sh/buildType: branch + lagoon.sh/environment: main + lagoon.sh/environmentType: production + lagoon.sh/project: example-project + lagoon.sh/service: basic + lagoon.sh/service-type: basic + lagoon.sh/template: basic-0.1.0 + name: basic +spec: + replicas: 1 + selector: + matchLabels: + app.kubernetes.io/instance: basic + app.kubernetes.io/name: basic + strategy: {} + template: + metadata: + annotations: + lagoon.sh/branch: main + lagoon.sh/configMapSha: abcdefg1234567890 + lagoon.sh/version: v2.7.x + creationTimestamp: null + labels: + app.kubernetes.io/instance: basic + app.kubernetes.io/managed-by: build-deploy-tool + app.kubernetes.io/name: basic + lagoon.sh/buildType: branch + lagoon.sh/environment: main + lagoon.sh/environmentType: production + lagoon.sh/project: example-project + lagoon.sh/service: basic + lagoon.sh/service-type: basic + lagoon.sh/template: basic-0.1.0 + spec: + containers: + - env: + - name: LAGOON_GIT_SHA + value: abcdefg123456 + - name: CRONJOBS + - name: SERVICE_NAME + value: basic + envFrom: + - configMapRef: + name: lagoon-env + image: harbor.example/example-project/main/basic@sha256:b2001babafaa8128fe89aa8fd11832cade59931d14c3de5b3ca32e2a010fbaa8 + imagePullPolicy: Always + livenessProbe: + initialDelaySeconds: 60 + tcpSocket: + port: 1234 + timeoutSeconds: 10 + name: basic + ports: + - containerPort: 1234 + name: tcp-1234 + protocol: TCP + - containerPort: 8191 + name: tcp-8191 + protocol: TCP + - containerPort: 9001 + name: udp-9001 + protocol: UDP + readinessProbe: + initialDelaySeconds: 1 + tcpSocket: + port: 1234 + timeoutSeconds: 1 + resources: + requests: + cpu: 10m + memory: 10Mi + securityContext: {} + enableServiceLinks: false + imagePullSecrets: + - name: lagoon-internal-registry-secret + - name: lagoon-private-registry-dockerhub + - name: lagoon-private-registry-my-custom-registry + - name: lagoon-private-registry-my-hardcode-registry + - name: lagoon-private-registry-my-other-registry + priorityClassName: lagoon-priority-production +status: {} diff --git a/internal/testdata/basic/cleanup-seed/basic-deployment/ingress-basic.yaml b/internal/testdata/basic/cleanup-seed/basic-deployment/ingress-basic.yaml new file mode 100644 index 00000000..2be080e8 --- /dev/null +++ b/internal/testdata/basic/cleanup-seed/basic-deployment/ingress-basic.yaml @@ -0,0 +1,47 @@ +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + annotations: + fastly.amazee.io/watch: "false" + idling.amazee.io/disable-request-verification: "false" + ingress.kubernetes.io/ssl-redirect: "true" + kubernetes.io/tls-acme: "true" + lagoon.sh/branch: main + lagoon.sh/version: v2.7.x + monitor.stakater.com/enabled: "false" + nginx.ingress.kubernetes.io/server-snippet: | + add_header X-Robots-Tag "noindex, nofollow"; + nginx.ingress.kubernetes.io/ssl-redirect: "true" + creationTimestamp: null + labels: + app.kubernetes.io/instance: basic + app.kubernetes.io/managed-by: build-deploy-tool + app.kubernetes.io/name: autogenerated-ingress + lagoon.sh/autogenerated: "true" + lagoon.sh/buildType: branch + lagoon.sh/environment: main + lagoon.sh/environmentType: production + lagoon.sh/project: example-project + lagoon.sh/service: basic + lagoon.sh/service-type: basic + lagoon.sh/template: autogenerated-ingress-0.1.0 + name: basic +spec: + rules: + - host: basic-example-project-main.example.com + http: + paths: + - backend: + service: + name: basic + port: + name: http + path: / + pathType: Prefix + tls: + - hosts: + - basic-example-project-main.example.com + secretName: basic-tls +status: + loadBalancer: {} diff --git a/internal/testdata/basic/cleanup-seed/basic-deployment/ingress-example.com.yaml b/internal/testdata/basic/cleanup-seed/basic-deployment/ingress-example.com.yaml new file mode 100644 index 00000000..bb27ab4d --- /dev/null +++ b/internal/testdata/basic/cleanup-seed/basic-deployment/ingress-example.com.yaml @@ -0,0 +1,52 @@ +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + annotations: + fastly.amazee.io/service-id: service-id + fastly.amazee.io/watch: "true" + idling.amazee.io/disable-request-verification: "false" + ingress.kubernetes.io/ssl-redirect: "true" + kubernetes.io/tls-acme: "true" + lagoon.sh/branch: main + lagoon.sh/version: v2.7.x + monitor.stakater.com/enabled: "true" + monitor.stakater.com/overridePath: / + nginx.ingress.kubernetes.io/ssl-redirect: "true" + uptimerobot.monitor.stakater.com/alert-contacts: alertcontact + uptimerobot.monitor.stakater.com/interval: "60" + uptimerobot.monitor.stakater.com/status-pages: statuspageid + creationTimestamp: null + labels: + activestandby.lagoon.sh/migrate: "false" + app.kubernetes.io/instance: example.com + app.kubernetes.io/managed-by: build-deploy-tool + app.kubernetes.io/name: custom-ingress + lagoon.sh/autogenerated: "false" + lagoon.sh/buildType: branch + lagoon.sh/environment: main + lagoon.sh/environmentType: production + lagoon.sh/primaryIngress: "true" + lagoon.sh/project: example-project + lagoon.sh/service: example.com + lagoon.sh/service-type: custom-ingress + lagoon.sh/template: custom-ingress-0.1.0 + name: example.com +spec: + rules: + - host: example.com + http: + paths: + - backend: + service: + name: node + port: + name: http + path: / + pathType: Prefix + tls: + - hosts: + - example.com + secretName: example.com-tls +status: + loadBalancer: {} diff --git a/internal/testdata/basic/cleanup-seed/basic-deployment/k8up-lagoon-backup-schedule.yaml b/internal/testdata/basic/cleanup-seed/basic-deployment/k8up-lagoon-backup-schedule.yaml new file mode 100644 index 00000000..69632bcf --- /dev/null +++ b/internal/testdata/basic/cleanup-seed/basic-deployment/k8up-lagoon-backup-schedule.yaml @@ -0,0 +1,41 @@ +--- +apiVersion: backup.appuio.ch/v1alpha1 +kind: Schedule +metadata: + annotations: + lagoon.sh/branch: main + lagoon.sh/version: v2.7.x + creationTimestamp: null + labels: + app.kubernetes.io/instance: k8up-lagoon-backup-schedule + app.kubernetes.io/managed-by: build-deploy-tool + app.kubernetes.io/name: k8up-schedule + lagoon.sh/buildType: branch + lagoon.sh/environment: main + lagoon.sh/environmentType: production + lagoon.sh/project: example-project + lagoon.sh/service: k8up-lagoon-backup-schedule + lagoon.sh/service-type: k8up-schedule + lagoon.sh/template: k8up-schedule-0.1.0 + name: k8up-lagoon-backup-schedule +spec: + backend: + repoPasswordSecretRef: + key: repo-pw + name: baas-repo-pw + s3: + bucket: baas-example-project + backup: + resources: {} + schedule: 48 22 * * * + check: + resources: {} + schedule: 48 5 * * 1 + prune: + resources: {} + retention: + keepDaily: 7 + keepWeekly: 6 + schedule: 48 3 * * 0 + resourceRequirementsTemplate: {} +status: {} diff --git a/internal/testdata/basic/cleanup-seed/basic-deployment/mariadbconsumer-mariadb.yaml b/internal/testdata/basic/cleanup-seed/basic-deployment/mariadbconsumer-mariadb.yaml new file mode 100644 index 00000000..d817a91d --- /dev/null +++ b/internal/testdata/basic/cleanup-seed/basic-deployment/mariadbconsumer-mariadb.yaml @@ -0,0 +1,34 @@ +--- +apiVersion: mariadb.amazee.io/v1 +kind: MariaDBConsumer +metadata: + annotations: + lagoon.sh/branch: main + lagoon.sh/version: v2.7.x + creationTimestamp: null + labels: + app.kubernetes.io/instance: mariadb + app.kubernetes.io/managed-by: build-deploy-tool + app.kubernetes.io/name: mariadb-dbaas + lagoon.sh/buildType: branch + lagoon.sh/environment: main + lagoon.sh/environmentType: production + lagoon.sh/project: lagoon-demo + lagoon.sh/service: mariadb + lagoon.sh/service-type: mariadb-dbaas + lagoon.sh/template: mariadb-dbaas-0.1.0 + name: mariadb +spec: + consumer: + database: lagoon-demo-mainabc + password: abcdefghijklmnop + services: + primary: mariadb-6e7da79a-5609-4b57-9c4f-3d6fd4bd0dda + username: lagoon-qrs + environment: production + provider: + hostname: mariadb.mariadb.svc.cluster.local + name: lagoon-remote-dbaas-operator-production + namespace: lagoon + port: '3306' +status: {} diff --git a/internal/testdata/basic/cleanup-seed/basic-deployment/prebackuppod-mariadb.yaml b/internal/testdata/basic/cleanup-seed/basic-deployment/prebackuppod-mariadb.yaml new file mode 100644 index 00000000..7212b498 --- /dev/null +++ b/internal/testdata/basic/cleanup-seed/basic-deployment/prebackuppod-mariadb.yaml @@ -0,0 +1,56 @@ +--- +apiVersion: backup.appuio.ch/v1alpha1 +kind: PreBackupPod +metadata: + annotations: + lagoon.sh/branch: main + lagoon.sh/version: v2.7.x + creationTimestamp: null + labels: + app.kubernetes.io/instance: mariadb + app.kubernetes.io/managed-by: build-deploy-tool + app.kubernetes.io/name: mariadb-dbaas + lagoon.sh/buildType: branch + lagoon.sh/environment: main + lagoon.sh/environmentType: production + lagoon.sh/project: example-project + lagoon.sh/service: mariadb + lagoon.sh/service-type: mariadb-dbaas + prebackuppod: mariadb + name: mariadb-prebackuppod +spec: + backupCommand: | + /bin/sh -c "if [ ! -z $BACKUP_DB_READREPLICA_HOSTS ]; then BACKUP_DB_HOST=$(echo $BACKUP_DB_READREPLICA_HOSTS | cut -d ',' -f1); fi && dump=$(mktemp) && mysqldump --max-allowed-packet=1G --events --routines --quick --add-locks --no-autocommit --single-transaction --no-create-db --no-data --no-tablespaces -h $BACKUP_DB_HOST -u $BACKUP_DB_USERNAME -p$BACKUP_DB_PASSWORD $BACKUP_DB_DATABASE > $dump && mysqldump --max-allowed-packet=1G --events --routines --quick --add-locks --no-autocommit --single-transaction --no-create-db --ignore-table=$BACKUP_DB_DATABASE.watchdog --no-create-info --no-tablespaces --skip-triggers -h $BACKUP_DB_HOST -u $BACKUP_DB_USERNAME -p$BACKUP_DB_PASSWORD $BACKUP_DB_DATABASE >> $dump && cat $dump && rm $dump" + fileExtension: .mariadb.sql + pod: + metadata: {} + spec: + containers: + - args: + - sleep + - infinity + env: + - name: BACKUP_DB_HOST + valueFrom: + configMapKeyRef: + key: MARIADB_HOST + name: lagoon-env + - name: BACKUP_DB_USERNAME + valueFrom: + configMapKeyRef: + key: MARIADB_USERNAME + name: lagoon-env + - name: BACKUP_DB_PASSWORD + valueFrom: + configMapKeyRef: + key: MARIADB_PASSWORD + name: lagoon-env + - name: BACKUP_DB_DATABASE + valueFrom: + configMapKeyRef: + key: MARIADB_DATABASE + name: lagoon-env + image: imagecache.example.com/uselagoon/database-tools:latest + imagePullPolicy: Always + name: mariadb-prebackuppod + resources: {} diff --git a/internal/testdata/basic/cleanup-seed/basic-deployment/service-basic.yaml b/internal/testdata/basic/cleanup-seed/basic-deployment/service-basic.yaml new file mode 100644 index 00000000..37e05b28 --- /dev/null +++ b/internal/testdata/basic/cleanup-seed/basic-deployment/service-basic.yaml @@ -0,0 +1,39 @@ +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + lagoon.sh/branch: main + lagoon.sh/version: v2.7.x + creationTimestamp: null + labels: + app.kubernetes.io/instance: basic + app.kubernetes.io/managed-by: build-deploy-tool + app.kubernetes.io/name: basic + lagoon.sh/buildType: branch + lagoon.sh/environment: main + lagoon.sh/environmentType: production + lagoon.sh/project: example-project + lagoon.sh/service: basic + lagoon.sh/service-type: basic + lagoon.sh/template: basic-0.1.0 + name: basic +spec: + ports: + - name: tcp-1234 + port: 1234 + protocol: TCP + targetPort: tcp-1234 + - name: tcp-8191 + port: 8191 + protocol: TCP + targetPort: tcp-8191 + - name: udp-9001 + port: 9001 + protocol: UDP + targetPort: udp-9001 + selector: + app.kubernetes.io/instance: basic + app.kubernetes.io/name: basic +status: + loadBalancer: {} diff --git a/internal/testdata/testdata.go b/internal/testdata/testdata.go index 6ee3af60..5befe555 100644 --- a/internal/testdata/testdata.go +++ b/internal/testdata/testdata.go @@ -6,7 +6,6 @@ import ( "strings" "time" - "github.com/spf13/cobra" "github.com/uselagoon/build-deploy-tool/internal/dbaasclient" generator "github.com/uselagoon/build-deploy-tool/internal/generator" "github.com/uselagoon/build-deploy-tool/internal/helpers" @@ -64,7 +63,7 @@ type TestData struct { } // helper function to set up all the environment variables from provided testdata -func SetupEnvironment(rootCmd cobra.Command, templatePath string, t TestData) (generator.GeneratorInput, error) { +func SetupEnvironment(genInput generator.GeneratorInput, templatePath string, t TestData) (generator.GeneratorInput, error) { err := os.Setenv("MONITORING_ALERTCONTACT", t.AlertContact) if err != nil { return generator.GeneratorInput{}, err @@ -207,27 +206,24 @@ func SetupEnvironment(rootCmd cobra.Command, templatePath string, t TestData) (g return generator.GeneratorInput{}, err } } - - generator, err := generator.GenerateInput(rootCmd, false) - if err != nil { - return generator, err - } - generator.LagoonYAML = t.LagoonYAML - generator.ImageReferences = t.ImageReferences - generator.ConfigMapSha = t.ConfigMapSha - generator.SavedTemplatesPath = templatePath + genInput.IgnoreMissingEnvFiles = true + genInput.IgnoreNonStringKeyErrors = true + genInput.LagoonYAML = t.LagoonYAML + genInput.ImageReferences = t.ImageReferences + genInput.ConfigMapSha = t.ConfigMapSha + genInput.SavedTemplatesPath = templatePath // add dbaasclient overrides for tests - generator.DBaaSClient = dbaasclient.NewClient(dbaasclient.Client{ + genInput.DBaaSClient = dbaasclient.NewClient(dbaasclient.Client{ RetryMax: 5, RetryWaitMin: time.Duration(10) * time.Millisecond, RetryWaitMax: time.Duration(50) * time.Millisecond, }) - generator.Namespace = namespace.GenerateNamespaceName("", t.EnvironmentName, t.ProjectName, "", "lagoon", false) + genInput.Namespace = namespace.GenerateNamespaceName("", t.EnvironmentName, t.ProjectName, "", "lagoon", false) - generator.BackupConfiguration.K8upVersion = t.K8UPVersion + genInput.BackupConfiguration.K8upVersion = t.K8UPVersion - return generator, nil + return genInput, nil } func GetSeedData(t TestData, defaultProjectVariables bool) TestData { diff --git a/legacy/build-deploy-docker-compose.sh b/legacy/build-deploy-docker-compose.sh index 0880467a..f6ecc6bd 100755 --- a/legacy/build-deploy-docker-compose.sh +++ b/legacy/build-deploy-docker-compose.sh @@ -230,22 +230,20 @@ buildStartTime="$(date +"%Y-%m-%d %H:%M:%S")" ### COLLECT INFORMATION ############################################## # run the collector -# @TODO: uncomment when collector is introduced -# @TODO: don't run the collector yet, leave this as placeholder to prevent possible introduction of issues -# ENVIRONMENT_DATA=$(build-deploy-tool collect environment) -# echo "$ENVIRONMENT_DATA" | jq -r '.deployments.items[]?.name' -# echo "$ENVIRONMENT_DATA" | jq -r '.cronjobs.items[]?.name' -# echo "$ENVIRONMENT_DATA" | jq -r '.ingress.items[]?.name' -# echo "$ENVIRONMENT_DATA" | jq -r '.services.items[]?.name' -# echo "$ENVIRONMENT_DATA" | jq -r '.secrets.items[]?.name' -# echo "$ENVIRONMENT_DATA" | jq -r '.pvcs.items[]?.name' -# echo "$ENVIRONMENT_DATA" | jq -r '.schedulesv1.items[]?.name' -# echo "$ENVIRONMENT_DATA" | jq -r '.schedulesv1alpha1.items[]?.name' -# echo "$ENVIRONMENT_DATA" | jq -r '.prebackuppodsv1.items[]?.name' -# echo "$ENVIRONMENT_DATA" | jq -r '.prebackuppodsv1alpha1.items[]?.name' -# echo "$ENVIRONMENT_DATA" | jq -r '.mariadbconsumers.items[]?.name' -# echo "$ENVIRONMENT_DATA" | jq -r '.mongodbconsumers.items[]?.name' -# echo "$ENVIRONMENT_DATA" | jq -r '.postgresqlconsumers.items[]?.name' +ENVIRONMENT_DATA=$(build-deploy-tool collect environment) +# echo "$ENVIRONMENT_DATA" | jq -r '.deployments.items[]?.metadata.name' +# echo "$ENVIRONMENT_DATA" | jq -r '.cronjobs.items[]?.metadata.name' +# echo "$ENVIRONMENT_DATA" | jq -r '.ingress.items[]?.metadata.name' +# echo "$ENVIRONMENT_DATA" | jq -r '.services.items[]?.metadata.name' +# echo "$ENVIRONMENT_DATA" | jq -r '.secrets.items[]?.metadata.name' +# echo "$ENVIRONMENT_DATA" | jq -r '.pvcs.items[]?.metadata.name' +# echo "$ENVIRONMENT_DATA" | jq -r '.schedulesv1.items[]?.metadata.name' +# echo "$ENVIRONMENT_DATA" | jq -r '.schedulesv1alpha1.items[]?.metadata.name' +# echo "$ENVIRONMENT_DATA" | jq -r '.prebackuppodsv1.items[]?.metadata.name' +# echo "$ENVIRONMENT_DATA" | jq -r '.prebackuppodsv1alpha1.items[]?.metadata.name' +# echo "$ENVIRONMENT_DATA" | jq -r '.mariadbconsumers.items[]?.metadata.name' +# echo "$ENVIRONMENT_DATA" | jq -r '.mongodbconsumers.items[]?.metadata.name' +# echo "$ENVIRONMENT_DATA" | jq -r '.postgresqlconsumers.items[]?.metadata.name' currentStepEnd="$(date +"%Y-%m-%d %H:%M:%S")" # @TODO: uncomment when collector is introduced @@ -1640,9 +1638,9 @@ beginBuildStep "Applying Deployments" "applyingDeployments" ############################################## # remove any storage calculator pods before applying deployments to prevent storage binding issues -STORAGE_CALCULATOR_PODS=$(kubectl -n ${NAMESPACE} get pods -l lagoon.sh/storageCalculator=true --no-headers | cut -d " " -f 1 | xargs) +STORAGE_CALCULATOR_PODS=$(kubectl -n ${NAMESPACE} get pods -l lagoon.sh/storageCalculator=true --no-headers 2>/dev/null | cut -d " " -f 1 | xargs) for STORAGE_CALCULATOR_POD in $STORAGE_CALCULATOR_PODS; do - kubectl -n ${NAMESPACE} delete pod ${STORAGE_CALCULATOR_POD} + kubectl -n ${NAMESPACE} delete pod ${STORAGE_CALCULATOR_POD} 2>/dev/null done if [ "$(ls -A $LAGOON_SERVICES_YAML_FOLDER/)" ]; then @@ -1700,6 +1698,51 @@ currentStepEnd="$(date +"%Y-%m-%d %H:%M:%S")" finalizeBuildStep "${buildStartTime}" "${previousStepEnd}" "${currentStepEnd}" "${NAMESPACE}" "deploymentApplyComplete" "Applying Deployments" "false" build-deploy-tool run hooks --hook-name "Pre Cronjob Cleanup" --hook-directory "pre-cronjob-cleanup" previousStepEnd=${currentStepEnd} + +############################################## +### CLEANUP services which have been removed from docker-compose.yaml +##############################################s + +# using the build-deploy-tool identify the deployments, volumes, and services that this build has created +beginBuildStep "Unused Service Cleanup" "unusedServiceCleanup" +CLEANUP_OUTPUT="" +if [ "$(featureFlag CLEANUP_REMOVED_LAGOON_SERVICES)" != enabled ]; then + # run it in dry-run mode + CLEANUP_OUTPUT=$(build-deploy-tool run cleanup --images /kubectl-build-deploy/images.yaml) +else + # run it with the delete flag to actually remove services + CLEANUP_OUTPUT=$(build-deploy-tool run cleanup --images /kubectl-build-deploy/images.yaml --delete=true) +fi +CLEANUP_WARNING=false +if [ "$CLEANUP_OUTPUT" != "" ]; then + echo "${CLEANUP_OUTPUT}" + CLEANUP_WARNING=true + ((++BUILD_WARNING_COUNT)) +else + echo ">> No services detected that require clean up" +fi + +# collect data and save in configmap structured json of environment state, remote-controller will check for this configmap to provide to the api environment services +# this is run after the cleanup to ensure that only items that exist are stored in the configmap +# if a service has been abandoned (removed from the docker-compose file) and not cleaned up +# then the payload will contain the `abandoned` flag on the resource for when it is added to the lagoon api later on +# this will allow for visual representation in the api/ui of things that probably don't need to exist +if build-deploy-tool identify lagoon-services --images /kubectl-build-deploy/images.yaml > /kubectl-build-deploy/lagoon-services.json; then + echo "Updating lagoon-services configmap with a current service configurations" + if kubectl -n ${NAMESPACE} get configmap lagoon-services &> /dev/null; then + # replace it, no need to check if the key is different, as that will happen in the pre-deploy phase + kubectl -n ${NAMESPACE} get configmap lagoon-services -o json | jq --arg add "`cat /kubectl-build-deploy/lagoon-services.json`" '.data."post-deploy" = $add' | kubectl apply -f - + else + # create it + kubectl -n ${NAMESPACE} create configmap lagoon-services --from-file=post-deploy=/kubectl-build-deploy/lagoon-services.json + fi +fi + +# finalize the service cleanup +currentStepEnd="$(date +"%Y-%m-%d %H:%M:%S")" +finalizeBuildStep "${buildStartTime}" "${previousStepEnd}" "${currentStepEnd}" "${NAMESPACE}" "unusedServiceCleanupComplete" "Unused Service Cleanup" "${CLEANUP_WARNING}" +previousStepEnd=${currentStepEnd} + beginBuildStep "Cronjob Cleanup" "cleaningUpCronjobs" ##############################################