]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph-deploy.git/commitdiff
moved test to tests to follow best practices 17/head
authorAlfredo Deza <alfredo@deza.pe>
Wed, 17 Jul 2013 20:31:23 +0000 (16:31 -0400)
committerAlfredo Deza <alfredo@deza.pe>
Wed, 17 Jul 2013 20:31:23 +0000 (16:31 -0400)
20 files changed:
ceph_deploy/test/__init__.py [deleted file]
ceph_deploy/test/conftest.py [deleted file]
ceph_deploy/test/directory.py [deleted file]
ceph_deploy/test/fakes.py [deleted file]
ceph_deploy/test/test_cli.py [deleted file]
ceph_deploy/test/test_cli_install.py [deleted file]
ceph_deploy/test/test_cli_mon.py [deleted file]
ceph_deploy/test/test_cli_new.py [deleted file]
ceph_deploy/test/test_cli_osd.py [deleted file]
ceph_deploy/test/test_conf.py [deleted file]
ceph_deploy/tests/__init__.py [new file with mode: 0644]
ceph_deploy/tests/conftest.py [new file with mode: 0644]
ceph_deploy/tests/directory.py [new file with mode: 0644]
ceph_deploy/tests/fakes.py [new file with mode: 0644]
ceph_deploy/tests/test_cli.py [new file with mode: 0644]
ceph_deploy/tests/test_cli_install.py [new file with mode: 0644]
ceph_deploy/tests/test_cli_mon.py [new file with mode: 0644]
ceph_deploy/tests/test_cli_new.py [new file with mode: 0644]
ceph_deploy/tests/test_cli_osd.py [new file with mode: 0644]
ceph_deploy/tests/test_conf.py [new file with mode: 0644]

