Skip to content

Commit 4d3e153

Browse files
luis5tbclaude
andcommitted
feat: add optional marketplace handler to OpenShift Helm chart
Add support for deploying the marketplace handler alongside the agent on OpenShift clusters running inside Google Cloud. The handler receives Pub/Sub events, approves entitlements via the Procurement API, and handles DCR from Gemini Enterprise. All handler resources are conditional on handler.enabled (default false), so existing deployments are unaffected. When enabled, a GCP service account key is mounted for ADC and the agent gains DATABASE_URL for order validation. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent a1a4fcd commit 4d3e153

File tree

10 files changed

+450
-35
lines changed

10 files changed

+450
-35
lines changed

deploy/openshift/README.md

Lines changed: 224 additions & 33 deletions
Large diffs are not rendered by default.

deploy/openshift/templates/_helpers.tpl

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,3 +70,18 @@ Redis service name
7070
{{- define "lightspeed-agent.redisServiceName" -}}
7171
{{- include "lightspeed-agent.fullname" . }}-redis
7272
{{- end }}
73+
74+
{{/*
75+
Selector labels for the marketplace handler
76+
*/}}
77+
{{- define "lightspeed-agent.handlerSelectorLabels" -}}
78+
app.kubernetes.io/name: {{ include "lightspeed-agent.fullname" . }}-handler
79+
app.kubernetes.io/component: handler
80+
{{- end }}
81+
82+
{{/*
83+
Handler service name
84+
*/}}
85+
{{- define "lightspeed-agent.handlerServiceName" -}}
86+
{{- include "lightspeed-agent.fullname" . }}-handler
87+
{{- end }}

deploy/openshift/templates/agent-deployment.yaml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,13 @@ spec:
5757
name: {{ include "lightspeed-agent.fullname" . }}-secrets
5858
key: SESSION_DATABASE_URL
5959
optional: true
60+
{{- if .Values.handler.enabled }}
61+
- name: DATABASE_URL
62+
valueFrom:
63+
secretKeyRef:
64+
name: {{ include "lightspeed-agent.fullname" . }}-secrets
65+
key: DATABASE_URL
66+
{{- end }}
6067
resources:
6168
{{- toYaml .Values.agent.resources | nindent 12 }}
6269
startupProbe:

deploy/openshift/templates/configmap.yaml

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,15 @@ data:
4242
RATE_LIMIT_REQUESTS_PER_MINUTE: {{ .Values.rateLimit.requestsPerMinute | quote }}
4343
RATE_LIMIT_REQUESTS_PER_HOUR: {{ .Values.rateLimit.requestsPerHour | quote }}
4444

45-
# Google Cloud Service Control (disabled for OpenShift)
46-
SERVICE_CONTROL_ENABLED: "false"
45+
# Google Cloud Service Control
46+
SERVICE_CONTROL_ENABLED: {{ .Values.serviceControl.enabled | quote }}
47+
48+
# Marketplace Handler
49+
HANDLER_HOST: {{ .Values.handler.host | quote }}
50+
HANDLER_PORT: {{ .Values.handler.port | quote }}
51+
DCR_ENABLED: {{ .Values.handler.dcr.enabled | quote }}
52+
DCR_CLIENT_NAME_PREFIX: {{ .Values.handler.dcr.clientNamePrefix | quote }}
53+
SERVICE_CONTROL_SERVICE_NAME: {{ .Values.handler.serviceControlServiceName | quote }}
4754

