Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
2 changes: 2 additions & 0 deletions src/azure-cli/azure/cli/command_modules/acs/_consts.py
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,8 @@
CONST_AZURE_SERVICE_MESH_UPGRADE_COMMAND_START = "Start"
CONST_AZURE_SERVICE_MESH_UPGRADE_COMMAND_COMPLETE = "Complete"
CONST_AZURE_SERVICE_MESH_UPGRADE_COMMAND_ROLLBACK = "Rollback"
CONST_AZURE_SERVICE_MESH_DEFAULT_EGRESS_NAMESPACE = "aks-istio-egress"
CONST_AZURE_SERVICE_MESH_MAX_EGRESS_NAME_LENGTH = 63

# Dns zone contributor role
CONST_PRIVATE_DNS_ZONE_CONTRIBUTOR_ROLE = "Private DNS Zone Contributor"
Expand Down
40 changes: 40 additions & 0 deletions src/azure-cli/azure/cli/command_modules/acs/_help.py
Original file line number Diff line number Diff line change
Expand Up @@ -2564,6 +2564,46 @@
text: az aks mesh disable-ingress-gateway --resource-group MyResourceGroup --name MyManagedCluster --ingress-gateway-type Internal
"""

helps['aks mesh enable-egress-gateway'] = """
type: command
short-summary: Enable an Azure Service Mesh egress gateway.
long-summary: This command enables an Azure Service Mesh egress gateway in given cluster.
parameters:
- name: --istio-eg-gtw-name --istio-egressgateway-name
type: string
short-summary: Specify the name of the Istio egress gateway.
long-summary: This required field specifies the name of the Istio egress gateway. Must be between 1 and 253 characters, must consist of lower case alphanumeric characters, '-' or '.', and must start and end with an alphanumeric character.
- name: --istio-eg-gtw-ns --istio-egressgateway-namespace
type: string
short-summary: Specify the namespace of the Istio egress gateway.
long-summary: This optional field specifies the namespace of the Istio egress gateway. Defaults to "aks-istio-egress" if unspecified.
- name: --gateway-configuration-name --gtw-config-name
type: string
short-summary: Specify the name of the StaticGatewayConfiguration resource.
long-summary: This required field specifies the name of the StaticGatewayConfiguration resource for the Istio egress gateway. See https://aka.ms/aks-static-egress-gateway on how to create and configure a Static Egress Gateway agentpool.
examples:
- name: Enable an Istio egress gateway. Static egress gateway must be enabled prior to creating an Istio egress gateway. See https://aka.ms/aks-static-egress-gateway on how to create and configure a Static Egress Gateway agentpool.
text: az aks mesh enable-egress-gateway --resource-group MyResourceGroup --name MyManagedCluster --istio-egressgateway-name my-istio-egress-1 --istio-egressgateway-namespace my-namespace-1 --gateway-configuration-name sgc-istio-egress-1
"""

helps['aks mesh disable-egress-gateway'] = """
type: command
short-summary: Disable an Azure Service Mesh egress gateway.
long-summary: This command disables an Azure Service Mesh egress gateway in given cluster.
parameters:
- name: --istio-eg-gtw-name --istio-egressgateway-name
type: string
short-summary: Specify the name of the Istio egress gateway.
long-summary: This required field specifies the name of the Istio egress gateway. Must be between 1 and 253 characters, must consist of lower case alphanumeric characters, '-' or '.', and must start and end with an alphanumeric character.
- name: --istio-eg-gtw-ns --istio-egressgateway-namespace
type: string
short-summary: Specify the namespace of the Istio egress gateway.
long-summary: This optional field specifies the namespace of the Istio egress gateway. Defaults to "aks-istio-egress" if unspecified.
examples:
- name: Disable an Istio egress gateway.
text: az aks mesh disable-egress-gateway --resource-group MyResourceGroup --name MyManagedCluster --istio-egressgateway-name my-istio-egress-1 --istio-egressgateway-namespace my-namespace-1
"""

helps["aks mesh get-revisions"] = """
type: command
short-summary: Discover available Azure Service Mesh revisions and their compatibility.
Expand Down
35 changes: 35 additions & 0 deletions src/azure-cli/azure/cli/command_modules/acs/_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
CONST_LOAD_BALANCER_BACKEND_POOL_TYPE_NODE_IP_CONFIGURATION,
CONST_AZURE_SERVICE_MESH_INGRESS_MODE_EXTERNAL,
CONST_AZURE_SERVICE_MESH_INGRESS_MODE_INTERNAL,
CONST_AZURE_SERVICE_MESH_DEFAULT_EGRESS_NAMESPACE,
CONST_NRG_LOCKDOWN_RESTRICTION_LEVEL_READONLY,
CONST_NRG_LOCKDOWN_RESTRICTION_LEVEL_UNRESTRICTED,
CONST_ARTIFACT_SOURCE_DIRECT,
Expand Down Expand Up @@ -115,6 +116,7 @@
validate_allowed_host_ports, validate_application_security_groups,
validate_node_public_ip_tags,
validate_disable_windows_outbound_nat,
validate_asm_egress_name,
validate_crg_id, validate_apiserver_subnet_id,
validate_azure_service_mesh_revision,
validate_message_of_the_day,
Expand Down Expand Up @@ -1087,6 +1089,39 @@ def load_arguments(self, _):
c.argument('ingress_gateway_type',
arg_type=get_enum_type(ingress_gateway_types))

