def create_probe(ctx, **_):
    """Uses an existing, or creates a new, Load Balancer Probe"""
    # Check if invalid external resource
    if ctx.node.properties.get('use_external_resource', False) and \
       not ctx.node.properties.get('name'):
        raise cfy_exc.NonRecoverableError(
            '"use_external_resource" specified without a resource "name"')
    # Generate a name if it doesn't exist
    azure_config = ctx.node.properties.get('azure_config')
    if not azure_config.get("subscription_id"):
        azure_config = ctx.node.properties.get('client_config')
    else:
        ctx.logger.warn("azure_config is deprecated please use client_config, "
                        "in later version it will be removed")
    resource_group_name = utils.get_resource_group(ctx)
    load_balancer_name = ctx.node.properties.get('load_balancer_name') or \
        utils.get_resource_name_ref(constants.REL_CONTAINED_IN_LB,
                                    'load_balancer_name',
                                    _ctx=ctx)
    load_balancer = LoadBalancer(azure_config, ctx.logger)
    probe_name = ctx.node.properties.get('name')
    probe_name = \
        get_unique_lb_prop_name(load_balancer, resource_group_name,
                                load_balancer_name, "probes", probe_name)
    ctx.instance.runtime_properties['name'] = probe_name
    # Get an interface to the Load Balancer
    lb_rel = utils.get_relationship_by_type(
        ctx.instance.relationships,
        constants.REL_CONTAINED_IN_LB)
    lb_name = utils.get_resource_name(lb_rel.target)
    # Get the existing probes
    lb_data = load_balancer.get(resource_group_name, lb_name)
    lb_probes = lb_data.get('probes', list())
    lb_probes.append({
        'name': probe_name,
    })
    lb_probes = \
        utils.handle_resource_config_params(lb_probes,
                                            ctx.node.properties.get(
                                                'resource_config', {}))
    # Update the Load Balancer with the new probe
    lb_params = {
        'probes': lb_probes
    }
    # clean empty values from params
    lb_params = \
        utils.cleanup_empty_params(lb_params)
    try:
        result = load_balancer.create_or_update(resource_group_name, lb_name,
                                                lb_params)
        for item in result.get("probes"):
            if item.get("name") == probe_name:
                ctx.instance.runtime_properties['resource_id'] = item.get("id")
                ctx.instance.runtime_properties['resource'] = item
    except CloudError as cr:
        raise cfy_exc.NonRecoverableError(
            "create probe '{0}' "
            "failed with this error : {1}".format(probe_name,
                                                  cr.message)
            )
def create(ctx, resource_group, cluster_name, resource_config, **kwargs):
    azure_config = ctx.node.properties.get('azure_config')
    if not azure_config.get("subscription_id"):
        azure_config = ctx.node.properties.get('client_config')
    else:
        ctx.logger.warn("azure_config is deprecated please use client_config, "
                        "in later version it will be removed")
    store_kube_config_in_runtime = \
        ctx.node.properties.get('store_kube_config_in_runtime')
    api_version = \
        ctx.node.properties.get('api_version',
                                constants.API_VER_MANAGED_CLUSTER)
    managed_cluster = ManagedCluster(azure_config, ctx.logger, api_version)
    resource_config_payload = {}
    resource_config_payload = \
        utils.handle_resource_config_params(resource_config_payload,
                                            resource_config)
    try:
        result = managed_cluster.get(resource_group, cluster_name)
        if ctx.node.properties.get('use_external_resource', False):
            ctx.logger.info("Using external resource")
        else:
            ctx.logger.info("Resource with name {0} exists".format(
                cluster_name))
            return
    except CloudError:
        if ctx.node.properties.get('use_external_resource', False):
            raise cfy_exc.NonRecoverableError(
                "Can't use non-existing managed_cluster '{0}'.".format(
                    cluster_name))
        else:
            try:
                result = \
                    managed_cluster.create_or_update(resource_group,
                                                     cluster_name,
                                                     resource_config_payload)
            except CloudError as cr:
                raise cfy_exc.NonRecoverableError(
                    "create managed_cluster '{0}' "
                    "failed with this error : {1}".format(cluster_name,
                                                          cr.message)
                    )

    ctx.instance.runtime_properties['resource_group'] = resource_group
    ctx.instance.runtime_properties['resource'] = result
    ctx.instance.runtime_properties['resource_id'] = result.get("id", "")
    ctx.instance.runtime_properties['name'] = cluster_name

    if store_kube_config_in_runtime:
        ctx.instance.runtime_properties['kubeconf'] = \
            yaml.load(base64.b64decode(managed_cluster.get_admin_kubeconf(
                resource_group, cluster_name)))