diff --git a/ceph_deploy/test/__init__.py b/ceph_deploy/test/__init__.py
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/ceph_deploy/test/conftest.py b/ceph_deploy/test/conftest.py
deleted file mode 100644 (file)
index 819fc34..0000000
+++ /dev/null
@@ -1,98 +0,0 @@
-import logging
-import os
-import subprocess
-import sys
-
-
-LOG = logging.getLogger(__name__)
-
-
-def _prepend_path(env):
-    """
-    Make sure the PATH contains the location where the Python binary
-    lives. This makes sure cli tools installed in a virtualenv work.
-    """
-    if env is None:
-        env = os.environ
-    env = dict(env)
-    new = os.path.dirname(sys.executable)
-    path = env.get('PATH')
-    if path is not None:
-        new = new + ':' + path
-    env['PATH'] = new
-    return env
-
-
-class CLIFailed(Exception):
-    """CLI tool failed"""
-
-    def __init__(self, args, status):
-        self.args = args
-        self.status = status
-
-    def __str__(self):
-        return '{doc}: {args}: exited with status {status}'.format(
-            doc=self.__doc__,
-            args=self.args,
-            status=self.status,
-            )
-
-
-class CLIProcess(object):
-    def __init__(self, **kw):
-        self.kw = kw
-
-    def __enter__(self):
-        try:
-            self.p = subprocess.Popen(**self.kw)
-        except OSError as e:
-            raise AssertionError(
-                'CLI tool {args!r} does not work: {err}'.format(
-                    args=self.kw['args'],
-                    err=e,
-                    ),
-                )
-        else:
-            return self.p
-
-    def __exit__(self, exc_type, exc_val, exc_tb):
-        self.p.wait()
-        if self.p.returncode != 0:
-            err = CLIFailed(
-                args=self.kw['args'],
-                status=self.p.returncode,
-                )
-            if exc_type is None:
-                # nothing else raised, so we should complain; if
-                # something else failed, we'll just log
-                raise err
-            else:
-                LOG.error(str(err))
-
-
-class CLITester(object):
-    # provide easy way for caller to access the exception class
-    # without importing us
-    Failed = CLIFailed
-
-    def __init__(self, tmpdir):
-        self.tmpdir = tmpdir
-
-    def __call__(self, **kw):
-        kw.setdefault('cwd', str(self.tmpdir))
-        kw['env'] = _prepend_path(kw.get('env'))
-        kw['env']['COLUMNS'] = '80'
-        return CLIProcess(**kw)
-
-
-def pytest_funcarg__cli(request):
-    """
-    Test command line behavior.
-    """
-
-    # the tmpdir here will be the same value as the test function
-    # sees; we rely on that to let caller prepare and introspect
-    # any files the cli tool will read or create
-    tmpdir = request.getfuncargvalue('tmpdir')
-
-    return CLITester(tmpdir=tmpdir)
diff --git a/ceph_deploy/test/directory.py b/ceph_deploy/test/directory.py
deleted file mode 100644 (file)
index 81d3e19..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-import contextlib
-import os
-
-
-@contextlib.contextmanager
-def directory(path):
-    prev = os.open('.', os.O_RDONLY | os.O_DIRECTORY)
-    try:
-        os.chdir(path)
-        yield
-    finally:
-        os.fchdir(prev)
-        os.close(prev)
diff --git a/ceph_deploy/test/fakes.py b/ceph_deploy/test/fakes.py
deleted file mode 100644 (file)
index a96bcf7..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
-def fake_getaddrinfo(*a, **kw):
-    return_host = kw.get('return_host', 'host1')
-    return [[0,0,0,0, return_host]]
diff --git a/ceph_deploy/test/test_cli.py b/ceph_deploy/test/test_cli.py
deleted file mode 100644 (file)
index 0e28378..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-import pytest
-import subprocess
-
-
-def test_help(tmpdir, cli):
-    with cli(
-        args=['ceph-deploy', '--help'],
-        stdout=subprocess.PIPE,
-        ) as p:
-        result = p.stdout.read()
-        assert 'usage: ceph-deploy' in result
-        assert 'Deploy Ceph' in result
-        assert 'optional arguments:' in result
-        assert 'commands:' in result
-
-
-def test_bad_command(tmpdir, cli):
-    with pytest.raises(cli.Failed) as err:
-        with cli(
-            args=['ceph-deploy', 'bork'],
-            stderr=subprocess.PIPE,
-            ) as p:
-            result = p.stderr.read()
-    assert 'usage: ceph-deploy' in result
-    assert err.value.status == 2
-    assert {p.basename for p in tmpdir.listdir()} == set()
-
-
-def test_bad_cluster(tmpdir, cli):
-    with pytest.raises(cli.Failed) as err:
-        with cli(
-            args=['ceph-deploy', '--cluster=/evil-this-should-not-be-created', 'new'],
-            stderr=subprocess.PIPE,
-            ) as p:
-            result = p.stderr.read()
-    assert 'usage: ceph-deploy' in result
-    assert err.value.status == 2
-    assert {p.basename for p in tmpdir.listdir()} == set()
diff --git a/ceph_deploy/test/test_cli_install.py b/ceph_deploy/test/test_cli_install.py
deleted file mode 100644 (file)
index 0e8dcb0..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-import argparse
-import collections
-import mock
-import pytest
-import subprocess
-
-from ..cli import main
-from .. import install
-
-from .directory import directory
-
-
-def test_help(tmpdir, cli):
-    with cli(
-        args=['ceph-deploy', 'install', '--help'],
-        stdout=subprocess.PIPE,
-        ) as p:
-        result = p.stdout.read()
-    assert 'usage: ceph-deploy' in result
-    assert 'positional arguments:' in result
-    assert 'optional arguments:' in result
-
-
-def test_bad_no_host(tmpdir, cli):
-    with pytest.raises(cli.Failed) as err:
-        with cli(
-            args=['ceph-deploy', 'install'],
-            stderr=subprocess.PIPE,
-            ) as p:
-            result = p.stderr.read()
-    assert 'usage: ceph-deploy install' in result
-    assert 'too few arguments' in result
-    assert err.value.status == 2
-
-
-def test_simple(tmpdir):
-    ns = argparse.Namespace()
-    ns.pushy = mock.Mock()
-    conn = mock.NonCallableMock(name='PushyClient')
-    ns.pushy.return_value = conn
-
-    mock_compiled = collections.defaultdict(mock.Mock)
-    conn.compile.return_value = mock.Mock(return_value = ('Ubuntu', 'precise','cuttlefish'))
-
-
-    try:
-        with directory(str(tmpdir)):
-            main(
-                args=['-v', 'install', 'storehost1'],
-                namespace=ns,
-                )
-    except SystemExit as e:
-        raise AssertionError('Unexpected exit: %s', e)
-
-    ns.pushy.assert_has_calls([
-            mock.call('ssh+sudo:storehost1'),
-        ])
-
-    call_list = conn.compile.call_args_list
-    mock.call(install.lsb.check_lsb_release) == call_list[0]
-    mock.call(install.lsb.lsb_release) == call_list[1]
-    mock.call(install.install_debian) == call_list[2]
-    assert len(call_list) == 3
diff --git a/ceph_deploy/test/test_cli_mon.py b/ceph_deploy/test/test_cli_mon.py
deleted file mode 100644 (file)
index 6df9096..0000000
+++ /dev/null
@@ -1,94 +0,0 @@
-import argparse
-import collections
-import mock
-import pytest
-import subprocess
-
-from ..cli import main
-from .. import mon
-
-from .directory import directory
-from .fakes import fake_getaddrinfo
-
-def test_help(tmpdir, cli):
-    with cli(
-        args=['ceph-deploy', 'mon', '--help'],
-        stdout=subprocess.PIPE,
-        ) as p:
-        result = p.stdout.read()
-    assert 'usage: ceph-deploy' in result
-    assert 'Deploy ceph monitor on remote hosts.' in result
-    assert 'positional arguments:'
-    assert 'optional arguments:'
-
-
-def test_bad_no_conf(tmpdir, cli):
-    with pytest.raises(cli.Failed) as err:
-        with cli(
-            args=['ceph-deploy', 'mon'],
-            stderr=subprocess.PIPE,
-            ) as p:
-            result = p.stderr.read()
-    assert 'usage: ceph-deploy' in result
-    assert 'too few arguments' in result
-    assert err.value.status == 2
-
-
-def test_bad_no_mon(tmpdir, cli):
-    with tmpdir.join('ceph.conf').open('w'):
-        pass
-    with pytest.raises(cli.Failed) as err:
-        with cli(
-            args=['ceph-deploy', 'mon'],
-            stderr=subprocess.PIPE,
-            ) as p:
-            result = p.stderr.read()
-    assert 'usage: ceph-deploy mon' in result
-    assert 'too few arguments' in result
-    assert err.value.status == 2
-
-
-def test_simple(tmpdir, capsys):
-    with tmpdir.join('ceph.conf').open('w') as f:
-        f.write("""\
-[global]
-fsid = 6ede5564-3cf1-44b5-aa96-1c77b0c3e1d0
-mon initial members = host1
-""")
-
-    ns = argparse.Namespace()
-    ns.pushy = mock.Mock()
-    conn = mock.NonCallableMock(name='PushyClient')
-    ns.pushy.return_value = conn
-
-    mock_compiled = collections.defaultdict(mock.Mock)
-    conn.compile.side_effect = mock_compiled.__getitem__
-
-    MON_SECRET = 'AQBWDj5QAP6LHhAAskVBnUkYHJ7eYREmKo5qKA=='
-
-    def _create_mon(cluster, get_monitor_secret):
-        secret = get_monitor_secret()
-        assert secret == MON_SECRET
-
-    mock_compiled[mon.create_mon].side_effect = _create_mon
-
-    try:
-        with mock.patch('socket.getaddrinfo', fake_getaddrinfo):
-            with directory(str(tmpdir)):
-                main(
-                    args=['-v', 'new', 'host1'],
-                    namespace=ns,
-                    )
-                main(
-                    args=['-v', 'mon', 'create', 'host1'],
-                    namespace=ns,
-                    )
-    except SystemExit as e:
-        raise AssertionError('Unexpected exit: %s', e)
-    out, err = capsys.readouterr()
-    err = err.lower()
-    assert 'creating new cluster named ceph' in err
-    assert 'monitor host1 at h' in err
-    assert 'resolving host host1' in err
-    assert "monitor initial members are ['host1']" in err
-    assert "monitor addrs are ['h']" in err
diff --git a/ceph_deploy/test/test_cli_new.py b/ceph_deploy/test/test_cli_new.py
deleted file mode 100644 (file)
index 182729e..0000000
+++ /dev/null
@@ -1,75 +0,0 @@
-import pytest
-from mock import patch
-import re
-import subprocess
-import uuid
-
-from .. import conf
-from ..cli import main
-from .directory import directory
-from .fakes import fake_getaddrinfo
-
-
-def test_help(tmpdir, cli):
-    with cli(
-        args=['ceph-deploy', 'new', '--help'],
-        stdout=subprocess.PIPE,
-        ) as p:
-        result = p.stdout.read()
-    assert 'usage: ceph-deploy new' in result
-    assert 'positional arguments' in result
-    assert 'optional arguments' in result
-
-
-def test_write_global_conf_section(tmpdir, cli):
-    with patch('ceph_deploy.new.socket.getaddrinfo', fake_getaddrinfo):
-        with directory(str(tmpdir)):
-            main(args=['new', 'host1'])
-    with tmpdir.join('ceph.conf').open() as f:
-        cfg = conf.parse(f)
-    assert cfg.sections() == ['global']
-
-
-def pytest_funcarg__newcfg(request):
-    tmpdir = request.getfuncargvalue('tmpdir')
-    cli = request.getfuncargvalue('cli')
-
-    def new(*args):
-        with patch('ceph_deploy.new.socket.getaddrinfo', fake_getaddrinfo):
-            with directory(str(tmpdir)):
-                main( args=['new'] + list(args))
-                with tmpdir.join('ceph.conf').open() as f:
-                    cfg = conf.parse(f)
-                return cfg
-    return new
-
-
-def test_uuid(newcfg):
-    cfg = newcfg('host1')
-    fsid = cfg.get('global', 'fsid')
-    # make sure it's a valid uuid
-    uuid.UUID(hex=fsid)
-    # make sure it looks pretty, too
-    UUID_RE = re.compile(
-        r'^[0-9a-f]{8}-'
-        + r'[0-9a-f]{4}-'
-        # constant 4 here, we want to enforce randomness and not leak
-        # MACs or time
-        + r'4[0-9a-f]{3}-'
-        + r'[0-9a-f]{4}-'
-        + r'[0-9a-f]{12}$',
-        )
-    assert UUID_RE.match(fsid)
-
-
-def test_mons(newcfg):
-    cfg = newcfg('node01', 'node07', 'node34')
-    mon_initial_members = cfg.get('global', 'mon_initial_members')
-    assert mon_initial_members == 'node01, node07, node34'
-
-
-def test_defaults(newcfg):
-    cfg = newcfg('host1')
-    assert cfg.get('global', 'auth_supported') == 'cephx'
-    assert cfg.get('global', 'osd_journal_size') == '1024'
-    assert cfg.get('global', 'filestore_xattr_use_omap') == 'true'
diff --git a/ceph_deploy/test/test_cli_osd.py b/ceph_deploy/test/test_cli_osd.py
deleted file mode 100644 (file)
index 25045af..0000000
+++ /dev/null
@@ -1,104 +0,0 @@
-import argparse
-import collections
-import mock
-import pytest
-import subprocess
-
-from ..cli import main
-from .. import osd
-
-from .directory import directory
-
-
-def test_help(tmpdir, cli):
-    with cli(
-        args=['ceph-deploy', 'osd', '--help'],
-        stdout=subprocess.PIPE,
-        ) as p:
-        result = p.stdout.read()
-    assert 'usage: ceph-deploy osd' in result
-    assert 'positional arguments' in result
-    assert 'optional arguments' in result
-
-
-def test_bad_no_conf(tmpdir, cli):
-    with pytest.raises(cli.Failed) as err:
-        with cli(
-            args=['ceph-deploy', 'osd', 'fakehost:/does-not-exist'],
-            stderr=subprocess.PIPE,
-            ) as p:
-            result = p.stderr.read()
-    assert 'ceph-deploy osd: error' in result
-    assert 'invalid choice' in result
-    assert err.value.status == 2
-
-
-def test_bad_no_disk(tmpdir, cli):
-    with tmpdir.join('ceph.conf').open('w'):
-        pass
-    with pytest.raises(cli.Failed) as err:
-        with cli(
-            args=['ceph-deploy', 'osd'],
-            stderr=subprocess.PIPE,
-            ) as p:
-            result = p.stderr.read()
-    assert 'usage: ceph-deploy osd' in result
-    assert err.value.status == 2
-
-
-def test_simple(tmpdir, capsys):
-    with tmpdir.join('ceph.conf').open('w') as f:
-        f.write("""\
-[global]
-fsid = 6ede5564-3cf1-44b5-aa96-1c77b0c3e1d0
-mon host = host1
-""")
-
-    ns = argparse.Namespace()
-
-    conn_osd = mock.NonCallableMock(name='PushyClient-osd')
-    mock_compiled_osd = collections.defaultdict(mock.Mock)
-    #conn_osd.compile.side_effect = mock_compiled_osd.__getitem__
-    conn_osd.compile.return_value = mock.Mock(return_value='fakekeyring')
-
-    conn_mon = mock.NonCallableMock(name='PushyClient-mon')
-    mock_compiled_mon = collections.defaultdict(mock.Mock)
-    conn_mon.compile.side_effect = mock_compiled_mon.__getitem__
-
-    ns.pushy = mock.Mock(name='pushy namespace')
-
-    def _conn(url):
-        if url == 'ssh+sudo:host1':
-            return conn_mon
-        elif url == 'ssh+sudo:storehost1:sdc':
-            return conn_osd
-        else:
-            raise AssertionError('Unexpected connection url: %r', url)
-    ns.pushy.side_effect = _conn
-
-    BOOTSTRAP_KEY = 'fakekeyring'
-
-    mock_compiled_mon[osd.get_bootstrap_osd_key].side_effect = BOOTSTRAP_KEY
-
-    def _create_osd(cluster, find_key):
-        key = find_key()
-        assert key == BOOTSTRAP_KEY
-
-    mock_compiled_osd[osd.create_osd].side_effect = _create_osd
-
-    with directory(str(tmpdir)):
-        main(
-            args=['-v', 'gatherkeys', 'storehost1:sdc'],
-            namespace=ns,
-        )
-        main(
-            args=['-v', 'osd', 'prepare', 'storehost1:sdc'],
-            namespace=ns,
-            )
-    out, err = capsys.readouterr()
-    err = err.lower()
-    assert 'have ceph.mon.keyring' in err
-    assert 'have ceph.client.admin.keyring' in err
-    assert 'have ceph.bootstrap-osd.keyring' in err
-    assert 'got ceph.bootstrap-mds.keyring key from storehost1:sdc' in err
-    assert 'got ceph.bootstrap-osd.keyring key from storehost1:sdc' in err
diff --git a/ceph_deploy/test/test_conf.py b/ceph_deploy/test/test_conf.py
deleted file mode 100644 (file)
index faa3688..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-from cStringIO import StringIO
-from .. import conf
-
-
-def test_simple():
-    f = StringIO("""\
-[foo]
-bar = baz
-""")
-    cfg = conf.parse(f)
-    assert cfg.get('foo', 'bar') == 'baz'
-
-
-def test_indent_space():
-    f = StringIO("""\
-[foo]
-        bar = baz
-""")
-    cfg = conf.parse(f)
-    assert cfg.get('foo', 'bar') == 'baz'
-
-
-def test_indent_tab():
-    f = StringIO("""\
-[foo]
-\tbar = baz
-""")
-    cfg = conf.parse(f)
-    assert cfg.get('foo', 'bar') == 'baz'
-
-
-def test_words_underscore():
-    f = StringIO("""\
-[foo]
-bar_thud = baz
-""")
-    cfg = conf.parse(f)
-    assert cfg.get('foo', 'bar_thud') == 'baz'
-    assert cfg.get('foo', 'bar thud') == 'baz'
-
-
-def test_words_space():
-    f = StringIO("""\
-[foo]
-bar thud = baz
-""")
-    cfg = conf.parse(f)
-    assert cfg.get('foo', 'bar_thud') == 'baz'
-    assert cfg.get('foo', 'bar thud') == 'baz'
-
-
-def test_words_many():
-    f = StringIO("""\
-[foo]
-bar__ thud   quux = baz
-""")
-    cfg = conf.parse(f)
-    assert cfg.get('foo', 'bar_thud_quux') == 'baz'
-    assert cfg.get('foo', 'bar thud quux') == 'baz'
diff --git a/ceph_deploy/tests/__init__.py b/ceph_deploy/tests/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/ceph_deploy/tests/conftest.py b/ceph_deploy/tests/conftest.py
new file mode 100644 (file)
index 0000000..819fc34
--- /dev/null
@@ -0,0 +1,98 @@
+import logging
+import os
+import subprocess
+import sys
+
+
+LOG = logging.getLogger(__name__)
+
+
+def _prepend_path(env):
+    """
+    Make sure the PATH contains the location where the Python binary
+    lives. This makes sure cli tools installed in a virtualenv work.
+    """
+    if env is None:
+        env = os.environ
+    env = dict(env)
+    new = os.path.dirname(sys.executable)
+    path = env.get('PATH')
+    if path is not None:
+        new = new + ':' + path
+    env['PATH'] = new
+    return env
+
+
+class CLIFailed(Exception):
+    """CLI tool failed"""
+
+    def __init__(self, args, status):
+        self.args = args
+        self.status = status
+
+    def __str__(self):
+        return '{doc}: {args}: exited with status {status}'.format(
+            doc=self.__doc__,
+            args=self.args,
+            status=self.status,
+            )
+
+
+class CLIProcess(object):
+    def __init__(self, **kw):
+        self.kw = kw
+
+    def __enter__(self):
+        try:
+            self.p = subprocess.Popen(**self.kw)
+        except OSError as e:
+            raise AssertionError(
+                'CLI tool {args!r} does not work: {err}'.format(
+                    args=self.kw['args'],
+                    err=e,
+                    ),
+                )
+        else:
+            return self.p
+
+    def __exit__(self, exc_type, exc_val, exc_tb):
+        self.p.wait()
+        if self.p.returncode != 0:
+            err = CLIFailed(
+                args=self.kw['args'],
+                status=self.p.returncode,
+                )
+            if exc_type is None:
+                # nothing else raised, so we should complain; if
+                # something else failed, we'll just log
+                raise err
+            else:
+                LOG.error(str(err))
+
+
+class CLITester(object):
+    # provide easy way for caller to access the exception class
+    # without importing us
+    Failed = CLIFailed
+
+    def __init__(self, tmpdir):
+        self.tmpdir = tmpdir
+
+    def __call__(self, **kw):
+        kw.setdefault('cwd', str(self.tmpdir))
+        kw['env'] = _prepend_path(kw.get('env'))
+        kw['env']['COLUMNS'] = '80'
+        return CLIProcess(**kw)
+
+
+def pytest_funcarg__cli(request):
+    """
+    Test command line behavior.
+    """
+
+    # the tmpdir here will be the same value as the test function
+    # sees; we rely on that to let caller prepare and introspect
+    # any files the cli tool will read or create
+    tmpdir = request.getfuncargvalue('tmpdir')
+
+    return CLITester(tmpdir=tmpdir)
diff --git a/ceph_deploy/tests/directory.py b/ceph_deploy/tests/directory.py
new file mode 100644 (file)
index 0000000..81d3e19
--- /dev/null
@@ -0,0 +1,13 @@
+import contextlib
+import os
+
+
+@contextlib.contextmanager
+def directory(path):
+    prev = os.open('.', os.O_RDONLY | os.O_DIRECTORY)
+    try:
+        os.chdir(path)
+        yield
+    finally:
+        os.fchdir(prev)
+        os.close(prev)
diff --git a/ceph_deploy/tests/fakes.py b/ceph_deploy/tests/fakes.py
new file mode 100644 (file)
index 0000000..a96bcf7
--- /dev/null
@@ -0,0 +1,5 @@
+
+
+def fake_getaddrinfo(*a, **kw):
+    return_host = kw.get('return_host', 'host1')
+    return [[0,0,0,0, return_host]]
diff --git a/ceph_deploy/tests/test_cli.py b/ceph_deploy/tests/test_cli.py
new file mode 100644 (file)
index 0000000..0e28378
--- /dev/null
@@ -0,0 +1,38 @@
+import pytest
+import subprocess
+
+
+def test_help(tmpdir, cli):
+    with cli(
+        args=['ceph-deploy', '--help'],
+        stdout=subprocess.PIPE,
+        ) as p:
+        result = p.stdout.read()
+        assert 'usage: ceph-deploy' in result
+        assert 'Deploy Ceph' in result
+        assert 'optional arguments:' in result
+        assert 'commands:' in result
+
+
+def test_bad_command(tmpdir, cli):
+    with pytest.raises(cli.Failed) as err:
+        with cli(
+            args=['ceph-deploy', 'bork'],
+            stderr=subprocess.PIPE,
+            ) as p:
+            result = p.stderr.read()
+    assert 'usage: ceph-deploy' in result
+    assert err.value.status == 2
+    assert {p.basename for p in tmpdir.listdir()} == set()
+
+
+def test_bad_cluster(tmpdir, cli):
+    with pytest.raises(cli.Failed) as err:
+        with cli(
+            args=['ceph-deploy', '--cluster=/evil-this-should-not-be-created', 'new'],
+            stderr=subprocess.PIPE,
+            ) as p:
+            result = p.stderr.read()
+    assert 'usage: ceph-deploy' in result
+    assert err.value.status == 2
+    assert {p.basename for p in tmpdir.listdir()} == set()
diff --git a/ceph_deploy/tests/test_cli_install.py b/ceph_deploy/tests/test_cli_install.py
new file mode 100644 (file)
index 0000000..0e8dcb0
--- /dev/null
@@ -0,0 +1,63 @@
+import argparse
+import collections
+import mock
+import pytest
+import subprocess
+
+from ..cli import main
+from .. import install
+
+from .directory import directory
+
+
+def test_help(tmpdir, cli):
+    with cli(
+        args=['ceph-deploy', 'install', '--help'],
+        stdout=subprocess.PIPE,
+        ) as p:
+        result = p.stdout.read()
+    assert 'usage: ceph-deploy' in result
+    assert 'positional arguments:' in result
+    assert 'optional arguments:' in result
+
+
+def test_bad_no_host(tmpdir, cli):
+    with pytest.raises(cli.Failed) as err:
+        with cli(
+            args=['ceph-deploy', 'install'],
+            stderr=subprocess.PIPE,
+            ) as p:
+            result = p.stderr.read()
+    assert 'usage: ceph-deploy install' in result
+    assert 'too few arguments' in result
+    assert err.value.status == 2
+
+
+def test_simple(tmpdir):
+    ns = argparse.Namespace()
+    ns.pushy = mock.Mock()
+    conn = mock.NonCallableMock(name='PushyClient')
+    ns.pushy.return_value = conn
+
+    mock_compiled = collections.defaultdict(mock.Mock)
+    conn.compile.return_value = mock.Mock(return_value = ('Ubuntu', 'precise','cuttlefish'))
+
+
+    try:
+        with directory(str(tmpdir)):
+            main(
+                args=['-v', 'install', 'storehost1'],
+                namespace=ns,
+                )
+    except SystemExit as e:
+        raise AssertionError('Unexpected exit: %s', e)
+
+    ns.pushy.assert_has_calls([
+            mock.call('ssh+sudo:storehost1'),
+        ])
+
+    call_list = conn.compile.call_args_list
+    mock.call(install.lsb.check_lsb_release) == call_list[0]
+    mock.call(install.lsb.lsb_release) == call_list[1]
+    mock.call(install.install_debian) == call_list[2]
+    assert len(call_list) == 3
diff --git a/ceph_deploy/tests/test_cli_mon.py b/ceph_deploy/tests/test_cli_mon.py
new file mode 100644 (file)
index 0000000..6df9096
--- /dev/null
@@ -0,0 +1,94 @@
+import argparse
+import collections
+import mock
+import pytest
+import subprocess
+
+from ..cli import main
+from .. import mon
+
+from .directory import directory
+from .fakes import fake_getaddrinfo
+
+def test_help(tmpdir, cli):
+    with cli(
+        args=['ceph-deploy', 'mon', '--help'],
+        stdout=subprocess.PIPE,
+        ) as p:
+        result = p.stdout.read()
+    assert 'usage: ceph-deploy' in result
+    assert 'Deploy ceph monitor on remote hosts.' in result
+    assert 'positional arguments:'
+    assert 'optional arguments:'
+
+
+def test_bad_no_conf(tmpdir, cli):
+    with pytest.raises(cli.Failed) as err:
+        with cli(
+            args=['ceph-deploy', 'mon'],
+            stderr=subprocess.PIPE,
+            ) as p:
+            result = p.stderr.read()
+    assert 'usage: ceph-deploy' in result
+    assert 'too few arguments' in result
+    assert err.value.status == 2
+
+
+def test_bad_no_mon(tmpdir, cli):
+    with tmpdir.join('ceph.conf').open('w'):
+        pass
+    with pytest.raises(cli.Failed) as err:
+        with cli(
+            args=['ceph-deploy', 'mon'],
+            stderr=subprocess.PIPE,
+            ) as p:
+            result = p.stderr.read()
+    assert 'usage: ceph-deploy mon' in result
+    assert 'too few arguments' in result
+    assert err.value.status == 2
+
+
+def test_simple(tmpdir, capsys):
+    with tmpdir.join('ceph.conf').open('w') as f:
+        f.write("""\
+[global]
+fsid = 6ede5564-3cf1-44b5-aa96-1c77b0c3e1d0
+mon initial members = host1
+""")
+
+    ns = argparse.Namespace()
+    ns.pushy = mock.Mock()
+    conn = mock.NonCallableMock(name='PushyClient')
+    ns.pushy.return_value = conn
+
+    mock_compiled = collections.defaultdict(mock.Mock)
+    conn.compile.side_effect = mock_compiled.__getitem__
+
+    MON_SECRET = 'AQBWDj5QAP6LHhAAskVBnUkYHJ7eYREmKo5qKA=='
+
+    def _create_mon(cluster, get_monitor_secret):
+        secret = get_monitor_secret()
+        assert secret == MON_SECRET
+
+    mock_compiled[mon.create_mon].side_effect = _create_mon
+
+    try:
+        with mock.patch('socket.getaddrinfo', fake_getaddrinfo):
+            with directory(str(tmpdir)):
+                main(
+                    args=['-v', 'new', 'host1'],
+                    namespace=ns,
+                    )
+                main(
+                    args=['-v', 'mon', 'create', 'host1'],
+                    namespace=ns,
+                    )
+    except SystemExit as e:
+        raise AssertionError('Unexpected exit: %s', e)
+    out, err = capsys.readouterr()
+    err = err.lower()
+    assert 'creating new cluster named ceph' in err
+    assert 'monitor host1 at h' in err
+    assert 'resolving host host1' in err
+    assert "monitor initial members are ['host1']" in err
+    assert "monitor addrs are ['h']" in err
diff --git a/ceph_deploy/tests/test_cli_new.py b/ceph_deploy/tests/test_cli_new.py
new file mode 100644 (file)
index 0000000..182729e
--- /dev/null
@@ -0,0 +1,75 @@
+import pytest
+from mock import patch
+import re
+import subprocess
+import uuid
+
+from .. import conf
+from ..cli import main
+from .directory import directory
+from .fakes import fake_getaddrinfo
+
+
+def test_help(tmpdir, cli):
+    with cli(
+        args=['ceph-deploy', 'new', '--help'],
+        stdout=subprocess.PIPE,
+        ) as p:
+        result = p.stdout.read()
+    assert 'usage: ceph-deploy new' in result
+    assert 'positional arguments' in result
+    assert 'optional arguments' in result
+
+
+def test_write_global_conf_section(tmpdir, cli):
+    with patch('ceph_deploy.new.socket.getaddrinfo', fake_getaddrinfo):
+        with directory(str(tmpdir)):
+            main(args=['new', 'host1'])
+    with tmpdir.join('ceph.conf').open() as f:
+        cfg = conf.parse(f)
+    assert cfg.sections() == ['global']
+
+
+def pytest_funcarg__newcfg(request):
+    tmpdir = request.getfuncargvalue('tmpdir')
+    cli = request.getfuncargvalue('cli')
+
+    def new(*args):
+        with patch('ceph_deploy.new.socket.getaddrinfo', fake_getaddrinfo):
+            with directory(str(tmpdir)):
+                main( args=['new'] + list(args))
+                with tmpdir.join('ceph.conf').open() as f:
+                    cfg = conf.parse(f)
+                return cfg
+    return new
+
+
+def test_uuid(newcfg):
+    cfg = newcfg('host1')
+    fsid = cfg.get('global', 'fsid')
+    # make sure it's a valid uuid
+    uuid.UUID(hex=fsid)
+    # make sure it looks pretty, too
+    UUID_RE = re.compile(
+        r'^[0-9a-f]{8}-'
+        + r'[0-9a-f]{4}-'
+        # constant 4 here, we want to enforce randomness and not leak
+        # MACs or time
+        + r'4[0-9a-f]{3}-'
+        + r'[0-9a-f]{4}-'
+        + r'[0-9a-f]{12}$',
+        )
+    assert UUID_RE.match(fsid)
+
+
+def test_mons(newcfg):
+    cfg = newcfg('node01', 'node07', 'node34')
+    mon_initial_members = cfg.get('global', 'mon_initial_members')
+    assert mon_initial_members == 'node01, node07, node34'
+
+
+def test_defaults(newcfg):
+    cfg = newcfg('host1')
+    assert cfg.get('global', 'auth_supported') == 'cephx'
+    assert cfg.get('global', 'osd_journal_size') == '1024'
+    assert cfg.get('global', 'filestore_xattr_use_omap') == 'true'
diff --git a/ceph_deploy/tests/test_cli_osd.py b/ceph_deploy/tests/test_cli_osd.py
new file mode 100644 (file)
index 0000000..25045af
--- /dev/null
@@ -0,0 +1,104 @@
+import argparse
+import collections
+import mock
+import pytest
+import subprocess
+
+from ..cli import main
+from .. import osd
+
+from .directory import directory
+
+
+def test_help(tmpdir, cli):
+    with cli(
+        args=['ceph-deploy', 'osd', '--help'],
+        stdout=subprocess.PIPE,
+        ) as p:
+        result = p.stdout.read()
+    assert 'usage: ceph-deploy osd' in result
+    assert 'positional arguments' in result
+    assert 'optional arguments' in result
+
+
+def test_bad_no_conf(tmpdir, cli):
+    with pytest.raises(cli.Failed) as err:
+        with cli(
+            args=['ceph-deploy', 'osd', 'fakehost:/does-not-exist'],
+            stderr=subprocess.PIPE,
+            ) as p:
+            result = p.stderr.read()
+    assert 'ceph-deploy osd: error' in result
+    assert 'invalid choice' in result
+    assert err.value.status == 2
+
+
+def test_bad_no_disk(tmpdir, cli):
+    with tmpdir.join('ceph.conf').open('w'):
+        pass
+    with pytest.raises(cli.Failed) as err:
+        with cli(
+            args=['ceph-deploy', 'osd'],
+            stderr=subprocess.PIPE,
+            ) as p:
+            result = p.stderr.read()
+    assert 'usage: ceph-deploy osd' in result
+    assert err.value.status == 2
+
+
+def test_simple(tmpdir, capsys):
+    with tmpdir.join('ceph.conf').open('w') as f:
+        f.write("""\
+[global]
+fsid = 6ede5564-3cf1-44b5-aa96-1c77b0c3e1d0
+mon host = host1
+""")
+
+    ns = argparse.Namespace()
+
+    conn_osd = mock.NonCallableMock(name='PushyClient-osd')
+    mock_compiled_osd = collections.defaultdict(mock.Mock)
+    #conn_osd.compile.side_effect = mock_compiled_osd.__getitem__
+    conn_osd.compile.return_value = mock.Mock(return_value='fakekeyring')
+
+    conn_mon = mock.NonCallableMock(name='PushyClient-mon')
+    mock_compiled_mon = collections.defaultdict(mock.Mock)
+    conn_mon.compile.side_effect = mock_compiled_mon.__getitem__
+
+    ns.pushy = mock.Mock(name='pushy namespace')
+
+    def _conn(url):
+        if url == 'ssh+sudo:host1':
+            return conn_mon
+        elif url == 'ssh+sudo:storehost1:sdc':
+            return conn_osd
+        else:
+            raise AssertionError('Unexpected connection url: %r', url)
+    ns.pushy.side_effect = _conn
+
+    BOOTSTRAP_KEY = 'fakekeyring'
+
+    mock_compiled_mon[osd.get_bootstrap_osd_key].side_effect = BOOTSTRAP_KEY
+
+    def _create_osd(cluster, find_key):
+        key = find_key()
+        assert key == BOOTSTRAP_KEY
+
+    mock_compiled_osd[osd.create_osd].side_effect = _create_osd
+
+    with directory(str(tmpdir)):
+        main(
+            args=['-v', 'gatherkeys', 'storehost1:sdc'],
+            namespace=ns,
+        )
+        main(
+            args=['-v', 'osd', 'prepare', 'storehost1:sdc'],
+            namespace=ns,
+            )
+    out, err = capsys.readouterr()
+    err = err.lower()
+    assert 'have ceph.mon.keyring' in err
+    assert 'have ceph.client.admin.keyring' in err
+    assert 'have ceph.bootstrap-osd.keyring' in err
+    assert 'got ceph.bootstrap-mds.keyring key from storehost1:sdc' in err
+    assert 'got ceph.bootstrap-osd.keyring key from storehost1:sdc' in err
diff --git a/ceph_deploy/tests/test_conf.py b/ceph_deploy/tests/test_conf.py
new file mode 100644 (file)
index 0000000..faa3688
--- /dev/null
@@ -0,0 +1,59 @@
+from cStringIO import StringIO
+from .. import conf
+
+
+def test_simple():
+    f = StringIO("""\
+[foo]
+bar = baz
+""")
+    cfg = conf.parse(f)
+    assert cfg.get('foo', 'bar') == 'baz'
+
+
+def test_indent_space():
+    f = StringIO("""\
+[foo]
+        bar = baz
+""")
+    cfg = conf.parse(f)
+    assert cfg.get('foo', 'bar') == 'baz'
+
+
+def test_indent_tab():
+    f = StringIO("""\
+[foo]
+\tbar = baz
+""")
+    cfg = conf.parse(f)
+    assert cfg.get('foo', 'bar') == 'baz'
+
+
+def test_words_underscore():
+    f = StringIO("""\
+[foo]
+bar_thud = baz
+""")
+    cfg = conf.parse(f)
+    assert cfg.get('foo', 'bar_thud') == 'baz'
+    assert cfg.get('foo', 'bar thud') == 'baz'
+
+
+def test_words_space():
+    f = StringIO("""\
+[foo]
+bar thud = baz
+""")
+    cfg = conf.parse(f)
+    assert cfg.get('foo', 'bar_thud') == 'baz'
+    assert cfg.get('foo', 'bar thud') == 'baz'
+
+
+def test_words_many():
+    f = StringIO("""\
+[foo]
+bar__ thud   quux = baz
+""")
+    cfg = conf.parse(f)
+    assert cfg.get('foo', 'bar_thud_quux') == 'baz'
+    assert cfg.get('foo', 'bar thud quux') == 'baz'