Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion src/connectedk8s/HISTORY.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@
Release History
===============

0.2.3
++++++
* `az connectedk8s connect`: Modified CLI params for proxy
* `az connectedk8s update`: Added update command

0.2.2
++++++
* `az connectedk8s connect`: Added CLI params to support proxy.
Expand All @@ -18,4 +23,4 @@ Release History

0.1.5
++++++
* Initial release.
* Initial release.
38 changes: 38 additions & 0 deletions src/connectedk8s/azext_connectedk8s/_constants.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# --------------------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License.txt in the project root for license information.
# --------------------------------------------------------------------------------------------


Invalid_Location_Fault_Type = 'location-validation-error'
Load_Kubeconfig_Fault_Type = 'kubeconfig-load-error'
Read_ConfigMap_Fault_Type = 'configmap-read-error'
Create_ConnectedCluster_Fault_Type = 'connected-cluster-create-error'
Delete_ConnectedCluster_Fault_Type = 'connected-cluster-delete-error'
Bad_DeleteRequest_Fault_Type = 'bad-delete-request-error'
Cluster_Already_Onboarded_Fault_Type = 'cluster-already-onboarded-error'
Resource_Already_Exists_Fault_Type = 'resource-already-exists-error'
Resource_Does_Not_Exist_Fault_Type = 'resource-does-not-exist-error'
Create_ResourceGroup_Fault_Type = 'resource-group-creation-error'
Add_HelmRepo_Fault_Type = 'helm-repo-add-error'
List_HelmRelease_Fault_Type = 'helm-list-release-error'
KeyPair_Generate_Fault_Type = 'keypair-generation-error'
PublicKey_Export_Fault_Type = 'publickey-export-error'
PrivateKey_Export_Fault_Type = 'privatekey-export-error'
Install_HelmRelease_Fault_Type = 'helm-release-install-error'
Delete_HelmRelease_Fault_Type = 'helm-release-delete-error'
Check_PodStatus_Fault_Type = 'check-pod-status-error'
Kubernetes_Connectivity_FaultType = 'kubernetes-cluster-connection-error'
Helm_Version_Fault_Type = 'helm-not-updated-error'
Check_HelmVersion_Fault_Type = 'helm-version-check-error'
Helm_Installation_Fault_Type = 'helm-not-installed-error'
Check_HelmInstallation_Fault_Type = 'check-helm-installed-error'
Get_HelmRegistery_Path_Fault_Type = 'helm-registry-path-fetch-error'
Pull_HelmChart_Fault_Type = 'helm-chart-pull-error'
Export_HelmChart_Fault_Type = 'helm-chart-export-error'
Get_Kubernetes_Version_Fault_Type = 'kubernetes-get-version-error'
Get_Kubernetes_Distro_Fault_Type = 'kubernetes-get-distribution-error'
Update_Not_Allowed_Fault_Type = "update-not-allowed-error"
Update_Not_Allowed = "Update allowed only for agents with version >= {} in stable and {} in dev release train"
Update_Agent_Success = 'Agents for Connected Cluster {} have been updated successfully'
Update_Agent_Failure = 'Error while updating agents. Please run \"kubectl get pods -n azure-arc\" to check the pods in case of timeout error. Error: {}'
Comment thread
Anumita marked this conversation as resolved.
10 changes: 9 additions & 1 deletion src/connectedk8s/azext_connectedk8s/_help.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,18 @@
- name: Onboard a connected kubernetes cluster by specifying the kubeconfig and kubecontext.
text: az connectedk8s connect -g resourceGroupName -n connectedClusterName --kube-config /path/to/kubeconfig --kube-context kubeContextName
- name: Onboard a connected kubernetes cluster by specifying the https proxy, http proxy, no proxy settings.
text: az connectedk8s connect -g resourceGroupName -n connectedClusterName --https-proxy https://proxy-url --http-proxy http://proxy-url --no-proxy excludedIP,excludedCIDR,exampleCIDRfollowed,10.0.0.0/24
text: az connectedk8s connect -g resourceGroupName -n connectedClusterName --proxy-https https://proxy-url --proxy-http http://proxy-url --proxy-skip-destinations excludedIP,excludedCIDR,exampleCIDRfollowed,10.0.0.0/24

