From 064b908207563b79c16c688bd97d3be364bf9855 Mon Sep 17 00:00:00 2001 From: gotsysdba Date: Wed, 5 Nov 2025 07:47:06 +0000 Subject: [PATCH 1/2] Update to Helm and Tofu --- .github/workflows/pytest.yml | 10 ++ .yamllint | 52 ++++++ helm/examples/values-kind-other.yaml | 2 +- helm/templates/_helpers.tpl | 2 +- helm/templates/server/database.yaml | 28 +-- helm/templates/server/oci-configmap.yaml | 11 +- helm/templates/server/service.yaml | 2 +- helm/values.yaml | 10 +- opentofu/cfgmgt/apply.py | 169 ++++++++++++------ opentofu/modules/kubernetes/cfgmgt.tf | 4 +- .../modules/kubernetes/cfgmgt_optimizer.tf | 4 +- opentofu/modules/kubernetes/locals.tf | 2 +- ...r_values.yaml => ai-optimizer-values.yaml} | 0 .../{k8s_manifest.yaml => k8s-manifest.yaml} | 11 +- opentofu/schema.yaml | 1 + pyproject.toml | 12 +- src/client/spring_ai/ollama-values.yaml | 1 - .../src/main/resources/application-dev.yml | 12 +- src/client/spring_ai/templates/obaas.yaml | 12 +- tests/opentofu/OMRMetaSchema.yaml | 10 +- 20 files changed, 238 insertions(+), 117 deletions(-) create mode 100644 .yamllint rename opentofu/modules/kubernetes/templates/{optimizer_values.yaml => ai-optimizer-values.yaml} (100%) rename opentofu/modules/kubernetes/templates/{k8s_manifest.yaml => k8s-manifest.yaml} (97%) diff --git a/.github/workflows/pytest.yml b/.github/workflows/pytest.yml index 63053c5d..bcf85b49 100644 --- a/.github/workflows/pytest.yml +++ b/.github/workflows/pytest.yml @@ -43,6 +43,16 @@ jobs: python -m pip install --upgrade pip wheel setuptools uv uv pip install torch==2.9.0+cpu -f https://download.pytorch.org/whl/cpu/torch --system uv pip install -e ".[all-test]" --system + curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash + + - name: Run yamllint on Code + run: yamllint . + + - name: Run Helm Lint (basic structure) + run: helm lint helm/ + + - name: Run Helm Lint (with required values) + run: helm lint helm/ --set global.api.apiKey=test-api-key - name: Run Pylint on IaC Code run: pylint opentofu diff --git a/.yamllint b/.yamllint new file mode 100644 index 00000000..3736a847 --- /dev/null +++ b/.yamllint @@ -0,0 +1,52 @@ +extends: default + +ignore: | + .venv/ + docs/themes/ + .github/ + helm/templates/ + opentofu/modules/*/templates/ + src/client/spring_ai/templates/ + +rules: + line-length: + max: 120 + level: warning + + indentation: + spaces: 2 + indent-sequences: true + + # Helm templates often use truthy values like yes/no, on/off + truthy: + allowed-values: ['true', 'false', 'yes', 'no', 'on', 'off'] + check-keys: false + + # Allow both quoted and unquoted strings + quoted-strings: + quote-type: any + required: false + + # Don't require document start marker (---) + document-start: disable + + # More lenient on comments + comments: + min-spaces-from-content: 1 + + # Disable for commented-out examples in Helm values + comments-indentation: disable + + # Allow empty values (common in Helm templates) + empty-values: + forbid-in-block-mappings: false + forbid-in-flow-mappings: false + + # Brackets and braces (lenient for Helm) + brackets: + min-spaces-inside: 0 + max-spaces-inside: 1 + + braces: + min-spaces-inside: 0 + max-spaces-inside: 1 diff --git a/helm/examples/values-kind-other.yaml b/helm/examples/values-kind-other.yaml index 20d052e8..e684b724 100644 --- a/helm/examples/values-kind-other.yaml +++ b/helm/examples/values-kind-other.yaml @@ -19,7 +19,7 @@ server: # service_name: "MYSERVICE" privAuthN: secretName: "db-priv-authn" - passwordKey: "password" + passwordKey: "password" client: replicaCount: 1 image: diff --git a/helm/templates/_helpers.tpl b/helm/templates/_helpers.tpl index d0911f4b..a5debdf8 100644 --- a/helm/templates/_helpers.tpl +++ b/helm/templates/_helpers.tpl @@ -286,7 +286,7 @@ These helpers provide consistent database type checking across templates. Database Service Name Helper Returns the short database type prefix (sidb or adb) for service naming. *********************************************** */}} -{{- define "server.database.shortType" -}} +{{- define "server.database.dbName" -}} {{- $dbType := include "server.database.type" . -}} {{- if $dbType -}} {{- lower (split "-" $dbType)._0 -}} diff --git a/helm/templates/server/database.yaml b/helm/templates/server/database.yaml index 4765229c..802f7818 100644 --- a/helm/templates/server/database.yaml +++ b/helm/templates/server/database.yaml @@ -3,13 +3,7 @@ # spell-checker: ignore nindent freepdb1 oserror selectai sidb spfile sqlplus # spell-checker: ignore sqlcode sqlerror varchar nolog ptype sysdba tablespace tblspace -# This file consolidates database-related Kubernetes resources: -# - Secrets (auth, priv, wallet) -# - Deployment (SIDB-FREE, ADB-FREE) -# - Job (database initialization) -# - AutonomousDatabase (ADB-S operator) -# -# Note: ConfigMap (initialization scripts) is now in db-configmap.yaml +# This file consolidates database-related Kubernetes resources {{- if .Values.server.database }} @@ -30,17 +24,17 @@ metadata: helm.sh/resource-policy: keep type: Opaque stringData: - username: "AI_OPTIMIZER" - password: {{ include "server.randomPassword" . | quote }} + {{ default "username" .Values.server.database.authN.usernameKey }}: "AI_OPTIMIZER" + {{ default "password" .Values.server.database.authN.passwordKey }}: {{ include "server.randomPassword" . | quote }} {{- if eq (include "server.database.isSIDB" .) "true" }} - service: "{{ .Release.Name }}-{{ include "server.database.shortType" . }}-1521:1521/FREEPDB1" + {{ default "service" .Values.server.database.authN.serviceKey }}: "{{ .Release.Name }}-{{ include "server.database.dbName" . }}-1521:1521/FREEPDB1" {{- else if eq (include "server.database.isADBFree" .) "true" }} - service: "{{ .Release.Name }}-{{ include "server.database.shortType" . }}-1521:1521/FREEPDB1" + {{ default "service" .Values.server.database.authN.serviceKey }}: "{{ .Release.Name }}-{{ include "server.database.dbName" . }}-1521:1521/FREEPDB1" {{- else if eq (include "server.database.isOther" .) "true" }} {{- if and .Values.server.database.other.dsn (ne (.Values.server.database.other.dsn | trim) "") }} - service: "{{ .Values.server.database.other.dsn }}" + {{ default "service" .Values.server.database.authN.serviceKey }}: "{{ .Values.server.database.other.dsn }}" {{- else }} - service: "{{ .Values.server.database.other.host }}:{{ .Values.server.database.other.port }}/{{ .Values.server.database.other.service_name }}" + {{ default "service" .Values.server.database.authN.serviceKey }}: "{{ .Values.server.database.other.host }}:{{ .Values.server.database.other.port }}/{{ .Values.server.database.other.service_name }}" {{- end }} {{- end }} {{- end }} @@ -85,7 +79,7 @@ stringData: apiVersion: apps/v1 kind: Deployment metadata: - name: {{ include "global.fullname" . }}-{{ include "server.database.shortType" . }} + name: {{ include "global.fullname" . }}-{{ include "server.database.dbName" . }} labels: app.kubernetes.io/component: database {{- include "global.labels" . | nindent 4}} @@ -238,10 +232,6 @@ metadata: labels: app.kubernetes.io/component: database {{- include "global.labels" . | nindent 4 }} - annotations: - "helm.sh/hook": pre-install,pre-upgrade - "helm.sh/hook-weight": "-5" - "helm.sh/hook-delete-policy": before-hook-creation spec: action: "Sync" details: @@ -253,7 +243,7 @@ spec: name: {{ .Release.Name }}-adb-wallet-pass-{{ .Release.Revision }} {{- if .Values.server.oci_config }} ociConfig: - configMapName: {{ .Release.Name }}-oci-config + configMapName: {{ .Values.server.oci_config.configMapName | default (printf "%s-oci-config" .Release.Name) }} {{- if .Values.server.oci_config.keySecretName }} secretName: {{ .Values.server.oci_config.keySecretName }} {{- end }} diff --git a/helm/templates/server/oci-configmap.yaml b/helm/templates/server/oci-configmap.yaml index dc42cbcb..0cd01490 100644 --- a/helm/templates/server/oci-configmap.yaml +++ b/helm/templates/server/oci-configmap.yaml @@ -3,10 +3,18 @@ # spell-checker: ignore nindent {{- if .Values.server.oci_config }} +{{- /* Determine the ConfigMap name to use or create */ -}} +{{- $configMapName := .Values.server.oci_config.configMapName | default (printf "%s-oci-config" .Release.Name) }} + +{{- /* Check if the ConfigMap already exists */ -}} +{{- $configMapExists := lookup "v1" "ConfigMap" .Release.Namespace $configMapName }} + +{{- /* Only create ConfigMap if it doesn't exist */ -}} +{{- if not $configMapExists }} apiVersion: v1 kind: ConfigMap metadata: - name: {{ .Release.Name }}-oci-config + name: {{ $configMapName }} labels: app.kubernetes.io/component: server {{- include "global.labels" . | nindent 4 }} @@ -25,4 +33,5 @@ data: region: {{ .region | quote }} {{- end }} {{- end }} +{{- end }} {{- end -}} \ No newline at end of file diff --git a/helm/templates/server/service.yaml b/helm/templates/server/service.yaml index a1d2c43c..fccd53ef 100644 --- a/helm/templates/server/service.yaml +++ b/helm/templates/server/service.yaml @@ -25,7 +25,7 @@ spec: apiVersion: v1 kind: Service metadata: - name: {{ .Release.Name }}-{{ include "server.database.shortType" . }}-1521 + name: {{ .Release.Name }}-{{ include "server.database.dbName" . }}-1521 labels: app.kubernetes.io/component: database {{- include "global.labels" . | nindent 4 }} diff --git a/helm/values.yaml b/helm/values.yaml index 180259de..b466700d 100644 --- a/helm/values.yaml +++ b/helm/values.yaml @@ -12,7 +12,9 @@ nameOverride: "" # ----------------------- # -- Global Configuration global: - # -- Either provide the 'apiKey' directly or provide a secretName referring to an existing Secret containing the API key. + # -- Either: + # 1) Provide the 'apiKey' directly + # 2) Provide a secretName referring to an existing Secret containing the API key. api: # -- Key for making API calls to the server. # Recommended to supply at command line or use the secretName to avoid storing in the values file. @@ -129,8 +131,10 @@ server: # -- Oracle Cloud Infrastructure Configuration oci_config: - # -- Enable Workload Identity Principals (WIP) (must be implemented) + # -- Enable Workload Identity Principals (IAM policies must exist) oke: false + # -- (Optional) Name of Pre-created configMap storing OCI API AuthN + configMapName: "" # -- Tenancy OCID. Required when specifying keySecretName. tenancy: "" # -- User OCID. Required when specifying keySecretName. @@ -469,4 +473,4 @@ ollama: tolerations: [] # - key: "key1" # operator: "Exists" - # effect: "NoSchedule" \ No newline at end of file + # effect: "NoSchedule" diff --git a/opentofu/cfgmgt/apply.py b/opentofu/cfgmgt/apply.py index a11614cf..55b574a5 100644 --- a/opentofu/cfgmgt/apply.py +++ b/opentofu/cfgmgt/apply.py @@ -2,7 +2,7 @@ Copyright (c) 2025, Oracle and/or its affiliates. Licensed under the Universal Permissive License v1.0 as shown at http://oss.oracle.com/licenses/upl. """ -# spell-checker:ignore kubeconfig +# spell-checker:ignore kubeconfig obaas prereqs import subprocess import argparse @@ -14,9 +14,17 @@ STAGE_PATH = os.path.join(os.path.dirname(__file__), "stage") os.environ["KUBECONFIG"] = os.path.join(STAGE_PATH, "kubeconfig") -# --- Helm Charts --- -OPTIMIZER_HELM_NAME = "ai-optimizer" -OPTIMIZER_HELM_REPO = "https://oracle.github.io/ai-optimizer/helm" +# --- Helm Charts Configuration --- +HELM_CHARTS = [ + { + "name": "ai-optimizer", + "chart_ref": "ai-optimizer/ai-optimizer", + "repo_url": "https://oracle.github.io/ai-optimizer/helm", + "repo_name": "ai-optimizer", + "values_file": "ai-optimizer-values.yaml", + }, +] + # --- Utility Functions --- def mod_kubeconfig(private_endpoint: str = None): @@ -77,75 +85,106 @@ def retry(func, retries=5, delay=15): # --- Core Functionalities --- -def helm_repo_add_if_missing(): - """Add/Update Helm Repo""" - print(f"➕ Adding Helm repo '{OPTIMIZER_HELM_NAME}'...") - _, stderr, rc = run_cmd(["helm", "repo", "add", OPTIMIZER_HELM_NAME, OPTIMIZER_HELM_REPO], capture_output=False) - if rc != 0: - print(f"❌ Failed to add repo:\n{stderr}") - sys.exit(1) +def helm_repo_add_if_missing(repos_to_add): + """Add/Update Helm Repos for charts that need remote repositories""" + if not repos_to_add: + print("ℹ️ No remote Helm repos to add.\n") + return + + for repo_name, repo_url in repos_to_add.items(): + print(f"➕ Adding Helm repo '{repo_name}'...") + _, stderr, rc = run_cmd(["helm", "repo", "add", repo_name, repo_url], capture_output=False) + if rc != 0: + print(f"❌ Failed to add repo '{repo_name}':\n{stderr}") + sys.exit(1) print("⬆️ Checking for Helm updates...") _, stderr, rc = run_cmd(["helm", "repo", "update"], capture_output=False) if rc != 0: print(f"❌ Failed to update repos:\n{stderr}") sys.exit(1) - print(f"✅ Repo '{OPTIMIZER_HELM_NAME}' added and updated.\n") - - -def apply_helm_chart_inner(release_name, namespace, optimizer_version=None): - """Apply Helm Chart""" - # Find all *-values.yaml files in the stage directory - values_files = [ - f for f in os.listdir(STAGE_PATH) - if f.endswith("-values.yaml") and os.path.isfile(os.path.join(STAGE_PATH, f)) - ] + print("✅ Repos added and updated.\n") - if not values_files: - print(f"⚠️ No values files (*-values.yaml) found in: {STAGE_PATH}") - print("ℹ️ Skipping Helm chart application.\n") - return True # Return True to indicate this is not a retriable failure - helm_repo_add_if_missing() +def apply_single_helm_chart_inner(chart_config, values_file, namespace, optimizer_version=None): + """Apply a single Helm Chart with its values file""" + chart_name = chart_config["name"] + chart_ref = chart_config["chart_ref"] + values_path = os.path.join(STAGE_PATH, values_file) - # Build helm command with all values files cmd = [ "helm", "upgrade", "--install", - release_name, - f"{OPTIMIZER_HELM_NAME}/{OPTIMIZER_HELM_NAME}", + chart_name, + chart_ref, "--namespace", namespace, + "--values", + values_path, ] - # Add version flag if optimizer_version is "Experimental" - if optimizer_version == "Experimental": + # Add version flag if this is the ai-optimizer chart and optimizer_version is "Experimental" + if chart_name == "ai-optimizer" and optimizer_version == "Experimental": cmd.extend(["--version", "0.0.0"]) print("🔬 Using Experimental version (0.0.0)") - else: + elif chart_name == "ai-optimizer": print("✅ Using latest Stable release") - # Add each values file to the command - for values_file in sorted(values_files): - values_path = os.path.join(STAGE_PATH, values_file) - cmd.extend(["--values", values_path]) - print(f"📄 Using values file: {values_file}") - - print(f"🚀 Applying Helm chart '{OPTIMIZER_HELM_NAME}' to namespace '{namespace}'...") + print(f"🚀 Applying Helm chart '{chart_name}' to namespace '{namespace}'...") + print(f"📄 Using values file: {values_file}") stdout, stderr, rc = run_cmd(cmd) if rc == 0: - print("✅ Helm chart applied:") - print(f"Apply Helm Chart: {stdout}") + print(f"✅ Helm chart '{chart_name}' applied successfully.") + if stdout: + print(f" {stdout}") return True - print(f"❌ Failed to apply Helm chart:\n{stderr}") + print(f"❌ Failed to apply Helm chart '{chart_name}':\n{stderr}") return False -def apply_helm_chart(release_name, namespace, optimizer_version=None): - """Retry Enabled Add/Update Helm Chart""" - retry(lambda: apply_helm_chart_inner(release_name, namespace, optimizer_version)) +def apply_single_helm_chart(chart_config, values_file, namespace, optimizer_version=None): + """Retry Enabled - Apply a single Helm Chart""" + retry(lambda: apply_single_helm_chart_inner(chart_config, values_file, namespace, optimizer_version)) + + +def apply_all_helm_charts(namespace, optimizer_version=None): + """Apply Helm charts in HELM_CHARTS order if their values files exist""" + # Match charts to values files (iterate through HELM_CHARTS to preserve order) + charts_to_apply = [] + repos_to_add = {} + + for chart_config in HELM_CHARTS: + values_filename = chart_config["values_file"] + values_path = os.path.join(STAGE_PATH, values_filename) + + # Check if values file exists + if os.path.isfile(values_path): + print(f"✓ Found values file for '{chart_config['name']}': {values_filename}") + charts_to_apply.append((chart_config, values_filename)) + # Collect remote repos that need to be added + if chart_config["repo_url"] is not None: + repos_to_add[chart_config["repo_name"]] = chart_config["repo_url"] + else: + print(f"⊘ Skipping '{chart_config['name']}': values file not found ({values_filename})") + + if not charts_to_apply: + print("\n⚠️ No charts to apply (no matching values files found).\n") + return + + print() # Blank line after file detection + + # Add all required Helm repos + helm_repo_add_if_missing(repos_to_add) + + # Apply each chart in order + print(f"📦 Applying {len(charts_to_apply)} Helm chart(s) in order...\n") + for chart_config, values_file in charts_to_apply: + apply_single_helm_chart(chart_config, values_file, namespace, optimizer_version) + print() # Add blank line between charts + + print("✅ All Helm charts applied successfully.\n") def apply_manifest_inner(namespace): @@ -184,8 +223,8 @@ def apply_manifest(namespace): retry(lambda: apply_manifest_inner(namespace)) -def patch_oracle_operator_inner(): - """Patch Oracle Database Operator deployment to disable readOnlyRootFilesystem""" +def patch_oracle_operator(): + """Patch Oracle Database Operator deployment and wait for it to be ready""" print("🔧 Patching oracle-database-operator deployment...") patch_json = ( '[{"op": "replace", "path": ' @@ -205,34 +244,48 @@ def patch_oracle_operator_inner(): patch_json, ] _, stderr, rc = run_cmd(cmd, capture_output=False) - if rc == 0: - print("✅ Oracle operator patched.\n") - return True + if rc != 0: + print(f"❌ Failed to patch operator:\n{stderr}") + sys.exit(1) - print(f"❌ Failed to patch operator:\n{stderr}") - return False + print("✅ Oracle operator patched.\n") + # Wait for operator to be ready after patching + print("⏳ Waiting for Oracle Database Operator to be ready...") + wait_cmd = [ + "kubectl", + "wait", + "--for=condition=Available", + "--timeout=300s", + "-n", + "oracle-database-operator-system", + "deployment/oracle-database-operator-controller-manager", + ] + _, stderr, rc = run_cmd(wait_cmd, capture_output=False) + if rc != 0: + print(f"❌ Operator readiness check failed:\n{stderr}") + sys.exit(1) -def patch_oracle_operator(): - """Retry Enabled Patch Oracle Operator""" - retry(patch_oracle_operator_inner) + print("✅ Oracle Database Operator is ready.\n") + # Additional wait to ensure webhook is fully operational + print("⏳ Waiting an additional 30 seconds for webhook stabilization...") + time.sleep(30) # --- Entry Point --- if __name__ == "__main__": parser = argparse.ArgumentParser(description="Apply a Helm chart and a Kubernetes manifest.") - parser.add_argument("release_name", help="Helm release name") parser.add_argument("namespace", help="Kubernetes namespace") parser.add_argument("--private_endpoint", nargs="?", const=None, default=None, help="Kubernetes Private Endpoint") parser.add_argument( "--optimizer_version", choices=["Stable", "Experimental"], default="Stable", - help="Optimizer version (Stable or Experimental)" + help="Optimizer version (Stable or Experimental)", ) args = parser.parse_args() mod_kubeconfig(args.private_endpoint) apply_manifest(args.namespace) patch_oracle_operator() - apply_helm_chart(args.release_name, args.namespace, args.optimizer_version) + apply_all_helm_charts(args.namespace, args.optimizer_version) diff --git a/opentofu/modules/kubernetes/cfgmgt.tf b/opentofu/modules/kubernetes/cfgmgt.tf index 4cf69228..c38fa1c2 100644 --- a/opentofu/modules/kubernetes/cfgmgt.tf +++ b/opentofu/modules/kubernetes/cfgmgt.tf @@ -3,7 +3,7 @@ # spell-checker: disable locals { - k8s_manifest = templatefile("${path.module}/templates/k8s_manifest.yaml", { + k8s_manifest = templatefile("${path.module}/templates/k8s-manifest.yaml", { label = var.label_prefix repository_host = local.repository_host repository_base = local.repository_base @@ -52,7 +52,7 @@ resource "null_resource" "apply" { provisioner "local-exec" { command = <- + Use this tool to answer any question that may benefit from + up-to-date or domain-specific information. capabilities: tool: true resource: true @@ -21,8 +23,8 @@ spring: vectorstore: oracle: distance-type: ${DISTANCE_TYPE} - remove-existing-vector-store-table: True - initialize-schema: True + remove-existing-vector-store-table: true + initialize-schema: true index-type: ${INDEX_TYPE} openai: base-url: {OPENAI_URL} @@ -49,12 +51,12 @@ spring: num-predict: {OL_MAX_TOKENS} model: ${OLLAMA_CHAT_MODEL} embedding: - options: + options: model: ${OLLAMA_EMBEDDING_MODEL} aims: sys_instr: ${SYS_INSTR} vectortable: name: ${VECTOR_STORE} - rag_params: + rag_params: search_type: Similarity top_k: ${TOP_K} diff --git a/src/client/spring_ai/templates/obaas.yaml b/src/client/spring_ai/templates/obaas.yaml index ed806232..28945e92 100644 --- a/src/client/spring_ai/templates/obaas.yaml +++ b/src/client/spring_ai/templates/obaas.yaml @@ -10,12 +10,12 @@ spring: vectorstore: oracle: distance-type: {vector_search[distance_metric]} - remove-existing-vector-store-table: True - initialize-schema: True + remove-existing-vector-store-table: true + initialize-schema: true index-type: {vector_search[index_type]} openai: base-url: \"{ll_model[api_base]}\" - api-key: \"{ll_model[api_key]}\" + api-key: \"{ll_model[api_key]}\" chat: options: temperature: {ll_model[temperature]} @@ -38,12 +38,12 @@ spring: top-p: {ll_model[top_p]} model: \"{ll_model[id]}\" embedding: - options: - model: \"{vector_search[id]}\" + options: + model: \"{vector_search[id]}\" aims: sys_instr: \"{sys_prompt}\" vectortable: name: {vector_search[vector_store]} - rag_params: + rag_params: search_type: Similarity top_k: {vector_search[top_k]} diff --git a/tests/opentofu/OMRMetaSchema.yaml b/tests/opentofu/OMRMetaSchema.yaml index 1d8fd4b4..c27d012c 100644 --- a/tests/opentofu/OMRMetaSchema.yaml +++ b/tests/opentofu/OMRMetaSchema.yaml @@ -317,7 +317,7 @@ definitions: - $ref: "#/definitions/mapVariable" - $ref: "#/definitions/objectVariable" - mapVariable: + mapVariable: allOf: - $ref: "#/definitions/baseVariable" - required: [type, valueType] @@ -330,7 +330,7 @@ definitions: type: [string] additionalProperties: true - listVariable: + listVariable: allOf: - $ref: "#/definitions/baseVariable" - required: [type, valueType] @@ -343,7 +343,7 @@ definitions: type: [string] additionalProperties: true - objectVariable: + objectVariable: allOf: - $ref: "#/definitions/baseVariable" - required: [type, attributes] @@ -551,7 +551,7 @@ definitions: format: variablereference additionalProperties: false additionalProperties: true - + imageVariable: allOf: - $ref: "#/definitions/baseVariable" @@ -1465,4 +1465,4 @@ definitions: enum: [ocid] value: $ref: "#/definitions/ocid" - additionalProperties: true \ No newline at end of file + additionalProperties: true From 30aa96d4cd5e38359fcd26709d038754f623acaa Mon Sep 17 00:00:00 2001 From: gotsysdba Date: Fri, 7 Nov 2025 08:08:57 +0000 Subject: [PATCH 2/2] IaC Updates --- helm/templates/_helpers.tpl | 21 +++++++++++++++++++++ helm/templates/server/oci-configmap.yaml | 13 ++++++------- opentofu/modules/kubernetes/output.tf | 2 +- opentofu/output.tf | 19 ++++++++++++------- opentofu/variables.tf | 6 ++++++ pyproject.toml | 6 +++--- 6 files changed, 49 insertions(+), 18 deletions(-) diff --git a/helm/templates/_helpers.tpl b/helm/templates/_helpers.tpl index a5debdf8..fcb3b731 100644 --- a/helm/templates/_helpers.tpl +++ b/helm/templates/_helpers.tpl @@ -243,6 +243,27 @@ Requires either 'dsn' OR all of (host, port, service_name). {{- end -}} {{- end -}} +{{/* ****************************************** +Validate that if server.oci_config.configMapName is specified, +then none of the other OCI config values (tenancy, user, fingerprint, region) should be provided. +*********************************************** */}} +{{- define "server.ociConfig.validate" -}} + {{- if .Values.server.oci_config -}} + {{- $configMapName := .Values.server.oci_config.configMapName | trim | default "" -}} + {{- $tenancy := .Values.server.oci_config.tenancy | trim | default "" -}} + {{- $user := .Values.server.oci_config.user | trim | default "" -}} + {{- $fingerprint := .Values.server.oci_config.fingerprint | trim | default "" -}} + {{- $region := .Values.server.oci_config.region | trim | default "" -}} + + {{- /* If configMapName is provided, ensure no other config values are provided */ -}} + {{- if ne $configMapName "" -}} + {{- if or (ne $tenancy "") (ne $user "") (ne $fingerprint "") (ne $region "") -}} + {{- fail "server.oci_config.configMapName is specified: you cannot also provide tenancy, user, fingerprint, or region. Either provide configMapName to reference an existing ConfigMap, OR provide the config values to create a new ConfigMap." -}} + {{- end -}} + {{- end -}} + {{- end -}} +{{- end -}} + {{/* ****************************************** Database Type Helpers diff --git a/helm/templates/server/oci-configmap.yaml b/helm/templates/server/oci-configmap.yaml index 0cd01490..d56bf1f7 100644 --- a/helm/templates/server/oci-configmap.yaml +++ b/helm/templates/server/oci-configmap.yaml @@ -3,14 +3,13 @@ # spell-checker: ignore nindent {{- if .Values.server.oci_config }} -{{- /* Determine the ConfigMap name to use or create */ -}} -{{- $configMapName := .Values.server.oci_config.configMapName | default (printf "%s-oci-config" .Release.Name) }} +{{- /* Validate OCI config settings */ -}} +{{- include "server.ociConfig.validate" . }} +{{- /* Only create ConfigMap if configMapName is not specified (user wants us to create it) */ -}} +{{- if not .Values.server.oci_config.configMapName }} +{{- /* Determine the default ConfigMap name */ -}} +{{- $configMapName := printf "%s-oci-config" .Release.Name }} -{{- /* Check if the ConfigMap already exists */ -}} -{{- $configMapExists := lookup "v1" "ConfigMap" .Release.Namespace $configMapName }} - -{{- /* Only create ConfigMap if it doesn't exist */ -}} -{{- if not $configMapExists }} apiVersion: v1 kind: ConfigMap metadata: diff --git a/opentofu/modules/kubernetes/output.tf b/opentofu/modules/kubernetes/output.tf index c88e7352..cba3e198 100644 --- a/opentofu/modules/kubernetes/output.tf +++ b/opentofu/modules/kubernetes/output.tf @@ -5,7 +5,7 @@ output "kubeconfig_cmd" { description = "Command to generate kubeconfig file" value = format( - "oci ce cluster create-kubeconfig --cluster-id %s --region %s --token-version 2.0.0 --kube-endpoint %s --file $HOME/.kube/config", + "oci ce cluster create-kubeconfig --cluster-id %s --region %s --token-version 2.0.0 --kube-endpoint %s --file $HOME/.kube/config --with-auth-context --profile DEFAULT", oci_containerengine_cluster.default_cluster.id, var.region, oci_containerengine_cluster.default_cluster.endpoint_config[0].is_public_ip_enabled ? "PUBLIC_ENDPOINT" : "PRIVATE_ENDPOINT" diff --git a/opentofu/output.tf b/opentofu/output.tf index 25e7300a..2dba6bf8 100644 --- a/opentofu/output.tf +++ b/opentofu/output.tf @@ -3,16 +3,21 @@ # spell-checker: disable output "app_version" { - description = "Oracle AI Optimizer and Toolkit Version" + description = "Application Version" value = local.app_version } -output "client_url" { - description = "URL for Client Access" - value = format("http://%s", oci_load_balancer_load_balancer.lb.ip_address_details[0].ip_address) +output "app_name" { + description = "Application Name (Label). The namespace for K8s installations" + value = local.label_prefix } -output "server_url" { - description = "URL for Client Access" - value = format("http://%s:8000/v1/docs", oci_load_balancer_load_balancer.lb.ip_address_details[0].ip_address) +output "optimizer_client_url" { + description = "URL for AI Optimizer and Toolkit Client Access" + value = var.deploy_optimizer ? format("http://%s", oci_load_balancer_load_balancer.lb.ip_address_details[0].ip_address) : "N/A" +} + +output "optimizer_server_url" { + description = "URL for AI Optimizer and Toolkit Server API Access" + value = var.deploy_optimizer ? format("http://%s:8000/v1/docs", oci_load_balancer_load_balancer.lb.ip_address_details[0].ip_address) : "N/A" } diff --git a/opentofu/variables.tf b/opentofu/variables.tf index 494757d1..f9806e79 100644 --- a/opentofu/variables.tf +++ b/opentofu/variables.tf @@ -7,6 +7,12 @@ ######################################################################### // Standard Default Vars +variable "deploy_optimizer" { + description = "Determines if the AI Optimizer and Toolkit is deployed" + type = bool + default = true +} + variable "optimizer_version" { description = "Determines if latest release or main code line is used" type = string diff --git a/pyproject.toml b/pyproject.toml index 715dc7c3..721e8871 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -26,7 +26,7 @@ server = [ "bokeh==3.8.0", "evaluate==0.4.6", "faiss-cpu==1.12.0", - "fastapi==0.120.2", + "fastapi==0.121.0", "fastmcp==2.13.0.2", "giskard==2.18.0", "langchain-aimlapi==0.1.0", @@ -43,12 +43,12 @@ server = [ "langchain-openai==0.3.35", "langchain-together==0.3.1", "langgraph==1.0.1", - "litellm==1.79.0", + "litellm==1.79.1", "llama-index==0.14.5", "lxml==6.0.2", "matplotlib==3.10.7", "oci~=2.0", - "psutil==7.1.2", + "psutil==7.1.3", "python-multipart==0.0.20", "torch==2.9.0", "umap-learn==0.5.9.post2",