Exemple #1
0
def main(destination, **kw):
    develop = os.environ['BATOU_DEVELOP']
    if develop:
        output.annotate(
            'Initializing with a development copy of batou will cause your '
            'project to have a reference outside its repository. '
            'Use at your own risk. ')
        develop = os.path.abspath(develop)
    print((
        'Bootstrapping new batou project in {}. This can take a while.'.format(
            os.path.abspath(destination))))
    if os.path.exists(destination):
        print(('{} exists already. Not copying template structure.'.format(
            destination)))
        os.chdir(destination)
    else:
        source = os.path.dirname(__file__) + '/init-template'
        shutil.copytree(source, destination)
        os.chdir(destination)
        cmd('hg -y init .')
    update_bootstrap(os.environ['BATOU_VERSION'], develop)
    # Need to clean up to avoid inheriting info that we're bootstrapped
    # already.
    for key in list(os.environ):
        if key.startswith('BATOU_'):
            del os.environ[key]
    cmd('./batou --help')
Exemple #2
0
def test_has_changes_counts_untracked_files_as_changes(root, repos_path):
    clone = batou.lib.git.Clone(repos_path, target="clone", branch="master")
    root.component += clone
    root.component.deploy()
    assert not clone.has_changes()
    cmd("touch {}/clone/bar".format(root.workdir))
    assert clone.has_changes()
Exemple #3
0
def test_cmd_quotes_spacey_args(popen):
    popen().communicate.return_value = (b'', b'')
    popen().returncode = 0
    cmd(['cat', 'foo', 'bar bz baz'])
    assert popen.call_args[0] == ("cat foo 'bar bz baz'", )
    cmd(['cat', 'foo', "bar 'bz baz"])
    assert popen.call_args[0] == (r"cat foo 'bar \'bz baz'", )
Exemple #4
0
def test_cmd_quotes_spacey_args(popen):
    popen().communicate.return_value = (b"", b"")
    popen().returncode = 0
    cmd(["cat", "foo", "bar bz baz"])
    assert popen.call_args[0] == ("cat foo 'bar bz baz'",)
    cmd(["cat", "foo", "bar 'bz baz"])
    assert popen.call_args[0] == (r"cat foo 'bar \'bz baz'",)
Exemple #5
0
    def _prepare_ssh(self, host):
        container = host.name

        # XXX application / user-specific files
        # https://unix.stackexchange.com/questions/312988/understanding-home-configuration-file-locations-config-and-local-sha
        KNOWN_HOSTS_FILE = os.path.expanduser('~/.batou/known_hosts')

        if not os.path.exists(KNOWN_HOSTS_FILE):
            prefix_dir = os.path.dirname(KNOWN_HOSTS_FILE)
            if not os.path.exists(prefix_dir):
                os.makedirs(prefix_dir)
            with open(KNOWN_HOSTS_FILE, 'w'):
                pass

        if self.rebuild:
            cmd(['ssh-keygen', '-R', container, '-f', KNOWN_HOSTS_FILE])

        ssh_config = []
        # We need to provide a version of the key that doesn't trigger
        # OpenSSHs "wrong permission" check.
        packaged_insecure_key = os.path.join(os.path.dirname(__file__),
                                             'insecure-private.key')
        local_insecure_key = os.path.abspath('insecure-private.key')
        with open(local_insecure_key, 'w') as f_target:
            with open(packaged_insecure_key) as f_packaged:
                f_target.write(f_packaged.read())
        os.chmod(local_insecure_key, 0o600)

        ssh_config.append("""
Host {container} {aliases}
    HostName {container}
    ProxyJump {target_host}
    User developer
    IdentityFile {insecure_private_key}
    StrictHostKeyChecking no
    UserKnownHostsFile {known_hosts}
""".format(container=container,
           aliases=' '.join(host._aliases),
           target_host=self.target_host,
           known_hosts=KNOWN_HOSTS_FILE,
           insecure_private_key=local_insecure_key))

        # More generic includes need to go last because parameters are
        # set by a match-first and things like User settings for * may
        # otherwise collide with our very specific settings. See
        # `man 5 ssh_config`.
        if os.path.exists(os.path.expanduser('~/.ssh/config')):
            ssh_config.append('Host *\n  Include ~/.ssh/config')
        if os.path.exists('ssh_config'):
            ssh_config.append('Host *\n  Include {}'.format(
                os.path.abspath('ssh_config')))

        # Place this in the deployment base directory persistently and
        # keep updating it. This helps users to also interact with containers
        # by running `ssh -F ssh_config_dev mycontainer`
        self.ssh_config_file = os.path.abspath('ssh_config_{}'.format(
            host.environment.name))
        with open(self.ssh_config_file, 'w') as f:
            f.write('\n'.join(ssh_config))
