Instruction:
Implement a Python 3 function for
requesting an instance from OpenStack.

Response:
def request_instance(vm_=None, call=None):
    '''
    Put together all of the information necessary to request an instance
    through Novaclient and then fire off the request the instance.

    Returns data about the instance
    '''
    if call == 'function':
        # Technically this function may be called other ways too, but it
        # definitely cannot be called with --function.
        raise SaltCloudSystemExit(
            'The request_instance action must be called with -a or --action.'
        )
    log.info('Creating Cloud VM %s', vm_['name'])
    salt.utils.cloud.check_name(vm_['name'], 'a-zA-Z0-9._-')
    conn = get_conn()
    kwargs = vm_.copy()

    try:
        kwargs['image_id'] = get_image(conn, vm_)
    except Exception as exc:
        raise SaltCloudSystemExit(
            'Error creating {0} on OPENSTACK\n\n'
            'Could not find image {1}: {2}\n'.format(
                vm_['name'], vm_['image'], exc
            )
        )

    try:
        kwargs['flavor_id'] = get_size(conn, vm_)
    except Exception as exc:
        raise SaltCloudSystemExit(
            'Error creating {0} on OPENSTACK\n\n'
            'Could not find size {1}: {2}\n'.format(
                vm_['name'], vm_['size'], exc
            )
        )

    kwargs['key_name'] = config.get_cloud_config_value(
        'ssh_key_name', vm_, __opts__, search_global=False
    )

    security_groups = config.get_cloud_config_value(
        'security_groups', vm_, __opts__, search_global=False
    )
    if security_groups is not None:
        vm_groups = security_groups
        avail_groups = conn.secgroup_list()
        group_list = []

        for vmg in vm_groups:
            if vmg in [name for name, details in six.iteritems(avail_groups)]:
                group_list.append(vmg)
            else:
                raise SaltCloudNotFound(
                    'No such security group: \'{0}\''.format(vmg)
                )

        kwargs['security_groups'] = group_list

    avz = config.get_cloud_config_value(
        'availability_zone', vm_, __opts__, default=None, search_global=False
    )
    if avz is not None:
        kwargs['availability_zone'] = avz

    kwargs['nics'] = config.get_cloud_config_value(
        'networks', vm_, __opts__, search_global=False, default=None
    )

    files = config.get_cloud_config_value(
        'files', vm_, __opts__, search_global=False
    )
    if files:
        kwargs['files'] = {}
        for src_path in files:
            if os.path.exists(files[src_path]):
                with salt.utils.files.fopen(files[src_path], 'r') as fp_:
                    kwargs['files'][src_path] = fp_.read()
            else:
                kwargs['files'][src_path] = files[src_path]

    userdata_file = config.get_cloud_config_value(
        'userdata_file', vm_, __opts__, search_global=False, default=None
    )
    if userdata_file is not None:
        try:
            with salt.utils.files.fopen(userdata_file, 'r') as fp_:
                kwargs['userdata'] = salt.utils.cloud.userdata_template(
                    __opts__, vm_, fp_.read()
                )
        except Exception as exc:
            log.exception(
                'Failed to read userdata from %s: %s', userdata_file, exc)

    kwargs['config_drive'] = config.get_cloud_config_value(
        'config_drive', vm_, __opts__, search_global=False
    )

    kwargs.update(get_block_mapping_opts(vm_))

    event_kwargs = {
        'name': kwargs['name'],
        'image': kwargs.get('image_id', 'Boot From Volume'),
        'size': kwargs['flavor_id'],
    }

    __utils__['cloud.fire_event'](
        'event',
        'requesting instance',
        'salt/cloud/{0}/requesting'.format(vm_['name']),
        args={
            'kwargs': __utils__['cloud.filter_event']('requesting', event_kwargs, list(event_kwargs)),
        },
        sock_dir=__opts__['sock_dir'],
        transport=__opts__['transport']
    )

    try:
        data = conn.boot(**kwargs)
    except Exception as exc:
        raise SaltCloudSystemExit(
            'Error creating {0} on Nova\n\n'
            'The following exception was thrown by libcloud when trying to '
            'run the initial deployment: {1}\n'.format(
                vm_['name'], exc
            )
        )
    if data.extra.get('password', None) is None and vm_.get('key_filename', None) is None:
        raise SaltCloudSystemExit('No password returned.  Set ssh_key_file.')

    floating_ip_conf = config.get_cloud_config_value('floating_ip',
                                                     vm_,
                                                     __opts__,
                                                     search_global=False,
                                                     default={})
    if floating_ip_conf.get('auto_assign', False):
        floating_ip = None
        if floating_ip_conf.get('ip_address', None) is not None:
            ip_address = floating_ip_conf.get('ip_address', None)
            try:
                fl_ip_dict = conn.floating_ip_show(ip_address)
                floating_ip = fl_ip_dict['ip']
            except Exception as err:
                raise SaltCloudSystemExit(
                    'Error assigning floating_ip for {0} on Nova\n\n'
                    'The following exception was thrown by libcloud when trying to '
                    'assign a floating ip: {1}\n'.format(
                        vm_['name'], err
                    )
                )

        else:
            pool = floating_ip_conf.get('pool', 'public')
            try:
                floating_ip = conn.floating_ip_create(pool)['ip']
            except Exception:
                log.info('A new IP address was unable to be allocated. '
                         'An IP address will be pulled from the already allocated list, '
                         'This will cause a race condition when building in parallel.')
                for fl_ip, opts in six.iteritems(conn.floating_ip_list()):
                    if opts['fixed_ip'] is None and opts['pool'] == pool:
                        floating_ip = fl_ip
                        break
                if floating_ip is None:
                    log.error('No IP addresses available to allocate for this server: %s', vm_['name'])

        def __query_node_data(vm_):
            try:
                node = show_instance(vm_['name'], 'action')
                log.debug('Loaded node data for %s:\n%s', vm_['name'], pprint.pformat(node))
            except Exception as err:
                log.error(
                    'Failed to get nodes list: %s', err,
                    # Show the traceback if the debug logging level is enabled
                    exc_info_on_loglevel=logging.DEBUG
                )
                # Trigger a failure in the wait for IP function
                return False
            return node['state'] == 'ACTIVE' or None

        # if we associate the floating ip here,then we will fail.
        # As if we attempt to associate a floating IP before the Nova instance has completed building,
        # it will fail.So we should associate it after the Nova instance has completed building.
        try:
            salt.utils.cloud.wait_for_ip(
                __query_node_data,
                update_args=(vm_,)
            )
        except (SaltCloudExecutionTimeout, SaltCloudExecutionFailure) as exc:
            try:
                # It might be already up, let's destroy it!
                destroy(vm_['name'])
            except SaltCloudSystemExit:
                pass
            finally:
                raise SaltCloudSystemExit(six.text_type(exc))

        try:
            conn.floating_ip_associate(vm_['name'], floating_ip)
            vm_['floating_ip'] = floating_ip
        except Exception as exc:
            raise SaltCloudSystemExit(
                'Error assigning floating_ip for {0} on Nova\n\n'
                'The following exception was thrown by libcloud when trying to '
                'assign a floating ip: {1}\n'.format(
                    vm_['name'], exc
                )
            )

    if not vm_.get('password', None):
        vm_['password'] = data.extra.get('password', '')

    return data, vm_


Instruction:
Here you have a function in Python 3, explain what it does
def create(vm_):
    '''
    Create a single VM from a data dict
    '''
    try:
        # Check for required profile parameters before sending any API calls.
        if vm_['profile'] and config.is_profile_configured(__opts__,
                                                           __active_provider_name__ or 'nova',
                                                           vm_['profile'],
                                                           vm_=vm_) is False:
            return False
    except AttributeError:
        pass

    deploy = config.get_cloud_config_value('deploy', vm_, __opts__)
    key_filename = config.get_cloud_config_value(
        'ssh_key_file', vm_, __opts__, search_global=False, default=None
    )
    if key_filename is not None and not os.path.isfile(key_filename):
        raise SaltCloudConfigError(
            'The defined ssh_key_file \'{0}\' does not exist'.format(
                key_filename
            )
        )

    vm_['key_filename'] = key_filename

    __utils__['cloud.fire_event'](
        'event',
        'starting create',
        'salt/cloud/{0}/creating'.format(vm_['name']),
        args=__utils__['cloud.filter_event']('creating', vm_, ['name', 'profile', 'provider', 'driver']),
        sock_dir=__opts__['sock_dir'],
        transport=__opts__['transport']
    )
    conn = get_conn()

    if 'instance_id' in vm_:
        # This was probably created via another process, and doesn't have
        # things like salt keys created yet, so let's create them now.
        if 'pub_key' not in vm_ and 'priv_key' not in vm_:
            log.debug('Generating minion keys for \'%s\'', vm_['name'])
            vm_['priv_key'], vm_['pub_key'] = salt.utils.cloud.gen_keys(
                salt.config.get_cloud_config_value(
                    'keysize',
                    vm_,
                    __opts__
                )
            )
        data = conn.server_show_libcloud(vm_['instance_id'])
        if vm_['key_filename'] is None and 'change_password' in __opts__ and __opts__['change_password'] is True:
            vm_['password'] = salt.utils.pycrypto.secure_password()
            conn.root_password(vm_['instance_id'], vm_['password'])
    else:
        # Put together all of the information required to request the instance,
        # and then fire off the request for it
        data, vm_ = request_instance(vm_)

        # Pull the instance ID, valid for both spot and normal instances
        vm_['instance_id'] = data.id

    try:
        data = salt.utils.cloud.wait_for_ip(
            _query_node_data,
            update_args=(vm_, data, conn),
            timeout=config.get_cloud_config_value(
                'wait_for_ip_timeout', vm_, __opts__, default=10 * 60),
            interval=config.get_cloud_config_value(
                'wait_for_ip_interval', vm_, __opts__, default=10),
        )
    except (SaltCloudExecutionTimeout, SaltCloudExecutionFailure) as exc:
        try:
            # It might be already up, let's destroy it!
            destroy(vm_['name'])
        except SaltCloudSystemExit:
            pass
        finally:
            raise SaltCloudSystemExit(six.text_type(exc))

    log.debug('VM is now running')

    if ssh_interface(vm_) == 'private_ips':
        ip_address = preferred_ip(vm_, data.private_ips)
    elif ssh_interface(vm_) == 'fixed_ips':
        ip_address = preferred_ip(vm_, data.fixed_ips)
    elif ssh_interface(vm_) == 'floating_ips':
        ip_address = preferred_ip(vm_, data.floating_ips)
    else:
        ip_address = preferred_ip(vm_, data.public_ips)
    log.debug('Using IP address %s', ip_address)

    if salt.utils.cloud.get_salt_interface(vm_, __opts__) == 'private_ips':
        salt_ip_address = preferred_ip(vm_, data.private_ips)
        log.info('Salt interface set to: %s', salt_ip_address)
    elif salt.utils.cloud.get_salt_interface(vm_, __opts__) == 'fixed_ips':
        salt_ip_address = preferred_ip(vm_, data.fixed_ips)
        log.info('Salt interface set to: %s', salt_ip_address)
    elif salt.utils.cloud.get_salt_interface(vm_, __opts__) == 'floating_ips':
        salt_ip_address = preferred_ip(vm_, data.floating_ips)
        log.info('Salt interface set to: %s', salt_ip_address)
    else:
        salt_ip_address = preferred_ip(vm_, data.public_ips)
        log.debug('Salt interface set to: %s', salt_ip_address)

    if not ip_address:
        raise SaltCloudSystemExit('A valid IP address was not found')

    vm_['ssh_host'] = ip_address
    vm_['salt_host'] = salt_ip_address

    ret = __utils__['cloud.bootstrap'](vm_, __opts__)

    ret.update(data.__dict__)

    if 'password' in ret['extra']:
        del ret['extra']['password']

    log.info('Created Cloud VM \'%s\'', vm_['name'])
    log.debug(
        '\'%s\' VM creation details:\n%s',
        vm_['name'], pprint.pformat(data.__dict__)
    )

    event_data = {
        'name': vm_['name'],
        'profile': vm_['profile'],
        'provider': vm_['driver'],
        'instance_id': vm_['instance_id'],
        'floating_ips': data.floating_ips,
        'fixed_ips': data.fixed_ips,
        'private_ips': data.private_ips,
        'public_ips': data.public_ips
    }

    __utils__['cloud.fire_event'](
        'event',
        'created instance',
        'salt/cloud/{0}/created'.format(vm_['name']),
        args=__utils__['cloud.filter_event']('created', event_data, list(event_data)),
        sock_dir=__opts__['sock_dir'],
        transport=__opts__['transport']
    )
    __utils__['cloud.cachedir_index_add'](vm_['name'], vm_['profile'], 'nova', vm_['driver'])
    return ret

