Skip to content

Commit b51def5

Browse files
Merge branch 'feature/issue-15-variable-standardization' into feature/issue-14-unified-standards
2 parents 3e9a42d + 422edba commit b51def5

7 files changed

Lines changed: 542 additions & 124 deletions

File tree

Lines changed: 22 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
# =============================================================================
2-
# validate-config.yml - Validate configuration files
2+
# validate-config.yml Validate config/variables.example.yml against schema
33
# =============================================================================
4-
# Validates YAML configs against JSON Schema and checks for syntax errors.
4+
# Triggered on PRs and pushes that touch config/ or this workflow.
5+
# Validates YAML syntax and JSON Schema compliance.
56
# =============================================================================
67

78
name: Validate Configuration
@@ -22,61 +23,38 @@ permissions:
2223
contents: read
2324

2425
jobs:
25-
validate-config:
26+
validate:
2627
runs-on: ubuntu-latest
2728

2829
steps:
2930
- name: Checkout repository
3031
uses: actions/checkout@v4
3132

32-
- name: Setup Node.js (for ajv-cli)
33-
uses: actions/setup-node@v4
33+
- name: Setup Python
34+
uses: actions/setup-python@v5
3435
with:
35-
node-version: '20'
36+
python-version: '3.12'
3637

37-
- name: Install validation tools
38-
run: |
39-
npm install -g ajv-cli yaml-lint
40-
41-
- name: Lint YAML files
42-
run: |
43-
find config -name '*.yml' -o -name '*.yaml' | while read f; do
44-
echo "Validating YAML syntax: $f"
45-
yamllint "$f" || echo "WARN: $f has lint issues"
46-
done
38+
- name: Install dependencies
39+
run: pip install pyyaml jsonschema
4740

