Skip to content
Draft
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
112 changes: 112 additions & 0 deletions src/aks-preview/azext_aks_preview/_help.py
Original file line number Diff line number Diff line change
Expand Up @@ -4453,3 +4453,115 @@
- name: Show a specific JWT authenticator configuration
text: az aks jwtauthenticator show -g MyResourceGroup --cluster-name MyCluster --name myjwt
"""

helps['aks openclaw'] = """
type: group
short-summary: Commands to deploy and manage OpenClaw on an AKS cluster.
"""

helps['aks openclaw deploy'] = """
type: command
short-summary: Deploy OpenClaw with Azure AI Foundry on an AKS cluster.
long-summary: |
Provisions Azure AI Foundry resources (or uses an existing one), deploys the
openclaw-kubernetes Helm chart with LiteLLM proxy, and configures the web UI.
By default, a new AIServices account is created using the resource group's location
and an auto-generated name. Use --ai-foundry-resource-id or --ai-foundry-endpoint
to bring your own AI Foundry resource instead.
parameters:
- name: --cluster-name
type: string
short-summary: Name of the AKS cluster.
- name: --ai-foundry-resource-id
type: string
short-summary: Full ARM resource ID of an existing AIServices account (BYO mode).
- name: --ai-foundry-endpoint
type: string
short-summary: Endpoint URL of an existing AI Foundry resource (BYO mode). Requires --ai-foundry-api-key.
- name: --ai-foundry-api-key
type: string
short-summary: API key for the AI Foundry endpoint. Required with --ai-foundry-endpoint.
- name: --ai-foundry-location
type: string
short-summary: Azure region for provisioning a new AIServices account. Defaults to the resource group's location.
- name: --model
type: string
short-summary: Model name to deploy. Default is gpt-5.1-chat.
- name: --model-version
type: string
short-summary: Model version to deploy. Default is 2025-11-13. Only used when provisioning new resources.
- name: --deployment-name
type: string
short-summary: Azure model deployment name. Auto-generated if not specified.
- name: --capacity
type: int
short-summary: Tokens-per-minute capacity for the model deployment. Default is 50. Only used when provisioning new resources.
- name: --namespace
type: string
short-summary: Kubernetes namespace for OpenClaw. Default is openclaw.
examples:
- name: Deploy OpenClaw with auto-provisioned AI Foundry (simplest)
text: az aks openclaw deploy -g MyResourceGroup --cluster-name MyCluster
- name: Deploy with a specific model and region override
text: az aks openclaw deploy -g MyResourceGroup --cluster-name MyCluster --model gpt-4o --ai-foundry-location westus
- name: Deploy using an existing AI Foundry resource (BYO by resource ID)
text: az aks openclaw deploy -g MyResourceGroup --cluster-name MyCluster --ai-foundry-resource-id /subscriptions/SUB_ID/resourceGroups/RG/providers/Microsoft.CognitiveServices/accounts/myaccount
- name: Deploy using a raw endpoint and API key (BYO by endpoint)
text: az aks openclaw deploy -g MyResourceGroup --cluster-name MyCluster --ai-foundry-endpoint https://eastus.api.cognitive.microsoft.com --ai-foundry-api-key MY_KEY --deployment-name gpt51chat
"""

helps['aks openclaw delete'] = """
type: command
short-summary: Delete OpenClaw deployment from an AKS cluster.
parameters:
- name: --cluster-name
type: string
short-summary: Name of the AKS cluster.
- name: --namespace
type: string
short-summary: Kubernetes namespace where OpenClaw is deployed. Default is openclaw.
- name: --delete-ai-resources
type: bool
short-summary: Also delete the auto-provisioned AIServices account. Default is false.
examples:
- name: Delete OpenClaw deployment
text: az aks openclaw delete -g MyResourceGroup --cluster-name MyCluster --yes
- name: Delete OpenClaw and the provisioned AI Foundry resources
text: az aks openclaw delete -g MyResourceGroup --cluster-name MyCluster --delete-ai-resources --yes
"""

helps['aks openclaw show'] = """
type: command
short-summary: Show OpenClaw deployment status on an AKS cluster.
parameters:
- name: --cluster-name
type: string
short-summary: Name of the AKS cluster.
- name: --namespace
type: string
short-summary: Kubernetes namespace where OpenClaw is deployed. Default is openclaw.
examples:
- name: Show OpenClaw status
text: az aks openclaw show -g MyResourceGroup --cluster-name MyCluster
"""

helps['aks openclaw connect'] = """
type: command
short-summary: Get OpenClaw gateway token and help with web UI connection.
long-summary: |
Retrieves the OpenClaw gateway authentication token from the K8s secret
and displays instructions for connecting to the web UI via port-forward.
Provides a direct link with the token embedded as a query parameter.
parameters:
- name: --cluster-name
type: string
short-summary: Name of the AKS cluster.
- name: --namespace
type: string
short-summary: Kubernetes namespace where OpenClaw is deployed. Default is openclaw.
examples:
- name: Get connection info and token
text: az aks openclaw connect -g MyResourceGroup --cluster-name MyCluster
- name: Get connection info for custom namespace
text: az aks openclaw connect -g MyResourceGroup --cluster-name MyCluster --namespace custom-ns
"""
56 changes: 56 additions & 0 deletions src/aks-preview/azext_aks_preview/_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -3149,6 +3149,62 @@ def load_arguments(self, _):
c.argument('config_file', options_list=['--config-file'], type=file_type, completer=FilesCompleter(),
help='Path to the JSON configuration file containing JWT authenticator properties.')

# OpenClaw commands
with self.argument_context("aks openclaw") as c:
c.argument("cluster_name", options_list=["--cluster-name"], help="The AKS cluster name.")
c.argument("namespace", help="Kubernetes namespace for OpenClaw. Default is openclaw.")

with self.argument_context("aks openclaw deploy") as c:
c.argument(
"ai_foundry_resource_id",
options_list=["--ai-foundry-resource-id"],
help="Full ARM resource ID of an existing AIServices account (BYO mode).",
)
c.argument(
"ai_foundry_endpoint",
options_list=["--ai-foundry-endpoint"],
help="Endpoint URL of an existing AI Foundry resource (BYO mode). Requires --ai-foundry-api-key.",
)
c.argument(
"ai_foundry_api_key",
options_list=["--ai-foundry-api-key"],
help="API key for the AI Foundry endpoint. Required with --ai-foundry-endpoint.",
)
c.argument(
"ai_foundry_location",
options_list=["--ai-foundry-location"],
help="Azure region for provisioning a new AIServices account. Defaults to the resource group's location.",
)
c.argument(
"model",
options_list=["--model"],
help="Model name to deploy. Default is gpt-5.1-chat.",
)
c.argument(
"model_version",
options_list=["--model-version"],
help="Model version to deploy. Default is 2025-11-13. Only used when provisioning new resources.",
)
c.argument(
"model_deployment_name",
options_list=["--deployment-name"],
help="Azure model deployment name. Auto-generated from model name if not specified.",
)
c.argument(
"capacity",
options_list=["--capacity"],
type=int,
help="Tokens-per-minute capacity for the model deployment. Default is 50.",
)

with self.argument_context("aks openclaw delete") as c:
c.argument(
"delete_ai_resources",
options_list=["--delete-ai-resources"],
action="store_true",
help="Also delete the auto-provisioned AIServices account.",
)


def _get_default_install_location(exe_name):
system = platform.system()
Expand Down
11 changes: 11 additions & 0 deletions src/aks-preview/azext_aks_preview/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -603,3 +603,14 @@ def load_command_table(self, _):
self.command_table["aks safeguards delete"] = Delete(loader=self)
self.command_table["aks safeguards list"] = List(loader=self)
self.command_table["aks safeguards wait"] = Wait(loader=self)

# AKS openclaw commands
with self.command_group(
"aks openclaw",
managed_clusters_sdk,
client_factory=cf_managed_clusters,
) as g:
g.custom_command("deploy", "aks_openclaw_deploy")
g.custom_command("delete", "aks_openclaw_delete", confirmation=True)
g.custom_show_command("show", "aks_openclaw_show")
g.custom_command("connect", "aks_openclaw_connect")
52 changes: 52 additions & 0 deletions src/aks-preview/azext_aks_preview/custom.py
Original file line number Diff line number Diff line change
Expand Up @@ -5375,3 +5375,55 @@ def aks_jwtauthenticator_list(cmd, client, resource_group_name, cluster_name, ak
def aks_jwtauthenticator_show(cmd, client, resource_group_name, cluster_name, name, aks_custom_headers=None):
headers = get_aks_custom_headers(aks_custom_headers)
return client.get(resource_group_name, cluster_name, name, headers=headers)


# openclaw commands
def aks_openclaw_deploy(cmd, client, resource_group_name, cluster_name,
ai_foundry_resource_id=None,
ai_foundry_endpoint=None,
ai_foundry_api_key=None,
ai_foundry_location=None,
model=None,
model_version=None,
model_deployment_name=None,
capacity=None,
namespace=None):
from azext_aks_preview.openclaw.deploy import deploy_openclaw
return deploy_openclaw(
cmd, resource_group_name, cluster_name,
ai_foundry_resource_id=ai_foundry_resource_id,
ai_foundry_endpoint=ai_foundry_endpoint,
ai_foundry_api_key=ai_foundry_api_key,
ai_foundry_location=ai_foundry_location,
model=model,
model_version=model_version,
deployment_name=model_deployment_name,
capacity=capacity,
namespace=namespace,
)


def aks_openclaw_delete(cmd, client, resource_group_name, cluster_name,
namespace=None):
from azext_aks_preview.openclaw.deploy import delete_openclaw
return delete_openclaw(
cmd, resource_group_name, cluster_name,
namespace=namespace,
)


def aks_openclaw_show(cmd, client, resource_group_name, cluster_name,
namespace=None):
from azext_aks_preview.openclaw.deploy import show_openclaw
return show_openclaw(
cmd, resource_group_name, cluster_name,
namespace=namespace,
)


def aks_openclaw_connect(cmd, client, resource_group_name, cluster_name=None, namespace=None):
from azext_aks_preview.openclaw.deploy import connect_openclaw
return connect_openclaw(
cmd, resource_group_name, cluster_name=cluster_name,
namespace=namespace,
)
4 changes: 4 additions & 0 deletions src/aks-preview/azext_aks_preview/openclaw/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# --------------------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License.txt in the project root for license information.
# --------------------------------------------------------------------------------------------
23 changes: 23 additions & 0 deletions src/aks-preview/azext_aks_preview/openclaw/_consts.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# --------------------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License.txt in the project root for license information.
# --------------------------------------------------------------------------------------------

# Helm chart
CONST_OPENCLAW_HELM_CHART_URL = "oci://ghcr.io/feiskyer/openclaw-kubernetes/openclaw"
CONST_OPENCLAW_DEFAULT_NAMESPACE = "openclaw"

# Azure AI Foundry defaults
CONST_OPENCLAW_DEFAULT_MODEL = "gpt-5.1-chat"
CONST_OPENCLAW_DEFAULT_MODEL_VERSION = "2025-11-13"
CONST_OPENCLAW_DEFAULT_CAPACITY = 50
CONST_OPENCLAW_DEFAULT_SKU = "GlobalStandard"
CONST_OPENCLAW_AI_SERVICES_KIND = "AIServices"
CONST_OPENCLAW_AI_SERVICES_SKU = "S0"
CONST_OPENCLAW_COGNITIVE_API_VERSION = "2024-10-01"

# Storage
CONST_OPENCLAW_STORAGE_CLASS_NAME = "azurefile-openclaw"

# LiteLLM
CONST_OPENCLAW_LITELLM_API_VERSION = "2024-10-01-preview"
Loading
Loading