"""

helps['connectedk8s update'] = """
type: command
short-summary: Update properties of the onboarded agents.
examples:
- name: Update proxy values for the agents
text: az connectedk8s update -g resourceGroupName -n connectedClusterName --proxy-https https://proxy-url --proxy-http http://proxy-url --proxy-skip-destinations excludedIP,excludedCIDR,exampleCIDRfollowed,10.0.0.0/24
"""

helps['connectedk8s list'] = """
type: command
short-summary: List connected kubernetes clusters.
Expand Down
16 changes: 13 additions & 3 deletions src/connectedk8s/azext_connectedk8s/_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,19 @@ def load_arguments(self, _):
c.argument('cluster_name', options_list=['--name', '-n'], help='The name of the connected cluster.')
c.argument('kube_config', options_list=['--kube-config'], help='Path to the kube config file.')
c.argument('kube_context', options_list=['--kube-context'], help='Kubconfig context from current machine.')
c.argument('https_proxy', options_list=['--https-proxy'], help='Https proxy url to be used.')
c.argument('http_proxy', options_list=['--http-proxy'], help='Http proxy url to be used.')
c.argument('no_proxy', options_list=['--no-proxy'], help='List of urls/CIDRs for which proxy should not to be used.')
c.argument('https_proxy', options_list=['--proxy-https'], help='Https proxy url to be used.')
c.argument('http_proxy', options_list=['--proxy-http'], help='Http proxy url to be used.')
c.argument('no_proxy', options_list=['--proxy-skip-destinations'], help='List of urls/CIDRs for which proxy should not to be used.')

with self.argument_context('connectedk8s update') as c:
Comment thread
Anumita marked this conversation as resolved.
c.argument('cluster_name', options_list=['--name', '-n'], id_part='name', help='The name of the connected cluster.')
c.argument('tags', tags_type)
c.argument('location', arg_type=get_location_type(self.cli_ctx), validator=get_default_location_from_resource_group)
c.argument('kube_config', options_list=['--kube-config'], help='Path to the kube config file.')
c.argument('kube_context', options_list=['--kube-context'], help='Kubconfig context from current machine.')
c.argument('https_proxy', options_list=['--proxy-https'], help='Https proxy url to be used.')
Comment thread
Anumita marked this conversation as resolved.
Outdated
c.argument('http_proxy', options_list=['--proxy-http'], help='Http proxy url to be used.')
Comment thread
Anumita marked this conversation as resolved.
Outdated
c.argument('no_proxy', options_list=['--proxy-skip-destinations'], help='List of urls/CIDRs for which proxy should not to be used.')

with self.argument_context('connectedk8s list') as c:
pass
Expand Down
121 changes: 121 additions & 0 deletions src/connectedk8s/azext_connectedk8s/_utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
# --------------------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License.txt in the project root for license information.
# --------------------------------------------------------------------------------------------

import os
import subprocess
from subprocess import Popen, PIPE
import requests

from knack.util import CLIError
from azure.cli.core.commands.client_factory import get_subscription_id
from azure.cli.core import telemetry
from azext_connectedk8s._client_factory import _resource_client_factory
import azext_connectedk8s._constants as consts


def validate_location(cmd, location):
subscription_id = get_subscription_id(cmd.cli_ctx)
rp_locations = []
resourceClient = _resource_client_factory(cmd.cli_ctx, subscription_id=subscription_id)
providerDetails = resourceClient.providers.get('Microsoft.Kubernetes')
for resourceTypes in providerDetails.resource_types:
if resourceTypes.resource_type == 'connectedClusters':
rp_locations = [location.replace(" ", "").lower() for location in resourceTypes.locations]
if location.lower() not in rp_locations:
telemetry.set_user_fault()
telemetry.set_exception(exception='Location not supported', fault_type=consts.Invalid_Location_Fault_Type,
summary='Provided location is not supported for creating connected clusters')
raise CLIError("Connected cluster resource creation is supported only in the following locations: " +
', '.join(map(str, rp_locations)) +
". Use the --location flag to specify one of these locations.")
break


def get_chart_path(registry_path, kube_config, kube_context):
# Pulling helm chart from registry
os.environ['HELM_EXPERIMENTAL_OCI'] = '1'
pull_helm_chart(registry_path, kube_config, kube_context)

# Exporting helm chart
chart_export_path = os.path.join(os.path.expanduser('~'), '.azure', 'AzureArcCharts')
export_helm_chart(registry_path, chart_export_path, kube_config, kube_context)
# Helm Install
helm_chart_path = os.path.join(chart_export_path, 'azure-arc-k8sagents')
chart_path = os.getenv('HELMCHART') if os.getenv('HELMCHART') else helm_chart_path
return chart_path


