Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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
20 changes: 20 additions & 0 deletions src/spring-cloud/azext_spring_cloud/_help.py
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,26 @@
short-summary: Show logs of an app instance, logs will be streamed when setting '-f/--follow'.
"""

helps['spring-cloud app identity'] = """
type: group
short-summary: manage an app's managed service identity
Comment thread
leonard520 marked this conversation as resolved.
Outdated
"""

helps['spring-cloud app identity assign'] = """
type: command
short-summary: Enable managed service identity on an app.
Comment thread
leonard520 marked this conversation as resolved.
"""

helps['spring-cloud app identity remove'] = """
type: command
short-summary: Remove managed service identity from a app.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

examples

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

s/a/an

"""

helps['spring-cloud app identity show'] = """
type: command
short-summary: Display app's managed identity info.
Comment thread
leonard520 marked this conversation as resolved.
"""

helps['spring-cloud app set-deployment'] = """
type: command
short-summary: Set production deployment of an app.
Expand Down
2 changes: 2 additions & 0 deletions src/spring-cloud/azext_spring_cloud/_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ def load_arguments(self, _):
with self.argument_context('spring-cloud app create') as c:
c.argument(
'is_public', arg_type=get_three_state_flag(), help='If true, assign public domain', default=False)
c.argument('assign_identity', arg_type=get_three_state_flag(),
help='Generate and assign an Azure Active Directory Identity for this app for use with key management services like Azure KeyVault.')

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

change the help text here too?


with self.argument_context('spring-cloud app update') as c:
c.argument('is_public', arg_type=get_three_state_flag(),
Expand Down
3 changes: 3 additions & 0 deletions src/spring-cloud/azext_spring_cloud/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,9 @@ def load_command_table(self, _):
g.custom_command('stop', 'app_stop', supports_no_wait=True)
g.custom_command('restart', 'app_restart', supports_no_wait=True)
g.custom_command('logs', 'app_tail_log')
g.custom_command('identity assign', 'app_identity_assign')
g.custom_command('identity remove', 'app_identity_remove')
g.custom_command('identity show', 'app_identity_show')
Comment thread
leonard520 marked this conversation as resolved.
Outdated

with self.command_group('spring-cloud app log', client_factory=cf_spring_cloud,
deprecate_info=g.deprecate(redirect='az spring-cloud app logs', hide=True)) as g:
Expand Down
59 changes: 54 additions & 5 deletions src/spring-cloud/azext_spring_cloud/custom.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,8 @@ def app_create(cmd, client, resource_group, service, name,
runtime_version=None,
jvm_options=None,
env=None,
enable_persistent_storage=None):
enable_persistent_storage=None,
assign_identity=None):
apps = _get_all_apps(client, resource_group, service)
if name in apps:
raise CLIError("App '{}' already exists.".format(name))
Expand All @@ -119,8 +120,14 @@ def app_create(cmd, client, resource_group, service, name,
resource = client.services.get(resource_group, service)
location = resource.location

app_resource = models.AppResource()
app_resource.properties = properties
app_resource.location = location
if assign_identity is True:
app_resource.identity = models.ManagedIdentityProperties(type="systemassigned")

poller = client.apps.create_or_update(
resource_group, service, name, properties, location)
resource_group, service, name, app_resource)
while poller.done() is False:
sleep(APP_CREATE_OR_UPDATE_SLEEP_INTERVAL)

