diff --git a/src/connectedk8s/HISTORY.rst b/src/connectedk8s/HISTORY.rst index 8cf543ef9f0..69a6c7c3e6b 100644 --- a/src/connectedk8s/HISTORY.rst +++ b/src/connectedk8s/HISTORY.rst @@ -2,6 +2,11 @@ Release History =============== +1.2.4 +++++++ + +* Custom cert changes, using "userValues.txt" for existing values in update command instead of --reuse-values, fix to wait for LRO to complete before starting agent installation/deletion + 1.2.3 ++++++ diff --git a/src/connectedk8s/azext_connectedk8s/_params.py b/src/connectedk8s/azext_connectedk8s/_params.py index 77223211f31..2621410e70e 100644 --- a/src/connectedk8s/azext_connectedk8s/_params.py +++ b/src/connectedk8s/azext_connectedk8s/_params.py @@ -44,7 +44,7 @@ def load_arguments(self, _): c.argument('https_proxy', options_list=['--proxy-https'], arg_group='Proxy', help='Https proxy URL to be used.') c.argument('http_proxy', options_list=['--proxy-http'], arg_group='Proxy', help='Http proxy URL to be used.') c.argument('no_proxy', options_list=['--proxy-skip-range'], arg_group='Proxy', help='List of URLs/CIDRs for which proxy should not to be used.') - c.argument('proxy_cert', options_list=['--proxy-cert'], arg_group='Proxy', type=file_type, completer=FilesCompleter(), help='Path to the certificate file for proxy') + c.argument('proxy_cert', options_list=['--proxy-cert'], arg_group='Proxy', type=file_type, completer=FilesCompleter(), help='Path to the any additional certificate file (for proxy as well)') c.argument('disable_proxy', options_list=['--disable-proxy'], arg_group='Proxy', action='store_true', help='Disables proxy settings for agents') c.argument('auto_upgrade', options_list=['--auto-upgrade'], help='Flag to enable/disable auto upgrade of arc agents. By default, auto upgrade of agents is enabled.', arg_type=get_enum_type(["true", "false"])) diff --git a/src/connectedk8s/azext_connectedk8s/_utils.py b/src/connectedk8s/azext_connectedk8s/_utils.py index 3ec025c2d76..4c87a356f03 100644 --- a/src/connectedk8s/azext_connectedk8s/_utils.py +++ b/src/connectedk8s/azext_connectedk8s/_utils.py @@ -322,6 +322,7 @@ def helm_install_release(chart_path, subscription_id, kubernetes_distro, kuberne cmd_helm_install.extend(["--set", "global.noProxy={}".format(no_proxy)]) if proxy_cert: cmd_helm_install.extend(["--set-file", "global.proxyCert={}".format(proxy_cert)]) + cmd_helm_install.extend(["--set", "global.isCustomCert={}".format(True)]) if https_proxy or http_proxy or no_proxy: cmd_helm_install.extend(["--set", "global.isProxyEnabled={}".format(True)]) if kube_config: diff --git a/src/connectedk8s/azext_connectedk8s/custom.py b/src/connectedk8s/azext_connectedk8s/custom.py index f66114fc499..4fde18967f2 100644 --- a/src/connectedk8s/azext_connectedk8s/custom.py +++ b/src/connectedk8s/azext_connectedk8s/custom.py @@ -181,7 +181,8 @@ def create_connectedk8s(cmd, client, resource_group_name, cluster_name, https_pr except Exception as e: # pylint: disable=broad-except utils.arm_exception_handler(e, consts.Get_ConnectedCluster_Fault_Type, 'Failed to check if connected cluster resource already exists.') cc = generate_request_payload(configuration, location, public_key, tags, kubernetes_distro, kubernetes_infra) - create_cc_resource(client, resource_group_name, cluster_name, cc, no_wait) + cc_response = create_cc_resource(client, resource_group_name, cluster_name, cc, no_wait).result() + return cc_response else: telemetry.set_exception(exception='The kubernetes cluster is already onboarded', fault_type=consts.Cluster_Already_Onboarded_Fault_Type, summary='Kubernetes cluster already onboarded') @@ -281,7 +282,7 @@ def create_connectedk8s(cmd, client, resource_group_name, cluster_name, https_pr cc = generate_request_payload(configuration, location, public_key, tags, kubernetes_distro, kubernetes_infra) # Create connected cluster resource - put_cc_response = create_cc_resource(client, resource_group_name, cluster_name, cc, no_wait) + put_cc_response = create_cc_resource(client, resource_group_name, cluster_name, cc, no_wait).result() # Checking if custom locations rp is registered and fetching oid if it is registered enable_custom_locations, custom_locations_oid = check_cl_registration_and_get_oid(cmd, cl_oid) @@ -679,7 +680,7 @@ def delete_connectedk8s(cmd, client, resource_group_name, cluster_name, release_namespace = get_release_namespace(kube_config, kube_context, helm_client_location) if not release_namespace: - delete_cc_resource(client, resource_group_name, cluster_name, no_wait) + delete_cc_resource(client, resource_group_name, cluster_name, no_wait).result() return # Loading config map @@ -704,7 +705,7 @@ def delete_connectedk8s(cmd, client, resource_group_name, cluster_name, summary='The resource cannot be deleted as user is using proxy kubeconfig.') raise ClientRequestError("az connectedk8s delete is not supported when using the Cluster Connect kubeconfig.", recommendation="Run the az connectedk8s delete command with your kubeconfig file pointing to the actual Kubernetes cluster to ensure that the agents are cleaned up successfully as part of the delete command.") - delete_cc_resource(client, resource_group_name, cluster_name, no_wait) + delete_cc_resource(client, resource_group_name, cluster_name, no_wait).result() else: telemetry.set_exception(exception='Unable to delete connected cluster', fault_type=consts.Bad_DeleteRequest_Fault_Type, summary='The resource cannot be deleted as kubernetes cluster is onboarded with some other resource id') @@ -752,9 +753,9 @@ def create_cc_resource(client, resource_group_name, cluster_name, cc, no_wait): def delete_cc_resource(client, resource_group_name, cluster_name, no_wait): try: - sdk_no_wait(no_wait, client.begin_delete, - resource_group_name=resource_group_name, - cluster_name=cluster_name) + return sdk_no_wait(no_wait, client.begin_delete, + resource_group_name=resource_group_name, + cluster_name=cluster_name) except Exception as e: utils.arm_exception_handler(e, consts.Delete_ConnectedCluster_Fault_Type, 'Unable to delete connected cluster resource') @@ -801,7 +802,7 @@ def update_agents(cmd, client, resource_group_name, cluster_name, https_proxy="" if https_proxy == "" and http_proxy == "" and no_proxy == "" and proxy_cert == "" and not disable_proxy and not auto_upgrade: raise RequiredArgumentMissingError(consts.No_Param_Error) - if (https_proxy or http_proxy or no_proxy or proxy_cert) and disable_proxy: + if (https_proxy or http_proxy or no_proxy) and disable_proxy: raise MutuallyExclusiveArgumentError(consts.EnableProxy_Conflict_Error) # Checking whether optional extra values file has been provided. @@ -879,9 +880,26 @@ def update_agents(cmd, client, resource_group_name, cluster_name, https_proxy="" # Get Helm chart path chart_path = utils.get_chart_path(registry_path, kube_config, kube_context, helm_client_location) + cmd_helm_values = [helm_client_location, "get", "values", "azure-arc", "--namespace", release_namespace] + if kube_config: + cmd_helm_values.extend(["--kubeconfig", kube_config]) + if kube_context: + cmd_helm_values.extend(["--kube-context", kube_context]) + + user_values_location = os.path.join(os.path.expanduser('~'), '.azure', 'userValues.txt') + existing_user_values = open(user_values_location, 'w+') + response_helm_values_get = Popen(cmd_helm_values, stdout=existing_user_values, stderr=PIPE) + _, error_helm_get_values = response_helm_values_get.communicate() + if response_helm_values_get.returncode != 0: + if ('forbidden' in error_helm_get_values.decode("ascii") or 'timed out waiting for the condition' in error_helm_get_values.decode("ascii")): + telemetry.set_user_fault() + telemetry.set_exception(exception=error_helm_get_values.decode("ascii"), fault_type=consts.Get_Helm_Values_Failed, + summary='Error while doing helm get values azure-arc') + raise CLIInternalError(str.format(consts.Update_Agent_Failure, error_helm_get_values.decode("ascii"))) + cmd_helm_upgrade = [helm_client_location, "upgrade", "azure-arc", chart_path, "--namespace", release_namespace, - "--reuse-values", - "--wait", "--output", "json"] + "-f", + user_values_location, "--wait", "--output", "json"] if values_file_provided: cmd_helm_upgrade.extend(["-f", values_file]) if auto_upgrade is not None: @@ -898,6 +916,7 @@ def update_agents(cmd, client, resource_group_name, cluster_name, https_proxy="" cmd_helm_upgrade.extend(["--set", "global.isProxyEnabled={}".format(False)]) if proxy_cert: cmd_helm_upgrade.extend(["--set-file", "global.proxyCert={}".format(proxy_cert)]) + cmd_helm_upgrade.extend(["--set", "global.isCustomCert={}".format(True)]) if kube_config: cmd_helm_upgrade.extend(["--kubeconfig", kube_config]) if kube_context: @@ -909,8 +928,15 @@ def update_agents(cmd, client, resource_group_name, cluster_name, https_proxy="" telemetry.set_user_fault() telemetry.set_exception(exception=error_helm_upgrade.decode("ascii"), fault_type=consts.Install_HelmRelease_Fault_Type, summary='Unable to install helm release') + try: + os.remove(user_values_location) + except OSError: + pass raise CLIInternalError(str.format(consts.Update_Agent_Failure, error_helm_upgrade.decode("ascii"))) - + try: + os.remove(user_values_location) + except OSError: + pass return str.format(consts.Update_Agent_Success, connected_cluster.name) diff --git a/src/connectedk8s/setup.py b/src/connectedk8s/setup.py index 66dc7977baa..df92c4d6167 100644 --- a/src/connectedk8s/setup.py +++ b/src/connectedk8s/setup.py @@ -17,7 +17,7 @@ # TODO: Confirm this is the right version number you want and it matches your # HISTORY.rst entry. -VERSION = '1.2.3' +VERSION = '1.2.4' # The full list of classifiers is available at # https://pypi.python.org/pypi?%3Aaction=list_classifiers