Skip to content

Commit d983efb

Browse files
committed
Generic Provider Config for LCore supported providers.
1 parent 53f416b commit d983efb

17 files changed

Lines changed: 1907 additions & 295 deletions

api/v1alpha1/olsconfig_types.go

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121
corev1 "k8s.io/api/core/v1"
2222
resource "k8s.io/apimachinery/pkg/api/resource"
2323
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
24+
runtime "k8s.io/apimachinery/pkg/runtime"
2425
)
2526

2627
// OLSConfigSpec defines the desired state of OLSConfig
@@ -36,6 +37,7 @@ type OLSConfigSpec struct {
3637
// +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="OLS Data Collector Settings"
3738
OLSDataCollectorConfig OLSDataCollectorSpec `json:"olsDataCollector,omitempty"`
3839
// MCP Server settings
40+
// +kubebuilder:validation:MaxItems=20
3941
// +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="MCP Server Settings"
4042
MCPServers []MCPServerConfig `json:"mcpServers,omitempty"`
4143
// Feature Gates holds list of features to be enabled explicitly, otherwise they are disabled by default.
@@ -160,6 +162,7 @@ const (
160162
// LLMSpec defines the desired state of the large language model (LLM).
161163
type LLMSpec struct {
162164
// +kubebuilder:validation:Required
165+
// +kubebuilder:validation:MaxItems=10
163166
// +required
164167
// +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Providers"
165168
Providers []ProviderSpec `json:"providers"`
@@ -451,6 +454,11 @@ type ModelSpec struct {
451454
// ProviderSpec defines the desired state of LLM provider.
452455
// +kubebuilder:validation:XValidation:message="'deploymentName' must be specified for 'azure_openai' provider",rule="self.type != \"azure_openai\" || self.deploymentName != \"\""
453456
// +kubebuilder:validation:XValidation:message="'projectID' must be specified for 'watsonx' provider",rule="self.type != \"watsonx\" || self.projectID != \"\""
457+
// +kubebuilder:validation:XValidation:message="'providerType' and 'config' must be used together in llamaStackGeneric mode",rule="!has(self.providerType) || has(self.config)"
458+
// +kubebuilder:validation:XValidation:message="'config' requires 'providerType' to be set",rule="!has(self.config) || has(self.providerType)"
459+
// +kubebuilder:validation:XValidation:message="Llama Stack Generic mode (providerType set) requires type='llamaStackGeneric'",rule="!has(self.providerType) || self.type == \"llamaStackGeneric\""
460+
// +kubebuilder:validation:XValidation:message="Llama Stack Generic mode cannot use legacy provider-specific fields",rule="self.type != \"llamaStackGeneric\" || (!has(self.deploymentName) && !has(self.projectID))"
461+
// +kubebuilder:validation:XValidation:message="credentialKey must not be empty or whitespace",rule="!has(self.credentialKey) || !self.credentialKey.matches('^[ \\t\\n\\r]*$')"
454462
type ProviderSpec struct {
455463
// Provider name
456464
// +kubebuilder:validation:Required
@@ -468,13 +476,14 @@ type ProviderSpec struct {
468476
CredentialsSecretRef corev1.LocalObjectReference `json:"credentialsSecretRef"`
469477
// List of models from the provider
470478
// +kubebuilder:validation:Required
479+
// +kubebuilder:validation:MaxItems=50
471480
// +required
472481
// +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Models"
473482
Models []ModelSpec `json:"models"`
474483
// Provider type
475484
// +kubebuilder:validation:Required
476485
// +required
477-
// +kubebuilder:validation:Enum=azure_openai;bam;openai;watsonx;rhoai_vllm;rhelai_vllm;fake_provider
486+
// +kubebuilder:validation:Enum=azure_openai;bam;openai;watsonx;rhoai_vllm;rhelai_vllm;fake_provider;llamaStackGeneric
478487
// +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Provider Type"
479488
Type string `json:"type"`
480489
// Deployment name for Azure OpenAI provider
@@ -493,6 +502,25 @@ type ProviderSpec struct {
493502
// +kubebuilder:validation:Optional
494503
// +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="TLS Security Profile",xDescriptors={"urn:alm:descriptor:com.tectonic.ui:advanced"}
495504
TLSSecurityProfile *configv1.TLSSecurityProfile `json:"tlsSecurityProfile,omitempty"`
505+
// Llama Stack Generic provider type for provider configuration (e.g., "remote::openai", "inline::sentence-transformers")
506+
// When set, this provider uses Llama Stack Generic mode instead of legacy mode.
507+
// Must follow pattern: (inline|remote)::<provider-name>
508+
// +kubebuilder:validation:Pattern=`^(inline|remote)::[a-z0-9][a-z0-9_-]*$`
509+
// +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Llama Stack Provider Type"
510+
ProviderType string `json:"providerType,omitempty"`
511+
// Arbitrary configuration for the provider (Llama Stack Generic mode only)
512+
// This map is passed directly to Llama Stack provider configuration.
513+
// Credentials are automatically injected as environment variable substitutions.
514+
// Example: {"url": "https://...", "custom_field": "value"}
515+
// +kubebuilder:pruning:PreserveUnknownFields
516+
// +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Llama Stack Provider Config"
517+
Config *runtime.RawExtension `json:"config,omitempty"`
518+
// Secret key name for provider credentials (defaults to "apitoken" if not set)
519+
// Specifies which key in credentialsSecretRef contains the API token.
520+
// The operator creates an environment variable named {PROVIDER_NAME}_API_KEY.
521+
// +kubebuilder:validation:Optional
522+
// +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Credential Key Name"
523+
CredentialKey string `json:"credentialKey,omitempty"`
496524
}
497525

498526
// UserDataCollectionSpec defines how we collect user data.
@@ -687,6 +715,7 @@ type MCPServerConfig struct {
687715
// Headers to send to the MCP server
688716
// Each header can reference a secret or use a special source (kubernetes token, client token)
689717
// +optional
718+
// +kubebuilder:validation:MaxItems=20
690719
// +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Headers"
691720
Headers []MCPHeader `json:"headers,omitempty"`
692721
}

api/v1alpha1/zz_generated.deepcopy.go

Lines changed: 6 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

bundle/manifests/lightspeed-operator.clusterserviceversion.yaml

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,9 @@ spec:
8181
- description: The name of the secret object that stores API provider credentials
8282
displayName: Credential Secret
8383
path: llm.providers[0].credentialsSecretRef
84-
- description: 'Feature Gates holds list of features to be enabled explicitly, otherwise they are disabled by default. possible values: MCPServer, ToolFiltering'
84+
- description: |-
85+
Feature Gates holds list of features to be enabled explicitly, otherwise they are disabled by default.
86+
possible values: MCPServer, ToolFiltering
8587
displayName: Feature Gates
8688
path: featureGates
8789
- displayName: LLM Settings
@@ -91,6 +93,19 @@ spec:
9193
- description: API Version for Azure OpenAI provider
9294
displayName: Azure OpenAI API Version
9395
path: llm.providers[0].apiVersion
96+
- description: |-
97+
Arbitrary configuration for the provider (Llama Stack Generic mode only)
98+
This map is passed directly to Llama Stack provider configuration.
99+
Credentials are automatically injected as environment variable substitutions.
100+
Example: {"url": "https://...", "custom_field": "value"}
101+
displayName: Llama Stack Provider Config
102+
path: llm.providers[0].config
103+
- description: |-
104+
Secret key name for provider credentials (defaults to "apitoken" if not set)
105+
Specifies which key in credentialsSecretRef contains the API token.
106+
The operator creates an environment variable named {PROVIDER_NAME}_API_KEY.
107+
displayName: Credential Key Name
108+
path: llm.providers[0].credentialKey
94109
- description: Azure OpenAI deployment name
95110
displayName: Azure OpenAI deployment name
96111
path: llm.providers[0].deploymentName
@@ -118,6 +133,12 @@ spec:
118133
- description: Watsonx Project ID
119134
displayName: Watsonx Project ID
120135
path: llm.providers[0].projectID
136+
- description: |-
137+
Llama Stack Generic provider type for provider configuration (e.g., "remote::openai", "inline::sentence-transformers")
138+
When set, this provider uses Llama Stack Generic mode instead of legacy mode.
139+
Must follow pattern: (inline|remote)::<provider-name>
140+
displayName: Llama Stack Provider Type
141+
path: llm.providers[0].providerType
121142
- description: TLS Security Profile used by connection to provider
122143
displayName: TLS Security Profile
123144
path: llm.providers[0].tlsSecurityProfile

bundle/manifests/ols.openshift.io_olsconfigs.yaml

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,20 @@ spec:
6161
apiVersion:
6262
description: API Version for Azure OpenAI provider
6363
type: string
64+
config:
65+
description: |-
66+
Arbitrary configuration for the provider (Llama Stack Generic mode only)
67+
This map is passed directly to Llama Stack provider configuration.
68+
Credentials are automatically injected as environment variable substitutions.
69+
Example: {"url": "https://...", "custom_field": "value"}
70+
type: object
71+
x-kubernetes-preserve-unknown-fields: true
72+
credentialKey:
73+
description: |-
74+
Secret key name for provider credentials (defaults to "apitoken" if not set)
75+
Specifies which key in credentialsSecretRef contains the API token.
76+
The operator creates an environment variable named {PROVIDER_NAME}_API_KEY.
77+
type: string
6478
credentialsSecretRef:
6579
description: The name of the secret object that stores API
6680
provider credentials
@@ -111,13 +125,21 @@ spec:
111125
required:
112126
- name
113127
type: object
128+
maxItems: 50
114129
type: array
115130
name:
116131
description: Provider name
117132
type: string
118133
projectID:
119134
description: Watsonx Project ID
120135
type: string
136+
providerType:
137+
description: |-
138+
Llama Stack Generic provider type for provider configuration (e.g., "remote::openai", "inline::sentence-transformers")
139+
When set, this provider uses Llama Stack Generic mode instead of legacy mode.
140+
Must follow pattern: (inline|remote)::<provider-name>
141+
pattern: ^(inline|remote)::[a-z0-9][a-z0-9_-]*$
142+
type: string
121143
tlsSecurityProfile:
122144
description: TLS Security Profile used by connection to
123145
provider
@@ -259,6 +281,7 @@ spec:
259281
- rhoai_vllm
260282
- rhelai_vllm
261283
- fake_provider
284+
- llamaStackGeneric
262285
type: string
263286
url:
264287
description: Provider API URL
@@ -278,6 +301,22 @@ spec:
278301
- message: '''projectID'' must be specified for ''watsonx''
279302
provider'
280303
rule: self.type != "watsonx" || self.projectID != ""
304+
- message: '''providerType'' and ''config'' must be used together
305+
in llamaStackGeneric mode'
306+
rule: '!has(self.providerType) || has(self.config)'
307+
- message: '''config'' requires ''providerType'' to be set'
308+
rule: '!has(self.config) || has(self.providerType)'
309+
- message: Llama Stack Generic mode (providerType set) requires
310+
type='llamaStackGeneric'
311+
rule: '!has(self.providerType) || self.type == "llamaStackGeneric"'
312+
- message: Llama Stack Generic mode cannot use legacy provider-specific
313+
fields
314+
rule: self.type != "llamaStackGeneric" || (!has(self.deploymentName)
315+
&& !has(self.projectID))
316+
- message: credentialKey must not be empty or whitespace
317+
rule: '!has(self.credentialKey) || !self.credentialKey.matches(''^[
318+
\t\n\r]*$'')'
319+
maxItems: 10
281320
type: array
282321
required:
283322
- providers
@@ -347,6 +386,7 @@ spec:
347386
- name
348387
- valueFrom
349388
type: object
389+
maxItems: 20
350390
type: array
351391
name:
352392
description: Name of the MCP server
@@ -364,6 +404,7 @@ spec:
364404
- name
365405
- url
366406
type: object
407+
maxItems: 20
367408
type: array
368409
ols:
369410
description: OLSSpec defines the desired state of OLS deployment.

bundle/metadata/annotations.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ annotations:
66
operators.operatorframework.io.bundle.package.v1: lightspeed-operator
77
operators.operatorframework.io.bundle.channels.v1: alpha
88
operators.operatorframework.io.bundle.channel.default.v1: alpha
9-
operators.operatorframework.io.metrics.builder: operator-sdk-v1.33.0
9+
operators.operatorframework.io.metrics.builder: operator-sdk-v1.36.1
1010
operators.operatorframework.io.metrics.mediatype.v1: metrics+v1
1111
operators.operatorframework.io.metrics.project_layout: go.kubebuilder.io/v4
1212
# Annotations for testing.

config/crd/bases/ols.openshift.io_olsconfigs.yaml

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,20 @@ spec:
6161
apiVersion:
6262
description: API Version for Azure OpenAI provider
6363
type: string
64+
config:
65+
description: |-
66+
Arbitrary configuration for the provider (Llama Stack Generic mode only)
67+
This map is passed directly to Llama Stack provider configuration.
68+
Credentials are automatically injected as environment variable substitutions.
69+
Example: {"url": "https://...", "custom_field": "value"}
70+
type: object
71+
x-kubernetes-preserve-unknown-fields: true
72+
credentialKey:
73+
description: |-
74+
Secret key name for provider credentials (defaults to "apitoken" if not set)
75+
Specifies which key in credentialsSecretRef contains the API token.
76+
The operator creates an environment variable named {PROVIDER_NAME}_API_KEY.
77+
type: string
6478
credentialsSecretRef:
6579
description: The name of the secret object that stores API
6680
provider credentials
@@ -111,13 +125,21 @@ spec:
111125
required:
112126
- name
113127
type: object
128+
maxItems: 50
114129
type: array
115130
name:
116131
description: Provider name
117132
type: string
118133
projectID:
119134
description: Watsonx Project ID
120135
type: string
136+
providerType:
137+
description: |-
138+
Llama Stack Generic provider type for provider configuration (e.g., "remote::openai", "inline::sentence-transformers")
139+
When set, this provider uses Llama Stack Generic mode instead of legacy mode.
140+
Must follow pattern: (inline|remote)::<provider-name>
141+
pattern: ^(inline|remote)::[a-z0-9][a-z0-9_-]*$
142+
type: string
121143
tlsSecurityProfile:
122144
description: TLS Security Profile used by connection to
123145
provider
@@ -259,6 +281,7 @@ spec:
259281
- rhoai_vllm
260282
- rhelai_vllm
261283
- fake_provider
284+
- llamaStackGeneric
262285
type: string
263286
url:
264287
description: Provider API URL
@@ -278,6 +301,22 @@ spec:
278301
- message: '''projectID'' must be specified for ''watsonx''
279302
provider'
280303
rule: self.type != "watsonx" || self.projectID != ""
304+
- message: '''providerType'' and ''config'' must be used together
305+
in llamaStackGeneric mode'
306+
rule: '!has(self.providerType) || has(self.config)'
307+
- message: '''config'' requires ''providerType'' to be set'
308+
rule: '!has(self.config) || has(self.providerType)'
309+
- message: Llama Stack Generic mode (providerType set) requires
310+
type='llamaStackGeneric'
311+
rule: '!has(self.providerType) || self.type == "llamaStackGeneric"'
312+
- message: Llama Stack Generic mode cannot use legacy provider-specific
313+
fields
314+
rule: self.type != "llamaStackGeneric" || (!has(self.deploymentName)
315+
&& !has(self.projectID))
316+
- message: credentialKey must not be empty or whitespace
317+
rule: '!has(self.credentialKey) || !self.credentialKey.matches(''^[
318+
\t\n\r]*$'')'
319+
maxItems: 10
281320
type: array
282321
required:
283322
- providers
@@ -347,6 +386,7 @@ spec:
347386
- name
348387
- valueFrom
349388
type: object
389+
maxItems: 20
350390
type: array
351391
name:
352392
description: Name of the MCP server
@@ -364,6 +404,7 @@ spec:
364404
- name
365405
- url
366406
type: object
407+
maxItems: 20
367408
type: array
368409
ols:
369410
description: OLSSpec defines the desired state of OLS deployment.

0 commit comments

Comments
 (0)