Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
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
6 changes: 6 additions & 0 deletions linter_exclusions.yml
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,9 @@ aks create:
workspace_resource_id:
rule_exclusions:
- option_length_too_long
enable_sgx_quote_helper:
rule_exclusions:
- option_length_too_long
aks enable-addons:
parameters:
appgw_watch_namespace:
Expand All @@ -81,6 +84,9 @@ aks enable-addons:
workspace_resource_id:
rule_exclusions:
- option_length_too_long
enable_sgx_quote_helper:
rule_exclusions:
- option_length_too_long
aks nodepool add:
parameters:
enable_node_public_ip:
Expand Down
4 changes: 4 additions & 0 deletions src/aks-preview/HISTORY.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

Release History
===============
0.4.62
+++++
* Add support for ACC SGX device plugin addon and quote helper.

0.4.61
+++++
* Fix AGIC typo and remove preview label from VN #2141
Expand Down
6 changes: 5 additions & 1 deletion src/aks-preview/azext_aks_preview/_consts.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,16 @@
# naming-and-referencing-containers--blobs--and-metadata#container-names
CONST_CONTAINER_NAME_MAX_LENGTH = 63

# ACC SGX addon keys
CONST_ACC_SGX_DEVICE_PLUGIN_ADDON_NAME = "ACCSGXDevicePlugin"
CONST_ACC_SGX_QUOTE_HELPER_ENABLED = "ACCSGXQuoteHelperEnabled"

ADDONS = {
'http_application_routing': 'httpApplicationRouting',
'monitoring': 'omsagent',
'virtual-node': 'aciConnector',
'azure-policy': 'azurepolicy',
'kube-dashboard': 'kubeDashboard',
'ingress-appgw': CONST_INGRESS_APPGW_ADDON_NAME
'ingress-appgw': CONST_INGRESS_APPGW_ADDON_NAME,
"acc-sgx-device-plugin": CONST_ACC_SGX_DEVICE_PLUGIN_ADDON_NAME
}
7 changes: 7 additions & 0 deletions src/aks-preview/azext_aks_preview/_help.py
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@
virtual-node - enable AKS Virtual Node. Requires --subnet-name to provide the name of an existing subnet for the Virtual Node to use.
azure-policy - enable Azure policy (PREVIEW).
ingress-appgw - enable Application Gateway Ingress Controller addon (PREVIEW).
acc-sgx-device-plugin - enable SGX device plugin addon for ACC (PREVIEW).
- name: --disable-rbac
type: bool
short-summary: Disable Kubernetes Role-Based Access Control.
Expand Down Expand Up @@ -242,6 +243,9 @@
- name: --appgw-watch-namespace
type: string
short-summary: Specify the namespace, which AGIC should watch. This could be a single string value, or a comma-separated list of namespaces.
- name: --enable-sgx-quote-helper
type: bool
short-summary: Enable SGX quote helper. SGX device plugin addon has to be enabled.
examples:
- name: Create a Kubernetes cluster with an existing SSH public key.
text: az aks create -g MyResourceGroup -n MyManagedCluster --ssh-key-value /path/to/publickey
Expand Down Expand Up @@ -647,6 +651,9 @@
- name: --appgw-watch-namespace
type: string
short-summary: Specify the namespace, which AGIC should watch. This could be a single string value, or a comma-separated list of namespaces. Use with ingress-azure addon.
- name: --enable-sgx-quote-helper
type: bool
short-summary: Enable SGX quote helper. SGX device plugin addon has to be enabled.
examples:
- name: Enable Kubernetes addons. (autogenerated)
text: az aks enable-addons --addons virtual-node --name MyManagedCluster --resource-group MyResourceGroup --subnet-name VirtualNodeSubnet
Expand Down
2 changes: 2 additions & 0 deletions src/aks-preview/azext_aks_preview/_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ def load_arguments(self, _):
c.argument('enable_private_cluster', action='store_true')
c.argument('enable_managed_identity', action='store_true')
c.argument('assign_identity', type=str, validator=validate_assign_identity)
c.argument('enable_sgx_quote_helper', action='store_true')

