Skip to content

Commit 6d81e8b

Browse files
committed
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
1 parent 878a10d commit 6d81e8b

File tree

14 files changed

+488
-93
lines changed

14 files changed

+488
-93
lines changed

.github/workflows/helm-tests.yml

Lines changed: 65 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@ jobs:
2525
- name: Run Helm unit tests
2626
run: make tests
2727

28-
integration:
29-
name: Integration Tests (K3s)
28+
k3s-integration-tests:
29+
name: K3s Integration Tests
3030
if: github.event.pull_request.head.repo.full_name == github.repository
3131
permissions:
3232
contents: 'read'
@@ -47,106 +47,85 @@ jobs:
4747
- name: Set release name
4848
run: echo "RELEASE_NAME=eoapi-$(echo "${{ github.sha }}" | cut -c1-8)" >> "$GITHUB_ENV"
4949

50-
- name: Deploy eoAPI
51-
id: deploy
52-
continue-on-error: true
50+
- name: Wait for K3s to be fully ready
5351
run: |
54-
echo "=== Starting eoAPI deployment ==="
55-
export RELEASE_NAME="$RELEASE_NAME"
56-
export PGO_VERSION="${{ env.PGO_VERSION }}"
57-
export GITHUB_SHA="${{ github.sha }}"
58-
./scripts/deploy.sh --ci
52+
echo "=== Waiting for K3s to be fully ready ==="
5953
60-
- name: Check deployment status
61-
id: check
62-
if: steps.deploy.outcome == 'success'
63-
run: |
64-
echo "=== Checking deployment status ==="
65-
export RELEASE_NAME="$RELEASE_NAME"
66-
./scripts/test.sh check-deployment --debug
54+
# Wait for core K3s components to be ready
55+
echo "Waiting for kube-system pods to be ready..."
56+
kubectl wait --for=condition=Ready pod -l k8s-app=kube-dns -n kube-system --timeout=300s
57+
kubectl wait --for=condition=Ready pod -l app.kubernetes.io/name=traefik -n kube-system --timeout=300s
6758
68-
- name: Debug pgstac jobs if deployment failed
69-
if: steps.deploy.outcome == 'failure'
70-
continue-on-error: true
71-
run: |
72-
echo "=== Debugging pgstac job failures ==="
73-
74-
# Check pgstac-migrate job
75-
echo "===== pgstac-migrate Job Status ====="
76-
kubectl get jobs -l app.kubernetes.io/name=pgstac-migrate -o wide || echo "No pgstac-migrate jobs found"
77-
78-
MIGRATE_PODS=$(kubectl get pods -l app.kubernetes.io/name=pgstac-migrate -o jsonpath='{.items[*].metadata.name}' 2>/dev/null)
79-
if [ -n "$MIGRATE_PODS" ]; then
80-
for POD in $MIGRATE_PODS; do
81-
echo "--- Logs from migrate pod $POD ---"
82-
kubectl logs "$POD" --tail=100 || true
83-
echo "--- Description of migrate pod $POD ---"
84-
kubectl describe pod "$POD"
85-
done
86-
fi
87-
88-
# Check pgstac-load-samples job
89-
echo "===== pgstac-load-samples Job Status ====="
90-
kubectl get jobs -l app.kubernetes.io/name=pgstac-load-samples -o wide || echo "No pgstac-load-samples jobs found"
91-
92-
SAMPLES_PODS=$(kubectl get pods -l app.kubernetes.io/name=pgstac-load-samples -o jsonpath='{.items[*].metadata.name}' 2>/dev/null)
93-
if [ -n "$SAMPLES_PODS" ]; then
94-
for POD in $SAMPLES_PODS; do
95-
echo "--- Logs from samples pod $POD ---"
96-
kubectl logs "$POD" --tail=100 || true
97-
echo "--- Description of samples pod $POD ---"
98-
kubectl describe pod "$POD"
99-
done
100-
fi
59+
# Wait for API server to be fully responsive
60+
echo "Checking API server responsiveness..."
61+
kubectl get nodes
62+
kubectl get pods --all-namespaces
10163
102-
# Check database status
103-
echo "===== Database Pod Status ====="
104-
kubectl get pods -l postgres-operator.crunchydata.com/cluster -o wide
105-
kubectl get postgrescluster -o wide
64+
# Give K3s a moment to initialize all CRDs
65+
echo "Waiting for K3s initialization to complete..."
66+
sleep 10
10667
107-
# Check ConfigMaps
108-
echo "===== Relevant ConfigMaps ====="
109-
kubectl get configmaps | grep -E "initdb|pgstac" || echo "No relevant configmaps found"
68+
echo "✅ K3s is ready"
11069
111-
# Check for any related events
112-
echo "===== Related Kubernetes Events ====="
113-
kubectl get events | grep -E "pgstac|initdb" || echo "No relevant events found"
11470
115-
# Check notification system status
116-
echo "===== Notification System Status ====="
117-
kubectl get deployments -l app.kubernetes.io/name=eoapi-notifier -o wide || echo "No eoapi-notifier deployment found"
118-
kubectl get ksvc -l app.kubernetes.io/component=cloudevents-sink -o wide || echo "No Knative CloudEvents sink found"
71+
- name: Wait for Traefik to be ready
72+
run: |
73+
echo "=== Waiting for Traefik to be ready ==="
74+
75+
# Wait for Traefik pods to be ready first
76+
echo "Waiting for Traefik controller to be ready..."
77+
kubectl wait --for=condition=Ready pod -l app.kubernetes.io/name=traefik -n kube-system --timeout=300s
78+
79+
# Wait for essential Traefik CRDs to be available
80+
echo "Checking for Traefik CRDs..."
81+
timeout=300
82+
counter=0
83+
required_crds=("middlewares.traefik.io" "ingressroutes.traefik.io")
84+
85+
for crd in "${required_crds[@]}"; do
86+
echo "Checking for CRD: $crd"
87+
counter=0
88+
while [ $counter -lt $timeout ]; do
89+
if kubectl get crd "$crd" &>/dev/null; then
90+
echo "✅ $crd is available"
91+
break
92+
fi
93+
echo "⏳ Waiting for $crd... ($counter/$timeout)"
94+
sleep 3
95+
counter=$((counter + 3))
96+
done
97+
98+
if [ $counter -ge $timeout ]; then
99+
echo "❌ Timeout waiting for $crd"
100+
echo "Available Traefik CRDs:"
101+
kubectl get crd | grep traefik || echo "No Traefik CRDs found"
102+
echo "All CRDs:"
103+
kubectl get crd
104+
exit 1
105+
fi
106+
done
107+
108+
echo "✅ All required Traefik CRDs are ready"
119109
120-
exit 1
110+
- name: Deploy eoAPI
111+
id: deploy
112+
run: |
113+
echo "=== Starting eoAPI deployment ==="
114+
export RELEASE_NAME="$RELEASE_NAME"
115+
export PGO_VERSION="${{ env.PGO_VERSION }}"
116+
export GITHUB_SHA="${{ github.sha }}"
117+
./scripts/deploy.sh --ci
121118
122119
- name: Run integration tests
123-
if: steps.deploy.outcome == 'success'
124120
run: |
125121
echo "=== Running integration tests ==="
126122
export RELEASE_NAME="$RELEASE_NAME"
127123
./scripts/test.sh integration --debug
128124
129-
- name: Debug deployment status
130-
if: always()
125+
- name: Debug failed deployment
126+
if: failure()
131127
run: |
132-
echo "=== Final Deployment Status ==="
133-
kubectl get pods -o wide
134-
kubectl get jobs -o wide
135-
kubectl get services -o wide
136-
kubectl get ingress
137-
138-
# Check notification system final status
139-
echo "=== Notification System Final Status ==="
140-
kubectl get deployments -l app.kubernetes.io/name=eoapi-notifier -o wide || echo "No eoapi-notifier deployment"
141-
kubectl get pods -l app.kubernetes.io/name=eoapi-notifier -o wide || echo "No eoapi-notifier pods"
142-
kubectl get ksvc -l app.kubernetes.io/component=cloudevents-sink -o wide || echo "No Knative CloudEvents sink"
143-
kubectl get pods -l serving.knative.dev/service -o wide || echo "No Knative CloudEvents sink pods"
144-
145-
# Show notification logs if they exist
146-
echo "=== eoapi-notifier Logs ==="
147-
kubectl logs -l app.kubernetes.io/name=eoapi-notifier --tail=20 || echo "No eoapi-notifier logs"
148-
echo "=== Knative CloudEvents Sink Logs ==="
149-
kubectl logs -l serving.knative.dev/service --tail=20 || echo "No Knative CloudEvents sink logs"
128+
./scripts/debug-deployment.sh
150129
151130
152131
- name: Cleanup

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,5 @@ charts/config.yaml
55
charts/eoapi/charts/*.tgz
66
config_ingress.yaml
77
__pycache__
8+
9+
CLAUDE.md

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
- Added knative in CI to test eoapi-notifier.
11+
1012
## [0.7.12] - 2025-10-17
1113

1214
- Bumped eoapi-notifier dependency version to 0.0.7

charts/eoapi/Chart.yaml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,10 @@ dependencies:
5454
repository: "https://devseed.com/eoapi-k8s/"
5555
condition: postgrescluster.enabled
5656
- name: eoapi-notifier
57-
version: 0.0.7
57+
version: 0.0.8
5858
repository: "oci://ghcr.io/developmentseed/charts"
5959
condition: eoapi-notifier.enabled
60+
- name: knative-operator
61+
version: 1.19.4
62+
repository: https://knative.github.io/operator
63+
condition: knative.enabled
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
{{- $hasCloudEventsOutput := false }}
2+
{{- range (index .Values "eoapi-notifier").outputs }}
3+
{{- if eq .type "cloudevents" }}
4+
{{- $hasCloudEventsOutput = true }}
5+
{{- end }}
6+
{{- end }}
7+
{{- if and (index .Values "eoapi-notifier").enabled .Values.knative.enabled .Values.knative.cloudEventsSink.enabled $hasCloudEventsOutput }}
8+
---
9+
apiVersion: serving.knative.dev/v1
10+
kind: Service
11+
metadata:
12+
name: eoapi-cloudevents-sink
13+
namespace: {{ .Release.Namespace }}
14+
labels:
15+
{{- include "eoapi.labels" . | nindent 4 }}
16+
app.kubernetes.io/component: cloudevents-sink
17+
annotations:
18+
helm.sh/hook: "post-install,post-upgrade"
19+
helm.sh/hook-weight: "10"
20+
helm.sh/hook-delete-policy: "before-hook-creation"
21+
spec:
22+
template:
23+
metadata:
24+
annotations:
25+
autoscaling.knative.dev/minScale: "1"
26+
autoscaling.knative.dev/maxScale: "1"
27+
labels:
28+
{{- include "eoapi.selectorLabels" . | nindent 8 }}
29+
app.kubernetes.io/component: cloudevents-sink
30+
spec:
31+
containers:
32+
- name: cloudevents-sink
33+
image: {{ .Values.knative.cloudEventsSink.image }}
34+
ports:
35+
- containerPort: 8080
36+
env:
37+
- name: TARGET
38+
value: "CloudEvents Sink"
39+
- name: PORT
40+
value: "8080"
41+
- name: LOG_LEVEL
42+
value: "info"
43+
resources:
44+
{{- toYaml .Values.knative.cloudEventsSink.resources | nindent 10 }}
45+
{{- end }}
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
{{- if .Values.knative.enabled }}
2+
apiVersion: batch/v1
3+
kind: Job
4+
metadata:
5+
name: {{ .Release.Name }}-knative-init
6+
namespace: {{ .Release.Namespace }}
7+
labels:
8+
{{- include "eoapi.labels" . | nindent 4 }}
9+
app.kubernetes.io/component: knative-init
10+
annotations:
11+
helm.sh/hook: "post-install,post-upgrade"
12+
helm.sh/hook-weight: "1"
13+
helm.sh/hook-delete-policy: "before-hook-creation,hook-succeeded"
14+
spec:
15+
template:
16+
metadata:
17+
name: {{ .Release.Name }}-knative-init
18+
labels:
19+
{{- include "eoapi.labels" . | nindent 8 }}
20+
app.kubernetes.io/component: knative-init
21+
spec:
22+
restartPolicy: Never
23+
serviceAccountName: {{ include "eoapi.serviceAccountName" . }}
24+
containers:
25+
- name: knative-init
26+
image: bitnami/kubectl:latest
27+
imagePullPolicy: IfNotPresent
28+
command:
29+
- /bin/bash
30+
- -c
31+
- |
32+
set -e
33+
echo "=== Knative Initialization ==="
34+
35+
# Wait for knative-operator to be ready
36+
echo "Waiting for knative-operator..."
37+
kubectl rollout status deployment/knative-operator -n default --timeout={{ .Values.knative.initTimeout | default "600s" }}
38+
39+
# Create namespaces
40+
kubectl create namespace knative-serving --dry-run=client -o yaml | kubectl apply -f -
41+
kubectl create namespace knative-eventing --dry-run=client -o yaml | kubectl apply -f -
42+
43+
# Create KnativeServing
44+
cat <<EOF | kubectl apply -f -
45+
apiVersion: operator.knative.dev/v1beta1
46+
kind: KnativeServing
47+
metadata:
48+
name: knative-serving
49+
namespace: knative-serving
50+
spec:
51+
version: {{ .Values.knative.version | quote }}
52+
EOF
53+
54+
if [ $? -eq 0 ]; then
55+
echo "✅ KnativeServing created successfully"
56+
else
57+
echo "❌ Failed to create KnativeServing. Checking operator status..."
58+
kubectl get pods -n default -l name=knative-operator
59+
exit 1
60+
fi
61+
62+
# Create KnativeEventing
63+
cat <<EOF | kubectl apply -f -
64+
apiVersion: operator.knative.dev/v1beta1
65+
kind: KnativeEventing
66+
metadata:
67+
name: knative-eventing
68+
namespace: knative-eventing
69+
spec:
70+
version: {{ .Values.knative.version | quote }}
71+
EOF
72+
73+
if [ $? -eq 0 ]; then
74+
echo "✅ KnativeEventing created successfully"
75+
else
76+
echo "❌ Failed to create KnativeEventing. Checking operator status..."
77+
kubectl get pods -n default -l name=knative-operator
78+
exit 1
79+
fi
80+
81+
echo "✅ Knative CRs created. Operator will install CRDs."
82+
83+
resources:
84+
requests:
85+
cpu: 25m
86+
memory: 32Mi
87+
limits:
88+
cpu: 50m
89+
memory: 64Mi
90+
backoffLimit: 3
91+
activeDeadlineSeconds: 600
92+
{{- end }}

charts/eoapi/templates/services/rbac.yaml

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,44 @@ rules:
1010
resources: ["jobs"]
1111
verbs: ["get", "list", "watch"]
1212
---
13+
{{- if .Values.knative.enabled }}
14+
apiVersion: rbac.authorization.k8s.io/v1
15+
kind: ClusterRole
16+
metadata:
17+
name: eoapi-cluster-role-{{ $.Release.Name }}
18+
labels:
19+
app: eoapi-{{ $.Release.Name }}
20+
rules:
21+
- apiGroups: ["apiextensions.k8s.io"]
22+
resources: ["customresourcedefinitions"]
23+
verbs: ["get", "list"]
24+
- apiGroups: [""]
25+
resources: ["pods", "namespaces"]
26+
verbs: ["get", "list", "create"]
27+
- apiGroups: ["apps"]
28+
resources: ["deployments"]
29+
verbs: ["get", "list"]
30+
- apiGroups: ["operator.knative.dev"]
31+
resources: ["knativeservings", "knativeeventings"]
32+
verbs: ["get", "list", "create"]
33+
---
34+
apiVersion: rbac.authorization.k8s.io/v1
35+
kind: ClusterRoleBinding
36+
metadata:
37+
name: eoapi-cluster-rolebinding-{{ $.Release.Name }}
38+
labels:
39+
app: eoapi-{{ $.Release.Name }}
40+
subjects:
41+
- kind: ServiceAccount
42+
name: {{ include "eoapi.serviceAccountName" . }}
43+
namespace: {{ $.Release.Namespace }}
44+
roleRef:
45+
kind: ClusterRole
46+
name: eoapi-cluster-role-{{ $.Release.Name }}
47+
apiGroup: rbac.authorization.k8s.io
48+
---
49+
{{- end }}
50+
---
1351
apiVersion: rbac.authorization.k8s.io/v1
1452
kind: RoleBinding
1553
metadata:

0 commit comments

Comments
 (0)