def setUp(self):
        super(TestConfig, self).setUp()

        self.data = {
            'playbook':
            'playbook.yml',
            'config_file':
            'test.cfg',
            'limit':
            'all',
            'verbose':
            'vvvv',
            'diff':
            True,
            'host_key_checking':
            False,
            'raw_ssh_args': [
                '-o UserKnownHostsFile=/dev/null', '-o IdentitiesOnly=yes',
                '-o ControlMaster=auto', '-o ControlPersist=60s'
            ],
            'raw_env_vars': {
                'TEST_1': 'test_1'
            }
        }

        self.ansible = AnsiblePlaybook(self.data)
Пример #2
0
    def execute(self, exit=True):

        self.molecule._create_templates()

        ansible = AnsiblePlaybook(self.molecule._config.config['ansible'])
        ansible.add_cli_arg('syntax-check', True)

        return ansible.execute(hide_errors=True)
Пример #3
0
    def test_inventory_generation(self):
        self._mock_molecule._provisioner = provisioners.get_provisioner(
            self._mock_molecule)
        self._mock_molecule._provisioner.destroy()
        self._mock_molecule._provisioner.up()

        self._mock_molecule._create_inventory_file()

        self.book = self._mock_molecule._provisioner.ansible_connection_params
        self.book['playbook'] = 'tests/playbook.yml'
        self.book['inventory'] = 'tests/ansible_inventory'

        self.ansible = AnsiblePlaybook(self.book)

        self.assertEqual((None, ''), self.ansible.execute())
Пример #4
0
    def test_provision(self):

        docker_provisioner = provisioners.DockerProvisioner(
            self._mock_molecule)
        docker_provisioner.destroy()
        docker_provisioner.up()

        self.book = docker_provisioner.ansible_connection_params
        self.book['playbook'] = 'tests/playbook.yml'
        self.book['inventory'] = 'test1,test2,'

        self.ansible = AnsiblePlaybook(self.book)

        self.assertEqual((None, ''), self.ansible.execute())

        docker_provisioner.destroy()
Пример #5
0
    def test_inventory_generation(self):
        self._mock_molecule._provisioner = provisioners.get_provisioner(self._mock_molecule)
        self._mock_molecule._provisioner.destroy()
        self._mock_molecule._provisioner.up()

        self._mock_molecule._create_inventory_file()

        self.book = self._mock_molecule._provisioner.ansible_connection_params
        self.book['playbook'] = 'tests/playbook.yml'
        self.book['inventory'] = 'tests/ansible_inventory'

        self.ansible = AnsiblePlaybook(self.book)

        self.assertEqual((None, ''), self.ansible.execute())
Пример #6
0
    def test_provision(self):

        docker_provisioner = provisioners.DockerProvisioner(self._mock_molecule)
        docker_provisioner.destroy()
        docker_provisioner.up()

        self.book = docker_provisioner.ansible_connection_params
        self.book['playbook'] = 'tests/playbook.yml'
        self.book['inventory'] = 'test1,test2,'

        self.ansible = AnsiblePlaybook(self.book)

        self.assertEqual((None, ''), self.ansible.execute())

        docker_provisioner.destroy()
Пример #7
0
    def setUp(self):
        super(TestConfig, self).setUp()

        self.data = {
            'playbook': 'playbook.yml',
            'config_file': 'test.cfg',
            'limit': 'all',
            'verbose': 'vvvv',
            'diff': True,
            'host_key_checking': False,
            'raw_ssh_args': [
                '-o UserKnownHostsFile=/dev/null', '-o IdentitiesOnly=yes',
                '-o ControlMaster=auto', '-o ControlPersist=60s'
            ],
            'raw_env_vars': {
                'TEST_1': 'test_1'
            }
        }

        self.ansible = AnsiblePlaybook(self.data)
