def test_perms_block_panic_stop(self):
     ''' Test that non-root can't run the important functions. '''
     oneoff = PuppetctlExecution(self.test_statefile)
     with mock.patch.object(PuppetctlExecution, '_allowed_to_run_command',
                            return_value=False):
         with self.assertRaises(SystemExit) as fail_break, \
                 mock.patch('sys.stdout', new=StringIO()):
             oneoff.panic_stop(True)
         self.assertEqual(fail_break.exception.code, 2)
Пример #2
0
 def setUp(self):
     ''' Preparing test rig '''
     self.test_statefile = '/tmp/exec-run-statefile-mods.test.txt'
     self.pe_patcher = mock.patch.object(PuppetctlExecution,
                                         '_allowed_to_run_command',
                                         return_value=True)
     self.library = PuppetctlExecution(self.test_statefile)
     self.library.logging_tag = 'testingpuppetctl[{}]'.format(
         self.library.invoking_user)
     self.pe_patcher.start()
Пример #3
0
 def test_perms_block_disable(self):
     ''' Test that non-root can't run the important functions. '''
     oneoff = PuppetctlExecution(self.test_statefile)
     with mock.patch.object(PuppetctlExecution,
                            '_allowed_to_run_command',
                            return_value=False):
         with self.assertRaises(SystemExit) as fail_disable, \
                 mock.patch('sys.stdout', new=StringIO()):
             oneoff.disable(False, int(time.time() + 60), 'failure testing')
         self.assertEqual(fail_disable.exception.code, 2)
Пример #4
0
 def test_nothing_to_do(self):
     ''' Test that we do nothing if there aren't locks to break. '''
     oneoff = PuppetctlExecution(self.test_statefile)
     with mock.patch.object(PuppetctlExecution, '_allowed_to_run_command',
                            return_value=True), \
             mock.patch.object(PuppetctlExecution, 'is_enabled', return_value=True), \
             mock.patch.object(PuppetctlExecution, 'is_operating', return_value=True), \
             self.assertRaises(SystemExit) as fail_break, \
             mock.patch('sys.stdout', new=StringIO()) as fake_out:
         oneoff.break_all_locks(2)
     self.assertIn('There are no locks', fake_out.getvalue())
     self.assertEqual(fail_break.exception.code, 0)
Пример #5
0
 def test_init_sudo(self):
     ''' Verify that the self object handles user edge-cases '''
     original_sudo = os.environ.get('SUDO_USER')
     original_user = os.environ.get('USER')
     os.environ.pop('SUDO_USER', None)
     os.environ.pop('USER', None)
     obj_unknown = PuppetctlExecution()
     self.assertEqual(obj_unknown.invoking_user, 'UNKNOWN')
     os.environ['USER'] = '******'
     obj_user = PuppetctlExecution()
     self.assertEqual(obj_user.invoking_user, 'someguy')
     os.environ['SUDO_USER'] = '******'
     obj_sudo = PuppetctlExecution()
     self.assertEqual(obj_sudo.invoking_user, 'otherguy')
     os.environ['USER'] = original_user
     # no cover begins here because the resets vary based on who you tested as.
     # This is just to put the house back in order.
     if original_sudo is None:  # pragma: no cover
         os.environ.pop('SUDO_USER', None)
     else:  # pragma: no cover
         os.environ['SUDO_USER'] = original_sudo
Пример #6
0
 def test_plain_init(self):
     ''' Verify that the class inits with no parameters '''
     library = PuppetctlExecution()
     self.assertEqual(
         library.puppet_bin_path,
         library.defaults.get('puppet_bin_path') + ':/bin:/usr/bin')
     self.assertIsInstance(library.lastrunfile, str)
     self.assertEqual(library.lastrunfile,
                      library.defaults.get('lastrunfile'))
     self.assertEqual(library.agent_catalog_run_lockfile,
                      library.defaults.get('agent_catalog_run_lockfile'))
     self.assertIsInstance(library.invoking_user, str)
     self.assertIsInstance(library.logging_tag, str)
     self.assertIsInstance(library.statefile_object, PuppetctlStatefile)
Пример #7
0
 def test_execution_allargs_pos(self):
     ''' Verify that the class inits positionally '''
     library = PuppetctlExecution('/tmp/somestate1', '/somepath1:/bin',
                                  '/opt/here1/last_run_summary.yaml',
                                  '/tmp/a.lock')
     self.assertEqual(library.puppet_bin_path, '/somepath1:/bin:/usr/bin')
     self.assertEqual(library.lastrunfile,
                      '/opt/here1/last_run_summary.yaml')
     self.assertEqual(library.agent_catalog_run_lockfile, '/tmp/a.lock')
     self.assertIsInstance(library.invoking_user, str)
     self.assertIsInstance(library.logging_tag, str)
     self.assertIsInstance(library.statefile_object, PuppetctlStatefile)
     self.assertEqual(library.statefile_object.state_file,
                      '/tmp/somestate1')
Пример #8
0
 def test_execution_allargs_kwargs(self):
     ''' Verify that the class inits with kwargs '''
     library = PuppetctlExecution(
         state_file='/tmp/somestate2',
         puppet_bin_path='/somepath2',
         lastrunfile='/opt/puppet/somewhere2/last_run_summary.yaml',
         agent_catalog_run_lockfile='/tmp/my.lck')
     self.assertEqual(library.puppet_bin_path, '/somepath2:/bin:/usr/bin')
     self.assertEqual(library.lastrunfile,
                      '/opt/puppet/somewhere2/last_run_summary.yaml')
     self.assertEqual(library.agent_catalog_run_lockfile, '/tmp/my.lck')
     self.assertIsInstance(library.invoking_user, str)
     self.assertIsInstance(library.logging_tag, str)
     self.assertIsInstance(library.statefile_object, PuppetctlStatefile)
     self.assertEqual(library.statefile_object.state_file,
                      '/tmp/somestate2')