Exemple #6
0
def test_changes_lost_on_update_without_incoming(root, repos_path):
    root.component += batou.lib.git.Clone(repos_path,
                                          target="clone",
                                          branch="master")
    root.component.deploy()
    cmd("cd {dir}/clone; echo foobar >foo".format(dir=root.workdir))
    root.component.deploy()
    assert not open(root.component.map("clone/foo")).read()
Exemple #7
0
def test_remote_deployment_initializable(sample_service):
    cmd("hg init")
    with open(".hg/hgrc", "w") as f:
        f.write("[paths]\ndefault=https://example.com")
    env = Environment("test-with-env-config")
    env.load()
    env.configure()
    Deployment(env, platform="", jobs=1, timeout=30, dirty=False)
Exemple #8
0
def test_has_changes_counts_changes_to_tracked_files(root, repos_path):
    clone = batou.lib.git.Clone(repos_path, target='clone', branch='master')
    root.component += clone
    root.component.deploy()
    assert not clone.has_changes()
    cmd('touch {}/clone/bar'.format(root.workdir))
    cmd('cd {}/clone; git add bar'.format(root.workdir))
    assert clone.has_changes()
Exemple #9
0
def test_remote_deployment_initializable(sample_service):
    cmd('hg init')
    with open('.hg/hgrc', 'w') as f:
        f.write('[paths]\ndefault=https://example.com')
    env = Environment('test-with-env-config')
    env.load()
    env.configure()
    Deployment(env, platform='', jobs=1, timeout=30, dirty=False)
Exemple #10
0
def _repos_path(root, name):
    repos_path = os.path.join(root.environment.workdir_base, name)
    cmd("mkdir {dir}; cd {dir}; git init;"
        "git config user.name Jenkins;"
        "git config user.email [email protected];"
        "touch foo; git add .;"
        'git commit -am "foo"'.format(dir=repos_path))
    return repos_path
Exemple #11
0
def test_changes_lost_on_update_without_incoming(root, repos_path):
    root.component += batou.lib.mercurial.Clone(repos_path,
                                                target='clone',
                                                branch='default')
    root.component.deploy()
    cmd('cd {dir}/clone; echo foobar >foo'.format(dir=root.workdir))
    root.component.deploy()
    assert not open(root.component.map('clone/foo')).read()
Exemple #12
0
def test_untracked_files_are_removed_on_update(root, repos_path):
    root.component += batou.lib.mercurial.Clone(repos_path,
                                                target='clone',
                                                branch='default')
    root.component.deploy()
    cmd('cd {dir}/clone; mkdir bar; echo foobar >bar/baz'.format(
        dir=root.workdir))
    root.component.deploy()
    assert not os.path.exists(root.component.map('clone/bar/baz'))
Exemple #13
0
def test_clean_clone_updates_on_incoming_changes(root, repos_path):
    root.component += batou.lib.mercurial.Clone(repos_path,
                                                target='clone',
                                                branch='default')
    root.component.deploy()
    cmd('cd {dir}; touch bar; hg addremove; hg ci -m "commit"'.format(
        dir=repos_path))
    root.component.deploy()
    assert os.path.isfile(root.component.map('clone/bar'))
Exemple #14
0
def test_has_changes_counts_untracked_files_as_changes(root, repos_path):
    clone = batou.lib.mercurial.Clone(repos_path,
                                      target='clone',
                                      branch='default')
    root.component += clone
    root.component.deploy()
    assert not clone.has_changes()
    cmd('touch {}/clone/bar'.format(root.workdir))
    assert clone.has_changes()
Exemple #15
0
def test_clean_clone_updates_on_incoming_changes(root, repos_path):
    root.component += batou.lib.git.Clone(repos_path,
                                          target="clone",
                                          branch="master")
    root.component.deploy()
    cmd('cd {dir}; touch bar; git add .; git commit -m "commit"'.format(
        dir=repos_path))
    root.component.deploy()
    assert os.path.isfile(root.component.map("clone/bar"))
