Skip to content

Commit

Permalink
AKS/ACI - Add install-connector and remove-connector commands (#4996)
Browse files Browse the repository at this point in the history
  • Loading branch information
julienstroheker authored and yugangw-msft committed Dec 1, 2017
1 parent f6292e3 commit c360569
Show file tree
Hide file tree
Showing 6 changed files with 136 additions and 1 deletion.
4 changes: 4 additions & 0 deletions src/command_modules/azure-cli-acs/HISTORY.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@
Release History
===============

2.0.21
++++++
* add `az aks install-connector` and `az aks remove-connector` commands

2.0.20
++++++
* `acs create`: emit out an actionable error if provisioning application failed for lack of permissions
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,3 +79,27 @@
type: command
short-summary: Wait for a Kubernetes cluster to reach a desired state.
"""
helps['aks install-connector'] = """
type: command
short-summary: Deploy the ACI-Connector to a AKS cluster.
examples:
- name: Install the ACI-Connector to an AKS Cluster.
text: az aks install-connector --name MyManagedCluster --resource-group MyResourceGroup --connector-name MyConnector
- name: Install the ACI-Connector for Windows to an AKS Cluster.
text: az aks install-connector --name MyManagedCluster --resource-group MyResourceGroup --connector-name MyConnector --os-type Windows
- name: Install the ACI-Connector for Windows and Linux to an AKS Cluster.
text: az aks install-connector --name MyManagedCluster --resource-group MyResourceGroup --connector-name MyConnector --os-type Both
- name: Install the ACI-Connector using specific SPN.
text: az aks install-connector --name MyManagedCluster --resource-group MyResourceGroup --connector-name MyConnector --service-principal <SPN_ID> --client-secret <SPN_SECRET>
- name: Install the ACI-Connector from a specific custom chart.
text: az aks install-connector --name MyManagedCluster --resource-group MyResourceGroup --connector-name MyConnector --chart-url <CustomURL>
"""
helps['aks remove-connector'] = """
type: command
short-summary: Undeploy the ACI-Connector from an AKS cluster.
examples:
- name: Undeploy the ACI-Connector on an AKS cluster.
text: az aks remove-connector --name MyManagedCluster --resource-group MyResourceGroup --connector-name MyConnector
- name: Undeploy the ACI-Connector on an AKS cluster using the graceful mode
text: az aks remove-connector --name MyManagedCluster --resource-group MyResourceGroup --connector-name MyConnector --graceful
"""
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,10 @@ def _get_feature_in_preview_message():

orchestratorTypes = ["Custom", "DCOS", "Kubernetes", "Swarm", "DockerCE"]

aci_connector_os_type = ['Windows', 'Linux', 'Both']

aci_connector_chart_url = 'https://github.com/Azure/aci-connector-k8s/raw/master/charts/aci-connector.tgz'

k8s_version_arg_type = CliArgumentType(options_list=('--kubernetes-version', '-k'), metavar='KUBERNETES_VERSION')

storageProfileTypes = ["StorageAccount", "ManagedDisks"]
Expand Down Expand Up @@ -182,3 +186,12 @@ def _get_feature_in_preview_message():
default=_get_default_install_location('kubectl'))
register_cli_argument('aks install-cli', 'client_version', options_list=('--client-version',),
validator=validate_k8s_client_version)
register_cli_argument('aks install-connector', 'os_type', help='The OS type of the connector', **enum_choice_list(aci_connector_os_type))
register_cli_argument('aks install-connector', 'chart_url', help='URL to the chart', default=aci_connector_chart_url)
register_cli_argument('aks install-connector', 'connector_name', help='The name for the ACI Connector')
register_cli_argument('aks install-connector', 'service_principal', help='Service principal for making calls into Azure APIs. If not set, auto generate a new service principal of Contributor role, and save it locally for reusing')
register_cli_argument('aks install-connector', 'client_secret', help='Client secret to use with the service principal for making calls to Azure APIs')
register_cli_argument('aks remove-connector', 'os_type', help='The OS type of the connector', **enum_choice_list(aci_connector_os_type))
register_cli_argument('aks remove-connector', 'graceful', help='Mention if you want to drain/uncordon your aci-connector to move your applications', action='store_true')
register_cli_argument('aks remove-connector', 'connector_name', help='The name for the ACI Connector')
register_cli_argument('aks remove-connector', 'resource_group', arg_type=resource_group_name_type, help='The name of the resource group where the AKS cluster is deployed')
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,10 @@ def aks_get_versions_table_format(result):
table_transformer=aks_get_versions_table_format)
cli_command(__name__, 'aks install-cli',
'azure.cli.command_modules.acs.custom#k8s_install_cli')
cli_command(__name__, 'aks install-connector',
'azure.cli.command_modules.acs.custom#k8s_install_connector', _aks_client_factory)
cli_command(__name__, 'aks remove-connector',
'azure.cli.command_modules.acs.custom#k8s_uninstall_connector', _aks_client_factory)
cli_command(__name__, 'aks list',
'azure.cli.command_modules.acs.custom#aks_list', _aks_client_factory,
table_transformer=aks_list_table_format)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,96 @@ def k8s_install_cli(client_version='latest', install_location=None):
raise CLIError('Connection error while attempting to download client ({})'.format(ex))


def k8s_install_connector(client, name, resource_group, connector_name,
location=None, service_principal=None, client_secret=None,
chart_url=None, os_type='Linux'):
from subprocess import PIPE, Popen
helm_not_installed = "Helm not detected, please verify if it is installed."
image_tag = 'latest'
url_chart = chart_url
# Check if Helm is installed locally
try:
Popen(["helm"], stdout=PIPE, stderr=PIPE)
except OSError:
raise CLIError(helm_not_installed)
# Validate if the RG exists
groups = _resource_client_factory().resource_groups
# Just do the get, we don't need the result, it will error out if the group doesn't exist.
rgkaci = groups.get(resource_group)
# Auto assign the location
if location is None:
location = rgkaci.location # pylint:disable=no-member
# Get the credentials from a AKS instance
_, browse_path = tempfile.mkstemp()
aks_get_credentials(client, resource_group, name, admin=False, path=browse_path)
subscription_id = _get_subscription_id()
dns_name_prefix = _get_default_dns_prefix(connector_name, resource_group, subscription_id)
# Ensure that the SPN exists
principal_obj = _ensure_service_principal(service_principal, client_secret, subscription_id,
dns_name_prefix, location, connector_name)
client_secret = principal_obj.get("client_secret")
service_principal = principal_obj.get("service_principal")
# Get the TenantID
profile = Profile()
_, _, tenant_id = profile.get_login_credentials()
# Check if we want the windows connector
if os_type.lower() in ['windows', 'both']:
# The current connector will deploy two connectors, one for Windows and another one for Linux
image_tag = 'canary'
logger.warning('Deploying the aci-connector using Helm')
try:
subprocess.call(["helm", "install", url_chart, "--name", connector_name, "--set", "env.azureClientId=" +
service_principal + ",env.azureClientKey=" + client_secret + ",env.azureSubscriptionId=" +
subscription_id + ",env.azureTenantId=" + tenant_id + ",env.aciResourceGroup=" + rgkaci.name +
",env.aciRegion=" + location + ",image.tag=" + image_tag])
except subprocess.CalledProcessError as err:
raise CLIError('Could not deploy the ACI Chart: {}'.format(err))


def k8s_uninstall_connector(client, name, connector_name, resource_group,
graceful=False, os_type='Linux'):
from subprocess import PIPE, Popen
helm_not_installed = "Error : Helm not detected, please verify if it is installed."
# Check if Helm is installed locally
try:
Popen(["helm"], stdout=PIPE, stderr=PIPE)
except OSError:
raise CLIError(helm_not_installed)
# Get the credentials from a AKS instance
_, browse_path = tempfile.mkstemp()
aks_get_credentials(client, resource_group, name, admin=False, path=browse_path)
if graceful:
logger.warning('Graceful option selected, will try to drain the node first')
kubectl_not_installed = "Kubectl not detected, please verify if it is installed."
try:
Popen(["kubectl"], stdout=PIPE, stderr=PIPE)
except OSError:
raise CLIError(kubectl_not_installed)
try:
if os_type.lower() in ['windows', 'both']:
nodes = ['-0', '-1']
for n in nodes:
drain_node = subprocess.check_output(
["kubectl", "drain", "aci-connector{}".format(n), "--force"],
universal_newlines=True)
else:
drain_node = subprocess.check_output(
["kubectl", "drain", "aci-connector", "--force"],
universal_newlines=True)
except subprocess.CalledProcessError as err:
raise CLIError('Could not find the node, make sure you' +
' are using the correct --os-type option: {}'.format(err))
if not drain_node:
raise CLIError('Could not find the node, make sure you' +
' are using the correct --os-type')

logger.warning('Undeploying the aci-connector using Helm')
try:
subprocess.call(["helm", "del", connector_name, "--purge"])
except subprocess.CalledProcessError as err:
raise CLIError('Could not deploy the ACI Chart: {}'.format(err))


def _build_service_principal(client, name, url, client_secret):
# use get_progress_controller
hook = APPLICATION.get_progress_controller(True)
Expand Down
2 changes: 1 addition & 1 deletion src/command_modules/azure-cli-acs/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
logger.warn("Wheel is not available, disabling bdist_wheel hook")
cmdclass = {}

VERSION = "2.0.20"
VERSION = "2.0.21"
CLASSIFIERS = [
'Development Status :: 5 - Production/Stable',
'Intended Audience :: Developers',
Expand Down

0 comments on commit c360569

Please sign in to comment.