Esempio n. 1
0
    def test_module_utils_basic_ansible_module_find_mount_point(self):
        from ansible_collections.notstdlib.moveitallout.plugins.module_utils import basic
        basic._ANSIBLE_ARGS = None

        am = basic.AnsibleModule(
            argument_spec=dict(),
        )

        def _mock_ismount(path):
            if path == b'/':
                return True
            return False

        with patch('os.path.ismount', side_effect=_mock_ismount):
            self.assertEqual(am.find_mount_point('/root/fs/../mounted/path/to/whatever'), '/')

        def _mock_ismount(path):
            if path == b'/subdir/mount':
                return True
            if path == b'/':
                return True
            return False

        with patch('os.path.ismount', side_effect=_mock_ismount):
            self.assertEqual(am.find_mount_point('/subdir/mount/path/to/whatever'), '/subdir/mount')
    def test_module_utils_basic_ansible_module_selinux_default_context(self):
        from ansible_collections.notstdlib.moveitallout.plugins.module_utils import basic
        basic._ANSIBLE_ARGS = None

        am = basic.AnsibleModule(
            argument_spec=dict(),
        )

        am.selinux_initial_context = MagicMock(return_value=[None, None, None, None])
        am.selinux_enabled = MagicMock(return_value=True)

        # we first test the cases where the python selinux lib is not installed
        basic.HAVE_SELINUX = False
        self.assertEqual(am.selinux_default_context(path='/foo/bar'), [None, None, None, None])

        # all following tests assume the python selinux bindings are installed
        basic.HAVE_SELINUX = True

        basic.selinux = Mock()

        with patch.dict('sys.modules', {'selinux': basic.selinux}):
            # next, we test with a mocked implementation of selinux.matchpathcon to simulate
            # an actual context being found
            with patch('selinux.matchpathcon', return_value=[0, 'unconfined_u:object_r:default_t:s0']):
                self.assertEqual(am.selinux_default_context(path='/foo/bar'), ['unconfined_u', 'object_r', 'default_t', 's0'])

            # we also test the case where matchpathcon returned a failure
            with patch('selinux.matchpathcon', return_value=[-1, '']):
                self.assertEqual(am.selinux_default_context(path='/foo/bar'), [None, None, None, None])

            # finally, we test where an OSError occurred during matchpathcon's call
            with patch('selinux.matchpathcon', side_effect=OSError):
                self.assertEqual(am.selinux_default_context(path='/foo/bar'), [None, None, None, None])

        delattr(basic, 'selinux')
Esempio n. 3
0
    def test_tmpdir_property(self, monkeypatch, args, expected, stat_exists):
        makedirs = {'called': False}

        def mock_mkdtemp(prefix, dir):
            return os.path.join(dir, prefix)

        def mock_makedirs(path, mode):
            makedirs['called'] = True
            makedirs['path'] = path
            makedirs['mode'] = mode
            return

        monkeypatch.setattr(tempfile, 'mkdtemp', mock_mkdtemp)
        monkeypatch.setattr(os.path, 'exists', lambda x: stat_exists)
        monkeypatch.setattr(os, 'makedirs', mock_makedirs)
        monkeypatch.setattr(shutil, 'rmtree', lambda x: None)
        monkeypatch.setattr(
            basic, '_ANSIBLE_ARGS',
            to_bytes(json.dumps({'ANSIBLE_MODULE_ARGS': args})))

        with patch('time.time', return_value=42):
            am = basic.AnsibleModule(argument_spec={})
            actual_tmpdir = am.tmpdir

        assert actual_tmpdir == expected

        # verify subsequent calls always produces the same tmpdir
        assert am.tmpdir == actual_tmpdir

        if not stat_exists:
            assert makedirs['called']
            expected = os.path.expanduser(os.path.expandvars(am._remote_tmp))
            assert makedirs['path'] == expected
            assert makedirs['mode'] == 0o700
    def test_options_type_list(self, stdin, options_argspec_list, expected):
        """Test that a basic creation with required and required_if works"""
        # should test ok, tests basic foo requirement and required_if
        am = basic.AnsibleModule(**options_argspec_list)

        assert isinstance(am.params['foobar'], list)
        assert am.params['foobar'] == expected
    def test_module_utils_basic_ansible_module_selinux_enabled(self):
        from ansible_collections.notstdlib.moveitallout.plugins.module_utils import basic
        basic._ANSIBLE_ARGS = None

        am = basic.AnsibleModule(
            argument_spec=dict(),
        )

        # we first test the cases where the python selinux lib is
        # not installed, which has two paths: one in which the system
        # does have selinux installed (and the selinuxenabled command
        # is present and returns 0 when run), or selinux is not installed
        basic.HAVE_SELINUX = False
        am.get_bin_path = MagicMock()
        am.get_bin_path.return_value = '/path/to/selinuxenabled'
        am.run_command = MagicMock()
        am.run_command.return_value = (0, '', '')
        self.assertRaises(SystemExit, am.selinux_enabled)
        am.get_bin_path.return_value = None
        self.assertEqual(am.selinux_enabled(), False)

        # finally we test the case where the python selinux lib is installed,
        # and both possibilities there (enabled vs. disabled)
        basic.HAVE_SELINUX = True
        basic.selinux = Mock()
        with patch.dict('sys.modules', {'selinux': basic.selinux}):
            with patch('selinux.is_selinux_enabled', return_value=0):
                self.assertEqual(am.selinux_enabled(), False)
            with patch('selinux.is_selinux_enabled', return_value=1):
                self.assertEqual(am.selinux_enabled(), True)
        delattr(basic, 'selinux')
 def test_list_with_elements_path(self, capfd, mocker, stdin,
                                  complex_argspec):
     """Test choices with list"""
     am = basic.AnsibleModule(**complex_argspec)
     assert isinstance(am.params['bar3'], list)
     assert am.params['bar3'][0].startswith('/')
     assert am.params['bar3'][1] == 'test/'