4855
# Authentication
4956
SKIP_JWT_VALIDATION: {{ .Values.auth.skipJwtValidation | quote }}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{{- if .Values.handler.enabled }}
2+
apiVersion: v1
3+
kind: Secret
4+
metadata:
5+
name: {{ include "lightspeed-agent.fullname" . }}-gcp-sa-key
6+
labels:
7+
{{- include "lightspeed-agent.labels" . | nindent 4 }}
8+
type: Opaque
9+
data:
10+
sa-key.json: {{ .Values.secrets.gcpServiceAccountKey }}
11+
{{- end }}
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
{{- if .Values.handler.enabled }}
2+
apiVersion: apps/v1
3+
kind: Deployment
4+
metadata:
5+
name: {{ include "lightspeed-agent.handlerServiceName" . }}
6+
labels:
7+
{{- include "lightspeed-agent.labels" . | nindent 4 }}
8+
app.kubernetes.io/component: handler
9+
spec:
10+
replicas: {{ .Values.handler.replicas }}
11+
selector:
12+
matchLabels:
13+
{{- include "lightspeed-agent.handlerSelectorLabels" . | nindent 6 }}
14+
template:
15+
metadata:
16+
labels:
17+
{{- include "lightspeed-agent.handlerSelectorLabels" . | nindent 8 }}
18+
spec:
19+
containers:
20+
- name: marketplace-handler
21+
image: {{ printf "%s:%s" .Values.handler.image.repository .Values.handler.image.tag }}
22+
imagePullPolicy: {{ .Values.handler.image.pullPolicy }}
23+
ports:
24+
- containerPort: {{ .Values.handler.port }}
25+
protocol: TCP
26+
name: http
27+
envFrom:
28+
- configMapRef:
29+
name: {{ include "lightspeed-agent.fullname" . }}-config
30+
env:
31+
- name: GOOGLE_APPLICATION_CREDENTIALS
32+
value: /var/run/secrets/gcp/sa-key.json
33+
- name: GOOGLE_API_KEY
34+
valueFrom:
35+
secretKeyRef:
36+
name: {{ include "lightspeed-agent.fullname" . }}-secrets
37+
key: GOOGLE_API_KEY
38+
- name: GOOGLE_CLOUD_PROJECT
39+
valueFrom:
40+
secretKeyRef:
41+
name: {{ include "lightspeed-agent.fullname" . }}-secrets
42+
key: GOOGLE_CLOUD_PROJECT
43+
optional: true
44+
- name: RED_HAT_SSO_CLIENT_ID
45+
valueFrom:
46+
secretKeyRef:
47+
name: {{ include "lightspeed-agent.fullname" . }}-secrets
48+
key: RED_HAT_SSO_CLIENT_ID
49+
- name: RED_HAT_SSO_CLIENT_SECRET
50+
valueFrom:
51+
secretKeyRef:
52+
name: {{ include "lightspeed-agent.fullname" . }}-secrets
53+
key: RED_HAT_SSO_CLIENT_SECRET
54+
- name: DATABASE_URL
55+
valueFrom:
56+
secretKeyRef:
57+
name: {{ include "lightspeed-agent.fullname" . }}-secrets
58+
key: DATABASE_URL
59+
- name: DCR_INITIAL_ACCESS_TOKEN
60+
valueFrom:
61+
secretKeyRef:
62+
name: {{ include "lightspeed-agent.fullname" . }}-secrets
63+
key: DCR_INITIAL_ACCESS_TOKEN
64+
- name: DCR_ENCRYPTION_KEY
65+
valueFrom:
66+
secretKeyRef:
67+
name: {{ include "lightspeed-agent.fullname" . }}-secrets
68+
key: DCR_ENCRYPTION_KEY
69+
volumeMounts:
70+
- name: gcp-sa-key
71+
mountPath: /var/run/secrets/gcp
72+
readOnly: true
73+
resources:
74+
{{- toYaml .Values.handler.resources | nindent 12 }}
75+
startupProbe:
76+
httpGet:
77+
path: /health
78+
port: {{ .Values.handler.port }}
79+
initialDelaySeconds: 5
80+
periodSeconds: 10
81+
failureThreshold: 6
82+
readinessProbe:
83+
httpGet:
84+
path: /ready
85+
port: {{ .Values.handler.port }}
86+
periodSeconds: 10
87+
failureThreshold: 3
88+
livenessProbe:
89+
httpGet:
90+
path: /health
91+
port: {{ .Values.handler.port }}
92+
periodSeconds: 30
93+
failureThreshold: 3
94+
volumes:
95+
- name: gcp-sa-key
96+
secret:
97+
secretName: {{ include "lightspeed-agent.fullname" . }}-gcp-sa-key
98+
{{- end }}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
{{- if and .Values.handler.enabled .Values.handler.route.enabled }}
2+
apiVersion: route.openshift.io/v1
3+
kind: Route
4+
metadata:
5+
name: {{ include "lightspeed-agent.handlerServiceName" . }}
6+
labels:
7+
{{- include "lightspeed-agent.labels" . | nindent 4 }}
8+
app.kubernetes.io/component: handler
9+
spec:
10+
to:
11+
kind: Service
12+
name: {{ include "lightspeed-agent.handlerServiceName" . }}
13+
weight: 100
14+
port:
15+
targetPort: http
16+
tls:
17+
termination: {{ .Values.route.tls.termination }}
18+
insecureEdgeTerminationPolicy: {{ .Values.route.tls.insecureEdgeTerminationPolicy }}
19+
wildcardPolicy: None
20+
{{- end }}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
{{- if .Values.handler.enabled }}
2+
apiVersion: v1
3+
kind: Service
4+
metadata:
5+
name: {{ include "lightspeed-agent.handlerServiceName" . }}
6+
labels:
7+
{{- include "lightspeed-agent.labels" . | nindent 4 }}
8+
app.kubernetes.io/component: handler
9+
spec:
10+
selector:
11+
{{- include "lightspeed-agent.handlerSelectorLabels" . | nindent 4 }}
12+
ports:
13+
- port: {{ .Values.handler.port }}
14+
targetPort: {{ .Values.handler.port }}
15+
protocol: TCP
16+
name: http
17+
type: ClusterIP
18+
{{- end }}