class TestConfig(testtools.TestCase):
    def setUp(self):
        super(TestConfig, self).setUp()

        self.data = {
            'playbook':
            'playbook.yml',
            'config_file':
            'test.cfg',
            'limit':
            'all',
            'verbose':
            'vvvv',
            'diff':
            True,
            'host_key_checking':
            False,
            'raw_ssh_args': [
                '-o UserKnownHostsFile=/dev/null', '-o IdentitiesOnly=yes',
                '-o ControlMaster=auto', '-o ControlPersist=60s'
            ],
            'raw_env_vars': {
                'TEST_1': 'test_1'
            }
        }

        self.ansible = AnsiblePlaybook(self.data)

    def test_arg_loading(self):
        # string value set
        self.assertEqual(self.ansible.cli['limit'], self.data['limit'])

        # true value set
        self.assertEqual(self.ansible.cli['diff'], self.data['diff'])

        # false values don't exist in arg dict at all
        self.assertIsNone(self.ansible.cli.get('sudo_user'))

    def test_parse_arg_special_cases(self):
        # raw environment variables are set
        self.assertIsNone(self.ansible.cli.get('raw_env_vars'))
        self.assertEqual(self.ansible.env['TEST_1'],
                         self.data['raw_env_vars']['TEST_1'])

        # raw_ssh_args set
        self.assertIsNone(self.ansible.cli.get('raw_ssh_args'))
        self.assertEqual(self.ansible.env['ANSIBLE_SSH_ARGS'],
                         ' '.join(self.data['raw_ssh_args']))

        # host_key_checking gets set in environment as string 'false'
        self.assertIsNone(self.ansible.cli.get('host_key_checking'))
        self.assertEqual(self.ansible.env['ANSIBLE_HOST_KEY_CHECKING'],
                         'false')

        # config_file is set in environment
        self.assertIsNone(self.ansible.cli.get('config_file'))
        self.assertEqual(self.ansible.env['ANSIBLE_CONFIG'],
                         self.data['config_file'])

        # playbook is set as attribute
        self.assertIsNone(self.ansible.cli.get('playbook'))
        self.assertEqual(self.ansible.playbook, self.data['playbook'])

        # verbose is set in the right place
        self.assertIsNone(self.ansible.cli.get('verbose'))
        self.assertIn('-' + self.data['verbose'], self.ansible.cli_pos)

    def test_add_cli_arg(self):
        # redefine a previously defined value
        self.ansible.add_cli_arg('limit', 'test')
        self.assertEqual(self.ansible.cli['limit'], 'test')

        # add a new value
        self.ansible.add_cli_arg('molecule_1', 'test')
        self.assertEqual(self.ansible.cli['molecule_1'], 'test')

        # values set as false shouldn't get added
        self.ansible.add_cli_arg('molecule_2', None)
        self.assertNotIn('molecule_2', self.ansible.cli)

    def test_remove_cli_arg(self):
        self.ansible.remove_cli_arg('limit')
        self.assertNotIn('limit', self.ansible.cli)

    def test_add_env_arg(self):
        # redefine a previously defined value
        self.ansible.add_env_arg('TEST_1', 'now')
        self.assertEqual(self.ansible.env['TEST_1'], 'now')

        # add a new value
        self.ansible.add_env_arg('MOLECULE_1', 'test')
        self.assertEqual(self.ansible.env['MOLECULE_1'], 'test')

    def test_remove_env_arg(self):
        self.ansible.remove_env_arg('TEST_1')
        self.assertNotIn('TEST_1', self.ansible.env)