48-
- name: Validate JSON files
41+
- name: Validate variables.example.yml against schema
4942
run: |
50-
find config -name '*.json' | while read f; do
51-
echo "Validating JSON syntax: $f"
52-
python3 -m json.tool "$f" > /dev/null
53-
done
54-
55-
- name: Validate master config against schema
56-
run: |
57-
# Convert YAML to JSON for schema validation
58-
pip install pyyaml
5943
python3 -c "
6044
import yaml, json, sys
61-
with open('config/variables/master-environment.yml') as f:
45+
from jsonschema import validate, ValidationError
46+
47+
with open('config/variables.example.yml') as f:
6248
data = yaml.safe_load(f)
63-
json.dump(data, sys.stdout)
64-
" > /tmp/master-config.json
6549
66-
ajv validate \
67-
-s config/variables/schema.json \
68-
-d /tmp/master-config.json \
69-
|| echo "Schema validation completed with issues"
50+
with open('config/schema/variables.schema.json') as f:
51+
schema = json.load(f)
7052
71-
- name: Validate solution configs
72-
run: |
73-
for f in config/variables/solutions/*.json; do
74-
echo "Checking solution config: $f"
75-
python3 -c "
76-
import json
77-
with open('$f') as fh:
78-
data = json.load(fh)
79-
assert '_metadata' in data, 'Missing _metadata section'
80-
print(f\" Solution: {data['_metadata']['solution']} - OK\")
53+
try:
54+
validate(instance=data, schema=schema)
55+
print('✅ config/variables.example.yml passes schema validation')
56+
except ValidationError as e:
57+
print(f'❌ Schema validation failed: {e.message}')
58+
print(f' Path: {\" > \".join(str(p) for p in e.absolute_path)}')
59+
sys.exit(1)
8160
"
82-
done

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@ config/credentials/*.key
3333
config/credentials/*.pem
3434
config/credentials/.env
3535

36+
# User-specific config (actual values — never commit)
37+
config/variables.yml
38+
3639
# Generated solution config files (built from master-environment.yml)
3740
# Uncomment the next line if you want these regenerated every time:
3841
# config/variables/solutions/*.json
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
{
2+
"$schema": "http://json-schema.org/draft-07/schema#",
3+
"$id": "https://github.com/AzureLocal/azurelocal-loadtools/config/schema/variables.schema.json",
4+
"title": "Load Tools Variables",
5+
"description": "Schema for config/variables.example.yml — validates required sections and key structure.",
6+
"type": "object",
7+
"required": ["azure", "keyvault", "azure_local", "storage", "credentials", "testing", "tags"],
8+
"properties": {
9+
"azure": {
10+
"type": "object",
11+
"required": ["subscription_id", "tenant_id", "resource_group", "location"],
12+
"properties": {
13+
"subscription_id": { "type": "string" },
14+
"tenant_id": { "type": "string" },
15+
"resource_group": { "type": "string" },
16+
"location": { "type": "string" }
17+
}
18+
},
19+
"keyvault": {
20+
"type": "object",
21+
"required": ["name"],
22+
"properties": {
23+
"name": { "type": "string" },
24+
"auth_method": { "type": "string", "enum": ["managed_identity", "service_principal", "az_cli"] }
25+
}
26+
},
27+
"azure_local": {
28+
"type": "object",
29+
"required": ["cluster_name", "nodes"],
30+
"properties": {
31+
"cluster_name": { "type": "string" },
32+
"cluster_domain": { "type": "string" },
33+
"nodes": {
34+
"type": "array",
35+
"minItems": 1,
36+
"items": {
37+
"type": "object",
38+
"required": ["name", "management_ip"],
39+
"properties": {
40+
"name": { "type": "string" },
41+
"management_ip": { "type": "string" },
42+
"storage_ip": { "type": "string" }
43+
}
44+
}
45+
}
46+
}
47+
},
48+
"storage": {
49+
"type": "object",
50+
"required": ["csv_path"],
51+
"properties": {
52+
"csv_path": { "type": "string" },
53+
"collect_volume_path": { "type": "string" },
54+
"base_vhd_path": { "type": "string" }
55+
}
56+
},
57+
"networking": {
58+
"type": "object",
59+
"properties": {
60+
"management": {
61+
"type": "object",
62+
"properties": {
63+
"subnet": { "type": "string" },
64+
"vlan_id": { "type": "integer" }
65+
}
66+
},
67+
"storage": {
68+
"type": "object",
69+
"properties": {
70+
"subnet": { "type": "string" },
71+
"vlan_id": { "type": "integer" },
72+
"rdma_enabled": { "type": "boolean" }
73+
}
74+
},
75+
"compute": {
76+
"type": "object",
77+
"properties": {
78+
"subnet": { "type": "string" },
79+
"vlan_id": { "type": "integer" }
80+
}
81+
}
82+
}
83+
},
84+
"credentials": {
85+
"type": "object",
86+
"required": ["cluster_admin_username", "cluster_admin_password"],
87+
"properties": {
88+
"cluster_admin_username": { "type": "string" },
89+
"cluster_admin_password": { "type": "string" },
90+
"vmfleet_admin_username": { "type": "string" },
91+
"vmfleet_admin_password": { "type": "string" }
92+
}
93+
},
94+
"testing": {
95+
"type": "object",
96+
"required": ["default_tool"],
97+
"properties": {
98+
"default_tool": { "type": "string", "enum": ["vmfleet", "fio", "iperf", "hammerdb", "stress-ng"] },
99+
"default_profile": { "type": "string" },
100+
"duration_seconds": { "type": "integer", "minimum": 1 },
101+
"warmup_seconds": { "type": "integer", "minimum": 0 }
102+
}
103+
},
104+
"monitoring": {
105+
"type": "object",
106+
"properties": {
107+
"log_analytics_workspace_id": { "type": "string" },
108+
"log_analytics_shared_key": { "type": "string" },
109+
"enable_real_time": { "type": "boolean" },
110+
"collection_interval_seconds": { "type": "integer", "minimum": 1 }
111+
}
112+
},
113+
"reporting": {
114+
"type": "object",
115+
"properties": {
116+
"output_dir": { "type": "string" },
117+
"format": { "type": "string", "enum": ["html", "json", "csv"] },
118+
"include_charts": { "type": "boolean" }
119+
}
120+
},
121+
"winrm": {
122+
"type": "object",
123+
"properties": {
124+
"port": { "type": "integer" },
125+
"use_ssl": { "type": "boolean" },
126+
"authentication": { "type": "string", "enum": ["Kerberos", "Negotiate", "Basic"] },
127+
"operation_timeout_seconds": { "type": "integer", "minimum": 1 }
128+
}
129+
},
130+
"tags": {
131+
"type": "object",
132+
"additionalProperties": { "type": "string" }
133+
}
134+
},
135+
"additionalProperties": false
136+
}

config/variables.example.yml

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
# =============================================================================
2+
# variables.example.yml
3+
# Central configuration — single source of truth for load testing deployments.
4+
#
5+
# Copy this file to variables.yml and fill in your values:
6+
# cp config/variables.example.yml config/variables.yml
7+
#
8+
# DO NOT commit variables.yml — it is excluded by .gitignore.
9+
#
10+
# Key Vault References:
11+
# Secrets use keyvault:// URIs and are resolved at runtime.
12+
# Format: keyvault://<vault-name>/<secret-name>
13+
# NEVER put actual passwords or secrets in this file.
14+
#
15+
# Detailed configs live in subdirectories:
16+
# - config/clusters/ Cluster definitions (per-cluster YAML)
17+
# - config/credentials/ Key Vault credential mappings
18+
# - config/profiles/ Workload profiles (vmfleet, fio, iperf, etc.)
19+
# - config/variables/ Master variable registry and solution schemas
20+
# =============================================================================
21+
22+
23+
# =============================================================================
24+
# Azure
25+
# =============================================================================
26+
azure:
27+
subscription_id: "00000000-0000-0000-0000-000000000000"
28+
tenant_id: "00000000-0000-0000-0000-000000000000"
29+
resource_group: "rg-loadtools-eus-01"
30+
location: "eastus"
31+
32+
33+
# =============================================================================
34+
# Key Vault
35+
# =============================================================================
36+
keyvault:
37+
name: "kv-iic-loadtools"
38+
auth_method: "az_cli" # managed_identity | service_principal | az_cli
39+
40+
41+
# =============================================================================
42+
# Azure Local Cluster
43+
# =============================================================================
44+
azure_local:
45+
cluster_name: "azl-cluster-01"
46+
cluster_domain: "iic.local"
47+
nodes:
48+
- name: "azl-node-01"
49+
management_ip: "10.0.0.1"
50+
storage_ip: "10.0.1.1"
51+
- name: "azl-node-02"
52+
management_ip: "10.0.0.2"
53+
storage_ip: "10.0.1.2"
54+
55+
56+
# =============================================================================
57+
# Storage
58+
# =============================================================================
59+
storage:
60+
csv_path: "C:\\ClusterStorage\\Volume1"
61+
collect_volume_path: "C:\\ClusterStorage\\Collect"
62+
base_vhd_path: "C:\\ClusterStorage\\Collect\\BaseImage.vhdx"
63+
64+
65+
# =============================================================================
66+
# Networking
67+
# =============================================================================
68+
networking:
69+
management:
70+
subnet: "10.0.0.0/24"
71+
vlan_id: 0
72+
storage:
73+
subnet: "10.0.1.0/24"
74+
vlan_id: 100
75+
rdma_enabled: true
76+
compute:
77+
subnet: "10.0.2.0/24"
78+
vlan_id: 200
79+
80+
81+
# =============================================================================
82+
# Credentials (mapped to Key Vault secrets)
83+
# =============================================================================
84+
credentials:
85+
cluster_admin_username: "keyvault://kv-iic-loadtools/hci-cluster-admin-user"
86+
cluster_admin_password: "keyvault://kv-iic-loadtools/hci-cluster-admin-pwd"
87+
vmfleet_admin_username: "keyvault://kv-iic-loadtools/vmfleet-admin-user"
88+
vmfleet_admin_password: "keyvault://kv-iic-loadtools/vmfleet-admin-pwd"
89+
90+
91+
# =============================================================================
92+
# Testing Defaults
93+
# =============================================================================
94+
testing:
95+
default_tool: "vmfleet" # vmfleet | fio | iperf | hammerdb | stress-ng
96+
default_profile: "general" # Profile name from config/profiles/<tool>/
97+
duration_seconds: 300
98+
warmup_seconds: 60
99+
100+
101+
# =============================================================================
102+
# Monitoring & Reporting
103+
# =============================================================================
104+
monitoring:
105+
log_analytics_workspace_id: "00000000-0000-0000-0000-000000000000"
106+
log_analytics_shared_key: "keyvault://kv-iic-loadtools/log-analytics-key"
107+
enable_real_time: true
108+
collection_interval_seconds: 10
109+
110+
reporting:
111+
output_dir: "reports"
112+
format: "html" # html | json | csv
113+
include_charts: true
114+
115+
116+
# =============================================================================
117+
# WinRM
118+
# =============================================================================
119+
winrm:
120+
port: 5985
121+
use_ssl: false
122+
authentication: "Kerberos" # Kerberos | Negotiate | Basic
123+
operation_timeout_seconds: 300
124+
125+
126+
# =============================================================================
127+
# Tags
128+
# =============================================================================
129+
tags:
130+
project: "LoadTools"
131+
environment: "production"
132+
workload: "performance-testing"
133+
solution: "loadtools-azure-local"

0 commit comments

Comments
 (0)