def build_ip_configuration(ipc):
    """
        Attempts to construct a proper IP Configuration from
        a context object

    :params `cloudify.context.RelationshipSubjectContext` ipc:
        IP Configuration context object
    :returns: IP Configuration dict
    :rtype: dict or None
    """
    if not ipc or not ipc.instance.relationships:
        return None
    # Find a referenced Subnet/PublicIPAddress
    rel_sub_type = constants.REL_IPC_CONNECTED_TO_SUBNET
    rel_pip_type = constants.REL_IPC_CONNECTED_TO_PUBIP
    subnet = None
    pubip = None
    for rel in ipc.instance.relationships:
        if isinstance(rel_sub_type, tuple):
            if any(x in rel.type_hierarchy for x in rel_sub_type):
                subnet = {
                    'id': rel.target.instance.runtime_properties['resource_id']
                }
        else:
            if rel_sub_type in rel.type_hierarchy:
                subnet = {
                    'id': rel.target.instance.runtime_properties['resource_id']
                }
        if isinstance(rel_pip_type, tuple):
            if any(x in rel.type_hierarchy for x in rel_pip_type):
                pubip = {
                    'id': rel.target.instance.runtime_properties['resource_id']
                }
        else:
            if rel_pip_type in rel.type_hierarchy:
                pubip = {
                    'id': rel.target.instance.runtime_properties['resource_id']
                }

    ip_configuration = {
        'name': utils.get_resource_name(ipc),
        'subnet': subnet,
        'public_ip_address': pubip
    }
    ip_configuration = \
        utils.handle_resource_config_params(ip_configuration,
                                            ipc.node.properties.get(
                                                "resource_config", {}))
    return ip_configuration
def create(ctx, **_):
    """Uses an existing, or creates a new, Public IP Address"""
    # Create a resource (if necessary)
    azure_config = ctx.node.properties.get('azure_config')
    if not azure_config.get("subscription_id"):
        azure_config = ctx.node.properties.get('client_config')
    else:
        ctx.logger.warn("azure_config is deprecated please use client_config, "
                        "in later version it will be removed")
    name = utils.get_resource_name(ctx)
    resource_group_name = utils.get_resource_group(ctx)
    public_ip_address_params = {
        'location': ctx.node.properties.get('location'),
        'tags': ctx.node.properties.get('tags'),
    }
    public_ip_address_params = \
        utils.handle_resource_config_params(public_ip_address_params,
                                            ctx.node.properties.get(
                                                'resource_config', {}))
    # Special Case dnsSettings
    public_ip_address_params['dns_settings'] = {
        'domain_name_label':
        public_ip_address_params.pop('domain_name_label', None),
        'reverse_fqdn':
        public_ip_address_params.pop('reverse_fqdn', None)
    }
    api_version = \
        ctx.node.properties.get('api_version', constants.API_VER_NETWORK)
    public_ip_address = PublicIPAddress(azure_config, ctx.logger, api_version)
    # clean empty values from params
    public_ip_address_params = \
        utils.cleanup_empty_params(public_ip_address_params)

    try:
        result = \
            public_ip_address.create_or_update(
                resource_group_name,
                name,
                public_ip_address_params)
    except CloudError as cr:
        raise cfy_exc.NonRecoverableError(
            "create public_ip_address '{0}' "
            "failed with this error : {1}".format(name, cr.message))

    ctx.instance.runtime_properties['resource_group'] = resource_group_name
    ctx.instance.runtime_properties['resource'] = result
    ctx.instance.runtime_properties['resource_id'] = result.get("id", "")
 def test_create(self, client, credentials):
     self.node.properties['azure_config'] = self.dummy_azure_credentials
     resource_group = 'sample_resource_group'
     cluster_name = 'mc_name'
     self.node.properties['store_kube_config_in_runtime'] = False
     managed_cluster_config = {
         'network_profile': None,
         'addon_profiles': None,
         'windows_profile': None,
         'dns_prefix': 'dummy-dns',
         'linux_profile': None,
         'agent_pool_profiles': None,
         'service_principal_profile': None,
         'location': 'westus',
         'enable_rbac': True,
         'kubernetes_version': None,
         'tags': None
     }
     cluster_payload = {}
     cluster_payload = \
         handle_resource_config_params(cluster_payload,
                                       managed_cluster_config)
     response = requests.Response()
     response.status_code = 404
     message = 'resource not found'
     client().managed_clusters.get.side_effect = \
         CloudError(response, message)
     with mock.patch('cloudify_azure.utils.secure_logging_content',
                     mock.Mock()):
         managed_cluster.create(self.fake_ctx, resource_group, cluster_name,
                                managed_cluster_config)
         client().managed_clusters.get.assert_called_with(
             resource_group_name=resource_group,
             resource_name=cluster_name,
         )
         client().managed_clusters.create_or_update.assert_called_with(
             resource_group_name=resource_group,
             resource_name=cluster_name,
             parameters=cluster_payload)
         self.assertEquals(
             self.fake_ctx.instance.runtime_properties.get("name"),
             cluster_name)
         self.assertEquals(
             self.fake_ctx.instance.runtime_properties.get(
                 "resource_group"), resource_group)