class TestExecutionPanicStop(unittest.TestCase):
    ''' Class of tests about executing puppetctl panic_stop commands. '''

    def setUp(self):
        ''' Preparing test rig '''
        self.test_statefile = '/tmp/exec-panic_stop-statefile-mods.test.txt'
        self.library = PuppetctlExecution(self.test_statefile)
        self.library.logging_tag = 'testingpuppetctl[{}]'.format(self.library.invoking_user)

    def tearDown(self):
        ''' Cleanup test rig '''
        try:
            os.remove(self.test_statefile)
        except OSError:  # pragma: no cover
            # we likely never created the file.
            pass

    def test_perms_block_panic_stop(self):
        ''' Test that non-root can't run the important functions. '''
        oneoff = PuppetctlExecution(self.test_statefile)
        with mock.patch.object(PuppetctlExecution, '_allowed_to_run_command',
                               return_value=False):
            with self.assertRaises(SystemExit) as fail_break, \
                    mock.patch('sys.stdout', new=StringIO()):
                oneoff.panic_stop(True)
            self.assertEqual(fail_break.exception.code, 2)

    def test_panic_stop_nothing_to_do(self):
        ''' Test that 'panic_stop' handles no-processes-to-kill nicely. '''
        with mock.patch.object(PuppetctlExecution, '_allowed_to_run_command',
                               return_value=True), \
                mock.patch.object(PuppetctlExecution, '_puppet_processes_running',
                                  return_value={}), \
                self.assertRaises(SystemExit) as exit_panicstop, \
                mock.patch('sys.stdout', new=StringIO()) as fake_out:
            self.library.panic_stop(False)
        self.assertIn("No running 'puppet agent' found", fake_out.getvalue())
        self.assertEqual(exit_panicstop.exception.code, 0)

    def test_panic_stop_well_behaved(self):
        ''' Test that 'panic_stop' leaves quietly if a process exits cleanly. '''
        with mock.patch.object(PuppetctlExecution, '_allowed_to_run_command',
                               return_value=True), \
                mock.patch.object(PuppetctlExecution, '_puppet_processes_running',
                                  side_effect=[{'123': 'test-puppet agent'}, {}]), \
                self.assertRaises(SystemExit) as exit_panicstop, \
                mock.patch('os.kill') as mock_kill, \
                mock.patch('time.sleep') as mock_sleep, \
                mock.patch('sys.stdout', new=StringIO()) as fake_out:
            self.library.panic_stop(False)
        mock_kill.assert_called_once_with(123, signal.SIGTERM)
        mock_sleep.assert_called_once_with(2)
        self.assertIn("Sending SIGTERM to pid 123 / 'test-puppet agent'", fake_out.getvalue())
        self.assertIn("No running 'puppet agent' found", fake_out.getvalue())
        self.assertEqual(exit_panicstop.exception.code, 0)

        with mock.patch.object(PuppetctlExecution, '_allowed_to_run_command',
                               return_value=True), \
                mock.patch.object(PuppetctlExecution, '_puppet_processes_running',
                                  side_effect=[{'234': 'test-puppet agent'}, {}]), \
                self.assertRaises(SystemExit) as exit_panicstop, \
                mock.patch('os.kill') as mock_kill, \
                mock.patch('time.sleep') as mock_sleep, \
                mock.patch('sys.stdout', new=StringIO()) as fake_out:
            self.library.panic_stop(True)
        mock_kill.assert_called_once_with(234, signal.SIGTERM)
        mock_sleep.assert_not_called()
        self.assertIn("Sending SIGTERM to pid 234 / 'test-puppet agent'", fake_out.getvalue())
        self.assertIn("No running 'puppet agent' found", fake_out.getvalue())
        self.assertEqual(exit_panicstop.exception.code, 0)

    def test_panic_stop_stubborn(self):
        ''' Test that 'panic_stop' fires a kill if term wasn't enough. '''
        with mock.patch.object(PuppetctlExecution, '_allowed_to_run_command',
                               return_value=True), \
                mock.patch.object(PuppetctlExecution, '_puppet_processes_running',
                                  side_effect=[{'123': 'test-puppet agent'},
                                               {'123': 'test-puppet agent'}, {}]), \
                self.assertRaises(SystemExit) as exit_panicstop, \
                mock.patch('os.kill') as mock_kill, \
                mock.patch('time.sleep') as mock_sleep, \
                mock.patch('sys.stdout', new=StringIO()) as fake_out:
            self.library.panic_stop(False)
        mock_kill.assert_any_call(123, signal.SIGTERM)
        mock_sleep.assert_any_call(2)  # the non-force pause
        mock_kill.assert_called_with(123, signal.SIGKILL)
        mock_sleep.assert_any_call(1)  # the mandatory pause after the kill signal
        self.assertIn("Sending SIGTERM to pid 123 / 'test-puppet agent'", fake_out.getvalue())
        self.assertIn("Sending SIGKILL to pid 123 / 'test-puppet agent'", fake_out.getvalue())
        self.assertIn("No running 'puppet agent' found", fake_out.getvalue())
        self.assertEqual(exit_panicstop.exception.code, 0)

        with mock.patch.object(PuppetctlExecution, '_allowed_to_run_command',
                               return_value=True), \
                mock.patch.object(PuppetctlExecution, '_puppet_processes_running',
                                  side_effect=[{'234': 'test-puppet agent'},
                                               {'234': 'test-puppet agent'}, {}]), \
                self.assertRaises(SystemExit) as exit_panicstop, \
                mock.patch('os.kill') as mock_kill, \
                mock.patch('time.sleep') as mock_sleep, \
                mock.patch('sys.stdout', new=StringIO()) as fake_out:
            self.library.panic_stop(True)
        mock_kill.assert_any_call(234, signal.SIGTERM)
        mock_kill.assert_called_with(234, signal.SIGKILL)
        mock_sleep.assert_any_call(1)  # the mandatory pause after the kill signal
        self.assertIn("Sending SIGTERM to pid 234 / 'test-puppet agent'", fake_out.getvalue())
        self.assertIn("Sending SIGKILL to pid 234 / 'test-puppet agent'", fake_out.getvalue())
        self.assertIn("No running 'puppet agent' found", fake_out.getvalue())
        self.assertEqual(exit_panicstop.exception.code, 0)

    def test_panic_stop_zombies(self):
        ''' Test that 'panic_stop' complains if a process outlives a sigkill. '''
        with mock.patch.object(PuppetctlExecution, '_allowed_to_run_command',
                               return_value=True), \
                mock.patch.object(PuppetctlExecution, '_puppet_processes_running',
                                  side_effect=[{'123': 'test-puppet agent'},
                                               {'123': 'test-puppet agent'},
                                               {'123': 'test-puppet agent'}]), \
                self.assertRaises(SystemExit) as exit_panicstop, \
                mock.patch('os.kill') as mock_kill, \
                mock.patch('time.sleep') as mock_sleep, \
                mock.patch('sys.stdout', new=StringIO()) as fake_out:
            self.library.panic_stop(False)
        mock_kill.assert_any_call(123, signal.SIGTERM)
        mock_sleep.assert_any_call(2)  # the non-force pause
        mock_kill.assert_called_with(123, signal.SIGKILL)
        mock_sleep.assert_any_call(1)  # the mandatory pause after the kill signal
        self.assertIn("Sending SIGTERM to pid 123 / 'test-puppet agent'", fake_out.getvalue())
        self.assertIn("Sending SIGKILL to pid 123 / 'test-puppet agent'", fake_out.getvalue())
        self.assertIn("pid 123 / 'test-puppet agent' did NOT die", fake_out.getvalue())
        self.assertEqual(exit_panicstop.exception.code, 1)

        with mock.patch.object(PuppetctlExecution, '_allowed_to_run_command',
                               return_value=True), \
                mock.patch.object(PuppetctlExecution, '_puppet_processes_running',
                                  side_effect=[{'234': 'test-puppet agent'},
                                               {'234': 'test-puppet agent'},
                                               {'234': 'test-puppet agent'}]), \
                self.assertRaises(SystemExit) as exit_panicstop, \
                mock.patch('os.kill') as mock_kill, \
                mock.patch('time.sleep') as mock_sleep, \
                mock.patch('sys.stdout', new=StringIO()) as fake_out:
            self.library.panic_stop(True)
        mock_kill.assert_any_call(234, signal.SIGTERM)
        mock_kill.assert_called_with(234, signal.SIGKILL)
        mock_sleep.assert_any_call(1)  # the mandatory pause after the kill signal
        self.assertIn("Sending SIGTERM to pid 234 / 'test-puppet agent'", fake_out.getvalue())
        self.assertIn("Sending SIGKILL to pid 234 / 'test-puppet agent'", fake_out.getvalue())
        self.assertIn("pid 234 / 'test-puppet agent' did NOT die", fake_out.getvalue())
        self.assertEqual(exit_panicstop.exception.code, 1)
