diff --git a/api/v1alpha1/frontendenvironment_types.go b/api/v1alpha1/frontendenvironment_types.go index c746ca0d..ba476c96 100644 --- a/api/v1alpha1/frontendenvironment_types.go +++ b/api/v1alpha1/frontendenvironment_types.go @@ -88,8 +88,11 @@ type FrontendEnvironmentSpec struct { EnableAkamaiCacheBust bool `json:"enableAkamaiCacheBust,omitempty"` // Set Akamai Cache Bust Image AkamaiCacheBustImage string `json:"akamaiCacheBustImage,omitempty"` - // Set Akamai Cache Bust URL that the files will hang off of + // Deprecated: Users should move to AkamaiCacheBustURLs + // Preserving for backwards compatibility AkamaiCacheBustURL string `json:"akamaiCacheBustURL,omitempty"` + // Set Akamai Cache Bust URL that the files will hang off of + AkamaiCacheBustURLs []string `json:"akamaiCacheBustURLs,omitempty"` // The name of the secret we will use to get the akamai credentials AkamaiSecretName string `json:"akamaiSecretName,omitempty"` // List of namespaces that should receive a copy of the frontend configuration as a config map diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go index 9ff5aa8b..239787f2 100644 --- a/api/v1alpha1/zz_generated.deepcopy.go +++ b/api/v1alpha1/zz_generated.deepcopy.go @@ -480,6 +480,11 @@ func (in *FrontendEnvironmentSpec) DeepCopyInto(out *FrontendEnvironmentSpec) { *out = new(MonitoringConfig) **out = **in } + if in.AkamaiCacheBustURLs != nil { + in, out := &in.AkamaiCacheBustURLs, &out.AkamaiCacheBustURLs + *out = make([]string, len(*in)) + copy(*out, *in) + } if in.TargetNamespaces != nil { in, out := &in.TargetNamespaces, &out.TargetNamespaces *out = make([]string, len(*in)) diff --git a/config/crd/bases/cloud.redhat.com_frontendenvironments.yaml b/config/crd/bases/cloud.redhat.com_frontendenvironments.yaml index a6a6a5ba..cb70d4e2 100644 --- a/config/crd/bases/cloud.redhat.com_frontendenvironments.yaml +++ b/config/crd/bases/cloud.redhat.com_frontendenvironments.yaml @@ -53,9 +53,16 @@ spec: description: Set Akamai Cache Bust Image type: string akamaiCacheBustURL: + description: |- + Deprecated: Users should move to AkamaiCacheBustURLs + Preserving for backwards compatibility + type: string + akamaiCacheBustURLs: description: Set Akamai Cache Bust URL that the files will hang off of - type: string + items: + type: string + type: array akamaiSecretName: description: The name of the secret we will use to get the akamai credentials diff --git a/controllers/reconcile.go b/controllers/reconcile.go index 4071ee35..d4b800d6 100644 --- a/controllers/reconcile.go +++ b/controllers/reconcile.go @@ -216,30 +216,64 @@ func makeAkamaiEdgercFileFromSecret(secret *v1.Secret) string { } func createCachePurgePathList(frontend *crd.Frontend, frontendEnvironment *crd.FrontendEnvironment) []string { - // Set purgeHost by ensuring the URL begins with https:// and has no trailing / - purgeHost := strings.TrimSuffix(fmt.Sprintf("https://%s", strings.TrimPrefix(frontendEnvironment.Spec.AkamaiCacheBustURL, "https://")), "/") + var purgePaths []string - // Initialize with a default path if AkamaiCacheBustPaths is nil - purgePaths := []string{fmt.Sprintf("%s/apps/%s/fed-mods.json", purgeHost, frontend.Name)} + // Helper function to check if a path is already in the list + contains := func(slice []string, item string) bool { + for _, existing := range slice { + if existing == item { + return true + } + } + return false + } + + cacheBustUrls := frontendEnvironment.Spec.AkamaiCacheBustURLs - if frontend.Spec.AkamaiCacheBustPaths == nil { + if frontendEnvironment.Spec.AkamaiCacheBustURL != "" { + cacheBustUrls = append(cacheBustUrls, frontendEnvironment.Spec.AkamaiCacheBustURL) + } + + // Return early if we have no cache bust URLs of any kind to process + if len(cacheBustUrls) == 0 { return purgePaths } - purgePaths = make([]string, 0, len(frontend.Spec.AkamaiCacheBustPaths)) - for _, path := range frontend.Spec.AkamaiCacheBustPaths { - // Check if path is a full URL (starts with "http://" or "https://") - if strings.HasPrefix(path, "http://") || strings.HasPrefix(path, "https://") { - // Add full URL path directly - purgePaths = append(purgePaths, path) - } else { - // Ensure each path has a leading slash but no double slashes - if !strings.HasPrefix(path, "/") { - path = "/" + path + for _, cacheBustURL := range cacheBustUrls { + // Ensure the URL begins with https:// and has no trailing / + purgeHost := strings.TrimSuffix(fmt.Sprintf("https://%s", strings.TrimPrefix(cacheBustURL, "https://")), "/") + + // Add default path if AkamaiCacheBustPaths is nil + if frontend.Spec.AkamaiCacheBustPaths == nil { + defaultPath := fmt.Sprintf("%s/apps/%s/fed-mods.json", purgeHost, frontend.Name) + if !contains(purgePaths, defaultPath) { + purgePaths = append(purgePaths, defaultPath) + } + continue + } + + // Append paths based on AkamaiCacheBustPaths + for _, path := range frontend.Spec.AkamaiCacheBustPaths { + var fullPath string + + if strings.HasPrefix(path, "http://") || strings.HasPrefix(path, "https://") { + // Add full URL path directly + fullPath = path + } else { + // Ensure each path has a leading slash but no double slashes + if !strings.HasPrefix(path, "/") { + path = "/" + path + } + fullPath = purgeHost + path + } + + // Append the fullPath only if it doesn't already exist in purgePaths + if !contains(purgePaths, fullPath) { + purgePaths = append(purgePaths, fullPath) } - purgePaths = append(purgePaths, purgeHost+path) } } + return purgePaths } diff --git a/deploy.yml b/deploy.yml index b4713810..478d3d39 100644 --- a/deploy.yml +++ b/deploy.yml @@ -256,9 +256,16 @@ objects: description: Set Akamai Cache Bust Image type: string akamaiCacheBustURL: + description: 'Deprecated: Users should move to AkamaiCacheBustURLs + + Preserving for backwards compatibility' + type: string + akamaiCacheBustURLs: description: Set Akamai Cache Bust URL that the files will hang off of - type: string + items: + type: string + type: array akamaiSecretName: description: The name of the secret we will use to get the akamai credentials diff --git a/docs/antora/modules/ROOT/pages/api_reference.adoc b/docs/antora/modules/ROOT/pages/api_reference.adoc index 5746dee5..1145558c 100644 --- a/docs/antora/modules/ROOT/pages/api_reference.adoc +++ b/docs/antora/modules/ROOT/pages/api_reference.adoc @@ -458,7 +458,9 @@ parts should be generated for the bundles. We want to do + do this in epehemeral environments but not in production + | | | *`enableAkamaiCacheBust`* __boolean__ | Enable Akamai Cache Bust + | | | *`akamaiCacheBustImage`* __string__ | Set Akamai Cache Bust Image + | | -| *`akamaiCacheBustURL`* __string__ | Set Akamai Cache Bust URL that the files will hang off of + | | +| *`akamaiCacheBustURL`* __string__ | Deprecated: Users should move to AkamaiCacheBustURLs + +Preserving for backwards compatibility + | | +| *`akamaiCacheBustURLs`* __string array__ | Set Akamai Cache Bust URL that the files will hang off of + | | | *`akamaiSecretName`* __string__ | The name of the secret we will use to get the akamai credentials + | | | *`targetNamespaces`* __string array__ | List of namespaces that should receive a copy of the frontend configuration as a config map + By configurations we mean the fed-modules.json, navigation files, etc. + | | @@ -618,6 +620,7 @@ FrontendSpec defines the desired state of Frontend | *`serviceTiles`* __xref:{anchor_prefix}-github-com-redhatinsights-frontend-operator-api-v1alpha1-servicetile[$$ServiceTile$$] array__ | Data for the all services dropdown + | | | *`widgetRegistry`* __xref:{anchor_prefix}-github-com-redhatinsights-frontend-operator-api-v1alpha1-widgetentry[$$WidgetEntry$$] array__ | Data for the available widgets for the resource + | | | *`replicas`* __integer__ | | | +| *`feoConfigEnabled`* __boolean__ | Injects configuration from application when enabled + | | |=== diff --git a/tests/e2e/cachebust-multiple-urls/00-create-namespace.yaml b/tests/e2e/cachebust-multiple-urls/00-create-namespace.yaml new file mode 100644 index 00000000..b2ce11ca --- /dev/null +++ b/tests/e2e/cachebust-multiple-urls/00-create-namespace.yaml @@ -0,0 +1,21 @@ +--- +apiVersion: v1 +kind: Namespace +metadata: + name: test-cachebust-multiple-urls +spec: + finalizers: + - kubernetes +--- +kind: Secret +apiVersion: v1 +metadata: + name: akamai + namespace: test-cachebust-multiple-urls +data: + access_token: "YWNjZXNzX3Rva2Vu" + client_secret: "Y2xpZW50X3NlY3JldA==" + client_token: "Y2xpZW50X3Rva2Vu" + host: "aG9zdA==" +type: Opaque + diff --git a/tests/e2e/cachebust-multiple-urls/01-create-resources.yaml b/tests/e2e/cachebust-multiple-urls/01-create-resources.yaml new file mode 100644 index 00000000..b641b187 --- /dev/null +++ b/tests/e2e/cachebust-multiple-urls/01-create-resources.yaml @@ -0,0 +1,83 @@ +--- +apiVersion: cloud.redhat.com/v1alpha1 +kind: FrontendEnvironment +metadata: + name: test-cachebust-multiple-urls-environment +spec: + generateNavJSON: false + ssl: false + hostname: foo.redhat.com + sso: https://sso.foo.redhat.com + enableAkamaiCacheBust: true + akamaiCacheBustImage: "quay.io/rh_ee_addrew/hi_true_bye:add_alias" + akamaiCacheBustURLs: + - "console.doesntexist.redhat.com" + - "us.console.doesntexist.redhat.com" +--- +apiVersion: cloud.redhat.com/v1alpha1 +kind: Frontend +metadata: + name: chrome-test-filelist + namespace: test-cachebust-multiple-urls +spec: + API: + versions: + - v1 + frontend: + paths: + - / + akamaiCacheBustPaths: + - /config/chrome/fed-modules.json + - apps/chrome/index.html + - https://app.company.com + deploymentRepo: https://github.com/RedHatInsights/insights-chrome + envName: test-cachebust-multiple-urls-environment + image: quay.io/cloudservices/insights-chrome-frontend:720317c + module: + config: + ssoUrl: 'https://' + manifestLocation: /apps/chrome/js/fed-mods.json + title: Chrome +--- +apiVersion: cloud.redhat.com/v1alpha1 +kind: Frontend +metadata: + name: chrome-test-defaults + namespace: test-cachebust-multiple-urls +spec: + API: + versions: + - v1 + frontend: + paths: + - /chrome/defaults + deploymentRepo: https://github.com/RedHatInsights/insights-chrome + envName: test-cachebust-multiple-urls-environment + image: quay.io/cloudservices/insights-chrome-frontend:720317c + module: + config: + ssoUrl: 'https://' + manifestLocation: /apps/chrome/js/fed-mods.json + title: Chrome +--- +apiVersion: cloud.redhat.com/v1alpha1 +kind: Frontend +metadata: + name: chrome-test-optout + namespace: test-cachebust-multiple-urls +spec: + akamaiCacheBustDisable: true + API: + versions: + - v1 + frontend: + paths: + - /chrome2 + deploymentRepo: https://github.com/RedHatInsights/insights-chrome + envName: test-cachebust-multiple-urls-environment + image: quay.io/cloudservices/insights-chrome-frontend:720317c + module: + config: + ssoUrl: 'https://' + manifestLocation: /apps/chrome/js/fed-mods.json + title: Chrome diff --git a/tests/e2e/cachebust-multiple-urls/02-assert.yaml b/tests/e2e/cachebust-multiple-urls/02-assert.yaml new file mode 100644 index 00000000..d74c5d04 --- /dev/null +++ b/tests/e2e/cachebust-multiple-urls/02-assert.yaml @@ -0,0 +1,198 @@ +kind: Deployment +apiVersion: apps/v1 +metadata: + name: chrome-test-filelist-frontend + namespace: test-cachebust-multiple-urls + labels: + frontend: chrome-test-filelist + ownerReferences: + - apiVersion: cloud.redhat.com/v1alpha1 + kind: Frontend + name: chrome-test-filelist +spec: + selector: + matchLabels: + frontend: chrome-test-filelist + template: + metadata: + labels: + frontend: chrome-test-filelist + spec: + volumes: + - name: config + configMap: + name: test-cachebust-multiple-urls-environment + defaultMode: 420 + containers: + - name: fe-image + image: quay.io/cloudservices/insights-chrome-frontend:720317c + ports: + - name: web + containerPort: 80 + protocol: TCP + - name: metrics + containerPort: 9000 + protocol: TCP + resources: {} + volumeMounts: + - name: config + mountPath: /opt/app-root/src/build/stable/operator-generated + terminationMessagePath: /dev/termination-log + terminationMessagePolicy: File + imagePullPolicy: IfNotPresent +--- +apiVersion: batch/v1 +kind: Job +metadata: + name: chrome-test-filelist-frontend-cachebust + namespace: test-cachebust-multiple-urls + labels: + frontend: chrome-test-filelist + ownerReferences: + - apiVersion: cloud.redhat.com/v1alpha1 + kind: Frontend + name: chrome-test-filelist +spec: + template: + metadata: + annotations: + frontend-image: quay.io/cloudservices/insights-chrome-frontend:720317c + spec: + volumes: + - name: akamai-edgerc + configMap: + name: akamai-edgerc + defaultMode: 420 + containers: + - name: akamai-cache-bust + image: quay.io/rh_ee_addrew/hi_true_bye:add_alias + command: + - /bin/bash + - '-c' + - 'sleep 120; /cli/.akamai-cli/src/cli-purge/bin/akamai-purge --edgerc /opt/app-root/edgerc delete https://console.doesntexist.redhat.com/config/chrome/fed-modules.json https://console.doesntexist.redhat.com/apps/chrome/index.html https://app.company.com https://us.console.doesntexist.redhat.com/config/chrome/fed-modules.json https://us.console.doesntexist.redhat.com/apps/chrome/index.html' + resources: {} + volumeMounts: + - name: akamai-edgerc + mountPath: /opt/app-root/edgerc + subPath: edgerc + restartPolicy: Never +--- +kind: Deployment +apiVersion: apps/v1 +metadata: + name: chrome-test-defaults-frontend + namespace: test-cachebust-multiple-urls + labels: + frontend: chrome-test-defaults + ownerReferences: + - apiVersion: cloud.redhat.com/v1alpha1 + kind: Frontend + name: chrome-test-defaults +spec: + selector: + matchLabels: + frontend: chrome-test-defaults + template: + metadata: + labels: + frontend: chrome-test-defaults + spec: + volumes: + - name: config + configMap: + name: test-cachebust-multiple-urls-environment + defaultMode: 420 + containers: + - name: fe-image + image: quay.io/cloudservices/insights-chrome-frontend:720317c + ports: + - name: web + containerPort: 80 + protocol: TCP + - name: metrics + containerPort: 9000 + protocol: TCP + resources: {} + volumeMounts: + - name: config + mountPath: /opt/app-root/src/build/stable/operator-generated + terminationMessagePath: /dev/termination-log + terminationMessagePolicy: File + imagePullPolicy: IfNotPresent +--- +apiVersion: batch/v1 +kind: Job +metadata: + name: chrome-test-defaults-frontend-cachebust + namespace: test-cachebust-multiple-urls + labels: + frontend: chrome-test-defaults + ownerReferences: + - apiVersion: cloud.redhat.com/v1alpha1 + kind: Frontend + name: chrome-test-defaults +spec: + template: + metadata: + annotations: + frontend-image: quay.io/cloudservices/insights-chrome-frontend:720317c + spec: + volumes: + - name: akamai-edgerc + configMap: + name: akamai-edgerc + defaultMode: 420 + containers: + - name: akamai-cache-bust + image: quay.io/rh_ee_addrew/hi_true_bye:add_alias + command: + - /bin/bash + - '-c' + - 'sleep 120; /cli/.akamai-cli/src/cli-purge/bin/akamai-purge --edgerc /opt/app-root/edgerc delete https://console.doesntexist.redhat.com/apps/chrome-test-defaults/fed-mods.json https://us.console.doesntexist.redhat.com/apps/chrome-test-defaults/fed-mods.json' + resources: {} + volumeMounts: + - name: akamai-edgerc + mountPath: /opt/app-root/edgerc + subPath: edgerc + restartPolicy: Never +--- +kind: Deployment +apiVersion: apps/v1 +metadata: + name: chrome-test-optout-frontend + namespace: test-cachebust-multiple-urls + labels: + frontend: chrome-test-optout + ownerReferences: + - apiVersion: cloud.redhat.com/v1alpha1 + kind: Frontend + name: chrome-test-optout +spec: + replicas: 1 + selector: + matchLabels: + frontend: chrome-test-optout + template: + metadata: + labels: + frontend: chrome-test-optout + spec: + volumes: + - name: config + configMap: + name: test-cachebust-multiple-urls-environment + defaultMode: 420 + containers: + - name: fe-image + image: quay.io/cloudservices/insights-chrome-frontend:720317c + ports: + - name: web + containerPort: 80 + protocol: TCP + - name: metrics + containerPort: 9000 + protocol: TCP + resources: {} + volumeMounts: + - name: config + mountPath: /opt/app-root/src/build/stable/operator-generated diff --git a/tests/e2e/cachebust/03-update-resources.yaml b/tests/e2e/cachebust/03-update-resources.yaml index e2ac0d0a..b08f5025 100644 --- a/tests/e2e/cachebust/03-update-resources.yaml +++ b/tests/e2e/cachebust/03-update-resources.yaml @@ -10,7 +10,8 @@ spec: sso: https://sso.foo.redhat.com enableAkamaiCacheBust: true akamaiCacheBustImage: "quay.io/rh_ee_addrew/hi_true_bye:add_alias" - akamaiCacheBustURL: "console.doesntexist.redhat.com" + akamaiCacheBustURLs: + - "console.doesntexist.redhat.com" --- apiVersion: cloud.redhat.com/v1alpha1 kind: Frontend