def create(ctx, resource_group, name, container_service_config, **kwargs):
    azure_config = ctx.node.properties.get('azure_config')
    if not azure_config.get("subscription_id"):
        azure_config = ctx.node.properties.get('client_config')
    else:
        ctx.logger.warn("azure_config is deprecated please use client_config, "
                        "in later version it will be removed")
    api_version = \
        ctx.node.properties.get('api_version', constants.API_VER_CONTAINER)
    container_service = ContainerService(azure_config, ctx.logger, api_version)
    container_service_payload = {}
    container_service_payload = \
        utils.handle_resource_config_params(container_service_payload,
                                            container_service_config)

    try:
        result = container_service.get(resource_group, name)
        if ctx.node.properties.get('use_external_resource', False):
            ctx.logger.info("Using external resource")
        else:
            ctx.logger.info("Resource with name {0} exists".format(name))
            return
    except CloudError:
        if ctx.node.properties.get('use_external_resource', False):
            raise cfy_exc.NonRecoverableError(
                "Can't use non-existing container_service '{0}'.".format(name))
        else:
            try:
                result = \
                    container_service.create_or_update(
                        resource_group,
                        name,
                        container_service_payload
                    )
            except CloudError as cr:
                raise cfy_exc.NonRecoverableError(
                    "create container_service '{0}' "
                    "failed with this error : {1}".format(name,
                                                          cr.message)
                    )

    ctx.instance.runtime_properties['resource_group'] = resource_group
    ctx.instance.runtime_properties['resource'] = result
    ctx.instance.runtime_properties['resource_id'] = result.get("id", "")
    ctx.instance.runtime_properties['name'] = name
def create(ctx, **_):
    """Uses an existing, or creates a new, Network Security Group"""
    # Create a resource (if necessary)
    azure_config = ctx.node.properties.get('azure_config')
    if not azure_config.get("subscription_id"):
        azure_config = ctx.node.properties.get('client_config')
    else:
        ctx.logger.warn("azure_config is deprecated please use client_config, "
                        "in later version it will be removed")
    name = utils.get_resource_name(ctx)
    resource_group_name = utils.get_resource_group(ctx)
    nsg_params = {
        'location': ctx.node.properties.get('location'),
        'tags': ctx.node.properties.get('tags'),
    }
    nsg_params = \
        utils.handle_resource_config_params(nsg_params,
                                            ctx.node.properties.get(
                                                'resource_config', {}))
    api_version = \
        ctx.node.properties.get('api_version', constants.API_VER_NETWORK)
    network_security_group = NetworkSecurityGroup(azure_config, ctx.logger,
                                                  api_version)
    # clean empty values from params
    nsg_params = \
        utils.cleanup_empty_params(nsg_params)

    try:
        result = \
            network_security_group.create_or_update(
                resource_group_name,
                name,
                nsg_params)
    except CloudError as cr:
        raise cfy_exc.NonRecoverableError(
            "create network_security_group '{0}' "
            "failed with this error : {1}".format(name, cr.message))

    ctx.instance.runtime_properties['resource_group'] = resource_group_name
    ctx.instance.runtime_properties['resource'] = result
    ctx.instance.runtime_properties['resource_id'] = result.get("id", "")