Expand All @@ -147,7 +154,10 @@ def app_create(cmd, client, resource_group, service, name,
properties = models.AppResourceProperties(
active_deployment_name=DEFAULT_DEPLOYMENT_NAME, public=is_public)

app_poller = client.apps.update(resource_group, service, name, properties, location)
app_resource.properties = properties
app_resource.location = location

app_poller = client.apps.update(resource_group, service, name, app_resource)
logger.warning(
"[4/4] Updating app '{}' (this operation can take a while to complete)".format(name))
while not poller.done() or not app_poller.done():
Expand Down Expand Up @@ -178,9 +188,13 @@ def app_update(cmd, client, resource_group, service, name,
resource = client.services.get(resource_group, service)
location = resource.location

app_resource = models.AppResource()
app_resource.properties = properties
app_resource.location = location

logger.warning("[1/2] updating app '{}'".format(name))
poller = client.apps.update(
resource_group, service, name, properties, location)
resource_group, service, name, app_resource)
while poller.done() is False:
sleep(APP_CREATE_OR_UPDATE_SLEEP_INTERVAL)

Expand Down Expand Up @@ -425,6 +439,37 @@ def app_tail_log(cmd, client, resource_group, service, name, instance=None, foll
raise exceptions[0]


def app_identity_assign(cmd, client, resource_group, service, name):
app_resource = models.AppResource()
identity = models.ManagedIdentityProperties(type="systemassigned")

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

do you have plan to support other type? if yes better to expose type as a param with default value

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Not yet. But we can refactor code if we will support in future.

properties = models.AppResourceProperties()
resource = client.services.get(resource_group, service)
location = resource.location

app_resource.identity = identity
app_resource.properties = properties
app_resource.location = location
return client.apps.update(resource_group, service, name, app_resource)


def app_identity_remove(cmd, client, resource_group, service, name):
app_resource = models.AppResource()
identity = models.ManagedIdentityProperties(type="none")
properties = models.AppResourceProperties()
resource = client.services.get(resource_group, service)
location = resource.location

app_resource.identity = identity
app_resource.properties = properties
app_resource.location = location
return client.apps.update(resource_group, service, name, app_resource)


def app_identity_show(cmd, client, resource_group, service, name):
app = client.apps.get(resource_group, service, name)
return app.identity


def app_set_deployment(cmd, client, resource_group, service, name, deployment):
deployments = _get_all_deployments(client, resource_group, service, name)
active_deployment = client.apps.get(
Expand All @@ -441,7 +486,11 @@ def app_set_deployment(cmd, client, resource_group, service, name, deployment):
resource = client.services.get(resource_group, service)
location = resource.location

return client.apps.update(resource_group, service, name, properties, location)
app_resource = models.AppResource()
app_resource.properties = properties
app_resource.location = location

return client.apps.update(resource_group, service, name, app_resource)


def deployment_create(cmd, client, resource_group, service, app, name,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
from ._models_py3 import GitPatternRepository
from ._models_py3 import LogFileUrlResponse
from ._models_py3 import LogSpecification
from ._models_py3 import ManagedIdentityProperties
from ._models_py3 import MetricDimension
from ._models_py3 import MetricSpecification
from ._models_py3 import NameAvailability
Expand Down Expand Up @@ -62,6 +63,7 @@
from ._models import GitPatternRepository
from ._models import LogFileUrlResponse
from ._models import LogSpecification
from ._models import ManagedIdentityProperties
from ._models import MetricDimension
from ._models import MetricSpecification
from ._models import NameAvailability
Expand Down Expand Up @@ -90,6 +92,7 @@
ProvisioningState,
ConfigServerState,
TraceProxyState,
ManagedIdentityType,
TestKeyType,
AppResourceProvisioningState,
UserSourceType,
Expand All @@ -115,6 +118,7 @@
'GitPatternRepository',
'LogFileUrlResponse',
'LogSpecification',
'ManagedIdentityProperties',
'MetricDimension',
'MetricSpecification',
'NameAvailability',
Expand Down Expand Up @@ -142,6 +146,7 @@
'ProvisioningState',
'ConfigServerState',
'TraceProxyState',
'ManagedIdentityType',
'TestKeyType',
'AppResourceProvisioningState',
'UserSourceType',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,14 @@ class TraceProxyState(str, Enum):
updating = "Updating"


class ManagedIdentityType(str, Enum):

none = "None"
system_assigned = "SystemAssigned"
user_assigned = "UserAssigned"

@xgugeng xgugeng Apr 8, 2020

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

keep none and system_assigned only, since the other two is not supported yet. Never mind, our backend handles the other two well

system_assigned_user_assigned = "SystemAssigned,UserAssigned"


class TestKeyType(str, Enum):

primary = "Primary"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,8 @@ class AppResource(ProxyResource):
:vartype type: str
:param properties: Properties of the App resource
:type properties: ~azure.mgmt.appplatform.models.AppResourceProperties
:param identity: The Managed Identity type of the app resource
:type identity: ~azure.mgmt.appplatform.models.ManagedIdentityProperties
:param location: The GEO location of the application, always the same with
its parent resource
:type location: str
Expand All @@ -107,12 +109,14 @@ class AppResource(ProxyResource):
'name': {'key': 'name', 'type': 'str'},
'type': {'key': 'type', 'type': 'str'},
'properties': {'key': 'properties', 'type': 'AppResourceProperties'},
'identity': {'key': 'identity', 'type': 'ManagedIdentityProperties'},
'location': {'key': 'location', 'type': 'str'},
}

def __init__(self, **kwargs):
super(AppResource, self).__init__(**kwargs)
self.properties = kwargs.get('properties', None)
self.identity = kwargs.get('identity', None)
self.location = kwargs.get('location', None)


Expand Down Expand Up @@ -778,6 +782,31 @@ def __init__(self, **kwargs):
self.blob_duration = kwargs.get('blob_duration', None)


class ManagedIdentityProperties(Model):
"""Managed identity properties retrieved from ARM request headers.

:param type: Possible values include: 'None', 'SystemAssigned',
'UserAssigned', 'SystemAssigned,UserAssigned'
:type type: str or ~azure.mgmt.appplatform.models.ManagedIdentityType
:param principal_id:
:type principal_id: str
:param tenant_id:
:type tenant_id: str
"""

_attribute_map = {
'type': {'key': 'type', 'type': 'str'},
'principal_id': {'key': 'principalId', 'type': 'str'},
'tenant_id': {'key': 'tenantId', 'type': 'str'},
}

def __init__(self, **kwargs):
super(ManagedIdentityProperties, self).__init__(**kwargs)
self.type = kwargs.get('type', None)
self.principal_id = kwargs.get('principal_id', None)
self.tenant_id = kwargs.get('tenant_id', None)


class MetricDimension(Model):
"""Specifications of the Dimension of metrics.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,8 @@ class AppResource(ProxyResource):
:vartype type: str
:param properties: Properties of the App resource
:type properties: ~azure.mgmt.appplatform.models.AppResourceProperties
:param identity: The Managed Identity type of the app resource
:type identity: ~azure.mgmt.appplatform.models.ManagedIdentityProperties
:param location: The GEO location of the application, always the same with
its parent resource
:type location: str
Expand All @@ -107,12 +109,14 @@ class AppResource(ProxyResource):
'name': {'key': 'name', 'type': 'str'},
'type': {'key': 'type', 'type': 'str'},
'properties': {'key': 'properties', 'type': 'AppResourceProperties'},
'identity': {'key': 'identity', 'type': 'ManagedIdentityProperties'},
'location': {'key': 'location', 'type': 'str'},
}

def __init__(self, *, properties=None, location: str=None, **kwargs) -> None:
def __init__(self, *, properties=None, identity=None, location: str=None, **kwargs) -> None:
super(AppResource, self).__init__(**kwargs)
self.properties = properties
self.identity = identity
self.location = location


Expand Down Expand Up @@ -778,6 +782,31 @@ def __init__(self, *, name: str=None, display_name: str=None, blob_duration: str
self.blob_duration = blob_duration


class ManagedIdentityProperties(Model):
"""Managed identity properties retrieved from ARM request headers.

:param type: Possible values include: 'None', 'SystemAssigned',
'UserAssigned', 'SystemAssigned,UserAssigned'
:type type: str or ~azure.mgmt.appplatform.models.ManagedIdentityType
:param principal_id:
:type principal_id: str
:param tenant_id:
:type tenant_id: str
"""

_attribute_map = {
'type': {'key': 'type', 'type': 'str'},
'principal_id': {'key': 'principalId', 'type': 'str'},
'tenant_id': {'key': 'tenantId', 'type': 'str'},
}

def __init__(self, *, type=None, principal_id: str=None, tenant_id: str=None, **kwargs) -> None:
super(ManagedIdentityProperties, self).__init__(**kwargs)
self.type = type
self.principal_id = principal_id
self.tenant_id = tenant_id


class MetricDimension(Model):
"""Specifications of the Dimension of metrics.

Expand Down
Loading