Skip to content

Commit 8362b19

Browse files
committed
[OSPRH-16305] Introduce OpenStackLightspeed
Introduce the OpenStackLightspeed custom resource that manages the deployment of Lightspeed-related functionalities. As of now, we expect the OLS operator to be present in the cluster. Otherwise, enabling of OpenStackLightspeed will fail. The Lightspeed functionalities can be enabled through the OpenStackLightspeed as follows: spec: llmEndpoint: <URL of the LLM> llmEndpointType: <endpoint type> llmCredentials: <secret containing token> modelName: <model name> tlsCACertBundle: <config map containg cert> Only one OpenStackLightspeed CR can configure OpenStack Lightspeed at a single time. If the user tries to manage the Lightspeed functionalities through two or more OpenStackLightspeed instances, the user will be warned, and the changes from the newest OpenStackLightspeed instance will be ignored.
1 parent 1483c08 commit 8362b19

25 files changed

+1628
-1
lines changed

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ help: ## Display this help.
137137
manifests: controller-gen ## Generate WebhookConfiguration, ClusterRole and CustomResourceDefinition objects.
138138
mkdir -p config/operator/rbac && \
139139
$(CONTROLLER_GEN) crd$(CRDDESC_OVERRIDE) output:crd:artifacts:config=config/crd/bases webhook paths="./..." && \
140-
$(CONTROLLER_GEN) rbac:roleName=manager-role paths="{./apis/client/...,./apis/core/...,./apis/dataplane/...,./controllers/client/...,./controllers/core/...,./controllers/dataplane/...,./pkg/...}" output:dir=config/rbac && \
140+
$(CONTROLLER_GEN) rbac:roleName=manager-role paths="{./apis/lightspeed/...,./apis/client/...,./apis/core/...,./apis/dataplane/...,./controllers/lightspeed/...,./controllers/client/...,./controllers/core/...,./controllers/dataplane/...,./pkg/...}" output:dir=config/rbac && \
141141
$(CONTROLLER_GEN) rbac:roleName=operator-role paths="./controllers/operator/..." paths="./apis/operator/..." output:dir=config/operator/rbac && \
142142
rm -f apis/bases/* && cp -a config/crd/bases apis/
143143

PROJECT

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,4 +86,13 @@ resources:
8686
kind: OpenStack
8787
path: github.com/openstack-k8s-operators/openstack-operator/apis/operator/v1beta1
8888
version: v1beta1
89+
- api:
90+
crdVersion: v1
91+
namespaced: true
92+
controller: true
93+
domain: openstack.org
94+
group: lightspeed
95+
kind: OpenStackLightspeed
96+
path: github.com/openstack-k8s-operators/openstack-operator/apis/lightspeed/v1beta1
97+
version: v1beta1
8998
version: "3"
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
---
2+
apiVersion: apiextensions.k8s.io/v1
3+
kind: CustomResourceDefinition
4+
metadata:
5+
annotations:
6+
controller-gen.kubebuilder.io/version: v0.14.0
7+
name: openstacklightspeeds.lightspeed.openstack.org
8+
spec:
9+
group: lightspeed.openstack.org
10+
names:
11+
kind: OpenStackLightspeed
12+
listKind: OpenStackLightspeedList
13+
plural: openstacklightspeeds
14+
singular: openstacklightspeed
15+
scope: Namespaced
16+
versions:
17+
- additionalPrinterColumns:
18+
- description: Status
19+
jsonPath: .status.conditions[0].status
20+
name: Status
21+
type: string
22+
- description: Message
23+
jsonPath: .status.conditions[0].message
24+
name: Message
25+
type: string
26+
name: v1beta1
27+
schema:
28+
openAPIV3Schema:
29+
properties:
30+
apiVersion:
31+
type: string
32+
kind:
33+
type: string
34+
metadata:
35+
type: object
36+
spec:
37+
properties:
38+
llmCredentials:
39+
type: string
40+
llmEndpoint:
41+
type: string
42+
llmEndpointType:
43+
enum:
44+
- azure_openai
45+
- bam
46+
- openai
47+
- watsonx
48+
- rhoai_vllm
49+
- rhelai_vllm
50+
- fake_provider
51+
type: string
52+
modelName:
53+
type: string
54+
ragImage:
55+
type: string
56+
tlsCACertBundle:
57+
type: string
58+
required:
59+
- llmCredentials
60+
- llmEndpoint
61+
- llmEndpointType
62+
- modelName
63+
type: object
64+
status:
65+
properties:
66+
conditions:
67+
items:
68+
properties:
69+
lastTransitionTime:
70+
format: date-time
71+
type: string
72+
message:
73+
type: string
74+
reason:
75+
type: string
76+
severity:
77+
type: string
78+
status:
79+
type: string
80+
type:
81+
type: string
82+
required:
83+
- lastTransitionTime
84+
- status
85+
- type
86+
type: object
87+
type: array
88+
observedGeneration:
89+
format: int64
90+
type: integer
91+
type: object
92+
type: object
93+
served: true
94+
storage: true
95+
subresources:
96+
status: {}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/*
2+
Copyright 2025.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package v1beta1
18+
19+
import (
20+
condition "github.com/openstack-k8s-operators/lib-common/modules/common/condition"
21+
)
22+
23+
// OpenStackLightspeed Condition Types used by API objects.
24+
const (
25+
// OpenStackLightspeedReadyCondition Status=True condition which indicates if OpenStackLightspeedReadyCondition
26+
// is configured and operational
27+
OpenStackLightspeedReadyCondition condition.Type = "OpenStackLightspeedReady"
28+
)
29+
30+
// Common Messages used by API objects.
31+
const (
32+
// OpenStackLightspeedReadyInitMessage
33+
OpenStackLightspeedReadyInitMessage = "OpenStack Lightspeed not started"
34+
35+
// OpenStackLightspeedReadyMessage
36+
OpenStackLightspeedReadyMessage = "OpenStack Lightspeed created"
37+
38+
// OpenStackLightspeedWaitingVectorDBMessage
39+
OpenStackLightspeedWaitingVectorDBMessage = "Waiting for OpenStackLightspeed vector DB pod to become ready"
40+
)
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/*
2+
Copyright 2025.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
// Package v1beta1 contains API Schema definitions for the lightspeed v1beta1 API group
18+
// +kubebuilder:object:generate=true
19+
// +groupName=lightspeed.openstack.org
20+
package v1beta1
21+
22+
import (
23+
"k8s.io/apimachinery/pkg/runtime/schema"
24+
"sigs.k8s.io/controller-runtime/pkg/scheme"
25+
)
26+
27+
var (
28+
// GroupVersion is group version used to register these objects
29+
GroupVersion = schema.GroupVersion{Group: "lightspeed.openstack.org", Version: "v1beta1"}
30+
31+
// SchemeBuilder is used to add go types to the GroupVersionKind scheme
32+
SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion}
33+
34+
// AddToScheme adds the types in this group-version to the given scheme.
35+
AddToScheme = SchemeBuilder.AddToScheme
36+
)
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
/*
2+
Copyright 2025.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package v1beta1
18+
19+
import (
20+
"github.com/openstack-k8s-operators/lib-common/modules/common/condition"
21+
"github.com/openstack-k8s-operators/lib-common/modules/common/util"
22+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
23+
)
24+
25+
const (
26+
// Container image fall-back defaults
27+
28+
// OpenStackLightspeedContainerImage is the fall-back container image for OpenStackLightspeed
29+
OpenStackLightspeedContainerImage = "quay.io/openstack-lightspeed/rag-content:os-docs-2024.2"
30+
)
31+
32+
// OpenStackLightspeedSpec defines the desired state of OpenStackLightspeed
33+
type OpenStackLightspeedSpec struct {
34+
OpenStackLightspeedCore `json:",inline"`
35+
36+
// +kubebuilder:validation:Optional
37+
// ContainerImage for the Openstack Lightspeed RAG container (will be set to environmental default if empty)
38+
RAGImage string `json:"ragImage"`
39+
}
40+
41+
// OpenStackLightspeedCore defines the desired state of OpenStackLightspeed
42+
type OpenStackLightspeedCore struct {
43+
// +kubebuilder:validation:Required
44+
// URL pointing to the LLM
45+
LLMEndpoint string `json:"llmEndpoint"`
46+
47+
// +kubebuilder:validation:Required
48+
// +kubebuilder:validation:Enum=azure_openai;bam;openai;watsonx;rhoai_vllm;rhelai_vllm;fake_provider
49+
// +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Provider Type"
50+
// Type of the provider serving the LLM
51+
LLMEndpointType string `json:"llmEndpointType"`
52+
53+
// +kubebuilder:validation:Required
54+
// Name of the model to use at the API endpoint provided in LLMEndpoint
55+
ModelName string `json:"modelName"`
56+
57+
// +kubebuilder:validation:Required
58+
// Secret name containing API token for the LLMEndpoint. The key for the field
59+
// in the secret that holds the token should be "apitoken".
60+
LLMCredentials string `json:"llmCredentials"`
61+
62+
// +kubebuilder:validation:Optional
63+
// Configmap name containing a CA Certificates bundle
64+
TLSCACertBundle string `json:"tlsCACertBundle"`
65+
}
66+
67+
// OpenStackLightspeedStatus defines the observed state of OpenStackLightspeed
68+
type OpenStackLightspeedStatus struct {
69+
// Conditions
70+
Conditions condition.Conditions `json:"conditions,omitempty" optional:"true"`
71+
72+
// ObservedGeneration - the most recent generation observed for this object.
73+
ObservedGeneration int64 `json:"observedGeneration,omitempty"`
74+
}
75+
76+
// +kubebuilder:object:root=true
77+
// +kubebuilder:subresource:status
78+
// +operator-sdk:csv:customresourcedefinitions:displayName="OpenStack Lightspeed"
79+
// +kubebuilder:printcolumn:name="Status",type="string",JSONPath=".status.conditions[0].status",description="Status"
80+
// +kubebuilder:printcolumn:name="Message",type="string",JSONPath=".status.conditions[0].message",description="Message"
81+
82+
// OpenStackLightspeed is the Schema for the openstacklightspeeds API
83+
type OpenStackLightspeed struct {
84+
metav1.TypeMeta `json:",inline"`
85+
metav1.ObjectMeta `json:"metadata,omitempty"`
86+
87+
Spec OpenStackLightspeedSpec `json:"spec,omitempty"`
88+
Status OpenStackLightspeedStatus `json:"status,omitempty"`
89+
}
90+
91+
//+kubebuilder:object:root=true
92+
93+
// OpenStackLightspeedList contains a list of OpenStackLightspeed
94+
type OpenStackLightspeedList struct {
95+
metav1.TypeMeta `json:",inline"`
96+
metav1.ListMeta `json:"metadata,omitempty"`
97+
Items []OpenStackLightspeed `json:"items"`
98+
}
99+
100+
func init() {
101+
SchemeBuilder.Register(&OpenStackLightspeed{}, &OpenStackLightspeedList{})
102+
}
103+
104+
// IsReady - returns true if OpenStackLightspeed is reconciled successfully
105+
func (instance OpenStackLightspeed) IsReady() bool {
106+
return instance.Status.Conditions.IsTrue(OpenStackLightspeedReadyCondition)
107+
}
108+
109+
type OpenStackLightspeedDefaults struct {
110+
RAGImageURL string
111+
}
112+
113+
var OpenStackLightspeedDefaultValues OpenStackLightspeedDefaults
114+
115+
// SetupDefaults - initializes OpenStackLightspeedDefaultValues with default values from env vars
116+
func SetupDefaults() {
117+
// Acquire environmental defaults and initialize OpenStackLightspeed defaults with them
118+
openStackLightspeedDefaults := OpenStackLightspeedDefaults{
119+
RAGImageURL: util.GetEnvVar(
120+
"RELATED_IMAGE_OPENSTACK_LIGHTSPEED_IMAGE_URL_DEFAULT", OpenStackLightspeedContainerImage),
121+
}
122+
123+
OpenStackLightspeedDefaultValues = openStackLightspeedDefaults
124+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/*
2+
Copyright 2025.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package v1beta1
18+
19+
import (
20+
. "github.com/onsi/ginkgo/v2"
21+
. "github.com/onsi/gomega"
22+
"testing"
23+
)
24+
25+
func TestAPIs(t *testing.T) {
26+
RegisterFailHandler(Fail)
27+
RunSpecs(t, "LightSpeed v1beta1 Suite")
28+
}

0 commit comments

Comments
 (0)