Пример #1
0
 def it_runs_before_debugging_a_service(self):
     proc = Popen(('setsid', 'pgctl', 'debug', 'sweet'), stdin=PIPE, stdout=PIPE)
     proc.stdin.close()
     try:
         assert proc.stdout.readline() == 'hello, i am a pre-start script in stdout\n'
     finally:
         ctrl_c(proc)
         proc.wait()
Пример #2
0
def run(cmd, **popen_args):
    """run the command, show the output, and return (stdout, stderr, returncode)"""
    from pgctl.subprocess import Popen, PIPE
    process = Popen(cmd, stdout=PIPE, stderr=PIPE, **popen_args)
    stdout, stderr = process.communicate()
    stdout, stderr = stdout.decode('UTF-8'), stderr.decode('UTF-8')
    show_both(stdout, stderr)
    return stdout, stderr, process.returncode
Пример #3
0
def run(cmd, **popen_args):
    """run the command, show the output, and return (stdout, stderr, returncode)"""
    from pgctl.subprocess import Popen, PIPE
    process = Popen(cmd, stdout=PIPE, stderr=PIPE, **popen_args)
    stdout, stderr = process.communicate()
    stdout, stderr = stdout.decode('UTF-8'), stderr.decode('UTF-8')
    show_both(stdout, stderr)
    return stdout, stderr, process.returncode
Пример #4
0
    def it_kills_processes_holding_the_lock(self, tmpdir):
        lockfile = tmpdir.ensure('lock')
        lock = lockfile.open()
        process = Popen(('sleep', 'infinity'))
        lock.close()

        # assert `process` has `lock`
        assert list(fuser(lockfile.strpath)) == [process.pid]

        with mock.patch('sys.stderr', new_callable=StringIO.StringIO) as mock_stderr:
            terminate_runaway_processes(lockfile.strpath)

        assert 'WARNING: Killing these runaway ' in mock_stderr.getvalue()
        wait_for(lambda: process.poll() == -9)
Пример #5
0
def assert_works_interactively():
    read, write = os.openpty()
    pty.normalize_newlines(read)
    # setsid: this simulates the shell's job-control behavior
    proc = Popen(('setsid', 'pgctl', 'debug', 'greeter'), stdin=PIPE, stdout=write)
    os.close(write)

    try:
        assert read_line(read) == 'What is your name?\n'
        proc.stdin.write(b'Buck\n')
        proc.stdin.flush()
        assert read_line(read) == 'Hello, Buck.\n'
    finally:
        ctrl_c(proc)
        proc.wait()
Пример #6
0
def assert_works_interactively():
    read, write = os.openpty()
    pty.normalize_newlines(read)
    # setsid: this simulates the shell's job-control behavior
    proc = Popen(('setsid', 'pgctl-2015', 'debug', 'greeter'), stdin=PIPE, stdout=write)
    os.close(write)

    try:
        assert read_line(read) == 'What is your name?\n'
        proc.stdin.write(b'Buck\n')
        proc.stdin.flush()
        assert read_line(read) == 'Hello, Buck.\n'
    finally:
        ctrl_c(proc)
        proc.wait()
Пример #7
0
def it_disables_polling():
    stderr = open('stderr', 'w')
    proc = Popen(('pgctl', 'debug', 'unreliable'), stdin=open(os.devnull), stdout=PIPE, stderr=stderr)

    def check_file_contents():
        expected = '''\
pgctl-poll-ready: disabled during debug -- quitting
'''
        with open('stderr') as fd:
            actual = fd.read()
        return expected == actual

    wait_for(check_file_contents)
    proc.terminate()
    stderr.close()
Пример #8
0
    def it_stays_locked_for_the_lifetime_of_subprocesses(self, tmpfile):
        from pgctl.subprocess import Popen

        with flock(tmpfile):
            p = Popen(('sleep', '99999'))
            assert p.poll() is None

            assert_locked(tmpfile)

        assert_locked(tmpfile)

        p.terminate()
        assert p.wait() == -15

        with flock(tmpfile):
            print('oh hi there!')
Пример #9
0
def it_disables_polling():
    stderr = open('stderr', 'w')
    proc = Popen(('pgctl', 'debug', 'unreliable'), stdin=open(os.devnull), stdout=PIPE, stderr=stderr)

    def check_file_contents():
        expected = '''\
[pgctl] Stopping: unreliable
[pgctl] Stopped: unreliable
pgctl-poll-ready: disabled during debug -- quitting
'''
        with open('stderr') as fd:
            actual = fd.read()
        return expected == actual

    wait_for(check_file_contents)
    proc.terminate()
    stderr.close()