with self.argument_context("aks mesh enable-egress-gateway") as c:
c.argument(
"istio_egressgateway_name",
validator=validate_asm_egress_name,
required=True,
options_list=["--istio-egressgateway-name", "--istio-eg-gtw-name"]
)
c.argument(
"istio_egressgateway_namespace",
required=False,
default=CONST_AZURE_SERVICE_MESH_DEFAULT_EGRESS_NAMESPACE,
options_list=["--istio-egressgateway-namespace", "--istio-eg-gtw-ns"]
)
c.argument(
"gateway_configuration_name",
required=True,
options_list=["--gateway-configuration-name", "--gtw-config-name"]
)

with self.argument_context("aks mesh disable-egress-gateway") as c:
c.argument(
"istio_egressgateway_name",
validator=validate_asm_egress_name,
required=True,
options_list=["--istio-egressgateway-name", "--istio-eg-gtw-name"]
)
c.argument(
"istio_egressgateway_namespace",
required=False,
default=CONST_AZURE_SERVICE_MESH_DEFAULT_EGRESS_NAMESPACE,
options_list=["--istio-egressgateway-namespace", "--istio-eg-gtw-ns"]
)

with self.argument_context('aks mesh enable') as c:
c.argument('revision', validator=validate_azure_service_mesh_revision)
c.argument('key_vault_id')
Expand Down
15 changes: 15 additions & 0 deletions src/azure-cli/azure/cli/command_modules/acs/_validators.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
CONST_NETWORK_POD_IP_ALLOCATION_MODE_DYNAMIC_INDIVIDUAL,
CONST_NETWORK_POD_IP_ALLOCATION_MODE_STATIC_BLOCK,
CONST_NODEPOOL_MODE_GATEWAY,
CONST_AZURE_SERVICE_MESH_MAX_EGRESS_NAME_LENGTH,
CONST_VIRTUAL_MACHINE_SCALE_SETS,
CONST_AVAILABILITY_SET,
CONST_VIRTUAL_MACHINES,
Expand Down Expand Up @@ -137,6 +138,20 @@ def validate_agent_pool_name(namespace):
_validate_nodepool_name(namespace.agent_pool_name)


def validate_asm_egress_name(namespace):
if namespace.istio_egressgateway_name is None:
return
name = namespace.istio_egressgateway_name
asm_egress_name_regex = re.compile(r'^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$')
match = asm_egress_name_regex.match(name)
if not match or len(name) > CONST_AZURE_SERVICE_MESH_MAX_EGRESS_NAME_LENGTH:
raise InvalidArgumentValueError(
f"Istio egress name {name} is invalid. Name must be between 1 and "
f"{CONST_AZURE_SERVICE_MESH_MAX_EGRESS_NAME_LENGTH} characters, must consist of lower case alphanumeric "
"characters, '-' or '.', and must start and end with an alphanumeric character."
)


