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 c19ed7ae2fb..07db9c054df 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/custom.py +++ b/src/azure-cli/azure/cli/command_modules/acs/custom.py @@ -1637,10 +1637,18 @@ def aks_check_acr(cmd, client, resource_group_name, name, acr): # pylint: disable=too-many-statements,too-many-branches -def aks_browse(cmd, client, resource_group_name, name, disable_browser=False, - listen_address='127.0.0.1', listen_port='8001'): +def _aks_browse( + cmd, + client, + resource_group_name, + name, + disable_browser=False, + listen_address="127.0.0.1", + listen_port="8001", + resource_type=ResourceType.MGMT_CONTAINERSERVICE, +): ManagedClusterAddonProfile = cmd.get_models('ManagedClusterAddonProfile', - resource_type=ResourceType.MGMT_CONTAINERSERVICE, + resource_type=resource_type, operation_group='managed_clusters') # verify the kube-dashboard addon was not disabled instance = client.get(resource_group_name, name) @@ -1650,6 +1658,7 @@ def aks_browse(cmd, client, resource_group_name, name, disable_browser=False, if k.lower() == CONST_KUBE_DASHBOARD_ADDON_NAME.lower()), ManagedClusterAddonProfile(enabled=False)) + return_msg = None # open portal view if addon is not enabled or k8s version >= 1.19.0 if StrictVersion(instance.kubernetes_version) >= StrictVersion('1.19.0') or (not addon_profile.enabled): subscription_id = get_subscription_id(cmd.cli_ctx) @@ -1665,10 +1674,11 @@ def aks_browse(cmd, client, resource_group_name, name, disable_browser=False, 'To view the Kubernetes resources view, please open %s in a new tab', dashboardURL) else: logger.warning('Kubernetes resources view on %s', dashboardURL) + return_msg = "Kubernetes resources view on {}".format(dashboardURL) if not disable_browser: webbrowser.open_new_tab(dashboardURL) - return + return return_msg # otherwise open the kube-dashboard addon if not which('kubectl'): @@ -1730,28 +1740,65 @@ def aks_browse(cmd, client, resource_group_name, name, disable_browser=False, else: logger.warning('Proxy running on %s', proxy_url) + timeout = None + if os.getenv("PYTEST_CURRENT_TEST", None): + timeout = 10 logger.warning('Press CTRL+C to close the tunnel...') if not disable_browser: wait_then_open_async(dashboardURL) try: try: subprocess.check_output(["kubectl", "--kubeconfig", browse_path, "proxy", "--address", - listen_address, "--port", listen_port], stderr=subprocess.STDOUT) + listen_address, "--port", listen_port], stderr=subprocess.STDOUT, timeout=timeout) except subprocess.CalledProcessError as err: if err.output.find(b'unknown flag: --address'): + return_msg = "Test Invalid Address! " if listen_address != '127.0.0.1': logger.warning( '"--address" is only supported in kubectl v1.13 and later.') logger.warning( 'The "--listen-address" argument will be ignored.') - subprocess.call(["kubectl", "--kubeconfig", - browse_path, "proxy", "--port", listen_port]) + try: + subprocess.call(["kubectl", "--kubeconfig", + browse_path, "proxy", "--port", listen_port], timeout=timeout) + except subprocess.TimeoutExpired: + logger.warning("Currently in a test environment, the proxy is closed due to a preset timeout!") + return_msg = return_msg if return_msg else "" + return_msg += "Test Passed!" + except subprocess.TimeoutExpired: + logger.warning("Currently in a test environment, the proxy is closed due to a preset timeout!") + return_msg = return_msg if return_msg else "" + return_msg += "Test Passed!" except KeyboardInterrupt: # Let command processing finish gracefully after the user presses [Ctrl+C] pass finally: if in_cloud_console(): requests.post('http://localhost:8888/closeport/8001') + return return_msg + + +# pylint: disable=too-many-statements,too-many-branches +def aks_browse( + cmd, + client, + resource_group_name, + name, + disable_browser=False, + listen_address="127.0.0.1", + listen_port="8001", +): + + return _aks_browse( + cmd, + client, + resource_group_name, + name, + disable_browser=disable_browser, + listen_address=listen_address, + listen_port=listen_port, + resource_type=ResourceType.MGMT_CONTAINERSERVICE, + ) def _trim_nodepoolname(nodepool_name): diff --git a/src/azure-cli/azure/cli/command_modules/acs/tests/latest/custom_preparers.py b/src/azure-cli/azure/cli/command_modules/acs/tests/latest/custom_preparers.py index 9210a87e66f..95ddf13b712 100644 --- a/src/azure-cli/azure/cli/command_modules/acs/tests/latest/custom_preparers.py +++ b/src/azure-cli/azure/cli/command_modules/acs/tests/latest/custom_preparers.py @@ -25,6 +25,7 @@ def __init__( dev_setting_location="AZURE_CLI_TEST_DEV_RESOURCE_GROUP_LOCATION", random_name_length=75, key="rg", + preserve_default_location=False, ): super(AKSCustomResourceGroupPreparer, self).__init__( name_prefix, @@ -39,7 +40,7 @@ def __init__( # use environment variable to modify the default value of location self.dev_setting_location = os.environ.get(dev_setting_location, None) - if self.dev_setting_location: + if not preserve_default_location and self.dev_setting_location: self.location = self.dev_setting_location else: self.dev_setting_location = location diff --git a/src/azure-cli/azure/cli/command_modules/acs/tests/latest/recordings/test_aks_browse.yaml b/src/azure-cli/azure/cli/command_modules/acs/tests/latest/recordings/test_aks_browse.yaml new file mode 100644 index 00000000000..364fb16738d --- /dev/null +++ b/src/azure-cli/azure/cli/command_modules/acs/tests/latest/recordings/test_aks_browse.yaml @@ -0,0 +1,731 @@ +interactions: +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + CommandName: + - aks create + Connection: + - keep-alive + ParameterSetName: + - --resource-group --name --ssh-key-value + User-Agent: + - AZURECLI/2.26.1 azsdk-python-azure-mgmt-resource/18.0.0 Python/3.8.10 (Linux-5.4.0-1055-azure-x86_64-with-glibc2.27) + method: GET + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/clitest000001?api-version=2021-04-01 + response: + body: + string: '{"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001","name":"clitest000001","type":"Microsoft.Resources/resourceGroups","location":"westus2","tags":{"product":"azurecli","cause":"automation","date":"2021-07-28T04:44:48Z"},"properties":{"provisioningState":"Succeeded"}}' + headers: + cache-control: + - no-cache + content-length: + - '313' + content-type: + - application/json; charset=utf-8 + date: + - Wed, 28 Jul 2021 04:44:49 GMT + expires: + - '-1' + pragma: + - no-cache + strict-transport-security: + - max-age=31536000; includeSubDomains + vary: + - Accept-Encoding + x-content-type-options: + - nosniff + status: + code: 200 + message: OK +- request: + body: '{"identity": {"type": "SystemAssigned"}, "properties": {"kubernetesVersion": + "", "dnsPrefix": "cliakstest-clitest3tjig7oyv-79a739", "agentPoolProfiles": + [{"count": 3, "vmSize": "Standard_DS2_v2", "osType": "Linux", "type": "VirtualMachineScaleSets", + "mode": "System", "enableNodePublicIP": false, "scaleSetPriority": "Regular", + "scaleSetEvictionPolicy": "Delete", "spotMaxPrice": -1.0, "enableEncryptionAtHost": + false, "enableUltraSSD": false, "name": "nodepool1"}], "linuxProfile": {"adminUsername": + "azureuser", "ssh": {"publicKeys": [{"keyData": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQCbIg1guRHbI0lV11wWDt1r2cUdcNd27CJsg+SfgC7miZeubtwUhbsPdhMQsfDyhOWHq1+ZL0M+nJZV63d/1dhmhtgyOqejUwrPlzKhydsbrsdUor+JmNJDdW01v7BXHyuymT8G4s09jCasNOwiufbP/qp72ruu0bIA1nySsvlf9pCQAuFkAnVnf/rFhUlOkhtRpwcq8SUNY2zRHR/EKb/4NWY1JzR4sa3q2fWIJdrrX0DvLoa5g9bIEd4Df79ba7v+yiUBOS0zT2ll+z4g9izHK3EO5d8hL4jYxcjKs+wcslSYRWrascfscLgMlMGh0CdKeNTDjHpGPncaf3Z+FwwwjWeuiNBxv7bJo13/8B/098KlVDl4GZqsoBCEjPyJfV6hO0y/LkRGkk7oHWKgeWAfKtfLItRp00eZ4fcJNK9kCaSMmEugoZWcI7NGbZXzqFWqbpRI7NcDP9+WIQ+i9U5vqWsqd/zng4kbuAJ6UuKqIzB0upYrLShfQE3SAck8oaLhJqqq56VfDuASNpJKidV+zq27HfSBmbXnkR/5AK337dc3MXKJypoK/QPMLKUAP5XLPbs+NddJQV7EZXd29DLgp+fRIg3edpKdO7ZErWhv7d+3Kws+e1Y+ypmR2WIVSwVyBEUfgv2C8Ts9gnTF4pNcEY/S2aBicz5Ew2+jdyGNQQ== + test@example.com\n"}]}}, "addonProfiles": {}, "enableRBAC": true, "networkProfile": + {"networkPlugin": "kubenet", "podCidr": "10.244.0.0/16", "serviceCidr": "10.0.0.0/16", + "dnsServiceIP": "10.0.0.10", "dockerBridgeCidr": "172.17.0.1/16", "outboundType": + "loadBalancer", "loadBalancerSku": "standard"}}, "location": "westus2"}' + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + CommandName: + - aks create + Connection: + - keep-alive + Content-Length: + - '1599' + Content-Type: + - application/json + ParameterSetName: + - --resource-group --name --ssh-key-value + User-Agent: + - AZURECLI/2.26.1 azsdk-python-azure-mgmt-containerservice/16.0.0 Python/3.8.10 + (Linux-5.4.0-1055-azure-x86_64-with-glibc2.27) + method: PUT + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.ContainerService/managedClusters/cliakstest000002?api-version=2021-05-01 + response: + body: + string: "{\n \"id\": \"/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/clitest000001/providers/Microsoft.ContainerService/managedClusters/cliakstest000002\",\n + \ \"location\": \"westus2\",\n \"name\": \"cliakstest000002\",\n \"type\": + \"Microsoft.ContainerService/ManagedClusters\",\n \"properties\": {\n \"provisioningState\": + \"Creating\",\n \"powerState\": {\n \"code\": \"Running\"\n },\n \"kubernetesVersion\": + \"1.19.11\",\n \"dnsPrefix\": \"cliakstest-clitest3tjig7oyv-79a739\",\n + \ \"fqdn\": \"cliakstest-clitest3tjig7oyv-79a739-d8be4ebc.hcp.westus2.azmk8s.io\",\n + \ \"azurePortalFQDN\": \"cliakstest-clitest3tjig7oyv-79a739-d8be4ebc.portal.hcp.westus2.azmk8s.io\",\n + \ \"agentPoolProfiles\": [\n {\n \"name\": \"nodepool1\",\n \"count\": + 3,\n \"vmSize\": \"Standard_DS2_v2\",\n \"osDiskSizeGB\": 128,\n \"osDiskType\": + \"Managed\",\n \"kubeletDiskType\": \"OS\",\n \"maxPods\": 110,\n + \ \"type\": \"VirtualMachineScaleSets\",\n \"provisioningState\": \"Creating\",\n + \ \"powerState\": {\n \"code\": \"Running\"\n },\n \"orchestratorVersion\": + \"1.19.11\",\n \"enableNodePublicIP\": false,\n \"nodeLabels\": {},\n + \ \"mode\": \"System\",\n \"enableEncryptionAtHost\": false,\n \"enableUltraSSD\": + false,\n \"osType\": \"Linux\",\n \"osSKU\": \"Ubuntu\",\n \"nodeImageVersion\": + \"AKSUbuntu-1804gen2containerd-2021.07.03\",\n \"enableFIPS\": false\n + \ }\n ],\n \"linuxProfile\": {\n \"adminUsername\": \"azureuser\",\n + \ \"ssh\": {\n \"publicKeys\": [\n {\n \"keyData\": \"ssh-rsa + AAAAB3NzaC1yc2EAAAADAQABAAACAQCbIg1guRHbI0lV11wWDt1r2cUdcNd27CJsg+SfgC7miZeubtwUhbsPdhMQsfDyhOWHq1+ZL0M+nJZV63d/1dhmhtgyOqejUwrPlzKhydsbrsdUor+JmNJDdW01v7BXHyuymT8G4s09jCasNOwiufbP/qp72ruu0bIA1nySsvlf9pCQAuFkAnVnf/rFhUlOkhtRpwcq8SUNY2zRHR/EKb/4NWY1JzR4sa3q2fWIJdrrX0DvLoa5g9bIEd4Df79ba7v+yiUBOS0zT2ll+z4g9izHK3EO5d8hL4jYxcjKs+wcslSYRWrascfscLgMlMGh0CdKeNTDjHpGPncaf3Z+FwwwjWeuiNBxv7bJo13/8B/098KlVDl4GZqsoBCEjPyJfV6hO0y/LkRGkk7oHWKgeWAfKtfLItRp00eZ4fcJNK9kCaSMmEugoZWcI7NGbZXzqFWqbpRI7NcDP9+WIQ+i9U5vqWsqd/zng4kbuAJ6UuKqIzB0upYrLShfQE3SAck8oaLhJqqq56VfDuASNpJKidV+zq27HfSBmbXnkR/5AK337dc3MXKJypoK/QPMLKUAP5XLPbs+NddJQV7EZXd29DLgp+fRIg3edpKdO7ZErWhv7d+3Kws+e1Y+ypmR2WIVSwVyBEUfgv2C8Ts9gnTF4pNcEY/S2aBicz5Ew2+jdyGNQQ== + test@example.com\\n\"\n }\n ]\n }\n },\n \"servicePrincipalProfile\": + {\n \"clientId\":\"00000000-0000-0000-0000-000000000001\"\n },\n \"nodeResourceGroup\": + \"MC_clitest000001_cliakstest000002_westus2\",\n \"enableRBAC\": true,\n + \ \"networkProfile\": {\n \"networkPlugin\": \"kubenet\",\n \"loadBalancerSku\": + \"standard\",\n \"loadBalancerProfile\": {\n \"managedOutboundIPs\": + {\n \"count\": 1\n }\n },\n \"podCidr\": \"10.244.0.0/16\",\n + \ \"serviceCidr\": \"10.0.0.0/16\",\n \"dnsServiceIP\": \"10.0.0.10\",\n + \ \"dockerBridgeCidr\": \"172.17.0.1/16\",\n \"outboundType\": \"loadBalancer\"\n + \ },\n \"maxAgentPools\": 100\n },\n \"identity\": {\n \"type\": \"SystemAssigned\",\n + \ \"principalId\":\"00000000-0000-0000-0000-000000000001\",\n \"tenantId\": + \"72f988bf-86f1-41af-91ab-2d7cd011db47\"\n },\n \"sku\": {\n \"name\": + \"Basic\",\n \"tier\": \"Free\"\n }\n }" + headers: + azure-asyncoperation: + - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.ContainerService/locations/westus2/operations/d0fb5726-6a67-4e2c-a7fc-725357a19dc6?api-version=2016-03-30 + cache-control: + - no-cache + content-length: + - '2984' + content-type: + - application/json + date: + - Wed, 28 Jul 2021 04:44:57 GMT + expires: + - '-1' + pragma: + - no-cache + server: + - nginx + strict-transport-security: + - max-age=31536000; includeSubDomains + x-content-type-options: + - nosniff + x-ms-ratelimit-remaining-subscription-writes: + - '1199' + status: + code: 201 + message: Created +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + CommandName: + - aks create + Connection: + - keep-alive + ParameterSetName: + - --resource-group --name --ssh-key-value + User-Agent: + - AZURECLI/2.26.1 azsdk-python-azure-mgmt-containerservice/16.0.0 Python/3.8.10 + (Linux-5.4.0-1055-azure-x86_64-with-glibc2.27) + method: GET + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.ContainerService/locations/westus2/operations/d0fb5726-6a67-4e2c-a7fc-725357a19dc6?api-version=2016-03-30 + response: + body: + string: "{\n \"name\": \"2657fbd0-676a-2c4e-a7fc-725357a19dc6\",\n \"status\": + \"InProgress\",\n \"startTime\": \"2021-07-28T04:44:57.5066666Z\"\n }" + headers: + cache-control: + - no-cache + content-length: + - '126' + content-type: + - application/json + date: + - Wed, 28 Jul 2021 04:45:27 GMT + expires: + - '-1' + pragma: + - no-cache + server: + - nginx + strict-transport-security: + - max-age=31536000; includeSubDomains + transfer-encoding: + - chunked + vary: + - Accept-Encoding + x-content-type-options: + - nosniff + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + CommandName: + - aks create + Connection: + - keep-alive + ParameterSetName: + - --resource-group --name --ssh-key-value + User-Agent: + - AZURECLI/2.26.1 azsdk-python-azure-mgmt-containerservice/16.0.0 Python/3.8.10 + (Linux-5.4.0-1055-azure-x86_64-with-glibc2.27) + method: GET + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.ContainerService/locations/westus2/operations/d0fb5726-6a67-4e2c-a7fc-725357a19dc6?api-version=2016-03-30 + response: + body: + string: "{\n \"name\": \"2657fbd0-676a-2c4e-a7fc-725357a19dc6\",\n \"status\": + \"InProgress\",\n \"startTime\": \"2021-07-28T04:44:57.5066666Z\"\n }" + headers: + cache-control: + - no-cache + content-length: + - '126' + content-type: + - application/json + date: + - Wed, 28 Jul 2021 04:45:57 GMT + expires: + - '-1' + pragma: + - no-cache + server: + - nginx + strict-transport-security: + - max-age=31536000; includeSubDomains + transfer-encoding: + - chunked + vary: + - Accept-Encoding + x-content-type-options: + - nosniff + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + CommandName: + - aks create + Connection: + - keep-alive + ParameterSetName: + - --resource-group --name --ssh-key-value + User-Agent: + - AZURECLI/2.26.1 azsdk-python-azure-mgmt-containerservice/16.0.0 Python/3.8.10 + (Linux-5.4.0-1055-azure-x86_64-with-glibc2.27) + method: GET + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.ContainerService/locations/westus2/operations/d0fb5726-6a67-4e2c-a7fc-725357a19dc6?api-version=2016-03-30 + response: + body: + string: "{\n \"name\": \"2657fbd0-676a-2c4e-a7fc-725357a19dc6\",\n \"status\": + \"InProgress\",\n \"startTime\": \"2021-07-28T04:44:57.5066666Z\"\n }" + headers: + cache-control: + - no-cache + content-length: + - '126' + content-type: + - application/json + date: + - Wed, 28 Jul 2021 04:46:27 GMT + expires: + - '-1' + pragma: + - no-cache + server: + - nginx + strict-transport-security: + - max-age=31536000; includeSubDomains + transfer-encoding: + - chunked + vary: + - Accept-Encoding + x-content-type-options: + - nosniff + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + CommandName: + - aks create + Connection: + - keep-alive + ParameterSetName: + - --resource-group --name --ssh-key-value + User-Agent: + - AZURECLI/2.26.1 azsdk-python-azure-mgmt-containerservice/16.0.0 Python/3.8.10 + (Linux-5.4.0-1055-azure-x86_64-with-glibc2.27) + method: GET + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.ContainerService/locations/westus2/operations/d0fb5726-6a67-4e2c-a7fc-725357a19dc6?api-version=2016-03-30 + response: + body: + string: "{\n \"name\": \"2657fbd0-676a-2c4e-a7fc-725357a19dc6\",\n \"status\": + \"InProgress\",\n \"startTime\": \"2021-07-28T04:44:57.5066666Z\"\n }" + headers: + cache-control: + - no-cache + content-length: + - '126' + content-type: + - application/json + date: + - Wed, 28 Jul 2021 04:46:57 GMT + expires: + - '-1' + pragma: + - no-cache + server: + - nginx + strict-transport-security: + - max-age=31536000; includeSubDomains + transfer-encoding: + - chunked + vary: + - Accept-Encoding + x-content-type-options: + - nosniff + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + CommandName: + - aks create + Connection: + - keep-alive + ParameterSetName: + - --resource-group --name --ssh-key-value + User-Agent: + - AZURECLI/2.26.1 azsdk-python-azure-mgmt-containerservice/16.0.0 Python/3.8.10 + (Linux-5.4.0-1055-azure-x86_64-with-glibc2.27) + method: GET + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.ContainerService/locations/westus2/operations/d0fb5726-6a67-4e2c-a7fc-725357a19dc6?api-version=2016-03-30 + response: + body: + string: "{\n \"name\": \"2657fbd0-676a-2c4e-a7fc-725357a19dc6\",\n \"status\": + \"InProgress\",\n \"startTime\": \"2021-07-28T04:44:57.5066666Z\"\n }" + headers: + cache-control: + - no-cache + content-length: + - '126' + content-type: + - application/json + date: + - Wed, 28 Jul 2021 04:47:27 GMT + expires: + - '-1' + pragma: + - no-cache + server: + - nginx + strict-transport-security: + - max-age=31536000; includeSubDomains + transfer-encoding: + - chunked + vary: + - Accept-Encoding + x-content-type-options: + - nosniff + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + CommandName: + - aks create + Connection: + - keep-alive + ParameterSetName: + - --resource-group --name --ssh-key-value + User-Agent: + - AZURECLI/2.26.1 azsdk-python-azure-mgmt-containerservice/16.0.0 Python/3.8.10 + (Linux-5.4.0-1055-azure-x86_64-with-glibc2.27) + method: GET + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.ContainerService/locations/westus2/operations/d0fb5726-6a67-4e2c-a7fc-725357a19dc6?api-version=2016-03-30 + response: + body: + string: "{\n \"name\": \"2657fbd0-676a-2c4e-a7fc-725357a19dc6\",\n \"status\": + \"InProgress\",\n \"startTime\": \"2021-07-28T04:44:57.5066666Z\"\n }" + headers: + cache-control: + - no-cache + content-length: + - '126' + content-type: + - application/json + date: + - Wed, 28 Jul 2021 04:47:58 GMT + expires: + - '-1' + pragma: + - no-cache + server: + - nginx + strict-transport-security: + - max-age=31536000; includeSubDomains + transfer-encoding: + - chunked + vary: + - Accept-Encoding + x-content-type-options: + - nosniff + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + CommandName: + - aks create + Connection: + - keep-alive + ParameterSetName: + - --resource-group --name --ssh-key-value + User-Agent: + - AZURECLI/2.26.1 azsdk-python-azure-mgmt-containerservice/16.0.0 Python/3.8.10 + (Linux-5.4.0-1055-azure-x86_64-with-glibc2.27) + method: GET + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.ContainerService/locations/westus2/operations/d0fb5726-6a67-4e2c-a7fc-725357a19dc6?api-version=2016-03-30 + response: + body: + string: "{\n \"name\": \"2657fbd0-676a-2c4e-a7fc-725357a19dc6\",\n \"status\": + \"InProgress\",\n \"startTime\": \"2021-07-28T04:44:57.5066666Z\"\n }" + headers: + cache-control: + - no-cache + content-length: + - '126' + content-type: + - application/json + date: + - Wed, 28 Jul 2021 04:48:28 GMT + expires: + - '-1' + pragma: + - no-cache + server: + - nginx + strict-transport-security: + - max-age=31536000; includeSubDomains + transfer-encoding: + - chunked + vary: + - Accept-Encoding + x-content-type-options: + - nosniff + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + CommandName: + - aks create + Connection: + - keep-alive + ParameterSetName: + - --resource-group --name --ssh-key-value + User-Agent: + - AZURECLI/2.26.1 azsdk-python-azure-mgmt-containerservice/16.0.0 Python/3.8.10 + (Linux-5.4.0-1055-azure-x86_64-with-glibc2.27) + method: GET + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.ContainerService/locations/westus2/operations/d0fb5726-6a67-4e2c-a7fc-725357a19dc6?api-version=2016-03-30 + response: + body: + string: "{\n \"name\": \"2657fbd0-676a-2c4e-a7fc-725357a19dc6\",\n \"status\": + \"Succeeded\",\n \"startTime\": \"2021-07-28T04:44:57.5066666Z\",\n \"endTime\": + \"2021-07-28T04:48:41.7327851Z\"\n }" + headers: + cache-control: + - no-cache + content-length: + - '170' + content-type: + - application/json + date: + - Wed, 28 Jul 2021 04:48:58 GMT + expires: + - '-1' + pragma: + - no-cache + server: + - nginx + strict-transport-security: + - max-age=31536000; includeSubDomains + transfer-encoding: + - chunked + vary: + - Accept-Encoding + x-content-type-options: + - nosniff + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + CommandName: + - aks create + Connection: + - keep-alive + ParameterSetName: + - --resource-group --name --ssh-key-value + User-Agent: + - AZURECLI/2.26.1 azsdk-python-azure-mgmt-containerservice/16.0.0 Python/3.8.10 + (Linux-5.4.0-1055-azure-x86_64-with-glibc2.27) + method: GET + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.ContainerService/managedClusters/cliakstest000002?api-version=2021-05-01 + response: + body: + string: "{\n \"id\": \"/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/clitest000001/providers/Microsoft.ContainerService/managedClusters/cliakstest000002\",\n + \ \"location\": \"westus2\",\n \"name\": \"cliakstest000002\",\n \"type\": + \"Microsoft.ContainerService/ManagedClusters\",\n \"properties\": {\n \"provisioningState\": + \"Succeeded\",\n \"powerState\": {\n \"code\": \"Running\"\n },\n \"kubernetesVersion\": + \"1.19.11\",\n \"dnsPrefix\": \"cliakstest-clitest3tjig7oyv-79a739\",\n + \ \"fqdn\": \"cliakstest-clitest3tjig7oyv-79a739-d8be4ebc.hcp.westus2.azmk8s.io\",\n + \ \"azurePortalFQDN\": \"cliakstest-clitest3tjig7oyv-79a739-d8be4ebc.portal.hcp.westus2.azmk8s.io\",\n + \ \"agentPoolProfiles\": [\n {\n \"name\": \"nodepool1\",\n \"count\": + 3,\n \"vmSize\": \"Standard_DS2_v2\",\n \"osDiskSizeGB\": 128,\n \"osDiskType\": + \"Managed\",\n \"kubeletDiskType\": \"OS\",\n \"maxPods\": 110,\n + \ \"type\": \"VirtualMachineScaleSets\",\n \"provisioningState\": \"Succeeded\",\n + \ \"powerState\": {\n \"code\": \"Running\"\n },\n \"orchestratorVersion\": + \"1.19.11\",\n \"enableNodePublicIP\": false,\n \"nodeLabels\": {},\n + \ \"mode\": \"System\",\n \"enableEncryptionAtHost\": false,\n \"enableUltraSSD\": + false,\n \"osType\": \"Linux\",\n \"osSKU\": \"Ubuntu\",\n \"nodeImageVersion\": + \"AKSUbuntu-1804gen2containerd-2021.07.03\",\n \"enableFIPS\": false\n + \ }\n ],\n \"linuxProfile\": {\n \"adminUsername\": \"azureuser\",\n + \ \"ssh\": {\n \"publicKeys\": [\n {\n \"keyData\": \"ssh-rsa + AAAAB3NzaC1yc2EAAAADAQABAAACAQCbIg1guRHbI0lV11wWDt1r2cUdcNd27CJsg+SfgC7miZeubtwUhbsPdhMQsfDyhOWHq1+ZL0M+nJZV63d/1dhmhtgyOqejUwrPlzKhydsbrsdUor+JmNJDdW01v7BXHyuymT8G4s09jCasNOwiufbP/qp72ruu0bIA1nySsvlf9pCQAuFkAnVnf/rFhUlOkhtRpwcq8SUNY2zRHR/EKb/4NWY1JzR4sa3q2fWIJdrrX0DvLoa5g9bIEd4Df79ba7v+yiUBOS0zT2ll+z4g9izHK3EO5d8hL4jYxcjKs+wcslSYRWrascfscLgMlMGh0CdKeNTDjHpGPncaf3Z+FwwwjWeuiNBxv7bJo13/8B/098KlVDl4GZqsoBCEjPyJfV6hO0y/LkRGkk7oHWKgeWAfKtfLItRp00eZ4fcJNK9kCaSMmEugoZWcI7NGbZXzqFWqbpRI7NcDP9+WIQ+i9U5vqWsqd/zng4kbuAJ6UuKqIzB0upYrLShfQE3SAck8oaLhJqqq56VfDuASNpJKidV+zq27HfSBmbXnkR/5AK337dc3MXKJypoK/QPMLKUAP5XLPbs+NddJQV7EZXd29DLgp+fRIg3edpKdO7ZErWhv7d+3Kws+e1Y+ypmR2WIVSwVyBEUfgv2C8Ts9gnTF4pNcEY/S2aBicz5Ew2+jdyGNQQ== + test@example.com\\n\"\n }\n ]\n }\n },\n \"servicePrincipalProfile\": + {\n \"clientId\":\"00000000-0000-0000-0000-000000000001\"\n },\n \"nodeResourceGroup\": + \"MC_clitest000001_cliakstest000002_westus2\",\n \"enableRBAC\": true,\n + \ \"networkProfile\": {\n \"networkPlugin\": \"kubenet\",\n \"loadBalancerSku\": + \"Standard\",\n \"loadBalancerProfile\": {\n \"managedOutboundIPs\": + {\n \"count\": 1\n },\n \"effectiveOutboundIPs\": [\n {\n + \ \"id\": \"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/MC_clitest000001_cliakstest000002_westus2/providers/Microsoft.Network/publicIPAddresses/ca29bb81-ab2f-47c8-b1ab-3e110deb82e7\"\n + \ }\n ]\n },\n \"podCidr\": \"10.244.0.0/16\",\n \"serviceCidr\": + \"10.0.0.0/16\",\n \"dnsServiceIP\": \"10.0.0.10\",\n \"dockerBridgeCidr\": + \"172.17.0.1/16\",\n \"outboundType\": \"loadBalancer\"\n },\n \"maxAgentPools\": + 100,\n \"identityProfile\": {\n \"kubeletidentity\": {\n \"resourceId\": + \"/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/MC_clitest000001_cliakstest000002_westus2/providers/Microsoft.ManagedIdentity/userAssignedIdentities/cliakstest000002-agentpool\",\n + \ \"clientId\":\"00000000-0000-0000-0000-000000000001\",\n \"objectId\":\"00000000-0000-0000-0000-000000000001\"\n + \ }\n }\n },\n \"identity\": {\n \"type\": \"SystemAssigned\",\n \"principalId\":\"00000000-0000-0000-0000-000000000001\",\n + \ \"tenantId\": \"72f988bf-86f1-41af-91ab-2d7cd011db47\"\n },\n \"sku\": + {\n \"name\": \"Basic\",\n \"tier\": \"Free\"\n }\n }" + headers: + cache-control: + - no-cache + content-length: + - '3647' + content-type: + - application/json + date: + - Wed, 28 Jul 2021 04:48:58 GMT + expires: + - '-1' + pragma: + - no-cache + server: + - nginx + strict-transport-security: + - max-age=31536000; includeSubDomains + transfer-encoding: + - chunked + vary: + - Accept-Encoding + x-content-type-options: + - nosniff + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + CommandName: + - aks browse + Connection: + - keep-alive + ParameterSetName: + - --resource-group --name --listen-address --listen-port --disable-browser + User-Agent: + - AZURECLI/2.26.1 azsdk-python-azure-mgmt-containerservice/16.0.0 Python/3.8.10 + (Linux-5.4.0-1055-azure-x86_64-with-glibc2.27) + method: GET + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.ContainerService/managedClusters/cliakstest000002?api-version=2021-05-01 + response: + body: + string: "{\n \"id\": \"/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/clitest000001/providers/Microsoft.ContainerService/managedClusters/cliakstest000002\",\n + \ \"location\": \"westus2\",\n \"name\": \"cliakstest000002\",\n \"type\": + \"Microsoft.ContainerService/ManagedClusters\",\n \"properties\": {\n \"provisioningState\": + \"Succeeded\",\n \"powerState\": {\n \"code\": \"Running\"\n },\n \"kubernetesVersion\": + \"1.19.11\",\n \"dnsPrefix\": \"cliakstest-clitest3tjig7oyv-79a739\",\n + \ \"fqdn\": \"cliakstest-clitest3tjig7oyv-79a739-d8be4ebc.hcp.westus2.azmk8s.io\",\n + \ \"azurePortalFQDN\": \"cliakstest-clitest3tjig7oyv-79a739-d8be4ebc.portal.hcp.westus2.azmk8s.io\",\n + \ \"agentPoolProfiles\": [\n {\n \"name\": \"nodepool1\",\n \"count\": + 3,\n \"vmSize\": \"Standard_DS2_v2\",\n \"osDiskSizeGB\": 128,\n \"osDiskType\": + \"Managed\",\n \"kubeletDiskType\": \"OS\",\n \"maxPods\": 110,\n + \ \"type\": \"VirtualMachineScaleSets\",\n \"provisioningState\": \"Succeeded\",\n + \ \"powerState\": {\n \"code\": \"Running\"\n },\n \"orchestratorVersion\": + \"1.19.11\",\n \"enableNodePublicIP\": false,\n \"nodeLabels\": {},\n + \ \"mode\": \"System\",\n \"enableEncryptionAtHost\": false,\n \"enableUltraSSD\": + false,\n \"osType\": \"Linux\",\n \"osSKU\": \"Ubuntu\",\n \"nodeImageVersion\": + \"AKSUbuntu-1804gen2containerd-2021.07.03\",\n \"enableFIPS\": false\n + \ }\n ],\n \"linuxProfile\": {\n \"adminUsername\": \"azureuser\",\n + \ \"ssh\": {\n \"publicKeys\": [\n {\n \"keyData\": \"ssh-rsa + AAAAB3NzaC1yc2EAAAADAQABAAACAQCbIg1guRHbI0lV11wWDt1r2cUdcNd27CJsg+SfgC7miZeubtwUhbsPdhMQsfDyhOWHq1+ZL0M+nJZV63d/1dhmhtgyOqejUwrPlzKhydsbrsdUor+JmNJDdW01v7BXHyuymT8G4s09jCasNOwiufbP/qp72ruu0bIA1nySsvlf9pCQAuFkAnVnf/rFhUlOkhtRpwcq8SUNY2zRHR/EKb/4NWY1JzR4sa3q2fWIJdrrX0DvLoa5g9bIEd4Df79ba7v+yiUBOS0zT2ll+z4g9izHK3EO5d8hL4jYxcjKs+wcslSYRWrascfscLgMlMGh0CdKeNTDjHpGPncaf3Z+FwwwjWeuiNBxv7bJo13/8B/098KlVDl4GZqsoBCEjPyJfV6hO0y/LkRGkk7oHWKgeWAfKtfLItRp00eZ4fcJNK9kCaSMmEugoZWcI7NGbZXzqFWqbpRI7NcDP9+WIQ+i9U5vqWsqd/zng4kbuAJ6UuKqIzB0upYrLShfQE3SAck8oaLhJqqq56VfDuASNpJKidV+zq27HfSBmbXnkR/5AK337dc3MXKJypoK/QPMLKUAP5XLPbs+NddJQV7EZXd29DLgp+fRIg3edpKdO7ZErWhv7d+3Kws+e1Y+ypmR2WIVSwVyBEUfgv2C8Ts9gnTF4pNcEY/S2aBicz5Ew2+jdyGNQQ== + test@example.com\\n\"\n }\n ]\n }\n },\n \"servicePrincipalProfile\": + {\n \"clientId\":\"00000000-0000-0000-0000-000000000001\"\n },\n \"nodeResourceGroup\": + \"MC_clitest000001_cliakstest000002_westus2\",\n \"enableRBAC\": true,\n + \ \"networkProfile\": {\n \"networkPlugin\": \"kubenet\",\n \"loadBalancerSku\": + \"Standard\",\n \"loadBalancerProfile\": {\n \"managedOutboundIPs\": + {\n \"count\": 1\n },\n \"effectiveOutboundIPs\": [\n {\n + \ \"id\": \"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/MC_clitest000001_cliakstest000002_westus2/providers/Microsoft.Network/publicIPAddresses/ca29bb81-ab2f-47c8-b1ab-3e110deb82e7\"\n + \ }\n ]\n },\n \"podCidr\": \"10.244.0.0/16\",\n \"serviceCidr\": + \"10.0.0.0/16\",\n \"dnsServiceIP\": \"10.0.0.10\",\n \"dockerBridgeCidr\": + \"172.17.0.1/16\",\n \"outboundType\": \"loadBalancer\"\n },\n \"maxAgentPools\": + 100,\n \"identityProfile\": {\n \"kubeletidentity\": {\n \"resourceId\": + \"/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/MC_clitest000001_cliakstest000002_westus2/providers/Microsoft.ManagedIdentity/userAssignedIdentities/cliakstest000002-agentpool\",\n + \ \"clientId\":\"00000000-0000-0000-0000-000000000001\",\n \"objectId\":\"00000000-0000-0000-0000-000000000001\"\n + \ }\n }\n },\n \"identity\": {\n \"type\": \"SystemAssigned\",\n \"principalId\":\"00000000-0000-0000-0000-000000000001\",\n + \ \"tenantId\": \"72f988bf-86f1-41af-91ab-2d7cd011db47\"\n },\n \"sku\": + {\n \"name\": \"Basic\",\n \"tier\": \"Free\"\n }\n }" + headers: + cache-control: + - no-cache + content-length: + - '3647' + content-type: + - application/json + date: + - Wed, 28 Jul 2021 04:48:59 GMT + expires: + - '-1' + pragma: + - no-cache + server: + - nginx + strict-transport-security: + - max-age=31536000; includeSubDomains + transfer-encoding: + - chunked + vary: + - Accept-Encoding + x-content-type-options: + - nosniff + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - gzip, deflate + CommandName: + - aks delete + Connection: + - keep-alive + Content-Length: + - '0' + ParameterSetName: + - -g -n --yes --no-wait + User-Agent: + - AZURECLI/2.26.1 azsdk-python-azure-mgmt-containerservice/16.0.0 Python/3.8.10 + (Linux-5.4.0-1055-azure-x86_64-with-glibc2.27) + method: DELETE + uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.ContainerService/managedClusters/cliakstest000002?api-version=2021-05-01 + response: + body: + string: '' + headers: + azure-asyncoperation: + - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.ContainerService/locations/westus2/operations/c92467c3-a53f-4589-a913-dd38f57fdcac?api-version=2016-03-30 + cache-control: + - no-cache + content-length: + - '0' + date: + - Wed, 28 Jul 2021 04:49:01 GMT + expires: + - '-1' + location: + - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.ContainerService/locations/westus2/operationresults/c92467c3-a53f-4589-a913-dd38f57fdcac?api-version=2016-03-30 + pragma: + - no-cache + server: + - nginx + strict-transport-security: + - max-age=31536000; includeSubDomains + x-content-type-options: + - nosniff + x-ms-ratelimit-remaining-subscription-deletes: + - '14999' + status: + code: 202 + message: Accepted +version: 1 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 1b15085fae1..9584b1152fa 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 @@ -4,17 +4,20 @@ # -------------------------------------------------------------------------------------------- import os +import subprocess import tempfile import unittest from knack.util import CLIError +from azure.cli.core.azclierror import CLIInternalError from azure.cli.testsdk import ( ResourceGroupPreparer, RoleBasedServicePrincipalPreparer, VirtualNetworkPreparer, ScenarioTest, live_only) from azure_devtools.scenario_tests import AllowLargeResponse from azure.cli.testsdk.checkers import ( - StringContainCheck, StringContainCheckIgnoreCase) + StringCheck, StringContainCheck, StringContainCheckIgnoreCase) from azure.cli.command_modules.acs._format import version_to_tuple +from azure.cli.command_modules.acs._consts import CONST_KUBE_DASHBOARD_ADDON_NAME from .recording_processors import KeyReplacer from .custom_preparers import AKSCustomResourceGroupPreparer, AKSCustomVirtualNetworkPreparer @@ -36,6 +39,51 @@ def __init__(self, method_name): method_name, recording_processors=[KeyReplacer()] ) + @classmethod + def generate_ssh_keys(cls): + TEST_SSH_KEY_PUB = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQCbIg1guRHbI0lV11wWDt1r2cUdcNd27CJsg+SfgC7miZeubtwUhbsPdhMQsfDyhOWHq1+ZL0M+nJZV63d/1dhmhtgyOqejUwrPlzKhydsbrsdUor+JmNJDdW01v7BXHyuymT8G4s09jCasNOwiufbP/qp72ruu0bIA1nySsvlf9pCQAuFkAnVnf/rFhUlOkhtRpwcq8SUNY2zRHR/EKb/4NWY1JzR4sa3q2fWIJdrrX0DvLoa5g9bIEd4Df79ba7v+yiUBOS0zT2ll+z4g9izHK3EO5d8hL4jYxcjKs+wcslSYRWrascfscLgMlMGh0CdKeNTDjHpGPncaf3Z+FwwwjWeuiNBxv7bJo13/8B/098KlVDl4GZqsoBCEjPyJfV6hO0y/LkRGkk7oHWKgeWAfKtfLItRp00eZ4fcJNK9kCaSMmEugoZWcI7NGbZXzqFWqbpRI7NcDP9+WIQ+i9U5vqWsqd/zng4kbuAJ6UuKqIzB0upYrLShfQE3SAck8oaLhJqqq56VfDuASNpJKidV+zq27HfSBmbXnkR/5AK337dc3MXKJypoK/QPMLKUAP5XLPbs+NddJQV7EZXd29DLgp+fRIg3edpKdO7ZErWhv7d+3Kws+e1Y+ypmR2WIVSwVyBEUfgv2C8Ts9gnTF4pNcEY/S2aBicz5Ew2+jdyGNQQ== test@example.com\n" # pylint: disable=line-too-long + _, pathname = tempfile.mkstemp() + with open(pathname, 'w') as key_file: + key_file.write(TEST_SSH_KEY_PUB) + return pathname + + def generate_vnet_subnet_id(self, resource_group): + vnet_name = self.create_random_name('clivnet', 16) + subnet_name = self.create_random_name('clisubnet', 16) + address_prefix = "192.168.0.0/16" + subnet_prefix = "192.168.0.0/24" + vnet_subnet = self.cmd('az network vnet create -n {} -g {} --address-prefix {} --subnet-name {} --subnet-prefix {}' + .format(vnet_name, resource_group, address_prefix, subnet_name, subnet_prefix)).get_output_in_json() + return vnet_subnet.get("newVNet").get("subnets")[0].get("id") + + def generate_ppg_id(self, resource_group, location): + ppg_name = self.create_random_name('clippg', 16) + ppg = self.cmd('az ppg create -n {} -g {} --location {}' + .format(ppg_name, resource_group, location)).get_output_in_json() + return ppg.get("id") + + def _get_versions(self, location): + """Return the previous and current Kubernetes minor release versions, such as ("1.11.6", "1.12.4").""" + versions = self._get_versions_by_location(location=location) + upgrade_version = versions[0] + # find the first version that doesn't start with the latest major.minor. + prefix = upgrade_version[:upgrade_version.rfind('.')] + create_version = next(x for x in versions if not x.startswith(prefix)) + return create_version, upgrade_version + + def _get_versions_by_location(self, location): + versions = self.cmd( + "az aks get-versions -l {} --query 'orchestrators[].orchestratorVersion'".format(location)).get_output_in_json() + # sort by semantic version, from newest to oldest + versions = sorted(versions, key=version_to_tuple, reverse=True) + return versions + + def generate_user_assigned_identity_resource_id(self, resource_group): + identity_name = self.create_random_name('cli', 16) + identity = self.cmd('az identity create -g {} -n {}'.format( + resource_group, identity_name)).get_output_in_json() + return identity.get("id") + @AllowLargeResponse() @AKSCustomResourceGroupPreparer(random_name_length=17, name_prefix='clitest', location='westus2') @RoleBasedServicePrincipalPreparer() @@ -218,7 +266,7 @@ def test_aks_create_service_no_wait(self, resource_group, resource_group_locatio self.cmd('aks show -g {resource_group} -n {name}', expect_failure=True) @AllowLargeResponse() - @AKSCustomResourceGroupPreparer(random_name_length=17, name_prefix='clitest', location='eastus2euap') + @AKSCustomResourceGroupPreparer(random_name_length=17, name_prefix='clitest', location='eastus2euap', preserve_default_location=True) @RoleBasedServicePrincipalPreparer() def test_aks_create_edge_zone(self, resource_group, resource_group_location, sp_name, sp_password): # reset the count so in replay mode the random names will start with 0 @@ -4324,47 +4372,6 @@ def test_aks_disable_addons_confcom_addon(self, resource_group, resource_group_l self.check('addonProfiles.ACCSGXDevicePlugin.config', None) ]) - @classmethod - def generate_ssh_keys(cls): - TEST_SSH_KEY_PUB = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQCbIg1guRHbI0lV11wWDt1r2cUdcNd27CJsg+SfgC7miZeubtwUhbsPdhMQsfDyhOWHq1+ZL0M+nJZV63d/1dhmhtgyOqejUwrPlzKhydsbrsdUor+JmNJDdW01v7BXHyuymT8G4s09jCasNOwiufbP/qp72ruu0bIA1nySsvlf9pCQAuFkAnVnf/rFhUlOkhtRpwcq8SUNY2zRHR/EKb/4NWY1JzR4sa3q2fWIJdrrX0DvLoa5g9bIEd4Df79ba7v+yiUBOS0zT2ll+z4g9izHK3EO5d8hL4jYxcjKs+wcslSYRWrascfscLgMlMGh0CdKeNTDjHpGPncaf3Z+FwwwjWeuiNBxv7bJo13/8B/098KlVDl4GZqsoBCEjPyJfV6hO0y/LkRGkk7oHWKgeWAfKtfLItRp00eZ4fcJNK9kCaSMmEugoZWcI7NGbZXzqFWqbpRI7NcDP9+WIQ+i9U5vqWsqd/zng4kbuAJ6UuKqIzB0upYrLShfQE3SAck8oaLhJqqq56VfDuASNpJKidV+zq27HfSBmbXnkR/5AK337dc3MXKJypoK/QPMLKUAP5XLPbs+NddJQV7EZXd29DLgp+fRIg3edpKdO7ZErWhv7d+3Kws+e1Y+ypmR2WIVSwVyBEUfgv2C8Ts9gnTF4pNcEY/S2aBicz5Ew2+jdyGNQQ== test@example.com\n" # pylint: disable=line-too-long - _, pathname = tempfile.mkstemp() - with open(pathname, 'w') as key_file: - key_file.write(TEST_SSH_KEY_PUB) - return pathname - - def generate_vnet_subnet_id(self, resource_group): - vnet_name = self.create_random_name('clivnet', 16) - subnet_name = self.create_random_name('clisubnet', 16) - address_prefix = "192.168.0.0/16" - subnet_prefix = "192.168.0.0/24" - vnet_subnet = self.cmd('az network vnet create -n {} -g {} --address-prefix {} --subnet-name {} --subnet-prefix {}' - .format(vnet_name, resource_group, address_prefix, subnet_name, subnet_prefix)).get_output_in_json() - return vnet_subnet.get("newVNet").get("subnets")[0].get("id") - - def generate_ppg_id(self, resource_group, location): - ppg_name = self.create_random_name('clippg', 16) - ppg = self.cmd('az ppg create -n {} -g {} --location {}' - .format(ppg_name, resource_group, location)).get_output_in_json() - return ppg.get("id") - - def _get_versions(self, location): - """Return the previous and current Kubernetes minor release versions, such as ("1.11.6", "1.12.4").""" - versions = self.cmd( - "az aks get-versions -l westus2 --query 'orchestrators[].orchestratorVersion'").get_output_in_json() - # sort by semantic version, from newest to oldest - versions = sorted(versions, key=version_to_tuple, reverse=True) - upgrade_version = versions[0] - # find the first version that doesn't start with the latest major.minor. - prefix = upgrade_version[:upgrade_version.rfind('.')] - create_version = next(x for x in versions if not x.startswith(prefix)) - return create_version, upgrade_version - - def generate_user_assigned_identity_resource_id(self, resource_group): - identity_name = self.create_random_name('cli', 16) - identity = self.cmd('az identity create -g {} -n {}'.format( - resource_group, identity_name)).get_output_in_json() - return identity.get("id") - @AllowLargeResponse() @AKSCustomResourceGroupPreparer(random_name_length=17, name_prefix='clitest', location='westus2') def test_aks_create_fqdn_subdomain(self, resource_group, resource_group_location): @@ -4605,3 +4612,102 @@ def test_aks_enable_utlra_ssd(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') + def test_aks_browse(self, resource_group, resource_group_location): + aks_name = self.create_random_name('cliakstest', 16) + self.kwargs.update({ + 'name': aks_name, + 'resource_group': resource_group, + 'ssh_key_value': self.generate_ssh_keys().replace('\\', '\\\\') + }) + + # create + create_cmd = 'aks create --resource-group={resource_group} --name={name} --ssh-key-value={ssh_key_value}' + self.cmd(create_cmd, checks=[ + self.check('provisioningState', 'Succeeded') + ]) + + # test aks browse cmd + subscription_id = self.get_subscription_id() + browse_cmd = 'aks browse --resource-group={resource_group} --name={name} --listen-address=127.0.0.1 --listen-port=8080 --disable-browser' + self.cmd(browse_cmd, checks=[ + StringCheck("Kubernetes resources view on https://portal.azure.com/#resource/subscriptions/{}/resourceGroups/{}/providers/Microsoft.ContainerService/managedClusters/{}/workloads".format(subscription_id, resource_group, aks_name)) + ]) + + # delete + self.cmd( + 'aks delete -g {resource_group} -n {name} --yes --no-wait', checks=[self.is_empty()]) + + # live only for the following reasons + # 1. execute `kubectl get pods` in subprocess and cannot be mocked by testsdk + # 2. rely on some environment variable to indicate the execution is under test environment (e.g. "PYTEST_CURRENT_TEST") + @live_only() + @AllowLargeResponse() + @AKSCustomResourceGroupPreparer(random_name_length=17, name_prefix='clitest', location='westus2') + def test_aks_browse_legacy(self, resource_group, resource_group_location): + aks_name = self.create_random_name('cliakstest', 16) + self.kwargs.update({ + 'name': aks_name, + 'resource_group': resource_group, + 'ssh_key_value': self.generate_ssh_keys().replace('\\', '\\\\') + }) + + # find the latest version lower than 1.19.0 + versions = self._get_versions_by_location(resource_group_location) + try: + legacy_version = next(x for x in versions if version_to_tuple(x) < version_to_tuple('1.19.0')) + except StopIteration: + raise CLIInternalError("No version lower than '1.19.0' is supported in region '{}'!".format(resource_group_location)) + + self.kwargs.update({ + 'k8s_version': legacy_version, + 'dashboard': "kube-dashboard", + + }) + # create legacy cluster and enable kube-dashboard addon + create_cmd = 'aks create --resource-group={resource_group} --name={name} --ssh-key-value={ssh_key_value} ' \ + '-k {k8s_version} -a {dashboard}' + self.cmd(create_cmd, checks=[ + self.check('provisioningState', 'Succeeded'), + self.check('kubernetesVersion', legacy_version), + self.check('addonProfiles.{}.enabled'.format(CONST_KUBE_DASHBOARD_ADDON_NAME), True) + ]) + + # install kubectl + try: + subprocess.call(["az", "aks", "install-cli"]) + except subprocess.CalledProcessError as err: + raise CLIInternalError("Failed to install kubectl with error: '{}'!".format(err)) + + # test aks browse cmd + browse_cmd = 'aks browse --resource-group={resource_group} --name={name} --listen-address=1.1.1.1 --listen-port=8080 --disable-browser' + self.cmd(browse_cmd, checks=[ + StringCheck("Test Invalid Address! Test Passed!") + ]) + + # delete + self.cmd( + 'aks delete -g {resource_group} -n {name} --yes --no-wait', checks=[self.is_empty()]) + + # live only, otherwise the current recording mechanism will also record the binary files of + # kubectl and kubelogin resulting in the cassette file size exceeding 100MB + @live_only() + def test_aks_install_kubectl(self): + ctl_fd, ctl_temp_file = tempfile.mkstemp() + login_fd, login_temp_file = tempfile.mkstemp() + version = "latest" + install_cmd = 'aks install-cli --client-version={} --install-location={} --base-src-url={} ' \ + '--kubelogin-version={} --kubelogin-install-location={} --kubelogin-base-src-url={}'.format(version, ctl_temp_file, "", version, login_temp_file, "") + + # install kubectl & kubelogin + try: + self.cmd(install_cmd, checks=[self.is_empty()]) + self.assertGreater(os.path.getsize(ctl_temp_file), 0) + self.assertGreater(os.path.getsize(login_temp_file), 0) + finally: + os.close(ctl_fd) + os.close(login_fd) + os.remove(ctl_temp_file) + os.remove(login_temp_file)