Esempio n. 1
0
def delete_vpc(ctx, vpc_name, dry_run):
    """Delete VPC"""
    obj_kind = ObjectKind.VPC.value
    obj_name = vpc_name
    # Check if fabric is set
    if not ctx.obj.state.get_current_fabric():
        log_error('Cannot delete VPC. Please select fabric first.')
        sys.exit(1)
    # Check if naming matches rules
    obj_name = ctx.obj.state.normalise_state_obj_name(obj_kind, obj_name)

    log_info('Deleting VPC {0!r}...'.format(obj_name))
    # Check if VPC exists
    if not ctx.obj.state.check_vpc(ctx.obj.state.get_current_fabric(), obj_name):
        log_error("Cannot delete. VPC {0!r} doesn't exist".format(obj_name))
        sys.exit(1)
    # Check if there are nodes in VPC
    node_list = []
    for node_kind in [ObjectKind.ORCHESTRATOR.value, ObjectKind.PROCESSOR.value, ObjectKind.WORKLOAD.value]:
        node_list = node_list + [x for x in ctx.obj.state.get_fabric_objects(node_kind).items()
                                 if obj_name in x[1][obj_kind]]
    if node_list:
        log_error("Cannot delete. VPC {0!r} contains nodes, delete them first:".format(obj_name))
        for node in node_list:
            log_error("{0!r}".format(node[0]))
        sys.exit(1)
    # Delete VPC
    if dry_run:
        log_warn('{0} {1!r} to be deleted (started with --dry-run)'.format(obj_kind.upper(), obj_name))
        return True
    # Get credentials
    credentials = Credentials(ctx.obj.state.get_current_fabric(), ctx.obj.state.get(), ctx.obj.state.config)
    if not credentials.get():
        log_error('Cannot delete VPC. Not able to get credentials')
        sys.exit(1)
    # Actual VPC deletion
    temp_state = deepcopy(ctx.obj.state)
    res = temp_state.delete_fabric_object(obj_kind, obj_name)
    if not res.status:
        log_error('{0} {1!r} cannot be deleted. {2!s}'.format(obj_kind.upper(), obj_name, res.value))
        sys.exit(1)
    # Run Terraform with new state
    terraform = Terraform(temp_state.get_current_fabric(), temp_state, credentials, ctx.obj.version)
    if not terraform.plan_generate():
        log_error('Cannot delete VPC. There is issue with terraform plan generation')
        sys.exit(1)

    terraform_result = terraform.plan_execute()
    if not terraform_result[0]:
        log_error('Cannot delete VPC. There is issue with terraform plan execution')
        sys.exit(terraform_result[1])
    # Delete VPCs batches
    temp_state.nodebatch_delete(vpc=obj_name)
    # Set new state to be current and dump it
    ctx.obj.state = deepcopy(temp_state)
    ctx.obj.state.dump()
    log_ok('{0} {1!r} deleted successfully'.format(obj_kind.upper(), obj_name))
    return True
Esempio n. 2
0
def delete_workload(ctx, workload_name, dry_run):
    """Delete workload"""
    obj_kind = ObjectKind.WORKLOAD.value
    obj_name = workload_name
    # Check if fabric is set
    if not ctx.obj.state.get_current_fabric():
        log_error('Cannot delete {0}. Please select fabric first.'.format(obj_kind))
        sys.exit(1)
    # Check if naming matches rules
    obj_name = ctx.obj.state.normalise_state_obj_name(obj_kind, obj_name)

    log_info('Deleting {0} {1!r}...'.format(obj_kind, obj_name))
    # Check if exists
    if not ctx.obj.state.check_workload(ctx.obj.state.get_current_fabric(), obj_name):
        log_error("Cannot delete. {0} {1!r} doesn't exist".format(obj_kind.title(), obj_name))
        sys.exit(1)

    if dry_run:
        log_warn('{0} {1!r} to be deleted (started with --dry-run)'.format(obj_kind.title(), obj_name))
        return True
    # Get credentials
    credentials = Credentials(ctx.obj.state.get_current_fabric(), ctx.obj.state.get(), ctx.obj.state.config)
    if not credentials.get():
        log_error('Cannot delete {0}. Not able to get credentials'.format(obj_kind))
        sys.exit(1)
    # Actual deletion
    temp_state = deepcopy(ctx.obj.state)
    res = temp_state.delete_fabric_object(obj_kind, obj_name)
    if not res.status:
        log_error('{0} {1!r} cannot be deleted. {2!s}'.format(obj_kind, obj_name, res.value))
        sys.exit(1)
    # Run Terraform with new state
    terraform = Terraform(temp_state.get_current_fabric(), temp_state, credentials, ctx.obj.version)
    if not terraform.plan_generate():
        log_error('Cannot delete {0}. There is issue with terraform plan generation'.format(obj_kind))
        sys.exit(1)
    terraform_result = terraform.plan_execute()
    if not terraform_result[0]:
        log_error('Cannot delete {0}. There is issue with terraform plan execution'.format(obj_kind))
        sys.exit(terraform_result[1])
    # Set new state to be current and dump it
    ctx.obj.state = deepcopy(temp_state)
    ctx.obj.state.dump()
    log_ok('{0} {1!r} deleted successfully'.format(obj_kind.title(), obj_name))
    # Generate SSH configuration
    ssh_config = SshConfig(ctx.obj.state)
    if ssh_config.generate_config():
        log_info('Generating SSH config...')
    else:
        log_warn('Error during SSH config generation')
    return True
