From 69c8fe5eb97c29daa01552eec84958eb605567f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20M=C3=BCller?= Date: Mon, 1 Jun 2026 16:06:43 +0200 Subject: [PATCH 1/5] chore: Add 6.1.0 and deprecate 6.0.0 --- docs/modules/superset/partials/supported-versions.adoc | 3 ++- tests/test-definition.yaml | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/docs/modules/superset/partials/supported-versions.adoc b/docs/modules/superset/partials/supported-versions.adoc index 98da91db..29c31be7 100644 --- a/docs/modules/superset/partials/supported-versions.adoc +++ b/docs/modules/superset/partials/supported-versions.adoc @@ -2,5 +2,6 @@ // This is a separate file, since it is used by both the direct Superset documentation, and the overarching // Stackable Platform documentation. -- 6.0.0 +- 6.1.0 +- 6.0.0 (deprecated) - 4.1.4 (LTS) diff --git a/tests/test-definition.yaml b/tests/test-definition.yaml index 1dc0e360..43aa681e 100644 --- a/tests/test-definition.yaml +++ b/tests/test-definition.yaml @@ -10,10 +10,12 @@ dimensions: - 6.0.0 # Or use a custom image: # - x.x.x,oci.stackable.tech/razvan/superset:x.x.x-stackable0.0.0-dev + - 6.1.0,oci.stackable.tech/sandbox/superset:6.1.0 - name: superset-latest values: - - 6.0.0 + # - 6.0.0 # - x.x.x,oci.stackable.tech/razvan/superset:x.x.x-stackable0.0.0-dev + - 6.1.0,oci.stackable.tech/sandbox/superset:6.1.0 - name: ldap-authentication values: - no-tls From 534ea34f935c9870d30a2be397167e1ba8491daa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20M=C3=BCller?= Date: Thu, 4 Jun 2026 08:59:46 +0200 Subject: [PATCH 2/5] chore: upgrade tests for superset 6.1.0 --- .../kuttl/upgrade-oidc/00-patch-ns.yaml.j2 | 9 + .../kuttl/upgrade-oidc/10-assert.yaml | 14 ++ .../upgrade-oidc/10-install-postgresql.yaml | 12 + .../10_helm-bitnami-postgresql-values.yaml.j2 | 44 ++++ ...tor-aggregator-discovery-configmap.yaml.j2 | 9 + .../kuttl/upgrade-oidc/30-assert.yaml | 14 ++ .../kuttl/upgrade-oidc/30-keycloak.yaml | 15 ++ .../upgrade-oidc/30_install-keycloak.yaml.j2 | 178 +++++++++++++ .../kuttl/upgrade-oidc/40-assert.yaml | 16 ++ .../upgrade-oidc/40-install-superset.yaml | 8 + .../upgrade-oidc/40_install-superset.yaml.j2 | 64 +++++ .../kuttl/upgrade-oidc/50-assert.yaml | 14 ++ .../50-install-test-container.yaml.j2 | 88 +++++++ .../kuttl/upgrade-oidc/60-assert.yaml | 8 + .../kuttl/upgrade-oidc/60-login.yaml | 9 + .../templates/kuttl/upgrade-oidc/60_login.py | 58 +++++ .../kuttl/upgrade-oidc/70-assert.yaml.j2 | 38 +++ .../upgrade-oidc/70-upgrade-superset.yaml.j2 | 14 ++ .../kuttl/upgrade-oidc/80-assert.yaml | 12 + .../kuttl/upgrade/00-limit-range.yaml | 11 + .../kuttl/upgrade/00-patch-ns.yaml.j2 | 9 + tests/templates/kuttl/upgrade/10-assert.yaml | 14 ++ .../kuttl/upgrade/10-install-postgresql.yaml | 12 + ...tor-aggregator-discovery-configmap.yaml.j2 | 9 + tests/templates/kuttl/upgrade/30-assert.yaml | 8 + .../kuttl/upgrade/30-install-superset.yaml.j2 | 64 +++++ tests/templates/kuttl/upgrade/40-assert.yaml | 14 ++ .../upgrade/40-install-test-container.yaml | 35 +++ tests/templates/kuttl/upgrade/50-assert.yaml | 8 + tests/templates/kuttl/upgrade/50-seed.yaml | 7 + .../templates/kuttl/upgrade/60-assert.yaml.j2 | 41 +++ .../kuttl/upgrade/60-upgrade-superset.yaml.j2 | 14 ++ tests/templates/kuttl/upgrade/70-assert.yaml | 8 + .../helm-bitnami-postgresql-values.yaml.j2 | 44 ++++ tests/templates/kuttl/upgrade/upgrade-test.py | 235 ++++++++++++++++++ tests/test-definition.yaml | 30 ++- 36 files changed, 1181 insertions(+), 6 deletions(-) create mode 100644 tests/templates/kuttl/upgrade-oidc/00-patch-ns.yaml.j2 create mode 100644 tests/templates/kuttl/upgrade-oidc/10-assert.yaml create mode 100644 tests/templates/kuttl/upgrade-oidc/10-install-postgresql.yaml create mode 100644 tests/templates/kuttl/upgrade-oidc/10_helm-bitnami-postgresql-values.yaml.j2 create mode 100644 tests/templates/kuttl/upgrade-oidc/20-install-vector-aggregator-discovery-configmap.yaml.j2 create mode 100644 tests/templates/kuttl/upgrade-oidc/30-assert.yaml create mode 100644 tests/templates/kuttl/upgrade-oidc/30-keycloak.yaml create mode 100644 tests/templates/kuttl/upgrade-oidc/30_install-keycloak.yaml.j2 create mode 100644 tests/templates/kuttl/upgrade-oidc/40-assert.yaml create mode 100644 tests/templates/kuttl/upgrade-oidc/40-install-superset.yaml create mode 100644 tests/templates/kuttl/upgrade-oidc/40_install-superset.yaml.j2 create mode 100644 tests/templates/kuttl/upgrade-oidc/50-assert.yaml create mode 100644 tests/templates/kuttl/upgrade-oidc/50-install-test-container.yaml.j2 create mode 100644 tests/templates/kuttl/upgrade-oidc/60-assert.yaml create mode 100644 tests/templates/kuttl/upgrade-oidc/60-login.yaml create mode 100644 tests/templates/kuttl/upgrade-oidc/60_login.py create mode 100644 tests/templates/kuttl/upgrade-oidc/70-assert.yaml.j2 create mode 100644 tests/templates/kuttl/upgrade-oidc/70-upgrade-superset.yaml.j2 create mode 100644 tests/templates/kuttl/upgrade-oidc/80-assert.yaml create mode 100644 tests/templates/kuttl/upgrade/00-limit-range.yaml create mode 100644 tests/templates/kuttl/upgrade/00-patch-ns.yaml.j2 create mode 100644 tests/templates/kuttl/upgrade/10-assert.yaml create mode 100644 tests/templates/kuttl/upgrade/10-install-postgresql.yaml create mode 100644 tests/templates/kuttl/upgrade/20-install-vector-aggregator-discovery-configmap.yaml.j2 create mode 100644 tests/templates/kuttl/upgrade/30-assert.yaml create mode 100644 tests/templates/kuttl/upgrade/30-install-superset.yaml.j2 create mode 100644 tests/templates/kuttl/upgrade/40-assert.yaml create mode 100644 tests/templates/kuttl/upgrade/40-install-test-container.yaml create mode 100644 tests/templates/kuttl/upgrade/50-assert.yaml create mode 100644 tests/templates/kuttl/upgrade/50-seed.yaml create mode 100644 tests/templates/kuttl/upgrade/60-assert.yaml.j2 create mode 100644 tests/templates/kuttl/upgrade/60-upgrade-superset.yaml.j2 create mode 100644 tests/templates/kuttl/upgrade/70-assert.yaml create mode 100644 tests/templates/kuttl/upgrade/helm-bitnami-postgresql-values.yaml.j2 create mode 100644 tests/templates/kuttl/upgrade/upgrade-test.py diff --git a/tests/templates/kuttl/upgrade-oidc/00-patch-ns.yaml.j2 b/tests/templates/kuttl/upgrade-oidc/00-patch-ns.yaml.j2 new file mode 100644 index 00000000..67185acf --- /dev/null +++ b/tests/templates/kuttl/upgrade-oidc/00-patch-ns.yaml.j2 @@ -0,0 +1,9 @@ +{% if test_scenario['values']['openshift'] == 'true' %} +# see https://github.com/stackabletech/issues/issues/566 +--- +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +commands: + - script: kubectl patch namespace $NAMESPACE -p '{"metadata":{"labels":{"pod-security.kubernetes.io/enforce":"privileged"}}}' + timeout: 120 +{% endif %} diff --git a/tests/templates/kuttl/upgrade-oidc/10-assert.yaml b/tests/templates/kuttl/upgrade-oidc/10-assert.yaml new file mode 100644 index 00000000..e9c60b15 --- /dev/null +++ b/tests/templates/kuttl/upgrade-oidc/10-assert.yaml @@ -0,0 +1,14 @@ +--- +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +metadata: + name: test-superset-postgresql +timeout: 480 +--- +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: superset-postgresql +status: + readyReplicas: 1 + replicas: 1 diff --git a/tests/templates/kuttl/upgrade-oidc/10-install-postgresql.yaml b/tests/templates/kuttl/upgrade-oidc/10-install-postgresql.yaml new file mode 100644 index 00000000..a9fc0d36 --- /dev/null +++ b/tests/templates/kuttl/upgrade-oidc/10-install-postgresql.yaml @@ -0,0 +1,12 @@ +--- +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +commands: + - script: >- + helm install superset-postgresql + --namespace $NAMESPACE + --version 12.5.6 + -f 10_helm-bitnami-postgresql-values.yaml + --repo https://charts.bitnami.com/bitnami postgresql + --wait + timeout: 600 diff --git a/tests/templates/kuttl/upgrade-oidc/10_helm-bitnami-postgresql-values.yaml.j2 b/tests/templates/kuttl/upgrade-oidc/10_helm-bitnami-postgresql-values.yaml.j2 new file mode 100644 index 00000000..2e851682 --- /dev/null +++ b/tests/templates/kuttl/upgrade-oidc/10_helm-bitnami-postgresql-values.yaml.j2 @@ -0,0 +1,44 @@ +--- +global: + security: + allowInsecureImages: true # needed starting with Chart version 16.3.0 if modifying images + +image: + repository: bitnamilegacy/postgresql + +volumePermissions: + enabled: false + image: + repository: bitnamilegacy/os-shell + securityContext: + runAsUser: auto + +metrics: + image: + repository: bitnamilegacy/postgres-exporter + +primary: + podSecurityContext: +{% if test_scenario['values']['openshift'] == 'true' %} + enabled: false +{% else %} + enabled: true +{% endif %} + containerSecurityContext: + enabled: false + resources: + requests: + memory: "128Mi" + cpu: "512m" + limits: + memory: "128Mi" + cpu: "1" + +shmVolume: + chmod: + enabled: false + +auth: + username: superset + password: superset + database: superset diff --git a/tests/templates/kuttl/upgrade-oidc/20-install-vector-aggregator-discovery-configmap.yaml.j2 b/tests/templates/kuttl/upgrade-oidc/20-install-vector-aggregator-discovery-configmap.yaml.j2 new file mode 100644 index 00000000..2d6a0df5 --- /dev/null +++ b/tests/templates/kuttl/upgrade-oidc/20-install-vector-aggregator-discovery-configmap.yaml.j2 @@ -0,0 +1,9 @@ +{% if lookup('env', 'VECTOR_AGGREGATOR') %} +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: vector-aggregator-discovery +data: + ADDRESS: {{ lookup('env', 'VECTOR_AGGREGATOR') }} +{% endif %} diff --git a/tests/templates/kuttl/upgrade-oidc/30-assert.yaml b/tests/templates/kuttl/upgrade-oidc/30-assert.yaml new file mode 100644 index 00000000..02818f1f --- /dev/null +++ b/tests/templates/kuttl/upgrade-oidc/30-assert.yaml @@ -0,0 +1,14 @@ +--- +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +metadata: + name: test-keycloak +timeout: 480 +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: keycloak1 +status: + readyReplicas: 1 + replicas: 1 diff --git a/tests/templates/kuttl/upgrade-oidc/30-keycloak.yaml b/tests/templates/kuttl/upgrade-oidc/30-keycloak.yaml new file mode 100644 index 00000000..8fe061be --- /dev/null +++ b/tests/templates/kuttl/upgrade-oidc/30-keycloak.yaml @@ -0,0 +1,15 @@ +--- +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +commands: + - script: | + INSTANCE_NAME=keycloak1 \ + REALM=test1 \ + USERNAME=jane.doe \ + FIRST_NAME=Jane \ + LAST_NAME=Doe \ + EMAIL=jane.doe@stackable.tech \ + PASSWORD=T8mn72D9 \ + CLIENT_ID=superset1 \ + CLIENT_SECRET=R1bxHUD569vHeQdw \ + envsubst < 30_install-keycloak.yaml | kubectl apply -n $NAMESPACE -f - diff --git a/tests/templates/kuttl/upgrade-oidc/30_install-keycloak.yaml.j2 b/tests/templates/kuttl/upgrade-oidc/30_install-keycloak.yaml.j2 new file mode 100644 index 00000000..f9098fc2 --- /dev/null +++ b/tests/templates/kuttl/upgrade-oidc/30_install-keycloak.yaml.j2 @@ -0,0 +1,178 @@ +# The environment variables must be replaced. +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: $INSTANCE_NAME-realms +data: + test-realm.json: | + { + "realm": "$REALM", + "enabled": true, + "users": [ + { + "enabled": true, + "username": "$USERNAME", + "firstName" : "$FIRST_NAME", + "lastName" : "$LAST_NAME", + "email" : "$EMAIL", + "credentials": [ + { + "type": "password", + "value": "$PASSWORD" + } + ], + "realmRoles": [ + "user" + ] + } + ], + "roles": { + "realm": [ + { + "name": "user", + "description": "User privileges" + } + ] + }, + "clients": [ + { + "clientId": "$CLIENT_ID", + "enabled": true, + "clientAuthenticatorType": "client-secret", + "secret": "$CLIENT_SECRET", + "redirectUris": [ + "*" + ], + "webOrigins": [ + "*" + ], + "standardFlowEnabled": true, + "protocol": "openid-connect" + } + ] + } +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: $INSTANCE_NAME + labels: + app: $INSTANCE_NAME +spec: + replicas: 1 + selector: + matchLabels: + app: $INSTANCE_NAME + template: + metadata: + labels: + app: $INSTANCE_NAME + spec: + serviceAccountName: keycloak + containers: + - name: keycloak + image: quay.io/keycloak/keycloak:23.0.4 + args: + - start-dev + - --import-realm + - --https-certificate-file=/tls/tls.crt + - --https-certificate-key-file=/tls/tls.key + env: + - name: KEYCLOAK_ADMIN + value: admin + - name: KEYCLOAK_ADMIN_PASSWORD + value: admin + ports: + - name: https + containerPort: 8443 + volumeMounts: + - name: realms + mountPath: /opt/keycloak/data/import + - name: tls + mountPath: /tls + readinessProbe: + httpGet: + scheme: HTTPS + path: /realms/$REALM + port: 8443 + volumes: + - name: realms + configMap: + name: $INSTANCE_NAME-realms + - name: tls + ephemeral: + volumeClaimTemplate: + metadata: + annotations: + secrets.stackable.tech/class: tls + secrets.stackable.tech/scope: service=$INSTANCE_NAME + spec: + storageClassName: secrets.stackable.tech + accessModes: + - ReadWriteOnce + resources: + requests: + storage: "1" +--- +apiVersion: v1 +kind: Service +metadata: + name: $INSTANCE_NAME +spec: + selector: + app: $INSTANCE_NAME + ports: + - protocol: TCP + port: 8443 +--- +apiVersion: authentication.stackable.tech/v1alpha1 +kind: AuthenticationClass +metadata: + name: $INSTANCE_NAME-$NAMESPACE +spec: + provider: + oidc: + hostname: $INSTANCE_NAME.$NAMESPACE.svc.cluster.local + port: 8443 + rootPath: /realms/$REALM/ + scopes: + - email + - openid + - profile + principalClaim: preferred_username + providerHint: Keycloak + tls: + verification: + server: + caCert: + secretClass: tls +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: keycloak +--- +kind: Role +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: keycloak +{% if test_scenario['values']['openshift'] == 'true' %} +rules: +- apiGroups: ["security.openshift.io"] + resources: ["securitycontextconstraints"] + resourceNames: ["privileged"] + verbs: ["use"] +{% endif %} +--- +kind: RoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: keycloak +subjects: + - kind: ServiceAccount + name: keycloak +roleRef: + kind: Role + name: keycloak + apiGroup: rbac.authorization.k8s.io diff --git a/tests/templates/kuttl/upgrade-oidc/40-assert.yaml b/tests/templates/kuttl/upgrade-oidc/40-assert.yaml new file mode 100644 index 00000000..daae9510 --- /dev/null +++ b/tests/templates/kuttl/upgrade-oidc/40-assert.yaml @@ -0,0 +1,16 @@ +--- +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +metadata: + name: install-superset +timeout: 600 +commands: + - script: kubectl -n $NAMESPACE wait --for=condition=available=true supersetclusters.superset.stackable.tech/superset --timeout 601s +--- +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: superset-node-default +status: + readyReplicas: 1 + replicas: 1 diff --git a/tests/templates/kuttl/upgrade-oidc/40-install-superset.yaml b/tests/templates/kuttl/upgrade-oidc/40-install-superset.yaml new file mode 100644 index 00000000..c97f66e8 --- /dev/null +++ b/tests/templates/kuttl/upgrade-oidc/40-install-superset.yaml @@ -0,0 +1,8 @@ +--- +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +timeout: 300 +commands: + - script: > + envsubst '$NAMESPACE' < 40_install-superset.yaml | + kubectl apply -n $NAMESPACE -f - diff --git a/tests/templates/kuttl/upgrade-oidc/40_install-superset.yaml.j2 b/tests/templates/kuttl/upgrade-oidc/40_install-superset.yaml.j2 new file mode 100644 index 00000000..e2851a40 --- /dev/null +++ b/tests/templates/kuttl/upgrade-oidc/40_install-superset.yaml.j2 @@ -0,0 +1,64 @@ +# $NAMESPACE will be replaced with the namespace of the test case. +--- +apiVersion: v1 +kind: Secret +metadata: + name: superset-admin-credentials +type: Opaque +stringData: + adminUser.username: admin + adminUser.firstname: Superset + adminUser.lastname: Admin + adminUser.email: admin@superset.com + adminUser.password: admin +--- +apiVersion: v1 +kind: Secret +metadata: + name: superset-postgresql-credentials +stringData: + username: superset + password: superset +--- +apiVersion: v1 +kind: Secret +metadata: + name: superset-keycloak1-client +stringData: + clientId: superset1 + clientSecret: R1bxHUD569vHeQdw +--- +apiVersion: superset.stackable.tech/v1alpha1 +kind: SupersetCluster +metadata: + name: superset +spec: + image: +{% if test_scenario['values']['superset-old'].find(",") > 0 %} + custom: "{{ test_scenario['values']['superset-old'].split(',')[1] }}" + productVersion: "{{ test_scenario['values']['superset-old'].split(',')[0] }}" +{% else %} + productVersion: "{{ test_scenario['values']['superset-old'] }}" +{% endif %} + pullPolicy: IfNotPresent + clusterConfig: + authentication: + - authenticationClass: keycloak1-$NAMESPACE + oidc: + clientCredentialsSecret: superset-keycloak1-client + credentialsSecretName: superset-admin-credentials + metadataDatabase: + postgresql: + host: superset-postgresql + database: superset + credentialsSecretName: superset-postgresql-credentials +{% if lookup('env', 'VECTOR_AGGREGATOR') %} + vectorAggregatorConfigMapName: vector-aggregator-discovery +{% endif %} + nodes: + config: + logging: + enableVectorAgent: {{ lookup('env', 'VECTOR_AGGREGATOR') | length > 0 }} + roleGroups: + default: + replicas: 1 diff --git a/tests/templates/kuttl/upgrade-oidc/50-assert.yaml b/tests/templates/kuttl/upgrade-oidc/50-assert.yaml new file mode 100644 index 00000000..58987778 --- /dev/null +++ b/tests/templates/kuttl/upgrade-oidc/50-assert.yaml @@ -0,0 +1,14 @@ +--- +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +metadata: + name: install-test-container +timeout: 300 +--- +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: python +status: + readyReplicas: 1 + replicas: 1 diff --git a/tests/templates/kuttl/upgrade-oidc/50-install-test-container.yaml.j2 b/tests/templates/kuttl/upgrade-oidc/50-install-test-container.yaml.j2 new file mode 100644 index 00000000..ff787c33 --- /dev/null +++ b/tests/templates/kuttl/upgrade-oidc/50-install-test-container.yaml.j2 @@ -0,0 +1,88 @@ +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: python +--- +kind: Role +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: python +{% if test_scenario['values']['openshift'] == 'true' %} +rules: +- apiGroups: ["security.openshift.io"] + resources: ["securitycontextconstraints"] + resourceNames: ["privileged"] + verbs: ["use"] +{% endif %} +--- +kind: RoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: python +subjects: + - kind: ServiceAccount + name: python +roleRef: + kind: Role + name: python + apiGroup: rbac.authorization.k8s.io +--- +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +metadata: + name: install-test-container +timeout: 300 +--- +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: python + labels: + app: python +spec: + replicas: 1 + selector: + matchLabels: + app: python + template: + metadata: + labels: + app: python + spec: + serviceAccountName: python + securityContext: + fsGroup: 1000 + containers: + - name: python + image: oci.stackable.tech/sdp/testing-tools:0.3.0-stackable0.0.0-dev + stdin: true + tty: true + resources: + requests: + memory: "128Mi" + cpu: "512m" + limits: + memory: "128Mi" + cpu: "1" + volumeMounts: + - name: tls + mountPath: /stackable/tls + env: + - name: REQUESTS_CA_BUNDLE + value: /stackable/tls/ca.crt + volumes: + - name: tls + ephemeral: + volumeClaimTemplate: + metadata: + annotations: + secrets.stackable.tech/class: tls + secrets.stackable.tech/scope: pod + spec: + storageClassName: secrets.stackable.tech + accessModes: + - ReadWriteOnce + resources: + requests: + storage: "1" diff --git a/tests/templates/kuttl/upgrade-oidc/60-assert.yaml b/tests/templates/kuttl/upgrade-oidc/60-assert.yaml new file mode 100644 index 00000000..df17232b --- /dev/null +++ b/tests/templates/kuttl/upgrade-oidc/60-assert.yaml @@ -0,0 +1,8 @@ +--- +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +metadata: + name: login +timeout: 300 +commands: + - script: kubectl exec -n $NAMESPACE python-0 -- python /stackable/60_login.py diff --git a/tests/templates/kuttl/upgrade-oidc/60-login.yaml b/tests/templates/kuttl/upgrade-oidc/60-login.yaml new file mode 100644 index 00000000..0e6aaac7 --- /dev/null +++ b/tests/templates/kuttl/upgrade-oidc/60-login.yaml @@ -0,0 +1,9 @@ +--- +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +metadata: + name: login +commands: + - script: > + envsubst '$NAMESPACE' < 60_login.py | + kubectl exec -n $NAMESPACE -i python-0 -- tee /stackable/60_login.py > /dev/null diff --git a/tests/templates/kuttl/upgrade-oidc/60_login.py b/tests/templates/kuttl/upgrade-oidc/60_login.py new file mode 100644 index 00000000..df173669 --- /dev/null +++ b/tests/templates/kuttl/upgrade-oidc/60_login.py @@ -0,0 +1,58 @@ +# $NAMESPACE will be replaced with the namespace of the test case. + +import json +import logging +import sys +import requests +from bs4 import BeautifulSoup + +logging.basicConfig( + level="DEBUG", format="%(asctime)s %(levelname)s: %(message)s", stream=sys.stdout +) + +session = requests.Session() + +# Click on "Sign In with keycloak" in Superset +login_page = session.get("http://superset-node:8088/login/keycloak?next=") + +assert login_page.ok, "Redirection from Superset to Keycloak failed" +assert login_page.url.startswith( + "https://keycloak1.$NAMESPACE.svc.cluster.local:8443/realms/test1/protocol/openid-connect/auth?response_type=code&client_id=superset1" +), "Redirection to the Keycloak login page expected" + +# Enter username and password into the Keycloak login page and click on "Sign In" +login_page_html = BeautifulSoup(login_page.text, "html.parser") +authenticate_url = login_page_html.form["action"] +welcome_page = session.post( + authenticate_url, data={"username": "jane.doe", "password": "T8mn72D9"} +) + +assert welcome_page.ok, "Login failed" +assert welcome_page.url == "http://superset-node:8088/superset/welcome/", ( + "Redirection to the Superset welcome page expected" +) + +# Open the user information page in Superset +userinfo_page = session.get("http://superset-node:8088/users/userinfo/") + +assert userinfo_page.ok, "Retrieving user information failed" +assert userinfo_page.url == "http://superset-node:8088/superset/welcome/", ( + "Redirection to the Superset welcome page expected" +) + +# Expect the user data provided by Keycloak in Superset +userinfo_page_html = BeautifulSoup(userinfo_page.text, "html.parser") +raw_data = userinfo_page_html.find(id="app")["data-bootstrap"] +data = json.loads(raw_data) +user_data = data["user"] + +assert user_data["firstName"] == "Jane", ( + "The first name of the user in Superset should match the one provided by Keycloak" +) +assert user_data["lastName"] == "Doe", ( + "The last name of the user in Superset should match the one provided by Keycloak" +) +assert user_data["email"] == "jane.doe@stackable.tech", ( + "The email of the user in Superset should match the one provided by Keycloak" +) + diff --git a/tests/templates/kuttl/upgrade-oidc/70-assert.yaml.j2 b/tests/templates/kuttl/upgrade-oidc/70-assert.yaml.j2 new file mode 100644 index 00000000..b21338eb --- /dev/null +++ b/tests/templates/kuttl/upgrade-oidc/70-assert.yaml.j2 @@ -0,0 +1,38 @@ +{# Compute the app.kubernetes.io/version label value which operator-rs derives #} +{# from the product image: "-" for custom images and #} +{# "-stackable" otherwise; tests always run #} +{# against a 0.0.0-dev operator. #} +{% if test_scenario['values']['superset-new'].find(",") > 0 %} +{% set product_version = test_scenario['values']['superset-new'].split(',')[0] %} +{% set image_tag = test_scenario['values']['superset-new'].split(',')[1].split(':')[-1] %} +{% set app_version = product_version ~ '-' ~ image_tag %} +{% else %} +{% set app_version = test_scenario['values']['superset-new'] ~ '-stackable0.0.0-dev' %} +{% endif %} +--- +# Asserting the version label on the pod (not only on the StatefulSet) ensures +# that the assertion cannot pass before the old pod was actually replaced. +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +metadata: + name: upgrade-superset +timeout: 600 +--- +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: superset-node-default + labels: + app.kubernetes.io/version: "{{ app_version }}" +status: + readyReplicas: 1 + replicas: 1 +--- +apiVersion: v1 +kind: Pod +metadata: + name: superset-node-default-0 + labels: + app.kubernetes.io/version: "{{ app_version }}" +status: + phase: Running diff --git a/tests/templates/kuttl/upgrade-oidc/70-upgrade-superset.yaml.j2 b/tests/templates/kuttl/upgrade-oidc/70-upgrade-superset.yaml.j2 new file mode 100644 index 00000000..4017ca79 --- /dev/null +++ b/tests/templates/kuttl/upgrade-oidc/70-upgrade-superset.yaml.j2 @@ -0,0 +1,14 @@ +--- +apiVersion: superset.stackable.tech/v1alpha1 +kind: SupersetCluster +metadata: + name: superset +spec: + image: +{% if test_scenario['values']['superset-new'].find(",") > 0 %} + custom: "{{ test_scenario['values']['superset-new'].split(',')[1] }}" + productVersion: "{{ test_scenario['values']['superset-new'].split(',')[0] }}" +{% else %} + custom: null + productVersion: "{{ test_scenario['values']['superset-new'] }}" +{% endif %} diff --git a/tests/templates/kuttl/upgrade-oidc/80-assert.yaml b/tests/templates/kuttl/upgrade-oidc/80-assert.yaml new file mode 100644 index 00000000..b11a5485 --- /dev/null +++ b/tests/templates/kuttl/upgrade-oidc/80-assert.yaml @@ -0,0 +1,12 @@ +--- +# Log in via Keycloak again after the upgrade. The user record was created by +# Flask-AppBuilder during the pre-upgrade login (step 60), so this exercises +# the existing-user OAuth login path on the new Superset/FAB version. The +# script was already copied to the test pod in step 60. +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +metadata: + name: login-after-upgrade +timeout: 300 +commands: + - script: kubectl exec -n $NAMESPACE python-0 -- python /stackable/60_login.py diff --git a/tests/templates/kuttl/upgrade/00-limit-range.yaml b/tests/templates/kuttl/upgrade/00-limit-range.yaml new file mode 100644 index 00000000..8fd02210 --- /dev/null +++ b/tests/templates/kuttl/upgrade/00-limit-range.yaml @@ -0,0 +1,11 @@ +--- +apiVersion: v1 +kind: LimitRange +metadata: + name: limit-request-ratio +spec: + limits: + - type: "Container" + maxLimitRequestRatio: + cpu: 5 + memory: 1 diff --git a/tests/templates/kuttl/upgrade/00-patch-ns.yaml.j2 b/tests/templates/kuttl/upgrade/00-patch-ns.yaml.j2 new file mode 100644 index 00000000..67185acf --- /dev/null +++ b/tests/templates/kuttl/upgrade/00-patch-ns.yaml.j2 @@ -0,0 +1,9 @@ +{% if test_scenario['values']['openshift'] == 'true' %} +# see https://github.com/stackabletech/issues/issues/566 +--- +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +commands: + - script: kubectl patch namespace $NAMESPACE -p '{"metadata":{"labels":{"pod-security.kubernetes.io/enforce":"privileged"}}}' + timeout: 120 +{% endif %} diff --git a/tests/templates/kuttl/upgrade/10-assert.yaml b/tests/templates/kuttl/upgrade/10-assert.yaml new file mode 100644 index 00000000..e9c60b15 --- /dev/null +++ b/tests/templates/kuttl/upgrade/10-assert.yaml @@ -0,0 +1,14 @@ +--- +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +metadata: + name: test-superset-postgresql +timeout: 480 +--- +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: superset-postgresql +status: + readyReplicas: 1 + replicas: 1 diff --git a/tests/templates/kuttl/upgrade/10-install-postgresql.yaml b/tests/templates/kuttl/upgrade/10-install-postgresql.yaml new file mode 100644 index 00000000..50c5ad67 --- /dev/null +++ b/tests/templates/kuttl/upgrade/10-install-postgresql.yaml @@ -0,0 +1,12 @@ +--- +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +commands: + - script: >- + helm install superset-postgresql + --namespace $NAMESPACE + --version 12.5.6 + -f helm-bitnami-postgresql-values.yaml + --repo https://charts.bitnami.com/bitnami postgresql + --wait + timeout: 600 diff --git a/tests/templates/kuttl/upgrade/20-install-vector-aggregator-discovery-configmap.yaml.j2 b/tests/templates/kuttl/upgrade/20-install-vector-aggregator-discovery-configmap.yaml.j2 new file mode 100644 index 00000000..2d6a0df5 --- /dev/null +++ b/tests/templates/kuttl/upgrade/20-install-vector-aggregator-discovery-configmap.yaml.j2 @@ -0,0 +1,9 @@ +{% if lookup('env', 'VECTOR_AGGREGATOR') %} +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: vector-aggregator-discovery +data: + ADDRESS: {{ lookup('env', 'VECTOR_AGGREGATOR') }} +{% endif %} diff --git a/tests/templates/kuttl/upgrade/30-assert.yaml b/tests/templates/kuttl/upgrade/30-assert.yaml new file mode 100644 index 00000000..468dcc2f --- /dev/null +++ b/tests/templates/kuttl/upgrade/30-assert.yaml @@ -0,0 +1,8 @@ +--- +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +metadata: + name: install-superset +timeout: 600 +commands: + - script: kubectl -n $NAMESPACE wait --for=condition=available=true supersetclusters.superset.stackable.tech/superset --timeout 601s diff --git a/tests/templates/kuttl/upgrade/30-install-superset.yaml.j2 b/tests/templates/kuttl/upgrade/30-install-superset.yaml.j2 new file mode 100644 index 00000000..c8313d27 --- /dev/null +++ b/tests/templates/kuttl/upgrade/30-install-superset.yaml.j2 @@ -0,0 +1,64 @@ +--- +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +metadata: + name: install-superset +timeout: 300 +--- +apiVersion: v1 +kind: Secret +metadata: + name: superset-admin-credentials +type: Opaque +stringData: + adminUser.username: admin + adminUser.firstname: Superset + adminUser.lastname: Admin + adminUser.email: admin@superset.com + adminUser.password: admin +--- +apiVersion: v1 +kind: Secret +metadata: + name: superset-postgresql-credentials +stringData: + username: superset + password: superset +--- +apiVersion: superset.stackable.tech/v1alpha1 +kind: SupersetCluster +metadata: + name: superset +spec: + image: +{% if test_scenario['values']['superset-old'].find(",") > 0 %} + custom: "{{ test_scenario['values']['superset-old'].split(',')[1] }}" + productVersion: "{{ test_scenario['values']['superset-old'].split(',')[0] }}" +{% else %} + productVersion: "{{ test_scenario['values']['superset-old'] }}" +{% endif %} + pullPolicy: IfNotPresent + clusterConfig: + credentialsSecretName: superset-admin-credentials + metadataDatabase: + postgresql: + host: superset-postgresql + database: superset + credentialsSecretName: superset-postgresql-credentials +{% if lookup('env', 'VECTOR_AGGREGATOR') %} + vectorAggregatorConfigMapName: vector-aggregator-discovery +{% endif %} + nodes: + configOverrides: + superset_config.py: + FILE_FOOTER: | + # The FAB security API is required by upgrade-test.py to seed a role + # and a user. Superset versions before 6.0.0 do not enable it by + # default. + FAB_ADD_SECURITY_API = True + config: + logging: + enableVectorAgent: {{ lookup('env', 'VECTOR_AGGREGATOR') | length > 0 }} + roleGroups: + default: + replicas: 1 diff --git a/tests/templates/kuttl/upgrade/40-assert.yaml b/tests/templates/kuttl/upgrade/40-assert.yaml new file mode 100644 index 00000000..58987778 --- /dev/null +++ b/tests/templates/kuttl/upgrade/40-assert.yaml @@ -0,0 +1,14 @@ +--- +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +metadata: + name: install-test-container +timeout: 300 +--- +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: python +status: + readyReplicas: 1 + replicas: 1 diff --git a/tests/templates/kuttl/upgrade/40-install-test-container.yaml b/tests/templates/kuttl/upgrade/40-install-test-container.yaml new file mode 100644 index 00000000..7d8002f3 --- /dev/null +++ b/tests/templates/kuttl/upgrade/40-install-test-container.yaml @@ -0,0 +1,35 @@ +--- +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +metadata: + name: install-test-container +timeout: 300 +--- +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: python + labels: + app: python +spec: + replicas: 1 + selector: + matchLabels: + app: python + template: + metadata: + labels: + app: python + spec: + containers: + - name: python + image: oci.stackable.tech/sdp/testing-tools:0.3.0-stackable0.0.0-dev + stdin: true + tty: true + resources: + requests: + memory: "128Mi" + cpu: "512m" + limits: + memory: "128Mi" + cpu: "1" diff --git a/tests/templates/kuttl/upgrade/50-assert.yaml b/tests/templates/kuttl/upgrade/50-assert.yaml new file mode 100644 index 00000000..4332fcf1 --- /dev/null +++ b/tests/templates/kuttl/upgrade/50-assert.yaml @@ -0,0 +1,8 @@ +--- +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +metadata: + name: seed +timeout: 300 +commands: + - script: kubectl exec -n $NAMESPACE python-0 -- python /tmp/upgrade-test.py seed diff --git a/tests/templates/kuttl/upgrade/50-seed.yaml b/tests/templates/kuttl/upgrade/50-seed.yaml new file mode 100644 index 00000000..572322a4 --- /dev/null +++ b/tests/templates/kuttl/upgrade/50-seed.yaml @@ -0,0 +1,7 @@ +--- +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +metadata: + name: seed +commands: + - script: kubectl cp -n $NAMESPACE ./upgrade-test.py python-0:/tmp diff --git a/tests/templates/kuttl/upgrade/60-assert.yaml.j2 b/tests/templates/kuttl/upgrade/60-assert.yaml.j2 new file mode 100644 index 00000000..6083cebd --- /dev/null +++ b/tests/templates/kuttl/upgrade/60-assert.yaml.j2 @@ -0,0 +1,41 @@ +{# Compute the app.kubernetes.io/version label value which operator-rs derives #} +{# from the product image: "-" for custom images and #} +{# "-stackable" otherwise; tests always run #} +{# against a 0.0.0-dev operator. #} +{% if test_scenario['values']['superset-new'].find(",") > 0 %} +{% set product_version = test_scenario['values']['superset-new'].split(',')[0] %} +{% set image_tag = test_scenario['values']['superset-new'].split(',')[1].split(':')[-1] %} +{% set app_version = product_version ~ '-' ~ image_tag %} +{% else %} +{% set app_version = test_scenario['values']['superset-new'] ~ '-stackable0.0.0-dev' %} +{% endif %} +--- +# A ready pod implies that `superset db upgrade`, `superset init` and the +# gunicorn startup all succeeded on the new version, because they run before +# the webserver can serve the /health readiness probe. Asserting the version +# label on the pod (not only on the StatefulSet) ensures that the assertion +# cannot pass before the old pod was actually replaced. +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +metadata: + name: upgrade-superset +timeout: 600 +--- +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: superset-node-default + labels: + app.kubernetes.io/version: "{{ app_version }}" +status: + readyReplicas: 1 + replicas: 1 +--- +apiVersion: v1 +kind: Pod +metadata: + name: superset-node-default-0 + labels: + app.kubernetes.io/version: "{{ app_version }}" +status: + phase: Running diff --git a/tests/templates/kuttl/upgrade/60-upgrade-superset.yaml.j2 b/tests/templates/kuttl/upgrade/60-upgrade-superset.yaml.j2 new file mode 100644 index 00000000..4017ca79 --- /dev/null +++ b/tests/templates/kuttl/upgrade/60-upgrade-superset.yaml.j2 @@ -0,0 +1,14 @@ +--- +apiVersion: superset.stackable.tech/v1alpha1 +kind: SupersetCluster +metadata: + name: superset +spec: + image: +{% if test_scenario['values']['superset-new'].find(",") > 0 %} + custom: "{{ test_scenario['values']['superset-new'].split(',')[1] }}" + productVersion: "{{ test_scenario['values']['superset-new'].split(',')[0] }}" +{% else %} + custom: null + productVersion: "{{ test_scenario['values']['superset-new'] }}" +{% endif %} diff --git a/tests/templates/kuttl/upgrade/70-assert.yaml b/tests/templates/kuttl/upgrade/70-assert.yaml new file mode 100644 index 00000000..3ef3872c --- /dev/null +++ b/tests/templates/kuttl/upgrade/70-assert.yaml @@ -0,0 +1,8 @@ +--- +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +metadata: + name: verify +timeout: 300 +commands: + - script: kubectl exec -n $NAMESPACE python-0 -- python /tmp/upgrade-test.py verify diff --git a/tests/templates/kuttl/upgrade/helm-bitnami-postgresql-values.yaml.j2 b/tests/templates/kuttl/upgrade/helm-bitnami-postgresql-values.yaml.j2 new file mode 100644 index 00000000..2e851682 --- /dev/null +++ b/tests/templates/kuttl/upgrade/helm-bitnami-postgresql-values.yaml.j2 @@ -0,0 +1,44 @@ +--- +global: + security: + allowInsecureImages: true # needed starting with Chart version 16.3.0 if modifying images + +image: + repository: bitnamilegacy/postgresql + +volumePermissions: + enabled: false + image: + repository: bitnamilegacy/os-shell + securityContext: + runAsUser: auto + +metrics: + image: + repository: bitnamilegacy/postgres-exporter + +primary: + podSecurityContext: +{% if test_scenario['values']['openshift'] == 'true' %} + enabled: false +{% else %} + enabled: true +{% endif %} + containerSecurityContext: + enabled: false + resources: + requests: + memory: "128Mi" + cpu: "512m" + limits: + memory: "128Mi" + cpu: "1" + +shmVolume: + chmod: + enabled: false + +auth: + username: superset + password: superset + database: superset diff --git a/tests/templates/kuttl/upgrade/upgrade-test.py b/tests/templates/kuttl/upgrade/upgrade-test.py new file mode 100644 index 00000000..0f4448b5 --- /dev/null +++ b/tests/templates/kuttl/upgrade/upgrade-test.py @@ -0,0 +1,235 @@ +"""Seed Superset with content before a product upgrade and verify it afterwards. + +Usage: upgrade-test.py seed|verify + +"seed" creates (idempotently, so kuttl assert retries are safe): + * a database connection pointing at the metadata PostgreSQL + * a physical dataset on the ab_user table + * a table chart on that dataset, attached to a dashboard + * a saved query + * a custom role and a user holding it + +"verify" runs after the upgrade and asserts that all of the above survived +the metadata database migrations and that a real SQL query still works. +""" + +import logging +import sys + +import requests + +BASE_URL = "http://superset-node:8088" + +DATABASE_NAME = "upgrade-test-database" +DATASET_TABLE = "ab_user" +CHART_NAME = "upgrade-test-chart" +DASHBOARD_TITLE = "upgrade-test-dashboard" +SAVED_QUERY_LABEL = "upgrade-test-saved-query" +SAVED_QUERY_SQL = "SELECT 1" +ROLE_NAME = "upgrade-test-role" +USER_NAME = "upgrade-test-user" +USER_PASSWORD = "upgrade-test-password" + +logging.basicConfig( + level="INFO", format="%(asctime)s %(levelname)s: %(message)s", stream=sys.stdout +) + + +def login(username, password): + session = requests.Session() + response = session.post( + f"{BASE_URL}/api/v1/security/login", + json={ + "username": username, + "password": password, + "provider": "db", + "refresh": True, + }, + ) + assert response.status_code == 200, f"Login of [{username}] failed: {response.text}" + session.headers["Authorization"] = f"Bearer {response.json()['access_token']}" + + response = session.get(f"{BASE_URL}/api/v1/security/csrf_token/") + assert response.status_code == 200, f"Fetching CSRF token failed: {response.text}" + session.headers["X-CSRFToken"] = response.json()["result"] + session.headers["Referer"] = BASE_URL + + return session + + +def find_by(session, endpoint, attribute, value): + """Return the first item of a list endpoint whose attribute matches, else None.""" + response = session.get(f"{BASE_URL}/api/v1/{endpoint}/?q=(page_size:100)") + assert response.status_code == 200, f"Listing [{endpoint}] failed: {response.text}" + return next( + (item for item in response.json()["result"] if item.get(attribute) == value), + None, + ) + + +def create(session, endpoint, payload): + response = session.post(f"{BASE_URL}/api/v1/{endpoint}/", json=payload) + assert response.status_code == 201, f"Creating [{endpoint}] failed: {response.text}" + return response.json()["id"] + + +def ensure(session, endpoint, attribute, value, payload): + """Create an object unless an object with the same attribute value exists.""" + existing = find_by(session, endpoint, attribute, value) + if existing: + logging.info("[%s] with %s=%s already exists", endpoint, attribute, value) + return existing["id"] + object_id = create(session, endpoint, payload) + logging.info("Created [%s] with %s=%s", endpoint, attribute, value) + return object_id + + +def seed(): + session = login("admin", "admin") + + database_id = ensure( + session, + "database", + "database_name", + DATABASE_NAME, + { + "database_name": DATABASE_NAME, + "sqlalchemy_uri": "postgresql://superset:superset@superset-postgresql:5432/superset", + "expose_in_sqllab": True, + }, + ) + + dataset_id = ensure( + session, + "dataset", + "table_name", + DATASET_TABLE, + {"database": database_id, "schema": "public", "table_name": DATASET_TABLE}, + ) + + dashboard_id = ensure( + session, + "dashboard", + "dashboard_title", + DASHBOARD_TITLE, + {"dashboard_title": DASHBOARD_TITLE, "published": True}, + ) + + ensure( + session, + "chart", + "slice_name", + CHART_NAME, + { + "slice_name": CHART_NAME, + "datasource_id": dataset_id, + "datasource_type": "table", + "viz_type": "table", + "params": "{}", + "dashboards": [dashboard_id], + }, + ) + + ensure( + session, + "saved_query", + "label", + SAVED_QUERY_LABEL, + {"label": SAVED_QUERY_LABEL, "sql": SAVED_QUERY_SQL, "db_id": database_id}, + ) + + role_id = ensure( + session, "security/roles", "name", ROLE_NAME, {"name": ROLE_NAME} + ) + gamma_role = find_by(session, "security/roles", "name", "Gamma") + assert gamma_role, "Built-in Gamma role not found." + + ensure( + session, + "security/users", + "username", + USER_NAME, + { + "username": USER_NAME, + "password": USER_PASSWORD, + "first_name": "Upgrade", + "last_name": "Test", + "email": "upgrade-test@superset.com", + "active": True, + "roles": [gamma_role["id"], role_id], + }, + ) + + +def verify(): + session = login("admin", "admin") + + database = find_by(session, "database", "database_name", DATABASE_NAME) + assert database, f"Database [{DATABASE_NAME}] not found after upgrade." + + dataset = find_by(session, "dataset", "table_name", DATASET_TABLE) + assert dataset, f"Dataset [{DATASET_TABLE}] not found after upgrade." + + # Run an actual SQL query against the dataset to prove that the upgraded + # installation can still query data, not just serve its metadata. + response = session.post( + f"{BASE_URL}/api/v1/chart/data", + json={ + "datasource": {"id": dataset["id"], "type": "table"}, + "queries": [{"columns": ["username"], "row_limit": 10}], + "result_format": "json", + "result_type": "full", + }, + ) + assert response.status_code == 200, f"Chart data query failed: {response.text}" + data = response.json()["result"][0]["data"] + assert data, "Chart data query returned no rows." + logging.info("Chart data query returned %d rows", len(data)) + + chart = find_by(session, "chart", "slice_name", CHART_NAME) + assert chart, f"Chart [{CHART_NAME}] not found after upgrade." + response = session.get(f"{BASE_URL}/api/v1/chart/{chart['id']}") + assert response.status_code == 200, f"Fetching chart failed: {response.text}" + dashboard_titles = [ + dashboard["dashboard_title"] + for dashboard in response.json()["result"].get("dashboards", []) + ] + assert DASHBOARD_TITLE in dashboard_titles, ( + f"Chart [{CHART_NAME}] is no longer attached " + f"to dashboard [{DASHBOARD_TITLE}]: {dashboard_titles}" + ) + + dashboard = find_by(session, "dashboard", "dashboard_title", DASHBOARD_TITLE) + assert dashboard, f"Dashboard [{DASHBOARD_TITLE}] not found after upgrade." + + saved_query = find_by(session, "saved_query", "label", SAVED_QUERY_LABEL) + assert saved_query, f"Saved query [{SAVED_QUERY_LABEL}] not found after upgrade." + response = session.get(f"{BASE_URL}/api/v1/saved_query/{saved_query['id']}") + assert response.status_code == 200, f"Fetching saved query failed: {response.text}" + assert response.json()["result"]["sql"] == SAVED_QUERY_SQL, ( + "Saved query SQL changed after upgrade." + ) + + user = find_by(session, "security/users", "username", USER_NAME) + assert user, f"User [{USER_NAME}] not found after upgrade." + role_names = [role["name"] for role in user.get("roles", [])] + assert ROLE_NAME in role_names, ( + f"User [{USER_NAME}] lost role [{ROLE_NAME}] after upgrade: {role_names}" + ) + + # The seeded user must still be able to log in with the FAB version + # shipped in the new Superset version. + user_session = login(USER_NAME, USER_PASSWORD) + response = user_session.get(f"{BASE_URL}/api/v1/me/") + assert response.status_code == 200, f"Fetching own user failed: {response.text}" + + logging.info("All seeded objects survived the upgrade.") + + +if __name__ == "__main__": + if sys.argv[1:] == ["seed"]: + seed() + elif sys.argv[1:] == ["verify"]: + verify() + else: + sys.exit(f"Usage: {sys.argv[0]} seed|verify (got {sys.argv[1:]})") diff --git a/tests/test-definition.yaml b/tests/test-definition.yaml index 43aa681e..a7658aad 100644 --- a/tests/test-definition.yaml +++ b/tests/test-definition.yaml @@ -6,16 +6,24 @@ dimensions: - name: superset values: - - 4.1.4 - - 6.0.0 + # - 4.1.4 + # - 6.0.0 # Or use a custom image: - # - x.x.x,oci.stackable.tech/razvan/superset:x.x.x-stackable0.0.0-dev - - 6.1.0,oci.stackable.tech/sandbox/superset:6.1.0 + - 6.0.0,oci.stackable.tech/sdp/superset:6.0.0-stackable0.0.0-dev + - 6.1.0,oci.stackable.tech/sdp/superset:6.1.0-stackable0.0.0-dev + # - 6.1.0,oci.stackable.tech/sandbox/superset:6.1.0 - name: superset-latest values: # - 6.0.0 - # - x.x.x,oci.stackable.tech/razvan/superset:x.x.x-stackable0.0.0-dev - - 6.1.0,oci.stackable.tech/sandbox/superset:6.1.0 + - 6.1.0,oci.stackable.tech/sdp/superset:6.1.0-stackable0.0.0-dev + #- 6.0.0,oci.stackable.tech/sandbox/superset:6.0.0 + - name: superset-old + values: + - 4.1.4,oci.stackable.tech/sdp/superset:4.1.4-stackable0.0.0-dev + - 6.0.0,oci.stackable.tech/sdp/superset:6.0.0-stackable0.0.0-dev + - name: superset-new + values: + - 6.1.0,oci.stackable.tech/sdp/superset:6.1.0-stackable0.0.0-dev - name: ldap-authentication values: - no-tls @@ -70,6 +78,16 @@ tests: dimensions: - superset - openshift + - name: upgrade + dimensions: + - superset-old + - superset-new + - openshift + - name: upgrade-oidc + dimensions: + - superset-old + - superset-new + - openshift suites: - name: nightly patch: From 0afb50707faf3406063a17bb147031d5b7780bf6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20M=C3=BCller?= Date: Thu, 4 Jun 2026 10:05:02 +0200 Subject: [PATCH 3/5] chore: formatting --- tests/templates/kuttl/upgrade-oidc/60_login.py | 1 - tests/templates/kuttl/upgrade/upgrade-test.py | 4 +--- tests/test-definition.yaml | 2 +- 3 files changed, 2 insertions(+), 5 deletions(-) diff --git a/tests/templates/kuttl/upgrade-oidc/60_login.py b/tests/templates/kuttl/upgrade-oidc/60_login.py index df173669..da5e9b82 100644 --- a/tests/templates/kuttl/upgrade-oidc/60_login.py +++ b/tests/templates/kuttl/upgrade-oidc/60_login.py @@ -55,4 +55,3 @@ assert user_data["email"] == "jane.doe@stackable.tech", ( "The email of the user in Superset should match the one provided by Keycloak" ) - diff --git a/tests/templates/kuttl/upgrade/upgrade-test.py b/tests/templates/kuttl/upgrade/upgrade-test.py index 0f4448b5..b3ec6b9d 100644 --- a/tests/templates/kuttl/upgrade/upgrade-test.py +++ b/tests/templates/kuttl/upgrade/upgrade-test.py @@ -138,9 +138,7 @@ def seed(): {"label": SAVED_QUERY_LABEL, "sql": SAVED_QUERY_SQL, "db_id": database_id}, ) - role_id = ensure( - session, "security/roles", "name", ROLE_NAME, {"name": ROLE_NAME} - ) + role_id = ensure(session, "security/roles", "name", ROLE_NAME, {"name": ROLE_NAME}) gamma_role = find_by(session, "security/roles", "name", "Gamma") assert gamma_role, "Built-in Gamma role not found." diff --git a/tests/test-definition.yaml b/tests/test-definition.yaml index a7658aad..400b13e0 100644 --- a/tests/test-definition.yaml +++ b/tests/test-definition.yaml @@ -16,7 +16,7 @@ dimensions: values: # - 6.0.0 - 6.1.0,oci.stackable.tech/sdp/superset:6.1.0-stackable0.0.0-dev - #- 6.0.0,oci.stackable.tech/sandbox/superset:6.0.0 + # - 6.0.0,oci.stackable.tech/sandbox/superset:6.0.0 - name: superset-old values: - 4.1.4,oci.stackable.tech/sdp/superset:4.1.4-stackable0.0.0-dev From f0bcaa0674744e0fb722188f513c98aa51959dfd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20M=C3=BCller?= Date: Thu, 4 Jun 2026 14:25:41 +0200 Subject: [PATCH 4/5] refactor: combine upgrade tests into single test --- .../kuttl/upgrade-oidc/00-patch-ns.yaml.j2 | 9 --- .../kuttl/upgrade-oidc/10-assert.yaml | 14 ---- .../upgrade-oidc/10-install-postgresql.yaml | 12 ---- ...tor-aggregator-discovery-configmap.yaml.j2 | 9 --- .../kuttl/upgrade-oidc/40-assert.yaml | 16 ----- .../kuttl/upgrade-oidc/50-assert.yaml | 14 ---- .../kuttl/upgrade-oidc/60-assert.yaml | 8 --- .../kuttl/upgrade-oidc/60-login.yaml | 9 --- .../kuttl/upgrade/10-install-postgresql.yaml | 2 +- .../10_helm-bitnami-postgresql-values.yaml.j2 | 0 tests/templates/kuttl/upgrade/30-assert.yaml | 8 --- .../30-assert.yaml.j2} | 2 + .../kuttl/upgrade/30-install-superset.yaml.j2 | 64 ------------------- .../30-keycloak.yaml.j2} | 2 + .../30_install-keycloak.yaml.j2 | 10 +++ tests/templates/kuttl/upgrade/40-assert.yaml | 8 ++- .../40-install-superset.yaml | 0 .../upgrade/40-install-test-container.yaml | 35 ---------- .../40_install-superset.yaml.j2 | 15 +++++ tests/templates/kuttl/upgrade/50-assert.yaml | 12 +++- .../50-install-test-container.yaml.j2 | 0 tests/templates/kuttl/upgrade/50-seed.yaml | 7 -- .../templates/kuttl/upgrade/60-assert.yaml.j2 | 48 ++++---------- .../kuttl/upgrade/60-copy-test-script.yaml.j2 | 19 ++++++ .../kuttl/upgrade/60-upgrade-superset.yaml.j2 | 14 ---- .../{upgrade-oidc => upgrade}/60_login.py | 0 tests/templates/kuttl/upgrade/70-assert.yaml | 8 --- .../70-assert.yaml.j2 | 7 +- .../70-upgrade-superset.yaml.j2 | 0 .../80-assert.yaml.j2} | 13 ++++ .../helm-bitnami-postgresql-values.yaml.j2 | 44 ------------- tests/test-definition.yaml | 13 ++-- 32 files changed, 102 insertions(+), 320 deletions(-) delete mode 100644 tests/templates/kuttl/upgrade-oidc/00-patch-ns.yaml.j2 delete mode 100644 tests/templates/kuttl/upgrade-oidc/10-assert.yaml delete mode 100644 tests/templates/kuttl/upgrade-oidc/10-install-postgresql.yaml delete mode 100644 tests/templates/kuttl/upgrade-oidc/20-install-vector-aggregator-discovery-configmap.yaml.j2 delete mode 100644 tests/templates/kuttl/upgrade-oidc/40-assert.yaml delete mode 100644 tests/templates/kuttl/upgrade-oidc/50-assert.yaml delete mode 100644 tests/templates/kuttl/upgrade-oidc/60-assert.yaml delete mode 100644 tests/templates/kuttl/upgrade-oidc/60-login.yaml rename tests/templates/kuttl/{upgrade-oidc => upgrade}/10_helm-bitnami-postgresql-values.yaml.j2 (100%) delete mode 100644 tests/templates/kuttl/upgrade/30-assert.yaml rename tests/templates/kuttl/{upgrade-oidc/30-assert.yaml => upgrade/30-assert.yaml.j2} (73%) delete mode 100644 tests/templates/kuttl/upgrade/30-install-superset.yaml.j2 rename tests/templates/kuttl/{upgrade-oidc/30-keycloak.yaml => upgrade/30-keycloak.yaml.j2} (84%) rename tests/templates/kuttl/{upgrade-oidc => upgrade}/30_install-keycloak.yaml.j2 (91%) rename tests/templates/kuttl/{upgrade-oidc => upgrade}/40-install-superset.yaml (100%) delete mode 100644 tests/templates/kuttl/upgrade/40-install-test-container.yaml rename tests/templates/kuttl/{upgrade-oidc => upgrade}/40_install-superset.yaml.j2 (72%) rename tests/templates/kuttl/{upgrade-oidc => upgrade}/50-install-test-container.yaml.j2 (100%) delete mode 100644 tests/templates/kuttl/upgrade/50-seed.yaml create mode 100644 tests/templates/kuttl/upgrade/60-copy-test-script.yaml.j2 delete mode 100644 tests/templates/kuttl/upgrade/60-upgrade-superset.yaml.j2 rename tests/templates/kuttl/{upgrade-oidc => upgrade}/60_login.py (100%) delete mode 100644 tests/templates/kuttl/upgrade/70-assert.yaml rename tests/templates/kuttl/{upgrade-oidc => upgrade}/70-assert.yaml.j2 (76%) rename tests/templates/kuttl/{upgrade-oidc => upgrade}/70-upgrade-superset.yaml.j2 (100%) rename tests/templates/kuttl/{upgrade-oidc/80-assert.yaml => upgrade/80-assert.yaml.j2} (54%) delete mode 100644 tests/templates/kuttl/upgrade/helm-bitnami-postgresql-values.yaml.j2 diff --git a/tests/templates/kuttl/upgrade-oidc/00-patch-ns.yaml.j2 b/tests/templates/kuttl/upgrade-oidc/00-patch-ns.yaml.j2 deleted file mode 100644 index 67185acf..00000000 --- a/tests/templates/kuttl/upgrade-oidc/00-patch-ns.yaml.j2 +++ /dev/null @@ -1,9 +0,0 @@ -{% if test_scenario['values']['openshift'] == 'true' %} -# see https://github.com/stackabletech/issues/issues/566 ---- -apiVersion: kuttl.dev/v1beta1 -kind: TestStep -commands: - - script: kubectl patch namespace $NAMESPACE -p '{"metadata":{"labels":{"pod-security.kubernetes.io/enforce":"privileged"}}}' - timeout: 120 -{% endif %} diff --git a/tests/templates/kuttl/upgrade-oidc/10-assert.yaml b/tests/templates/kuttl/upgrade-oidc/10-assert.yaml deleted file mode 100644 index e9c60b15..00000000 --- a/tests/templates/kuttl/upgrade-oidc/10-assert.yaml +++ /dev/null @@ -1,14 +0,0 @@ ---- -apiVersion: kuttl.dev/v1beta1 -kind: TestAssert -metadata: - name: test-superset-postgresql -timeout: 480 ---- -apiVersion: apps/v1 -kind: StatefulSet -metadata: - name: superset-postgresql -status: - readyReplicas: 1 - replicas: 1 diff --git a/tests/templates/kuttl/upgrade-oidc/10-install-postgresql.yaml b/tests/templates/kuttl/upgrade-oidc/10-install-postgresql.yaml deleted file mode 100644 index a9fc0d36..00000000 --- a/tests/templates/kuttl/upgrade-oidc/10-install-postgresql.yaml +++ /dev/null @@ -1,12 +0,0 @@ ---- -apiVersion: kuttl.dev/v1beta1 -kind: TestStep -commands: - - script: >- - helm install superset-postgresql - --namespace $NAMESPACE - --version 12.5.6 - -f 10_helm-bitnami-postgresql-values.yaml - --repo https://charts.bitnami.com/bitnami postgresql - --wait - timeout: 600 diff --git a/tests/templates/kuttl/upgrade-oidc/20-install-vector-aggregator-discovery-configmap.yaml.j2 b/tests/templates/kuttl/upgrade-oidc/20-install-vector-aggregator-discovery-configmap.yaml.j2 deleted file mode 100644 index 2d6a0df5..00000000 --- a/tests/templates/kuttl/upgrade-oidc/20-install-vector-aggregator-discovery-configmap.yaml.j2 +++ /dev/null @@ -1,9 +0,0 @@ -{% if lookup('env', 'VECTOR_AGGREGATOR') %} ---- -apiVersion: v1 -kind: ConfigMap -metadata: - name: vector-aggregator-discovery -data: - ADDRESS: {{ lookup('env', 'VECTOR_AGGREGATOR') }} -{% endif %} diff --git a/tests/templates/kuttl/upgrade-oidc/40-assert.yaml b/tests/templates/kuttl/upgrade-oidc/40-assert.yaml deleted file mode 100644 index daae9510..00000000 --- a/tests/templates/kuttl/upgrade-oidc/40-assert.yaml +++ /dev/null @@ -1,16 +0,0 @@ ---- -apiVersion: kuttl.dev/v1beta1 -kind: TestAssert -metadata: - name: install-superset -timeout: 600 -commands: - - script: kubectl -n $NAMESPACE wait --for=condition=available=true supersetclusters.superset.stackable.tech/superset --timeout 601s ---- -apiVersion: apps/v1 -kind: StatefulSet -metadata: - name: superset-node-default -status: - readyReplicas: 1 - replicas: 1 diff --git a/tests/templates/kuttl/upgrade-oidc/50-assert.yaml b/tests/templates/kuttl/upgrade-oidc/50-assert.yaml deleted file mode 100644 index 58987778..00000000 --- a/tests/templates/kuttl/upgrade-oidc/50-assert.yaml +++ /dev/null @@ -1,14 +0,0 @@ ---- -apiVersion: kuttl.dev/v1beta1 -kind: TestAssert -metadata: - name: install-test-container -timeout: 300 ---- -apiVersion: apps/v1 -kind: StatefulSet -metadata: - name: python -status: - readyReplicas: 1 - replicas: 1 diff --git a/tests/templates/kuttl/upgrade-oidc/60-assert.yaml b/tests/templates/kuttl/upgrade-oidc/60-assert.yaml deleted file mode 100644 index df17232b..00000000 --- a/tests/templates/kuttl/upgrade-oidc/60-assert.yaml +++ /dev/null @@ -1,8 +0,0 @@ ---- -apiVersion: kuttl.dev/v1beta1 -kind: TestAssert -metadata: - name: login -timeout: 300 -commands: - - script: kubectl exec -n $NAMESPACE python-0 -- python /stackable/60_login.py diff --git a/tests/templates/kuttl/upgrade-oidc/60-login.yaml b/tests/templates/kuttl/upgrade-oidc/60-login.yaml deleted file mode 100644 index 0e6aaac7..00000000 --- a/tests/templates/kuttl/upgrade-oidc/60-login.yaml +++ /dev/null @@ -1,9 +0,0 @@ ---- -apiVersion: kuttl.dev/v1beta1 -kind: TestStep -metadata: - name: login -commands: - - script: > - envsubst '$NAMESPACE' < 60_login.py | - kubectl exec -n $NAMESPACE -i python-0 -- tee /stackable/60_login.py > /dev/null diff --git a/tests/templates/kuttl/upgrade/10-install-postgresql.yaml b/tests/templates/kuttl/upgrade/10-install-postgresql.yaml index 50c5ad67..a9fc0d36 100644 --- a/tests/templates/kuttl/upgrade/10-install-postgresql.yaml +++ b/tests/templates/kuttl/upgrade/10-install-postgresql.yaml @@ -6,7 +6,7 @@ commands: helm install superset-postgresql --namespace $NAMESPACE --version 12.5.6 - -f helm-bitnami-postgresql-values.yaml + -f 10_helm-bitnami-postgresql-values.yaml --repo https://charts.bitnami.com/bitnami postgresql --wait timeout: 600 diff --git a/tests/templates/kuttl/upgrade-oidc/10_helm-bitnami-postgresql-values.yaml.j2 b/tests/templates/kuttl/upgrade/10_helm-bitnami-postgresql-values.yaml.j2 similarity index 100% rename from tests/templates/kuttl/upgrade-oidc/10_helm-bitnami-postgresql-values.yaml.j2 rename to tests/templates/kuttl/upgrade/10_helm-bitnami-postgresql-values.yaml.j2 diff --git a/tests/templates/kuttl/upgrade/30-assert.yaml b/tests/templates/kuttl/upgrade/30-assert.yaml deleted file mode 100644 index 468dcc2f..00000000 --- a/tests/templates/kuttl/upgrade/30-assert.yaml +++ /dev/null @@ -1,8 +0,0 @@ ---- -apiVersion: kuttl.dev/v1beta1 -kind: TestAssert -metadata: - name: install-superset -timeout: 600 -commands: - - script: kubectl -n $NAMESPACE wait --for=condition=available=true supersetclusters.superset.stackable.tech/superset --timeout 601s diff --git a/tests/templates/kuttl/upgrade-oidc/30-assert.yaml b/tests/templates/kuttl/upgrade/30-assert.yaml.j2 similarity index 73% rename from tests/templates/kuttl/upgrade-oidc/30-assert.yaml rename to tests/templates/kuttl/upgrade/30-assert.yaml.j2 index 02818f1f..f253a856 100644 --- a/tests/templates/kuttl/upgrade-oidc/30-assert.yaml +++ b/tests/templates/kuttl/upgrade/30-assert.yaml.j2 @@ -1,3 +1,4 @@ +{% if test_scenario['values']['authentication'] == 'oidc' %} --- apiVersion: kuttl.dev/v1beta1 kind: TestAssert @@ -12,3 +13,4 @@ metadata: status: readyReplicas: 1 replicas: 1 +{% endif %} diff --git a/tests/templates/kuttl/upgrade/30-install-superset.yaml.j2 b/tests/templates/kuttl/upgrade/30-install-superset.yaml.j2 deleted file mode 100644 index c8313d27..00000000 --- a/tests/templates/kuttl/upgrade/30-install-superset.yaml.j2 +++ /dev/null @@ -1,64 +0,0 @@ ---- -apiVersion: kuttl.dev/v1beta1 -kind: TestStep -metadata: - name: install-superset -timeout: 300 ---- -apiVersion: v1 -kind: Secret -metadata: - name: superset-admin-credentials -type: Opaque -stringData: - adminUser.username: admin - adminUser.firstname: Superset - adminUser.lastname: Admin - adminUser.email: admin@superset.com - adminUser.password: admin ---- -apiVersion: v1 -kind: Secret -metadata: - name: superset-postgresql-credentials -stringData: - username: superset - password: superset ---- -apiVersion: superset.stackable.tech/v1alpha1 -kind: SupersetCluster -metadata: - name: superset -spec: - image: -{% if test_scenario['values']['superset-old'].find(",") > 0 %} - custom: "{{ test_scenario['values']['superset-old'].split(',')[1] }}" - productVersion: "{{ test_scenario['values']['superset-old'].split(',')[0] }}" -{% else %} - productVersion: "{{ test_scenario['values']['superset-old'] }}" -{% endif %} - pullPolicy: IfNotPresent - clusterConfig: - credentialsSecretName: superset-admin-credentials - metadataDatabase: - postgresql: - host: superset-postgresql - database: superset - credentialsSecretName: superset-postgresql-credentials -{% if lookup('env', 'VECTOR_AGGREGATOR') %} - vectorAggregatorConfigMapName: vector-aggregator-discovery -{% endif %} - nodes: - configOverrides: - superset_config.py: - FILE_FOOTER: | - # The FAB security API is required by upgrade-test.py to seed a role - # and a user. Superset versions before 6.0.0 do not enable it by - # default. - FAB_ADD_SECURITY_API = True - config: - logging: - enableVectorAgent: {{ lookup('env', 'VECTOR_AGGREGATOR') | length > 0 }} - roleGroups: - default: - replicas: 1 diff --git a/tests/templates/kuttl/upgrade-oidc/30-keycloak.yaml b/tests/templates/kuttl/upgrade/30-keycloak.yaml.j2 similarity index 84% rename from tests/templates/kuttl/upgrade-oidc/30-keycloak.yaml rename to tests/templates/kuttl/upgrade/30-keycloak.yaml.j2 index 8fe061be..029c6b63 100644 --- a/tests/templates/kuttl/upgrade-oidc/30-keycloak.yaml +++ b/tests/templates/kuttl/upgrade/30-keycloak.yaml.j2 @@ -1,3 +1,4 @@ +{% if test_scenario['values']['authentication'] == 'oidc' %} --- apiVersion: kuttl.dev/v1beta1 kind: TestStep @@ -13,3 +14,4 @@ commands: CLIENT_ID=superset1 \ CLIENT_SECRET=R1bxHUD569vHeQdw \ envsubst < 30_install-keycloak.yaml | kubectl apply -n $NAMESPACE -f - +{% endif %} diff --git a/tests/templates/kuttl/upgrade-oidc/30_install-keycloak.yaml.j2 b/tests/templates/kuttl/upgrade/30_install-keycloak.yaml.j2 similarity index 91% rename from tests/templates/kuttl/upgrade-oidc/30_install-keycloak.yaml.j2 rename to tests/templates/kuttl/upgrade/30_install-keycloak.yaml.j2 index f9098fc2..37680200 100644 --- a/tests/templates/kuttl/upgrade-oidc/30_install-keycloak.yaml.j2 +++ b/tests/templates/kuttl/upgrade/30_install-keycloak.yaml.j2 @@ -83,6 +83,16 @@ spec: value: admin - name: KEYCLOAK_ADMIN_PASSWORD value: admin + # Both requests and limits must be set and satisfy the ratios in + # 00-limit-range.yaml (memory ratio 1 requires request == limit), + # otherwise the LimitRanger admission controller rejects the pod. + resources: + requests: + memory: "1Gi" + cpu: "500m" + limits: + memory: "1Gi" + cpu: "2" ports: - name: https containerPort: 8443 diff --git a/tests/templates/kuttl/upgrade/40-assert.yaml b/tests/templates/kuttl/upgrade/40-assert.yaml index 58987778..daae9510 100644 --- a/tests/templates/kuttl/upgrade/40-assert.yaml +++ b/tests/templates/kuttl/upgrade/40-assert.yaml @@ -2,13 +2,15 @@ apiVersion: kuttl.dev/v1beta1 kind: TestAssert metadata: - name: install-test-container -timeout: 300 + name: install-superset +timeout: 600 +commands: + - script: kubectl -n $NAMESPACE wait --for=condition=available=true supersetclusters.superset.stackable.tech/superset --timeout 601s --- apiVersion: apps/v1 kind: StatefulSet metadata: - name: python + name: superset-node-default status: readyReplicas: 1 replicas: 1 diff --git a/tests/templates/kuttl/upgrade-oidc/40-install-superset.yaml b/tests/templates/kuttl/upgrade/40-install-superset.yaml similarity index 100% rename from tests/templates/kuttl/upgrade-oidc/40-install-superset.yaml rename to tests/templates/kuttl/upgrade/40-install-superset.yaml diff --git a/tests/templates/kuttl/upgrade/40-install-test-container.yaml b/tests/templates/kuttl/upgrade/40-install-test-container.yaml deleted file mode 100644 index 7d8002f3..00000000 --- a/tests/templates/kuttl/upgrade/40-install-test-container.yaml +++ /dev/null @@ -1,35 +0,0 @@ ---- -apiVersion: kuttl.dev/v1beta1 -kind: TestStep -metadata: - name: install-test-container -timeout: 300 ---- -apiVersion: apps/v1 -kind: StatefulSet -metadata: - name: python - labels: - app: python -spec: - replicas: 1 - selector: - matchLabels: - app: python - template: - metadata: - labels: - app: python - spec: - containers: - - name: python - image: oci.stackable.tech/sdp/testing-tools:0.3.0-stackable0.0.0-dev - stdin: true - tty: true - resources: - requests: - memory: "128Mi" - cpu: "512m" - limits: - memory: "128Mi" - cpu: "1" diff --git a/tests/templates/kuttl/upgrade-oidc/40_install-superset.yaml.j2 b/tests/templates/kuttl/upgrade/40_install-superset.yaml.j2 similarity index 72% rename from tests/templates/kuttl/upgrade-oidc/40_install-superset.yaml.j2 rename to tests/templates/kuttl/upgrade/40_install-superset.yaml.j2 index e2851a40..2785c497 100644 --- a/tests/templates/kuttl/upgrade-oidc/40_install-superset.yaml.j2 +++ b/tests/templates/kuttl/upgrade/40_install-superset.yaml.j2 @@ -19,6 +19,7 @@ metadata: stringData: username: superset password: superset +{% if test_scenario['values']['authentication'] == 'oidc' %} --- apiVersion: v1 kind: Secret @@ -27,6 +28,7 @@ metadata: stringData: clientId: superset1 clientSecret: R1bxHUD569vHeQdw +{% endif %} --- apiVersion: superset.stackable.tech/v1alpha1 kind: SupersetCluster @@ -42,10 +44,12 @@ spec: {% endif %} pullPolicy: IfNotPresent clusterConfig: +{% if test_scenario['values']['authentication'] == 'oidc' %} authentication: - authenticationClass: keycloak1-$NAMESPACE oidc: clientCredentialsSecret: superset-keycloak1-client +{% endif %} credentialsSecretName: superset-admin-credentials metadataDatabase: postgresql: @@ -56,6 +60,17 @@ spec: vectorAggregatorConfigMapName: vector-aggregator-discovery {% endif %} nodes: +{% if test_scenario['values']['authentication'] != 'oidc' %} +{# upgrade-test.py requires database authentication which is replaced by #} +{# OAuth in the oidc scenario, so the override is not needed there. #} + configOverrides: + superset_config.py: + FILE_FOOTER: | + # The FAB security API is required by upgrade-test.py to seed a role + # and a user. Superset versions before 6.0.0 do not enable it by + # default. + FAB_ADD_SECURITY_API = True +{% endif %} config: logging: enableVectorAgent: {{ lookup('env', 'VECTOR_AGGREGATOR') | length > 0 }} diff --git a/tests/templates/kuttl/upgrade/50-assert.yaml b/tests/templates/kuttl/upgrade/50-assert.yaml index 4332fcf1..58987778 100644 --- a/tests/templates/kuttl/upgrade/50-assert.yaml +++ b/tests/templates/kuttl/upgrade/50-assert.yaml @@ -2,7 +2,13 @@ apiVersion: kuttl.dev/v1beta1 kind: TestAssert metadata: - name: seed + name: install-test-container timeout: 300 -commands: - - script: kubectl exec -n $NAMESPACE python-0 -- python /tmp/upgrade-test.py seed +--- +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: python +status: + readyReplicas: 1 + replicas: 1 diff --git a/tests/templates/kuttl/upgrade-oidc/50-install-test-container.yaml.j2 b/tests/templates/kuttl/upgrade/50-install-test-container.yaml.j2 similarity index 100% rename from tests/templates/kuttl/upgrade-oidc/50-install-test-container.yaml.j2 rename to tests/templates/kuttl/upgrade/50-install-test-container.yaml.j2 diff --git a/tests/templates/kuttl/upgrade/50-seed.yaml b/tests/templates/kuttl/upgrade/50-seed.yaml deleted file mode 100644 index 572322a4..00000000 --- a/tests/templates/kuttl/upgrade/50-seed.yaml +++ /dev/null @@ -1,7 +0,0 @@ ---- -apiVersion: kuttl.dev/v1beta1 -kind: TestStep -metadata: - name: seed -commands: - - script: kubectl cp -n $NAMESPACE ./upgrade-test.py python-0:/tmp diff --git a/tests/templates/kuttl/upgrade/60-assert.yaml.j2 b/tests/templates/kuttl/upgrade/60-assert.yaml.j2 index 6083cebd..02f06fdc 100644 --- a/tests/templates/kuttl/upgrade/60-assert.yaml.j2 +++ b/tests/templates/kuttl/upgrade/60-assert.yaml.j2 @@ -1,41 +1,19 @@ -{# Compute the app.kubernetes.io/version label value which operator-rs derives #} -{# from the product image: "-" for custom images and #} -{# "-stackable" otherwise; tests always run #} -{# against a 0.0.0-dev operator. #} -{% if test_scenario['values']['superset-new'].find(",") > 0 %} -{% set product_version = test_scenario['values']['superset-new'].split(',')[0] %} -{% set image_tag = test_scenario['values']['superset-new'].split(',')[1].split(':')[-1] %} -{% set app_version = product_version ~ '-' ~ image_tag %} -{% else %} -{% set app_version = test_scenario['values']['superset-new'] ~ '-stackable0.0.0-dev' %} -{% endif %} +{% if test_scenario['values']['authentication'] == 'oidc' %} --- -# A ready pod implies that `superset db upgrade`, `superset init` and the -# gunicorn startup all succeeded on the new version, because they run before -# the webserver can serve the /health readiness probe. Asserting the version -# label on the pod (not only on the StatefulSet) ensures that the assertion -# cannot pass before the old pod was actually replaced. apiVersion: kuttl.dev/v1beta1 kind: TestAssert metadata: - name: upgrade-superset -timeout: 600 ---- -apiVersion: apps/v1 -kind: StatefulSet -metadata: - name: superset-node-default - labels: - app.kubernetes.io/version: "{{ app_version }}" -status: - readyReplicas: 1 - replicas: 1 + name: login +timeout: 300 +commands: + - script: kubectl exec -n $NAMESPACE python-0 -- python /stackable/60_login.py +{% else %} --- -apiVersion: v1 -kind: Pod +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert metadata: - name: superset-node-default-0 - labels: - app.kubernetes.io/version: "{{ app_version }}" -status: - phase: Running + name: seed +timeout: 300 +commands: + - script: kubectl exec -n $NAMESPACE python-0 -- python /tmp/upgrade-test.py seed +{% endif %} diff --git a/tests/templates/kuttl/upgrade/60-copy-test-script.yaml.j2 b/tests/templates/kuttl/upgrade/60-copy-test-script.yaml.j2 new file mode 100644 index 00000000..f7b72e21 --- /dev/null +++ b/tests/templates/kuttl/upgrade/60-copy-test-script.yaml.j2 @@ -0,0 +1,19 @@ +{% if test_scenario['values']['authentication'] == 'oidc' %} +--- +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +metadata: + name: login +commands: + - script: > + envsubst '$NAMESPACE' < 60_login.py | + kubectl exec -n $NAMESPACE -i python-0 -- tee /stackable/60_login.py > /dev/null +{% else %} +--- +apiVersion: kuttl.dev/v1beta1 +kind: TestStep +metadata: + name: seed +commands: + - script: kubectl cp -n $NAMESPACE ./upgrade-test.py python-0:/tmp +{% endif %} diff --git a/tests/templates/kuttl/upgrade/60-upgrade-superset.yaml.j2 b/tests/templates/kuttl/upgrade/60-upgrade-superset.yaml.j2 deleted file mode 100644 index 4017ca79..00000000 --- a/tests/templates/kuttl/upgrade/60-upgrade-superset.yaml.j2 +++ /dev/null @@ -1,14 +0,0 @@ ---- -apiVersion: superset.stackable.tech/v1alpha1 -kind: SupersetCluster -metadata: - name: superset -spec: - image: -{% if test_scenario['values']['superset-new'].find(",") > 0 %} - custom: "{{ test_scenario['values']['superset-new'].split(',')[1] }}" - productVersion: "{{ test_scenario['values']['superset-new'].split(',')[0] }}" -{% else %} - custom: null - productVersion: "{{ test_scenario['values']['superset-new'] }}" -{% endif %} diff --git a/tests/templates/kuttl/upgrade-oidc/60_login.py b/tests/templates/kuttl/upgrade/60_login.py similarity index 100% rename from tests/templates/kuttl/upgrade-oidc/60_login.py rename to tests/templates/kuttl/upgrade/60_login.py diff --git a/tests/templates/kuttl/upgrade/70-assert.yaml b/tests/templates/kuttl/upgrade/70-assert.yaml deleted file mode 100644 index 3ef3872c..00000000 --- a/tests/templates/kuttl/upgrade/70-assert.yaml +++ /dev/null @@ -1,8 +0,0 @@ ---- -apiVersion: kuttl.dev/v1beta1 -kind: TestAssert -metadata: - name: verify -timeout: 300 -commands: - - script: kubectl exec -n $NAMESPACE python-0 -- python /tmp/upgrade-test.py verify diff --git a/tests/templates/kuttl/upgrade-oidc/70-assert.yaml.j2 b/tests/templates/kuttl/upgrade/70-assert.yaml.j2 similarity index 76% rename from tests/templates/kuttl/upgrade-oidc/70-assert.yaml.j2 rename to tests/templates/kuttl/upgrade/70-assert.yaml.j2 index b21338eb..6083cebd 100644 --- a/tests/templates/kuttl/upgrade-oidc/70-assert.yaml.j2 +++ b/tests/templates/kuttl/upgrade/70-assert.yaml.j2 @@ -10,8 +10,11 @@ {% set app_version = test_scenario['values']['superset-new'] ~ '-stackable0.0.0-dev' %} {% endif %} --- -# Asserting the version label on the pod (not only on the StatefulSet) ensures -# that the assertion cannot pass before the old pod was actually replaced. +# A ready pod implies that `superset db upgrade`, `superset init` and the +# gunicorn startup all succeeded on the new version, because they run before +# the webserver can serve the /health readiness probe. Asserting the version +# label on the pod (not only on the StatefulSet) ensures that the assertion +# cannot pass before the old pod was actually replaced. apiVersion: kuttl.dev/v1beta1 kind: TestAssert metadata: diff --git a/tests/templates/kuttl/upgrade-oidc/70-upgrade-superset.yaml.j2 b/tests/templates/kuttl/upgrade/70-upgrade-superset.yaml.j2 similarity index 100% rename from tests/templates/kuttl/upgrade-oidc/70-upgrade-superset.yaml.j2 rename to tests/templates/kuttl/upgrade/70-upgrade-superset.yaml.j2 diff --git a/tests/templates/kuttl/upgrade-oidc/80-assert.yaml b/tests/templates/kuttl/upgrade/80-assert.yaml.j2 similarity index 54% rename from tests/templates/kuttl/upgrade-oidc/80-assert.yaml rename to tests/templates/kuttl/upgrade/80-assert.yaml.j2 index b11a5485..f3f6851e 100644 --- a/tests/templates/kuttl/upgrade-oidc/80-assert.yaml +++ b/tests/templates/kuttl/upgrade/80-assert.yaml.j2 @@ -1,3 +1,4 @@ +{% if test_scenario['values']['authentication'] == 'oidc' %} --- # Log in via Keycloak again after the upgrade. The user record was created by # Flask-AppBuilder during the pre-upgrade login (step 60), so this exercises @@ -10,3 +11,15 @@ metadata: timeout: 300 commands: - script: kubectl exec -n $NAMESPACE python-0 -- python /stackable/60_login.py +{% else %} +--- +# Verify that the content seeded in step 60 survived the metadata database +# migrations and that a real SQL query still works. +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +metadata: + name: verify +timeout: 300 +commands: + - script: kubectl exec -n $NAMESPACE python-0 -- python /tmp/upgrade-test.py verify +{% endif %} diff --git a/tests/templates/kuttl/upgrade/helm-bitnami-postgresql-values.yaml.j2 b/tests/templates/kuttl/upgrade/helm-bitnami-postgresql-values.yaml.j2 deleted file mode 100644 index 2e851682..00000000 --- a/tests/templates/kuttl/upgrade/helm-bitnami-postgresql-values.yaml.j2 +++ /dev/null @@ -1,44 +0,0 @@ ---- -global: - security: - allowInsecureImages: true # needed starting with Chart version 16.3.0 if modifying images - -image: - repository: bitnamilegacy/postgresql - -volumePermissions: - enabled: false - image: - repository: bitnamilegacy/os-shell - securityContext: - runAsUser: auto - -metrics: - image: - repository: bitnamilegacy/postgres-exporter - -primary: - podSecurityContext: -{% if test_scenario['values']['openshift'] == 'true' %} - enabled: false -{% else %} - enabled: true -{% endif %} - containerSecurityContext: - enabled: false - resources: - requests: - memory: "128Mi" - cpu: "512m" - limits: - memory: "128Mi" - cpu: "1" - -shmVolume: - chmod: - enabled: false - -auth: - username: superset - password: superset - database: superset diff --git a/tests/test-definition.yaml b/tests/test-definition.yaml index 400b13e0..a2d3cf11 100644 --- a/tests/test-definition.yaml +++ b/tests/test-definition.yaml @@ -29,6 +29,13 @@ dimensions: - no-tls - insecure-tls - server-verification-tls + # Authentication used in the upgrade test. "none" tests that seeded content + # survives the metadata database migrations, "oidc" tests that the OAuth + # login of an existing user still works after the upgrade. + - name: authentication + values: + - none + - oidc - name: opa-latest values: - 1.16.2 @@ -82,11 +89,7 @@ tests: dimensions: - superset-old - superset-new - - openshift - - name: upgrade-oidc - dimensions: - - superset-old - - superset-new + - authentication - openshift suites: - name: nightly From a29fbe4a9ef3563f084a1a34beada8aa5b3da4fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20M=C3=BCller?= Date: Fri, 5 Jun 2026 13:45:44 +0200 Subject: [PATCH 5/5] chore: update image names --- tests/test-definition.yaml | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/tests/test-definition.yaml b/tests/test-definition.yaml index a2d3cf11..f8d59409 100644 --- a/tests/test-definition.yaml +++ b/tests/test-definition.yaml @@ -6,24 +6,22 @@ dimensions: - name: superset values: - # - 4.1.4 - # - 6.0.0 + - 4.1.4 + - 6.0.0 + - 6.1.0 # Or use a custom image: - - 6.0.0,oci.stackable.tech/sdp/superset:6.0.0-stackable0.0.0-dev - - 6.1.0,oci.stackable.tech/sdp/superset:6.1.0-stackable0.0.0-dev # - 6.1.0,oci.stackable.tech/sandbox/superset:6.1.0 - name: superset-latest values: - # - 6.0.0 - - 6.1.0,oci.stackable.tech/sdp/superset:6.1.0-stackable0.0.0-dev + - 6.1.0 # - 6.0.0,oci.stackable.tech/sandbox/superset:6.0.0 - name: superset-old values: - - 4.1.4,oci.stackable.tech/sdp/superset:4.1.4-stackable0.0.0-dev - - 6.0.0,oci.stackable.tech/sdp/superset:6.0.0-stackable0.0.0-dev + - 4.1.4 + - 6.0.0 - name: superset-new values: - - 6.1.0,oci.stackable.tech/sdp/superset:6.1.0-stackable0.0.0-dev + - 6.1.0 - name: ldap-authentication values: - no-tls