Пример #9
0
    def execute(self,
                idempotent=False,
                create_instances=True,
                create_inventory=True,
                exit=True,
                hide_errors=True):
        """
        :param idempotent: Optionally provision servers quietly so output can be parsed for idempotence
        :param create_inventory: Toggle inventory creation
        :param create_instances: Toggle instance creation
        :return: Provisioning output
        """
        if self.molecule._state.get('created'):
            create_instances = False

        if self.molecule._state.get('converged'):
            create_inventory = False

        if self.static:
            create_instances = False
            create_inventory = False

        if create_instances and not idempotent:
            command_args, args = utilities.remove_args(self.command_args,
                                                       self.args, ['--tags'])
            c = Create(command_args, args, self.molecule)
            c.execute()

        if create_inventory:
            self.molecule._create_inventory_file()

        # install role dependencies only during `molecule converge`
        if not idempotent and 'requirements_file' in self.molecule._config.config[
                'ansible']:
            print('{}Installing role dependencies ...{}'.format(
                colorama.Fore.CYAN, colorama.Fore.RESET))
            galaxy_install = AnsibleGalaxyInstall(self.molecule._config.config[
                'ansible']['requirements_file'])
            galaxy_install.add_env_arg(
                'ANSIBLE_CONFIG',
                self.molecule._config.config['ansible']['config_file'])
            galaxy_install.bake()
            output = galaxy_install.execute()

        ansible = AnsiblePlaybook(self.molecule._config.config['ansible'])

        # params to work with provisioner
        for k, v in self.molecule._provisioner.ansible_connection_params.items(
        ):
            ansible.add_cli_arg(k, v)

        # target tags passed in via CLI
        if self.molecule._args.get('--tags'):
            ansible.add_cli_arg('tags', self.molecule._args['--tags'].pop(0))

        if idempotent:
            ansible.remove_cli_arg('_out')
            ansible.remove_cli_arg('_err')
            ansible.add_env_arg('ANSIBLE_NOCOLOR', 'true')
            ansible.add_env_arg('ANSIBLE_FORCE_COLOR', 'false')

            # Save the previous callback plugin if any.
            callback_plugin = ansible.env.get('ANSIBLE_CALLBACK_PLUGINS', '')

            # Set the idempotence plugin.
            if callback_plugin:
                ansible.add_env_arg(
                    'ANSIBLE_CALLBACK_PLUGINS',
                    callback_plugin + ':' + os.path.join(
                        sys.prefix,
                        'share/molecule/ansible/plugins/callback/idempotence'))
            else:
                ansible.add_env_arg('ANSIBLE_CALLBACK_PLUGINS', os.path.join(
                    sys.prefix,
                    'share/molecule/ansible/plugins/callback/idempotence'))

        ansible.bake()
        if self.molecule._args.get('--debug'):
            ansible_env = {k: v
                           for (k, v) in ansible.env.items() if 'ANSIBLE' in k}
            other_env = {k: v
                         for (k, v) in ansible.env.items()
                         if 'ANSIBLE' not in k}
            utilities.debug('OTHER ENVIRONMENT',
                            yaml.dump(other_env,
                                      default_flow_style=False,
                                      indent=2))
            utilities.debug('ANSIBLE ENVIRONMENT',
                            yaml.dump(ansible_env,
                                      default_flow_style=False,
                                      indent=2))
            utilities.debug('ANSIBLE PLAYBOOK', str(ansible.ansible))

        status, output = ansible.execute(hide_errors=hide_errors)
        if status is not None:
            if exit:
                sys.exit(status)
            return status, None

        if not self.molecule._state.get('converged'):
            self.molecule._state['converged'] = True
            self.molecule._write_state_file()

        return None, output
Пример #10
0
class TestConfig(testtools.TestCase):
    def setUp(self):
        super(TestConfig, self).setUp()

        self.data = {
            'playbook': 'playbook.yml',
            'config_file': 'test.cfg',
            'limit': 'all',
            'verbose': 'vvvv',
            'diff': True,
            'host_key_checking': False,
            'raw_ssh_args': [
                '-o UserKnownHostsFile=/dev/null', '-o IdentitiesOnly=yes',
                '-o ControlMaster=auto', '-o ControlPersist=60s'
            ],
            'raw_env_vars': {
                'TEST_1': 'test_1'
            }
        }

        self.ansible = AnsiblePlaybook(self.data)

    def test_arg_loading(self):
        # string value set
        self.assertEqual(self.ansible.cli['limit'], self.data['limit'])

        # true value set
        self.assertEqual(self.ansible.cli['diff'], self.data['diff'])

        # false values don't exist in arg dict at all
        self.assertIsNone(self.ansible.cli.get('sudo_user'))

    def test_parse_arg_special_cases(self):
        # raw environment variables are set
        self.assertIsNone(self.ansible.cli.get('raw_env_vars'))
        self.assertEqual(self.ansible.env['TEST_1'],
                         self.data['raw_env_vars']['TEST_1'])

        # raw_ssh_args set
        self.assertIsNone(self.ansible.cli.get('raw_ssh_args'))
        self.assertEqual(self.ansible.env['ANSIBLE_SSH_ARGS'],
                         ' '.join(self.data['raw_ssh_args']))

        # host_key_checking gets set in environment as string 'false'
        self.assertIsNone(self.ansible.cli.get('host_key_checking'))
        self.assertEqual(self.ansible.env['ANSIBLE_HOST_KEY_CHECKING'],
                         'false')

        # config_file is set in environment
        self.assertIsNone(self.ansible.cli.get('config_file'))
        self.assertEqual(self.ansible.env['ANSIBLE_CONFIG'],
                         self.data['config_file'])

        # playbook is set as attribute
        self.assertIsNone(self.ansible.cli.get('playbook'))
        self.assertEqual(self.ansible.playbook, self.data['playbook'])

        # verbose is set in the right place
        self.assertIsNone(self.ansible.cli.get('verbose'))
        self.assertIn('-' + self.data['verbose'], self.ansible.cli_pos)

    def test_add_cli_arg(self):
        # redefine a previously defined value
        self.ansible.add_cli_arg('limit', 'test')
        self.assertEqual(self.ansible.cli['limit'], 'test')

        # add a new value
        self.ansible.add_cli_arg('molecule_1', 'test')
        self.assertEqual(self.ansible.cli['molecule_1'], 'test')

        # values set as false shouldn't get added
        self.ansible.add_cli_arg('molecule_2', None)
        self.assertNotIn('molecule_2', self.ansible.cli)

    def test_remove_cli_arg(self):
        self.ansible.remove_cli_arg('limit')
        self.assertNotIn('limit', self.ansible.cli)

    def test_add_env_arg(self):
        # redefine a previously defined value
        self.ansible.add_env_arg('TEST_1', 'now')
        self.assertEqual(self.ansible.env['TEST_1'], 'now')

        # add a new value
        self.ansible.add_env_arg('MOLECULE_1', 'test')
        self.assertEqual(self.ansible.env['MOLECULE_1'], 'test')

    def test_remove_env_arg(self):
        self.ansible.remove_env_arg('TEST_1')
        self.assertNotIn('TEST_1', self.ansible.env)
