modified storageaccount fact return curated result with connection string (#49702)

This commit is contained in:
Yuwei Zhou 2019-02-18 16:48:56 +08:00 committed by Yunge Zhu
parent 896e320142
commit 664e6fb9c8
8 changed files with 521 additions and 66 deletions

View file

@ -205,7 +205,7 @@ def normalize_location_name(name):
AZURE_PKG_VERSIONS = {
'StorageManagementClient': {
'package_name': 'storage',
'expected_version': '1.5.0'
'expected_version': '3.1.0'
},
'ComputeManagementClient': {
'package_name': 'compute',
@ -379,6 +379,7 @@ class AzureRMModuleBase(object):
:param tags: metadata tags from the object
:return: bool, dict
'''
tags = tags or dict()
new_tags = copy.copy(tags) if isinstance(tags, dict) else dict()
param_tags = self.module.params.get('tags') if isinstance(self.module.params.get('tags'), dict) else dict()
append_tags = self.module.params.get('append_tags') if self.module.params.get('append_tags') is not None else True
@ -790,12 +791,12 @@ class AzureRMModuleBase(object):
if not self._storage_client:
self._storage_client = self.get_mgmt_svc_client(StorageManagementClient,
base_url=self._cloud_environment.endpoints.resource_manager,
api_version='2017-10-01')
api_version='2018-07-01')
return self._storage_client
@property
def storage_models(self):
return StorageManagementClient.models("2017-10-01")
return StorageManagementClient.models("2018-07-01")
@property
def network_client(self):

View file

@ -54,6 +54,7 @@ options:
- StandardSSD_LRS
- Standard_RAGRS
- Standard_ZRS
- Premium_ZRS
aliases:
- type
custom_domain:
@ -62,6 +63,8 @@ options:
keys where 'name' is the CNAME source. Only one custom domain is supported per storage account at this
time. To clear the existing custom domain, use an empty string for the custom domain name property.
- Can be added to an existing storage account. Will be ignored during storage account creation.
aliases:
- custom_dns_domain_suffix
kind:
description:
- The 'kind' of storage.
@ -78,10 +81,51 @@ options:
- Hot
- Cool
version_added: "2.4"
force:
force_delete_nonempty:
description:
- Attempt deletion if resource already exists and cannot be updated
type: bool
aliases:
- force
https_only:
description:
- Allows https traffic only to storage service if sets to true.
type: bool
version_added: "2.8"
blob_cors:
description:
- Specifies CORS rules for the Blob service.
- You can include up to five CorsRule elements in the request.
- If no blob_cors elements are included in the argument list, nothing about CORS will be changed.
- "If you want to delete all CORS rules and disable CORS for the Blob service, explicitly set blob_cors: []."
type: list
version_added: "2.8"
suboptions:
allowed_origins:
description:
- A list of origin domains that will be allowed via CORS, or "*" to allow all domains.
type: list
required: true
allowed_methods:
description:
- A list of HTTP methods that are allowed to be executed by the origin.
type: list
required: true
max_age_in_seconds:
description:
- The number of seconds that the client/browser should cache a preflight response.
type: int
required: true
exposed_headers:
description:
- A list of response headers to expose to CORS clients.
type: list
required: true
allowed_headers:
description:
- A list of headers allowed to be part of the cross-origin request.
type: list
required: true
extends_documentation_fragment:
- azure
@ -90,7 +134,6 @@ extends_documentation_fragment:
author:
- "Chris Houseknecht (@chouseknecht)"
- "Matt Davis (@nitzmahone)"
'''
EXAMPLES = '''
@ -108,6 +151,25 @@ EXAMPLES = '''
tags:
testing: testing
delete: on-exit
- name: create an account with blob CORS
azure_rm_storageaccount:
resource_group: Testing
name: clh002
type: Standard_RAGRS
blob_cors:
- allowed_origins:
- http://www.example.com/
allowed_methods:
- GET
- POST
allowed_headers:
- x-ms-meta-data*
- x-ms-meta-target*
- x-ms-meta-abc
exposed_headers:
- x-ms-meta-*
max_age_in_seconds: 200
'''
@ -151,7 +213,36 @@ except ImportError:
# This is handled in azure_rm_common
pass
from ansible.module_utils.azure_rm_common import AZURE_SUCCESS_STATE, AzureRMModuleBase, HAS_AZURE
import copy
from ansible.module_utils.azure_rm_common import AZURE_SUCCESS_STATE, AzureRMModuleBase
from ansible.module_utils._text import to_native
cors_rule_spec = dict(
allowed_origins=dict(type='list', elements='str', required=True),
allowed_methods=dict(type='list', elements='str', required=True),
max_age_in_seconds=dict(type='int', required=True),
exposed_headers=dict(type='list', elements='str', required=True),
allowed_headers=dict(type='list', elements='str', required=True),
)
def compare_cors(cors1, cors2):
if len(cors1) != len(cors2):
return False
copy2 = copy.copy(cors2)
for rule1 in cors1:
matched = False
for rule2 in copy2:
if (rule1['max_age_in_seconds'] == rule2['max_age_in_seconds']
and set(rule1['allowed_methods']) == set(rule2['allowed_methods'])
and set(rule1['allowed_origins']) == set(rule2['allowed_origins'])
and set(rule1['allowed_headers']) == set(rule2['allowed_headers'])
and set(rule1['exposed_headers']) == set(rule2['exposed_headers'])):
matched = True
copy2.remove(rule2)
if not matched:
return False
return True
class AzureRMStorageAccount(AzureRMModuleBase):
@ -159,24 +250,22 @@ class AzureRMStorageAccount(AzureRMModuleBase):
def __init__(self):
self.module_arg_spec = dict(
account_type=dict(type='str', choices=['Premium_LRS', 'Standard_GRS', 'Standard_LRS', 'StandardSSD_LRS', 'Standard_RAGRS', 'Standard_ZRS'],
account_type=dict(type='str',
choices=['Premium_LRS', 'Standard_GRS', 'Standard_LRS', 'StandardSSD_LRS', 'Standard_RAGRS', 'Standard_ZRS', 'Premium_ZRS'],
aliases=['type']),
custom_domain=dict(type='dict'),
custom_domain=dict(type='dict', aliases=['custom_dns_domain_suffix']),
location=dict(type='str'),
name=dict(type='str', required=True),
resource_group=dict(required=True, type='str', aliases=['resource_group_name']),
state=dict(default='present', choices=['present', 'absent']),
force=dict(type='bool', default=False),
force_delete_nonempty=dict(type='bool', default=False, aliases=['force']),
tags=dict(type='dict'),
kind=dict(type='str', default='Storage', choices=['Storage', 'StorageV2', 'BlobStorage']),
access_tier=dict(type='str', choices=['Hot', 'Cool'])
access_tier=dict(type='str', choices=['Hot', 'Cool']),
https_only=dict(type='bool', default=False),
blob_cors=dict(type='list', options=cors_rule_spec, elements='dict')
)
if HAS_AZURE:
for key in self.storage_models.SkuName:
if getattr(key, 'value') not in self.module_arg_spec['account_type']['choices']:
self.module_arg_spec['account_type']['choices'].append(getattr(key, 'value'))
self.results = dict(
changed=False,
state=dict()
@ -190,9 +279,11 @@ class AzureRMStorageAccount(AzureRMModuleBase):
self.account_type = None
self.custom_domain = None
self.tags = None
self.force = None
self.force_delete_nonempty = None
self.kind = None
self.access_tier = None
self.https_only = None
self.blob_cors = None
super(AzureRMStorageAccount, self).__init__(self.module_arg_spec,
supports_check_mode=True)
@ -254,19 +345,21 @@ class AzureRMStorageAccount(AzureRMModuleBase):
def get_account(self):
self.log('Get properties for account {0}'.format(self.name))
account_obj = None
blob_service_props = None
account_dict = None
try:
account_obj = self.storage_client.storage_accounts.get_properties(self.resource_group, self.name)
blob_service_props = self.storage_client.blob_services.get_service_properties(self.resource_group, self.name)
except CloudError:
pass
if account_obj:
account_dict = self.account_obj_to_dict(account_obj)
account_dict = self.account_obj_to_dict(account_obj, blob_service_props)
return account_dict
def account_obj_to_dict(self, account_obj):
def account_obj_to_dict(self, account_obj, blob_service_props=None):
account_dict = dict(
id=account_obj.id,
name=account_obj.name,
@ -283,7 +376,8 @@ class AzureRMStorageAccount(AzureRMModuleBase):
if account_obj.status_of_primary is not None else None),
status_of_secondary=(account_obj.status_of_secondary.value
if account_obj.status_of_secondary is not None else None),
primary_location=account_obj.primary_location
primary_location=account_obj.primary_location,
https_only=account_obj.enable_https_traffic_only
)
account_dict['custom_domain'] = None
if account_obj.custom_domain:
@ -309,10 +403,30 @@ class AzureRMStorageAccount(AzureRMModuleBase):
account_dict['tags'] = None
if account_obj.tags:
account_dict['tags'] = account_obj.tags
if blob_service_props and blob_service_props.cors and blob_service_props.cors.cors_rules:
account_dict['blob_cors'] = [dict(
allowed_origins=[to_native(y) for y in x.allowed_origins],
allowed_methods=[to_native(y) for y in x.allowed_methods],
max_age_in_seconds=x.max_age_in_seconds,
exposed_headers=[to_native(y) for y in x.exposed_headers],
allowed_headers=[to_native(y) for y in x.allowed_headers]
) for x in blob_service_props.cors.cors_rules]
return account_dict
def update_account(self):
self.log('Update storage account {0}'.format(self.name))
if bool(self.https_only) != bool(self.account_dict.get('https_only')):
self.results['changed'] = True
self.account_dict['https_only'] = self.https_only
if not self.check_mode:
try:
parameters = self.storage_models.StorageAccountUpdateParameters(enable_https_traffic_only=self.https_only)
self.storage_client.storage_accounts.update(self.resource_group,
self.name,
parameters)
except Exception as exc:
self.fail("Failed to update account type: {0}".format(str(exc)))
if self.account_type:
if self.account_type != self.account_dict['sku_name']:
# change the account type
@ -332,7 +446,7 @@ class AzureRMStorageAccount(AzureRMModuleBase):
try:
self.log("sku_name: %s" % self.account_dict['sku_name'])
self.log("sku_tier: %s" % self.account_dict['sku_tier'])
sku = self.storage_models.Sku(SkuName(self.account_dict['sku_name']))
sku = self.storage_models.Sku(name=SkuName(self.account_dict['sku_name']))
sku.tier = self.storage_models.SkuTier(self.account_dict['sku_tier'])
parameters = self.storage_models.StorageAccountUpdateParameters(sku=sku)
self.storage_client.storage_accounts.update(self.resource_group,
@ -377,6 +491,11 @@ class AzureRMStorageAccount(AzureRMModuleBase):
except Exception as exc:
self.fail("Failed to update tags: {0}".format(str(exc)))
if self.blob_cors and not compare_cors(self.account_dict.get('blob_cors', []), self.blob_cors):
self.results['changed'] = True
if not self.check_mode:
self.set_blob_cors()
def create_account(self):
self.log("Creating account {0}".format(self.name))
@ -398,16 +517,22 @@ class AzureRMStorageAccount(AzureRMModuleBase):
account_type=self.account_type,
name=self.name,
resource_group=self.resource_group,
enable_https_traffic_only=self.https_only,
tags=dict()
)
if self.tags:
account_dict['tags'] = self.tags
if self.blob_cors:
account_dict['blob_cors'] = self.blob_cors
return account_dict
sku = self.storage_models.Sku(self.storage_models.SkuName(self.account_type))
sku = self.storage_models.Sku(name=self.storage_models.SkuName(self.account_type))
sku.tier = self.storage_models.SkuTier.standard if 'Standard' in self.account_type else \
self.storage_models.SkuTier.premium
parameters = self.storage_models.StorageAccountCreateParameters(sku, self.kind, self.location,
tags=self.tags, access_tier=self.access_tier)
parameters = self.storage_models.StorageAccountCreateParameters(sku=sku,
kind=self.kind,
location=self.location,
tags=self.tags,
access_tier=self.access_tier)
self.log(str(parameters))
try:
poller = self.storage_client.storage_accounts.create(self.resource_group, self.name, parameters)
@ -415,13 +540,15 @@ class AzureRMStorageAccount(AzureRMModuleBase):
except CloudError as e:
self.log('Error creating storage account.')
self.fail("Failed to create account: {0}".format(str(e)))
if self.blob_cors:
self.set_blob_cors()
# the poller doesn't actually return anything
return self.get_account()
def delete_account(self):
if self.account_dict['provisioning_state'] == self.storage_models.ProvisioningState.succeeded.value and \
self.account_has_blob_containers() and self.force:
self.fail("Account contains blob containers. Is it in use? Use the force option to attempt deletion.")
not self.force_delete_nonempty and self.account_has_blob_containers():
self.fail("Account contains blob containers. Is it in use? Use the force_delete_nonempty option to attempt deletion.")
self.log('Delete storage account {0}'.format(self.name))
self.results['changed'] = True
@ -451,6 +578,15 @@ class AzureRMStorageAccount(AzureRMModuleBase):
return True
return False
def set_blob_cors(self):
try:
cors_rules = self.storage_models.CorsRules(cors_rules=[self.storage_models.CorsRule(**x) for x in self.blob_cors])
self.storage_client.blob_services.set_service_properties(self.resource_group,
self.name,
self.storage_models.BlobServiceProperties(cors=cors_rules))
except Exception as exc:
self.fail("Failed to set CORS rules: {0}".format(str(exc)))
def main():
AzureRMStorageAccount()

View file

@ -37,6 +37,18 @@ options:
tags:
description:
- Limit results by providing a list of tags. Format tags as 'key' or 'key:value'.
show_connection_string:
description:
- Show the connection string for each of the storageaccount's endpoints.
- Note that it will cost a lot of time when list all storageaccount rather than query a single one.
type: bool
version_added: "2.8"
show_blob_cors:
description:
- Show the blob CORS settings for each of the storageaccount's blob.
- Note that it will cost a lot time when list all storageaccount rather than querry a single one.
type: bool
version_added: "2.8"
extends_documentation_fragment:
- azure
@ -89,6 +101,176 @@ azure_storageaccounts:
"tags": {},
"type": "Microsoft.Storage/storageAccounts"
}]
storageaccounts:
description: List of storage account dicts in resource module's parameter format.
returned: always
type: complex
contains:
id:
description:
- Resource ID.
sample: "/subscriptions/XXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXX/resourceGroups/testing/providers/Microsoft.Storage/storageAccounts/testaccount001"
name:
description:
- Name of the storage account to update or create.
sample: "testaccount001"
location:
description:
- Valid azure location. Defaults to location of the resource group.
sample: eastus
account_type:
description:
- Type of storage account.
- "NOTE: Standard_ZRS and Premium_LRS accounts cannot be changed to other account types."
- Other account types cannot be changed to Standard_ZRS or Premium_LRS.
sample: Standard_ZRS
custom_domain:
description:
- User domain assigned to the storage account.
- Must be a dictionary with 'name' and 'use_sub_domain' keys where 'name' is the CNAME source.
type: complex
contains:
name:
description:
- CNAME source.
sample: testaccount
use_sub_domain:
description:
- whether to use sub domain.
sample: true
kind:
description:
- The 'kind' of storage.
sample: Storage
access_tier:
description:
- The access tier for this storage account.
sample: Hot
https_only:
description:
- Allows https traffic only to storage service if sets to true.
sample: false
provisioning_state:
description:
- Gets the status of the storage account at the time the operation was called.
- Possible values include 'Creating', 'ResolvingDNS', 'Succeeded'.
sample: Succeeded
secondary_location:
description:
- Gets the location of the geo-replicated secondary for the storage account.
- Only available if the accountType is Standard_GRS or Standard_RAGRS.
sample: westus
status_of_primary:
description:
- Gets the status indicating whether the primary location of the storage account is available or unavailable.
sample: available
status_of_secondary:
description:
- Gets the status indicating whether the secondary location of the storage account is available or unavailable.
sample: available
primary_location:
description:
- Gets the location of the primary data center for the storage account.
sample: eastus
primary_endpoints:
description:
- Gets the URLs that are used to perform a retrieval of a public blob, queue, or table object.
- Note that Standard_ZRS and Premium_LRS accounts only return the blob endpoint.
type: complex
contains:
blob:
description:
- Gets the primary blob endpoint and connection string.
type: complex
contains:
endpoint:
description:
- Gets the primary blob endpoint.
sample: "https://testaccount001.blob.core.windows.net/"
connectionstring:
description:
- Connectionstring of the blob endpoint
sample: "DefaultEndpointsProtocol=https;EndpointSuffix=core.windows.net;AccountName=X;AccountKey=X;BlobEndpoint=X"
queue:
description:
- Gets the primary queue endpoint and connection string.
type: complex
contains:
endpoint:
description:
- Gets the primary queue endpoint.
sample: "https://testaccount001.queue.core.windows.net/"
connectionstring:
description:
- Connectionstring of the queue endpoint
sample: "DefaultEndpointsProtocol=https;EndpointSuffix=core.windows.net;AccountName=X;AccountKey=X;QueueEndpoint=X"
table:
description:
- Gets the primary table endpoint and connection string.
type: complex
contains:
endpoint:
description:
- Gets the primary table endpoint.
sample: "https://testaccount001.table.core.windows.net/"
connectionstring:
description:
- Connectionstring of the table endpoint
sample: "DefaultEndpointsProtocol=https;EndpointSuffix=core.windows.net;AccountName=X;AccountKey=X;TableEndpoint=X"
secondary_endpoints:
description:
- Gets the URLs that are used to perform a retrieval of a public blob, queue, or table object from the secondary location.
- Only available if the SKU name is Standard_RAGRS.
type: complex
contains:
blob:
description:
- Gets the secondary blob endpoint and connection string.
type: complex
contains:
endpoint:
description:
- Gets the secondary blob endpoint.
sample: "https://testaccount001.blob.core.windows.net/"
connectionstring:
description:
- Connectionstring of the blob endpoint
sample: "DefaultEndpointsProtocol=https;EndpointSuffix=core.windows.net;AccountName=X;AccountKey=X;BlobEndpoint=X"
queue:
description:
- Gets the secondary queue endpoint and connection string.
type: complex
contains:
endpoint:
description:
- Gets the secondary queue endpoint.
sample: "https://testaccount001.queue.core.windows.net/"
connectionstring:
description:
- Connectionstring of the queue endpoint
sample: "DefaultEndpointsProtocol=https;EndpointSuffix=core.windows.net;AccountName=X;AccountKey=X;QueueEndpoint=X"
table:
description:
- Gets the secondary table endpoint and connection string.
type: complex
contains:
endpoint:
description:
- Gets the secondary table endpoint.
sample: "https://testaccount001.table.core.windows.net/"
connectionstring:
description:
- Connectionstring of the table endpoint
sample: "DefaultEndpointsProtocol=https;EndpointSuffix=core.windows.net;AccountName=X;AccountKey=X;TableEndpoint=X"
tags:
description:
- Resource tags.
type: dict
sample: { "tag1": "abc" }
blob_cors:
description:
- Blob CORS of blob.
type: list
'''
try:
@ -98,6 +280,7 @@ except Exception:
pass
from ansible.module_utils.azure_rm_common import AzureRMModuleBase
from ansible.module_utils._text import to_native
AZURE_OBJECT_CLASS = 'StorageAccount'
@ -110,16 +293,21 @@ class AzureRMStorageAccountFacts(AzureRMModuleBase):
name=dict(type='str'),
resource_group=dict(type='str', aliases=['resource_group_name']),
tags=dict(type='list'),
show_connection_string=dict(type='bool'),
show_blob_cors=dict(type='bool')
)
self.results = dict(
changed=False,
ansible_facts=dict(azure_storageaccounts=[])
ansible_facts=dict(azure_storageaccounts=[]),
storageaccounts=[]
)
self.name = None
self.resource_group = None
self.tags = None
self.show_connection_string = None
self.show_blob_cors = None
super(AzureRMStorageAccountFacts, self).__init__(self.module_arg_spec,
supports_tags=False,
@ -133,29 +321,29 @@ class AzureRMStorageAccountFacts(AzureRMModuleBase):
if self.name and not self.resource_group:
self.fail("Parameter error: resource group required when filtering by name.")
results = []
if self.name:
self.results['ansible_facts']['azure_storageaccounts'] = self.get_account()
results = self.get_account()
elif self.resource_group:
self.results['ansible_facts']['azure_storageaccounts'] = self.list_resource_group()
results = self.list_resource_group()
else:
self.results['ansible_facts']['azure_storageaccounts'] = self.list_all()
results = self.list_all()
filtered = self.filter_tag(results)
self.results['ansible_facts']['azure_storageaccounts'] = self.serialize(filtered)
self.results['ansible_facts']['storageaccounts'] = self.format_to_dict(filtered)
return self.results
def get_account(self):
self.log('Get properties for account {0}'.format(self.name))
account = None
result = []
try:
account = self.storage_client.storage_accounts.get_properties(self.resource_group, self.name)
return [account]
except CloudError:
pass
if account and self.has_tags(account.tags, self.tags):
result = [self.serialize_obj(account, AZURE_OBJECT_CLASS)]
return result
return []
def list_resource_group(self):
self.log('List items')
@ -164,11 +352,7 @@ class AzureRMStorageAccountFacts(AzureRMModuleBase):
except Exception as exc:
self.fail("Error listing for resource group {0} - {1}".format(self.resource_group, str(exc)))
results = []
for item in response:
if self.has_tags(item.tags, self.tags):
results.append(self.serialize_obj(item, AZURE_OBJECT_CLASS))
return results
return response
def list_all(self):
self.log('List all items')
@ -177,11 +361,110 @@ class AzureRMStorageAccountFacts(AzureRMModuleBase):
except Exception as exc:
self.fail("Error listing all items - {0}".format(str(exc)))
results = []
for item in response:
if self.has_tags(item.tags, self.tags):
results.append(self.serialize_obj(item, AZURE_OBJECT_CLASS))
return results
return response
def filter_tag(self, raw):
return [item for item in raw if self.has_tags(item.tags, self.tags)]
def serialize(self, raw):
return [self.serialize_obj(item, AZURE_OBJECT_CLASS) for item in raw]
def format_to_dict(self, raw):
return [self.account_obj_to_dict(item) for item in raw]
def account_obj_to_dict(self, account_obj, blob_service_props=None):
account_dict = dict(
id=account_obj.id,
name=account_obj.name,
location=account_obj.location,
access_tier=(account_obj.access_tier.value
if account_obj.access_tier is not None else None),
account_type=account_obj.sku.name.value,
kind=account_obj.kind.value if account_obj.kind else None,
provisioning_state=account_obj.provisioning_state.value,
secondary_location=account_obj.secondary_location,
status_of_primary=(account_obj.status_of_primary.value
if account_obj.status_of_primary is not None else None),
status_of_secondary=(account_obj.status_of_secondary.value
if account_obj.status_of_secondary is not None else None),
primary_location=account_obj.primary_location,
https_only=account_obj.enable_https_traffic_only
)
id_dict = self.parse_resource_to_dict(account_obj.id)
account_dict['resource_group'] = id_dict.get('resource_group')
account_key = self.get_connectionstring(account_dict['resource_group'], account_dict['name'])
account_dict['custom_domain'] = None
if account_obj.custom_domain:
account_dict['custom_domain'] = dict(
name=account_obj.custom_domain.name,
use_sub_domain=account_obj.custom_domain.use_sub_domain
)
account_dict['primary_endpoints'] = None
if account_obj.primary_endpoints:
account_dict['primary_endpoints'] = dict(
blob=self.format_endpoint_dict(account_dict['name'], account_key[0], account_obj.primary_endpoints.blob, 'blob'),
queue=self.format_endpoint_dict(account_dict['name'], account_key[0], account_obj.primary_endpoints.queue, 'queue'),
table=self.format_endpoint_dict(account_dict['name'], account_key[0], account_obj.primary_endpoints.table, 'table')
)
account_dict['secondary_endpoints'] = None
if account_obj.secondary_endpoints:
account_dict['secondary_endpoints'] = dict(
blob=self.format_endpoint_dict(account_dict['name'], account_key[1], account_obj.primary_endpoints.blob, 'blob'),
queue=self.format_endpoint_dict(account_dict['name'], account_key[1], account_obj.primary_endpoints.queue, 'queue'),
table=self.format_endpoint_dict(account_dict['name'], account_key[1], account_obj.primary_endpoints.table, 'table'),
)
account_dict['tags'] = None
if account_obj.tags:
account_dict['tags'] = account_obj.tags
blob_service_props = self.get_blob_service_props(account_dict['resource_group'], account_dict['name'])
if blob_service_props and blob_service_props.cors and blob_service_props.cors.cors_rules:
account_dict['blob_cors'] = [dict(
allowed_origins=to_native(x.allowed_origins),
allowed_methods=to_native(x.allowed_methods),
max_age_in_seconds=x.max_age_in_seconds,
exposed_headers=to_native(x.exposed_headers),
allowed_headers=to_native(x.allowed_headers)
) for x in blob_service_props.cors.cors_rules]
return account_dict
def format_endpoint_dict(self, name, key, endpoint, storagetype, protocol='https'):
result = dict(endpoint=endpoint)
if key:
result['connectionstring'] = 'DefaultEndpointsProtocol={0};EndpointSuffix={1};AccountName={2};AccountKey={3};{4}Endpoint={5}'.format(
protocol,
self._cloud_environment.suffixes.storage_endpoint,
name,
key,
str.title(storagetype),
endpoint)
return result
def get_blob_service_props(self, resource_group, name):
if not self.show_blob_cors:
return None
try:
blob_service_props = self.storage_client.blob_services.get_service_properties(resource_group, name)
return blob_service_props
except Exception:
pass
return None
def get_connectionstring(self, resource_group, name):
keys = ['', '']
if not self.show_connection_string:
return keys
try:
cred = self.storage_client.storage_accounts.list_keys(resource_group, name)
# get the following try catch from CLI
try:
keys = [cred.keys[0].value, cred.keys[1].value]
except AttributeError:
keys = [cred.key1, cred.key2]
except Exception:
pass
return keys
def main():

View file

@ -1779,10 +1779,10 @@ class AzureRMVirtualMachine(AzureRMModuleBase):
self.log("Storage account {0} found.".format(storage_account_name))
self.check_provisioning_state(account)
return account
sku = self.storage_models.Sku(self.storage_models.SkuName.standard_lrs)
sku = self.storage_models.Sku(name=self.storage_models.SkuName.standard_lrs)
sku.tier = self.storage_models.SkuTier.standard
kind = self.storage_models.Kind.storage
parameters = self.storage_models.StorageAccountCreateParameters(sku, kind, self.location)
parameters = self.storage_models.StorageAccountCreateParameters(sku=sku, kind=kind, location=self.location)
self.log("Creating storage account {0} in location {1}".format(storage_account_name, self.location))
self.results['actions'].append("Created storage account {0}".format(storage_account_name))
try:

View file

@ -19,7 +19,7 @@ azure-mgmt-redis==5.0.0
azure-mgmt-resource==1.2.2
azure-mgmt-rdbms==1.4.1
azure-mgmt-sql==0.10.0
azure-mgmt-storage==1.5.0
azure-mgmt-storage==3.1.0
azure-mgmt-trafficmanager==0.50.0
azure-mgmt-web==0.32.0
azure-nspkg==2.0.0

View file

@ -18,6 +18,7 @@
resource_group: "{{ resource_group }}"
name: "{{ storage_account }}"
state: absent
force_delete_nonempty: True
- name: Create new storage account
azure_rm_storageaccount:
@ -25,6 +26,19 @@
name: "{{ storage_account }}"
account_type: Standard_LRS
append_tags: no
blob_cors:
- allowed_origins:
- http://www.example.com/
allowed_methods:
- GET
- POST
allowed_headers:
- x-ms-meta-data*
- x-ms-meta-target*
- x-ms-meta-abc
exposed_headers:
- x-ms-meta-*
max_age_in_seconds: 200
tags:
test: test
galaxy: galaxy
@ -35,6 +49,35 @@
that:
- output.changed
- output.state.id is defined
- output.state.blob_cors | length == 1
- name: Create new storage account (idempotence)
azure_rm_storageaccount:
resource_group: "{{ resource_group }}"
name: "{{ storage_account }}"
account_type: Standard_LRS
append_tags: no
blob_cors:
- allowed_origins:
- http://www.example.com/
allowed_methods:
- GET
- POST
allowed_headers:
- x-ms-meta-data*
- x-ms-meta-target*
- x-ms-meta-abc
exposed_headers:
- x-ms-meta-*
max_age_in_seconds: 200
tags:
test: test
galaxy: galaxy
register: output
- assert:
that:
- not output.changed
- name: Gather facts by tags
azure_rm_storageaccount_facts:
@ -69,22 +112,6 @@
- name: Assert CNAME failure
assert: { that: "'custom domain name could not be verified' in change_account['msg']" }
- name: Update account tags
azure_rm_storageaccount:
resource_group: "{{ resource_group }}"
name: "{{ storage_account }}"
append_tags: no
tags:
testing: testing
delete: never
galaxy: 'no'
register: output
- assert:
that:
- "output.state.tags | length == 3"
- "output.state.tags.galaxy == 'no'"
- name: Update account tags
azure_rm_storageaccount:
resource_group: "{{ resource_group }}"
@ -105,10 +132,17 @@
azure_rm_storageaccount_facts:
resource_group: "{{ resource_group }}"
name: "{{ storage_account }}"
show_connection_string: True
show_blob_cors: True
- assert:
that:
- "azure_storageaccounts| length == 1"
- "storageaccounts | length == 1"
- not storageaccounts[0].custom_domain
- storageaccounts[0].account_type == "Standard_GRS"
- storageaccounts[0].primary_endpoints.blob.connectionstring
- storageaccounts[0].blob_cors
- name: Gather facts
azure_rm_storageaccount_facts:

View file

@ -165,6 +165,7 @@
name: "{{ storage_account }}"
type: Standard_LRS
state: absent
force_delete_nonempty: true
- name: Delete Network Security Group that allows SSH
azure_rm_securitygroup:

View file

@ -19,7 +19,7 @@ azure-mgmt-redis==5.0.0
azure-mgmt-resource==1.2.2
azure-mgmt-rdbms==1.4.1
azure-mgmt-sql==0.10.0
azure-mgmt-storage==1.5.0
azure-mgmt-storage==3.1.0
azure-mgmt-trafficmanager==0.50.0
azure-mgmt-web==0.32.0
azure-nspkg==2.0.0