def execute(self): """ Execute the actions necessary to perform a `molecule init role` and returns None. :return: None """ role_name = self._command_args['role_name'] role_directory = os.getcwd() msg = 'Initializing new role {}...'.format(role_name) LOG.info(msg) if os.path.isdir(role_name): msg = ('The directory {} exists. ' 'Cannot create new role.').format(role_name) util.sysexit_with_message(msg) self._process_templates('role', self._command_args, role_directory) scenario_base_directory = os.path.join(role_directory, role_name) templates = [ 'scenario/driver/{driver_name}'.format(**self._command_args), 'scenario/verifier/{verifier_name}'.format(**self._command_args), ] for template in templates: self._process_templates(template, self._command_args, scenario_base_directory) self._process_templates('molecule', self._command_args, scenario_base_directory) role_directory = os.path.join(role_directory, role_name) msg = 'Initialized role in {} successfully.'.format(role_directory) LOG.success(msg)
def _role_exists(ctx, param, value): # pragma: no cover role_directory = os.path.join(os.pardir, value) if not os.path.exists(role_directory): msg = ("The role '{}' not found. " 'Please choose the proper role name.').format(value) util.sysexit_with_message(msg) return value
def test_sysexit_with_message_and_custom_code(patched_logger_critical): with pytest.raises(SystemExit) as e: util.sysexit_with_message('foo', 2) assert 2 == e.value.code patched_logger_critical.assert_called_once_with('foo')
def _verify_inventory(self): """ Verify the inventory is valid and returns None. :return: None """ if not self.inventory: msg = ("Instances missing from the 'platform' " "section of molecule.yml.") util.sysexit_with_message(msg)
def _default_scenario_exists(ctx, param, value): # pragma: no cover if value == 'default': return value default_scenario_directory = os.path.join('molecule', 'default') if not os.path.exists(default_scenario_directory): msg = ('The default scenario not found. Please create a scenario ' "named 'default' first.") util.sysexit_with_message(msg) return value
def _verify(self): """ Verify the specified scenario was found and returns None. :return: None """ scenario_names = [c.scenario.name for c in self._configs] if self._scenario_name not in scenario_names: msg = ("Scenario '{}' not found. " 'Exiting.').format(self._scenario_name) util.sysexit_with_message(msg)
def execute(self): """ Executes `ansible-playbook` and returns a string. :return: str """ if self._ansible_command is None: self.bake() try: cmd = util.run_command( self._ansible_command, debug=self._config.debug) return cmd.stdout.decode('utf-8') except sh.ErrorReturnCode as e: out = e.stdout.decode('utf-8') util.sysexit_with_message(str(out), e.exit_code)
def execute(self): """ Execute the actions necessary to perform a `molecule login` and returns None. :return: None """ c = self._config if not c.state.created and (c.driver.delegated and not c.driver.managed): msg = 'Instances not created. Please create instances first.' util.sysexit_with_message(msg) hosts = [d['name'] for d in self._config.platforms.instances] hostname = self._get_hostname(hosts) self._get_login(hostname)
def _link_or_update_vars(self): """ Creates or updates the symlink to group_vars and returns None. :returns: None """ for d, source in self.links.items(): target = os.path.join(self._config.scenario.ephemeral_directory, d) source = os.path.join(self._config.scenario.ephemeral_directory, source) if not os.path.exists(source): msg = "The source path '{}' does not exist.".format(source) util.sysexit_with_message(msg) msg = "Inventory {} linked to {}".format(source, target) LOG.info(msg) os.symlink(source, target)
def _get_driver_name(self): driver_from_state_file = self.state.driver driver_from_cli = self.command_args.get('driver_name') if driver_from_state_file: driver_name = driver_from_state_file elif driver_from_cli: driver_name = driver_from_cli else: driver_name = self.config['driver']['name'] if driver_from_cli and (driver_from_cli != driver_name): msg = ("Instance(s) were created with the '{}' driver, but the " "subcommand is using '{}' driver.").format( driver_name, driver_from_cli) util.sysexit_with_message(msg) return driver_name
def _verify_configs(configs): """ Verify a Molecule config was found and returns None. :param configs: A list containing absolute paths to Molecule config files. :return: None """ if configs: scenario_names = [c.scenario.name for c in configs] for scenario_name, n in collections.Counter(scenario_names).items(): if n > 1: msg = ("Duplicate scenario name '{}' found. " 'Exiting.').format(scenario_name) util.sysexit_with_message(msg) else: msg = "'{}' glob failed. Exiting.".format(MOLECULE_GLOB) util.sysexit_with_message(msg)
def __init__(self, old_molecule_file, driver_name): self._old_molecule_file = old_molecule_file if not os.path.isfile(old_molecule_file): msg = 'Unable to find {}. Exiting.'.format(old_molecule_file) util.sysexit_with_message(msg) self._m = migrate.Migrate(old_molecule_file) self._old_role_dir = os.path.join(os.path.dirname(old_molecule_file)) self._old_dot_molecule_dir = scenario.ephemeral_directory( self._old_role_dir) self._old_test_dir = os.path.join(self._old_role_dir, 'tests') self._old_playbook = os.path.join(self._old_role_dir, 'playbook.yml') self._molecule_dir = config.molecule_directory(self._old_role_dir) self._scenario_dir = os.path.join(self._molecule_dir, 'default') self._test_dir = os.path.join(self._scenario_dir, 'tests') self._molecule_file = config.molecule_file(self._scenario_dir) self._role_name = os.path.basename( os.path.normpath(self._old_role_dir))
def _get_hostname(self, hosts): hostname = self._config.command_args.get('host') if hostname is None: if len(hosts) == 1: hostname = hosts[0] else: msg = ('There are {} running hosts. Please specify ' 'which with --host.\n\n' 'Available hosts:\n{}'.format( len(hosts), '\n'.join(sorted(hosts)))) util.sysexit_with_message(msg) match = [x for x in hosts if x.startswith(hostname)] if len(match) == 0: msg = ("There are no hosts that match '{}'. You " 'can only login to valid hosts.').format(hostname) util.sysexit_with_message(msg) elif len(match) != 1: # If there are multiple matches, but one of them is an exact string # match, assume this is the one they're looking for and use it. if hostname in match: match = [ hostname, ] else: msg = ("There are {} hosts that match '{}'. You " 'can only login to one at a time.\n\n' 'Available hosts:\n{}'.format( len(match), hostname, '\n'.join(sorted(hosts)))) util.sysexit_with_message(msg) return match[0]
def execute(self): """ Execute the actions necessary to perform a `molecule idempotence` and returns None. :return: None """ self.print_info() if not self._config.state.converged: msg = 'Instances not converged. Please converge instances first.' util.sysexit_with_message(msg) output = self._config.provisioner.converge(out=None, err=None) idempotent = self._is_idempotent(output) if idempotent: msg = 'Idempotence completed successfully.' LOG.success(msg) else: msg = ('Idempotence test failed because of the following tasks:\n' '{}').format('\n'.join(self._non_idempotent_tasks(output))) util.sysexit_with_message(msg)
def execute(self): """ Execute the actions necessary to perform a `molecule init scenario` and returns None. :return: None """ scenario_name = self._command_args['scenario_name'] role_name = os.getcwd().split(os.sep)[-1] role_directory = util.abs_path(os.path.join(os.getcwd(), os.pardir)) msg = 'Initializing new scenario {}...'.format(scenario_name) LOG.info(msg) molecule_directory = config.molecule_directory( os.path.join(role_directory, role_name)) scenario_directory = os.path.join(molecule_directory, scenario_name) scenario_base_directory = os.path.dirname(scenario_directory) if os.path.isdir(scenario_directory): msg = ('The directory molecule/{} exists. ' 'Cannot create new scenario.').format(scenario_name) util.sysexit_with_message(msg) scenario_base_directory = os.path.join(role_directory, role_name) templates = [ 'scenario/driver/{driver_name}'.format(**self._command_args), 'scenario/verifier/{verifier_name}'.format(**self._command_args), ] for template in templates: self._process_templates(template, self._command_args, scenario_base_directory) self._process_templates('molecule', self._command_args, scenario_base_directory) role_directory = os.path.join(role_directory, role_name) msg = 'Initialized scenario in {} successfully.'.format( scenario_directory) LOG.success(msg)
def _supported_ansible_version(): # pragma: no cover if (distutils.version.LooseVersion(_get_ansible_version()) <= distutils.version.LooseVersion('2.2')): msg = ("Ansible version '{}' not supported. " 'Molecule only supports Ansible versions ' "'>= 2.2'.").format(_get_ansible_version()) util.sysexit_with_message(msg) if _supported_python2_version(): pass elif _supported_python3_version(): if (distutils.version.LooseVersion(_get_ansible_version()) < distutils.version.LooseVersion('2.4')): msg = ("Ansible version '{}' not supported. " 'Molecule only supports Ansible versions ' "'>=2.5' with Python version '{}'").format( _get_ansible_version(), _get_python_version()) util.sysexit_with_message(msg) else: msg = ("Python version '{}' not supported. " 'Molecule only supports Python versions ' "'2.7' and '3.6'.").format(_get_python_version()) util.sysexit_with_message(msg)
def execute(self): """ Execute the actions necessary to perform a `molecule init role` and \ returns None. :return: None """ namespace = None role_name = self._command_args["role_name"] role_directory = os.getcwd() # outside collections our tooling needs a namespace. if not os.path.isfile("../galaxy.yml"): name_re = re.compile(r"^[a-z][a-z0-9_]+\.[a-z][a-z0-9_]+$") if not name_re.match(role_name): util.sysexit_with_message( "Outside collections you must mention role " "namespace like: molecule init role 'acme.myrole'. Be sure " "you use only lowercase characters and underlines. See https://galaxy.ansible.com/docs/contributing/creating_role.html" ) namespace, role_name = role_name.split(".") msg = f"Initializing new role {role_name}..." LOG.info(msg) if os.path.isdir(role_name): msg = f"The directory {role_name} exists. Cannot create new role." util.sysexit_with_message(msg) cmd = ["ansible-galaxy", "init", "-v", "--offline", role_name] result = util.run_command(cmd) if result.returncode != 0: util.sysexit_with_message( f"Galaxy failed to create role, returned {result.returncode!s}" ) if namespace: # we need to inject namespace info into meta/main.yml cmd = [ "ansible", "localhost", "-o", # one line output "-m", "lineinfile", "-a", f'path={role_name}/meta/main.yml line=" namespace: {namespace}" insertafter=" author: your name"', ] util.run_command(cmd, check=True) scenario_base_directory = os.path.join(role_directory, role_name) templates = [ api.drivers()[self._command_args["driver_name"]].template_dir(), api.verifiers()[ self._command_args["verifier_name"]].template_dir(), ] self._process_templates("molecule", { **self._command_args, "role_name": role_name }, role_directory) for template in templates: self._process_templates(template, self._command_args, scenario_base_directory) role_directory = os.path.join(role_directory, role_name) msg = f"Initialized role in {role_directory} successfully." LOG.info(msg)
def _preflight(self, data: MutableMapping): env = set_env_from_file(os.environ.copy(), self.env_file) errors, data = schema_v3.pre_validate(data, env, MOLECULE_KEEP_STRING) if errors: msg = "Failed to pre-validate.\n\n{}".format(errors) util.sysexit_with_message(msg, detail=data)
interpolated_config = self._interpolate(s, env, keep_string) defaults = util.merge_dicts(defaults, <<<<<<< HEAD >>>>>>> 0fa82e7a3daa84ebd03d8af67403c6551113d3e4:molecule/config.py ======= ======= try: interpolated_config = i.interpolate(stream.read()) base = self.merge_dicts(base, >>>>>>> b1eb06d375fd544a849fcf5c39f51dc334b87338:Rake/molecule/__GEMS_.py/__GEMS_.py/apt-py.git/commandinit.yaml/init.yml/config.py >>>>>>> e91355cf081d9dcd78efe38cdcc6f0353a1aa3ac util.safe_load(interpolated_config)) except interpolation.InvalidInterpolation as e: msg = ("parsing config file '{}'.\n\n" '{}\n{}'.format(self.molecule_file, e.place, e.string)) util.sysexit_with_message(msg) schema.validate(base) <<<<<<< HEAD <<<<<<< HEAD:Rake/molecule/__GEMS_.py/__GEMS_.py/apt-py.git/commandinit.yaml/init.yml/config.py return base ======= ======= <<<<<<< HEAD:molecule/config.py >>>>>>> e91355cf081d9dcd78efe38cdcc6f0353a1aa3ac def _interpolate(self, stream, env, keep_string): env = self._set_env(env) i = interpolation.Interpolator(interpolation.TemplateWithDefaults, env)
def _validate_template_dir(self, template_dir): if not os.path.isdir(template_dir): util.sysexit_with_message("The specified template directory (" + str(template_dir) + ") does not exist")
def _allowed(): # pragma: no cover if distutils.version.LooseVersion( ansible.__version__) <= distutils.version.LooseVersion('2.2'): msg = ("Ansible version '{}' not supported. Molecule only supports " 'versions >= 2.2.').format(ansible.__version__) util.sysexit_with_message(msg)
def _check_errors(self, errors): if errors: msg = "Failed to validate.\n\n{}".format(errors) util.sysexit_with_message(msg)
def sanity_checks(self): if not which("vagrant"): util.sysexit_with_message("vagrant executable was not found!")
def _preflight(self, data): errors = schema_v2.pre_validate(data) if errors: msg = "Failed to validate.\n\n{}".format(errors) util.sysexit_with_message(msg)
def _exit_with_invalid_section(self, section, name): msg = "Invalid {} named '{}' configured.".format(section, name) util.sysexit_with_message(msg)
<<<<<<< HEAD:Rake/molecule/__GEMS_.py/__GEMS_.py/apt-py.git/commandinit.yaml/login.py if not c.state.created and (c.driver.delegated and not c.driver.managed): ======= if ((not c.state.created) and c.driver.managed): >>>>>>> 0fa82e7a3daa84ebd03d8af67403c6551113d3e4:molecule/command/login.py ======= <<<<<<< HEAD:molecule/command/login.py if ((not c.state.created) and c.driver.managed): ======= if not c.state.created and (c.driver.delegated and not c.driver.managed): >>>>>>> b1eb06d375fd544a849fcf5c39f51dc334b87338:Rake/molecule/__GEMS_.py/__GEMS_.py/apt-py.git/commandinit.yaml/login.py >>>>>>> e91355cf081d9dcd78efe38cdcc6f0353a1aa3ac msg = 'Instances not created. Please create instances first.' util.sysexit_with_message(msg) hosts = [d['name'] for d in self._config.platforms.instances] hostname = self._get_hostname(hosts) self._get_login(hostname) def _get_hostname(self, hosts): hostname = self._config.command_args.get('host') if hostname is None: if len(hosts) == 1: hostname = hosts[0] else: msg = ('There are {} running hosts. Please specify ' 'which with --host.\n\n' 'Available hosts:\n{}'.format( len(hosts), '\n'.join(sorted(hosts))))