with self.argument_context('aks update') as c:
c.argument('enable_cluster_autoscaler', options_list=["--enable-cluster-autoscaler", "-e"], action='store_true')
Expand Down Expand Up @@ -176,6 +177,7 @@ def load_arguments(self, _):
with self.argument_context('aks enable-addons') as c:
c.argument('addons', options_list=['--addons', '-a'], validator=validate_addons)
c.argument('subnet_name', options_list=['--subnet-name', '-s'])
c.argument('enable_sgx_quote_helper', action='store_true')

with self.argument_context('aks get-credentials') as c:
c.argument('admin', options_list=['--admin', '-a'], default=False)
Expand Down
30 changes: 26 additions & 4 deletions src/aks-preview/azext_aks_preview/custom.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@
from ._consts import CONST_INGRESS_APPGW_SUBNET_PREFIX, CONST_INGRESS_APPGW_SUBNET_ID
from ._consts import CONST_INGRESS_APPGW_WATCH_NAMESPACE
from ._consts import CONST_SCALE_SET_PRIORITY_REGULAR, CONST_SCALE_SET_PRIORITY_SPOT, CONST_SPOT_EVICTION_POLICY_DELETE
from ._consts import CONST_ACC_SGX_DEVICE_PLUGIN_ADDON_NAME, CONST_ACC_SGX_QUOTE_HELPER_ENABLED
from ._consts import ADDONS
logger = get_logger(__name__)