Exemple #16
0
def test_untracked_files_are_removed_on_update(root, repos_path):
    root.component += batou.lib.git.Clone(repos_path,
                                          target="clone",
                                          branch="master")
    root.component.deploy()
    cmd("cd {dir}/clone; mkdir bar; echo foobar >bar/baz".format(
        dir=root.workdir))
    root.component.deploy()
    assert not os.path.exists(root.component.map("clone/bar/baz"))
Exemple #17
0
def test_has_changes_counts_changes_to_tracked_files(root, repos_path):
    clone = batou.lib.mercurial.Clone(repos_path,
                                      target="clone",
                                      branch="default")
    root.component += clone
    root.component.deploy()
    assert not clone.has_changes()
    cmd("touch {}/clone/bar".format(root.workdir))
    cmd("cd {}/clone; hg add bar".format(root.workdir))
    assert clone.has_changes()
Exemple #18
0
def test_setting_branch_updates_on_incoming_changes(root, repos_path):
    root.component += batou.lib.git.Clone(repos_path,
                                          target="clone",
                                          branch="master")
    root.component.deploy()
    cmd('cd {dir}; touch bar; git add .; git commit -m "commit"'.format(
        dir=repos_path))
    root.component.deploy()
    assert os.path.isfile(
        os.path.join(root.environment.workdir_base, "mycomponent/clone/bar"))
Exemple #19
0
def test_setting_branch_updates_on_incoming_changes(root, repos_path):
    root.component += batou.lib.mercurial.Clone(repos_path,
                                                target='clone',
                                                branch='default')
    root.component.deploy()
    cmd('cd {dir}; touch bar; hg addremove; hg ci -m "commit"'.format(
        dir=repos_path))
    root.component.deploy()
    assert os.path.isfile(
        os.path.join(root.environment.workdir_base, 'mycomponent/clone/bar'))
Exemple #20
0
def test_branch_does_switch_branch(root, repos_path):
    cmd('cd {dir}; hg branch bar; hg ci -m "commit branch"'.format(
        dir=repos_path))
    root.component += batou.lib.mercurial.Clone(repos_path,
                                                target='clone',
                                                branch='bar')
    root.component.deploy()
    stdout, stderr = cmd(
        'cd {workdir}/clone; hg branch'.format(workdir=root.workdir))
    assert 'bar' == stdout.strip()
Exemple #21
0
def test_changes_lost_on_update_with_incoming(root, repos_path):
    root.component += batou.lib.git.Clone(repos_path,
                                          target="clone",
                                          branch="master")
    root.component.deploy()
    cmd('cd {dir}; touch bar; git add .; git commit -m "commit"'.format(
        dir=repos_path))
    cmd("cd {dir}/clone; echo foobar >foo".format(dir=root.workdir))
    root.component.deploy()
    assert os.path.exists(root.component.map("clone/bar"))
    assert not open(root.component.map("clone/foo")).read()
Exemple #22
0
def test_runs_svn_to_clone_repository(root):
    repos_path = os.path.join(root.environment.workdir_base, "repos")
    cmd("svnadmin create " + repos_path)
    cmd("svn checkout file://{dir} upstream; cd upstream;"
        'touch foo; svn add foo; svn commit -m "bar"'.format(dir=repos_path))
    root.component += batou.lib.svn.Checkout(
        "file://" + repos_path, target="clone", revision="head")
    root.component.deploy()
    assert os.path.isfile(
        os.path.join(root.environment.workdir_base, "mycomponent/clone/foo"))
    root.component.deploy()  # trigger verify
Exemple #23
0
def test_changes_lost_on_update_with_incoming(root, repos_path):
    root.component += batou.lib.mercurial.Clone(repos_path,
                                                target='clone',
                                                branch='default')
    root.component.deploy()
    cmd('cd {dir}; touch bar; hg addremove; hg ci -m "commit"'.format(
        dir=repos_path))
    cmd('cd {dir}/clone; echo foobar >foo'.format(dir=root.workdir))
    root.component.deploy()
    assert os.path.exists(root.component.map('clone/bar'))
    assert not open(root.component.map('clone/foo')).read()
