Skip to content

Commit b61cdf0

Browse files
ABZhang0Alan Zhang
andauthored
[AMG] Support multi-subscription scenario for AMW integration (#8664)
* Support optional subscription id arg * Add shorter param name * Update integration test scenario * Deprecate notification-channel cmd group * Correct version number * Update all test recordings --------- Co-authored-by: Alan Zhang <alanzhang@microsoft.com>
1 parent ce277e0 commit b61cdf0

21 files changed

+16857
-16119
lines changed

src/amg/HISTORY.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,3 +131,9 @@ Release History
131131
2.5.5
132132
++++++
133133
* `az grafana notification-channel test`: fix issue with test output parsing
134+
135+
2.6.0
136+
++++++
137+
* `az grafana integrations monitor add`: support optional subscription id argument for multi-subscription scenarios
138+
* `az grafana integrations monitor delete`: support optional subscription id argument for multi-subscription scenarios
139+
* `az grafana notification-channel`: deprecate command group as part of Grafana legacy alerting deprecation

src/amg/azext_amg/_help.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@
180180
helps['grafana notification-channel'] = """
181181
type: group
182182
short-summary: Commands to manage notification channels of an instance.
183-
long-summary: As part of legacy alerting, this command group will be deprecated in a future release
183+
long-summary: As part of Grafana legacy alerting, this command group only works with Grafana 10 and below.
184184
"""
185185

186186
helps['grafana notification-channel list'] = """

src/amg/azext_amg/_params.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,4 +127,5 @@ def load_arguments(self, _):
127127
with self.argument_context("grafana integrations monitor") as c:
128128
c.argument("monitor_name", help="name of the Azure Monitor workspace")
129129
c.argument("monitor_resource_group_name", options_list=["--monitor-resource-group-name", "--monitor-rg-name"], help="name of the resource group of the Azure Monitor workspace")
130+
c.argument("monitor_subscription_id", options_list=["--monitor-subscription-id", "--monitor-sub-id"], help="subscription id of the Azure Monitor workspace. Uses the current subscription id if not specified")
130131
c.argument("skip_role_assignments", options_list=["-s", "--skip-role-assignments"], arg_type=get_three_state_flag(), help="skip assigning the appropriate role on the Azure Monitor workspace to let Grafana read data from it. Default: false")

src/amg/azext_amg/commands.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ def load_command_table(self, _):
3434
g.custom_command('query', 'query_data_source')
3535
g.custom_command('update', 'update_data_source')
3636

37-
with self.command_group('grafana notification-channel') as g:
37+
with self.command_group('grafana notification-channel', deprecate_info=self.deprecate()) as g:
3838
g.custom_command('list', 'list_notification_channels')
3939
g.custom_show_command('show', 'show_notification_channel')
4040
g.custom_command('create', 'create_notification_channel')

src/amg/azext_amg/custom.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -826,18 +826,18 @@ def query_data_source(cmd, grafana_name, data_source, time_from=None, time_to=No
826826
return json.loads(response.content)
827827

828828

829-
def link_monitor(cmd, grafana_name, monitor_name, monitor_resource_group_name, resource_group_name=None,
830-
skip_role_assignments=False):
829+
def link_monitor(cmd, grafana_name, monitor_name, monitor_resource_group_name, monitor_subscription_id=None,
830+
resource_group_name=None, skip_role_assignments=False):
831831
from .integrations import link_amw_to_amg
832832
link_amw_to_amg(cmd, grafana_name, monitor_name, resource_group_name, monitor_resource_group_name,
833-
skip_role_assignments)
833+
monitor_subscription_id, skip_role_assignments)
834834

835835

836-
def unlink_monitor(cmd, grafana_name, monitor_name, monitor_resource_group_name, resource_group_name=None,
837-
skip_role_assignments=False):
836+
def unlink_monitor(cmd, grafana_name, monitor_name, monitor_resource_group_name, monitor_subscription_id=None,
837+
resource_group_name=None, skip_role_assignments=False):
838838
from .integrations import unlink_amw_from_amg
839839
unlink_amw_from_amg(cmd, grafana_name, monitor_name, resource_group_name, monitor_resource_group_name,
840-
skip_role_assignments)
840+
monitor_subscription_id, skip_role_assignments)
841841

842842

843843
def list_monitors(cmd, grafana_name, resource_group_name=None):

src/amg/azext_amg/integrations.py

Lines changed: 38 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -17,23 +17,30 @@
1717

1818

1919
def link_amw_to_amg(cmd, grafana_name, monitor_name, grafana_resource_group_name, monitor_resource_group_name,
20-
skip_role_assignments):
20+
monitor_subscription_id, skip_role_assignments):
2121
grafana_client = cf_amg(cmd.cli_ctx, subscription=None)
2222
grafana = grafana_client.grafana.get(grafana_resource_group_name, grafana_name)
2323

2424
principal_id = grafana.identity.principal_id
2525
if not principal_id:
2626
raise ArgumentUsageError("The Grafana instance does not have a managed identity.")
2727

28-
monitor = MonitorAccountShow(cli_ctx=cmd.cli_ctx)(command_args={
29-
"resource_group": monitor_resource_group_name,
30-
"azure_monitor_workspace_name": monitor_name
31-
})
28+
if monitor_subscription_id:
29+
monitor_resource_id = '/subscriptions/{}/resourceGroups/{}/providers/Microsoft.Monitor/accounts/{}'.format(
30+
monitor_subscription_id, monitor_resource_group_name, monitor_name)
31+
else:
32+
monitor = MonitorAccountShow(cli_ctx=cmd.cli_ctx)(command_args={
33+
"resource_group": monitor_resource_group_name,
34+
"azure_monitor_workspace_name": monitor_name
35+
})
36+
monitor_resource_id = monitor['id']
3237

3338
monitors = grafana.properties.grafana_integrations.azure_monitor_workspace_integrations
34-
if monitor['id'].lower() in [m.azure_monitor_workspace_resource_id.lower() for m in monitors]:
39+
40+
if monitor_resource_id.lower() in [m.azure_monitor_workspace_resource_id.lower() for m in monitors]:
3541
raise ArgumentUsageError("The Azure Monitor workspace is already linked to the Grafana instance.")
36-
monitors.append({"azureMonitorWorkspaceResourceId": monitor['id']})
42+
43+
monitors.append({"azureMonitorWorkspaceResourceId": monitor_resource_id})
3744
resource = {
3845
"properties": {
3946
"grafanaIntegrations": {
@@ -43,30 +50,39 @@ def link_amw_to_amg(cmd, grafana_name, monitor_name, grafana_resource_group_name
4350
}
4451

4552
grafana_client.grafana.update(grafana_resource_group_name, grafana_name, resource)
53+
logger.info("Azure Monitor workspace of '%s' was linked to the Grafana instance.", monitor_name)
4654

4755
if not skip_role_assignments:
48-
subscription_scope = '/'.join(monitor['id'].split('/')[0:3]) # /subscriptions/<sub_id>
56+
subscription_scope = '/'.join(monitor_resource_id.split('/')[0:3]) # /subscriptions/<sub_id>
4957
monitor_role_id = resolve_role_id(cmd.cli_ctx, "Monitoring Data Reader", subscription_scope)
5058
# assign the Grafana instance the Monitoring Data Reader role on the Azure Monitor workspace
51-
logger.warning("Azure Monitor workspace of '%s' was linked to the Grafana instance. Now assigning the Grafana"
52-
" instance the Monitoring Data Reader role on the Azure Monitor workspace.", monitor['name'])
53-
_create_role_assignment(cmd.cli_ctx, principal_id, monitor_role_id, monitor['id'])
59+
logger.info("Now assigning the Grafana instance the Monitoring Data Reader role on the Azure Monitor "
60+
"workspace.")
61+
_create_role_assignment(cmd.cli_ctx, principal_id, monitor_role_id, monitor_resource_id)
62+
else:
63+
logger.warning("Skipping role assignment. Please note the Grafana instance needs the Monitoring Data "
64+
"Reader role on the Azure Monitor workspace to access its data.")
5465

5566

5667
def unlink_amw_from_amg(cmd, grafana_name, monitor_name, grafana_resource_group_name, monitor_resource_group_name,
57-
skip_role_assignments):
68+
monitor_subscription_id, skip_role_assignments):
5869
grafana_client = cf_amg(cmd.cli_ctx, subscription=None)
5970
grafana = grafana_client.grafana.get(grafana_resource_group_name, grafana_name)
6071

61-
monitor = MonitorAccountShow(cli_ctx=cmd.cli_ctx)(command_args={
62-
"resource_group": monitor_resource_group_name,
63-
"azure_monitor_workspace_name": monitor_name
64-
})
72+
if monitor_subscription_id:
73+
monitor_resource_id = '/subscriptions/{}/resourceGroups/{}/providers/Microsoft.Monitor/accounts/{}'.format(
74+
monitor_subscription_id, monitor_resource_group_name, monitor_name)
75+
else:
76+
monitor = MonitorAccountShow(cli_ctx=cmd.cli_ctx)(command_args={
77+
"resource_group": monitor_resource_group_name,
78+
"azure_monitor_workspace_name": monitor_name
79+
})
80+
monitor_resource_id = monitor['id']
6581

6682
monitors = grafana.properties.grafana_integrations.azure_monitor_workspace_integrations
67-
if monitor['id'].lower() not in [m.azure_monitor_workspace_resource_id.lower() for m in monitors]:
83+
if monitor_resource_id.lower() not in [m.azure_monitor_workspace_resource_id.lower() for m in monitors]:
6884
raise ArgumentUsageError("The Azure Monitor workspace is not linked to the Grafana instance.")
69-
monitors = [m for m in monitors if m.azure_monitor_workspace_resource_id != monitor['id']]
85+
monitors = [m for m in monitors if m.azure_monitor_workspace_resource_id.lower() != monitor_resource_id.lower()]
7086
resource = {
7187
"properties": {
7288
"grafanaIntegrations": {
@@ -76,15 +92,15 @@ def unlink_amw_from_amg(cmd, grafana_name, monitor_name, grafana_resource_group_
7692
}
7793

7894
grafana_client.grafana.update(grafana_resource_group_name, grafana_name, resource)
95+
logger.info("Azure Monitor workspace of '%s' was unlinked from the Grafana instance.", monitor_name)
7996

8097
principal_id = grafana.identity.principal_id
8198
if principal_id and not skip_role_assignments:
82-
subscription_scope = '/'.join(monitor['id'].split('/')[0:3]) # /subscriptions/<sub_id>
99+
subscription_scope = '/'.join(monitor_resource_id.split('/')[0:3]) # /subscriptions/<sub_id>
83100
monitor_role_id = resolve_role_id(cmd.cli_ctx, "Monitoring Data Reader", subscription_scope)
84101
# assign the Grafana instance the Monitoring Data Reader role on the Azure Monitor workspace
85-
logger.warning("Azure Monitor workspace of '%s' was unlinked from the Grafana instance. Now removing the"
86-
" Monitoring Data Reader role assignment from the Azure Monitor workspace.", monitor['name'])
87-
_delete_role_assignment(cmd.cli_ctx, principal_id, monitor_role_id, monitor['id'])
102+
logger.info("Now removing the Monitoring Data Reader role assignment from the Azure Monitor workspace.")
103+
_delete_role_assignment(cmd.cli_ctx, principal_id, monitor_role_id, monitor_resource_id)
88104

89105

90106
def list_amw_linked_to_amg(cmd, grafana_name, grafana_resource_group_name):

0 commit comments

Comments
 (0)