Skip to content
Merged
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
6 changes: 6 additions & 0 deletions src/amg/HISTORY.rst
Original file line number Diff line number Diff line change
Expand Up @@ -131,3 +131,9 @@ Release History
2.5.5
++++++
* `az grafana notification-channel test`: fix issue with test output parsing

2.6.0
++++++
* `az grafana integrations monitor add`: support optional subscription id argument for multi-subscription scenarios
* `az grafana integrations monitor delete`: support optional subscription id argument for multi-subscription scenarios
* `az grafana notification-channel`: deprecate command group as part of Grafana legacy alerting deprecation
2 changes: 1 addition & 1 deletion src/amg/azext_amg/_help.py
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@
helps['grafana notification-channel'] = """
type: group
short-summary: Commands to manage notification channels of an instance.
long-summary: As part of legacy alerting, this command group will be deprecated in a future release
long-summary: As part of Grafana legacy alerting, this command group only works with Grafana 10 and below.
"""

helps['grafana notification-channel list'] = """
Expand Down
1 change: 1 addition & 0 deletions src/amg/azext_amg/_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,4 +127,5 @@ def load_arguments(self, _):
with self.argument_context("grafana integrations monitor") as c:
c.argument("monitor_name", help="name of the Azure Monitor workspace")
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")
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")
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")
2 changes: 1 addition & 1 deletion src/amg/azext_amg/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ def load_command_table(self, _):
g.custom_command('query', 'query_data_source')
g.custom_command('update', 'update_data_source')

with self.command_group('grafana notification-channel') as g:
with self.command_group('grafana notification-channel', deprecate_info=self.deprecate()) as g:
g.custom_command('list', 'list_notification_channels')
g.custom_show_command('show', 'show_notification_channel')
g.custom_command('create', 'create_notification_channel')
Expand Down
12 changes: 6 additions & 6 deletions src/amg/azext_amg/custom.py
Original file line number Diff line number Diff line change
Expand Up @@ -826,18 +826,18 @@ def query_data_source(cmd, grafana_name, data_source, time_from=None, time_to=No
return json.loads(response.content)


def link_monitor(cmd, grafana_name, monitor_name, monitor_resource_group_name, resource_group_name=None,
skip_role_assignments=False):
def link_monitor(cmd, grafana_name, monitor_name, monitor_resource_group_name, monitor_subscription_id=None,
resource_group_name=None, skip_role_assignments=False):
from .integrations import link_amw_to_amg
link_amw_to_amg(cmd, grafana_name, monitor_name, resource_group_name, monitor_resource_group_name,
skip_role_assignments)
monitor_subscription_id, skip_role_assignments)


def unlink_monitor(cmd, grafana_name, monitor_name, monitor_resource_group_name, resource_group_name=None,
skip_role_assignments=False):
def unlink_monitor(cmd, grafana_name, monitor_name, monitor_resource_group_name, monitor_subscription_id=None,
resource_group_name=None, skip_role_assignments=False):
from .integrations import unlink_amw_from_amg
unlink_amw_from_amg(cmd, grafana_name, monitor_name, resource_group_name, monitor_resource_group_name,
skip_role_assignments)
monitor_subscription_id, skip_role_assignments)


def list_monitors(cmd, grafana_name, resource_group_name=None):
Expand Down
60 changes: 38 additions & 22 deletions src/amg/azext_amg/integrations.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,23 +17,30 @@


def link_amw_to_amg(cmd, grafana_name, monitor_name, grafana_resource_group_name, monitor_resource_group_name,
skip_role_assignments):
monitor_subscription_id, skip_role_assignments):
grafana_client = cf_amg(cmd.cli_ctx, subscription=None)
grafana = grafana_client.grafana.get(grafana_resource_group_name, grafana_name)

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

monitor = MonitorAccountShow(cli_ctx=cmd.cli_ctx)(command_args={
"resource_group": monitor_resource_group_name,
"azure_monitor_workspace_name": monitor_name
})
if monitor_subscription_id:
monitor_resource_id = '/subscriptions/{}/resourceGroups/{}/providers/Microsoft.Monitor/accounts/{}'.format(
monitor_subscription_id, monitor_resource_group_name, monitor_name)
else:
monitor = MonitorAccountShow(cli_ctx=cmd.cli_ctx)(command_args={
"resource_group": monitor_resource_group_name,
"azure_monitor_workspace_name": monitor_name
})
monitor_resource_id = monitor['id']

monitors = grafana.properties.grafana_integrations.azure_monitor_workspace_integrations
if monitor['id'].lower() in [m.azure_monitor_workspace_resource_id.lower() for m in monitors]:

if monitor_resource_id.lower() in [m.azure_monitor_workspace_resource_id.lower() for m in monitors]:
raise ArgumentUsageError("The Azure Monitor workspace is already linked to the Grafana instance.")
monitors.append({"azureMonitorWorkspaceResourceId": monitor['id']})

monitors.append({"azureMonitorWorkspaceResourceId": monitor_resource_id})
resource = {
"properties": {
"grafanaIntegrations": {
Expand All @@ -43,30 +50,39 @@ def link_amw_to_amg(cmd, grafana_name, monitor_name, grafana_resource_group_name
}

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

if not skip_role_assignments:
subscription_scope = '/'.join(monitor['id'].split('/')[0:3]) # /subscriptions/<sub_id>
subscription_scope = '/'.join(monitor_resource_id.split('/')[0:3]) # /subscriptions/<sub_id>
monitor_role_id = resolve_role_id(cmd.cli_ctx, "Monitoring Data Reader", subscription_scope)
# assign the Grafana instance the Monitoring Data Reader role on the Azure Monitor workspace
logger.warning("Azure Monitor workspace of '%s' was linked to the Grafana instance. Now assigning the Grafana"
" instance the Monitoring Data Reader role on the Azure Monitor workspace.", monitor['name'])
_create_role_assignment(cmd.cli_ctx, principal_id, monitor_role_id, monitor['id'])
logger.info("Now assigning the Grafana instance the Monitoring Data Reader role on the Azure Monitor "
"workspace.")
_create_role_assignment(cmd.cli_ctx, principal_id, monitor_role_id, monitor_resource_id)
else:
logger.warning("Skipping role assignment. Please note the Grafana instance needs the Monitoring Data "
"Reader role on the Azure Monitor workspace to access its data.")


def unlink_amw_from_amg(cmd, grafana_name, monitor_name, grafana_resource_group_name, monitor_resource_group_name,
skip_role_assignments):
monitor_subscription_id, skip_role_assignments):
grafana_client = cf_amg(cmd.cli_ctx, subscription=None)
grafana = grafana_client.grafana.get(grafana_resource_group_name, grafana_name)

monitor = MonitorAccountShow(cli_ctx=cmd.cli_ctx)(command_args={
"resource_group": monitor_resource_group_name,
"azure_monitor_workspace_name": monitor_name
})
if monitor_subscription_id:
monitor_resource_id = '/subscriptions/{}/resourceGroups/{}/providers/Microsoft.Monitor/accounts/{}'.format(
monitor_subscription_id, monitor_resource_group_name, monitor_name)
else:
monitor = MonitorAccountShow(cli_ctx=cmd.cli_ctx)(command_args={
"resource_group": monitor_resource_group_name,
"azure_monitor_workspace_name": monitor_name
})
monitor_resource_id = monitor['id']

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

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

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


def list_amw_linked_to_amg(cmd, grafana_name, grafana_resource_group_name):
Expand Down
Loading
Loading