def pull_helm_chart(registry_path, kube_config, kube_context):
cmd_helm_chart_pull = ["helm", "chart", "pull", registry_path, "--kubeconfig", kube_config]
if kube_context:
cmd_helm_chart_pull.extend(["--kube-context", kube_context])
response_helm_chart_pull = subprocess.Popen(cmd_helm_chart_pull, stdout=PIPE, stderr=PIPE)
_, error_helm_chart_pull = response_helm_chart_pull.communicate()
if response_helm_chart_pull.returncode != 0:
telemetry.set_exception(exception=error_helm_chart_pull.decode("ascii"), fault_type=consts.Pull_HelmChart_Fault_Type,
summary='Unable to pull helm chart from the registry')
raise CLIError("Unable to pull helm chart from the registry '{}': ".format(registry_path) + error_helm_chart_pull.decode("ascii"))


def export_helm_chart(registry_path, chart_export_path, kube_config, kube_context):
chart_export_path = os.path.join(os.path.expanduser('~'), '.azure', 'AzureArcCharts')
cmd_helm_chart_export = ["helm", "chart", "export", registry_path, "--destination", chart_export_path, "--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')
raise CLIError("Unable to export helm chart from the registry '{}': ".format(registry_path) + error_helm_chart_export.decode("ascii"))


def add_helm_repo(kube_config, kube_context):
if os.getenv('HELMREPONAME') and os.getenv('HELMREPOURL'):
Comment thread
Anumita marked this conversation as resolved.
Outdated
repo_name = os.getenv('HELMREPONAME')
repo_url = os.getenv('HELMREPOURL')
cmd_helm_repo = ["helm", "repo", "add", repo_name, repo_url, "--kubeconfig", kube_config]
if kube_context:
cmd_helm_repo.extend(["--kube-context", kube_context])
response_helm_repo = Popen(cmd_helm_repo, stdout=PIPE, stderr=PIPE)
_, error_helm_repo = response_helm_repo.communicate()
if response_helm_repo.returncode != 0:
telemetry.set_exception(exception=error_helm_repo.decode("ascii"), fault_type=consts.Add_HelmRepo_Fault_Type,
summary='Failed to add helm repository')
raise CLIError("Unable to add repository {} to helm: ".format(repo_url) + error_helm_repo.decode("ascii"))


def get_helm_registry(profile, location):
cred, _, _ = profile.get_login_credentials(
resource='https://management.core.windows.net/')
token = cred._token_retriever()[2].get('accessToken') # pylint: disable=protected-access

get_chart_location_url = "https://{}.dp.kubernetesconfiguration.azure.com/{}/GetLatestHelmPackagePath?api-version=2019-11-01-preview".format(location, 'azure-arc-k8sagents')
query_parameters = {}
query_parameters['releaseTrain'] = os.getenv('RELEASETRAIN') if os.getenv('RELEASETRAIN') else 'stable'
header_parameters = {}
header_parameters['Authorization'] = "Bearer {}".format(str(token))
try:
response = requests.post(get_chart_location_url, params=query_parameters, headers=header_parameters)
except Exception as e:
telemetry.set_exception(exception=e, fault_type=consts.Get_HelmRegistery_Path_Fault_Type,
summary='Error while fetching helm chart registry path')
raise CLIError("Error while fetching helm chart registry path: " + str(e))
if response.status_code == 200:
return response.json().get('repositoryPath')
telemetry.set_exception(exception=str(response.json()), fault_type=consts.Get_HelmRegistery_Path_Fault_Type,
summary='Error while fetching helm chart registry path')
raise CLIError("Error while fetching helm chart registry path: {}".format(str(response.json())))


def is_update_allowed(agent_version):
release_train = os.getenv('RELEASETRAIN') if os.getenv('RELEASETRAIN') else 'stable'
if release_train == "stable" and agent_version >= "0.2.5":
return True

if release_train == "dev" and agent_version >= "0.1.214-dev":
return True

return False
Comment thread
Anumita marked this conversation as resolved.
Outdated
1 change: 1 addition & 0 deletions src/connectedk8s/azext_connectedk8s/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ def load_command_table(self, _):

with self.command_group('connectedk8s', connectedk8s_sdk, client_factory=cf_connected_cluster) as g:
g.custom_command('connect', 'create_connectedk8s', supports_no_wait=True)
g.custom_command('update', 'update_agents', supports_no_wait=True)
Comment thread
Anumita marked this conversation as resolved.
Outdated
g.custom_command('delete', 'delete_connectedk8s', confirmation=True, supports_no_wait=True)
g.custom_command('list', 'list_connectedk8s', table_transformer=connectedk8s_list_table_format)
g.custom_show_command('show', 'get_connectedk8s', table_transformer=connectedk8s_show_table_format)
Expand Down
Loading