Response: Create a single VM from a data dict


Instruction:
Write a Python 3 function for
returning a list of the VMs that are in this location

Response:
def list_nodes(call=None, **kwargs):
    '''
    Return a list of the VMs that in this location
    '''
    if call == 'action':
        raise SaltCloudSystemExit(
            'The list_nodes function must be called with -f or --function.'
        )

    ret = {}
    conn = get_conn()
    server_list = conn.server_list()

    if not server_list:
        return {}
    for server in server_list:
        server_tmp = conn.server_show(server_list[server]['id']).get(server)

        # If the server is deleted while looking it up, skip
        if server_tmp is None:
            continue

        private = []
        public = []
        if 'addresses' not in server_tmp:
            server_tmp['addresses'] = {}
        for network in server_tmp['addresses']:
            for address in server_tmp['addresses'][network]:
                if salt.utils.cloud.is_public_ip(address.get('addr', '')):
                    public.append(address['addr'])
                elif ':' in address['addr']:
                    public.append(address['addr'])
                elif '.' in address['addr']:
                    private.append(address['addr'])

        if server_tmp['accessIPv4']:
            if salt.utils.cloud.is_public_ip(server_tmp['accessIPv4']):
                public.append(server_tmp['accessIPv4'])
            else:
                private.append(server_tmp['accessIPv4'])
        if server_tmp['accessIPv6']:
            public.append(server_tmp['accessIPv6'])

        ret[server] = {
            'id': server_tmp['id'],
            'image': server_tmp['image']['id'],
            'size': server_tmp['flavor']['id'],
            'state': server_tmp['state'],
            'private_ips': private,
            'public_ips': public,
        }
    return ret


Instruction:
Write a Python 3 script for
returning a list of the VMs that are in this location

Response:
def list_nodes_full(call=None, **kwargs):
    '''
    Return a list of the VMs that in this location
    '''
    if call == 'action':
        raise SaltCloudSystemExit(
            (
                'The list_nodes_full function must be called with'
                ' -f or --function.'
            )
        )

    ret = {}
    conn = get_conn()
    server_list = conn.server_list()

    if not server_list:
        return {}
    for server in server_list:
        try:
            ret[server] = conn.server_show_libcloud(
                server_list[server]['id']
            ).__dict__
        except IndexError as exc:
            ret = {}

    __utils__['cloud.cache_node_list'](ret, __active_provider_name__.split(':')[0], __opts__)
    return ret


Instruction:
Create a Python 3 function for
returning a list of the VMs that are in this location

Response:
def list_nodes_min(call=None, **kwargs):
    '''
    Return a list of the VMs that in this location
    '''
    if call == 'action':
        raise SaltCloudSystemExit(
            (
                'The list_nodes_min function must be called with'
                ' -f or --function.'
            )
        )

    conn = get_conn()
    server_list = conn.server_list_min()

    if not server_list:
        return {}
    return server_list


Instruction:
Explain what the following Python 3 code does
def volume_create(name, size=100, snapshot=None, voltype=None, **kwargs):
    '''
    Create block storage device
    '''
    conn = get_conn()
    create_kwargs = {'name': name,
                     'size': size,
                     'snapshot': snapshot,
                     'voltype': voltype}
    create_kwargs['availability_zone'] = kwargs.get('availability_zone', None)
    return conn.volume_create(**create_kwargs)

Response: Create block storage device


Instruction:
Can you generate a brief explanation for the following Python 3 code
def volume_attach(name, server_name, device='/dev/xvdb', **kwargs):
    '''
    Attach block volume
    '''
    conn = get_conn()
    return conn.volume_attach(
        name,
        server_name,
        device,
        timeout=300
    )

Response: Attach a block volume to a server


Instruction:
Given the following Python 3 function, write the documentation
def volume_create_attach(name, call=None, **kwargs):
    '''
    Create and attach volumes to created node
    '''
    if call == 'function':
        raise SaltCloudSystemExit(
            'The create_attach_volumes action must be called with '
            '-a or --action.'
        )

    if type(kwargs['volumes']) is str:
        volumes = salt.utils.yaml.safe_load(kwargs['volumes'])
    else:
        volumes = kwargs['volumes']

    ret = []
    for volume in volumes:
        created = False

        volume_dict = {
            'name': volume['name'],
        }
        if 'volume_id' in volume:
            volume_dict['volume_id'] = volume['volume_id']
        elif 'snapshot' in volume:
            volume_dict['snapshot'] = volume['snapshot']
        else:
            volume_dict['size'] = volume['size']

            if 'type' in volume:
                volume_dict['type'] = volume['type']
            if 'iops' in volume:
                volume_dict['iops'] = volume['iops']

        if 'id' not in volume_dict:
            created_volume = create_volume(**volume_dict)
            created = True
            volume_dict.update(created_volume)

        attach = attach_volume(
            name=volume['name'],
            server_name=name,
            device=volume.get('device', None),
            call='action'
        )

        if attach:
            msg = (
                '{0} attached to {1} (aka {2})'.format(
                    volume_dict['id'],
                    name,
                    volume_dict['name'],
                )
            )
            log.info(msg)
            ret.append(msg)
    return ret

Response: Create and attach volumes to a node


Instruction:
Write a Python 3 function for
allocating a floating IP and return the resource

Response:
def floating_ip_create(kwargs, call=None):
    '''
    Allocate a floating IP

    .. versionadded:: 2016.3.0
    '''
    if call != 'function':
        raise SaltCloudSystemExit(
            'The floating_ip_create action must be called with -f or --function'
        )

    if 'pool' not in kwargs:
        log.error('pool is required')
        return False

    conn = get_conn()
    return conn.floating_ip_create(kwargs['pool'])


Instruction:
Implement a function in Python 3 to
associate a floating IP address to a server

Response:
def floating_ip_associate(name, kwargs, call=None):
    '''
    Associate a floating IP address to a server

    .. versionadded:: 2016.3.0
    '''
    if call != 'action':
        raise SaltCloudSystemExit(
            'The floating_ip_associate action must be called with -a of --action.'
        )

    if 'floating_ip' not in kwargs:
        log.error('floating_ip is required')
        return False

    conn = get_conn()
    conn.floating_ip_associate(name, kwargs['floating_ip'])
    return list_nodes()[name]


Instruction:
Explain what the following Python 3 code does
def create(vm_):
    '''
    Create a single VM from a data dict
    '''
    try:
        # Check for required profile parameters before sending any API calls.
        if vm_['profile'] and config.is_profile_configured(__opts__,
                                                           __active_provider_name__ or 'gogrid',
                                                           vm_['profile'],
                                                           vm_=vm_) is False:
            return False
    except AttributeError:
        pass

    __utils__['cloud.fire_event'](
        'event',
        'starting create',
        'salt/cloud/{0}/creating'.format(vm_['name']),
        args=__utils__['cloud.filter_event']('creating', vm_, ['name', 'profile', 'provider', 'driver']),
        sock_dir=__opts__['sock_dir'],
        transport=__opts__['transport']
    )

    if len(vm_['name']) > 20:
        raise SaltCloudException('VM names must not be longer than 20 characters')

    log.info('Creating Cloud VM %s', vm_['name'])
    image_id = avail_images()[vm_['image']]['id']
    if 'assign_public_ip' in vm_:
        host_ip = vm_['assign_public_ip']
    else:
        public_ips = list_public_ips()
        if not public_ips:
            raise SaltCloudException('No more IPs available')
        host_ip = next(iter(public_ips))

    create_kwargs = {
        'name': vm_['name'],
        'image': image_id,
        'ram': vm_['size'],
        'ip': host_ip,
    }

    __utils__['cloud.fire_event'](
        'event',
        'requesting instance',
        'salt/cloud/{0}/requesting'.format(vm_['name']),
        args={
            'kwargs': __utils__['cloud.filter_event']('requesting', create_kwargs, list(create_kwargs)),
        },
        sock_dir=__opts__['sock_dir'],
        transport=__opts__['transport']
    )

    try:
        data = _query('grid', 'server/add', args=create_kwargs)
    except Exception:
        log.error(
            'Error creating %s on GOGRID\n\n'
            'The following exception was thrown when trying to '
            'run the initial deployment:\n', vm_['name'],
            # Show the traceback if the debug logging level is enabled
            exc_info_on_loglevel=logging.DEBUG
        )
        return False

    ssh_username = config.get_cloud_config_value(
        'ssh_username', vm_, __opts__, default='root'
    )

    def wait_for_apipass():
        '''
        Wait for the password to become available, via the API
        '''
        try:
            passwords = list_passwords()
            return passwords[vm_['name']][0]['password']
        except KeyError:
            pass
        time.sleep(5)
        return False

    vm_['password'] = salt.utils.cloud.wait_for_fun(
        wait_for_apipass,
        timeout=config.get_cloud_config_value(
            'wait_for_fun_timeout', vm_, __opts__, default=15 * 60),
    )

    vm_['ssh_host'] = host_ip
    ret = __utils__['cloud.bootstrap'](vm_, __opts__)
    ret.update(data)

    log.info('Created Cloud VM \'%s\'', vm_['name'])
    log.debug(
        '\'%s\' VM creation details:\n%s',
        vm_['name'], pprint.pformat(data)
    )

    __utils__['cloud.fire_event'](
        'event',
        'created instance',
        'salt/cloud/{0}/created'.format(vm_['name']),
        args=__utils__['cloud.filter_event']('created', vm_, ['name', 'profile', 'provider', 'driver']),
        sock_dir=__opts__['sock_dir'],
        transport=__opts__['transport']
    )

    return ret

Response: Create a single VM from a data dict


Instruction:
Can you implement a function in Python 3 that
returns a list of nodes in the cloud provider