Esempio n. 3
0
def delete_orchestrator(ctx, orchestrator_name, dry_run):
    """Delete orchestrator"""
    obj_kind = ObjectKind.ORCHESTRATOR.value
    obj_name = orchestrator_name
    # Check if fabric is set
    if not ctx.obj.state.get_current_fabric():
        log_error('Cannot delete {0}. Please select fabric first.'.format(obj_kind))
        sys.exit(1)
    # Check if naming matches rules
    obj_name = ctx.obj.state.normalise_state_obj_name(obj_kind, obj_name)

    log_info('Deleting {0} {1!r}...'.format(obj_kind, obj_name))
    # Check if exists
    if not ctx.obj.state.check_orchestrator(ctx.obj.state.get_current_fabric(), obj_name):
        log_error("Cannot delete. {0} {1!r} doesn't exist".format(obj_kind.title(), obj_name))
        sys.exit(1)

    if dry_run:
        log_warn('{0} {1!r} to be deleted (started with --dry-run)'.format(obj_kind.title(), obj_name))
        return True
    # Check if configured
    obj = ctx.obj.state.get_fabric_object(obj_kind, obj_name)
    if not ctx.obj.state.check_object_state(obj, ObjectState.CREATED):
        # Delete orchestrator
        ansible_vars = []
        ansible_nodes = [obj_name]
        ansible_playbook = "delete-" + obj['type'] + ".yml"
        # Get swarm manager
        managers = [x for x in ctx.obj.state.get_fabric_objects(obj_kind).items() if 'manager' in x[1]['role']]
        workers = [x for x in ctx.obj.state.get_fabric_objects(obj_kind).items() if 'worker' in x[1]['role']]
        if not managers:
            log_warn('There is no swarm manager found. Nothing should be done with ansible')
        else:
            # Check if manager and there are workers
            if obj['role'] == 'manager' and workers:
                log_error(
                    '{0} {1!r} is swarm manager. Remove workers first:'.format(obj_kind.title(), orchestrator_name))
                for node in workers:
                    log_error("{0!r}".format(node[0]))
                sys.exit(1)
            ansible_vars = ansible_vars + [('env_swarm_manager_host', managers[0][0])]
            ansible_nodes = ansible_nodes + [managers[0][0]]
            ansible = Ansible(ctx.obj.state, ctx.obj.state.get_current_fabric(), ctx.obj.state.get_ssh_key())
            if ansible.inventory_generate(ansible_nodes, node_vars=ansible_vars):
                ansible_result = ansible.run_playbook(ansible_playbook)
                if not ansible_result[0]:
                    log_error('Cannot delete {0}. There is issue with ansible playbook execution'.format(obj_kind))
                    sys.exit(ansible_result[1])
            else:
                sys.exit(1)
    # Get credentials
    credentials = Credentials(ctx.obj.state.get_current_fabric(), ctx.obj.state.get(), ctx.obj.state.config)
    if not credentials.get():
        log_error('Cannot delete {0}. Not able to get credentials'.format(obj_kind))
        sys.exit(1)
    # Actual deletion
    temp_state = deepcopy(ctx.obj.state)
    res = temp_state.delete_fabric_object(obj_kind, obj_name)
    if not res.status:
        log_error('{0} {1!r} cannot be deleted. {2!s}'.format(obj_kind, obj_name, res.value))
        sys.exit(1)
    # Run Terraform with new state
    terraform = Terraform(temp_state.get_current_fabric(), temp_state, credentials, ctx.obj.version)
    if not terraform.plan_generate():
        log_error('Cannot delete {0}. There is issue with terraform plan generation'.format(obj_kind))
        sys.exit(1)
    terraform_result = terraform.plan_execute()
    if not terraform_result[0]:
        log_error('Cannot delete {0}. There is issue with terraform plan execution'.format(obj_kind))
        sys.exit(terraform_result[1])
    # Set new state to be current and dump it
    ctx.obj.state = deepcopy(temp_state)
    ctx.obj.state.dump()
    log_ok('{0} {1!r} deleted successfully'.format(obj_kind.title(), obj_name))
    # Generate SSH configuration
    ssh_config = SshConfig(ctx.obj.state)
    if ssh_config.generate_config():
        log_info('Generating SSH config...')
    else:
        log_warn('Error during SSH config generation')
    return True
