cache.py 3.41 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129
from fabric.api import task, runs_once, env, serial, puts, settings
from fabric.utils import fastprint
from fabric.colors import blue, red, white

from output import notify
from packages import PackageDescriptor
from output import unsquelched
from hosts import exemplar
from ssh_tunnel import setup_tunnel
from packages import PackageInfo


@task
@runs_once
def from_exemplar(**tags):
    """
    Cache the set of packages installed on one host from the specified tags.

    """
    host_string = setup_tunnel([exemplar(**tags)])[0]
    with settings(host_string=host_string):
        installed_packages()


@task
@runs_once
def limit_prefix(*prefix_list):
    """
    Limits cached packages to those that
    match one or more prefix strings
    """
    env.package_descriptors = filter(
        lambda pkg: any(pkg.name.startswith(prefix)
                        for prefix in prefix_list), env.package_descriptors)


@task(default=True)
@runs_once
def installed_packages(prefix=None):
    """
    Cache the set of packages installed on the selected host.
    """
    pkg_info = PackageInfo()
    env.package_descriptors = [
        package for package in pkg_info.installed_packages()
        if prefix is None or package.name.startswith(prefix)
    ]


@task
@runs_once
def from_strings(**pkg_revs):
    """
    Cache packages based on strings, that can be either checked with confirm
    or deployed with deploy.

    Each named argument specifies a package by name, and the revision of
    the package to deploy
    """
    packages = []
    for pkg_name, pkg_rev in pkg_revs.items():
        packages.append(PackageDescriptor(pkg_name, pkg_rev))

    env.package_descriptors = packages

    notify(env.package_descriptors)


@task
@runs_once
def from_stdin(prefix=None):
    """
    Cache a list of packages from stdin.
    Package names must start with prefix, if specified (any that don't
    will be skipped). Package names and revisions should be separated
    by = signs, and should be one per line.
    """

    if prefix:
        prefix_msg = white('pkg_name', bold=True) + white(
            ' must start with ') + blue(prefix)
    else:
        prefix_msg = ''
    fastprint('\n')
    fastprint('\n'.join([
        white('Please enter pkg_name=pkg_rev, one per line\n', bold=True),
        white('pkg_rev', bold=True) + white(' is a git revision hash'),
        prefix_msg,
        white('Complete your selections by entering a blank line.'),
    ]))
    fastprint('\n\n')

    packages = {}
    while True:
        line = raw_input("> ")
        if not line:
            break

        if '=' not in line:
            fastprint(red("Expected = in '{line}'. Skipping...".format(
                          line=line)) + white('\n'))
            continue

        pkg_name, _, pkg_rev = line.partition('=')
        pkg_name = pkg_name.strip()
        pkg_rev = pkg_rev.strip()

        if prefix and not pkg_name.startswith(prefix):
            fastprint(red("'{0}' does not start with '{1}'".format(
                          pkg_name, prefix)) + white('\n'))
            continue

        packages[pkg_name] = pkg_rev

    from_strings(**packages)


@task
@serial
@runs_once
def prompt(*pkg_names):
    packages = {}
    with unsquelched():
        puts("Please supply git revisions to "
             "deploy for the following packages:")
        for pkg in pkg_names:
            packages[pkg] = raw_input("{pkg} = ".format(pkg=pkg)).strip()

        from_strings(**packages)