diff --git a/assets/src/generated/graphql.ts b/assets/src/generated/graphql.ts index 473d30c56e..519b810318 100644 --- a/assets/src/generated/graphql.ts +++ b/assets/src/generated/graphql.ts @@ -1011,6 +1011,8 @@ export type AnthropicSettings = { __typename?: 'AnthropicSettings'; /** the anthropic model version to use */ model?: Maybe; + /** addditional models to support within the integrated ai proxy */ + proxyModels?: Maybe>>; /** the model to use for tool calls, which are less frequent and require more complex reasoning */ toolModel?: Maybe; }; @@ -1020,6 +1022,8 @@ export type AnthropicSettingsAttributes = { /** the model to use for vector embeddings */ embeddingModel?: InputMaybe; model?: InputMaybe; + /** addditional models to support within the integrated ai proxy */ + proxyModels?: InputMaybe>>; /** the model to use for tool calls, which are less frequent and require more complex reasoning */ toolModel?: InputMaybe; }; @@ -1337,6 +1341,8 @@ export type AzureOpenaiAttributes = { endpoint: Scalars['String']['input']; /** the exact model you wish to use */ model?: InputMaybe; + /** addditional models to support within the integrated ai proxy */ + proxyModels?: InputMaybe>>; /** the model to use for tool calls, which are less frequent and require more complex reasoning */ toolModel?: InputMaybe; }; @@ -1351,6 +1357,8 @@ export type AzureOpenaiSettings = { /** the endpoint of your azure openai version, should look like: https://{endpoint}/openai/deployments/{deployment-id} */ endpoint: Scalars['String']['output']; model?: Maybe; + /** addditional models to support within the integrated ai proxy */ + proxyModels?: Maybe>>; /** the model to use for tool calls, which are less frequent and require more complex reasoning */ toolModel?: Maybe; }; @@ -1402,6 +1410,8 @@ export type BedrockAiAttributes = { embeddingModel?: InputMaybe; /** the bedrock model id to use */ modelId: Scalars['String']['input']; + /** addditional models to support within the integrated ai proxy */ + proxyModels?: InputMaybe>>; /** the aws region the model is hosted in */ region?: InputMaybe; /** the model to use for tool calls, which are less frequent and require more complex reasoning */ @@ -1417,6 +1427,8 @@ export type BedrockAiSettings = { embeddingModel?: Maybe; /** the bedrock model to use */ modelId: Scalars['String']['output']; + /** addditional models to support within the integrated ai proxy */ + proxyModels?: Maybe>>; /** the aws region the model is hosted in */ region?: Maybe; /** the model to use for tool calls, which are less frequent and require more complex reasoning */ @@ -6227,6 +6239,8 @@ export type OllamaAttributes = { /** the model to use for vector embeddings */ embeddingModel?: InputMaybe; model: Scalars['String']['input']; + /** addditional models to support within the integrated ai proxy */ + proxyModels?: InputMaybe>>; /** the model to use for tool calls, which are less frequent and require more complex reasoning */ toolModel?: InputMaybe; url: Scalars['String']['input']; @@ -6251,6 +6265,8 @@ export type OpenaiSettings = { embeddingModel?: Maybe; /** the openai model version to use */ model?: Maybe; + /** addditional models to support within the integrated ai proxy */ + proxyModels?: Maybe>>; /** the model to use for tool calls, which are less frequent and require more complex reasoning */ toolModel?: Maybe; }; @@ -6261,6 +6277,8 @@ export type OpenaiSettingsAttributes = { /** the model to use for vector embeddings */ embeddingModel?: InputMaybe; model?: InputMaybe; + /** addditional models to support within the integrated ai proxy */ + proxyModels?: InputMaybe>>; /** the model to use for tool calls, which are less frequent and require more complex reasoning */ toolModel?: InputMaybe; }; @@ -13529,6 +13547,8 @@ export type VertexAiAttributes = { model?: InputMaybe; /** the gcp project id to use */ project: Scalars['String']['input']; + /** addditional models to support within the integrated ai proxy */ + proxyModels?: InputMaybe>>; /** optional service account json to auth to the GCP vertex apis */ serviceAccountJson?: InputMaybe; /** the model to use for tool calls, which are less frequent and require more complex reasoning */ @@ -13546,6 +13566,8 @@ export type VertexAiSettings = { model?: Maybe; /** the gcp project id to use */ project: Scalars['String']['output']; + /** addditional models to support within the integrated ai proxy */ + proxyModels?: Maybe>>; /** the model to use for tool calls, which are less frequent and require more complex reasoning */ toolModel?: Maybe; }; diff --git a/charts/console-rapid/Chart.yaml b/charts/console-rapid/Chart.yaml index 34f50b0e35..55f0e7529c 100644 --- a/charts/console-rapid/Chart.yaml +++ b/charts/console-rapid/Chart.yaml @@ -2,7 +2,7 @@ apiVersion: v2 name: console-rapid description: rapid channel chart for the plural console (used for testing) appVersion: 0.11.65 -version: 0.3.175 +version: 0.4.0 dependencies: - name: kas version: 0.3.1 diff --git a/charts/console-rapid/charts/controller-0.0.169.tgz b/charts/console-rapid/charts/controller-0.0.169.tgz index dd69ce94c8..ca803b0f34 100644 Binary files a/charts/console-rapid/charts/controller-0.0.169.tgz and b/charts/console-rapid/charts/controller-0.0.169.tgz differ diff --git a/charts/console-rapid/charts/kas-0.3.1.tgz b/charts/console-rapid/charts/kas-0.3.1.tgz index bb0e0c180f..29e26bfdfa 100644 Binary files a/charts/console-rapid/charts/kas-0.3.1.tgz and b/charts/console-rapid/charts/kas-0.3.1.tgz differ diff --git a/charts/console/charts/controller-0.0.169.tgz b/charts/console/charts/controller-0.0.169.tgz index 05c2acadb8..33516b28e8 100644 Binary files a/charts/console/charts/controller-0.0.169.tgz and b/charts/console/charts/controller-0.0.169.tgz differ diff --git a/charts/console/charts/kas-0.3.1.tgz b/charts/console/charts/kas-0.3.1.tgz index 73bd236fa0..ebfe9ad572 100644 Binary files a/charts/console/charts/kas-0.3.1.tgz and b/charts/console/charts/kas-0.3.1.tgz differ diff --git a/charts/controller/crds/deployments.plural.sh_deploymentsettings.yaml b/charts/controller/crds/deployments.plural.sh_deploymentsettings.yaml index 59e8ab5f51..07d553cb71 100644 --- a/charts/controller/crds/deployments.plural.sh_deploymentsettings.yaml +++ b/charts/controller/crds/deployments.plural.sh_deploymentsettings.yaml @@ -95,6 +95,12 @@ spec: model: description: Model is the LLM model name to use. type: string + proxyModels: + description: ProxyModels are additional models to support + within our integrated ai proxy. + items: + type: string + type: array tokenSecretRef: description: |- TokenSecretRef is a reference to the local secret holding the token to access @@ -149,6 +155,12 @@ spec: description: Model - the OpenAi model you wish to use. If not specified, Plural will provide a default. type: string + proxyModels: + description: ProxyModels are additional models to support + within the integrated ai proxy. + items: + type: string + type: array tokenSecretRef: description: |- TokenSecretRef is a reference to the local secret holding the token to access @@ -222,6 +234,12 @@ spec: will use the openai compatible endpoint, so the model id must be supported. type: string + proxyModels: + description: ProxyModels are additional models to support + within the integrated ai proxy. + items: + type: string + type: array region: description: Region is the AWS region the model is hosted in @@ -393,6 +411,12 @@ spec: model: description: Model is the LLM model name to use. type: string + proxyModels: + description: ProxyModels are additional models to support + within our integrated ai proxy. + items: + type: string + type: array tokenSecretRef: description: |- TokenSecretRef is a reference to the local secret holding the token to access @@ -630,6 +654,12 @@ spec: project: description: Project is the GCP project you'll be using type: string + proxyModels: + description: ProxyModels are additional models to support + within the integrated ai proxy. + items: + type: string + type: array serviceAccountJsonSecretRef: description: ServiceAccountJsonSecretRef is a Service Account json file stored w/in a kubernetes secret to use for authentication diff --git a/charts/controller/crds/deployments.plural.sh_globalservices.yaml b/charts/controller/crds/deployments.plural.sh_globalservices.yaml index c6d8ebcf58..4168630acd 100644 --- a/charts/controller/crds/deployments.plural.sh_globalservices.yaml +++ b/charts/controller/crds/deployments.plural.sh_globalservices.yaml @@ -639,6 +639,9 @@ spec: items: properties: helm: + description: Helm is the Helm configuration to use for this + renderer, use if `path` points to a helm chart and you + want to override the default helm configuration. properties: ignoreHooks: description: IgnoreHooks indicates whether to ignore @@ -660,8 +663,10 @@ spec: type: array type: object path: + description: Path is the path to the renderer works under. type: string type: + description: Type is the type of renderer to use. enum: - AUTO - RAW diff --git a/charts/controller/crds/deployments.plural.sh_infrastructurestacks.yaml b/charts/controller/crds/deployments.plural.sh_infrastructurestacks.yaml index d3e5514260..f554f4a901 100644 --- a/charts/controller/crds/deployments.plural.sh_infrastructurestacks.yaml +++ b/charts/controller/crds/deployments.plural.sh_infrastructurestacks.yaml @@ -9955,9 +9955,7 @@ spec: It is useful for projects with external modules or nested folder structures. type: string required: - - clusterRef - git - - repositoryRef - type type: object status: diff --git a/charts/controller/crds/deployments.plural.sh_managednamespaces.yaml b/charts/controller/crds/deployments.plural.sh_managednamespaces.yaml index 6ee370efbc..10ba413996 100644 --- a/charts/controller/crds/deployments.plural.sh_managednamespaces.yaml +++ b/charts/controller/crds/deployments.plural.sh_managednamespaces.yaml @@ -515,6 +515,9 @@ spec: items: properties: helm: + description: Helm is the Helm configuration to use for this + renderer, use if `path` points to a helm chart and you + want to override the default helm configuration. properties: ignoreHooks: description: IgnoreHooks indicates whether to ignore @@ -536,8 +539,10 @@ spec: type: array type: object path: + description: Path is the path to the renderer works under. type: string type: + description: Type is the type of renderer to use. enum: - AUTO - RAW diff --git a/charts/controller/crds/deployments.plural.sh_previewenvironmenttemplates.yaml b/charts/controller/crds/deployments.plural.sh_previewenvironmenttemplates.yaml index 7809ca6775..9cb240fad9 100644 --- a/charts/controller/crds/deployments.plural.sh_previewenvironmenttemplates.yaml +++ b/charts/controller/crds/deployments.plural.sh_previewenvironmenttemplates.yaml @@ -569,6 +569,9 @@ spec: items: properties: helm: + description: Helm is the Helm configuration to use for this + renderer, use if `path` points to a helm chart and you + want to override the default helm configuration. properties: ignoreHooks: description: IgnoreHooks indicates whether to ignore @@ -590,8 +593,10 @@ spec: type: array type: object path: + description: Path is the path to the renderer works under. type: string type: + description: Type is the type of renderer to use. enum: - AUTO - RAW diff --git a/charts/controller/crds/deployments.plural.sh_servicecontexts.yaml b/charts/controller/crds/deployments.plural.sh_servicecontexts.yaml index abdb7663ff..cc58847976 100644 --- a/charts/controller/crds/deployments.plural.sh_servicecontexts.yaml +++ b/charts/controller/crds/deployments.plural.sh_servicecontexts.yaml @@ -50,6 +50,51 @@ spec: spec: description: ServiceContextSpec defines the desired state of the ServiceContext. properties: + configMapRef: + description: |- + ConfigMapRef references a ConfigMap containing configuration data to merge into the Configuration. + The keys and values from the ConfigMap will be merged into the Configuration JSON. + properties: + apiVersion: + description: API version of the referent. + type: string + fieldPath: + description: |- + If referring to a piece of an object instead of an entire object, this string + should contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2]. + For example, if the object reference is to a container within a pod, this would take on a value like: + "spec.containers{name}" (where "name" refers to the name of the container that triggered + the event) or if no container name is specified "spec.containers[2]" (container with + index 2 in this pod). This syntax is chosen only to have some well-defined way of + referencing a part of an object. + type: string + kind: + description: |- + Kind of the referent. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + name: + description: |- + Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + namespace: + description: |- + Namespace of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/ + type: string + resourceVersion: + description: |- + Specific resourceVersion to which this reference is made, if any. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency + type: string + uid: + description: |- + UID of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids + type: string + type: object + x-kubernetes-map-type: atomic configuration: description: |- Configuration is a reusable configuration context that can include any JSON-compatible configuration data @@ -129,6 +174,21 @@ spec: example: 5m30s type: string type: object + secretRef: + description: |- + SecretRef references a Secret containing configuration data to merge into the Configuration. + The keys and values from the Secret will be merged into the Configuration JSON. + properties: + name: + description: name is unique within a namespace to reference a + secret resource. + type: string + namespace: + description: namespace defines the space within which the secret + name must be unique. + type: string + type: object + x-kubernetes-map-type: atomic type: object status: properties: diff --git a/charts/controller/crds/deployments.plural.sh_servicedeployments.yaml b/charts/controller/crds/deployments.plural.sh_servicedeployments.yaml index d526d79716..f49863cac7 100644 --- a/charts/controller/crds/deployments.plural.sh_servicedeployments.yaml +++ b/charts/controller/crds/deployments.plural.sh_servicedeployments.yaml @@ -558,6 +558,9 @@ spec: items: properties: helm: + description: Helm is the Helm configuration to use for this + renderer, use if `path` points to a helm chart and you want + to override the default helm configuration. properties: ignoreHooks: description: IgnoreHooks indicates whether to ignore Helm @@ -579,8 +582,10 @@ spec: type: array type: object path: + description: Path is the path to the renderer works under. type: string type: + description: Type is the type of renderer to use. enum: - AUTO - RAW diff --git a/go/client/models_gen.go b/go/client/models_gen.go index a6785751aa..cad18b41d9 100644 --- a/go/client/models_gen.go +++ b/go/client/models_gen.go @@ -790,6 +790,8 @@ type AnthropicSettings struct { Model *string `json:"model,omitempty"` // the model to use for tool calls, which are less frequent and require more complex reasoning ToolModel *string `json:"toolModel,omitempty"` + // addditional models to support within the integrated ai proxy + ProxyModels []*string `json:"proxyModels,omitempty"` } type AnthropicSettingsAttributes struct { @@ -799,6 +801,8 @@ type AnthropicSettingsAttributes struct { ToolModel *string `json:"toolModel,omitempty"` // the model to use for vector embeddings EmbeddingModel *string `json:"embeddingModel,omitempty"` + // addditional models to support within the integrated ai proxy + ProxyModels []*string `json:"proxyModels,omitempty"` } // a representation of a kubernetes api deprecation @@ -1044,6 +1048,8 @@ type AzureOpenaiAttributes struct { EmbeddingModel *string `json:"embeddingModel,omitempty"` // the azure openai access token to use AccessToken string `json:"accessToken"` + // addditional models to support within the integrated ai proxy + ProxyModels []*string `json:"proxyModels,omitempty"` } // Settings for configuring against Azure OpenAI @@ -1057,6 +1063,8 @@ type AzureOpenaiSettings struct { ToolModel *string `json:"toolModel,omitempty"` // the api version you want to use APIVersion *string `json:"apiVersion,omitempty"` + // addditional models to support within the integrated ai proxy + ProxyModels []*string `json:"proxyModels,omitempty"` } type AzureSettingsAttributes struct { @@ -1109,6 +1117,8 @@ type BedrockAiAttributes struct { AWSSecretAccessKey *string `json:"awsSecretAccessKey,omitempty"` // the model to use for vector embeddings EmbeddingModel *string `json:"embeddingModel,omitempty"` + // addditional models to support within the integrated ai proxy + ProxyModels []*string `json:"proxyModels,omitempty"` } // Settings for usage of AWS Bedrock for LLMs @@ -1123,6 +1133,8 @@ type BedrockAiSettings struct { Region *string `json:"region,omitempty"` // the model to use for vector embeddings EmbeddingModel *string `json:"embeddingModel,omitempty"` + // addditional models to support within the integrated ai proxy + ProxyModels []*string `json:"proxyModels,omitempty"` } type BindingAttributes struct { @@ -5114,6 +5126,8 @@ type OllamaAttributes struct { URL string `json:"url"` // An http authorization header to use on calls to the Ollama api Authorization *string `json:"authorization,omitempty"` + // addditional models to support within the integrated ai proxy + ProxyModels []*string `json:"proxyModels,omitempty"` } // Settings for a self-hosted ollama-based LLM deployment @@ -5135,6 +5149,8 @@ type OpenaiSettings struct { ToolModel *string `json:"toolModel,omitempty"` // the model to use for vector embeddings EmbeddingModel *string `json:"embeddingModel,omitempty"` + // addditional models to support within the integrated ai proxy + ProxyModels []*string `json:"proxyModels,omitempty"` } type OpenaiSettingsAttributes struct { @@ -5145,6 +5161,8 @@ type OpenaiSettingsAttributes struct { ToolModel *string `json:"toolModel,omitempty"` // the model to use for vector embeddings EmbeddingModel *string `json:"embeddingModel,omitempty"` + // addditional models to support within the integrated ai proxy + ProxyModels []*string `json:"proxyModels,omitempty"` } type OpensearchConnection struct { @@ -8626,6 +8644,8 @@ type VertexAiAttributes struct { Project string `json:"project"` // the gcp region the model is hosted in Location string `json:"location"` + // addditional models to support within the integrated ai proxy + ProxyModels []*string `json:"proxyModels,omitempty"` } // Settings for usage of GCP VertexAI for LLMs @@ -8640,6 +8660,8 @@ type VertexAiSettings struct { Project string `json:"project"` // the gcp region the model Location string `json:"location"` + // addditional models to support within the integrated ai proxy + ProxyModels []*string `json:"proxyModels,omitempty"` } type VerticalPodAutoscaler struct { diff --git a/go/controller/api/v1alpha1/deploymentsettings_types.go b/go/controller/api/v1alpha1/deploymentsettings_types.go index a1b1056310..e6b83ffdd8 100644 --- a/go/controller/api/v1alpha1/deploymentsettings_types.go +++ b/go/controller/api/v1alpha1/deploymentsettings_types.go @@ -580,6 +580,7 @@ func (in *AISettings) Attributes(ctx context.Context, c client.Client, namespace BaseURL: in.OpenAI.BaseUrl, ToolModel: in.OpenAI.ToolModel, EmbeddingModel: in.OpenAI.EmbeddingModel, + ProxyModels: lo.ToSlicePtr(in.OpenAI.ProxyModels), } } @@ -594,6 +595,7 @@ func (in *AISettings) Attributes(ctx context.Context, c client.Client, namespace Model: in.Anthropic.Model, ToolModel: in.Anthropic.ToolModel, EmbeddingModel: in.Anthropic.EmbeddingModel, + ProxyModels: lo.ToSlicePtr(in.Anthropic.ProxyModels), } } @@ -610,6 +612,7 @@ func (in *AISettings) Attributes(ctx context.Context, c client.Client, namespace ToolModel: in.Azure.ToolModel, EmbeddingModel: in.Azure.EmbeddingModel, AccessToken: token, + ProxyModels: lo.ToSlicePtr(in.Azure.ProxyModels), } } @@ -631,6 +634,7 @@ func (in *AISettings) Attributes(ctx context.Context, c client.Client, namespace Endpoint: in.Vertex.Endpoint, EmbeddingModel: in.Vertex.EmbeddingModel, ToolModel: in.Vertex.ToolModel, + ProxyModels: lo.ToSlicePtr(in.Vertex.ProxyModels), } } @@ -655,6 +659,7 @@ func (in *AISettings) Attributes(ctx context.Context, c client.Client, namespace AccessToken: secret, Region: lo.ToPtr(in.Bedrock.Region), EmbeddingModel: in.Bedrock.EmbeddingModel, + ProxyModels: lo.ToSlicePtr(in.Bedrock.ProxyModels), AWSSecretAccessKey: secretKey, AWSAccessKeyID: in.Bedrock.AwsAccessKeyID, } @@ -747,6 +752,11 @@ type AIProviderSettings struct { // +kubebuilder:validation:Optional EmbeddingModel *string `json:"embeddingModel,omitempty"` + // ProxyModels are additional models to support within our integrated ai proxy. + // + // +kubebuilder:validation:Optional + ProxyModels []string `json:"proxyModels,omitempty"` + // BaseUrl is a custom base url to use, for reimplementations // of the same API scheme (for instance Together.ai uses the OpenAI API spec) // @@ -812,6 +822,11 @@ type AzureOpenAISettings struct { // +kubebuilder:validation:Optional EmbeddingModel *string `json:"embeddingModel,omitempty"` + // ProxyModels are additional models to support within the integrated ai proxy. + // + // +kubebuilder:validation:Optional + ProxyModels []string `json:"proxyModels,omitempty"` + // TokenSecretRef is a reference to the local secret holding the token to access // the configured AI provider. // @@ -835,6 +850,11 @@ type BedrockSettings struct { // +kubebuilder:validation:Optional EmbeddingModel *string `json:"embeddingModel,omitempty"` + // ProxyModels are additional models to support within the integrated ai proxy. + // + // +kubebuilder:validation:Optional + ProxyModels []string `json:"proxyModels,omitempty"` + // Region is the AWS region the model is hosted in // // +kubebuilder:validation:Required @@ -873,6 +893,11 @@ type VertexSettings struct { // +kubebuilder:validation:Optional EmbeddingModel *string `json:"embeddingModel,omitempty"` + // ProxyModels are additional models to support within the integrated ai proxy. + // + // +kubebuilder:validation:Optional + ProxyModels []string `json:"proxyModels,omitempty"` + // Project is the GCP project you'll be using // // +kubebuilder:validation:Required diff --git a/go/controller/api/v1alpha1/infrastructurestack_types.go b/go/controller/api/v1alpha1/infrastructurestack_types.go index d03fa1673a..03ab53f6db 100644 --- a/go/controller/api/v1alpha1/infrastructurestack_types.go +++ b/go/controller/api/v1alpha1/infrastructurestack_types.go @@ -74,11 +74,11 @@ type InfrastructureStackSpec struct { Interval *string `json:"interval,omitempty"` // RepositoryRef references the GitRepository containing the IaC source code. Leave empty to use git:url instead. - // +kubebuilder:validation:Required + // +kubebuilder:validation:Optional RepositoryRef corev1.ObjectReference `json:"repositoryRef"` // ClusterRef references the target Cluster where this stack will be executed. - // +kubebuilder:validation:Required + // +kubebuilder:validation:Optional ClusterRef corev1.ObjectReference `json:"clusterRef"` // Cluster is the handle of the target Cluster where this service will be deployed. Leave it empty to use the clusterRef field instead. diff --git a/go/controller/api/v1alpha1/sentinel_types.go b/go/controller/api/v1alpha1/sentinel_types.go index f269cbef09..36a113a68f 100644 --- a/go/controller/api/v1alpha1/sentinel_types.go +++ b/go/controller/api/v1alpha1/sentinel_types.go @@ -128,6 +128,7 @@ type SentinelCheckIntegrationTestCaseRaw struct { //+kubebuilder:validation:Optional ExpectedResult *console.SentinelRawResult `json:"expectedResult,omitempty"` } + type SentinelCheckIntegrationTestCaseCoredns struct { // DialFqdns the fqdns to dial for this test case DialFqdns []string `json:"dialFqdns,omitempty"` diff --git a/go/controller/api/v1alpha1/servicecontext_types.go b/go/controller/api/v1alpha1/servicecontext_types.go index 348105813b..312ffebea4 100644 --- a/go/controller/api/v1alpha1/servicecontext_types.go +++ b/go/controller/api/v1alpha1/servicecontext_types.go @@ -18,6 +18,16 @@ type ServiceContextSpec struct { // that needs to be shared across multiple services. Configuration runtime.RawExtension `json:"configuration,omitempty"` + // ConfigMapRef references a ConfigMap containing configuration data to merge into the Configuration. + // The keys and values from the ConfigMap will be merged into the Configuration JSON. + // +kubebuilder:validation:Optional + ConfigMapRef *v1.ObjectReference `json:"configMapRef,omitempty"` + + // SecretRef references a Secret containing configuration data to merge into the Configuration. + // The keys and values from the Secret will be merged into the Configuration JSON. + // +kubebuilder:validation:Optional + SecretRef *v1.SecretReference `json:"secretRef,omitempty"` + // ProjectRef references the project this service context belongs to. // If not provided, it will use the default project. // +kubebuilder:validation:Optional diff --git a/go/controller/api/v1alpha1/servicedeployment_types.go b/go/controller/api/v1alpha1/servicedeployment_types.go index 934cc44f8e..f53ff41fb0 100644 --- a/go/controller/api/v1alpha1/servicedeployment_types.go +++ b/go/controller/api/v1alpha1/servicedeployment_types.go @@ -341,21 +341,30 @@ type ServiceSpec struct { type Source struct { // Path the subdirectory this source will live in the final tarball + // +kubebuilder:validation:Optional Path *string `json:"path,omitempty"` // RepositoryRef the reference of the Git repository to source from. + // +kubebuilder:validation:Optional RepositoryRef *corev1.ObjectReference `json:"repositoryRef,omitempty"` // Git contains a location in a Git repository to use. + // +kubebuilder:validation:Optional Git *GitRef `json:"git,omitempty"` } type Renderer struct { + // Path is the path to the renderer works under. + // +kubebuilder:validation:Required Path string `json:"path"` + // Type is the type of renderer to use. + // +kubebuilder:validation:Required // +kubebuilder:validation:Enum=AUTO;RAW;HELM;KUSTOMIZE Type console.RendererType `json:"type"` + // Helm is the Helm configuration to use for this renderer, use if `path` points to a helm chart and you want to override the default helm configuration. + // +kubebuilder:validation:Optional Helm *HelmMinimal `json:"helm,omitempty"` } diff --git a/go/controller/api/v1alpha1/zz_generated.deepcopy.go b/go/controller/api/v1alpha1/zz_generated.deepcopy.go index feaabd0f04..6ed074267e 100644 --- a/go/controller/api/v1alpha1/zz_generated.deepcopy.go +++ b/go/controller/api/v1alpha1/zz_generated.deepcopy.go @@ -46,6 +46,11 @@ func (in *AIProviderSettings) DeepCopyInto(out *AIProviderSettings) { *out = new(string) **out = **in } + if in.ProxyModels != nil { + in, out := &in.ProxyModels, &out.ProxyModels + *out = make([]string, len(*in)) + copy(*out, *in) + } if in.BaseUrl != nil { in, out := &in.BaseUrl, &out.BaseUrl *out = new(string) @@ -326,6 +331,11 @@ func (in *AzureOpenAISettings) DeepCopyInto(out *AzureOpenAISettings) { *out = new(string) **out = **in } + if in.ProxyModels != nil { + in, out := &in.ProxyModels, &out.ProxyModels + *out = make([]string, len(*in)) + copy(*out, *in) + } in.TokenSecretRef.DeepCopyInto(&out.TokenSecretRef) } @@ -352,6 +362,11 @@ func (in *BedrockSettings) DeepCopyInto(out *BedrockSettings) { *out = new(string) **out = **in } + if in.ProxyModels != nil { + in, out := &in.ProxyModels, &out.ProxyModels + *out = make([]string, len(*in)) + copy(*out, *in) + } if in.TokenSecretRef != nil { in, out := &in.TokenSecretRef, &out.TokenSecretRef *out = new(v1.SecretKeySelector) @@ -7914,6 +7929,16 @@ func (in *ServiceContextSpec) DeepCopyInto(out *ServiceContextSpec) { **out = **in } in.Configuration.DeepCopyInto(&out.Configuration) + if in.ConfigMapRef != nil { + in, out := &in.ConfigMapRef, &out.ConfigMapRef + *out = new(v1.ObjectReference) + **out = **in + } + if in.SecretRef != nil { + in, out := &in.SecretRef, &out.SecretRef + *out = new(v1.SecretReference) + **out = **in + } if in.ProjectRef != nil { in, out := &in.ProjectRef, &out.ProjectRef *out = new(v1.ObjectReference) @@ -9184,6 +9209,11 @@ func (in *VertexSettings) DeepCopyInto(out *VertexSettings) { *out = new(string) **out = **in } + if in.ProxyModels != nil { + in, out := &in.ProxyModels, &out.ProxyModels + *out = make([]string, len(*in)) + copy(*out, *in) + } if in.Endpoint != nil { in, out := &in.Endpoint, &out.Endpoint *out = new(string) diff --git a/go/controller/config/crd/bases/deployments.plural.sh_deploymentsettings.yaml b/go/controller/config/crd/bases/deployments.plural.sh_deploymentsettings.yaml index 59e8ab5f51..07d553cb71 100644 --- a/go/controller/config/crd/bases/deployments.plural.sh_deploymentsettings.yaml +++ b/go/controller/config/crd/bases/deployments.plural.sh_deploymentsettings.yaml @@ -95,6 +95,12 @@ spec: model: description: Model is the LLM model name to use. type: string + proxyModels: + description: ProxyModels are additional models to support + within our integrated ai proxy. + items: + type: string + type: array tokenSecretRef: description: |- TokenSecretRef is a reference to the local secret holding the token to access @@ -149,6 +155,12 @@ spec: description: Model - the OpenAi model you wish to use. If not specified, Plural will provide a default. type: string + proxyModels: + description: ProxyModels are additional models to support + within the integrated ai proxy. + items: + type: string + type: array tokenSecretRef: description: |- TokenSecretRef is a reference to the local secret holding the token to access @@ -222,6 +234,12 @@ spec: will use the openai compatible endpoint, so the model id must be supported. type: string + proxyModels: + description: ProxyModels are additional models to support + within the integrated ai proxy. + items: + type: string + type: array region: description: Region is the AWS region the model is hosted in @@ -393,6 +411,12 @@ spec: model: description: Model is the LLM model name to use. type: string + proxyModels: + description: ProxyModels are additional models to support + within our integrated ai proxy. + items: + type: string + type: array tokenSecretRef: description: |- TokenSecretRef is a reference to the local secret holding the token to access @@ -630,6 +654,12 @@ spec: project: description: Project is the GCP project you'll be using type: string + proxyModels: + description: ProxyModels are additional models to support + within the integrated ai proxy. + items: + type: string + type: array serviceAccountJsonSecretRef: description: ServiceAccountJsonSecretRef is a Service Account json file stored w/in a kubernetes secret to use for authentication diff --git a/go/controller/config/crd/bases/deployments.plural.sh_globalservices.yaml b/go/controller/config/crd/bases/deployments.plural.sh_globalservices.yaml index c6d8ebcf58..4168630acd 100644 --- a/go/controller/config/crd/bases/deployments.plural.sh_globalservices.yaml +++ b/go/controller/config/crd/bases/deployments.plural.sh_globalservices.yaml @@ -639,6 +639,9 @@ spec: items: properties: helm: + description: Helm is the Helm configuration to use for this + renderer, use if `path` points to a helm chart and you + want to override the default helm configuration. properties: ignoreHooks: description: IgnoreHooks indicates whether to ignore @@ -660,8 +663,10 @@ spec: type: array type: object path: + description: Path is the path to the renderer works under. type: string type: + description: Type is the type of renderer to use. enum: - AUTO - RAW diff --git a/go/controller/config/crd/bases/deployments.plural.sh_infrastructurestacks.yaml b/go/controller/config/crd/bases/deployments.plural.sh_infrastructurestacks.yaml index d3e5514260..f554f4a901 100644 --- a/go/controller/config/crd/bases/deployments.plural.sh_infrastructurestacks.yaml +++ b/go/controller/config/crd/bases/deployments.plural.sh_infrastructurestacks.yaml @@ -9955,9 +9955,7 @@ spec: It is useful for projects with external modules or nested folder structures. type: string required: - - clusterRef - git - - repositoryRef - type type: object status: diff --git a/go/controller/config/crd/bases/deployments.plural.sh_managednamespaces.yaml b/go/controller/config/crd/bases/deployments.plural.sh_managednamespaces.yaml index 6ee370efbc..10ba413996 100644 --- a/go/controller/config/crd/bases/deployments.plural.sh_managednamespaces.yaml +++ b/go/controller/config/crd/bases/deployments.plural.sh_managednamespaces.yaml @@ -515,6 +515,9 @@ spec: items: properties: helm: + description: Helm is the Helm configuration to use for this + renderer, use if `path` points to a helm chart and you + want to override the default helm configuration. properties: ignoreHooks: description: IgnoreHooks indicates whether to ignore @@ -536,8 +539,10 @@ spec: type: array type: object path: + description: Path is the path to the renderer works under. type: string type: + description: Type is the type of renderer to use. enum: - AUTO - RAW diff --git a/go/controller/config/crd/bases/deployments.plural.sh_previewenvironmenttemplates.yaml b/go/controller/config/crd/bases/deployments.plural.sh_previewenvironmenttemplates.yaml index 7809ca6775..9cb240fad9 100644 --- a/go/controller/config/crd/bases/deployments.plural.sh_previewenvironmenttemplates.yaml +++ b/go/controller/config/crd/bases/deployments.plural.sh_previewenvironmenttemplates.yaml @@ -569,6 +569,9 @@ spec: items: properties: helm: + description: Helm is the Helm configuration to use for this + renderer, use if `path` points to a helm chart and you + want to override the default helm configuration. properties: ignoreHooks: description: IgnoreHooks indicates whether to ignore @@ -590,8 +593,10 @@ spec: type: array type: object path: + description: Path is the path to the renderer works under. type: string type: + description: Type is the type of renderer to use. enum: - AUTO - RAW diff --git a/go/controller/config/crd/bases/deployments.plural.sh_servicecontexts.yaml b/go/controller/config/crd/bases/deployments.plural.sh_servicecontexts.yaml index abdb7663ff..cc58847976 100644 --- a/go/controller/config/crd/bases/deployments.plural.sh_servicecontexts.yaml +++ b/go/controller/config/crd/bases/deployments.plural.sh_servicecontexts.yaml @@ -50,6 +50,51 @@ spec: spec: description: ServiceContextSpec defines the desired state of the ServiceContext. properties: + configMapRef: + description: |- + ConfigMapRef references a ConfigMap containing configuration data to merge into the Configuration. + The keys and values from the ConfigMap will be merged into the Configuration JSON. + properties: + apiVersion: + description: API version of the referent. + type: string + fieldPath: + description: |- + If referring to a piece of an object instead of an entire object, this string + should contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2]. + For example, if the object reference is to a container within a pod, this would take on a value like: + "spec.containers{name}" (where "name" refers to the name of the container that triggered + the event) or if no container name is specified "spec.containers[2]" (container with + index 2 in this pod). This syntax is chosen only to have some well-defined way of + referencing a part of an object. + type: string + kind: + description: |- + Kind of the referent. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + name: + description: |- + Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + namespace: + description: |- + Namespace of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/ + type: string + resourceVersion: + description: |- + Specific resourceVersion to which this reference is made, if any. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency + type: string + uid: + description: |- + UID of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids + type: string + type: object + x-kubernetes-map-type: atomic configuration: description: |- Configuration is a reusable configuration context that can include any JSON-compatible configuration data @@ -129,6 +174,21 @@ spec: example: 5m30s type: string type: object + secretRef: + description: |- + SecretRef references a Secret containing configuration data to merge into the Configuration. + The keys and values from the Secret will be merged into the Configuration JSON. + properties: + name: + description: name is unique within a namespace to reference a + secret resource. + type: string + namespace: + description: namespace defines the space within which the secret + name must be unique. + type: string + type: object + x-kubernetes-map-type: atomic type: object status: properties: diff --git a/go/controller/config/crd/bases/deployments.plural.sh_servicedeployments.yaml b/go/controller/config/crd/bases/deployments.plural.sh_servicedeployments.yaml index d526d79716..f49863cac7 100644 --- a/go/controller/config/crd/bases/deployments.plural.sh_servicedeployments.yaml +++ b/go/controller/config/crd/bases/deployments.plural.sh_servicedeployments.yaml @@ -558,6 +558,9 @@ spec: items: properties: helm: + description: Helm is the Helm configuration to use for this + renderer, use if `path` points to a helm chart and you want + to override the default helm configuration. properties: ignoreHooks: description: IgnoreHooks indicates whether to ignore Helm @@ -579,8 +582,10 @@ spec: type: array type: object path: + description: Path is the path to the renderer works under. type: string type: + description: Type is the type of renderer to use. enum: - AUTO - RAW diff --git a/go/controller/docs/api.md b/go/controller/docs/api.md index 193811f3b1..f412f9b147 100644 --- a/go/controller/docs/api.md +++ b/go/controller/docs/api.md @@ -70,6 +70,7 @@ _Appears in:_ | `model` _string_ | Model is the LLM model name to use. | | Optional: \{\}
| | `toolModel` _string_ | ToolModel to use for tool calling, which is less frequent and often requires more advanced reasoning | | Optional: \{\}
| | `embeddingModel` _string_ | EmbeddingModel to use for generating embeddings | | Optional: \{\}
| +| `proxyModels` _string array_ | ProxyModels are additional models to support within our integrated ai proxy. | | Optional: \{\}
| | `baseUrl` _string_ | BaseUrl is a custom base url to use, for reimplementations
of the same API scheme (for instance Together.ai uses the OpenAI API spec) | | Optional: \{\}
| | `tokenSecretRef` _[SecretKeySelector](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#secretkeyselector-v1-core)_ | TokenSecretRef is a reference to the local secret holding the token to access
the configured AI provider. | | Required: \{\}
| @@ -252,6 +253,7 @@ _Appears in:_ | `model` _string_ | Model - the OpenAi model you wish to use. If not specified, Plural will provide a default. | | Optional: \{\}
| | `toolModel` _string_ | ToolModel to use for tool calling, which is less frequent and often requires more advanced reasoning. | | Optional: \{\}
| | `embeddingModel` _string_ | EmbeddingModel to use for generating embeddings. | | Optional: \{\}
| +| `proxyModels` _string array_ | ProxyModels are additional models to support within the integrated ai proxy. | | Optional: \{\}
| | `tokenSecretRef` _[SecretKeySelector](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#secretkeyselector-v1-core)_ | TokenSecretRef is a reference to the local secret holding the token to access
the configured AI provider. | | Required: \{\}
| @@ -271,6 +273,7 @@ _Appears in:_ | `modelId` _string_ | ModelID is the AWS Bedrock Model ID to use. This will use the openai compatible endpoint, so the model id must be supported. | | Required: \{\}
| | `toolModelId` _string_ | ToolModelId to use for tool calling, which is less frequent and often requires more advanced reasoning | | Optional: \{\}
| | `embeddingModel` _string_ | EmbeddingModel to use for generating embeddings | | Optional: \{\}
| +| `proxyModels` _string array_ | ProxyModels are additional models to support within the integrated ai proxy. | | Optional: \{\}
| | `region` _string_ | Region is the AWS region the model is hosted in | | Required: \{\}
| | `tokenSecretRef` _[SecretKeySelector](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#secretkeyselector-v1-core)_ | TokenSecretRef is a reference to the local secret holding the token to access
the configured AI provider. | | Optional: \{\}
| | `awsAccessKeyId` _string_ | AWS Access Key ID to use for authentication | | Optional: \{\}
| @@ -2035,8 +2038,8 @@ _Appears in:_ | `name` _string_ | Name of this stack.
If not provided, the name from InfrastructureStack.ObjectMeta will be used. | | Optional: \{\}
| | `type` _[StackType](#stacktype)_ | Type specifies the IaC tool to use for executing the stack.
One of TERRAFORM, ANSIBLE, CUSTOM. | | Enum: [TERRAFORM ANSIBLE CUSTOM]
Required: \{\}
| | `interval` _string_ | Interval specifies the interval at which the stack will be reconciled, default is 5m | | Optional: \{\}
| -| `repositoryRef` _[ObjectReference](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#objectreference-v1-core)_ | RepositoryRef references the GitRepository containing the IaC source code. Leave empty to use git:url instead. | | Required: \{\}
| -| `clusterRef` _[ObjectReference](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#objectreference-v1-core)_ | ClusterRef references the target Cluster where this stack will be executed. | | Required: \{\}
| +| `repositoryRef` _[ObjectReference](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#objectreference-v1-core)_ | RepositoryRef references the GitRepository containing the IaC source code. Leave empty to use git:url instead. | | Optional: \{\}
| +| `clusterRef` _[ObjectReference](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#objectreference-v1-core)_ | ClusterRef references the target Cluster where this stack will be executed. | | Optional: \{\}
| | `cluster` _string_ | Cluster is the handle of the target Cluster where this service will be deployed. Leave it empty to use the clusterRef field instead. | | Optional: \{\}
| | `projectRef` _[ObjectReference](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#objectreference-v1-core)_ | ProjectRef references a project this stack belongs to.
If not provided, it will use the default project. | | Optional: \{\}
| | `git` _[GitRef](#gitref)_ | Git contains reference within the repository where the IaC manifests are located. | | | @@ -3909,9 +3912,9 @@ _Appears in:_ | Field | Description | Default | Validation | | --- | --- | --- | --- | -| `path` _string_ | | | | -| `type` _[RendererType](#renderertype)_ | | | Enum: [AUTO RAW HELM KUSTOMIZE]
| -| `helm` _[HelmMinimal](#helmminimal)_ | | | | +| `path` _string_ | Path is the path to the renderer works under. | | Required: \{\}
| +| `type` _[RendererType](#renderertype)_ | Type is the type of renderer to use. | | Enum: [AUTO RAW HELM KUSTOMIZE]
Required: \{\}
| +| `helm` _[HelmMinimal](#helmminimal)_ | Helm is the Helm configuration to use for this renderer, use if `path` points to a helm chart and you want to override the default helm configuration. | | Optional: \{\}
| #### RouterFilters @@ -4350,6 +4353,8 @@ _Appears in:_ | --- | --- | --- | --- | | `name` _string_ | Name of this service context.
If not provided, the name from ServiceContext.ObjectMeta will be used. | | Optional: \{\}
| | `configuration` _[RawExtension](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#rawextension-runtime-pkg)_ | Configuration is a reusable configuration context that can include any JSON-compatible configuration data
that needs to be shared across multiple services. | | | +| `configMapRef` _[ObjectReference](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#objectreference-v1-core)_ | ConfigMapRef references a ConfigMap containing configuration data to merge into the Configuration.
The keys and values from the ConfigMap will be merged into the Configuration JSON. | | Optional: \{\}
| +| `secretRef` _[SecretReference](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#secretreference-v1-core)_ | SecretRef references a Secret containing configuration data to merge into the Configuration.
The keys and values from the Secret will be merged into the Configuration JSON. | | Optional: \{\}
| | `projectRef` _[ObjectReference](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#objectreference-v1-core)_ | ProjectRef references the project this service context belongs to.
If not provided, it will use the default project. | | Optional: \{\}
| | `reconciliation` _[Reconciliation](#reconciliation)_ | Reconciliation settings for this resource.
Controls drift detection and reconciliation intervals. | | Optional: \{\}
| @@ -4601,9 +4606,9 @@ _Appears in:_ | Field | Description | Default | Validation | | --- | --- | --- | --- | -| `path` _string_ | Path the subdirectory this source will live in the final tarball | | | -| `repositoryRef` _[ObjectReference](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#objectreference-v1-core)_ | RepositoryRef the reference of the Git repository to source from. | | | -| `git` _[GitRef](#gitref)_ | Git contains a location in a Git repository to use. | | | +| `path` _string_ | Path the subdirectory this source will live in the final tarball | | Optional: \{\}
| +| `repositoryRef` _[ObjectReference](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#objectreference-v1-core)_ | RepositoryRef the reference of the Git repository to source from. | | Optional: \{\}
| +| `git` _[GitRef](#gitref)_ | Git contains a location in a Git repository to use. | | Optional: \{\}
| #### SpecTemplate @@ -5003,6 +5008,7 @@ _Appears in:_ | `model` _string_ | Model is the Vertex AI model to use. Must support the OpenAI completions api, see: https://cloud.google.com/vertex-ai/generative-ai/docs/migrate/openai/overview | | Optional: \{\}
| | `toolModel` _string_ | ToolModel to use for tool calling, which is less frequent and often requires more advanced reasoning | | Optional: \{\}
| | `embeddingModel` _string_ | EmbeddingModel to use for generating embeddings | | Optional: \{\}
| +| `proxyModels` _string array_ | ProxyModels are additional models to support within the integrated ai proxy. | | Optional: \{\}
| | `project` _string_ | Project is the GCP project you'll be using | | Required: \{\}
| | `location` _string_ | Location is the GCP region Vertex is queried from | | Required: \{\}
| | `endpoint` _string_ | Endpoint is a custom endpoint for self-deployed models | | Optional: \{\}
| diff --git a/go/controller/internal/controller/project_controller.go b/go/controller/internal/controller/project_controller.go index 0623013473..bf5d507b8c 100644 --- a/go/controller/internal/controller/project_controller.go +++ b/go/controller/internal/controller/project_controller.go @@ -136,7 +136,7 @@ func (in *ProjectReconciler) addOrRemoveFinalizer(ctx context.Context, project * // If it fails to delete the external dependency here, return with the error // so that it can be retried. utils.MarkCondition(project.SetCondition, v1alpha1.SynchronizedConditionType, v1.ConditionFalse, v1alpha1.SynchronizedConditionReasonError, err.Error()) - return lo.ToPtr(project.Spec.Reconciliation.Requeue()) + return lo.ToPtr(common.Wait()) } } diff --git a/go/controller/internal/controller/servicecontext_controller.go b/go/controller/internal/controller/servicecontext_controller.go index fe612c050d..abe811f800 100644 --- a/go/controller/internal/controller/servicecontext_controller.go +++ b/go/controller/internal/controller/servicecontext_controller.go @@ -2,18 +2,24 @@ package controller import ( "context" + "encoding/json" + "fmt" console "github.com/pluralsh/console/go/client" consoleclient "github.com/pluralsh/console/go/controller/internal/client" "github.com/pluralsh/console/go/controller/internal/common" "github.com/pluralsh/console/go/controller/internal/utils" "github.com/samber/lo" + corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/errors" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" "sigs.k8s.io/controller-runtime/pkg/builder" "sigs.k8s.io/controller-runtime/pkg/controller" "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" + "sigs.k8s.io/controller-runtime/pkg/handler" "sigs.k8s.io/controller-runtime/pkg/predicate" + "sigs.k8s.io/controller-runtime/pkg/reconcile" "k8s.io/apimachinery/pkg/runtime" ctrl "sigs.k8s.io/controller-runtime" @@ -37,6 +43,8 @@ type ServiceContextReconciler struct { //+kubebuilder:rbac:groups=deployments.plural.sh,resources=servicecontexts,verbs=get;list;watch;create;update;patch;delete //+kubebuilder:rbac:groups=deployments.plural.sh,resources=servicecontexts/status,verbs=get;update;patch //+kubebuilder:rbac:groups=deployments.plural.sh,resources=servicecontexts/finalizers,verbs=update +//+kubebuilder:rbac:groups=core,resources=secrets,verbs=get;list;watch;patch +//+kubebuilder:rbac:groups=core,resources=configmaps,verbs=get;list;watch;patch // Reconcile is part of the main kubernetes reconciliation loop which aims to // move the current state of the cluster closer to the desired state. @@ -87,7 +95,8 @@ func (r *ServiceContextReconciler) Reconcile(ctx context.Context, req ctrl.Reque return common.HandleRequeue(result, err, serviceContext.SetCondition) } - apiServiceContext, err := r.sync(serviceContext, project) + // Track secret/configmap references for updates + apiServiceContext, err := r.sync(ctx, serviceContext, project) if err != nil { logger.Error(err, "unable to create or update sa") utils.MarkCondition(serviceContext.SetCondition, v1alpha1.SynchronizedConditionType, v1.ConditionFalse, v1alpha1.SynchronizedConditionReasonError, err.Error()) @@ -103,13 +112,69 @@ func (r *ServiceContextReconciler) Reconcile(ctx context.Context, req ctrl.Reque return serviceContext.Spec.Reconciliation.Requeue(), nil } -func (r *ServiceContextReconciler) sync(sc *v1alpha1.ServiceContext, project *v1alpha1.Project) (*console.ServiceContextFragment, error) { - attributes := console.ServiceContextAttributes{} - attributes.Configuration = lo.ToPtr("{}") - if sc.Spec.Configuration.Raw != nil { - attributes.Configuration = lo.ToPtr(string(sc.Spec.Configuration.Raw)) +func (r *ServiceContextReconciler) sync(ctx context.Context, sc *v1alpha1.ServiceContext, project *v1alpha1.Project) (*console.ServiceContextFragment, error) { + // Start with existing configuration + configMap := make(map[string]interface{}) + if len(sc.Spec.Configuration.Raw) > 0 { + if err := json.Unmarshal(sc.Spec.Configuration.Raw, &configMap); err != nil { + return nil, fmt.Errorf("failed to parse configuration JSON: %w", err) + } + } + + // Merge configmap data if specified + if sc.Spec.ConfigMapRef != nil { + cm := &corev1.ConfigMap{} + namespace := sc.Spec.ConfigMapRef.Namespace + if namespace == "" { + namespace = sc.GetNamespace() + } + if err := r.Get(ctx, types.NamespacedName{Name: sc.Spec.ConfigMapRef.Name, Namespace: namespace}, cm); err != nil { + return nil, fmt.Errorf("failed to get configmap %s/%s: %w", namespace, sc.Spec.ConfigMapRef.Name, err) + } + + if err := utils.AddOwnerRefAnnotation(ctx, r.Client, sc, cm); err != nil { + return nil, err + } + + if cm.Data != nil { + for k, v := range cm.Data { + configMap[k] = v + } + } + } + + // Merge secret data if specified + if sc.Spec.SecretRef != nil { + secret := &corev1.Secret{} + namespace := sc.Spec.SecretRef.Namespace + if namespace == "" { + namespace = sc.GetNamespace() + } + + if err := r.Get(ctx, types.NamespacedName{Name: sc.Spec.SecretRef.Name, Namespace: namespace}, secret); err != nil { + return nil, fmt.Errorf("failed to get secret %s/%s: %w", namespace, sc.Spec.SecretRef.Name, err) + } + + if err := utils.AddOwnerRefAnnotation(ctx, r.Client, sc, secret); err != nil { + return nil, err + } + + if secret.Data != nil { + for k, v := range secret.Data { + configMap[k] = string(v) + } + } } + // Convert merged map back to JSON + configJSON, err := json.Marshal(configMap) + if err != nil { + return nil, fmt.Errorf("failed to marshal configuration JSON: %w", err) + } + + attributes := console.ServiceContextAttributes{} + attributes.Configuration = lo.ToPtr(string(configJSON)) + if project != nil { attributes.ProjectID = project.Status.ID } @@ -184,6 +249,14 @@ func (r *ServiceContextReconciler) addOrRemoveFinalizer(serviceContext *v1alpha1 func (r *ServiceContextReconciler) SetupWithManager(mgr ctrl.Manager) error { return ctrl.NewControllerManagedBy(mgr). WithOptions(controller.Options{MaxConcurrentReconciles: 1}). + Watches(&corev1.Secret{}, OnSecretChange(r.Client, new(v1alpha1.ServiceContext))). + Watches(&corev1.ConfigMap{}, OnConfigMapChange(r.Client, new(v1alpha1.ServiceContext))). For(&v1alpha1.ServiceContext{}, builder.WithPredicates(predicate.GenerationChangedPredicate{})). Complete(r) } + +func OnConfigMapChange[T client.Object](c client.Client, obj T) handler.EventHandler { + return handler.EnqueueRequestsFromMapFunc(func(ctx context.Context, configMap client.Object) []reconcile.Request { + return utils.GetOwnerRefsAnnotationRequests(ctx, c, configMap, obj) + }) +} diff --git a/go/controller/internal/controller/servicecontext_controller_test.go b/go/controller/internal/controller/servicecontext_controller_test.go index 40eea2c213..4f34a9ef92 100644 --- a/go/controller/internal/controller/servicecontext_controller_test.go +++ b/go/controller/internal/controller/servicecontext_controller_test.go @@ -2,6 +2,7 @@ package controller_test import ( "context" + "encoding/json" "k8s.io/apimachinery/pkg/runtime" @@ -9,6 +10,7 @@ import ( . "github.com/onsi/gomega" "github.com/samber/lo" "github.com/stretchr/testify/mock" + corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" @@ -20,6 +22,7 @@ import ( internalerror "github.com/pluralsh/console/go/controller/internal/errors" common "github.com/pluralsh/console/go/controller/internal/test/common" "github.com/pluralsh/console/go/controller/internal/test/mocks" + "github.com/pluralsh/console/go/controller/internal/utils" ) var _ = Describe("ServiceContext Controller", Ordered, func() { @@ -183,6 +186,115 @@ var _ = Describe("ServiceContext Controller", Ordered, func() { Expect(common.SanitizeStatusConditions(f.Status)).To(Equal(common.SanitizeStatusConditions(test.expectedStatus))) }) + It("should successfully merge configMapRef and secretRef into configuration", func() { + By("Create secret and configmap") + secretName := "test-secret" + configMapName := "test-configmap" + secretNamespacedName := types.NamespacedName{Name: secretName, Namespace: namespace} + configMapNamespacedName := types.NamespacedName{Name: configMapName, Namespace: namespace} + + // Create secret + secret := &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: secretName, + Namespace: namespace, + }, + Data: map[string][]byte{ + "secretKey1": []byte("secretValue1"), + "secretKey2": []byte("secretValue2"), + }, + } + Expect(k8sClient.Create(ctx, secret)).To(Succeed()) + defer func() { + Expect(k8sClient.Delete(ctx, secret)).To(Succeed()) + }() + + // Create configmap + configMap := &corev1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Name: configMapName, + Namespace: namespace, + }, + Data: map[string]string{ + "configKey1": "configValue1", + "configKey2": "configValue2", + }, + } + Expect(k8sClient.Create(ctx, configMap)).To(Succeed()) + defer func() { + Expect(k8sClient.Delete(ctx, configMap)).To(Succeed()) + }() + + By("Create ServiceContext with configMapRef and secretRef") + scName := "test-with-refs" + scNamespacedName := types.NamespacedName{Name: scName, Namespace: namespace} + sc := &v1alpha1.ServiceContext{ + ObjectMeta: metav1.ObjectMeta{ + Name: scName, + Namespace: namespace, + }, + Spec: v1alpha1.ServiceContextSpec{ + Configuration: runtime.RawExtension{Raw: []byte(`{"existingKey":"existingValue"}`)}, + ConfigMapRef: &corev1.ObjectReference{ + Name: configMapName, + Namespace: namespace, + }, + SecretRef: &corev1.SecretReference{ + Name: secretName, + Namespace: namespace, + }, + }, + } + Expect(k8sClient.Create(ctx, sc)).To(Succeed()) + defer func() { + Expect(k8sClient.Delete(ctx, sc)).To(Succeed()) + }() + + By("Reconcile the ServiceContext") + fakeConsoleClient := mocks.NewConsoleClientMock(mocks.TestingT) + fakeConsoleClient.On("GetServiceContext", mock.Anything).Return(nil, internalerror.NewNotFound()) + + // Verify that SaveServiceContext is called with merged configuration + fakeConsoleClient.On("SaveServiceContext", mock.Anything, mock.MatchedBy(func(attrs gqlclient.ServiceContextAttributes) bool { + if attrs.Configuration == nil { + return false + } + var config map[string]interface{} + if err := json.Unmarshal([]byte(*attrs.Configuration), &config); err != nil { + return false + } + // Check that all keys are present + return config["existingKey"] == "existingValue" && + config["configKey1"] == "configValue1" && + config["configKey2"] == "configValue2" && + config["secretKey1"] == "secretValue1" && + config["secretKey2"] == "secretValue2" + })).Return(&gqlclient.ServiceContextFragment{ID: "456"}, nil) + + nr := &controller.ServiceContextReconciler{ + Client: k8sClient, + Scheme: k8sClient.Scheme(), + ConsoleClient: fakeConsoleClient, + } + + _, err := nr.Reconcile(ctx, reconcile.Request{ + NamespacedName: scNamespacedName, + }) + + Expect(err).NotTo(HaveOccurred()) + + By("Verify annotations were added to secret and configmap") + updatedSecret := &corev1.Secret{} + Expect(k8sClient.Get(ctx, secretNamespacedName, updatedSecret)).To(Succeed()) + Expect(updatedSecret.GetAnnotations()).NotTo(BeNil()) + Expect(updatedSecret.GetAnnotations()[utils.OwnerRefAnnotation]).To(ContainSubstring(namespace + "/" + scName)) + + updatedConfigMap := &corev1.ConfigMap{} + Expect(k8sClient.Get(ctx, configMapNamespacedName, updatedConfigMap)).To(Succeed()) + Expect(updatedConfigMap.GetAnnotations()).NotTo(BeNil()) + Expect(updatedConfigMap.GetAnnotations()[utils.OwnerRefAnnotation]).To(ContainSubstring(namespace + "/" + scName)) + }) + }) }) diff --git a/go/nexus/internal/bifrost/account.go b/go/nexus/internal/bifrost/account.go index ebe8cd478b..0b1e6fd733 100644 --- a/go/nexus/internal/bifrost/account.go +++ b/go/nexus/internal/bifrost/account.go @@ -76,7 +76,7 @@ func (in *Account) GetKeysForProvider(ctx context.Context, provider schemas.Mode Value: schemas.EnvVar{ Val: cfg.GetApiKey(), }, - Models: []string{cfg.GetModel(), cfg.GetEmbeddingModel(), cfg.GetToolModel()}, + Models: filterModels(append([]string{cfg.GetModel(), cfg.GetEmbeddingModel(), cfg.GetToolModel()}, cfg.GetProxyModels()...)), UseForBatchAPI: lo.ToPtr(true), Weight: 1.0, }, @@ -94,7 +94,7 @@ func (in *Account) GetKeysForProvider(ctx context.Context, provider schemas.Mode Value: schemas.EnvVar{ Val: cfg.GetApiKey(), }, - Models: []string{cfg.GetModel(), cfg.GetToolModel()}, + Models: filterModels(append([]string{cfg.GetModel(), cfg.GetToolModel()}, cfg.GetProxyModels()...)), UseForBatchAPI: lo.ToPtr(true), Weight: 1.0, }, @@ -133,3 +133,9 @@ func (in *Account) GetConfigForProvider(provider schemas.ModelProvider) (*schema return config, nil } + +func filterModels(models []string) []string { + return lo.Filter(models, func(model string, _ int) bool { + return model != "" + }) +} diff --git a/go/nexus/internal/proto/console.pb.go b/go/nexus/internal/proto/console.pb.go index 8d9f8d7f25..31e3f8664e 100644 --- a/go/nexus/internal/proto/console.pb.go +++ b/go/nexus/internal/proto/console.pb.go @@ -148,6 +148,7 @@ type OpenAiConfig struct { EmbeddingModel *string `protobuf:"bytes,3,opt,name=embeddingModel,proto3,oneof" json:"embeddingModel,omitempty"` ToolModel *string `protobuf:"bytes,4,opt,name=toolModel,proto3,oneof" json:"toolModel,omitempty"` BaseUrl *string `protobuf:"bytes,5,opt,name=baseUrl,proto3,oneof" json:"baseUrl,omitempty"` + ProxyModels []string `protobuf:"bytes,6,rep,name=proxyModels,proto3" json:"proxyModels,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -217,6 +218,13 @@ func (x *OpenAiConfig) GetBaseUrl() string { return "" } +func (x *OpenAiConfig) GetProxyModels() []string { + if x != nil { + return x.ProxyModels + } + return nil +} + type AnthropicConfig struct { state protoimpl.MessageState `protogen:"open.v1"` BaseUrl *string `protobuf:"bytes,1,opt,name=baseUrl,proto3,oneof" json:"baseUrl,omitempty"` @@ -224,6 +232,7 @@ type AnthropicConfig struct { Model *string `protobuf:"bytes,3,opt,name=model,proto3,oneof" json:"model,omitempty"` EmbeddingModel *string `protobuf:"bytes,4,opt,name=embeddingModel,proto3,oneof" json:"embeddingModel,omitempty"` ToolModel *string `protobuf:"bytes,5,opt,name=toolModel,proto3,oneof" json:"toolModel,omitempty"` + ProxyModels []string `protobuf:"bytes,6,rep,name=proxyModels,proto3" json:"proxyModels,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -293,6 +302,13 @@ func (x *AnthropicConfig) GetToolModel() string { return "" } +func (x *AnthropicConfig) GetProxyModels() []string { + if x != nil { + return x.ProxyModels + } + return nil +} + type VertexAiConfig struct { state protoimpl.MessageState `protogen:"open.v1"` ApiKey *string `protobuf:"bytes,1,opt,name=apiKey,proto3,oneof" json:"apiKey,omitempty"` @@ -303,6 +319,7 @@ type VertexAiConfig struct { ToolModel *string `protobuf:"bytes,6,opt,name=toolModel,proto3,oneof" json:"toolModel,omitempty"` Project *string `protobuf:"bytes,7,opt,name=project,proto3,oneof" json:"project,omitempty"` Location *string `protobuf:"bytes,8,opt,name=location,proto3,oneof" json:"location,omitempty"` + ProxyModels []string `protobuf:"bytes,9,rep,name=proxyModels,proto3" json:"proxyModels,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -393,6 +410,13 @@ func (x *VertexAiConfig) GetLocation() string { return "" } +func (x *VertexAiConfig) GetProxyModels() []string { + if x != nil { + return x.ProxyModels + } + return nil +} + type BedrockConfig struct { state protoimpl.MessageState `protogen:"open.v1"` ModelId *string `protobuf:"bytes,1,opt,name=modelId,proto3,oneof" json:"modelId,omitempty"` @@ -402,6 +426,7 @@ type BedrockConfig struct { EmbeddingModelId *string `protobuf:"bytes,5,opt,name=embeddingModelId,proto3,oneof" json:"embeddingModelId,omitempty"` AwsAccessKeyId *string `protobuf:"bytes,6,opt,name=awsAccessKeyId,proto3,oneof" json:"awsAccessKeyId,omitempty"` AwsSecretAccessKey *string `protobuf:"bytes,7,opt,name=awsSecretAccessKey,proto3,oneof" json:"awsSecretAccessKey,omitempty"` + ProxyModels []string `protobuf:"bytes,8,rep,name=proxyModels,proto3" json:"proxyModels,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -485,6 +510,13 @@ func (x *BedrockConfig) GetAwsSecretAccessKey() string { return "" } +func (x *BedrockConfig) GetProxyModels() []string { + if x != nil { + return x.ProxyModels + } + return nil +} + type AzureOpenAiConfig struct { state protoimpl.MessageState `protogen:"open.v1"` ApiVersion *string `protobuf:"bytes,1,opt,name=apiVersion,proto3,oneof" json:"apiVersion,omitempty"` @@ -493,6 +525,7 @@ type AzureOpenAiConfig struct { EmbeddingModel *string `protobuf:"bytes,5,opt,name=embeddingModel,proto3,oneof" json:"embeddingModel,omitempty"` ToolModel *string `protobuf:"bytes,6,opt,name=toolModel,proto3,oneof" json:"toolModel,omitempty"` AccessToken *string `protobuf:"bytes,7,opt,name=accessToken,proto3,oneof" json:"accessToken,omitempty"` + ProxyModels []string `protobuf:"bytes,8,rep,name=proxyModels,proto3" json:"proxyModels,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -569,6 +602,13 @@ func (x *AzureOpenAiConfig) GetAccessToken() string { return "" } +func (x *AzureOpenAiConfig) GetProxyModels() []string { + if x != nil { + return x.ProxyModels + } + return nil +} + type ProxyAuthenticationRequest struct { state protoimpl.MessageState `protogen:"open.v1"` Token string `protobuf:"bytes,1,opt,name=token,proto3" json:"token,omitempty"` @@ -669,33 +709,35 @@ const file_console_proto_rawDesc = "" + "\tanthropic\x18\x03 \x01(\v2\x15.plrl.AnthropicConfigR\tanthropic\x120\n" + "\bvertexAi\x18\x04 \x01(\v2\x14.plrl.VertexAiConfigR\bvertexAi\x12-\n" + "\abedrock\x18\x05 \x01(\v2\x13.plrl.BedrockConfigR\abedrock\x12-\n" + - "\x05azure\x18\x06 \x01(\v2\x17.plrl.AzureOpenAiConfigR\x05azure\"\xf7\x01\n" + + "\x05azure\x18\x06 \x01(\v2\x17.plrl.AzureOpenAiConfigR\x05azure\"\x99\x02\n" + "\fOpenAiConfig\x12\x1b\n" + "\x06apiKey\x18\x01 \x01(\tH\x00R\x06apiKey\x88\x01\x01\x12\x19\n" + "\x05model\x18\x02 \x01(\tH\x01R\x05model\x88\x01\x01\x12+\n" + "\x0eembeddingModel\x18\x03 \x01(\tH\x02R\x0eembeddingModel\x88\x01\x01\x12!\n" + "\ttoolModel\x18\x04 \x01(\tH\x03R\ttoolModel\x88\x01\x01\x12\x1d\n" + - "\abaseUrl\x18\x05 \x01(\tH\x04R\abaseUrl\x88\x01\x01B\t\n" + + "\abaseUrl\x18\x05 \x01(\tH\x04R\abaseUrl\x88\x01\x01\x12 \n" + + "\vproxyModels\x18\x06 \x03(\tR\vproxyModelsB\t\n" + "\a_apiKeyB\b\n" + "\x06_modelB\x11\n" + "\x0f_embeddingModelB\f\n" + "\n" + "_toolModelB\n" + "\n" + - "\b_baseUrl\"\xfa\x01\n" + + "\b_baseUrl\"\x9c\x02\n" + "\x0fAnthropicConfig\x12\x1d\n" + "\abaseUrl\x18\x01 \x01(\tH\x00R\abaseUrl\x88\x01\x01\x12\x1b\n" + "\x06apiKey\x18\x02 \x01(\tH\x01R\x06apiKey\x88\x01\x01\x12\x19\n" + "\x05model\x18\x03 \x01(\tH\x02R\x05model\x88\x01\x01\x12+\n" + "\x0eembeddingModel\x18\x04 \x01(\tH\x03R\x0eembeddingModel\x88\x01\x01\x12!\n" + - "\ttoolModel\x18\x05 \x01(\tH\x04R\ttoolModel\x88\x01\x01B\n" + + "\ttoolModel\x18\x05 \x01(\tH\x04R\ttoolModel\x88\x01\x01\x12 \n" + + "\vproxyModels\x18\x06 \x03(\tR\vproxyModelsB\n" + "\n" + "\b_baseUrlB\t\n" + "\a_apiKeyB\b\n" + "\x06_modelB\x11\n" + "\x0f_embeddingModelB\f\n" + "\n" + - "_toolModel\"\xa1\x03\n" + + "_toolModel\"\xc3\x03\n" + "\x0eVertexAiConfig\x12\x1b\n" + "\x06apiKey\x18\x01 \x01(\tH\x00R\x06apiKey\x88\x01\x01\x12\x19\n" + "\x05model\x18\x02 \x01(\tH\x01R\x05model\x88\x01\x01\x12\x1f\n" + @@ -704,7 +746,8 @@ const file_console_proto_rawDesc = "" + "\x0eembeddingModel\x18\x05 \x01(\tH\x04R\x0eembeddingModel\x88\x01\x01\x12!\n" + "\ttoolModel\x18\x06 \x01(\tH\x05R\ttoolModel\x88\x01\x01\x12\x1d\n" + "\aproject\x18\a \x01(\tH\x06R\aproject\x88\x01\x01\x12\x1f\n" + - "\blocation\x18\b \x01(\tH\aR\blocation\x88\x01\x01B\t\n" + + "\blocation\x18\b \x01(\tH\aR\blocation\x88\x01\x01\x12 \n" + + "\vproxyModels\x18\t \x03(\tR\vproxyModelsB\t\n" + "\a_apiKeyB\b\n" + "\x06_modelB\v\n" + "\t_endpointB\x15\n" + @@ -714,7 +757,7 @@ const file_console_proto_rawDesc = "" + "_toolModelB\n" + "\n" + "\b_projectB\v\n" + - "\t_location\"\xa2\x03\n" + + "\t_location\"\xc4\x03\n" + "\rBedrockConfig\x12\x1d\n" + "\amodelId\x18\x01 \x01(\tH\x00R\amodelId\x88\x01\x01\x12%\n" + "\vtoolModelId\x18\x02 \x01(\tH\x01R\vtoolModelId\x88\x01\x01\x12%\n" + @@ -722,7 +765,8 @@ const file_console_proto_rawDesc = "" + "\x06region\x18\x04 \x01(\tH\x03R\x06region\x88\x01\x01\x12/\n" + "\x10embeddingModelId\x18\x05 \x01(\tH\x04R\x10embeddingModelId\x88\x01\x01\x12+\n" + "\x0eawsAccessKeyId\x18\x06 \x01(\tH\x05R\x0eawsAccessKeyId\x88\x01\x01\x123\n" + - "\x12awsSecretAccessKey\x18\a \x01(\tH\x06R\x12awsSecretAccessKey\x88\x01\x01B\n" + + "\x12awsSecretAccessKey\x18\a \x01(\tH\x06R\x12awsSecretAccessKey\x88\x01\x01\x12 \n" + + "\vproxyModels\x18\b \x03(\tR\vproxyModelsB\n" + "\n" + "\b_modelIdB\x0e\n" + "\f_toolModelIdB\x0e\n" + @@ -730,7 +774,7 @@ const file_console_proto_rawDesc = "" + "\a_regionB\x13\n" + "\x11_embeddingModelIdB\x11\n" + "\x0f_awsAccessKeyIdB\x15\n" + - "\x13_awsSecretAccessKey\"\xc2\x02\n" + + "\x13_awsSecretAccessKey\"\xe4\x02\n" + "\x11AzureOpenAiConfig\x12#\n" + "\n" + "apiVersion\x18\x01 \x01(\tH\x00R\n" + @@ -739,7 +783,8 @@ const file_console_proto_rawDesc = "" + "\bendpoint\x18\x04 \x01(\tH\x02R\bendpoint\x88\x01\x01\x12+\n" + "\x0eembeddingModel\x18\x05 \x01(\tH\x03R\x0eembeddingModel\x88\x01\x01\x12!\n" + "\ttoolModel\x18\x06 \x01(\tH\x04R\ttoolModel\x88\x01\x01\x12%\n" + - "\vaccessToken\x18\a \x01(\tH\x05R\vaccessToken\x88\x01\x01B\r\n" + + "\vaccessToken\x18\a \x01(\tH\x05R\vaccessToken\x88\x01\x01\x12 \n" + + "\vproxyModels\x18\b \x03(\tR\vproxyModelsB\r\n" + "\v_apiVersionB\b\n" + "\x06_modelB\v\n" + "\t_endpointB\x11\n" + diff --git a/lib/console/ai/tools/pr.ex b/lib/console/ai/tools/pr.ex index 18cbb6eaab..fa6c0ca069 100644 --- a/lib/console/ai/tools/pr.ex +++ b/lib/console/ai/tools/pr.ex @@ -65,6 +65,7 @@ defmodule Console.AI.Tools.Pr do {:ok, identifier} <- slug(conn, url), impl = Dispatcher.dispatcher(conn) do impl.create(%PrAutomation{ + ignore_templates: true, branch: conn.branch, connection: conn, title: pr.pr_title, diff --git a/lib/console/graphql/deployments/settings.ex b/lib/console/graphql/deployments/settings.ex index f9f46c54ef..15e6426c96 100644 --- a/lib/console/graphql/deployments/settings.ex +++ b/lib/console/graphql/deployments/settings.ex @@ -114,6 +114,7 @@ defmodule Console.GraphQl.Deployments.Settings do field :model, :string field :tool_model, :string, description: "the model to use for tool calls, which are less frequent and require more complex reasoning" field :embedding_model, :string, description: "the model to use for vector embeddings" + field :proxy_models, list_of(:string), description: "addditional models to support within the integrated ai proxy" end input_object :anthropic_settings_attributes do @@ -121,6 +122,7 @@ defmodule Console.GraphQl.Deployments.Settings do field :model, :string field :tool_model, :string, description: "the model to use for tool calls, which are less frequent and require more complex reasoning" field :embedding_model, :string, description: "the model to use for vector embeddings" + field :proxy_models, list_of(:string), description: "addditional models to support within the integrated ai proxy" end input_object :ollama_attributes do @@ -129,6 +131,7 @@ defmodule Console.GraphQl.Deployments.Settings do field :embedding_model, :string, description: "the model to use for vector embeddings" field :url, non_null(:string) field :authorization, :string, description: "An http authorization header to use on calls to the Ollama api" + field :proxy_models, list_of(:string), description: "addditional models to support within the integrated ai proxy" end input_object :azure_openai_attributes do @@ -138,6 +141,7 @@ defmodule Console.GraphQl.Deployments.Settings do field :tool_model, :string, description: "the model to use for tool calls, which are less frequent and require more complex reasoning" field :embedding_model, :string, description: "the model to use for vector embeddings" field :access_token, non_null(:string), description: "the azure openai access token to use" + field :proxy_models, list_of(:string), description: "addditional models to support within the integrated ai proxy" end input_object :bedrock_ai_attributes do @@ -148,6 +152,7 @@ defmodule Console.GraphQl.Deployments.Settings do field :aws_access_key_id, :string, description: "the aws access key id to use (DEPRECATED)" field :aws_secret_access_key, :string, description: "the aws secret access key to use (DEPRECATED)" field :embedding_model, :string, description: "the model to use for vector embeddings" + field :proxy_models, list_of(:string), description: "addditional models to support within the integrated ai proxy" end input_object :vertex_ai_attributes do @@ -158,6 +163,7 @@ defmodule Console.GraphQl.Deployments.Settings do field :endpoint, :string, description: "custom vertexai endpoint if for dedicated customer deployments" field :project, non_null(:string), description: "the gcp project id to use" field :location, non_null(:string), description: "the gcp region the model is hosted in" + field :proxy_models, list_of(:string), description: "addditional models to support within the integrated ai proxy" end input_object :vector_store_attributes do @@ -331,12 +337,14 @@ defmodule Console.GraphQl.Deployments.Settings do field :model, :string, description: "the openai model version to use" field :tool_model, :string, description: "the model to use for tool calls, which are less frequent and require more complex reasoning" field :embedding_model, :string, description: "the model to use for vector embeddings" + field :proxy_models, list_of(:string), description: "addditional models to support within the integrated ai proxy" end @desc "Anthropic connection information" object :anthropic_settings do - field :model, :string, description: "the anthropic model version to use" - field :tool_model, :string, description: "the model to use for tool calls, which are less frequent and require more complex reasoning" + field :model, :string, description: "the anthropic model version to use" + field :tool_model, :string, description: "the model to use for tool calls, which are less frequent and require more complex reasoning" + field :proxy_models, list_of(:string), description: "addditional models to support within the integrated ai proxy" end @desc "Settings for a self-hosted ollama-based LLM deployment" @@ -353,6 +361,7 @@ defmodule Console.GraphQl.Deployments.Settings do field :embedding_model, :string, description: "the model to use for vector embeddings" field :tool_model, :string, description: "the model to use for tool calls, which are less frequent and require more complex reasoning" field :api_version, :string, description: "the api version you want to use" + field :proxy_models, list_of(:string), description: "addditional models to support within the integrated ai proxy" end @desc "Settings for usage of AWS Bedrock for LLMs" @@ -362,6 +371,7 @@ defmodule Console.GraphQl.Deployments.Settings do field :access_key_id, :string, description: "the openai bedrock aws access key id to use (DEPRECATED)" field :region, :string, description: "the aws region the model is hosted in" field :embedding_model, :string, description: "the model to use for vector embeddings" + field :proxy_models, list_of(:string), description: "addditional models to support within the integrated ai proxy" end @desc "Settings for usage of GCP VertexAI for LLMs" @@ -371,6 +381,7 @@ defmodule Console.GraphQl.Deployments.Settings do field :tool_model, :string, description: "the model to use for tool calls, which are less frequent and require more complex reasoning" field :project, non_null(:string), description: "the gcp project id to use" field :location, non_null(:string), description: "the gcp region the model" + field :proxy_models, list_of(:string), description: "addditional models to support within the integrated ai proxy" end @desc "Settings for configuring log aggregation throughout Plural" diff --git a/lib/console/grpc/server.ex b/lib/console/grpc/server.ex index 9123783e6e..1e9ede6e86 100644 --- a/lib/console/grpc/server.ex +++ b/lib/console/grpc/server.ex @@ -38,7 +38,11 @@ defmodule Console.GRPC.Server do defp to_pb(%AI.OpenAi{} = openai) do %Plrl.OpenAiConfig{ apiKey: openai.access_token, - model: openai.model + model: openai.model, + embeddingModel: openai.embedding_model, + toolModel: openai.tool_model, + baseUrl: openai.base_url, + proxyModels: proxy_models(openai) } end @@ -47,7 +51,8 @@ defmodule Console.GRPC.Server do apiKey: anthropic.access_token, model: anthropic.model, toolModel: anthropic.tool_model, - baseUrl: anthropic.base_url + baseUrl: anthropic.base_url, + proxyModels: proxy_models(anthropic) } end @@ -59,7 +64,8 @@ defmodule Console.GRPC.Server do endpoint: vertex_ai.endpoint, embeddingModel: vertex_ai.embedding_model, project: vertex_ai.project, - location: vertex_ai.location + location: vertex_ai.location, + proxyModels: proxy_models(vertex_ai) } end @@ -70,7 +76,8 @@ defmodule Console.GRPC.Server do embeddingModelId: bedrock.embedding_model, region: bedrock.region, awsAccessKeyId: bedrock.aws_access_key_id, - awsSecretAccessKey: bedrock.aws_secret_access_key + awsSecretAccessKey: bedrock.aws_secret_access_key, + proxyModels: proxy_models(bedrock) } end @@ -80,9 +87,13 @@ defmodule Console.GRPC.Server do endpoint: azure.endpoint, embeddingModel: azure.embedding_model, toolModel: azure.tool_model, - accessToken: azure.access_token + accessToken: azure.access_token, + proxyModels: proxy_models(azure) } end defp to_pb(_), do: %Plrl.AiConfig{enabled: false} + + defp proxy_models(%{proxy_models: [_ | _] = models}), do: models + defp proxy_models(_), do: [] end diff --git a/lib/console/schema/deployment_settings.ex b/lib/console/schema/deployment_settings.ex index 52142b486e..dc6ea81cfe 100644 --- a/lib/console/schema/deployment_settings.ex +++ b/lib/console/schema/deployment_settings.ex @@ -188,6 +188,8 @@ defmodule Console.Schema.DeploymentSettings do field :model, :string field :tool_model, :string field :embedding_model, :string + + field :proxy_models, {:array, :string} end embeds_one :anthropic, Anthropic, on_replace: :update do @@ -196,6 +198,8 @@ defmodule Console.Schema.DeploymentSettings do field :model, :string field :tool_model, :string field :embedding_model, :string + + field :proxy_models, {:array, :string} end embeds_one :ollama, Ollama, on_replace: :update do @@ -213,6 +217,8 @@ defmodule Console.Schema.DeploymentSettings do field :tool_model, :string field :embedding_model, :string field :access_token, EncryptedString + + field :proxy_models, {:array, :string} end embeds_one :bedrock, Bedrock, on_replace: :update do @@ -223,6 +229,7 @@ defmodule Console.Schema.DeploymentSettings do field :embedding_model, :string field :aws_access_key_id, :string field :aws_secret_access_key, EncryptedString + field :proxy_models, {:array, :string} end embeds_one :vertex, Vertex, on_replace: :update do @@ -233,6 +240,7 @@ defmodule Console.Schema.DeploymentSettings do field :endpoint, :string field :location, :string field :embedding_model, :string + field :proxy_models, {:array, :string} end end @@ -322,7 +330,7 @@ defmodule Console.Schema.DeploymentSettings do defp ai_api_changeset(model, attrs) do model - |> cast(attrs, ~w(access_token model tool_model embedding_model base_url)a) + |> cast(attrs, ~w(access_token model tool_model embedding_model base_url proxy_models)a) end defp ollama_changeset(model, attrs) do @@ -333,7 +341,7 @@ defmodule Console.Schema.DeploymentSettings do defp azure_openai_changeset(model, attrs) do model - |> cast(attrs, ~w(endpoint api_version access_token tool_model embedding_model model)a) + |> cast(attrs, ~w(endpoint api_version access_token tool_model embedding_model model proxy_models)a) |> validate_required(~w(access_token endpoint)a) |> validate_change(:endpoint, fn :endpoint, endpoint -> with %URI{path: path, scheme: "https"} <- URI.parse(endpoint), @@ -348,13 +356,13 @@ defmodule Console.Schema.DeploymentSettings do defp bedrock_changeset(model, attrs) do model - |> cast(attrs, ~w(model_id tool_model_id access_token region embedding_model aws_access_key_id aws_secret_access_key)a) + |> cast(attrs, ~w(model_id tool_model_id access_token region embedding_model aws_access_key_id aws_secret_access_key proxy_models)a) |> validate_required(~w(model_id region)a) end defp vertex_changeset(model, attrs) do model - |> cast(attrs, ~w(model tool_model embedding_model service_account_json project location endpoint)a) + |> cast(attrs, ~w(model tool_model embedding_model service_account_json project location endpoint proxy_models)a) |> validate_required([:project, :location]) |> validate_change(:service_account_json, fn :service_account_json, json -> case Jason.decode(json) do diff --git a/lib/grpc/console.pb.ex b/lib/grpc/console.pb.ex index 08ceebb382..97230b2ae5 100644 --- a/lib/grpc/console.pb.ex +++ b/lib/grpc/console.pb.ex @@ -27,6 +27,7 @@ defmodule Plrl.OpenAiConfig do field :embeddingModel, 3, proto3_optional: true, type: :string field :toolModel, 4, proto3_optional: true, type: :string field :baseUrl, 5, proto3_optional: true, type: :string + field :proxyModels, 6, repeated: true, type: :string end defmodule Plrl.AnthropicConfig do @@ -39,6 +40,7 @@ defmodule Plrl.AnthropicConfig do field :model, 3, proto3_optional: true, type: :string field :embeddingModel, 4, proto3_optional: true, type: :string field :toolModel, 5, proto3_optional: true, type: :string + field :proxyModels, 6, repeated: true, type: :string end defmodule Plrl.VertexAiConfig do @@ -54,6 +56,7 @@ defmodule Plrl.VertexAiConfig do field :toolModel, 6, proto3_optional: true, type: :string field :project, 7, proto3_optional: true, type: :string field :location, 8, proto3_optional: true, type: :string + field :proxyModels, 9, repeated: true, type: :string end defmodule Plrl.BedrockConfig do @@ -68,6 +71,7 @@ defmodule Plrl.BedrockConfig do field :embeddingModelId, 5, proto3_optional: true, type: :string field :awsAccessKeyId, 6, proto3_optional: true, type: :string field :awsSecretAccessKey, 7, proto3_optional: true, type: :string + field :proxyModels, 8, repeated: true, type: :string end defmodule Plrl.AzureOpenAiConfig do @@ -81,6 +85,7 @@ defmodule Plrl.AzureOpenAiConfig do field :embeddingModel, 5, proto3_optional: true, type: :string field :toolModel, 6, proto3_optional: true, type: :string field :accessToken, 7, proto3_optional: true, type: :string + field :proxyModels, 8, repeated: true, type: :string end defmodule Plrl.ProxyAuthenticationRequest do diff --git a/proto/console.proto b/proto/console.proto index a81950fb72..27e6e532cf 100644 --- a/proto/console.proto +++ b/proto/console.proto @@ -23,6 +23,7 @@ message OpenAiConfig { optional string embeddingModel = 3; optional string toolModel = 4; optional string baseUrl = 5; + repeated string proxyModels = 6; } message AnthropicConfig { @@ -31,6 +32,7 @@ message AnthropicConfig { optional string model = 3; optional string embeddingModel = 4; optional string toolModel = 5; + repeated string proxyModels = 6; } message VertexAiConfig { @@ -42,6 +44,7 @@ message VertexAiConfig { optional string toolModel = 6; optional string project = 7; optional string location = 8; + repeated string proxyModels = 9; } message BedrockConfig { @@ -52,6 +55,7 @@ message BedrockConfig { optional string embeddingModelId = 5; optional string awsAccessKeyId = 6; optional string awsSecretAccessKey = 7; + repeated string proxyModels = 8; } message AzureOpenAiConfig { @@ -61,6 +65,7 @@ message AzureOpenAiConfig { optional string embeddingModel = 5; optional string toolModel = 6; optional string accessToken = 7; + repeated string proxyModels = 8; } message ProxyAuthenticationRequest { diff --git a/schema/schema.graphql b/schema/schema.graphql index ce1deb1fcd..04dc6e0c81 100644 --- a/schema/schema.graphql +++ b/schema/schema.graphql @@ -3446,6 +3446,9 @@ input OpenaiSettingsAttributes { "the model to use for vector embeddings" embeddingModel: String + + "addditional models to support within the integrated ai proxy" + proxyModels: [String] } input AnthropicSettingsAttributes { @@ -3458,6 +3461,9 @@ input AnthropicSettingsAttributes { "the model to use for vector embeddings" embeddingModel: String + + "addditional models to support within the integrated ai proxy" + proxyModels: [String] } input OllamaAttributes { @@ -3473,6 +3479,9 @@ input OllamaAttributes { "An http authorization header to use on calls to the Ollama api" authorization: String + + "addditional models to support within the integrated ai proxy" + proxyModels: [String] } input AzureOpenaiAttributes { @@ -3493,6 +3502,9 @@ input AzureOpenaiAttributes { "the azure openai access token to use" accessToken: String! + + "addditional models to support within the integrated ai proxy" + proxyModels: [String] } input BedrockAiAttributes { @@ -3516,6 +3528,9 @@ input BedrockAiAttributes { "the model to use for vector embeddings" embeddingModel: String + + "addditional models to support within the integrated ai proxy" + proxyModels: [String] } input VertexAiAttributes { @@ -3539,6 +3554,9 @@ input VertexAiAttributes { "the gcp region the model is hosted in" location: String! + + "addditional models to support within the integrated ai proxy" + proxyModels: [String] } input VectorStoreAttributes { @@ -3781,6 +3799,9 @@ type OpenaiSettings { "the model to use for vector embeddings" embeddingModel: String + + "addditional models to support within the integrated ai proxy" + proxyModels: [String] } "Anthropic connection information" @@ -3790,6 +3811,9 @@ type AnthropicSettings { "the model to use for tool calls, which are less frequent and require more complex reasoning" toolModel: String + + "addditional models to support within the integrated ai proxy" + proxyModels: [String] } "Settings for a self-hosted ollama-based LLM deployment" @@ -3818,6 +3842,9 @@ type AzureOpenaiSettings { "the api version you want to use" apiVersion: String + + "addditional models to support within the integrated ai proxy" + proxyModels: [String] } "Settings for usage of AWS Bedrock for LLMs" @@ -3836,6 +3863,9 @@ type BedrockAiSettings { "the model to use for vector embeddings" embeddingModel: String + + "addditional models to support within the integrated ai proxy" + proxyModels: [String] } "Settings for usage of GCP VertexAI for LLMs" @@ -3854,6 +3884,9 @@ type VertexAiSettings { "the gcp region the model" location: String! + + "addditional models to support within the integrated ai proxy" + proxyModels: [String] } "Settings for configuring log aggregation throughout Plural"