def create(ctx, **_):
    """Uses an existing, or creates a new, Availability Set"""
    azure_config = ctx.node.properties.get('azure_config')
    if not azure_config.get("subscription_id"):
        azure_config = ctx.node.properties.get('client_config')
    else:
        ctx.logger.warn("azure_config is deprecated please use client_config, "
                        "in later version it will be removed")
    name = utils.get_resource_name(ctx)
    resource_group_name = utils.get_resource_group(ctx)
    resource_config = ctx.node.properties.get('resource_config')
    availability_set_conf = {
        'location': ctx.node.properties.get('location'),
        'tags': ctx.node.properties.get('tags'),
    }
    availability_set_conf = \
        utils.handle_resource_config_params(availability_set_conf,
                                            resource_config)
    api_version = \
        ctx.node.properties.get('api_version', constants.API_VER_COMPUTE)
    availability_set = AvailabilitySet(azure_config, ctx.logger, api_version)
    # clean empty values from params
    availability_set_conf = utils.cleanup_empty_params(availability_set_conf)

    try:
        result = \
            availability_set.create_or_update(resource_group_name,
                                              name,
                                              availability_set_conf)
    except CloudError as cr:
        raise cfy_exc.NonRecoverableError(
            "create availability_set '{0}' "
            "failed with this error : {1}".format(name,
                                                  cr.message)
            )

    ctx.instance.runtime_properties['resource_group'] = resource_group_name
    ctx.instance.runtime_properties['resource'] = result
    ctx.instance.runtime_properties['resource_id'] = result.get("id", "")
Esempio n. 9
0
def create(ctx, args=None, **_):
    """Uses an existing, or creates a new, Virtual Machine"""
    azure_config = utils.get_client_config(ctx.node.properties)
    name = utils.get_resource_name(ctx)
    resource_group_name = utils.get_resource_group(ctx)
    api_version = \
        ctx.node.properties.get('api_version', constants.API_VER_COMPUTE)
    virtual_machine = VirtualMachine(azure_config, ctx.logger, api_version)
    res_cfg = ctx.node.properties.get("resource_config", {})
    spot_instance = res_cfg.pop("spot_instance", None)
    # Build storage profile
    osdisk = build_osdisk_profile(ctx, res_cfg.get(
        'storageProfile', dict()).get('osDisk', dict()))
    datadisks = build_datadisks_profile(ctx, res_cfg.get(
        'storageProfile', dict()).get('dataDisks', list()))
    storage_profile = {
        'os_disk': osdisk,
        'data_disks': datadisks
    }
    # Build the network profile
    network_profile = build_network_profile(ctx)
    # Build the OS profile
    os_family = ctx.node.properties.get('os_family', '').lower()
    os_profile = dict()
    # Set defaults for Windows installs to enable WinRM listener
    if os_family == 'windows' and \
            not res_cfg.get('osProfile', dict()).get('windowsConfiguration'):
        os_profile = {
            'windows_configuration': {
                # This is required for extension scripts to work
                'provision_vm_agent': True,
                'win_rm': {
                    'listeners': [{
                        'protocol': 'Http',
                        'certificate_url': None
                    }]
                }
            },
            'linux_configuration': None
        }
    elif not res_cfg.get('osProfile', dict()).get('linuxConfiguration'):
        os_profile = {
            'linux_configuration': {
                'disable_password_authentication': False
            },
            'windows_configuration': None
        }
    # Set the computerName if it's not set already
    os_profile['computer_name'] = \
        res_cfg.get(
            'osProfile', dict()
        ).get('computerName', name)

    availability_set = None
    rel_type = constants.REL_CONNECTED_TO_AS
    for rel in ctx.instance.relationships:
        if isinstance(rel_type, tuple):
            if any(x in rel.type_hierarchy for x in rel_type):
                availability_set = {
                    'id': rel.target.instance.runtime_properties.get(
                        "resource_id")
                }
        else:
            if rel_type in rel.type_hierarchy:
                availability_set = {
                    'id': rel.target.instance.runtime_properties.get(
                        "resource_id")
                }
    resource_create_payload = {
        'location': ctx.node.properties.get('location'),
        'tags': ctx.node.properties.get('tags'),
        'plan': ctx.node.properties.get('plan'),
        'availabilitySet': availability_set,
        'networkProfile': network_profile,
        'storageProfile': storage_profile,
        'osProfile': os_profile
    }
    # check if spot_instance
    if spot_instance and spot_instance.get("is_spot_instance"):
        # this is just an indacator not part of the api
        spot_instance.pop("is_spot_instance")
        #  handle the params
        resource_create_payload = \
            utils.dict_update(resource_create_payload, spot_instance)
    resource_create_payload = \
        utils.handle_resource_config_params(resource_create_payload,
                                            utils.get_resource_config(
                                                _ctx=ctx,
                                                args=args))
    # support userdata from args.
    os_profile = resource_create_payload['os_profile']
    userdata = _handle_userdata(ctx, os_profile.get('custom_data'))
    if userdata:
        ctx.logger.warn(
            'Azure customData implementation is dependent on '
            'Virtual Machine image support.')
        resource_create_payload['os_profile']['custom_data'] = \
            base64.b64encode(userdata.encode('utf-8')).decode('utf-8')
    # Remove custom_data from os_profile if empty to avoid Errors.
    elif 'custom_data' in resource_create_payload['os_profile']:
        del resource_create_payload['os_profile']['custom_data']
    # Create a resource (if necessary)
    try:
        result = \
            virtual_machine.create_or_update(resource_group_name, name,
                                             resource_create_payload)
    except CloudError as cr:
        raise cfy_exc.NonRecoverableError(
            "create virtual_machine '{0}' "
            "failed with this error : {1}".format(name,
                                                  cr.message)
            )

    ctx.instance.runtime_properties['resource_group'] = resource_group_name
    ctx.instance.runtime_properties['resource'] = result
    ctx.instance.runtime_properties['resource_id'] = result.get("id", "")