Пример #10
0
def it_is_disallowed():
    assert_command(
        ('pgctl-2015', 'start'),
        '',
        '''\
[pgctl] Starting: sweet
[pgctl] Started: sweet
''',
        0,
    )

    first = Popen(('pgctl-2015', 'restart'), stdout=PIPE, stderr=PIPE)

    # slow-shutdown takes two seconds to shut down; aim for the middle:
    sleep(1)

    second = Popen(('pgctl-2015', 'restart'), stdout=PIPE, stderr=PIPE)

    first_stdout, first_stderr = first.communicate()
    first_stdout, first_stderr = first_stdout.decode('UTF-8'), first_stderr.decode('UTF-8')
    show_both(first_stdout, first_stderr)
    assert norm.pgctl(first_stderr) == '''\
[pgctl] Stopping: sweet
[pgctl] ERROR: service 'sweet' failed to stop after {TIME} seconds, its status is ready (pid {PID}) {TIME} seconds
==> playground/sweet/log <==
{TIMESTAMP} sweet
{TIMESTAMP} sweet_error
[pgctl]
[pgctl] There might be useful information further up in the log; you can view it by running:
[pgctl]     less +G playground/sweet/log
[pgctl] ERROR: Some services failed to stop: sweet
'''
    assert first_stdout == ''
    assert first.returncode == 1

    second_stdout, second_stderr = second.communicate()
    second_stdout, second_stderr = second_stdout.decode('UTF-8'), second_stderr.decode('UTF-8')
    show_both(second_stdout, second_stderr)
    assert norm.pgctl(second_stderr) == '''\
[pgctl] ERROR: another pgctl command is currently managing this service: (playground/sweet/.pgctl.lock)
{PS-HEADER}
{PS-STATS} ${PREFIX}/bin/python ${PREFIX}/bin/pgctl-2015 restart

'''
    assert second_stdout == ''
    assert second.returncode == 1
Пример #11
0
    def it_logs_continuously_when_run_interactively(self, in_example_dir):
        check_call(('pgctl', 'start'))

        # this pty simulates running in a terminal
        read, write = os.openpty()
        pty.normalize_newlines(read)
        p = Popen(('pgctl', 'log'), stdout=write, stderr=write)
        os.close(write)

        import fcntl
        fl = fcntl.fcntl(read, fcntl.F_GETFL)
        fcntl.fcntl(read, fcntl.F_SETFL, fl | os.O_NONBLOCK)

        assert p.poll() is None  # it's still running

        # needs to loop for several seconds because the default event loop
        # in tail-f is one second.
        # TODO: buf is a list, use wait_for() to append to it
        limit = 3.0
        wait = .1
        buf = b''
        while True:
            try:
                block = os.read(read, 1024)
                print('BLOCK:', block)
            except OSError as error:
                print('ERROR:', error)
                if error.errno == 11:  # other end didn't write yet
                    if limit > 0:
                        import time
                        time.sleep(wait)
                        limit -= wait
                        continue
                    else:
                        break
                else:
                    raise
            buf += block

        from testfixtures import StringComparison as S
        buf = norm.pgctl(buf.decode('UTF-8'))
        print('NORMED:')
        print(buf)
        assert buf == S('''(?s)\
==> playground/ohhi/log <==
{TIMESTAMP} [oe].*
==> playground/sweet/log <==
{TIMESTAMP} sweet
{TIMESTAMP} sweet_error

==> playground/ohhi/log <==
.*{TIMESTAMP} .*$''')
        assert p.poll() is None  # it's still running

        p.terminate()

        assert p.wait() == -15
Пример #12
0
def it_disables_polling_heartbeat():
    from mock import patch
    with patch.dict(os.environ, [('PGCTL_TIMEOUT', '5')]):
        proc = Popen(('pgctl-2015', 'debug', 'slow-startup'), stdin=open(os.devnull), stdout=PIPE, stderr=PIPE)

    from testing.assertions import wait_for
    wait_for(lambda: assert_svstat('playground/slow-startup', state='ready'))

    check_call(('pgctl-2015', 'stop'))
    stdout, stderr = proc.communicate()
    stdout, stderr = stdout.decode('UTF-8'), stderr.decode('UTF-8')

    assert stderr == '''\
[pgctl] Stopping: slow-startup
[pgctl] Stopped: slow-startup
pgctl-poll-ready: service's ready check succeeded
pgctl-poll-ready: heartbeat is disabled during debug -- quitting
'''
    assert stdout == ''
    assert proc.returncode == 0