Пример #11
0
    def execute(self, exit=True):
        if self.static:
            self.disabled('verify')

        serverspec_dir = self.molecule._config.config['molecule'][
            'serverspec_dir']
        testinfra_dir = self.molecule._config.config['molecule'][
            'testinfra_dir']
        inventory_file = self.molecule._config.config['ansible'][
            'inventory_file']
        rakefile = self.molecule._config.config['molecule']['rakefile_file']
        ignore_paths = self.molecule._config.config['molecule']['ignore_paths']

        # whitespace & trailing newline check
        validators.check_trailing_cruft(ignore_paths=ignore_paths, exit=exit)

        # no serverspec or testinfra
        if not os.path.isdir(serverspec_dir) and not os.path.isdir(
                testinfra_dir):
            msg = '{}Skipping tests, could not find {}/ or {}/.{}'
            print(
                msg.format(Fore.YELLOW, serverspec_dir, testinfra_dir,
                           Fore.RESET))
            return None, None

        self.molecule._write_ssh_config()
        # testinfra's Ansible calls get same env vars as ansible-playbook
        ansible = AnsiblePlaybook(self.molecule._config.config['ansible'],
                                  _env=self.molecule._env)
        kwargs = {'env': ansible.env}
        kwargs['env']['PYTHONDONTWRITEBYTECODE'] = '1'
        kwargs['debug'] = True if self.molecule._args.get('--debug') else False

        try:
            # testinfra
            if os.path.isdir(testinfra_dir):
                msg = '\n{}Executing testinfra tests found in {}/.{}'
                print(msg.format(Fore.MAGENTA, testinfra_dir, Fore.RESET))
                validators.testinfra(inventory_file, testinfra_dir, **kwargs)
                print()
            else:
                msg = '{}No testinfra tests found in {}/.\n{}'
                print(msg.format(Fore.YELLOW, testinfra_dir, Fore.RESET))

            # serverspec / rubocop
            if os.path.isdir(serverspec_dir):
                msg = '{}Executing rubocop on *.rb files found in {}/.{}'
                print(msg.format(Fore.MAGENTA, serverspec_dir, Fore.RESET))
                validators.rubocop(serverspec_dir, **kwargs)
                print()

                msg = '{}Executing serverspec tests found in {}/.{}'
                print(msg.format(Fore.MAGENTA, serverspec_dir, Fore.RESET))
                validators.rake(rakefile, **kwargs)
                print()
            else:
                msg = '{}No serverspec tests found in {}/.\n{}'
                print(msg.format(Fore.YELLOW, serverspec_dir, Fore.RESET))
        except sh.ErrorReturnCode as e:
            print('ERROR: {}'.format(e))
            if exit:
                sys.exit(e.exit_code)
            return e.exit_code, None

        return None, None