Esempio n. 10
0
 def test_create(self, _, client, credentials):
     self.node.properties['azure_config'] = self.dummy_azure_credentials
     resource_group = 'sample_resource_group'
     name = 'mockvm'
     self.node.properties['resource_group_name'] = resource_group
     self.node.properties['name'] = name
     self.node.properties['location'] = 'eastus'
     self.node.properties['os_family'] = 'linux'
     self.node.properties['resource_config'] = {
         'hardwareProfile': {
             'vmSize': 'Standard_A2',
         },
         'storageProfile': {
             'imageReference': {
                 'publisher': 'Canonical',
                 'offer': 'UbuntuServer',
                 'sku': '14.04.4-LTS',
                 'version': '14.04.201604060'
             }
         },
         'osProfile': {
             'computerName': name,
             'adminUsername': '******',
             'adminPassword': '******',
             'linuxConfiguration': {
                 'ssh': {
                     'publicKeys': {
                         'path': '/home/cloudify/.ssh/authorized_keys',
                         'keyData': 'ssh-rsa AAAAA3----MOCK----aabbzz'
                     }
                 },
                 'disablePasswordAuthentication': True
             }
         }
     }
     storage_profile = {
         'os_disk': {
             'caching': 'ReadWrite',
             'vhd': {
                 'uri': 'http://None.blob./vhds/mockvm.vhd'
             },
             'name': 'mockvm',
             'create_option': 'FromImage'
         }
     }
     vm_params = {
         'location': self.node.properties.get('location'),
         'storageProfile': storage_profile,
     }
     vm_params = utils.handle_resource_config_params(
         vm_params, self.node.properties.get("resource_config"))
     response = requests.Response()
     response.status_code = 404
     message = 'resource not found'
     client().virtual_machines.get.side_effect = \
         CloudError(response, message)
     with mock.patch('cloudify_azure.utils.secure_logging_content',
                     mock.Mock()):
         virtualmachine.create(ctx=self.fake_ctx)
         client().virtual_machines.get.assert_called_with(
             resource_group_name=resource_group, vm_name=name)
         client().virtual_machines.create_or_update.assert_called_with(
             resource_group_name=resource_group,
             vm_name=name,
             parameters=vm_params)
         self.assertEquals(
             self.fake_ctx.instance.runtime_properties.get("name"), name)
         self.assertEquals(
             self.fake_ctx.instance.runtime_properties.get(
                 "resource_group"), resource_group)
