Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 23 additions & 12 deletions opentofu/cfgmgt/apply.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,12 @@
import time

# --- Constants ---
HELM_NAME = "ai-optimizer"
HELM_REPO = "https://oracle.github.io/ai-optimizer/helm"
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"

# --- Utility Functions ---
def mod_kubeconfig(private_endpoint: str = None):
Expand Down Expand Up @@ -78,8 +79,8 @@ def retry(func, retries=5, delay=15):
# --- Core Functionalities ---
def helm_repo_add_if_missing():
"""Add/Update Helm Repo"""
print(f"➕ Adding Helm repo '{HELM_NAME}'...")
_, stderr, rc = run_cmd(["helm", "repo", "add", HELM_NAME, HELM_REPO], capture_output=False)
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)
Expand All @@ -89,32 +90,42 @@ def helm_repo_add_if_missing():
if rc != 0:
print(f"❌ Failed to update repos:\n{stderr}")
sys.exit(1)
print(f"✅ Repo '{HELM_NAME}' added and updated.\n")
print(f"✅ Repo '{OPTIMIZER_HELM_NAME}' added and updated.\n")


def apply_helm_chart_inner(release_name, namespace):
"""Apply Helm Chart"""
values_path = os.path.join(STAGE_PATH, "optimizer-helm-values.yaml")
if not os.path.isfile(values_path):
print(f"⚠️ Values file not found: {values_path}")
# 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))
]

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()

# Build helm command with all values files
cmd = [
"helm",
"upgrade",
"--install",
release_name,
f"{HELM_NAME}/{HELM_NAME}",
f"{OPTIMIZER_HELM_NAME}/{OPTIMIZER_HELM_NAME}",
"--namespace",
namespace,
"--values",
values_path,
]

print(f"🚀 Applying Helm chart '{HELM_NAME}' to namespace '{namespace}'...")
# 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}'...")
stdout, stderr, rc = run_cmd(cmd)
if rc == 0:
print("✅ Helm chart applied:")
Expand Down
65 changes: 63 additions & 2 deletions opentofu/examples/manual-test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,19 @@ set -euo pipefail
# Navigate to opentofu root
cd "$(dirname "$(dirname "$0")")" || exit 1

# Check for tofu or terraform in PATH
if command -v tofu &> /dev/null; then
TF_CMD="tofu"
elif command -v terraform &> /dev/null; then
TF_CMD="terraform"
else
echo "Error: Neither 'tofu' nor 'terraform' found in PATH" >&2
exit 1
fi

echo "Using command: $TF_CMD"
echo ""

PROFILE="${1:-DEFAULT}"
OCI_CONFIG="${OCI_CONFIG_FILE:-$HOME/.oci/config}"

Expand Down Expand Up @@ -44,6 +57,51 @@ export TF_VAR_compartment_ocid="$TF_VAR_tenancy_ocid"
echo "✅ OCI credentials loaded (Profile: $PROFILE, Region: $TF_VAR_region)"
echo ""

# Pre-flight checks: format and validate
echo "Running pre-flight checks..."
echo ""

echo "1. Formatting code with '$TF_CMD fmt --recursive'..."
if $TF_CMD fmt --recursive > /dev/null; then
echo " ✅ Format check passed"
else
echo " ❌ Format check failed"
exit 1
fi

echo "2. Validating configuration with '$TF_CMD validate'..."
if $TF_CMD validate > /dev/null 2>&1; then
echo " ✅ Validation passed"
else
echo " ❌ Validation failed"
echo ""
echo "Re-run: $TF_CMD validate"
exit 1
fi

echo ""

# Check for existing deployed resources
if [ -f "terraform.tfstate" ] && [ -s "terraform.tfstate" ]; then
echo "Checking for deployed resources..."

# Use terraform state list to check if there are any managed resources
if resource_count=$($TF_CMD state list 2>/dev/null | wc -l | xargs); then
if [ "$resource_count" -gt 0 ]; then
echo "❌ ERROR: Found $resource_count deployed resource(s) in the state"
echo ""
echo "This test script requires a clean state to test multiple configurations."
echo "Please destroy existing resources first:"
echo ""
echo " $TF_CMD destroy -auto-approve"
echo ""
exit 1
else
echo " ✅ State file exists but no resources are deployed (likely from previous destroy)"
fi
fi
fi