def test_validator_fail(stdin, capfd, argspec, expected):
    with pytest.raises(SystemExit):
        basic.AnsibleModule(argument_spec=argspec)

    out, err = capfd.readouterr()
    assert not err
    assert expected in json.loads(out)['msg']
    assert json.loads(out)['failed']
def test_validator_function(mocker, stdin):
    # Type is a callable
    MOCK_VALIDATOR_SUCCESS = mocker.MagicMock(return_value=27)
    argspec = {'arg': {'type': MOCK_VALIDATOR_SUCCESS}}
    am = basic.AnsibleModule(argspec)

    assert isinstance(am.params['arg'], integer_types)
    assert am.params['arg'] == 27
def test_no_log_true(stdin, capfd):
    """Explicitly mask an argument (no_log=True)."""
    arg_spec = {"arg_pass": {"no_log": True}}
    am = basic.AnsibleModule(arg_spec)
    # no_log=True is picked up by both am._log_invocation and list_no_log_values
    # (called by am._handle_no_log_values). As a result, we can check for the
    # value in am.no_log_values.
    assert "testing" in am.no_log_values
    def test_elements_path_in_option(self, mocker, stdin,
                                     options_argspec_dict):
        """Test that the complex argspec works with elements path type"""

        am = basic.AnsibleModule(**options_argspec_dict)

        assert isinstance(am.params['foobar']['bar4'][0], str)
        assert am.params['foobar']['bar4'][0].startswith('/')
def test_no_log_none(stdin, capfd):
    """Allow Ansible to make the decision by matching the argument name
    against PASSWORD_MATCH."""
    arg_spec = {"arg_pass": {}}
    am = basic.AnsibleModule(arg_spec)
    # Omitting no_log is only picked up by _log_invocation, so the value never
    # makes it into am.no_log_values. Instead we can check for the warning
    # emitted by am._log_invocation.
    assert len(am._warnings) > 0
    def test_fail_required_together(self, capfd, stdin, complex_argspec):
        """Fail because only one of a required_together pair of parameters was specified"""
        with pytest.raises(SystemExit):
            am = basic.AnsibleModule(**complex_argspec)

        out, err = capfd.readouterr()
        results = json.loads(out)

        assert results['failed']
        assert results['msg'] == "parameters are required together: bam, baz"
    def test_fail_validate_options_list(self, capfd, stdin,
                                        options_argspec_list, expected):
        """Fail because one of a required_together pair of parameters has a default and the other was not specified"""
        with pytest.raises(SystemExit):
            am = basic.AnsibleModule(**options_argspec_list)

        out, err = capfd.readouterr()
        results = json.loads(out)

        assert results['failed']
        assert expected in results['msg']
    def test_fail_mutually_exclusive(self, capfd, stdin, complex_argspec):
        """Fail because of mutually exclusive parameters"""
        with pytest.raises(SystemExit):
            am = basic.AnsibleModule(**complex_argspec)

        out, err = capfd.readouterr()
        results = json.loads(out)

        assert results['failed']
        assert results[
            'msg'] == "parameters are mutually exclusive: bar|bam, bing|bang|bong"
    def test_fail_list_with_choices(self, capfd, mocker, stdin,
                                    complex_argspec):
        """Fail because one of the items is not in the choice"""
        with pytest.raises(SystemExit):
            basic.AnsibleModule(**complex_argspec)

        out, err = capfd.readouterr()
        results = json.loads(out)

        assert results['failed']
        assert results[
            'msg'] == "value of zardoz2 must be one or more of: one, two, three. Got no match for: four, five"