def configure(ctx, **_):
    """Uses an existing, or creates a new, Load Balancer"""
    # Get the Frontend IP Configuration
    fe_ip_cfg = get_ip_configurations(rel=constants.REL_LB_CONNECTED_TO_IPC)
    ctx.logger.debug('fe_ip_cfg: {0}'.format(fe_ip_cfg))
    if not len(fe_ip_cfg):
        raise cfy_exc.NonRecoverableError(
            'At least 1 Frontend IP Configuration must be '
            'associated with the Load Balancer')
    # Remove the subnet if there's a public IP present
    for ip_cfg in fe_ip_cfg:
        if ip_cfg.get('public_ip_address'):
            if ip_cfg.get('subnet'):
                del ip_cfg['subnet']
    # Create a resource (if necessary)
    azure_config = ctx.node.properties.get('azure_config')
    if not azure_config.get("subscription_id"):
        azure_config = ctx.node.properties.get('client_config')
    else:
        ctx.logger.warn("azure_config is deprecated please use client_config, "
                        "in later version it will be removed")
    name = ctx.instance.runtime_properties.get('name')
    resource_group_name = utils.get_resource_group(ctx)
    api_version = \
        ctx.node.properties.get('api_version', constants.API_VER_NETWORK)
    load_balancer = LoadBalancer(azure_config, ctx.logger, api_version)
    lb_params = {
        'location': ctx.node.properties.get('location'),
        'tags': ctx.node.properties.get('tags'),
    }
    lb_params = \
        utils.handle_resource_config_params(lb_params,
                                            ctx.node.properties.get(
                                                'resource_config', {}))
    lb_params = utils.dict_update(
        lb_params, {
            'frontend_ip_configurations': fe_ip_cfg
        }
    )
    # clean empty values from params
    lb_params = \
        utils.cleanup_empty_params(lb_params)
    try:
        result = \
            load_balancer.create_or_update(resource_group_name,
                                           name,
                                           lb_params)
    except CloudError as cr:
        raise cfy_exc.NonRecoverableError(
            "create load_balancer '{0}' "
            "failed with this error : {1}".format(name,
                                                  cr.message)
            )

    ctx.instance.runtime_properties['resource_group'] = resource_group_name
    ctx.instance.runtime_properties['resource'] = result
    ctx.instance.runtime_properties['resource_id'] = result.get("id", "")
    ctx.instance.runtime_properties['name'] = name

    for fe_ipc_data in result.get('frontend_ip_configurations', list()):
        ctx.instance.runtime_properties['ip'] = \
            fe_ipc_data.get('private_ip_address')
        public_ip = \
            fe_ipc_data.get('public_ip_address', {}).get('ip_address', None)
        if not public_ip:
            pip = PublicIPAddress(azure_config, ctx.logger)
            pip_name = \
                ip_cfg.get('public_ip_address').get('id').rsplit('/', 1)[1]
            public_ip_data = pip.get(resource_group_name, pip_name)
            public_ip = public_ip_data.get("ip_address")
        ctx.instance.runtime_properties['public_ip'] = public_ip