Response:
def list_nodes(full=False, call=None):
    '''
    List of nodes, keeping only a brief listing

    CLI Example:

    .. code-block:: bash

        salt-cloud -Q
    '''
    if call == 'action':
        raise SaltCloudSystemExit(
            'The list_nodes function must be called with -f or --function.'
        )

    ret = {}
    nodes = list_nodes_full('function')
    if full:
        return nodes

    for node in nodes:
        ret[node] = {}
        for item in ('id', 'image', 'size', 'public_ips', 'private_ips', 'state'):
            ret[node][item] = nodes[node][item]

    return ret


Instruction:
Here you have a function in Python 3, explain what it does
def list_nodes_full(call=None):
    '''
    List nodes, with all available information

    CLI Example:

    .. code-block:: bash

        salt-cloud -F
    '''
    response = _query('grid', 'server/list')

    ret = {}
    for item in response['list']:
        name = item['name']
        ret[name] = item

        ret[name]['image_info'] = item['image']
        ret[name]['image'] = item['image']['friendlyName']
        ret[name]['size'] = item['ram']['name']
        ret[name]['public_ips'] = [item['ip']['ip']]
        ret[name]['private_ips'] = []
        ret[name]['state_info'] = item['state']
        if 'active' in item['state']['description']:
            ret[name]['state'] = 'RUNNING'

    return ret

Response: List all available nodes


Instruction:
Can you write a function in Python 3 where it
returns a dict of available locations

Response:
def avail_locations():
    '''
    Available locations
    '''
    response = list_common_lookups(kwargs={'lookup': 'ip.datacenter'})

    ret = {}
    for item in response['list']:
        name = item['name']
        ret[name] = item

    return ret


Instruction:
Make a summary of the following Python 3 code
def avail_sizes():
    '''
    Available sizes
    '''
    response = list_common_lookups(kwargs={'lookup': 'server.ram'})

    ret = {}
    for item in response['list']:
        name = item['name']
        ret[name] = item

    return ret

Response: Returns a dict of available sizes for the current server.


Instruction:
Create a Python 3 function to
get a list of available images

Response:
def avail_images():
    '''
    Available images
    '''
    response = _query('grid', 'image/list')

    ret = {}
    for item in response['list']:
        name = item['friendlyName']
        ret[name] = item

    return ret


Instruction:
Can you create a Python 3 function that
lists all passwords on the account.

Response:
def list_passwords(kwargs=None, call=None):
    '''
    List all password on the account

    .. versionadded:: 2015.8.0
    '''
    response = _query('support', 'password/list')

    ret = {}
    for item in response['list']:
        if 'server' in item:
            server = item['server']['name']
            if server not in ret:
                ret[server] = []
            ret[server].append(item)

    return ret


Instruction:
Can you write a function in Python 3 where it
lists all available public IPs.

Response:
def list_public_ips(kwargs=None, call=None):
    '''
    List all available public IPs.

    CLI Example:
    .. code-block:: bash

        salt-cloud -f list_public_ips <provider>

    To list unavailable (assigned) IPs, use:

    CLI Example:
    .. code-block:: bash

        salt-cloud -f list_public_ips <provider> state=assigned

    .. versionadded:: 2015.8.0
    '''
    if kwargs is None:
        kwargs = {}

    args = {}
    if 'state' in kwargs:
        if kwargs['state'] == 'assigned':
            args['ip.state'] = 'Assigned'
        else:
            args['ip.state'] = 'Unassigned'
    else:
        args['ip.state'] = 'Unassigned'

    args['ip.type'] = 'Public'

    response = _query('grid', 'ip/list', args=args)

    ret = {}
    for item in response['list']:
        name = item['ip']
        ret[name] = item

    return ret


Instruction:
Explain what the following Python 3 code does
def list_common_lookups(kwargs=None, call=None):
    '''
    List common lookups for a particular type of item

    .. versionadded:: 2015.8.0
    '''
    if kwargs is None:
        kwargs = {}

    args = {}
    if 'lookup' in kwargs:
        args['lookup'] = kwargs['lookup']

    response = _query('common', 'lookup/list', args=args)

    return response

Response: List common lookups for a particular type of item.


Instruction:
Can you generate a brief explanation for the following Python 3 code
def show_instance(name, call=None):
    '''
    Start a machine by name

    CLI Example:

    .. code-block:: bash

        salt-cloud -a show_instance vm_name

    .. versionadded:: 2015.8.0
    '''
    response = _query('grid', 'server/get', args={'name': name})
    ret = {}
    for item in response['list']:
        name = item['name']
        ret[name] = item

        ret[name]['image_info'] = item['image']
        ret[name]['image'] = item['image']['friendlyName']
        ret[name]['size'] = item['ram']['name']
        ret[name]['public_ips'] = [item['ip']['ip']]
        ret[name]['private_ips'] = []
        ret[name]['state_info'] = item['state']
        if 'active' in item['state']['description']:
            ret[name]['state'] = 'RUNNING'
    return ret

Response: Show the details of a single virtual machine by name


Instruction:
Here you have a function in Python 3, explain what it does
def _query(action=None,
           command=None,
           args=None,
           method='GET',
           header_dict=None,
           data=None):
    '''
    Make a web call to GoGrid

    .. versionadded:: 2015.8.0
    '''
    vm_ = get_configured_provider()
    apikey = config.get_cloud_config_value(
        'apikey', vm_, __opts__, search_global=False
    )
    sharedsecret = config.get_cloud_config_value(
        'sharedsecret', vm_, __opts__, search_global=False
    )

    path = 'https://api.gogrid.com/api/'

    if action:
        path += action

    if command:
        path += '/{0}'.format(command)

    log.debug('GoGrid URL: %s', path)

    if not isinstance(args, dict):
        args = {}

    epoch = six.text_type(int(time.time()))
    hashtext = ''.join((apikey, sharedsecret, epoch))
    args['sig'] = salt.utils.hashutils.md5_digest(hashtext)
    args['format'] = 'json'
    args['v'] = '1.0'
    args['api_key'] = apikey

    if header_dict is None:
        header_dict = {}

    if method != 'POST':
        header_dict['Accept'] = 'application/json'

    decode = True
    if method == 'DELETE':
        decode = False

    return_content = None
    result = salt.utils.http.query(
        path,
        method,
        params=args,
        data=data,
        header_dict=header_dict,
        decode=decode,
        decode_type='json',
        text=True,
        status=True,
        opts=__opts__,
    )
    log.debug('GoGrid Response Status Code: %s', result['status'])

    return result['dict']

Response: Make a web call to GoGrid s API


Instruction:
Here you have a function in Python 3, explain what it does
def _parse_key(key):
    '''
    split the hive from the key
    '''
    splt = key.split("\\")
    hive = splt.pop(0)
    key = '\\'.join(splt)
    return hive, key

Response: parse the hive from the key


Instruction:
Can you generate the documentation for the following Python 3 function
def key_absent(name, use_32bit_registry=False):
    r'''
    .. versionadded:: 2015.5.4

    Ensure a registry key is removed. This will remove the key, subkeys, and all
    value entries.

    Args:

        name (str):
            A string representing the full path to the key to be removed to
            include the hive and the keypath. The hive can be any of the
            following:

                - HKEY_LOCAL_MACHINE or HKLM
                - HKEY_CURRENT_USER or HKCU
                - HKEY_USER or HKU

        use_32bit_registry (bool):
            Use the 32bit portion of the registry. Applies only to 64bit
            windows. 32bit Windows will ignore this parameter. Default is False.

    Returns:
        dict: A dictionary showing the results of the registry operation.

    CLI Example:

        The following example will delete the ``SOFTWARE\DeleteMe`` key in the
        ``HKEY_LOCAL_MACHINE`` hive including all its subkeys and value pairs.

        .. code-block:: yaml

            remove_key_demo:
              reg.key_absent:
                - name: HKEY_CURRENT_USER\SOFTWARE\DeleteMe

        In the above example the path is interpreted as follows:

            - ``HKEY_CURRENT_USER`` is the hive
            - ``SOFTWARE\DeleteMe`` is the key
    '''
    ret = {'name': name,
           'result': True,
           'changes': {},
           'comment': ''}

    hive, key = _parse_key(name)

    # Determine what to do
    if not __utils__['reg.read_value'](hive=hive,
                                       key=key,
                                       use_32bit_registry=use_32bit_registry)['success']:
        ret['comment'] = '{0} is already absent'.format(name)
        return ret

    ret['changes'] = {
        'reg': {
            'Removed': {
                'Key': r'{0}\{1}'.format(hive, key)}}}

    # Check for test option
    if __opts__['test']:
        ret['result'] = None
        return ret

    # Delete the value
    __utils__['reg.delete_key_recursive'](hive=hive,
                                          key=key,
                                          use_32bit_registry=use_32bit_registry)
    if __utils__['reg.read_value'](hive=hive,
                                   key=key,
                                   use_32bit_registry=use_32bit_registry)['success']:
        ret['result'] = False
        ret['changes'] = {}
        ret['comment'] = 'Failed to remove registry key {0}'.format(name)

    return ret

Response: r Ensure a key is absent in the registry.


Instruction:
Can you tell what is the following Python 3 function doing
def _get_salt_call(*dirs, **namespaces):
    '''
    Return salt-call source, based on configuration.
    This will include additional namespaces for another versions of Salt,
    if needed (e.g. older interpreters etc).

    :dirs: List of directories to include in the system path
    :namespaces: Dictionary of namespace
    :return:
    '''
    template = '''# -*- coding: utf-8 -*-
import os
import sys

# Namespaces is a map: {namespace: major/minor version}, like {'2016.11.4': [2, 6]}
# Appears only when configured in Master configuration.
namespaces = %namespaces%

# Default system paths alongside the namespaces
syspaths = %dirs%
syspaths.append('py{0}'.format(sys.version_info[0]))

curr_ver = (sys.version_info[0], sys.version_info[1],)

namespace = ''
for ns in namespaces:
    if curr_ver == tuple(namespaces[ns]):
        namespace = ns
        break

for base in syspaths:
    sys.path.insert(0, os.path.join(os.path.dirname(__file__),
                                    namespace and os.path.join(namespace, base) or base))

if __name__ == '__main__':
    from salt.scripts import salt_call
    salt_call()
'''

    for tgt, cnt in [('%dirs%', dirs), ('%namespaces%', namespaces)]:
        template = template.replace(tgt, salt.utils.json.dumps(cnt))

    return salt.utils.stringutils.to_bytes(template)

Response: Return salt - call source based on configuration.


Instruction:
Can you implement a function in Python 3 that
adds a dependency to the top list.

Response:
def _add_dependency(container, obj):
    '''
    Add a dependency to the top list.

    :param obj:
    :param is_file:
    :return:
    '''
    if os.path.basename(obj.__file__).split('.')[0] == '__init__':
        container.append(os.path.dirname(obj.__file__))
    else:
        container.append(obj.__file__.replace('.pyc', '.py'))


Instruction:
Can you create a Python 3 function that
returns the alternative Python interpreter from within _get_tops function.

Response:
def gte():
    '''
    This function is called externally from the alternative
    Python interpreter from within _get_tops function.

    :param extra_mods:
    :param so_mods:
    :return:
    '''
    extra = salt.utils.json.loads(sys.argv[1])
    tops = get_tops(**extra)

    return salt.utils.json.dumps(tops, ensure_ascii=False)


