From 7892852b8120e835ceb8f441fcd3164ba5c9a68c Mon Sep 17 00:00:00 2001 From: shreddedbacon Date: Thu, 19 Oct 2023 13:11:23 +1100 Subject: [PATCH] refactor: generate the ingress name in the generator phase to allow easier cleanups refactor: ignore autogenerated, there is a separate cleanup for those refactor: wording for cleanups refactor: additional changes --- cmd/identify_ingress.go | 25 +++-- cmd/identify_ingress_test.go | 65 +++++++++-- internal/generator/ingress.go | 1 + internal/generator/ingress_test.go | 19 ++++ internal/lagoon/routes.go | 12 ++ internal/lagoon/routes_test.go | 21 ++++ .../templating/ingress/templates_ingress.go | 13 +-- .../ingress/templates_ingress_test.go | 11 ++ legacy/build-deploy-docker-compose.sh | 40 +++---- .../test18/docker-compose.yml | 104 ++++++++++++++++++ .../identify-ingress/test18/lagoon.yml | 13 +++ 11 files changed, 274 insertions(+), 50 deletions(-) create mode 100644 test-resources/identify-ingress/test18/docker-compose.yml create mode 100644 test-resources/identify-ingress/test18/lagoon.yml diff --git a/cmd/identify_ingress.go b/cmd/identify_ingress.go index a57a5b68..2ea79daf 100644 --- a/cmd/identify_ingress.go +++ b/cmd/identify_ingress.go @@ -69,20 +69,21 @@ func IdentifyPrimaryIngress(g generator.GeneratorInput) (string, []string, []str } var autogenIngressIdentify = &cobra.Command{ - Use: "autogenerated-ingress", - Aliases: []string{"ai"}, - Short: "Identify all autogenerated ingress object names for a specific environment", + Use: "created-ingress", + Aliases: []string{"ci"}, + Short: "Identify all created 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) + autogen, secondary, err := CreatedIngressIdentification(generator) if err != nil { return err } ret := ingressIdentifyJSON{ Autogenerated: autogen, + Secondary: secondary, } retJSON, _ := json.Marshal(ret) fmt.Println(string(retJSON)) @@ -90,13 +91,13 @@ var autogenIngressIdentify = &cobra.Command{ }, } -// AutogeneratedIngressIdentification handles identifying autogenerated ingress -func AutogeneratedIngressIdentification(g generator.GeneratorInput) ([]string, error) { +// CreatedIngressIdentification handles identifying autogenerated ingress +func CreatedIngressIdentification(g generator.GeneratorInput) ([]string, []string, error) { lagoonBuild, err := generator.NewGenerator( g, ) if err != nil { - return nil, err + return nil, nil, err } autogenIngress := []string{} @@ -105,7 +106,15 @@ func AutogeneratedIngressIdentification(g generator.GeneratorInput) ([]string, e autogenIngress = append(autogenIngress, route.LagoonService) } - return autogenIngress, nil + secondary := []string{} + // generate the templates + for _, route := range lagoonBuild.MainRoutes.Routes { + secondary = append(secondary, route.IngressName) + } + for _, route := range lagoonBuild.ActiveStandbyRoutes.Routes { + secondary = append(secondary, route.IngressName) + } + return autogenIngress, secondary, nil } func init() { diff --git a/cmd/identify_ingress_test.go b/cmd/identify_ingress_test.go index fa42628c..22a777d1 100644 --- a/cmd/identify_ingress_test.go +++ b/cmd/identify_ingress_test.go @@ -419,6 +419,27 @@ func TestIdentifyRoute(t *testing.T) { 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", + 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/test18/lagoon.yml", + templatePath: "../test-resources/output", + }, + 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) { @@ -534,7 +555,7 @@ func TestIdentifyRoute(t *testing.T) { } } -func TestAutogeneratedIngressIdentification(t *testing.T) { +func TestCreatedIngressIdentification(t *testing.T) { type args struct { alertContact string statusPageID string @@ -582,8 +603,9 @@ func TestAutogeneratedIngressIdentification(t *testing.T) { lagoonYAML: "../test-resources/identify-ingress/test13/lagoon.yml", templatePath: "../test-resources/output", }, + wantRemain: []string{"example.com"}, wantautoGen: []string{}, - wantJSON: `{"primary":"","secondary":null,"autogenerated":[]}`, + wantJSON: `{"primary":"","secondary":["example.com"],"autogenerated":[]}`, }, { name: "test14 only autogenerated route", @@ -601,8 +623,9 @@ func TestAutogeneratedIngressIdentification(t *testing.T) { lagoonYAML: "../test-resources/identify-ingress/test14/lagoon.yml", templatePath: "../test-resources/output", }, + wantRemain: []string{}, wantautoGen: []string{"node"}, - wantJSON: `{"primary":"","secondary":null,"autogenerated":["node"]}`, + wantJSON: `{"primary":"","secondary":[],"autogenerated":["node"]}`, }, { name: "test15 only autogenerated route complex", @@ -620,8 +643,9 @@ func TestAutogeneratedIngressIdentification(t *testing.T) { lagoonYAML: "../test-resources/identify-ingress/test15/lagoon.yml", templatePath: "../test-resources/output", }, + wantRemain: []string{}, wantautoGen: []string{"nginx"}, - wantJSON: `{"primary":"","secondary":null,"autogenerated":["nginx"]}`, + wantJSON: `{"primary":"","secondary":[],"autogenerated":["nginx"]}`, }, { name: "test16 autogenerated routes where lagoon.name of service does not match service names", @@ -639,8 +663,9 @@ func TestAutogeneratedIngressIdentification(t *testing.T) { lagoonYAML: "../test-resources/identify-ingress/test16/lagoon.yml", templatePath: "../test-resources/output", }, + wantRemain: []string{}, wantautoGen: []string{"nginx-php"}, - wantJSON: `{"primary":"","secondary":null,"autogenerated":["nginx-php"]}`, + wantJSON: `{"primary":"","secondary":[],"autogenerated":["nginx-php"]}`, }, { name: "test17 autogenerated routes with mulitple routeable services", @@ -658,8 +683,29 @@ func TestAutogeneratedIngressIdentification(t *testing.T) { lagoonYAML: "../test-resources/identify-ingress/test17/lagoon.yml", templatePath: "../test-resources/output", }, + wantRemain: []string{}, wantautoGen: []string{"nginx", "varnish"}, - wantJSON: `{"primary":"","secondary":null,"autogenerated":["nginx","varnish"]}`, + wantJSON: `{"primary":"","secondary":[],"autogenerated":["nginx","varnish"]}`, + }, + { + name: "test18 autogenerated routes with wildcard and altnames", + 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/test18/lagoon.yml", + templatePath: "../test-resources/output", + }, + 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 { @@ -745,7 +791,7 @@ func TestAutogeneratedIngressIdentification(t *testing.T) { RetryWaitMax: time.Duration(50) * time.Millisecond, }) - autogen, err := AutogeneratedIngressIdentification(generator) + autogen, remainders, err := CreatedIngressIdentification(generator) if err != nil { t.Errorf("%v", err) } @@ -754,8 +800,13 @@ func TestAutogeneratedIngressIdentification(t *testing.T) { t.Errorf("returned autogen %v doesn't match want %v", autogen, tt.wantautoGen) } + if !reflect.DeepEqual(remainders, tt.wantRemain) { + t.Errorf("returned remainders %v doesn't match want %v", remainders, tt.wantRemain) + } + ret := ingressIdentifyJSON{ Autogenerated: autogen, + Secondary: remainders, } retJSON, _ := json.Marshal(ret) diff --git a/internal/generator/ingress.go b/internal/generator/ingress.go index c942349a..82247882 100644 --- a/internal/generator/ingress.go +++ b/internal/generator/ingress.go @@ -187,6 +187,7 @@ func generateAutogenRoutes( IngressClass: ingressClass, Autogenerated: true, LagoonService: serviceOverrideName, + IngressName: serviceOverrideName, ComposeService: service.Name, Insecure: &insecure, AlternativeNames: alternativeNames, diff --git a/internal/generator/ingress_test.go b/internal/generator/ingress_test.go index 225f085c..a43b2b2f 100644 --- a/internal/generator/ingress_test.go +++ b/internal/generator/ingress_test.go @@ -169,6 +169,7 @@ func Test_generateAndMerge(t *testing.T) { Insecure: helpers.StrPtr("Redirect"), MonitoringPath: "/bypass-cache", AlternativeNames: []string{}, + IngressName: "a.example.com", }, { Domain: "b.example.com", @@ -178,6 +179,7 @@ func Test_generateAndMerge(t *testing.T) { Insecure: helpers.StrPtr("Redirect"), MonitoringPath: "/", AlternativeNames: []string{}, + IngressName: "b.example.com", }, { Domain: "c.example.com", @@ -187,6 +189,7 @@ func Test_generateAndMerge(t *testing.T) { Insecure: helpers.StrPtr("Redirect"), MonitoringPath: "/", AlternativeNames: []string{}, + IngressName: "c.example.com", }, { Domain: "test1.example.com", @@ -196,6 +199,7 @@ func Test_generateAndMerge(t *testing.T) { Insecure: helpers.StrPtr("Redirect"), Annotations: map[string]string{}, AlternativeNames: []string{}, + IngressName: "test1.example.com", }, }, }, @@ -234,6 +238,7 @@ func Test_generateAndMerge(t *testing.T) { Insecure: helpers.StrPtr("Redirect"), Annotations: map[string]string{}, AlternativeNames: []string{}, + IngressName: "test1.example.com", }, { Domain: "a.example.com", @@ -243,6 +248,7 @@ func Test_generateAndMerge(t *testing.T) { Insecure: helpers.StrPtr("Redirect"), MonitoringPath: "/bypass-cache", AlternativeNames: []string{}, + IngressName: "a.example.com", }, }, }, @@ -307,6 +313,7 @@ func Test_generateAndMerge(t *testing.T) { MonitoringPath: "/bypass-cache", IngressClass: "nginx", AlternativeNames: []string{}, + IngressName: "a.example.com", }, { Domain: "b.example.com", @@ -317,6 +324,7 @@ func Test_generateAndMerge(t *testing.T) { MonitoringPath: "/", IngressClass: "nginx", AlternativeNames: []string{}, + IngressName: "b.example.com", }, { Domain: "c.example.com", @@ -327,6 +335,7 @@ func Test_generateAndMerge(t *testing.T) { MonitoringPath: "/", IngressClass: "nginx", AlternativeNames: []string{}, + IngressName: "c.example.com", }, { Domain: "test1.example.com", @@ -337,6 +346,7 @@ func Test_generateAndMerge(t *testing.T) { Annotations: map[string]string{}, IngressClass: "nginx", AlternativeNames: []string{}, + IngressName: "test1.example.com", }, }, }, @@ -393,6 +403,7 @@ func Test_generateAndMerge(t *testing.T) { HSTSEnabled: helpers.BoolPtr(true), HSTSMaxAge: 36000, AlternativeNames: []string{}, + IngressName: "a.example.com", }, }, }, @@ -437,6 +448,7 @@ func Test_generateAndMerge(t *testing.T) { IngressClass: "nginx", AlternativeNames: []string{}, Wildcard: helpers.BoolPtr(true), + IngressName: "wildcard-a.example.com", }, }, }, @@ -537,6 +549,7 @@ func Test_generateActiveStandbyRoutes(t *testing.T) { Insecure: helpers.StrPtr("Redirect"), MonitoringPath: "/", AlternativeNames: []string{}, + IngressName: "active.example.com", }, }, }, @@ -581,6 +594,7 @@ func Test_generateActiveStandbyRoutes(t *testing.T) { MonitoringPath: "/", IngressClass: "nginx", AlternativeNames: []string{}, + IngressName: "active.example.com", }, }, }, @@ -626,6 +640,7 @@ func Test_generateActiveStandbyRoutes(t *testing.T) { MonitoringPath: "/", IngressClass: "custom-nginx", AlternativeNames: []string{}, + IngressName: "active.example.com", }, }, }, @@ -706,6 +721,7 @@ func Test_generateActiveStandbyRoutes(t *testing.T) { IngressClass: "nginx", AlternativeNames: []string{}, Wildcard: helpers.BoolPtr(true), + IngressName: "wildcard-active.example.com", }, }, }, @@ -835,6 +851,7 @@ func Test_generateAutogenRoutes(t *testing.T) { "lagoon.sh/service": "nginx", "lagoon.sh/service-type": "nginx", }, + IngressName: "nginx", }, }, }, @@ -887,6 +904,7 @@ func Test_generateAutogenRoutes(t *testing.T) { "lagoon.sh/service": "nginx", "lagoon.sh/service-type": "nginx", }, + IngressName: "nginx", }, }, }, @@ -945,6 +963,7 @@ func Test_generateAutogenRoutes(t *testing.T) { "lagoon.sh/service": "nginx", "lagoon.sh/service-type": "nginx", }, + IngressName: "nginx", }, }, }, diff --git a/internal/lagoon/routes.go b/internal/lagoon/routes.go index c4302672..86291569 100644 --- a/internal/lagoon/routes.go +++ b/internal/lagoon/routes.go @@ -136,6 +136,7 @@ func GenerateRoutesV2(yamlRoutes *RoutesV2, routeMap map[string][]Route, variabl for iName, ingress := range lagoonRoute.Ingresses { newRoute.Domain = iName newRoute.LagoonService = rName + newRoute.IngressName = iName newRoute.IngressClass = defaultIngressClass newRoute.Fastly = ingress.Fastly if ingress.Annotations != nil { @@ -185,6 +186,10 @@ func GenerateRoutesV2(yamlRoutes *RoutesV2, routeMap map[string][]Route, variabl if ingress.AlternativeNames != nil && *newRoute.Wildcard == true { return fmt.Errorf("Route %s has wildcard: true and alternativenames defined, this is not supported", newRoute.Domain) } + newRoute.IngressName = fmt.Sprintf("wildcard-%s", newRoute.Domain) + if err := validation.IsDNS1123Subdomain(strings.ToLower(newRoute.IngressName)); err != nil { + newRoute.IngressName = fmt.Sprintf("%s-%s", newRoute.IngressName[:len(newRoute.IngressName)-10], helpers.GetMD5HashWithNewLine(newRoute.Domain)[:5]) + } } } } else { @@ -192,6 +197,7 @@ func GenerateRoutesV2(yamlRoutes *RoutesV2, routeMap map[string][]Route, variabl // keep the defaults, just set the name and service newRoute.Domain = lagoonRoute.Name newRoute.LagoonService = rName + newRoute.IngressName = lagoonRoute.Name } // generate the fastly configuration for this route err := GenerateFastlyConfiguration(&newRoute.Fastly, "", newRoute.Fastly.ServiceID, newRoute.Domain, secretPrefix, variables) @@ -289,6 +295,8 @@ func handleAPIRoute(defaultIngressClass string, apiRoute RouteV2) (RouteV2, erro routeAdd := apiRoute // copy in the apiroute fastly configuration routeAdd.Fastly = apiRoute.Fastly + + routeAdd.IngressName = apiRoute.Domain if apiRoute.TLSAcme != nil { routeAdd.TLSAcme = apiRoute.TLSAcme } else { @@ -343,6 +351,10 @@ func handleAPIRoute(defaultIngressClass string, apiRoute RouteV2) (RouteV2, erro if apiRoute.AlternativeNames != nil && *routeAdd.Wildcard == true { return routeAdd, fmt.Errorf("Route %s has wildcard=true and alternativenames defined, this is not supported", routeAdd.Domain) } + apiRoute.IngressName = fmt.Sprintf("wildcard-%s", apiRoute.Domain) + if err := validation.IsDNS1123Subdomain(strings.ToLower(apiRoute.IngressName)); err != nil { + apiRoute.IngressName = fmt.Sprintf("%s-%s", apiRoute.IngressName[:len(apiRoute.IngressName)-10], helpers.GetMD5HashWithNewLine(apiRoute.Domain)[:5]) + } } return routeAdd, nil } diff --git a/internal/lagoon/routes_test.go b/internal/lagoon/routes_test.go index d2ff9be5..86657702 100644 --- a/internal/lagoon/routes_test.go +++ b/internal/lagoon/routes_test.go @@ -54,6 +54,7 @@ func TestGenerateRouteStructure(t *testing.T) { Watch: false, }, AlternativeNames: []string{}, + IngressName: "example.com", }, { Domain: "www.example.com", @@ -66,6 +67,7 @@ func TestGenerateRouteStructure(t *testing.T) { Watch: false, }, AlternativeNames: []string{}, + IngressName: "www.example.com", }, }, }, @@ -108,6 +110,7 @@ func TestGenerateRouteStructure(t *testing.T) { Watch: false, }, AlternativeNames: []string{}, + IngressName: "example.com", }, { Domain: "www.example.com", @@ -122,6 +125,7 @@ func TestGenerateRouteStructure(t *testing.T) { ServiceID: "12345", }, AlternativeNames: []string{}, + IngressName: "www.example.com", }, }, }, @@ -170,6 +174,7 @@ func TestGenerateRouteStructure(t *testing.T) { "www.example.com", "en.example.com", }, + IngressName: "example.com", }, }, }, @@ -206,6 +211,7 @@ func TestGenerateRouteStructure(t *testing.T) { Watch: false, }, AlternativeNames: []string{}, + IngressName: "example.com", }, { Domain: "www.example.com", @@ -219,6 +225,7 @@ func TestGenerateRouteStructure(t *testing.T) { Watch: false, }, AlternativeNames: []string{}, + IngressName: "www.example.com", }, }, }, @@ -264,6 +271,7 @@ func TestGenerateRouteStructure(t *testing.T) { Watch: false, }, AlternativeNames: []string{}, + IngressName: "example.com", }, { Domain: "www.example.com", @@ -279,6 +287,7 @@ func TestGenerateRouteStructure(t *testing.T) { ServiceID: "12345", }, AlternativeNames: []string{}, + IngressName: "www.example.com", }, }, }, @@ -323,6 +332,7 @@ func TestGenerateRouteStructure(t *testing.T) { Watch: false, }, AlternativeNames: []string{}, + IngressName: "example.com", }, { Domain: "www.example.com", @@ -339,6 +349,7 @@ func TestGenerateRouteStructure(t *testing.T) { HSTSEnabled: helpers.BoolPtr(true), HSTSMaxAge: 10000, AlternativeNames: []string{}, + IngressName: "www.example.com", }, }, }, @@ -397,6 +408,7 @@ func TestGenerateRouteStructure(t *testing.T) { Annotations: map[string]string{}, AlternativeNames: []string{}, Wildcard: helpers.BoolPtr(true), + IngressName: "wildcard-www.example.com", }, }, }, @@ -449,6 +461,7 @@ func TestMergeRouteStructures(t *testing.T) { ServiceID: "12345", APISecretName: "annotationscom", }, + IngressName: "example.com", }, { Domain: "www.example.com", @@ -457,6 +470,7 @@ func TestMergeRouteStructures(t *testing.T) { Insecure: helpers.StrPtr("Redirect"), TLSAcme: helpers.BoolPtr(true), Annotations: map[string]string{}, + IngressName: "www.example.com", }, { Domain: "hsts.example.com", @@ -467,6 +481,7 @@ func TestMergeRouteStructures(t *testing.T) { Annotations: map[string]string{}, HSTSEnabled: helpers.BoolPtr(true), HSTSMaxAge: 20000, + IngressName: "hsts.example.com", }, }, }, @@ -519,6 +534,7 @@ func TestMergeRouteStructures(t *testing.T) { APISecretName: "fastly-api-annotationscom", }, AlternativeNames: []string{}, + IngressName: "example.com", }, { Domain: "www.example.com", @@ -530,6 +546,7 @@ func TestMergeRouteStructures(t *testing.T) { "nginx": "nginx", }, AlternativeNames: []string{}, + IngressName: "www.example.com", }, { Domain: "hsts.example.com", @@ -541,6 +558,7 @@ func TestMergeRouteStructures(t *testing.T) { HSTSEnabled: helpers.BoolPtr(true), HSTSMaxAge: 10000, AlternativeNames: []string{}, + IngressName: "hsts.example.com", }, { Domain: "another.example.com", @@ -550,6 +568,7 @@ func TestMergeRouteStructures(t *testing.T) { TLSAcme: helpers.BoolPtr(true), Annotations: map[string]string{}, AlternativeNames: []string{}, + IngressName: "another.example.com", }, }, }, @@ -614,6 +633,7 @@ func TestMergeRouteStructures(t *testing.T) { Annotations: map[string]string{}, AlternativeNames: []string{}, Wildcard: helpers.BoolPtr(true), + IngressName: "example.com", }, { Domain: "a.example.com", @@ -624,6 +644,7 @@ func TestMergeRouteStructures(t *testing.T) { Annotations: map[string]string{}, AlternativeNames: []string{}, Wildcard: helpers.BoolPtr(true), + IngressName: "a.example.com", }, }, }, diff --git a/internal/templating/ingress/templates_ingress.go b/internal/templating/ingress/templates_ingress.go index 88bb863b..741b09a4 100644 --- a/internal/templating/ingress/templates_ingress.go +++ b/internal/templating/ingress/templates_ingress.go @@ -13,7 +13,6 @@ import ( apivalidation "k8s.io/apimachinery/pkg/api/validation" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metavalidation "k8s.io/apimachinery/pkg/apis/meta/v1/validation" - "k8s.io/apimachinery/pkg/util/validation" utilvalidation "k8s.io/apimachinery/pkg/util/validation" "sigs.k8s.io/yaml" @@ -41,20 +40,10 @@ func GenerateIngressTemplate( Kind: "Ingress", APIVersion: "networking.k8s.io/v1", } - ingress.ObjectMeta.Name = route.Domain - if route.Autogenerated { - // autogenerated routes just have the service name - ingress.ObjectMeta.Name = route.LagoonService - } + ingress.ObjectMeta.Name = route.IngressName // if this is a wildcard ingress, handle templating that here if route.Wildcard != nil && *route.Wildcard == true { - // prefix the object name with wildcard - ingress.ObjectMeta.Name = fmt.Sprintf("wildcard-%s", ingress.ObjectMeta.Name) - // if the new name exceeds the validation spec, truncate it - if err := validation.IsDNS1123Subdomain(strings.ToLower(ingress.ObjectMeta.Name)); err != nil { - ingress.ObjectMeta.Name = fmt.Sprintf("%s-%s", ingress.ObjectMeta.Name[:len(ingress.ObjectMeta.Name)-10], helpers.GetMD5HashWithNewLine(route.Domain)[:5]) - } truncatedRouteDomain = fmt.Sprintf("wildcard-%s", truncatedRouteDomain) if len(truncatedRouteDomain) >= 53 { subdomain := strings.Split(truncatedRouteDomain, "-")[0] diff --git a/internal/templating/ingress/templates_ingress_test.go b/internal/templating/ingress/templates_ingress_test.go index 8f2c4cd7..bd4065ec 100644 --- a/internal/templating/ingress/templates_ingress_test.go +++ b/internal/templating/ingress/templates_ingress_test.go @@ -40,6 +40,7 @@ func TestGenerateKubeTemplate(t *testing.T) { Fastly: lagoon.Fastly{ Watch: false, }, + IngressName: "extra-long-name.a-really-long-name-that-should-truncate.www.example.com", }, values: generator.BuildValues{ Project: "example-project", @@ -77,6 +78,7 @@ func TestGenerateKubeTemplate(t *testing.T) { Fastly: lagoon.Fastly{ Watch: false, }, + IngressName: "extra-long-name.a-really-long-name-that-should-truncate.www.example.com", }, values: generator.BuildValues{ Project: "example-project", @@ -114,6 +116,7 @@ func TestGenerateKubeTemplate(t *testing.T) { Fastly: lagoon.Fastly{ Watch: false, }, + IngressName: "extra-long-name.a-really-long-name-that-should-truncate.www.example.com", }, values: generator.BuildValues{ Project: "example-project", @@ -152,6 +155,7 @@ func TestGenerateKubeTemplate(t *testing.T) { Watch: false, }, IngressClass: "nginx", + IngressName: "extra-long-name.a-really-long-name-that-should-truncate.www.example.com", }, values: generator.BuildValues{ Project: "example-project", @@ -192,6 +196,7 @@ func TestGenerateKubeTemplate(t *testing.T) { IngressClass: "nginx", HSTSEnabled: helpers.BoolPtr(true), HSTSMaxAge: 31536000, + IngressName: "extra-long-name.a-really-long-name-that-should-truncate.www.example.com", }, values: generator.BuildValues{ Project: "example-project", @@ -235,6 +240,7 @@ func TestGenerateKubeTemplate(t *testing.T) { HSTSMaxAge: 31536000, HSTSIncludeSubdomains: helpers.BoolPtr(true), HSTSPreload: helpers.BoolPtr(true), + IngressName: "extra-long-name.a-really-long-name-that-should-truncate.www.example.com", }, values: generator.BuildValues{ Project: "example-project", @@ -274,6 +280,7 @@ func TestGenerateKubeTemplate(t *testing.T) { Watch: false, }, IngressClass: "nginx", + IngressName: "extra-long-name.a-really-long-name-that-should-truncate.www.example.com", }, values: generator.BuildValues{ Project: "example-project", @@ -314,6 +321,7 @@ func TestGenerateKubeTemplate(t *testing.T) { Watch: false, }, IngressClass: "nginx", + IngressName: "extra-long-name.a-really-long-name-that-should-truncate.www.example.com", }, values: generator.BuildValues{ Project: "example-project", @@ -351,6 +359,7 @@ func TestGenerateKubeTemplate(t *testing.T) { Watch: false, }, IngressClass: "nginx", + IngressName: "hmm-this-is-a-really-long-branch-name-designed-to-test-a-specific-feature.www.example.com", }, values: generator.BuildValues{ Project: "example-project", @@ -389,6 +398,7 @@ func TestGenerateKubeTemplate(t *testing.T) { }, IngressClass: "nginx", Wildcard: helpers.BoolPtr(true), + IngressName: "wildcard-www.example.com", }, values: generator.BuildValues{ Project: "example-project", @@ -427,6 +437,7 @@ func TestGenerateKubeTemplate(t *testing.T) { }, IngressClass: "nginx", Wildcard: helpers.BoolPtr(true), + IngressName: "wildcard-this-truncate.extra-long-name.a-really-long-name-that-should-truncate.extra-long-name.a-really-long-name-that-should-truncate.extra-long-name.a-really-long-name-that-should-truncate.extra-long-name.a-really-long-name-that-should-truncate.www.e-f1945", }, values: generator.BuildValues{ Project: "example-project", diff --git a/legacy/build-deploy-docker-compose.sh b/legacy/build-deploy-docker-compose.sh index e85acfce..20035fe2 100755 --- a/legacy/build-deploy-docker-compose.sh +++ b/legacy/build-deploy-docker-compose.sh @@ -1090,7 +1090,7 @@ else fi # identify any autognerated resources based on their resource name -AUTOGEN_INGRESS=$(build-deploy-tool identify autogenerated-ingress | jq -r '.autogenerated[]') +AUTOGEN_INGRESS=$(build-deploy-tool identify created-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=() @@ -1717,64 +1717,58 @@ set +x currentStepEnd="$(date +"%Y-%m-%d %H:%M:%S")" patchBuildStep "${buildStartTime}" "${previousStepEnd}" "${currentStepEnd}" "${NAMESPACE}" "cronjobCleanupComplete" "Cronjob Cleanup" previousStepEnd=${currentStepEnd} -beginBuildStep "Removed Route Cleanup" "cleanupRemovedRoutes" -set -x +beginBuildStep "Route/Ingress Cleanup" "cleanupRemovedRoutes" ############################################## ### CLEANUP Ingress/routes which have been removed from .lagoon.yml ############################################## -set +x + # collect the current routes, its possible to exclude ingress by adding a label 'lagoon.sh/noclean=true' and it won't get deleted -CURRENT_ROUTES=$(kubectl -n ${NAMESPACE} get ingress -l "lagoon.sh/noclean!=true" --no-headers | cut -d " " -f 1 | xargs) +CURRENT_ROUTES=$(kubectl -n ${NAMESPACE} get ingress -l "lagoon.sh/noclean!=true" -l "lagoon.sh/autogenerated!=true" --no-headers | cut -d " " -f 1 | xargs) # collect the routes that Lagoon thinks it should have based on the .lagoon.yml and any routes that have come from the api # using the build-deploy-tool generator -YAML_ROUTES_TO_JSON=$(build-deploy-tool identify ingress | jq -r '.secondary[]') +YAML_ROUTES_TO_JSON=$(build-deploy-tool identify created-ingress | jq -r '.secondary[]') -IFS=' ' read -a SPLIT_CURRENT_ROUTES <<< $CURRENT_ROUTES MATCHED_INGRESS=false DELETE_INGRESS=() # loop over the routes from kubernetes -for SINGLE_ROUTE in ${SPLIT_CURRENT_ROUTES[@]} -do +for SINGLE_ROUTE in ${CURRENT_ROUTES}; do # loop over the routes that Lagoon thinks it should have - for YAML_ROUTE in ${YAML_ROUTES_TO_JSON} - do - re="http?(s)://$SINGLE_ROUTE" - if [[ "$YAML_ROUTE" =~ $re ]]; then - # if it matches one, drop out + for YAML_ROUTE in ${YAML_ROUTES_TO_JSON}; do + if [ "${SINGLE_ROUTE}" == "${YAML_ROUTE}" ]; then MATCHED_INGRESS=true continue fi done - # if the route doesn't exist in what Lagoon thinks it should have - # delete it or flag it for deletion - if [ "$MATCHED_INGRESS" != "true" ]; then + if [ "${MATCHED_INGRESS}" != "true" ]; then DELETE_INGRESS+=($SINGLE_ROUTE) fi MATCHED_INGRESS=false done if [ ${#DELETE_INGRESS[@]} -ne 0 ]; then + echo ">> Lagoon detected routes that have been removed from the .lagoon.yml or Lagoon API" if [ "$(featureFlag CLEANUP_REMOVED_LAGOON_ROUTES)" != enabled ]; then - echo ">> Lagoon detected routes that have been removed from the .lagoon.yml or Lagoon API" echo "> You can remove these in the next build by setting the flag 'LAGOON_FEATURE_FLAG_CLEANUP_REMOVED_LAGOON_ROUTES=enabled' as a GLOBAL scoped variable to this environment or project" fi for DI in ${DELETE_INGRESS[@]} do if [ "$(featureFlag CLEANUP_REMOVED_LAGOON_ROUTES)" = enabled ]; then - kubectl -n ${NAMESPACE} delete ingress ${SINGLE_ROUTE} + if kubectl -n ${NAMESPACE} get ingress ${DELETE_INGRESS[$DI]} &> /dev/null; then + echo ">> Removing ingress ${DELETE_INGRESS[$DI]} because it was removed" + kubectl -n ${NAMESPACE} delete ingress ${DELETE_INGRESS[$DI]} + #delete anything else? + fi else - echo "> The route '${SINGLE_ROUTE}' would be removed" + echo "> The route '${DI}' would be removed, and any other associated " fi done else echo "No route cleanup required" fi -set -x -set +x currentStepEnd="$(date +"%Y-%m-%d %H:%M:%S")" -patchBuildStep "${buildStartTime}" "${previousStepEnd}" "${currentStepEnd}" "${NAMESPACE}" "cleanupRemovedRoutesComplete" "Removed Route Cleanup" +patchBuildStep "${buildStartTime}" "${previousStepEnd}" "${currentStepEnd}" "${NAMESPACE}" "cleanupRemovedRoutesComplete" "Route/Ingress Cleanup" previousStepEnd=${currentStepEnd} beginBuildStep "Post-Rollout Tasks" "runningPostRolloutTasks" set -x diff --git a/test-resources/identify-ingress/test18/docker-compose.yml b/test-resources/identify-ingress/test18/docker-compose.yml new file mode 100644 index 00000000..8620df9d --- /dev/null +++ b/test-resources/identify-ingress/test18/docker-compose.yml @@ -0,0 +1,104 @@ +version: '2.3' + +x-volumes: + &default-volumes + # Define all volumes you would like to have real-time mounted into the docker containers + volumes: + - .:/app:delegated ### Local overrides to mount host filesystem. Automatically removed in CI and PROD. + - files:/app/web/sites/default/files + +x-environment: + &default-environment + # Route that should be used locally, if you are using pygmy, this route *must* end with .docker.amazee.io + LAGOON_ROUTE: &default-url http://${COMPOSE_PROJECT_NAME:-drupal9-varnish}.docker.amazee.io + # Uncomment if you like to have the system behave like in production + #LAGOON_ENVIRONMENT_TYPE: production + # Uncomment to enable xdebug and then restart via `docker-compose up -d` + #XDEBUG_ENABLE: "true" + +x-user: + &default-user + # The default user under which the containers should run. Change this if you are on linux and run with another user than id `1000` + user: '1000' + +volumes: + files: + {} + db: + {} + +services: + + cli: # cli container, will be used for executing composer and any local commands (drush, drupal, etc.) + build: + context: . + dockerfile: lagoon/cli.dockerfile + image: &cli-image ${COMPOSE_PROJECT_NAME:-drupal9-varnish}-cli # this image will be reused as `CLI_IMAGE` in subsequent Docker builds + labels: + # Lagoon Labels + lagoon.type: cli-persistent + lagoon.persistent.name: nginx # mount the persistent storage of nginx into this container + lagoon.persistent: /app/web/sites/default/files/ # location where the persistent storage should be mounted + lando.type: php-cli-drupal + << : *default-volumes # loads the defined volumes from the top + user: root + volumes_from: ### mount the ssh-agent from the pygmy or cachalot ssh-agent. Automatically removed in CI. + - container:amazeeio-ssh-agent ### Local overrides to mount host SSH keys. Automatically removed in CI. + environment: + << : *default-environment # loads the defined environment variables from the top + + nginx: + build: + context: . + dockerfile: lagoon/nginx.dockerfile + args: + CLI_IMAGE: *cli-image # Inject the name of the cli image + labels: + lagoon.type: nginx-php-persistent + lagoon.persistent: /app/web/sites/default/files/ # define where the persistent storage should be mounted too + lando.type: nginx-drupal + << : *default-volumes # loads the defined volumes from the top + << : *default-user # uses the defined user from top + depends_on: + - cli # basically just tells docker-compose to build the cli first + environment: + << : *default-environment # loads the defined environment variables from the top + LAGOON_LOCALDEV_URL: nginx-${COMPOSE_PROJECT_NAME:-drupal9-varnish} # generate another route for nginx, by default we go to varnish + networks: + - amazeeio-network + - default + + php: + build: + context: . + dockerfile: lagoon/php.dockerfile + args: + CLI_IMAGE: *cli-image + labels: + lagoon.type: nginx-php-persistent + lagoon.name: nginx # we want this service be part of the nginx pod in Lagoon + lagoon.persistent: /app/web/sites/default/files/ # define where the persistent storage should be mounted too + lando.type: php-fpm + << : *default-volumes # loads the defined volumes from the top + << : *default-user # uses the defined user from top + depends_on: + - cli # basically just tells docker-compose to build the cli first + environment: + << : *default-environment # loads the defined environment variables from the top + + mariadb: + image: uselagoon/mariadb-10.5-drupal:latest + labels: + lagoon.type: mariadb + lando.type: mariadb-drupal + ports: + - "3306" # exposes the port 3306 with a random local port, find it with `docker-compose port mariadb 3306` + << : *default-user # uses the defined user from top + environment: + << : *default-environment + volumes: + - db:/var/lib/mysql + +networks: + amazeeio-network: + external: true diff --git a/test-resources/identify-ingress/test18/lagoon.yml b/test-resources/identify-ingress/test18/lagoon.yml new file mode 100644 index 00000000..e0704f17 --- /dev/null +++ b/test-resources/identify-ingress/test18/lagoon.yml @@ -0,0 +1,13 @@ +docker-compose-yaml: ../test-resources/identify-ingress/test18/docker-compose.yml + +environments: + main: + routes: + - nginx: + - "wild.example.com": + wildcard: true + tls-acme: false + - "alt.example.com": + alternativenames: + - www.example.com + - en.example.com \ No newline at end of file