Esempio n. 16
0
def validate_config(spec, data):
    """
    Validate if the input data against the AnsibleModule spec format
    :param spec: Ansible argument spec
    :param data: Data to be validated
    :return:
    """
    params = basic._ANSIBLE_ARGS
    basic._ANSIBLE_ARGS = to_bytes(json.dumps({'ANSIBLE_MODULE_ARGS': data}))
    validated_data = basic.AnsibleModule(spec).params
    basic._ANSIBLE_ARGS = params
    return validated_data
    def test_fail_required_together_and_default(self, capfd, stdin,
                                                complex_argspec):
        """Fail because one of a required_together pair of parameters has a default and the other was not specified"""
        complex_argspec['argument_spec']['baz'] = {'default': 42}
        with pytest.raises(SystemExit):
            am = basic.AnsibleModule(**complex_argspec)

        out, err = capfd.readouterr()
        results = json.loads(out)

        assert results['failed']
        assert results['msg'] == "parameters are required together: bam, baz"
    def test_complex_type_fallback(self, mocker, stdin, complex_argspec):
        """Test that the complex argspec works if we get a required parameter via fallback"""
        environ = os.environ.copy()
        environ['BAZ'] = 'test data'
        mocker.patch(
            'ansible_collections.notstdlib.moveitallout.plugins.module_utils.basic.os.environ',
            environ)

        am = basic.AnsibleModule(**complex_argspec)

        assert isinstance(am.params['baz'], str)
        assert am.params['baz'] == 'test data'
    def test_module_utils_basic_ansible_module_selinux_initial_context(self):
        from ansible_collections.notstdlib.moveitallout.plugins.module_utils import basic
        basic._ANSIBLE_ARGS = None

        am = basic.AnsibleModule(
            argument_spec=dict(),
        )

        am.selinux_mls_enabled = MagicMock()
        am.selinux_mls_enabled.return_value = False
        self.assertEqual(am.selinux_initial_context(), [None, None, None])
        am.selinux_mls_enabled.return_value = True
        self.assertEqual(am.selinux_initial_context(), [None, None, None, None])
def test_validator_basic_types(argspec, expected, stdin):

    am = basic.AnsibleModule(argspec)

    if 'type' in argspec['arg']:
        if argspec['arg']['type'] == 'int':
            type_ = integer_types
        else:
            type_ = getattr(builtins, argspec['arg']['type'])
    else:
        type_ = str

    assert isinstance(am.params['arg'], type_)
    assert am.params['arg'] == expected
Esempio n. 21
0
 def get_info_mock_object(self, kind=None):
     """
     Helper method to return an na_ontap_info object
     """
     module = basic.AnsibleModule(
         argument_spec=netapp_utils.na_ontap_host_argument_spec(),
         supports_check_mode=True)
     obj = info_module(module)
     obj.netapp_info = dict()
     if kind is None:
         obj.server = MockONTAPConnection()
     else:
         obj.server = MockONTAPConnection(kind)
     return obj