Пример #12
0
    def execute(self,
                idempotent=False,
                create_instances=True,
                create_inventory=True,
                exit=True,
                hide_errors=True):
        """
        :param idempotent: Optionally provision servers quietly so output can be parsed for idempotence
        :param create_inventory: Toggle inventory creation
        :param create_instances: Toggle instance creation
        :return: Provisioning output
        """
        if self.molecule._state.get('created'):
            create_instances = False

        if self.molecule._state.get('converged'):
            create_inventory = False

        if self.static:
            create_instances = False
            create_inventory = False

        if create_instances and not idempotent:
            command_args, args = utilities.remove_args(self.command_args,
                                                       self.args, ['--tags'])
            c = Create(command_args, args, self.molecule)
            c.execute()

        if create_inventory:
            self.molecule._create_inventory_file()

        # install role dependencies only during `molecule converge`
        if not idempotent and 'requirements_file' in self.molecule._config.config[
                'ansible']:
            print('{}Installing role dependencies ...{}'.format(
                Fore.CYAN, Fore.RESET))
            galaxy_install = AnsibleGalaxyInstall(
                self.molecule._config.config['ansible']['requirements_file'])
            galaxy_install.add_env_arg(
                'ANSIBLE_CONFIG',
                self.molecule._config.config['ansible']['config_file'])
            galaxy_install.bake()
            output = galaxy_install.execute()

        ansible = AnsiblePlaybook(self.molecule._config.config['ansible'])

        # target tags passed in via CLI
        if self.molecule._args.get('--tags'):
            ansible.add_cli_arg('tags', self.molecule._args['--tags'].pop(0))

        if idempotent:
            ansible.remove_cli_arg('_out')
            ansible.remove_cli_arg('_err')
            ansible.add_env_arg('ANSIBLE_NOCOLOR', 'true')
            ansible.add_env_arg('ANSIBLE_FORCE_COLOR', 'false')

            # Save the previous callback plugin if any.
            callback_plugin = ansible.env.get('ANSIBLE_CALLBACK_PLUGINS', '')

            # Set the idempotence plugin.
            if callback_plugin:
                ansible.add_env_arg(
                    'ANSIBLE_CALLBACK_PLUGINS',
                    callback_plugin + ':' + os.path.join(
                        sys.prefix,
                        'share/molecule/ansible/plugins/callback/idempotence'))
            else:
                ansible.add_env_arg(
                    'ANSIBLE_CALLBACK_PLUGINS',
                    os.path.join(
                        sys.prefix,
                        'share/molecule/ansible/plugins/callback/idempotence'))

        ansible.bake()
        if self.molecule._args.get('--debug'):
            ansible_env = {
                k: v
                for (k, v) in ansible.env.items() if 'ANSIBLE' in k
            }
            other_env = {
                k: v
                for (k, v) in ansible.env.items() if 'ANSIBLE' not in k
            }
            utilities.debug(
                'OTHER ENVIRONMENT',
                yaml.dump(other_env, default_flow_style=False, indent=2))
            utilities.debug(
                'ANSIBLE ENVIRONMENT',
                yaml.dump(ansible_env, default_flow_style=False, indent=2))
            utilities.debug('ANSIBLE PLAYBOOK', str(ansible.ansible))

        status, output = ansible.execute(hide_errors=hide_errors)
        if status is not None:
            if exit:
                sys.exit(status)
            return status, None

        if not self.molecule._state.get('converged'):
            self.molecule._state['converged'] = True
            self.molecule._write_state_file()

        return None, output
