Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Upgrade Helm for connectedk8s #6915

Merged
merged 14 commits into from
Dec 14, 2023
Merged
4 changes: 4 additions & 0 deletions src/connectedk8s/HISTORY.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

Release History
===============
1.6.0
++++++

* Updated Helm from 3.6.3 to 3.12.2

1.5.6
++++++
Expand Down
3 changes: 2 additions & 1 deletion src/connectedk8s/azext_connectedk8s/_constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@
Kubectl_Cluster_Info_Failed_Fault_Type = "Error while doing kubectl cluster-info"
Fetch_Kubectl_Cluster_Info_Fault_Type = "Error occured while fetching cluster-info"
Fetch_Kubectl_Cluster_Info = "kubectl_cluster_info"
Operation_Not_Supported_Fault_Type = "This CLI version does not support this operation for Agents older than v1.14"
Failed_To_Change_Telemetry_Push_Interval = "Failed to change the telemetry push interval to 1 hr"
Diagnostic_Check_Passed = "Passed"
Diagnostic_Check_Failed = "Failed"
Expand Down Expand Up @@ -232,5 +233,5 @@
CSP_Storage_Url_Mooncake = "https://k8sconnectcsp.blob.core.chinacloudapi.cn"
CSP_Storage_Url_Fairfax = "https://k8sconnectcsp.azureedge.us"
HELM_STORAGE_URL = "https://k8connecthelm.azureedge.net"
HELM_VERSION = 'v3.6.3'
HELM_VERSION = 'v3.12.2'
Download_And_Install_Kubectl_Fault_Type = "Failed to download and install kubectl"
2 changes: 1 addition & 1 deletion src/connectedk8s/azext_connectedk8s/_precheckutils.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ def executing_cluster_diagnostic_checks_job(corev1_api_instance, batchv1_api_ins
telemetry.set_exception(exception=error_kubectl_delete_helm.decode("ascii"), fault_type=consts.Cluster_Diagnostic_Checks_Release_Cleanup_Failed, summary="Error while executing cluster diagnostic checks Job")
return

chart_path = azext_utils.get_chart_path(consts.Cluster_Diagnostic_Checks_Job_Registry_Path, kube_config, kube_context, helm_client_location, consts.Pre_Onboarding_Helm_Charts_Folder_Name, consts.Pre_Onboarding_Helm_Charts_Release_Name)
chart_path = azext_utils.get_chart_path(consts.Cluster_Diagnostic_Checks_Job_Registry_Path, kube_config, kube_context, helm_client_location, consts.Pre_Onboarding_Helm_Charts_Folder_Name, consts.Pre_Onboarding_Helm_Charts_Release_Name, False)
kitnhl marked this conversation as resolved.
Show resolved Hide resolved

helm_install_release_cluster_diagnostic_checks(chart_path, location, http_proxy, https_proxy, no_proxy, proxy_cert, azure_cloud, kube_config, kube_context, helm_client_location)

Expand Down
43 changes: 19 additions & 24 deletions src/connectedk8s/azext_connectedk8s/_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@
import sys
import os
import shutil
from packaging import version
import subprocess
from subprocess import Popen, PIPE
import time
import requests
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry
import json
Expand Down Expand Up @@ -92,20 +92,16 @@ def validate_custom_token(cmd, resource_group_name, location):
return False, location


def get_chart_path(registry_path, kube_config, kube_context, helm_client_location, chart_folder_name='AzureArcCharts', chart_name='azure-arc-k8sagents'):
# Pulling helm chart from registry
os.environ['HELM_EXPERIMENTAL_OCI'] = '1'
pull_helm_chart(registry_path, kube_config, kube_context, helm_client_location, chart_name)

# Exporting helm chart after cleanup
def get_chart_path(registry_path, kube_config, kube_context, helm_client_location, chart_folder_name='AzureArcCharts', chart_name='azure-arc-k8sagents', new_path=True):
# Exporting Helm chart
chart_export_path = os.path.join(os.path.expanduser('~'), '.azure', chart_folder_name)
try:
if os.path.isdir(chart_export_path):
shutil.rmtree(chart_export_path)
except:
logger.warning("Unable to cleanup the {} already present on the machine. In case of failure, please cleanup the directory '{}' and try again.".format(chart_folder_name, chart_export_path))

export_helm_chart(registry_path, chart_export_path, kube_config, kube_context, helm_client_location, chart_name)
pull_helm_chart(registry_path, chart_export_path, kube_config, kube_context, helm_client_location, new_path, chart_name)

# Returning helm chart path
helm_chart_path = os.path.join(chart_export_path, chart_name)
Expand All @@ -117,8 +113,21 @@ def get_chart_path(registry_path, kube_config, kube_context, helm_client_locatio
return chart_path


def pull_helm_chart(registry_path, kube_config, kube_context, helm_client_location, chart_name='azure-arc-k8sagents', retry_count=5, retry_delay=3):
cmd_helm_chart_pull = [helm_client_location, "chart", "pull", registry_path]
def pull_helm_chart(registry_path, chart_export_path, kube_config, kube_context, helm_client_location, new_path, chart_name='azure-arc-k8sagents', retry_count=5, retry_delay=3):
chart_url = registry_path.split(':')[0]
chart_version = registry_path.split(':')[1]

if new_path:
if (version.parse(chart_version) < version.parse("1.14.0")):
error_summary = "This CLI version does not support upgrading to Agents versions older than v1.14"
telemetry.set_exception(exception='Operation not supported on older Agents', fault_type=consts.Operation_Not_Supported_Fault_Type, summary=error_summary)
raise ClientRequestError(error_summary, recommendation="Please select an agent-version >= v1.14 to upgrade to using 'az connectedk8s upgrade -g <rg_name> -n <cluster_name> --agent-version <at-least-1.14>'.")

base_path = os.path.dirname(chart_url)
image_name = os.path.basename(chart_url)
chart_url = base_path + '/v2/' + image_name

cmd_helm_chart_pull = [helm_client_location, "pull", "oci://" + chart_url, "--untar", "--untardir", chart_export_path, "--version", chart_version]
if kube_config:
cmd_helm_chart_pull.extend(["--kubeconfig", kube_config])
if kube_context:
Expand All @@ -136,20 +145,6 @@ def pull_helm_chart(registry_path, kube_config, kube_context, helm_client_locati
break


def export_helm_chart(registry_path, chart_export_path, kube_config, kube_context, helm_client_location, chart_name='azure-arc-k8sagents'):
cmd_helm_chart_export = [helm_client_location, "chart", "export", registry_path, "--destination", chart_export_path]
if kube_config:
cmd_helm_chart_export.extend(["--kubeconfig", kube_config])
if kube_context:
cmd_helm_chart_export.extend(["--kube-context", kube_context])
response_helm_chart_export = subprocess.Popen(cmd_helm_chart_export, stdout=PIPE, stderr=PIPE)
_, error_helm_chart_export = response_helm_chart_export.communicate()
if response_helm_chart_export.returncode != 0:
telemetry.set_exception(exception=error_helm_chart_export.decode("ascii"), fault_type=consts.Export_HelmChart_Fault_Type,
summary='Unable to export {} helm chart from the registry'.format(chart_name))
raise CLIInternalError("Unable to export {} helm chart from the registry '{}': ".format(chart_name, registry_path) + error_helm_chart_export.decode("ascii"))


def save_cluster_diagnostic_checks_pod_description(corev1_api_instance, batchv1_api_instance, helm_client_location, kubectl_client_location, kube_config, kube_context, filepath_with_timestamp, storage_space_available):
try:
job_name = "cluster-diagnostic-checks-job"
Expand Down
23 changes: 20 additions & 3 deletions src/connectedk8s/azext_connectedk8s/custom.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import json
import tempfile
import time
from packaging import version
import subprocess
from subprocess import Popen, PIPE, run, STDOUT, call, DEVNULL
from base64 import b64encode, b64decode
Expand Down Expand Up @@ -498,14 +499,17 @@ def install_helm_client():
telemetry.add_extension_event('connectedk8s', {'Context.Default.AzureCLI.MachineType': machine_type})

# Set helm binary download & install locations
# TODO: [Kit] Move helm binaries to internal endpoints
kitnhl marked this conversation as resolved.
Show resolved Hide resolved
if(operating_system == 'windows'):
download_location_string = f'.azure\\helm\\{consts.HELM_VERSION}\\helm-{consts.HELM_VERSION}-{operating_system}-amd64.zip'
install_location_string = f'.azure\\helm\\{consts.HELM_VERSION}\\{operating_system}-amd64\\helm.exe'
requestUri = f'{consts.HELM_STORAGE_URL}/helm/helm-{consts.HELM_VERSION}-{operating_system}-amd64.zip'
# requestUri = f'{consts.HELM_STORAGE_URL}/helm/helm-{consts.HELM_VERSION}-{operating_system}-amd64.zip'
requestUri = f'https://get.helm.sh/helm-{consts.HELM_VERSION}-{operating_system}-amd64.zip'
elif(operating_system == 'linux' or operating_system == 'darwin'):
download_location_string = f'.azure/helm/{consts.HELM_VERSION}/helm-{consts.HELM_VERSION}-{operating_system}-amd64.tar.gz'
install_location_string = f'.azure/helm/{consts.HELM_VERSION}/{operating_system}-amd64/helm'
requestUri = f'{consts.HELM_STORAGE_URL}/helm/helm-{consts.HELM_VERSION}-{operating_system}-amd64.tar.gz'
# requestUri = f'{consts.HELM_STORAGE_URL}/helm/helm-{consts.HELM_VERSION}-{operating_system}-amd64.tar.gz'
requestUri = f'https://get.helm.sh/helm-{consts.HELM_VERSION}-{operating_system}-amd64.tar.gz'
else:
telemetry.set_exception(exception='Unsupported OS for installing helm client', fault_type=consts.Helm_Unsupported_OS_Fault_Type,
summary=f'{operating_system} is not supported for installing helm client')
Expand Down Expand Up @@ -1073,6 +1077,8 @@ def update_connected_cluster(cmd, client, resource_group_name, cluster_name, htt
agent_version = connected_cluster.agent_version
registry_path = reg_path_array[0] + ":" + agent_version

check_operation_support("update (properties)", agent_version)

telemetry.add_extension_event('connectedk8s', {'Context.Default.AzureCLI.AgentVersion': agent_version})

# Get Helm chart path
Expand Down Expand Up @@ -1168,7 +1174,7 @@ def upgrade_agents(cmd, client, resource_group_name, cluster_name, kube_config=N
# Install helm client
helm_client_location = install_helm_client()

# Check Release Existance
# Check Release Existence
release_namespace = utils.get_release_namespace(kube_config, kube_context, helm_client_location)
if release_namespace:
# Loading config map
Expand Down Expand Up @@ -1467,6 +1473,8 @@ def enable_features(cmd, client, resource_group_name, cluster_name, features, ku
agent_version = connected_cluster.agent_version
registry_path = reg_path_array[0] + ":" + agent_version

check_operation_support("enable-features", agent_version)

telemetry.add_extension_event('connectedk8s', {'Context.Default.AzureCLI.AgentVersion': agent_version})

# Get Helm chart path
Expand Down Expand Up @@ -1596,6 +1604,8 @@ def get_chart_and_disable_features(cmd, connected_cluster, kube_config, kube_con
agent_version = connected_cluster.agent_version
registry_path = reg_path_array[0] + ":" + agent_version

check_operation_support("disable-features", agent_version)

telemetry.add_extension_event('connectedk8s', {'Context.Default.AzureCLI.AgentVersion': agent_version})

# Get Helm chart path
Expand Down Expand Up @@ -2466,3 +2476,10 @@ def crd_cleanup_force_delete(kubectl_client_location, kube_config, kube_context)
patch_cmd.extend(["--context", kube_context])
output_patch_cmd = Popen(patch_cmd, stdout=PIPE, stderr=PIPE)
_, error_helm_delete = output_patch_cmd.communicate()


def check_operation_support(operation_name, agent_version):
error_summary = 'This CLI version does not support {} for Agents older than v1.14'.format(operation_name)
if (version.parse(agent_version) < version.parse("1.14.0")):
telemetry.set_exception(exception='Operation not supported on older Agents', fault_type=consts.Operation_Not_Supported_Fault_Type, summary=error_summary)
raise ClientRequestError(error_summary, recommendation="Please upgrade to the latest version of the Agents using 'az connectedk8s upgrade -g <rg_name> -n <cluster_name>'.")
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,8 @@ class Connectedk8sScenarioTest(LiveScenarioTest):
@live_only()
@ResourceGroupPreparer(name_prefix='conk8stest', location=CONFIG['location'], random_name_length=16)
def test_connect(self,resource_group):
# os.environ.setdefault('HELMREGISTRY', 'mcr.microsoft.com/azurearck8s/batch1/preview/azure-arc-k8sagents:1.1.59-preview')

managed_cluster_name = self.create_random_name(prefix='test-connect', length=24)
kubeconfig="%s" % (_get_test_data_file(managed_cluster_name + '-config.yaml'))
self.kwargs.update({
Expand Down Expand Up @@ -178,7 +180,6 @@ def test_connect(self,resource_group):
@live_only()
@ResourceGroupPreparer(name_prefix='conk8stest', location=CONFIG['location'], random_name_length=16)
def test_forcedelete(self,resource_group):

managed_cluster_name = self.create_random_name(prefix='test-force-delete', length=24)
kubeconfig="%s" % (_get_test_data_file(managed_cluster_name + '-config.yaml'))
self.kwargs.update({
Expand Down Expand Up @@ -218,6 +219,7 @@ def test_forcedelete(self,resource_group):
@live_only()
@ResourceGroupPreparer(name_prefix='conk8stest', location=CONFIG['location'], random_name_length=16)
def test_enable_disable_features(self,resource_group):
# os.environ.setdefault('HELMREGISTRY', 'mcr.microsoft.com/azurearck8s/batch1/preview/azure-arc-k8sagents:1.1.59-preview')

managed_cluster_name = self.create_random_name(prefix='test-enable-disable', length=24)
kubeconfig="%s" % (_get_test_data_file(managed_cluster_name + '-config.yaml'))
Expand Down Expand Up @@ -319,7 +321,6 @@ def test_enable_disable_features(self,resource_group):
@live_only()
@ResourceGroupPreparer(name_prefix='conk8stest', location=CONFIG['location'], random_name_length=16)
def test_connectedk8s_list(self,resource_group):

managed_cluster_name = self.create_random_name(prefix='first', length=24)
managed_cluster_name_second = self.create_random_name(prefix='second', length=24)
kubeconfig="%s" % (_get_test_data_file(managed_cluster_name + '-config.yaml'))
Expand Down Expand Up @@ -393,6 +394,7 @@ def test_connectedk8s_list(self,resource_group):
@live_only()
@ResourceGroupPreparer(name_prefix='conk8stest', location=CONFIG['location'], random_name_length=16)
def test_upgrade(self,resource_group):
# os.environ.setdefault('HELMREGISTRY', 'mcr.microsoft.com/azurearck8s/batch1/preview/azure-arc-k8sagents:1.1.59-preview')

managed_cluster_name = self.create_random_name(prefix='test-upgrade', length=24)
kubeconfig="%s" % (_get_test_data_file(managed_cluster_name + '-config.yaml'))
Expand Down Expand Up @@ -459,6 +461,8 @@ def test_upgrade(self,resource_group):
@live_only()
@ResourceGroupPreparer(name_prefix='conk8stest', location=CONFIG['location'], random_name_length=16)
def test_update(self,resource_group):
# os.environ.setdefault('HELMREGISTRY', 'mcr.microsoft.com/azurearck8s/batch1/preview/azure-arc-k8sagents:1.1.59-preview')

managed_cluster_name = self.create_random_name(prefix='test-update', length=24)
kubeconfig="%s" % (_get_test_data_file(managed_cluster_name + '-config.yaml'))
self.kwargs.update({
Expand Down
2 changes: 1 addition & 1 deletion src/connectedk8s/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
# TODO: Confirm this is the right version number you want and it matches your
# HISTORY.rst entry.

VERSION = '1.5.6'
VERSION = '1.6.0'

# The full list of classifiers is available at
# https://pypi.python.org/pypi?%3Aaction=list_classifiers
Expand Down