Esempio n. 22
0
    def test_module_utils_basic_ansible_module_user_and_group(self):
        from ansible_collections.notstdlib.moveitallout.plugins.module_utils import basic
        basic._ANSIBLE_ARGS = None

        am = basic.AnsibleModule(
            argument_spec=dict(),
        )

        mock_stat = MagicMock()
        mock_stat.st_uid = 0
        mock_stat.st_gid = 0

        with patch('os.lstat', return_value=mock_stat):
            self.assertEqual(am.user_and_group('/path/to/file'), (0, 0))
    def test_fail_required_together_and_fallback(self, capfd, mocker, stdin,
                                                 complex_argspec):
        """Fail because one of a required_together pair of parameters has a fallback and the other was not specified"""
        environ = os.environ.copy()
        environ['BAZ'] = 'test data'
        mocker.patch(
            'ansible_collections.notstdlib.moveitallout.plugins.module_utils.basic.os.environ',
            environ)

        with pytest.raises(SystemExit):
            am = basic.AnsibleModule(**complex_argspec)

        out, err = capfd.readouterr()
        results = json.loads(out)

        assert results['failed']
        assert results['msg'] == "parameters are required together: bam, baz"
    def test_module_utils_basic_ansible_module_set_context_if_different(self):
        from ansible_collections.notstdlib.moveitallout.plugins.module_utils import basic
        basic._ANSIBLE_ARGS = None

        am = basic.AnsibleModule(
            argument_spec=dict(),
        )

        basic.HAVE_SELINUX = False

        am.selinux_enabled = MagicMock(return_value=False)
        self.assertEqual(am.set_context_if_different('/path/to/file', ['foo_u', 'foo_r', 'foo_t', 's0'], True), True)
        self.assertEqual(am.set_context_if_different('/path/to/file', ['foo_u', 'foo_r', 'foo_t', 's0'], False), False)

        basic.HAVE_SELINUX = True

        am.selinux_enabled = MagicMock(return_value=True)
        am.selinux_context = MagicMock(return_value=['bar_u', 'bar_r', None, None])
        am.is_special_selinux_path = MagicMock(return_value=(False, None))

        basic.selinux = Mock()
        with patch.dict('sys.modules', {'selinux': basic.selinux}):
            with patch('selinux.lsetfilecon', return_value=0) as m:
                self.assertEqual(am.set_context_if_different('/path/to/file', ['foo_u', 'foo_r', 'foo_t', 's0'], False), True)
                m.assert_called_with('/path/to/file', 'foo_u:foo_r:foo_t:s0')
                m.reset_mock()
                am.check_mode = True
                self.assertEqual(am.set_context_if_different('/path/to/file', ['foo_u', 'foo_r', 'foo_t', 's0'], False), True)
                self.assertEqual(m.called, False)
                am.check_mode = False

            with patch('selinux.lsetfilecon', return_value=1) as m:
                self.assertRaises(SystemExit, am.set_context_if_different, '/path/to/file', ['foo_u', 'foo_r', 'foo_t', 's0'], True)

            with patch('selinux.lsetfilecon', side_effect=OSError) as m:
                self.assertRaises(SystemExit, am.set_context_if_different, '/path/to/file', ['foo_u', 'foo_r', 'foo_t', 's0'], True)

            am.is_special_selinux_path = MagicMock(return_value=(True, ['sp_u', 'sp_r', 'sp_t', 's0']))

            with patch('selinux.lsetfilecon', return_value=0) as m:
                self.assertEqual(am.set_context_if_different('/path/to/file', ['foo_u', 'foo_r', 'foo_t', 's0'], False), True)
                m.assert_called_with('/path/to/file', 'sp_u:sp_r:sp_t:s0')

        delattr(basic, 'selinux')
    def test_module_utils_basic_ansible_module_is_special_selinux_path(self):
        from ansible_collections.notstdlib.moveitallout.plugins.module_utils import basic

        args = json.dumps(dict(ANSIBLE_MODULE_ARGS={'_ansible_selinux_special_fs': "nfs,nfsd,foos",
                                                    '_ansible_remote_tmp': "/tmp",
                                                    '_ansible_keep_remote_files': False}))

        with swap_stdin_and_argv(stdin_data=args):
            basic._ANSIBLE_ARGS = None
            am = basic.AnsibleModule(
                argument_spec=dict(),
            )

            def _mock_find_mount_point(path):
                if path.startswith('/some/path'):
                    return '/some/path'
                elif path.startswith('/weird/random/fstype'):
                    return '/weird/random/fstype'
                return '/'

            am.find_mount_point = MagicMock(side_effect=_mock_find_mount_point)
            am.selinux_context = MagicMock(return_value=['foo_u', 'foo_r', 'foo_t', 's0'])

            m = mock_open()
            m.side_effect = OSError

            with patch.object(builtins, 'open', m, create=True):
                self.assertEqual(am.is_special_selinux_path('/some/path/that/should/be/nfs'), (False, None))

            mount_data = [
                '/dev/disk1 / ext4 rw,seclabel,relatime,data=ordered 0 0\n',
                '1.1.1.1:/path/to/nfs /some/path nfs ro 0 0\n',
                'whatever /weird/random/fstype foos rw 0 0\n',
            ]

            # mock_open has a broken readlines() implementation apparently...
            # this should work by default but doesn't, so we fix it
            m = mock_open(read_data=''.join(mount_data))
            m.return_value.readlines.return_value = mount_data

            with patch.object(builtins, 'open', m, create=True):
                self.assertEqual(am.is_special_selinux_path('/some/random/path'), (False, None))
                self.assertEqual(am.is_special_selinux_path('/some/path/that/should/be/nfs'), (True, ['foo_u', 'foo_r', 'foo_t', 's0']))
                self.assertEqual(am.is_special_selinux_path('/weird/random/fstype/path'), (True, ['foo_u', 'foo_r', 'foo_t', 's0']))
    def test_module_utils_basic_ansible_module_selinux_mls_enabled(self):
        from ansible_collections.notstdlib.moveitallout.plugins.module_utils import basic
        basic._ANSIBLE_ARGS = None

        am = basic.AnsibleModule(
            argument_spec=dict(),
        )

        basic.HAVE_SELINUX = False
        self.assertEqual(am.selinux_mls_enabled(), False)

        basic.HAVE_SELINUX = True
        basic.selinux = Mock()
        with patch.dict('sys.modules', {'selinux': basic.selinux}):
            with patch('selinux.is_selinux_mls_enabled', return_value=0):
                self.assertEqual(am.selinux_mls_enabled(), False)
            with patch('selinux.is_selinux_mls_enabled', return_value=1):
                self.assertEqual(am.selinux_mls_enabled(), True)
        delattr(basic, 'selinux')