Пример #13
0
class TestDockerProvisioner(testtools.TestCase):
    def setUp(self):
        super(TestDockerProvisioner, self).setUp()
        # Setup mock molecule
        self._mock_molecule = Molecule(dict())

        self.temp = '/tmp/test_config_load_defaults_external_file.yml'
        data = {
            'molecule': {
                'molecule_dir': '.test_molecule',
                'inventory_file': 'tests/ansible_inventory'
            },

            'docker': {
                'containers': [
                    {'name': 'test1',
                     'image': 'ubuntu',
                     'image_version': 'latest',
                     'ansible_groups': ['group1']},
                    {'name': 'test2',
                     'image': 'ubuntu',
                     'image_version': 'latest',
                     'ansible_groups': ['group2']}
                ]
            },
            'ansible': {
                'config_file': 'test_config',
                'inventory_file': 'test_inventory'
            }
        }

        with open(self.temp, 'w') as f:
            f.write(yaml.dump(data, default_flow_style=True))

        self._mock_molecule._config.load_defaults_file(defaults_file=self.temp)

        self._mock_molecule._state = dict()

    def test_name(self):
        docker_provisioner = provisioners.DockerProvisioner(self._mock_molecule)
        # false values don't exist in arg dict at all
        self.assertEqual(docker_provisioner.name, 'docker')

    def test_get_provisioner(self):
        self.assertEqual(provisioners.get_provisioner(self._mock_molecule).name, 'docker')

    def test_up(self):
        docker_provisioner = provisioners.DockerProvisioner(self._mock_molecule)
        docker_provisioner.up()
        docker_provisioner.destroy()

    def test_instances(self):
        docker_provisioner = provisioners.DockerProvisioner(self._mock_molecule)
        self.assertEqual(docker_provisioner.instances[0]['name'], 'test1')
        self.assertEqual(docker_provisioner.instances[1]['name'], 'test2')

    def test_status(self):
        docker_provisioner = provisioners.DockerProvisioner(self._mock_molecule)

        docker_provisioner.up()

        self.assertEquals('test1', docker_provisioner.status()[1].name)
        self.assertEquals('test2', docker_provisioner.status()[0].name)

        self.assertIn('Up', docker_provisioner.status()[1].state)
        self.assertIn('Up', docker_provisioner.status()[0].state)

        self.assertEqual('docker', docker_provisioner.status()[0].provider)
        self.assertEqual('docker', docker_provisioner.status()[1].provider)

    def test_destroy(self):
        docker_provisioner = provisioners.DockerProvisioner(self._mock_molecule)

        docker_provisioner.up()

        self.assertEquals('test1', docker_provisioner.status()[1].name)
        self.assertEquals('test2', docker_provisioner.status()[0].name)

        self.assertIn('Up', docker_provisioner.status()[1].state)
        self.assertIn('Up', docker_provisioner.status()[0].state)

        docker_provisioner.destroy()

        self.assertIn('Not Created', docker_provisioner.status()[1].state)
        self.assertIn('Not Created', docker_provisioner.status()[0].state)

    def test_provision(self):

        docker_provisioner = provisioners.DockerProvisioner(self._mock_molecule)
        docker_provisioner.destroy()
        docker_provisioner.up()

        self.book = docker_provisioner.ansible_connection_params
        self.book['playbook'] = 'tests/playbook.yml'
        self.book['inventory'] = 'test1,test2,'

        self.ansible = AnsiblePlaybook(self.book)

        self.assertEqual((None, ''), self.ansible.execute())

        docker_provisioner.destroy()

    def test_inventory_generation(self):
        self._mock_molecule._provisioner = provisioners.get_provisioner(self._mock_molecule)
        self._mock_molecule._provisioner.destroy()
        self._mock_molecule._provisioner.up()

        self._mock_molecule._create_inventory_file()

        self.book = self._mock_molecule._provisioner.ansible_connection_params
        self.book['playbook'] = 'tests/playbook.yml'
        self.book['inventory'] = 'tests/ansible_inventory'

        self.ansible = AnsiblePlaybook(self.book)

        self.assertEqual((None, ''), self.ansible.execute())
