def test_merge_dicts(): # Example taken from python-anyconfig/anyconfig/__init__.py a = {'b': [{'c': 0}, {'c': 2}], 'd': {'e': 'aaa', 'f': 3}} b = {'a': 1, 'b': [{'c': 3}], 'd': {'e': 'bbb'}} expected = {'a': 1, 'b': [{'c': 0}, {'c': 2}, {'c': 3}], 'd': {'e': "bbb", 'f': 3}} result = util.merge_dicts(a, b) assert expected == result
def _reget_config(self): """ Perform the same prioritized recursive merge from `get_config`. Interpolates the ``keep_string`` left behind in the original ``get_config`` call. This is probably __very__ bad. :return: dict """ env = util.merge_dicts(os.environ, self.env) env = set_env_from_file(env, self.env_file) return self._combine(env=env)
def validate(c): """Perform schema validation.""" schema = base_schema # Dependency if c['dependency']['name'] == 'shell': schema = util.merge_dicts(schema, dependency_command_nullable_schema) # Driver if c['driver']['name'] == 'docker': schema = util.merge_dicts(schema, platforms_docker_schema) elif c['driver']['name'] == 'podman': schema = util.merge_dicts(schema, platforms_podman_schema) # Verifier schema = util.merge_dicts(schema, api.verifiers()[c['verifier']['name']].schema()) v = Validator(allow_unknown=True) v.validate(c, schema) return v.errors
def default_env(self): env = util.merge_dicts(os.environ.copy(), self._config.env) env = util.merge_dicts( env, { 'ANSIBLE_CONFIG': self._config.provisioner.config_file, 'ANSIBLE_ROLES_PATH': ':'.join([ util.abs_path( os.path.join(self._config.scenario.ephemeral_directory, 'roles')), util.abs_path( os.path.join(self._config.project_directory, os.path.pardir)), ]), 'ANSIBLE_LIBRARY': ':'.join([ self._get_libraries_directory(), util.abs_path( os.path.join(self._config.scenario.ephemeral_directory, 'library')), util.abs_path( os.path.join(self._config.project_directory, 'library')), ]), 'ANSIBLE_FILTER_PLUGINS': ':'.join([ self._get_filter_plugin_directory(), util.abs_path( os.path.join(self._config.scenario.ephemeral_directory, 'plugins', 'filters')), util.abs_path( os.path.join(self._config.project_directory, 'plugins', 'filters')), ]), }) env = util.merge_dicts(env, self._config.env) return env
def validate(c): """Perform schema validation.""" schema = base_schema # Dependency if c["dependency"]["name"] == "shell": schema = util.merge_dicts(schema, dependency_command_nullable_schema) # Driver if c["driver"]["name"] == "docker": schema = util.merge_dicts(schema, platforms_docker_schema) elif c["driver"]["name"] == "podman": schema = util.merge_dicts(schema, platforms_podman_schema) # Verifier schema = util.merge_dicts(schema, api.verifiers()[c["verifier"]["name"]].schema()) v = Validator(allow_unknown=True) v.validate(c, schema) return v.errors
def default_options(self): general = super(Roles, self).default_options specific = util.merge_dicts( general, { "role-file": os.path.join(self._config.scenario.directory, "requirements.yml"), "roles-path": os.path.join(self._config.scenario.ephemeral_directory, "roles"), }, ) return specific
def _config(_molecule_file, request): with open(_molecule_file) as f: d = util.safe_load(f) if hasattr(request, "param"): if isinstance(request.getfixturevalue(request.param), str): d2 = util.safe_load(request.getfixturevalue(request.param)) else: d2 = request.getfixturevalue(request.param) # print(100, d) # print(200, d2) d = util.merge_dicts(d, d2) # print(300, d) return d
def molecule_data( _molecule_dependency_galaxy_section_data, _molecule_driver_section_data, _molecule_lint_section_data, _molecule_platforms_section_data, _molecule_provisioner_section_data, _molecule_scenario_section_data, _molecule_verifier_section_data): fixtures = [ _molecule_dependency_galaxy_section_data, _molecule_driver_section_data, _molecule_lint_section_data, _molecule_platforms_section_data, _molecule_provisioner_section_data, _molecule_scenario_section_data, _molecule_verifier_section_data ] return functools.reduce(lambda x, y: util.merge_dicts(x, y), fixtures)
def execute(self, exit=True): ansible = ansible_playbook.AnsiblePlaybook( self._molecule.config.config['ansible'], _env=self._molecule._env) testinfra_options = util.merge_dicts( self._molecule._driver.testinfra_args, self._molecule.config.config['testinfra']) testinfra_options['env'] = ansible.env testinfra_options['debug'] = self._molecule._args.get('--debug', False) testinfra_options['sudo'] = self._molecule._args.get('--sudo', False) tests_glob = self._get_tests() if len(tests_glob) > 0: self._testinfra(tests_glob, **testinfra_options)
def config_instance( molecule_file_fixture: str, molecule_data, request ) -> Generator[config.Config, None, None]: mdc = copy.deepcopy(molecule_data) if hasattr(request, "param"): mdc = util.merge_dicts(mdc, request.getfixturevalue(request.param)) write_molecule_file(molecule_file_fixture, mdc) _environ = dict(os.environ) c = config.Config(molecule_file_fixture) c.command_args = {"subcommand": "test"} yield c # restore environ which can be modified by Config() os.environ.clear() os.environ.update(_environ)
def bake(self): """ Bake an ``ansible-playbook`` command so it's ready to execute and \ returns ``None``. :return: None """ if not self._playbook: return # Pass a directory as inventory to let Ansible merge the multiple # inventory sources located under self.add_cli_arg("inventory", self._config.provisioner.inventory_directory) options = util.merge_dicts(self._config.provisioner.options, self._cli) verbose_flag = util.verbose_flag(options) if self._playbook != self._config.provisioner.playbooks.converge: if options.get("become"): del options["become"] # We do not pass user-specified Ansible arguments to the create and # destroy invocations because playbooks involved in those two # operations are not always provided by end users. And in those cases, # custom Ansible arguments can break the creation and destruction # processes. # # If users need to modify the creation of deletion, they can supply # custom playbooks and specify them in the scenario configuration. if self._config.action not in ["create", "destroy"]: ansible_args = list(self._config.provisioner.ansible_args) + list( self._config.ansible_args) else: ansible_args = [] self._ansible_command = util.BakedCommand( cmd=[ "ansible-playbook", *util.dict2args(options), *util.bool2args(verbose_flag), *ansible_args, self._playbook, # must always go last ], cwd=self._config.scenario.directory, env=self._env, )
def bake(self): """ Bake an ``ansible-playbook`` command so it's ready to execute and \ returns ``None``. :return: None """ if not self._playbook: return # Pass a directory as inventory to let Ansible merge the multiple # inventory sources located under self.add_cli_arg("inventory", self._config.provisioner.inventory_directory) options = util.merge_dicts(self._config.provisioner.options, self._cli) verbose_flag = util.verbose_flag(options) if self._playbook != self._config.provisioner.playbooks.converge: if options.get("become"): del options["become"] ansible_args = list(self._config.provisioner.ansible_args) + list( self._config.ansible_args) # if ansible_args: # if self._config.action not in ["create", "destroy"]: # # inserts ansible_args at index 1 # self._ansible_command.cmd.extend(ansible_args) self._ansible_command = util.BakedCommand( cmd=[ "ansible-playbook", *util.dict2args(options), *util.bool2args(verbose_flag), *ansible_args, self._playbook, # must always go last ], cwd=self._config.scenario.directory, env=self._env, stdout=self._out, stderr=self._err, )
def bake(self): """ Bake ansible-galaxy command so it's ready to execute. :return: None """ requirements_file = self._config['ansible']['requirements_file'] roles_path = os.path.join(self._config['molecule']['molecule_dir'], 'roles') galaxy_default_options = { 'force': True, 'role-file': requirements_file, 'roles-path': roles_path } galaxy_options = util.merge_dicts(galaxy_default_options, self._config['ansible']['galaxy']) self._galaxy = sh.ansible_galaxy.bake('install', _env=self.env, _out=self.out, _err=self.err, **galaxy_options)
def _combine(self): """ Perform a prioritized recursive merge of the `molecule_file` with defaults, interpolate the result with environment variables, and returns a new dict. :return: dict """ i = interpolation.Interpolator(interpolation.TemplateWithDefaults, os.environ) base = self._get_defaults() with util.open_file(self.molecule_file) as stream: try: interpolated_config = i.interpolate(stream.read()) base = util.merge_dicts(base, 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) return base
def ansible_connection_options(self, instance_name): try: d = self._get_instance_config(instance_name) plat_conn_opts = next( (item for item in self._config.config.get("platforms", []) if item["name"] == instance_name), {}, ).get("connection_options", {}) conn_opts = util.merge_dicts( { "ansible_user": d["user"], "ansible_host": d["address"], "ansible_port": d["port"], "ansible_private_key_file": d["identity_file"], "connection": "ssh", "ansible_ssh_common_args": " ".join(self.ssh_connection_options), }, plat_conn_opts, ) if conn_opts.get("ansible_connection") == "winrm" and ( not conn_opts.get("ansible_password")): conn_opts[ "ansible_password"] = self._get_windows_instance_pass( d["instance_ids"][0], d["identity_file"]) return conn_opts except StopIteration: return {} except IOError: # Instance has yet to be provisioned , therefore the # instance_config is not on disk. return {}
def bake(self): """ Bake an ``ansible-playbook`` command so it's ready to execute and \ returns ``None``. :return: None """ if not self._playbook: return # Pass a directory as inventory to let Ansible merge the multiple # inventory sources located under self.add_cli_arg("inventory", self._config.provisioner.inventory_directory) options = util.merge_dicts(self._config.provisioner.options, self._cli) verbose_flag = util.verbose_flag(options) if self._playbook != self._config.provisioner.playbooks.converge: if options.get("become"): del options["become"] self._ansible_command = sh.ansible_playbook.bake( options, self._playbook, *verbose_flag, _cwd=self._config.scenario.directory, _env=self._env, _out=self._out, _err=self._err) ansible_args = list(self._config.provisioner.ansible_args) + list( self._config.ansible_args) if ansible_args: if self._config.action not in ["create", "destroy"]: self._ansible_command = self._ansible_command.bake( ansible_args)
def env(self): return util.merge_dicts( self.default_env, self._config.config['verifier']['env'] )
def options(self): return util.merge_dicts( self.default_options, self._config.config['verifier']['options'] )
def test_merge_dicts(a, b, x): assert x == util.merge_dicts(a, b)
def env(self): return util.merge_dicts(self.default_env, self._config.config['dependency']['env'])
def options(self): return util.merge_dicts(self.default_options, self._config.config['dependency']['options'])
def default_env(self): env = util.merge_dicts(os.environ.copy(), self._config.env) env = util.merge_dicts(env, self._config.provisioner.env) return env
def connection_options(self, instance_name): d = self._config.driver.ansible_connection_options(instance_name) return util.merge_dicts( d, self._config.config["provisioner"]["connection_options"] )
def config_options(self): return util.merge_dicts( self.default_config_options, self._config.config["provisioner"]["config_options"], )
def validate(c): schema = copy.deepcopy(base_schema) # Dependency if c['dependency']['name'] == 'shell': util.merge_dicts(schema, dependency_command_nullable_schema) # Driver util.merge_dicts(schema, platforms_base_schema) if c['driver']['name'] == 'docker': util.merge_dicts(schema, platforms_docker_schema) elif c['driver']['name'] == 'vagrant': util.merge_dicts(schema, driver_vagrant_provider_section_schema) util.merge_dicts(schema, platforms_vagrant_schema) else: util.merge_dicts(schema, platforms_base_schema) # Verifier if c['verifier']['name'] == 'goss': util.merge_dicts(schema, verifier_options_readonly_schema) util.merge_dicts(schema, verifier_goss_mutually_exclusive_schema) elif c['verifier']['name'] == 'inspec': util.merge_dicts(schema, verifier_options_readonly_schema) util.merge_dicts(schema, verifier_inspec_mutually_exclusive_schema) elif c['verifier']['name'] == 'testinfra': util.merge_dicts(schema, verifier_testinfra_mutually_exclusive_schema) v = Validator(allow_unknown=True) v.validate(c, schema) return v.errors
def _config(_molecule_file, request): d = util.safe_load(open(_molecule_file)) if hasattr(request, 'param'): d = util.merge_dicts(d, request.getfixturevalue(request.param)) return d
def options(self): return util.merge_dicts(self.default_options, self._config.config["dependency"]["options"])
def default_env(self): return util.merge_dicts(os.environ.copy(), self._config.env)
def molecule_docker_config(molecule_section_data, docker_section_data, ansible_section_data): return reduce( lambda x, y: util.merge_dicts(x, y), [molecule_section_data, docker_section_data, ansible_section_data])
def login_options(self, instance_name): d = {'instance': instance_name} return util.merge_dicts(d, self._get_instance_config(instance_name))
def molecule_openstack_config(molecule_section_data, openstack_section_data, ansible_section_data): return reduce( lambda x, y: util.merge_dicts(x, y), [molecule_section_data, openstack_section_data, ansible_section_data])
def env(self): return util.merge_dicts(self.default_env, self._config.config["dependency"]["env"])
def env(self): return util.merge_dicts(self._config.env, os.environ)