def up(self, no_provision=True): self.molecule.state.change_state('driver', self.name) kpn = self._get_keypair() active_instances = self._openstack.list_servers() active_instance_names = { instance['name']: instance['status'] for instance in active_instances } util.print_warn('Creating openstack instances...') for instance in self.instances: if instance['name'] not in active_instance_names: msg = '\tBringing up {}...'.format(instance['name']) util.print_info(msg) server = self._openstack.create_server( name=instance['name'], image=self._openstack.get_image(instance['image']), flavor=self._openstack.get_flavor(instance['flavor']), auto_ip=True, wait=True, key_name=kpn, security_groups=instance['security_groups'] if 'security_groups' in instance else None) self._reset_known_host_key(server['interface_ip']) instance['created'] = True num_retries = 0 while not self._check_ssh_availability( server['interface_ip'], instance['sshuser'], timeout=6, sshkey_filename=self._get_keyfile( )) or num_retries == 5: util.print_info('\t Waiting for ssh availability...') num_retries += 1
def test_print_warn(capsys): util.print_warn('test') result, _ = capsys.readouterr() print '{}{}'.format(colorama.Fore.YELLOW, 'test'.rstrip()) expected, _ = capsys.readouterr() assert expected == result
def test_print_warn(capsys): util.print_warn("test") result, _ = capsys.readouterr() print "{}{}".format(colorama.Fore.YELLOW, "test".rstrip()) expected, _ = capsys.readouterr() assert expected == result
def up(self, no_provision=True): self.molecule.state.change_state('driver', self.name) kpn = self._get_keypair() active_instances = self._openstack.list_servers() active_instance_names = { instance['name']: instance['status'] for instance in active_instances } util.print_warn('Creating openstack instances...') for instance in self.instances: try: # We divide the ssh_timeout by 2, because the connect # itself takes at least a second and is followed by # a 1 sec sleep ssh_timeout = int( instance.get('ssh_timeout', self.ssh_timeout) / 2) except TypeError: util.print_error('Can not cast ssh_timeout setting "%s"' ' to int' % instance.get('ssh_timeout', self.ssh_timeout)) util.sysexit() if instance['name'] not in active_instance_names: msg = '\tBringing up {}...'.format(instance['name']) util.print_info(msg) server = self._openstack.create_server( name=instance['name'], image=self._openstack.get_image(instance['image']), flavor=self._openstack.get_flavor(instance['flavor']), auto_ip=True, wait=True, key_name=kpn, ip_pool=instance.get('ip_pool') if instance.get('ip_pool') else self.ip_pool, network=instance.get('networks', []), security_groups=instance.get('security_groups', [])) instance['created'] = True instance['reachable'] = False for _ in range(ssh_timeout): util.print_info('\t Waiting for ssh availability...') if self._check_ssh_availability( server['interface_ip'], instance['sshuser'], timeout=1, sshkey_filename=self._get_keyfile()): instance['reachable'] = True break if not instance['reachable']: util.print_error( 'Could not reach instance "%s"' ' within limit of %s seconds' % (instance['name'], instance.get('ssh_timeout', self.ssh_timeout))) util.sysexit()
def up(self, no_provision=True, image_tag='molecule_local/{}:{}'): self.molecule.state.change_state('driver', self.name) for container in self.instances: # check global docker driver or specific container config for # overrides for molecule image creation if (container.get('build_image') or (self.molecule.config.config['docker']['build_image'] and container.get('build_image', True))): container['image_tag'] = image_tag self._build_ansible_compatible_image(container) else: container['image_tag'] = '{}:{}' privileged = container.get('privileged', False) port_bindings = container.get('port_bindings', {}) volume_mounts = container.get('volume_mounts', []) links = container.get('links', {}) network_mode = container.get('network_mode', '') cap_add = container.get('cap_add', []) cap_drop = container.get('cap_drop', []) command = container.get('command', '') environment = container.get('environment') docker_host_config = self._docker.create_host_config( privileged=privileged, port_bindings=port_bindings, binds=volume_mounts, links=links, network_mode=network_mode, cap_add=cap_add, cap_drop=cap_drop) if (container['created'] is not True): msg = ('Creating container {} ' 'with base image {}:{}...').format( container['name'], container['image'], container['image_version']) util.print_warn(msg) container = self._docker.create_container( image=container['image_tag'].format( container['image'], container['image_version']), tty=True, detach=False, name=container['name'], ports=port_bindings.keys(), host_config=docker_host_config, environment=environment, command=command) self._docker.start(container=container.get('Id')) container['created'] = True util.print_success('Container created.') else: self._docker.start(container['name']) msg = 'Starting container {}...'.format(container['name']) util.print_info(msg)
def destroy(self): for container in self.instances: if (container['created']): msg = 'Stopping container {}...'.format(container['name']) util.print_warn(msg) self._docker.stop(container['name'], timeout=0) self._docker.remove_container(container['name']) msg = 'Removed container {}.'.format(container['name']) util.print_success(msg) container['created'] = False
def _cleanup_temp_keypair(self): # if we don't have a keypair config, delete the temp one if ('keypair' not in self.molecule.config.config['openstack']): kpn = self._get_temp_keyname() if self._openstack.search_keypairs(kpn): msg = '\tRemoving openstack keypair {}...'.format(kpn) util.print_warn(msg) if not self._openstack.delete_keypair(kpn): msg = 'Unable to remove openstack keypair {}.'.format(kpn) util.print_error(msg) else: msg = '\tRemoved openstack keypair {}.'.format(kpn) util.print_success(msg)
def _cleanup_temp_keyfile(self): # if we don't have a keyfile config, delete the temp one if ('keyfile' not in self.molecule.config.config['openstack']): kn = self._get_temp_keyname() kl = self._get_temp_keylocation() pvtloc = kl + '/' + kn publoc = kl + '/' + kn + '.pub' if os.path.exists(pvtloc): util.print_warn('\tRemoving {}...'.format(pvtloc)) os.remove(pvtloc) if os.path.exists(publoc): util.print_warn('\tRemoving {}...'.format(publoc)) os.remove(publoc)
def up(self, no_provision=True): self.molecule.state.change_state('driver', self.name) if self.molecule.config.config['docker']['build_image']: self._build_ansible_compatible_image() else: self.image_tag = '{}:{}' for container in self.instances: privileged = container.get('privileged', False) port_bindings = container.get('port_bindings', {}) volume_mounts = container.get('volume_mounts', []) links = container.get('links', {}) network_mode = container.get('network_mode', '') cap_add = container.get('cap_add', []) cap_drop = container.get('cap_drop', []) command = container.get('command', '') environment = container.get('environment') docker_host_config = self._docker.create_host_config( privileged=privileged, port_bindings=port_bindings, binds=volume_mounts, links=links, network_mode=network_mode, cap_add=cap_add, cap_drop=cap_drop) if (container['created'] is not True): msg = ('Creating container {} ' 'with base image {}:{}...').format( container['name'], container['image'], container['image_version']) util.print_warn(msg) container = self._docker.create_container( image=self.image_tag.format(container['image'], container['image_version']), tty=True, detach=False, name=container['name'], ports=port_bindings.keys(), host_config=docker_host_config, environment=environment, command=command) self._docker.start(container=container.get('Id')) container['created'] = True util.print_success('Container created.') else: self._docker.start(container['name']) msg = 'Starting container {}...'.format(container['name']) util.print_info(msg)
def up(self, no_provision=True): self.molecule.state.change_state('driver', self.name) if self.molecule.config.config['docker']['build_image']: self._build_ansible_compatible_image() else: self.image_tag = '{}:{}' for container in self.instances: privileged = container.get('privileged', False) port_bindings = container.get('port_bindings', {}) volume_mounts = container.get('volume_mounts', []) links = container.get('links', {}) cap_add = container.get('cap_add', []) cap_drop = container.get('cap_drop', []) command = container.get('command', '') environment = container.get('environment') docker_host_config = self._docker.create_host_config( privileged=privileged, port_bindings=port_bindings, binds=volume_mounts, links=links, cap_add=cap_add, cap_drop=cap_drop) if (container['created'] is not True): msg = ('Creating container {} ' 'with base image {}:{}...').format( container['name'], container['image'], container['image_version']) util.print_warn(msg) container = self._docker.create_container( image=self.image_tag.format(container['image'], container['image_version']), tty=True, detach=False, name=container['name'], ports=port_bindings.keys(), host_config=docker_host_config, environment=environment, command=command) self._docker.start(container=container.get('Id')) container['created'] = True util.print_success('Container created.') else: self._docker.start(container['name']) msg = 'Starting container {}...'.format(container['name']) util.print_info(msg)
def create_inventory_file(self): """ Creates the inventory file used by molecule and returns None. :return: None """ inventory = '' for instance in self.driver.instances: inventory += self.driver.inventory_entry(instance) groups = {} for instance in self.driver.instances: ansible_groups = instance.get('ansible_groups') if ansible_groups: for group in ansible_groups: if isinstance(group, str): if group not in groups: groups[group] = [] groups[group].append(instance['name']) elif isinstance(group, dict): for group_name, group_list in group.iteritems(): for g in group_list: if group_name not in groups: groups[group_name] = [] groups[group_name].append(g) if self.args.get('platform') == 'all': self.driver.platform = 'all' for group, subgroups in groups.iteritems(): inventory += '\n[{}]\n'.format(group) for subgroup in subgroups: instance_name = util.format_instance_name( subgroup, self.driver.platform, self.driver.instances) if instance_name: inventory += '{}\n'.format(instance_name) else: inventory += '{}\n'.format(subgroup) inventory_file = self.config.config['ansible']['inventory_file'] try: util.write_file(inventory_file, inventory) except IOError: msg = 'WARNING: could not write inventory file {}.'.format( inventory_file) util.print_warn(msg)
def main(self): """ A mechanism to initialize molecule by calling its main method. This can be redefined by classes which do not want this behavior (:class:`.Init`). :returns: None """ if (not self._config.molecule_file_exists() and not self._config.molecule_local_config_file_exists()): msg = ('Unable to find {}. ' 'Exiting.').format(self._config.molecule_file) util.print_error(msg) util.sysexit() elif (not self._config.molecule_file_exists() and self._config.molecule_local_config_file_exists()): util.print_warn('No molecule.yml found in project, ' 'using config file at %s only' % self._config.molecule_local_config_file) self.molecule.main()
def destroy(self): util.print_info('Deleting openstack instances...') active_instances = self._openstack.list_servers() active_instance_names = { instance['name']: instance['id'] for instance in active_instances } for instance in self.instances: util.print_warn('\tRemoving {}...'.format(instance['name'])) if instance['name'] in active_instance_names: if not self._openstack.delete_server( active_instance_names[instance['name']], wait=True): msg = 'Unable to remove {}.'.format(instance['name']) util.print_error(msg) else: util.print_success('\tRemoved {}.'.format(instance[ 'name'])) instance['created'] = False # cleanup any molecule generated ssh keysfiles self._cleanup_temp_keypair() self._cleanup_temp_keyfile()
def up(self, no_provision=True): self.molecule.state.change_state('driver', self.name) kpn = self._get_keypair() active_instances = self._openstack.list_servers() active_instance_names = { instance['name']: instance['status'] for instance in active_instances } util.print_warn('Creating openstack instances...') for instance in self.instances: if instance['name'] not in active_instance_names: msg = '\tBringing up {}...'.format(instance['name']) util.print_info(msg) server = self._openstack.create_server( name=instance['name'], image=self._openstack.get_image(instance['image']), flavor=self._openstack.get_flavor(instance['flavor']), auto_ip=True, wait=True, key_name=kpn, ip_pool=instance.get('ip_pool') if instance.get('ip_pool') else self.ip_pool, security_groups=instance.get('security_groups', [])) self._reset_known_host_key(server['interface_ip']) instance['created'] = True num_retries = 0 while not self._check_ssh_availability( server['interface_ip'], instance['sshuser'], timeout=6, sshkey_filename=self._get_keyfile( )) or num_retries == 5: util.print_info('\t Waiting for ssh availability...') num_retries += 1
def destroy(self): util.print_info('Deleting openstack instances...') active_instances = self._openstack.list_servers() active_instance_names = { instance['name']: instance['id'] for instance in active_instances } for instance in self.instances: util.print_warn('\tRemoving {}...'.format(instance['name'])) if instance['name'] in active_instance_names: if not self._openstack.delete_server( active_instance_names[instance['name']], wait=True): msg = 'Unable to remove {}.'.format(instance['name']) util.print_error(msg) else: util.print_success('\tRemoved {}.'.format( instance['name'])) instance['created'] = False # cleanup any molecule generated ssh keysfiles self._cleanup_temp_keypair() self._cleanup_temp_keyfile()
def destroy(self): for container in self.instances: if (container['created']): msg = 'Stopping container {}...'.format(container['name']) util.print_warn(msg) self._docker.stop(container['name'], timeout=0) self._docker.remove_container(container['name']) msg = 'Removed container {}.'.format(container['name']) util.print_success(msg) container['created'] = False if self._network is not None: for network in self._network: try: d_net = self._docker.networks(names=[network['name']])[0] msg = 'Removing network {}'.format(network['name']) util.print_warn(msg) self._docker.remove_network(d_net['Id']) except IndexError: msg = ('Could not find network {}. ' 'Skipping remove').format(network['name']) util.print_warn(msg) util.print_success('Network(s) removed')
def _build_ansible_compatible_image(self, container): available_images = [ tag.encode('utf-8') for image in self._docker.images() if image.get('RepoTags') is not None for tag in image.get('RepoTags') ] msg = ('Creating Ansible compatible ' 'image of {}:{} ...').format(container['image'], container['image_version']) util.print_info(msg) if 'registry' in container: container['registry'] += '/' else: container['registry'] = '' dockerfile = ''' FROM {container_image}:{container_version} {container_environment} RUN /bin/sh -c 'if [ -x "$(command -v apt-get)" ]; then apt-get update && apt-get install -y python sudo bash; fi' RUN /bin/sh -c 'if [ -x "$(command -v yum)" ]; then touch /var/lib/rpm/* && yum makecache fast && yum update -y && yum install -y python sudo yum-plugin-ovl bash && sed -i 's/plugins=0/plugins=1/g' /etc/yum.conf; fi' RUN /bin/sh -c 'if [ -x "$(command -v zypper)" ]; then zypper refresh && zypper update -y && zypper install -y python sudo bash; fi' RUN /bin/sh -c 'if [ -x "$(command -v apk)" ]; then apk update && apk add python sudo bash; fi' RUN /bin/sh -c 'if [ -x "$(command -v pacman)" ]; then pacman --sync --noconfirm --refresh python2 bash; fi' RUN /bin/sh -c 'if [ -x "$(command -v dnf)" ]; then dnf makecache fast; dnf --assumeyes install python python-devel python2-dnf bash; fi' RUN /bin/sh -c 'if [ -x "$(command -v emerge)" ]; then emerge --ask n =dev-lang/python-2\* gentoolkit; fi' ''' # noqa if 'dockerfile' in container: dockerfile = container['dockerfile'] f = io.open(dockerfile) else: environment = container.get('environment') if environment: environment = '\n'.join('ENV {} {}'.format(k, v) for k, v in environment.iteritems()) else: environment = '' dockerfile = dockerfile.format( container_image=container['registry'] + container['image'], container_version=container['image_version'], container_environment=environment) f = io.BytesIO(dockerfile.encode('utf-8')) container['image'] = container['registry'].replace( '/', '_').replace(':', '_') + container['image'] tag_string = container['image_tag'].format(container['image'], container['image_version']) errors = False if tag_string not in available_images or 'dockerfile' in container: util.print_info('Building ansible compatible image...') previous_line = '' for line in self._docker.build(fileobj=f, tag=tag_string): for line_split in line.split('\n'): if len(line_split) > 0: line = json.loads(line_split) if 'stream' in line: msg = '\t{}'.format(line['stream']) util.print_warn(msg) if 'errorDetail' in line: ed = line['errorDetail']['message'] msg = '\t{}'.format(ed) util.print_warn(msg) errors = True if 'status' in line: if previous_line not in line['status']: msg = '\t{} ...'.format(line['status']) util.print_warn(msg) previous_line = line['status'] if errors: msg = 'Build failed for {}.'.format(tag_string) util.print_error(msg) return else: util.print_success('Finished building {}.'.format(tag_string))
def up(self, no_provision=True, image_tag='molecule_local/{}:{}'): self.molecule.state.change_state('driver', self.name) if self._network is not None: for network in self._network: driver = network.get('driver', 'bridge') msg = ('Creating network {} ' 'with driver {}').format(network['name'], driver) util.print_warn(msg) self._docker.create_network(network['name'], driver=driver) util.print_success('Network(s) created') for container in self.instances: # check global docker driver or specific container config for # overrides for molecule image creation if (container.get('build_image') or (self.molecule.config.config['docker']['build_image'] and container.get('build_image', True))): container['image_tag'] = image_tag self._build_ansible_compatible_image(container) else: container['image_tag'] = '{}:{}' privileged = container.get('privileged', False) port_bindings = container.get('port_bindings', {}) volume_mounts = container.get('volume_mounts', []) links = container.get('links', {}) network_mode = container.get('network_mode', '') cap_add = container.get('cap_add', []) cap_drop = container.get('cap_drop', []) command = container.get('command', '') environment = container.get('environment') hostname = container.get('hostname') docker_host_config = self._docker.create_host_config( privileged=privileged, port_bindings=port_bindings, binds=volume_mounts, links=links, network_mode=network_mode, cap_add=cap_add, cap_drop=cap_drop) if (container['created'] is not True): msg = ('Creating container {} ' 'with base image {}:{}...').format( container['name'], container['image'], container['image_version']) util.print_warn(msg) container = self._docker.create_container( image=container['image_tag'].format( container['image'], container['image_version']), tty=True, detach=False, name=container['name'], ports=port_bindings.keys(), host_config=docker_host_config, environment=environment, command=command, hostname=hostname) self._docker.start(container=container.get('Id')) container['created'] = True util.print_success('Container created.') else: self._docker.start(container['name']) msg = 'Starting container {}...'.format(container['name']) util.print_info(msg)
def _build_ansible_compatible_image(self): available_images = [ tag.encode('utf-8') for image in self._docker.images() for tag in image.get('RepoTags', []) ] for container in self.instances: if container.get('build_image'): msg = ('Creating Ansible compatible ' 'image of {}:{} ...').format(container['image'], container['image_version']) util.print_info(msg) if 'registry' in container: container['registry'] += '/' else: container['registry'] = '' dockerfile = ''' FROM {container_image}:{container_version} {container_environment} RUN bash -c 'if [ -x "$(command -v apt-get)" ]; then apt-get update && apt-get install -y python sudo; fi' RUN bash -c 'if [ -x "$(command -v yum)" ]; then yum makecache fast && yum update -y && yum install -y python sudo which yum-plugin-ovl && sed -i 's/plugins=0/plugins=1/g' /etc/yum.conf; fi' RUN bash -c 'if [ -x "$(command -v zypper)" ]; then zypper refresh && zypper update -y && zypper install -y python sudo; fi' ''' # noqa if 'dockerfile' in container: dockerfile = container['dockerfile'] f = io.open(dockerfile) else: environment = container.get('environment') if environment: environment = '\n'.join( 'ENV {} {}'.format(k, v) for k, v in environment.iteritems()) else: environment = '' dockerfile = dockerfile.format( container_image=container['registry'] + container['image'], container_version=container['image_version'], container_environment=environment) f = io.BytesIO(dockerfile.encode('utf-8')) container['image'] = container['registry'].replace( '/', '_').replace(':', '_') + container['image'] tag_string = self.image_tag.format(container['image'], container['image_version']) errors = False if tag_string not in available_images or 'dockerfile' in container: util.print_info('Building ansible compatible image...') previous_line = '' for line in self._docker.build(fileobj=f, tag=tag_string): for line_split in line.split('\n'): if len(line_split) > 0: line = json.loads(line_split) if 'stream' in line: msg = '\t{}'.format(line['stream']) util.print_warn(msg) if 'errorDetail' in line: ed = line['errorDetail']['message'] msg = '\t{}'.format(ed) util.print_warn(msg) errors = True if 'status' in line: if previous_line not in line['status']: msg = '\t{} ...'.format(line['status']) util.print_warn(msg) previous_line = line['status'] if errors: msg = 'Build failed for {}.'.format(tag_string) util.print_error(msg) return else: util.print_success( 'Finished building {}.'.format(tag_string))
def up(self, no_provision=True): self.molecule.state.change_state('driver', self.name) kpn = self._get_keypair() active_instances = self._openstack.list_servers() active_instance_names = { instance['name']: instance['interface_ip'] for instance in active_instances } util.print_warn('Creating openstack instances...') for instance in self.instances: try: # We divide the ssh_timeout by 2, because the connect # itself takes at least a second and is followed by # a 1 sec sleep ssh_timeout = int( instance.get('ssh_timeout', self.ssh_timeout) / 2) except TypeError: util.print_error('Can not cast ssh_timeout setting "%s"' ' to int' % instance.get('ssh_timeout', self.ssh_timeout)) util.sysexit() if instance['name'] not in active_instance_names: msg = '\tBringing up {}...'.format(instance['name']) util.print_info(msg) server = self._openstack.create_server( name=instance['name'], image=self._openstack.get_image(instance['image']), flavor=self._openstack.get_flavor(instance['flavor']), auto_ip=True, wait=False, key_name=kpn, ip_pool=instance.get('ip_pool') if instance.get('ip_pool') else self.ip_pool, network=instance.get('networks', []), security_groups=instance.get('security_groups', [])) instance['created'] = True instance['reachable'] = False instance['server'] = server else: instance['address'] = active_instance_names[instance['name']] instance['reachable'] = True for instance in self.instances: if not instance.get('server'): instance['server'] = self._openstack.get_server(instance[ 'name']) if not instance.get('address'): util.print_info( '\t Waiting for instance %s to be in state active...' % instance['name']) server = self._openstack.wait_for_server( instance['server'], auto_ip=True) instance['address'] = server['interface_ip'] for instance in self.instances: for _ in range(ssh_timeout): util.print_info( '\t Waiting for ssh availability of instance %s...' % instance['name']) if self._check_ssh_availability( instance['address'], instance['sshuser'], timeout=1, sshkey_filename=self._get_keyfile()): instance['reachable'] = True break if not instance['reachable']: util.print_error( 'Could not reach instance "%s"' ' within limit of %s seconds' % (instance['name'], instance.get('ssh_timeout', self.ssh_timeout))) util.sysexit()
def _build_ansible_compatible_image(self): available_images = [ tag.encode('utf-8') for image in self._docker.images() for tag in image.get('RepoTags', []) ] for container in self.instances: if container.get('build_image'): msg = ('Creating Ansible compatible ' 'image of {}:{} ...').format(container['image'], container['image_version']) util.print_info(msg) if 'registry' in container: container['registry'] += '/' else: container['registry'] = '' dockerfile = ''' FROM {container_image}:{container_version} {container_environment} RUN bash -c 'if [ -x "$(command -v apt-get)" ]; then apt-get update && apt-get install -y python sudo; fi' RUN bash -c 'if [ -x "$(command -v yum)" ]; then yum makecache fast && yum update -y && yum install -y python sudo yum-plugin-ovl && sed -i 's/plugins=0/plugins=1/g' /etc/yum.conf; fi' RUN bash -c 'if [ -x "$(command -v zypper)" ]; then zypper refresh && zypper update -y && zypper install -y python sudo; fi' ''' # noqa if 'dockerfile' in container: dockerfile = container['dockerfile'] f = io.open(dockerfile) else: environment = container.get('environment') if environment: environment = '\n'.join( 'ENV {} {}'.format(k, v) for k, v in environment.iteritems()) else: environment = '' dockerfile = dockerfile.format( container_image=container['registry'] + container['image'], container_version=container['image_version'], container_environment=environment) f = io.BytesIO(dockerfile.encode('utf-8')) container['image'] = container['registry'].replace( '/', '_').replace(':', '_') + container['image'] tag_string = self.image_tag.format(container['image'], container['image_version']) errors = False if tag_string not in available_images or 'dockerfile' in container: util.print_info('Building ansible compatible image...') previous_line = '' for line in self._docker.build(fileobj=f, tag=tag_string): for line_split in line.split('\n'): if len(line_split) > 0: line = json.loads(line_split) if 'stream' in line: msg = '\t{}'.format(line['stream']) util.print_warn(msg) if 'errorDetail' in line: ed = line['errorDetail']['message'] msg = '\t{}'.format(ed) util.print_warn(msg) errors = True if 'status' in line: if previous_line not in line['status']: msg = '\t{} ...'.format(line['status']) util.print_warn(msg) previous_line = line['status'] if errors: msg = 'Build failed for {}.'.format(tag_string) util.print_error(msg) return else: util.print_success('Finished building {}.'.format( tag_string))