Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
ebdc33b
List instances and List revision should use ST Id not name
Mar 2, 2026
cf07a53
Merge branch 'Azure:main' into avpatra/RevisionInstancesFix
Avisiktapatra Mar 2, 2026
9e85d13
Add history
Mar 2, 2026
62b8b53
Merge branch 'avpatra/RevisionInstancesFix' of https://github.com/man…
Mar 2, 2026
94c1821
upgrade version
Mar 2, 2026
82cb3e5
Fix the version sequence in history file
Mar 2, 2026
2845dd8
fix review comments
Mar 2, 2026
9630b19
Update src/workload-orchestration/azext_workload_orchestration/aaz/la…
Avisiktapatra Mar 2, 2026
dafc862
Update src/workload-orchestration/azext_workload_orchestration/aaz/la…
Avisiktapatra Mar 2, 2026
61d4b59
feat: add az workload-orchestration support create-bundle command
Mar 11, 2026
99054c4
improve: enhance bundle data + RBAC errors + disk check
Mar 11, 2026
aca7edb
feat(support-bundle): add retry, timeout, namespace validation, resou…
Mar 11, 2026
ee91522
docs: update HISTORY.rst and clean up conftest for PR readiness
Mar 11, 2026
2ba769c
refactor: restructure support bundle into support/ subpackage
Mar 11, 2026
be71134
docs: expand README with complete guide for adding checks, collectors…
Mar 11, 2026
d75e8eb
chore: remove unused imports (tempfile, json, os)
Mar 11, 2026
03040c6
chore: remove unused get_enum_type import from _params.py
Mar 11, 2026
98dd6a7
feat: add --bundle-name param and network config collection
Mar 12, 2026
e4146a2
feat: add checks/summary.json with consolidated check results
Mar 12, 2026
1ed5bec
fix: keep support/ at extension root, add AAZ mocks to conftest
Mar 12, 2026
1ee66d3
chore: bump version to 6.0.0 for support bundle feature
Mar 12, 2026
ce3d176
refactor: remove health summary (HEALTHY/DEGRADED/CRITICAL) markers
Mar 12, 2026
e859d1d
chore: remove accidentally committed zip file
Mar 12, 2026
e8e58f2
fix: restore health summary, only remove HEALTHY/DEGRADED/CRITICAL la…
Mar 12, 2026
bac7b5a
feat: add comprehensive SUMMARY.md to bundle root
Mar 12, 2026
337b4d7
refactor: organize resources into per-namespace subdirectories
Mar 12, 2026
243674d
feat: add Arc dependency check, WO services/deployments check, cluste…
Mar 12, 2026
18023b9
Merge branch 'Azure:main' into avpatra/RevisionInstancesFix
manaswita-chichili Mar 16, 2026
92ec4f7
Validate site id for context site reference and config link
manaswita-chichili Mar 16, 2026
f171502
Merge branch 'avpatra/RevisionInstancesFix' of https://github.com/man…
manaswita-chichili Mar 16, 2026
e13ab16
Simply code to use same validation helper class
manaswita-chichili Mar 16, 2026
3d051a2
resolve review comments
Mar 16, 2026
3791191
version upgrade
Mar 16, 2026
b541e54
Merge branch 'Azure:main' into avpatra/RevisionInstancesFix
manaswita-chichili Mar 17, 2026
dd79fb1
add chnges
Mar 17, 2026
38371c4
version chnge
Mar 17, 2026
6100dff
Add new command for capability upates
Nishad94 Mar 17, 2026
6bcad89
Merge pull request #4 from manaswita-chichili/ndawkhar/cap-deletion-st
Avisiktapatra Mar 17, 2026
3c9b7c0
merge: add support bundle feature into combined CLI release
Mar 18, 2026
75eb01d
fix: resolve all pylint warnings for CI pipeline
Mar 18, 2026
9724729
fix: resolve all pylint and flake8 lint errors for CI
Mar 18, 2026
aa2528b
fix: resolve ALL remaining pylint errors for CI
Mar 18, 2026
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
11 changes: 11 additions & 0 deletions src/workload-orchestration/HISTORY.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,17 @@

