@@ -17,31 +17,110 @@ limitations under the License.
1717package v1beta1
1818
1919import (
20+ condition "github.com/openstack-k8s-operators/lib-common/modules/common/condition"
21+ "github.com/openstack-k8s-operators/lib-common/modules/common/util"
22+ corev1 "k8s.io/api/core/v1"
2023 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2124)
2225
23- // EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN!
24- // NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized.
26+ const (
27+ // OpenStackAssistantContainerImage is the fall-back container image for OpenStackAssistant
28+ OpenStackAssistantContainerImage = "quay.io/dprince/goose:oc-fedora"
29+ )
30+
31+ // ProviderType defines the AI agent provider
32+ // +kubebuilder:validation:Enum=goose
33+ type ProviderType string
34+
35+ const (
36+ // ProviderGoose is the Goose AI agent provider
37+ ProviderGoose ProviderType = "goose"
38+ )
39+
40+ // LightspeedStackSpec defines connectivity to the Lightspeed Stack AI backend
41+ type LightspeedStackSpec struct {
42+ // ProviderSecret is the name of a Secret containing the lightspeed
43+ // provider config JSON (custom_providers/lightspeed.json content).
44+ // Must contain key "lightspeed.json".
45+ // +kubebuilder:validation:Required
46+ ProviderSecret string `json:"providerSecret"`
47+
48+ // CaBundleSecretName is the name of a Secret containing CA certs
49+ // to trust for TLS connections to the lightspeed-stack endpoint.
50+ // The Secret must contain a key "ca-bundle.crt" with PEM-encoded certs.
51+ // +kubebuilder:validation:Optional
52+ CaBundleSecretName string `json:"caBundleSecretName,omitempty"`
53+ }
54+
55+ // GooseConfig defines Goose-specific provider configuration
56+ type GooseConfig struct {
57+ // Recipes is a ConfigMap name containing Goose recipe YAML files.
58+ // Each key in the ConfigMap becomes a recipe file registered as a
59+ // Goose slash command (e.g., /cluster-health).
60+ // +kubebuilder:validation:Optional
61+ Recipes * string `json:"recipes,omitempty"`
62+
63+ // Hints is a ConfigMap name containing Goose hints/context.
64+ // The ConfigMap must have a key "hints" with the content that
65+ // will be written to ~/.goosehints in the pod.
66+ // +kubebuilder:validation:Optional
67+ Hints * string `json:"hints,omitempty"`
68+ }
2569
26- // OpenStackAssistantSpec defines the desired state of OpenStackAssistant.
70+ // OpenStackAssistantSpec defines the desired state of OpenStackAssistant
2771type OpenStackAssistantSpec struct {
28- // INSERT ADDITIONAL SPEC FIELDS - desired state of cluster
29- // Important: Run "make" to regenerate code after modifying this file
72+ // ContainerImage for the assistant container.
73+ // +kubebuilder:validation:Required
74+ ContainerImage string `json:"containerImage"`
75+
76+ // Provider is the AI agent provider type. Currently only "goose" is supported.
77+ // +kubebuilder:validation:Optional
78+ // +kubebuilder:default=goose
79+ Provider ProviderType `json:"provider,omitempty"`
80+
81+ // LightspeedStack configuration for the AI backend.
82+ // +kubebuilder:validation:Required
83+ LightspeedStack LightspeedStackSpec `json:"lightspeedStack"`
84+
85+ // Goose contains Goose-specific provider configuration.
86+ // Only applicable when provider is "goose".
87+ // +kubebuilder:validation:Optional
88+ Goose * GooseConfig `json:"goose,omitempty"`
89+
90+ // NodeSelector to target subset of worker nodes for pod scheduling.
91+ // +kubebuilder:validation:Optional
92+ NodeSelector * map [string ]string `json:"nodeSelector,omitempty"`
3093
31- // Foo is an example field of OpenStackAssistant. Edit openstackassistant_types.go to remove/update
32- Foo string `json:"foo,omitempty"`
94+ // Env is a list of additional environment variables for the container.
95+ // +kubebuilder:validation:Optional
96+ // +listType=map
97+ // +listMapKey=name
98+ Env []corev1.EnvVar `json:"env,omitempty"`
3399}
34100
35- // OpenStackAssistantStatus defines the observed state of OpenStackAssistant.
101+ // OpenStackAssistantStatus defines the observed state of OpenStackAssistant
36102type OpenStackAssistantStatus struct {
37- // INSERT ADDITIONAL STATUS FIELD - define observed state of cluster
38- // Important: Run "make" to regenerate code after modifying this file
103+ // PodName is the name of the running assistant pod
104+ PodName string `json:"podName,omitempty"`
105+
106+ // Conditions tracks the state of each sub-resource
107+ Conditions condition.Conditions `json:"conditions,omitempty" optional:"true"`
108+
109+ // ObservedGeneration - the most recent generation observed
110+ ObservedGeneration int64 `json:"observedGeneration,omitempty"`
111+
112+ // Hash tracks input hashes to detect changes
113+ Hash map [string ]string `json:"hash,omitempty"`
39114}
40115
41116// +kubebuilder:object:root=true
42117// +kubebuilder:subresource:status
118+ // +operator-sdk:csv:customresourcedefinitions:displayName="OpenStack Assistant"
119+ // +kubebuilder:resource:shortName=osassistant;osassistants
120+ // +kubebuilder:printcolumn:name="Status",type="string",JSONPath=".status.conditions[0].status",description="Status"
121+ // +kubebuilder:printcolumn:name="Message",type="string",JSONPath=".status.conditions[0].message",description="Message"
43122
44- // OpenStackAssistant is the Schema for the openstackassistants API.
123+ // OpenStackAssistant is the Schema for the openstackassistants API
45124type OpenStackAssistant struct {
46125 metav1.TypeMeta `json:",inline"`
47126 metav1.ObjectMeta `json:"metadata,omitempty"`
@@ -52,7 +131,7 @@ type OpenStackAssistant struct {
52131
53132// +kubebuilder:object:root=true
54133
55- // OpenStackAssistantList contains a list of OpenStackAssistant.
134+ // OpenStackAssistantList contains a list of OpenStackAssistant
56135type OpenStackAssistantList struct {
57136 metav1.TypeMeta `json:",inline"`
58137 metav1.ListMeta `json:"metadata,omitempty"`
@@ -62,3 +141,51 @@ type OpenStackAssistantList struct {
62141func init () {
63142 SchemeBuilder .Register (& OpenStackAssistant {}, & OpenStackAssistantList {})
64143}
144+
145+ // IsReady - returns true if OpenStackAssistant is reconciled successfully
146+ func (instance OpenStackAssistant ) IsReady () bool {
147+ return instance .Status .Conditions .IsTrue (OpenStackAssistantReadyCondition )
148+ }
149+
150+ // RbacConditionsSet - set the conditions for the rbac object
151+ func (instance OpenStackAssistant ) RbacConditionsSet (c * condition.Condition ) {
152+ instance .Status .Conditions .Set (c )
153+ }
154+
155+ // RbacNamespace - return the namespace
156+ func (instance OpenStackAssistant ) RbacNamespace () string {
157+ return instance .Namespace
158+ }
159+
160+ // RbacResourceName - return the name to be used for rbac objects (serviceaccount, role, rolebinding)
161+ func (instance OpenStackAssistant ) RbacResourceName () string {
162+ return "openstackassistant-" + instance .Name
163+ }
164+
165+ // OpenStackAssistantDefaults holds defaults for the assistant
166+ type OpenStackAssistantDefaults struct {
167+ ContainerImageURL string
168+ }
169+
170+ var openStackAssistantDefaults OpenStackAssistantDefaults
171+
172+ // SetupOpenStackAssistantDefaults - initialize OpenStackAssistant spec defaults
173+ func SetupOpenStackAssistantDefaults (defaults OpenStackAssistantDefaults ) {
174+ openStackAssistantDefaults = defaults
175+ }
176+
177+ // SetupDefaults - initializes any CRD field defaults based on environment variables
178+ func SetupDefaults () {
179+ openStackAssistantDefaults := OpenStackAssistantDefaults {
180+ ContainerImageURL : util .GetEnvVar ("RELATED_IMAGE_OPENSTACK_ASSISTANT_IMAGE_URL_DEFAULT" , OpenStackAssistantContainerImage ),
181+ }
182+
183+ SetupOpenStackAssistantDefaults (openStackAssistantDefaults )
184+ }
185+
186+ // Default implements webhook.Defaulter
187+ func (r * OpenStackAssistant ) Default () {
188+ if r .Spec .ContainerImage == "" {
189+ r .Spec .ContainerImage = openStackAssistantDefaults .ContainerImageURL
190+ }
191+ }
0 commit comments