From 5bdf2f5c1438f344b51ddfcc90220b99a6e8a2f9 Mon Sep 17 00:00:00 2001 From: shreddedbacon Date: Tue, 10 Oct 2023 10:05:07 +1100 Subject: [PATCH] fix: tls cleanup and autogen cleanup --- cmd/identify_ingress.go | 41 +++++ cmd/identify_ingress_test.go | 232 ++++++++++++++++++++++++++ legacy/build-deploy-docker-compose.sh | 54 ++++-- 3 files changed, 311 insertions(+), 16 deletions(-) diff --git a/cmd/identify_ingress.go b/cmd/identify_ingress.go index 35cb9e38..a57a5b68 100644 --- a/cmd/identify_ingress.go +++ b/cmd/identify_ingress.go @@ -68,7 +68,48 @@ func IdentifyPrimaryIngress(g generator.GeneratorInput) (string, []string, []str return lagoonBuild.BuildValues.Route, lagoonBuild.BuildValues.Routes, lagoonBuild.BuildValues.AutogeneratedRoutes, nil } +var autogenIngressIdentify = &cobra.Command{ + Use: "autogenerated-ingress", + Aliases: []string{"ai"}, + Short: "Identify all autogenerated ingress object names for a specific environment", + RunE: func(cmd *cobra.Command, args []string) error { + generator, err := generatorInput(false) + if err != nil { + return err + } + autogen, err := AutogeneratedIngressIdentification(generator) + if err != nil { + return err + } + ret := ingressIdentifyJSON{ + Autogenerated: autogen, + } + retJSON, _ := json.Marshal(ret) + fmt.Println(string(retJSON)) + return nil + }, +} + +// AutogeneratedIngressIdentification handles identifying autogenerated ingress +func AutogeneratedIngressIdentification(g generator.GeneratorInput) ([]string, error) { + lagoonBuild, err := generator.NewGenerator( + g, + ) + if err != nil { + return nil, err + } + + autogenIngress := []string{} + // generate the templates + for _, route := range lagoonBuild.AutogeneratedRoutes.Routes { + autogenIngress = append(autogenIngress, route.LagoonService) + } + + return autogenIngress, nil +} + func init() { identifyCmd.AddCommand(primaryIngressIdentify) identifyCmd.AddCommand(ingressIdentify) + identifyCmd.AddCommand(autogenIngressIdentify) } diff --git a/cmd/identify_ingress_test.go b/cmd/identify_ingress_test.go index 4d47fde1..fa42628c 100644 --- a/cmd/identify_ingress_test.go +++ b/cmd/identify_ingress_test.go @@ -533,3 +533,235 @@ func TestIdentifyRoute(t *testing.T) { }) } } + +func TestAutogeneratedIngressIdentification(t *testing.T) { + type args struct { + alertContact string + statusPageID string + projectName string + environmentName string + branch string + prNumber string + prHeadBranch string + prBaseBranch string + environmentType string + buildType string + activeEnvironment string + standbyEnvironment string + cacheNoCache string + serviceID string + secretPrefix string + projectVars string + envVars string + lagoonVersion string + lagoonYAML string + valuesFilePath string + templatePath string + } + tests := []struct { + name string + args args + want string + wantJSON string + wantRemain []string + wantautoGen []string + }{ + { + name: "test13 no autogenerated routes", + args: args{ + alertContact: "alertcontact", + statusPageID: "statuspageid", + projectName: "example-project", + environmentName: "main", + environmentType: "production", + buildType: "branch", + lagoonVersion: "v2.7.x", + branch: "main", + projectVars: `[{"name":"LAGOON_SYSTEM_ROUTER_PATTERN","value":"${service}-${project}-${environment}.example.com","scope":"internal_system"}]`, + envVars: `[]`, + lagoonYAML: "../test-resources/identify-ingress/test13/lagoon.yml", + templatePath: "../test-resources/output", + }, + wantautoGen: []string{}, + wantJSON: `{"primary":"","secondary":null,"autogenerated":[]}`, + }, + { + name: "test14 only autogenerated route", + args: args{ + alertContact: "alertcontact", + statusPageID: "statuspageid", + projectName: "example-project", + environmentName: "main", + environmentType: "production", + buildType: "branch", + lagoonVersion: "v2.7.x", + branch: "main", + projectVars: `[{"name":"LAGOON_SYSTEM_ROUTER_PATTERN","value":"${service}-${project}-${environment}.example.com","scope":"internal_system"}]`, + envVars: `[]`, + lagoonYAML: "../test-resources/identify-ingress/test14/lagoon.yml", + templatePath: "../test-resources/output", + }, + wantautoGen: []string{"node"}, + wantJSON: `{"primary":"","secondary":null,"autogenerated":["node"]}`, + }, + { + name: "test15 only autogenerated route complex", + args: args{ + alertContact: "alertcontact", + statusPageID: "statuspageid", + projectName: "sales-customer-support", + environmentName: "develop", + environmentType: "development", + buildType: "branch", + lagoonVersion: "v2.7.x", + branch: "develop", + projectVars: `[{"name":"LAGOON_SYSTEM_ROUTER_PATTERN","value":"${service}-${project}-${environment}.ex1.example-web.com","scope":"internal_system"}]`, + envVars: `[]`, + lagoonYAML: "../test-resources/identify-ingress/test15/lagoon.yml", + templatePath: "../test-resources/output", + }, + wantautoGen: []string{"nginx"}, + wantJSON: `{"primary":"","secondary":null,"autogenerated":["nginx"]}`, + }, + { + name: "test16 autogenerated routes where lagoon.name of service does not match service names", + args: args{ + alertContact: "alertcontact", + statusPageID: "statuspageid", + projectName: "content-example-com", + environmentName: "feature-migration", + environmentType: "development", + buildType: "branch", + lagoonVersion: "v2.7.x", + branch: "feature/migration", + projectVars: `[{"name":"LAGOON_SYSTEM_ROUTER_PATTERN","value":"${environment}.${project}.example.com","scope":"internal_system"}]`, + envVars: `[]`, + lagoonYAML: "../test-resources/identify-ingress/test16/lagoon.yml", + templatePath: "../test-resources/output", + }, + wantautoGen: []string{"nginx-php"}, + wantJSON: `{"primary":"","secondary":null,"autogenerated":["nginx-php"]}`, + }, + { + name: "test17 autogenerated routes with mulitple routeable services", + args: args{ + alertContact: "alertcontact", + statusPageID: "statuspageid", + projectName: "example-project", + environmentName: "main", + environmentType: "production", + buildType: "branch", + lagoonVersion: "v2.7.x", + branch: "main", + projectVars: `[{"name":"LAGOON_SYSTEM_ROUTER_PATTERN","value":"${service}-${project}-${environment}.example.com","scope":"internal_system"}]`, + envVars: `[]`, + lagoonYAML: "../test-resources/identify-ingress/test17/lagoon.yml", + templatePath: "../test-resources/output", + }, + wantautoGen: []string{"nginx", "varnish"}, + wantJSON: `{"primary":"","secondary":null,"autogenerated":["nginx","varnish"]}`, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + // set the environment variables from args + err := os.Setenv("MONITORING_ALERTCONTACT", tt.args.alertContact) + if err != nil { + t.Errorf("%v", err) + } + err = os.Setenv("MONITORING_STATUSPAGEID", tt.args.statusPageID) + if err != nil { + t.Errorf("%v", err) + } + err = os.Setenv("PROJECT", tt.args.projectName) + if err != nil { + t.Errorf("%v", err) + } + err = os.Setenv("ENVIRONMENT", tt.args.environmentName) + if err != nil { + t.Errorf("%v", err) + } + err = os.Setenv("BRANCH", tt.args.branch) + if err != nil { + t.Errorf("%v", err) + } + err = os.Setenv("LAGOON_GIT_BRANCH", tt.args.branch) + if err != nil { + t.Errorf("%v", err) + } + err = os.Setenv("PR_NUMBER", tt.args.prNumber) + if err != nil { + t.Errorf("%v", err) + } + err = os.Setenv("PR_HEAD_BRANCH", tt.args.prHeadBranch) + if err != nil { + t.Errorf("%v", err) + } + err = os.Setenv("PR_BASE_BRANCH", tt.args.prBaseBranch) + if err != nil { + t.Errorf("%v", err) + } + err = os.Setenv("ENVIRONMENT_TYPE", tt.args.environmentType) + if err != nil { + t.Errorf("%v", err) + } + err = os.Setenv("BUILD_TYPE", tt.args.buildType) + if err != nil { + t.Errorf("%v", err) + } + err = os.Setenv("ACTIVE_ENVIRONMENT", tt.args.activeEnvironment) + if err != nil { + t.Errorf("%v", err) + } + err = os.Setenv("STANDBY_ENVIRONMENT", tt.args.standbyEnvironment) + if err != nil { + t.Errorf("%v", err) + } + err = os.Setenv("LAGOON_FASTLY_NOCACHE_SERVICE_ID", tt.args.cacheNoCache) + if err != nil { + t.Errorf("%v", err) + } + err = os.Setenv("LAGOON_PROJECT_VARIABLES", tt.args.projectVars) + if err != nil { + t.Errorf("%v", err) + } + err = os.Setenv("LAGOON_ENVIRONMENT_VARIABLES", tt.args.envVars) + if err != nil { + t.Errorf("%v", err) + } + err = os.Setenv("LAGOON_VERSION", tt.args.lagoonVersion) + if err != nil { + t.Errorf("%v", err) + } + generator, err := generatorInput(false) + if err != nil { + t.Errorf("%v", err) + } + generator.LagoonYAML = tt.args.lagoonYAML + // add dbaasclient overrides for tests + generator.DBaaSClient = dbaasclient.NewClient(dbaasclient.Client{ + RetryMax: 5, + RetryWaitMin: time.Duration(10) * time.Millisecond, + RetryWaitMax: time.Duration(50) * time.Millisecond, + }) + + autogen, err := AutogeneratedIngressIdentification(generator) + if err != nil { + t.Errorf("%v", err) + } + + if !reflect.DeepEqual(autogen, tt.wantautoGen) { + t.Errorf("returned autogen %v doesn't match want %v", autogen, tt.wantautoGen) + } + + ret := ingressIdentifyJSON{ + Autogenerated: autogen, + } + retJSON, _ := json.Marshal(ret) + + if string(retJSON) != tt.wantJSON { + t.Errorf("returned autogen %v doesn't match want %v", string(retJSON), tt.wantJSON) + } + }) + } +} diff --git a/legacy/build-deploy-docker-compose.sh b/legacy/build-deploy-docker-compose.sh index 9d0f81db..2055b992 100755 --- a/legacy/build-deploy-docker-compose.sh +++ b/legacy/build-deploy-docker-compose.sh @@ -1083,18 +1083,37 @@ if [ ! -z "$LAGOON_ENVIRONMENT_VARIABLES" ]; then fi if [ ! "$AUTOGEN_ROUTES_DISABLED" == true ]; then -build-deploy-tool template autogenerated-ingress + build-deploy-tool template autogenerated-ingress else echo ">> Autogenerated ingress templates disabled for this build" - # delete any autogenerated ingress in the namespace as they are disabled - if kubectl -n ${NAMESPACE} get ingress -l "lagoon.sh/autogenerated=true" &> /dev/null; then - echo ">> Removing any autogenerated ingress" - kubectl -n ${NAMESPACE} delete ingress -l "lagoon.sh/autogenerated=true" - echo ">> Autogenerated ingress removed" - fi # end custom route fi +# identify any autognerated resources based on their resource name +AUTOGEN_INGRESS=$(build-deploy-tool identify autogenerated-ingress | jq -r '.autogenerated[]') +AUTOGEN_ROUTES=$(kubectl -n ${NAMESPACE} get ingress --no-headers -l "lagoon.sh/autogenerated=true" | cut -d " " -f 1 | xargs) +MATCHED_AUTOGEN=false +DELETE_AUTOGEN=() +for AR in $AUTOGEN_ROUTES; do + for AI in $AUTOGEN_INGRESS; do + if [ "${AR}" == "${AI}" ]; then + MATCHED_AUTOGEN=true + continue + fi + done + if [ "${MATCHED_AUTOGEN}" != "true" ]; then + DELETE_AUTOGEN+=($AR) + fi + MATCHED_AUTOGEN=false +done +for DA in $DELETE_AUTOGEN; do + # delete any autogenerated ingress in the namespace as they are disabled + if kubectl -n ${NAMESPACE} get ingress ${DA} &> /dev/null; then + echo ">> Removing autogenerated ingress for ${DA} because it was disabled" + kubectl -n ${NAMESPACE} delete ingress ${DA} + fi +done + for SERVICE_TYPES_ENTRY in "${SERVICE_TYPES[@]}" do echo "=== BEGIN route processing for service ${SERVICE_TYPES_ENTRY} ===" @@ -1197,15 +1216,6 @@ fi # Get list of autogenerated routes AUTOGENERATED_ROUTES=$(kubectl -n ${NAMESPACE} get ingress --sort-by='{.metadata.name}' -l "lagoon.sh/autogenerated=true" -o=go-template --template='{{range $indexItems, $ingress := .items}}{{if $indexItems}},{{end}}{{$tls := .spec.tls}}{{range $indexRule, $rule := .spec.rules}}{{if $indexRule}},{{end}}{{if $tls}}https://{{else}}http://{{end}}{{.host}}{{end}}{{end}}') -# remove any certificates for tls-acme false ingress to prevent reissuing attempts -TLS_FALSE_INGRESSES=$(kubectl -n ${NAMESPACE} get ingress -o json | jq -r '.items[] | select(.metadata.annotations["kubernetes.io/tls-acme"] == "false") | .metadata.name') -for TLS_FALSE_INGRESS in $TLS_FALSE_INGRESSES; do - if kubectl -n ${NAMESPACE} get certificate ${TLS_FALSE_INGRESS}-tls &> /dev/null; then - echo ">> Cleaning up certificate for ${TLS_FALSE_INGRESS} as tls-acme is set to false" - kubectl -n ${NAMESPACE} delete certificate ${TLS_FALSE_INGRESS}-tls - fi -done - yq3 write -i -- /kubectl-build-deploy/values.yaml 'route' "$ROUTE" yq3 write -i -- /kubectl-build-deploy/values.yaml 'routes' "$ROUTES" yq3 write -i -- /kubectl-build-deploy/values.yaml 'autogeneratedRoutes' "$AUTOGENERATED_ROUTES" @@ -1736,6 +1746,18 @@ if kubectl -n ${NAMESPACE} get configmap docker-compose-yaml &> /dev/null; then # create it kubectl -n ${NAMESPACE} create configmap docker-compose-yaml --from-file=post-deploy=${DOCKER_COMPOSE_YAML} fi + +# remove any certificates for tls-acme false ingress to prevent reissuing attempts +TLS_FALSE_INGRESSES=$(kubectl -n ${NAMESPACE} get ingress -o json | jq -r '.items[] | select(.metadata.annotations["kubernetes.io/tls-acme"] == "false") | .metadata.name') +for TLS_FALSE_INGRESS in $TLS_FALSE_INGRESSES; do + TLS_SECRETS=$(kubectl -n ${NAMESPACE} get ingress ${TLS_FALSE_INGRESS} -o json | jq -r '.spec.tls[].secretName') + for TLS_SECRET in $TLS_SECRETS; do + if kubectl -n ${NAMESPACE} get certificates.cert-manager.io ${TLS_SECRET} &> /dev/null; then + echo ">> Cleaning up certificate for ${TLS_SECRET} as tls-acme is set to false" + kubectl -n ${NAMESPACE} delete certificates.cert-manager.io ${TLS_SECRET} + fi + done +done set -x set +x