Release History
===============
5.1.1
++++++
* Resolved solution template name to uniqueIdentifier for ``az workload-orchestration target solution-revision-list`` and ``az workload-orchestration target solution-instance-list``
* Added shared ``_target_helper.py`` for reusable solution template resolution logic
* Added ``az workload-orchestration support create-bundle`` command for troubleshooting Day 0 (installation) and Day N (runtime) issues on 3rd-party Kubernetes clusters:
* Collects cluster info, node details, pod/deployment/service/event descriptions across configurable namespaces
* Collects container logs (current + previous for crash-looping pods) with configurable tail lines
* Runs prerequisite validation checks across 10 categories
* Generates a zip bundle for sharing with Microsoft support
* Includes retry with exponential backoff and per-call timeout for resilient K8s API access

5.1.0
++++++
* Added new target solution management command:
Expand Down
37 changes: 37 additions & 0 deletions src/workload-orchestration/azext_workload_orchestration/_help.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,40 @@
# pylint: disable=too-many-lines

from knack.help_files import helps # pylint: disable=unused-import


helps['workload-orchestration support'] = """
type: group
short-summary: Commands for troubleshooting and diagnostics of workload orchestration deployments.
"""

helps['workload-orchestration support create-bundle'] = """
type: command
short-summary: Create a support bundle for troubleshooting workload orchestration issues.
long-summary: |
Collects cluster information, resource descriptions, container logs, and runs
prerequisite validation checks. The output is a zip file that can be shared with
Microsoft support for troubleshooting Day 0 (installation) and Day N (runtime) issues.

Collected data includes:
- Cluster info (version, nodes, namespaces)
- Pod/Deployment/Service/DaemonSet/Event descriptions per namespace
- Container logs (tailed by default)
- Network configuration (kube-proxy, external services, pod CIDRs)
- StorageClass, PV, webhook, CRD inventory
- WO component health (Symphony, cert-manager)
- Prerequisite checks (K8s version, node capacity, DNS, storage, RBAC)
examples:
- name: Create a support bundle with defaults
text: az workload-orchestration support create-bundle
- name: Create a named bundle
text: az workload-orchestration support create-bundle --bundle-name my-cluster-debug
- name: Create a bundle in a specific directory
text: az workload-orchestration support create-bundle --output-dir /tmp/bundles
- name: Collect full logs (no tail) for WO namespace only
text: az workload-orchestration support create-bundle --full-logs --namespaces workloadorchestration
- name: Run checks only, skip log collection
text: az workload-orchestration support create-bundle --skip-logs
- name: Use a specific kubeconfig and context
text: az workload-orchestration support create-bundle --kube-config ~/.kube/prod-config --kube-context my-cluster
"""
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,58 @@


