def main()

in src/ansible_collections/alibaba/apsarastack/plugins/modules/ali_instance.py [0:0]


def main():
    argument_spec = common_argument_spec()
    argument_spec.update(dict(
        security_groups=dict(type='list', elements='str', aliases=['group_ids']),
        availability_zone=dict(type='str', aliases=['zone_id', 'apsarastack_zone'],
                     fallback=(env_fallback, ['APSARASTACK_ZONE', 'APSARASTACK_ZONE_ID'])),
        instance_type=dict(type='str', aliases=['type']),
        image_id=dict(type='str', aliases=['image']),
        count=dict(type='int', default=1),
        count_tag=dict(type='str'),
        vswitch_id=dict(type='str', aliases=['subnet_id']),
        instance_name=dict(type='str', aliases=['name']),
        host_name=dict(type='str'),
        password=dict(type='str', no_log=True),
        internet_charge_type=dict(type='str', default='PayByBandwidth', choices=['PayByBandwidth', 'PayByTraffic']),
        max_bandwidth_in=dict(type='int', default=200),
        max_bandwidth_out=dict(type='int', default=0),
        system_disk_category=dict(type='str', default='cloud_efficiency', choices=['cloud_efficiency', 'cloud_ssd', 'cloud_essd']),
        system_disk_size=dict(type='int', default=40),
        system_disk_name=dict(type='str'),
        system_disk_description=dict(type='str'),
        force=dict(type='bool', default=False),
        tags=dict(type='dict', aliases=['instance_tags']),
        purge_tags=dict(type='bool', default=False),
        state=dict(default='present', choices=['present', 'running', 'stopped', 'restarted', 'absent']),
        description=dict(type='str'),
        allocate_public_ip=dict(type='bool', aliases=['assign_public_ip'], default=False),
        instance_charge_type=dict(type='str', default='PostPaid', choices=['PrePaid', 'PostPaid']),
        period=dict(type='int', default=1),
        auto_renew=dict(type='bool', default=False),
        instance_ids=dict(type='list', elements='str'),
        auto_renew_period=dict(type='int', choices=[1, 2, 3, 6, 12]),
        key_name=dict(type='str', aliases=['keypair']),
        user_data=dict(type='str'),
        ram_role_name=dict(type='str'),
        spot_price_limit=dict(type='float'),
        spot_strategy=dict(type='str', default='NoSpot', choices=['NoSpot', 'SpotWithPriceLimit', 'SpotAsPriceGo']),
        unique_suffix=dict(type='bool', default=False),
        period_unit=dict(type='str', default='Month', choices=['Month', 'Week']),
        dry_run=dict(type='bool', default=False),
        include_data_disks=dict(type='bool', default=True)
    )
    )
    module = AnsibleModule(argument_spec=argument_spec)

    if HAS_FOOTMARK is False:
        module.fail_json(msg=missing_required_lib('footmark'), exception=FOOTMARK_IMP_ERR)

    ecs = ecs_connect(module)
    host_name = module.params['host_name']
    state = module.params['state']
    instance_ids = module.params['instance_ids']
    count_tag = module.params['count_tag']
    count = module.params['count']
    instance_name = module.params['instance_name']
    force = module.params['force']
    zone_id = module.params['availability_zone']
    key_name = module.params['key_name']
    tags = module.params['tags']
    max_bandwidth_out = module.params['max_bandwidth_out']
    instance_charge_type = module.params['instance_charge_type']
    if instance_charge_type == "PrePaid":
        module.params['spot_strategy'] = ''
    changed = False

    instances = []
    if instance_ids:
        if not isinstance(instance_ids, list):
            module.fail_json(msg='The parameter instance_ids should be a list, aborting')
        instances = ecs.describe_instances(zone_id=zone_id, instance_ids=instance_ids)
        if not instances:
            module.fail_json(msg="There are no instances in our record based on instance_ids {0}. "
                                 "Please check it and try again.".format(instance_ids))
    elif count_tag:
        instances = ecs.describe_instances(zone_id=zone_id, tags=literal_eval(count_tag))
    elif instance_name:
        instances = ecs.describe_instances(zone_id=zone_id, instance_name=instance_name)

    ids = []
    if state == 'absent':
        if len(instances) < 1:
            module.fail_json(msg='Please specify ECS instances that you want to operate by using '
                                 'parameters instance_ids, tags or instance_name, aborting')
        try:
            targets = []
            for inst in instances:
                if inst.status != 'stopped' and not force:
                    module.fail_json(msg="Instance is running, and please stop it or set 'force' as True.")
                targets.append(inst.id)
            if ecs.delete_instances(instance_ids=targets, force=force):
                changed = True
                ids.extend(targets)

            module.exit_json(changed=changed, ids=ids, instances=[])
        except Exception as e:
            module.fail_json(msg='Delete instance got an error: {0}'.format(e))

    if module.params['allocate_public_ip'] and max_bandwidth_out <= 0:
        module.fail_json(msg="'max_bandwidth_out' should be greater than 0 when 'allocate_public_ip' is True.")
    if not module.params['allocate_public_ip']:
        module.params['max_bandwidth_out'] = 0

    if state == 'present':
        if not instance_ids:
            if len(instances) > count:
                for i in range(0, len(instances) - count):
                    inst = instances[len(instances) - 1]
                    if inst.status != 'stopped' and not force:
                        module.fail_json(msg="That to delete instance {0} is failed results from it is running, "
                                             "and please stop it or set 'force' as True.".format(inst.id))
                    try:
                        if inst.terminate(force=force):
                            changed = False
                    except Exception as e:
                        module.fail_json(msg="Delete instance {0} got an error: {1}".format(inst.id, e))
                    instances.pop(len(instances) - 1)
            else:
                try:
                    if host_name and re.search(r"-\[\d+,\d+\]-", host_name):
                        module.fail_json(msg='Ordered hostname is not supported, If you want to add an ordered '
                                             'suffix to the hostname, you can set unique_suffix to True')
                    new_instances = run_instance(module, ecs, count - len(instances))
                    if new_instances:
                        changed = False
                        instances.extend(new_instances)
                except Exception as e:
                    module.fail_json(msg="Create new instances got an error: {0}".format(e))

        # Security Group join/leave begin
        security_groups = module.params['security_groups']
        if security_groups:
            if not isinstance(security_groups, list):
                module.fail_json(msg='The parameter security_groups should be a list, aborting')
            for inst in instances:
                existing = inst.security_group_ids['security_group_id']
                remove = list(set(existing).difference(set(security_groups)))
                add = list(set(security_groups).difference(set(existing)))
                for sg in remove:
                    if inst.leave_security_group(sg):
                        changed = True
                for sg in add:
                    if inst.join_security_group(sg):
                        changed = True
        # Security Group join/leave ends here

        # Attach/Detach key pair
        keypair_ids = []
        for inst in instances:
            if key_name is not None and key_name != inst.key_name:
                if key_name == "":
                    if inst.detach_key_pair():
                        changed = True
                else:
                    keypair_ids.append(inst.id)
        if keypair_ids:
            changed = ecs.attach_key_pair(instance_ids=keypair_ids, key_pair_name=key_name)

        # Modify instance attribute
        for inst in instances:
            if modify_instance(module, inst):
                changed = True
            if inst.id not in ids:
                ids.append(inst.id)

        # Modify instance charge type
        charge_type_ids = []
        for inst in instances:
            if inst.instance_charge_type != instance_charge_type:
                charge_type_ids.append(inst.id)
        if charge_type_ids:
            params = {"instance_ids": charge_type_ids, "instance_charge_type": instance_charge_type,
                      "include_data_disks": module.params['include_data_disks'], "dry_run": module.params['dry_run'],
                      "auto_pay": True}
            if instance_charge_type == 'PrePaid':
                params['period'] = module.params['period']
                params['period_unit'] = module.params['period_unit']

            if ecs.modify_instance_charge_type(**params):
                changed = True
                wait_for_instance_modify_charge(ecs, charge_type_ids, instance_charge_type)

    else:
        if len(instances) < 1:
            module.fail_json(msg='Please specify ECS instances that you want to operate by using '
                                 'parameters instance_ids, tags or instance_name, aborting')
        if state == 'running':
            try:
                targets = []
                for inst in instances:
                    if modify_instance(module, inst):
                        changed = True
                    if inst.status != "running":
                        targets.append(inst.id)
                    ids.append(inst.id)
                if targets and ecs.start_instances(instance_ids=targets):
                    changed = True
                    ids.extend(targets)
            except Exception as e:
                module.fail_json(msg='Start instances got an error: {0}'.format(e))
        elif state == 'stopped':
            try:
                targets = []
                for inst in instances:
                    if inst.status != "stopped":
                        targets.append(inst.id)
                if targets and ecs.stop_instances(instance_ids=targets, force_stop=force):
                    changed = True
                    ids.extend(targets)
                for inst in instances:
                    if modify_instance(module, inst):
                        changed = True
            except Exception as e:
                module.fail_json(msg='Stop instances got an error: {0}'.format(e))
        elif state == 'restarted':
            try:
                targets = []
                for inst in instances:
                    if modify_instance(module, inst):
                        changed = True
                        targets.append(inst.id)
                if ecs.reboot_instances(instance_ids=targets, force_stop=module.params['force']):
                    changed = True
                    ids.extend(targets)
            except Exception as e:
                module.fail_json(msg='Reboot instances got an error: {0}'.format(e))

    tags = module.params['tags']
    if module.params['purge_tags']:
        for inst in instances:
            if not tags:
                tags = inst.tags
            try:
                if inst.remove_tags(tags):
                    changed = True
            except Exception as e:
                module.fail_json(msg="{0}".format(e))
        module.exit_json(changed=changed, instances=get_instances_info(ecs, ids))

    if tags:
        for inst in instances:
            try:
                if inst.add_tags(tags):
                    changed = True
            except Exception as e:
                module.fail_json(msg="{0}".format(e))
    module.exit_json(changed=changed, instances=get_instances_info(ecs, ids))