Instruction:
Create a Python 3 function for
getting the top directories for the dependencies based on external configuration.

Response:
def get_ext_tops(config):
    '''
    Get top directories for the dependencies, based on external configuration.

    :return:
    '''
    config = copy.deepcopy(config)
    alternatives = {}
    required = ['jinja2', 'yaml', 'tornado', 'msgpack']
    tops = []
    for ns, cfg in salt.ext.six.iteritems(config or {}):
        alternatives[ns] = cfg
        locked_py_version = cfg.get('py-version')
        err_msg = None
        if not locked_py_version:
            err_msg = 'Alternative Salt library: missing specific locked Python version'
        elif not isinstance(locked_py_version, (tuple, list)):
            err_msg = ('Alternative Salt library: specific locked Python version '
                       'should be a list of major/minor version')
        if err_msg:
            raise salt.exceptions.SaltSystemExit(err_msg)

        if cfg.get('dependencies') == 'inherit':
            # TODO: implement inheritance of the modules from _here_
            raise NotImplementedError('This feature is not yet implemented')
        else:
            for dep in cfg.get('dependencies'):
                mod = cfg['dependencies'][dep] or ''
                if not mod:
                    log.warning('Module %s has missing configuration', dep)
                    continue
                elif mod.endswith('.py') and not os.path.isfile(mod):
                    log.warning('Module %s configured with not a file or does not exist: %s', dep, mod)
                    continue
                elif not mod.endswith('.py') and not os.path.isfile(os.path.join(mod, '__init__.py')):
                    log.warning('Module %s is not a Python importable module with %s', dep, mod)
                    continue
                tops.append(mod)

                if dep in required:
                    required.pop(required.index(dep))

            required = ', '.join(required)
            if required:
                msg = 'Missing dependencies for the alternative version' \
                      ' in the external configuration: {}'.format(required)
                log.error(msg)
                raise salt.exceptions.SaltSystemExit(msg)
        alternatives[ns]['dependencies'] = tops
    return alternatives


Instruction:
Given the following Python 3 function, write the documentation
def _get_ext_namespaces(config):
    '''
    Get namespaces from the existing configuration.

    :param config:
    :return:
    '''
    namespaces = {}
    if not config:
        return namespaces

    for ns in config:
        constraint_version = tuple(config[ns].get('py-version', []))
        if not constraint_version:
            raise salt.exceptions.SaltSystemExit("An alternative version is configured, but not defined "
                                                 "to what Python's major/minor version it should be constrained.")
        else:
            namespaces[ns] = constraint_version

    return namespaces

Response: Get the namespaces from the existing configuration.


Instruction:
Can you tell what is the following Python 3 function doing
def get_tops(extra_mods='', so_mods=''):
    '''
    Get top directories for the dependencies, based on Python interpreter.

    :param extra_mods:
    :param so_mods:
    :return:
    '''
    tops = []
    for mod in [salt, jinja2, yaml, tornado, msgpack, certifi, singledispatch, concurrent,
                singledispatch_helpers, ssl_match_hostname, markupsafe, backports_abc]:
        if mod:
            log.debug('Adding module to the tops: "%s"', mod.__name__)
            _add_dependency(tops, mod)

    for mod in [m for m in extra_mods.split(',') if m]:
        if mod not in locals() and mod not in globals():
            try:
                locals()[mod] = __import__(mod)
                moddir, modname = os.path.split(locals()[mod].__file__)
                base, _ = os.path.splitext(modname)
                if base == '__init__':
                    tops.append(moddir)
                else:
                    tops.append(os.path.join(moddir, base + '.py'))
            except ImportError as err:
                log.exception(err)
                log.error('Unable to import extra-module "%s"', mod)

    for mod in [m for m in so_mods.split(',') if m]:
        try:
            locals()[mod] = __import__(mod)
            tops.append(locals()[mod].__file__)
        except ImportError as err:
            log.exception(err)
            log.error('Unable to import so-module "%s"', mod)

    return tops

Response: Get the top directories for the dependencies based on Python interpreter.


Instruction:
Can you tell what is the following Python 3 function doing
def _get_supported_py_config(tops, extended_cfg):
    '''
    Based on the Salt SSH configuration, create a YAML configuration
    for the supported Python interpreter versions. This is then written into the thin.tgz
    archive and then verified by salt.client.ssh.ssh_py_shim.get_executable()

    Note: Minimum default of 2.x versions is 2.7 and 3.x is 3.0, unless specified in namespaces.

    :return:
    '''
    pymap = []
    for py_ver, tops in _six.iteritems(copy.deepcopy(tops)):
        py_ver = int(py_ver)
        if py_ver == 2:
            pymap.append('py2:2:7')
        elif py_ver == 3:
            pymap.append('py3:3:0')

    for ns, cfg in _six.iteritems(copy.deepcopy(extended_cfg) or {}):
        pymap.append('{}:{}:{}'.format(ns, *cfg.get('py-version')))
    pymap.append('')

    return salt.utils.stringutils.to_bytes(os.linesep.join(pymap))

Response: Create a YAML configuration for the supported Python interpreter versions.


Instruction:
Implement a function in Python 3 to
return the tarball name prefixed with. thin -.

Response:
def _get_thintar_prefix(tarname):
    '''
    Make sure thintar temporary name is concurrent and secure.

    :param tarname: name of the chosen tarball
    :return: prefixed tarname
    '''
    tfd, tmp_tarname = tempfile.mkstemp(dir=os.path.dirname(tarname), prefix=".thin-",
                                        suffix="." + os.path.basename(tarname).split(".", 1)[-1])
    os.close(tfd)

    return tmp_tarname


