From d9201fcb71dc90f1f277858399eb51d261413ae7 Mon Sep 17 00:00:00 2001 From: Kaveesh Dubey Date: Mon, 3 Apr 2023 10:41:13 -0700 Subject: [PATCH 01/41] {AKS} feat: Azure Monitor Metrics addon (v2) (Managed Prometheus) GA --- .../azure/cli/command_modules/acs/_help.py | 41 + .../azure/cli/command_modules/acs/_params.py | 19 +- .../cli/command_modules/acs/_validators.py | 27 + .../azuremonitorprofile.py | 785 ++++++++++++++++++ .../amwlocationresponseparser.py | 24 + .../azure/cli/command_modules/acs/custom.py | 32 +- .../acs/managed_cluster_decorator.py | 126 +++ 7 files changed, 1052 insertions(+), 2 deletions(-) create mode 100644 src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/azuremonitorprofile.py create mode 100644 src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/responseparsers/amwlocationresponseparser.py diff --git a/src/azure-cli/azure/cli/command_modules/acs/_help.py b/src/azure-cli/azure/cli/command_modules/acs/_help.py index 8f05993eeca..a66fac6587b 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/_help.py +++ b/src/azure-cli/azure/cli/command_modules/acs/_help.py @@ -479,6 +479,24 @@ - name: --enable-keda type: bool short-summary: Enable KEDA workload auto-scaler. + - name: --enable-azuremonitormetrics + type: bool + short-summary: Enable Azure Monitor Metrics Profile + - name: --azure-monitor-workspace-resource-id + type: string + short-summary: Resource ID of the Azure Monitor Workspace + - name: --ksm-metric-labels-allow-list + type: string + short-summary: Comma-separated list of additional Kubernetes label keys that will be used in the resource' labels metric. By default the metric contains only name and namespace labels. To include additional labels provide a list of resource names in their plural form and Kubernetes label keys you would like to allow for them (e.g. '=namespaces=[k8s-label-1,k8s-label-n,...],pods=[app],...)'. A single '*' can be provided per resource instead to allow any labels, but that has severe performance implications (e.g. '=pods=[*]'). + - name: --ksm-metric-annotations-allow-list + type: string + short-summary: Comma-separated list of additional Kubernetes label keys that will be used in the resource' labels metric. By default the metric contains only name and namespace labels. To include additional labels provide a list of resource names in their plural form and Kubernetes label keys you would like to allow for them (e.g.'=namespaces=[k8s-label-1,k8s-label-n,...],pods=[app],...)'. A single '*' can be provided per resource instead to allow any labels, but that has severe performance implications (e.g. '=pods=[*]'). + - name: --grafana-resource-id + type: string + short-summary: Resource ID of the Azure Managed Grafana Workspace + - name: --enable-windows-recording-rules + type: bool + short-summary: Enable Windows Recording Rules when enabling the Azure Monitor Metrics addon examples: - name: Create a Kubernetes cluster with an existing SSH public key. @@ -549,6 +567,8 @@ text: az aks create -g MyResourceGroup -n MyManagedCluster --network-plugin none - name: Create a kubernetes cluster with KEDA workload autoscaler enabled. text: az aks create -g MyResourceGroup -n MyManagedCluster --enable-keda + - name: Create a kubernetes cluster with Azure Monitor Metrics enabled. + text: az aks create -g MyResourceGroup -n MyManagedCluster --enable-azuremonitormetrics """ helps['aks update'] = """ @@ -785,6 +805,27 @@ - name: --disable-keda type: bool short-summary: Disable KEDA workload auto-scaler. + - name: --enable-azuremonitormetrics + type: bool + short-summary: Enable Azure Monitor Metrics Profile + - name: --azure-monitor-workspace-resource-id + type: string + short-summary: Resource ID of the Azure Monitor Workspace + - name: --ksm-metric-labels-allow-list + type: string + short-summary: Comma-separated list of additional Kubernetes label keys that will be used in the resource' labels metric. By default the metric contains only name and namespace labels. To include additional labels provide a list of resource names in their plural form and Kubernetes label keys you would like to allow for them (e.g. '=namespaces=[k8s-label-1,k8s-label-n,...],pods=[app],...)'. A single '*' can be provided per resource instead to allow any labels, but that has severe performance implications (e.g. '=pods=[*]'). + - name: --ksm-metric-annotations-allow-list + type: string + short-summary: Comma-separated list of additional Kubernetes label keys that will be used in the resource' labels metric. By default the metric contains only name and namespace labels. To include additional labels provide a list of resource names in their plural form and Kubernetes label keys you would like to allow for them (e.g.'=namespaces=[k8s-label-1,k8s-label-n,...],pods=[app],...)'. A single '*' can be provided per resource instead to allow any labels, but that has severe performance implications (e.g. '=pods=[*]'). + - name: --grafana-resource-id + type: string + short-summary: Resource ID of the Azure Managed Grafana Workspace + - name: --enable-windows-recording-rules + type: bool + short-summary: Enable Windows Recording Rules when enabling the Azure Monitor Metrics addon + - name: --disable-azuremonitormetrics + type: bool + short-summary: Disable Azure Monitor Metrics Profile examples: - name: Reconcile the cluster back to its current state. diff --git a/src/azure-cli/azure/cli/command_modules/acs/_params.py b/src/azure-cli/azure/cli/command_modules/acs/_params.py index 22aea041346..a7983be6858 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/_params.py +++ b/src/azure-cli/azure/cli/command_modules/acs/_params.py @@ -56,7 +56,9 @@ validate_ppg, validate_priority, validate_registry_name, validate_snapshot_id, validate_snapshot_name, validate_spot_max_price, validate_ssh_key, validate_taints, validate_vm_set_type, - validate_vnet_subnet_id) + validate_vnet_subnet_id, + validate_azuremonitorworkspaceresourceid, + validate_grafanaresourceid) from azure.cli.core.commands.parameters import ( edge_zone_type, file_type, get_enum_type, get_resource_name_completion_list, get_three_state_flag, name_type, @@ -281,6 +283,13 @@ def load_arguments(self, _): c.argument('linux_os_config') c.argument('host_group_id', validator=validate_host_group_id) c.argument('gpu_instance_profile', arg_type=get_enum_type(gpu_instance_profiles)) + # azure monitor profile + c.argument('enable_azuremonitormetrics', action='store_true', is_preview=True) + c.argument('azure_monitor_workspace_resource_id', validator=validate_azuremonitorworkspaceresourceid, is_preview=True) + c.argument('ksm_metric_labels_allow_list', is_preview=True) + c.argument('ksm_metric_annotations_allow_list', is_preview=True) + c.argument('grafana_resource_id', validator=validate_grafanaresourceid, is_preview=True) + c.argument('enable_windows_recording_rules', action='store_true', is_preview=True) # misc c.argument('yes', options_list=['--yes', '-y'], help='Do not prompt for confirmation.', action='store_true') @@ -361,6 +370,14 @@ def load_arguments(self, _): c.argument('max_count', type=int, validator=validate_nodes_count) c.argument('nodepool_labels', nargs='*', validator=validate_nodepool_labels, help='space-separated labels: key[=value] [key[=value] ...]. See https://aka.ms/node-labels for syntax of labels.') + # azure monitor profile + c.argument('enable_azuremonitormetrics', action='store_true', is_preview=True) + c.argument('azure_monitor_workspace_resource_id', validator=validate_azuremonitorworkspaceresourceid, is_preview=True) + c.argument('ksm_metric_labels_allow_list', is_preview=True) + c.argument('ksm_metric_annotations_allow_list', is_preview=True) + c.argument('grafana_resource_id', validator=validate_grafanaresourceid, is_preview=True) + c.argument('enable_windows_recording_rules', action='store_true', is_preview=True) + c.argument('disable_azuremonitormetrics', action='store_true', is_preview=True) # misc c.argument('yes', options_list=['--yes', '-y'], help='Do not prompt for confirmation.', action='store_true') diff --git a/src/azure-cli/azure/cli/command_modules/acs/_validators.py b/src/azure-cli/azure/cli/command_modules/acs/_validators.py index 762aaf87426..e7590ef1e54 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/_validators.py +++ b/src/azure-cli/azure/cli/command_modules/acs/_validators.py @@ -614,3 +614,30 @@ def validate_registry_name(cmd, namespace): if pos == -1: logger.warning("The login server endpoint suffix '%s' is automatically appended.", acr_suffix) namespace.acr = registry + acr_suffix + + +def sanitize_resource_id(resource_id): + resource_id = resource_id.strip() + if not resource_id.startswith("/"): + resource_id = "/" + resource_id + if resource_id.endswith("/"): + resource_id = resource_id.rstrip("/") + return resource_id.lower() + + +def validate_azuremonitorworkspaceresourceid(namespace): + resource_id = namespace.azure_monitor_workspace_resource_id + if resource_id is None: + return + resource_id = sanitize_resource_id(resource_id) + if (bool(re.match(r'/subscriptions/.*/resourcegroups/.*/providers/microsoft.monitor/accounts/.*', resource_id))) is False: + raise ArgumentUsageError("--azure-monitor-workspace-resource-id not in the correct format. It should match `/subscriptions//resourceGroups//providers/microsoft.monitor/accounts/`") + + +def validate_grafanaresourceid(namespace): + resource_id = namespace.grafana_resource_id + if resource_id is None: + return + resource_id = sanitize_resource_id(resource_id) + if (bool(re.match(r'/subscriptions/.*/resourcegroups/.*/providers/microsoft.dashboard/grafana/.*', resource_id))) is False: + raise ArgumentUsageError("--grafana-resource-id not in the correct format. It should match `/subscriptions//resourceGroups//providers/microsoft.dashboard/grafana/`") diff --git a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/azuremonitorprofile.py b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/azuremonitorprofile.py new file mode 100644 index 00000000000..6d7a2822427 --- /dev/null +++ b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/azuremonitorprofile.py @@ -0,0 +1,785 @@ +# -------------------------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# -------------------------------------------------------------------------------------------- +import json +import uuid +from sre_constants import FAILURE, SUCCESS +from azure.cli.command_modules.acs.azuremonitormetrics.responseparsers.amwlocationresponseparser import parseResourceProviderResponseForLocations + +from knack.util import CLIError +from azure.cli.core.azclierror import ( + UnknownError, + InvalidArgumentValueError, + ClientRequestError +) +from .._client_factory import get_resources_client, get_resource_groups_client +from enum import Enum +from six import with_metaclass +from azure.core import CaseInsensitiveEnumMeta +from azure.core.exceptions import HttpResponseError + +AKS_CLUSTER_API = "2023-01-01" # "2023-01-01" +MAC_API = "2023-04-03" +DC_API = "2022-06-01" +GRAFANA_API = "2022-08-01" +GRAFANA_ROLE_ASSIGNMENT_API = "2022-04-01" +RULES_API = "2023-03-01" +FEATURE_API = "2020-09-01" +RP_API = "2021-04-01" +ALERTS_API = "2023-01-01-preview" +RP_LOCATION_API = "2022-01-01" + +class GrafanaLink(with_metaclass(CaseInsensitiveEnumMeta, str, Enum)): + """ + Status of Grafana link to the Prometheus Addon + """ + SUCCESS = "SUCCESS" + FAILURE = "FAILURE" + ALREADYPRESENT = "ALREADYPRESENT" + NOPARAMPROVIDED = "NOPARAMPROVIDED" + + +class DC_TYPE(with_metaclass(CaseInsensitiveEnumMeta, str, Enum)): + """ + Types of DC* objects + """ + DCE = "DCE" + DCR = "DCR" + DCRA = "DCRA" + + +first_supported_region = "" + + +MapToClosestMACRegion = { + "australiacentral": "eastus", + "australiacentral2": "eastus", + "australiaeast": "eastus", + "australiasoutheast": "eastus", + "brazilsouth": "eastus", + "canadacentral": "eastus", + "canadaeast": "eastus", + "centralus": "centralus", + "centralindia": "centralindia", + "eastasia": "westeurope", + "eastus": "eastus", + "eastus2": "eastus2", + "francecentral": "westeurope", + "francesouth": "westeurope", + "japaneast": "eastus", + "japanwest": "eastus", + "koreacentral": "westeurope", + "koreasouth": "westeurope", + "northcentralus": "eastus", + "northeurope": "westeurope", + "southafricanorth": "westeurope", + "southafricawest": "westeurope", + "southcentralus": "eastus", + "southeastasia": "westeurope", + "southindia": "centralindia", + "uksouth": "westeurope", + "ukwest": "westeurope", + "westcentralus": "eastus", + "westeurope": "westeurope", + "westindia": "centralindia", + "westus": "westus", + "westus2": "westus2", + "westus3": "westus", + "norwayeast": "westeurope", + "norwaywest": "westeurope", + "switzerlandnorth": "westeurope", + "switzerlandwest": "westeurope", + "uaenorth": "westeurope", + "germanywestcentral": "westeurope", + "germanynorth": "westeurope", + "uaecentral": "westeurope", + "eastus2euap": "eastus2euap", + "centraluseuap": "westeurope", + "brazilsoutheast": "eastus", + "jioindiacentral": "centralindia", + "swedencentral": "westeurope", + "swedensouth": "westeurope", + "qatarcentral": "westeurope" +} + +def check_azuremonitormetrics_profile(cmd, cluster_subscription, cluster_resource_group_name, cluster_name): + from azure.cli.core.util import send_raw_request + feature_check_url = f"https://management.azure.com/subscriptions/{cluster_subscription}/resourceGroups/{cluster_resource_group_name}/providers/Microsoft.ContainerService/managedClusters/{cluster_name}?api-version={AKS_CLUSTER_API}" + try: + headers = ['User-Agent=azuremonitormetrics.check_azuremonitormetrics_profile'] + r = send_raw_request(cmd.cli_ctx, "GET", feature_check_url, + body={}, headers=headers) + except CLIError as e: + raise UnknownError(e) + json_response = json.loads(r.text) + values_array = json_response["properties"] + if "azureMonitorProfile" in values_array: + if "metrics" in values_array["azureMonitorProfile"]: + if values_array["azureMonitorProfile"]["metrics"]["enabled"] is True: + raise CLIError(f"Azure Monitor Metrics is already enabled for this cluster. Please use `az aks update --disable-azuremonitormetrics -g {cluster_resource_group_name} -n {cluster_name}` and then try enabling.") + + +# check if `az feature register --namespace Microsoft.ContainerService --name AKS-PrometheusAddonPreview` is Registered +def check_azuremonitoraddon_feature(cmd, cluster_subscription, raw_parameters): + aks_custom_headers = raw_parameters.get("aks_custom_headers") + if (aks_custom_headers is not None) and ("aks-prometheusaddonpreview" in aks_custom_headers.lower()): + return + from azure.cli.core.util import send_raw_request + feature_check_url = f"https://management.azure.com/subscriptions/{cluster_subscription}/providers/Microsoft.Features/subscriptionFeatureRegistrations?api-version={FEATURE_API}&featurename=AKS-PrometheusAddonPreview" + try: + headers = ['User-Agent=azuremonitormetrics.check_azuremonitoraddon_feature'] + r = send_raw_request(cmd.cli_ctx, "GET", feature_check_url, + body={}, headers=headers) + except CLIError as e: + raise UnknownError(e) + json_response = json.loads(r.text) + values_array = json_response["value"] + for value in values_array: + if value["properties"]["providerNamespace"].lower() == "microsoft.containerservice" and value["properties"]["state"].lower() == "registered": + return + raise CLIError("Please enable the feature AKS-PrometheusAddonPreview on your subscription using `az feature register --namespace Microsoft.ContainerService --name AKS-PrometheusAddonPreview` to use this feature.\ + If this feature was recently registered then please wait upto 5 mins for the feature registration to finish") + + +# DCR = 64, DCE = 44, DCRA = 64 +# All DC* object names should end only in alpha numeric (after `length` trim) +# DCE remove underscore from cluster name +def sanitize_name(name, type, length): + length = length - 1 + if type == DC_TYPE.DCE: + name = name.replace("_", "") + name = name[0:length] + lastIndexAlphaNumeric = len(name) - 1 + while ((name[lastIndexAlphaNumeric].isalnum() is False) and lastIndexAlphaNumeric > -1): + lastIndexAlphaNumeric = lastIndexAlphaNumeric - 1 + if (lastIndexAlphaNumeric < 0): + return "" + + return name[0:lastIndexAlphaNumeric + 1] + + +def sanitize_resource_id(resource_id): + resource_id = resource_id.strip() + if not resource_id.startswith("/"): + resource_id = "/" + resource_id + if resource_id.endswith("/"): + resource_id = resource_id.rstrip("/") + return resource_id.lower() + + +def get_supported_rp_locations(cmd, rp_name): + from azure.cli.core.util import send_raw_request + supported_locations = [] + headers = ['User-Agent=azuremonitormetrics.get_supported_rp_locations'] + association_url = f"https://management.azure.com/providers/{rp_name}?api-version={RP_LOCATION_API}" + r = send_raw_request(cmd.cli_ctx, "GET", association_url, headers=headers) + data = json.loads(r.text) + supported_locations = parseResourceProviderResponseForLocations(data) + return supported_locations + + +def get_default_region(cmd): + cloud_name = cmd.cli_ctx.cloud.name + if cloud_name.lower() == 'azurechinacloud': + raise CLIError("Azure China Cloud is not supported for the Azure Monitor Metrics addon") + if cloud_name.lower() == 'azureusgovernment': + return "usgovvirginia" + return "eastus" + +def get_default_mac_region(cmd, cluster_region): + global first_supported_region + if first_supported_region is not None and len(first_supported_region) != 0: + return first_supported_region + supported_locations = get_supported_rp_locations(cmd, 'Microsoft.Monitor') + if cluster_region in supported_locations: + return cluster_region + if len(supported_locations) > 0: + first_supported_region = supported_locations[0] + return supported_locations[0] + cloud_name = cmd.cli_ctx.cloud.name + if cloud_name.lower() == 'azurechinacloud': + raise CLIError("Azure China Cloud is not supported for the Azure Monitor Metrics addon") + if cloud_name.lower() == 'azureusgovernment': + return "usgovvirginia" + # default to public cloud + return get_default_region(cmd) + +def get_default_mac_name(cmd, cluster_region): + default_mac_name = "DefaultAzureMonitorWorkspace-" + get_default_mac_region(cmd, cluster_region) + default_mac_name = default_mac_name[0:43] + return default_mac_name + + +def create_default_mac(cmd, cluster_subscription, cluster_region): + from azure.cli.core.util import send_raw_request + default_mac_name = get_default_mac_name(cmd, cluster_region) + default_resource_group_name = "DefaultResourceGroup-{0}".format(get_default_mac_region(cmd, cluster_region)) + azure_monitor_workspace_resource_id = "/subscriptions/{0}/resourceGroups/{1}/providers/microsoft.monitor/accounts/{2}".format(cluster_subscription, default_resource_group_name, default_mac_name) + # Check if default resource group exists or not, if it does not then create it + resource_groups = get_resource_groups_client(cmd.cli_ctx, cluster_subscription) + resources = get_resources_client(cmd.cli_ctx, cluster_subscription) + + if resource_groups.check_existence(default_resource_group_name): + try: + resources.get_by_id(azure_monitor_workspace_resource_id, MAC_API) + # If MAC already exists then return from here + return azure_monitor_workspace_resource_id + except HttpResponseError as ex: + if ex.status_code != 404: + raise ex + else: + resource_groups.create_or_update(default_resource_group_name, {"location": get_default_mac_region(cmd, cluster_region)}) + association_body = json.dumps({"location": get_default_mac_region(cmd, cluster_region), "properties": {}}) + association_url = f"https://management.azure.com{azure_monitor_workspace_resource_id}?api-version={MAC_API}" + try: + headers = ['User-Agent=azuremonitormetrics.create_default_mac'] + send_raw_request(cmd.cli_ctx, "PUT", association_url, + body=association_body, headers=headers) + return azure_monitor_workspace_resource_id + except CLIError as e: + raise e + + +def get_azure_monitor_workspace_resource_id(cmd, cluster_subscription, cluster_region, raw_parameters): + azure_monitor_workspace_resource_id = raw_parameters.get("azure_monitor_workspace_resource_id") + if azure_monitor_workspace_resource_id is None or azure_monitor_workspace_resource_id == "": + azure_monitor_workspace_resource_id = create_default_mac(cmd, cluster_subscription, cluster_region) + else: + azure_monitor_workspace_resource_id = sanitize_resource_id(azure_monitor_workspace_resource_id) + return azure_monitor_workspace_resource_id.lower() + + +def get_default_dce_name(cmd, mac_region, cluster_name): + region = get_default_region(cmd) + if mac_region in MapToClosestMACRegion: + region = MapToClosestMACRegion[mac_region] + default_dce_name = "MSProm-" + region + "-" + cluster_name + return sanitize_name(default_dce_name, DC_TYPE.DCE, 44) + + +def get_default_dcr_name(cmd, mac_region, cluster_name): + region = get_default_region(cmd) + if mac_region in MapToClosestMACRegion: + region = MapToClosestMACRegion[mac_region] + default_dcr_name = "MSProm-" + region + "-" + cluster_name + return sanitize_name(default_dcr_name, DC_TYPE.DCR, 64) + + +def get_default_dcra_name(cmd, cluster_region, cluster_name): + region = get_default_region(cmd) + if cluster_region in MapToClosestMACRegion: + region = MapToClosestMACRegion[cluster_region] + default_dcra_name = "ContainerInsightsMetricsExtension-" + region + "-" + cluster_name + return sanitize_name(default_dcra_name, DC_TYPE.DCRA, 64) + + +def get_mac_region_and_check_support(cmd, azure_monitor_workspace_resource_id, cluster_region): + from azure.cli.core.util import send_raw_request + from azure.core.exceptions import HttpResponseError + # region of MAC can be different from region of RG so find the location of the azure_monitor_workspace_resource_id + mac_subscription_id = azure_monitor_workspace_resource_id.split("/")[2] + resources = get_resources_client(cmd.cli_ctx, mac_subscription_id) + try: + resource = resources.get_by_id( + azure_monitor_workspace_resource_id, MAC_API) + mac_location = resource.location + except HttpResponseError as ex: + raise ex + # first get the association between region display names and region IDs (because for some reason + # the "which RPs are available in which regions" check returns region display names) + region_names_to_id = {} + # retry the request up to two times + for _ in range(3): + try: + headers = ['User-Agent=azuremonitormetrics.get_mac_region_and_check_support.mac_subscription_location_support_check'] + location_list_url = f"https://management.azure.com/subscriptions/{mac_subscription_id}/locations?api-version=2019-11-01" + r = send_raw_request(cmd.cli_ctx, "GET", location_list_url, headers=headers) + + # this is required to fool the static analyzer. The else statement will only run if an exception + # is thrown, but flake8 will complain that e is undefined if we don"t also define it here. + error = None + break + except CLIError as e: + error = e + else: + # This will run if the above for loop was not broken out of. This means all three requests failed + raise error + json_response = json.loads(r.text) + for region_data in json_response["value"]: + region_names_to_id[region_data["displayName"] + ] = region_data["name"] + # check if region supports DCR and DCRA + for _ in range(3): + try: + feature_check_url = f"https://management.azure.com/subscriptions/{mac_subscription_id}/providers/Microsoft.Insights?api-version=2020-10-01" + headers = ['User-Agent=azuremonitormetrics.get_mac_region_and_check_support.mac_subscription_dcr_dcra_regions_support_check'] + r = send_raw_request(cmd.cli_ctx, "GET", feature_check_url, headers=headers) + error = None + break + except CLIError as e: + error = e + else: + raise error + json_response = json.loads(r.text) + for resource in json_response["resourceTypes"]: + region_ids = map(lambda x: region_names_to_id[x], + resource["locations"]) # map is lazy, so doing this for every region isn"t slow + if resource["resourceType"].lower() == "datacollectionrules" and mac_location not in region_ids: + raise ClientRequestError( + f"Data Collection Rules are not supported for MAC region {mac_location}") + elif resource[ + "resourceType"].lower() == "datacollectionruleassociations" and cluster_region not in region_ids: + raise ClientRequestError( + f"Data Collection Rule Associations are not supported for cluster region {cluster_region}") + return mac_location + + +def create_dce(cmd, cluster_subscription, cluster_resource_group_name, cluster_name, mac_region): + from azure.cli.core.util import send_raw_request + dce_name = get_default_dce_name(cmd, mac_region, cluster_name) + dce_resource_id = "/subscriptions/{0}/resourceGroups/{1}/providers/Microsoft.Insights/dataCollectionEndpoints/{2}".format(cluster_subscription, cluster_resource_group_name, dce_name) + try: + dce_url = f"https://management.azure.com{dce_resource_id}?api-version={DC_API}" + dce_creation_body = json.dumps({"name": dce_name, + "location": mac_region, + "kind": "Linux", + "properties": {}}) + headers = ['User-Agent=azuremonitormetrics.create_dce'] + send_raw_request(cmd.cli_ctx, "PUT", + dce_url, body=dce_creation_body, headers=headers) + error = None + return dce_resource_id + except CLIError as error: + raise error + + +# pylint: disable=too-many-locals,too-many-branches,too-many-statements,line-too-long +def create_dcr(cmd, mac_region, azure_monitor_workspace_resource_id, cluster_subscription, cluster_resource_group_name, cluster_name, dce_resource_id): + from azure.cli.core.util import send_raw_request + dcr_name = get_default_dcr_name(cmd, mac_region, cluster_name) + dcr_resource_id = "/subscriptions/{0}/resourceGroups/{1}/providers/Microsoft.Insights/dataCollectionRules/{2}".format( + cluster_subscription, + cluster_resource_group_name, + dcr_name + ) + dcr_creation_body = json.dumps({"location": mac_region, + "kind": "Linux", + "properties": { + "dataCollectionEndpointId": dce_resource_id, + "dataSources": {"prometheusForwarder": [{"name": "PrometheusDataSource", "streams": ["Microsoft-PrometheusMetrics"], "labelIncludeFilter": {}}]}, + "dataFlows": [{"destinations": ["MonitoringAccount1"], "streams": ["Microsoft-PrometheusMetrics"]}], + "description": "DCR description", + "destinations": { + "monitoringAccounts": [{"accountResourceId": azure_monitor_workspace_resource_id, "name": "MonitoringAccount1"}]}}}) + dcr_url = f"https://management.azure.com{dcr_resource_id}?api-version={DC_API}" + try: + headers = ['User-Agent=azuremonitormetrics.create_dcr'] + send_raw_request(cmd.cli_ctx, "PUT", + dcr_url, body=dcr_creation_body, headers=headers) + error = None + return dcr_resource_id + except CLIError as error: + raise error + + +def create_dcra(cmd, cluster_region, cluster_subscription, cluster_resource_group_name, cluster_name, dcr_resource_id): + from azure.cli.core.util import send_raw_request + cluster_resource_id = "/subscriptions/{0}/resourceGroups/{1}/providers/Microsoft.ContainerService/managedClusters/{2}".format( + cluster_subscription, + cluster_resource_group_name, + cluster_name + ) + dcra_name = get_default_dcra_name(cmd, cluster_region, cluster_name) + dcra_resource_id = "/subscriptions/{0}/resourceGroups/{1}/providers/Microsoft.Insights/dataCollectionRuleAssociations/{2}".format( + cluster_subscription, + cluster_resource_group_name, + dcra_name + ) + # only create or delete the association between the DCR and cluster + association_body = json.dumps({"location": cluster_region, + "properties": { + "dataCollectionRuleId": dcr_resource_id, + "description": "Promtheus data collection association between DCR, DCE and target AKS resource" + }}) + association_url = f"https://management.azure.com{cluster_resource_id}/providers/Microsoft.Insights/dataCollectionRuleAssociations/{dcra_name}?api-version={DC_API}" + try: + headers = ['User-Agent=azuremonitormetrics.create_dcra'] + send_raw_request(cmd.cli_ctx, "PUT", association_url, + body=association_body, headers=headers) + error = None + return dcra_resource_id + except CLIError as error: + raise error + + +def link_grafana_instance(cmd, raw_parameters, azure_monitor_workspace_resource_id): + from azure.cli.core.util import send_raw_request + # GET grafana principal ID + try: + grafana_resource_id = raw_parameters.get("grafana_resource_id") + if grafana_resource_id is None or grafana_resource_id == "": + return GrafanaLink.NOPARAMPROVIDED + grafana_resource_id = sanitize_resource_id(grafana_resource_id) + grafanaURI = "https://management.azure.com{0}?api-version={1}".format( + grafana_resource_id, + GRAFANA_API + ) + headers = ['User-Agent=azuremonitormetrics.link_grafana_instance'] + grafanaArmResponse = send_raw_request(cmd.cli_ctx, "GET", grafanaURI, body={}, headers=headers) + servicePrincipalId = grafanaArmResponse.json()["identity"]["principalId"] + except CLIError as e: + raise CLIError(e) + # Add Role Assignment + try: + MonitoringDataReader = "b0d8363b-8ddd-447d-831f-62ca05bff136" + roleDefinitionURI = "https://management.azure.com{0}/providers/Microsoft.Authorization/roleAssignments/{1}?api-version={2}".format( + azure_monitor_workspace_resource_id, + uuid.uuid4(), + GRAFANA_ROLE_ASSIGNMENT_API + ) + roleDefinitionId = "{0}/providers/Microsoft.Authorization/roleDefinitions/{1}".format( + azure_monitor_workspace_resource_id, + MonitoringDataReader + ) + association_body = json.dumps({"properties": {"roleDefinitionId": roleDefinitionId, "principalId": servicePrincipalId}}) + headers = ['User-Agent=azuremonitormetrics.add_role_assignment'] + send_raw_request(cmd.cli_ctx, "PUT", roleDefinitionURI, body=association_body, headers=headers) + except CLIError as e: + if e.response.status_code != 409: + erroString = "Role Assingment failed. Please manually assign the `Monitoring Data Reader` role to the Azure Monitor Workspace ({0}) for the Azure Managed Grafana System Assigned Managed Identity ({1})".format( + azure_monitor_workspace_resource_id, + servicePrincipalId + ) + print(erroString) + # Setting up AMW Integration + targetGrafanaArmPayload = grafanaArmResponse.json() + if targetGrafanaArmPayload["properties"] is None: + raise CLIError("Invalid grafana payload to add AMW integration") + if "grafanaIntegrations" not in json.dumps(targetGrafanaArmPayload): + targetGrafanaArmPayload["properties"]["grafanaIntegrations"] = {} + if "azureMonitorWorkspaceIntegrations" not in json.dumps(targetGrafanaArmPayload): + targetGrafanaArmPayload["properties"]["grafanaIntegrations"]["azureMonitorWorkspaceIntegrations"] = [] + amwIntegrations = targetGrafanaArmPayload["properties"]["grafanaIntegrations"]["azureMonitorWorkspaceIntegrations"] + if amwIntegrations != [] and azure_monitor_workspace_resource_id in json.dumps(amwIntegrations).lower(): + return GrafanaLink.ALREADYPRESENT + try: + grafanaURI = "https://management.azure.com{0}?api-version={1}".format( + grafana_resource_id, + GRAFANA_API + ) + targetGrafanaArmPayload["properties"]["grafanaIntegrations"]["azureMonitorWorkspaceIntegrations"].append({"azureMonitorWorkspaceResourceId": azure_monitor_workspace_resource_id}) + targetGrafanaArmPayload = json.dumps(targetGrafanaArmPayload) + headers = ['User-Agent=azuremonitormetrics.setup_amw_grafana_integration', 'Content-Type=application/json'] + send_raw_request(cmd.cli_ctx, "PUT", grafanaURI, body=targetGrafanaArmPayload, headers=headers) + except CLIError as e: + raise CLIError(e) + return GrafanaLink.SUCCESS + + +def put_rules(cmd, default_rule_group_id, default_rule_group_name, mac_region, azure_monitor_workspace_resource_id, cluster_name, default_rules_template, url, i): + from azure.cli.core.util import send_raw_request + body = json.dumps({ + "id": default_rule_group_id, + "name": default_rule_group_name, + "type": "Microsoft.AlertsManagement/prometheusRuleGroups", + "location": mac_region, + "properties": { + "scopes": [ + azure_monitor_workspace_resource_id + ], + "enabled": True, + "clusterName": cluster_name, + "interval": "PT1M", + "rules": default_rules_template[i]["properties"]["rulesArmTemplate"]["resources"][0]["properties"]["rules"] + } + }) + for _ in range(3): + try: + headers = ['User-Agent=azuremonitormetrics.put_rules.' + default_rule_group_name] + send_raw_request(cmd.cli_ctx, "PUT", url, + body=body, headers=headers) + error = None + break + except CLIError as e: + error = e + else: + raise error + + +def delete_rule(cmd, cluster_subscription, cluster_resource_group_name, cluster_name, default_rule_group_name): + from azure.cli.core.util import send_raw_request + default_rule_group_id = "/subscriptions/{0}/resourceGroups/{1}/providers/Microsoft.AlertsManagement/prometheusRuleGroups/{2}".format( + cluster_subscription, + cluster_resource_group_name, + default_rule_group_name + ) + headers = ['User-Agent=azuremonitormetrics.delete_rule.' + default_rule_group_name] + url = "https://management.azure.com{0}?api-version={1}".format( + default_rule_group_id, + RULES_API + ) + send_raw_request(cmd.cli_ctx, "DELETE", url, headers=headers) + + +def get_recording_rules_template(cmd, azure_monitor_workspace_resource_id): + from azure.cli.core.util import send_raw_request + headers = ['User-Agent=azuremonitormetrics.get_recording_rules_template'] + url = f"https://management.azure.com{azure_monitor_workspace_resource_id}/providers/microsoft.alertsManagement/alertRuleRecommendations?api-version={ALERTS_API}" + r = send_raw_request(cmd.cli_ctx, "GET", url, headers=headers) + data = json.loads(r.text) + return data['value'] + + +def create_rules(cmd, cluster_subscription, cluster_resource_group_name, cluster_name, azure_monitor_workspace_resource_id, mac_region, raw_parameters): + # with urllib.request.urlopen("https://defaultrulessc.blob.core.windows.net/defaultrules/ManagedPrometheusDefaultRecordingRules.json") as url: + # default_rules_template = json.loads(url.read().decode()) + default_rules_template = get_recording_rules_template(cmd, azure_monitor_workspace_resource_id) + default_rule_group_name = "NodeRecordingRulesRuleGroup-{0}".format(cluster_name) + default_rule_group_id = "/subscriptions/{0}/resourceGroups/{1}/providers/Microsoft.AlertsManagement/prometheusRuleGroups/{2}".format( + cluster_subscription, + cluster_resource_group_name, + default_rule_group_name + ) + url = "https://management.azure.com{0}?api-version={1}".format( + default_rule_group_id, + RULES_API + ) + put_rules(cmd, default_rule_group_id, default_rule_group_name, mac_region, azure_monitor_workspace_resource_id, cluster_name, default_rules_template, url, 0) + + default_rule_group_name = "KubernetesRecordingRulesRuleGroup-{0}".format(cluster_name) + default_rule_group_id = "/subscriptions/{0}/resourceGroups/{1}/providers/Microsoft.AlertsManagement/prometheusRuleGroups/{2}".format( + cluster_subscription, + cluster_resource_group_name, + default_rule_group_name + ) + url = "https://management.azure.com{0}?api-version={1}".format( + default_rule_group_id, + RULES_API + ) + put_rules(cmd, default_rule_group_id, default_rule_group_name, mac_region, azure_monitor_workspace_resource_id, cluster_name, default_rules_template, url, 1) + + enable_windows_recording_rules = raw_parameters.get("enable_windows_recording_rules") + + if enable_windows_recording_rules is True: + default_rule_group_name = "NodeRecordingRulesRuleGroup-Win-{0}".format(cluster_name) + default_rule_group_id = "/subscriptions/{0}/resourceGroups/{1}/providers/Microsoft.AlertsManagement/prometheusRuleGroups/{2}".format( + cluster_subscription, + cluster_resource_group_name, + default_rule_group_name + ) + url = "https://management.azure.com{0}?api-version={1}".format( + default_rule_group_id, + RULES_API + ) + put_rules(cmd, default_rule_group_id, default_rule_group_name, mac_region, azure_monitor_workspace_resource_id, cluster_name, default_rules_template, url, 2) + + default_rule_group_name = "NodeAndKubernetesRecordingRulesRuleGroup-Win-{0}".format(cluster_name) + default_rule_group_id = "/subscriptions/{0}/resourceGroups/{1}/providers/Microsoft.AlertsManagement/prometheusRuleGroups/{2}".format( + cluster_subscription, + cluster_resource_group_name, + default_rule_group_name + ) + url = "https://management.azure.com{0}?api-version={1}".format( + default_rule_group_id, + RULES_API + ) + put_rules(cmd, default_rule_group_id, default_rule_group_name, mac_region, azure_monitor_workspace_resource_id, cluster_name, default_rules_template, url, 3) + + +def get_dce_from_dcr(cmd, dcrId): + from azure.cli.core.util import send_raw_request + association_url = f"https://management.azure.com{dcrId}?api-version={DC_API}" + headers = ['User-Agent=azuremonitormetrics.get_dce_from_dcr'] + r = send_raw_request(cmd.cli_ctx, "GET", association_url, headers=headers) + data = json.loads(r.text) + return data['properties']['dataCollectionEndpointId'] + + +def get_dc_objects_list(cmd, cluster_region, cluster_subscription, cluster_resource_group_name, cluster_name): + try: + from azure.cli.core.util import send_raw_request + cluster_resource_id = "/subscriptions/{0}/resourceGroups/{1}/providers/Microsoft.ContainerService/managedClusters/{2}".format( + cluster_subscription, + cluster_resource_group_name, + cluster_name + ) + association_url = f"https://management.azure.com{cluster_resource_id}/providers/Microsoft.Insights/dataCollectionRuleAssociations?api-version={DC_API}" + headers = ['User-Agent=azuremonitormetrics.get_dcra'] + r = send_raw_request(cmd.cli_ctx, "GET", association_url, headers=headers) + data = json.loads(r.text) + dc_object_array = [] + for item in data['value']: + dce_id = get_dce_from_dcr(cmd, item['properties']['dataCollectionRuleId']) + dc_object_array.append({'name': item['name'], 'dataCollectionRuleId': item['properties']['dataCollectionRuleId'], 'dceId': dce_id}) + return dc_object_array + except CLIError as e: + error = e + raise CLIError(error) + + +def delete_dc_objects_if_prometheus_enabled(cmd, dc_objects_list, cluster_subscription, cluster_resource_group_name, cluster_name): + from azure.cli.core.util import send_raw_request + cluster_resource_id = "/subscriptions/{0}/resourceGroups/{1}/providers/Microsoft.ContainerService/managedClusters/{2}".format( + cluster_subscription, + cluster_resource_group_name, + cluster_name + ) + for item in dc_objects_list: + association_url = f"https://management.azure.com{item['dataCollectionRuleId']}?api-version={DC_API}" + try: + headers = ['User-Agent=azuremonitormetrics.get_dcr_if_prometheus_enabled'] + r = send_raw_request(cmd.cli_ctx, "GET", association_url, headers=headers) + data = json.loads(r.text) + if 'microsoft-prometheusmetrics' in [stream.lower() for stream in data['properties']['dataFlows'][0]['streams']]: + # delete DCE + url = f"https://management.azure.com{item['dceId']}?api-version={DC_API}" + headers = ['User-Agent=azuremonitormetrics.delete_dce'] + send_raw_request(cmd.cli_ctx, "DELETE", url, headers=headers) + # delete DCR + url = f"https://management.azure.com{item['dataCollectionRuleId']}?api-version={DC_API}" + headers = ['User-Agent=azuremonitormetrics.delete_dcr'] + send_raw_request(cmd.cli_ctx, "DELETE", url, headers=headers) + # delete DCRA + url = f"https://management.azure.com{cluster_resource_id}/providers/Microsoft.Insights/dataCollectionRuleAssociations/{item['name']}?api-version={DC_API}" + headers = ['User-Agent=azuremonitormetrics.delete_dcra'] + send_raw_request(cmd.cli_ctx, "DELETE", url, headers=headers) + error = None + except CLIError as e: + error = e + raise CLIError(error) + + +def delete_rules(cmd, cluster_subscription, cluster_resource_group_name, cluster_name): + delete_rule(cmd, cluster_subscription, cluster_resource_group_name, cluster_name, "NodeRecordingRulesRuleGroup-{0}".format(cluster_name)) + delete_rule(cmd, cluster_subscription, cluster_resource_group_name, cluster_name, "KubernetesRecordingRulesRuleGroup-{0}".format(cluster_name)) + delete_rule(cmd, cluster_subscription, cluster_resource_group_name, cluster_name, "NodeRecordingRulesRuleGroup-Win-{0}".format(cluster_name)) + delete_rule(cmd, cluster_subscription, cluster_resource_group_name, cluster_name, "NodeAndKubernetesRecordingRulesRuleGroup-Win-{0}".format(cluster_name)) + + +def link_azure_monitor_profile_artifacts(cmd, cluster_subscription, cluster_resource_group_name, cluster_name, cluster_region, raw_parameters): + # MAC creation if required + azure_monitor_workspace_resource_id = get_azure_monitor_workspace_resource_id(cmd, cluster_subscription, cluster_region, raw_parameters) + # Get MAC region (required for DCE, DCR creation) and check support for DCE,DCR creation + mac_region = get_mac_region_and_check_support(cmd, azure_monitor_workspace_resource_id, cluster_region) + # DCE creation + dce_resource_id = create_dce(cmd, cluster_subscription, cluster_resource_group_name, cluster_name, mac_region) + # DCR creation + dcr_resource_id = create_dcr(cmd, mac_region, azure_monitor_workspace_resource_id, cluster_subscription, cluster_resource_group_name, cluster_name, dce_resource_id) + # DCRA creation + create_dcra(cmd, cluster_region, cluster_subscription, cluster_resource_group_name, cluster_name, dcr_resource_id) + # Link grafana + link_grafana_instance(cmd, raw_parameters, azure_monitor_workspace_resource_id) + # create recording rules and alerts + create_rules(cmd, cluster_subscription, cluster_resource_group_name, cluster_name, azure_monitor_workspace_resource_id, mac_region, raw_parameters) + + +def unlink_azure_monitor_profile_artifacts(cmd, cluster_subscription, cluster_resource_group_name, cluster_name, cluster_region): + ################ CHECK IF DCR IS LINKED WITH ANOTHER DCRA ############################################## + # Remove DC* if prometheus is enabled + dc_objects_list = get_dc_objects_list(cmd, cluster_region, cluster_subscription, cluster_resource_group_name, cluster_name) + delete_dc_objects_if_prometheus_enabled(cmd, dc_objects_list, cluster_subscription, cluster_resource_group_name, cluster_name) + # Delete rules (Conflict({"error":{"code":"InvalidResourceLocation","message":"The resource 'NodeRecordingRulesRuleGroup-' already exists in location 'eastus2' in resource group ''. A resource with the same name cannot be created in location 'eastus'. Please select a new resource name."}}) + delete_rules(cmd, cluster_subscription, cluster_resource_group_name, cluster_name) + + +def post_request(cmd, subscription_id, rp_name, headers): + from azure.cli.core.util import send_raw_request + customUrl = "https://management.azure.com/subscriptions/{0}/providers/{1}/register?api-version={2}".format( + subscription_id, + rp_name, + RP_API + ) + try: + send_raw_request(cmd.cli_ctx, "POST", customUrl, headers=headers) + except CLIError as e: + raise CLIError(e) + + +def rp_registrations(cmd, subscription_id): + from azure.cli.core.util import send_raw_request + # Get list of RP's for RP's subscription + try: + headers = ['User-Agent=azuremonitormetrics.get_mac_sub_list'] + customUrl = "https://management.azure.com/subscriptions/{0}/providers?api-version={1}&$select=namespace,registrationstate".format( + subscription_id, + RP_API + ) + r = send_raw_request(cmd.cli_ctx, "GET", customUrl, headers=headers) + except CLIError as e: + raise CLIError(e) + isInsightsRpRegistered = False + isAlertsManagementRpRegistered = False + isMoniotrRpRegistered = False + isDashboardRpRegistered = False + json_response = json.loads(r.text) + values_array = json_response["value"] + for value in values_array: + if value["namespace"].lower() == "microsoft.insights" and value["registrationState"].lower() == "registered": + isInsightsRpRegistered = True + if value["namespace"].lower() == "microsoft.alertsmanagement" and value["registrationState"].lower() == "registered": + isAlertsManagementRpRegistered = True + if value["namespace"].lower() == "microsoft.monitor" and value["registrationState"].lower() == "registered": + isAlertsManagementRpRegistered = True + if value["namespace"].lower() == "microsoft.dashboard" and value["registrationState"].lower() == "registered": + isAlertsManagementRpRegistered = True + if isInsightsRpRegistered is False: + headers = ['User-Agent=azuremonitormetrics.register_insights_rp'] + post_request(cmd, subscription_id, "microsoft.insights", headers) + if isAlertsManagementRpRegistered is False: + headers = ['User-Agent=azuremonitormetrics.register_alertsmanagement_rp'] + post_request(cmd, subscription_id, "microsoft.alertsmanagement", headers) + if isMoniotrRpRegistered is False: + headers = ['User-Agent=azuremonitormetrics.register_monitor_rp'] + post_request(cmd, subscription_id, "microsoft.monitor", headers) + if isDashboardRpRegistered is False: + headers = ['User-Agent=azuremonitormetrics.register_dashboard_rp'] + post_request(cmd, subscription_id, "microsoft.dashboard", headers) + + +# pylint: disable=too-many-locals,too-many-branches,too-many-statements,line-too-long +def ensure_azure_monitor_profile_prerequisites( + cmd, + client, + cluster_subscription, + cluster_resource_group_name, + cluster_name, + cluster_region, + raw_parameters, + remove_azuremonitormetrics, + create_flow=False +): + cloud_name = cmd.cli_ctx.cloud.name + if cloud_name.lower() == 'azurechinacloud': + raise CLIError("Azure China Cloud is not supported for the Azure Monitor Metrics addon") + + if cloud_name.lower() == "azureusgovernment": + grafana_resource_id = raw_parameters.get("grafana_resource_id") + if grafana_resource_id is not None or grafana_resource_id != "": + raise InvalidArgumentValueError("Azure US Government cloud does not support Azure Managed Grarfana yet. Please follow this documenation for enabling it via the public cloud : aka.ms/ama-grafana-link-ff") + + if (remove_azuremonitormetrics): + unlink_azure_monitor_profile_artifacts( + cmd, + cluster_subscription, + cluster_resource_group_name, + cluster_name, + cluster_region + ) + else: + # Check if already onboarded + if create_flow == False: + check_azuremonitormetrics_profile(cmd, cluster_subscription, cluster_resource_group_name, cluster_name) + # If the feature is not registered then STOP onboarding and request to register the feature + check_azuremonitoraddon_feature(cmd, cluster_subscription, raw_parameters) + # Do RP registrations if required + rp_registrations(cmd, cluster_subscription) + link_azure_monitor_profile_artifacts( + cmd, + cluster_subscription, + cluster_resource_group_name, + cluster_name, + cluster_region, + raw_parameters + ) + return diff --git a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/responseparsers/amwlocationresponseparser.py b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/responseparsers/amwlocationresponseparser.py new file mode 100644 index 00000000000..ca3016a0665 --- /dev/null +++ b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/responseparsers/amwlocationresponseparser.py @@ -0,0 +1,24 @@ +from typing import List + +def parseResourceProviderResponseForLocations(resourceProviderResponse): + supportedLocationMap = {} + if not resourceProviderResponse.get('resourceTypes'): + return supportedLocationMap + resourceTypesRawArr = resourceProviderResponse['resourceTypes'] + for resourceTypeResponse in resourceTypesRawArr: + if resourceTypeResponse['resourceType'] == 'accounts': + supportedLocationMap = parseLocations(resourceTypeResponse['locations']) + return supportedLocationMap + + +def parseLocations(locations: List[str]) -> List[str]: + if not locations or not len(locations): + return [] + return list(map(lambda location: reduceLocation(location), locations)) + + +def reduceLocation(location: str) -> str: + if not location: + return location + location = location.replace(' ', '').lower() + return location diff --git a/src/azure-cli/azure/cli/command_modules/acs/custom.py b/src/azure-cli/azure/cli/command_modules/acs/custom.py index f7609856692..d75aca43b16 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/custom.py +++ b/src/azure-cli/azure/cli/command_modules/acs/custom.py @@ -25,6 +25,7 @@ from distutils.version import StrictVersion from urllib.error import URLError from urllib.request import urlopen +from azure.cli.command_modules.acs.azuremonitormetrics.azuremonitorprofile import ensure_azure_monitor_profile_prerequisites import colorama import requests @@ -493,6 +494,13 @@ def aks_create( linux_os_config=None, host_group_id=None, gpu_instance_profile=None, + # azure monitor profile + enable_azuremonitormetrics=False, + azure_monitor_workspace_resource_id=None, + ksm_metric_labels_allow_list=None, + ksm_metric_annotations_allow_list=None, + grafana_resource_id=None, + enable_windows_recording_rules=False, # misc yes=False, no_wait=False, @@ -530,7 +538,21 @@ def aks_create( # exit gracefully return None # send request to create a real managed cluster - return aks_create_decorator.create_mc(mc) + cluster = aks_create_decorator.create_mc(mc) + + if raw_parameters.get("enable_azuremonitormetrics"): + ensure_azure_monitor_profile_prerequisites( + cmd, + client, + get_subscription_id(cmd.cli_ctx), + resource_group_name, + name, + location, + raw_parameters, + False, + True) + + return cluster def aks_update( @@ -609,6 +631,14 @@ def aks_update( min_count=None, max_count=None, nodepool_labels=None, + # azure monitor profile + enable_azuremonitormetrics=False, + azure_monitor_workspace_resource_id=None, + ksm_metric_labels_allow_list=None, + ksm_metric_annotations_allow_list=None, + grafana_resource_id=None, + enable_windows_recording_rules=False, + disable_azuremonitormetrics=False, # misc yes=False, no_wait=False, diff --git a/src/azure-cli/azure/cli/command_modules/acs/managed_cluster_decorator.py b/src/azure-cli/azure/cli/command_modules/acs/managed_cluster_decorator.py index c137d7d7986..066e6d70627 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/managed_cluster_decorator.py +++ b/src/azure-cli/azure/cli/command_modules/acs/managed_cluster_decorator.py @@ -61,6 +61,7 @@ AKSAgentPoolModels, AKSAgentPoolUpdateDecorator, ) +from azure.cli.command_modules.acs.azuremonitormetrics.azuremonitorprofile import ensure_azure_monitor_profile_prerequisites from azure.cli.command_modules.acs.base_decorator import ( BaseAKSContext, BaseAKSManagedClusterDecorator, @@ -4738,6 +4739,64 @@ def get_aks_custom_headers(self) -> Dict[str, str]: # this parameter does not need validation return aks_custom_headers + def _get_enable_azure_monitor_metrics(self, enable_validation: bool = False) -> bool: + """Internal function to obtain the value of enable_azure_monitor_metrics. + This function supports the option of enable_validation. When enabled, if both enable_azure_monitor_metrics and disable_azure_monitor_metrics are + specified, raise a MutuallyExclusiveArgumentError. + + :return: bool + """ + # print("_get_enable_azure_monitor_metrics being called...") + # Read the original value passed by the command. + enable_azure_monitor_metrics = self.raw_param.get("enable_azuremonitormetrics") + # In create mode, try to read the property value corresponding to the parameter from the `mc` object. + if self.decorator_mode == DecoratorMode.CREATE: + if ( + self.mc and + self.mc.azure_monitor_profile and + self.mc.azure_monitor_profile.metrics + ): + enable_azure_monitor_metrics = self.mc.azure_monitor_profile.metrics.enabled + # This parameter does not need dynamic completion. + if enable_validation: + if enable_azure_monitor_metrics and self._get_disable_azure_monitor_metrics(False): + raise MutuallyExclusiveArgumentError( + "Cannot specify --enable-azuremonitormetrics and --disable-azuremonitormetrics at the same time." + ) + if enable_azure_monitor_metrics and not check_is_msi_cluster(self.mc): + raise RequiredArgumentMissingError( + "--enable-azuremonitormetrics can only be specified for clusters with managed identity enabled" + ) + return enable_azure_monitor_metrics + + def get_enable_azure_monitor_metrics(self) -> bool: + """Obtain the value of enable_azure_monitor_metrics. + This function will verify the parameter by default. If both enable_azure_monitor_metrics and disable_azure_monitor_metrics are specified, raise a + MutuallyExclusiveArgumentError. + :return: bool + """ + return self._get_enable_azure_monitor_metrics(enable_validation=True) + + def _get_disable_azure_monitor_metrics(self, enable_validation: bool = False) -> bool: + """Internal function to obtain the value of disable_azure_monitor_metrics. + This function supports the option of enable_validation. When enabled, if both enable_azure_monitor_metrics and disable_azure_monitor_metrics are + specified, raise a MutuallyExclusiveArgumentError. + :return: bool + """ + # Read the original value passed by the command. + disable_azure_monitor_metrics = self.raw_param.get("disable_azuremonitormetrics") + if disable_azure_monitor_metrics and self._get_enable_azure_monitor_metrics(False): + raise MutuallyExclusiveArgumentError("Cannot specify --enable-azuremonitormetrics and --disable-azuremonitormetrics at the same time.") + return disable_azure_monitor_metrics + + def get_disable_azure_monitor_metrics(self) -> bool: + """Obtain the value of disable_azure_monitor_metrics. + This function will verify the parameter by default. If both enable_azure_monitor_metrics and disable_azure_monitor_metrics are specified, raise a + MutuallyExclusiveArgumentError. + :return: bool + """ + return self._get_disable_azure_monitor_metrics(enable_validation=True) + class AKSManagedClusterCreateDecorator(BaseAKSManagedClusterDecorator): def __init__( @@ -5767,6 +5826,27 @@ def set_up_node_resource_group(self, mc: ManagedCluster) -> ManagedCluster: mc.node_resource_group = self.context.get_node_resource_group() return mc + def set_up_azure_monitor_profile(self, mc: ManagedCluster) -> ManagedCluster: + """Set up azure monitor profile for the ManagedCluster object. + :return: the ManagedCluster object + """ + self._ensure_mc(mc) + # read the original value passed by the command + ksm_metric_labels_allow_list = self.context.raw_param.get("ksm_metric_labels_allow_list") + ksm_metric_annotations_allow_list = self.context.raw_param.get("ksm_metric_annotations_allow_list") + if ksm_metric_labels_allow_list is None: + ksm_metric_labels_allow_list = "" + if ksm_metric_annotations_allow_list is None: + ksm_metric_annotations_allow_list = "" + if self.context.get_enable_azure_monitor_metrics(): + if mc.azure_monitor_profile is None: + mc.azure_monitor_profile = self.models.ManagedClusterAzureMonitorProfile() + mc.azure_monitor_profile.metrics = self.models.ManagedClusterAzureMonitorProfileMetrics(enabled=True) + mc.azure_monitor_profile.metrics.kube_state_metrics = self.models.ManagedClusterAzureMonitorProfileKubeStateMetrics( + metric_labels_allowlist=str(ksm_metric_labels_allow_list), + metric_annotations_allow_list=str(ksm_metric_annotations_allow_list)) + return mc + def construct_mc_profile_default(self, bypass_restore_defaults: bool = False) -> ManagedCluster: """The overall controller used to construct the default ManagedCluster profile. @@ -5832,6 +5912,8 @@ def construct_mc_profile_default(self, bypass_restore_defaults: bool = False) -> mc = self.set_up_http_proxy_config(mc) # set up workload autoscaler profile mc = self.set_up_workload_auto_scaler_profile(mc) + # set up azure monitor metrics profile + mc = self.set_up_azure_monitor_profile(mc) # DO NOT MOVE: keep this at the bottom, restore defaults if not bypass_restore_defaults: @@ -6798,6 +6880,48 @@ def update_workload_auto_scaler_profile(self, mc: ManagedCluster) -> ManagedClus return mc + def update_azure_monitor_profile(self, mc: ManagedCluster) -> ManagedCluster: + """Update azure monitor profile for the ManagedCluster object. + :return: the ManagedCluster object + """ + self._ensure_mc(mc) + + # read the original value passed by the command + ksm_metric_labels_allow_list = self.context.raw_param.get("ksm_metric_labels_allow_list") + ksm_metric_annotations_allow_list = self.context.raw_param.get("ksm_metric_annotations_allow_list") + + if ksm_metric_labels_allow_list is None: + ksm_metric_labels_allow_list = "" + if ksm_metric_annotations_allow_list is None: + ksm_metric_annotations_allow_list = "" + + if self.context.get_enable_azure_monitor_metrics(): + if mc.azure_monitor_profile is None: + mc.azure_monitor_profile = self.models.ManagedClusterAzureMonitorProfile() + mc.azure_monitor_profile.metrics = self.models.ManagedClusterAzureMonitorProfileMetrics(enabled=True) + mc.azure_monitor_profile.metrics.kube_state_metrics = self.models.ManagedClusterAzureMonitorProfileKubeStateMetrics( + metric_labels_allowlist=str(ksm_metric_labels_allow_list), + metric_annotations_allow_list=str(ksm_metric_annotations_allow_list)) + + if self.context.get_disable_azure_monitor_metrics(): + if mc.azure_monitor_profile is None: + mc.azure_monitor_profile = self.models.ManagedClusterAzureMonitorProfile() + mc.azure_monitor_profile.metrics = self.models.ManagedClusterAzureMonitorProfileMetrics(enabled=False) + + if (self.context.raw_param.get("enable_azuremonitormetrics") or self.context.raw_param.get("disable_azuremonitormetrics")): + ensure_azure_monitor_profile_prerequisites( + self.cmd, + self.client, + self.context.get_subscription_id(), + self.context.get_resource_group_name(), + self.context.get_name(), + self.context.get_location(), + self.__raw_parameters, + self.context.get_disable_azure_monitor_metrics(), + False) + + return mc + def update_mc_profile_default(self) -> ManagedCluster: """The overall controller used to update the default ManagedCluster profile. @@ -6857,6 +6981,8 @@ def update_mc_profile_default(self) -> ManagedCluster: mc = self.update_http_proxy_config(mc) # update workload autoscaler profile mc = self.update_workload_auto_scaler_profile(mc) + # update azure monitor metrics profile + mc = self.update_azure_monitor_profile(mc) return mc def check_is_postprocessing_required(self, mc: ManagedCluster) -> bool: From 5038ec1d92a495b42cdf8590471deb31e67f40c4 Mon Sep 17 00:00:00 2001 From: Kaveesh Dubey Date: Mon, 3 Apr 2023 14:53:20 -0700 Subject: [PATCH 02/41] some changes to post_processing after cluster create --- .../azuremonitorprofile.py | 13 +++++------ .../azure/cli/command_modules/acs/custom.py | 16 +------------- .../acs/managed_cluster_decorator.py | 22 ++++++++++++++++++- 3 files changed, 28 insertions(+), 23 deletions(-) diff --git a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/azuremonitorprofile.py b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/azuremonitorprofile.py index 6d7a2822427..37ad6eb6712 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/azuremonitorprofile.py +++ b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/azuremonitorprofile.py @@ -632,19 +632,18 @@ def delete_dc_objects_if_prometheus_enabled(cmd, dc_objects_list, cluster_subscr r = send_raw_request(cmd.cli_ctx, "GET", association_url, headers=headers) data = json.loads(r.text) if 'microsoft-prometheusmetrics' in [stream.lower() for stream in data['properties']['dataFlows'][0]['streams']]: - # delete DCE - url = f"https://management.azure.com{item['dceId']}?api-version={DC_API}" - headers = ['User-Agent=azuremonitormetrics.delete_dce'] + # delete DCRA + url = f"https://management.azure.com{cluster_resource_id}/providers/Microsoft.Insights/dataCollectionRuleAssociations/{item['name']}?api-version={DC_API}" + headers = ['User-Agent=azuremonitormetrics.delete_dcra'] send_raw_request(cmd.cli_ctx, "DELETE", url, headers=headers) # delete DCR url = f"https://management.azure.com{item['dataCollectionRuleId']}?api-version={DC_API}" headers = ['User-Agent=azuremonitormetrics.delete_dcr'] send_raw_request(cmd.cli_ctx, "DELETE", url, headers=headers) - # delete DCRA - url = f"https://management.azure.com{cluster_resource_id}/providers/Microsoft.Insights/dataCollectionRuleAssociations/{item['name']}?api-version={DC_API}" - headers = ['User-Agent=azuremonitormetrics.delete_dcra'] + # delete DCE + url = f"https://management.azure.com{item['dceId']}?api-version={DC_API}" + headers = ['User-Agent=azuremonitormetrics.delete_dce'] send_raw_request(cmd.cli_ctx, "DELETE", url, headers=headers) - error = None except CLIError as e: error = e raise CLIError(error) diff --git a/src/azure-cli/azure/cli/command_modules/acs/custom.py b/src/azure-cli/azure/cli/command_modules/acs/custom.py index d75aca43b16..d3f25fc4206 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/custom.py +++ b/src/azure-cli/azure/cli/command_modules/acs/custom.py @@ -538,21 +538,7 @@ def aks_create( # exit gracefully return None # send request to create a real managed cluster - cluster = aks_create_decorator.create_mc(mc) - - if raw_parameters.get("enable_azuremonitormetrics"): - ensure_azure_monitor_profile_prerequisites( - cmd, - client, - get_subscription_id(cmd.cli_ctx), - resource_group_name, - name, - location, - raw_parameters, - False, - True) - - return cluster + return aks_create_decorator.create_mc(mc) def aks_update( diff --git a/src/azure-cli/azure/cli/command_modules/acs/managed_cluster_decorator.py b/src/azure-cli/azure/cli/command_modules/acs/managed_cluster_decorator.py index 066e6d70627..a9c426e24ba 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/managed_cluster_decorator.py +++ b/src/azure-cli/azure/cli/command_modules/acs/managed_cluster_decorator.py @@ -252,6 +252,7 @@ def external_functions(self) -> SimpleNamespace: external_functions["add_monitoring_role_assignment"] = add_monitoring_role_assignment external_functions["add_virtual_node_role_assignment"] = add_virtual_node_role_assignment external_functions["ensure_container_insights_for_monitoring"] = ensure_container_insights_for_monitoring + external_functions["ensure_azure_monitor_profile_prerequisites"] = ensure_azure_monitor_profile_prerequisites external_functions[ "ensure_default_log_analytics_workspace_for_monitoring" ] = ensure_default_log_analytics_workspace_for_monitoring @@ -5845,6 +5846,8 @@ def set_up_azure_monitor_profile(self, mc: ManagedCluster) -> ManagedCluster: mc.azure_monitor_profile.metrics.kube_state_metrics = self.models.ManagedClusterAzureMonitorProfileKubeStateMetrics( metric_labels_allowlist=str(ksm_metric_labels_allow_list), metric_annotations_allow_list=str(ksm_metric_annotations_allow_list)) + # set intermediate + self.context.set_intermediate("azuremonitormetrics_addon_enabled", True, overwrite_exists=True) return mc def construct_mc_profile_default(self, bypass_restore_defaults: bool = False) -> ManagedCluster: @@ -5930,6 +5933,7 @@ def check_is_postprocessing_required(self, mc: ManagedCluster) -> bool: monitoring_addon_enabled = self.context.get_intermediate("monitoring_addon_enabled", default_value=False) ingress_appgw_addon_enabled = self.context.get_intermediate("ingress_appgw_addon_enabled", default_value=False) virtual_node_addon_enabled = self.context.get_intermediate("virtual_node_addon_enabled", default_value=False) + azuremonitormetrics_addon_enabled = self.context.get_intermediate("azuremonitormetrics_addon_enabled", default_value=False) enable_managed_identity = self.context.get_enable_managed_identity() attach_acr = self.context.get_attach_acr() need_grant_vnet_permission_to_cluster_identity = self.context.get_intermediate( @@ -5940,6 +5944,7 @@ def check_is_postprocessing_required(self, mc: ManagedCluster) -> bool: monitoring_addon_enabled or ingress_appgw_addon_enabled or virtual_node_addon_enabled or + azuremonitormetrics_addon_enabled or (enable_managed_identity and attach_acr) or need_grant_vnet_permission_to_cluster_identity ): @@ -6050,6 +6055,21 @@ def postprocessing_after_mc_created(self, cluster: ManagedCluster) -> None: is_service_principal=False, ) + # azure monitor metrics addon (v2) + azuremonitormetrics_addon_enabled = self.context.get_intermediate("azuremonitormetrics_addon_enabled", default_value=False) + if azuremonitormetrics_addon_enabled: + # Create the DC* objects, AMW, recording rules and grafana link here + self.context.external_functions.ensure_azure_monitor_profile_prerequisites( + self.cmd, + self.client, + self.context.get_subscription_id(), + self.context.get_resource_group_name(), + self.context.get_name(), + self.context.get_location(), + self.__raw_parameters, + self.context.get_disable_azure_monitor_metrics(), + True) + def put_mc(self, mc: ManagedCluster) -> ManagedCluster: if self.check_is_postprocessing_required(mc): # send request @@ -6909,7 +6929,7 @@ def update_azure_monitor_profile(self, mc: ManagedCluster) -> ManagedCluster: mc.azure_monitor_profile.metrics = self.models.ManagedClusterAzureMonitorProfileMetrics(enabled=False) if (self.context.raw_param.get("enable_azuremonitormetrics") or self.context.raw_param.get("disable_azuremonitormetrics")): - ensure_azure_monitor_profile_prerequisites( + self.context.external_functions.ensure_azure_monitor_profile_prerequisites( self.cmd, self.client, self.context.get_subscription_id(), From 8cd010e765e433fff07859f4c2015f8a3b8262ae Mon Sep 17 00:00:00 2001 From: Kaveesh Dubey Date: Tue, 4 Apr 2023 16:30:28 -0700 Subject: [PATCH 03/41] move all calls to after cluster creation and do another PUT for enabling the addon --- .../acs/azuremonitormetrics/addonput.py | 33 +++++++++++++++ .../azuremonitorprofile.py | 40 +++++-------------- .../acs/managed_cluster_decorator.py | 2 +- 3 files changed, 45 insertions(+), 30 deletions(-) create mode 100644 src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/addonput.py diff --git a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/addonput.py b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/addonput.py new file mode 100644 index 00000000000..87642fb5f09 --- /dev/null +++ b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/addonput.py @@ -0,0 +1,33 @@ +import json + +from azure.cli.core.azclierror import ( + UnknownError, + CLIError +) + +AKS_CLUSTER_API = "2023-01-01" # "2023-01-01" + +def addon_put(cmd, cluster_subscription, cluster_resource_group_name, cluster_name): + from azure.cli.core.util import send_raw_request + feature_check_url = f"https://management.azure.com/subscriptions/{cluster_subscription}/resourceGroups/{cluster_resource_group_name}/providers/Microsoft.ContainerService/managedClusters/{cluster_name}?api-version={AKS_CLUSTER_API}" + try: + headers = ['User-Agent=azuremonitormetrics.addon_get'] + r = send_raw_request(cmd.cli_ctx, "GET", feature_check_url, + body={}, headers=headers) + except CLIError as e: + raise UnknownError(e) + json_response = json.loads(r.text) + values_array = json_response["properties"] + if "azureMonitorProfile" in values_array: + if "metrics" in values_array["azureMonitorProfile"]: + if values_array["azureMonitorProfile"]["metrics"]["enabled"] is False: + ## What if enabled doesn't exist + values_array["azureMonitorProfile"]["metrics"]["enabled"] = True + try: + headers = ['User-Agent=azuremonitormetrics.addon_put'] + body = json.dumps(values_array) + r = send_raw_request(cmd.cli_ctx, "PUT", feature_check_url, + body=body, headers=headers) + except CLIError as e: + raise UnknownError(e) + \ No newline at end of file diff --git a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/azuremonitorprofile.py b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/azuremonitorprofile.py index 37ad6eb6712..bd13cf23acd 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/azuremonitorprofile.py +++ b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/azuremonitorprofile.py @@ -4,14 +4,16 @@ # -------------------------------------------------------------------------------------------- import json import uuid -from sre_constants import FAILURE, SUCCESS +# from sre_constants import FAILURE, SUCCESS + +from azure-cli.azure.cli.command_modules.acs.azuremonitormetrics.addonput import addon_put from azure.cli.command_modules.acs.azuremonitormetrics.responseparsers.amwlocationresponseparser import parseResourceProviderResponseForLocations -from knack.util import CLIError from azure.cli.core.azclierror import ( UnknownError, InvalidArgumentValueError, - ClientRequestError + ClientRequestError, + CLIError ) from .._client_factory import get_resources_client, get_resource_groups_client from enum import Enum @@ -120,28 +122,6 @@ def check_azuremonitormetrics_profile(cmd, cluster_subscription, cluster_resourc raise CLIError(f"Azure Monitor Metrics is already enabled for this cluster. Please use `az aks update --disable-azuremonitormetrics -g {cluster_resource_group_name} -n {cluster_name}` and then try enabling.") -# check if `az feature register --namespace Microsoft.ContainerService --name AKS-PrometheusAddonPreview` is Registered -def check_azuremonitoraddon_feature(cmd, cluster_subscription, raw_parameters): - aks_custom_headers = raw_parameters.get("aks_custom_headers") - if (aks_custom_headers is not None) and ("aks-prometheusaddonpreview" in aks_custom_headers.lower()): - return - from azure.cli.core.util import send_raw_request - feature_check_url = f"https://management.azure.com/subscriptions/{cluster_subscription}/providers/Microsoft.Features/subscriptionFeatureRegistrations?api-version={FEATURE_API}&featurename=AKS-PrometheusAddonPreview" - try: - headers = ['User-Agent=azuremonitormetrics.check_azuremonitoraddon_feature'] - r = send_raw_request(cmd.cli_ctx, "GET", feature_check_url, - body={}, headers=headers) - except CLIError as e: - raise UnknownError(e) - json_response = json.loads(r.text) - values_array = json_response["value"] - for value in values_array: - if value["properties"]["providerNamespace"].lower() == "microsoft.containerservice" and value["properties"]["state"].lower() == "registered": - return - raise CLIError("Please enable the feature AKS-PrometheusAddonPreview on your subscription using `az feature register --namespace Microsoft.ContainerService --name AKS-PrometheusAddonPreview` to use this feature.\ - If this feature was recently registered then please wait upto 5 mins for the feature registration to finish") - - # DCR = 64, DCE = 44, DCRA = 64 # All DC* object names should end only in alpha numeric (after `length` trim) # DCE remove underscore from cluster name @@ -656,7 +636,7 @@ def delete_rules(cmd, cluster_subscription, cluster_resource_group_name, cluster delete_rule(cmd, cluster_subscription, cluster_resource_group_name, cluster_name, "NodeAndKubernetesRecordingRulesRuleGroup-Win-{0}".format(cluster_name)) -def link_azure_monitor_profile_artifacts(cmd, cluster_subscription, cluster_resource_group_name, cluster_name, cluster_region, raw_parameters): +def link_azure_monitor_profile_artifacts(cmd, cluster_subscription, cluster_resource_group_name, cluster_name, cluster_region, raw_parameters, create_flow): # MAC creation if required azure_monitor_workspace_resource_id = get_azure_monitor_workspace_resource_id(cmd, cluster_subscription, cluster_region, raw_parameters) # Get MAC region (required for DCE, DCR creation) and check support for DCE,DCR creation @@ -671,6 +651,9 @@ def link_azure_monitor_profile_artifacts(cmd, cluster_subscription, cluster_reso link_grafana_instance(cmd, raw_parameters, azure_monitor_workspace_resource_id) # create recording rules and alerts create_rules(cmd, cluster_subscription, cluster_resource_group_name, cluster_name, azure_monitor_workspace_resource_id, mac_region, raw_parameters) + # if aks cluster create flow -> do a PUT on the AKS cluster to enable the addon + if create_flow: + addon_put(cmd, cluster_subscription, cluster_resource_group_name, cluster_name) def unlink_azure_monitor_profile_artifacts(cmd, cluster_subscription, cluster_resource_group_name, cluster_name, cluster_region): @@ -769,8 +752,6 @@ def ensure_azure_monitor_profile_prerequisites( # Check if already onboarded if create_flow == False: check_azuremonitormetrics_profile(cmd, cluster_subscription, cluster_resource_group_name, cluster_name) - # If the feature is not registered then STOP onboarding and request to register the feature - check_azuremonitoraddon_feature(cmd, cluster_subscription, raw_parameters) # Do RP registrations if required rp_registrations(cmd, cluster_subscription) link_azure_monitor_profile_artifacts( @@ -779,6 +760,7 @@ def ensure_azure_monitor_profile_prerequisites( cluster_resource_group_name, cluster_name, cluster_region, - raw_parameters + raw_parameters, + create_flow ) return diff --git a/src/azure-cli/azure/cli/command_modules/acs/managed_cluster_decorator.py b/src/azure-cli/azure/cli/command_modules/acs/managed_cluster_decorator.py index a9c426e24ba..5ce68a3b91d 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/managed_cluster_decorator.py +++ b/src/azure-cli/azure/cli/command_modules/acs/managed_cluster_decorator.py @@ -5842,7 +5842,7 @@ def set_up_azure_monitor_profile(self, mc: ManagedCluster) -> ManagedCluster: if self.context.get_enable_azure_monitor_metrics(): if mc.azure_monitor_profile is None: mc.azure_monitor_profile = self.models.ManagedClusterAzureMonitorProfile() - mc.azure_monitor_profile.metrics = self.models.ManagedClusterAzureMonitorProfileMetrics(enabled=True) + mc.azure_monitor_profile.metrics = self.models.ManagedClusterAzureMonitorProfileMetrics(enabled=False) mc.azure_monitor_profile.metrics.kube_state_metrics = self.models.ManagedClusterAzureMonitorProfileKubeStateMetrics( metric_labels_allowlist=str(ksm_metric_labels_allow_list), metric_annotations_allow_list=str(ksm_metric_annotations_allow_list)) From e76a69fead3ecfa19e3cbd007895f36367c1eb3a Mon Sep 17 00:00:00 2001 From: Kaveesh Dubey Date: Wed, 5 Apr 2023 10:23:55 -0700 Subject: [PATCH 04/41] . --- .../acs/azuremonitormetrics/dc/dcra.py | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/dcra.py diff --git a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/dcra.py b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/dcra.py new file mode 100644 index 00000000000..f6a0731b7a0 --- /dev/null +++ b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/dcra.py @@ -0,0 +1,49 @@ +import json + +from azure.cli.core.azclierror import ( + CLIError +) + +def get_default_dcra_name(cmd, cluster_region, cluster_name): + region = get_default_region(cmd) + if cluster_region in MapToClosestMACRegion: + region = MapToClosestMACRegion[cluster_region] + default_dcra_name = "ContainerInsightsMetricsExtension-" + region + "-" + cluster_name + return sanitize_name(default_dcra_name, DC_TYPE.DCRA, 64) + +def get_default_region(cmd): + cloud_name = cmd.cli_ctx.cloud.name + if cloud_name.lower() == 'azurechinacloud': + raise CLIError("Azure China Cloud is not supported for the Azure Monitor Metrics addon") + if cloud_name.lower() == 'azureusgovernment': + return "usgovvirginia" + return "eastus" + +def create_dcra(cmd, cluster_region, cluster_subscription, cluster_resource_group_name, cluster_name, dcr_resource_id): + from azure.cli.core.util import send_raw_request + cluster_resource_id = "/subscriptions/{0}/resourceGroups/{1}/providers/Microsoft.ContainerService/managedClusters/{2}".format( + cluster_subscription, + cluster_resource_group_name, + cluster_name + ) + dcra_name = get_default_dcra_name(cmd, cluster_region, cluster_name) + dcra_resource_id = "/subscriptions/{0}/resourceGroups/{1}/providers/Microsoft.Insights/dataCollectionRuleAssociations/{2}".format( + cluster_subscription, + cluster_resource_group_name, + dcra_name + ) + # only create or delete the association between the DCR and cluster + association_body = json.dumps({"location": cluster_region, + "properties": { + "dataCollectionRuleId": dcr_resource_id, + "description": "Promtheus data collection association between DCR, DCE and target AKS resource" + }}) + association_url = f"https://management.azure.com{cluster_resource_id}/providers/Microsoft.Insights/dataCollectionRuleAssociations/{dcra_name}?api-version={DC_API}" + try: + headers = ['User-Agent=azuremonitormetrics.create_dcra'] + send_raw_request(cmd.cli_ctx, "PUT", association_url, + body=association_body, headers=headers) + error = None + return dcra_resource_id + except CLIError as error: + raise error From b70b17f4c70ee060d3f3dc21fecb65ea868bdcd2 Mon Sep 17 00:00:00 2001 From: Kaveesh Dubey Date: Thu, 6 Apr 2023 16:41:56 -0700 Subject: [PATCH 05/41] . --- .../acs/azuremonitormetrics/addonput.py | 2 - .../acs/azuremonitormetrics/amg/link.py | 73 ++ .../acs/azuremonitormetrics/amw/create.py | 37 + .../acs/azuremonitormetrics/amw/defaults.py | 40 + .../acs/azuremonitormetrics/amw/helper.py | 31 + .../azuremonitorprofile.py | 699 +----------------- .../acs/azuremonitormetrics/constants.py | 85 +++ .../acs/azuremonitormetrics/dc/dce_api.py | 23 + .../acs/azuremonitormetrics/dc/dcr_api.py | 42 ++ .../dc/{dcra.py => dcra_api.py} | 15 - .../acs/azuremonitormetrics/dc/defaults.py | 38 + .../acs/azuremonitormetrics/dc/delete.py | 61 ++ .../acs/azuremonitormetrics/deaults.py | 9 + .../acs/azuremonitormetrics/helper.py | 89 +++ .../recordingrules/create.py | 95 +++ .../recordingrules/delete.py | 20 + 16 files changed, 658 insertions(+), 701 deletions(-) create mode 100644 src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/amg/link.py create mode 100644 src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/amw/create.py create mode 100644 src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/amw/defaults.py create mode 100644 src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/amw/helper.py create mode 100644 src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/constants.py create mode 100644 src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/dce_api.py create mode 100644 src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/dcr_api.py rename src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/{dcra.py => dcra_api.py} (71%) create mode 100644 src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/defaults.py create mode 100644 src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/delete.py create mode 100644 src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/deaults.py create mode 100644 src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/helper.py create mode 100644 src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/recordingrules/create.py create mode 100644 src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/recordingrules/delete.py diff --git a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/addonput.py b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/addonput.py index 87642fb5f09..e8661bd564d 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/addonput.py +++ b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/addonput.py @@ -5,7 +5,6 @@ CLIError ) -AKS_CLUSTER_API = "2023-01-01" # "2023-01-01" def addon_put(cmd, cluster_subscription, cluster_resource_group_name, cluster_name): from azure.cli.core.util import send_raw_request @@ -30,4 +29,3 @@ def addon_put(cmd, cluster_subscription, cluster_resource_group_name, cluster_na body=body, headers=headers) except CLIError as e: raise UnknownError(e) - \ No newline at end of file diff --git a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/amg/link.py b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/amg/link.py new file mode 100644 index 00000000000..3848751b095 --- /dev/null +++ b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/amg/link.py @@ -0,0 +1,73 @@ +import json +import uuid +from knack.util import CLIError +from azure.cli.command_modules.acs.azuremonitormetrics.constants import ( + GRAFANA_API, + GRAFANA_ROLE_ASSIGNMENT_API, + GrafanaLink +) +from azure.cli.command_modules.acs.azuremonitormetrics.helper import sanitize_resource_id + + +def link_grafana_instance(cmd, raw_parameters, azure_monitor_workspace_resource_id): + from azure.cli.core.util import send_raw_request + # GET grafana principal ID + try: + grafana_resource_id = raw_parameters.get("grafana_resource_id") + if grafana_resource_id is None or grafana_resource_id == "": + return GrafanaLink.NOPARAMPROVIDED + grafana_resource_id = sanitize_resource_id(grafana_resource_id) + grafanaURI = "https://management.azure.com{0}?api-version={1}".format( + grafana_resource_id, + GRAFANA_API + ) + headers = ['User-Agent=azuremonitormetrics.link_grafana_instance'] + grafanaArmResponse = send_raw_request(cmd.cli_ctx, "GET", grafanaURI, body={}, headers=headers) + servicePrincipalId = grafanaArmResponse.json()["identity"]["principalId"] + except CLIError as e: + raise CLIError(e) + # Add Role Assignment + try: + MonitoringDataReader = "b0d8363b-8ddd-447d-831f-62ca05bff136" + roleDefinitionURI = "https://management.azure.com{0}/providers/Microsoft.Authorization/roleAssignments/{1}?api-version={2}".format( + azure_monitor_workspace_resource_id, + uuid.uuid4(), + GRAFANA_ROLE_ASSIGNMENT_API + ) + roleDefinitionId = "{0}/providers/Microsoft.Authorization/roleDefinitions/{1}".format( + azure_monitor_workspace_resource_id, + MonitoringDataReader + ) + association_body = json.dumps({"properties": {"roleDefinitionId": roleDefinitionId, "principalId": servicePrincipalId}}) + headers = ['User-Agent=azuremonitormetrics.add_role_assignment'] + send_raw_request(cmd.cli_ctx, "PUT", roleDefinitionURI, body=association_body, headers=headers) + except CLIError as e: + if e.response.status_code != 409: + erroString = "Role Assingment failed. Please manually assign the `Monitoring Data Reader` role to the Azure Monitor Workspace ({0}) for the Azure Managed Grafana System Assigned Managed Identity ({1})".format( + azure_monitor_workspace_resource_id, + servicePrincipalId + ) + print(erroString) + # Setting up AMW Integration + targetGrafanaArmPayload = grafanaArmResponse.json() + if targetGrafanaArmPayload["properties"] is None: + raise CLIError("Invalid grafana payload to add AMW integration") + if "grafanaIntegrations" not in json.dumps(targetGrafanaArmPayload): + targetGrafanaArmPayload["properties"]["grafanaIntegrations"] = {} + if "azureMonitorWorkspaceIntegrations" not in json.dumps(targetGrafanaArmPayload): + targetGrafanaArmPayload["properties"]["grafanaIntegrations"]["azureMonitorWorkspaceIntegrations"] = [] + amwIntegrations = targetGrafanaArmPayload["properties"]["grafanaIntegrations"]["azureMonitorWorkspaceIntegrations"] + if amwIntegrations != [] and azure_monitor_workspace_resource_id in json.dumps(amwIntegrations).lower(): + return GrafanaLink.ALREADYPRESENT + try: + grafanaURI = "https://management.azure.com{0}?api-version={1}".format( + grafana_resource_id, + GRAFANA_API + ) + targetGrafanaArmPayload["properties"]["grafanaIntegrations"]["azureMonitorWorkspaceIntegrations"].append({"azureMonitorWorkspaceResourceId": azure_monitor_workspace_resource_id}) + targetGrafanaArmPayload = json.dumps(targetGrafanaArmPayload) + headers = ['User-Agent=azuremonitormetrics.setup_amw_grafana_integration', 'Content-Type=application/json'] + send_raw_request(cmd.cli_ctx, "PUT", grafanaURI, body=targetGrafanaArmPayload, headers=headers) + except CLIError as e: + raise CLIError(e) + return GrafanaLink.SUCCESS diff --git a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/amw/create.py b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/amw/create.py new file mode 100644 index 00000000000..81555695997 --- /dev/null +++ b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/amw/create.py @@ -0,0 +1,37 @@ +import json + +from azure.cli.command_modules.acs.azuremonitormetrics.constants import MAC_API +from azure.cli.command_modules.acs._client_factory import get_resource_groups_client, get_resources_client +from azure.core.exceptions import HttpResponseError +from knack.util import CLIError +from azure.cli.command_modules.acs.azuremonitormetrics.amw.defaults import get_default_mac_name_and_region + + +def create_default_mac(cmd, cluster_subscription, cluster_region): + from azure.cli.core.util import send_raw_request + default_mac_name, default_mac_region = get_default_mac_name_and_region(cmd, cluster_region) + default_resource_group_name = "DefaultResourceGroup-{0}".format(default_mac_region) + azure_monitor_workspace_resource_id = "/subscriptions/{0}/resourceGroups/{1}/providers/microsoft.monitor/accounts/{2}".format(cluster_subscription, default_resource_group_name, default_mac_name) + # Check if default resource group exists or not, if it does not then create it + resource_groups = get_resource_groups_client(cmd.cli_ctx, cluster_subscription) + resources = get_resources_client(cmd.cli_ctx, cluster_subscription) + + if resource_groups.check_existence(default_resource_group_name): + try: + resource = resources.get_by_id(azure_monitor_workspace_resource_id, MAC_API) + # If MAC already exists then return from here + return azure_monitor_workspace_resource_id, resource.location + except HttpResponseError as ex: + if ex.status_code != 404: + raise ex + else: + resource_groups.create_or_update(default_resource_group_name, {"location": default_mac_region}) + association_body = json.dumps({"location": default_mac_region, "properties": {}}) + association_url = f"https://management.azure.com{azure_monitor_workspace_resource_id}?api-version={MAC_API}" + try: + headers = ['User-Agent=azuremonitormetrics.create_default_mac'] + send_raw_request(cmd.cli_ctx, "PUT", association_url, + body=association_body, headers=headers) + return azure_monitor_workspace_resource_id, default_mac_region + except CLIError as e: + raise e \ No newline at end of file diff --git a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/amw/defaults.py b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/amw/defaults.py new file mode 100644 index 00000000000..d94ce58475e --- /dev/null +++ b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/amw/defaults.py @@ -0,0 +1,40 @@ +import json +from azure.cli.command_modules.acs.azuremonitormetrics.deaults import get_default_region +from azure.cli.command_modules.acs.azuremonitormetrics.responseparsers.amwlocationresponseparser import parseResourceProviderResponseForLocations + +from knack.util import CLIError + +def get_supported_rp_locations(cmd, rp_name): + from azure.cli.core.util import send_raw_request + supported_locations = [] + headers = ['User-Agent=azuremonitormetrics.get_supported_rp_locations'] + association_url = f"https://management.azure.com/providers/{rp_name}?api-version={RP_LOCATION_API}" + r = send_raw_request(cmd.cli_ctx, "GET", association_url, headers=headers) + data = json.loads(r.text) + supported_locations = parseResourceProviderResponseForLocations(data) + return supported_locations + +def get_default_mac_region(cmd, cluster_region): + global first_supported_region + if first_supported_region is not None and len(first_supported_region) != 0: + return first_supported_region + supported_locations = get_supported_rp_locations(cmd, 'Microsoft.Monitor') + if cluster_region in supported_locations: + return cluster_region + if len(supported_locations) > 0: + first_supported_region = supported_locations[0] + return supported_locations[0] + cloud_name = cmd.cli_ctx.cloud.name + if cloud_name.lower() == 'azurechinacloud': + raise CLIError("Azure China Cloud is not supported for the Azure Monitor Metrics addon") + if cloud_name.lower() == 'azureusgovernment': + return "usgovvirginia" + # default to public cloud + return get_default_region(cmd) + + +def get_default_mac_name_and_region(cmd, cluster_region): + default_mac_region = get_default_mac_region(cmd, cluster_region) + default_mac_name = "DefaultAzureMonitorWorkspace-" + default_mac_region + default_mac_name = default_mac_name[0:43] + return default_mac_name, default_mac_region diff --git a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/amw/helper.py b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/amw/helper.py new file mode 100644 index 00000000000..f2b8b1336da --- /dev/null +++ b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/amw/helper.py @@ -0,0 +1,31 @@ + + +import json +from azure.cli.command_modules.acs.azuremonitormetrics.amw.create import create_default_mac +from azure.cli.command_modules.acs.azuremonitormetrics.constants import MAC_API +from azure.cli.command_modules.acs.azuremonitormetrics.helper import sanitize_resource_id +from azure.cli.core.azclierror import ClientRequestError +from azure.core.exceptions import HttpResponseError +from azure.cli.command_modules.acs._client_factory import get_resources_client +from knack.util import CLIError + +def get_amw_region(cmd, azure_monitor_workspace_resource_id): + # region of MAC can be different from region of RG so find the location of the azure_monitor_workspace_resource_id + amw_subscription_id = azure_monitor_workspace_resource_id.split("/")[2] + resources = get_resources_client(cmd.cli_ctx, amw_subscription_id) + try: + resource = resources.get_by_id( + azure_monitor_workspace_resource_id, MAC_API) + return resource.location.lower() + except HttpResponseError as ex: + raise ex + + +def get_azure_monitor_workspace_resource(cmd, cluster_subscription, cluster_region, raw_parameters): + azure_monitor_workspace_resource_id = raw_parameters.get("azure_monitor_workspace_resource_id") + if azure_monitor_workspace_resource_id is None or azure_monitor_workspace_resource_id == "": + azure_monitor_workspace_resource_id, azure_monitor_workspace_location = create_default_mac(cmd, cluster_subscription, cluster_region) + else: + azure_monitor_workspace_resource_id = sanitize_resource_id(azure_monitor_workspace_resource_id) + azure_monitor_workspace_location = get_amw_region(cmd, azure_monitor_workspace_resource_id) + return azure_monitor_workspace_resource_id, azure_monitor_workspace_location.lower() diff --git a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/azuremonitorprofile.py b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/azuremonitorprofile.py index bd13cf23acd..4cea9c85e60 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/azuremonitorprofile.py +++ b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/azuremonitorprofile.py @@ -2,655 +2,40 @@ # Copyright (c) Microsoft Corporation. All rights reserved. # Licensed under the MIT License. See License.txt in the project root for license information. # -------------------------------------------------------------------------------------------- -import json -import uuid -# from sre_constants import FAILURE, SUCCESS +from azure.cli.command_modules.acs.azuremonitormetrics.addonput import addon_put +from azure.cli.command_modules.acs.azuremonitormetrics.amg.link import link_grafana_instance +from azure.cli.command_modules.acs.azuremonitormetrics.amw.helper import get_azure_monitor_workspace_resource +from azure.cli.command_modules.acs.azuremonitormetrics.dc.dce_api import create_dce +from azure.cli.command_modules.acs.azuremonitormetrics.dc.dcr_api import create_dcr +from azure.cli.command_modules.acs.azuremonitormetrics.dc.dcra_api import create_dcra +from azure.cli.command_modules.acs.azuremonitormetrics.dc.delete import delete_dc_objects_if_prometheus_enabled, get_dc_objects_list +from azure.cli.command_modules.acs.azuremonitormetrics.helper import check_azuremonitormetrics_profile, rp_registrations +from azure.cli.command_modules.acs.azuremonitormetrics.recordingrules.create import create_rules +from azure.cli.command_modules.acs.azuremonitormetrics.recordingrules.delete import delete_rules +from knack.util import CLIError -from azure-cli.azure.cli.command_modules.acs.azuremonitormetrics.addonput import addon_put -from azure.cli.command_modules.acs.azuremonitormetrics.responseparsers.amwlocationresponseparser import parseResourceProviderResponseForLocations from azure.cli.core.azclierror import ( - UnknownError, InvalidArgumentValueError, - ClientRequestError, - CLIError ) from .._client_factory import get_resources_client, get_resource_groups_client -from enum import Enum -from six import with_metaclass -from azure.core import CaseInsensitiveEnumMeta from azure.core.exceptions import HttpResponseError -AKS_CLUSTER_API = "2023-01-01" # "2023-01-01" -MAC_API = "2023-04-03" -DC_API = "2022-06-01" -GRAFANA_API = "2022-08-01" -GRAFANA_ROLE_ASSIGNMENT_API = "2022-04-01" -RULES_API = "2023-03-01" -FEATURE_API = "2020-09-01" -RP_API = "2021-04-01" -ALERTS_API = "2023-01-01-preview" -RP_LOCATION_API = "2022-01-01" - -class GrafanaLink(with_metaclass(CaseInsensitiveEnumMeta, str, Enum)): - """ - Status of Grafana link to the Prometheus Addon - """ - SUCCESS = "SUCCESS" - FAILURE = "FAILURE" - ALREADYPRESENT = "ALREADYPRESENT" - NOPARAMPROVIDED = "NOPARAMPROVIDED" - - -class DC_TYPE(with_metaclass(CaseInsensitiveEnumMeta, str, Enum)): - """ - Types of DC* objects - """ - DCE = "DCE" - DCR = "DCR" - DCRA = "DCRA" - - first_supported_region = "" - -MapToClosestMACRegion = { - "australiacentral": "eastus", - "australiacentral2": "eastus", - "australiaeast": "eastus", - "australiasoutheast": "eastus", - "brazilsouth": "eastus", - "canadacentral": "eastus", - "canadaeast": "eastus", - "centralus": "centralus", - "centralindia": "centralindia", - "eastasia": "westeurope", - "eastus": "eastus", - "eastus2": "eastus2", - "francecentral": "westeurope", - "francesouth": "westeurope", - "japaneast": "eastus", - "japanwest": "eastus", - "koreacentral": "westeurope", - "koreasouth": "westeurope", - "northcentralus": "eastus", - "northeurope": "westeurope", - "southafricanorth": "westeurope", - "southafricawest": "westeurope", - "southcentralus": "eastus", - "southeastasia": "westeurope", - "southindia": "centralindia", - "uksouth": "westeurope", - "ukwest": "westeurope", - "westcentralus": "eastus", - "westeurope": "westeurope", - "westindia": "centralindia", - "westus": "westus", - "westus2": "westus2", - "westus3": "westus", - "norwayeast": "westeurope", - "norwaywest": "westeurope", - "switzerlandnorth": "westeurope", - "switzerlandwest": "westeurope", - "uaenorth": "westeurope", - "germanywestcentral": "westeurope", - "germanynorth": "westeurope", - "uaecentral": "westeurope", - "eastus2euap": "eastus2euap", - "centraluseuap": "westeurope", - "brazilsoutheast": "eastus", - "jioindiacentral": "centralindia", - "swedencentral": "westeurope", - "swedensouth": "westeurope", - "qatarcentral": "westeurope" -} - -def check_azuremonitormetrics_profile(cmd, cluster_subscription, cluster_resource_group_name, cluster_name): - from azure.cli.core.util import send_raw_request - feature_check_url = f"https://management.azure.com/subscriptions/{cluster_subscription}/resourceGroups/{cluster_resource_group_name}/providers/Microsoft.ContainerService/managedClusters/{cluster_name}?api-version={AKS_CLUSTER_API}" - try: - headers = ['User-Agent=azuremonitormetrics.check_azuremonitormetrics_profile'] - r = send_raw_request(cmd.cli_ctx, "GET", feature_check_url, - body={}, headers=headers) - except CLIError as e: - raise UnknownError(e) - json_response = json.loads(r.text) - values_array = json_response["properties"] - if "azureMonitorProfile" in values_array: - if "metrics" in values_array["azureMonitorProfile"]: - if values_array["azureMonitorProfile"]["metrics"]["enabled"] is True: - raise CLIError(f"Azure Monitor Metrics is already enabled for this cluster. Please use `az aks update --disable-azuremonitormetrics -g {cluster_resource_group_name} -n {cluster_name}` and then try enabling.") - - -# DCR = 64, DCE = 44, DCRA = 64 -# All DC* object names should end only in alpha numeric (after `length` trim) -# DCE remove underscore from cluster name -def sanitize_name(name, type, length): - length = length - 1 - if type == DC_TYPE.DCE: - name = name.replace("_", "") - name = name[0:length] - lastIndexAlphaNumeric = len(name) - 1 - while ((name[lastIndexAlphaNumeric].isalnum() is False) and lastIndexAlphaNumeric > -1): - lastIndexAlphaNumeric = lastIndexAlphaNumeric - 1 - if (lastIndexAlphaNumeric < 0): - return "" - - return name[0:lastIndexAlphaNumeric + 1] - - -def sanitize_resource_id(resource_id): - resource_id = resource_id.strip() - if not resource_id.startswith("/"): - resource_id = "/" + resource_id - if resource_id.endswith("/"): - resource_id = resource_id.rstrip("/") - return resource_id.lower() - - -def get_supported_rp_locations(cmd, rp_name): - from azure.cli.core.util import send_raw_request - supported_locations = [] - headers = ['User-Agent=azuremonitormetrics.get_supported_rp_locations'] - association_url = f"https://management.azure.com/providers/{rp_name}?api-version={RP_LOCATION_API}" - r = send_raw_request(cmd.cli_ctx, "GET", association_url, headers=headers) - data = json.loads(r.text) - supported_locations = parseResourceProviderResponseForLocations(data) - return supported_locations - - -def get_default_region(cmd): - cloud_name = cmd.cli_ctx.cloud.name - if cloud_name.lower() == 'azurechinacloud': - raise CLIError("Azure China Cloud is not supported for the Azure Monitor Metrics addon") - if cloud_name.lower() == 'azureusgovernment': - return "usgovvirginia" - return "eastus" - -def get_default_mac_region(cmd, cluster_region): - global first_supported_region - if first_supported_region is not None and len(first_supported_region) != 0: - return first_supported_region - supported_locations = get_supported_rp_locations(cmd, 'Microsoft.Monitor') - if cluster_region in supported_locations: - return cluster_region - if len(supported_locations) > 0: - first_supported_region = supported_locations[0] - return supported_locations[0] - cloud_name = cmd.cli_ctx.cloud.name - if cloud_name.lower() == 'azurechinacloud': - raise CLIError("Azure China Cloud is not supported for the Azure Monitor Metrics addon") - if cloud_name.lower() == 'azureusgovernment': - return "usgovvirginia" - # default to public cloud - return get_default_region(cmd) - -def get_default_mac_name(cmd, cluster_region): - default_mac_name = "DefaultAzureMonitorWorkspace-" + get_default_mac_region(cmd, cluster_region) - default_mac_name = default_mac_name[0:43] - return default_mac_name - - -def create_default_mac(cmd, cluster_subscription, cluster_region): - from azure.cli.core.util import send_raw_request - default_mac_name = get_default_mac_name(cmd, cluster_region) - default_resource_group_name = "DefaultResourceGroup-{0}".format(get_default_mac_region(cmd, cluster_region)) - azure_monitor_workspace_resource_id = "/subscriptions/{0}/resourceGroups/{1}/providers/microsoft.monitor/accounts/{2}".format(cluster_subscription, default_resource_group_name, default_mac_name) - # Check if default resource group exists or not, if it does not then create it - resource_groups = get_resource_groups_client(cmd.cli_ctx, cluster_subscription) - resources = get_resources_client(cmd.cli_ctx, cluster_subscription) - - if resource_groups.check_existence(default_resource_group_name): - try: - resources.get_by_id(azure_monitor_workspace_resource_id, MAC_API) - # If MAC already exists then return from here - return azure_monitor_workspace_resource_id - except HttpResponseError as ex: - if ex.status_code != 404: - raise ex - else: - resource_groups.create_or_update(default_resource_group_name, {"location": get_default_mac_region(cmd, cluster_region)}) - association_body = json.dumps({"location": get_default_mac_region(cmd, cluster_region), "properties": {}}) - association_url = f"https://management.azure.com{azure_monitor_workspace_resource_id}?api-version={MAC_API}" - try: - headers = ['User-Agent=azuremonitormetrics.create_default_mac'] - send_raw_request(cmd.cli_ctx, "PUT", association_url, - body=association_body, headers=headers) - return azure_monitor_workspace_resource_id - except CLIError as e: - raise e - - -def get_azure_monitor_workspace_resource_id(cmd, cluster_subscription, cluster_region, raw_parameters): - azure_monitor_workspace_resource_id = raw_parameters.get("azure_monitor_workspace_resource_id") - if azure_monitor_workspace_resource_id is None or azure_monitor_workspace_resource_id == "": - azure_monitor_workspace_resource_id = create_default_mac(cmd, cluster_subscription, cluster_region) - else: - azure_monitor_workspace_resource_id = sanitize_resource_id(azure_monitor_workspace_resource_id) - return azure_monitor_workspace_resource_id.lower() - - -def get_default_dce_name(cmd, mac_region, cluster_name): - region = get_default_region(cmd) - if mac_region in MapToClosestMACRegion: - region = MapToClosestMACRegion[mac_region] - default_dce_name = "MSProm-" + region + "-" + cluster_name - return sanitize_name(default_dce_name, DC_TYPE.DCE, 44) - - -def get_default_dcr_name(cmd, mac_region, cluster_name): - region = get_default_region(cmd) - if mac_region in MapToClosestMACRegion: - region = MapToClosestMACRegion[mac_region] - default_dcr_name = "MSProm-" + region + "-" + cluster_name - return sanitize_name(default_dcr_name, DC_TYPE.DCR, 64) - - -def get_default_dcra_name(cmd, cluster_region, cluster_name): - region = get_default_region(cmd) - if cluster_region in MapToClosestMACRegion: - region = MapToClosestMACRegion[cluster_region] - default_dcra_name = "ContainerInsightsMetricsExtension-" + region + "-" + cluster_name - return sanitize_name(default_dcra_name, DC_TYPE.DCRA, 64) - - -def get_mac_region_and_check_support(cmd, azure_monitor_workspace_resource_id, cluster_region): - from azure.cli.core.util import send_raw_request - from azure.core.exceptions import HttpResponseError - # region of MAC can be different from region of RG so find the location of the azure_monitor_workspace_resource_id - mac_subscription_id = azure_monitor_workspace_resource_id.split("/")[2] - resources = get_resources_client(cmd.cli_ctx, mac_subscription_id) - try: - resource = resources.get_by_id( - azure_monitor_workspace_resource_id, MAC_API) - mac_location = resource.location - except HttpResponseError as ex: - raise ex - # first get the association between region display names and region IDs (because for some reason - # the "which RPs are available in which regions" check returns region display names) - region_names_to_id = {} - # retry the request up to two times - for _ in range(3): - try: - headers = ['User-Agent=azuremonitormetrics.get_mac_region_and_check_support.mac_subscription_location_support_check'] - location_list_url = f"https://management.azure.com/subscriptions/{mac_subscription_id}/locations?api-version=2019-11-01" - r = send_raw_request(cmd.cli_ctx, "GET", location_list_url, headers=headers) - - # this is required to fool the static analyzer. The else statement will only run if an exception - # is thrown, but flake8 will complain that e is undefined if we don"t also define it here. - error = None - break - except CLIError as e: - error = e - else: - # This will run if the above for loop was not broken out of. This means all three requests failed - raise error - json_response = json.loads(r.text) - for region_data in json_response["value"]: - region_names_to_id[region_data["displayName"] - ] = region_data["name"] - # check if region supports DCR and DCRA - for _ in range(3): - try: - feature_check_url = f"https://management.azure.com/subscriptions/{mac_subscription_id}/providers/Microsoft.Insights?api-version=2020-10-01" - headers = ['User-Agent=azuremonitormetrics.get_mac_region_and_check_support.mac_subscription_dcr_dcra_regions_support_check'] - r = send_raw_request(cmd.cli_ctx, "GET", feature_check_url, headers=headers) - error = None - break - except CLIError as e: - error = e - else: - raise error - json_response = json.loads(r.text) - for resource in json_response["resourceTypes"]: - region_ids = map(lambda x: region_names_to_id[x], - resource["locations"]) # map is lazy, so doing this for every region isn"t slow - if resource["resourceType"].lower() == "datacollectionrules" and mac_location not in region_ids: - raise ClientRequestError( - f"Data Collection Rules are not supported for MAC region {mac_location}") - elif resource[ - "resourceType"].lower() == "datacollectionruleassociations" and cluster_region not in region_ids: - raise ClientRequestError( - f"Data Collection Rule Associations are not supported for cluster region {cluster_region}") - return mac_location - - -def create_dce(cmd, cluster_subscription, cluster_resource_group_name, cluster_name, mac_region): - from azure.cli.core.util import send_raw_request - dce_name = get_default_dce_name(cmd, mac_region, cluster_name) - dce_resource_id = "/subscriptions/{0}/resourceGroups/{1}/providers/Microsoft.Insights/dataCollectionEndpoints/{2}".format(cluster_subscription, cluster_resource_group_name, dce_name) - try: - dce_url = f"https://management.azure.com{dce_resource_id}?api-version={DC_API}" - dce_creation_body = json.dumps({"name": dce_name, - "location": mac_region, - "kind": "Linux", - "properties": {}}) - headers = ['User-Agent=azuremonitormetrics.create_dce'] - send_raw_request(cmd.cli_ctx, "PUT", - dce_url, body=dce_creation_body, headers=headers) - error = None - return dce_resource_id - except CLIError as error: - raise error - - -# pylint: disable=too-many-locals,too-many-branches,too-many-statements,line-too-long -def create_dcr(cmd, mac_region, azure_monitor_workspace_resource_id, cluster_subscription, cluster_resource_group_name, cluster_name, dce_resource_id): - from azure.cli.core.util import send_raw_request - dcr_name = get_default_dcr_name(cmd, mac_region, cluster_name) - dcr_resource_id = "/subscriptions/{0}/resourceGroups/{1}/providers/Microsoft.Insights/dataCollectionRules/{2}".format( - cluster_subscription, - cluster_resource_group_name, - dcr_name - ) - dcr_creation_body = json.dumps({"location": mac_region, - "kind": "Linux", - "properties": { - "dataCollectionEndpointId": dce_resource_id, - "dataSources": {"prometheusForwarder": [{"name": "PrometheusDataSource", "streams": ["Microsoft-PrometheusMetrics"], "labelIncludeFilter": {}}]}, - "dataFlows": [{"destinations": ["MonitoringAccount1"], "streams": ["Microsoft-PrometheusMetrics"]}], - "description": "DCR description", - "destinations": { - "monitoringAccounts": [{"accountResourceId": azure_monitor_workspace_resource_id, "name": "MonitoringAccount1"}]}}}) - dcr_url = f"https://management.azure.com{dcr_resource_id}?api-version={DC_API}" - try: - headers = ['User-Agent=azuremonitormetrics.create_dcr'] - send_raw_request(cmd.cli_ctx, "PUT", - dcr_url, body=dcr_creation_body, headers=headers) - error = None - return dcr_resource_id - except CLIError as error: - raise error - - -def create_dcra(cmd, cluster_region, cluster_subscription, cluster_resource_group_name, cluster_name, dcr_resource_id): - from azure.cli.core.util import send_raw_request - cluster_resource_id = "/subscriptions/{0}/resourceGroups/{1}/providers/Microsoft.ContainerService/managedClusters/{2}".format( - cluster_subscription, - cluster_resource_group_name, - cluster_name - ) - dcra_name = get_default_dcra_name(cmd, cluster_region, cluster_name) - dcra_resource_id = "/subscriptions/{0}/resourceGroups/{1}/providers/Microsoft.Insights/dataCollectionRuleAssociations/{2}".format( - cluster_subscription, - cluster_resource_group_name, - dcra_name - ) - # only create or delete the association between the DCR and cluster - association_body = json.dumps({"location": cluster_region, - "properties": { - "dataCollectionRuleId": dcr_resource_id, - "description": "Promtheus data collection association between DCR, DCE and target AKS resource" - }}) - association_url = f"https://management.azure.com{cluster_resource_id}/providers/Microsoft.Insights/dataCollectionRuleAssociations/{dcra_name}?api-version={DC_API}" - try: - headers = ['User-Agent=azuremonitormetrics.create_dcra'] - send_raw_request(cmd.cli_ctx, "PUT", association_url, - body=association_body, headers=headers) - error = None - return dcra_resource_id - except CLIError as error: - raise error - - -def link_grafana_instance(cmd, raw_parameters, azure_monitor_workspace_resource_id): - from azure.cli.core.util import send_raw_request - # GET grafana principal ID - try: - grafana_resource_id = raw_parameters.get("grafana_resource_id") - if grafana_resource_id is None or grafana_resource_id == "": - return GrafanaLink.NOPARAMPROVIDED - grafana_resource_id = sanitize_resource_id(grafana_resource_id) - grafanaURI = "https://management.azure.com{0}?api-version={1}".format( - grafana_resource_id, - GRAFANA_API - ) - headers = ['User-Agent=azuremonitormetrics.link_grafana_instance'] - grafanaArmResponse = send_raw_request(cmd.cli_ctx, "GET", grafanaURI, body={}, headers=headers) - servicePrincipalId = grafanaArmResponse.json()["identity"]["principalId"] - except CLIError as e: - raise CLIError(e) - # Add Role Assignment - try: - MonitoringDataReader = "b0d8363b-8ddd-447d-831f-62ca05bff136" - roleDefinitionURI = "https://management.azure.com{0}/providers/Microsoft.Authorization/roleAssignments/{1}?api-version={2}".format( - azure_monitor_workspace_resource_id, - uuid.uuid4(), - GRAFANA_ROLE_ASSIGNMENT_API - ) - roleDefinitionId = "{0}/providers/Microsoft.Authorization/roleDefinitions/{1}".format( - azure_monitor_workspace_resource_id, - MonitoringDataReader - ) - association_body = json.dumps({"properties": {"roleDefinitionId": roleDefinitionId, "principalId": servicePrincipalId}}) - headers = ['User-Agent=azuremonitormetrics.add_role_assignment'] - send_raw_request(cmd.cli_ctx, "PUT", roleDefinitionURI, body=association_body, headers=headers) - except CLIError as e: - if e.response.status_code != 409: - erroString = "Role Assingment failed. Please manually assign the `Monitoring Data Reader` role to the Azure Monitor Workspace ({0}) for the Azure Managed Grafana System Assigned Managed Identity ({1})".format( - azure_monitor_workspace_resource_id, - servicePrincipalId - ) - print(erroString) - # Setting up AMW Integration - targetGrafanaArmPayload = grafanaArmResponse.json() - if targetGrafanaArmPayload["properties"] is None: - raise CLIError("Invalid grafana payload to add AMW integration") - if "grafanaIntegrations" not in json.dumps(targetGrafanaArmPayload): - targetGrafanaArmPayload["properties"]["grafanaIntegrations"] = {} - if "azureMonitorWorkspaceIntegrations" not in json.dumps(targetGrafanaArmPayload): - targetGrafanaArmPayload["properties"]["grafanaIntegrations"]["azureMonitorWorkspaceIntegrations"] = [] - amwIntegrations = targetGrafanaArmPayload["properties"]["grafanaIntegrations"]["azureMonitorWorkspaceIntegrations"] - if amwIntegrations != [] and azure_monitor_workspace_resource_id in json.dumps(amwIntegrations).lower(): - return GrafanaLink.ALREADYPRESENT - try: - grafanaURI = "https://management.azure.com{0}?api-version={1}".format( - grafana_resource_id, - GRAFANA_API - ) - targetGrafanaArmPayload["properties"]["grafanaIntegrations"]["azureMonitorWorkspaceIntegrations"].append({"azureMonitorWorkspaceResourceId": azure_monitor_workspace_resource_id}) - targetGrafanaArmPayload = json.dumps(targetGrafanaArmPayload) - headers = ['User-Agent=azuremonitormetrics.setup_amw_grafana_integration', 'Content-Type=application/json'] - send_raw_request(cmd.cli_ctx, "PUT", grafanaURI, body=targetGrafanaArmPayload, headers=headers) - except CLIError as e: - raise CLIError(e) - return GrafanaLink.SUCCESS - - -def put_rules(cmd, default_rule_group_id, default_rule_group_name, mac_region, azure_monitor_workspace_resource_id, cluster_name, default_rules_template, url, i): - from azure.cli.core.util import send_raw_request - body = json.dumps({ - "id": default_rule_group_id, - "name": default_rule_group_name, - "type": "Microsoft.AlertsManagement/prometheusRuleGroups", - "location": mac_region, - "properties": { - "scopes": [ - azure_monitor_workspace_resource_id - ], - "enabled": True, - "clusterName": cluster_name, - "interval": "PT1M", - "rules": default_rules_template[i]["properties"]["rulesArmTemplate"]["resources"][0]["properties"]["rules"] - } - }) - for _ in range(3): - try: - headers = ['User-Agent=azuremonitormetrics.put_rules.' + default_rule_group_name] - send_raw_request(cmd.cli_ctx, "PUT", url, - body=body, headers=headers) - error = None - break - except CLIError as e: - error = e - else: - raise error - - -def delete_rule(cmd, cluster_subscription, cluster_resource_group_name, cluster_name, default_rule_group_name): - from azure.cli.core.util import send_raw_request - default_rule_group_id = "/subscriptions/{0}/resourceGroups/{1}/providers/Microsoft.AlertsManagement/prometheusRuleGroups/{2}".format( - cluster_subscription, - cluster_resource_group_name, - default_rule_group_name - ) - headers = ['User-Agent=azuremonitormetrics.delete_rule.' + default_rule_group_name] - url = "https://management.azure.com{0}?api-version={1}".format( - default_rule_group_id, - RULES_API - ) - send_raw_request(cmd.cli_ctx, "DELETE", url, headers=headers) - - -def get_recording_rules_template(cmd, azure_monitor_workspace_resource_id): - from azure.cli.core.util import send_raw_request - headers = ['User-Agent=azuremonitormetrics.get_recording_rules_template'] - url = f"https://management.azure.com{azure_monitor_workspace_resource_id}/providers/microsoft.alertsManagement/alertRuleRecommendations?api-version={ALERTS_API}" - r = send_raw_request(cmd.cli_ctx, "GET", url, headers=headers) - data = json.loads(r.text) - return data['value'] - - -def create_rules(cmd, cluster_subscription, cluster_resource_group_name, cluster_name, azure_monitor_workspace_resource_id, mac_region, raw_parameters): - # with urllib.request.urlopen("https://defaultrulessc.blob.core.windows.net/defaultrules/ManagedPrometheusDefaultRecordingRules.json") as url: - # default_rules_template = json.loads(url.read().decode()) - default_rules_template = get_recording_rules_template(cmd, azure_monitor_workspace_resource_id) - default_rule_group_name = "NodeRecordingRulesRuleGroup-{0}".format(cluster_name) - default_rule_group_id = "/subscriptions/{0}/resourceGroups/{1}/providers/Microsoft.AlertsManagement/prometheusRuleGroups/{2}".format( - cluster_subscription, - cluster_resource_group_name, - default_rule_group_name - ) - url = "https://management.azure.com{0}?api-version={1}".format( - default_rule_group_id, - RULES_API - ) - put_rules(cmd, default_rule_group_id, default_rule_group_name, mac_region, azure_monitor_workspace_resource_id, cluster_name, default_rules_template, url, 0) - - default_rule_group_name = "KubernetesRecordingRulesRuleGroup-{0}".format(cluster_name) - default_rule_group_id = "/subscriptions/{0}/resourceGroups/{1}/providers/Microsoft.AlertsManagement/prometheusRuleGroups/{2}".format( - cluster_subscription, - cluster_resource_group_name, - default_rule_group_name - ) - url = "https://management.azure.com{0}?api-version={1}".format( - default_rule_group_id, - RULES_API - ) - put_rules(cmd, default_rule_group_id, default_rule_group_name, mac_region, azure_monitor_workspace_resource_id, cluster_name, default_rules_template, url, 1) - - enable_windows_recording_rules = raw_parameters.get("enable_windows_recording_rules") - - if enable_windows_recording_rules is True: - default_rule_group_name = "NodeRecordingRulesRuleGroup-Win-{0}".format(cluster_name) - default_rule_group_id = "/subscriptions/{0}/resourceGroups/{1}/providers/Microsoft.AlertsManagement/prometheusRuleGroups/{2}".format( - cluster_subscription, - cluster_resource_group_name, - default_rule_group_name - ) - url = "https://management.azure.com{0}?api-version={1}".format( - default_rule_group_id, - RULES_API - ) - put_rules(cmd, default_rule_group_id, default_rule_group_name, mac_region, azure_monitor_workspace_resource_id, cluster_name, default_rules_template, url, 2) - - default_rule_group_name = "NodeAndKubernetesRecordingRulesRuleGroup-Win-{0}".format(cluster_name) - default_rule_group_id = "/subscriptions/{0}/resourceGroups/{1}/providers/Microsoft.AlertsManagement/prometheusRuleGroups/{2}".format( - cluster_subscription, - cluster_resource_group_name, - default_rule_group_name - ) - url = "https://management.azure.com{0}?api-version={1}".format( - default_rule_group_id, - RULES_API - ) - put_rules(cmd, default_rule_group_id, default_rule_group_name, mac_region, azure_monitor_workspace_resource_id, cluster_name, default_rules_template, url, 3) - - -def get_dce_from_dcr(cmd, dcrId): - from azure.cli.core.util import send_raw_request - association_url = f"https://management.azure.com{dcrId}?api-version={DC_API}" - headers = ['User-Agent=azuremonitormetrics.get_dce_from_dcr'] - r = send_raw_request(cmd.cli_ctx, "GET", association_url, headers=headers) - data = json.loads(r.text) - return data['properties']['dataCollectionEndpointId'] - - -def get_dc_objects_list(cmd, cluster_region, cluster_subscription, cluster_resource_group_name, cluster_name): - try: - from azure.cli.core.util import send_raw_request - cluster_resource_id = "/subscriptions/{0}/resourceGroups/{1}/providers/Microsoft.ContainerService/managedClusters/{2}".format( - cluster_subscription, - cluster_resource_group_name, - cluster_name - ) - association_url = f"https://management.azure.com{cluster_resource_id}/providers/Microsoft.Insights/dataCollectionRuleAssociations?api-version={DC_API}" - headers = ['User-Agent=azuremonitormetrics.get_dcra'] - r = send_raw_request(cmd.cli_ctx, "GET", association_url, headers=headers) - data = json.loads(r.text) - dc_object_array = [] - for item in data['value']: - dce_id = get_dce_from_dcr(cmd, item['properties']['dataCollectionRuleId']) - dc_object_array.append({'name': item['name'], 'dataCollectionRuleId': item['properties']['dataCollectionRuleId'], 'dceId': dce_id}) - return dc_object_array - except CLIError as e: - error = e - raise CLIError(error) - - -def delete_dc_objects_if_prometheus_enabled(cmd, dc_objects_list, cluster_subscription, cluster_resource_group_name, cluster_name): - from azure.cli.core.util import send_raw_request - cluster_resource_id = "/subscriptions/{0}/resourceGroups/{1}/providers/Microsoft.ContainerService/managedClusters/{2}".format( - cluster_subscription, - cluster_resource_group_name, - cluster_name - ) - for item in dc_objects_list: - association_url = f"https://management.azure.com{item['dataCollectionRuleId']}?api-version={DC_API}" - try: - headers = ['User-Agent=azuremonitormetrics.get_dcr_if_prometheus_enabled'] - r = send_raw_request(cmd.cli_ctx, "GET", association_url, headers=headers) - data = json.loads(r.text) - if 'microsoft-prometheusmetrics' in [stream.lower() for stream in data['properties']['dataFlows'][0]['streams']]: - # delete DCRA - url = f"https://management.azure.com{cluster_resource_id}/providers/Microsoft.Insights/dataCollectionRuleAssociations/{item['name']}?api-version={DC_API}" - headers = ['User-Agent=azuremonitormetrics.delete_dcra'] - send_raw_request(cmd.cli_ctx, "DELETE", url, headers=headers) - # delete DCR - url = f"https://management.azure.com{item['dataCollectionRuleId']}?api-version={DC_API}" - headers = ['User-Agent=azuremonitormetrics.delete_dcr'] - send_raw_request(cmd.cli_ctx, "DELETE", url, headers=headers) - # delete DCE - url = f"https://management.azure.com{item['dceId']}?api-version={DC_API}" - headers = ['User-Agent=azuremonitormetrics.delete_dce'] - send_raw_request(cmd.cli_ctx, "DELETE", url, headers=headers) - except CLIError as e: - error = e - raise CLIError(error) - - -def delete_rules(cmd, cluster_subscription, cluster_resource_group_name, cluster_name): - delete_rule(cmd, cluster_subscription, cluster_resource_group_name, cluster_name, "NodeRecordingRulesRuleGroup-{0}".format(cluster_name)) - delete_rule(cmd, cluster_subscription, cluster_resource_group_name, cluster_name, "KubernetesRecordingRulesRuleGroup-{0}".format(cluster_name)) - delete_rule(cmd, cluster_subscription, cluster_resource_group_name, cluster_name, "NodeRecordingRulesRuleGroup-Win-{0}".format(cluster_name)) - delete_rule(cmd, cluster_subscription, cluster_resource_group_name, cluster_name, "NodeAndKubernetesRecordingRulesRuleGroup-Win-{0}".format(cluster_name)) - - def link_azure_monitor_profile_artifacts(cmd, cluster_subscription, cluster_resource_group_name, cluster_name, cluster_region, raw_parameters, create_flow): # MAC creation if required - azure_monitor_workspace_resource_id = get_azure_monitor_workspace_resource_id(cmd, cluster_subscription, cluster_region, raw_parameters) - # Get MAC region (required for DCE, DCR creation) and check support for DCE,DCR creation - mac_region = get_mac_region_and_check_support(cmd, azure_monitor_workspace_resource_id, cluster_region) + azure_monitor_workspace_resource_id, azure_monitor_workspace_location = get_azure_monitor_workspace_resource(cmd, cluster_subscription, cluster_region, raw_parameters) # DCE creation - dce_resource_id = create_dce(cmd, cluster_subscription, cluster_resource_group_name, cluster_name, mac_region) + dce_resource_id = create_dce(cmd, cluster_subscription, cluster_resource_group_name, cluster_name, azure_monitor_workspace_location) # DCR creation - dcr_resource_id = create_dcr(cmd, mac_region, azure_monitor_workspace_resource_id, cluster_subscription, cluster_resource_group_name, cluster_name, dce_resource_id) + dcr_resource_id = create_dcr(cmd, azure_monitor_workspace_location, azure_monitor_workspace_resource_id, cluster_subscription, cluster_resource_group_name, cluster_name, dce_resource_id) # DCRA creation create_dcra(cmd, cluster_region, cluster_subscription, cluster_resource_group_name, cluster_name, dcr_resource_id) # Link grafana link_grafana_instance(cmd, raw_parameters, azure_monitor_workspace_resource_id) # create recording rules and alerts - create_rules(cmd, cluster_subscription, cluster_resource_group_name, cluster_name, azure_monitor_workspace_resource_id, mac_region, raw_parameters) + create_rules(cmd, cluster_subscription, cluster_resource_group_name, cluster_name, azure_monitor_workspace_resource_id, azure_monitor_workspace_location, raw_parameters) # if aks cluster create flow -> do a PUT on the AKS cluster to enable the addon if create_flow: addon_put(cmd, cluster_subscription, cluster_resource_group_name, cluster_name) @@ -665,60 +50,6 @@ def unlink_azure_monitor_profile_artifacts(cmd, cluster_subscription, cluster_re delete_rules(cmd, cluster_subscription, cluster_resource_group_name, cluster_name) -def post_request(cmd, subscription_id, rp_name, headers): - from azure.cli.core.util import send_raw_request - customUrl = "https://management.azure.com/subscriptions/{0}/providers/{1}/register?api-version={2}".format( - subscription_id, - rp_name, - RP_API - ) - try: - send_raw_request(cmd.cli_ctx, "POST", customUrl, headers=headers) - except CLIError as e: - raise CLIError(e) - - -def rp_registrations(cmd, subscription_id): - from azure.cli.core.util import send_raw_request - # Get list of RP's for RP's subscription - try: - headers = ['User-Agent=azuremonitormetrics.get_mac_sub_list'] - customUrl = "https://management.azure.com/subscriptions/{0}/providers?api-version={1}&$select=namespace,registrationstate".format( - subscription_id, - RP_API - ) - r = send_raw_request(cmd.cli_ctx, "GET", customUrl, headers=headers) - except CLIError as e: - raise CLIError(e) - isInsightsRpRegistered = False - isAlertsManagementRpRegistered = False - isMoniotrRpRegistered = False - isDashboardRpRegistered = False - json_response = json.loads(r.text) - values_array = json_response["value"] - for value in values_array: - if value["namespace"].lower() == "microsoft.insights" and value["registrationState"].lower() == "registered": - isInsightsRpRegistered = True - if value["namespace"].lower() == "microsoft.alertsmanagement" and value["registrationState"].lower() == "registered": - isAlertsManagementRpRegistered = True - if value["namespace"].lower() == "microsoft.monitor" and value["registrationState"].lower() == "registered": - isAlertsManagementRpRegistered = True - if value["namespace"].lower() == "microsoft.dashboard" and value["registrationState"].lower() == "registered": - isAlertsManagementRpRegistered = True - if isInsightsRpRegistered is False: - headers = ['User-Agent=azuremonitormetrics.register_insights_rp'] - post_request(cmd, subscription_id, "microsoft.insights", headers) - if isAlertsManagementRpRegistered is False: - headers = ['User-Agent=azuremonitormetrics.register_alertsmanagement_rp'] - post_request(cmd, subscription_id, "microsoft.alertsmanagement", headers) - if isMoniotrRpRegistered is False: - headers = ['User-Agent=azuremonitormetrics.register_monitor_rp'] - post_request(cmd, subscription_id, "microsoft.monitor", headers) - if isDashboardRpRegistered is False: - headers = ['User-Agent=azuremonitormetrics.register_dashboard_rp'] - post_request(cmd, subscription_id, "microsoft.dashboard", headers) - - # pylint: disable=too-many-locals,too-many-branches,too-many-statements,line-too-long def ensure_azure_monitor_profile_prerequisites( cmd, diff --git a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/constants.py b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/constants.py new file mode 100644 index 00000000000..1a9b5130f3b --- /dev/null +++ b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/constants.py @@ -0,0 +1,85 @@ +from azure.core import CaseInsensitiveEnumMeta +from enum import Enum +from six import with_metaclass + +AKS_CLUSTER_API = "2023-01-01" # "2023-01-01" +MAC_API = "2023-04-03" +DC_API = "2022-06-01" +GRAFANA_API = "2022-08-01" +GRAFANA_ROLE_ASSIGNMENT_API = "2022-04-01" +RULES_API = "2023-03-01" +FEATURE_API = "2020-09-01" +RP_API = "2021-04-01" +ALERTS_API = "2023-01-01-preview" +RP_LOCATION_API = "2022-01-01" + + +MapToClosestMACRegion = { + "australiacentral": "eastus", + "australiacentral2": "eastus", + "australiaeast": "eastus", + "australiasoutheast": "eastus", + "brazilsouth": "eastus", + "canadacentral": "eastus", + "canadaeast": "eastus", + "centralus": "centralus", + "centralindia": "centralindia", + "eastasia": "westeurope", + "eastus": "eastus", + "eastus2": "eastus2", + "francecentral": "westeurope", + "francesouth": "westeurope", + "japaneast": "eastus", + "japanwest": "eastus", + "koreacentral": "westeurope", + "koreasouth": "westeurope", + "northcentralus": "eastus", + "northeurope": "westeurope", + "southafricanorth": "westeurope", + "southafricawest": "westeurope", + "southcentralus": "eastus", + "southeastasia": "westeurope", + "southindia": "centralindia", + "uksouth": "westeurope", + "ukwest": "westeurope", + "westcentralus": "eastus", + "westeurope": "westeurope", + "westindia": "centralindia", + "westus": "westus", + "westus2": "westus2", + "westus3": "westus", + "norwayeast": "westeurope", + "norwaywest": "westeurope", + "switzerlandnorth": "westeurope", + "switzerlandwest": "westeurope", + "uaenorth": "westeurope", + "germanywestcentral": "westeurope", + "germanynorth": "westeurope", + "uaecentral": "westeurope", + "eastus2euap": "eastus2euap", + "centraluseuap": "westeurope", + "brazilsoutheast": "eastus", + "jioindiacentral": "centralindia", + "swedencentral": "westeurope", + "swedensouth": "westeurope", + "qatarcentral": "westeurope" +} + + +class GrafanaLink(with_metaclass(CaseInsensitiveEnumMeta, str, Enum)): + """ + Status of Grafana link to the Prometheus Addon + """ + SUCCESS = "SUCCESS" + FAILURE = "FAILURE" + ALREADYPRESENT = "ALREADYPRESENT" + NOPARAMPROVIDED = "NOPARAMPROVIDED" + + +class DC_TYPE(with_metaclass(CaseInsensitiveEnumMeta, str, Enum)): + """ + Types of DC* objects + """ + DCE = "DCE" + DCR = "DCR" + DCRA = "DCRA" diff --git a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/dce_api.py b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/dce_api.py new file mode 100644 index 00000000000..b459ba8ffea --- /dev/null +++ b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/dce_api.py @@ -0,0 +1,23 @@ +import json +from azure.cli.command_modules.acs.azuremonitormetrics.constants import DC_API +from azure.cli.command_modules.acs.azuremonitormetrics.dc.defaults import get_default_dce_name +from knack.util import CLIError + + +def create_dce(cmd, cluster_subscription, cluster_resource_group_name, cluster_name, mac_region): + from azure.cli.core.util import send_raw_request + dce_name = get_default_dce_name(cmd, mac_region, cluster_name) + dce_resource_id = "/subscriptions/{0}/resourceGroups/{1}/providers/Microsoft.Insights/dataCollectionEndpoints/{2}".format(cluster_subscription, cluster_resource_group_name, dce_name) + try: + dce_url = f"https://management.azure.com{dce_resource_id}?api-version={DC_API}" + dce_creation_body = json.dumps({"name": dce_name, + "location": mac_region, + "kind": "Linux", + "properties": {}}) + headers = ['User-Agent=azuremonitormetrics.create_dce'] + send_raw_request(cmd.cli_ctx, "PUT", + dce_url, body=dce_creation_body, headers=headers) + error = None + return dce_resource_id + except CLIError as error: + raise error \ No newline at end of file diff --git a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/dcr_api.py b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/dcr_api.py new file mode 100644 index 00000000000..b5bc58b2239 --- /dev/null +++ b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/dcr_api.py @@ -0,0 +1,42 @@ +import json +from azure.cli.command_modules.acs.azuremonitormetrics.constants import MapToClosestMACRegion +from azure.cli.command_modules.acs.azuremonitormetrics.dc.defaults import get_default_region, sanitize_name +from azure.cli.command_modules.acs.azuremonitormetrics.constants import DC_TYPE +from knack.util import CLIError + + +def get_default_dcr_name(cmd, mac_region, cluster_name): + region = get_default_region(cmd) + if mac_region in MapToClosestMACRegion: + region = MapToClosestMACRegion[mac_region] + default_dcr_name = "MSProm-" + region + "-" + cluster_name + return sanitize_name(default_dcr_name, DC_TYPE.DCR, 64) + + +# pylint: disable=too-many-locals,too-many-branches,too-many-statements,line-too-long +def create_dcr(cmd, mac_region, azure_monitor_workspace_resource_id, cluster_subscription, cluster_resource_group_name, cluster_name, dce_resource_id): + from azure.cli.core.util import send_raw_request + dcr_name = get_default_dcr_name(cmd, mac_region, cluster_name) + dcr_resource_id = "/subscriptions/{0}/resourceGroups/{1}/providers/Microsoft.Insights/dataCollectionRules/{2}".format( + cluster_subscription, + cluster_resource_group_name, + dcr_name + ) + dcr_creation_body = json.dumps({"location": mac_region, + "kind": "Linux", + "properties": { + "dataCollectionEndpointId": dce_resource_id, + "dataSources": {"prometheusForwarder": [{"name": "PrometheusDataSource", "streams": ["Microsoft-PrometheusMetrics"], "labelIncludeFilter": {}}]}, + "dataFlows": [{"destinations": ["MonitoringAccount1"], "streams": ["Microsoft-PrometheusMetrics"]}], + "description": "DCR description", + "destinations": { + "monitoringAccounts": [{"accountResourceId": azure_monitor_workspace_resource_id, "name": "MonitoringAccount1"}]}}}) + dcr_url = f"https://management.azure.com{dcr_resource_id}?api-version={DC_API}" + try: + headers = ['User-Agent=azuremonitormetrics.create_dcr'] + send_raw_request(cmd.cli_ctx, "PUT", + dcr_url, body=dcr_creation_body, headers=headers) + error = None + return dcr_resource_id + except CLIError as error: + raise error diff --git a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/dcra.py b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/dcra_api.py similarity index 71% rename from src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/dcra.py rename to src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/dcra_api.py index f6a0731b7a0..4b8d071af94 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/dcra.py +++ b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/dcra_api.py @@ -4,21 +4,6 @@ CLIError ) -def get_default_dcra_name(cmd, cluster_region, cluster_name): - region = get_default_region(cmd) - if cluster_region in MapToClosestMACRegion: - region = MapToClosestMACRegion[cluster_region] - default_dcra_name = "ContainerInsightsMetricsExtension-" + region + "-" + cluster_name - return sanitize_name(default_dcra_name, DC_TYPE.DCRA, 64) - -def get_default_region(cmd): - cloud_name = cmd.cli_ctx.cloud.name - if cloud_name.lower() == 'azurechinacloud': - raise CLIError("Azure China Cloud is not supported for the Azure Monitor Metrics addon") - if cloud_name.lower() == 'azureusgovernment': - return "usgovvirginia" - return "eastus" - def create_dcra(cmd, cluster_region, cluster_subscription, cluster_resource_group_name, cluster_name, dcr_resource_id): from azure.cli.core.util import send_raw_request cluster_resource_id = "/subscriptions/{0}/resourceGroups/{1}/providers/Microsoft.ContainerService/managedClusters/{2}".format( diff --git a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/defaults.py b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/defaults.py new file mode 100644 index 00000000000..904b17fec79 --- /dev/null +++ b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/defaults.py @@ -0,0 +1,38 @@ + +from azure.cli.command_modules.acs.azuremonitormetrics.constants import ( + DC_TYPE, + MapToClosestMACRegion +) +from azure.cli.command_modules.acs.azuremonitormetrics.deaults import get_default_region + +# DCR = 64, DCE = 44, DCRA = 64 +# All DC* object names should end only in alpha numeric (after `length` trim) +# DCE remove underscore from cluster name +def sanitize_name(name, type, length): + length = length - 1 + if type == DC_TYPE.DCE: + name = name.replace("_", "") + name = name[0:length] + lastIndexAlphaNumeric = len(name) - 1 + while ((name[lastIndexAlphaNumeric].isalnum() is False) and lastIndexAlphaNumeric > -1): + lastIndexAlphaNumeric = lastIndexAlphaNumeric - 1 + if (lastIndexAlphaNumeric < 0): + return "" + return name[0:lastIndexAlphaNumeric + 1] + +def get_default_dce_name(cmd, mac_region, cluster_name): + region = get_default_region(cmd) + if mac_region in MapToClosestMACRegion: + region = MapToClosestMACRegion[mac_region] + default_dce_name = "MSProm-" + region + "-" + cluster_name + return sanitize_name(default_dce_name, DC_TYPE.DCE, 44) + + +def get_default_dcra_name(cmd, cluster_region, cluster_name): + region = get_default_region(cmd) + if cluster_region in MapToClosestMACRegion: + region = MapToClosestMACRegion[cluster_region] + default_dcra_name = "ContainerInsightsMetricsExtension-" + region + "-" + cluster_name + return sanitize_name(default_dcra_name, DC_TYPE.DCRA, 64) + + diff --git a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/delete.py b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/delete.py new file mode 100644 index 00000000000..55a0d943399 --- /dev/null +++ b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/delete.py @@ -0,0 +1,61 @@ + +def get_dce_from_dcr(cmd, dcrId): + from azure.cli.core.util import send_raw_request + association_url = f"https://management.azure.com{dcrId}?api-version={DC_API}" + headers = ['User-Agent=azuremonitormetrics.get_dce_from_dcr'] + r = send_raw_request(cmd.cli_ctx, "GET", association_url, headers=headers) + data = json.loads(r.text) + return data['properties']['dataCollectionEndpointId'] + + +def get_dc_objects_list(cmd, cluster_region, cluster_subscription, cluster_resource_group_name, cluster_name): + try: + from azure.cli.core.util import send_raw_request + cluster_resource_id = "/subscriptions/{0}/resourceGroups/{1}/providers/Microsoft.ContainerService/managedClusters/{2}".format( + cluster_subscription, + cluster_resource_group_name, + cluster_name + ) + association_url = f"https://management.azure.com{cluster_resource_id}/providers/Microsoft.Insights/dataCollectionRuleAssociations?api-version={DC_API}" + headers = ['User-Agent=azuremonitormetrics.get_dcra'] + r = send_raw_request(cmd.cli_ctx, "GET", association_url, headers=headers) + data = json.loads(r.text) + dc_object_array = [] + for item in data['value']: + dce_id = get_dce_from_dcr(cmd, item['properties']['dataCollectionRuleId']) + dc_object_array.append({'name': item['name'], 'dataCollectionRuleId': item['properties']['dataCollectionRuleId'], 'dceId': dce_id}) + return dc_object_array + except CLIError as e: + error = e + raise CLIError(error) + + +def delete_dc_objects_if_prometheus_enabled(cmd, dc_objects_list, cluster_subscription, cluster_resource_group_name, cluster_name): + from azure.cli.core.util import send_raw_request + cluster_resource_id = "/subscriptions/{0}/resourceGroups/{1}/providers/Microsoft.ContainerService/managedClusters/{2}".format( + cluster_subscription, + cluster_resource_group_name, + cluster_name + ) + for item in dc_objects_list: + association_url = f"https://management.azure.com{item['dataCollectionRuleId']}?api-version={DC_API}" + try: + headers = ['User-Agent=azuremonitormetrics.get_dcr_if_prometheus_enabled'] + r = send_raw_request(cmd.cli_ctx, "GET", association_url, headers=headers) + data = json.loads(r.text) + if 'microsoft-prometheusmetrics' in [stream.lower() for stream in data['properties']['dataFlows'][0]['streams']]: + # delete DCRA + url = f"https://management.azure.com{cluster_resource_id}/providers/Microsoft.Insights/dataCollectionRuleAssociations/{item['name']}?api-version={DC_API}" + headers = ['User-Agent=azuremonitormetrics.delete_dcra'] + send_raw_request(cmd.cli_ctx, "DELETE", url, headers=headers) + # delete DCR + url = f"https://management.azure.com{item['dataCollectionRuleId']}?api-version={DC_API}" + headers = ['User-Agent=azuremonitormetrics.delete_dcr'] + send_raw_request(cmd.cli_ctx, "DELETE", url, headers=headers) + # delete DCE + url = f"https://management.azure.com{item['dceId']}?api-version={DC_API}" + headers = ['User-Agent=azuremonitormetrics.delete_dce'] + send_raw_request(cmd.cli_ctx, "DELETE", url, headers=headers) + except CLIError as e: + error = e + raise CLIError(error) diff --git a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/deaults.py b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/deaults.py new file mode 100644 index 00000000000..fada6792353 --- /dev/null +++ b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/deaults.py @@ -0,0 +1,9 @@ +from knack.util import CLIError + +def get_default_region(cmd): + cloud_name = cmd.cli_ctx.cloud.name + if cloud_name.lower() == 'azurechinacloud': + raise CLIError("Azure China Cloud is not supported for the Azure Monitor Metrics addon") + if cloud_name.lower() == 'azureusgovernment': + return "usgovvirginia" + return "eastus" \ No newline at end of file diff --git a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/helper.py b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/helper.py new file mode 100644 index 00000000000..ff5621de3d9 --- /dev/null +++ b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/helper.py @@ -0,0 +1,89 @@ +import json +from knack.util import CLIError +from azure.cli.core.azclierror import ( + UnknownError +) +from azure.cli.command_modules.acs.azuremonitormetrics.constants import ( + RP_API, + AKS_CLUSTER_API +) + + +def sanitize_resource_id(resource_id): + resource_id = resource_id.strip() + if not resource_id.startswith("/"): + resource_id = "/" + resource_id + if resource_id.endswith("/"): + resource_id = resource_id.rstrip("/") + return resource_id.lower() + + +def post_request(cmd, subscription_id, rp_name, headers): + from azure.cli.core.util import send_raw_request + customUrl = "https://management.azure.com/subscriptions/{0}/providers/{1}/register?api-version={2}".format( + subscription_id, + rp_name, + RP_API, + ) + try: + send_raw_request(cmd.cli_ctx, "POST", customUrl, headers=headers) + except CLIError as e: + raise CLIError(e) + + +def rp_registrations(cmd, subscription_id): + from azure.cli.core.util import send_raw_request + # Get list of RP's for RP's subscription + try: + headers = ['User-Agent=azuremonitormetrics.get_mac_sub_list'] + customUrl = "https://management.azure.com/subscriptions/{0}/providers?api-version={1}&$select=namespace,registrationstate".format( + subscription_id, + RP_API + ) + r = send_raw_request(cmd.cli_ctx, "GET", customUrl, headers=headers) + except CLIError as e: + raise CLIError(e) + isInsightsRpRegistered = False + isAlertsManagementRpRegistered = False + isMoniotrRpRegistered = False + isDashboardRpRegistered = False + json_response = json.loads(r.text) + values_array = json_response["value"] + for value in values_array: + if value["namespace"].lower() == "microsoft.insights" and value["registrationState"].lower() == "registered": + isInsightsRpRegistered = True + if value["namespace"].lower() == "microsoft.alertsmanagement" and value["registrationState"].lower() == "registered": + isAlertsManagementRpRegistered = True + if value["namespace"].lower() == "microsoft.monitor" and value["registrationState"].lower() == "registered": + isAlertsManagementRpRegistered = True + if value["namespace"].lower() == "microsoft.dashboard" and value["registrationState"].lower() == "registered": + isAlertsManagementRpRegistered = True + if isInsightsRpRegistered is False: + headers = ['User-Agent=azuremonitormetrics.register_insights_rp'] + post_request(cmd, subscription_id, "microsoft.insights", headers) + if isAlertsManagementRpRegistered is False: + headers = ['User-Agent=azuremonitormetrics.register_alertsmanagement_rp'] + post_request(cmd, subscription_id, "microsoft.alertsmanagement", headers) + if isMoniotrRpRegistered is False: + headers = ['User-Agent=azuremonitormetrics.register_monitor_rp'] + post_request(cmd, subscription_id, "microsoft.monitor", headers) + if isDashboardRpRegistered is False: + headers = ['User-Agent=azuremonitormetrics.register_dashboard_rp'] + post_request(cmd, subscription_id, "microsoft.dashboard", headers) + + +def check_azuremonitormetrics_profile(cmd, cluster_subscription, cluster_resource_group_name, cluster_name): + from azure.cli.core.util import send_raw_request + feature_check_url = f"https://management.azure.com/subscriptions/{cluster_subscription}/resourceGroups/{cluster_resource_group_name}/providers/Microsoft.ContainerService/managedClusters/{cluster_name}?api-version={AKS_CLUSTER_API}" + try: + headers = ['User-Agent=azuremonitormetrics.check_azuremonitormetrics_profile'] + r = send_raw_request(cmd.cli_ctx, "GET", feature_check_url, + body={}, headers=headers) + except CLIError as e: + raise UnknownError(e) + json_response = json.loads(r.text) + values_array = json_response["properties"] + if "azureMonitorProfile" in values_array: + if "metrics" in values_array["azureMonitorProfile"]: + if values_array["azureMonitorProfile"]["metrics"]["enabled"] is True: + raise CLIError(f"Azure Monitor Metrics is already enabled for this cluster. Please use `az aks update --disable-azuremonitormetrics -g {cluster_resource_group_name} -n {cluster_name}` and then try enabling.") diff --git a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/recordingrules/create.py b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/recordingrules/create.py new file mode 100644 index 00000000000..6a14063a672 --- /dev/null +++ b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/recordingrules/create.py @@ -0,0 +1,95 @@ +import json + + +def get_recording_rules_template(cmd, azure_monitor_workspace_resource_id): + from azure.cli.core.util import send_raw_request + headers = ['User-Agent=azuremonitormetrics.get_recording_rules_template'] + url = f"https://management.azure.com{azure_monitor_workspace_resource_id}/providers/microsoft.alertsManagement/alertRuleRecommendations?api-version={ALERTS_API}" + r = send_raw_request(cmd.cli_ctx, "GET", url, headers=headers) + data = json.loads(r.text) + return data['value'] + + +def put_rules(cmd, default_rule_group_id, default_rule_group_name, mac_region, azure_monitor_workspace_resource_id, cluster_name, default_rules_template, url, i): + from azure.cli.core.util import send_raw_request + body = json.dumps({ + "id": default_rule_group_id, + "name": default_rule_group_name, + "type": "Microsoft.AlertsManagement/prometheusRuleGroups", + "location": mac_region, + "properties": { + "scopes": [ + azure_monitor_workspace_resource_id + ], + "enabled": True, + "clusterName": cluster_name, + "interval": "PT1M", + "rules": default_rules_template[i]["properties"]["rulesArmTemplate"]["resources"][0]["properties"]["rules"] + } + }) + for _ in range(3): + try: + headers = ['User-Agent=azuremonitormetrics.put_rules.' + default_rule_group_name] + send_raw_request(cmd.cli_ctx, "PUT", url, + body=body, headers=headers) + error = None + break + except CLIError as e: + error = e + else: + raise error + +def create_rules(cmd, cluster_subscription, cluster_resource_group_name, cluster_name, azure_monitor_workspace_resource_id, mac_region, raw_parameters): + # with urllib.request.urlopen("https://defaultrulessc.blob.core.windows.net/defaultrules/ManagedPrometheusDefaultRecordingRules.json") as url: + # default_rules_template = json.loads(url.read().decode()) + default_rules_template = get_recording_rules_template(cmd, azure_monitor_workspace_resource_id) + default_rule_group_name = "NodeRecordingRulesRuleGroup-{0}".format(cluster_name) + default_rule_group_id = "/subscriptions/{0}/resourceGroups/{1}/providers/Microsoft.AlertsManagement/prometheusRuleGroups/{2}".format( + cluster_subscription, + cluster_resource_group_name, + default_rule_group_name + ) + url = "https://management.azure.com{0}?api-version={1}".format( + default_rule_group_id, + RULES_API + ) + put_rules(cmd, default_rule_group_id, default_rule_group_name, mac_region, azure_monitor_workspace_resource_id, cluster_name, default_rules_template, url, 0) + + default_rule_group_name = "KubernetesRecordingRulesRuleGroup-{0}".format(cluster_name) + default_rule_group_id = "/subscriptions/{0}/resourceGroups/{1}/providers/Microsoft.AlertsManagement/prometheusRuleGroups/{2}".format( + cluster_subscription, + cluster_resource_group_name, + default_rule_group_name + ) + url = "https://management.azure.com{0}?api-version={1}".format( + default_rule_group_id, + RULES_API + ) + put_rules(cmd, default_rule_group_id, default_rule_group_name, mac_region, azure_monitor_workspace_resource_id, cluster_name, default_rules_template, url, 1) + + enable_windows_recording_rules = raw_parameters.get("enable_windows_recording_rules") + + if enable_windows_recording_rules is True: + default_rule_group_name = "NodeRecordingRulesRuleGroup-Win-{0}".format(cluster_name) + default_rule_group_id = "/subscriptions/{0}/resourceGroups/{1}/providers/Microsoft.AlertsManagement/prometheusRuleGroups/{2}".format( + cluster_subscription, + cluster_resource_group_name, + default_rule_group_name + ) + url = "https://management.azure.com{0}?api-version={1}".format( + default_rule_group_id, + RULES_API + ) + put_rules(cmd, default_rule_group_id, default_rule_group_name, mac_region, azure_monitor_workspace_resource_id, cluster_name, default_rules_template, url, 2) + + default_rule_group_name = "NodeAndKubernetesRecordingRulesRuleGroup-Win-{0}".format(cluster_name) + default_rule_group_id = "/subscriptions/{0}/resourceGroups/{1}/providers/Microsoft.AlertsManagement/prometheusRuleGroups/{2}".format( + cluster_subscription, + cluster_resource_group_name, + default_rule_group_name + ) + url = "https://management.azure.com{0}?api-version={1}".format( + default_rule_group_id, + RULES_API + ) + put_rules(cmd, default_rule_group_id, default_rule_group_name, mac_region, azure_monitor_workspace_resource_id, cluster_name, default_rules_template, url, 3) diff --git a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/recordingrules/delete.py b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/recordingrules/delete.py new file mode 100644 index 00000000000..5c2f69c83a5 --- /dev/null +++ b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/recordingrules/delete.py @@ -0,0 +1,20 @@ +def delete_rule(cmd, cluster_subscription, cluster_resource_group_name, cluster_name, default_rule_group_name): + from azure.cli.core.util import send_raw_request + default_rule_group_id = "/subscriptions/{0}/resourceGroups/{1}/providers/Microsoft.AlertsManagement/prometheusRuleGroups/{2}".format( + cluster_subscription, + cluster_resource_group_name, + default_rule_group_name + ) + headers = ['User-Agent=azuremonitormetrics.delete_rule.' + default_rule_group_name] + url = "https://management.azure.com{0}?api-version={1}".format( + default_rule_group_id, + RULES_API + ) + send_raw_request(cmd.cli_ctx, "DELETE", url, headers=headers) + + +def delete_rules(cmd, cluster_subscription, cluster_resource_group_name, cluster_name): + delete_rule(cmd, cluster_subscription, cluster_resource_group_name, cluster_name, "NodeRecordingRulesRuleGroup-{0}".format(cluster_name)) + delete_rule(cmd, cluster_subscription, cluster_resource_group_name, cluster_name, "KubernetesRecordingRulesRuleGroup-{0}".format(cluster_name)) + delete_rule(cmd, cluster_subscription, cluster_resource_group_name, cluster_name, "NodeRecordingRulesRuleGroup-Win-{0}".format(cluster_name)) + delete_rule(cmd, cluster_subscription, cluster_resource_group_name, cluster_name, "NodeAndKubernetesRecordingRulesRuleGroup-Win-{0}".format(cluster_name)) From 6db071041e1a523ef969ac448a6e7bf58b98212e Mon Sep 17 00:00:00 2001 From: Kaveesh Dubey Date: Fri, 7 Apr 2023 18:06:23 -0700 Subject: [PATCH 06/41] . --- .../acs/azuremonitormetrics/dc/dce_api.py | 1 + .../acs/azuremonitormetrics/dc/dcr_api.py | 5 ++++- .../acs/azuremonitormetrics/dc/dcra_api.py | 4 +++- .../acs/azuremonitormetrics/recordingrules/create.py | 2 ++ .../acs/azuremonitormetrics/recordingrules/delete.py | 12 +++++++----- 5 files changed, 17 insertions(+), 7 deletions(-) diff --git a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/dce_api.py b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/dce_api.py index b459ba8ffea..19c92354811 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/dce_api.py +++ b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/dce_api.py @@ -1,6 +1,7 @@ import json from azure.cli.command_modules.acs.azuremonitormetrics.constants import DC_API from azure.cli.command_modules.acs.azuremonitormetrics.dc.defaults import get_default_dce_name +from azure.cli.command_modules.acs.azuremonitormetrics.constants import DC_API from knack.util import CLIError diff --git a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/dcr_api.py b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/dcr_api.py index b5bc58b2239..15f0ce181f4 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/dcr_api.py +++ b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/dcr_api.py @@ -1,7 +1,10 @@ import json from azure.cli.command_modules.acs.azuremonitormetrics.constants import MapToClosestMACRegion from azure.cli.command_modules.acs.azuremonitormetrics.dc.defaults import get_default_region, sanitize_name -from azure.cli.command_modules.acs.azuremonitormetrics.constants import DC_TYPE +from azure.cli.command_modules.acs.azuremonitormetrics.constants import ( + DC_TYPE, + DC_API +) from knack.util import CLIError diff --git a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/dcra_api.py b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/dcra_api.py index 4b8d071af94..bf91b9e7e73 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/dcra_api.py +++ b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/dcra_api.py @@ -1,9 +1,11 @@ import json - +from azure.cli.command_modules.acs.azuremonitormetrics.constants import DC_API +from azure.cli.command_modules.acs.azuremonitormetrics.dc.defaults import get_default_dcra_name from azure.cli.core.azclierror import ( CLIError ) + def create_dcra(cmd, cluster_region, cluster_subscription, cluster_resource_group_name, cluster_name, dcr_resource_id): from azure.cli.core.util import send_raw_request cluster_resource_id = "/subscriptions/{0}/resourceGroups/{1}/providers/Microsoft.ContainerService/managedClusters/{2}".format( diff --git a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/recordingrules/create.py b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/recordingrules/create.py index 6a14063a672..a832ec74191 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/recordingrules/create.py +++ b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/recordingrules/create.py @@ -1,4 +1,6 @@ import json +from azure.cli.command_modules.acs.azuremonitormetrics.constants import ALERTS_API, RULES_API +from knack.util import CLIError def get_recording_rules_template(cmd, azure_monitor_workspace_resource_id): diff --git a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/recordingrules/delete.py b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/recordingrules/delete.py index 5c2f69c83a5..0a221074952 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/recordingrules/delete.py +++ b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/recordingrules/delete.py @@ -1,4 +1,6 @@ -def delete_rule(cmd, cluster_subscription, cluster_resource_group_name, cluster_name, default_rule_group_name): +from azure.cli.command_modules.acs.azuremonitormetrics.constants import RULES_API + +def delete_rule(cmd, cluster_subscription, cluster_resource_group_name, default_rule_group_name): from azure.cli.core.util import send_raw_request default_rule_group_id = "/subscriptions/{0}/resourceGroups/{1}/providers/Microsoft.AlertsManagement/prometheusRuleGroups/{2}".format( cluster_subscription, @@ -14,7 +16,7 @@ def delete_rule(cmd, cluster_subscription, cluster_resource_group_name, cluster_ def delete_rules(cmd, cluster_subscription, cluster_resource_group_name, cluster_name): - delete_rule(cmd, cluster_subscription, cluster_resource_group_name, cluster_name, "NodeRecordingRulesRuleGroup-{0}".format(cluster_name)) - delete_rule(cmd, cluster_subscription, cluster_resource_group_name, cluster_name, "KubernetesRecordingRulesRuleGroup-{0}".format(cluster_name)) - delete_rule(cmd, cluster_subscription, cluster_resource_group_name, cluster_name, "NodeRecordingRulesRuleGroup-Win-{0}".format(cluster_name)) - delete_rule(cmd, cluster_subscription, cluster_resource_group_name, cluster_name, "NodeAndKubernetesRecordingRulesRuleGroup-Win-{0}".format(cluster_name)) + delete_rule(cmd, cluster_subscription, cluster_resource_group_name, "NodeRecordingRulesRuleGroup-{0}".format(cluster_name)) + delete_rule(cmd, cluster_subscription, cluster_resource_group_name, "KubernetesRecordingRulesRuleGroup-{0}".format(cluster_name)) + delete_rule(cmd, cluster_subscription, cluster_resource_group_name, "NodeRecordingRulesRuleGroup-Win-{0}".format(cluster_name)) + delete_rule(cmd, cluster_subscription, cluster_resource_group_name, "NodeAndKubernetesRecordingRulesRuleGroup-Win-{0}".format(cluster_name)) From 4e049b15154ae4d22110250e06320020059574ca Mon Sep 17 00:00:00 2001 From: Kaveesh Dubey Date: Mon, 10 Apr 2023 12:32:38 -0700 Subject: [PATCH 07/41] . --- .../azure/cli/command_modules/acs/_help.py | 2 +- .../acs/azuremonitormetrics/addonput.py | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/azure-cli/azure/cli/command_modules/acs/_help.py b/src/azure-cli/azure/cli/command_modules/acs/_help.py index a66fac6587b..c19606bd9e7 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/_help.py +++ b/src/azure-cli/azure/cli/command_modules/acs/_help.py @@ -825,7 +825,7 @@ short-summary: Enable Windows Recording Rules when enabling the Azure Monitor Metrics addon - name: --disable-azuremonitormetrics type: bool - short-summary: Disable Azure Monitor Metrics Profile + short-summary: Disable Azure Monitor Metrics Profile. This will delete all DCRA's associated with the cluster, any linked DCRs with the data stream = prometheus-stream and the recording rule groups created by the addon for this AKS cluster. examples: - name: Reconcile the cluster back to its current state. diff --git a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/addonput.py b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/addonput.py index e8661bd564d..e37977fecd6 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/addonput.py +++ b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/addonput.py @@ -1,5 +1,6 @@ import json - +from azure.cli.command_modules.acs.azuremonitormetrics.constants import AKS_CLUSTER_API +from azure.cli.core.profiles import ResourceType from azure.cli.core.azclierror import ( UnknownError, CLIError @@ -16,15 +17,14 @@ def addon_put(cmd, cluster_subscription, cluster_resource_group_name, cluster_na except CLIError as e: raise UnknownError(e) json_response = json.loads(r.text) - values_array = json_response["properties"] - if "azureMonitorProfile" in values_array: - if "metrics" in values_array["azureMonitorProfile"]: - if values_array["azureMonitorProfile"]["metrics"]["enabled"] is False: + if "azureMonitorProfile" in json_response["properties"]: + if "metrics" in json_response["properties"]["azureMonitorProfile"]: + if json_response["properties"]["azureMonitorProfile"]["metrics"]["enabled"] is False: ## What if enabled doesn't exist - values_array["azureMonitorProfile"]["metrics"]["enabled"] = True + json_response["properties"]["azureMonitorProfile"]["metrics"]["enabled"] = True try: headers = ['User-Agent=azuremonitormetrics.addon_put'] - body = json.dumps(values_array) + body = json.dumps(json_response) r = send_raw_request(cmd.cli_ctx, "PUT", feature_check_url, body=body, headers=headers) except CLIError as e: From 49ba4599fd87f32f2c537c7f245d7c97c34cf3df Mon Sep 17 00:00:00 2001 From: Kaveesh Dubey Date: Wed, 19 Apr 2023 10:33:43 -0700 Subject: [PATCH 08/41] fairfax --- .../acs/azuremonitormetrics/addonput.py | 5 +++-- .../acs/azuremonitormetrics/amg/link.py | 9 ++++++--- .../acs/azuremonitormetrics/amw/create.py | 3 ++- .../acs/azuremonitormetrics/amw/defaults.py | 5 +++-- .../azuremonitorprofile.py | 14 ++++--------- .../acs/azuremonitormetrics/constants.py | 2 +- .../acs/azuremonitormetrics/dc/dce_api.py | 3 ++- .../acs/azuremonitormetrics/dc/dcr_api.py | 3 ++- .../acs/azuremonitormetrics/dc/dcra_api.py | 7 +++---- .../acs/azuremonitormetrics/dc/delete.py | 20 +++++++++++++------ .../acs/azuremonitormetrics/helper.py | 11 +++++++--- .../recordingrules/create.py | 15 +++++++++----- .../recordingrules/delete.py | 3 ++- .../azure/cli/command_modules/acs/custom.py | 1 - 14 files changed, 60 insertions(+), 41 deletions(-) diff --git a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/addonput.py b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/addonput.py index e37977fecd6..97a737972c6 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/addonput.py +++ b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/addonput.py @@ -7,9 +7,10 @@ ) -def addon_put(cmd, cluster_subscription, cluster_resource_group_name, cluster_name): +def addon_put(cmd, client, cluster_subscription, cluster_resource_group_name, cluster_name): from azure.cli.core.util import send_raw_request - feature_check_url = f"https://management.azure.com/subscriptions/{cluster_subscription}/resourceGroups/{cluster_resource_group_name}/providers/Microsoft.ContainerService/managedClusters/{cluster_name}?api-version={AKS_CLUSTER_API}" + armendpoint = cmd.cli_ctx.cloud.endpoints.resource_manager + feature_check_url = f"{armendpoint}/subscriptions/{cluster_subscription}/resourceGroups/{cluster_resource_group_name}/providers/Microsoft.ContainerService/managedClusters/{cluster_name}?api-version={AKS_CLUSTER_API}" try: headers = ['User-Agent=azuremonitormetrics.addon_get'] r = send_raw_request(cmd.cli_ctx, "GET", feature_check_url, diff --git a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/amg/link.py b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/amg/link.py index 3848751b095..c51360fac96 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/amg/link.py +++ b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/amg/link.py @@ -17,7 +17,8 @@ def link_grafana_instance(cmd, raw_parameters, azure_monitor_workspace_resource_ if grafana_resource_id is None or grafana_resource_id == "": return GrafanaLink.NOPARAMPROVIDED grafana_resource_id = sanitize_resource_id(grafana_resource_id) - grafanaURI = "https://management.azure.com{0}?api-version={1}".format( + grafanaURI = "{0}{1}?api-version={2}".format( + cmd.cli_ctx.cloud.endpoints.resource_manager, grafana_resource_id, GRAFANA_API ) @@ -29,7 +30,8 @@ def link_grafana_instance(cmd, raw_parameters, azure_monitor_workspace_resource_ # Add Role Assignment try: MonitoringDataReader = "b0d8363b-8ddd-447d-831f-62ca05bff136" - roleDefinitionURI = "https://management.azure.com{0}/providers/Microsoft.Authorization/roleAssignments/{1}?api-version={2}".format( + roleDefinitionURI = "{0}{1}/providers/Microsoft.Authorization/roleAssignments/{2}?api-version={3}".format( + cmd.cli_ctx.cloud.endpoints.resource_manager, azure_monitor_workspace_resource_id, uuid.uuid4(), GRAFANA_ROLE_ASSIGNMENT_API @@ -60,7 +62,8 @@ def link_grafana_instance(cmd, raw_parameters, azure_monitor_workspace_resource_ if amwIntegrations != [] and azure_monitor_workspace_resource_id in json.dumps(amwIntegrations).lower(): return GrafanaLink.ALREADYPRESENT try: - grafanaURI = "https://management.azure.com{0}?api-version={1}".format( + grafanaURI = "{0}{1}?api-version={2}".format( + cmd.cli_ctx.cloud.endpoints.resource_manager, grafana_resource_id, GRAFANA_API ) diff --git a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/amw/create.py b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/amw/create.py index 81555695997..360bd0bef0b 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/amw/create.py +++ b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/amw/create.py @@ -27,7 +27,8 @@ def create_default_mac(cmd, cluster_subscription, cluster_region): else: resource_groups.create_or_update(default_resource_group_name, {"location": default_mac_region}) association_body = json.dumps({"location": default_mac_region, "properties": {}}) - association_url = f"https://management.azure.com{azure_monitor_workspace_resource_id}?api-version={MAC_API}" + armendpoint = cmd.cli_ctx.cloud.endpoints.resource_manager + association_url = f"{armendpoint}{azure_monitor_workspace_resource_id}?api-version={MAC_API}" try: headers = ['User-Agent=azuremonitormetrics.create_default_mac'] send_raw_request(cmd.cli_ctx, "PUT", association_url, diff --git a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/amw/defaults.py b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/amw/defaults.py index d94ce58475e..e6694be31f4 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/amw/defaults.py +++ b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/amw/defaults.py @@ -1,14 +1,15 @@ import json from azure.cli.command_modules.acs.azuremonitormetrics.deaults import get_default_region from azure.cli.command_modules.acs.azuremonitormetrics.responseparsers.amwlocationresponseparser import parseResourceProviderResponseForLocations - +from azure.cli.command_modules.acs.azuremonitormetrics.constants import RP_LOCATION_API from knack.util import CLIError def get_supported_rp_locations(cmd, rp_name): from azure.cli.core.util import send_raw_request supported_locations = [] headers = ['User-Agent=azuremonitormetrics.get_supported_rp_locations'] - association_url = f"https://management.azure.com/providers/{rp_name}?api-version={RP_LOCATION_API}" + armendpoint = cmd.cli_ctx.cloud.endpoints.resource_manager + association_url = f"{armendpoint}/providers/{rp_name}?api-version={RP_LOCATION_API}" r = send_raw_request(cmd.cli_ctx, "GET", association_url, headers=headers) data = json.loads(r.text) supported_locations = parseResourceProviderResponseForLocations(data) diff --git a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/azuremonitorprofile.py b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/azuremonitorprofile.py index 4cea9c85e60..a3ea33f494d 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/azuremonitorprofile.py +++ b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/azuremonitorprofile.py @@ -13,17 +13,10 @@ from azure.cli.command_modules.acs.azuremonitormetrics.recordingrules.create import create_rules from azure.cli.command_modules.acs.azuremonitormetrics.recordingrules.delete import delete_rules from knack.util import CLIError +from azure.cli.core.azclierror import InvalidArgumentValueError -from azure.cli.core.azclierror import ( - InvalidArgumentValueError, -) -from .._client_factory import get_resources_client, get_resource_groups_client -from azure.core.exceptions import HttpResponseError - -first_supported_region = "" - -def link_azure_monitor_profile_artifacts(cmd, cluster_subscription, cluster_resource_group_name, cluster_name, cluster_region, raw_parameters, create_flow): +def link_azure_monitor_profile_artifacts(cmd, client, cluster_subscription, cluster_resource_group_name, cluster_name, cluster_region, raw_parameters, create_flow): # MAC creation if required azure_monitor_workspace_resource_id, azure_monitor_workspace_location = get_azure_monitor_workspace_resource(cmd, cluster_subscription, cluster_region, raw_parameters) # DCE creation @@ -38,7 +31,7 @@ def link_azure_monitor_profile_artifacts(cmd, cluster_subscription, cluster_reso create_rules(cmd, cluster_subscription, cluster_resource_group_name, cluster_name, azure_monitor_workspace_resource_id, azure_monitor_workspace_location, raw_parameters) # if aks cluster create flow -> do a PUT on the AKS cluster to enable the addon if create_flow: - addon_put(cmd, cluster_subscription, cluster_resource_group_name, cluster_name) + addon_put(cmd, client, cluster_subscription, cluster_resource_group_name, cluster_name) def unlink_azure_monitor_profile_artifacts(cmd, cluster_subscription, cluster_resource_group_name, cluster_name, cluster_region): @@ -87,6 +80,7 @@ def ensure_azure_monitor_profile_prerequisites( rp_registrations(cmd, cluster_subscription) link_azure_monitor_profile_artifacts( cmd, + client, cluster_subscription, cluster_resource_group_name, cluster_name, diff --git a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/constants.py b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/constants.py index 1a9b5130f3b..556daaa4a51 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/constants.py +++ b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/constants.py @@ -2,7 +2,7 @@ from enum import Enum from six import with_metaclass -AKS_CLUSTER_API = "2023-01-01" # "2023-01-01" +AKS_CLUSTER_API = "2023-01-01" MAC_API = "2023-04-03" DC_API = "2022-06-01" GRAFANA_API = "2022-08-01" diff --git a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/dce_api.py b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/dce_api.py index 19c92354811..4a61e0c7e80 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/dce_api.py +++ b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/dce_api.py @@ -10,7 +10,8 @@ def create_dce(cmd, cluster_subscription, cluster_resource_group_name, cluster_n dce_name = get_default_dce_name(cmd, mac_region, cluster_name) dce_resource_id = "/subscriptions/{0}/resourceGroups/{1}/providers/Microsoft.Insights/dataCollectionEndpoints/{2}".format(cluster_subscription, cluster_resource_group_name, dce_name) try: - dce_url = f"https://management.azure.com{dce_resource_id}?api-version={DC_API}" + armendpoint = cmd.cli_ctx.cloud.endpoints.resource_manager + dce_url = f"{armendpoint}{dce_resource_id}?api-version={DC_API}" dce_creation_body = json.dumps({"name": dce_name, "location": mac_region, "kind": "Linux", diff --git a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/dcr_api.py b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/dcr_api.py index 15f0ce181f4..970fff00cc5 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/dcr_api.py +++ b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/dcr_api.py @@ -34,7 +34,8 @@ def create_dcr(cmd, mac_region, azure_monitor_workspace_resource_id, cluster_sub "description": "DCR description", "destinations": { "monitoringAccounts": [{"accountResourceId": azure_monitor_workspace_resource_id, "name": "MonitoringAccount1"}]}}}) - dcr_url = f"https://management.azure.com{dcr_resource_id}?api-version={DC_API}" + armendpoint = cmd.cli_ctx.cloud.endpoints.resource_manager + dcr_url = f"{armendpoint}{dcr_resource_id}?api-version={DC_API}" try: headers = ['User-Agent=azuremonitormetrics.create_dcr'] send_raw_request(cmd.cli_ctx, "PUT", diff --git a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/dcra_api.py b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/dcra_api.py index bf91b9e7e73..130c06a3d55 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/dcra_api.py +++ b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/dcra_api.py @@ -1,9 +1,7 @@ import json from azure.cli.command_modules.acs.azuremonitormetrics.constants import DC_API from azure.cli.command_modules.acs.azuremonitormetrics.dc.defaults import get_default_dcra_name -from azure.cli.core.azclierror import ( - CLIError -) +from knack.util import CLIError def create_dcra(cmd, cluster_region, cluster_subscription, cluster_resource_group_name, cluster_name, dcr_resource_id): @@ -25,7 +23,8 @@ def create_dcra(cmd, cluster_region, cluster_subscription, cluster_resource_grou "dataCollectionRuleId": dcr_resource_id, "description": "Promtheus data collection association between DCR, DCE and target AKS resource" }}) - association_url = f"https://management.azure.com{cluster_resource_id}/providers/Microsoft.Insights/dataCollectionRuleAssociations/{dcra_name}?api-version={DC_API}" + armendpoint = cmd.cli_ctx.cloud.endpoints.resource_manager + association_url = f"{armendpoint}{cluster_resource_id}/providers/Microsoft.Insights/dataCollectionRuleAssociations/{dcra_name}?api-version={DC_API}" try: headers = ['User-Agent=azuremonitormetrics.create_dcra'] send_raw_request(cmd.cli_ctx, "PUT", association_url, diff --git a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/delete.py b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/delete.py index 55a0d943399..453bb7dd9da 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/delete.py +++ b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/delete.py @@ -1,7 +1,12 @@ +import json +from azure.cli.command_modules.acs.azuremonitormetrics.constants import DC_API +from knack.util import CLIError + def get_dce_from_dcr(cmd, dcrId): from azure.cli.core.util import send_raw_request - association_url = f"https://management.azure.com{dcrId}?api-version={DC_API}" + armendpoint = cmd.cli_ctx.cloud.endpoints.resource_manager + association_url = f"{armendpoint}{dcrId}?api-version={DC_API}" headers = ['User-Agent=azuremonitormetrics.get_dce_from_dcr'] r = send_raw_request(cmd.cli_ctx, "GET", association_url, headers=headers) data = json.loads(r.text) @@ -16,7 +21,8 @@ def get_dc_objects_list(cmd, cluster_region, cluster_subscription, cluster_resou cluster_resource_group_name, cluster_name ) - association_url = f"https://management.azure.com{cluster_resource_id}/providers/Microsoft.Insights/dataCollectionRuleAssociations?api-version={DC_API}" + armendpoint = cmd.cli_ctx.cloud.endpoints.resource_manager + association_url = f"{armendpoint}{cluster_resource_id}/providers/Microsoft.Insights/dataCollectionRuleAssociations?api-version={DC_API}" headers = ['User-Agent=azuremonitormetrics.get_dcra'] r = send_raw_request(cmd.cli_ctx, "GET", association_url, headers=headers) data = json.loads(r.text) @@ -38,22 +44,24 @@ def delete_dc_objects_if_prometheus_enabled(cmd, dc_objects_list, cluster_subscr cluster_name ) for item in dc_objects_list: - association_url = f"https://management.azure.com{item['dataCollectionRuleId']}?api-version={DC_API}" + armendpoint = cmd.cli_ctx.cloud.endpoints.resource_manager + association_url = f"{armendpoint}{item['dataCollectionRuleId']}?api-version={DC_API}" try: headers = ['User-Agent=azuremonitormetrics.get_dcr_if_prometheus_enabled'] r = send_raw_request(cmd.cli_ctx, "GET", association_url, headers=headers) data = json.loads(r.text) if 'microsoft-prometheusmetrics' in [stream.lower() for stream in data['properties']['dataFlows'][0]['streams']]: # delete DCRA - url = f"https://management.azure.com{cluster_resource_id}/providers/Microsoft.Insights/dataCollectionRuleAssociations/{item['name']}?api-version={DC_API}" + armendpoint = cmd.cli_ctx.cloud.endpoints.resource_manager + url = f"{armendpoint}{cluster_resource_id}/providers/Microsoft.Insights/dataCollectionRuleAssociations/{item['name']}?api-version={DC_API}" headers = ['User-Agent=azuremonitormetrics.delete_dcra'] send_raw_request(cmd.cli_ctx, "DELETE", url, headers=headers) # delete DCR - url = f"https://management.azure.com{item['dataCollectionRuleId']}?api-version={DC_API}" + url = f"{armendpoint}{item['dataCollectionRuleId']}?api-version={DC_API}" headers = ['User-Agent=azuremonitormetrics.delete_dcr'] send_raw_request(cmd.cli_ctx, "DELETE", url, headers=headers) # delete DCE - url = f"https://management.azure.com{item['dceId']}?api-version={DC_API}" + url = f"{armendpoint}{item['dceId']}?api-version={DC_API}" headers = ['User-Agent=azuremonitormetrics.delete_dce'] send_raw_request(cmd.cli_ctx, "DELETE", url, headers=headers) except CLIError as e: diff --git a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/helper.py b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/helper.py index ff5621de3d9..cea9eabd476 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/helper.py +++ b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/helper.py @@ -20,7 +20,9 @@ def sanitize_resource_id(resource_id): def post_request(cmd, subscription_id, rp_name, headers): from azure.cli.core.util import send_raw_request - customUrl = "https://management.azure.com/subscriptions/{0}/providers/{1}/register?api-version={2}".format( + armendpoint = cmd.cli_ctx.cloud.endpoints.resource_manager + customUrl = "{0}/subscriptions/{1}/providers/{2}/register?api-version={3}".format( + armendpoint, subscription_id, rp_name, RP_API, @@ -36,7 +38,9 @@ def rp_registrations(cmd, subscription_id): # Get list of RP's for RP's subscription try: headers = ['User-Agent=azuremonitormetrics.get_mac_sub_list'] - customUrl = "https://management.azure.com/subscriptions/{0}/providers?api-version={1}&$select=namespace,registrationstate".format( + armendpoint = cmd.cli_ctx.cloud.endpoints.resource_manager + customUrl = "{0}/subscriptions/{1}/providers?api-version={2}&$select=namespace,registrationstate".format( + armendpoint, subscription_id, RP_API ) @@ -74,7 +78,8 @@ def rp_registrations(cmd, subscription_id): def check_azuremonitormetrics_profile(cmd, cluster_subscription, cluster_resource_group_name, cluster_name): from azure.cli.core.util import send_raw_request - feature_check_url = f"https://management.azure.com/subscriptions/{cluster_subscription}/resourceGroups/{cluster_resource_group_name}/providers/Microsoft.ContainerService/managedClusters/{cluster_name}?api-version={AKS_CLUSTER_API}" + armendpoint = cmd.cli_ctx.cloud.endpoints.resource_manager + feature_check_url = f"{armendpoint}/subscriptions/{cluster_subscription}/resourceGroups/{cluster_resource_group_name}/providers/Microsoft.ContainerService/managedClusters/{cluster_name}?api-version={AKS_CLUSTER_API}" try: headers = ['User-Agent=azuremonitormetrics.check_azuremonitormetrics_profile'] r = send_raw_request(cmd.cli_ctx, "GET", feature_check_url, diff --git a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/recordingrules/create.py b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/recordingrules/create.py index a832ec74191..8980a044f17 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/recordingrules/create.py +++ b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/recordingrules/create.py @@ -6,7 +6,8 @@ def get_recording_rules_template(cmd, azure_monitor_workspace_resource_id): from azure.cli.core.util import send_raw_request headers = ['User-Agent=azuremonitormetrics.get_recording_rules_template'] - url = f"https://management.azure.com{azure_monitor_workspace_resource_id}/providers/microsoft.alertsManagement/alertRuleRecommendations?api-version={ALERTS_API}" + armendpoint = cmd.cli_ctx.cloud.endpoints.resource_manager + url = f"{armendpoint}{azure_monitor_workspace_resource_id}/providers/microsoft.alertsManagement/alertRuleRecommendations?api-version={ALERTS_API}" r = send_raw_request(cmd.cli_ctx, "GET", url, headers=headers) data = json.loads(r.text) return data['value'] @@ -51,7 +52,8 @@ def create_rules(cmd, cluster_subscription, cluster_resource_group_name, cluster cluster_resource_group_name, default_rule_group_name ) - url = "https://management.azure.com{0}?api-version={1}".format( + url = "{0}{1}?api-version={2}".format( + cmd.cli_ctx.cloud.endpoints.resource_manager, default_rule_group_id, RULES_API ) @@ -63,7 +65,8 @@ def create_rules(cmd, cluster_subscription, cluster_resource_group_name, cluster cluster_resource_group_name, default_rule_group_name ) - url = "https://management.azure.com{0}?api-version={1}".format( + url = "{0}{1}?api-version={2}".format( + cmd.cli_ctx.cloud.endpoints.resource_manager, default_rule_group_id, RULES_API ) @@ -78,7 +81,8 @@ def create_rules(cmd, cluster_subscription, cluster_resource_group_name, cluster cluster_resource_group_name, default_rule_group_name ) - url = "https://management.azure.com{0}?api-version={1}".format( + url = "{0}{1}?api-version={2}".format( + cmd.cli_ctx.cloud.endpoints.resource_manager, default_rule_group_id, RULES_API ) @@ -90,7 +94,8 @@ def create_rules(cmd, cluster_subscription, cluster_resource_group_name, cluster cluster_resource_group_name, default_rule_group_name ) - url = "https://management.azure.com{0}?api-version={1}".format( + url = "{0}{1}?api-version={2}".format( + cmd.cli_ctx.cloud.endpoints.resource_manager, default_rule_group_id, RULES_API ) diff --git a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/recordingrules/delete.py b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/recordingrules/delete.py index 0a221074952..15f07cf960b 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/recordingrules/delete.py +++ b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/recordingrules/delete.py @@ -8,7 +8,8 @@ def delete_rule(cmd, cluster_subscription, cluster_resource_group_name, default_ default_rule_group_name ) headers = ['User-Agent=azuremonitormetrics.delete_rule.' + default_rule_group_name] - url = "https://management.azure.com{0}?api-version={1}".format( + url = "{0}{1}?api-version={2}".format( + cmd.cli_ctx.cloud.endpoints.resource_manager, default_rule_group_id, RULES_API ) diff --git a/src/azure-cli/azure/cli/command_modules/acs/custom.py b/src/azure-cli/azure/cli/command_modules/acs/custom.py index d3f25fc4206..4c812c5a95e 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/custom.py +++ b/src/azure-cli/azure/cli/command_modules/acs/custom.py @@ -25,7 +25,6 @@ from distutils.version import StrictVersion from urllib.error import URLError from urllib.request import urlopen -from azure.cli.command_modules.acs.azuremonitormetrics.azuremonitorprofile import ensure_azure_monitor_profile_prerequisites import colorama import requests From 7debb4d59bbeaf0e3a1ae55c61c172da8c6a069e Mon Sep 17 00:00:00 2001 From: Kaveesh Dubey Date: Wed, 19 Apr 2023 11:57:41 -0700 Subject: [PATCH 09/41] . --- .../command_modules/acs/azuremonitormetrics/amw/defaults.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/amw/defaults.py b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/amw/defaults.py index e6694be31f4..5e6bad33234 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/amw/defaults.py +++ b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/amw/defaults.py @@ -16,14 +16,10 @@ def get_supported_rp_locations(cmd, rp_name): return supported_locations def get_default_mac_region(cmd, cluster_region): - global first_supported_region - if first_supported_region is not None and len(first_supported_region) != 0: - return first_supported_region supported_locations = get_supported_rp_locations(cmd, 'Microsoft.Monitor') if cluster_region in supported_locations: return cluster_region if len(supported_locations) > 0: - first_supported_region = supported_locations[0] return supported_locations[0] cloud_name = cmd.cli_ctx.cloud.name if cloud_name.lower() == 'azurechinacloud': From 3b43a05fc33464fb8b5b6303f28b4b597d3ddf89 Mon Sep 17 00:00:00 2001 From: Kaveesh Dubey Date: Wed, 19 Apr 2023 12:43:11 -0700 Subject: [PATCH 10/41] add linter exclusions --- .../command_modules/acs/linter_exclusions.yml | 36 +++++++++++++++++-- 1 file changed, 33 insertions(+), 3 deletions(-) diff --git a/src/azure-cli/azure/cli/command_modules/acs/linter_exclusions.yml b/src/azure-cli/azure/cli/command_modules/acs/linter_exclusions.yml index 12b1549e918..eee0ea2cf21 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/linter_exclusions.yml +++ b/src/azure-cli/azure/cli/command_modules/acs/linter_exclusions.yml @@ -24,7 +24,22 @@ aks create: - option_length_too_long image_cleaner_interval_hours: rule_exclusions: - - option_length_too_long + - option_length_too_long + azure_monitor_workspace_resource_id: + rule_exclusions: + - option_length_too_long + disable_azuremonitormetrics: + rule_exclusions: + - option_length_too_long + enable_azuremonitormetrics: + rule_exclusions: + - option_length_too_long + ksm_metric_annotations_allow_list: + rule_exclusions: + - option_length_too_long + ksm_metric_labels_allow_list: + rule_exclusions: + - option_length_too_long aks enable-addons: parameters: @@ -59,7 +74,7 @@ aks update: - option_length_too_long assign_kubelet_identity: rule_exclusions: - - option_length_too_long + - option_length_too_long enable_snapshot_controller: rule_exclusions: - option_length_too_long @@ -68,5 +83,20 @@ aks update: - option_length_too_long image_cleaner_interval_hours: rule_exclusions: - - option_length_too_long + - option_length_too_long + azure_monitor_workspace_resource_id: + rule_exclusions: + - option_length_too_long + disable_azuremonitormetrics: + rule_exclusions: + - option_length_too_long + enable_azuremonitormetrics: + rule_exclusions: + - option_length_too_long + ksm_metric_annotations_allow_list: + rule_exclusions: + - option_length_too_long + ksm_metric_labels_allow_list: + rule_exclusions: + - option_length_too_long ... From 57f7eba002798765376ad66c836f2b2d7f4b7626 Mon Sep 17 00:00:00 2001 From: Kaveesh Dubey Date: Wed, 19 Apr 2023 12:46:43 -0700 Subject: [PATCH 11/41] licence check --- .../cli/command_modules/acs/azuremonitormetrics/addonput.py | 4 ++++ .../cli/command_modules/acs/azuremonitormetrics/amg/link.py | 4 ++++ .../command_modules/acs/azuremonitormetrics/amw/create.py | 4 ++++ .../command_modules/acs/azuremonitormetrics/amw/defaults.py | 4 ++++ .../command_modules/acs/azuremonitormetrics/amw/helper.py | 6 ++++-- .../command_modules/acs/azuremonitormetrics/constants.py | 4 ++++ .../command_modules/acs/azuremonitormetrics/dc/dce_api.py | 4 ++++ .../command_modules/acs/azuremonitormetrics/dc/dcr_api.py | 4 ++++ .../command_modules/acs/azuremonitormetrics/dc/dcra_api.py | 4 ++++ .../command_modules/acs/azuremonitormetrics/dc/defaults.py | 5 ++++- .../command_modules/acs/azuremonitormetrics/dc/delete.py | 5 ++++- .../cli/command_modules/acs/azuremonitormetrics/deaults.py | 4 ++++ .../cli/command_modules/acs/azuremonitormetrics/helper.py | 4 ++++ .../acs/azuremonitormetrics/recordingrules/create.py | 4 ++++ .../acs/azuremonitormetrics/recordingrules/delete.py | 4 ++++ .../responseparsers/amwlocationresponseparser.py | 4 ++++ 16 files changed, 64 insertions(+), 4 deletions(-) diff --git a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/addonput.py b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/addonput.py index 97a737972c6..a49407f0b3b 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/addonput.py +++ b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/addonput.py @@ -1,3 +1,7 @@ +# -------------------------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# -------------------------------------------------------------------------------------------- import json from azure.cli.command_modules.acs.azuremonitormetrics.constants import AKS_CLUSTER_API from azure.cli.core.profiles import ResourceType diff --git a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/amg/link.py b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/amg/link.py index c51360fac96..7d29b0fc74f 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/amg/link.py +++ b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/amg/link.py @@ -1,3 +1,7 @@ +# -------------------------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# -------------------------------------------------------------------------------------------- import json import uuid from knack.util import CLIError diff --git a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/amw/create.py b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/amw/create.py index 360bd0bef0b..a422c73e246 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/amw/create.py +++ b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/amw/create.py @@ -1,3 +1,7 @@ +# -------------------------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# -------------------------------------------------------------------------------------------- import json from azure.cli.command_modules.acs.azuremonitormetrics.constants import MAC_API diff --git a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/amw/defaults.py b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/amw/defaults.py index 5e6bad33234..bf13e92698c 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/amw/defaults.py +++ b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/amw/defaults.py @@ -1,3 +1,7 @@ +# -------------------------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# -------------------------------------------------------------------------------------------- import json from azure.cli.command_modules.acs.azuremonitormetrics.deaults import get_default_region from azure.cli.command_modules.acs.azuremonitormetrics.responseparsers.amwlocationresponseparser import parseResourceProviderResponseForLocations diff --git a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/amw/helper.py b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/amw/helper.py index f2b8b1336da..13d0f502839 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/amw/helper.py +++ b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/amw/helper.py @@ -1,5 +1,7 @@ - - +# -------------------------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# -------------------------------------------------------------------------------------------- import json from azure.cli.command_modules.acs.azuremonitormetrics.amw.create import create_default_mac from azure.cli.command_modules.acs.azuremonitormetrics.constants import MAC_API diff --git a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/constants.py b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/constants.py index 556daaa4a51..ca5e49a7d8a 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/constants.py +++ b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/constants.py @@ -1,3 +1,7 @@ +# -------------------------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# -------------------------------------------------------------------------------------------- from azure.core import CaseInsensitiveEnumMeta from enum import Enum from six import with_metaclass diff --git a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/dce_api.py b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/dce_api.py index 4a61e0c7e80..c83b4f919d7 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/dce_api.py +++ b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/dce_api.py @@ -1,3 +1,7 @@ +# -------------------------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# -------------------------------------------------------------------------------------------- import json from azure.cli.command_modules.acs.azuremonitormetrics.constants import DC_API from azure.cli.command_modules.acs.azuremonitormetrics.dc.defaults import get_default_dce_name diff --git a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/dcr_api.py b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/dcr_api.py index 970fff00cc5..efbef75e78a 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/dcr_api.py +++ b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/dcr_api.py @@ -1,3 +1,7 @@ +# -------------------------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# -------------------------------------------------------------------------------------------- import json from azure.cli.command_modules.acs.azuremonitormetrics.constants import MapToClosestMACRegion from azure.cli.command_modules.acs.azuremonitormetrics.dc.defaults import get_default_region, sanitize_name diff --git a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/dcra_api.py b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/dcra_api.py index 130c06a3d55..40feccae34f 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/dcra_api.py +++ b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/dcra_api.py @@ -1,3 +1,7 @@ +# -------------------------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# -------------------------------------------------------------------------------------------- import json from azure.cli.command_modules.acs.azuremonitormetrics.constants import DC_API from azure.cli.command_modules.acs.azuremonitormetrics.dc.defaults import get_default_dcra_name diff --git a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/defaults.py b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/defaults.py index 904b17fec79..1c4d9962c74 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/defaults.py +++ b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/defaults.py @@ -1,4 +1,7 @@ - +# -------------------------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# -------------------------------------------------------------------------------------------- from azure.cli.command_modules.acs.azuremonitormetrics.constants import ( DC_TYPE, MapToClosestMACRegion diff --git a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/delete.py b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/delete.py index 453bb7dd9da..1d23ba968d7 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/delete.py +++ b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/delete.py @@ -1,4 +1,7 @@ - +# -------------------------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# -------------------------------------------------------------------------------------------- import json from azure.cli.command_modules.acs.azuremonitormetrics.constants import DC_API from knack.util import CLIError diff --git a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/deaults.py b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/deaults.py index fada6792353..f55ce449663 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/deaults.py +++ b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/deaults.py @@ -1,3 +1,7 @@ +# -------------------------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# -------------------------------------------------------------------------------------------- from knack.util import CLIError def get_default_region(cmd): diff --git a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/helper.py b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/helper.py index cea9eabd476..76a48423782 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/helper.py +++ b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/helper.py @@ -1,3 +1,7 @@ +# -------------------------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# -------------------------------------------------------------------------------------------- import json from knack.util import CLIError from azure.cli.core.azclierror import ( diff --git a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/recordingrules/create.py b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/recordingrules/create.py index 8980a044f17..410ec50f1bf 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/recordingrules/create.py +++ b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/recordingrules/create.py @@ -1,3 +1,7 @@ +# -------------------------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# -------------------------------------------------------------------------------------------- import json from azure.cli.command_modules.acs.azuremonitormetrics.constants import ALERTS_API, RULES_API from knack.util import CLIError diff --git a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/recordingrules/delete.py b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/recordingrules/delete.py index 15f07cf960b..95b2253e2de 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/recordingrules/delete.py +++ b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/recordingrules/delete.py @@ -1,3 +1,7 @@ +# -------------------------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# -------------------------------------------------------------------------------------------- from azure.cli.command_modules.acs.azuremonitormetrics.constants import RULES_API def delete_rule(cmd, cluster_subscription, cluster_resource_group_name, default_rule_group_name): diff --git a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/responseparsers/amwlocationresponseparser.py b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/responseparsers/amwlocationresponseparser.py index ca3016a0665..8c4612764d0 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/responseparsers/amwlocationresponseparser.py +++ b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/responseparsers/amwlocationresponseparser.py @@ -1,3 +1,7 @@ +# -------------------------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# -------------------------------------------------------------------------------------------- from typing import List def parseResourceProviderResponseForLocations(resourceProviderResponse): From fb435abb93ff9cc4081033d6735c1f35aeba8da9 Mon Sep 17 00:00:00 2001 From: Kaveesh Dubey Date: Wed, 19 Apr 2023 15:46:06 -0700 Subject: [PATCH 12/41] styling update --- .../cli/command_modules/acs/_validators.py | 2 + .../acs/azuremonitormetrics/addonput.py | 2 +- .../acs/azuremonitormetrics/amw/create.py | 2 +- .../acs/azuremonitormetrics/amw/defaults.py | 2 + .../acs/azuremonitormetrics/amw/helper.py | 1 + .../azuremonitorprofile.py | 5 +- .../acs/azuremonitormetrics/dc/dce_api.py | 3 +- .../acs/azuremonitormetrics/dc/dcr_api.py | 1 - .../acs/azuremonitormetrics/dc/dcra_api.py | 1 - .../acs/azuremonitormetrics/dc/defaults.py | 4 +- .../acs/azuremonitormetrics/dc/delete.py | 1 + .../acs/azuremonitormetrics/deaults.py | 3 +- .../recordingrules/create.py | 2 +- .../recordingrules/delete.py | 1 + .../amwlocationresponseparser.py | 1 + .../acs/managed_cluster_decorator.py | 59 +++++++++++++------ 16 files changed, 58 insertions(+), 32 deletions(-) diff --git a/src/azure-cli/azure/cli/command_modules/acs/_validators.py b/src/azure-cli/azure/cli/command_modules/acs/_validators.py index e7590ef1e54..c0b940535ec 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/_validators.py +++ b/src/azure-cli/azure/cli/command_modules/acs/_validators.py @@ -625,6 +625,7 @@ def sanitize_resource_id(resource_id): return resource_id.lower() +# pylint:disable=line-too-long def validate_azuremonitorworkspaceresourceid(namespace): resource_id = namespace.azure_monitor_workspace_resource_id if resource_id is None: @@ -634,6 +635,7 @@ def validate_azuremonitorworkspaceresourceid(namespace): raise ArgumentUsageError("--azure-monitor-workspace-resource-id not in the correct format. It should match `/subscriptions//resourceGroups//providers/microsoft.monitor/accounts/`") +# pylint:disable=line-too-long def validate_grafanaresourceid(namespace): resource_id = namespace.grafana_resource_id if resource_id is None: diff --git a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/addonput.py b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/addonput.py index a49407f0b3b..f7696e399fe 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/addonput.py +++ b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/addonput.py @@ -25,7 +25,7 @@ def addon_put(cmd, client, cluster_subscription, cluster_resource_group_name, cl if "azureMonitorProfile" in json_response["properties"]: if "metrics" in json_response["properties"]["azureMonitorProfile"]: if json_response["properties"]["azureMonitorProfile"]["metrics"]["enabled"] is False: - ## What if enabled doesn't exist + # What if enabled doesn't exist json_response["properties"]["azureMonitorProfile"]["metrics"]["enabled"] = True try: headers = ['User-Agent=azuremonitormetrics.addon_put'] diff --git a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/amw/create.py b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/amw/create.py index a422c73e246..93324c8a739 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/amw/create.py +++ b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/amw/create.py @@ -39,4 +39,4 @@ def create_default_mac(cmd, cluster_subscription, cluster_region): body=association_body, headers=headers) return azure_monitor_workspace_resource_id, default_mac_region except CLIError as e: - raise e \ No newline at end of file + raise e diff --git a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/amw/defaults.py b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/amw/defaults.py index bf13e92698c..820f799caa6 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/amw/defaults.py +++ b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/amw/defaults.py @@ -8,6 +8,7 @@ from azure.cli.command_modules.acs.azuremonitormetrics.constants import RP_LOCATION_API from knack.util import CLIError + def get_supported_rp_locations(cmd, rp_name): from azure.cli.core.util import send_raw_request supported_locations = [] @@ -19,6 +20,7 @@ def get_supported_rp_locations(cmd, rp_name): supported_locations = parseResourceProviderResponseForLocations(data) return supported_locations + def get_default_mac_region(cmd, cluster_region): supported_locations = get_supported_rp_locations(cmd, 'Microsoft.Monitor') if cluster_region in supported_locations: diff --git a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/amw/helper.py b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/amw/helper.py index 13d0f502839..b6f54a31f59 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/amw/helper.py +++ b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/amw/helper.py @@ -11,6 +11,7 @@ from azure.cli.command_modules.acs._client_factory import get_resources_client from knack.util import CLIError + def get_amw_region(cmd, azure_monitor_workspace_resource_id): # region of MAC can be different from region of RG so find the location of the azure_monitor_workspace_resource_id amw_subscription_id = azure_monitor_workspace_resource_id.split("/")[2] diff --git a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/azuremonitorprofile.py b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/azuremonitorprofile.py index a3ea33f494d..e3d26201164 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/azuremonitorprofile.py +++ b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/azuremonitorprofile.py @@ -35,12 +35,11 @@ def link_azure_monitor_profile_artifacts(cmd, client, cluster_subscription, clus def unlink_azure_monitor_profile_artifacts(cmd, cluster_subscription, cluster_resource_group_name, cluster_name, cluster_region): - ################ CHECK IF DCR IS LINKED WITH ANOTHER DCRA ############################################## # Remove DC* if prometheus is enabled dc_objects_list = get_dc_objects_list(cmd, cluster_region, cluster_subscription, cluster_resource_group_name, cluster_name) delete_dc_objects_if_prometheus_enabled(cmd, dc_objects_list, cluster_subscription, cluster_resource_group_name, cluster_name) # Delete rules (Conflict({"error":{"code":"InvalidResourceLocation","message":"The resource 'NodeRecordingRulesRuleGroup-' already exists in location 'eastus2' in resource group ''. A resource with the same name cannot be created in location 'eastus'. Please select a new resource name."}}) - delete_rules(cmd, cluster_subscription, cluster_resource_group_name, cluster_name) + delete_rules(cmd, cluster_subscription, cluster_resource_group_name, cluster_name) # pylint: disable=too-many-locals,too-many-branches,too-many-statements,line-too-long @@ -74,7 +73,7 @@ def ensure_azure_monitor_profile_prerequisites( ) else: # Check if already onboarded - if create_flow == False: + if create_flow is False: check_azuremonitormetrics_profile(cmd, cluster_subscription, cluster_resource_group_name, cluster_name) # Do RP registrations if required rp_registrations(cmd, cluster_subscription) diff --git a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/dce_api.py b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/dce_api.py index c83b4f919d7..00fb2484bde 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/dce_api.py +++ b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/dce_api.py @@ -23,7 +23,6 @@ def create_dce(cmd, cluster_subscription, cluster_resource_group_name, cluster_n headers = ['User-Agent=azuremonitormetrics.create_dce'] send_raw_request(cmd.cli_ctx, "PUT", dce_url, body=dce_creation_body, headers=headers) - error = None return dce_resource_id except CLIError as error: - raise error \ No newline at end of file + raise error diff --git a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/dcr_api.py b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/dcr_api.py index efbef75e78a..e9dc6a12159 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/dcr_api.py +++ b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/dcr_api.py @@ -44,7 +44,6 @@ def create_dcr(cmd, mac_region, azure_monitor_workspace_resource_id, cluster_sub headers = ['User-Agent=azuremonitormetrics.create_dcr'] send_raw_request(cmd.cli_ctx, "PUT", dcr_url, body=dcr_creation_body, headers=headers) - error = None return dcr_resource_id except CLIError as error: raise error diff --git a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/dcra_api.py b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/dcra_api.py index 40feccae34f..c50fea6eb2f 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/dcra_api.py +++ b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/dcra_api.py @@ -33,7 +33,6 @@ def create_dcra(cmd, cluster_region, cluster_subscription, cluster_resource_grou headers = ['User-Agent=azuremonitormetrics.create_dcra'] send_raw_request(cmd.cli_ctx, "PUT", association_url, body=association_body, headers=headers) - error = None return dcra_resource_id except CLIError as error: raise error diff --git a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/defaults.py b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/defaults.py index 1c4d9962c74..6885ab3d374 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/defaults.py +++ b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/defaults.py @@ -8,6 +8,7 @@ ) from azure.cli.command_modules.acs.azuremonitormetrics.deaults import get_default_region + # DCR = 64, DCE = 44, DCRA = 64 # All DC* object names should end only in alpha numeric (after `length` trim) # DCE remove underscore from cluster name @@ -23,6 +24,7 @@ def sanitize_name(name, type, length): return "" return name[0:lastIndexAlphaNumeric + 1] + def get_default_dce_name(cmd, mac_region, cluster_name): region = get_default_region(cmd) if mac_region in MapToClosestMACRegion: @@ -37,5 +39,3 @@ def get_default_dcra_name(cmd, cluster_region, cluster_name): region = MapToClosestMACRegion[cluster_region] default_dcra_name = "ContainerInsightsMetricsExtension-" + region + "-" + cluster_name return sanitize_name(default_dcra_name, DC_TYPE.DCRA, 64) - - diff --git a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/delete.py b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/delete.py index 1d23ba968d7..131a3112fa7 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/delete.py +++ b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/delete.py @@ -6,6 +6,7 @@ from azure.cli.command_modules.acs.azuremonitormetrics.constants import DC_API from knack.util import CLIError + def get_dce_from_dcr(cmd, dcrId): from azure.cli.core.util import send_raw_request armendpoint = cmd.cli_ctx.cloud.endpoints.resource_manager diff --git a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/deaults.py b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/deaults.py index f55ce449663..2e338217c2a 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/deaults.py +++ b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/deaults.py @@ -4,10 +4,11 @@ # -------------------------------------------------------------------------------------------- from knack.util import CLIError + def get_default_region(cmd): cloud_name = cmd.cli_ctx.cloud.name if cloud_name.lower() == 'azurechinacloud': raise CLIError("Azure China Cloud is not supported for the Azure Monitor Metrics addon") if cloud_name.lower() == 'azureusgovernment': return "usgovvirginia" - return "eastus" \ No newline at end of file + return "eastus" diff --git a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/recordingrules/create.py b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/recordingrules/create.py index 410ec50f1bf..5765e250404 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/recordingrules/create.py +++ b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/recordingrules/create.py @@ -39,13 +39,13 @@ def put_rules(cmd, default_rule_group_id, default_rule_group_name, mac_region, a headers = ['User-Agent=azuremonitormetrics.put_rules.' + default_rule_group_name] send_raw_request(cmd.cli_ctx, "PUT", url, body=body, headers=headers) - error = None break except CLIError as e: error = e else: raise error + def create_rules(cmd, cluster_subscription, cluster_resource_group_name, cluster_name, azure_monitor_workspace_resource_id, mac_region, raw_parameters): # with urllib.request.urlopen("https://defaultrulessc.blob.core.windows.net/defaultrules/ManagedPrometheusDefaultRecordingRules.json") as url: # default_rules_template = json.loads(url.read().decode()) diff --git a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/recordingrules/delete.py b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/recordingrules/delete.py index 95b2253e2de..befd4eba61e 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/recordingrules/delete.py +++ b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/recordingrules/delete.py @@ -4,6 +4,7 @@ # -------------------------------------------------------------------------------------------- from azure.cli.command_modules.acs.azuremonitormetrics.constants import RULES_API + def delete_rule(cmd, cluster_subscription, cluster_resource_group_name, default_rule_group_name): from azure.cli.core.util import send_raw_request default_rule_group_id = "/subscriptions/{0}/resourceGroups/{1}/providers/Microsoft.AlertsManagement/prometheusRuleGroups/{2}".format( diff --git a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/responseparsers/amwlocationresponseparser.py b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/responseparsers/amwlocationresponseparser.py index 8c4612764d0..0485fe9160f 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/responseparsers/amwlocationresponseparser.py +++ b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/responseparsers/amwlocationresponseparser.py @@ -4,6 +4,7 @@ # -------------------------------------------------------------------------------------------- from typing import List + def parseResourceProviderResponseForLocations(resourceProviderResponse): supportedLocationMap = {} if not resourceProviderResponse.get('resourceTypes'): diff --git a/src/azure-cli/azure/cli/command_modules/acs/managed_cluster_decorator.py b/src/azure-cli/azure/cli/command_modules/acs/managed_cluster_decorator.py index 5ce68a3b91d..2bed7d02d5f 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/managed_cluster_decorator.py +++ b/src/azure-cli/azure/cli/command_modules/acs/managed_cluster_decorator.py @@ -61,7 +61,9 @@ AKSAgentPoolModels, AKSAgentPoolUpdateDecorator, ) -from azure.cli.command_modules.acs.azuremonitormetrics.azuremonitorprofile import ensure_azure_monitor_profile_prerequisites +from azure.cli.command_modules.acs.azuremonitormetrics.azuremonitorprofile import ( + ensure_azure_monitor_profile_prerequisites +) from azure.cli.command_modules.acs.base_decorator import ( BaseAKSContext, BaseAKSManagedClusterDecorator, @@ -252,7 +254,9 @@ def external_functions(self) -> SimpleNamespace: external_functions["add_monitoring_role_assignment"] = add_monitoring_role_assignment external_functions["add_virtual_node_role_assignment"] = add_virtual_node_role_assignment external_functions["ensure_container_insights_for_monitoring"] = ensure_container_insights_for_monitoring - external_functions["ensure_azure_monitor_profile_prerequisites"] = ensure_azure_monitor_profile_prerequisites + external_functions[ + "ensure_azure_monitor_profile_prerequisites" + ] = ensure_azure_monitor_profile_prerequisites external_functions[ "ensure_default_log_analytics_workspace_for_monitoring" ] = ensure_default_log_analytics_workspace_for_monitoring @@ -4742,7 +4746,8 @@ def get_aks_custom_headers(self) -> Dict[str, str]: def _get_enable_azure_monitor_metrics(self, enable_validation: bool = False) -> bool: """Internal function to obtain the value of enable_azure_monitor_metrics. - This function supports the option of enable_validation. When enabled, if both enable_azure_monitor_metrics and disable_azure_monitor_metrics are + This function supports the option of enable_validation. + When enabled, if both enable_azure_monitor_metrics and disable_azure_monitor_metrics are specified, raise a MutuallyExclusiveArgumentError. :return: bool @@ -4772,28 +4777,34 @@ def _get_enable_azure_monitor_metrics(self, enable_validation: bool = False) -> def get_enable_azure_monitor_metrics(self) -> bool: """Obtain the value of enable_azure_monitor_metrics. - This function will verify the parameter by default. If both enable_azure_monitor_metrics and disable_azure_monitor_metrics are specified, raise a - MutuallyExclusiveArgumentError. + This function will verify the parameter by default. + If both enable_azure_monitor_metrics and disable_azure_monitor_metrics are specified, + raise a MutuallyExclusiveArgumentError. :return: bool """ return self._get_enable_azure_monitor_metrics(enable_validation=True) def _get_disable_azure_monitor_metrics(self, enable_validation: bool = False) -> bool: - """Internal function to obtain the value of disable_azure_monitor_metrics. - This function supports the option of enable_validation. When enabled, if both enable_azure_monitor_metrics and disable_azure_monitor_metrics are + """Internal function to obtain the value of disable_azure_monito4790r_metrics. + This function supports the option of enable_validation. + When enabled, if both enable_azure_monitor_metrics and disable_azure_monitor_metrics are specified, raise a MutuallyExclusiveArgumentError. :return: bool """ # Read the original value passed by the command. disable_azure_monitor_metrics = self.raw_param.get("disable_azuremonitormetrics") - if disable_azure_monitor_metrics and self._get_enable_azure_monitor_metrics(False): - raise MutuallyExclusiveArgumentError("Cannot specify --enable-azuremonitormetrics and --disable-azuremonitormetrics at the same time.") + if enable_validation: + if disable_azure_monitor_metrics and self._get_enable_azure_monitor_metrics(False): + raise MutuallyExclusiveArgumentError( + "Cannot specify --enable-azuremonitormetrics and --disable-azuremonitormetrics at the same time." + ) return disable_azure_monitor_metrics def get_disable_azure_monitor_metrics(self) -> bool: """Obtain the value of disable_azure_monitor_metrics. - This function will verify the parameter by default. If both enable_azure_monitor_metrics and disable_azure_monitor_metrics are specified, raise a - MutuallyExclusiveArgumentError. + This function will verify the parameter by default. + If both enable_azure_monitor_metrics and disable_azure_monitor_metrics are specified, + raise a MutuallyExclusiveArgumentError. :return: bool """ return self._get_disable_azure_monitor_metrics(enable_validation=True) @@ -5843,7 +5854,7 @@ def set_up_azure_monitor_profile(self, mc: ManagedCluster) -> ManagedCluster: if mc.azure_monitor_profile is None: mc.azure_monitor_profile = self.models.ManagedClusterAzureMonitorProfile() mc.azure_monitor_profile.metrics = self.models.ManagedClusterAzureMonitorProfileMetrics(enabled=False) - mc.azure_monitor_profile.metrics.kube_state_metrics = self.models.ManagedClusterAzureMonitorProfileKubeStateMetrics( + mc.azure_monitor_profile.metrics.kube_state_metrics = self.models.ManagedClusterAzureMonitorProfileKubeStateMetrics( # pylint:disable=line-too-long metric_labels_allowlist=str(ksm_metric_labels_allow_list), metric_annotations_allow_list=str(ksm_metric_annotations_allow_list)) # set intermediate @@ -5933,7 +5944,10 @@ def check_is_postprocessing_required(self, mc: ManagedCluster) -> bool: monitoring_addon_enabled = self.context.get_intermediate("monitoring_addon_enabled", default_value=False) ingress_appgw_addon_enabled = self.context.get_intermediate("ingress_appgw_addon_enabled", default_value=False) virtual_node_addon_enabled = self.context.get_intermediate("virtual_node_addon_enabled", default_value=False) - azuremonitormetrics_addon_enabled = self.context.get_intermediate("azuremonitormetrics_addon_enabled", default_value=False) + azuremonitormetrics_addon_enabled = self.context.get_intermediate( + "azuremonitormetrics_addon_enabled", + default_value=False + ) enable_managed_identity = self.context.get_enable_managed_identity() attach_acr = self.context.get_attach_acr() need_grant_vnet_permission_to_cluster_identity = self.context.get_intermediate( @@ -6056,10 +6070,13 @@ def postprocessing_after_mc_created(self, cluster: ManagedCluster) -> None: ) # azure monitor metrics addon (v2) - azuremonitormetrics_addon_enabled = self.context.get_intermediate("azuremonitormetrics_addon_enabled", default_value=False) + azuremonitormetrics_addon_enabled = self.context.get_intermediate( + "azuremonitormetrics_addon_enabled", + default_value=False + ) if azuremonitormetrics_addon_enabled: - # Create the DC* objects, AMW, recording rules and grafana link here - self.context.external_functions.ensure_azure_monitor_profile_prerequisites( + # Create the DC* objects, AMW, recording rules and grafana link here + self.context.external_functions.ensure_azure_monitor_profile_prerequisites( self.cmd, self.client, self.context.get_subscription_id(), @@ -6068,7 +6085,8 @@ def postprocessing_after_mc_created(self, cluster: ManagedCluster) -> None: self.context.get_location(), self.__raw_parameters, self.context.get_disable_azure_monitor_metrics(), - True) + True + ) def put_mc(self, mc: ManagedCluster) -> ManagedCluster: if self.check_is_postprocessing_required(mc): @@ -6919,7 +6937,7 @@ def update_azure_monitor_profile(self, mc: ManagedCluster) -> ManagedCluster: if mc.azure_monitor_profile is None: mc.azure_monitor_profile = self.models.ManagedClusterAzureMonitorProfile() mc.azure_monitor_profile.metrics = self.models.ManagedClusterAzureMonitorProfileMetrics(enabled=True) - mc.azure_monitor_profile.metrics.kube_state_metrics = self.models.ManagedClusterAzureMonitorProfileKubeStateMetrics( + mc.azure_monitor_profile.metrics.kube_state_metrics = self.models.ManagedClusterAzureMonitorProfileKubeStateMetrics( # pylint:disable=line-too-long metric_labels_allowlist=str(ksm_metric_labels_allow_list), metric_annotations_allow_list=str(ksm_metric_annotations_allow_list)) @@ -6928,7 +6946,10 @@ def update_azure_monitor_profile(self, mc: ManagedCluster) -> ManagedCluster: mc.azure_monitor_profile = self.models.ManagedClusterAzureMonitorProfile() mc.azure_monitor_profile.metrics = self.models.ManagedClusterAzureMonitorProfileMetrics(enabled=False) - if (self.context.raw_param.get("enable_azuremonitormetrics") or self.context.raw_param.get("disable_azuremonitormetrics")): + if ( + self.context.raw_param.get("enable_azuremonitormetrics") or + self.context.raw_param.get("disable_azuremonitormetrics") + ): self.context.external_functions.ensure_azure_monitor_profile_prerequisites( self.cmd, self.client, From a41cb3a1b1524a0f06aeb9b41e362339fb19fdf5 Mon Sep 17 00:00:00 2001 From: Kaveesh Dubey Date: Wed, 19 Apr 2023 16:02:53 -0700 Subject: [PATCH 13/41] linter --- .../azure/cli/command_modules/acs/linter_exclusions.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/azure-cli/azure/cli/command_modules/acs/linter_exclusions.yml b/src/azure-cli/azure/cli/command_modules/acs/linter_exclusions.yml index eee0ea2cf21..c161888262a 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/linter_exclusions.yml +++ b/src/azure-cli/azure/cli/command_modules/acs/linter_exclusions.yml @@ -40,6 +40,9 @@ aks create: ksm_metric_labels_allow_list: rule_exclusions: - option_length_too_long + enable_windows_recording_rules: + rule_exclusions: + - option_length_too_long aks enable-addons: parameters: @@ -99,4 +102,7 @@ aks update: ksm_metric_labels_allow_list: rule_exclusions: - option_length_too_long + enable_windows_recording_rules: + rule_exclusions: + - option_length_too_long ... From 1635170b907eebf517a78e4dc3e060b78369a275 Mon Sep 17 00:00:00 2001 From: Kaveesh Dubey Date: Mon, 24 Apr 2023 16:14:41 -0700 Subject: [PATCH 14/41] cli tests --- .../acs/tests/latest/test_aks_commands.py | 82 ++++++++++++++++++- 1 file changed, 79 insertions(+), 3 deletions(-) diff --git a/src/azure-cli/azure/cli/command_modules/acs/tests/latest/test_aks_commands.py b/src/azure-cli/azure/cli/command_modules/acs/tests/latest/test_aks_commands.py index a43809ae49d..4be71a22435 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/tests/latest/test_aks_commands.py +++ b/src/azure-cli/azure/cli/command_modules/acs/tests/latest/test_aks_commands.py @@ -7,7 +7,7 @@ import os import subprocess import tempfile -import time +import time import unittest from azure.cli.command_modules.acs._consts import CONST_KUBE_DASHBOARD_ADDON_NAME @@ -2038,7 +2038,7 @@ def test_aks_create_with_paid_sku(self, resource_group, resource_group_location, # delete self.cmd( 'aks delete -g {resource_group} -n {name} --yes --no-wait', checks=[self.is_empty()]) - + @AllowLargeResponse() @AKSCustomResourceGroupPreparer(random_name_length=17, name_prefix='clitest', location='westus2') @AKSCustomRoleBasedServicePrincipalPreparer() @@ -6300,6 +6300,82 @@ def test_aks_update_with_defender(self, resource_group, resource_group_location) self.cmd( 'aks delete -g {resource_group} -n {name} --yes --no-wait', checks=[self.is_empty()]) + @AllowLargeResponse() + @AKSCustomResourceGroupPreparer(random_name_length=17, name_prefix='clitest', location='centraluseuap') + def test_aks_create_with_azuremonitormetrics(self, resource_group, resource_group_location): + # reset the count so in replay mode the random names will start with 0 + self.test_resources_count = 0 + # kwargs for string formatting + aks_name = self.create_random_name('cliakstest', 16) + + node_vm_size = 'standard_d2s_v3' + self.kwargs.update({ + 'resource_group': resource_group, + 'name': aks_name, + 'location': resource_group_location, + 'resource_type': 'Microsoft.ContainerService/ManagedClusters', + 'ssh_key_value': self.generate_ssh_keys(), + 'node_vm_size': node_vm_size + }) + + create_cmd = ' '.join([ + 'aks', 'create', '--resource-group={resource_group}', '--name={name}', '--location={location}', + '--enable-managed-identity', '--enable-azuremonitormetrics --enable-windows-recording-rules', + '--ssh-key-value={ssh_key_value} --node-vm-size={node_vm_size}', + ]) + self.cmd(create_cmd, checks=[ + self.check('provisioningState', 'Succeeded'), + self.check('azureMonitorProfile.metrics.enabled', True), + ]) + + # delete + cmd = 'aks delete --resource-group={resource_group} --name={name} --yes --no-wait' + self.cmd(cmd, checks=[ + self.is_empty(), + ]) + + @AllowLargeResponse() + @AKSCustomResourceGroupPreparer(random_name_length=17, name_prefix='clitest', location='westus2') + def test_aks_update_with_azuremonitormetrics(self, resource_group, resource_group_location): + aks_name = self.create_random_name('cliakstest', 16) + node_vm_size = 'standard_d2s_v3' + self.kwargs.update({ + 'resource_group': resource_group, + 'name': aks_name, + 'location': resource_group_location, + 'ssh_key_value': self.generate_ssh_keys(), + 'node_vm_size': node_vm_size, + }) + + # create: without enable-azuremonitormetrics + create_cmd = 'aks create --resource-group={resource_group} --name={name} --location={location} --ssh-key-value={ssh_key_value} --node-vm-size={node_vm_size} --enable-managed-identity --output=json' + self.cmd(create_cmd, checks=[ + self.check('provisioningState', 'Succeeded'), + self.not_exists('azureMonitorProfile.metrics'), + ]) + + # update: enable-azuremonitormetrics + update_cmd = 'aks update --resource-group={resource_group} --name={name} --yes --output=json ' \ + '--enable-azuremonitormetrics --enable-managed-identity --enable-windows-recording-rules' + self.cmd(update_cmd, checks=[ + self.check('provisioningState', 'Succeeded'), + self.check('azureMonitorProfile.metrics.enabled', True), + ]) + + # update: disable-azuremonitormetrics + update_cmd = 'aks update --resource-group={resource_group} --name={name} --yes --output=json ' \ + '--disable-azuremonitormetrics' + self.cmd(update_cmd, checks=[ + self.check('provisioningState', 'Succeeded'), + self.check('azureMonitorProfile.metrics.enabled', False), + ]) + + # delete + cmd = 'aks delete --resource-group={resource_group} --name={name} --yes --no-wait' + self.cmd(cmd, checks=[ + self.is_empty(), + ]) + @AllowLargeResponse() @AKSCustomResourceGroupPreparer(random_name_length=17, name_prefix='clitest', location='westus2') def test_aks_create_with_custom_monitoring_workspace(self, resource_group, resource_group_location): @@ -8401,7 +8477,7 @@ def test_aks_create_dualstack_with_default_network(self, resource_group, resourc # delete self.cmd( 'aks delete -g {resource_group} -n {name} --yes --no-wait', checks=[self.is_empty()]) - + @AllowLargeResponse() @AKSCustomResourceGroupPreparer(random_name_length=17, name_prefix='clitest', location='westus2', preserve_default_location=True) def test_aks_create_and_update_ipv6_count(self, resource_group, resource_group_location): From efd8bb9bb833b43c12f03304576e276157fe331d Mon Sep 17 00:00:00 2001 From: Kaveesh Dubey Date: Mon, 24 Apr 2023 16:46:12 -0700 Subject: [PATCH 15/41] live only --- .../cli/command_modules/acs/tests/latest/test_aks_commands.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/azure-cli/azure/cli/command_modules/acs/tests/latest/test_aks_commands.py b/src/azure-cli/azure/cli/command_modules/acs/tests/latest/test_aks_commands.py index 4be71a22435..6cbc5760c01 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/tests/latest/test_aks_commands.py +++ b/src/azure-cli/azure/cli/command_modules/acs/tests/latest/test_aks_commands.py @@ -6300,6 +6300,7 @@ def test_aks_update_with_defender(self, resource_group, resource_group_location) self.cmd( 'aks delete -g {resource_group} -n {name} --yes --no-wait', checks=[self.is_empty()]) + @live_only() @AllowLargeResponse() @AKSCustomResourceGroupPreparer(random_name_length=17, name_prefix='clitest', location='centraluseuap') def test_aks_create_with_azuremonitormetrics(self, resource_group, resource_group_location): @@ -6334,6 +6335,7 @@ def test_aks_create_with_azuremonitormetrics(self, resource_group, resource_grou self.is_empty(), ]) + @live_only() @AllowLargeResponse() @AKSCustomResourceGroupPreparer(random_name_length=17, name_prefix='clitest', location='westus2') def test_aks_update_with_azuremonitormetrics(self, resource_group, resource_group_location): From 081ac835b733b2e6527ee9f1d98d9cbae067ff5d Mon Sep 17 00:00:00 2001 From: bragi92 Date: Mon, 24 Apr 2023 21:51:53 -0700 Subject: [PATCH 16/41] Update src/azure-cli/azure/cli/command_modules/acs/managed_cluster_decorator.py Co-authored-by: FumingZhang <81607949+FumingZhang@users.noreply.github.com> --- .../azure/cli/command_modules/acs/managed_cluster_decorator.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/azure-cli/azure/cli/command_modules/acs/managed_cluster_decorator.py b/src/azure-cli/azure/cli/command_modules/acs/managed_cluster_decorator.py index 2bed7d02d5f..b04b6e19a71 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/managed_cluster_decorator.py +++ b/src/azure-cli/azure/cli/command_modules/acs/managed_cluster_decorator.py @@ -4759,6 +4759,7 @@ def _get_enable_azure_monitor_metrics(self, enable_validation: bool = False) -> if self.decorator_mode == DecoratorMode.CREATE: if ( self.mc and + hasattr(self.mc, "azure_monitor_profile") and self.mc.azure_monitor_profile and self.mc.azure_monitor_profile.metrics ): From 5427e44f9f3a8171d9af6a91c6141ff8c4966f44 Mon Sep 17 00:00:00 2001 From: Kaveesh Dubey Date: Tue, 25 Apr 2023 18:02:39 -0700 Subject: [PATCH 17/41] fix deletion --- .../acs/azuremonitormetrics/azuremonitorprofile.py | 5 +++-- .../acs/azuremonitormetrics/dc/delete.py | 12 ++++++++---- .../command_modules/acs/managed_cluster_decorator.py | 5 ++++- 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/azuremonitorprofile.py b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/azuremonitorprofile.py index e3d26201164..6853ee9d563 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/azuremonitorprofile.py +++ b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/azuremonitorprofile.py @@ -36,7 +36,7 @@ def link_azure_monitor_profile_artifacts(cmd, client, cluster_subscription, clus def unlink_azure_monitor_profile_artifacts(cmd, cluster_subscription, cluster_resource_group_name, cluster_name, cluster_region): # Remove DC* if prometheus is enabled - dc_objects_list = get_dc_objects_list(cmd, cluster_region, cluster_subscription, cluster_resource_group_name, cluster_name) + dc_objects_list = get_dc_objects_list(cmd, cluster_subscription, cluster_resource_group_name, cluster_name) delete_dc_objects_if_prometheus_enabled(cmd, dc_objects_list, cluster_subscription, cluster_resource_group_name, cluster_name) # Delete rules (Conflict({"error":{"code":"InvalidResourceLocation","message":"The resource 'NodeRecordingRulesRuleGroup-' already exists in location 'eastus2' in resource group ''. A resource with the same name cannot be created in location 'eastus'. Please select a new resource name."}}) delete_rules(cmd, cluster_subscription, cluster_resource_group_name, cluster_name) @@ -60,7 +60,8 @@ def ensure_azure_monitor_profile_prerequisites( if cloud_name.lower() == "azureusgovernment": grafana_resource_id = raw_parameters.get("grafana_resource_id") - if grafana_resource_id is not None or grafana_resource_id != "": + if grafana_resource_id is not None: + if grafana_resource_id != "": raise InvalidArgumentValueError("Azure US Government cloud does not support Azure Managed Grarfana yet. Please follow this documenation for enabling it via the public cloud : aka.ms/ama-grafana-link-ff") if (remove_azuremonitormetrics): diff --git a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/delete.py b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/delete.py index 131a3112fa7..11a2bed0f7f 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/delete.py +++ b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/delete.py @@ -14,10 +14,13 @@ def get_dce_from_dcr(cmd, dcrId): headers = ['User-Agent=azuremonitormetrics.get_dce_from_dcr'] r = send_raw_request(cmd.cli_ctx, "GET", association_url, headers=headers) data = json.loads(r.text) - return data['properties']['dataCollectionEndpointId'] + if 'dataCollectionEndpointId' in data['properties']: + return str(data['properties']['dataCollectionEndpointId']) + else: + return "" -def get_dc_objects_list(cmd, cluster_region, cluster_subscription, cluster_resource_group_name, cluster_name): +def get_dc_objects_list(cmd, cluster_subscription, cluster_resource_group_name, cluster_name): try: from azure.cli.core.util import send_raw_request cluster_resource_id = "/subscriptions/{0}/resourceGroups/{1}/providers/Microsoft.ContainerService/managedClusters/{2}".format( @@ -32,8 +35,9 @@ def get_dc_objects_list(cmd, cluster_region, cluster_subscription, cluster_resou data = json.loads(r.text) dc_object_array = [] for item in data['value']: - dce_id = get_dce_from_dcr(cmd, item['properties']['dataCollectionRuleId']) - dc_object_array.append({'name': item['name'], 'dataCollectionRuleId': item['properties']['dataCollectionRuleId'], 'dceId': dce_id}) + if 'properties' in item and 'dataCollectionRuleId' in item['properties']: + dce_id = get_dce_from_dcr(cmd, item['properties']['dataCollectionRuleId']) + dc_object_array.append({'name': item['name'], 'dataCollectionRuleId': item['properties']['dataCollectionRuleId'], 'dceId': dce_id}) return dc_object_array except CLIError as e: error = e diff --git a/src/azure-cli/azure/cli/command_modules/acs/managed_cluster_decorator.py b/src/azure-cli/azure/cli/command_modules/acs/managed_cluster_decorator.py index b04b6e19a71..d667908713b 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/managed_cluster_decorator.py +++ b/src/azure-cli/azure/cli/command_modules/acs/managed_cluster_decorator.py @@ -7064,7 +7064,10 @@ def postprocessing_after_mc_created(self, cluster: ManagedCluster) -> None: """ # monitoring addon monitoring_addon_enabled = self.context.get_intermediate("monitoring_addon_enabled", default_value=False) - if monitoring_addon_enabled: + if ((self.context.raw_param.get("enable_addons") is not None or + self.context.raw_param.get("disable_addons") is not None) and + monitoring_addon_enabled + ): enable_msi_auth_for_monitoring = self.context.get_enable_msi_auth_for_monitoring() if not enable_msi_auth_for_monitoring: # add cluster spn/msi Monitoring Metrics Publisher role assignment to publish metrics to MDM From 9091ef7f427c1b1a61bfaa28fc37c3829ab8d001 Mon Sep 17 00:00:00 2001 From: Kaveesh Dubey Date: Tue, 25 Apr 2023 18:46:47 -0700 Subject: [PATCH 18/41] fix unit test --- .../command_modules/acs/managed_cluster_decorator.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/azure-cli/azure/cli/command_modules/acs/managed_cluster_decorator.py b/src/azure-cli/azure/cli/command_modules/acs/managed_cluster_decorator.py index d667908713b..3ccc202c146 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/managed_cluster_decorator.py +++ b/src/azure-cli/azure/cli/command_modules/acs/managed_cluster_decorator.py @@ -6018,7 +6018,7 @@ def postprocessing_after_mc_created(self, cluster: ManagedCluster) -> None: self.context.external_functions.add_monitoring_role_assignment( cluster, cluster_resource_id, self.cmd ) - else: + elif self.context.raw_param.get("enable_addons") is not None: # Create the DCR Association here addon_consts = self.context.get_addon_consts() CONST_MONITORING_ADDON_NAME = addon_consts.get("CONST_MONITORING_ADDON_NAME") @@ -7064,10 +7064,7 @@ def postprocessing_after_mc_created(self, cluster: ManagedCluster) -> None: """ # monitoring addon monitoring_addon_enabled = self.context.get_intermediate("monitoring_addon_enabled", default_value=False) - if ((self.context.raw_param.get("enable_addons") is not None or - self.context.raw_param.get("disable_addons") is not None) and - monitoring_addon_enabled - ): + if monitoring_addon_enabled: enable_msi_auth_for_monitoring = self.context.get_enable_msi_auth_for_monitoring() if not enable_msi_auth_for_monitoring: # add cluster spn/msi Monitoring Metrics Publisher role assignment to publish metrics to MDM @@ -7086,7 +7083,10 @@ def postprocessing_after_mc_created(self, cluster: ManagedCluster) -> None: self.context.external_functions.add_monitoring_role_assignment( cluster, cluster_resource_id, self.cmd ) - else: + elif ( + self.context.raw_param.get("enable_addons") is not None or + self.context.raw_param.get("disable_addons") is not None + ): # Create the DCR Association here addon_consts = self.context.get_addon_consts() CONST_MONITORING_ADDON_NAME = addon_consts.get("CONST_MONITORING_ADDON_NAME") From b71f454cc57b9855071cccb49cd48d1d12aee67a Mon Sep 17 00:00:00 2001 From: Kaveesh Dubey Date: Tue, 25 Apr 2023 19:26:49 -0700 Subject: [PATCH 19/41] test --- .../tests/latest/test_managed_cluster_decorator.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/azure-cli/azure/cli/command_modules/acs/tests/latest/test_managed_cluster_decorator.py b/src/azure-cli/azure/cli/command_modules/acs/tests/latest/test_managed_cluster_decorator.py index eb9f27d6492..88d0c045ddd 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/tests/latest/test_managed_cluster_decorator.py +++ b/src/azure-cli/azure/cli/command_modules/acs/tests/latest/test_managed_cluster_decorator.py @@ -1737,7 +1737,7 @@ def test_get_network_plugin_mode(self): DecoratorMode.CREATE, ) self.assertEqual(ctx_3.get_network_plugin_mode(), "overlay") - + def test_get_network_plugin(self): # default ctx_1 = AKSManagedClusterContext( @@ -2174,7 +2174,7 @@ def test_get_enable_addons(self): # fail on aci_subnet_name/vnet_subnet_id not specified with self.assertRaises(RequiredArgumentMissingError): ctx_6.get_enable_addons() - + def test_get_http_proxy_config(self): # default ctx_1 = AKSManagedClusterContext( @@ -7226,7 +7226,8 @@ def test_postprocessing_after_mc_created(self): dec_2 = AKSManagedClusterCreateDecorator( self.cmd, self.client, - {"resource_group_name": "test_rg_name", "name": "test_name", "enable_msi_auth_for_monitoring": True}, + {"resource_group_name": "test_rg_name", "name": "test_name", "enable_msi_auth_for_monitoring": True, + "enable_addons": "monitoring"}, ResourceType.MGMT_CONTAINERSERVICE, ) monitoring_addon_profile_2 = self.models.ManagedClusterAddonProfile( @@ -7377,7 +7378,7 @@ def test_create_mc(self): return_value=mc_1, ): self.assertEqual(dec_1.create_mc(mc_1), mc_1) - + def test_set_up_http_proxy_config(self): dec_1 = AKSManagedClusterCreateDecorator( self.cmd, @@ -9706,7 +9707,8 @@ def test_postprocessing_after_mc_created(self): dec_2 = AKSManagedClusterUpdateDecorator( self.cmd, self.client, - {"resource_group_name": "test_rg_name", "name": "test_name", "enable_msi_auth_for_monitoring": True}, + {"resource_group_name": "test_rg_name", "name": "test_name", "enable_msi_auth_for_monitoring": True, + "enable_addons": "monitoring"g}, ResourceType.MGMT_CONTAINERSERVICE, ) monitoring_addon_profile_2 = self.models.ManagedClusterAddonProfile( From 411fe13ea6399ce49a4d415ba9a148db110297ab Mon Sep 17 00:00:00 2001 From: Kaveesh Dubey Date: Wed, 26 Apr 2023 09:54:30 -0700 Subject: [PATCH 20/41] proper format --- .../latest/test_managed_cluster_decorator.py | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/azure-cli/azure/cli/command_modules/acs/tests/latest/test_managed_cluster_decorator.py b/src/azure-cli/azure/cli/command_modules/acs/tests/latest/test_managed_cluster_decorator.py index 88d0c045ddd..81252e90974 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/tests/latest/test_managed_cluster_decorator.py +++ b/src/azure-cli/azure/cli/command_modules/acs/tests/latest/test_managed_cluster_decorator.py @@ -7226,8 +7226,12 @@ def test_postprocessing_after_mc_created(self): dec_2 = AKSManagedClusterCreateDecorator( self.cmd, self.client, - {"resource_group_name": "test_rg_name", "name": "test_name", "enable_msi_auth_for_monitoring": True, - "enable_addons": "monitoring"}, + { + "resource_group_name": "test_rg_name", + "name": "test_name", + "enable_msi_auth_for_monitoring": True, + "enable_addons": "monitoring" + }, ResourceType.MGMT_CONTAINERSERVICE, ) monitoring_addon_profile_2 = self.models.ManagedClusterAddonProfile( @@ -9707,8 +9711,12 @@ def test_postprocessing_after_mc_created(self): dec_2 = AKSManagedClusterUpdateDecorator( self.cmd, self.client, - {"resource_group_name": "test_rg_name", "name": "test_name", "enable_msi_auth_for_monitoring": True, - "enable_addons": "monitoring"g}, + { + "resource_group_name": "test_rg_name", + "name": "test_name", + "enable_msi_auth_for_monitoring": True, + "enable_addons": "monitoring" + }, ResourceType.MGMT_CONTAINERSERVICE, ) monitoring_addon_profile_2 = self.models.ManagedClusterAddonProfile( From a860239023c94e01e652f1edd7b704b5aa9f0176 Mon Sep 17 00:00:00 2001 From: Kaveesh Dubey Date: Wed, 26 Apr 2023 11:12:29 -0700 Subject: [PATCH 21/41] styling error --- .../acs/azuremonitormetrics/azuremonitorprofile.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/azuremonitorprofile.py b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/azuremonitorprofile.py index 6853ee9d563..ec3f46d72c3 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/azuremonitorprofile.py +++ b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/azuremonitorprofile.py @@ -61,8 +61,8 @@ def ensure_azure_monitor_profile_prerequisites( if cloud_name.lower() == "azureusgovernment": grafana_resource_id = raw_parameters.get("grafana_resource_id") if grafana_resource_id is not None: - if grafana_resource_id != "": - raise InvalidArgumentValueError("Azure US Government cloud does not support Azure Managed Grarfana yet. Please follow this documenation for enabling it via the public cloud : aka.ms/ama-grafana-link-ff") + if grafana_resource_id != "": + raise InvalidArgumentValueError("Azure US Government cloud does not support Azure Managed Grarfana yet. Please follow this documenation for enabling it via the public cloud : aka.ms/ama-grafana-link-ff") if (remove_azuremonitormetrics): unlink_azure_monitor_profile_artifacts( From 505edf3c14901613819a1a06944cef5502db0250 Mon Sep 17 00:00:00 2001 From: Kaveesh Dubey Date: Wed, 26 Apr 2023 15:41:41 -0700 Subject: [PATCH 22/41] add blank __init__.py files for python modules --- .../azure/cli/command_modules/acs/azuremonitormetrics/__init__.py | 0 .../cli/command_modules/acs/azuremonitormetrics/amg/__init__.py | 0 .../cli/command_modules/acs/azuremonitormetrics/amw/__init__.py | 0 .../cli/command_modules/acs/azuremonitormetrics/dc/__init__.py | 0 .../acs/azuremonitormetrics/recordingrules/__init__.py | 0 .../acs/azuremonitormetrics/responseparsers/__init__.py | 0 6 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/__init__.py create mode 100644 src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/amg/__init__.py create mode 100644 src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/amw/__init__.py create mode 100644 src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/__init__.py create mode 100644 src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/recordingrules/__init__.py create mode 100644 src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/responseparsers/__init__.py diff --git a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/__init__.py b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/amg/__init__.py b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/amg/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/amw/__init__.py b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/amw/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/__init__.py b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/recordingrules/__init__.py b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/recordingrules/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/responseparsers/__init__.py b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/responseparsers/__init__.py new file mode 100644 index 00000000000..e69de29bb2d From 711f42a9877fcabc238606a6dba7e1537f515b3d Mon Sep 17 00:00:00 2001 From: Kaveesh Dubey Date: Wed, 26 Apr 2023 17:20:11 -0700 Subject: [PATCH 23/41] style --- .../azure/cli/command_modules/acs/azuremonitormetrics/helper.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/helper.py b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/helper.py index 76a48423782..62f12875ce0 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/helper.py +++ b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/helper.py @@ -37,6 +37,7 @@ def post_request(cmd, subscription_id, rp_name, headers): raise CLIError(e) +# pylint: disable=line-too-long def rp_registrations(cmd, subscription_id): from azure.cli.core.util import send_raw_request # Get list of RP's for RP's subscription @@ -80,6 +81,7 @@ def rp_registrations(cmd, subscription_id): post_request(cmd, subscription_id, "microsoft.dashboard", headers) +# pylint: disable=line-too-long def check_azuremonitormetrics_profile(cmd, cluster_subscription, cluster_resource_group_name, cluster_name): from azure.cli.core.util import send_raw_request armendpoint = cmd.cli_ctx.cloud.endpoints.resource_manager From d8e98114dd93707713777af8f15b1c819a235111 Mon Sep 17 00:00:00 2001 From: Kaveesh Dubey Date: Wed, 26 Apr 2023 17:31:20 -0700 Subject: [PATCH 24/41] remove preview tag from commands --- .../azure/cli/command_modules/acs/_params.py | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/azure-cli/azure/cli/command_modules/acs/_params.py b/src/azure-cli/azure/cli/command_modules/acs/_params.py index a7983be6858..243fbdabb6f 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/_params.py +++ b/src/azure-cli/azure/cli/command_modules/acs/_params.py @@ -284,12 +284,12 @@ def load_arguments(self, _): c.argument('host_group_id', validator=validate_host_group_id) c.argument('gpu_instance_profile', arg_type=get_enum_type(gpu_instance_profiles)) # azure monitor profile - c.argument('enable_azuremonitormetrics', action='store_true', is_preview=True) - c.argument('azure_monitor_workspace_resource_id', validator=validate_azuremonitorworkspaceresourceid, is_preview=True) - c.argument('ksm_metric_labels_allow_list', is_preview=True) - c.argument('ksm_metric_annotations_allow_list', is_preview=True) - c.argument('grafana_resource_id', validator=validate_grafanaresourceid, is_preview=True) - c.argument('enable_windows_recording_rules', action='store_true', is_preview=True) + c.argument('enable_azuremonitormetrics', action='store_true') + c.argument('azure_monitor_workspace_resource_id', validator=validate_azuremonitorworkspaceresourceid) + c.argument('ksm_metric_labels_allow_list') + c.argument('ksm_metric_annotations_allow_list') + c.argument('grafana_resource_id', validator=validate_grafanaresourceid) + c.argument('enable_windows_recording_rules', action='store_true') # misc c.argument('yes', options_list=['--yes', '-y'], help='Do not prompt for confirmation.', action='store_true') @@ -371,13 +371,13 @@ def load_arguments(self, _): c.argument('nodepool_labels', nargs='*', validator=validate_nodepool_labels, help='space-separated labels: key[=value] [key[=value] ...]. See https://aka.ms/node-labels for syntax of labels.') # azure monitor profile - c.argument('enable_azuremonitormetrics', action='store_true', is_preview=True) - c.argument('azure_monitor_workspace_resource_id', validator=validate_azuremonitorworkspaceresourceid, is_preview=True) - c.argument('ksm_metric_labels_allow_list', is_preview=True) - c.argument('ksm_metric_annotations_allow_list', is_preview=True) - c.argument('grafana_resource_id', validator=validate_grafanaresourceid, is_preview=True) - c.argument('enable_windows_recording_rules', action='store_true', is_preview=True) - c.argument('disable_azuremonitormetrics', action='store_true', is_preview=True) + c.argument('enable_azuremonitormetrics', action='store_true') + c.argument('azure_monitor_workspace_resource_id', validator=validate_azuremonitorworkspaceresourceid) + c.argument('ksm_metric_labels_allow_list') + c.argument('ksm_metric_annotations_allow_list') + c.argument('grafana_resource_id', validator=validate_grafanaresourceid) + c.argument('enable_windows_recording_rules', action='store_true') + c.argument('disable_azuremonitormetrics', action='store_true') # misc c.argument('yes', options_list=['--yes', '-y'], help='Do not prompt for confirmation.', action='store_true') From 4b360c6c936745a9ae95c785f981cf8963f14682 Mon Sep 17 00:00:00 2001 From: Kaveesh Dubey Date: Wed, 26 Apr 2023 19:51:02 -0700 Subject: [PATCH 25/41] so much styling --- .../acs/azuremonitormetrics/addonput.py | 4 +- .../acs/azuremonitormetrics/amg/link.py | 15 +++++-- .../acs/azuremonitormetrics/amw/create.py | 10 ++++- .../acs/azuremonitormetrics/amw/defaults.py | 4 +- .../acs/azuremonitormetrics/amw/helper.py | 11 +++--- .../azuremonitorprofile.py | 36 +++++++++++------ .../acs/azuremonitormetrics/constants.py | 6 +-- .../acs/azuremonitormetrics/dc/dce_api.py | 4 +- .../acs/azuremonitormetrics/dc/dcr_api.py | 2 +- .../acs/azuremonitormetrics/dc/dcra_api.py | 29 ++++++++------ .../acs/azuremonitormetrics/dc/defaults.py | 10 ++--- .../acs/azuremonitormetrics/dc/delete.py | 16 ++++---- .../recordingrules/create.py | 3 ++ .../recordingrules/delete.py | 39 ++++++++++++++----- .../amwlocationresponseparser.py | 4 +- .../acs/managed_cluster_decorator.py | 2 - 16 files changed, 127 insertions(+), 68 deletions(-) diff --git a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/addonput.py b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/addonput.py index f7696e399fe..95b92ce4b27 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/addonput.py +++ b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/addonput.py @@ -4,14 +4,14 @@ # -------------------------------------------------------------------------------------------- import json from azure.cli.command_modules.acs.azuremonitormetrics.constants import AKS_CLUSTER_API -from azure.cli.core.profiles import ResourceType from azure.cli.core.azclierror import ( UnknownError, CLIError ) -def addon_put(cmd, client, cluster_subscription, cluster_resource_group_name, cluster_name): +# pylint: disable=line-too-long +def addon_put(cmd, cluster_subscription, cluster_resource_group_name, cluster_name): from azure.cli.core.util import send_raw_request armendpoint = cmd.cli_ctx.cloud.endpoints.resource_manager feature_check_url = f"{armendpoint}/subscriptions/{cluster_subscription}/resourceGroups/{cluster_resource_group_name}/providers/Microsoft.ContainerService/managedClusters/{cluster_name}?api-version={AKS_CLUSTER_API}" diff --git a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/amg/link.py b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/amg/link.py index 7d29b0fc74f..3a6127b70b6 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/amg/link.py +++ b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/amg/link.py @@ -44,12 +44,19 @@ def link_grafana_instance(cmd, raw_parameters, azure_monitor_workspace_resource_ azure_monitor_workspace_resource_id, MonitoringDataReader ) - association_body = json.dumps({"properties": {"roleDefinitionId": roleDefinitionId, "principalId": servicePrincipalId}}) + association_body = json.dumps({ + "properties": { + "roleDefinitionId": roleDefinitionId, + "principalId": servicePrincipalId + } + }) headers = ['User-Agent=azuremonitormetrics.add_role_assignment'] send_raw_request(cmd.cli_ctx, "PUT", roleDefinitionURI, body=association_body, headers=headers) except CLIError as e: if e.response.status_code != 409: - erroString = "Role Assingment failed. Please manually assign the `Monitoring Data Reader` role to the Azure Monitor Workspace ({0}) for the Azure Managed Grafana System Assigned Managed Identity ({1})".format( + erroString = "Role Assingment failed. Please manually assign the `Monitoring Data Reader` role\ + to the Azure Monitor Workspace ({0}) for the Azure Managed Grafana\ + System Assigned Managed Identity ({1})".format( azure_monitor_workspace_resource_id, servicePrincipalId ) @@ -71,7 +78,9 @@ def link_grafana_instance(cmd, raw_parameters, azure_monitor_workspace_resource_ grafana_resource_id, GRAFANA_API ) - targetGrafanaArmPayload["properties"]["grafanaIntegrations"]["azureMonitorWorkspaceIntegrations"].append({"azureMonitorWorkspaceResourceId": azure_monitor_workspace_resource_id}) + targetGrafanaArmPayload["properties"]["grafanaIntegrations"]["azureMonitorWorkspaceIntegrations"].append({ + "azureMonitorWorkspaceResourceId": azure_monitor_workspace_resource_id + }) targetGrafanaArmPayload = json.dumps(targetGrafanaArmPayload) headers = ['User-Agent=azuremonitormetrics.setup_amw_grafana_integration', 'Content-Type=application/json'] send_raw_request(cmd.cli_ctx, "PUT", grafanaURI, body=targetGrafanaArmPayload, headers=headers) diff --git a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/amw/create.py b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/amw/create.py index 93324c8a739..c8bac89251c 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/amw/create.py +++ b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/amw/create.py @@ -5,17 +5,23 @@ import json from azure.cli.command_modules.acs.azuremonitormetrics.constants import MAC_API +from azure.cli.command_modules.acs.azuremonitormetrics.amw.defaults import get_default_mac_name_and_region from azure.cli.command_modules.acs._client_factory import get_resource_groups_client, get_resources_client from azure.core.exceptions import HttpResponseError from knack.util import CLIError -from azure.cli.command_modules.acs.azuremonitormetrics.amw.defaults import get_default_mac_name_and_region def create_default_mac(cmd, cluster_subscription, cluster_region): from azure.cli.core.util import send_raw_request default_mac_name, default_mac_region = get_default_mac_name_and_region(cmd, cluster_region) default_resource_group_name = "DefaultResourceGroup-{0}".format(default_mac_region) - azure_monitor_workspace_resource_id = "/subscriptions/{0}/resourceGroups/{1}/providers/microsoft.monitor/accounts/{2}".format(cluster_subscription, default_resource_group_name, default_mac_name) + azure_monitor_workspace_resource_id = \ + "/subscriptions/{0}/resourceGroups/{1}/providers/microsoft.monitor/accounts/{2}"\ + .format( + cluster_subscription, + default_resource_group_name, + default_mac_name + ) # Check if default resource group exists or not, if it does not then create it resource_groups = get_resource_groups_client(cmd.cli_ctx, cluster_subscription) resources = get_resources_client(cmd.cli_ctx, cluster_subscription) diff --git a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/amw/defaults.py b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/amw/defaults.py index 820f799caa6..88832f87dbd 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/amw/defaults.py +++ b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/amw/defaults.py @@ -4,7 +4,9 @@ # -------------------------------------------------------------------------------------------- import json from azure.cli.command_modules.acs.azuremonitormetrics.deaults import get_default_region -from azure.cli.command_modules.acs.azuremonitormetrics.responseparsers.amwlocationresponseparser import parseResourceProviderResponseForLocations +from azure.cli.command_modules.acs.azuremonitormetrics.responseparsers.amwlocationresponseparser import ( + parseResourceProviderResponseForLocations +) from azure.cli.command_modules.acs.azuremonitormetrics.constants import RP_LOCATION_API from knack.util import CLIError diff --git a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/amw/helper.py b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/amw/helper.py index b6f54a31f59..4738dace719 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/amw/helper.py +++ b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/amw/helper.py @@ -2,14 +2,11 @@ # Copyright (c) Microsoft Corporation. All rights reserved. # Licensed under the MIT License. See License.txt in the project root for license information. # -------------------------------------------------------------------------------------------- -import json from azure.cli.command_modules.acs.azuremonitormetrics.amw.create import create_default_mac from azure.cli.command_modules.acs.azuremonitormetrics.constants import MAC_API from azure.cli.command_modules.acs.azuremonitormetrics.helper import sanitize_resource_id -from azure.cli.core.azclierror import ClientRequestError -from azure.core.exceptions import HttpResponseError from azure.cli.command_modules.acs._client_factory import get_resources_client -from knack.util import CLIError +from azure.core.exceptions import HttpResponseError def get_amw_region(cmd, azure_monitor_workspace_resource_id): @@ -27,7 +24,11 @@ def get_amw_region(cmd, azure_monitor_workspace_resource_id): def get_azure_monitor_workspace_resource(cmd, cluster_subscription, cluster_region, raw_parameters): azure_monitor_workspace_resource_id = raw_parameters.get("azure_monitor_workspace_resource_id") if azure_monitor_workspace_resource_id is None or azure_monitor_workspace_resource_id == "": - azure_monitor_workspace_resource_id, azure_monitor_workspace_location = create_default_mac(cmd, cluster_subscription, cluster_region) + azure_monitor_workspace_resource_id, azure_monitor_workspace_location = create_default_mac( + cmd, + cluster_subscription, + cluster_region + ) else: azure_monitor_workspace_resource_id = sanitize_resource_id(azure_monitor_workspace_resource_id) azure_monitor_workspace_location = get_amw_region(cmd, azure_monitor_workspace_resource_id) diff --git a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/azuremonitorprofile.py b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/azuremonitorprofile.py index ec3f46d72c3..8865827f270 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/azuremonitorprofile.py +++ b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/azuremonitorprofile.py @@ -8,15 +8,30 @@ from azure.cli.command_modules.acs.azuremonitormetrics.dc.dce_api import create_dce from azure.cli.command_modules.acs.azuremonitormetrics.dc.dcr_api import create_dcr from azure.cli.command_modules.acs.azuremonitormetrics.dc.dcra_api import create_dcra -from azure.cli.command_modules.acs.azuremonitormetrics.dc.delete import delete_dc_objects_if_prometheus_enabled, get_dc_objects_list -from azure.cli.command_modules.acs.azuremonitormetrics.helper import check_azuremonitormetrics_profile, rp_registrations +from azure.cli.command_modules.acs.azuremonitormetrics.dc.delete import ( + delete_dc_objects_if_prometheus_enabled, + get_dc_objects_list +) +from azure.cli.command_modules.acs.azuremonitormetrics.helper import ( + check_azuremonitormetrics_profile, + rp_registrations +) from azure.cli.command_modules.acs.azuremonitormetrics.recordingrules.create import create_rules from azure.cli.command_modules.acs.azuremonitormetrics.recordingrules.delete import delete_rules -from knack.util import CLIError from azure.cli.core.azclierror import InvalidArgumentValueError +from knack.util import CLIError -def link_azure_monitor_profile_artifacts(cmd, client, cluster_subscription, cluster_resource_group_name, cluster_name, cluster_region, raw_parameters, create_flow): +# pylint: disable=line-too-long +def link_azure_monitor_profile_artifacts( + cmd, + cluster_subscription, + cluster_resource_group_name, + cluster_name, + cluster_region, + raw_parameters, + create_flow +): # MAC creation if required azure_monitor_workspace_resource_id, azure_monitor_workspace_location = get_azure_monitor_workspace_resource(cmd, cluster_subscription, cluster_region, raw_parameters) # DCE creation @@ -31,21 +46,22 @@ def link_azure_monitor_profile_artifacts(cmd, client, cluster_subscription, clus create_rules(cmd, cluster_subscription, cluster_resource_group_name, cluster_name, azure_monitor_workspace_resource_id, azure_monitor_workspace_location, raw_parameters) # if aks cluster create flow -> do a PUT on the AKS cluster to enable the addon if create_flow: - addon_put(cmd, client, cluster_subscription, cluster_resource_group_name, cluster_name) + addon_put(cmd, cluster_subscription, cluster_resource_group_name, cluster_name) -def unlink_azure_monitor_profile_artifacts(cmd, cluster_subscription, cluster_resource_group_name, cluster_name, cluster_region): +# pylint: disable=line-too-long +def unlink_azure_monitor_profile_artifacts(cmd, cluster_subscription, cluster_resource_group_name, cluster_name): # Remove DC* if prometheus is enabled dc_objects_list = get_dc_objects_list(cmd, cluster_subscription, cluster_resource_group_name, cluster_name) delete_dc_objects_if_prometheus_enabled(cmd, dc_objects_list, cluster_subscription, cluster_resource_group_name, cluster_name) - # Delete rules (Conflict({"error":{"code":"InvalidResourceLocation","message":"The resource 'NodeRecordingRulesRuleGroup-' already exists in location 'eastus2' in resource group ''. A resource with the same name cannot be created in location 'eastus'. Please select a new resource name."}}) + # Delete rules (Conflict({"error":{"code":"InvalidResourceLocation","message":"The resource 'NodeRecordingRulesRuleGroup-' already exists in location 'eastus2' in resource group ''. + # A resource with the same name cannot be created in location 'eastus'. Please select a new resource name."}}) delete_rules(cmd, cluster_subscription, cluster_resource_group_name, cluster_name) # pylint: disable=too-many-locals,too-many-branches,too-many-statements,line-too-long def ensure_azure_monitor_profile_prerequisites( cmd, - client, cluster_subscription, cluster_resource_group_name, cluster_name, @@ -64,7 +80,7 @@ def ensure_azure_monitor_profile_prerequisites( if grafana_resource_id != "": raise InvalidArgumentValueError("Azure US Government cloud does not support Azure Managed Grarfana yet. Please follow this documenation for enabling it via the public cloud : aka.ms/ama-grafana-link-ff") - if (remove_azuremonitormetrics): + if remove_azuremonitormetrics: unlink_azure_monitor_profile_artifacts( cmd, cluster_subscription, @@ -80,7 +96,6 @@ def ensure_azure_monitor_profile_prerequisites( rp_registrations(cmd, cluster_subscription) link_azure_monitor_profile_artifacts( cmd, - client, cluster_subscription, cluster_resource_group_name, cluster_name, @@ -88,4 +103,3 @@ def ensure_azure_monitor_profile_prerequisites( raw_parameters, create_flow ) - return diff --git a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/constants.py b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/constants.py index ca5e49a7d8a..9c39a8d2aa4 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/constants.py +++ b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/constants.py @@ -2,9 +2,7 @@ # Copyright (c) Microsoft Corporation. All rights reserved. # Licensed under the MIT License. See License.txt in the project root for license information. # -------------------------------------------------------------------------------------------- -from azure.core import CaseInsensitiveEnumMeta from enum import Enum -from six import with_metaclass AKS_CLUSTER_API = "2023-01-01" MAC_API = "2023-04-03" @@ -70,7 +68,7 @@ } -class GrafanaLink(with_metaclass(CaseInsensitiveEnumMeta, str, Enum)): +class GrafanaLink(Enum): """ Status of Grafana link to the Prometheus Addon """ @@ -80,7 +78,7 @@ class GrafanaLink(with_metaclass(CaseInsensitiveEnumMeta, str, Enum)): NOPARAMPROVIDED = "NOPARAMPROVIDED" -class DC_TYPE(with_metaclass(CaseInsensitiveEnumMeta, str, Enum)): +class DC_TYPE(Enum): """ Types of DC* objects """ diff --git a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/dce_api.py b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/dce_api.py index 00fb2484bde..59f7d0b2be0 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/dce_api.py +++ b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/dce_api.py @@ -5,14 +5,14 @@ import json from azure.cli.command_modules.acs.azuremonitormetrics.constants import DC_API from azure.cli.command_modules.acs.azuremonitormetrics.dc.defaults import get_default_dce_name -from azure.cli.command_modules.acs.azuremonitormetrics.constants import DC_API from knack.util import CLIError def create_dce(cmd, cluster_subscription, cluster_resource_group_name, cluster_name, mac_region): from azure.cli.core.util import send_raw_request dce_name = get_default_dce_name(cmd, mac_region, cluster_name) - dce_resource_id = "/subscriptions/{0}/resourceGroups/{1}/providers/Microsoft.Insights/dataCollectionEndpoints/{2}".format(cluster_subscription, cluster_resource_group_name, dce_name) + dce_resource_id = "/subscriptions/{0}/resourceGroups/{1}/providers/Microsoft.Insights/dataCollectionEndpoints/{2}"\ + .format(cluster_subscription, cluster_resource_group_name, dce_name) try: armendpoint = cmd.cli_ctx.cloud.endpoints.resource_manager dce_url = f"{armendpoint}{dce_resource_id}?api-version={DC_API}" diff --git a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/dcr_api.py b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/dcr_api.py index e9dc6a12159..c6f1975a1f4 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/dcr_api.py +++ b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/dcr_api.py @@ -14,7 +14,7 @@ def get_default_dcr_name(cmd, mac_region, cluster_name): region = get_default_region(cmd) - if mac_region in MapToClosestMACRegion: + if dict.get(MapToClosestMACRegion, mac_region): region = MapToClosestMACRegion[mac_region] default_dcr_name = "MSProm-" + region + "-" + cluster_name return sanitize_name(default_dcr_name, DC_TYPE.DCR, 64) diff --git a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/dcra_api.py b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/dcra_api.py index c50fea6eb2f..c9648431ebc 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/dcra_api.py +++ b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/dcra_api.py @@ -10,25 +10,30 @@ def create_dcra(cmd, cluster_region, cluster_subscription, cluster_resource_group_name, cluster_name, dcr_resource_id): from azure.cli.core.util import send_raw_request - cluster_resource_id = "/subscriptions/{0}/resourceGroups/{1}/providers/Microsoft.ContainerService/managedClusters/{2}".format( - cluster_subscription, - cluster_resource_group_name, - cluster_name - ) + cluster_resource_id = \ + "/subscriptions/{0}/resourceGroups/{1}/providers/Microsoft.ContainerService/managedClusters/{2}".format( + cluster_subscription, + cluster_resource_group_name, + cluster_name + ) dcra_name = get_default_dcra_name(cmd, cluster_region, cluster_name) - dcra_resource_id = "/subscriptions/{0}/resourceGroups/{1}/providers/Microsoft.Insights/dataCollectionRuleAssociations/{2}".format( - cluster_subscription, - cluster_resource_group_name, - dcra_name - ) + dcra_resource_id = \ + "/subscriptions/{0}/resourceGroups/{1}/providers/Microsoft.Insights/dataCollectionRuleAssociations/{2}"\ + .format( + cluster_subscription, + cluster_resource_group_name, + dcra_name + ) + description_str = "Promtheus data collection association between DCR, DCE and target AKS resource" # only create or delete the association between the DCR and cluster association_body = json.dumps({"location": cluster_region, "properties": { "dataCollectionRuleId": dcr_resource_id, - "description": "Promtheus data collection association between DCR, DCE and target AKS resource" + "description": description_str }}) armendpoint = cmd.cli_ctx.cloud.endpoints.resource_manager - association_url = f"{armendpoint}{cluster_resource_id}/providers/Microsoft.Insights/dataCollectionRuleAssociations/{dcra_name}?api-version={DC_API}" + association_url = f"{armendpoint}{cluster_resource_id}\ + /providers/Microsoft.Insights/dataCollectionRuleAssociations/{dcra_name}?api-version={DC_API}" try: headers = ['User-Agent=azuremonitormetrics.create_dcra'] send_raw_request(cmd.cli_ctx, "PUT", association_url, diff --git a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/defaults.py b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/defaults.py index 6885ab3d374..4a2007fd185 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/defaults.py +++ b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/defaults.py @@ -12,22 +12,22 @@ # DCR = 64, DCE = 44, DCRA = 64 # All DC* object names should end only in alpha numeric (after `length` trim) # DCE remove underscore from cluster name -def sanitize_name(name, type, length): +def sanitize_name(name, objtype, length): length = length - 1 - if type == DC_TYPE.DCE: + if objtype == DC_TYPE.DCE: name = name.replace("_", "") name = name[0:length] lastIndexAlphaNumeric = len(name) - 1 while ((name[lastIndexAlphaNumeric].isalnum() is False) and lastIndexAlphaNumeric > -1): lastIndexAlphaNumeric = lastIndexAlphaNumeric - 1 - if (lastIndexAlphaNumeric < 0): + if lastIndexAlphaNumeric < 0: return "" return name[0:lastIndexAlphaNumeric + 1] def get_default_dce_name(cmd, mac_region, cluster_name): region = get_default_region(cmd) - if mac_region in MapToClosestMACRegion: + if dict.get(MapToClosestMACRegion, mac_region): region = MapToClosestMACRegion[mac_region] default_dce_name = "MSProm-" + region + "-" + cluster_name return sanitize_name(default_dce_name, DC_TYPE.DCE, 44) @@ -35,7 +35,7 @@ def get_default_dce_name(cmd, mac_region, cluster_name): def get_default_dcra_name(cmd, cluster_region, cluster_name): region = get_default_region(cmd) - if cluster_region in MapToClosestMACRegion: + if dict.get(MapToClosestMACRegion, cluster_region): region = MapToClosestMACRegion[cluster_region] default_dcra_name = "ContainerInsightsMetricsExtension-" + region + "-" + cluster_name return sanitize_name(default_dcra_name, DC_TYPE.DCRA, 64) diff --git a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/delete.py b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/delete.py index 11a2bed0f7f..48566bae071 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/delete.py +++ b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/delete.py @@ -16,18 +16,19 @@ def get_dce_from_dcr(cmd, dcrId): data = json.loads(r.text) if 'dataCollectionEndpointId' in data['properties']: return str(data['properties']['dataCollectionEndpointId']) - else: - return "" + return "" +# pylint: disable=line-too-long def get_dc_objects_list(cmd, cluster_subscription, cluster_resource_group_name, cluster_name): try: from azure.cli.core.util import send_raw_request - cluster_resource_id = "/subscriptions/{0}/resourceGroups/{1}/providers/Microsoft.ContainerService/managedClusters/{2}".format( - cluster_subscription, - cluster_resource_group_name, - cluster_name - ) + cluster_resource_id = \ + "/subscriptions/{0}/resourceGroups/{1}/providers/Microsoft.ContainerService/managedClusters/{2}".format( + cluster_subscription, + cluster_resource_group_name, + cluster_name + ) armendpoint = cmd.cli_ctx.cloud.endpoints.resource_manager association_url = f"{armendpoint}{cluster_resource_id}/providers/Microsoft.Insights/dataCollectionRuleAssociations?api-version={DC_API}" headers = ['User-Agent=azuremonitormetrics.get_dcra'] @@ -44,6 +45,7 @@ def get_dc_objects_list(cmd, cluster_subscription, cluster_resource_group_name, raise CLIError(error) +# pylint: disable=line-too-long def delete_dc_objects_if_prometheus_enabled(cmd, dc_objects_list, cluster_subscription, cluster_resource_group_name, cluster_name): from azure.cli.core.util import send_raw_request cluster_resource_id = "/subscriptions/{0}/resourceGroups/{1}/providers/Microsoft.ContainerService/managedClusters/{2}".format( diff --git a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/recordingrules/create.py b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/recordingrules/create.py index 5765e250404..9aa88be1011 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/recordingrules/create.py +++ b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/recordingrules/create.py @@ -7,6 +7,7 @@ from knack.util import CLIError +# pylint: disable=line-too-long def get_recording_rules_template(cmd, azure_monitor_workspace_resource_id): from azure.cli.core.util import send_raw_request headers = ['User-Agent=azuremonitormetrics.get_recording_rules_template'] @@ -17,6 +18,7 @@ def get_recording_rules_template(cmd, azure_monitor_workspace_resource_id): return data['value'] +# pylint: disable=line-too-long def put_rules(cmd, default_rule_group_id, default_rule_group_name, mac_region, azure_monitor_workspace_resource_id, cluster_name, default_rules_template, url, i): from azure.cli.core.util import send_raw_request body = json.dumps({ @@ -46,6 +48,7 @@ def put_rules(cmd, default_rule_group_id, default_rule_group_name, mac_region, a raise error +# pylint: disable=line-too-long def create_rules(cmd, cluster_subscription, cluster_resource_group_name, cluster_name, azure_monitor_workspace_resource_id, mac_region, raw_parameters): # with urllib.request.urlopen("https://defaultrulessc.blob.core.windows.net/defaultrules/ManagedPrometheusDefaultRecordingRules.json") as url: # default_rules_template = json.loads(url.read().decode()) diff --git a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/recordingrules/delete.py b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/recordingrules/delete.py index befd4eba61e..e0552e867e2 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/recordingrules/delete.py +++ b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/recordingrules/delete.py @@ -7,11 +7,12 @@ def delete_rule(cmd, cluster_subscription, cluster_resource_group_name, default_rule_group_name): from azure.cli.core.util import send_raw_request - default_rule_group_id = "/subscriptions/{0}/resourceGroups/{1}/providers/Microsoft.AlertsManagement/prometheusRuleGroups/{2}".format( - cluster_subscription, - cluster_resource_group_name, - default_rule_group_name - ) + default_rule_group_id = \ + "/subscriptions/{0}/resourceGroups/{1}/providers/Microsoft.AlertsManagement/prometheusRuleGroups/{2}".format( + cluster_subscription, + cluster_resource_group_name, + default_rule_group_name + ) headers = ['User-Agent=azuremonitormetrics.delete_rule.' + default_rule_group_name] url = "{0}{1}?api-version={2}".format( cmd.cli_ctx.cloud.endpoints.resource_manager, @@ -22,7 +23,27 @@ def delete_rule(cmd, cluster_subscription, cluster_resource_group_name, default_ def delete_rules(cmd, cluster_subscription, cluster_resource_group_name, cluster_name): - delete_rule(cmd, cluster_subscription, cluster_resource_group_name, "NodeRecordingRulesRuleGroup-{0}".format(cluster_name)) - delete_rule(cmd, cluster_subscription, cluster_resource_group_name, "KubernetesRecordingRulesRuleGroup-{0}".format(cluster_name)) - delete_rule(cmd, cluster_subscription, cluster_resource_group_name, "NodeRecordingRulesRuleGroup-Win-{0}".format(cluster_name)) - delete_rule(cmd, cluster_subscription, cluster_resource_group_name, "NodeAndKubernetesRecordingRulesRuleGroup-Win-{0}".format(cluster_name)) + delete_rule( + cmd, + cluster_subscription, + cluster_resource_group_name, + "NodeRecordingRulesRuleGroup-{0}".format(cluster_name) + ) + delete_rule( + cmd, + cluster_subscription, + cluster_resource_group_name, + "KubernetesRecordingRulesRuleGroup-{0}".format(cluster_name) + ) + delete_rule( + cmd, + cluster_subscription, + cluster_resource_group_name, + "NodeRecordingRulesRuleGroup-Win-{0}".format(cluster_name) + ) + delete_rule( + cmd, + cluster_subscription, + cluster_resource_group_name, + "NodeAndKubernetesRecordingRulesRuleGroup-Win-{0}".format(cluster_name) + ) diff --git a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/responseparsers/amwlocationresponseparser.py b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/responseparsers/amwlocationresponseparser.py index 0485fe9160f..ab0fbe9df8e 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/responseparsers/amwlocationresponseparser.py +++ b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/responseparsers/amwlocationresponseparser.py @@ -17,9 +17,9 @@ def parseResourceProviderResponseForLocations(resourceProviderResponse): def parseLocations(locations: List[str]) -> List[str]: - if not locations or not len(locations): + if not locations or len(locations) == 0: return [] - return list(map(lambda location: reduceLocation(location), locations)) + return [reduceLocation(location) for location in locations] def reduceLocation(location: str) -> str: diff --git a/src/azure-cli/azure/cli/command_modules/acs/managed_cluster_decorator.py b/src/azure-cli/azure/cli/command_modules/acs/managed_cluster_decorator.py index 5eb22200876..709d739e3b0 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/managed_cluster_decorator.py +++ b/src/azure-cli/azure/cli/command_modules/acs/managed_cluster_decorator.py @@ -6082,7 +6082,6 @@ def postprocessing_after_mc_created(self, cluster: ManagedCluster) -> None: # Create the DC* objects, AMW, recording rules and grafana link here self.context.external_functions.ensure_azure_monitor_profile_prerequisites( self.cmd, - self.client, self.context.get_subscription_id(), self.context.get_resource_group_name(), self.context.get_name(), @@ -6991,7 +6990,6 @@ def update_azure_monitor_profile(self, mc: ManagedCluster) -> ManagedCluster: ): self.context.external_functions.ensure_azure_monitor_profile_prerequisites( self.cmd, - self.client, self.context.get_subscription_id(), self.context.get_resource_group_name(), self.context.get_name(), From 9e8862de54ff333e2fe9f457da7ab47b1516611d Mon Sep 17 00:00:00 2001 From: Kaveesh Dubey Date: Thu, 27 Apr 2023 11:19:11 -0700 Subject: [PATCH 26/41] . --- .../command_modules/acs/azuremonitormetrics/dc/dcra_api.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/dcra_api.py b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/dcra_api.py index c9648431ebc..daddb2cc589 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/dcra_api.py +++ b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/dc/dcra_api.py @@ -8,6 +8,7 @@ from knack.util import CLIError +# pylint: disable=line-too-long def create_dcra(cmd, cluster_region, cluster_subscription, cluster_resource_group_name, cluster_name, dcr_resource_id): from azure.cli.core.util import send_raw_request cluster_resource_id = \ @@ -32,8 +33,7 @@ def create_dcra(cmd, cluster_region, cluster_subscription, cluster_resource_grou "description": description_str }}) armendpoint = cmd.cli_ctx.cloud.endpoints.resource_manager - association_url = f"{armendpoint}{cluster_resource_id}\ - /providers/Microsoft.Insights/dataCollectionRuleAssociations/{dcra_name}?api-version={DC_API}" + association_url = f"{armendpoint}{cluster_resource_id}/providers/Microsoft.Insights/dataCollectionRuleAssociations/{dcra_name}?api-version={DC_API}" try: headers = ['User-Agent=azuremonitormetrics.create_dcra'] send_raw_request(cmd.cli_ctx, "PUT", association_url, From 4e40299c41f214b8e9a3fb388f80433c43b5fd99 Mon Sep 17 00:00:00 2001 From: Kaveesh Dubey Date: Tue, 2 May 2023 10:45:55 -0700 Subject: [PATCH 27/41] text update --- .../acs/azuremonitormetrics/amw/create.py | 1 + .../recordingrules/create.py | 64 ++++++++++--------- 2 files changed, 36 insertions(+), 29 deletions(-) diff --git a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/amw/create.py b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/amw/create.py index c8bac89251c..1920d3e4581 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/amw/create.py +++ b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/amw/create.py @@ -43,6 +43,7 @@ def create_default_mac(cmd, cluster_subscription, cluster_region): headers = ['User-Agent=azuremonitormetrics.create_default_mac'] send_raw_request(cmd.cli_ctx, "PUT", association_url, body=association_body, headers=headers) + print(f"Created Azure Monitor Workspace (stores prometheus metrics) : {azure_monitor_workspace_resource_id}") return azure_monitor_workspace_resource_id, default_mac_region except CLIError as e: raise e diff --git a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/recordingrules/create.py b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/recordingrules/create.py index 9aa88be1011..6ba80fad208 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/recordingrules/create.py +++ b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/recordingrules/create.py @@ -19,7 +19,7 @@ def get_recording_rules_template(cmd, azure_monitor_workspace_resource_id): # pylint: disable=line-too-long -def put_rules(cmd, default_rule_group_id, default_rule_group_name, mac_region, azure_monitor_workspace_resource_id, cluster_name, default_rules_template, url, i): +def put_rules(cmd, default_rule_group_id, default_rule_group_name, mac_region, azure_monitor_workspace_resource_id, cluster_name, default_rules_template, url, enable_rules, i): from azure.cli.core.util import send_raw_request body = json.dumps({ "id": default_rule_group_id, @@ -30,17 +30,21 @@ def put_rules(cmd, default_rule_group_id, default_rule_group_name, mac_region, a "scopes": [ azure_monitor_workspace_resource_id ], - "enabled": True, + "enabled": enable_rules, "clusterName": cluster_name, "interval": "PT1M", "rules": default_rules_template[i]["properties"]["rulesArmTemplate"]["resources"][0]["properties"]["rules"] } }) + rule_group_text = "Disabled" + if enable_rules is True: + rule_group_text = "Enabled" for _ in range(3): try: headers = ['User-Agent=azuremonitormetrics.put_rules.' + default_rule_group_name] send_raw_request(cmd.cli_ctx, "PUT", url, body=body, headers=headers) + print(f"Created rule group ({rule_group_text}) : {default_rule_group_id}") break except CLIError as e: error = e @@ -64,7 +68,7 @@ def create_rules(cmd, cluster_subscription, cluster_resource_group_name, cluster default_rule_group_id, RULES_API ) - put_rules(cmd, default_rule_group_id, default_rule_group_name, mac_region, azure_monitor_workspace_resource_id, cluster_name, default_rules_template, url, 0) + put_rules(cmd, default_rule_group_id, default_rule_group_name, mac_region, azure_monitor_workspace_resource_id, cluster_name, default_rules_template, url, True, 0) default_rule_group_name = "KubernetesRecordingRulesRuleGroup-{0}".format(cluster_name) default_rule_group_id = "/subscriptions/{0}/resourceGroups/{1}/providers/Microsoft.AlertsManagement/prometheusRuleGroups/{2}".format( @@ -77,33 +81,35 @@ def create_rules(cmd, cluster_subscription, cluster_resource_group_name, cluster default_rule_group_id, RULES_API ) - put_rules(cmd, default_rule_group_id, default_rule_group_name, mac_region, azure_monitor_workspace_resource_id, cluster_name, default_rules_template, url, 1) + put_rules(cmd, default_rule_group_id, default_rule_group_name, mac_region, azure_monitor_workspace_resource_id, cluster_name, default_rules_template, url, True, 1) enable_windows_recording_rules = raw_parameters.get("enable_windows_recording_rules") - if enable_windows_recording_rules is True: - default_rule_group_name = "NodeRecordingRulesRuleGroup-Win-{0}".format(cluster_name) - default_rule_group_id = "/subscriptions/{0}/resourceGroups/{1}/providers/Microsoft.AlertsManagement/prometheusRuleGroups/{2}".format( - cluster_subscription, - cluster_resource_group_name, - default_rule_group_name - ) - url = "{0}{1}?api-version={2}".format( - cmd.cli_ctx.cloud.endpoints.resource_manager, - default_rule_group_id, - RULES_API - ) - put_rules(cmd, default_rule_group_id, default_rule_group_name, mac_region, azure_monitor_workspace_resource_id, cluster_name, default_rules_template, url, 2) + if enable_windows_recording_rules is not True: + enable_windows_recording_rules = False - default_rule_group_name = "NodeAndKubernetesRecordingRulesRuleGroup-Win-{0}".format(cluster_name) - default_rule_group_id = "/subscriptions/{0}/resourceGroups/{1}/providers/Microsoft.AlertsManagement/prometheusRuleGroups/{2}".format( - cluster_subscription, - cluster_resource_group_name, - default_rule_group_name - ) - url = "{0}{1}?api-version={2}".format( - cmd.cli_ctx.cloud.endpoints.resource_manager, - default_rule_group_id, - RULES_API - ) - put_rules(cmd, default_rule_group_id, default_rule_group_name, mac_region, azure_monitor_workspace_resource_id, cluster_name, default_rules_template, url, 3) + default_rule_group_name = "NodeRecordingRulesRuleGroup-Win-{0}".format(cluster_name) + default_rule_group_id = "/subscriptions/{0}/resourceGroups/{1}/providers/Microsoft.AlertsManagement/prometheusRuleGroups/{2}".format( + cluster_subscription, + cluster_resource_group_name, + default_rule_group_name + ) + url = "{0}{1}?api-version={2}".format( + cmd.cli_ctx.cloud.endpoints.resource_manager, + default_rule_group_id, + RULES_API + ) + put_rules(cmd, default_rule_group_id, default_rule_group_name, mac_region, azure_monitor_workspace_resource_id, cluster_name, default_rules_template, url, enable_windows_recording_rules, 2) + + default_rule_group_name = "NodeAndKubernetesRecordingRulesRuleGroup-Win-{0}".format(cluster_name) + default_rule_group_id = "/subscriptions/{0}/resourceGroups/{1}/providers/Microsoft.AlertsManagement/prometheusRuleGroups/{2}".format( + cluster_subscription, + cluster_resource_group_name, + default_rule_group_name + ) + url = "{0}{1}?api-version={2}".format( + cmd.cli_ctx.cloud.endpoints.resource_manager, + default_rule_group_id, + RULES_API + ) + put_rules(cmd, default_rule_group_id, default_rule_group_name, mac_region, azure_monitor_workspace_resource_id, cluster_name, default_rules_template, url, enable_windows_recording_rules, 3) From 262759e08a8ab758db668a9b7ef4dd60ed09f057 Mon Sep 17 00:00:00 2001 From: Kaveesh Dubey Date: Tue, 2 May 2023 10:49:34 -0700 Subject: [PATCH 28/41] . --- .../acs/azuremonitormetrics/azuremonitorprofile.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/azuremonitorprofile.py b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/azuremonitorprofile.py index 8865827f270..fa52b903267 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/azuremonitorprofile.py +++ b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/azuremonitorprofile.py @@ -85,8 +85,7 @@ def ensure_azure_monitor_profile_prerequisites( cmd, cluster_subscription, cluster_resource_group_name, - cluster_name, - cluster_region + cluster_name ) else: # Check if already onboarded From ffb96f0c31199344875fefcd352a1848097485ba Mon Sep 17 00:00:00 2001 From: Kaveesh Dubey Date: Tue, 2 May 2023 11:06:04 -0700 Subject: [PATCH 29/41] final changes --- .../cli/command_modules/acs/azuremonitormetrics/amw/create.py | 1 - .../cli/command_modules/acs/azuremonitormetrics/amw/helper.py | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/amw/create.py b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/amw/create.py index 1920d3e4581..c8bac89251c 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/amw/create.py +++ b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/amw/create.py @@ -43,7 +43,6 @@ def create_default_mac(cmd, cluster_subscription, cluster_region): headers = ['User-Agent=azuremonitormetrics.create_default_mac'] send_raw_request(cmd.cli_ctx, "PUT", association_url, body=association_body, headers=headers) - print(f"Created Azure Monitor Workspace (stores prometheus metrics) : {azure_monitor_workspace_resource_id}") return azure_monitor_workspace_resource_id, default_mac_region except CLIError as e: raise e diff --git a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/amw/helper.py b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/amw/helper.py index 4738dace719..b88439e1694 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/amw/helper.py +++ b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/amw/helper.py @@ -32,4 +32,5 @@ def get_azure_monitor_workspace_resource(cmd, cluster_subscription, cluster_regi else: azure_monitor_workspace_resource_id = sanitize_resource_id(azure_monitor_workspace_resource_id) azure_monitor_workspace_location = get_amw_region(cmd, azure_monitor_workspace_resource_id) + print(f"Using Azure Monitor Workspace (stores prometheus metrics) : {azure_monitor_workspace_resource_id}") return azure_monitor_workspace_resource_id, azure_monitor_workspace_location.lower() From a8b41f2e9f4fc655102bfaca9c9b04e578195110 Mon Sep 17 00:00:00 2001 From: Kaveesh Dubey Date: Fri, 5 May 2023 12:42:18 -0700 Subject: [PATCH 30/41] . --- .../cli/command_modules/acs/tests/latest/test_aks_commands.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/azure-cli/azure/cli/command_modules/acs/tests/latest/test_aks_commands.py b/src/azure-cli/azure/cli/command_modules/acs/tests/latest/test_aks_commands.py index a8230b06782..0f339d8813d 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/tests/latest/test_aks_commands.py +++ b/src/azure-cli/azure/cli/command_modules/acs/tests/latest/test_aks_commands.py @@ -6347,9 +6347,11 @@ def test_aks_create_with_azuremonitormetrics(self, resource_group, resource_grou '--enable-managed-identity', '--enable-azuremonitormetrics --enable-windows-recording-rules', '--ssh-key-value={ssh_key_value} --node-vm-size={node_vm_size}', ]) + # azuremonitor metrics will be set to false after initial creation command as its in the + # postprocessing step that we do an update to enable it. This behavior is expected. self.cmd(create_cmd, checks=[ self.check('provisioningState', 'Succeeded'), - self.check('azureMonitorProfile.metrics.enabled', True), + self.check('azureMonitorProfile.metrics.enabled', False), ]) # delete From ce9c42ec2edbcc693170e5111030cb016d5fc759 Mon Sep 17 00:00:00 2001 From: bragi92 Date: Mon, 8 May 2023 12:54:47 -0700 Subject: [PATCH 31/41] Update src/azure-cli/azure/cli/command_modules/acs/_validators.py Co-authored-by: Xing Zhou --- src/azure-cli/azure/cli/command_modules/acs/_validators.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/azure-cli/azure/cli/command_modules/acs/_validators.py b/src/azure-cli/azure/cli/command_modules/acs/_validators.py index c0b940535ec..db98f96c5b4 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/_validators.py +++ b/src/azure-cli/azure/cli/command_modules/acs/_validators.py @@ -632,7 +632,7 @@ def validate_azuremonitorworkspaceresourceid(namespace): return resource_id = sanitize_resource_id(resource_id) if (bool(re.match(r'/subscriptions/.*/resourcegroups/.*/providers/microsoft.monitor/accounts/.*', resource_id))) is False: - raise ArgumentUsageError("--azure-monitor-workspace-resource-id not in the correct format. It should match `/subscriptions//resourceGroups//providers/microsoft.monitor/accounts/`") + raise InvalidArgumentValueError("--azure-monitor-workspace-resource-id not in the correct format. It should match `/subscriptions//resourceGroups//providers/microsoft.monitor/accounts/`") # pylint:disable=line-too-long From 774649ebe0975acdc008397f1b3985ec36195aaf Mon Sep 17 00:00:00 2001 From: bragi92 Date: Mon, 8 May 2023 12:55:15 -0700 Subject: [PATCH 32/41] Update src/azure-cli/azure/cli/command_modules/acs/_validators.py Co-authored-by: Xing Zhou --- src/azure-cli/azure/cli/command_modules/acs/_validators.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/azure-cli/azure/cli/command_modules/acs/_validators.py b/src/azure-cli/azure/cli/command_modules/acs/_validators.py index db98f96c5b4..195acd68461 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/_validators.py +++ b/src/azure-cli/azure/cli/command_modules/acs/_validators.py @@ -642,4 +642,4 @@ def validate_grafanaresourceid(namespace): return resource_id = sanitize_resource_id(resource_id) if (bool(re.match(r'/subscriptions/.*/resourcegroups/.*/providers/microsoft.dashboard/grafana/.*', resource_id))) is False: - raise ArgumentUsageError("--grafana-resource-id not in the correct format. It should match `/subscriptions//resourceGroups//providers/microsoft.dashboard/grafana/`") + raise InvalidArgumentValueError("--grafana-resource-id not in the correct format. It should match `/subscriptions//resourceGroups//providers/microsoft.dashboard/grafana/`") From 963621a43496ee964b3d1bc6a7df1247862b003a Mon Sep 17 00:00:00 2001 From: Kaveesh Dubey Date: Mon, 8 May 2023 12:59:29 -0700 Subject: [PATCH 33/41] remove live only requirment --- .../cli/command_modules/acs/tests/latest/test_aks_commands.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/azure-cli/azure/cli/command_modules/acs/tests/latest/test_aks_commands.py b/src/azure-cli/azure/cli/command_modules/acs/tests/latest/test_aks_commands.py index 0f339d8813d..f6ab4bf03dc 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/tests/latest/test_aks_commands.py +++ b/src/azure-cli/azure/cli/command_modules/acs/tests/latest/test_aks_commands.py @@ -6323,7 +6323,6 @@ def test_aks_update_with_defender(self, resource_group, resource_group_location) self.cmd( 'aks delete -g {resource_group} -n {name} --yes --no-wait', checks=[self.is_empty()]) - @live_only() @AllowLargeResponse() @AKSCustomResourceGroupPreparer(random_name_length=17, name_prefix='clitest', location='centraluseuap') def test_aks_create_with_azuremonitormetrics(self, resource_group, resource_group_location): @@ -6360,7 +6359,6 @@ def test_aks_create_with_azuremonitormetrics(self, resource_group, resource_grou self.is_empty(), ]) - @live_only() @AllowLargeResponse() @AKSCustomResourceGroupPreparer(random_name_length=17, name_prefix='clitest', location='westus2') def test_aks_update_with_azuremonitormetrics(self, resource_group, resource_group_location): From 104af4821ee27653bf25b6657a5b3996102056eb Mon Sep 17 00:00:00 2001 From: Kaveesh Dubey Date: Mon, 8 May 2023 16:49:41 -0700 Subject: [PATCH 34/41] add live_only for tests --- .../cli/command_modules/acs/tests/latest/test_aks_commands.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/azure-cli/azure/cli/command_modules/acs/tests/latest/test_aks_commands.py b/src/azure-cli/azure/cli/command_modules/acs/tests/latest/test_aks_commands.py index f6ab4bf03dc..0f339d8813d 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/tests/latest/test_aks_commands.py +++ b/src/azure-cli/azure/cli/command_modules/acs/tests/latest/test_aks_commands.py @@ -6323,6 +6323,7 @@ def test_aks_update_with_defender(self, resource_group, resource_group_location) self.cmd( 'aks delete -g {resource_group} -n {name} --yes --no-wait', checks=[self.is_empty()]) + @live_only() @AllowLargeResponse() @AKSCustomResourceGroupPreparer(random_name_length=17, name_prefix='clitest', location='centraluseuap') def test_aks_create_with_azuremonitormetrics(self, resource_group, resource_group_location): @@ -6359,6 +6360,7 @@ def test_aks_create_with_azuremonitormetrics(self, resource_group, resource_grou self.is_empty(), ]) + @live_only() @AllowLargeResponse() @AKSCustomResourceGroupPreparer(random_name_length=17, name_prefix='clitest', location='westus2') def test_aks_update_with_azuremonitormetrics(self, resource_group, resource_group_location): From 03d907a50c10c06d833406b7b4aa97ba4a027303 Mon Sep 17 00:00:00 2001 From: Kaveesh Dubey Date: Tue, 9 May 2023 10:53:47 -0700 Subject: [PATCH 35/41] live test --- .../acs/tests/latest/test_aks_commands.py | 20 ++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/src/azure-cli/azure/cli/command_modules/acs/tests/latest/test_aks_commands.py b/src/azure-cli/azure/cli/command_modules/acs/tests/latest/test_aks_commands.py index 0f339d8813d..297b4b00540 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/tests/latest/test_aks_commands.py +++ b/src/azure-cli/azure/cli/command_modules/acs/tests/latest/test_aks_commands.py @@ -6347,11 +6347,25 @@ def test_aks_create_with_azuremonitormetrics(self, resource_group, resource_grou '--enable-managed-identity', '--enable-azuremonitormetrics --enable-windows-recording-rules', '--ssh-key-value={ssh_key_value} --node-vm-size={node_vm_size}', ]) - # azuremonitor metrics will be set to false after initial creation command as its in the - # postprocessing step that we do an update to enable it. This behavior is expected. self.cmd(create_cmd, checks=[ + self.is_empty(), + ]) + + # azuremonitor metrics will be set to false after initial creation command as its in the + # postprocessing step that we do an update to enable it. Adding a wait for the second put request + # in addonput.py which enables the Azure Monitor Metrics addon as all the DC* resources + # have now been created. + wait_cmd = ' '.join([ + 'aks', 'wait', '--resource-group={resource_group}', '--name={name}', '--updated', + '--interval 60', '--timeout 300', + ]) + self.cmd(wait_cmd, checks=[ + self.is_empty(), + ]) + + self.cmd('aks show -g {resource_group} -n {name}', checks=[ self.check('provisioningState', 'Succeeded'), - self.check('azureMonitorProfile.metrics.enabled', False), + self.check('azureMonitorProfile.metrics.enabled', True), ]) # delete From 31b0d912a5f9d3e099465ed63e5b620f0ccadf9c Mon Sep 17 00:00:00 2001 From: Kaveesh Dubey Date: Tue, 9 May 2023 12:42:07 -0700 Subject: [PATCH 36/41] update unit tests --- .../acs/tests/latest/test_aks_commands.py | 90 ++++++++++--------- 1 file changed, 50 insertions(+), 40 deletions(-) diff --git a/src/azure-cli/azure/cli/command_modules/acs/tests/latest/test_aks_commands.py b/src/azure-cli/azure/cli/command_modules/acs/tests/latest/test_aks_commands.py index 297b4b00540..ba15c626c0d 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/tests/latest/test_aks_commands.py +++ b/src/azure-cli/azure/cli/command_modules/acs/tests/latest/test_aks_commands.py @@ -6374,7 +6374,56 @@ def test_aks_create_with_azuremonitormetrics(self, resource_group, resource_grou self.is_empty(), ]) - @live_only() + @AllowLargeResponse() + @AKSCustomResourceGroupPreparer(random_name_length=17, name_prefix='clitest', location='centraluseuap') + def test_aks_create_with_azuremonitormetrics(self, resource_group, resource_group_location): + # reset the count so in replay mode the random names will start with 0 + self.test_resources_count = 0 + # kwargs for string formatting + aks_name = self.create_random_name('cliakstest', 16) + + node_vm_size = 'standard_d2s_v3' + self.kwargs.update({ + 'resource_group': resource_group, + 'name': aks_name, + 'location': resource_group_location, + 'resource_type': 'Microsoft.ContainerService/ManagedClusters', + 'ssh_key_value': self.generate_ssh_keys(), + 'node_vm_size': node_vm_size + }) + + create_cmd = ' '.join([ + 'aks', 'create', '--resource-group={resource_group}', '--name={name}', '--location={location}', + '--enable-managed-identity', '--enable-azuremonitormetrics --enable-windows-recording-rules', + '--ssh-key-value={ssh_key_value} --node-vm-size={node_vm_size}', + ]) + self.cmd(create_cmd, checks=[ + self.check('provisioningState', 'Succeeded'), + ]) + + # azuremonitor metrics will be set to false after initial creation command as its in the + # postprocessing step that we do an update to enable it. Adding a wait for the second put request + # in addonput.py which enables the Azure Monitor Metrics addon as all the DC* resources + # have now been created. + wait_cmd = ' '.join([ + 'aks', 'wait', '--resource-group={resource_group}', '--name={name}', '--updated', + '--interval 60', '--timeout 300', + ]) + self.cmd(wait_cmd, checks=[ + self.is_empty(), + ]) + + self.cmd('aks show -g {resource_group} -n {name}', checks=[ + self.check('provisioningState', 'Succeeded'), + self.check('azureMonitorProfile.metrics.enabled', True), + ]) + + # delete + cmd = 'aks delete --resource-group={resource_group} --name={name} --yes --no-wait' + self.cmd(cmd, checks=[ + self.is_empty(), + ]) + @AllowLargeResponse() @AKSCustomResourceGroupPreparer(random_name_length=17, name_prefix='clitest', location='westus2') def test_aks_update_with_azuremonitormetrics(self, resource_group, resource_group_location): @@ -6417,45 +6466,6 @@ def test_aks_update_with_azuremonitormetrics(self, resource_group, resource_grou self.is_empty(), ]) - @AllowLargeResponse() - @AKSCustomResourceGroupPreparer(random_name_length=17, name_prefix='clitest', location='westus2') - def test_aks_create_with_custom_monitoring_workspace(self, resource_group, resource_group_location): - aks_name = self.create_random_name('cliakstest', 16) - workspace_name = self.create_random_name('cliaksworkspace', 20) - self.kwargs.update({ - 'name': aks_name, - 'resource_group': resource_group, - 'ssh_key_value': self.generate_ssh_keys(), - 'workspace_name': workspace_name - }) - - # create workspace - create_workspace_cmd = 'monitor log-analytics workspace create -g {resource_group} -n {workspace_name}' - self.cmd(create_workspace_cmd, checks=[ - # self.check('provisioningState', 'Succeeded'), - self.check('name', workspace_name) - ]) - - # get workspace id - subscription_id = self.get_subscription_id() - workspace_id = "/subscriptions/{}/resourcegroups/{}/providers/microsoft.operationalinsights/workspaces/{}".format(subscription_id, resource_group, workspace_name) - self.kwargs.update({ - 'workspace_id': workspace_id - }) - - # create - create_cmd = 'aks create --resource-group={resource_group} --name={name} ' \ - '--ssh-key-value={ssh_key_value} -a monitoring --workspace-resource-id {workspace_id}' - self.cmd(create_cmd, checks=[ - self.check('provisioningState', 'Succeeded'), - self.check('addonProfiles.omsagent.enabled', True), - self.check('addonProfiles.omsagent.config.logAnalyticsWorkspaceResourceID', workspace_id) - ]) - - # delete - self.cmd( - 'aks delete -g {resource_group} -n {name} --yes --no-wait', checks=[self.is_empty()]) - # live only due to dependency `_add_role_assignment` is not mocked @live_only() @AllowLargeResponse() From d3efd9ffafec7ef52a7cb884b089db79527efd43 Mon Sep 17 00:00:00 2001 From: Kaveesh Dubey Date: Tue, 9 May 2023 20:53:55 -0700 Subject: [PATCH 37/41] . --- .../acs/azuremonitormetrics/recordingrules/create.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/recordingrules/create.py b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/recordingrules/create.py index 6ba80fad208..7628011e078 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/recordingrules/create.py +++ b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/recordingrules/create.py @@ -44,7 +44,6 @@ def put_rules(cmd, default_rule_group_id, default_rule_group_name, mac_region, a headers = ['User-Agent=azuremonitormetrics.put_rules.' + default_rule_group_name] send_raw_request(cmd.cli_ctx, "PUT", url, body=body, headers=headers) - print(f"Created rule group ({rule_group_text}) : {default_rule_group_id}") break except CLIError as e: error = e From 80f9d858601629a4f86c5c00bad04b380191f57a Mon Sep 17 00:00:00 2001 From: Kaveesh Dubey Date: Wed, 10 May 2023 18:50:51 -0700 Subject: [PATCH 38/41] pr fixes --- .../azure/cli/command_modules/acs/_help.py | 8 +-- .../azure/cli/command_modules/acs/_params.py | 6 +- .../acs/azuremonitormetrics/helper.py | 2 +- .../azure/cli/command_modules/acs/custom.py | 6 +- .../command_modules/acs/linter_exclusions.yml | 8 +-- .../acs/managed_cluster_decorator.py | 14 ++-- .../acs/tests/latest/test_aks_commands.py | 67 ++----------------- 7 files changed, 29 insertions(+), 82 deletions(-) diff --git a/src/azure-cli/azure/cli/command_modules/acs/_help.py b/src/azure-cli/azure/cli/command_modules/acs/_help.py index 8cde4ba4aa9..3729e82b00d 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/_help.py +++ b/src/azure-cli/azure/cli/command_modules/acs/_help.py @@ -479,7 +479,7 @@ - name: --enable-keda type: bool short-summary: Enable KEDA workload auto-scaler. - - name: --enable-azuremonitormetrics + - name: --enable-azure-monitor-metrics type: bool short-summary: Enable Azure Monitor Metrics Profile - name: --azure-monitor-workspace-resource-id @@ -568,7 +568,7 @@ - name: Create a kubernetes cluster with KEDA workload autoscaler enabled. text: az aks create -g MyResourceGroup -n MyManagedCluster --enable-keda - name: Create a kubernetes cluster with Azure Monitor Metrics enabled. - text: az aks create -g MyResourceGroup -n MyManagedCluster --enable-azuremonitormetrics + text: az aks create -g MyResourceGroup -n MyManagedCluster --enable-azure-monitor-metrics """ helps['aks update'] = """ @@ -811,7 +811,7 @@ - name: --disable-keda type: bool short-summary: Disable KEDA workload auto-scaler. - - name: --enable-azuremonitormetrics + - name: --enable-azure-monitor-metrics type: bool short-summary: Enable Azure Monitor Metrics Profile - name: --azure-monitor-workspace-resource-id @@ -829,7 +829,7 @@ - name: --enable-windows-recording-rules type: bool short-summary: Enable Windows Recording Rules when enabling the Azure Monitor Metrics addon - - name: --disable-azuremonitormetrics + - name: --disable-azure-monitor-metrics type: bool short-summary: Disable Azure Monitor Metrics Profile. This will delete all DCRA's associated with the cluster, any linked DCRs with the data stream = prometheus-stream and the recording rule groups created by the addon for this AKS cluster. diff --git a/src/azure-cli/azure/cli/command_modules/acs/_params.py b/src/azure-cli/azure/cli/command_modules/acs/_params.py index 243fbdabb6f..425514c2770 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/_params.py +++ b/src/azure-cli/azure/cli/command_modules/acs/_params.py @@ -284,7 +284,7 @@ def load_arguments(self, _): c.argument('host_group_id', validator=validate_host_group_id) c.argument('gpu_instance_profile', arg_type=get_enum_type(gpu_instance_profiles)) # azure monitor profile - c.argument('enable_azuremonitormetrics', action='store_true') + c.argument('enable_azure_monitor_metrics', action='store_true') c.argument('azure_monitor_workspace_resource_id', validator=validate_azuremonitorworkspaceresourceid) c.argument('ksm_metric_labels_allow_list') c.argument('ksm_metric_annotations_allow_list') @@ -371,13 +371,13 @@ def load_arguments(self, _): c.argument('nodepool_labels', nargs='*', validator=validate_nodepool_labels, help='space-separated labels: key[=value] [key[=value] ...]. See https://aka.ms/node-labels for syntax of labels.') # azure monitor profile - c.argument('enable_azuremonitormetrics', action='store_true') + c.argument('enable_azure_monitor_metrics', action='store_true') c.argument('azure_monitor_workspace_resource_id', validator=validate_azuremonitorworkspaceresourceid) c.argument('ksm_metric_labels_allow_list') c.argument('ksm_metric_annotations_allow_list') c.argument('grafana_resource_id', validator=validate_grafanaresourceid) c.argument('enable_windows_recording_rules', action='store_true') - c.argument('disable_azuremonitormetrics', action='store_true') + c.argument('disable_azure_monitor_metrics', action='store_true') # misc c.argument('yes', options_list=['--yes', '-y'], help='Do not prompt for confirmation.', action='store_true') diff --git a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/helper.py b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/helper.py index 62f12875ce0..07a913facf0 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/helper.py +++ b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/helper.py @@ -97,4 +97,4 @@ def check_azuremonitormetrics_profile(cmd, cluster_subscription, cluster_resourc if "azureMonitorProfile" in values_array: if "metrics" in values_array["azureMonitorProfile"]: if values_array["azureMonitorProfile"]["metrics"]["enabled"] is True: - raise CLIError(f"Azure Monitor Metrics is already enabled for this cluster. Please use `az aks update --disable-azuremonitormetrics -g {cluster_resource_group_name} -n {cluster_name}` and then try enabling.") + raise CLIError(f"Azure Monitor Metrics is already enabled for this cluster. Please use `az aks update --disable-azure-monitor-metrics -g {cluster_resource_group_name} -n {cluster_name}` and then try enabling.") diff --git a/src/azure-cli/azure/cli/command_modules/acs/custom.py b/src/azure-cli/azure/cli/command_modules/acs/custom.py index e98c351f73c..276b52a088b 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/custom.py +++ b/src/azure-cli/azure/cli/command_modules/acs/custom.py @@ -494,7 +494,7 @@ def aks_create( host_group_id=None, gpu_instance_profile=None, # azure monitor profile - enable_azuremonitormetrics=False, + enable_azure_monitor_metrics=False, azure_monitor_workspace_resource_id=None, ksm_metric_labels_allow_list=None, ksm_metric_annotations_allow_list=None, @@ -619,13 +619,13 @@ def aks_update( max_count=None, nodepool_labels=None, # azure monitor profile - enable_azuremonitormetrics=False, + enable_azure_monitor_metrics=False, azure_monitor_workspace_resource_id=None, ksm_metric_labels_allow_list=None, ksm_metric_annotations_allow_list=None, grafana_resource_id=None, enable_windows_recording_rules=False, - disable_azuremonitormetrics=False, + disable_azure_monitor_metrics=False, # misc yes=False, no_wait=False, diff --git a/src/azure-cli/azure/cli/command_modules/acs/linter_exclusions.yml b/src/azure-cli/azure/cli/command_modules/acs/linter_exclusions.yml index c161888262a..f92f123db6e 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/linter_exclusions.yml +++ b/src/azure-cli/azure/cli/command_modules/acs/linter_exclusions.yml @@ -28,10 +28,10 @@ aks create: azure_monitor_workspace_resource_id: rule_exclusions: - option_length_too_long - disable_azuremonitormetrics: + disable_azure_monitor_metrics: rule_exclusions: - option_length_too_long - enable_azuremonitormetrics: + enable_azure_monitor_metrics: rule_exclusions: - option_length_too_long ksm_metric_annotations_allow_list: @@ -90,10 +90,10 @@ aks update: azure_monitor_workspace_resource_id: rule_exclusions: - option_length_too_long - disable_azuremonitormetrics: + disable_azure_monitor_metrics: rule_exclusions: - option_length_too_long - enable_azuremonitormetrics: + enable_azure_monitor_metrics: rule_exclusions: - option_length_too_long ksm_metric_annotations_allow_list: diff --git a/src/azure-cli/azure/cli/command_modules/acs/managed_cluster_decorator.py b/src/azure-cli/azure/cli/command_modules/acs/managed_cluster_decorator.py index 709d739e3b0..205bbc18db2 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/managed_cluster_decorator.py +++ b/src/azure-cli/azure/cli/command_modules/acs/managed_cluster_decorator.py @@ -4757,7 +4757,7 @@ def _get_enable_azure_monitor_metrics(self, enable_validation: bool = False) -> """ # print("_get_enable_azure_monitor_metrics being called...") # Read the original value passed by the command. - enable_azure_monitor_metrics = self.raw_param.get("enable_azuremonitormetrics") + enable_azure_monitor_metrics = self.raw_param.get("enable_azure_monitor_metrics") # In create mode, try to read the property value corresponding to the parameter from the `mc` object. if self.decorator_mode == DecoratorMode.CREATE: if ( @@ -4771,11 +4771,11 @@ def _get_enable_azure_monitor_metrics(self, enable_validation: bool = False) -> if enable_validation: if enable_azure_monitor_metrics and self._get_disable_azure_monitor_metrics(False): raise MutuallyExclusiveArgumentError( - "Cannot specify --enable-azuremonitormetrics and --disable-azuremonitormetrics at the same time." + "Cannot specify --enable-azure-monitor-metrics and --disable-azure-monitor-metrics at the same time." ) if enable_azure_monitor_metrics and not check_is_msi_cluster(self.mc): raise RequiredArgumentMissingError( - "--enable-azuremonitormetrics can only be specified for clusters with managed identity enabled" + "--enable-azure-monitor-metrics can only be specified for clusters with managed identity enabled" ) return enable_azure_monitor_metrics @@ -4796,11 +4796,11 @@ def _get_disable_azure_monitor_metrics(self, enable_validation: bool = False) -> :return: bool """ # Read the original value passed by the command. - disable_azure_monitor_metrics = self.raw_param.get("disable_azuremonitormetrics") + disable_azure_monitor_metrics = self.raw_param.get("disable_azure_monitor_metrics") if enable_validation: if disable_azure_monitor_metrics and self._get_enable_azure_monitor_metrics(False): raise MutuallyExclusiveArgumentError( - "Cannot specify --enable-azuremonitormetrics and --disable-azuremonitormetrics at the same time." + "Cannot specify --enable-azure-monitor-metrics and --disable-azure-monitor-metrics at the same time." ) return disable_azure_monitor_metrics @@ -6985,8 +6985,8 @@ def update_azure_monitor_profile(self, mc: ManagedCluster) -> ManagedCluster: mc.azure_monitor_profile.metrics = self.models.ManagedClusterAzureMonitorProfileMetrics(enabled=False) if ( - self.context.raw_param.get("enable_azuremonitormetrics") or - self.context.raw_param.get("disable_azuremonitormetrics") + self.context.raw_param.get("enable_azure_monitor_metrics") or + self.context.raw_param.get("disable_azure_monitor_metrics") ): self.context.external_functions.ensure_azure_monitor_profile_prerequisites( self.cmd, diff --git a/src/azure-cli/azure/cli/command_modules/acs/tests/latest/test_aks_commands.py b/src/azure-cli/azure/cli/command_modules/acs/tests/latest/test_aks_commands.py index ba15c626c0d..29b732c07cf 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/tests/latest/test_aks_commands.py +++ b/src/azure-cli/azure/cli/command_modules/acs/tests/latest/test_aks_commands.py @@ -6323,59 +6323,8 @@ def test_aks_update_with_defender(self, resource_group, resource_group_location) self.cmd( 'aks delete -g {resource_group} -n {name} --yes --no-wait', checks=[self.is_empty()]) - @live_only() - @AllowLargeResponse() - @AKSCustomResourceGroupPreparer(random_name_length=17, name_prefix='clitest', location='centraluseuap') - def test_aks_create_with_azuremonitormetrics(self, resource_group, resource_group_location): - # reset the count so in replay mode the random names will start with 0 - self.test_resources_count = 0 - # kwargs for string formatting - aks_name = self.create_random_name('cliakstest', 16) - - node_vm_size = 'standard_d2s_v3' - self.kwargs.update({ - 'resource_group': resource_group, - 'name': aks_name, - 'location': resource_group_location, - 'resource_type': 'Microsoft.ContainerService/ManagedClusters', - 'ssh_key_value': self.generate_ssh_keys(), - 'node_vm_size': node_vm_size - }) - - create_cmd = ' '.join([ - 'aks', 'create', '--resource-group={resource_group}', '--name={name}', '--location={location}', - '--enable-managed-identity', '--enable-azuremonitormetrics --enable-windows-recording-rules', - '--ssh-key-value={ssh_key_value} --node-vm-size={node_vm_size}', - ]) - self.cmd(create_cmd, checks=[ - self.is_empty(), - ]) - - # azuremonitor metrics will be set to false after initial creation command as its in the - # postprocessing step that we do an update to enable it. Adding a wait for the second put request - # in addonput.py which enables the Azure Monitor Metrics addon as all the DC* resources - # have now been created. - wait_cmd = ' '.join([ - 'aks', 'wait', '--resource-group={resource_group}', '--name={name}', '--updated', - '--interval 60', '--timeout 300', - ]) - self.cmd(wait_cmd, checks=[ - self.is_empty(), - ]) - - self.cmd('aks show -g {resource_group} -n {name}', checks=[ - self.check('provisioningState', 'Succeeded'), - self.check('azureMonitorProfile.metrics.enabled', True), - ]) - - # delete - cmd = 'aks delete --resource-group={resource_group} --name={name} --yes --no-wait' - self.cmd(cmd, checks=[ - self.is_empty(), - ]) - @AllowLargeResponse() - @AKSCustomResourceGroupPreparer(random_name_length=17, name_prefix='clitest', location='centraluseuap') + @AKSCustomResourceGroupPreparer(random_name_length=17, name_prefix='clitest', location='westus2') def test_aks_create_with_azuremonitormetrics(self, resource_group, resource_group_location): # reset the count so in replay mode the random names will start with 0 self.test_resources_count = 0 @@ -6392,11 +6341,9 @@ def test_aks_create_with_azuremonitormetrics(self, resource_group, resource_grou 'node_vm_size': node_vm_size }) - create_cmd = ' '.join([ - 'aks', 'create', '--resource-group={resource_group}', '--name={name}', '--location={location}', - '--enable-managed-identity', '--enable-azuremonitormetrics --enable-windows-recording-rules', - '--ssh-key-value={ssh_key_value} --node-vm-size={node_vm_size}', - ]) + create_cmd = 'aks create --resource-group={resource_group} --name={name} --location={location} ' \ + '--ssh-key-value={ssh_key_value} --node-vm-size={node_vm_size} --enable-managed-identity ' \ + '--enable-azuremonitormetrics --enable-windows-recording-rules --output=json' self.cmd(create_cmd, checks=[ self.check('provisioningState', 'Succeeded'), ]) @@ -6413,7 +6360,7 @@ def test_aks_create_with_azuremonitormetrics(self, resource_group, resource_grou self.is_empty(), ]) - self.cmd('aks show -g {resource_group} -n {name}', checks=[ + self.cmd('aks show -g {resource_group} -n {name} --output=json', checks=[ self.check('provisioningState', 'Succeeded'), self.check('azureMonitorProfile.metrics.enabled', True), ]) @@ -6452,9 +6399,9 @@ def test_aks_update_with_azuremonitormetrics(self, resource_group, resource_grou self.check('azureMonitorProfile.metrics.enabled', True), ]) - # update: disable-azuremonitormetrics + # update: disable-azure-monitor-metrics update_cmd = 'aks update --resource-group={resource_group} --name={name} --yes --output=json ' \ - '--disable-azuremonitormetrics' + '--disable-azure-monitor-metrics' self.cmd(update_cmd, checks=[ self.check('provisioningState', 'Succeeded'), self.check('azureMonitorProfile.metrics.enabled', False), From dea7db83e93f62f0a0697ffe9ff0966c0c541f83 Mon Sep 17 00:00:00 2001 From: Kaveesh Dubey Date: Thu, 11 May 2023 11:01:40 -0700 Subject: [PATCH 39/41] fix --- .../acs/azuremonitormetrics/recordingrules/create.py | 3 --- .../cli/command_modules/acs/managed_cluster_decorator.py | 4 ++-- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/recordingrules/create.py b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/recordingrules/create.py index 7628011e078..8471a65d19c 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/recordingrules/create.py +++ b/src/azure-cli/azure/cli/command_modules/acs/azuremonitormetrics/recordingrules/create.py @@ -36,9 +36,6 @@ def put_rules(cmd, default_rule_group_id, default_rule_group_name, mac_region, a "rules": default_rules_template[i]["properties"]["rulesArmTemplate"]["resources"][0]["properties"]["rules"] } }) - rule_group_text = "Disabled" - if enable_rules is True: - rule_group_text = "Enabled" for _ in range(3): try: headers = ['User-Agent=azuremonitormetrics.put_rules.' + default_rule_group_name] diff --git a/src/azure-cli/azure/cli/command_modules/acs/managed_cluster_decorator.py b/src/azure-cli/azure/cli/command_modules/acs/managed_cluster_decorator.py index f66fa5e5ecd..e9121878ed2 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/managed_cluster_decorator.py +++ b/src/azure-cli/azure/cli/command_modules/acs/managed_cluster_decorator.py @@ -4771,7 +4771,7 @@ def _get_enable_azure_monitor_metrics(self, enable_validation: bool = False) -> if enable_validation: if enable_azure_monitor_metrics and self._get_disable_azure_monitor_metrics(False): raise MutuallyExclusiveArgumentError( - "Cannot specify --enable-azure-monitor-metrics and --disable-azure-monitor-metrics at the same time." + "Cannot specify --enable-azure-monitor-metrics and --disable-azure-monitor-metrics at the same time" ) if enable_azure_monitor_metrics and not check_is_msi_cluster(self.mc): raise RequiredArgumentMissingError( @@ -4800,7 +4800,7 @@ def _get_disable_azure_monitor_metrics(self, enable_validation: bool = False) -> if enable_validation: if disable_azure_monitor_metrics and self._get_enable_azure_monitor_metrics(False): raise MutuallyExclusiveArgumentError( - "Cannot specify --enable-azure-monitor-metrics and --disable-azure-monitor-metrics at the same time." + "Cannot specify --enable-azure-monitor-metrics and --disable-azure-monitor-metrics at the same time" ) return disable_azure_monitor_metrics From 0b81ab692cf56ce663f42dae34c2a68508517225 Mon Sep 17 00:00:00 2001 From: Kaveesh Dubey Date: Thu, 11 May 2023 11:04:47 -0700 Subject: [PATCH 40/41] missed --- .../command_modules/acs/tests/latest/test_aks_commands.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/azure-cli/azure/cli/command_modules/acs/tests/latest/test_aks_commands.py b/src/azure-cli/azure/cli/command_modules/acs/tests/latest/test_aks_commands.py index a6fdf4400c3..e0c69b0c94e 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/tests/latest/test_aks_commands.py +++ b/src/azure-cli/azure/cli/command_modules/acs/tests/latest/test_aks_commands.py @@ -6343,7 +6343,7 @@ def test_aks_create_with_azuremonitormetrics(self, resource_group, resource_grou create_cmd = 'aks create --resource-group={resource_group} --name={name} --location={location} ' \ '--ssh-key-value={ssh_key_value} --node-vm-size={node_vm_size} --enable-managed-identity ' \ - '--enable-azuremonitormetrics --enable-windows-recording-rules --output=json' + '--enable-azure-monitor-metrics --enable-windows-recording-rules --output=json' self.cmd(create_cmd, checks=[ self.check('provisioningState', 'Succeeded'), ]) @@ -6384,16 +6384,16 @@ def test_aks_update_with_azuremonitormetrics(self, resource_group, resource_grou 'node_vm_size': node_vm_size, }) - # create: without enable-azuremonitormetrics + # create: without enable-azure-monitor-metrics create_cmd = 'aks create --resource-group={resource_group} --name={name} --location={location} --ssh-key-value={ssh_key_value} --node-vm-size={node_vm_size} --enable-managed-identity --output=json' self.cmd(create_cmd, checks=[ self.check('provisioningState', 'Succeeded'), self.not_exists('azureMonitorProfile.metrics'), ]) - # update: enable-azuremonitormetrics + # update: enable-azure-monitor-metrics update_cmd = 'aks update --resource-group={resource_group} --name={name} --yes --output=json ' \ - '--enable-azuremonitormetrics --enable-managed-identity --enable-windows-recording-rules' + '--enable-azure-monitor-metrics --enable-managed-identity --enable-windows-recording-rules' self.cmd(update_cmd, checks=[ self.check('provisioningState', 'Succeeded'), self.check('azureMonitorProfile.metrics.enabled', True), From 929f564a210969352d8d21b4035b9591a90617d8 Mon Sep 17 00:00:00 2001 From: Kaveesh Dubey Date: Thu, 11 May 2023 11:45:17 -0700 Subject: [PATCH 41/41] test with liveonly --- .../cli/command_modules/acs/tests/latest/test_aks_commands.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/azure-cli/azure/cli/command_modules/acs/tests/latest/test_aks_commands.py b/src/azure-cli/azure/cli/command_modules/acs/tests/latest/test_aks_commands.py index e0c69b0c94e..2fa59aed646 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/tests/latest/test_aks_commands.py +++ b/src/azure-cli/azure/cli/command_modules/acs/tests/latest/test_aks_commands.py @@ -6323,6 +6323,7 @@ def test_aks_update_with_defender(self, resource_group, resource_group_location) self.cmd( 'aks delete -g {resource_group} -n {name} --yes --no-wait', checks=[self.is_empty()]) + @live_only() @AllowLargeResponse() @AKSCustomResourceGroupPreparer(random_name_length=17, name_prefix='clitest', location='westus2') def test_aks_create_with_azuremonitormetrics(self, resource_group, resource_group_location): @@ -6371,6 +6372,7 @@ def test_aks_create_with_azuremonitormetrics(self, resource_group, resource_grou self.is_empty(), ]) + @live_only() @AllowLargeResponse() @AKSCustomResourceGroupPreparer(random_name_length=17, name_prefix='clitest', location='westus2') def test_aks_update_with_azuremonitormetrics(self, resource_group, resource_group_location):