Пример #14
0
    def execute(self, exit=True):
        if self.static:
            self.disabled('verify')

        serverspec_dir = self.molecule._config.config['molecule'][
            'serverspec_dir']
        testinfra_dir = self.molecule._config.config['molecule'][
            'testinfra_dir']
        rakefile = self.molecule._config.config['molecule']['rakefile_file']
        ignore_paths = self.molecule._config.config['molecule']['ignore_paths']

        # whitespace & trailing newline check
        validators.check_trailing_cruft(ignore_paths=ignore_paths, exit=exit)

        # no serverspec or testinfra
        if not os.path.isdir(serverspec_dir) and not os.path.isdir(
                testinfra_dir):
            msg = '{}Skipping tests, could not find {}/ or {}/.{}'
            utilities.logger.warning(
                msg.format(colorama.Fore.YELLOW, serverspec_dir, testinfra_dir,
                           colorama.Fore.RESET))
            return None, None

        self.molecule._write_ssh_config()

        # testinfra's Ansible calls get same env vars as ansible-playbook
        ansible = AnsiblePlaybook(self.molecule._config.config['ansible'],
                                  _env=self.molecule._env)

        testinfra_kwargs = self.molecule._provisioner.testinfra_args
        serverspec_kwargs = self.molecule._provisioner.serverspec_args
        testinfra_kwargs['env'] = ansible.env
        testinfra_kwargs['env']['PYTHONDONTWRITEBYTECODE'] = '1'
        testinfra_kwargs['debug'] = True if self.molecule._args.get(
            '--debug') else False
        testinfra_kwargs['sudo'] = True if self.molecule._args.get(
            '--sudo') else False
        serverspec_kwargs['env'] = testinfra_kwargs['env']
        serverspec_kwargs['debug'] = testinfra_kwargs['debug']

        try:
            # testinfra
            if len(glob.glob1(testinfra_dir, "test_*.py")) > 0:
                msg = '\n{}Executing testinfra tests found in {}/.{}'
                print(
                    msg.format(colorama.Fore.MAGENTA, testinfra_dir,
                               colorama.Fore.RESET))
                validators.testinfra(testinfra_dir, **testinfra_kwargs)
                print()
            else:
                msg = '{}No testinfra tests found in {}/.\n{}'
                utilities.logger.warning(
                    msg.format(colorama.Fore.YELLOW, testinfra_dir,
                               colorama.Fore.RESET))

            # serverspec / rubocop
            if os.path.isdir(serverspec_dir):
                msg = '{}Executing rubocop on *.rb files found in {}/.{}'
                print(
                    msg.format(colorama.Fore.MAGENTA, serverspec_dir,
                               colorama.Fore.RESET))
                validators.rubocop(serverspec_dir, **serverspec_kwargs)
                print()

                msg = '{}Executing serverspec tests found in {}/.{}'
                print(
                    msg.format(colorama.Fore.MAGENTA, serverspec_dir,
                               colorama.Fore.RESET))
                validators.rake(rakefile, **serverspec_kwargs)
                print()
            else:
                msg = '{}No serverspec tests found in {}/.\n{}'
                utilities.logger.warning(
                    msg.format(colorama.Fore.YELLOW, serverspec_dir,
                               colorama.Fore.RESET))
        except sh.ErrorReturnCode as e:
            utilities.logger.error('ERROR: {}'.format(e))
            if exit:
                sys.exit(e.exit_code)
            return e.exit_code, e.stdout

        return None, None
Пример #15
0
    def execute(self, idempotent=False, create_instances=True, create_inventory=True):
        """
        Provisions all instances using ansible-playbook.

        :param idempotent: Optionally provision servers quietly so output can be parsed for idempotence
        :param create_inventory: Toggle inventory creation
        :param create_instances: Toggle instance creation
        :return: Provisioning output
        """

        if self.molecule._state.get('created'):
            create_instances = False

        if self.molecule._state.get('converged'):
            create_inventory = False

        if self.static:
            create_instances = False
            create_inventory = False

        if create_instances and not idempotent:
            c = Create(self.args, self.molecule)
            c.execute()

        if create_inventory:
            self.molecule._create_inventory_file()

        ansible = AnsiblePlaybook(self.molecule._config.config['ansible'])

        # target tags passed in via CLI
        ansible.add_cli_arg('tags', self.molecule._args.get('--tags'))

        if idempotent:
            ansible.remove_cli_arg('_out')
            ansible.remove_cli_arg('_err')
            ansible.add_env_arg('ANSIBLE_NOCOLOR', 'true')
            ansible.add_env_arg('ANSIBLE_FORCE_COLOR', 'false')

            # Save the previous callback plugin if any.
            callback_plugin = ansible.env.get('ANSIBLE_CALLBACK_PLUGINS', '')

            # Set the idempotence plugin.
            if callback_plugin:
                ansible.add_env_arg('ANSIBLE_CALLBACK_PLUGINS', callback_plugin + ':' + os.path.join(
                    sys.prefix, 'share/molecule/ansible/plugins/callback/idempotence'))
            else:
                ansible.add_env_arg('ANSIBLE_CALLBACK_PLUGINS',
                                    os.path.join(sys.prefix, 'share/molecule/ansible/plugins/callback/idempotence'))

        ansible.bake()
        if self.molecule._args['--debug']:
            ansible_env = {k: v for (k, v) in ansible.env.items() if 'ANSIBLE' in k}
            other_env = {k: v for (k, v) in ansible.env.items() if 'ANSIBLE' not in k}
            utilities.debug('OTHER ENVIRONMENT', yaml.dump(other_env, default_flow_style=False, indent=2))
            utilities.debug('ANSIBLE ENVIRONMENT', yaml.dump(ansible_env, default_flow_style=False, indent=2))
            utilities.debug('ANSIBLE PLAYBOOK', str(ansible.ansible))

        output = ansible.execute()

        if not self.molecule._state.get('converged'):
            self.molecule._state['converged'] = True
            self.molecule._write_state_file()

        return output