class TestExecutionStatusPuppetctl(unittest.TestCase):
    ''' Class of tests about executing puppetctl status commands. '''
    def setUp(self):
        ''' Preparing test rig '''
        self.test_statefile = '/tmp/exec-status-puppet-statefile-mods.test.txt'
        self.library = PuppetctlExecution(self.test_statefile)
        self.library.logging_tag = 'testingpuppetctl[{}]'.format(
            self.library.invoking_user)

    def tearDown(self):
        ''' Cleanup test rig '''
        try:
            os.remove(self.test_statefile)
        except OSError:
            # we likely never created the file.
            pass

    def test_status_puppetctl_nolocks(self):
        ''' Test the status of puppetctl, no locks.  Valid with or without root. '''
        result = self.library._status_of_puppetctl()
        self.assertIn('message', result)
        self.assertIn('Puppet is enabled and in operating mode',
                      result['message'])
        self.assertIn('color', result)
        self.assertIsNone(result['color'])

    def test_status_puppetctl_disable(self):
        ''' Test the status of puppetctl, disable lock.  Valid with or without root. '''
        now = int(time.time())
        with mock.patch.object(PuppetctlStatefile,
                               '_allowed_to_write_statefile',
                               return_value=True):
            self.library.statefile_object.add_lock('somebody2', 'disable',
                                                   now + 30 * 60,
                                                   'I disabled it')
        result = self.library._status_of_puppetctl()
        self.assertIn('message', result)
        self.assertIn('Puppet has been disabled', result['message'])
        self.assertIn('somebody2', result['message'])
        self.assertIn('I disabled it', result['message'])
        self.assertIn('color', result)
        self.assertIsNotNone(result['color'])

    def test_status_puppetctl_nooperate(self):
        ''' Test the status of puppetctl, noop lock.  Valid with or without root. '''
        now = int(time.time())
        with mock.patch.object(PuppetctlStatefile,
                               '_allowed_to_write_statefile',
                               return_value=True):
            self.library.statefile_object.add_lock('somebody3', 'nooperate',
                                                   now + 30 * 60,
                                                   'I nooped it')
        result = self.library._status_of_puppetctl()
        self.assertIn('message', result)
        self.assertIn('Puppet is in nooperate mode', result['message'])
        self.assertIn('somebody3', result['message'])
        self.assertIn('I nooped it', result['message'])
        self.assertIn('color', result)
        self.assertIsNotNone(result['color'])

    def test_status_puppetctl_multilock(self):
        ''' Test the status of puppetctl, noop and disable locks.  Valid with or without root. '''
        now = int(time.time())
        with mock.patch.object(PuppetctlStatefile,
                               '_allowed_to_write_statefile',
                               return_value=True):
            self.library.statefile_object.add_lock('somebody2', 'disable',
                                                   now + 30 * 60,
                                                   'I disabled it')
            self.library.statefile_object.add_lock('somebody3', 'nooperate',
                                                   now + 30 * 60,
                                                   'I nooped it')
        result = self.library._status_of_puppetctl()
        self.assertIn('message', result)
        self.assertIn('Puppet has been disabled', result['message'])
        self.assertIn('somebody2', result['message'])
        self.assertIn('I disabled it', result['message'])
        self.assertIn('Puppet is in nooperate mode', result['message'])
        self.assertIn('somebody3', result['message'])
        self.assertIn('I nooped it', result['message'])
        self.assertIn('color', result)
        self.assertIsNotNone(result['color'])

    def test_lock_status_call(self):
        '''
            This is not an interesting test.  The real work is done in _status_of_puppetctl,
            so this is just for coverage.
        '''
        with mock.patch('sys.stdout', new=StringIO()), \
                mock.patch.object(PuppetctlExecution, '_status_of_puppetctl') as mock_pc:
            self.library.lock_status()
        mock_pc.assert_called_once()

    def test_motd_status_call(self):
        '''
            Make sure that we print nothing when there's no errors.
        '''
        with mock.patch('sys.stdout', new=StringIO()), \
                self.assertRaises(SystemExit) as mock_motd, \
                mock.patch('sys.stdout', new=StringIO()) as fake_out, \
                mock.patch.object(PuppetctlExecution, '_status_of_puppetctl',
                                  return_value={'message': 'foo', 'color': None,
                                                'disable': 0, 'nooperate': 0}) as mock_pc:
            self.library.motd_status()
        mock_pc.assert_called_once()
        self.assertEqual('', fake_out.getvalue())
        self.assertEqual(mock_motd.exception.code, 0)

        with mock.patch('sys.stdout', new=StringIO()), \
                self.assertRaises(SystemExit) as mock_motd, \
                mock.patch('sys.stdout', new=StringIO()) as fake_out, \
                mock.patch.object(PuppetctlExecution, '_status_of_puppetctl',
                                  return_value={'message': 'foo', 'color': '1;31',
                                                'disable': 1, 'nooperate': 0}) as mock_pc:
            self.library.motd_status()
        mock_pc.assert_called_once()
        self.assertIn('foo', fake_out.getvalue())
        self.assertEqual(mock_motd.exception.code, 0)
Пример #11
0
 def setUp(self):
     ''' Preparing test rig '''
     self.test_statefile = '/tmp/unused-statefile.txt'
     self.library = PuppetctlExecution(self.test_statefile)
class TestExecutionStatusPuppet(unittest.TestCase):
    ''' Class of tests about executing puppetctl status commands. '''

    def setUp(self):
        ''' Preparing test rig '''
        self.test_statefile = '/tmp/exec-status-puppetctl-statefile-mods.test.txt'
        self.library = PuppetctlExecution(self.test_statefile)
        self.library.logging_tag = 'testingpuppetctl[{}]'.format(self.library.invoking_user)

    def tearDown(self):
        ''' Cleanup test rig '''
        try:
            os.remove(self.test_statefile)
        except OSError:
            # we likely never created the file.
            pass

    def test_parse_lastrunfile(self):
        ''' Run our test files through _parse_puppet_lastrunfile '''
        devnull = open(os.devnull, 'w')
        retcode = subprocess.call(['ruby', '--version'],
                                  env={'PATH': self.library.puppet_bin_path}, stdout=devnull)
        if retcode != 0:  # pragma: no cover
            self.skipTest('Cannot test without the puppet ruby environment')
        devnull.close()
        mydir = os.path.dirname(__file__)

        cleanfile = os.path.join(mydir, 'last_run_summary', 'clean_last_run_summary.yaml')
        cleancodes = self.library._parse_puppet_lastrunfile(cleanfile)
        # The values here are visually copied from the files in test/last_run_summary/*
        age = int(time.time()) - 1586995296
        nearage = [age-1, age, age+1]
        self.assertIn(cleancodes['age'], nearage)
        self.assertEqual(cleancodes['errors'], 0)
        self.assertEqual(cleancodes['config'], 'a294ac4f4fcd5264e5246df0787757a74fc3d966')

        onefailfile = os.path.join(mydir, 'last_run_summary', 'fail_one_last_run_summary.yaml')
        onefailcodes = self.library._parse_puppet_lastrunfile(onefailfile)
        # The values here are visually copied from the files in test/last_run_summary/*
        age = int(time.time()) - 1587278457
        nearage = [age-1, age, age+1]
        self.assertIn(onefailcodes['age'], nearage)
        self.assertEqual(onefailcodes['errors'], 1)
        self.assertEqual(onefailcodes['config'], '3a3d5827a1637456d360f888462d2aa0dbd975f6')

    def test_status_puppet(self):
        ''' Emulate testing the status of puppet '''
        with mock.patch('os.geteuid', return_value=0), \
                mock.patch('os.path.exists', return_value=True), \
                mock.patch.object(PuppetctlExecution, '_parse_puppet_lastrunfile') as mock_parse:
            self.library._status_of_puppet('/tmp/pretend-i-exist.txt')
        mock_parse.assert_called_once_with('/tmp/pretend-i-exist.txt')

    def test_status_puppet_nonroot(self):
        ''' Emulate testing the status of puppet when not root '''
        with mock.patch('os.geteuid', return_value=1006), \
                mock.patch('os.path.exists', return_value=True), \
                mock.patch.object(PuppetctlExecution, '_parse_puppet_lastrunfile') as mock_parse:
            self.library._status_of_puppet('/tmp/pretend-i-exist.txt')
        mock_parse.assert_not_called()

    def test_status_puppet_nofile(self):
        ''' Emulate testing the status of puppet when the file doesn't exist '''
        with mock.patch('os.geteuid', return_value=0), \
                mock.patch('os.path.exists', return_value=False), \
                mock.patch.object(PuppetctlExecution, '_parse_puppet_lastrunfile') as mock_parse:
            self.library._status_of_puppet('/tmp/pretend-i-exist.txt')
        mock_parse.assert_not_called()

    def test_main_status_call(self):
        '''
            This is not an interesting test.  The real work is done in _status_of_puppet
            and _status_of_puppetctl, so this is just for coverage.
        '''
        with self.assertRaises(SystemExit) as status_run:
            with mock.patch('sys.stdout', new=StringIO()), \
                    mock.patch.object(PuppetctlExecution, '_status_of_puppet') as mock_p, \
                    mock.patch.object(PuppetctlExecution, '_status_of_puppetctl') as mock_pc:
                self.library.status()
        self.assertIn(status_run.exception.code, [0, 1])
        mock_p.assert_called_once()
        mock_pc.assert_called_once()

    def test_puppet_process_detect(self):
        ''' Test our detection of a running puppet process. '''
        # If we're not root, we can't check.
        with mock.patch('os.geteuid', return_value=1006):
            result = self.library._puppet_processes_running('/tmp/whocares.txt')
        self.assertEqual(result, {})
        # If we are root, and the file isn't there, we can't do anything.
        with mock.patch('os.geteuid', return_value=0):
            result = self.library._puppet_processes_running('/tmp/whocares.txt')
        self.assertEqual(result, {})

        # Make a sample lock, that we'll use on the rest of the tests.
        sample_pid = '13579'
        test_lockfile = '/tmp/process_detect_pid.lock'
        with open(test_lockfile, 'w') as writelock:
            writelock.write(sample_pid)
        fake_os_stat = os.stat('/')

        # All future checks have root privs
        with mock.patch('os.geteuid', return_value=0):

            with mock.patch.object(six.moves.builtins, 'open',
                                   mock.mock_open(read_data='not_a_pid')):
                result = self.library._puppet_processes_running(test_lockfile)
            self.assertEqual(result, {})

            # Pretend we get something from the lockfile, but the command
            # has exited between then and the time we look in /proc.
            with mock.patch('os.stat', side_effect=OSError):
                result = self.library._puppet_processes_running(test_lockfile)
            self.assertEqual(result, {})

            # Pretend that the pid in the lockfile is somehow a process
            # not owned by root.
            with mock.patch('os.stat') as mock_oss:
                mock_oss.return_value.st_uid.return_value = 1020
                result = self.library._puppet_processes_running(test_lockfile)
            self.assertEqual(result, {})

            # All future tests have a pid, a root-owned process in /proc...
            with mock.patch('os.stat', return_value=fake_os_stat):
                # ... and because we're about to take over the 'open' call, we have
                # to replace the inital call from where we read the pid the first time.
                # This makes the handlers messy to read.
                #
                # Pretend that the proc has disappeared in the sliver of
                # time between the time we stat'ed it.
                with mock.patch.object(six.moves.builtins, 'open') as mopen:
                    handlers = (mock.mock_open(read_data=sample_pid).return_value,
                                IOError)
                    mopen.side_effect = handlers
                    result = self.library._puppet_processes_running(test_lockfile)
                self.assertEqual(result, {})

                # Pretend that the proc is somehow not puppet.
                with mock.patch.object(six.moves.builtins, 'open') as mopen:
                    handlers = (mock.mock_open(read_data=sample_pid).return_value,
                                mock.mock_open(read_data='echo\0some\0string\0').return_value)
                    mopen.side_effect = handlers
                    result = self.library._puppet_processes_running(test_lockfile)
                self.assertEqual(result, {})

                # FINALLY.  Pretend that this was an actual puppet run.
                with mock.patch.object(six.moves.builtins, 'open') as mopen:
                    handlers = (mock.mock_open(read_data=sample_pid).return_value,
                                mock.mock_open(read_data=('/opt/puppetlabs/puppet/bin/ruby\0'
                                                          '/opt/puppetlabs/puppet/bin/puppet\0'
                                                          'agent\0--verbose\0--onetime\0'
                                                          '--no-daemonize\0--no-splay\0'
                                                          '')).return_value)
                    mopen.side_effect = handlers
                    result = self.library._puppet_processes_running(test_lockfile)
                self.assertIn(sample_pid, result)
                self.assertIn('puppet agent', result[sample_pid])
Пример #13
0
 def setUp(self):
     ''' Preparing test rig '''
     self.library = PuppetctlExecution('/tmp/does-not-matter.status.txt')
Пример #14
0
class TestExecutionStatusBool(unittest.TestCase):
    ''' Class of tests about is-enabled and is-operating puppetctl commands. '''

    # Here in the setup, override our statefile object's read command.
    # We fully test that in another test suite, so assume it works and
    # just let us shoot out the dict that would come from that func.
    # Since the state file is the basis of all our decisionmaking,
    # stomping that one function should cover all our state worries.
    def setUp(self):
        ''' Preparing test rig '''
        self.test_statefile = '/tmp/unused-statefile.txt'
        self.library = PuppetctlExecution(self.test_statefile)

    def tearDown(self):
        ''' Cleanup test rig '''
        os.remove(self.test_statefile)

    def test_is_enabled(self, ):
        ''' Test the is_enabled function '''
        self.assertTrue(self.library.is_enabled())
        self.assertTrue(self.library.is_enabled('somebody1'))
        self.assertTrue(self.library.is_enabled('somebody2'))
        self.assertTrue(self.library.is_enabled('somebody3'))
        now = int(time.time())
        with mock.patch.object(PuppetctlStatefile,
                               '_allowed_to_write_statefile',
                               return_value=True):
            self.library.statefile_object.add_lock('somebody2', 'disable',
                                                   now + 30 * 60,
                                                   'I disabled 1h')
            self.library.statefile_object.add_lock('somebody3', 'nooperate',
                                                   now + 90 * 60,
                                                   'I nooped 2h')
        self.assertFalse(self.library.is_enabled())
        self.assertTrue(self.library.is_enabled('somebody1'))
        self.assertFalse(self.library.is_enabled('somebody2'))
        self.assertTrue(self.library.is_enabled('somebody3'))

    def test_is_operating(self, ):
        ''' Test the is_operating function '''
        self.assertTrue(self.library.is_operating())
        self.assertTrue(self.library.is_operating('somebody1'))
        self.assertTrue(self.library.is_operating('somebody2'))
        self.assertTrue(self.library.is_operating('somebody3'))
        now = int(time.time())
        with mock.patch.object(PuppetctlStatefile,
                               '_allowed_to_write_statefile',
                               return_value=True):
            self.library.statefile_object.add_lock('somebody2', 'disable',
                                                   now + 30 * 60,
                                                   'I disabled 1h')
            self.library.statefile_object.add_lock('somebody3', 'nooperate',
                                                   now + 90 * 60,
                                                   'I nooped 2h')
        self.assertFalse(self.library.is_operating())
        self.assertTrue(self.library.is_operating('somebody1'))
        self.assertTrue(self.library.is_operating('somebody2'))
        self.assertFalse(self.library.is_operating('somebody3'))
Пример #15
0
class TestExecutionStatics(unittest.TestCase):
    ''' Class of tests about PuppetctlExecution's static method. '''

    def setUp(self):
        ''' Preparing test rig '''
        self.library = PuppetctlExecution('/tmp/does-not-matter.status.txt')

    def test_dhms(self):
        ''' Test the dhms function for various times '''
        self.assertEqual(self.library.dhms(0), '0s')
        self.assertEqual(self.library.dhms(30), '30s')
        self.assertEqual(self.library.dhms(60), '1m')
        self.assertEqual(self.library.dhms(90), '1m 30s')
        self.assertEqual(self.library.dhms(60*60), '1h')
        self.assertEqual(self.library.dhms(61*60), '1h 1m')
        self.assertEqual(self.library.dhms(61*60+20), '1h 1m 20s')
        self.assertEqual(self.library.dhms(11*60*60), '11h')
        self.assertEqual(self.library.dhms(24*60*60), '1d')

    def test_log(self):
        ''' test the syslog call of log '''
        with mock.patch('syslog.openlog') as mock_openlog, \
                mock.patch('syslog.syslog') as mock_syslog:
            self.library.syslog = mock_syslog
            self.library.log('foo bar baz')
            mock_openlog.assert_called_once_with(self.library.logging_tag)
            mock_syslog.assert_called_once_with('foo bar baz')

    def test_log_print_to_log(self):
        ''' test that log_print calls what it should '''
        with mock.patch.object(PuppetctlExecution, 'log') as mock_log, \
                mock.patch.object(PuppetctlExecution, 'color_print') as mock_print:
            # we don't care what it prints, just that it tries to.
            with mock.patch('sys.stdout', new=StringIO()):
                self.library.log_print('foo', '1;31')
            mock_log.assert_called_once_with('foo')
            mock_print.assert_called_once_with('foo', '1;31')

    def test_color_print_notty(self):
        ''' test that color_print handles a notty '''
        # Order matters here: isatty comes second since we are touching stdout twice.
        with mock.patch('sys.stdout', new=StringIO()) as fake_out, \
                mock.patch('sys.stdout.isatty', return_value=False):
            self.library.color_print('bar')
            self.assertEqual(fake_out.getvalue(), 'puppetctl: bar\n')

    def test_color_print_tty(self):
        ''' test that color_print handles a tty '''
        # Order matters here: isatty comes second since we are touching stdout twice.
        with mock.patch('sys.stdout', new=StringIO()) as fake_out, \
                mock.patch('sys.stdout.isatty', return_value=True):
            self.library.color_print('baz')
            self.assertEqual(fake_out.getvalue(), 'baz\n')

    def test_color_print_tty_color(self):
        ''' test that color_print handles a tty with color '''
        # Order matters here: isatty comes second since we are touching stdout twice.
        with mock.patch('sys.stdout', new=StringIO()) as fake_out, \
                mock.patch('sys.stdout.isatty', return_value=True):
            self.library.color_print('quux', '1;31')
            self.assertEqual(fake_out.getvalue(), '\033[1;31mquux\033[0m\n')

    def test_error_print(self):
        ''' Test if error_print works correctly '''
        # most of the testing here is actually done by log_print
        with self.assertRaises(SystemExit) as error_print, \
                mock.patch('sys.stdout', new=StringIO()) as fake_out:
            self.library.error_print('some test message')
        self.assertIn('some test message', fake_out.getvalue())
        self.assertEqual(error_print.exception.code, 2)
Пример #16
0
class TestExecutionEnable(unittest.TestCase):
    ''' Class of tests about executing puppetctl enable commands. '''

    def setUp(self):
        ''' Preparing test rig '''
        self.test_statefile = '/tmp/exec-enable-statefile-mods.test.txt'
        self.pe_patcher = mock.patch.object(PuppetctlExecution, '_allowed_to_run_command',
                                            return_value=True)
        self.sf_patcher = mock.patch.object(PuppetctlStatefile, '_allowed_to_write_statefile',
                                            return_value=True)
        self.library = PuppetctlExecution(self.test_statefile)
        self.library.logging_tag = 'testingpuppetctl[{}]'.format(self.library.invoking_user)
        self.pe_patcher.start()
        self.sf_patcher.start()

    def tearDown(self):
        ''' Cleanup test rig '''
        try:
            os.remove(self.test_statefile)
        except OSError:  # pragma: no cover
            # we likely never created the file.
            pass
        self.pe_patcher.stop()
        self.sf_patcher.stop()

    def test_perms_block_enable(self):
        ''' Test that non-root can't run the important functions. '''
        oneoff = PuppetctlExecution(self.test_statefile)
        with mock.patch.object(PuppetctlExecution, '_allowed_to_run_command',
                               return_value=False):
            with self.assertRaises(SystemExit) as fail_enable, \
                    mock.patch('sys.stdout', new=StringIO()):
                oneoff.enable()
            self.assertEqual(fail_enable.exception.code, 2)

    def test_enable_nolocks(self):
        ''' Test that "enable" does nothing when there are no locks. '''
        with mock.patch('sys.stdout', new=StringIO()) as fake_out:
            self.library.enable()
        self.assertIn('Puppet is already enabled.', fake_out.getvalue())

    def test_enable_not_our_locks_1(self):
        ''' Test that "enable" does nothing when we have no locks, but others disable. '''
        now = int(time.time())
        self.library.statefile_object.add_lock('somebody2', 'disable', now+30*60, 'I disabled 1h')
        self.library.statefile_object.add_lock('somebody3', 'nooperate', now+90*60, 'I nooped 2h')
        with mock.patch('sys.stdout', new=StringIO()) as fake_out:
            with mock.patch.object(PuppetctlExecution, 'lock_status') as mock_status:
                self.library.enable()
        self.assertIn('Puppet is already enabled for ', fake_out.getvalue())
        self.assertIn(', but other users have puppet disabled.', fake_out.getvalue())
        mock_status.assert_called_once_with()

    def test_enable_not_our_locks_2(self):
        ''' Test that "enable" does nothing when we have no locks, but root does. '''
        now = int(time.time())
        self.library.statefile_object.add_lock('root', 'disable', now+30*60, 'I disabled 1h')
        with mock.patch('sys.stdout', new=StringIO()) as fake_out:
            with mock.patch.object(PuppetctlExecution, 'lock_status') as mock_status:
                self.library.enable()
        self.assertIn('Puppet is already enabled for ', fake_out.getvalue())
        self.assertIn(', but root has puppet disabled.', fake_out.getvalue())
        mock_status.assert_called_once_with()

    def test_enable_not_our_locks_3(self):
        ''' Test that "enable" does nothing when we have no locks, but others noop. '''
        now = int(time.time())
        self.library.statefile_object.add_lock('somebody3', 'nooperate', now+90*60, 'I nooped 2h')
        with mock.patch('sys.stdout', new=StringIO()) as fake_out:
            with mock.patch.object(PuppetctlExecution, 'lock_status') as mock_status:
                self.library.enable()
        self.assertIn('Puppet is already enabled for ', fake_out.getvalue())
        self.assertIn(', but other users have puppet in noop mode.', fake_out.getvalue())
        mock_status.assert_called_once_with()

    def test_enable_disable_mylock(self):
        ''' Test that "enable" wants to enable when it's my lock. '''
        now = int(time.time())
        self.library.statefile_object.add_lock(self.library.invoking_user, 'disable',
                                               now+30*60, 'It is my lock')
        with mock.patch('sys.stdout', new=StringIO()) as fake_out:
            self.library.enable()
        self.assertIn('Puppet has been enabled.', fake_out.getvalue())

    def test_enable_noop_mylock(self):
        ''' Test that "enable" assists, but doesn't enable, when there's a noop lock. '''
        now = int(time.time())
        self.library.statefile_object.add_lock(self.library.invoking_user, 'nooperate',
                                               now+30*60, 'It is my lock')
        with mock.patch('sys.stdout', new=StringIO()) as fake_out:
            self.library.enable()
        self.assertIn('Puppet is enabled, but is in nooperate mode.', fake_out.getvalue())

    def test_enable_fails_remove_lock(self):
        ''' Test that "enable" complains if it can't remove the lock. '''
        now = int(time.time())
        self.library.statefile_object.add_lock(self.library.invoking_user, 'disable',
                                               now+30*60, 'It is my lock')
        with mock.patch.object(PuppetctlStatefile, 'remove_lock', return_value=False), \
                self.assertRaises(SystemExit) as lockfail, \
                mock.patch('sys.stdout', new=StringIO()) as fake_out:
            self.library.enable()
        self.assertIn('Unable to remove', fake_out.getvalue())
        self.assertEqual(lockfail.exception.code, 2)
Пример #17
0
class TestExecutionRun(unittest.TestCase):
    ''' Class of tests about executing puppetctl run commands. '''
    def setUp(self):
        ''' Preparing test rig '''
        self.test_statefile = '/tmp/exec-run-statefile-mods.test.txt'
        self.pe_patcher = mock.patch.object(PuppetctlExecution,
                                            '_allowed_to_run_command',
                                            return_value=True)
        self.library = PuppetctlExecution(self.test_statefile)
        self.library.logging_tag = 'testingpuppetctl[{}]'.format(
            self.library.invoking_user)
        self.pe_patcher.start()

    def tearDown(self):
        ''' Cleanup test rig '''
        try:
            os.remove(self.test_statefile)
        except OSError:  # pragma: no cover
            # we likely never created the file.
            pass
        self.pe_patcher.stop()

    def test_perms_block_run(self):
        ''' Test that non-root can't run the important functions. '''
        oneoff = PuppetctlExecution(self.test_statefile)
        with mock.patch.object(PuppetctlExecution,
                               '_allowed_to_run_command',
                               return_value=False):
            with self.assertRaises(SystemExit) as fail_run, \
                    mock.patch('sys.stdout', new=StringIO()):
                oneoff.run([])
            self.assertEqual(fail_run.exception.code, 2)

    def test_run_nolocks(self):
        ''' Test that "run" fires when there are no locks. '''
        with mock.patch('os.execvpe') as mock_exec:
            self.library.run([])
        my_env = os.environ
        my_env['PATH'] = self.library.puppet_bin_path
        mock_exec.assert_called_once_with('puppet', [
            'puppet', 'agent', '--verbose', '--onetime', '--no-daemonize',
            '--no-splay'
        ],
                                          env=my_env)

    def test_run_nolocks_with_args(self):
        ''' Test that "run" passes args along. '''
        with mock.patch('os.execvpe') as mock_exec:
            self.library.run(['--nonsense1', '--shenanigans2'])
        my_env = os.environ
        my_env['PATH'] = self.library.puppet_bin_path
        mock_exec.assert_called_once_with('puppet', [
            'puppet', 'agent', '--verbose', '--onetime', '--no-daemonize',
            '--no-splay', '--nonsense1', '--shenanigans2'
        ],
                                          env=my_env)

    def test_run_not_our_locks(self):
        ''' Test that "run" does nothing when we have no locks, but others do. '''
        now = int(time.time())
        with mock.patch.object(PuppetctlStatefile,
                               '_allowed_to_write_statefile',
                               return_value=True):
            self.library.statefile_object.add_lock('somebody2', 'disable',
                                                   now + 30 * 60,
                                                   'I disabled 1h')
            self.library.statefile_object.add_lock('somebody3', 'nooperate',
                                                   now + 90 * 60,
                                                   'I nooped 2h')
        with self.assertRaises(SystemExit) as fail_run:
            with mock.patch('sys.stdout', new=StringIO()):
                self.library.run([])
        self.assertEqual(fail_run.exception.code, 0)
        # We don't test the stdout result here because of isatty and py2.
        # We could extend this once we're pure py3

    def test_run_disable_lock_tty(self):
        ''' Test that "run" does nothing when I have a lock, and tells me. '''
        now = int(time.time())
        with mock.patch.object(PuppetctlStatefile,
                               '_allowed_to_write_statefile',
                               return_value=True):
            self.library.statefile_object.add_lock(self.library.invoking_user,
                                                   'disable', now + 30 * 60,
                                                   'It is my lock')
        with self.assertRaises(SystemExit) as fail_run:
            # Order matters here: isatty comes second since we are touching stdout twice.
            with mock.patch('sys.stdout', new=StringIO()) as fake_out, \
                    mock.patch('sys.stdout.isatty', return_value=True):
                self.library.run([])
        self.assertEqual(fail_run.exception.code, 0)
        self.assertIn('Puppet has been disabled', fake_out.getvalue())

    def test_run_disable_lock_notty(self):
        ''' Test that "run" does nothing when I have a lock, and is silent '''
        now = int(time.time())
        with mock.patch.object(PuppetctlStatefile,
                               '_allowed_to_write_statefile',
                               return_value=True):
            self.library.statefile_object.add_lock(self.library.invoking_user,
                                                   'disable', now + 30 * 60,
                                                   'It is my lock')
        with self.assertRaises(SystemExit) as fail_run:
            # Order matters here: isatty comes second since we are touching stdout twice.
            with mock.patch('sys.stdout', new=StringIO()) as fake_out, \
                    mock.patch('sys.stdout.isatty', return_value=False):
                self.library.run([])
        self.assertEqual(fail_run.exception.code, 0)
        self.assertIn('Puppet has been disabled', fake_out.getvalue())

    def test_run_noop_lock(self):
        ''' Test that "run" fires noop mode I have a noop lock. '''
        now = int(time.time())
        with mock.patch.object(PuppetctlStatefile,
                               '_allowed_to_write_statefile',
                               return_value=True):
            self.library.statefile_object.add_lock(self.library.invoking_user,
                                                   'nooperate', now + 30 * 60,
                                                   'It is my lock')
        with mock.patch('os.execvpe') as mock_exec:
            self.library.run([])
        my_env = os.environ
        my_env['PATH'] = self.library.puppet_bin_path
        mock_exec.assert_called_once_with('puppet', [
            'puppet', 'agent', '--verbose', '--onetime', '--no-daemonize',
            '--no-splay', '--noop'
        ],
                                          env=my_env)
Пример #18
0
class TestExecutionNooperate(unittest.TestCase):
    ''' Class of tests about executing puppetctl nooperate commands. '''
    def setUp(self):
        ''' Preparing test rig '''
        self.test_statefile = '/tmp/exec-nooperate-statefile-mods.test.txt'
        self.library = PuppetctlExecution(self.test_statefile)
        self.library.logging_tag = 'testingpuppetctl[{}]'.format(
            self.library.invoking_user)

    def tearDown(self):
        ''' Cleanup test rig '''
        try:
            os.remove(self.test_statefile)
        except OSError:  # pragma: no cover
            # we likely never created the file.
            pass

    def test_permissions_block_noop(self):
        ''' Test that non-root can't run the important functions. '''
        oneoff = PuppetctlExecution(self.test_statefile)
        with mock.patch.object(PuppetctlExecution,
                               '_allowed_to_run_command',
                               return_value=False):
            with self.assertRaises(SystemExit) as fail_nooperate, \
                    mock.patch('sys.stdout', new=StringIO()):
                oneoff.nooperate(False, int(time.time() + 60),
                                 'failure testing')
            self.assertEqual(fail_nooperate.exception.code, 2)

    def test_noop_nolocks(self):
        ''' Test that "nooperate" noops when there are no locks. '''
        with mock.patch.object(PuppetctlStatefile,
                               '_allowed_to_write_statefile',
                               return_value=True):
            with mock.patch('sys.stdout', new=StringIO()) as fake_out, \
                    mock.patch.object(PuppetctlExecution, '_puppet_processes_running',
                                      return_value={}), \
                    mock.patch.object(PuppetctlExecution, '_allowed_to_run_command',
                                      return_value=True):
                self.library.nooperate(force=False,
                                       expiry=int(time.time()) + 60 * 60,
                                       message='')
        self.assertIn('Puppet is in nooperate mode', fake_out.getvalue())

    def test_noop_nolocks_puppetrun(self):
        ''' Test that "nooperate" noops when there are no locks but puppet is running '''
        with mock.patch.object(PuppetctlStatefile,
                               '_allowed_to_write_statefile',
                               return_value=True):
            with mock.patch('sys.stdout', new=StringIO()) as fake_out, \
                    mock.patch.object(PuppetctlExecution, '_puppet_processes_running',
                                      return_value={'2468': 'mock-puppet agent --no-splay'}), \
                    mock.patch.object(PuppetctlExecution, '_allowed_to_run_command',
                                      return_value=True):
                self.library.nooperate(force=False,
                                       expiry=int(time.time()) + 60 * 60,
                                       message='')
        self.assertIn('mock-puppet agent --no-splay', fake_out.getvalue())
        self.assertIn(
            'If you need to stop an active puppet run from finishing',
            fake_out.getvalue())
        self.assertIn('Puppet is in nooperate mode', fake_out.getvalue())

    def test_noop_not_our_locks(self):
        ''' Test that "nooperate" noops when we have no locks, but others do. '''
        now = int(time.time())
        with mock.patch.object(PuppetctlStatefile,
                               '_allowed_to_write_statefile',
                               return_value=True):
            self.library.statefile_object.add_lock('somebody2', 'disable',
                                                   now + 30 * 60,
                                                   'I disabled 1h')
            self.library.statefile_object.add_lock('somebody3', 'nooperate',
                                                   now + 90 * 60,
                                                   'I nooped 2h')
            with mock.patch('sys.stdout', new=StringIO()) as fake_out, \
                    mock.patch.object(PuppetctlExecution, '_allowed_to_run_command',
                                      return_value=True):
                self.library.nooperate(force=False,
                                       expiry=int(time.time()) + 60 * 60,
                                       message='')
        self.assertIn('Puppet is in nooperate mode', fake_out.getvalue())

    def test_noop_disable_mylock(self):
        ''' Test that "nooperate" refuses to noop when I have a disable. '''
        now = int(time.time())
        with mock.patch.object(PuppetctlStatefile,
                               '_allowed_to_write_statefile',
                               return_value=True):
            self.library.statefile_object.add_lock(self.library.invoking_user,
                                                   'disable', now + 30 * 60,
                                                   'It is my lock')
        with self.assertRaises(SystemExit) as catch_noforce, \
                mock.patch('sys.stdout', new=StringIO()) as fake_out, \
                mock.patch.object(PuppetctlExecution, '_allowed_to_run_command',
                                  return_value=True):
            self.library.nooperate(force=False,
                                   expiry=int(time.time()) + 60 * 60,
                                   message='')
        self.assertIn('must be enabled to enter nooperate mode',
                      fake_out.getvalue())
        self.assertEqual(catch_noforce.exception.code, 2)

    def test_noop_force_mylock(self):
        ''' Test that "nooperate" noops when I force a lock. '''
        now = int(time.time())
        with mock.patch.object(PuppetctlStatefile,
                               '_allowed_to_write_statefile',
                               return_value=True):
            self.library.statefile_object.add_lock(self.library.invoking_user,
                                                   'nooperate', now + 30 * 60,
                                                   'old lock')
            with mock.patch('sys.stdout', new=StringIO()) as fake_out, \
                    mock.patch.object(PuppetctlExecution, '_allowed_to_run_command',
                                      return_value=True):
                self.library.nooperate(force=True,
                                       expiry=int(time.time()) + 60 * 60,
                                       message='new lock')
        self.assertIn('Puppet is in nooperate mode', fake_out.getvalue())
        self.assertIn('new lock', fake_out.getvalue())

    def test_noop_noop_mylock(self):
        ''' Test that "nooperate" doesn't act when there's a noop lock. '''
        now = int(time.time())
        with mock.patch.object(PuppetctlStatefile,
                               '_allowed_to_write_statefile',
                               return_value=True):
            self.library.statefile_object.add_lock(self.library.invoking_user,
                                                   'nooperate', now + 30 * 60,
                                                   'old lock')
        with self.assertRaises(SystemExit) as catch_noforce, \
                mock.patch('sys.stdout', new=StringIO()) as fake_out, \
                mock.patch.object(PuppetctlExecution, '_allowed_to_run_command',
                                  return_value=True):
            self.library.nooperate(force=False,
                                   expiry=int(time.time()) + 60 * 60,
                                   message='new lock')
        self.assertIn('Puppet is already in nooperate mode',
                      fake_out.getvalue())
        self.assertEqual(catch_noforce.exception.code, 1)

    def test_noop_fail_add_lock(self):
        ''' Test that "nooperate" complains if it can't add a lock '''
        with mock.patch.object(PuppetctlStatefile, 'add_lock', return_value=False), \
                self.assertRaises(SystemExit) as lockfail, \
                mock.patch('sys.stdout', new=StringIO()) as fake_out, \
                mock.patch.object(PuppetctlExecution, '_allowed_to_run_command',
                                  return_value=True):
            self.library.nooperate(force=False,
                                   expiry=int(time.time()) + 60 * 60,
                                   message='lock')
        self.assertEqual(lockfail.exception.code, 2)
        self.assertIn('Unable to add lock', fake_out.getvalue())

    def test_noop_failremovenoop(self):
        ''' Test that "nooperate" complains if it can't override noop locks. '''
        now = int(time.time())
        with mock.patch.object(PuppetctlStatefile,
                               '_allowed_to_write_statefile',
                               return_value=True):
            self.library.statefile_object.add_lock(self.library.invoking_user,
                                                   'nooperate', now + 30 * 60,
                                                   'It is my lock')
        with mock.patch.object(PuppetctlStatefile, 'remove_lock', return_value=False), \
                self.assertRaises(SystemExit) as lockfail, \
                mock.patch('sys.stdout', new=StringIO()) as fake_out, \
                mock.patch.object(PuppetctlExecution, '_allowed_to_run_command',
                                  return_value=True):
            self.library.nooperate(force=True,
                                   expiry=int(time.time()) + 60 * 60,
                                   message='new lock')
        self.assertIn('Unable to remove', fake_out.getvalue())
        self.assertEqual(lockfail.exception.code, 2)