Esempio n. 27
0
    def test_module_utils_basic_ansible_module_set_group_if_different(self):
        from ansible_collections.notstdlib.moveitallout.plugins.module_utils import basic
        basic._ANSIBLE_ARGS = None

        am = basic.AnsibleModule(
            argument_spec=dict(),
        )

        self.assertEqual(am.set_group_if_different('/path/to/file', None, True), True)
        self.assertEqual(am.set_group_if_different('/path/to/file', None, False), False)

        am.user_and_group = MagicMock(return_value=(500, 500))

        with patch('os.lchown', return_value=None) as m:
            self.assertEqual(am.set_group_if_different('/path/to/file', 0, False), True)
            m.assert_called_with(b'/path/to/file', -1, 0)

            def _mock_getgrnam(*args, **kwargs):
                mock_gr = MagicMock()
                mock_gr.gr_gid = 0
                return mock_gr

            m.reset_mock()
            with patch('grp.getgrnam', side_effect=_mock_getgrnam):
                self.assertEqual(am.set_group_if_different('/path/to/file', 'root', False), True)
                m.assert_called_with(b'/path/to/file', -1, 0)

            with patch('grp.getgrnam', side_effect=KeyError):
                self.assertRaises(SystemExit, am.set_group_if_different, '/path/to/file', 'root', False)

            m.reset_mock()
            am.check_mode = True
            self.assertEqual(am.set_group_if_different('/path/to/file', 0, False), True)
            self.assertEqual(m.called, False)
            am.check_mode = False

        with patch('os.lchown', side_effect=OSError) as m:
            self.assertRaises(SystemExit, am.set_group_if_different, '/path/to/file', 'root', False)
    def test_deprecated_alias(self, capfd, mocker, stdin, complex_argspec):
        """Test a deprecated alias"""
        am = basic.AnsibleModule(**complex_argspec)

        assert "Alias 'zodraz' is deprecated." in am._deprecations[0]['msg']
        assert am._deprecations[0]['version'] == '9.99'
 def test_complex_duplicate_warning(self, stdin, complex_argspec):
     """Test that the complex argspec issues a warning if we specify an option both with its canonical name and its alias"""
     am = basic.AnsibleModule(**complex_argspec)
     assert isinstance(am.params['foo'], str)
     assert 'Both option foo and its alias dup are set.' in am._warnings
     assert am.params['foo'] == 'hello2'
 def test_list_with_choices(self, capfd, mocker, stdin, complex_argspec):
     """Test choices with list"""
     am = basic.AnsibleModule(**complex_argspec)
     assert isinstance(am.params['zardoz2'], list)
     assert am.params['zardoz2'] == ['one', 'three']