Пример #13
0
    def it_logs_continuously_when_run_interactively(self, in_example_dir):
        check_call(('pgctl', 'start'))

        # this pty simulates running in a terminal
        read, write = os.openpty()
        pty.normalize_newlines(read)
        p = Popen(('pgctl', 'log'), stdout=write, stderr=write)
        os.close(write)

        import fcntl
        fl = fcntl.fcntl(read, fcntl.F_GETFL)
        fcntl.fcntl(read, fcntl.F_SETFL, fl | os.O_NONBLOCK)

        assert p.poll() is None  # it's still running

        # needs to loop for several seconds because the default event loop
        # in tail-f is one second.
        # TODO: buf is a list, use wait_for() to append to it
        limit = 3.0
        wait = .1
        buf = b''
        while True:
            try:
                block = os.read(read, 1024)
                print('BLOCK:', block)
            except OSError as error:
                print('ERROR:', error)
                if error.errno == 11:  # other end didn't write yet
                    if limit > 0:
                        import time
                        time.sleep(wait)
                        limit -= wait
                        continue
                    else:
                        break
                else:
                    raise
            buf += block

        from testfixtures import StringComparison as S
        buf = norm.pgctl(buf.decode('UTF-8'))
        print('NORMED:')
        print(buf)
        assert buf == S('''(?s)\
==> playground/ohhi/logs/current <==
{TIMESTAMP} [oe].*
==> playground/sweet/logs/current <==
{TIMESTAMP} sweet
{TIMESTAMP} sweet_error

==> playground/ohhi/logs/current <==
.*{TIMESTAMP} .*$''')
        assert p.poll() is None  # it's still running

        p.terminate()

        assert p.wait() == -15
Пример #14
0
    def it_stays_locked_for_the_lifetime_of_subprocesses(self, tmpfile):
        from pgctl.subprocess import Popen

        with flock(tmpfile):
            p = Popen(('sleep', '99999'))
            assert p.poll() is None

            assert_locked(tmpfile)

        assert_locked(tmpfile)

        p.terminate()
        assert p.wait() == -15

        with flock(tmpfile):
            print('oh hi there!')
Пример #15
0
def it_is_disallowed():
    assert_command(
        ('pgctl', 'start'),
        '',
        '''\
[pgctl] Starting: sweet
[pgctl] Started: sweet
''',
        0,
    )

    first = Popen(('pgctl', 'restart'), stdout=PIPE, stderr=PIPE)

    # slow-shutdown takes two seconds to shut down; aim for the middle:
    sleep(1)

    second = Popen(('pgctl', 'restart'), stdout=PIPE, stderr=PIPE)

    first_stdout, first_stderr = first.communicate()
    first_stdout, first_stderr = first_stdout.decode('UTF-8'), first_stderr.decode('UTF-8')
    show_both(first_stdout, first_stderr)
    assert norm.pgctl(first_stderr) == '''\
[pgctl] Stopping: sweet
[pgctl] ERROR: service 'sweet' failed to stop after {TIME} seconds, its status is ready (pid {PID}) {TIME} seconds
==> playground/sweet/log <==
{TIMESTAMP} sweet
{TIMESTAMP} sweet_error
[pgctl]
[pgctl] There might be useful information further up in the log; you can view it by running:
[pgctl]     less +G playground/sweet/log
[pgctl] ERROR: Some services failed to stop: sweet
'''
    assert first_stdout == ''
    assert first.returncode == 1

    second_stdout, second_stderr = second.communicate()
    second_stdout, second_stderr = second_stdout.decode('UTF-8'), second_stderr.decode('UTF-8')
    show_both(second_stdout, second_stderr)
    assert norm.pgctl(second_stderr) == '''\
[pgctl] ERROR: another pgctl command is currently managing this service: (playground/sweet/.pgctl.lock)
{PS-HEADER}
{PS-STATS} ${PREFIX}/bin/python ${PREFIX}/bin/pgctl restart

'''
    assert second_stdout == ''
    assert second.returncode == 1