Skip to content
This repository was archived by the owner on Jul 13, 2026. It is now read-only.

Commit c00651b

Browse files
committed
Introduce KUTTL tests
Depends-On: openshift/release#71750
1 parent 42361b6 commit c00651b

8 files changed

Lines changed: 315 additions & 0 deletions

File tree

Makefile

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,12 +247,14 @@ KUSTOMIZE ?= $(LOCALBIN)/kustomize
247247
CONTROLLER_GEN ?= $(LOCALBIN)/controller-gen
248248
ENVTEST ?= $(LOCALBIN)/setup-envtest
249249
GOLANGCI_LINT = $(LOCALBIN)/golangci-lint
250+
KUTTL ?= $(LOCALBIN)/kubectl-kuttl
250251

251252
## Tool Versions
252253
KUSTOMIZE_VERSION ?= v5.4.2
253254
CONTROLLER_TOOLS_VERSION ?= v0.16.5
254255
ENVTEST_VERSION ?= release-0.18
255256
GOLANGCI_LINT_VERSION ?= v2.6.0
257+
KUTTL_VERSION ?= 0.17.0
256258

257259
.PHONY: kustomize
258260
kustomize: $(KUSTOMIZE) ## Download kustomize locally if necessary.
@@ -274,6 +276,16 @@ golangci-lint: $(GOLANGCI_LINT) ## Download golangci-lint locally if necessary.
274276
$(GOLANGCI_LINT): $(LOCALBIN)
275277
curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/HEAD/install.sh | sh -s -- -b $(LOCALBIN) $(GOLANGCI_LINT_VERSION)
276278

279+
.PHONY: kuttl
280+
kuttl: $(KUTTL) ## Download kubectl-kuttl locally if necessary.
281+
$(KUTTL): $(LOCALBIN)
282+
test -s $(LOCALBIN)/kubectl-kuttl || curl -L -o $(LOCALBIN)/kubectl-kuttl https://github.com/kudobuilder/kuttl/releases/download/v$(KUTTL_VERSION)/kubectl-kuttl_$(KUTTL_VERSION)_linux_x86_64
283+
chmod +x $(LOCALBIN)/kubectl-kuttl
284+
285+
.PHONY: kuttl-test
286+
kuttl-test: kuttl ## Run kuttl tests
287+
$(LOCALBIN)/kubectl-kuttl test --config kuttl-test.yaml tests/kuttl/tests $(KUTTL_ARGS)
288+
277289
# go-install-tool will 'go install' any package with custom target and name of binary, if it doesn't exist
278290
# $1 - target path with name of binary
279291
# $2 - package url which can be installed