Esempio n. 4
0
def delete_processor(ctx, processor_name, dry_run):
    """Delete processor"""
    obj_kind = ObjectKind.PROCESSOR.value
    obj_name = processor_name
    # Check if fabric is set
    if not ctx.obj.state.get_current_fabric():
        log_error('Cannot delete {0}. Please select fabric first.'.format(obj_kind))
        sys.exit(1)
    # Check if naming matches rules
    obj_name = ctx.obj.state.normalise_state_obj_name(obj_kind, obj_name)

    log_info('Deleting {0} {1!r}...'.format(obj_kind, obj_name))
    # Check if exists
    if not ctx.obj.state.check_processor(ctx.obj.state.get_current_fabric(), obj_name):
        log_error("Cannot delete. {0} {1!r} doesn't exist".format(obj_kind.title(), obj_name))
        sys.exit(1)
    # Check if its the only processor in VPC and there are workloads
    obj_vpc = ctx.obj.state.get_fabric_object(obj_kind, obj_name)['vpc']
    processors = [x[0] for x in ctx.obj.state.get_fabric_objects(obj_kind).items() if obj_vpc == x[1]['vpc']]
    workloads = [x[0] for x in ctx.obj.state.get_fabric_objects(ObjectKind.WORKLOAD.value).items()
                 if obj_vpc == x[1]['vpc']]
    if len(processors) < 2 and bool(workloads):
        log_error(
            "Cannot delete {0!r}. At least one {1} should left in VPC {2!r} to manage workloads: {3}".format(
                obj_name, obj_kind.title(), obj_vpc, workloads))
        sys.exit(1)

    if dry_run:
        log_warn('{0} {1!r} to be deleted (started with --dry-run)'.format(obj_kind.title(), obj_name))
        return True
    # Get credentials
    credentials = Credentials(ctx.obj.state.get_current_fabric(), ctx.obj.state.get(), ctx.obj.state.config)
    if not credentials.get():
        log_error('Cannot delete {0}. Not able to get credentials'.format(obj_kind))
        sys.exit(1)
    # Actual deletion
    temp_state = deepcopy(ctx.obj.state)
    res = temp_state.delete_fabric_object(obj_kind, obj_name)
    if not res.status:
        log_error('{0} {1!r} cannot be deleted. {2!s}'.format(obj_kind, obj_name, res.value))
        sys.exit(1)
    # Run Terraform with new state
    terraform = Terraform(temp_state.get_current_fabric(), temp_state, credentials, ctx.obj.version)
    if not terraform.plan_generate():
        log_error('Cannot delete {0}. There is issue with terraform plan generation'.format(obj_kind))
        sys.exit(1)
    terraform_result = terraform.plan_execute()
    if not terraform_result[0]:
        log_error('Cannot delete {0}. There is issue with terraform plan execution'.format(obj_kind))
        sys.exit(terraform_result[1])
    # Set new state to be current and dump it
    ctx.obj.state = deepcopy(temp_state)
    ctx.obj.state.dump()
    log_ok('{0} {1!r} deleted successfully'.format(obj_kind.title(), obj_name))
    # Generate SSH configuration
    ssh_config = SshConfig(ctx.obj.state)
    if ssh_config.generate_config():
        log_info('Generating SSH config...')
    else:
        log_warn('Error during SSH config generation')
    return True
