Skip to content
This repository was archived by the owner on Mar 11, 2026. It is now read-only.

Commit 103e31e

Browse files
authored
feat(deploy): implement robotics infrastructure with Azure resources (#9)
* feat(deploy): implement robotics infrastructure with Azure resources - add Terraform configurations for resource group, AKS, PostgreSQL, and Redis - create deployment scripts for OSMO Control Plane components - define Helm charts and values for OSMO services - establish internal load balancer ingress for secure connectivity 🔧 - Generated by Copilot * chore(deploy): remove unused variable for OSMO private DNS creation 🔒 - Generated by Copilot * feat(deploy): add key vault output for robotics secrets - include key vault name in outputs - remove unused variables for PostgreSQL and Redis 🔒 - Generated by Copilot
1 parent 959ca7b commit 103e31e

17 files changed

Lines changed: 1525 additions & 0 deletions

.cspell-dictionary.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,4 @@ PYTHONHASHSEED
1010
PYTHONPATH
1111
rollouts
1212
skrl
13+
tolerations

.gitignore

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -396,6 +396,35 @@ MigrationBackup/
396396
# Fody - auto-generated XML schema
397397
FodyWeavers.xsd
398398

399+
# Local .terraform directories
400+
**/.terraform/*
401+
402+
# .tfstate files
403+
*.tfstate
404+
*.tfstate.*
405+
406+
# Ignore tfplan files
407+
*.tfplan
408+
409+
# Ignore .terraform lock
410+
.terraform.lock.hcl
411+
412+
# Crash log files
413+
crash.log
414+
415+
# Ignore all .tfvars files, which are likely to contain sensitive data, such as passwords
416+
*.tfvars
417+
418+
# Ignore override files as they are usually used to override resources locally and should not be shared
419+
override.tf
420+
override.tf.json
421+
*_override.tf
422+
*_override.tf.json
423+
424+
# Ignore CLI configuration files
425+
.terraformrc
426+
terraform.rc
427+
399428
# VS Code files for those working on multiple tools
400429
.vscode/*
401430
!.vscode/settings.json
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
#!/usr/bin/env bash
2+
3+
tenant=""
4+
help="Usage: az-sub-init.sh [--tenant your-tenant.onmicrosoft.com] [--help]
5+
6+
Attempts to set the ARM_SUBSCRIPTION_ID env var to 'id' from 'az account show' in the following ways:
7+
- 'az login' if not logged in (optionally with specific tenant)
8+
- 'az account show -o tsv --query id' for the current logged in account
9+
10+
Needed for Terraform
11+
12+
Current ARM_SUBSCRIPTION_ID: ${ARM_SUBSCRIPTION_ID}"
13+
14+
while [[ $# -gt 0 ]]; do
15+
case $1 in
16+
--tenant)
17+
tenant="$2"
18+
shift 2
19+
;;
20+
--help)
21+
echo "${help}"
22+
exit 0
23+
;;
24+
*)
25+
echo "${help}"
26+
echo
27+
echo "Unknown option: $1"
28+
exit 1
29+
;;
30+
esac
31+
done
32+
33+
get_current_subscription_id() {
34+
az account show -o tsv --query "id" 2>/dev/null
35+
}
36+
37+
is_correct_tenant() {
38+
if [[ -z "${tenant}" ]]; then
39+
return 0 # No specific tenant required
40+
fi
41+
42+
local current_tenant
43+
current_tenant=$(az rest --method get --url https://graph.microsoft.com/v1.0/domains \
44+
--query 'value[?isDefault].id' -o tsv 2>/dev/null || echo "")
45+
46+
[[ "${tenant}" == "${current_tenant}" ]]
47+
}
48+
49+
login_to_azure() {
50+
echo "Logging into Azure..."
51+
if [[ -n "${tenant}" ]]; then
52+
if ! az login --tenant "${tenant}"; then
53+
echo "Error: Failed to login to Azure with tenant ${tenant}"
54+
exit 1
55+
fi
56+
else
57+
if ! az login; then
58+
echo "Error: Failed to login to Azure"
59+
exit 1
60+
fi
61+
fi
62+
}
63+
64+
current_subscription_id=$(get_current_subscription_id)
65+
66+
if [[ -z "${current_subscription_id}" ]] || ! is_correct_tenant; then
67+
login_to_azure
68+
69+
current_subscription_id=$(get_current_subscription_id)
70+
if [[ -z "${current_subscription_id}" ]]; then
71+
echo "Error: Login succeeded but could not retrieve subscription ID"
72+
exit 1
73+
fi
74+
fi
75+
76+
export ARM_SUBSCRIPTION_ID="${current_subscription_id}"
77+
echo "ARM_SUBSCRIPTION_ID set to: ${ARM_SUBSCRIPTION_ID}"
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
#!/usr/bin/env bash
2+
# Generate MEK for OSMO
3+
4+
# Generate random 32-byte key
5+
RANDOM_KEY="$(openssl rand -base64 32 | tr -d '\n')"
6+
7+
# Create JWK
8+
JWK_JSON="{\"k\":\"$RANDOM_KEY\",\"kid\":\"key1\",\"kty\":\"oct\"}"
9+
10+
# Base64 encode the JWK
11+
ENCODED_JWK="$(echo -n "$JWK_JSON" | base64 | tr -d '\n')"
12+
13+
mkdir -p ./out
14+
15+
cat > ./out/mek-config.yaml <<EOF
16+
apiVersion: v1
17+
kind: ConfigMap
18+
metadata:
19+
name: mek-config
20+
data:
21+
mek.yaml: |
22+
currentMek: key1
23+
meks:
24+
key1: $ENCODED_JWK
25+
EOF
26+
27+
echo "ConfigMap written to ./out/mek-config.yaml"

deploy/001-iac/dns/main.tf

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/**
2+
* Private DNS Zone for OSMO UI Service
3+
*
4+
* Creates a private DNS zone for internal resolution of the OSMO UI service
5+
* running on an internal LoadBalancer within the AKS cluster.
6+
*/
7+
locals {
8+
resource_group_name = coalesce(var.resource_group_name, "rg-${var.resource_prefix}-${var.environment}-${var.instance}")
9+
virtual_network_name = coalesce(var.virtual_network_name, "vnet-${var.resource_prefix}-${var.environment}-${var.instance}")
10+
}
11+
12+
data "azurerm_virtual_network" "this" {
13+
name = local.virtual_network_name
14+
resource_group_name = local.resource_group_name
15+
}
16+
17+
resource "azurerm_private_dns_zone" "osmo" {
18+
name = var.osmo_private_dns_zone_name
19+
resource_group_name = local.resource_group_name
20+
}
21+
22+
resource "azurerm_private_dns_zone_virtual_network_link" "osmo" {
23+
name = "vnet-pzl-osmo-${var.resource_prefix}-${var.environment}-${var.instance}"
24+
resource_group_name = local.resource_group_name
25+
private_dns_zone_name = azurerm_private_dns_zone.osmo.name
26+
virtual_network_id = data.azurerm_virtual_network.this.id
27+
registration_enabled = false
28+
}
29+
30+
resource "azurerm_private_dns_a_record" "osmo" {
31+
name = var.osmo_hostname
32+
zone_name = azurerm_private_dns_zone.osmo.name
33+
resource_group_name = local.resource_group_name
34+
ttl = 300
35+
records = [var.osmo_loadbalancer_ip]
36+
}

deploy/001-iac/dns/outputs.tf

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
/*
2+
* OSMO Private DNS Outputs
3+
*/
4+
5+
output "osmo_private_dns_zone" {
6+
description = "Private DNS zone for OSMO services"
7+
value = {
8+
id = azurerm_private_dns_zone.osmo.id
9+
name = azurerm_private_dns_zone.osmo.name
10+
resource_group = azurerm_private_dns_zone.osmo.resource_group_name
11+
}
12+
}
13+
14+
output "osmo_fqdn" {
15+
description = "Fully qualified domain name for OSMO service"
16+
value = "${var.osmo_hostname}.${var.osmo_private_dns_zone_name}"
17+
}

deploy/001-iac/dns/variables.tf

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
/*
2+
* Core Variables - Required
3+
*/
4+
5+
variable "environment" {
6+
type = string
7+
description = "Environment for all resources in this module: dev, test, or prod"
8+
}
9+
10+
variable "location" {
11+
type = string
12+
description = "Location for all resources in this module"
13+
}
14+
15+
variable "resource_prefix" {
16+
type = string
17+
description = "Prefix for all resources in this module"
18+
}
19+
20+
/*
21+
* Core Variables - Optional
22+
*/
23+
24+
variable "instance" {
25+
type = string
26+
description = "Instance identifier for naming resources: 001, 002, etc"
27+
default = "001"
28+
}
29+
30+
variable "resource_group_name" {
31+
type = string
32+
description = "Existing resource group name containing foundational and ML resources (Otherwise 'rg-{resource_prefix}-{environment}-{instance}')"
33+
default = null
34+
}
35+
36+
variable "virtual_network_name" {
37+
type = string
38+
description = "Existing virtual network name (Otherwise 'vnet-{resource_prefix}-{environment}-{instance}')"
39+
default = null
40+
}
41+
42+
/*
43+
* OSMO Private DNS Configuration - Required
44+
*/
45+
46+
variable "osmo_loadbalancer_ip" {
47+
type = string
48+
description = "Internal LoadBalancer IP address for the OSMO service"
49+
}
50+
51+
/*
52+
* OSMO Private DNS Configuration - Optional
53+
*/
54+
55+
variable "osmo_private_dns_zone_name" {
56+
type = string
57+
description = "Private DNS zone name for OSMO services (e.g., osmo.local, osmo.internal)"
58+
default = "osmo.local"
59+
}
60+
61+
variable "osmo_hostname" {
62+
type = string
63+
description = "Hostname for the OSMO service within the private DNS zone"
64+
default = "dev"
65+
}

deploy/001-iac/dns/versions.tf

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
terraform {
2+
required_providers {
3+
azurerm = {
4+
source = "hashicorp/azurerm"
5+
version = ">= 4.51.0"
6+
}
7+
}
8+
required_version = ">= 1.9.8, < 2.0"
9+
}
10+
11+
provider "azurerm" {
12+
storage_use_azuread = true
13+
partner_id = "acce1e78-0375-4637-a593-86aa36dcfeac"
14+
features {}
15+
}

0 commit comments

Comments
 (0)