deploy/openshift/templates/secret.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,7 @@ stringData:
1313
RED_HAT_SSO_CLIENT_SECRET: {{ .Values.secrets.redHatSsoClientSecret | quote }}
1414
SESSION_DB_PASSWORD: {{ .Values.secrets.sessionDbPassword | quote }}
1515
SESSION_DATABASE_URL: {{ .Values.secrets.sessionDatabaseUrl | quote }}
16+
DATABASE_URL: {{ .Values.secrets.databaseUrl | quote }}
17+
DCR_INITIAL_ACCESS_TOKEN: {{ .Values.secrets.dcrInitialAccessToken | quote }}
18+
DCR_ENCRYPTION_KEY: {{ .Values.secrets.dcrEncryptionKey | quote }}
1619
{{- end }}

deploy/openshift/values.yaml

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,41 @@ redis:
139139
cpu: 500m
140140
memory: 256Mi
141141

142+
# ---------------------------------------------------------------------------
143+
# Marketplace Handler (optional — enable for GCP deployments with
144+
# Google Cloud Marketplace integration)
145+
# ---------------------------------------------------------------------------
146+
handler:
147+
enabled: false
148+
image:
149+
repository: quay.io/ecosystem-appeng/lightspeed-agent-handler
150+
tag: latest
151+
pullPolicy: Always
152+
replicas: 1
153+
host: "0.0.0.0"
154+
port: 8001
155+
# Marketplace product identifier (managed service name from Producer Portal).
156+
# Required for entitlement approval and product-level Pub/Sub event filtering.
157+
serviceControlServiceName: ""
158+
dcr:
159+
enabled: true
160+
clientNamePrefix: "gemini-order-"
161+
route:
162+
enabled: true
163+
resources:
164+
requests:
165+
cpu: 250m
166+
memory: 256Mi
167+
limits:
168+
cpu: "1"
169+
memory: 512Mi
170+
171+
# ---------------------------------------------------------------------------
172+
# Google Cloud Service Control (usage reporting)
173+
# ---------------------------------------------------------------------------
174+
serviceControl:
175+
enabled: false
176+
142177
# ---------------------------------------------------------------------------
143178
# Route
144179
# ---------------------------------------------------------------------------
@@ -164,3 +199,13 @@ secrets:
164199
sessionDbPassword: "sessions"
165200
# Full connection URL (contains credentials, stored in the Secret)
166201
sessionDatabaseUrl: "postgresql+asyncpg://sessions:sessions@lightspeed-agent-postgresql:5432/agent_sessions"
202+
# --- Handler secrets (only needed when handler.enabled=true) ---
203+
# Marketplace database URL (shared with agent for order validation).
204+
# Points to the same PostgreSQL instance by default.
205+
databaseUrl: "postgresql+asyncpg://sessions:sessions@lightspeed-agent-postgresql:5432/agent_sessions"
206+
# Keycloak Initial Access Token for Dynamic Client Registration
207+
dcrInitialAccessToken: ""
208+
# Fernet key for encrypting stored client secrets
209+
dcrEncryptionKey: ""
210+
# Base64-encoded GCP service account key JSON (for ADC outside Cloud Run)
211+
gcpServiceAccountKey: ""

0 commit comments

Comments
 (0)