Instruction:
Explain what the following Python 3 code does
def gen_thin(cachedir, extra_mods='', overwrite=False, so_mods='',
             python2_bin='python2', python3_bin='python3', absonly=True,
             compress='gzip', extended_cfg=None):
    '''
    Generate the salt-thin tarball and print the location of the tarball
    Optional additional mods to include (e.g. mako) can be supplied as a comma
    delimited string.  Permits forcing an overwrite of the output file as well.

    CLI Example:

    .. code-block:: bash

        salt-run thin.generate
        salt-run thin.generate mako
        salt-run thin.generate mako,wempy 1
        salt-run thin.generate overwrite=1
    '''
    if sys.version_info < (2, 6):
        raise salt.exceptions.SaltSystemExit('The minimum required python version to run salt-ssh is "2.6".')
    if compress not in ['gzip', 'zip']:
        log.warning('Unknown compression type: "%s". Falling back to "gzip" compression.', compress)
        compress = 'gzip'

    thindir = os.path.join(cachedir, 'thin')
    if not os.path.isdir(thindir):
        os.makedirs(thindir)
    thintar = os.path.join(thindir, 'thin.' + (compress == 'gzip' and 'tgz' or 'zip'))
    thinver = os.path.join(thindir, 'version')
    pythinver = os.path.join(thindir, '.thin-gen-py-version')
    salt_call = os.path.join(thindir, 'salt-call')
    pymap_cfg = os.path.join(thindir, 'supported-versions')
    code_checksum = os.path.join(thindir, 'code-checksum')
    digest_collector = salt.utils.hashutils.DigestCollector()

    with salt.utils.files.fopen(salt_call, 'wb') as fp_:
        fp_.write(_get_salt_call('pyall', **_get_ext_namespaces(extended_cfg)))

    if os.path.isfile(thintar):
        if not overwrite:
            if os.path.isfile(thinver):
                with salt.utils.files.fopen(thinver) as fh_:
                    overwrite = fh_.read() != salt.version.__version__
                if overwrite is False and os.path.isfile(pythinver):
                    with salt.utils.files.fopen(pythinver) as fh_:
                        overwrite = fh_.read() != str(sys.version_info[0])  # future lint: disable=blacklisted-function
            else:
                overwrite = True

        if overwrite:
            try:
                log.debug('Removing %s archive file', thintar)
                os.remove(thintar)
            except OSError as exc:
                log.error('Error while removing %s file: %s', thintar, exc)
                if os.path.exists(thintar):
                    raise salt.exceptions.SaltSystemExit(
                        'Unable to remove {0}. See logs for details.'.format(thintar)
                    )
        else:
            return thintar
    if _six.PY3:
        # Let's check for the minimum python 2 version requirement, 2.6
        py_shell_cmd = "{} -c 'import sys;sys.stdout.write(\"%s.%s\\n\" % sys.version_info[:2]);'".format(python2_bin)
        cmd = subprocess.Popen(py_shell_cmd, stdout=subprocess.PIPE, shell=True)
        stdout, _ = cmd.communicate()
        if cmd.returncode == 0:
            py2_version = tuple(int(n) for n in stdout.decode('utf-8').strip().split('.'))
            if py2_version < (2, 6):
                raise salt.exceptions.SaltSystemExit(
                    'The minimum required python version to run salt-ssh is "2.6".'
                    'The version reported by "{0}" is "{1}". Please try "salt-ssh '
                    '--python2-bin=<path-to-python-2.6-binary-or-higher>".'.format(python2_bin, stdout.strip()))
        else:
            log.error('Unable to detect Python-2 version')
            log.debug(stdout)

    tops_failure_msg = 'Failed %s tops for Python binary %s.'
    tops_py_version_mapping = {}
    tops = get_tops(extra_mods=extra_mods, so_mods=so_mods)
    tops_py_version_mapping[sys.version_info.major] = tops

    # Collect tops, alternative to 2.x version
    if _six.PY2 and sys.version_info.major == 2:
        # Get python 3 tops
        py_shell_cmd = "{0} -c 'import salt.utils.thin as t;print(t.gte())' '{1}'".format(
            python3_bin, salt.utils.json.dumps({'extra_mods': extra_mods, 'so_mods': so_mods}))
        cmd = subprocess.Popen(py_shell_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
        stdout, stderr = cmd.communicate()
        if cmd.returncode == 0:
            try:
                tops = salt.utils.json.loads(stdout)
                tops_py_version_mapping['3'] = tops
            except ValueError as err:
                log.error(tops_failure_msg, 'parsing', python3_bin)
                log.exception(err)
        else:
            log.error(tops_failure_msg, 'collecting', python3_bin)
            log.debug(stderr)

    # Collect tops, alternative to 3.x version
    if _six.PY3 and sys.version_info.major == 3:
        # Get python 2 tops
        py_shell_cmd = "{0} -c 'import salt.utils.thin as t;print(t.gte())' '{1}'".format(
            python2_bin, salt.utils.json.dumps({'extra_mods': extra_mods, 'so_mods': so_mods}))
        cmd = subprocess.Popen(py_shell_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
        stdout, stderr = cmd.communicate()
        if cmd.returncode == 0:
            try:
                tops = salt.utils.json.loads(stdout.decode('utf-8'))
                tops_py_version_mapping['2'] = tops
            except ValueError as err:
                log.error(tops_failure_msg, 'parsing', python2_bin)
                log.exception(err)
        else:
            log.error(tops_failure_msg, 'collecting', python2_bin)
            log.debug(stderr)

    with salt.utils.files.fopen(pymap_cfg, 'wb') as fp_:
        fp_.write(_get_supported_py_config(tops=tops_py_version_mapping, extended_cfg=extended_cfg))

    tmp_thintar = _get_thintar_prefix(thintar)
    if compress == 'gzip':
        tfp = tarfile.open(tmp_thintar, 'w:gz', dereference=True)
    elif compress == 'zip':
        tfp = zipfile.ZipFile(tmp_thintar, 'w', compression=zlib and zipfile.ZIP_DEFLATED or zipfile.ZIP_STORED)
        tfp.add = tfp.write

    try:  # cwd may not exist if it was removed but salt was run from it
        start_dir = os.getcwd()
    except OSError:
        start_dir = None
    tempdir = None

    # Pack default data
    log.debug('Packing default libraries based on current Salt version')
    for py_ver, tops in _six.iteritems(tops_py_version_mapping):
        for top in tops:
            if absonly and not os.path.isabs(top):
                continue
            base = os.path.basename(top)
            top_dirname = os.path.dirname(top)
            if os.path.isdir(top_dirname):
                os.chdir(top_dirname)
            else:
                # This is likely a compressed python .egg
                tempdir = tempfile.mkdtemp()
                egg = zipfile.ZipFile(top_dirname)
                egg.extractall(tempdir)
                top = os.path.join(tempdir, base)
                os.chdir(tempdir)

            site_pkg_dir = _is_shareable(base) and 'pyall' or 'py{}'.format(py_ver)

            log.debug('Packing "%s" to "%s" destination', base, site_pkg_dir)
            if not os.path.isdir(top):
                # top is a single file module
                if os.path.exists(os.path.join(top_dirname, base)):
                    tfp.add(base, arcname=os.path.join(site_pkg_dir, base))
                continue
            for root, dirs, files in salt.utils.path.os_walk(base, followlinks=True):
                for name in files:
                    if not name.endswith(('.pyc', '.pyo')):
                        digest_collector.add(os.path.join(root, name))
                        arcname = os.path.join(site_pkg_dir, root, name)
                        if hasattr(tfp, 'getinfo'):
                            try:
                                # This is a little slow but there's no clear way to detect duplicates
                                tfp.getinfo(os.path.join(site_pkg_dir, root, name))
                                arcname = None
                            except KeyError:
                                log.debug('ZIP: Unable to add "%s" with "getinfo"', arcname)
                        if arcname:
                            tfp.add(os.path.join(root, name), arcname=arcname)

            if tempdir is not None:
                shutil.rmtree(tempdir)
                tempdir = None

    # Pack alternative data
    if extended_cfg:
        log.debug('Packing libraries based on alternative Salt versions')
    for ns, cfg in _six.iteritems(get_ext_tops(extended_cfg)):
        tops = [cfg.get('path')] + cfg.get('dependencies')
        py_ver_major, py_ver_minor = cfg.get('py-version')
        for top in tops:
            base, top_dirname = os.path.basename(top), os.path.dirname(top)
            os.chdir(top_dirname)
            site_pkg_dir = _is_shareable(base) and 'pyall' or 'py{0}'.format(py_ver_major)
            log.debug('Packing alternative "%s" to "%s/%s" destination', base, ns, site_pkg_dir)
            if not os.path.isdir(top):
                # top is a single file module
                if os.path.exists(os.path.join(top_dirname, base)):
                    tfp.add(base, arcname=os.path.join(ns, site_pkg_dir, base))
                continue
            for root, dirs, files in salt.utils.path.os_walk(base, followlinks=True):
                for name in files:
                    if not name.endswith(('.pyc', '.pyo')):
                        digest_collector.add(os.path.join(root, name))
                        arcname = os.path.join(ns, site_pkg_dir, root, name)
                        if hasattr(tfp, 'getinfo'):
                            try:
                                tfp.getinfo(os.path.join(site_pkg_dir, root, name))
                                arcname = None
                            except KeyError:
                                log.debug('ZIP: Unable to add "%s" with "getinfo"', arcname)
                        if arcname:
                            tfp.add(os.path.join(root, name), arcname=arcname)

    os.chdir(thindir)
    with salt.utils.files.fopen(thinver, 'w+') as fp_:
        fp_.write(salt.version.__version__)
    with salt.utils.files.fopen(pythinver, 'w+') as fp_:
        fp_.write(str(sys.version_info.major))  # future lint: disable=blacklisted-function
    with salt.utils.files.fopen(code_checksum, 'w+') as fp_:
        fp_.write(digest_collector.digest())
    os.chdir(os.path.dirname(thinver))

    for fname in ['version', '.thin-gen-py-version', 'salt-call', 'supported-versions', 'code-checksum']:
        tfp.add(fname)

    if start_dir:
        os.chdir(start_dir)
    tfp.close()

    shutil.move(tmp_thintar, thintar)

    return thintar

Response: Generate a salt - thin tarball and print the location of the tarball.


Instruction:
Can you generate the documentation for the following Python 3 function
def thin_sum(cachedir, form='sha1'):
    '''
    Return the checksum of the current thin tarball
    '''
    thintar = gen_thin(cachedir)
    code_checksum_path = os.path.join(cachedir, 'thin', 'code-checksum')
    if os.path.isfile(code_checksum_path):
        with salt.utils.files.fopen(code_checksum_path, 'r') as fh:
            code_checksum = "'{0}'".format(fh.read().strip())
    else:
        code_checksum = "'0'"

    return code_checksum, salt.utils.hashutils.get_hash(thintar, form)

Response: Return the checksum of the current thin tarball


Instruction:
Write a Python 3 function that can
generate the salt - min tarball and print the location of the tarball.

Response:
def gen_min(cachedir, extra_mods='', overwrite=False, so_mods='',
            python2_bin='python2', python3_bin='python3'):
    '''
    Generate the salt-min tarball and print the location of the tarball
    Optional additional mods to include (e.g. mako) can be supplied as a comma
    delimited string.  Permits forcing an overwrite of the output file as well.

    CLI Example:

    .. code-block:: bash

        salt-run min.generate
        salt-run min.generate mako
        salt-run min.generate mako,wempy 1
        salt-run min.generate overwrite=1
    '''
    mindir = os.path.join(cachedir, 'min')
    if not os.path.isdir(mindir):
        os.makedirs(mindir)
    mintar = os.path.join(mindir, 'min.tgz')
    minver = os.path.join(mindir, 'version')
    pyminver = os.path.join(mindir, '.min-gen-py-version')
    salt_call = os.path.join(mindir, 'salt-call')
    with salt.utils.files.fopen(salt_call, 'wb') as fp_:
        fp_.write(_get_salt_call())
    if os.path.isfile(mintar):
        if not overwrite:
            if os.path.isfile(minver):
                with salt.utils.files.fopen(minver) as fh_:
                    overwrite = fh_.read() != salt.version.__version__
                if overwrite is False and os.path.isfile(pyminver):
                    with salt.utils.files.fopen(pyminver) as fh_:
                        overwrite = fh_.read() != str(sys.version_info[0])  # future lint: disable=blacklisted-function
            else:
                overwrite = True

        if overwrite:
            try:
                os.remove(mintar)
            except OSError:
                pass
        else:
            return mintar
    if _six.PY3:
        # Let's check for the minimum python 2 version requirement, 2.6
        py_shell_cmd = (
            python2_bin + ' -c \'from __future__ import print_function; import sys; '
            'print("{0}.{1}".format(*(sys.version_info[:2])));\''
        )
        cmd = subprocess.Popen(py_shell_cmd, stdout=subprocess.PIPE, shell=True)
        stdout, _ = cmd.communicate()
        if cmd.returncode == 0:
            py2_version = tuple(int(n) for n in stdout.decode('utf-8').strip().split('.'))
            if py2_version < (2, 6):
                # Bail!
                raise salt.exceptions.SaltSystemExit(
                    'The minimum required python version to run salt-ssh is "2.6".'
                    'The version reported by "{0}" is "{1}". Please try "salt-ssh '
                    '--python2-bin=<path-to-python-2.6-binary-or-higher>".'.format(python2_bin,
                                                                                stdout.strip())
                )
    elif sys.version_info < (2, 6):
        # Bail! Though, how did we reached this far in the first place.
        raise salt.exceptions.SaltSystemExit(
            'The minimum required python version to run salt-ssh is "2.6".'
        )

    tops_py_version_mapping = {}
    tops = get_tops(extra_mods=extra_mods, so_mods=so_mods)
    if _six.PY2:
        tops_py_version_mapping['2'] = tops
    else:
        tops_py_version_mapping['3'] = tops

    # TODO: Consider putting known py2 and py3 compatible libs in it's own sharable directory.
    #       This would reduce the min size.
    if _six.PY2 and sys.version_info[0] == 2:
        # Get python 3 tops
        py_shell_cmd = (
            python3_bin + ' -c \'import sys; import json; import salt.utils.thin; '
            'print(json.dumps(salt.utils.thin.get_tops(**(json.loads(sys.argv[1]))), ensure_ascii=False)); exit(0);\' '
            '\'{0}\''.format(salt.utils.json.dumps({'extra_mods': extra_mods, 'so_mods': so_mods}))
        )
        cmd = subprocess.Popen(py_shell_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
        stdout, stderr = cmd.communicate()
        if cmd.returncode == 0:
            try:
                tops = salt.utils.json.loads(stdout)
                tops_py_version_mapping['3'] = tops
            except ValueError:
                pass
    if _six.PY3 and sys.version_info[0] == 3:
        # Get python 2 tops
        py_shell_cmd = (
            python2_bin + ' -c \'from __future__ import print_function; '
            'import sys; import json; import salt.utils.thin; '
            'print(json.dumps(salt.utils.thin.get_tops(**(json.loads(sys.argv[1]))), ensure_ascii=False)); exit(0);\' '
            '\'{0}\''.format(salt.utils.json.dumps({'extra_mods': extra_mods, 'so_mods': so_mods}))
        )
        cmd = subprocess.Popen(py_shell_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
        stdout, stderr = cmd.communicate()
        if cmd.returncode == 0:
            try:
                tops = salt.utils.json.loads(stdout.decode('utf-8'))
                tops_py_version_mapping['2'] = tops
            except ValueError:
                pass

    tfp = tarfile.open(mintar, 'w:gz', dereference=True)
    try:  # cwd may not exist if it was removed but salt was run from it
        start_dir = os.getcwd()
    except OSError:
        start_dir = None
    tempdir = None

    # This is the absolute minimum set of files required to run salt-call
    min_files = (
        'salt/__init__.py',
        'salt/utils',
        'salt/utils/__init__.py',
        'salt/utils/atomicfile.py',
        'salt/utils/validate',
        'salt/utils/validate/__init__.py',
        'salt/utils/validate/path.py',
        'salt/utils/decorators',
        'salt/utils/decorators/__init__.py',
        'salt/utils/cache.py',
        'salt/utils/xdg.py',
        'salt/utils/odict.py',
        'salt/utils/minions.py',
        'salt/utils/dicttrim.py',
        'salt/utils/sdb.py',
        'salt/utils/migrations.py',
        'salt/utils/files.py',
        'salt/utils/parsers.py',
        'salt/utils/locales.py',
        'salt/utils/lazy.py',
        'salt/utils/s3.py',
        'salt/utils/dictupdate.py',
        'salt/utils/verify.py',
        'salt/utils/args.py',
        'salt/utils/kinds.py',
        'salt/utils/xmlutil.py',
        'salt/utils/debug.py',
        'salt/utils/jid.py',
        'salt/utils/openstack',
        'salt/utils/openstack/__init__.py',
        'salt/utils/openstack/swift.py',
        'salt/utils/asynchronous.py',
        'salt/utils/process.py',
        'salt/utils/jinja.py',
        'salt/utils/rsax931.py',
        'salt/utils/context.py',
        'salt/utils/minion.py',
        'salt/utils/error.py',
        'salt/utils/aws.py',
        'salt/utils/timed_subprocess.py',
        'salt/utils/zeromq.py',
        'salt/utils/schedule.py',
        'salt/utils/url.py',
        'salt/utils/yamlencoding.py',
        'salt/utils/network.py',
        'salt/utils/http.py',
        'salt/utils/gzip_util.py',
        'salt/utils/vt.py',
        'salt/utils/templates.py',
        'salt/utils/aggregation.py',
        'salt/utils/yaml.py',
        'salt/utils/yamldumper.py',
        'salt/utils/yamlloader.py',
        'salt/utils/event.py',
        'salt/utils/state.py',
        'salt/serializers',
        'salt/serializers/__init__.py',
        'salt/serializers/yamlex.py',
        'salt/template.py',
        'salt/_compat.py',
        'salt/loader.py',
        'salt/client',
        'salt/client/__init__.py',
        'salt/ext',
        'salt/ext/__init__.py',
        'salt/ext/six.py',
        'salt/ext/ipaddress.py',
        'salt/version.py',
        'salt/syspaths.py',
        'salt/defaults',
        'salt/defaults/__init__.py',
        'salt/defaults/exitcodes.py',
        'salt/renderers',
        'salt/renderers/__init__.py',
        'salt/renderers/jinja.py',
        'salt/renderers/yaml.py',
        'salt/modules',
        'salt/modules/__init__.py',
        'salt/modules/test.py',
        'salt/modules/selinux.py',
        'salt/modules/cmdmod.py',
        'salt/modules/saltutil.py',
        'salt/minion.py',
        'salt/pillar',
        'salt/pillar/__init__.py',
        'salt/textformat.py',
        'salt/log',
        'salt/log/__init__.py',
        'salt/log/handlers',
        'salt/log/handlers/__init__.py',
        'salt/log/mixins.py',
        'salt/log/setup.py',
        'salt/cli',
        'salt/cli/__init__.py',
        'salt/cli/caller.py',
        'salt/cli/daemons.py',
        'salt/cli/salt.py',
        'salt/cli/call.py',
        'salt/fileserver',
        'salt/fileserver/__init__.py',
        'salt/transport',
        'salt/transport/__init__.py',
        'salt/transport/client.py',
        'salt/exceptions.py',
        'salt/grains',
        'salt/grains/__init__.py',
        'salt/grains/extra.py',
        'salt/scripts.py',
        'salt/state.py',
        'salt/fileclient.py',
        'salt/crypt.py',
        'salt/config.py',
        'salt/beacons',
        'salt/beacons/__init__.py',
        'salt/payload.py',
        'salt/output',
        'salt/output/__init__.py',
        'salt/output/nested.py',
    )

    for py_ver, tops in _six.iteritems(tops_py_version_mapping):
        for top in tops:
            base = os.path.basename(top)
            top_dirname = os.path.dirname(top)
            if os.path.isdir(top_dirname):
                os.chdir(top_dirname)
            else:
                # This is likely a compressed python .egg
                tempdir = tempfile.mkdtemp()
                egg = zipfile.ZipFile(top_dirname)
                egg.extractall(tempdir)
                top = os.path.join(tempdir, base)
                os.chdir(tempdir)
            if not os.path.isdir(top):
                # top is a single file module
                tfp.add(base, arcname=os.path.join('py{0}'.format(py_ver), base))
                continue
            for root, dirs, files in salt.utils.path.os_walk(base, followlinks=True):
                for name in files:
                    if name.endswith(('.pyc', '.pyo')):
                        continue
                    if root.startswith('salt') and os.path.join(root, name) not in min_files:
                        continue
                    tfp.add(os.path.join(root, name),
                            arcname=os.path.join('py{0}'.format(py_ver), root, name))
            if tempdir is not None:
                shutil.rmtree(tempdir)
                tempdir = None

    os.chdir(mindir)
    tfp.add('salt-call')
    with salt.utils.files.fopen(minver, 'w+') as fp_:
        fp_.write(salt.version.__version__)
    with salt.utils.files.fopen(pyminver, 'w+') as fp_:
        fp_.write(str(sys.version_info[0]))  # future lint: disable=blacklisted-function
    os.chdir(os.path.dirname(minver))
    tfp.add('version')
    tfp.add('.min-gen-py-version')
    if start_dir:
        os.chdir(start_dir)
    tfp.close()
    return mintar


Instruction:
Can you generate a brief explanation for the following Python 3 code
def min_sum(cachedir, form='sha1'):
    '''
    Return the checksum of the current thin tarball
    '''
    mintar = gen_min(cachedir)
    return salt.utils.hashutils.get_hash(mintar, form)

Response: Return the checksum of the current thin tarball


Instruction:
How would you implement a function in Python 3 that
refreshes the remote repos database.

Response:
def refresh_db(full=False, **kwargs):
    '''
    Updates the remote repos database.

    full : False

        Set to ``True`` to force a refresh of the pkg DB from all publishers,
        regardless of the last refresh time.

    CLI Example:

    .. code-block:: bash

        salt '*' pkg.refresh_db
        salt '*' pkg.refresh_db full=True
    '''
    # Remove rtag file to keep multiple refreshes from happening in pkg states
    salt.utils.pkg.clear_rtag(__opts__)
    if full:
        return __salt__['cmd.retcode']('/bin/pkg refresh --full') == 0
    else:
        return __salt__['cmd.retcode']('/bin/pkg refresh') == 0


Instruction:
Here you have a function in Python 3, explain what it does
def upgrade_available(name, **kwargs):
    '''
    Check if there is an upgrade available for a certain package
    Accepts full or partial FMRI. Returns all matches found.

    CLI Example:

    .. code-block:: bash

        salt '*' pkg.upgrade_available apache-22
    '''
    version = None
    cmd = ['pkg', 'list', '-Huv', name]
    lines = __salt__['cmd.run_stdout'](cmd).splitlines()
    if not lines:
        return {}
    ret = {}
    for line in lines:
        ret[_ips_get_pkgname(line)] = _ips_get_pkgversion(line)
    return ret

Response: Check if there is an upgrade available for a certain package. Returns all matches found


Instruction:
Can you generate the documentation for the following Python 3 function
def list_upgrades(refresh=True, **kwargs):  # pylint: disable=W0613
    '''
    Lists all packages available for update.

    When run in global zone, it reports only upgradable packages for the global
    zone.

    When run in non-global zone, it can report more upgradable packages than
    ``pkg update -vn``, because ``pkg update`` hides packages that require
    newer version of ``pkg://solaris/entire`` (which means that they can be
    upgraded only from the global zone). If ``pkg://solaris/entire`` is found
    in the list of upgrades, then the global zone should be updated to get all
    possible updates. Use ``refresh=True`` to refresh the package database.

    refresh : True
        Runs a full package database refresh before listing. Set to ``False`` to
        disable running the refresh.

        .. versionchanged:: 2017.7.0

        In previous versions of Salt, ``refresh`` defaulted to ``False``. This was
        changed to default to ``True`` in the 2017.7.0 release to make the behavior
        more consistent with the other package modules, which all default to ``True``.

    CLI Example:

    .. code-block:: bash

        salt '*' pkg.list_upgrades
        salt '*' pkg.list_upgrades refresh=False
    '''
    if salt.utils.data.is_true(refresh):
        refresh_db(full=True)
    upgrades = {}
    # awk is in core-os package so we can use it without checking
    lines = __salt__['cmd.run_stdout']("/bin/pkg list -Huv").splitlines()
    for line in lines:
        upgrades[_ips_get_pkgname(line)] = _ips_get_pkgversion(line)
    return upgrades

Response: List all packages available for update.


Instruction:
Can you tell what is the following Python 3 function doing
def upgrade(refresh=False, **kwargs):
    '''
    Upgrade all packages to the latest possible version.
    When run in global zone, it updates also all non-global zones.
    In non-global zones upgrade is limited by dependency constrains linked to
    the version of pkg://solaris/entire.

    Returns a dictionary containing the changes:

    .. code-block:: python

        {'<package>':  {'old': '<old-version>',
                        'new': '<new-version>'}}

    When there is a failure, an explanation is also included in the error
    message, based on the return code of the ``pkg update`` command.

    CLI Example:

    .. code-block:: bash

        salt '*' pkg.upgrade
    '''
    if salt.utils.data.is_true(refresh):
        refresh_db()

    # Get a list of the packages before install so we can diff after to see
    # what got installed.
    old = list_pkgs()

    # Install or upgrade the package
    # If package is already installed
    cmd = ['pkg', 'update', '-v', '--accept']
    result = __salt__['cmd.run_all'](cmd,
                                     output_loglevel='trace',
                                     python_shell=False)
    __context__.pop('pkg.list_pkgs', None)
    new = list_pkgs()
    ret = salt.utils.data.compare_dicts(old, new)

    if result['retcode'] != 0:
        raise CommandExecutionError(
            'Problem encountered upgrading packages',
            info={'changes': ret,
                  'retcode': ips_pkg_return_values[result['retcode']],
                  'result': result}
        )

    return ret

Response: Upgrade all packages to the latest possible version.


Instruction:
Create a Python 3 function to
list the currently installed packages as a dict.

Response:
def list_pkgs(versions_as_list=False, **kwargs):
    '''
    List the currently installed packages as a dict::

        {'<package_name>': '<version>'}

    CLI Example:

    .. code-block:: bash

        salt '*' pkg.list_pkgs
    '''
    # not yet implemented or not applicable
    if any([salt.utils.data.is_true(kwargs.get(x))
        for x in ('removed', 'purge_desired')]):
        return {}

    if 'pkg.list_pkgs' in __context__:
        if versions_as_list:
            return __context__['pkg.list_pkgs']
        else:
            ret = copy.deepcopy(__context__['pkg.list_pkgs'])
            __salt__['pkg_resource.stringify'](ret)
            return ret

    ret = {}
    cmd = '/bin/pkg list -Hv'
    lines = __salt__['cmd.run_stdout'](cmd).splitlines()
    # column 1 is full FMRI name in form pkg://publisher/class/name@version
    for line in lines:
        name = _ips_get_pkgname(line)
        version = _ips_get_pkgversion(line)
        __salt__['pkg_resource.add_pkg'](ret, name, version)

    __salt__['pkg_resource.sort_pkglist'](ret)
    __context__['pkg.list_pkgs'] = copy.deepcopy(ret)
    if not versions_as_list:
        __salt__['pkg_resource.stringify'](ret)
    return ret


Instruction:
Can you create a Python 3 function that
returns the version of the specified packages.

Response:
def version(*names, **kwargs):
    '''
    Common interface for obtaining the version of installed packages.
    Accepts full or partial FMRI. If called using pkg_resource, full FMRI is required.
    Partial FMRI is returned if the package is not installed.

    CLI Example:

    .. code-block:: bash

        salt '*' pkg.version vim
        salt '*' pkg.version foo bar baz
        salt '*' pkg_resource.version pkg://solaris/entire

    '''
    if not names:
        return ''

    cmd = ['/bin/pkg', 'list', '-Hv']
    cmd.extend(names)
    lines = __salt__['cmd.run_stdout'](cmd, ignore_retcode=True).splitlines()
    ret = {}
    for line in lines:
        ret[_ips_get_pkgname(line)] = _ips_get_pkgversion(line)

    # Append package names which are not installed/found
    unmatched = list([name for name in names if not reduce(lambda x, y: x or name in y, ret, False)])  # pylint: disable=W0640
    ret.update(zip(unmatched, itertools.cycle(('',))))

    # Return a string if only one package name passed
    if len(names) == 1:
        try:
            return next(six.itervalues(ret))
        except StopIteration:
            return ''

    return ret


Instruction:
How would you explain what the following Python 3 function does
def get_fmri(name, **kwargs):
    '''
    Returns FMRI from partial name. Returns empty string ('') if not found.
    In case of multiple match, the function returns list of all matched packages.

    CLI Example:

    .. code-block:: bash

        salt '*' pkg.get_fmri bash
    '''
    if name.startswith('pkg://'):
        # already full fmri
        return name
    cmd = ['/bin/pkg', 'list', '-aHv', name]
    # there can be more packages matching the name
    lines = __salt__['cmd.run_stdout'](cmd).splitlines()
    if not lines:
        # empty string = package not found
        return ''
    ret = []
    for line in lines:
        ret.append(_ips_get_pkgname(line))

    return ret

Response: Returns FMRI from partial name.


Instruction:
Implement a function in Python 3 to
normalize pkg name to full FMRI before running it.

Response:
def normalize_name(name, **kwargs):
    '''
    Internal function. Normalizes pkg name to full FMRI before running
    pkg.install. In case of multiple matches or no match, it returns the name
    without modifications.

    CLI Example:

    .. code-block:: bash

        salt '*' pkg.normalize_name vim
    '''
    if name.startswith('pkg://'):
        # already full fmri
        return name
    cmd = ['/bin/pkg', 'list', '-aHv', name]
    # there can be more packages matching the name
    lines = __salt__['cmd.run_stdout'](cmd).splitlines()
    # if we get more lines, it's multiple match (name not unique)
    # if we get zero lines, pkg is not installed
    # in both ways it's safer to return original (unmodified) name and let "pkg install" to deal with it
    if len(lines) != 1:
        return name
    # return pkg name
    return _ips_get_pkgname(lines[0])


Instruction:
Write a Python 3 function that can
search the repository for a given pkg name.

Response:
def search(name, versions_as_list=False, **kwargs):
    '''
    Searches the repository for given pkg name.
    The name can be full or partial FMRI. All matches are printed. Globs are
    also supported.

    CLI Example:

    .. code-block:: bash

        salt '*' pkg.search bash
    '''

    ret = {}
    cmd = ['/bin/pkg', 'list', '-aHv', name]
    out = __salt__['cmd.run_all'](cmd, ignore_retcode=True)
    if out['retcode'] != 0:
        # error = nothing found
        return {}
    # no error, processing pkg listing
    # column 1 is full FMRI name in form pkg://publisher/pkg/name@version
    for line in out['stdout'].splitlines():
        name = _ips_get_pkgname(line)
        version = _ips_get_pkgversion(line)
        __salt__['pkg_resource.add_pkg'](ret, name, version)

    if not versions_as_list:
        __salt__['pkg_resource.stringify'](ret)
    return ret


Instruction:
Create a Python 3 function for
installing a named package using the IPS pkg command.

Response:
def install(name=None, refresh=False, pkgs=None, version=None, test=False, **kwargs):
    '''
    Install the named package using the IPS pkg command.
    Accepts full or partial FMRI.

    Returns a dict containing the new package names and versions::

        {'<package>': {'old': '<old-version>',
                       'new': '<new-version>'}}

    Multiple Package Installation Options:

    pkgs
        A list of packages to install. Must be passed as a python list.

    CLI Example:

    .. code-block:: bash

        salt '*' pkg.install vim
        salt '*' pkg.install pkg://solaris/editor/vim
        salt '*' pkg.install pkg://solaris/editor/vim refresh=True
        salt '*' pkg.install pkgs='["foo", "bar"]'
    '''
    if not pkgs:
        if is_installed(name):
            return {}

    if refresh:
        refresh_db(full=True)

    pkg2inst = ''
    if pkgs:    # multiple packages specified
        pkg2inst = []
        for pkg in pkgs:
            if getattr(pkg, 'items', False):
                if list(pkg.items())[0][1]:   # version specified
                    pkg2inst.append('{0}@{1}'.format(list(pkg.items())[0][0],
                                                     list(pkg.items())[0][1]))
                else:
                    pkg2inst.append(list(pkg.items())[0][0])
            else:
                pkg2inst.append("{0}".format(pkg))
        log.debug('Installing these packages instead of %s: %s',
                  name, pkg2inst)

    else:   # install single package
        if version:
            pkg2inst = "{0}@{1}".format(name, version)
        else:
            pkg2inst = "{0}".format(name)

    cmd = ['pkg', 'install', '-v', '--accept']
    if test:
        cmd.append('-n')

    # Get a list of the packages before install so we can diff after to see
    # what got installed.
    old = list_pkgs()

    # Install or upgrade the package
    # If package is already installed
    if isinstance(pkg2inst, string_types):
        cmd.append(pkg2inst)
    elif isinstance(pkg2inst, list):
        cmd = cmd + pkg2inst

    out = __salt__['cmd.run_all'](cmd, output_loglevel='trace')

    # Get a list of the packages again, including newly installed ones.
    __context__.pop('pkg.list_pkgs', None)
    new = list_pkgs()
    ret = salt.utils.data.compare_dicts(old, new)

    if out['retcode'] != 0:
        raise CommandExecutionError(
            'Error occurred installing package(s)',
            info={
                'changes': ret,
                'retcode': ips_pkg_return_values[out['retcode']],
                'errors': [out['stderr']]
            }
        )

    # No error occurred
    if test:
        return 'Test succeeded.'

    return ret


Instruction:
How would you implement a function in Python 3 that
removes a package from the system.

Response:
def remove(name=None, pkgs=None, **kwargs):
    '''
    Remove specified package. Accepts full or partial FMRI.
    In case of multiple match, the command fails and won't modify the OS.

    name
        The name of the package to be deleted.

    Multiple Package Options:

    pkgs
        A list of packages to delete. Must be passed as a python list. The
        ``name`` parameter will be ignored if this option is passed.

    Returns a list containing the removed packages.

    CLI Example:

    .. code-block:: bash

        salt '*' pkg.remove <package name>
        salt '*' pkg.remove tcsh
        salt '*' pkg.remove pkg://solaris/shell/tcsh
        salt '*' pkg.remove pkgs='["foo", "bar"]'
    '''
    targets = salt.utils.args.split_input(pkgs) if pkgs else [name]
    if not targets:
        return {}

    if pkgs:
        log.debug('Removing these packages instead of %s: %s', name, targets)

    # Get a list of the currently installed pkgs.
    old = list_pkgs()

    # Remove the package(s)
    cmd = ['/bin/pkg', 'uninstall', '-v'] + targets
    out = __salt__['cmd.run_all'](cmd, output_loglevel='trace')

    # Get a list of the packages after the uninstall
    __context__.pop('pkg.list_pkgs', None)
    new = list_pkgs()
    ret = salt.utils.data.compare_dicts(old, new)

    if out['retcode'] != 0:
        raise CommandExecutionError(
            'Error occurred removing package(s)',
            info={
                'changes': ret,
                'retcode': ips_pkg_return_values[out['retcode']],
                'errors': [out['stderr']]
            }
        )

    return ret


Instruction:
Create a Python 3 function for
executing a command and read the output as JSON

Response:
def ext_pillar(minion_id,  # pylint: disable=W0613
               pillar,  # pylint: disable=W0613
               command):
    '''
    Execute a command and read the output as JSON
    '''
    try:
        command = command.replace('%s', minion_id)
        return salt.utils.json.loads(__salt__['cmd.run'](command))
    except Exception:
        log.critical('JSON data from %s failed to parse', command)
        return {}


Instruction:
How would you explain what the following Python 3 function does
def _tap(tap, runas=None):
    '''
    Add unofficial GitHub repos to the list of formulas that brew tracks,
    updates, and installs from.
    '''
    if tap in _list_taps():
        return True

    cmd = 'tap {0}'.format(tap)
    try:
        _call_brew(cmd)
    except CommandExecutionError:
        log.error('Failed to tap "%s"', tap)
        return False

    return True

Response: Return True if the given command is successful False otherwise.


Instruction:
Can you write a function in Python 3 where it
calls the brew command with the user account of brew

Response:
def _call_brew(cmd, failhard=True):
    '''
    Calls the brew command with the user account of brew
    '''
    user = __salt__['file.get_user'](_homebrew_bin())
    runas = user if user != __opts__['user'] else None
    cmd = '{} {}'.format(salt.utils.path.which('brew'), cmd)
    result = __salt__['cmd.run_all'](cmd,
                                     runas=runas,
                                     output_loglevel='trace',
                                     python_shell=False)
    if failhard and result['retcode'] != 0:
        raise CommandExecutionError('Brew command failed',
                                    info={'result': result})
    return result


Instruction:
Can you generate the documentation for the following Python 3 function
def list_pkgs(versions_as_list=False, **kwargs):
    '''
    List the packages currently installed in a dict::

        {'<package_name>': '<version>'}

    CLI Example:

    .. code-block:: bash

        salt '*' pkg.list_pkgs
    '''
    versions_as_list = salt.utils.data.is_true(versions_as_list)
    # not yet implemented or not applicable
    if any([salt.utils.data.is_true(kwargs.get(x))
            for x in ('removed', 'purge_desired')]):
        return {}

    if 'pkg.list_pkgs' in __context__:
        if versions_as_list:
            return __context__['pkg.list_pkgs']
        else:
            ret = copy.deepcopy(__context__['pkg.list_pkgs'])
            __salt__['pkg_resource.stringify'](ret)
            return ret

    ret = {}
    cmd = 'info --json=v1 --installed'
    package_info = salt.utils.json.loads(_call_brew(cmd)['stdout'])

    for package in package_info:
        # Brew allows multiple versions of the same package to be installed.
        # Salt allows for this, so it must be accounted for.
        versions = [v['version'] for v in package['installed']]
        # Brew allows for aliasing of packages, all of which will be
        # installable from a Salt call, so all names must be accounted for.
        names = package['aliases'] + [package['name'], package['full_name']]
        # Create a list of tuples containing all possible combinations of
        # names and versions, because all are valid.
        combinations = [(n, v) for n in names for v in versions]

        for name, version in combinations:
            __salt__['pkg_resource.add_pkg'](ret, name, version)

    # Grab packages from brew cask, if available.
    # Brew Cask doesn't provide a JSON interface, must be parsed the old way.
    try:
        cask_cmd = 'cask list --versions'
        out = _call_brew(cask_cmd)['stdout']

        for line in out.splitlines():
            try:
                name_and_versions = line.split(' ')
                name = '/'.join(('caskroom/cask', name_and_versions[0]))
                installed_versions = name_and_versions[1:]
                key_func = functools.cmp_to_key(salt.utils.versions.version_cmp)
                newest_version = sorted(installed_versions, key=key_func).pop()
            except ValueError:
                continue
            __salt__['pkg_resource.add_pkg'](ret, name, newest_version)
    except CommandExecutionError:
        pass

    __salt__['pkg_resource.sort_pkglist'](ret)
    __context__['pkg.list_pkgs'] = copy.deepcopy(ret)
    if not versions_as_list:
        __salt__['pkg_resource.stringify'](ret)
    return ret

Response: List the packages currently installed in a dict.


Instruction:
Can you tell what is the following Python 3 function doing
def remove(name=None, pkgs=None, **kwargs):
    '''
    Removes packages with ``brew uninstall``.

    name
        The name of the package to be deleted.

    Multiple Package Options:

    pkgs
        A list of packages to delete. Must be passed as a python list. The
        ``name`` parameter will be ignored if this option is passed.

    .. versionadded:: 0.16.0

    Returns a dict containing the changes.

    CLI Example:

    .. code-block:: bash

        salt '*' pkg.remove <package name>
        salt '*' pkg.remove <package1>,<package2>,<package3>
        salt '*' pkg.remove pkgs='["foo", "bar"]'
    '''
    try:
        pkg_params = __salt__['pkg_resource.parse_targets'](
            name, pkgs, **kwargs
        )[0]
    except MinionError as exc:
        raise CommandExecutionError(exc)

    old = list_pkgs()
    targets = [x for x in pkg_params if x in old]
    if not targets:
        return {}
    cmd = 'uninstall {0}'.format(' '.join(targets))

    out = _call_brew(cmd)
    if out['retcode'] != 0 and out['stderr']:
        errors = [out['stderr']]
    else:
        errors = []

    __context__.pop('pkg.list_pkgs', None)
    new = list_pkgs()
    ret = salt.utils.data.compare_dicts(old, new)

    if errors:
        raise CommandExecutionError(
            'Problem encountered removing package(s)',
            info={'errors': errors, 'changes': ret}
        )

    return ret

Response: Removes packages with brew uninstall.


Instruction:
Here you have a function in Python 3, explain what it does
def refresh_db(**kwargs):
    '''
    Update the homebrew package repository.

    CLI Example:

    .. code-block:: bash

        salt '*' pkg.refresh_db
    '''
    # Remove rtag file to keep multiple refreshes from happening in pkg states
    salt.utils.pkg.clear_rtag(__opts__)
    cmd = 'update'
    if _call_brew(cmd)['retcode']:
        log.error('Failed to update')
        return False

    return True

Response: Update the homebrew package repository.


Instruction:
Can you tell what is the following Python 3 function doing
def _info(*pkgs):
    '''
    Get all info brew can provide about a list of packages.

    Does not do any kind of processing, so the format depends entirely on
    the output brew gives. This may change if a new version of the format is
    requested.

    On failure, returns an empty dict and logs failure.
    On success, returns a dict mapping each item in pkgs to its corresponding
    object in the output of 'brew info'.

    Caveat: If one of the packages does not exist, no packages will be
            included in the output.
    '''
    cmd = 'info --json=v1 {0}'.format(' '.join(pkgs))
    brew_result = _call_brew(cmd)
    if brew_result['retcode']:
        log.error('Failed to get info about packages: %s',
                  ' '.join(pkgs))
        return {}
    output = salt.utils.json.loads(brew_result['stdout'])
    return dict(zip(pkgs, output))

Response: Return info about a list of packages.


Instruction:
Can you generate a brief explanation for the following Python 3 code
def install(name=None, pkgs=None, taps=None, options=None, **kwargs):
    '''
    Install the passed package(s) with ``brew install``

    name
        The name of the formula to be installed. Note that this parameter is
        ignored if "pkgs" is passed.

        CLI Example:

        .. code-block:: bash

            salt '*' pkg.install <package name>

    taps
        Unofficial GitHub repos to use when updating and installing formulas.

        CLI Example:

        .. code-block:: bash

            salt '*' pkg.install <package name> tap='<tap>'
            salt '*' pkg.install zlib taps='homebrew/dupes'
            salt '*' pkg.install php54 taps='["josegonzalez/php", "homebrew/dupes"]'

    options
        Options to pass to brew. Only applies to initial install. Due to how brew
        works, modifying chosen options requires a full uninstall followed by a
        fresh install. Note that if "pkgs" is used, all options will be passed
        to all packages. Unrecognized options for a package will be silently
        ignored by brew.

        CLI Example:

        .. code-block:: bash

            salt '*' pkg.install <package name> tap='<tap>'
            salt '*' pkg.install php54 taps='["josegonzalez/php", "homebrew/dupes"]' options='["--with-fpm"]'

    Multiple Package Installation Options:

    pkgs
        A list of formulas to install. Must be passed as a python list.

        CLI Example:

        .. code-block:: bash

            salt '*' pkg.install pkgs='["foo","bar"]'

    Returns a dict containing the new package names and versions::

        {'<package>': {'old': '<old-version>',
                       'new': '<new-version>'}}

    CLI Example:

    .. code-block:: bash

        salt '*' pkg.install 'package package package'
    '''
    try:
        pkg_params, pkg_type = __salt__['pkg_resource.parse_targets'](
            name, pkgs, kwargs.get('sources', {})
        )
    except MinionError as exc:
        raise CommandExecutionError(exc)

    if not pkg_params:
        return {}

    formulas = ' '.join(pkg_params)
    old = list_pkgs()

    # Ensure we've tapped the repo if necessary
    if taps:
        if not isinstance(taps, list):
            # Feels like there is a better way to allow for tap being
            # specified as both a string and a list
            taps = [taps]

        for tap in taps:
            _tap(tap)

    if options:
        cmd = 'install {0} {1}'.format(formulas, ' '.join(options))
    else:
        cmd = 'install {0}'.format(formulas)

    out = _call_brew(cmd)
    if out['retcode'] != 0 and out['stderr']:
        errors = [out['stderr']]
    else:
        errors = []

    __context__.pop('pkg.list_pkgs', None)
    new = list_pkgs()
    ret = salt.utils.data.compare_dicts(old, new)

    if errors:
        raise CommandExecutionError(
            'Problem encountered installing package(s)',
            info={'errors': errors, 'changes': ret}
        )

    return ret

Response: Returns a dict containing the new packages and versions of the passed package.


Instruction:
Can you write a function in Python 3 where it
lists the available upgrade packages for all packages

Response:
def list_upgrades(refresh=True, **kwargs):  # pylint: disable=W0613
    '''
    Check whether or not an upgrade is available for all packages

    CLI Example:

    .. code-block:: bash

        salt '*' pkg.list_upgrades
    '''
    if refresh:
        refresh_db()

    res = _call_brew('outdated --json=v1')
    ret = {}

    try:
        data = salt.utils.json.loads(res['stdout'])
    except ValueError as err:
        msg = 'unable to interpret output from "brew outdated": {0}'.format(err)
        log.error(msg)
        raise CommandExecutionError(msg)

    for pkg in data:
        # current means latest available to brew
        ret[pkg['name']] = pkg['current_version']
    return ret


Instruction:
Explain what the following Python 3 code does
def upgrade(refresh=True, **kwargs):
    '''
    Upgrade outdated, unpinned brews.

    refresh
        Fetch the newest version of Homebrew and all formulae from GitHub before installing.

    Returns a dictionary containing the changes:

    .. code-block:: python

        {'<package>':  {'old': '<old-version>',
                        'new': '<new-version>'}}

    CLI Example:

    .. code-block:: bash

        salt '*' pkg.upgrade
    '''
    ret = {'changes': {},
           'result': True,
           'comment': '',
           }

    old = list_pkgs()

    if salt.utils.data.is_true(refresh):
        refresh_db()

    result = _call_brew('upgrade', failhard=False)
    __context__.pop('pkg.list_pkgs', None)
    new = list_pkgs()
    ret = salt.utils.data.compare_dicts(old, new)

    if result['retcode'] != 0:
        raise CommandExecutionError(
            'Problem encountered upgrading packages',
            info={'changes': ret, 'result': result}
        )

    return ret

Response: Upgrade outdated unpinned brews.


Instruction:
Make a summary of the following Python 3 code
def config(name, config):
    '''
    Ensure that the chronos job with the given name is present and is configured
    to match the given config values.

    :param name: The job name
    :param config: The configuration to apply (dict)
    :return: A standard Salt changes dictionary
    '''
    # setup return structure
    ret = {
        'name': name,
        'changes': {},
        'result': False,
        'comment': '',
    }

    # get existing config if job is present
    existing_config = None
    if __salt__['chronos.has_job'](name):
        existing_config = __salt__['chronos.job'](name)['job']

    # compare existing config with defined config
    if existing_config:
        update_config = copy.deepcopy(existing_config)
        salt.utils.configcomparer.compare_and_update_config(
            config,
            update_config,
            ret['changes'],
        )
    else:
        # the job is not configured--we need to create it from scratch
        ret['changes']['job'] = {
            'new': config,
            'old': None,
        }
        update_config = config

    if ret['changes']:
        # if the only change is in schedule, check to see if patterns are equivalent
        if 'schedule' in ret['changes'] and len(ret['changes']) == 1:
            if 'new' in ret['changes']['schedule'] and 'old' in ret['changes']['schedule']:
                new = ret['changes']['schedule']['new']
                log.debug('new schedule: %s', new)
                old = ret['changes']['schedule']['old']
                log.debug('old schedule: %s', old)
                if new and old:
                    _new = new.split('/')
                    log.debug('_new schedule: %s', _new)
                    _old = old.split('/')
                    log.debug('_old schedule: %s', _old)
                    if len(_new) == 3 and len(_old) == 3:
                        log.debug('_new[0] == _old[0]: %s',
                                  six.text_type(_new[0]) == six.text_type(_old[0]))
                        log.debug('_new[2] == _old[2]: %s',
                                  six.text_type(_new[2]) == six.text_type(_old[2]))
                        if six.text_type(_new[0]) == six.text_type(_old[0]) and \
                                six.text_type(_new[2]) == six.text_type(_old[2]):
                            log.debug('schedules match--no need for changes')
                            ret['changes'] = {}

    # update the config if we registered any changes
    log.debug('schedules match--no need for changes')
    if ret['changes']:
        # if test report there will be an update
        if __opts__['test']:
            ret['result'] = None
            ret['comment'] = 'Chronos job {0} is set to be updated'.format(
                name
            )
            return ret

        update_result = __salt__['chronos.update_job'](name, update_config)
        if 'exception' in update_result:
            ret['result'] = False
            ret['comment'] = 'Failed to update job config for {0}: {1}'.format(
                name,
                update_result['exception'],
            )
            return ret
        else:
            ret['result'] = True
            ret['comment'] = 'Updated job config for {0}'.format(name)
            return ret
    ret['result'] = True
    ret['comment'] = 'Chronos job {0} configured correctly'.format(name)
    return ret

Response: Ensure that the chronos job with the given name is configured with the given config values.