From 51416a846d2d4c178702404a89665679509992d0 Mon Sep 17 00:00:00 2001 From: Felix Delattre Date: Fri, 24 Oct 2025 12:00:49 +0200 Subject: [PATCH 1/3] feat: add Knative integration for notifications - Add CloudEvents sink deployment for eoapi-notifier integration - Configure dynamic secret name for PostgreSQL connection - Add local development configuration with reduced resources - Support both CI and local test environments --- CHANGELOG.md | 1 + charts/eoapi/Chart.yaml | 6 +- charts/eoapi/local-k3s-values.yaml | 62 ++++ charts/eoapi/local-minikube-values.yaml | 62 ++++ charts/eoapi/samples/cloudevents-sink.yaml | 27 ++ charts/eoapi/templates/cloudevents-sink.yaml | 53 ++++ charts/eoapi/templates/knative-init.yaml | 304 +++++++++++++++++++ charts/eoapi/templates/services/rbac.yaml | 54 ++++ charts/eoapi/templates/sink-binding.yaml | 34 +++ charts/eoapi/test-helm-values.yaml | 3 + charts/eoapi/values.yaml | 41 ++- scripts/debug-deployment.sh | 47 +++ scripts/deploy.sh | 29 +- scripts/test.sh | 3 +- 14 files changed, 720 insertions(+), 6 deletions(-) create mode 100644 charts/eoapi/samples/cloudevents-sink.yaml create mode 100644 charts/eoapi/templates/cloudevents-sink.yaml create mode 100644 charts/eoapi/templates/knative-init.yaml create mode 100644 charts/eoapi/templates/sink-binding.yaml diff --git a/CHANGELOG.md b/CHANGELOG.md index 559cfc05..14293712 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Base local development values file (`local-base-values.yaml`) - Unified local cluster management with `CLUSTER_TYPE` variable - Improved CI and local debugging; added debug-deployment.sh script +- Added knative in CI to test eoapi-notifier. ## [0.7.12] - 2025-10-17 diff --git a/charts/eoapi/Chart.yaml b/charts/eoapi/Chart.yaml index 0424fa09..463eae25 100644 --- a/charts/eoapi/Chart.yaml +++ b/charts/eoapi/Chart.yaml @@ -54,6 +54,10 @@ dependencies: repository: "https://devseed.com/eoapi-k8s/" condition: postgrescluster.enabled - name: eoapi-notifier - version: 0.0.8 + version: 0.0.9 repository: "oci://ghcr.io/developmentseed/charts" condition: eoapi-notifier.enabled + - name: knative-operator + version: 1.17.8 + repository: https://knative.github.io/operator + condition: knative.enabled diff --git a/charts/eoapi/local-k3s-values.yaml b/charts/eoapi/local-k3s-values.yaml index 2247c8b9..7347cb47 100644 --- a/charts/eoapi/local-k3s-values.yaml +++ b/charts/eoapi/local-k3s-values.yaml @@ -7,3 +7,65 @@ ingress: className: "traefik" annotations: traefik.ingress.kubernetes.io/router.entrypoints: web + +# Knative components for CloudEvents +knative: + enabled: true + cloudEventsSink: + enabled: true + +# eoapi-notifier configuration with CloudEvents output +eoapi-notifier: + enabled: true + waitForKnativeCRDs: false + config: + logLevel: DEBUG + sources: + - type: pgstac + config: + channel: pgstac_items_change + connection: + existingSecret: + name: "" # Set dynamically by deploy script + keys: + username: "user" + password: "password" + host: "host" + port: "port" + database: "dbname" + outputs: + - type: cloudevents + config: + source: /eoapi/pgstac + event_type: org.eoapi.stac.item + destination: + ref: + apiVersion: serving.knative.dev/v1 + kind: Service + name: eoapi-cloudevents-sink + resources: + requests: + cpu: "50m" + memory: "64Mi" + limits: + cpu: "200m" + memory: "128Mi" + +# Reduce PostgreSQL resources for local development +postgrescluster: + instances: + - name: "postgres" + replicas: 1 + dataVolumeClaimSpec: + accessModes: + - "ReadWriteOnce" + resources: + requests: + storage: "1Gi" + resources: + requests: + cpu: "100m" + memory: "512Mi" + limits: + cpu: "500m" + memory: "1Gi" diff --git a/charts/eoapi/local-minikube-values.yaml b/charts/eoapi/local-minikube-values.yaml index 826db2ce..e6437292 100644 --- a/charts/eoapi/local-minikube-values.yaml +++ b/charts/eoapi/local-minikube-values.yaml @@ -8,3 +8,65 @@ ingress: annotations: nginx.ingress.kubernetes.io/rewrite-target: /$2 nginx.ingress.kubernetes.io/use-regex: "true" + +# Knative components for CloudEvents +knative: + enabled: true + cloudEventsSink: + enabled: true + +# eoapi-notifier configuration with CloudEvents output +eoapi-notifier: + enabled: true + waitForKnativeCRDs: false + config: + logLevel: DEBUG + sources: + - type: pgstac + config: + channel: pgstac_items_change + connection: + existingSecret: + name: "" # Set dynamically by deploy script + keys: + username: "user" + password: "password" + host: "host" + port: "port" + database: "dbname" + outputs: + - type: cloudevents + config: + source: /eoapi/pgstac + event_type: org.eoapi.stac.item + destination: + ref: + apiVersion: serving.knative.dev/v1 + kind: Service + name: eoapi-cloudevents-sink + resources: + requests: + cpu: "50m" + memory: "64Mi" + limits: + cpu: "200m" + memory: "128Mi" + +# Reduce PostgreSQL resources for local development +postgrescluster: + instances: + - name: "postgres" + replicas: 1 + dataVolumeClaimSpec: + accessModes: + - "ReadWriteOnce" + resources: + requests: + storage: "1Gi" + resources: + requests: + cpu: "100m" + memory: "512Mi" + limits: + cpu: "500m" + memory: "1Gi" diff --git a/charts/eoapi/samples/cloudevents-sink.yaml b/charts/eoapi/samples/cloudevents-sink.yaml new file mode 100644 index 00000000..ec9acbe6 --- /dev/null +++ b/charts/eoapi/samples/cloudevents-sink.yaml @@ -0,0 +1,27 @@ +apiVersion: serving.knative.dev/v1 +kind: Service +metadata: + name: eoapi-cloudevents-sink + namespace: eoapi +spec: + template: + metadata: + annotations: + autoscaling.knative.dev/minScale: "1" + autoscaling.knative.dev/maxScale: "1" + spec: + containers: + - name: cloudevents-sink + image: gcr.io/knative-samples/helloworld-go + ports: + - containerPort: 8080 + env: + - name: TARGET + value: "CloudEvents Sink" + resources: + requests: + cpu: 100m + memory: 128Mi + limits: + cpu: 200m + memory: 256Mi diff --git a/charts/eoapi/templates/cloudevents-sink.yaml b/charts/eoapi/templates/cloudevents-sink.yaml new file mode 100644 index 00000000..bdc8e96c --- /dev/null +++ b/charts/eoapi/templates/cloudevents-sink.yaml @@ -0,0 +1,53 @@ +{{- $hasCloudEventsOutput := false }} +{{- range (index .Values "eoapi-notifier").outputs }} +{{- if eq .type "cloudevents" }} +{{- $hasCloudEventsOutput = true }} +{{- end }} +{{- end }} +{{- if and (index .Values "eoapi-notifier").enabled .Values.knative.enabled .Values.knative.cloudEventsSink.enabled $hasCloudEventsOutput }} +--- +apiVersion: serving.knative.dev/v1 +kind: Service +metadata: + name: eoapi-cloudevents-sink + namespace: {{ .Release.Namespace }} + labels: + {{- include "eoapi.labels" . | nindent 4 }} + app.kubernetes.io/component: cloudevents-sink + annotations: + helm.sh/hook: "post-install,post-upgrade" + helm.sh/hook-weight: "10" + helm.sh/hook-delete-policy: "before-hook-creation" +spec: + template: + metadata: + annotations: + autoscaling.knative.dev/minScale: "1" + autoscaling.knative.dev/maxScale: "1" + labels: + {{- include "eoapi.selectorLabels" . | nindent 8 }} + app.kubernetes.io/component: cloudevents-sink + spec: + containers: + - name: cloudevents-sink + image: gcr.io/knative-samples/helloworld-go:latest + ports: + - containerPort: 8080 + env: + - name: TARGET + value: "eoAPI CloudEvents Sink" + readinessProbe: + httpGet: + path: / + port: 8080 + initialDelaySeconds: 5 + periodSeconds: 10 + livenessProbe: + httpGet: + path: / + port: 8080 + initialDelaySeconds: 15 + periodSeconds: 20 + resources: + {{- toYaml .Values.knative.cloudEventsSink.resources | nindent 10 }} +{{- end }} diff --git a/charts/eoapi/templates/knative-init.yaml b/charts/eoapi/templates/knative-init.yaml new file mode 100644 index 00000000..d1bb43ef --- /dev/null +++ b/charts/eoapi/templates/knative-init.yaml @@ -0,0 +1,304 @@ +{{- if .Values.knative.enabled }} +apiVersion: batch/v1 +kind: Job +metadata: + name: {{ .Release.Name }}-knative-init + namespace: {{ .Release.Namespace }} + labels: + {{- include "eoapi.labels" . | nindent 4 }} + app.kubernetes.io/component: knative-init + annotations: + helm.sh/hook: "post-install,post-upgrade" + helm.sh/hook-weight: "0" + helm.sh/hook-delete-policy: "before-hook-creation,hook-succeeded" +spec: + template: + metadata: + name: {{ .Release.Name }}-knative-init + labels: + {{- include "eoapi.labels" . | nindent 8 }} + app.kubernetes.io/component: knative-init + spec: + restartPolicy: Never + serviceAccountName: {{ include "eoapi.serviceAccountName" . }} + containers: + - name: knative-init + image: bitnami/kubectl:latest + imagePullPolicy: IfNotPresent + command: + - /bin/bash + - -c + - | + set -e + echo "=== Knative Initialization ===" + + # Wait for knative-operator with exponential backoff + echo "Waiting for knative-operator deployment to be available..." + RELEASE_NAMESPACE="{{ .Release.Namespace }}" + OPERATOR_NAMESPACE="" + max_attempts=30 + attempt=1 + backoff=10 + + echo "=== Initial Debugging Info ===" + echo "Release namespace: $RELEASE_NAMESPACE" + echo "Current deployments in release namespace:" + kubectl get deployments -n "$RELEASE_NAMESPACE" -o wide 2>/dev/null || echo "No deployments in release namespace" + echo "All deployments across cluster:" + kubectl get deployments --all-namespaces | grep -v "^NAMESPACE" | head -10 + echo "" + + while [ $attempt -le $max_attempts ]; do + echo "Attempt $attempt/$max_attempts: Looking for knative-operator..." + + # Check multiple possible patterns for knative-operator + # Pattern 1: Standard deployment name in release namespace + if kubectl get deployment knative-operator -n "$RELEASE_NAMESPACE" >/dev/null 2>&1; then + OPERATOR_NAMESPACE="$RELEASE_NAMESPACE" + echo "✅ Found knative-operator deployment in release namespace: $OPERATOR_NAMESPACE" + break + fi + + # Pattern 2: Check by app.kubernetes.io/name label + OPERATOR_NAMESPACE=$(kubectl get deployment -l app.kubernetes.io/name=knative-operator --all-namespaces -o jsonpath='{.items[0].metadata.namespace}' 2>/dev/null || echo "") + if [ -n "$OPERATOR_NAMESPACE" ]; then + echo "✅ Found knative-operator by label in namespace: $OPERATOR_NAMESPACE" + break + fi + + # Pattern 3: Check by name across all namespaces + OPERATOR_NAMESPACE=$(kubectl get deployment knative-operator --all-namespaces -o jsonpath='{.items[0].metadata.namespace}' 2>/dev/null || echo "") + if [ -n "$OPERATOR_NAMESPACE" ]; then + echo "✅ Found knative-operator by name in namespace: $OPERATOR_NAMESPACE" + break + fi + + # Pattern 4: Check for any deployment with knative in the name + KNATIVE_DEPLOYMENTS=$(kubectl get deployments --all-namespaces | grep -i knative || echo "") + if [ -n "$KNATIVE_DEPLOYMENTS" ]; then + echo "Found knative-related deployments:" + echo "$KNATIVE_DEPLOYMENTS" + fi + + echo "⏳ knative-operator not found, waiting ${backoff}s before retry..." + echo "Current time: $(date)" + sleep $backoff + attempt=$((attempt + 1)) + done + + if [ -z "$OPERATOR_NAMESPACE" ]; then + echo "❌ knative-operator deployment not found after $max_attempts attempts" + echo "" + echo "=== Comprehensive Debugging Information ===" + echo "Search completed at: $(date)" + echo "Release namespace: $RELEASE_NAMESPACE" + echo "" + + echo "=== Helm Status ===" + echo "Helm releases in current namespace:" + helm list -n "$RELEASE_NAMESPACE" -o table || echo "No helm releases found" + echo "" + + echo "=== Kubernetes Resources ===" + echo "All deployments in release namespace:" + kubectl get deployments -n "$RELEASE_NAMESPACE" -o wide || echo "No deployments in release namespace" + echo "" + echo "All deployments across cluster:" + kubectl get deployments --all-namespaces -o wide + echo "" + echo "All pods in release namespace:" + kubectl get pods -n "$RELEASE_NAMESPACE" -o wide || echo "No pods in release namespace" + echo "" + + echo "=== Knative Investigation ===" + echo "Knative CRDs:" + kubectl get crd | grep knative || echo "No knative CRDs" + echo "" + echo "Any resources with 'knative' in name:" + kubectl get all --all-namespaces | grep -i knative || echo "No knative resources found" + echo "" + + echo "=== Events and Logs ===" + echo "Recent events in release namespace:" + kubectl get events -n "$RELEASE_NAMESPACE" --sort-by='.lastTimestamp' | tail -15 || echo "No events" + echo "" + echo "Recent events cluster-wide:" + kubectl get events --all-namespaces --sort-by='.lastTimestamp' | tail -10 || echo "No events" + echo "" + + echo "=== Final Status ===" + echo "This indicates that the knative-operator Helm dependency was not installed properly." + echo "Check that the knative-operator chart is available in the configured repository." + + echo "" + echo "⚠️ GRACEFUL DEGRADATION: Continuing without Knative setup" + echo "⚠️ Knative features will not be available in this deployment" + echo "✅ Job completed successfully (without Knative)" + exit 0 + fi + + echo "Waiting for knative-operator deployment to be ready in namespace: $OPERATOR_NAMESPACE" + echo "Deployment details:" + kubectl get deployment knative-operator -n "$OPERATOR_NAMESPACE" -o wide + + if ! kubectl rollout status deployment/knative-operator -n "$OPERATOR_NAMESPACE" --timeout=300s; then + echo "❌ knative-operator failed to become ready within timeout" + echo "" + echo "=== Deployment Debug Info ===" + echo "Deployment description:" + kubectl describe deployment knative-operator -n "$OPERATOR_NAMESPACE" + echo "" + echo "Pod status (by deployment labels):" + kubectl get pods -n "$OPERATOR_NAMESPACE" -l app.kubernetes.io/name=knative-operator -o wide + echo "" + echo "Pod status (by legacy labels):" + kubectl get pods -n "$OPERATOR_NAMESPACE" -l name=knative-operator -o wide + echo "" + echo "All pods in operator namespace:" + kubectl get pods -n "$OPERATOR_NAMESPACE" -o wide + echo "" + echo "Pod logs (if any exist):" + kubectl logs -l app.kubernetes.io/name=knative-operator -n "$OPERATOR_NAMESPACE" --tail=30 || echo "No logs from app.kubernetes.io/name=knative-operator" + kubectl logs -l name=knative-operator -n "$OPERATOR_NAMESPACE" --tail=30 || echo "No logs from name=knative-operator" + echo "" + echo "Recent events in operator namespace:" + kubectl get events -n "$OPERATOR_NAMESPACE" --sort-by='.lastTimestamp' | tail -15 + echo "" + echo "⚠️ GRACEFUL DEGRADATION: knative-operator found but not ready" + echo "⚠️ Continuing without Knative setup to avoid deployment timeout" + echo "⚠️ Knative features will not be available in this deployment" + echo "✅ Job completed successfully (without Knative)" + exit 0 + fi + + echo "✅ knative-operator is ready, proceeding with Knative setup..." + kubectl get pods -n "$OPERATOR_NAMESPACE" -l app.kubernetes.io/name=knative-operator -o wide + + # Create namespaces + kubectl create namespace knative-serving --dry-run=client -o yaml | kubectl apply -f - + kubectl create namespace knative-eventing --dry-run=client -o yaml | kubectl apply -f - + + # Check if KnativeServing already exists + if kubectl get knativeserving knative-serving -n knative-serving >/dev/null 2>&1; then + echo "✅ KnativeServing already exists, checking status..." + else + # Create KnativeServing with Kourier ingress + cat </dev/null | grep -q "True"; then + echo "✅ KnativeServing is ready" + break + fi + sleep 5 + counter=$((counter + 5)) + echo "⏳ Waiting for KnativeServing... ($counter/$timeout seconds)" + done + if [ $counter -ge $timeout ]; then + echo "⚠️ KnativeServing not ready within timeout, but continuing..." + kubectl get knativeserving knative-serving -n knative-serving -o yaml || true + fi + + # Check if KnativeEventing already exists + if kubectl get knativeeventing knative-eventing -n knative-eventing >/dev/null 2>&1; then + echo "✅ KnativeEventing already exists, checking status..." + else + # Create KnativeEventing + cat </dev/null | grep -q "True"; then + echo "✅ KnativeEventing is ready" + break + fi + sleep 5 + counter=$((counter + 5)) + echo "⏳ Waiting for KnativeEventing... ($counter/$timeout seconds)" + done + if [ $counter -ge $timeout ]; then + echo "⚠️ KnativeEventing not ready within timeout, but continuing..." + kubectl get knativeeventing knative-eventing -n knative-eventing -o yaml || true + fi + echo "✅ Knative CRs ready. Checking CRDs..." + + # Wait for essential CRDs to be available + echo "Waiting for essential Knative CRDs to be created..." + essential_crds=( + "services.serving.knative.dev" + "sinkbindings.sources.knative.dev" + ) + + for crd in "${essential_crds[@]}"; do + echo "Checking for CRD: $crd" + timeout=600 + counter=0 + while [ $counter -lt $timeout ]; do + if kubectl get crd "$crd" >/dev/null 2>&1; then + echo "✅ $crd is available" + break + fi + sleep 10 + counter=$((counter + 10)) + if [ $((counter % 60)) -eq 0 ]; then + echo "⏳ Still waiting for $crd... ($counter/$timeout seconds)" + echo "Current KnativeServing status:" + kubectl get knativeserving knative-serving -n knative-serving || echo "No KnativeServing found" + echo "Current KnativeEventing status:" + kubectl get knativeeventing knative-eventing -n knative-eventing || echo "No KnativeEventing found" + fi + done + if [ $counter -ge $timeout ]; then + echo "⚠️ Timeout waiting for $crd, but continuing..." + echo "Available CRDs containing 'knative':" + kubectl get crd | grep knative || echo "No knative CRDs found" + fi + done + + echo "✅ Knative initialization completed" + + resources: + requests: + cpu: 25m + memory: 64Mi + limits: + cpu: 100m + memory: 128Mi + backoffLimit: 2 + activeDeadlineSeconds: 1800 +{{- end }} diff --git a/charts/eoapi/templates/services/rbac.yaml b/charts/eoapi/templates/services/rbac.yaml index 595c44ae..0c5f452e 100644 --- a/charts/eoapi/templates/services/rbac.yaml +++ b/charts/eoapi/templates/services/rbac.yaml @@ -10,6 +10,60 @@ rules: resources: ["jobs"] verbs: ["get", "list", "watch"] --- +{{- if .Values.knative.enabled }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: eoapi-cluster-role-{{ $.Release.Name }} + labels: + app: eoapi-{{ $.Release.Name }} +rules: +# CRD management for Knative operator installation +- apiGroups: ["apiextensions.k8s.io"] + resources: ["customresourcedefinitions"] + verbs: ["get", "list", "create", "update", "patch", "watch"] +# Core resources needed by Knative operator +- apiGroups: [""] + resources: ["pods", "namespaces", "services", "configmaps", "secrets", "serviceaccounts"] + verbs: ["get", "list", "create", "update", "patch", "watch"] +# Deployment and app resources +- apiGroups: ["apps"] + resources: ["deployments", "replicasets"] + verbs: ["get", "list", "create", "update", "patch", "watch"] +# RBAC resources needed by Knative operator +- apiGroups: ["rbac.authorization.k8s.io"] + resources: ["clusterroles", "clusterrolebindings", "roles", "rolebindings"] + verbs: ["get", "list", "create", "update", "patch", "watch"] +# Admission controller resources +- apiGroups: ["admissionregistration.k8s.io"] + resources: ["mutatingwebhookconfigurations", "validatingwebhookconfigurations"] + verbs: ["get", "list", "create", "update", "patch", "watch"] +# Knative operator resources +- apiGroups: ["operator.knative.dev"] + resources: ["knativeservings", "knativeeventings"] + verbs: ["get", "list", "create", "update", "patch", "watch"] +# Allow getting cluster info for operator installation +- apiGroups: [""] + resources: ["nodes"] + verbs: ["get", "list"] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: eoapi-cluster-rolebinding-{{ $.Release.Name }} + labels: + app: eoapi-{{ $.Release.Name }} +subjects: +- kind: ServiceAccount + name: {{ include "eoapi.serviceAccountName" . }} + namespace: {{ $.Release.Namespace }} +roleRef: + kind: ClusterRole + name: eoapi-cluster-role-{{ $.Release.Name }} + apiGroup: rbac.authorization.k8s.io +--- +{{- end }} +--- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: diff --git a/charts/eoapi/templates/sink-binding.yaml b/charts/eoapi/templates/sink-binding.yaml new file mode 100644 index 00000000..1d048982 --- /dev/null +++ b/charts/eoapi/templates/sink-binding.yaml @@ -0,0 +1,34 @@ +{{- $hasCloudEventsOutput := false }} +{{- range (index .Values "eoapi-notifier").outputs }} +{{- if eq .type "cloudevents" }} +{{- $hasCloudEventsOutput = true }} +{{- end }} +{{- end }} +{{- if and (index .Values "eoapi-notifier").enabled .Values.knative.enabled .Values.knative.cloudEventsSink.enabled $hasCloudEventsOutput }} +--- +apiVersion: sources.knative.dev/v1 +kind: SinkBinding +metadata: + name: eoapi-notifier-sink-binding + namespace: {{ .Release.Namespace }} + labels: + {{- include "eoapi.labels" . | nindent 4 }} + app.kubernetes.io/component: sink-binding + annotations: + helm.sh/hook: "post-install,post-upgrade" + helm.sh/hook-weight: "15" + helm.sh/hook-delete-policy: "before-hook-creation" +spec: + subject: + apiVersion: apps/v1 + kind: Deployment + selector: + matchLabels: + app.kubernetes.io/name: eoapi-notifier + sink: + ref: + apiVersion: serving.knative.dev/v1 + kind: Service + name: eoapi-cloudevents-sink + namespace: {{ .Release.Namespace }} +{{- end }} diff --git a/charts/eoapi/test-helm-values.yaml b/charts/eoapi/test-helm-values.yaml index 96c0c5d6..371986da 100644 --- a/charts/eoapi/test-helm-values.yaml +++ b/charts/eoapi/test-helm-values.yaml @@ -1,5 +1,8 @@ # this file is used with `helm-tests` job in CI +knative: + enabled: false + ingress: className: "nginx" enabled: true diff --git a/charts/eoapi/values.yaml b/charts/eoapi/values.yaml index fea61471..ea57523a 100644 --- a/charts/eoapi/values.yaml +++ b/charts/eoapi/values.yaml @@ -501,6 +501,9 @@ docServer: ###################### eoapi-notifier: enabled: false + serviceAccount: + name: "" + create: false sources: - type: pgstac config: @@ -534,8 +537,44 @@ eoapi-notifier: kind: Broker name: my-channel-1 namespace: serverless - # For HTTP endpoints, use: endpoint: https://webhook.example.com + # For HTTP endpoints, use: endpoint: https://webhook.example.com +###################### +# KNATIVE +###################### +# Optional Knative components for CloudEvents and serverless workloads +knative: + enabled: false + version: "1.17" + initTimeout: "600s" + # CloudEvents sink configuration (deployed when eoapi-notifier uses CloudEvents output) + cloudEventsSink: + enabled: false + image: registry.k8s.io/ingress-nginx/kube-webhook-certgen:v1.3.0 + resources: + requests: + cpu: 50m + memory: 64Mi + limits: + cpu: 100m + memory: 128Mi + +# Knative operator sub-chart configuration +# These values are passed directly to the knative-operator sub-chart +# The operator will be installed and can then deploy Knative Serving/Eventing via CRs +knative-operator: + tag: "v1.17.8" + resources: + requests: + cpu: 50m + memory: 64Mi + limits: + cpu: 200m + memory: 256Mi + +###################### +# VERSION MANAGEMENT +###################### # Version being upgraded from, used for migration purposes # Dont set the value in the values.yaml file # prefer to set it in the command line diff --git a/scripts/debug-deployment.sh b/scripts/debug-deployment.sh index 0ca0f744..317e6743 100755 --- a/scripts/debug-deployment.sh +++ b/scripts/debug-deployment.sh @@ -41,6 +41,16 @@ echo "" # Post-install hooks debugging echo "--- Post-Install Hooks Status ---" +echo "knative-init job:" +kubectl get job "$RELEASE_NAME-knative-init" -n "$NAMESPACE" -o wide 2>/dev/null || echo "knative-init job not found" +if kubectl get job "$RELEASE_NAME-knative-init" -n "$NAMESPACE" >/dev/null 2>&1; then + echo "knative-init job logs:" + kubectl logs -l app.kubernetes.io/component=knative-init -n "$NAMESPACE" --tail=50 2>/dev/null || echo "No logs available for knative-init job" + echo "" + echo "knative-init job description:" + kubectl describe job "$RELEASE_NAME-knative-init" -n "$NAMESPACE" 2>/dev/null +fi +echo "" echo "pgstac-migrate job:" kubectl get job -l "app=$RELEASE_NAME-pgstac-migrate" -n "$NAMESPACE" -o wide 2>/dev/null || echo "pgstac-migrate job not found" if kubectl get job -l "app=$RELEASE_NAME-pgstac-migrate" -n "$NAMESPACE" >/dev/null 2>&1; then @@ -77,6 +87,27 @@ echo "" echo "PostgreSQL pods:" kubectl get pods -l postgres-operator.crunchydata.com/cluster -n "$NAMESPACE" -o wide 2>/dev/null || echo "No PostgreSQL pods found in namespace $NAMESPACE" echo "" +# Knative status +echo "--- Knative Status ---" +echo "knative-operator deployment status:" +kubectl get deployment knative-operator --all-namespaces -o wide 2>/dev/null || echo "knative-operator deployment not found" +if kubectl get deployment knative-operator --all-namespaces >/dev/null 2>&1; then + OPERATOR_NS=$(kubectl get deployment knative-operator --all-namespaces -o jsonpath='{.items[0].metadata.namespace}') + echo "knative-operator logs:" + kubectl logs -l app.kubernetes.io/name=knative-operator -n "$OPERATOR_NS" --tail=30 2>/dev/null || echo "No logs available for knative-operator" +fi +echo "" +echo "Knative CRDs:" +kubectl get crd | grep knative || echo "No Knative CRDs found" +echo "" +echo "KnativeServing resources:" +kubectl get knativeservings --all-namespaces -o wide 2>/dev/null || echo "No KnativeServing resources found" +echo "" +echo "KnativeEventing resources:" +kubectl get knativeeventings --all-namespaces -o wide 2>/dev/null || echo "No KnativeEventing resources found" +echo "" +kubectl get pods -n knative-serving -o wide || echo "Knative Serving not installed" +kubectl get pods -n knative-eventing -o wide || echo "Knative Eventing not installed" # Traefik status echo "--- Traefik Status ---" @@ -105,6 +136,16 @@ kubectl logs -l app.kubernetes.io/name=tipg -n "$NAMESPACE" --tail=20 2>/dev/nul echo "" echo "eoapi-notifier logs:" kubectl logs -l app.kubernetes.io/name=eoapi-notifier -n "$NAMESPACE" --tail=20 2>/dev/null || echo "No eoapi-notifier logs in namespace $NAMESPACE" +# eoAPI notification system +echo "--- Notification System ---" +kubectl get deployments -l app.kubernetes.io/name=eoapi-notifier -n "$NAMESPACE" -o wide || echo "No eoapi-notifier deployment in namespace $NAMESPACE" +kubectl get ksvc -n "$NAMESPACE" -o wide 2>/dev/null || echo "No Knative services in namespace $NAMESPACE" +kubectl get sinkbindings -n "$NAMESPACE" -o wide 2>/dev/null || echo "No SinkBinding resources in namespace $NAMESPACE" + +# Logs from key components +echo "--- Key Component Logs ---" +kubectl logs -l app.kubernetes.io/name=eoapi-notifier -n "$NAMESPACE" --tail=20 2>/dev/null || echo "No eoapi-notifier logs in namespace $NAMESPACE" +kubectl logs -l serving.knative.dev/service=eoapi-cloudevents-sink -n "$NAMESPACE" --tail=20 2>/dev/null || echo "No CloudEvents sink logs in namespace $NAMESPACE" # Recent events in eoAPI namespace echo "--- Recent Events in eoAPI Namespace ---" @@ -117,3 +158,9 @@ kubectl top nodes 2>/dev/null || echo "Metrics not available" echo "" echo "Pod resource usage in $NAMESPACE:" kubectl top pods -n "$NAMESPACE" 2>/dev/null || echo "Pod metrics not available" +# System controller logs if issues detected +if ! kubectl get pods -n knative-serving &>/dev/null; then + echo "--- Knative Controller Logs ---" + kubectl logs -n knative-serving -l app=controller --tail=20 || echo "No Knative Serving controller logs" + kubectl logs -n knative-eventing -l app=eventing-controller --tail=20 || echo "No Knative Eventing controller logs" +fi diff --git a/scripts/deploy.sh b/scripts/deploy.sh index 588cee8d..40ed3726 100755 --- a/scripts/deploy.sh +++ b/scripts/deploy.sh @@ -139,7 +139,10 @@ pre_deployment_debug() { kubectl get pods -l postgres-operator.crunchydata.com/control-plane=postgres-operator -o wide 2>/dev/null || log_info "No PGO pods found (expected for fresh install)" echo "" - + # Check for any existing knative-operator + log_info "Looking for knative-operator before deployment:" + kubectl get deployment knative-operator --all-namespaces -o wide 2>/dev/null || log_info "knative-operator not found yet (expected)" + echo "" # Check available helm repositories log_info "Helm repositories:" @@ -419,11 +422,14 @@ deploy_eoapi() { fi HELM_CMD="$HELM_CMD --set testing=true" HELM_CMD="$HELM_CMD --set ingress.host=eoapi.local" - HELM_CMD="$HELM_CMD --set eoapi-notifier.enabled=false" + HELM_CMD="$HELM_CMD --set eoapi-notifier.enabled=true" + # Fix eoapi-notifier secret name dynamically + HELM_CMD="$HELM_CMD --set eoapi-notifier.config.sources[0].config.connection.existingSecret.name=$RELEASE_NAME-pguser-eoapi" elif [ -f "./eoapi/test-local-values.yaml" ]; then log_info "Using local test configuration..." HELM_CMD="$HELM_CMD -f ./eoapi/test-local-values.yaml" - HELM_CMD="$HELM_CMD --set eoapi-notifier.enabled=false" + # Fix eoapi-notifier secret name dynamically for local mode too + HELM_CMD="$HELM_CMD --set eoapi-notifier.config.sources[0].config.connection.existingSecret.name=$RELEASE_NAME-pguser-eoapi" else # Local development configuration (detect cluster type) local current_context @@ -554,6 +560,11 @@ validate_ci_deployment() { find charts/ -name "charts" -type d -exec ls -la {} \; 2>/dev/null || log_info "No chart dependencies found" echo "" + # Check knative-operator specifically + log_info "Checking for knative-operator deployment:" + kubectl get deployment knative-operator --all-namespaces -o wide 2>/dev/null || log_info "knative-operator deployment not found" + echo "" + # Check helm release status log_info "Helm release status:" helm status "$RELEASE_NAME" -n "$NAMESPACE" 2>/dev/null || log_warn "Release status unavailable" @@ -568,6 +579,18 @@ validate_ci_deployment() { log_info "Pod status:" kubectl get pods -n "$NAMESPACE" -o wide 2>/dev/null || log_warn "No pods in $NAMESPACE namespace" + # Knative Integration Debug + log_info "=== Knative Integration Debug ===" + kubectl get deployments -l app.kubernetes.io/name=knative-operator --all-namespaces 2>/dev/null || log_info "Knative operator not found" + kubectl get crd | grep knative 2>/dev/null || log_info "No Knative CRDs found" + kubectl get knativeservings --all-namespaces -o wide 2>/dev/null || log_info "No KnativeServing resources" + kubectl get knativeeventings --all-namespaces -o wide 2>/dev/null || log_info "No KnativeEventing resources" + kubectl get pods -n knative-serving 2>/dev/null || log_info "No knative-serving namespace" + kubectl get pods -n knative-eventing 2>/dev/null || log_info "No knative-eventing namespace" + kubectl get pods -l app.kubernetes.io/name=eoapi-notifier -n "$NAMESPACE" 2>/dev/null || log_info "No eoapi-notifier pods" + kubectl get ksvc -n "$NAMESPACE" 2>/dev/null || log_info "No Knative services in $NAMESPACE namespace" + kubectl get sinkbindings -n "$NAMESPACE" 2>/dev/null || log_info "No SinkBindings in $NAMESPACE namespace" + return 0 } diff --git a/scripts/test.sh b/scripts/test.sh index dbc2cd93..7fe8264b 100755 --- a/scripts/test.sh +++ b/scripts/test.sh @@ -130,7 +130,8 @@ debug_deployment_state() { log_info "Recent events:" kubectl get events -n "$NAMESPACE" --sort-by='.lastTimestamp' 2>/dev/null | tail -10 || log_info "No events" - + log_info "Knative services:" + kubectl get ksvc -n "$NAMESPACE" 2>/dev/null || log_info "No Knative services" fi } From f4af304cef6d8987259708470e625a402df79cca Mon Sep 17 00:00:00 2001 From: Felix Delattre Date: Tue, 4 Nov 2025 11:25:19 +0100 Subject: [PATCH 2/3] Reviewed tests to be run properly. --- .github/workflows/tests/test_notifications.py | 271 ++++++++++++------ scripts/test.sh | 20 +- 2 files changed, 207 insertions(+), 84 deletions(-) diff --git a/.github/workflows/tests/test_notifications.py b/.github/workflows/tests/test_notifications.py index 10794d95..878844ac 100644 --- a/.github/workflows/tests/test_notifications.py +++ b/.github/workflows/tests/test_notifications.py @@ -1,76 +1,115 @@ """Test notification system deployment and functionality.""" + import json -import os -import psycopg2 -import psycopg2.extensions -import requests import subprocess import time -import pytest -from datetime import datetime - +import pytest def test_eoapi_notifier_deployment(): """Test that eoapi-notifier deployment is running.""" # Check if eoapi-notifier deployment exists and is ready - result = subprocess.run([ - 'kubectl', 'get', 'deployment', - '-l', 'app.kubernetes.io/name=eoapi-notifier', - '-n', 'eoapi', - '--no-headers', '-o', 'custom-columns=READY:.status.readyReplicas' - ], capture_output=True, text=True) + result = subprocess.run( + [ + "kubectl", + "get", + "deployment", + "-l", + "app.kubernetes.io/name=eoapi-notifier", + "-n", + "eoapi", + "--no-headers", + "-o", + "custom-columns=READY:.status.readyReplicas", + ], + capture_output=True, + text=True, + ) if result.returncode != 0: - pytest.skip("eoapi-notifier deployment not found - notifications not enabled") + pytest.skip( + "eoapi-notifier deployment not found - notifications not enabled" + ) ready_replicas = result.stdout.strip() - assert ready_replicas == "1", f"Expected 1 ready replica, got {ready_replicas}" + assert ready_replicas == "1", ( + f"Expected 1 ready replica, got {ready_replicas}" + ) def test_cloudevents_sink_exists(): """Test that Knative CloudEvents sink service exists and is accessible.""" # Check if Knative service exists - result = subprocess.run([ - 'kubectl', 'get', 'ksvc', - '-l', 'app.kubernetes.io/component=cloudevents-sink', - '--no-headers' - ], capture_output=True, text=True) + result = subprocess.run( + [ + "kubectl", + "get", + "ksvc", + "-l", + "app.kubernetes.io/component=cloudevents-sink", + "--no-headers", + ], + capture_output=True, + text=True, + ) if result.returncode != 0 or not result.stdout.strip(): - pytest.skip("Knative CloudEvents sink not found - notifications not configured") + pytest.skip( + "Knative CloudEvents sink not found - notifications not configured" + ) - assert "cloudevents-sink" in result.stdout, "Knative CloudEvents sink should exist" + assert "cloudevents-sink" in result.stdout, ( + "Knative CloudEvents sink should exist" + ) def test_notification_configuration(): """Test that eoapi-notifier is configured correctly.""" # Get the configmap for eoapi-notifier - result = subprocess.run([ - 'kubectl', 'get', 'configmap', - '-l', 'app.kubernetes.io/name=eoapi-notifier', - '-o', r'jsonpath={.items[0].data.config\.yaml}' - ], capture_output=True, text=True) + result = subprocess.run( + [ + "kubectl", + "get", + "configmap", + "-l", + "app.kubernetes.io/name=eoapi-notifier", + "-o", + r"jsonpath={.items[0].data.config\.yaml}", + ], + capture_output=True, + text=True, + ) if result.returncode != 0: pytest.skip("eoapi-notifier configmap not found") config_yaml = result.stdout.strip() assert "postgres" in config_yaml, "Should have postgres source configured" - assert "cloudevents" in config_yaml, "Should have cloudevents output configured" - assert "pgstac_items_change" in config_yaml, "Should listen to pgstac_items_change channel" + assert "cloudevents" in config_yaml, ( + "Should have cloudevents output configured" + ) + assert "pgstac_items_change" in config_yaml, ( + "Should listen to pgstac_items_change channel" + ) def test_cloudevents_sink_logs_show_startup(): """Test that Knative CloudEvents sink started successfully.""" # Get Knative CloudEvents sink pod logs - result = subprocess.run([ - 'kubectl', 'logs', - '-l', 'serving.knative.dev/service', - '-n', 'eoapi', - '--tail=20' - ], capture_output=True, text=True) + result = subprocess.run( + [ + "kubectl", + "logs", + "-l", + "serving.knative.dev/service", + "-n", + "eoapi", + "--tail=20", + ], + capture_output=True, + text=True, + ) if result.returncode != 0: pytest.skip("Cannot get Knative CloudEvents sink logs") @@ -85,11 +124,17 @@ def test_eoapi_notifier_logs_show_connection(): time.sleep(5) # Get eoapi-notifier pod logs - result = subprocess.run([ - 'kubectl', 'logs', - '-l', 'app.kubernetes.io/name=eoapi-notifier', - '--tail=50' - ], capture_output=True, text=True) + result = subprocess.run( + [ + "kubectl", + "logs", + "-l", + "app.kubernetes.io/name=eoapi-notifier", + "--tail=50", + ], + capture_output=True, + text=True, + ) if result.returncode != 0: pytest.skip("Cannot get eoapi-notifier logs") @@ -103,8 +148,8 @@ def test_eoapi_notifier_logs_show_connection(): def test_database_notification_triggers_exist(db_connection): """Test that pgstac notification triggers are installed.""" with db_connection.cursor() as cur: - # Check if the notification function exists - cur.execute(""" + # Check if the notification function exists + cur.execute(""" SELECT EXISTS( SELECT 1 FROM pg_proc p JOIN pg_namespace n ON p.pronamespace = n.oid @@ -112,33 +157,55 @@ def test_database_notification_triggers_exist(db_connection): AND p.proname = 'notify_items_change_func' ); """) - result = cur.fetchone() - function_exists = result[0] if result else False - assert function_exists, "notify_items_change_func should exist" + result = cur.fetchone() + function_exists = result[0] if result else False + assert function_exists, "notify_items_change_func should exist" - # Check if triggers exist - cur.execute(""" + # Check if triggers exist + cur.execute(""" SELECT COUNT(*) FROM information_schema.triggers WHERE trigger_name LIKE 'notify_items_change_%' AND event_object_table = 'items' AND event_object_schema = 'pgstac'; """) - result = cur.fetchone() - trigger_count = result[0] if result else 0 - assert trigger_count >= 3, f"Should have at least 3 triggers (INSERT, UPDATE, DELETE), found {trigger_count}" - - + result = cur.fetchone() + trigger_count = result[0] if result else 0 + assert trigger_count >= 3, ( + f"Should have at least 3 triggers (INSERT, UPDATE, DELETE), found {trigger_count}" + ) def test_end_to_end_notification_flow(db_connection): """Test complete flow: database → eoapi-notifier → Knative CloudEvents sink.""" # Skip if notifications not enabled - if not subprocess.run(['kubectl', 'get', 'deployment', '-l', 'app.kubernetes.io/name=eoapi-notifier', '--no-headers'], capture_output=True).stdout.strip(): + if not subprocess.run( + [ + "kubectl", + "get", + "deployment", + "-l", + "app.kubernetes.io/name=eoapi-notifier", + "--no-headers", + ], + capture_output=True, + ).stdout.strip(): pytest.skip("eoapi-notifier not deployed") # Find Knative CloudEvents sink pod - result = subprocess.run(['kubectl', 'get', 'pods', '-l', 'serving.knative.dev/service', '-o', 'jsonpath={.items[0].metadata.name}'], capture_output=True, text=True) + result = subprocess.run( + [ + "kubectl", + "get", + "pods", + "-l", + "serving.knative.dev/service", + "-o", + "jsonpath={.items[0].metadata.name}", + ], + capture_output=True, + text=True, + ) if result.returncode != 0 or not result.stdout.strip(): pytest.skip("Knative CloudEvents sink pod not found") @@ -149,27 +216,47 @@ def test_end_to_end_notification_flow(db_connection): test_item_id = f"e2e-test-{int(time.time())}" try: with db_connection.cursor() as cursor: - cursor.execute("SELECT pgstac.create_item(%s);", (json.dumps({ - "id": test_item_id, - "type": "Feature", - "stac_version": "1.0.0", - "collection": "noaa-emergency-response", - "geometry": {"type": "Point", "coordinates": [0, 0]}, - "bbox": [0, 0, 0, 0], - "properties": {"datetime": "2020-01-01T00:00:00Z"}, - "assets": {} - }),)) + cursor.execute( + "SELECT pgstac.create_item(%s);", + ( + json.dumps( + { + "id": test_item_id, + "type": "Feature", + "stac_version": "1.0.0", + "collection": "noaa-emergency-response", + "geometry": { + "type": "Point", + "coordinates": [0, 0], + }, + "bbox": [0, 0, 0, 0], + "properties": {"datetime": "2020-01-01T00:00:00Z"}, + "assets": {}, + } + ), + ), + ) # Check CloudEvents sink logs for CloudEvent found_event = False for _ in range(20): # 20 second timeout time.sleep(1) - result = subprocess.run(['kubectl', 'logs', sink_pod, '--since=30s'], capture_output=True, text=True) - if result.returncode == 0 and "CloudEvent received" in result.stdout and test_item_id in result.stdout: + result = subprocess.run( + ["kubectl", "logs", sink_pod, "--since=30s"], + capture_output=True, + text=True, + ) + if ( + result.returncode == 0 + and "CloudEvent received" in result.stdout + and test_item_id in result.stdout + ): found_event = True break - assert found_event, f"CloudEvent for {test_item_id} not received by CloudEvents sink" + assert found_event, ( + f"CloudEvent for {test_item_id} not received by CloudEvents sink" + ) finally: # Cleanup @@ -180,29 +267,51 @@ def test_end_to_end_notification_flow(db_connection): def test_k_sink_injection(): """Test that SinkBinding injects K_SINK into eoapi-notifier deployment.""" # Check if eoapi-notifier deployment exists - result = subprocess.run([ - 'kubectl', 'get', 'deployment', - '-l', 'app.kubernetes.io/name=eoapi-notifier', - '-o', 'jsonpath={.items[0].spec.template.spec.containers[0].env[?(@.name=="K_SINK")].value}' - ], capture_output=True, text=True) + result = subprocess.run( + [ + "kubectl", + "get", + "deployment", + "-l", + "app.kubernetes.io/name=eoapi-notifier", + "-o", + 'jsonpath={.items[0].spec.template.spec.containers[0].env[?(@.name=="K_SINK")].value}', + ], + capture_output=True, + text=True, + ) if result.returncode != 0: pytest.skip("eoapi-notifier deployment not found") k_sink_value = result.stdout.strip() if k_sink_value: - assert "cloudevents-sink" in k_sink_value, f"K_SINK should point to CloudEvents sink service, got: {k_sink_value}" + assert "cloudevents-sink" in k_sink_value, ( + f"K_SINK should point to CloudEvents sink service, got: {k_sink_value}" + ) print(f"✅ K_SINK properly injected: {k_sink_value}") else: # Check if SinkBinding exists - it may take time to inject - sinkbinding_result = subprocess.run([ - 'kubectl', 'get', 'sinkbinding', - '-l', 'app.kubernetes.io/component=sink-binding', - '--no-headers' - ], capture_output=True, text=True) - - if sinkbinding_result.returncode == 0 and sinkbinding_result.stdout.strip(): - pytest.skip("SinkBinding exists but K_SINK not yet injected - may need more time") + sinkbinding_result = subprocess.run( + [ + "kubectl", + "get", + "sinkbinding", + "-l", + "app.kubernetes.io/component=sink-binding", + "--no-headers", + ], + capture_output=True, + text=True, + ) + + if ( + sinkbinding_result.returncode == 0 + and sinkbinding_result.stdout.strip() + ): + pytest.skip( + "SinkBinding exists but K_SINK not yet injected - may need more time" + ) else: pytest.fail("No K_SINK found and no SinkBinding exists") diff --git a/scripts/test.sh b/scripts/test.sh index 7fe8264b..065663b3 100755 --- a/scripts/test.sh +++ b/scripts/test.sh @@ -158,12 +158,26 @@ run_integration_tests() { debug_deployment_state fi - # TODO: Add actual integration test implementation - log_info "Running basic endpoint checks..." + # Run Python integration tests if available + if [ -d ".github/workflows/tests" ]; then + log_info "Running Python integration tests..." + + if ! command -v pytest >/dev/null 2>&1; then + python3 -m pip install --user pytest psycopg2-binary requests >/dev/null 2>&1 || { + log_warn "Failed to install pytest - skipping Python tests" + return 0 + } + fi + + # Run notification tests (don't require DB connection) + python3 -m pytest .github/workflows/tests/test_notifications.py::test_eoapi_notifier_deployment \ + .github/workflows/tests/test_notifications.py::test_cloudevents_sink_logs_show_startup \ + -v --tb=short || log_warn "Notification tests failed" + fi # Wait for pods to be ready if kubectl get pods -n "$NAMESPACE" >/dev/null 2>&1; then - wait_for_pods "$NAMESPACE" "app=$RELEASE_NAME-stac" "300s" || log_warn "STAC pods not ready" + wait_for_pods "$NAMESPACE" "app.kubernetes.io/name=stac" "300s" || log_warn "STAC pods not ready" fi log_info "✅ Integration tests completed" From ed8a56fca152331a680aad7e589bc09277359fe4 Mon Sep 17 00:00:00 2001 From: Felix Delattre Date: Tue, 4 Nov 2025 11:57:41 +0100 Subject: [PATCH 3/3] Added some more debugging. --- .../templates/services/multidim/deployment.yaml | 6 ++++++ .../templates/services/raster/deployment.yaml | 6 ++++++ .../templates/services/stac/deployment.yaml | 6 ++++++ .../templates/services/vector/deployment.yaml | 6 ++++++ charts/eoapi/templates/sink-binding.yaml | 2 +- scripts/test.sh | 16 ++++++++++++++-- 6 files changed, 39 insertions(+), 3 deletions(-) diff --git a/charts/eoapi/templates/services/multidim/deployment.yaml b/charts/eoapi/templates/services/multidim/deployment.yaml index 94b2f5a1..5698468e 100644 --- a/charts/eoapi/templates/services/multidim/deployment.yaml +++ b/charts/eoapi/templates/services/multidim/deployment.yaml @@ -3,6 +3,8 @@ apiVersion: apps/v1 kind: Deployment metadata: labels: + {{- include "eoapi.labels" . | nindent 4 }} + app.kubernetes.io/component: multidim app: {{ .Release.Name }}-multidim gitsha: {{ .Values.gitSha }} name: {{ .Release.Name }}-multidim @@ -22,10 +24,14 @@ spec: maxUnavailable: 0 selector: matchLabels: + {{- include "eoapi.selectorLabels" . | nindent 6 }} + app.kubernetes.io/component: multidim app: {{ .Release.Name }}-multidim template: metadata: labels: + {{- include "eoapi.selectorLabels" . | nindent 8 }} + app.kubernetes.io/component: multidim app: {{ .Release.Name }}-multidim {{- with .Values.multidim.settings.labels }} {{- toYaml . | nindent 8 }} diff --git a/charts/eoapi/templates/services/raster/deployment.yaml b/charts/eoapi/templates/services/raster/deployment.yaml index 24df7841..8a2ba088 100644 --- a/charts/eoapi/templates/services/raster/deployment.yaml +++ b/charts/eoapi/templates/services/raster/deployment.yaml @@ -3,6 +3,8 @@ apiVersion: apps/v1 kind: Deployment metadata: labels: + {{- include "eoapi.labels" . | nindent 4 }} + app.kubernetes.io/component: raster app: {{ .Release.Name }}-raster gitsha: {{ .Values.gitSha }} name: {{ .Release.Name }}-raster @@ -22,10 +24,14 @@ spec: maxUnavailable: 0 selector: matchLabels: + {{- include "eoapi.selectorLabels" . | nindent 6 }} + app.kubernetes.io/component: raster app: {{ .Release.Name }}-raster template: metadata: labels: + {{- include "eoapi.selectorLabels" . | nindent 8 }} + app.kubernetes.io/component: raster app: {{ .Release.Name }}-raster {{- with .Values.raster.settings.labels }} {{- toYaml . | nindent 8 }} diff --git a/charts/eoapi/templates/services/stac/deployment.yaml b/charts/eoapi/templates/services/stac/deployment.yaml index 273655f3..e9a7cf54 100644 --- a/charts/eoapi/templates/services/stac/deployment.yaml +++ b/charts/eoapi/templates/services/stac/deployment.yaml @@ -3,6 +3,8 @@ apiVersion: apps/v1 kind: Deployment metadata: labels: + {{- include "eoapi.labels" . | nindent 4 }} + app.kubernetes.io/component: stac app: {{ .Release.Name }}-stac gitsha: {{ .Values.gitSha }} name: {{ .Release.Name }}-stac @@ -22,10 +24,14 @@ spec: maxUnavailable: 0 selector: matchLabels: + {{- include "eoapi.selectorLabels" . | nindent 6 }} + app.kubernetes.io/component: stac app: {{ .Release.Name }}-stac template: metadata: labels: + {{- include "eoapi.selectorLabels" . | nindent 8 }} + app.kubernetes.io/component: stac app: {{ .Release.Name }}-stac {{- with .Values.stac.settings.labels }} {{- toYaml . | nindent 8 }} diff --git a/charts/eoapi/templates/services/vector/deployment.yaml b/charts/eoapi/templates/services/vector/deployment.yaml index ac484cce..bb11a2ff 100644 --- a/charts/eoapi/templates/services/vector/deployment.yaml +++ b/charts/eoapi/templates/services/vector/deployment.yaml @@ -3,6 +3,8 @@ apiVersion: apps/v1 kind: Deployment metadata: labels: + {{- include "eoapi.labels" . | nindent 4 }} + app.kubernetes.io/component: vector app: {{ .Release.Name }}-vector gitsha: {{ .Values.gitSha }} name: {{ .Release.Name }}-vector @@ -22,10 +24,14 @@ spec: maxUnavailable: 0 selector: matchLabels: + {{- include "eoapi.selectorLabels" . | nindent 6 }} + app.kubernetes.io/component: vector app: {{ .Release.Name }}-vector template: metadata: labels: + {{- include "eoapi.selectorLabels" . | nindent 8 }} + app.kubernetes.io/component: vector app: {{ .Release.Name }}-vector {{- with .Values.vector.settings.labels }} {{- toYaml . | nindent 8 }} diff --git a/charts/eoapi/templates/sink-binding.yaml b/charts/eoapi/templates/sink-binding.yaml index 1d048982..ab7c7a7c 100644 --- a/charts/eoapi/templates/sink-binding.yaml +++ b/charts/eoapi/templates/sink-binding.yaml @@ -16,7 +16,7 @@ metadata: app.kubernetes.io/component: sink-binding annotations: helm.sh/hook: "post-install,post-upgrade" - helm.sh/hook-weight: "15" + helm.sh/hook-weight: "30" helm.sh/hook-delete-policy: "before-hook-creation" spec: subject: diff --git a/scripts/test.sh b/scripts/test.sh index 065663b3..d09ad0f5 100755 --- a/scripts/test.sh +++ b/scripts/test.sh @@ -175,9 +175,21 @@ run_integration_tests() { -v --tb=short || log_warn "Notification tests failed" fi - # Wait for pods to be ready + # Wait for pods to be ready - try standard labels first, fallback to legacy if kubectl get pods -n "$NAMESPACE" >/dev/null 2>&1; then - wait_for_pods "$NAMESPACE" "app.kubernetes.io/name=stac" "300s" || log_warn "STAC pods not ready" + if ! wait_for_pods "$NAMESPACE" "app.kubernetes.io/name=eoapi,app.kubernetes.io/component=stac" "300s" 2>/dev/null; then + wait_for_pods "$NAMESPACE" "app=${RELEASE_NAME}-stac" "300s" || log_warn "STAC pods not ready" + fi + fi + + # Wait for Knative services to be ready if they exist + if kubectl get ksvc -n "$NAMESPACE" >/dev/null 2>&1; then + if kubectl get ksvc eoapi-cloudevents-sink -n "$NAMESPACE" >/dev/null 2>&1; then + log_info "Waiting for Knative cloudevents sink to be ready..." + if ! kubectl wait --for=condition=Ready ksvc/eoapi-cloudevents-sink -n "$NAMESPACE" --timeout=120s 2>/dev/null; then + log_warn "Knative cloudevents sink not ready - this may cause SinkBinding warnings" + fi + fi fi log_info "✅ Integration tests completed"