Esempio n. 5
0
def delete_batch(ctx, filename, input_format, dry_run, yes):
    """Delete batch"""
    log_info('Deleting batch: file={!r}, input=format={!r}, dry-run={!r}'.format(filename, input_format, dry_run))
    # Only YAML currently
    if input_format != 'yaml':
        log_warn('Only YAML supported')

    # Safely load YAML
    # noinspection PyBroadException
    try:
        with open(filename, 'r') as config_f:
            try:
                batch = yaml.safe_load(config_f)
            except yaml.YAMLError as err:
                log_error("Error while loading YAML: {0!r}".format(err))
                if hasattr(err, 'problem_mark'):
                    mark = err.problem_mark
                    log_error("Error position: ({}:{})".format(mark.line + 1, mark.column + 1))
                sys.exit(1)
        config_f.close()
    except IOError as err:
        log_error(err)
        sys.exit(1)
    except Exception:  # handle other exceptions such as attribute errors
        print("Unexpected error:", sys.exc_info()[0])
        sys.exit(1)

    # Parse batch
    try:
        batch = BatchSpec(batch, ctx.obj.state.api_version)
    except TypeError as err:
        log_error("Cannot parse batch: {0!r}".format(err))
        sys.exit(1)

    # Get objects to be deleted (by fabric)
    delete_target = {}
    for obj_kind in [ObjectKind.FABRIC, ObjectKind.VPC, ObjectKind.ORCHESTRATOR, ObjectKind.PROCESSOR,
                     ObjectKind.WORKLOAD]:
        for obj in batch.get_attr_list(obj_kind):
            if obj_kind == ObjectKind.FABRIC:
                fabric_name = obj['metadata']['name']
            else:
                fabric_name = obj['metadata']['fabric']
            if fabric_name not in delete_target:
                delete_target[fabric_name] = {ObjectKind.FABRIC: [], ObjectKind.VPC: [], ObjectKind.WORKLOAD: [],
                                              ObjectKind.ORCHESTRATOR: [], ObjectKind.PROCESSOR: []}
            delete_target[fabric_name][obj_kind].append(batch.get_attr_name(obj))

    for fabric in delete_target:
        for obj_kind in [ObjectKind.FABRIC, ObjectKind.VPC, ObjectKind.ORCHESTRATOR, ObjectKind.PROCESSOR,
                         ObjectKind.WORKLOAD]:
            if obj_kind in delete_target[fabric]:
                if delete_target[fabric][obj_kind]:
                    log_info('{0}: {1!r}'.format(obj_kind.value.title(), delete_target[fabric][obj_kind]))

    def confirm_yes_no(message, default="no"):
        """Requires confirmation with yes/no"""
        valid = {"yes": True, "y": True, "ye": True, "no": False, "n": False}
        prompt = " [y/N] "
        while True:
            log_info(message + prompt)
            choice = input().lower()
            if choice == '':
                return valid[default]
            elif choice in valid:
                return valid[choice]
            else:
                log_info("Please respond with 'yes' or 'no'")

    if not yes:
        if not confirm_yes_no('Do you want to delete these objects?'):
            log_info('Exiting...')
            return True

    # For all fabrics in delete target
    for fabric in delete_target:
        # Processing fabrics
        if fabric in delete_target[fabric][ObjectKind.FABRIC]:
            temp_state_ok = deepcopy(ctx.obj.state)
            temp_state_failed = deepcopy(ctx.obj.state)
            if temp_state_failed.check_fabric(fabric):
                log_warn('Fabric {0!r} is going to be deleted with all nested objects'.format(fabric))
                # Set deleting status in state
                temp_state_failed.set_object_state_status(temp_state_failed.get_fabric(fabric), ObjectState.DELETING,
                                                          ObjectStatus.FAILED)
                # Get nested objects
                nested = []
                for obj_kind in [ObjectKind.VPC, ObjectKind.ORCHESTRATOR, ObjectKind.PROCESSOR, ObjectKind.WORKLOAD]:
                    nested.append([obj[0] for obj in
                                   temp_state_failed.get_fabric_objects(obj_kind.value, fabric).items()])
                # Set nested state to deleting
                for index, obj_kind in enumerate([ObjectKind.VPC, ObjectKind.ORCHESTRATOR, ObjectKind.PROCESSOR,
                                                  ObjectKind.WORKLOAD]):
                    for obj_name in nested[index]:
                        obj = temp_state_failed.get_fabric_object(obj_kind.value, obj_name, fabric)
                        temp_state_failed.set_object_state_status(obj, ObjectState.DELETING, ObjectStatus.FAILED)
                        if obj_kind != ObjectKind.VPC:
                            res = temp_state_ok.delete_fabric_object(obj_kind.value, obj_name, fabric)
                            if not res.status:
                                log_error('Fabric {0!r} cannot be deleted. {1!s}'.format(fabric, res.value))
                                sys.exit(1)

                # Try to delete nodes-only nested objects
                nested_nodes = nested[1] + nested[2] + nested[3]
                if nested_nodes:
                    log_info("Deleting nested nodes first")
                    # Get credentials
                    credentials = Credentials(fabric, temp_state_failed.get(), ctx.obj.state.config)
                    if not credentials.get():
                        log_error('Batch failed. Not able to get credentials')
                        sys.exit(1)
                    # Run terraform
                    terraform = Terraform(fabric, temp_state_ok, credentials, ctx.obj.version)
                    if not terraform.plan_generate():
                        log_error('Batch failed to delete nested nodes: {!r}. Exiting'.format(nested_nodes))
                        ctx.obj.state = deepcopy(temp_state_failed)
                        ctx.obj.state.dump()
                        sys.exit(1)
                    terraform_result = terraform.plan_execute()
                    if not terraform_result[0]:
                        log_error('Batch failed to delete nested nodes: {!r}. Exiting'.format(nested_nodes))
                        ctx.obj.state = deepcopy(temp_state_failed)
                        ctx.obj.state.dump()
                        sys.exit(terraform_result[1])
                # If this is current fabric, unset it
                if temp_state_failed.get_current_fabric() == fabric:
                    ctx.obj.set_current_fabric(None)
                # Delete fabric from state
                res = temp_state_ok.delete_fabric(fabric)
                if not res.status:
                    log_error('Fabric {0!r} cannot be deleted. {1!s}'.format(fabric, res.value))
                    sys.exit(1)
                # Try to delete nested VPCs
                if nested[0]:
                    log_info("Deleting nested VPCs")
                    # Get credentials
                    credentials = Credentials(fabric, temp_state_failed.get(), ctx.obj.state.config)
                    if not credentials.get():
                        log_error('Batch failed. Not able to get credentials')
                        sys.exit(1)
                    # Run terraform
                    terraform = Terraform(fabric, temp_state_ok, credentials, ctx.obj.version)
                    if not terraform.plan_generate():
                        log_error('Batch failed to delete fabric: {!r}. Exiting'.format(fabric))
                        ctx.obj.state = deepcopy(temp_state_failed)
                        ctx.obj.state.dump()
                        sys.exit(1)
                    terraform_result = terraform.plan_execute()
                    if not terraform_result[0]:
                        log_error('Batch failed to delete fabric: {!r}. Exiting'.format(fabric))
                        ctx.obj.state = deepcopy(temp_state_failed)
                        ctx.obj.state.dump()
                        sys.exit(terraform_result[1])
                # Run ansible playbook
                ansible_playbook = "delete-fabric.yml"
                ansible = Ansible(temp_state_failed, fabric, temp_state_failed.get_ssh_key())
                log_info("Delete {0!r} fabric's files".format(fabric))
                ansible_result = ansible.run_playbook(ansible_playbook, local=True)
                if not ansible_result[0]:
                    log_error('Cannot delete fabric. There is issue with ansible playbook execution')
                    ctx.obj.state = deepcopy(temp_state_failed)
                    ctx.obj.dump()
                    sys.exit(ansible_result[1])
                # Delete fabrics batches
                temp_state_ok.nodebatch_delete(fabric=fabric)
                # Success
                ctx.obj.state = deepcopy(temp_state_ok)
                ctx.obj.state.dump()
        # Processing VPCs
        nested = {}
        temp_state_ok = deepcopy(ctx.obj.state)
        temp_state_failed = deepcopy(ctx.obj.state)
        # For all vpc in delete target
        vpc_list = delete_target[fabric][ObjectKind.VPC][:]
        for vpc in vpc_list:
            # Check if objects are exist
            if not temp_state_failed.check_fabric(fabric):
                delete_target[fabric][ObjectKind.VPC].remove(vpc)
                continue
            elif not temp_state_failed.check_vpc(fabric, vpc):
                delete_target[fabric][ObjectKind.VPC].remove(vpc)
                continue
            log_warn('VPC {0!r} is going to be deleted with all nested objects'.format(vpc))
            # Set deleting status in state
            obj = temp_state_failed.get_fabric_object(ObjectKind.VPC.value, vpc, fabric)
            temp_state_failed.set_object_state_status(obj, ObjectState.DELETING, ObjectStatus.FAILED)
            # Get nested objects
            nested[vpc] = []
            for obj_kind in [ObjectKind.ORCHESTRATOR, ObjectKind.PROCESSOR, ObjectKind.WORKLOAD]:
                nested[vpc].append([obj[0] for obj in
                                    temp_state_failed.get_fabric_objects(obj_kind.value, fabric).items()
                                    if vpc in obj[1][ObjectKind.VPC.value]])
            # Set nested state to deleting
            for index, obj_kind in enumerate([ObjectKind.ORCHESTRATOR, ObjectKind.PROCESSOR, ObjectKind.WORKLOAD]):
                for obj_name in nested[vpc][index]:
                    obj = temp_state_failed.get_fabric_object(obj_kind.value, obj_name, fabric)
                    temp_state_failed.set_object_state_status(obj, ObjectState.DELETING, ObjectStatus.FAILED)
                    res = temp_state_ok.delete_fabric_object(obj_kind.value, obj_name, fabric)
                    if not res.status:
                        log_error('Nested object {0!r} cannot be deleted. {1!s}'.format(obj_name, res.value))
                        sys.exit(1)
        # Try to delete nodes-only nested objects
        delete_nodes = False
        for vpc in delete_target[fabric][ObjectKind.VPC]:
            if nested[vpc][0] or nested[vpc][1] or nested[vpc][2]:
                delete_nodes = True
        if delete_nodes:
            log_info("Deleting nested nodes first")
            # Get credentials
            credentials = Credentials(fabric, temp_state_failed.get(), ctx.obj.state.config)
            if not credentials.get():
                log_error('Batch failed. Not able to get credentials')
                sys.exit(1)
            # Run terraform
            terraform = Terraform(fabric, temp_state_ok, credentials, ctx.obj.version)
            if not terraform.plan_generate():
                log_error('Batch failed to delete nodes, that nested to VPCs: {!r}. Exiting'.
                          format(delete_target[fabric][ObjectKind.VPC]))
                ctx.obj.state = deepcopy(temp_state_failed)
                ctx.obj.state.dump()
                sys.exit(1)
            terraform_result = terraform.plan_execute()
            if not terraform_result[0]:
                log_error('Batch failed to delete nodes, that nested to VPCs: {!r}. Exiting'.
                          format(delete_target[fabric][ObjectKind.VPC]))
                ctx.obj.state = deepcopy(temp_state_failed)
                ctx.obj.state.dump()
                sys.exit(terraform_result[1])
        # Delete VPC from state
        for vpc in delete_target[fabric][ObjectKind.VPC]:
            res = temp_state_ok.delete_fabric_object(ObjectKind.VPC.value, vpc, fabric)
            if not res.status:
                log_error('VPC {0!r} cannot be deleted. {1!s}'.format(vpc, res.value))
                sys.exit(1)
        # Actual VPC delete
        if delete_target[fabric][ObjectKind.VPC]:
            log_info("Deleting VPCs")
            # Get credentials
            credentials = Credentials(fabric, temp_state_failed.get(), ctx.obj.state.config)
            if not credentials.get():
                log_error('Batch failed. Not able to get credentials')
                sys.exit(1)
            # Run terraform
            terraform = Terraform(fabric, temp_state_ok, credentials, ctx.obj.version)
            if not terraform.plan_generate():
                log_error('Batch failed to delete VPCs: {!r}. Exiting'.format(delete_target[fabric][ObjectKind.VPC]))
                ctx.obj.state = deepcopy(temp_state_failed)
                ctx.obj.state.dump()
                sys.exit(1)
            terraform_result = terraform.plan_execute()
            if not terraform_result[0]:
                log_error('Batch failed to delete VPCs: {!r}. Exiting'.format(delete_target[fabric][ObjectKind.VPC]))
                ctx.obj.state = deepcopy(temp_state_failed)
                ctx.obj.state.dump()
                sys.exit(terraform_result[1])
        # Delete VPCs batches
        for vpc in delete_target[fabric][ObjectKind.VPC]:
            temp_state_ok.nodebatch_delete(vpc=vpc)
        # Success
        ctx.obj.state = deepcopy(temp_state_ok)
        ctx.obj.state.dump()
        # Processing nodes
        temp_state_ok = deepcopy(ctx.obj.state)
        temp_state_failed = deepcopy(ctx.obj.state)
        node_list = {}
        # For all nodes in delete target
        for obj_kind in [ObjectKind.ORCHESTRATOR, ObjectKind.PROCESSOR, ObjectKind.WORKLOAD]:
            node_list[obj_kind] = delete_target[fabric][obj_kind][:]
            for node in node_list[obj_kind]:
                # Check if objects are exist
                if not temp_state_failed.check_fabric(fabric):
                    delete_target[fabric][obj_kind].remove(node)
                    continue
                else:
                    if obj_kind is ObjectKind.ORCHESTRATOR:
                        if not temp_state_failed.check_orchestrator(fabric, node):
                            delete_target[fabric][obj_kind].remove(node)
                            continue
                    elif obj_kind is ObjectKind.PROCESSOR:
                        if not temp_state_failed.check_processor(fabric, node):
                            delete_target[fabric][obj_kind].remove(node)
                            continue
                    elif obj_kind is ObjectKind.WORKLOAD:
                        if not temp_state_failed.check_workload(fabric, node):
                            delete_target[fabric][obj_kind].remove(node)
                            continue
                # Set deleting status in state
                obj = temp_state_failed.get_fabric_object(obj_kind.value, node, fabric)
                temp_state_failed.set_object_state_status(obj, ObjectState.DELETING, ObjectStatus.FAILED)
                # Delete node from state
                res = temp_state_ok.delete_fabric_object(obj_kind.value, node, fabric)
                if not res.status:
                    log_error('Node {0!r} cannot be deleted. {1!s}'.format(node, res.value))
                    sys.exit(1)
        # Check if there is at least one processor left in VPC where workloads are present
        for proc in delete_target[fabric][ObjectKind.PROCESSOR][:]:
            # Check if its the only processor in VPC and there are workloads
            proc_vpc = temp_state_failed.get_fabric_object(ObjectKind.PROCESSOR.value, proc, fabric).get('vpc')
            processors = [x[0] for x in temp_state_ok.get_fabric_object(ObjectKind.PROCESSOR.value, fabric).items() if
                          proc_vpc == x[1]['vpc']]
            workloads = [x[0] for x in temp_state_ok.get_fabric_object(ObjectKind.WORKLOAD.value, fabric).items() if
                         proc_vpc == x[1]['vpc']]
            if not bool(processors) and bool(workloads):
                log_error("Cannot delete {0!r}. At least one {1} should left in VPC {2!r} to manage workloads: {3}"
                          .format(proc, ObjectKind.PROCESSOR.value.title(), proc_vpc, workloads))
                sys.exit(1)
        # Actual node delete
        if delete_target[fabric][ObjectKind.ORCHESTRATOR] or delete_target[fabric][ObjectKind.PROCESSOR] or \
                delete_target[fabric][ObjectKind.WORKLOAD]:
            # Get credentials
            credentials = Credentials(fabric, temp_state_failed.get(), ctx.obj.state.config)
            if not credentials.get():
                log_error('Batch failed. Not able to get credentials')
                sys.exit(1)
            # Run terraform
            terraform = Terraform(fabric, temp_state_ok, credentials, ctx.obj.version)
            if not terraform.plan_generate():
                delete_nodes = delete_target[fabric][ObjectKind.ORCHESTRATOR] + \
                               delete_target[fabric][ObjectKind.PROCESSOR] + delete_target[fabric][ObjectKind.WORKLOAD]
                log_error('Batch failed to delete nodes: {!r}. Exiting'.format(delete_nodes))
                ctx.obj.state = deepcopy(temp_state_failed)
                ctx.obj.state.dump()
                sys.exit(1)
            terraform_result = terraform.plan_execute()
            if not terraform_result[0]:
                log_error('Batch failed to delete nodes: {!r}. Exiting'.format(delete_nodes))
                ctx.obj.state = deepcopy(temp_state_failed)
                ctx.obj.state.dump()
                sys.exit(terraform_result[1])
        # Success
        ctx.obj.state = deepcopy(temp_state_ok)
        ctx.obj.state.dump()
    log_ok('Batch is finished')
    # Generate SSH configuration
    ssh_config = SshConfig(ctx.obj.state)
    if ssh_config.generate_config():
        log_info('Generating SSH config...')
    else:
        log_warn('Error during SSH config generation')
    return True