Exemple #24
0
def test_branch_does_switch_branch(root, repos_path):
    cmd("cd {dir}; touch bar; git add .; git checkout -b bar;"
        'git commit -m "commit branch"'.format(dir=repos_path))
    root.component += batou.lib.git.Clone(repos_path,
                                          target="clone",
                                          branch="bar")
    root.component.deploy()
    stdout, stderr = cmd(
        "cd {workdir}/clone; git rev-parse --abbrev-ref HEAD".format(
            workdir=root.workdir))
    assert "bar" == stdout.strip()
Exemple #25
0
def test_runs_svn_to_clone_repository(root):
    repos_path = os.path.join(root.environment.workdir_base, 'repos')
    cmd('svnadmin create ' + repos_path)
    cmd('svn checkout file://{dir} upstream; cd upstream;'
        'touch foo; svn add foo; svn commit -m "bar"'.format(dir=repos_path))
    root.component += batou.lib.svn.Checkout(
        'file://' + repos_path, target='clone', revision='head')
    root.component.deploy()
    assert os.path.isfile(
        os.path.join(root.environment.workdir_base, 'mycomponent/clone/foo'))
    root.component.deploy()  # trigger verify
Exemple #26
0
def test_clean_clone_vcs_update_false_leaves_changes_intact(root, repos_path):
    root.component += batou.lib.git.Clone(repos_path,
                                          target="clone",
                                          branch="master",
                                          vcs_update=False)
    root.component.deploy()
    cmd("cd {dir}; echo foobar >foo; touch bar; git add .; "
        'git commit -m "commit"'.format(dir=repos_path))
    cmd("cd {dir}/clone; echo asdf >foo".format(dir=root.workdir))
    root.component.deploy()
    assert "asdf\n" == open(root.component.map("clone/foo")).read()
    assert not os.path.exists(root.component.map("clone/bar"))
Exemple #27
0
def test_clean_clone_vcs_update_false_leaves_changes_intact(root, repos_path):
    root.component += batou.lib.mercurial.Clone(repos_path,
                                                target='clone',
                                                branch='default',
                                                vcs_update=False)
    root.component.deploy()
    cmd('cd {dir}; echo foobar >foo; touch bar; hg addremove; '
        'hg ci -m "commit"'.format(dir=repos_path))
    cmd('cd {dir}/clone; echo asdf >foo'.format(dir=root.workdir))
    root.component.deploy()
    assert 'asdf\n' == open(root.component.map('clone/foo')).read()
    assert not os.path.exists(root.component.map('clone/bar'))
Exemple #28
0
def test_setting_revision_updates_on_incoming_changes(root, repos_path):
    cmd('cd {dir}; touch bar; git add .; git commit -m "commit2"'.format(
        dir=repos_path))
    commit1, _ = cmd("cd {dir}; git rev-parse HEAD^".format(dir=repos_path))
    root.component += batou.lib.git.Clone(repos_path,
                                          target="clone",
                                          revision=commit1)
    root.component.deploy()
    cmd('cd {dir}; touch qux; git add .; git commit -m "commit3"'.format(
        dir=repos_path))
    root.component.deploy()  # Our main assertion: Nothing breaks here
    assert not os.path.isfile(
        os.path.join(root.environment.workdir_base, "mycomponent/clone/qux"))
Exemple #29
0
def test_example_async_sync_deployment():
    os.chdir('examples/sync_async')
    out, _ = cmd('./batou -d deploy default')
    print(out)
    assert "Number of jobs: 1" in out

    out, _ = cmd('./batou -d deploy -j 2 default')
    print(out)
    assert "Number of jobs: 2" in out

    out, _ = cmd('./batou -d deploy async')
    print(out)
    assert "Number of jobs: 2" in out
Exemple #30
0
def test_changed_remote_is_updated(root, repos_path, repos_path2):
    git = batou.lib.git.Clone(repos_path, target="clone", branch="master")
    root.component += git

    # Fresh, unrelated repo
    cmd("cd {dir}; echo baz >bar; git add .;"
        'git commit -m "commit"'.format(dir=repos_path2))

    root.component.deploy()
    assert not os.path.exists(root.component.map("clone/bar"))
    git.url = repos_path2
    root.component.deploy()
    assert os.path.exists(root.component.map("clone/bar"))