# Run tests
EXAMPLES=(
examples/vm-new-adb.tfvars
Expand All @@ -56,13 +114,16 @@ EXAMPLES=(
for example in "${EXAMPLES[@]}"; do
echo "Testing $example..."

if plan_output=$(tofu plan -var-file="$example" 2>&1); then
if plan_output=$($TF_CMD plan -var-file="$example" 2>&1); then
plan_summary=$(echo "$plan_output" | grep -i "plan:" | tail -1 | sed 's/^[[:space:]]*//')
echo " ✅ ${plan_summary:-PASSED}"
else
echo " ❌ FAILED"
echo ""
echo "Re-run: tofu plan -var-file=$example"
echo "Error output:"
echo "$plan_output" | tail -20
echo ""
echo "Re-run: $TF_CMD plan -var-file=$example"
exit 1
fi
done
Expand Down
61 changes: 19 additions & 42 deletions opentofu/modules/kubernetes/cfgmgt.tf
Original file line number Diff line number Diff line change
Expand Up @@ -4,43 +4,27 @@

locals {
k8s_manifest = templatefile("${path.module}/templates/k8s_manifest.yaml", {
label = var.label_prefix
repository_host = local.repository_host
optimizer_repository_server = local.optimizer_repository_server
optimizer_repository_client = local.optimizer_repository_client
compartment_ocid = var.lb.compartment_id
lb_ocid = var.lb.id
lb_subnet_ocid = var.public_subnet_id
lb_ip_ocid = var.lb.ip_address_details[0].ip_address
lb_nsgs = var.lb_nsg_id
lb_min_shape = var.lb.shape_details[0].minimum_bandwidth_in_mbps
lb_max_shape = var.lb.shape_details[0].maximum_bandwidth_in_mbps
db_name = lower(var.db_name)
db_username = var.db_conn.username
db_password = var.db_conn.password
db_service = var.db_conn.service
optimizer_api_key = random_string.optimizer_api_key.result
deploy_buildkit = var.byo_ocir_url == ""
deploy_optimizer = var.deploy_optimizer
optimizer_version = var.optimizer_version
})

helm_values = templatefile("${path.module}/templates/optimizer_helm_values.yaml", {
label = var.label_prefix
optimizer_repository_server = local.optimizer_repository_server
optimizer_repository_client = local.optimizer_repository_client
oci_tenancy = var.tenancy_id
oci_region = var.region
db_type = var.db_conn.db_type
db_ocid = var.db_ocid
db_dsn = var.db_conn.service
db_name = lower(var.db_name)
node_pool_gpu_deploy = var.node_pool_gpu_deploy
lb_ip = var.lb.ip_address_details[0].ip_address
label = var.label_prefix
repository_host = local.repository_host
repository_base = local.repository_base
compartment_ocid = var.lb.compartment_id
lb_ocid = var.lb.id
lb_subnet_ocid = var.public_subnet_id
lb_ip_ocid = var.lb.ip_address_details[0].ip_address
lb_nsgs = var.lb_nsg_id
lb_min_shape = var.lb.shape_details[0].minimum_bandwidth_in_mbps
lb_max_shape = var.lb.shape_details[0].maximum_bandwidth_in_mbps
db_name = lower(var.db_name)
db_username = var.db_conn.username
db_password = var.db_conn.password
db_service = var.db_conn.service
optimizer_api_key = random_string.optimizer_api_key.result
deploy_buildkit = var.byo_ocir_url == ""
deploy_optimizer = var.deploy_optimizer
optimizer_version = var.optimizer_version
})
}


resource "local_sensitive_file" "kubeconfig" {
content = data.oci_containerengine_cluster_kube_config.default_cluster_kube_config.content
filename = "${path.root}/cfgmgt/stage/kubeconfig"
Expand All @@ -53,13 +37,6 @@ resource "local_sensitive_file" "k8s_manifest" {
file_permission = 0600
}

resource "local_sensitive_file" "optimizer_helm_values" {
count = var.deploy_optimizer ? 1 : 0
content = local.helm_values
filename = "${path.root}/cfgmgt/stage/optimizer-helm-values.yaml"
file_permission = 0600
}

resource "null_resource" "apply" {
count = var.run_cfgmgt ? 1 : 0
triggers = {
Expand All @@ -81,7 +58,7 @@ resource "null_resource" "apply" {
depends_on = [
local_sensitive_file.kubeconfig,
local_sensitive_file.k8s_manifest,
local_sensitive_file.optimizer_helm_values,
local_sensitive_file.optimizer_values,
oci_containerengine_node_pool.cpu_node_pool_details,
oci_containerengine_node_pool.gpu_node_pool_details,
oci_containerengine_addon.oraoper_addon,
Expand Down
24 changes: 24 additions & 0 deletions opentofu/modules/kubernetes/cfgmgt_optimizer.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Copyright (c) 2024, 2025, Oracle and/or its affiliates.
# All rights reserved. The Universal Permissive License (UPL), Version 1.0 as shown at http://oss.oracle.com/licenses/upl
# spell-checker: disable

locals {
optimizer_values = templatefile("${path.module}/templates/optimizer_values.yaml", {
label = var.label_prefix
repository_base = local.repository_base
oci_region = var.region
db_type = var.db_conn.db_type
db_ocid = var.db_ocid
db_dsn = var.db_conn.service
db_name = lower(var.db_name)
node_pool_gpu_deploy = var.node_pool_gpu_deploy
lb_ip = var.lb.ip_address_details[0].ip_address
})
}

resource "local_sensitive_file" "optimizer_values" {
count = var.deploy_optimizer ? 1 : 0
content = local.optimizer_values
filename = "${path.root}/cfgmgt/stage/optimizer-values.yaml"
file_permission = 0600
}
10 changes: 4 additions & 6 deletions opentofu/modules/kubernetes/locals.tf
Original file line number Diff line number Diff line change
Expand Up @@ -58,12 +58,10 @@ locals {
"ai-optimizer-server",
"ai-optimizer-client"
]
region_map = { for r in data.oci_identity_regions.identity_regions.regions : r.name => r.key }
image_region = lookup(local.region_map, var.region)
repository_host = lower(format("%s.ocir.io", local.image_region))
repository_base = var.byo_ocir_url != "" ? var.byo_ocir_url : lower(format("%s/%s/%s", local.repository_host, data.oci_objectstorage_namespace.objectstorage_namespace.namespace, var.label_prefix))
optimizer_repository_server = lower(format("%s/ai-optimizer-server", local.repository_base))
optimizer_repository_client = lower(format("%s/ai-optimizer-client", local.repository_base))
region_map = { for r in data.oci_identity_regions.identity_regions.regions : r.name => r.key }
image_region = lookup(local.region_map, var.region)
repository_host = lower(format("%s.ocir.io", local.image_region))
repository_base = var.byo_ocir_url != "" ? var.byo_ocir_url : lower(format("%s/%s/%s", local.repository_host, data.oci_objectstorage_namespace.objectstorage_namespace.namespace, var.label_prefix))
}

// Cluster Details
Expand Down
Loading
Loading