Пример #16
0
class TestDockerProvisioner(testtools.TestCase):
    def setUp(self):
        super(TestDockerProvisioner, self).setUp()
        # Setup mock molecule
        self._mock_molecule = Molecule(dict())

        self.temp = '/tmp/test_config_load_defaults_external_file.yml'
        data = {
            'molecule': {
                'molecule_dir': '.test_molecule',
                'inventory_file': 'tests/ansible_inventory'
            },
            'docker': {
                'containers': [{
                    'name': 'test1',
                    'image': 'ubuntu',
                    'image_version': 'latest',
                    'ansible_groups': ['group1']
                }, {
                    'name': 'test2',
                    'image': 'ubuntu',
                    'image_version': 'latest',
                    'ansible_groups': ['group2']
                }]
            },
            'ansible': {
                'config_file': 'test_config',
                'inventory_file': 'test_inventory'
            }
        }

        with open(self.temp, 'w') as f:
            f.write(yaml.dump(data, default_flow_style=True))

        self._mock_molecule._config.load_defaults_file(defaults_file=self.temp)

        self._mock_molecule._state = dict()

    def test_name(self):
        docker_provisioner = provisioners.DockerProvisioner(
            self._mock_molecule)
        # false values don't exist in arg dict at all
        self.assertEqual(docker_provisioner.name, 'docker')

    def test_get_provisioner(self):
        self.assertEqual(
            provisioners.get_provisioner(self._mock_molecule).name, 'docker')

    def test_up(self):
        docker_provisioner = provisioners.DockerProvisioner(
            self._mock_molecule)
        docker_provisioner.up()
        docker_provisioner.destroy()

    def test_instances(self):
        docker_provisioner = provisioners.DockerProvisioner(
            self._mock_molecule)
        self.assertEqual(docker_provisioner.instances[0]['name'], 'test1')
        self.assertEqual(docker_provisioner.instances[1]['name'], 'test2')

    def test_status(self):
        docker_provisioner = provisioners.DockerProvisioner(
            self._mock_molecule)

        docker_provisioner.up()

        self.assertEquals('test1', docker_provisioner.status()[1].name)
        self.assertEquals('test2', docker_provisioner.status()[0].name)

        self.assertIn('Up', docker_provisioner.status()[1].state)
        self.assertIn('Up', docker_provisioner.status()[0].state)

        self.assertEqual('docker', docker_provisioner.status()[0].provider)
        self.assertEqual('docker', docker_provisioner.status()[1].provider)

    def test_destroy(self):
        docker_provisioner = provisioners.DockerProvisioner(
            self._mock_molecule)

        docker_provisioner.up()

        self.assertEquals('test1', docker_provisioner.status()[1].name)
        self.assertEquals('test2', docker_provisioner.status()[0].name)

        self.assertIn('Up', docker_provisioner.status()[1].state)
        self.assertIn('Up', docker_provisioner.status()[0].state)

        docker_provisioner.destroy()

        self.assertIn('Not Created', docker_provisioner.status()[1].state)
        self.assertIn('Not Created', docker_provisioner.status()[0].state)

    def test_provision(self):

        docker_provisioner = provisioners.DockerProvisioner(
            self._mock_molecule)
        docker_provisioner.destroy()
        docker_provisioner.up()

        self.book = docker_provisioner.ansible_connection_params
        self.book['playbook'] = 'tests/playbook.yml'
        self.book['inventory'] = 'test1,test2,'

        self.ansible = AnsiblePlaybook(self.book)

        self.assertEqual((None, ''), self.ansible.execute())

        docker_provisioner.destroy()

    def test_inventory_generation(self):
        self._mock_molecule._provisioner = provisioners.get_provisioner(
            self._mock_molecule)
        self._mock_molecule._provisioner.destroy()
        self._mock_molecule._provisioner.up()

        self._mock_molecule._create_inventory_file()

        self.book = self._mock_molecule._provisioner.ansible_connection_params
        self.book['playbook'] = 'tests/playbook.yml'
        self.book['inventory'] = 'tests/ansible_inventory'

        self.ansible = AnsiblePlaybook(self.book)

        self.assertEqual((None, ''), self.ansible.execute())