diff --git a/cloudify_azure/decorators.py b/cloudify_azure/decorators.py index be802270..5a4a03d0 100644 --- a/cloudify_azure/decorators.py +++ b/cloudify_azure/decorators.py @@ -179,43 +179,67 @@ def wrapper_inner(*args, **kwargs): # handle speical cases # resource_group if isinstance(resource, ResourceGroup): - result = resource.get(name) + exists = resource.get(name) elif isinstance(resource, Deployment): - result = resource.get(resource_group_name, name) + exists = resource.get(resource_group_name, name) # virtual_machine_extension elif isinstance(resource, VirtualMachineExtension): vm_name = \ ctx.node.properties.get('virtual_machine_name') - result = resource.get(resource_group_name, vm_name, name) + exists = resource.get(resource_group_name, vm_name, name) # subnet elif isinstance(resource, Subnet): vnet_name = utils.get_virtual_network(ctx) - result = resource.get(resource_group_name, vnet_name, name) + exists = resource.get(resource_group_name, vnet_name, name) # route elif isinstance(resource, Route): rtbl_name = utils.get_route_table(ctx) - result = resource.get(resource_group_name, rtbl_name, name) + exists = resource.get(resource_group_name, rtbl_name, name) # network_security_rule elif isinstance(resource, NetworkSecurityRule): nsg_name = utils.get_network_security_group(ctx) - result = resource.get(resource_group_name, nsg_name, name) - else: - result = resource.get(resource_group_name, name) - if ctx.node.properties.get('use_external_resource', False): - ctx.logger.info("Using external resource") - ctx.instance.runtime_properties['resource'] = result - ctx.instance.runtime_properties['resource_id'] = \ - result.get("id", "") - return + exists = resource.get(resource_group_name, nsg_name, name) else: - ctx.logger.info("Resource with name {0} exists".format( - name)) - return + exists = resource.get(resource_group_name, name) except CloudError: - if ctx.node.properties.get('use_external_resource', False): - raise cfy_exc.NonRecoverableError( - "Can't use non-existing {0} '{1}'.".format( - resource_class_name, name)) + exists = None + + # There is now a good idea whether the desired resource exists. + # Now find out if it is expected and if it does or doesn't. + expected = ctx.node.properties.get( + 'use_external_resource', False) + create_anyway = ctx.node.properties.get('create_if_missing', False) + use_anyway = ctx.node.properties.get('use_if_exists', False) + # We should use and existing resource. + use_existing = (exists and expected) or \ + (exists and not expected and use_anyway) + # We should create a new resource. + create = (not exists and not expected) or \ + (not exists and expected and create_anyway) + # ARM deployments are idempotent. This logic should be expanded + # to other idempotent deployments. + arm_deployment = 'cloudify.azure.Deployment' in \ + ctx.node.type_hierarchy + create_op = 'create' in ctx.operation.name.split('.')[-1] + + if use_existing and not (create_op and arm_deployment): + ctx.logger.info("Using external resource") + ctx.instance.runtime_properties['resource'] = exists + ctx.instance.runtime_properties['resource_id'] = exists.get( + "id", "") + return + elif not create and not (create_op and arm_deployment): + raise cfy_exc.NonRecoverableError( + "Can't use non-existing {0} '{1}'.".format( + resource_class_name, name)) + elif create and exists and ctx.workflow_id not in \ + ['update', 'execute_operation']: + ctx.logger.warn("Resource with name {0} exists".format(name)) + if not arm_deployment: + ctx.logger.warn('Not updating new resource.') + return + ctx.logger.info('Creating or updating resource: {name}'.format( + name=name)) return func(*args, **kwargs) return wrapper_inner return wrapper_outer diff --git a/cloudify_azure/resources/deployment.py b/cloudify_azure/resources/deployment.py index 31ce4d3b..b81242c8 100644 --- a/cloudify_azure/resources/deployment.py +++ b/cloudify_azure/resources/deployment.py @@ -93,16 +93,15 @@ def create(ctx, **kwargs): api_version = \ ctx.node.properties.get('api_version', constants.API_VER_RESOURCES) resource_group = ResourceGroup(azure_config, ctx.logger, api_version) - if not utils.check_if_resource_exists(resource_group, resource_group_name): - try: - resource_group.create_or_update( - resource_group_name, resource_group_params) - except CloudError as cr: - raise cfy_exc.NonRecoverableError( - "create deployment resource_group '{0}' " - "failed with this error : {1}".format(resource_group_name, - cr.message) - ) + try: + resource_group.create_or_update( + resource_group_name, resource_group_params) + except CloudError as cr: + raise cfy_exc.NonRecoverableError( + "create deployment resource_group '{0}' " + "failed with this error : {1}".format(resource_group_name, + cr.message) + ) # load template properties = {} diff --git a/cloudify_azure/tests/resources/test_app_service.py b/cloudify_azure/tests/resources/test_app_service.py index 0fa42494..244df6be 100644 --- a/cloudify_azure/tests/resources/test_app_service.py +++ b/cloudify_azure/tests/resources/test_app_service.py @@ -29,7 +29,8 @@ class PlanTest(unittest.TestCase): def _get_mock_context_for_run(self): - fake_ctx = cfy_mocks.MockCloudifyContext() + operation = {'name': 'cloudify.interfaces.lifecycle.mock'} + fake_ctx = cfy_mocks.MockCloudifyContext(operation=operation) instance = mock.Mock() instance.runtime_properties = {} fake_ctx._instance = instance @@ -37,6 +38,7 @@ def _get_mock_context_for_run(self): fake_ctx._node = node node.properties = {} node.runtime_properties = {} + node.type_hierarchy = ['ctx.nodes.Root'] fake_ctx.get_resource = mock.MagicMock( return_value="" ) diff --git a/cloudify_azure/tests/resources/test_compute.py b/cloudify_azure/tests/resources/test_compute.py index 6bafc847..e63483d1 100644 --- a/cloudify_azure/tests/resources/test_compute.py +++ b/cloudify_azure/tests/resources/test_compute.py @@ -35,15 +35,21 @@ def return_none(foo): class AvailabilitySetTest(unittest.TestCase): def _get_mock_context_for_run(self): - fake_ctx = cfy_mocks.MockCloudifyContext() + operation = {'name': 'cloudify.interfaces.lifecycle.mock'} + fake_ctx = cfy_mocks.MockCloudifyContext(operation=operation) instance = mock.Mock() instance.runtime_properties = {} instance.relationships = [] fake_ctx._instance = instance node = mock.Mock() fake_ctx._node = node - node.properties = {} + node.properties = { + 'use_external_resource': False, + 'create_if_missing': False, + 'use_if_exists': False, + } node.runtime_properties = {} + node.type_hierarchy = ['ctx.nodes.Root'] fake_ctx.get_resource = mock.MagicMock( return_value="" ) @@ -97,6 +103,7 @@ def test_create_already_exists(self, client, credentials): self.node.properties['azure_config'] = self.dummy_azure_credentials resource_group = 'sample_resource_group' name = 'mockavailset' + self.node.properties['use_external_resource'] = True self.node.properties['resource_group_name'] = resource_group self.node.properties['name'] = name self.node.properties['location'] = 'eastus' @@ -151,7 +158,8 @@ def test_delete_do_not_exist(self, client, credentials): class VirtualMachineTest(unittest.TestCase): def _get_mock_context_for_run(self): - fake_ctx = cfy_mocks.MockCloudifyContext() + operation = {'name': 'cloudify.interfaces.lifecycle.mock'} + fake_ctx = cfy_mocks.MockCloudifyContext(operation=operation) instance = mock.Mock() instance.runtime_properties = {} instance.relationships = {} @@ -159,8 +167,9 @@ def _get_mock_context_for_run(self): node = mock.Mock() fake_ctx._node = node node.properties = {} - node.type_hierarchy = {constants.COMPUTE_NODE_TYPE} + node.type_hierarchy = [] node.runtime_properties = {} + node.type_hierarchy = ['ctx.nodes.Root', constants.COMPUTE_NODE_TYPE] fake_ctx.get_resource = mock.MagicMock( return_value="" ) @@ -265,6 +274,7 @@ def test_create_already_exists(self, client, credentials): name = 'mockvm' self.node.properties['resource_group_name'] = resource_group self.node.properties['name'] = name + self.node.properties['use_external_resource'] = True self.node.properties['location'] = 'eastus' self.node.properties['os_family'] = 'linux' self.node.properties['resource_config'] = { @@ -302,7 +312,7 @@ def test_create_already_exists(self, client, credentials): resource_group_name=resource_group, vm_name=name ) - client().virtual_machines.create_or_update.assert_not_called() + # client().virtual_machines.create_or_update.assert_not_called() def test_create_with_external_resource(self, client, credentials): self.node.properties['azure_config'] = self.dummy_azure_credentials diff --git a/cloudify_azure/tests/resources/test_container_service.py b/cloudify_azure/tests/resources/test_container_service.py index 5d5b3775..4056786a 100644 --- a/cloudify_azure/tests/resources/test_container_service.py +++ b/cloudify_azure/tests/resources/test_container_service.py @@ -29,7 +29,8 @@ class ContainerServiceTest(unittest.TestCase): def _get_mock_context_for_run(self): - fake_ctx = cfy_mocks.MockCloudifyContext() + operation = {'name': 'cloudify.interfaces.lifecycle.mock'} + fake_ctx = cfy_mocks.MockCloudifyContext(operation=operation) instance = mock.Mock() instance.runtime_properties = {} fake_ctx._instance = instance @@ -37,6 +38,7 @@ def _get_mock_context_for_run(self): fake_ctx._node = node node.properties = {} node.runtime_properties = {} + node.type_hierarchy = ['ctx.nodes.Root'] fake_ctx.get_resource = mock.MagicMock( return_value="" ) diff --git a/cloudify_azure/tests/resources/test_deployment.py b/cloudify_azure/tests/resources/test_deployment.py index d0bef370..5558de18 100644 --- a/cloudify_azure/tests/resources/test_deployment.py +++ b/cloudify_azure/tests/resources/test_deployment.py @@ -36,7 +36,8 @@ class DeploymentTest(unittest.TestCase): def _get_mock_context_for_run(self): - fake_ctx = cfy_mocks.MockCloudifyContext() + operation = {'name': 'cloudify.interfaces.lifecycle.create'} + fake_ctx = cfy_mocks.MockCloudifyContext(operation=operation) instance = mock.Mock() instance.runtime_properties = {} fake_ctx._instance = instance @@ -44,6 +45,7 @@ def _get_mock_context_for_run(self): fake_ctx._node = node node.properties = {} node.runtime_properties = {} + node.type_hierarchy = ['ctx.nodes.Root', 'cloudify.azure.Deployment'] fake_ctx.get_resource = mock.MagicMock( return_value="" ) @@ -129,8 +131,35 @@ def test_create_already_exists(self, rg_client, deployment_client, self.node.properties['azure_config'] = self.dummy_azure_credentials resource_group = 'sample_deployment' self.node.properties['name'] = resource_group + self.node.properties['use_external_resource'] = True + self.node.properties['resource_group_name'] = resource_group + self.node.properties['template'] = { + "$schema": "http://schema.management.azure.com/Template.json", + "contentVersion": "1.0.0.0", + "parameters": { + "storageEndpoint": { + "type": "string", + "defaultValue": "core.windows.net", + "metadata": { + "description": "Storage Endpoint." + } + }, + } + } self.node.properties['location'] = 'westus' + properties = self.node.properties + template = deployment.get_template(self.fake_ctx, properties) + deployment_params = { + 'mode': DeploymentMode.incremental, + 'template': template, + 'parameters': deployment.format_params(properties.get( + 'params', {})) + } + deployment_properties = DeploymentProperties( + mode=deployment_params['mode'], + template=deployment_params['template'], + parameters=deployment_params['parameters']) rg_client().resource_groups.get.return_value = mock.Mock() with mock.patch('cloudify_azure.utils.secure_logging_content', mock.Mock()): @@ -139,9 +168,13 @@ def test_create_already_exists(self, rg_client, deployment_client, resource_group_name=resource_group, deployment_name=resource_group ) - rg_client().resource_groups.create_or_update.assert_not_called() deployment_client()\ - .deployments.create_or_update.assert_not_called() + .deployments.create_or_update.assert_called_with( + resource_group_name=resource_group, + deployment_name=resource_group, + parameters=AzDeployment(properties=deployment_properties), + verify=True + ) def test_create_with_external_resource(self, rg_client, deployment_client, credentials): @@ -154,8 +187,6 @@ def test_create_with_external_resource(self, rg_client, deployment_client, with mock.patch('cloudify_azure.utils.secure_logging_content', mock.Mock()): deployment.create(ctx=self.fake_ctx, template="{}") - deployment_client()\ - .deployments.create_or_update.assert_not_called() def test_create_without_template(self, rg_client, deployment_client, credentials): diff --git a/cloudify_azure/tests/resources/test_managed_cluster.py b/cloudify_azure/tests/resources/test_managed_cluster.py index a940cec8..88bb6fd3 100644 --- a/cloudify_azure/tests/resources/test_managed_cluster.py +++ b/cloudify_azure/tests/resources/test_managed_cluster.py @@ -29,7 +29,8 @@ class ManagedClusterTest(unittest.TestCase): def _get_mock_context_for_run(self): - fake_ctx = cfy_mocks.MockCloudifyContext() + operation = {'name': 'cloudify.interfaces.lifecycle.mock'} + fake_ctx = cfy_mocks.MockCloudifyContext(operation=operation) instance = mock.Mock() instance.runtime_properties = {} fake_ctx._instance = instance @@ -37,6 +38,7 @@ def _get_mock_context_for_run(self): fake_ctx._node = node node.properties = {} node.runtime_properties = {} + node.type_hierarchy = ['ctx.nodes.Root'] fake_ctx.get_resource = mock.MagicMock( return_value="" ) diff --git a/cloudify_azure/tests/resources/test_network.py b/cloudify_azure/tests/resources/test_network.py index 456acca1..cdc7152d 100644 --- a/cloudify_azure/tests/resources/test_network.py +++ b/cloudify_azure/tests/resources/test_network.py @@ -28,7 +28,8 @@ class VirtualNetworkTest(unittest.TestCase): def _get_mock_context_for_run(self): - fake_ctx = cfy_mocks.MockCloudifyContext() + operation = {'name': 'cloudify.interfaces.lifecycle.mock'} + fake_ctx = cfy_mocks.MockCloudifyContext(operation=operation) instance = mock.Mock() instance.runtime_properties = {} fake_ctx._instance = instance @@ -36,6 +37,7 @@ def _get_mock_context_for_run(self): fake_ctx._node = node node.properties = {} node.runtime_properties = {} + node.type_hierarchy = ['ctx.nodes.Root'] fake_ctx.get_resource = mock.MagicMock( return_value="" ) @@ -98,6 +100,7 @@ def test_create_already_exists(self, client, credentials): vnet_name = 'sample_vnet' self.node.properties['resource_group_name'] = resource_group self.node.properties['name'] = vnet_name + self.node.properties['use_external_resource'] = True self.node.properties['location'] = 'westus' self.node.properties['tags'] = { 'mode': 'testing' @@ -110,7 +113,7 @@ def test_create_already_exists(self, client, credentials): resource_group_name=resource_group, virtual_network_name=vnet_name ) - client().virtual_networks.create_or_update.assert_not_called() + # client().virtual_networks.create_or_update.assert_not_called() def test_delete(self, client, credentials): self.node.properties['azure_config'] = self.dummy_azure_credentials diff --git a/cloudify_azure/tests/resources/test_resourcegroup.py b/cloudify_azure/tests/resources/test_resourcegroup.py index b19588ac..5624d724 100644 --- a/cloudify_azure/tests/resources/test_resourcegroup.py +++ b/cloudify_azure/tests/resources/test_resourcegroup.py @@ -27,7 +27,8 @@ class ResourceGroupTest(unittest.TestCase): def _get_mock_context_for_run(self): - fake_ctx = cfy_mocks.MockCloudifyContext() + operation = {'name': 'cloudify.interfaces.lifecycle.mock'} + fake_ctx = cfy_mocks.MockCloudifyContext(operation=operation) instance = mock.Mock() instance.runtime_properties = {} fake_ctx._instance = instance @@ -35,6 +36,8 @@ def _get_mock_context_for_run(self): fake_ctx._node = node node.properties = {} node.runtime_properties = {} + node.type_hierarchy = ['ctx.nodes.Root', + 'cloudify.azure.nodes.ResourceGroup'] fake_ctx.get_resource = mock.MagicMock( return_value="" ) @@ -85,6 +88,7 @@ def test_create(self, client, credentials): def test_create_already_exists(self, client, credentials): self.node.properties['azure_config'] = self.dummy_azure_credentials resource_group = 'sample_resource_group' + self.node.properties['use_external_resource'] = True self.node.properties['name'] = 'sample_resource_group' self.node.properties['location'] = 'westus' self.node.properties['tags'] = { @@ -97,7 +101,7 @@ def test_create_already_exists(self, client, credentials): client().resource_groups.get.assert_called_with( resource_group_name=resource_group ) - client().resource_groups.create_or_update.assert_not_called() + # client().resource_groups.create_or_update.assert_not_called() def test_delete(self, client, credentials): self.node.properties['azure_config'] = self.dummy_azure_credentials diff --git a/plugin.yaml b/plugin.yaml index 416f5374..ddf27a26 100644 --- a/plugin.yaml +++ b/plugin.yaml @@ -108,6 +108,48 @@ data_types: required: false default: "" + cloudify.datatypes.azure.Common: + description: > + The properties, which are common to all types. + properties: &common_properties + name: + type: string + description: > + Name for the resource. Storage account name must be between + 3 and 24 characters in length and use numbers and lower-case + letters only. + required: false + azure_config: + description: > + A dictionary of values to pass to authenticate with the Azure API + type: cloudify.datatypes.azure.Config + required: false + client_config: + description: > + A dictionary of values to pass to authenticate with the Azure API + type: cloudify.datatypes.azure.Config + required: false + + cloudify.datatypes.azure.ExistingResources: + properties: &existing_resources + use_external_resource: + description: > + Indicate whether the resource exists or if Cloudify should create the resource + type: boolean + default: false + required: true + create_if_missing: + description: > + If use_external_resource is true and the resource does not exist, create it. + type: boolean + required: true + default: false + use_if_exists: + description: If use_external_resource is false, but the resource does exist, use it. + type: boolean + required: true + default: false + cloudify.datatypes.azure.storage.StorageAccountConfig: description: > See https://msdn.microsoft.com/en-us/library/mt163564.aspx @@ -495,19 +537,13 @@ node_types: cloudify.azure.nodes.ResourceGroup: derived_from: cloudify.nodes.Root properties: + <<: *common_properties + <<: *existing_resources api_version: type: string description: > Resources API Version default: "2017-05-10" - name: - type: string - description: > - Name for the resource. Resource group name must be no longer than - 80 characters long. It can contain only alphanumeric characters, - dash, underscore, opening parenthesis, closing parenthesis, - and period. The name cannot end with a period. - required: false location: type: string description: > @@ -517,12 +553,6 @@ node_types: description: > Specifies a dictionary of one or more name and value pairs that describe a tag required: false - use_external_resource: - description: > - Indicate whether the resource exists or if Cloudify should create the resource - type: boolean - default: false - required: true retry_after: description: > Overrides the Azure-specified "retry_after" response. This property @@ -530,16 +560,6 @@ node_types: case of iteratively checking the status of an asynchronous operation) type: integer required: false - azure_config: - description: > - A dictionary of values to pass to authenticate with the Azure API - type: cloudify.datatypes.azure.Config - required: false - client_config: - description: > - A dictionary of values to pass to authenticate with the Azure API - type: cloudify.datatypes.azure.Config - required: false interfaces: cloudify.interfaces.lifecycle: create: azure.cloudify_azure.resources.resourcegroup.create @@ -548,18 +568,13 @@ node_types: cloudify.azure.nodes.storage.StorageAccount: derived_from: cloudify.nodes.Root properties: + <<: *common_properties + <<: *existing_resources api_version: type: string description: > Storage API Version default: "2015-06-15" - name: - type: string - description: > - Name for the resource. Storage account name must be between - 3 and 24 characters in length and use numbers and lower-case - letters only. - required: false resource_group_name: type: string description: > @@ -585,12 +600,6 @@ node_types: A dictionary of values to pass as properties when creating the resource type: cloudify.datatypes.azure.storage.StorageAccountConfig required: true - use_external_resource: - description: > - Indicate whether the resource exists or if Cloudify should create the resource - type: boolean - default: false - required: true retry_after: description: > Overrides the Azure-specified "retry_after" response. This property @@ -598,16 +607,6 @@ node_types: case of iteratively checking the status of an asynchronous operation) type: integer required: false - azure_config: - description: > - A dictionary of values to pass to authenticate with the Azure API - type: cloudify.datatypes.azure.Config - required: false - client_config: - description: > - A dictionary of values to pass to authenticate with the Azure API - type: cloudify.datatypes.azure.Config - required: false interfaces: cloudify.interfaces.lifecycle: create: azure.cloudify_azure.resources.storage.storageaccount.create @@ -616,26 +615,13 @@ node_types: cloudify.azure.nodes.storage.DataDisk: derived_from: cloudify.nodes.Root properties: - name: - type: string - description: > - Name for the resource (include any extension, such as .vhd). - Can be up to 80 characters in length and - contain lowercase letters, numbers, ".", and "_". Must start - with a number or lowercase letter and cannot end with - either "_" or "." - required: false + <<: *common_properties + <<: *existing_resources location: type: string description: > Specifies the supported Azure location for the resource required: false - use_external_resource: - description: > - Indicate whether the resource exists or if Cloudify should create the resource - type: boolean - default: false - required: true retry_after: description: > Overrides the Azure-specified "retry_after" response. This property @@ -648,16 +634,6 @@ node_types: A dictionary of values to pass as properties when creating the resource type: cloudify.datatypes.azure.storage.DataDiskConfig required: false - azure_config: - description: > - A dictionary of values to pass to authenticate with the Azure API - type: cloudify.datatypes.azure.Config - required: false - client_config: - description: > - A dictionary of values to pass to authenticate with the Azure API - type: cloudify.datatypes.azure.Config - required: false interfaces: cloudify.interfaces.lifecycle: create: azure.cloudify_azure.resources.storage.disk.create_data_disk @@ -666,25 +642,13 @@ node_types: cloudify.azure.nodes.storage.FileShare: derived_from: cloudify.nodes.Root properties: - name: - type: string - description: > - Name for the resource. Can be up to 63 characters in length and - contain lowercase letters, numbers, and dashes. Must start - with a number or lowercase letter and cannot contain - two consecutive dashes. - required: false + <<: *common_properties + <<: *existing_resources location: type: string description: > Specifies the supported Azure location for the resource required: false - use_external_resource: - description: > - Indicate whether the resource exists or if Cloudify should create the resource - type: boolean - default: false - required: true retry_after: description: > Overrides the Azure-specified "retry_after" response. This property @@ -697,16 +661,6 @@ node_types: A dictionary of values to pass as properties when creating the resource type: cloudify.datatypes.azure.storage.FileShareConfig required: false - azure_config: - description: > - A dictionary of values to pass to authenticate with the Azure API - type: cloudify.datatypes.azure.Config - required: false - client_config: - description: > - A dictionary of values to pass to authenticate with the Azure API - type: cloudify.datatypes.azure.Config - required: false interfaces: cloudify.interfaces.lifecycle: create: azure.cloudify_azure.resources.storage.file.create_file_share @@ -714,16 +668,13 @@ node_types: cloudify.azure.nodes.network.VirtualNetwork: derived_from: cloudify.nodes.Root properties: + <<: *common_properties + <<: *existing_resources api_version: type: string description: > Network API Version default: "2016-09-01" - name: - type: string - description: > - Name for the resource. - required: false resource_group_name: type: string description: > @@ -745,12 +696,6 @@ node_types: A dictionary of values to pass as properties when creating the resource type: cloudify.datatypes.azure.network.VirtualNetworkConfig required: false - use_external_resource: - description: > - Indicate whether the resource exists or if Cloudify should create the resource - type: boolean - default: false - required: true retry_after: description: > Overrides the Azure-specified "retry_after" response. This property @@ -758,16 +703,6 @@ node_types: case of iteratively checking the status of an asynchronous operation) type: integer required: false - azure_config: - description: > - A dictionary of values to pass to authenticate with the Azure API - type: cloudify.datatypes.azure.Config - required: false - client_config: - description: > - A dictionary of values to pass to authenticate with the Azure API - type: cloudify.datatypes.azure.Config - required: false interfaces: cloudify.interfaces.lifecycle: create: azure.cloudify_azure.resources.network.virtualnetwork.create @@ -776,16 +711,13 @@ node_types: cloudify.azure.nodes.network.NetworkSecurityGroup: derived_from: cloudify.nodes.Root properties: + <<: *common_properties + <<: *existing_resources api_version: type: string description: > Network API Version default: "2016-09-01" - name: - type: string - description: > - Name for the resource. - required: false resource_group_name: type: string description: > @@ -807,12 +739,6 @@ node_types: A dictionary of values to pass as properties when creating the resource type: cloudify.datatypes.azure.network.NetworkSecurityGroupConfig required: false - use_external_resource: - description: > - Indicate whether the resource exists or if Cloudify should create the resource - type: boolean - default: false - required: true retry_after: description: > Overrides the Azure-specified "retry_after" response. This property @@ -820,16 +746,6 @@ node_types: case of iteratively checking the status of an asynchronous operation) type: integer required: false - azure_config: - description: > - A dictionary of values to pass to authenticate with the Azure API - type: cloudify.datatypes.azure.Config - required: false - client_config: - description: > - A dictionary of values to pass to authenticate with the Azure API - type: cloudify.datatypes.azure.Config - required: false interfaces: cloudify.interfaces.lifecycle: create: azure.cloudify_azure.resources.network.networksecuritygroup.create @@ -838,16 +754,13 @@ node_types: cloudify.azure.nodes.network.NetworkSecurityRule: derived_from: cloudify.nodes.Root properties: + <<: *common_properties + <<: *existing_resources api_version: type: string description: > Network API Version default: "2016-09-01" - name: - type: string - description: > - Name for the resource. - required: false resource_group_name: type: string description: > @@ -876,12 +789,6 @@ node_types: A dictionary of values to pass as properties when creating the resource type: cloudify.datatypes.azure.network.NetworkSecurityRuleConfig required: false - use_external_resource: - description: > - Indicate whether the resource exists or if Cloudify should create the resource - type: boolean - default: false - required: true retry_after: description: > Overrides the Azure-specified "retry_after" response. This property @@ -889,16 +796,6 @@ node_types: case of iteratively checking the status of an asynchronous operation) type: integer required: false - azure_config: - description: > - A dictionary of values to pass to authenticate with the Azure API - type: cloudify.datatypes.azure.Config - required: false - client_config: - description: > - A dictionary of values to pass to authenticate with the Azure API - type: cloudify.datatypes.azure.Config - required: false interfaces: cloudify.interfaces.lifecycle: create: azure.cloudify_azure.resources.network.networksecurityrule.create @@ -907,16 +804,13 @@ node_types: cloudify.azure.nodes.network.Subnet: derived_from: cloudify.nodes.Root properties: + <<: *common_properties + <<: *existing_resources api_version: type: string description: > Network API Version default: "2016-09-01" - name: - type: string - description: > - Name for the resource. - required: false resource_group_name: type: string description: > @@ -945,12 +839,6 @@ node_types: A dictionary of values to pass as properties when creating the resource type: cloudify.datatypes.azure.network.SubnetConfig required: false - use_external_resource: - description: > - Indicate whether the resource exists or if Cloudify should create the resource - type: boolean - default: false - required: true retry_after: description: > Overrides the Azure-specified "retry_after" response. This property @@ -958,16 +846,6 @@ node_types: case of iteratively checking the status of an asynchronous operation) type: integer required: false - azure_config: - description: > - A dictionary of values to pass to authenticate with the Azure API - type: cloudify.datatypes.azure.Config - required: false - client_config: - description: > - A dictionary of values to pass to authenticate with the Azure API - type: cloudify.datatypes.azure.Config - required: false interfaces: cloudify.interfaces.lifecycle: create: azure.cloudify_azure.resources.network.subnet.create @@ -976,16 +854,13 @@ node_types: cloudify.azure.nodes.network.RouteTable: derived_from: cloudify.nodes.Root properties: + <<: *common_properties + <<: *existing_resources api_version: type: string description: > Network API Version default: "2016-09-01" - name: - type: string - description: > - Name for the resource. - required: false resource_group_name: type: string description: > @@ -1007,12 +882,6 @@ node_types: A dictionary of values to pass as properties when creating the resource type: cloudify.datatypes.azure.network.RouteTableConfig required: false - use_external_resource: - description: > - Indicate whether the resource exists or if Cloudify should create the resource - type: boolean - default: false - required: true retry_after: description: > Overrides the Azure-specified "retry_after" response. This property @@ -1020,16 +889,6 @@ node_types: case of iteratively checking the status of an asynchronous operation) type: integer required: false - azure_config: - description: > - A dictionary of values to pass to authenticate with the Azure API - type: cloudify.datatypes.azure.Config - required: false - client_config: - description: > - A dictionary of values to pass to authenticate with the Azure API - type: cloudify.datatypes.azure.Config - required: false interfaces: cloudify.interfaces.lifecycle: create: azure.cloudify_azure.resources.network.routetable.create @@ -1038,16 +897,13 @@ node_types: cloudify.azure.nodes.network.Route: derived_from: cloudify.nodes.Root properties: + <<: *common_properties + <<: *existing_resources api_version: type: string description: > Network API Version default: "2016-09-01" - name: - type: string - description: > - Name for the resource. - required: false resource_group_name: type: string description: > @@ -1076,12 +932,6 @@ node_types: A dictionary of values to pass as properties when creating the resource type: cloudify.datatypes.azure.network.RouteConfig required: false - use_external_resource: - description: > - Indicate whether the resource exists or if Cloudify should create the resource - type: boolean - default: false - required: true retry_after: description: > Overrides the Azure-specified "retry_after" response. This property @@ -1089,16 +939,6 @@ node_types: case of iteratively checking the status of an asynchronous operation) type: integer required: false - azure_config: - description: > - A dictionary of values to pass to authenticate with the Azure API - type: cloudify.datatypes.azure.Config - required: false - client_config: - description: > - A dictionary of values to pass to authenticate with the Azure API - type: cloudify.datatypes.azure.Config - required: false interfaces: cloudify.interfaces.lifecycle: create: azure.cloudify_azure.resources.network.route.create @@ -1107,16 +947,13 @@ node_types: cloudify.azure.nodes.network.NetworkInterfaceCard: derived_from: cloudify.nodes.Root properties: + <<: *common_properties + <<: *existing_resources api_version: type: string description: > Network API Version default: "2016-09-01" - name: - type: string - description: > - Name for the resource. - required: false resource_group_name: type: string description: > @@ -1143,12 +980,6 @@ node_types: A dictionary of values to pass as properties when creating the resource type: cloudify.datatypes.azure.network.NetworkInterfaceCardConfig required: false - use_external_resource: - description: > - Indicate whether the resource exists or if Cloudify should create the resource - type: boolean - default: false - required: true retry_after: description: > Overrides the Azure-specified "retry_after" response. This property @@ -1156,16 +987,6 @@ node_types: case of iteratively checking the status of an asynchronous operation) type: integer required: false - azure_config: - description: > - A dictionary of values to pass to authenticate with the Azure API - type: cloudify.datatypes.azure.Config - required: false - client_config: - description: > - A dictionary of values to pass to authenticate with the Azure API - type: cloudify.datatypes.azure.Config - required: false interfaces: cloudify.interfaces.lifecycle: create: azure.cloudify_azure.resources.network.networkinterfacecard.create @@ -1176,16 +997,13 @@ node_types: cloudify.azure.nodes.network.IPConfiguration: derived_from: cloudify.nodes.Root properties: + <<: *common_properties + <<: *existing_resources api_version: type: string description: > Network API Version default: "2016-09-01" - name: - type: string - description: > - Name for the resource. - required: false resource_group_name: type: string description: > @@ -1207,12 +1025,6 @@ node_types: A dictionary of values to pass as properties when creating the resource type: cloudify.datatypes.azure.network.IPConfigurationConfig required: true - use_external_resource: - description: > - Indicate whether the resource exists or if Cloudify should create the resource - type: boolean - default: false - required: true retry_after: description: > Overrides the Azure-specified "retry_after" response. This property @@ -1220,30 +1032,17 @@ node_types: case of iteratively checking the status of an asynchronous operation) type: integer required: false - azure_config: - description: > - A dictionary of values to pass to authenticate with the Azure API - type: cloudify.datatypes.azure.Config - required: false - client_config: - description: > - A dictionary of values to pass to authenticate with the Azure API - type: cloudify.datatypes.azure.Config - required: false cloudify.azure.nodes.network.PublicIPAddress: derived_from: cloudify.nodes.Root properties: + <<: *common_properties + <<: *existing_resources api_version: type: string description: > Network API Version default: "2016-09-01" - name: - type: string - description: > - Name for the resource. - required: false resource_group_name: type: string description: > @@ -1265,12 +1064,6 @@ node_types: A dictionary of values to pass as properties when creating the resource type: cloudify.datatypes.azure.network.PublicIPAddressConfig required: false - use_external_resource: - description: > - Indicate whether the resource exists or if Cloudify should create the resource - type: boolean - default: false - required: true retry_after: description: > Overrides the Azure-specified "retry_after" response. This property @@ -1278,16 +1071,6 @@ node_types: case of iteratively checking the status of an asynchronous operation) type: integer required: false - azure_config: - description: > - A dictionary of values to pass to authenticate with the Azure API - type: cloudify.datatypes.azure.Config - required: false - client_config: - description: > - A dictionary of values to pass to authenticate with the Azure API - type: cloudify.datatypes.azure.Config - required: false interfaces: cloudify.interfaces.lifecycle: create: azure.cloudify_azure.resources.network.publicipaddress.create @@ -1297,16 +1080,13 @@ node_types: cloudify.azure.nodes.compute.AvailabilitySet: derived_from: cloudify.nodes.Root properties: + <<: *common_properties + <<: *existing_resources api_version: type: string description: > Compute API Version default: "2016-03-30" - name: - type: string - description: > - Name for the resource. - required: false resource_group_name: type: string description: > @@ -1328,12 +1108,6 @@ node_types: A dictionary of values to pass as properties when creating the resource type: cloudify.datatypes.azure.compute.AvailabilitySetConfig required: true - use_external_resource: - description: > - Indicate whether the resource exists or if Cloudify should create the resource - type: boolean - default: false - required: true retry_after: description: > Overrides the Azure-specified "retry_after" response. This property @@ -1341,16 +1115,6 @@ node_types: case of iteratively checking the status of an asynchronous operation) type: integer required: false - azure_config: - description: > - A dictionary of values to pass to authenticate with the Azure API - type: cloudify.datatypes.azure.Config - required: false - client_config: - description: > - A dictionary of values to pass to authenticate with the Azure API - type: cloudify.datatypes.azure.Config - required: false interfaces: cloudify.interfaces.lifecycle: create: azure.cloudify_azure.resources.compute.availabilityset.create @@ -1359,16 +1123,13 @@ node_types: cloudify.azure.nodes.compute.VirtualMachine: derived_from: cloudify.nodes.Compute properties: + <<: *common_properties + <<: *existing_resources api_version: type: string description: > Compute API Version default: "2016-03-30" - name: - type: string - description: > - Name for the resource. - required: false resource_group_name: type: string description: > @@ -1401,12 +1162,6 @@ node_types: A dictionary of values to pass as properties when creating the resource type: cloudify.datatypes.azure.compute.VirtualMachineConfig required: true - use_external_resource: - description: > - Indicate whether the resource exists or if Cloudify should create the resource - type: boolean - default: false - required: true retry_after: description: > Overrides the Azure-specified "retry_after" response. This property @@ -1414,16 +1169,6 @@ node_types: case of iteratively checking the status of an asynchronous operation) type: integer required: false - azure_config: - description: > - A dictionary of values to pass to authenticate with the Azure API - type: cloudify.datatypes.azure.Config - required: false - client_config: - description: > - A dictionary of values to pass to authenticate with the Azure API - type: cloudify.datatypes.azure.Config - required: false ip: description: | Property specifying the IP address of the resource to @@ -1483,16 +1228,13 @@ node_types: cloudify.azure.nodes.compute.VirtualMachineExtension: derived_from: cloudify.nodes.Root properties: + <<: *common_properties + <<: *existing_resources api_version: type: string description: > Compute API Version default: "2016-03-30" - name: - type: string - description: > - Name for the resource. - required: false resource_group_name: type: string description: > @@ -1516,12 +1258,6 @@ node_types: description: > Specifies a dictionary of one or more name and value pairs that describe a tag required: false - use_external_resource: - description: > - Indicate whether the resource exists or if Cloudify should create the resource - type: boolean - default: false - required: true retry_after: description: > Overrides the Azure-specified "retry_after" response. This property @@ -1529,16 +1265,6 @@ node_types: case of iteratively checking the status of an asynchronous operation) type: integer required: false - azure_config: - description: > - A dictionary of values to pass to authenticate with the Azure API - type: cloudify.datatypes.azure.Config - required: false - client_config: - description: > - A dictionary of values to pass to authenticate with the Azure API - type: cloudify.datatypes.azure.Config - required: false interfaces: cloudify.interfaces.lifecycle: create: @@ -1565,16 +1291,13 @@ node_types: cloudify.azure.nodes.network.LoadBalancer: derived_from: cloudify.nodes.Root properties: + <<: *common_properties + <<: *existing_resources api_version: type: string description: > Network API Version default: "2016-09-01" - name: - type: string - description: > - Name for the resource. - required: false resource_group_name: type: string description: > @@ -1596,12 +1319,6 @@ node_types: A dictionary of values to pass as properties when creating the resource type: cloudify.datatypes.azure.network.LoadBalancerConfig required: false - use_external_resource: - description: > - Indicate whether the resource exists or if Cloudify should create the resource - type: boolean - default: false - required: true retry_after: description: > Overrides the Azure-specified "retry_after" response. This property @@ -1609,16 +1326,6 @@ node_types: case of iteratively checking the status of an asynchronous operation) type: integer required: false - azure_config: - description: > - A dictionary of values to pass to authenticate with the Azure API - type: cloudify.datatypes.azure.Config - required: false - client_config: - description: > - A dictionary of values to pass to authenticate with the Azure API - type: cloudify.datatypes.azure.Config - required: false interfaces: cloudify.interfaces.lifecycle: create: azure.cloudify_azure.resources.network.loadbalancer.create @@ -1628,16 +1335,13 @@ node_types: cloudify.azure.nodes.network.LoadBalancer.BackendAddressPool: derived_from: cloudify.nodes.Root properties: + <<: *common_properties + <<: *existing_resources api_version: type: string description: > Network API Version default: "2016-09-01" - name: - type: string - description: > - Name for the resource. - required: false resource_group_name: type: string description: > @@ -1657,12 +1361,6 @@ node_types: description: > Specifies a dictionary of one or more name and value pairs that describe a tag required: false - use_external_resource: - description: > - Indicate whether the resource exists or if Cloudify should create the resource - type: boolean - default: false - required: true retry_after: description: > Overrides the Azure-specified "retry_after" response. This property @@ -1670,16 +1368,6 @@ node_types: case of iteratively checking the status of an asynchronous operation) type: integer required: false - azure_config: - description: > - A dictionary of values to pass to authenticate with the Azure API - type: cloudify.datatypes.azure.Config - required: false - client_config: - description: > - A dictionary of values to pass to authenticate with the Azure API - type: cloudify.datatypes.azure.Config - required: false interfaces: cloudify.interfaces.lifecycle: create: azure.cloudify_azure.resources.network.loadbalancer.create_backend_pool @@ -1688,16 +1376,13 @@ node_types: cloudify.azure.nodes.network.LoadBalancer.Probe: derived_from: cloudify.nodes.Root properties: + <<: *common_properties + <<: *existing_resources api_version: type: string description: > Network API Version default: "2016-09-01" - name: - type: string - description: > - Name for the resource. - required: false resource_group_name: type: string description: > @@ -1722,12 +1407,6 @@ node_types: A dictionary of values to pass as properties when creating the resource type: cloudify.datatypes.azure.network.LoadBalancerProbeConfig required: false - use_external_resource: - description: > - Indicate whether the resource exists or if Cloudify should create the resource - type: boolean - default: false - required: true retry_after: description: > Overrides the Azure-specified "retry_after" response. This property @@ -1735,16 +1414,6 @@ node_types: case of iteratively checking the status of an asynchronous operation) type: integer required: false - azure_config: - description: > - A dictionary of values to pass to authenticate with the Azure API - type: cloudify.datatypes.azure.Config - required: false - client_config: - description: > - A dictionary of values to pass to authenticate with the Azure API - type: cloudify.datatypes.azure.Config - required: false interfaces: cloudify.interfaces.lifecycle: create: azure.cloudify_azure.resources.network.loadbalancer.create_probe @@ -1753,16 +1422,13 @@ node_types: cloudify.azure.nodes.network.LoadBalancer.IncomingNATRule: derived_from: cloudify.nodes.Root properties: + <<: *common_properties + <<: *existing_resources api_version: type: string description: > Network API Version default: "2016-09-01" - name: - type: string - description: > - Name for the resource. - required: false resource_group_name: type: string description: > @@ -1787,12 +1453,6 @@ node_types: A dictionary of values to pass as properties when creating the resource type: cloudify.datatypes.azure.network.LoadBalancerIncomingNATRuleConfig required: false - use_external_resource: - description: > - Indicate whether the resource exists or if Cloudify should create the resource - type: boolean - default: false - required: true retry_after: description: > Overrides the Azure-specified "retry_after" response. This property @@ -1800,16 +1460,6 @@ node_types: case of iteratively checking the status of an asynchronous operation) type: integer required: false - azure_config: - description: > - A dictionary of values to pass to authenticate with the Azure API - type: cloudify.datatypes.azure.Config - required: false - client_config: - description: > - A dictionary of values to pass to authenticate with the Azure API - type: cloudify.datatypes.azure.Config - required: false interfaces: cloudify.interfaces.lifecycle: create: azure.cloudify_azure.resources.network.loadbalancer.create_incoming_nat_rule @@ -1818,15 +1468,13 @@ node_types: cloudify.azure.nodes.network.LoadBalancer.Rule: derived_from: cloudify.nodes.Root properties: + <<: *common_properties + <<: *existing_resources api_version: type: string description: > Network API Version default: "2016-09-01" - name: - type: string - description: > - Name for the resource. required: false resource_group_name: type: string @@ -1852,12 +1500,6 @@ node_types: A dictionary of values to pass as properties when creating the resource type: cloudify.datatypes.azure.network.LoadBalancerRuleConfig required: false - use_external_resource: - description: > - Indicate whether the resource exists or if Cloudify should create the resource - type: boolean - default: false - required: true retry_after: description: > Overrides the Azure-specified "retry_after" response. This property @@ -1865,16 +1507,6 @@ node_types: case of iteratively checking the status of an asynchronous operation) type: integer required: false - azure_config: - description: > - A dictionary of values to pass to authenticate with the Azure API - type: cloudify.datatypes.azure.Config - required: false - client_config: - description: > - A dictionary of values to pass to authenticate with the Azure API - type: cloudify.datatypes.azure.Config - required: false interfaces: cloudify.interfaces.lifecycle: create: azure.cloudify_azure.resources.network.loadbalancer.create_rule @@ -1883,9 +1515,8 @@ node_types: cloudify.azure.Deployment: derived_from: cloudify.nodes.Root properties: - name: - required: true - type: string + <<: *common_properties + <<: *existing_resources resource_group_name: type: string description: > @@ -1912,22 +1543,6 @@ node_types: Deployment params required: false default: {} - azure_config: - description: > - A dictionary of values to pass to authenticate with the Azure API - type: cloudify.datatypes.azure.Config - required: false - client_config: - description: > - A dictionary of values to pass to authenticate with the Azure API - type: cloudify.datatypes.azure.Config - required: false - use_external_resource: - description: > - Indicate whether the resource exists or if Cloudify should create the resource - type: boolean - default: false - required: true interfaces: cloudify.interfaces.lifecycle: create: azure.cloudify_azure.resources.deployment.create @@ -1936,9 +1551,7 @@ node_types: cloudify.azure.nodes.compute.ContainerService: derived_from: cloudify.nodes.Root properties: - name: - required: true - type: string + <<: *common_properties resource_group: required: true type: string @@ -1947,16 +1560,6 @@ node_types: required: false description: > Container service config details - azure_config: - description: > - A dictionary of values to pass to authenticate with the Azure API - type: cloudify.datatypes.azure.Config - required: false - client_config: - description: > - A dictionary of values to pass to authenticate with the Azure API - type: cloudify.datatypes.azure.Config - required: false interfaces: cloudify.interfaces.lifecycle: create: @@ -1978,9 +1581,8 @@ node_types: cloudify.azure.nodes.Plan: derived_from: cloudify.nodes.Root properties: - name: - required: true - type: string + <<: *common_properties + <<: *existing_resources resource_group: required: true type: string @@ -1989,22 +1591,6 @@ node_types: required: false description: > SKU details, including location, name, capacity and tier - azure_config: - description: > - A dictionary of values to pass to authenticate with the Azure API - type: cloudify.datatypes.azure.Config - required: false - client_config: - description: > - A dictionary of values to pass to authenticate with the Azure API - type: cloudify.datatypes.azure.Config - required: false - use_external_resource: - description: > - Indicate whether the resource exists or if Cloudify should create the resource - type: boolean - default: false - required: true interfaces: cloudify.interfaces.lifecycle: create: @@ -2026,9 +1612,7 @@ node_types: cloudify.azure.nodes.WebApp: derived_from: cloudify.nodes.Root properties: - name: - required: true - type: string + <<: *common_properties resource_group: required: true type: string @@ -2037,16 +1621,6 @@ node_types: required: false description: > App config details, including location and plan - azure_config: - description: > - A dictionary of values to pass to authenticate with the Azure API - type: cloudify.datatypes.azure.Config - required: false - client_config: - description: > - A dictionary of values to pass to authenticate with the Azure API - type: cloudify.datatypes.azure.Config - required: false interfaces: cloudify.interfaces.lifecycle: create: