Blame cloudinit/cmd/tests/test_status.py

Packit bc9a3a
# This file is part of cloud-init. See LICENSE file for license information.
Packit bc9a3a
Packit bc9a3a
from collections import namedtuple
Packit bc9a3a
import os
Packit bc9a3a
from six import StringIO
Packit bc9a3a
from textwrap import dedent
Packit bc9a3a
Packit bc9a3a
from cloudinit.atomic_helper import write_json
Packit bc9a3a
from cloudinit.cmd import status
Packit bc9a3a
from cloudinit.util import ensure_file
Packit bc9a3a
from cloudinit.tests.helpers import CiTestCase, wrap_and_call, mock
Packit bc9a3a
Packit bc9a3a
mypaths = namedtuple('MyPaths', 'run_dir')
Packit bc9a3a
myargs = namedtuple('MyArgs', 'long wait')
Packit bc9a3a
Packit bc9a3a
Packit bc9a3a
class TestStatus(CiTestCase):
Packit bc9a3a
Packit bc9a3a
    def setUp(self):
Packit bc9a3a
        super(TestStatus, self).setUp()
Packit bc9a3a
        self.new_root = self.tmp_dir()
Packit bc9a3a
        self.status_file = self.tmp_path('status.json', self.new_root)
Packit bc9a3a
        self.disable_file = self.tmp_path('cloudinit-disable', self.new_root)
Packit bc9a3a
        self.paths = mypaths(run_dir=self.new_root)
Packit bc9a3a
Packit bc9a3a
        class FakeInit(object):
Packit bc9a3a
            paths = self.paths
Packit bc9a3a
Packit bc9a3a
            def __init__(self, ds_deps):
Packit bc9a3a
                pass
Packit bc9a3a
Packit bc9a3a
            def read_cfg(self):
Packit bc9a3a
                pass
Packit bc9a3a
Packit bc9a3a
        self.init_class = FakeInit
Packit bc9a3a
Packit bc9a3a
    def test__is_cloudinit_disabled_false_on_sysvinit(self):
Packit bc9a3a
        '''When not in an environment using systemd, return False.'''
Packit bc9a3a
        ensure_file(self.disable_file)  # Create the ignored disable file
Packit bc9a3a
        (is_disabled, reason) = wrap_and_call(
Packit bc9a3a
            'cloudinit.cmd.status',
Packit bc9a3a
            {'uses_systemd': False,
Packit bc9a3a
             'get_cmdline': "root=/dev/my-root not-important"},
Packit bc9a3a
            status._is_cloudinit_disabled, self.disable_file, self.paths)
Packit bc9a3a
        self.assertFalse(
Packit bc9a3a
            is_disabled, 'expected enabled cloud-init on sysvinit')
Packit bc9a3a
        self.assertEqual('Cloud-init enabled on sysvinit', reason)
Packit bc9a3a
Packit bc9a3a
    def test__is_cloudinit_disabled_true_on_disable_file(self):
Packit bc9a3a
        '''When using systemd and disable_file is present return disabled.'''
Packit bc9a3a
        ensure_file(self.disable_file)  # Create observed disable file
Packit bc9a3a
        (is_disabled, reason) = wrap_and_call(
Packit bc9a3a
            'cloudinit.cmd.status',
Packit bc9a3a
            {'uses_systemd': True,
Packit bc9a3a
             'get_cmdline': "root=/dev/my-root not-important"},
Packit bc9a3a
            status._is_cloudinit_disabled, self.disable_file, self.paths)
Packit bc9a3a
        self.assertTrue(is_disabled, 'expected disabled cloud-init')
Packit bc9a3a
        self.assertEqual(
Packit bc9a3a
            'Cloud-init disabled by {0}'.format(self.disable_file), reason)
Packit bc9a3a
Packit bc9a3a
    def test__is_cloudinit_disabled_false_on_kernel_cmdline_enable(self):
Packit bc9a3a
        '''Not disabled when using systemd and enabled via commandline.'''
Packit bc9a3a
        ensure_file(self.disable_file)  # Create ignored disable file
Packit bc9a3a
        (is_disabled, reason) = wrap_and_call(
Packit bc9a3a
            'cloudinit.cmd.status',
Packit bc9a3a
            {'uses_systemd': True,
Packit bc9a3a
             'get_cmdline': 'something cloud-init=enabled else'},
Packit bc9a3a
            status._is_cloudinit_disabled, self.disable_file, self.paths)
Packit bc9a3a
        self.assertFalse(is_disabled, 'expected enabled cloud-init')
Packit bc9a3a
        self.assertEqual(
Packit bc9a3a
            'Cloud-init enabled by kernel command line cloud-init=enabled',
Packit bc9a3a
            reason)
Packit bc9a3a
Packit bc9a3a
    def test__is_cloudinit_disabled_true_on_kernel_cmdline(self):
Packit bc9a3a
        '''When using systemd and disable_file is present return disabled.'''
Packit bc9a3a
        (is_disabled, reason) = wrap_and_call(
Packit bc9a3a
            'cloudinit.cmd.status',
Packit bc9a3a
            {'uses_systemd': True,
Packit bc9a3a
             'get_cmdline': 'something cloud-init=disabled else'},
Packit bc9a3a
            status._is_cloudinit_disabled, self.disable_file, self.paths)
Packit bc9a3a
        self.assertTrue(is_disabled, 'expected disabled cloud-init')
Packit bc9a3a
        self.assertEqual(
Packit bc9a3a
            'Cloud-init disabled by kernel parameter cloud-init=disabled',
Packit bc9a3a
            reason)
Packit bc9a3a
Packit bc9a3a
    def test__is_cloudinit_disabled_true_when_generator_disables(self):
Packit bc9a3a
        '''When cloud-init-generator doesn't write enabled file return True.'''
Packit bc9a3a
        enabled_file = os.path.join(self.paths.run_dir, 'enabled')
Packit bc9a3a
        self.assertFalse(os.path.exists(enabled_file))
Packit bc9a3a
        (is_disabled, reason) = wrap_and_call(
Packit bc9a3a
            'cloudinit.cmd.status',
Packit bc9a3a
            {'uses_systemd': True,
Packit bc9a3a
             'get_cmdline': 'something'},
Packit bc9a3a
            status._is_cloudinit_disabled, self.disable_file, self.paths)
Packit bc9a3a
        self.assertTrue(is_disabled, 'expected disabled cloud-init')
Packit bc9a3a
        self.assertEqual('Cloud-init disabled by cloud-init-generator', reason)
Packit bc9a3a
Packit bc9a3a
    def test__is_cloudinit_disabled_false_when_enabled_in_systemd(self):
Packit bc9a3a
        '''Report enabled when systemd generator creates the enabled file.'''
Packit bc9a3a
        enabled_file = os.path.join(self.paths.run_dir, 'enabled')
Packit bc9a3a
        ensure_file(enabled_file)
Packit bc9a3a
        (is_disabled, reason) = wrap_and_call(
Packit bc9a3a
            'cloudinit.cmd.status',
Packit bc9a3a
            {'uses_systemd': True,
Packit bc9a3a
             'get_cmdline': 'something ignored'},
Packit bc9a3a
            status._is_cloudinit_disabled, self.disable_file, self.paths)
Packit bc9a3a
        self.assertFalse(is_disabled, 'expected enabled cloud-init')
Packit bc9a3a
        self.assertEqual(
Packit bc9a3a
            'Cloud-init enabled by systemd cloud-init-generator', reason)
Packit bc9a3a
Packit bc9a3a
    def test_status_returns_not_run(self):
Packit bc9a3a
        '''When status.json does not exist yet, return 'not run'.'''
Packit bc9a3a
        self.assertFalse(
Packit bc9a3a
            os.path.exists(self.status_file), 'Unexpected status.json found')
Packit bc9a3a
        cmdargs = myargs(long=False, wait=False)
Packit bc9a3a
        with mock.patch('sys.stdout', new_callable=StringIO) as m_stdout:
Packit bc9a3a
            retcode = wrap_and_call(
Packit bc9a3a
                'cloudinit.cmd.status',
Packit bc9a3a
                {'_is_cloudinit_disabled': (False, ''),
Packit bc9a3a
                 'Init': {'side_effect': self.init_class}},
Packit bc9a3a
                status.handle_status_args, 'ignored', cmdargs)
Packit bc9a3a
        self.assertEqual(0, retcode)
Packit bc9a3a
        self.assertEqual('status: not run\n', m_stdout.getvalue())
Packit bc9a3a
Packit bc9a3a
    def test_status_returns_disabled_long_on_presence_of_disable_file(self):
Packit bc9a3a
        '''When cloudinit is disabled, return disabled reason.'''
Packit bc9a3a
Packit bc9a3a
        checked_files = []
Packit bc9a3a
Packit bc9a3a
        def fakeexists(filepath):
Packit bc9a3a
            checked_files.append(filepath)
Packit bc9a3a
            status_file = os.path.join(self.paths.run_dir, 'status.json')
Packit bc9a3a
            return bool(not filepath == status_file)
Packit bc9a3a
Packit bc9a3a
        cmdargs = myargs(long=True, wait=False)
Packit bc9a3a
        with mock.patch('sys.stdout', new_callable=StringIO) as m_stdout:
Packit bc9a3a
            retcode = wrap_and_call(
Packit bc9a3a
                'cloudinit.cmd.status',
Packit bc9a3a
                {'os.path.exists': {'side_effect': fakeexists},
Packit bc9a3a
                 '_is_cloudinit_disabled': (True, 'disabled for some reason'),
Packit bc9a3a
                 'Init': {'side_effect': self.init_class}},
Packit bc9a3a
                status.handle_status_args, 'ignored', cmdargs)
Packit bc9a3a
        self.assertEqual(0, retcode)
Packit bc9a3a
        self.assertEqual(
Packit bc9a3a
            [os.path.join(self.paths.run_dir, 'status.json')],
Packit bc9a3a
            checked_files)
Packit bc9a3a
        expected = dedent('''\
Packit bc9a3a
            status: disabled
Packit bc9a3a
            detail:
Packit bc9a3a
            disabled for some reason
Packit bc9a3a
        ''')
Packit bc9a3a
        self.assertEqual(expected, m_stdout.getvalue())
Packit bc9a3a
Packit bc9a3a
    def test_status_returns_running_on_no_results_json(self):
Packit bc9a3a
        '''Report running when status.json exists but result.json does not.'''
Packit bc9a3a
        result_file = self.tmp_path('result.json', self.new_root)
Packit bc9a3a
        write_json(self.status_file, {})
Packit bc9a3a
        self.assertFalse(
Packit bc9a3a
            os.path.exists(result_file), 'Unexpected result.json found')
Packit bc9a3a
        cmdargs = myargs(long=False, wait=False)
Packit bc9a3a
        with mock.patch('sys.stdout', new_callable=StringIO) as m_stdout:
Packit bc9a3a
            retcode = wrap_and_call(
Packit bc9a3a
                'cloudinit.cmd.status',
Packit bc9a3a
                {'_is_cloudinit_disabled': (False, ''),
Packit bc9a3a
                 'Init': {'side_effect': self.init_class}},
Packit bc9a3a
                status.handle_status_args, 'ignored', cmdargs)
Packit bc9a3a
        self.assertEqual(0, retcode)
Packit bc9a3a
        self.assertEqual('status: running\n', m_stdout.getvalue())
Packit bc9a3a
Packit bc9a3a
    def test_status_returns_running(self):
Packit bc9a3a
        '''Report running when status exists with an unfinished stage.'''
Packit bc9a3a
        ensure_file(self.tmp_path('result.json', self.new_root))
Packit bc9a3a
        write_json(self.status_file,
Packit bc9a3a
                   {'v1': {'init': {'start': 1, 'finished': None}}})
Packit bc9a3a
        cmdargs = myargs(long=False, wait=False)
Packit bc9a3a
        with mock.patch('sys.stdout', new_callable=StringIO) as m_stdout:
Packit bc9a3a
            retcode = wrap_and_call(
Packit bc9a3a
                'cloudinit.cmd.status',
Packit bc9a3a
                {'_is_cloudinit_disabled': (False, ''),
Packit bc9a3a
                 'Init': {'side_effect': self.init_class}},
Packit bc9a3a
                status.handle_status_args, 'ignored', cmdargs)
Packit bc9a3a
        self.assertEqual(0, retcode)
Packit bc9a3a
        self.assertEqual('status: running\n', m_stdout.getvalue())
Packit bc9a3a
Packit bc9a3a
    def test_status_returns_done(self):
Packit bc9a3a
        '''Report done results.json exists no stages are unfinished.'''
Packit bc9a3a
        ensure_file(self.tmp_path('result.json', self.new_root))
Packit bc9a3a
        write_json(
Packit bc9a3a
            self.status_file,
Packit bc9a3a
            {'v1': {'stage': None,  # No current stage running
Packit bc9a3a
                    'datasource': (
Packit bc9a3a
                        'DataSourceNoCloud [seed=/var/.../seed/nocloud-net]'
Packit bc9a3a
                        '[dsmode=net]'),
Packit bc9a3a
                    'blah': {'finished': 123.456},
Packit bc9a3a
                    'init': {'errors': [], 'start': 124.567,
Packit bc9a3a
                             'finished': 125.678},
Packit bc9a3a
                    'init-local': {'start': 123.45, 'finished': 123.46}}})
Packit bc9a3a
        cmdargs = myargs(long=False, wait=False)
Packit bc9a3a
        with mock.patch('sys.stdout', new_callable=StringIO) as m_stdout:
Packit bc9a3a
            retcode = wrap_and_call(
Packit bc9a3a
                'cloudinit.cmd.status',
Packit bc9a3a
                {'_is_cloudinit_disabled': (False, ''),
Packit bc9a3a
                 'Init': {'side_effect': self.init_class}},
Packit bc9a3a
                status.handle_status_args, 'ignored', cmdargs)
Packit bc9a3a
        self.assertEqual(0, retcode)
Packit bc9a3a
        self.assertEqual('status: done\n', m_stdout.getvalue())
Packit bc9a3a
Packit bc9a3a
    def test_status_returns_done_long(self):
Packit bc9a3a
        '''Long format of done status includes datasource info.'''
Packit bc9a3a
        ensure_file(self.tmp_path('result.json', self.new_root))
Packit bc9a3a
        write_json(
Packit bc9a3a
            self.status_file,
Packit bc9a3a
            {'v1': {'stage': None,
Packit bc9a3a
                    'datasource': (
Packit bc9a3a
                        'DataSourceNoCloud [seed=/var/.../seed/nocloud-net]'
Packit bc9a3a
                        '[dsmode=net]'),
Packit bc9a3a
                    'init': {'start': 124.567, 'finished': 125.678},
Packit bc9a3a
                    'init-local': {'start': 123.45, 'finished': 123.46}}})
Packit bc9a3a
        cmdargs = myargs(long=True, wait=False)
Packit bc9a3a
        with mock.patch('sys.stdout', new_callable=StringIO) as m_stdout:
Packit bc9a3a
            retcode = wrap_and_call(
Packit bc9a3a
                'cloudinit.cmd.status',
Packit bc9a3a
                {'_is_cloudinit_disabled': (False, ''),
Packit bc9a3a
                 'Init': {'side_effect': self.init_class}},
Packit bc9a3a
                status.handle_status_args, 'ignored', cmdargs)
Packit bc9a3a
        self.assertEqual(0, retcode)
Packit bc9a3a
        expected = dedent('''\
Packit bc9a3a
            status: done
Packit bc9a3a
            time: Thu, 01 Jan 1970 00:02:05 +0000
Packit bc9a3a
            detail:
Packit bc9a3a
            DataSourceNoCloud [seed=/var/.../seed/nocloud-net][dsmode=net]
Packit bc9a3a
        ''')
Packit bc9a3a
        self.assertEqual(expected, m_stdout.getvalue())
Packit bc9a3a
Packit bc9a3a
    def test_status_on_errors(self):
Packit bc9a3a
        '''Reports error when any stage has errors.'''
Packit bc9a3a
        write_json(
Packit bc9a3a
            self.status_file,
Packit bc9a3a
            {'v1': {'stage': None,
Packit bc9a3a
                    'blah': {'errors': [], 'finished': 123.456},
Packit bc9a3a
                    'init': {'errors': ['error1'], 'start': 124.567,
Packit bc9a3a
                             'finished': 125.678},
Packit bc9a3a
                    'init-local': {'start': 123.45, 'finished': 123.46}}})
Packit bc9a3a
        cmdargs = myargs(long=False, wait=False)
Packit bc9a3a
        with mock.patch('sys.stdout', new_callable=StringIO) as m_stdout:
Packit bc9a3a
            retcode = wrap_and_call(
Packit bc9a3a
                'cloudinit.cmd.status',
Packit bc9a3a
                {'_is_cloudinit_disabled': (False, ''),
Packit bc9a3a
                 'Init': {'side_effect': self.init_class}},
Packit bc9a3a
                status.handle_status_args, 'ignored', cmdargs)
Packit bc9a3a
        self.assertEqual(1, retcode)
Packit bc9a3a
        self.assertEqual('status: error\n', m_stdout.getvalue())
Packit bc9a3a
Packit bc9a3a
    def test_status_on_errors_long(self):
Packit bc9a3a
        '''Long format of error status includes all error messages.'''
Packit bc9a3a
        write_json(
Packit bc9a3a
            self.status_file,
Packit bc9a3a
            {'v1': {'stage': None,
Packit bc9a3a
                    'datasource': (
Packit bc9a3a
                        'DataSourceNoCloud [seed=/var/.../seed/nocloud-net]'
Packit bc9a3a
                        '[dsmode=net]'),
Packit bc9a3a
                    'init': {'errors': ['error1'], 'start': 124.567,
Packit bc9a3a
                             'finished': 125.678},
Packit bc9a3a
                    'init-local': {'errors': ['error2', 'error3'],
Packit bc9a3a
                                   'start': 123.45, 'finished': 123.46}}})
Packit bc9a3a
        cmdargs = myargs(long=True, wait=False)
Packit bc9a3a
        with mock.patch('sys.stdout', new_callable=StringIO) as m_stdout:
Packit bc9a3a
            retcode = wrap_and_call(
Packit bc9a3a
                'cloudinit.cmd.status',
Packit bc9a3a
                {'_is_cloudinit_disabled': (False, ''),
Packit bc9a3a
                 'Init': {'side_effect': self.init_class}},
Packit bc9a3a
                status.handle_status_args, 'ignored', cmdargs)
Packit bc9a3a
        self.assertEqual(1, retcode)
Packit bc9a3a
        expected = dedent('''\
Packit bc9a3a
            status: error
Packit bc9a3a
            time: Thu, 01 Jan 1970 00:02:05 +0000
Packit bc9a3a
            detail:
Packit bc9a3a
            error1
Packit bc9a3a
            error2
Packit bc9a3a
            error3
Packit bc9a3a
        ''')
Packit bc9a3a
        self.assertEqual(expected, m_stdout.getvalue())
Packit bc9a3a
Packit bc9a3a
    def test_status_returns_running_long_format(self):
Packit bc9a3a
        '''Long format reports the stage in which we are running.'''
Packit bc9a3a
        write_json(
Packit bc9a3a
            self.status_file,
Packit bc9a3a
            {'v1': {'stage': 'init',
Packit bc9a3a
                    'init': {'start': 124.456, 'finished': None},
Packit bc9a3a
                    'init-local': {'start': 123.45, 'finished': 123.46}}})
Packit bc9a3a
        cmdargs = myargs(long=True, wait=False)
Packit bc9a3a
        with mock.patch('sys.stdout', new_callable=StringIO) as m_stdout:
Packit bc9a3a
            retcode = wrap_and_call(
Packit bc9a3a
                'cloudinit.cmd.status',
Packit bc9a3a
                {'_is_cloudinit_disabled': (False, ''),
Packit bc9a3a
                 'Init': {'side_effect': self.init_class}},
Packit bc9a3a
                status.handle_status_args, 'ignored', cmdargs)
Packit bc9a3a
        self.assertEqual(0, retcode)
Packit bc9a3a
        expected = dedent('''\
Packit bc9a3a
            status: running
Packit bc9a3a
            time: Thu, 01 Jan 1970 00:02:04 +0000
Packit bc9a3a
            detail:
Packit bc9a3a
            Running in stage: init
Packit bc9a3a
        ''')
Packit bc9a3a
        self.assertEqual(expected, m_stdout.getvalue())
Packit bc9a3a
Packit bc9a3a
    def test_status_wait_blocks_until_done(self):
Packit bc9a3a
        '''Specifying wait will poll every 1/4 second until done state.'''
Packit bc9a3a
        running_json = {
Packit bc9a3a
            'v1': {'stage': 'init',
Packit bc9a3a
                   'init': {'start': 124.456, 'finished': None},
Packit bc9a3a
                   'init-local': {'start': 123.45, 'finished': 123.46}}}
Packit bc9a3a
        done_json = {
Packit bc9a3a
            'v1': {'stage': None,
Packit bc9a3a
                   'init': {'start': 124.456, 'finished': 125.678},
Packit bc9a3a
                   'init-local': {'start': 123.45, 'finished': 123.46}}}
Packit bc9a3a
Packit bc9a3a
        self.sleep_calls = 0
Packit bc9a3a
Packit bc9a3a
        def fake_sleep(interval):
Packit bc9a3a
            self.assertEqual(0.25, interval)
Packit bc9a3a
            self.sleep_calls += 1
Packit bc9a3a
            if self.sleep_calls == 2:
Packit bc9a3a
                write_json(self.status_file, running_json)
Packit bc9a3a
            elif self.sleep_calls == 3:
Packit bc9a3a
                write_json(self.status_file, done_json)
Packit bc9a3a
                result_file = self.tmp_path('result.json', self.new_root)
Packit bc9a3a
                ensure_file(result_file)
Packit bc9a3a
Packit bc9a3a
        cmdargs = myargs(long=False, wait=True)
Packit bc9a3a
        with mock.patch('sys.stdout', new_callable=StringIO) as m_stdout:
Packit bc9a3a
            retcode = wrap_and_call(
Packit bc9a3a
                'cloudinit.cmd.status',
Packit bc9a3a
                {'sleep': {'side_effect': fake_sleep},
Packit bc9a3a
                 '_is_cloudinit_disabled': (False, ''),
Packit bc9a3a
                 'Init': {'side_effect': self.init_class}},
Packit bc9a3a
                status.handle_status_args, 'ignored', cmdargs)
Packit bc9a3a
        self.assertEqual(0, retcode)
Packit bc9a3a
        self.assertEqual(4, self.sleep_calls)
Packit bc9a3a
        self.assertEqual('....\nstatus: done\n', m_stdout.getvalue())
Packit bc9a3a
Packit bc9a3a
    def test_status_wait_blocks_until_error(self):
Packit bc9a3a
        '''Specifying wait will poll every 1/4 second until error state.'''
Packit bc9a3a
        running_json = {
Packit bc9a3a
            'v1': {'stage': 'init',
Packit bc9a3a
                   'init': {'start': 124.456, 'finished': None},
Packit bc9a3a
                   'init-local': {'start': 123.45, 'finished': 123.46}}}
Packit bc9a3a
        error_json = {
Packit bc9a3a
            'v1': {'stage': None,
Packit bc9a3a
                   'init': {'errors': ['error1'], 'start': 124.456,
Packit bc9a3a
                            'finished': 125.678},
Packit bc9a3a
                   'init-local': {'start': 123.45, 'finished': 123.46}}}
Packit bc9a3a
Packit bc9a3a
        self.sleep_calls = 0
Packit bc9a3a
Packit bc9a3a
        def fake_sleep(interval):
Packit bc9a3a
            self.assertEqual(0.25, interval)
Packit bc9a3a
            self.sleep_calls += 1
Packit bc9a3a
            if self.sleep_calls == 2:
Packit bc9a3a
                write_json(self.status_file, running_json)
Packit bc9a3a
            elif self.sleep_calls == 3:
Packit bc9a3a
                write_json(self.status_file, error_json)
Packit bc9a3a
Packit bc9a3a
        cmdargs = myargs(long=False, wait=True)
Packit bc9a3a
        with mock.patch('sys.stdout', new_callable=StringIO) as m_stdout:
Packit bc9a3a
            retcode = wrap_and_call(
Packit bc9a3a
                'cloudinit.cmd.status',
Packit bc9a3a
                {'sleep': {'side_effect': fake_sleep},
Packit bc9a3a
                 '_is_cloudinit_disabled': (False, ''),
Packit bc9a3a
                 'Init': {'side_effect': self.init_class}},
Packit bc9a3a
                status.handle_status_args, 'ignored', cmdargs)
Packit bc9a3a
        self.assertEqual(1, retcode)
Packit bc9a3a
        self.assertEqual(4, self.sleep_calls)
Packit bc9a3a
        self.assertEqual('....\nstatus: error\n', m_stdout.getvalue())
Packit bc9a3a
Packit bc9a3a
    def test_status_main(self):
Packit bc9a3a
        '''status.main can be run as a standalone script.'''
Packit bc9a3a
        write_json(self.status_file,
Packit bc9a3a
                   {'v1': {'init': {'start': 1, 'finished': None}}})
Packit bc9a3a
        with self.assertRaises(SystemExit) as context_manager:
Packit bc9a3a
            with mock.patch('sys.stdout', new_callable=StringIO) as m_stdout:
Packit bc9a3a
                wrap_and_call(
Packit bc9a3a
                    'cloudinit.cmd.status',
Packit bc9a3a
                    {'sys.argv': {'new': ['status']},
Packit bc9a3a
                     'sys.exit': {'side_effect': self.sys_exit},
Packit bc9a3a
                     '_is_cloudinit_disabled': (False, ''),
Packit bc9a3a
                     'Init': {'side_effect': self.init_class}},
Packit bc9a3a
                    status.main)
Packit bc9a3a
        self.assertEqual(0, context_manager.exception.code)
Packit bc9a3a
        self.assertEqual('status: running\n', m_stdout.getvalue())
Packit bc9a3a
Packit bc9a3a
# vi: ts=4 expandtab syntax=python