def create_incoming_nat_rule(ctx, **_):
    """Uses an existing, or creates a new, Load Balancer Incoming NAT Rule"""
    # Check if invalid external resource
    if ctx.node.properties.get('use_external_resource', False) and \
       not ctx.node.properties.get('name'):
        raise cfy_exc.NonRecoverableError(
            '"use_external_resource" specified without a resource "name"')
    # Generate a name if it doesn't exist
    azure_config = ctx.node.properties.get('azure_config')
    if not azure_config.get("subscription_id"):
        azure_config = ctx.node.properties.get('client_config')
    else:
        ctx.logger.warn("azure_config is deprecated please use client_config, "
                        "in later version it will be removed")
    resource_group_name = utils.get_resource_group(ctx)
    load_balancer_name = ctx.node.properties.get('load_balancer_name') or \
        utils.get_resource_name_ref(constants.REL_CONTAINED_IN_LB,
                                    'load_balancer_name',
                                    _ctx=ctx)
    load_balancer = LoadBalancer(azure_config, ctx.logger)
    incoming_nat_rule_name = ctx.node.properties.get('name')
    incoming_nat_rule_name = \
        get_unique_lb_prop_name(load_balancer, resource_group_name,
                                load_balancer_name, "inbound_nat_rules",
                                incoming_nat_rule_name)
    ctx.instance.runtime_properties['name'] = incoming_nat_rule_name
    # Get an interface to the Load Balancer
    lb_rel = utils.get_relationship_by_type(
        ctx.instance.relationships,
        constants.REL_CONTAINED_IN_LB)
    lb_name = utils.get_resource_name(lb_rel.target)
    # Get the existing rules
    lb_data = load_balancer.get(resource_group_name, lb_name)
    lb_rules = lb_data.get('inbound_nat_rules', list())
    # Get the Load Balancer Frontend IP Configuration
    lb_fe_ipc_id = ""
    rel_type = constants.REL_CONNECTED_TO_IPC
    for rel in ctx.instance.relationships:
        if isinstance(rel_type, tuple):
            if any(x in rel.type_hierarchy for x in rel_type):
                lb_fe_ipc_id = \
                    rel.target.instance.runtime_properties.get('resource_id')
        else:
            if constants.REL_CONNECTED_TO_IPC in rel.type_hierarchy:
                lb_fe_ipc_id = \
                    rel.target.instance.runtime_properties.get('resource_id')
    lb_rules.append({
        'name': incoming_nat_rule_name,
        'frontend_ip_configuration': {
            'id': lb_fe_ipc_id
        }
    })
    lb_rules = \
        utils.handle_resource_config_params(lb_rules,
                                            ctx.node.properties.get(
                                                'resource_config', {}))
    # Update the Load Balancer with the new NAT rule
    lb_params = {
        'inbound_nat_rules': lb_rules
    }
    # clean empty values from params
    lb_params = \
        utils.cleanup_empty_params(lb_params)
    try:
        result = load_balancer.create_or_update(resource_group_name, lb_name,
                                                lb_params)
        for item in result.get("inbound_nat_rules"):
            if item.get("name") == incoming_nat_rule_name:
                ctx.instance.runtime_properties['resource_id'] = item.get("id")
                ctx.instance.runtime_properties['resource'] = item
    except CloudError as cr:
        raise cfy_exc.NonRecoverableError(
            "create incoming_nat_rule '{0}' "
            "failed with this error : {1}".format(incoming_nat_rule_name,
                                                  cr.message)
            )
def configure(ctx, **_):
    """
        Uses an existing, or creates a new, Network Interface Card

    .. warning::
        The "configure" operation is actually the second half of
        the "create" operation. This is necessary since IP
        Configuration nodes are treated as separate, stand-alone
        types and must be "connected" to the NIC before
        it's actually created.  The actual "create" operation
        simply assigns a UUID for the node and the "configure"
        operation creates the object
    """
    # Create a resource (if necessary)
    azure_config = ctx.node.properties.get('azure_config')
    if not azure_config.get("subscription_id"):
        azure_config = ctx.node.properties.get('client_config')
    else:
        ctx.logger.warn("azure_config is deprecated please use client_config, "
                        "in later version it will be removed")
    name = ctx.instance.runtime_properties.get('name')
    resource_group_name = utils.get_resource_group(ctx)
    api_version = \
        ctx.node.properties.get('api_version', constants.API_VER_NETWORK)
    network_interface_card = NetworkInterfaceCard(azure_config, ctx.logger,
                                                  api_version)
    nic_params = {
        'location': ctx.node.properties.get('location'),
        'tags': ctx.node.properties.get('tags'),
        'primary': ctx.node.properties.get('primary'),
    }
    nic_params = \
        utils.handle_resource_config_params(nic_params,
                                            ctx.node.properties.get(
                                                'resource_config', {}))
    # Special Case network_security_group instead of networkSecurityGroups
    nic_params['network_security_group'] = \
        nic_params.pop('network_security_groups', None)
    # clean empty values from params
    nic_params = \
        utils.cleanup_empty_params(nic_params)
    nic_params = utils.dict_update(
        nic_params, {
            'network_security_group': get_connected_nsg(ctx),
            'ip_configurations': get_ip_configurations(ctx)
        })
    # clean empty values from params
    nic_params = \
        utils.cleanup_empty_params(nic_params)

    try:
        result = \
            network_interface_card.create_or_update(
                resource_group_name,
                name,
                nic_params)
    except CloudError as cr:
        raise cfy_exc.NonRecoverableError(
            "configure nic '{0}' "
            "failed with this error : {1}".format(name, cr.message))

    ctx.instance.runtime_properties['resource_group'] = resource_group_name
    ctx.instance.runtime_properties['resource'] = result
    ctx.instance.runtime_properties['resource_id'] = result.get("id", "")
    ctx.instance.runtime_properties['name'] = name