Пример #19
0
 def test_init_statefile_kwarg(self):
     ''' Verify the object was initialized with a state file, kwarg arg '''
     library = PuppetctlExecution(state_file=self.test_statefile)
     self.assertEqual(library.statefile_object.state_file,
                      self.test_statefile)
Пример #20
0
 def setUp(self):
     ''' Preparing test rig '''
     self.test_statefile = '/tmp/exec-nooperate-statefile-mods.test.txt'
     self.library = PuppetctlExecution(self.test_statefile)
     self.library.logging_tag = 'testingpuppetctl[{}]'.format(
         self.library.invoking_user)
Пример #21
0
class TestExecutionBreakAllLocks(unittest.TestCase):
    ''' Class of tests about executing puppetctl break_all_locks commands. '''
    def setUp(self):
        ''' Preparing test rig '''
        self.test_statefile = '/tmp/exec-break_all_locks-statefile-mods.test.txt'
        self.library = PuppetctlExecution(self.test_statefile)
        self.library.logging_tag = 'testingpuppetctl[{}]'.format(
            self.library.invoking_user)

    def tearDown(self):
        ''' Cleanup test rig '''
        try:
            os.remove(self.test_statefile)
        except OSError:  # pragma: no cover
            # we likely never created the file.
            pass

    def test_nothing_to_do(self):
        ''' Test that we do nothing if there aren't locks to break. '''
        oneoff = PuppetctlExecution(self.test_statefile)
        with mock.patch.object(PuppetctlExecution, '_allowed_to_run_command',
                               return_value=True), \
                mock.patch.object(PuppetctlExecution, 'is_enabled', return_value=True), \
                mock.patch.object(PuppetctlExecution, 'is_operating', return_value=True), \
                self.assertRaises(SystemExit) as fail_break, \
                mock.patch('sys.stdout', new=StringIO()) as fake_out:
            oneoff.break_all_locks(2)
        self.assertIn('There are no locks', fake_out.getvalue())
        self.assertEqual(fail_break.exception.code, 0)

    def test_perms_block_break(self):
        ''' Test that non-root can't run the important functions. '''
        oneoff = PuppetctlExecution(self.test_statefile)
        with mock.patch.object(PuppetctlExecution, '_allowed_to_run_command',
                               return_value=False), \
                mock.patch.object(PuppetctlExecution, 'is_enabled', return_value=False), \
                self.assertRaises(SystemExit) as fail_break, \
                mock.patch('sys.stdout', new=StringIO()):
            oneoff.break_all_locks(2)
        self.assertEqual(fail_break.exception.code, 2)

    def test_break_bad_parameters(self):
        ''' Test that 'break_all_locks' fails if double-force isn't applied. '''
        with mock.patch.object(PuppetctlExecution, '_allowed_to_run_command',
                               return_value=True), \
                mock.patch.object(PuppetctlExecution, 'is_enabled', return_value=False):
            with self.assertRaises(SystemExit) as fail_break_weak_force0, \
                    mock.patch('sys.stdout', new=StringIO()):
                self.library.break_all_locks(0)
            self.assertEqual(fail_break_weak_force0.exception.code, 2)
            with self.assertRaises(SystemExit) as fail_break_weak_force1, \
                    mock.patch('sys.stdout', new=StringIO()):
                self.library.break_all_locks(1)
            self.assertEqual(fail_break_weak_force1.exception.code, 2)
            with self.assertRaises(SystemExit) as fail_break_weirdparam, \
                    mock.patch('sys.stdout', new=StringIO()):
                self.library.break_all_locks(True)
            self.assertEqual(fail_break_weirdparam.exception.code, 2)

    def test_break_good_no_write(self):
        ''' Test that 'break_all_locks' fails if somehow we can't write the file. '''
        with mock.patch.object(PuppetctlExecution, '_allowed_to_run_command',
                               return_value=True), \
                mock.patch.object(PuppetctlExecution, 'is_enabled', return_value=False), \
                mock.patch.object(PuppetctlStatefile, '_allowed_to_write_statefile',
                                  return_value=False):
            with self.assertRaises(SystemExit) as fail_break_writing, \
                    mock.patch('time.sleep'), \
                    mock.patch('sys.stdout', new=StringIO()):
                self.library.break_all_locks(2)
            self.assertEqual(fail_break_writing.exception.code, 2)

    def test_break_good(self):
        ''' Test that 'break_all_locks' can work. '''
        with mock.patch.object(PuppetctlExecution, '_allowed_to_run_command',
                               return_value=True), \
                mock.patch.object(PuppetctlExecution, 'is_enabled', return_value=False), \
                mock.patch.object(PuppetctlStatefile, '_allowed_to_write_statefile',
                                  return_value=True):
            # make sure there's a file there, or our reset count will be > 1
            # below during the actual test.
            self.library.statefile_object.reset_state_file()
            # "Hey, you're not testing with locks!"  Yeah.  Since we're stomping all
            # locks it doesn't really matter what was in it before.
            with mock.patch.object(PuppetctlStatefile, 'reset_state_file') as mock_reset, \
                    mock.patch('time.sleep'), \
                    mock.patch('sys.stdout', new=StringIO()):
                self.library.break_all_locks(2)
            mock_reset.assert_called_once_with()