kuttl-test.yaml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
apiVersion: kuttl.dev/v1beta1
2+
kind: TestSuite
3+
reportFormat: xml
4+
reportName: kuttl-report-openstack-lightspeed
5+
reportGranularity: test
6+
namespace: openshift-lightspeed
7+
timeout: 600
8+
parallel: 1
9+
suppress:
10+
- events # Remove spammy event logs
11+
skipDelete: true # Prevent KUTTL from deleting namespace after tests
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
apiVersion: v1
2+
kind: Namespace
3+
metadata:
4+
name: openshift-lightspeed
5+
---
6+
apiVersion: operators.coreos.com/v1
7+
kind: OperatorGroup
8+
metadata:
9+
name: openshift-lightspeed-operatorgroup
10+
namespace: openshift-lightspeed
11+
spec:
12+
targetNamespaces:
13+
- openshift-lightspeed
14+
---
15+
apiVersion: operators.coreos.com/v1alpha1
16+
kind: CatalogSource
17+
metadata:
18+
name: lightspeed-catalog
19+
namespace: openshift-lightspeed
20+
spec:
21+
displayName: Lightspeed Operator Catalog
22+
publisher: Red Hat
23+
sourceType: grpc
24+
image: quay.io/openstack-lightspeed/operator-catalog:v0.1.0-9bb8439
25+
updateStrategy:
26+
registryPoll:
27+
interval: 10m
28+
---
29+
apiVersion: operators.coreos.com/v1alpha1
30+
kind: Subscription
31+
metadata:
32+
name: openstack-lightspeed-operator
33+
namespace: openshift-lightspeed
34+
spec:
35+
channel: alpha
36+
name: openstack-lightspeed-operator
37+
source: lightspeed-catalog
38+
sourceNamespace: openshift-lightspeed
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
---
2+
apiVersion: v1
3+
kind: Pod
4+
metadata:
5+
name: mock-llm-api-server-pod
6+
labels:
7+
app: mock-llm-api-server-pod
8+
spec:
9+
containers:
10+
- name: mock-llm-api-server
11+
image: registry.redhat.io/ubi8/python-311:latest
12+
ports:
13+
- containerPort: 8000
14+
volumeMounts:
15+
- name: app-code
16+
mountPath: /app
17+
workingDir: /app
18+
command:
19+
- sh
20+
- -c
21+
- |
22+
pip install "fastapi[standard]" && \
23+
uvicorn app:app --host 0.0.0.0 --port 8000
24+
volumes:
25+
- name: app-code
26+
configMap:
27+
name: mock-llm-code
28+
---
29+
apiVersion: v1
30+
kind: Service
31+
metadata:
32+
name: mock-llm-api-server-pod
33+
spec:
34+
selector:
35+
app: mock-llm-api-server-pod
36+
ports:
37+
- protocol: TCP
38+
port: 8000
39+
targetPort: 8000
40+
---
41+
apiVersion: v1
42+
kind: ConfigMap
43+
metadata:
44+
name: mock-llm-code
45+
data:
46+
app.py: |
47+
from fastapi import FastAPI, Request
48+
from fastapi.responses import JSONResponse
49+
50+
app = FastAPI()
51+
@app.post("/v1/chat/completions")
52+
async def completions_post(request: Request):
53+
try:
54+
body = await request.json()
55+
except Exception:
56+
body = {}
57+
58+
# Always return a valid OpenAI-like response, handle missing/None body gracefully
59+
model = body.get("model", "gpt-3.5-turbo") if isinstance(body, dict) else "gpt-3.5-turbo"
60+
61+
# The OpenAI API expects 'messages' (for chat) or 'prompt' (for completions), but for mock, we will accept either
62+
response = {
63+
"id": "cmpl-123",
64+
"object": "chat.completion",
65+
"created": 1234567890,
66+
"model": model,
67+
"choices": [
68+
{
69+
"index": 0,
70+
"message": {
71+
"role": "assistant",
72+
"content": "Hello, this is a dummy chat completion."
73+
},
74+
"finish_reason": "stop"
75+
}
76+
],
77+
"usage": {
78+
"prompt_tokens": 5,
79+
"completion_tokens": 7,
80+
"total_tokens": 12
81+
}
82+
}
83+
return JSONResponse(content=response)
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
---
2+
apiVersion: v1
3+
kind: Secret
4+
type: Opaque
5+
metadata:
6+
name: openstack-lightspeed-apitoken
7+
namespace: openshift-lightspeed
8+
stringData:
9+
apitoken: secret
10+
---
11+
apiVersion: v1
12+
kind: ConfigMap
13+
type: Opaque
14+
metadata:
15+
name: openstack-lightspeed-cert
16+
namespace: openshift-lightspeed
17+
data:
18+
# Note that this is a public cert for testing purposes:)
19+
cert: |
20+
-----BEGIN CERTIFICATE-----
21+
MIIEMDCCAxigAwIBAgIJANqb7HHzA7AZMA0GCSqGSIb3DQEBCwUAMIGkMQswCQYD
22+
VQQGEwJQQTEPMA0GA1UECAwGUGFuYW1hMRQwEgYDVQQHDAtQYW5hbWEgQ2l0eTEk
23+
MCIGA1UECgwbVHJ1c3RDb3IgU3lzdGVtcyBTLiBkZSBSLkwuMScwJQYDVQQLDB5U
24+
cnVzdENvciBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxHzAdBgNVBAMMFlRydXN0Q29y
25+
IFJvb3RDZXJ0IENBLTEwHhcNMTYwMjA0MTIzMjE2WhcNMjkxMjMxMTcyMzE2WjCB
26+
pDELMAkGA1UEBhMCUEExDzANBgNVBAgMBlBhbmFtYTEUMBIGA1UEBwwLUGFuYW1h
27+
IENpdHkxJDAiBgNVBAoMG1RydXN0Q29yIFN5c3RlbXMgUy4gZGUgUi5MLjEnMCUG
28+
A1UECwweVHJ1c3RDb3IgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MR8wHQYDVQQDDBZU
29+
cnVzdENvciBSb290Q2VydCBDQS0xMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
30+
CgKCAQEAv463leLCJhJrMxnHQFgKq1mqjQCj/IDHUHuO1CAmujIS2CNUSSUQIpid
31+
RtLByZ5OGy4sDjjzGiVoHKZaBeYei0i/mJZ0PmnK6bV4pQa81QBeCQryJ3pS/C3V
32+
seq0iWEk8xoT26nPUu0MJLq5nux+AHT6k61sKZKuUbS701e/s/OojZz0JEsq1pme
33+
9J7+wH5COucLlVPat2gOkEz7cD+PSiyU8ybdY2mplNgQTsVHCJCZGxdNuWxu72CV
34+
EY4hgLW9oHPY0LJ3xEXqWib7ZnZ2+AYfYW0PVcWDtxBWcgYHpfOxGgMFZA6dWorW
35+
hnAbJN7+KIor0Gqw/Hqi3LJ5DotlDwIDAQABo2MwYTAdBgNVHQ4EFgQU7mtJPHo/
36+
DeOxCbeKyKsZn3MzUOcwHwYDVR0jBBgwFoAU7mtJPHo/DeOxCbeKyKsZn3MzUOcw
37+
DwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYwDQYJKoZIhvcNAQELBQAD
38+
ggEBACUY1JGPE+6PHh0RU9otRCkZoB5rMZ5NDp6tPVxBb5UrJKF5mDo4Nvu7Zp5I
39+
/5CQ7z3UuJu0h3U/IJvOcs+hVcFNZKIZBqEHMwwLKeXx6quj7LUKdJDHfXLy11yf
40+
ke+Ri7fc7Waiz45mO7yfOgLgJ90WmMCV1Aqk5IGadZQ1nJBfiDcGrVmVCrDRZ9MZ
41+
yonnMlo2HD6CqFqTvsbQZJG2z9m2GM/bftJlo6bEjhcxwft+dtvTheNYsnd6djts
42+
L1Ac59v2Z3kf9YKVmgenFK+P3CghZwnS1k1aHBkcjndcw5QkPTJrS37UeJSDvjdN
43+
zl/HHk484IkzlQsPpTLWPFp5LBk=
44+
-----END CERTIFICATE-----
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
---
2+
apiVersion: v1
3+
kind: Namespace
4+
metadata:
5+
name: openshift-lightspeed
6+
---
7+
apiVersion: operators.coreos.com/v1
8+
kind: OperatorGroup
9+
metadata:
10+
name: openshift-lightspeed-operatorgroup
11+
namespace: openshift-lightspeed
12+
---
13+
apiVersion: operators.coreos.com/v1alpha1
14+
kind: CatalogSource
15+
metadata:
16+
name: lightspeed-catalog
17+
namespace: openshift-lightspeed
18+
---
19+
apiVersion: operators.coreos.com/v1alpha1
20+
kind: Subscription
21+
metadata:
22+
name: openstack-lightspeed-operator
23+
namespace: openshift-lightspeed
24+
---
25+
apiVersion: v1
26+
kind: Secret
27+
metadata:
28+
name: openstack-lightspeed-apitoken
29+
namespace: openshift-lightspeed
30+
---
31+
apiVersion: v1
32+
kind: ConfigMap
33+
metadata:
34+
name: openstack-lightspeed-cert
35+
namespace: openshift-lightspeed
36+
---
37+
apiVersion: v1
38+
kind: Pod
39+
metadata:
40+
name: mock-llm-api-server-pod
41+
namespace: openshift-lightspeed
42+
status:
43+
phase: Running
44+
---
45+
---
46+
apiVersion: v1
47+
kind: Pod
48+
metadata:
49+
namespace: openshift-lightspeed
50+
labels:
51+
name: openstack-lightspeed-operator-controller
52+
# name can be a partial match, so omit for robustness
53+
status:
54+
phase: Running
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
---
2+
apiVersion: lightspeed.openstack.org/v1beta1
3+
kind: OpenStackLightspeed
4+
metadata:
5+
name: openstack-lightspeed
6+
namespace: openshift-lightspeed
7+
spec:
8+
llmEndpoint: http://mock-llm-api-server-pod:8000/v1
9+
llmEndpointType: openai
10+
llmCredentials: openstack-lightspeed-apitoken
11+
modelName: ibm-granite/granite-3.1-8b-instruct
12+
tlsCACertBundle: openstack-lightspeed-cert
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
---
2+
apiVersion: v1
3+
items:
4+
- apiVersion: ols.openshift.io/v1alpha1
5+
kind: OLSConfig
6+
metadata:
7+
creationTimestamp: "2025-11-26T17:10:00Z"
8+
finalizers:
9+
- openstack.org/openstacklightspeed
10+
generation: 1
11+
labels:
12+
openstack-lightspeed/ping: "5172198679171520754"
13+
openstack.org/lightspeed-owner-id: d83d9c08-869b-44a4-acf1-82d593508542
14+
name: cluster
15+
resourceVersion: "43573"
16+
uid: 8f2fd4ce-27af-437a-bbe8-16c7ac202de9
17+
spec:
18+
llm:
19+
providers:
20+
- credentialsSecretRef:
21+
name: openstack-lightspeed-apitoken
22+
models:
23+
- name: ibm-granite/granite-3.1-8b-instruct
24+
parameters:
25+
maxTokensForResponse: 2048
26+
name: openstack-lightspeed-provider
27+
type: openai
28+
url: http://mock-llm-api-server-pod:8000/v1/completions
29+
ols:
30+
additionalCAConfigMapRef:
31+
name: openstack-lightspeed-cert
32+
byokRAGOnly: true
33+
defaultModel: ibm-granite/granite-3.1-8b-instruct
34+
defaultProvider: openstack-lightspeed-provider
35+
logLevel: INFO
36+
rag:
37+
- image: quay.io/openstack-lightspeed/rag-content:os-docs-2024.2
38+
indexID: os-docs-2024.2
39+
indexPath: /rag/vector_db/os_product_docs
40+
status:
41+
conditions:
42+
- lastTransitionTime: "2025-11-26T17:10:21Z"
43+
message: All components are successfully deployed
44+
reason: Reconciling
45+
status: "True"
46+
type: ConsolePluginReady
47+
- lastTransitionTime: "2025-11-26T17:10:21Z"
48+
message: All components are successfully deployed
49+
reason: Reconciling
50+
status: "True"
51+
type: CacheReady
52+
- lastTransitionTime: "2025-11-26T17:10:02Z"
53+
message: 'Failed: failed to reconcile OLSConfigMap: failed to generate OLS configmap:
54+
failed to generate OLS config file, additional CA error: failed to validate
55+
additional CA certificate cert: failed to decode PEM certificate'
56+
reason: Reconciling
57+
status: "False"
58+
type: ApiReady
59+
kind: List
60+
metadata:
61+
resourceVersion: ""

0 commit comments

Comments
 (0)