Expand Down Expand Up @@ -843,6 +844,7 @@ def aks_create(cmd, # pylint: disable=too-many-locals,too-many-statements,to
enable_aad=False,
enable_azure_rbac=False,
aad_admin_group_object_ids=None,
enable_sgx_quote_helper=False,
assign_identity=None,
no_wait=False):
if not no_ssh_key:
Expand Down Expand Up @@ -1004,7 +1006,8 @@ def aks_create(cmd, # pylint: disable=too-many-locals,too-many-statements,to
appgw_subnet_prefix,
appgw_id,
appgw_subnet_id,
appgw_watch_namespace
appgw_watch_namespace,
enable_sgx_quote_helper
)
monitoring = False
if 'omsagent' in addon_profiles:
Expand Down Expand Up @@ -1727,7 +1730,8 @@ def _upgrade_single_agent_pool_node_image(client, resource_group_name, cluster_n


def _handle_addons_args(cmd, addons_str, subscription_id, resource_group_name, addon_profiles=None,
workspace_resource_id=None, appgw_name=None, appgw_subnet_prefix=None, appgw_id=None, appgw_subnet_id=None, appgw_watch_namespace=None):
workspace_resource_id=None, appgw_name=None, appgw_subnet_prefix=None, appgw_id=None,
appgw_subnet_id=None, appgw_watch_namespace=None, enable_sgx_quote_helper=False):
if not addon_profiles:
addon_profiles = {}
addons = addons_str.split(',') if addons_str else []
Expand Down Expand Up @@ -1772,6 +1776,13 @@ def _handle_addons_args(cmd, addons_str, subscription_id, resource_group_name, a
addon_profile.config[CONST_INGRESS_APPGW_WATCH_NAMESPACE] = appgw_watch_namespace
addon_profiles[CONST_INGRESS_APPGW_ADDON_NAME] = addon_profile
addons.remove('ingress-appgw')
if 'acc-sgx-device-plugin' in addons:
addon_profile = ManagedClusterAddonProfile(enabled=True, config={CONST_ACC_SGX_QUOTE_HELPER_ENABLED: "false"})
if enable_sgx_quote_helper:
addon_profile.config[CONST_ACC_SGX_QUOTE_HELPER_ENABLED] = "true"
addon_profiles[CONST_ACC_SGX_DEVICE_PLUGIN_ADDON_NAME] = addon_profile
addons.remove('acc-sgx-device-plugin')

# error out if any (unrecognized) addons remain
if addons:
raise CLIError('"{}" {} not recognized by the --enable-addons argument.'.format(
Expand Down Expand Up @@ -2424,12 +2435,13 @@ def aks_disable_addons(cmd, client, resource_group_name, name, addons, no_wait=F


def aks_enable_addons(cmd, client, resource_group_name, name, addons, workspace_resource_id=None,
subnet_name=None, appgw_name=None, appgw_subnet_prefix=None, appgw_id=None, appgw_subnet_id=None, appgw_watch_namespace=None, no_wait=False):
subnet_name=None, appgw_name=None, appgw_subnet_prefix=None, appgw_id=None, appgw_subnet_id=None, appgw_watch_namespace=None, enable_sgx_quote_helper=False, no_wait=False):
instance = client.get(resource_group_name, name)
subscription_id = get_subscription_id(cmd.cli_ctx)
instance = _update_addons(cmd, instance, subscription_id, resource_group_name, name, addons, enable=True,
workspace_resource_id=workspace_resource_id, subnet_name=subnet_name,
appgw_name=appgw_name, appgw_subnet_prefix=appgw_subnet_prefix, appgw_id=appgw_id, appgw_subnet_id=appgw_subnet_id, appgw_watch_namespace=appgw_watch_namespace, no_wait=no_wait)
appgw_name=appgw_name, appgw_subnet_prefix=appgw_subnet_prefix, appgw_id=appgw_id, appgw_subnet_id=appgw_subnet_id, appgw_watch_namespace=appgw_watch_namespace,
enable_sgx_quote_helper=enable_sgx_quote_helper, no_wait=no_wait)

if 'omsagent' in instance.addon_profiles and instance.addon_profiles['omsagent'].enabled:
_ensure_container_insights_for_monitoring(cmd, instance.addon_profiles['omsagent'])
Expand Down Expand Up @@ -2479,6 +2491,7 @@ def _update_addons(cmd, # pylint: disable=too-many-branches,too-many-statements
appgw_id=None,
appgw_subnet_id=None,
appgw_watch_namespace=None,
enable_sgx_quote_helper=False,
no_wait=False): # pylint: disable=unused-argument

# parse the comma-separated addons argument
Expand Down Expand Up @@ -2544,6 +2557,15 @@ def _update_addons(cmd, # pylint: disable=too-many-branches,too-many-statements
addon_profile.config[CONST_INGRESS_APPGW_SUBNET_ID] = appgw_subnet_id
if appgw_watch_namespace is not None:
addon_profile.config[CONST_INGRESS_APPGW_WATCH_NAMESPACE] = appgw_watch_namespace
elif addon.lower() == CONST_ACC_SGX_DEVICE_PLUGIN_ADDON_NAME.lower():
if addon_profile.enabled:
raise CLIError('The acc-sgx-device-plugin addon is already enabled for this managed cluster.\n'
'To change acc-sgx-device-plugin configuration, run '
f'"az aks disable-addons -a acc-sgx-device-plugin -n {name} -g {resource_group_name}" '
'before enabling it again.')
addon_profile = ManagedClusterAddonProfile(enabled=True, config={CONST_ACC_SGX_QUOTE_HELPER_ENABLED: "false"})
if enable_sgx_quote_helper:
addon_profile.config[CONST_ACC_SGX_QUOTE_HELPER_ENABLED] = "true"
addon_profiles[addon] = addon_profile
else:
if addon not in addon_profiles:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -280,3 +280,70 @@ def test_aks_byo_appgw_with_ingress_appgw_addon(self, resource_group, resource_g
self.cmd(check_role_assignment, checks=[
self.check('[0].roleDefinitionName', 'Contributor')
])

@live_only()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any special case to mark it as live_only ? Same question for below cases.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it will fail at "az login" without live-only

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

any advice how to fix it?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now I'm getting this error with recordings:
vcr.errors.CannotOverwriteExistingCassetteException: Can't overwrite existing cassette ('/home/vsts/work/1/s/src/aks-preview/azext_aks_preview/tests/latest/recordings/test_aks_enable_addons_confcom_addon.yaml') in your current record mode ('once').
No match for the request (<Request (GET) https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.ContainerService/managedClusters/cliakstest000002?api-version=2020-06-01>) was found.
Found 1 similar requests with 0 different matcher(s) :

1 - (<Request (GET) https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/clitest000001/providers/Microsoft.ContainerService/managedClusters/cliakstest000002?api-version=2020-06-01>).
Matchers succeeded : ['method', 'scheme', 'host', 'port', 'path', '_custom_request_query_matcher']
Matchers failed :

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Marking two failing tests as live-only for now since I need to merge this PR asap. They passed locally for me.

Copy link
Contributor

@arrownj arrownj Sep 2, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @bowang-666, not sure why the tests required az login ? If actually needed, the test framework also provides a replacer function to handle this case.

Are the failed cases new added ? It's better not to skip any CI failure for there may be potential bugs we didn't find. If you need to use the extension in a short time, you can build a wheel file in your local environment(just cd aks-preview, and run python ./setup.py bdist_wheel). For the normal release, let's follow the release process to get CI passed first.

Thanks

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It does not need "az login" now, the only issue now is "Can't overwrite existing cassette" error in test pipeline. I need to release a new version of aks-preview for ACC team asap, but I also agree we should investigate this further. How about I open a bug to track this issue separately? The tests passed lively so I'm confident the functionality is working.

@AllowLargeResponse()
@ResourceGroupPreparer(random_name_length=17, name_prefix='clitest', location='westus2')
def test_aks_create_with_acc_sgx_device_plugin_addon(self, resource_group, resource_group_location):
aks_name = self.create_random_name('cliakstest', 16)
self.kwargs.update({
'resource_group': resource_group,
'name': aks_name
})

create_cmd = 'aks create --resource-group={resource_group} --name={name} --enable-managed-identity --service-principal xxxx --client-secret yyyy --generate-ssh-keys ' \
'-a acc-sgx-device-plugin --enable-sgx-quote-helper -o json'
self.cmd(create_cmd, checks=[
self.check('provisioningState', 'Succeeded'),
self.check('addonProfiles.ACCSGXDevicePlugin.enabled', True),
self.check('addonProfiles.ACCSGXDevicePlugin.config.ACCSGXQuoteHelperEnabled', "true")
])

@live_only()
@AllowLargeResponse()
@ResourceGroupPreparer(random_name_length=17, name_prefix='clitest', location='westus2')
def test_aks_enable_addons_acc_sgx_device_plugin_addon(self, resource_group, resource_group_location):
aks_name = self.create_random_name('cliakstest', 16)
self.kwargs.update({
'resource_group': resource_group,
'name': aks_name
})

create_cmd = 'aks create --resource-group={resource_group} --name={name} --enable-managed-identity --service-principal xxxx --client-secret yyyy --generate-ssh-keys ' \
'-o json'
self.cmd(create_cmd, checks=[
self.check('provisioningState', 'Succeeded'),
self.check('addonProfiles.ACCSGXDevicePlugin', None)
])

enable_cmd = 'aks enable-addons --addons acc-sgx-device-plugin --enable-sgx-quote-helper --resource-group={resource_group} --name={name} -o json'
self.cmd(enable_cmd, checks=[
self.check('provisioningState', 'Succeeded'),
self.check('addonProfiles.ACCSGXDevicePlugin.enabled', True),
self.check('addonProfiles.ACCSGXDevicePlugin.config.ACCSGXQuoteHelperEnabled', "true")
])

@live_only()
@AllowLargeResponse()
@ResourceGroupPreparer(random_name_length=17, name_prefix='clitest', location='westus2')
def test_aks_disable_addons_acc_sgx_device_plugin_addon(self, resource_group, resource_group_location):
aks_name = self.create_random_name('cliakstest', 16)
self.kwargs.update({
'resource_group': resource_group,
'name': aks_name
})

create_cmd = 'aks create --resource-group={resource_group} --name={name} --enable-managed-identity --service-principal xxxx --client-secret yyyy --generate-ssh-keys ' \
'-a acc-sgx-device-plugin --enable-sgx-quote-helper -o json'
self.cmd(create_cmd, checks=[
self.check('provisioningState', 'Succeeded'),
self.check('addonProfiles.ACCSGXDevicePlugin.enabled', True),
self.check('addonProfiles.ACCSGXDevicePlugin.config.ACCSGXQuoteHelperEnabled', "true")
])

disable_cmd = 'aks disable-addons --addons acc-sgx-device-plugin --resource-group={resource_group} --name={name} -o json'
self.cmd(disable_cmd, checks=[
self.check('provisioningState', 'Succeeded'),
self.check('addonProfiles.ACCSGXDevicePlugin.enabled', False),
self.check('addonProfiles.ACCSGXDevicePlugin.config', None)
])
2 changes: 1 addition & 1 deletion src/aks-preview/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from codecs import open as open1
from setuptools import setup, find_packages

VERSION = "0.4.61"
VERSION = "0.4.62"
CLASSIFIERS = [
'Development Status :: 4 - Beta',
'Intended Audience :: Developers',
Expand Down