def validate_kubectl_version(namespace):
"""Validates a string as a possible Kubernetes version."""
k8s_release_regex = re.compile(r'^[v|V]?(\d+\.\d+\.\d+.*|latest)$')
Expand Down
9 changes: 9 additions & 0 deletions src/azure-cli/azure/cli/command_modules/acs/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -254,11 +254,20 @@ def load_command_table(self, _):
'enable-ingress-gateway',
'aks_mesh_enable_ingress_gateway',
supports_no_wait=True)
g.custom_command(
"enable-egress-gateway",
"aks_mesh_enable_egress_gateway",
supports_no_wait=True)
g.custom_command(
'disable-ingress-gateway',
'aks_mesh_disable_ingress_gateway',
supports_no_wait=True,
confirmation=True)
g.custom_command(
"disable-egress-gateway",
"aks_mesh_disable_egress_gateway",
supports_no_wait=True,
confirmation=True)
g.custom_command(
'get-revisions',
'aks_mesh_get_revisions',
Expand Down
43 changes: 43 additions & 0 deletions src/azure-cli/azure/cli/command_modules/acs/custom.py
Original file line number Diff line number Diff line change
Expand Up @@ -3412,6 +3412,44 @@ def aks_mesh_disable_ingress_gateway(
ingress_gateway_type=ingress_gateway_type)


def aks_mesh_enable_egress_gateway(
cmd,
client,
resource_group_name,
name,
istio_egressgateway_name,
istio_egressgateway_namespace,
gateway_configuration_name,
):
return _aks_mesh_update(
cmd,
client,
resource_group_name,
name,
enable_egress_gateway=True,
istio_egressgateway_name=istio_egressgateway_name,
istio_egressgateway_namespace=istio_egressgateway_namespace,
gateway_configuration_name=gateway_configuration_name)


def aks_mesh_disable_egress_gateway(
cmd,
client,
resource_group_name,
name,
istio_egressgateway_name,
istio_egressgateway_namespace,
):
return _aks_mesh_update(
cmd,
client,
resource_group_name,
name,
istio_egressgateway_name=istio_egressgateway_name,
istio_egressgateway_namespace=istio_egressgateway_namespace,
disable_egress_gateway=True)


def aks_mesh_get_revisions(
cmd,
client,
Expand Down Expand Up @@ -3534,6 +3572,11 @@ def _aks_mesh_update(
enable_ingress_gateway=None,
disable_ingress_gateway=None,
ingress_gateway_type=None,
enable_egress_gateway=None,
disable_egress_gateway=None,
istio_egressgateway_name=None,
istio_egressgateway_namespace=None,
gateway_configuration_name=None,
revision=None,
yes=False,
mesh_upgrade_command=None,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
CONST_AZURE_SERVICE_MESH_UPGRADE_COMMAND_START,
CONST_AZURE_SERVICE_MESH_UPGRADE_COMMAND_COMPLETE,
CONST_AZURE_SERVICE_MESH_UPGRADE_COMMAND_ROLLBACK,
CONST_AZURE_SERVICE_MESH_DEFAULT_EGRESS_NAMESPACE,
CONST_PRIVATE_DNS_ZONE_CONTRIBUTOR_ROLE,
CONST_DNS_ZONE_CONTRIBUTOR_ROLE,
CONST_ARTIFACT_SOURCE_CACHE,
Expand Down Expand Up @@ -4658,7 +4659,7 @@ def _handle_ingress_gateways_asm(self, new_profile: ServiceMeshProfile) -> Tuple
disable_ingress_gateway = self.raw_param.get("disable_ingress_gateway", False)
ingress_gateway_type = self.raw_param.get("ingress_gateway_type", None)

# disallow disable ingress gateway on a cluser with no asm enabled
# disallow disable ingress gateway on a cluster with no asm enabled
if disable_ingress_gateway:
if new_profile is None or new_profile.mode == CONST_AZURE_SERVICE_MESH_MODE_DISABLED:
raise ArgumentUsageError(
Expand Down Expand Up @@ -4712,6 +4713,97 @@ def _handle_ingress_gateways_asm(self, new_profile: ServiceMeshProfile) -> Tuple

return new_profile, updated

def _handle_egress_gateways_asm(self, new_profile: ServiceMeshProfile) -> Tuple[ServiceMeshProfile, bool]:
updated = False
enable_egress_gateway = self.raw_param.get("enable_egress_gateway", False)
disable_egress_gateway = self.raw_param.get("disable_egress_gateway", False)
istio_egressgateway_name = self.raw_param.get("istio_egressgateway_name", None)
istio_egressgateway_namespace = self.raw_param.get(
"istio_egressgateway_namespace",
CONST_AZURE_SERVICE_MESH_DEFAULT_EGRESS_NAMESPACE
)
gateway_configuration_name = self.raw_param.get("gateway_configuration_name", None)

# disallow disable egress gateway on a cluster with no asm enabled
if disable_egress_gateway:
if new_profile is None or new_profile.mode == CONST_AZURE_SERVICE_MESH_MODE_DISABLED:
raise ArgumentUsageError(
"Istio has not been enabled for this cluster, please refer to https://aka.ms/asm-aks-addon-docs "
"for more details on enabling Azure Service Mesh."
)
# deal with egress gateways
if enable_egress_gateway and disable_egress_gateway:
raise MutuallyExclusiveArgumentError(
"Cannot both enable and disable azure service mesh egress gateway at the same time.",
)
if enable_egress_gateway or disable_egress_gateway:
# if a gateway is enabled, enable the mesh
if enable_egress_gateway:

new_profile.mode = CONST_AZURE_SERVICE_MESH_MODE_ISTIO
if new_profile.istio is None:
new_profile.istio = self.models.IstioServiceMesh() # pylint: disable=no-member
updated = True

# Gateway configuration name is required for Istio egress gateway enablement
if not gateway_configuration_name:
raise RequiredArgumentMissingError("--gateway-configuration-name is required.")

if not istio_egressgateway_name:
raise RequiredArgumentMissingError("--istio-egressgateway-name is required.")

# ensure necessary fields
if new_profile.istio.components is None:
new_profile.istio.components = self.models.IstioComponents() # pylint: disable=no-member
updated = True
if new_profile.istio.components.egress_gateways is None:
new_profile.istio.components.egress_gateways = []
updated = True
# make update if the egress gateway already exists
egress_gateway_exists = False
for egress in new_profile.istio.components.egress_gateways:
if egress.name == istio_egressgateway_name and egress.namespace == istio_egressgateway_namespace:
if not egress.enabled and disable_egress_gateway:
raise ArgumentUsageError(
f'Egress gateway {istio_egressgateway_name} '
f'in namespace {istio_egressgateway_namespace} is already disabled.'
)
if egress.enabled and enable_egress_gateway:
if egress.gateway_configuration_name == gateway_configuration_name:
raise ArgumentUsageError(
f'Egress gateway {istio_egressgateway_name} '
f'in namespace {istio_egressgateway_namespace} is already enabled '
f'with gateway configuration name {gateway_configuration_name}.'
)
egress.enabled = enable_egress_gateway
# only update gateway configuration name for enabled egress gateways
if enable_egress_gateway:
egress.gateway_configuration_name = gateway_configuration_name
egress_gateway_exists = True
updated = True
break

# egress gateway doesn't exist, append
if not egress_gateway_exists:
if enable_egress_gateway:
new_profile.istio.components.egress_gateways.append(
self.models.IstioEgressGateway( # pylint: disable=no-member
enabled=enable_egress_gateway,
name=istio_egressgateway_name,
namespace=istio_egressgateway_namespace,
gateway_configuration_name=gateway_configuration_name,
)
)
elif disable_egress_gateway:
raise ArgumentUsageError(
f'Egress gateway {istio_egressgateway_name} '
f'in namespace {istio_egressgateway_namespace} does not exist, cannot disable.'
)

updated = True

return new_profile, updated

def _handle_enable_disable_asm(self, new_profile: ServiceMeshProfile) -> Tuple[ServiceMeshProfile, bool]:
updated = False
# enable/disable
Expand Down Expand Up @@ -4773,6 +4865,9 @@ def update_azure_service_mesh_profile(self) -> ServiceMeshProfile:
new_profile, updated_ingress_gateways_asm = self._handle_ingress_gateways_asm(new_profile)
updated |= updated_ingress_gateways_asm

new_profile, updated_egress_gateways_asm = self._handle_egress_gateways_asm(new_profile)
updated |= updated_egress_gateways_asm

new_profile, updated_pluginca_asm = self._handle_pluginca_asm(new_profile)
updated |= updated_pluginca_asm

Expand Down
Loading