def load_arguments(self, _): # pylint: disable=unused-argument
pass
with self.argument_context('workload-orchestration support create-bundle') as c:
c.argument(
'bundle_name',
options_list=['--bundle-name', '-n'],
help='Optional name for the support bundle. '
'Defaults to wo-support-bundle-YYYYMMDD-HHMMSS.',
)
c.argument(
'output_dir',
options_list=['--output-dir', '-d'],
help='Directory where the support bundle zip will be saved. Defaults to current directory.',
)
c.argument(
'namespaces',
options_list=['--namespaces'],
nargs='+',
help='Kubernetes namespaces to collect logs and resources from. '
'Defaults to kube-system, workloadorchestration, cert-manager.',
)
c.argument(
'tail_lines',
options_list=['--tail-lines'],
type=int,
help='Number of log lines to collect per container (default: 1000). '
'Use --full-logs to collect all lines.',
)
c.argument(
'full_logs',
options_list=['--full-logs'],
action='store_true',
help='Collect full container logs instead of tailing. '
'Warning: may produce very large bundles.',
)
c.argument(
'skip_checks',
options_list=['--skip-checks'],
action='store_true',
help='Skip prerequisite validation checks and only collect logs/resources.',
)
c.argument(
'skip_logs',
options_list=['--skip-logs'],
action='store_true',
help='Skip container log collection and only run checks/collect resources.',
)
c.argument(
'kube_config',
options_list=['--kube-config'],
help='Path to kubeconfig file. Defaults to ~/.kube/config.',
)
c.argument(
'kube_context',
options_list=['--kube-context'],
help='Kubernetes context to use. Defaults to current context.',
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
# --------------------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License.txt in the project root for license information.
# --------------------------------------------------------------------------------------------

# pylint: skip-file
# flake8: noqa

from azure.cli.core.aaz import *
from azure.cli.core.azclierror import ValidationError


class ValidateResourceExists(AAZHttpOperation):
"""Validates that an ARM resource exists by making a GET request to its resource ID."""
CLIENT_TYPE = "MgmtClient"

def __init__(self, ctx, resource_id, resource_label="Resource"):
super().__init__(ctx)
self._resource_id = str(resource_id)
self._resource_label = resource_label

def __call__(self, *args, **kwargs):
request = self.make_request()
session = self.client.send_request(request=request, stream=False, **kwargs)
if session.http_response.status_code == 404:
raise ValidationError(
f"{self._resource_label} not found. The resource with ID '{self._resource_id}' does not exist. "
f"Please provide a valid {self._resource_label.lower()} resource ID."
)
if session.http_response.status_code != 200:
raise ValidationError(
f"Failed to validate {self._resource_label.lower()} existence for ID '{self._resource_id}'. "
f"Received status code: {session.http_response.status_code}"
)

@property
def url(self):
return self.client.format_url(
"{resourceId}",
**self.url_parameters
)

@property
def method(self):
return "GET"

@property
def error_format(self):
return "MgmtErrorFormat"

@property
def url_parameters(self):
parameters = {
**self.serialize_url_param(
"resourceId", self._resource_id,
required=True,
skip_quote=True,
),
}
return parameters

@property
def query_parameters(self):
parameters = {
**self.serialize_query_param(
"api-version", "2025-06-01",
required=True,
),
}
return parameters

@property
def header_parameters(self):
parameters = {
**self.serialize_header_param(
"Accept", "application/json",
),
}
return parameters
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
# flake8: noqa

from azure.cli.core.aaz import *
from azext_workload_orchestration.aaz.latest.workload_orchestration._resource_validator import ValidateResourceExists


@register_command(
"workload-orchestration config-template link",
Expand Down Expand Up @@ -71,6 +73,9 @@ def _build_arguments_schema(cls, *args, **kwargs):

def _execute_operations(self):
self.pre_operations()
if has_value(self.ctx.args.hierarchy_ids):
for hierarchy_id in self.ctx.args.hierarchy_ids:
ValidateResourceExists(ctx=self.ctx, resource_id=hierarchy_id, resource_label="Hierarchy")()
yield self.ConfigTemplatesLinkToHierarchies(ctx=self.ctx)()
self.post_operations()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,8 +115,19 @@ def try_get_config_id(lookup_id, api_version = "2025-08-01"):


# If we reach here, no configuration was found
raise CLIInternalError(f"No configuration linked to this hierarchy: {hierarchy_id_str}")

if "microsoft.edge/targets" in hierarchy_id_str.lower():
raise CLIInternalError(
f"Missing target configuration and configuration reference for Target: {hierarchy_id_str}"
)
elif "microsoft.edge/sites" in hierarchy_id_str.lower():
raise CLIInternalError(
f"Missing site configuration and configuration reference for Site: {hierarchy_id_str}"
)
else:
raise CLIInternalError(
f"Hierarchy Id can either be of Target or Site Resource. Invalid Id: {hierarchy_id_str}"
)

@staticmethod
def getTemplateUniqueIdentifier(subscription_id, template_resource_group_name, template_name, solution_flag, client):
"""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
# flake8: noqa

from azure.cli.core.aaz import *
from azext_workload_orchestration.aaz.latest.workload_orchestration._resource_validator import ValidateResourceExists


@register_command(
Expand Down Expand Up @@ -78,6 +79,8 @@ def _build_arguments_schema(cls, *args, **kwargs):

def _execute_operations(self):
self.pre_operations()
if has_value(self.ctx.args.site_id):
ValidateResourceExists(ctx=self.ctx, resource_id=self.ctx.args.site_id, resource_label="Site")()
yield self.SiteReferencesCreateOrUpdate(ctx=self.ctx)()
self.post_operations()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,5 @@
from ._bulk_publish_solution import *
from ._bulk_review_solution import *
# from ._update import *
from ._update_capabilities import *
from ._wait import *
Loading
Loading