Пример #1
0
def git_command(cmdline, repo_dir, error_messages=True):
    """
    Runs the given git command line in the given directory.

    Returns stdout of the command.
    """
    cmdline = ["git"] + cmdline
    io.debug(_("running '{}' in {}").format(
        " ".join(cmdline),
        repo_dir,
    ))
    git_process = Popen(
        cmdline,
        cwd=repo_dir,
        preexec_fn=setpgrp,
        stderr=PIPE,
        stdout=PIPE,
    )
    stdout, stderr = git_process.communicate()
    # FIXME integrate this into Item._command_results
    if git_process.returncode != 0:
        if error_messages:
            io.stderr(
                _("{} failed command: {}").format(getpid(), " ".join(cmdline)))
            io.stderr(_("{} failed in dir: {}").format(getpid(), repo_dir))
            io.stderr(_("{} stdout:\n{}").format(getpid(), stdout))
            io.stderr(_("{} stderr:\n{}").format(getpid(), stderr))
        raise RuntimeError(
            _("`git {command}` failed in {dir}").format(
                command=cmdline[1],
                dir=repo_dir,
            ))
    return stdout.decode('utf-8').strip()
Пример #2
0
def get_local_repo_path(bw_repo_path, repo_name):
    """
    From the given BundleWrap repo, get the filesystem path to the git
    repo associated with the given internal repo name.
    """
    repo_map_path = join(bw_repo_path, REPO_MAP_FILENAME)
    if not isfile(repo_map_path):
        io.stderr(_("missing repo map for git_deploy at {}").format(repo_map_path))
        io.stderr(_("you must create this file with the following format:"))
        io.stderr(_("  <value of repo attribute on git_deploy item>: "
                    "<absolute path to local git repo>"))
        io.stderr(_("since the path is local, you should also add the "
                    "{} file to your gitignore").format(REPO_MAP_FILENAME))
        raise RepositoryError(_("missing repo map for git_deploy"))

    with open(join(bw_repo_path, REPO_MAP_FILENAME)) as f:
        repo_map = f.readlines()

    for line in repo_map:
        if not line.strip() or line.startswith("#"):
            continue
        try:
            repo, path = line.split(":", 1)
        except:
            raise RepositoryError(_("unable to parse line from {path}: '{line}'").format(
                line=line,
                path=repo_map_path,
            ))
        if repo_name == repo:
            return path.strip()

    raise RepositoryError(_("no path found for repo '{repo}' in {path}").format(
        path=repo_map_path,
        repo=repo_name,
    ))
Пример #3
0
def get_local_repo_path(bw_repo_path, repo_name):
    """
    From the given BundleWrap repo, get the filesystem path to the git
    repo associated with the given internal repo name.
    """
    repo_map_path = join(bw_repo_path, REPO_MAP_FILENAME)
    if not isfile(repo_map_path):
        io.stderr(_("missing repo map for git_deploy at {}").format(repo_map_path))
        io.stderr(_("you must create this file with the following format:"))
        io.stderr(_("  <value of repo attribute on git_deploy item>: "
                    "<absolute path to local git repo>"))
        io.stderr(_("since the path is local, you should also add the "
                    "{} file to your gitignore").format(REPO_MAP_FILENAME))
        raise RepositoryError(_("missing repo map for git_deploy"))

    with open(join(bw_repo_path, REPO_MAP_FILENAME)) as f:
        repo_map = f.readlines()

    for line in repo_map:
        if not line.strip() or line.startswith("#"):
            continue
        try:
            repo, path = line.split(":", 1)
        except:
            raise RepositoryError(_("unable to parse line from {path}: '{line}'").format(
                line=line,
                path=repo_map_path,
            ))
        if repo_name == repo:
            return path.strip()

    raise RepositoryError(_("no path found for repo '{repo}' in {path}").format(
        path=repo_map_path,
        repo=repo_name,
    ))
Пример #4
0
def content_processor_mako(item):
    template = Template(
        item._template_content.encode('utf-8'),
        input_encoding='utf-8',
        lookup=TemplateLookup(directories=[item.item_data_dir, item.item_dir]),
        output_encoding=item.attributes['encoding'],
    )
    io.debug("{node}:{bundle}:{item}: rendering with Mako...".format(
        bundle=item.bundle.name,
        item=item.id,
        node=item.node.name,
    ))
    start = datetime.now()
    try:
        content = template.render(item=item,
                                  bundle=item.bundle,
                                  node=item.node,
                                  repo=item.node.repo,
                                  **item.attributes['context'])
    except FaultUnavailable:
        raise
    except Exception as e:
        io.stderr("".join(format_exception(*exc_info())))
        if isinstance(e, NameError) and str(e) == "Undefined":
            # Mako isn't very verbose here. Try to give a more useful
            # error message - even though we can't pinpoint the excat
            # location of the error. :/
            e = _("Undefined variable (look for '${...}')")
        elif isinstance(e, KeyError):
            e = _("KeyError: {}").format(str(e))
        raise TemplateError(
            _("Error while rendering template for {node}:{bundle}:{item}: {error}"
              ).format(
                  bundle=item.bundle.name,
                  error=e,
                  item=item.id,
                  node=item.node.name,
              ))
    duration = datetime.now() - start
    io.debug("{node}:{bundle}:{item}: rendered in {time}s".format(
        bundle=item.bundle.name,
        item=item.id,
        node=item.node.name,
        time=duration.total_seconds(),
    ))
    return content
Пример #5
0
def _notify(url,
            message=None,
            title=None,
            fallback=None,
            user=None,
            target=None,
            color="#000000"):
    payload = {
        "icon_url": "http://bundlewrap.org/img/icon.png",
        "username": "******",
    }
    if fallback:
        payload["attachments"] = [{
            "color": color,
            "fallback": fallback,
        }]
        if message:
            payload["attachments"][0]["text"] = message
        if title:
            payload["attachments"][0]["title"] = title
        if target and user:
            payload["attachments"][0]["fields"] = [
                {
                    "short": True,
                    "title": "User",
                    "value": user,
                },
                {
                    "short": True,
                    "title": "Target",
                    "value": target,
                },
            ]
    else:
        payload["text"] = message

    try:
        post(
            url,
            headers={
                'content-type': 'application/json',
            },
            data=dumps(payload),
        )
    except ConnectionError as e:
        io.stderr("Failed to submit Slack notification: {}".format(e))
Пример #6
0
def main():
    io.activate()
    try:
        repo = Repository("")
    except NoSuchRepository:
        io.stderr("{} Not inside a bundlewrap repository".format(red("!")))
        sys.exit(1)
    my_path = pathlib.Path(__file__).parent.absolute()
    relpath = my_path.relative_to(repo.path)
    if not str(relpath).startswith("collections/"):
        io.stderr(
            "{} Collection should be installed to <repo>/collections".format(
                yellow("!")))
        sys.exit(1)
    install_dir(my_path / "hooks", repo.hooks_dir)
    install_dir(my_path / "libs", repo.libs_dir)
    install_dir(my_path / "items", repo.items_dir)
Пример #7
0
def _get_config(repo_path):
    config_path = join(repo_path, ".slack.cfg")
    if not exists(config_path):
        _create_config(config_path)
    config = SafeConfigParser()
    config.read(config_path)
    if config.get("configuration", "enabled", fallback="unconfigured") == "unconfigured":
        io.stderr("Slack notifications not configured. Please edit .slack.cfg "
                  "(it has already been created) and set enabled to 'yes' "
                  "(or 'no' to silence this message and disable Slack notifications).")
        return None
    elif config.get("configuration", "enabled").lower() not in ("yes", "true", "1"):
        io.debug("Slack notifications not enabled in .slack.cfg, skipping...")
        return None
    elif not REQUESTS:
        io.stderr("Slack notifications need the requests library. "
                  "You can usually install it with `pip install requests`.")
        return None
    return config
Пример #8
0
def git_command(cmdline, repo_dir):
    """
    Runs the given git command line in the given directory.

    Returns stdout of the command.
    """
    cmdline = ["git"] + cmdline
    io.debug(_("running '{}' in {}").format(
        " ".join(cmdline),
        repo_dir,
    ))
    git_process = Popen(
        cmdline,
        cwd=repo_dir,
        stderr=PIPE,
        stdout=PIPE,
    )
    stdout, stderr = git_process.communicate()
    if git_process.returncode != 0:
        io.stderr(_("failed command: {}").format(" ".join(cmdline)))
        io.stderr(_("stdout:\n{}").format(stdout))
        io.stderr(_("stderr:\n{}").format(stderr))
        raise RuntimeError(_("`git {command}` failed in {dir}").format(
            command=cmdline[1],
            dir=repo_dir,
        ))
    return stdout.decode('utf-8').strip()
Пример #9
0
def _notify(url, message=None, title=None, fallback=None, user=None, target=None, color="#000000"):
    payload = {
        "icon_url": "http://bundlewrap.org/img/icon.png",
        "username": "******",
    }
    if fallback:
        payload["attachments"] = [{
            "color": color,
            "fallback": fallback,
        }]
        if message:
            payload["attachments"][0]["text"] = message
        if title:
            payload["attachments"][0]["title"] = title
        if target and user:
            payload["attachments"][0]["fields"] = [
                {
                    "short": True,
                    "title": "User",
                    "value": user,
                },
                {
                    "short": True,
                    "title": "Target",
                    "value": target,
                },
            ]
    else:
        payload["text"] = message

    try:
        post(
            url,
            headers={
                'content-type': 'application/json',
            },
            data=dumps(payload),
        )
    except ConnectionError as e:
        io.stderr("Failed to submit Slack notification: {}".format(e))
Пример #10
0
def git_command(cmdline, repo_dir):
    """
    Runs the given git command line in the given directory.

    Returns stdout of the command.
    """
    cmdline = ["git"] + cmdline
    io.debug(_("running '{}' in {}").format(
        " ".join(cmdline),
        repo_dir,
    ))
    git_process = Popen(
        cmdline,
        cwd=repo_dir,
        preexec_fn=setpgrp,
        stderr=PIPE,
        stdout=PIPE,
    )
    stdout, stderr = git_process.communicate()
    if git_process.returncode != 0:
        io.stderr(_("failed command: {}").format(" ".join(cmdline)))
        io.stderr(_("stdout:\n{}").format(stdout))
        io.stderr(_("stderr:\n{}").format(stderr))
        raise RuntimeError(_("`git {command}` failed in {dir}").format(
            command=cmdline[1],
            dir=repo_dir,
        ))
    return stdout.decode('utf-8').strip()
Пример #11
0
def content_processor_jinja2(item):
    loader = FileSystemLoader(searchpath=[item.item_data_dir, item.item_dir])
    env = Environment(loader=loader)

    template = env.from_string(item._template_content)

    io.debug("{node}:{bundle}:{item}: rendering with Jinja2...".format(
        bundle=item.bundle.name,
        item=item.id,
        node=item.node.name,
    ))
    start = datetime.now()
    try:
        content = template.render(item=item,
                                  bundle=item.bundle,
                                  node=item.node,
                                  repo=item.node.repo,
                                  **item.attributes['context'])
    except FaultUnavailable:
        raise
    except Exception as e:
        io.stderr("".join(format_exception(*exc_info())))
        raise TemplateError(
            _("Error while rendering template for {node}:{bundle}:{item}: {error}"
              ).format(
                  bundle=item.bundle.name,
                  error=e,
                  item=item.id,
                  node=item.node.name,
              ))
    duration = datetime.now() - start
    io.debug("{node}:{bundle}:{item}: rendered in {time}s".format(
        bundle=item.bundle.name,
        item=item.id,
        node=item.node.name,
        time=duration.total_seconds(),
    ))
    return content.encode(item.attributes['encoding'])
Пример #12
0
def _get_config(repo_path):
    config_path = join(repo_path, ".slack.cfg")
    if not exists(config_path):
        _create_config(config_path)
    config = SafeConfigParser()
    config.read(config_path)
    if config.get("configuration", "enabled",
                  fallback="unconfigured") == "unconfigured":
        io.stderr(
            "Slack notifications not configured. Please edit .slack.cfg "
            "(it has already been created) and set enabled to 'yes' "
            "(or 'no' to silence this message and disable Slack notifications)."
        )
        return None
    elif config.get("configuration",
                    "enabled").lower() not in ("yes", "true", "1"):
        io.debug("Slack notifications not enabled in .slack.cfg, skipping...")
        return None
    elif not REQUESTS:
        io.stderr("Slack notifications need the requests library. "
                  "You can usually install it with `pip install requests`.")
        return None
    return config
Пример #13
0
from bundlewrap.utils.text import bold, mark_for_translation as _, yellow
from bundlewrap.utils.ui import io
from passlib.hash import apr_md5_crypt, sha512_crypt
from requests import Session

CONFIG_PATH = expanduser(
    environ.get("BW_TEAMVAULT_SECRETS_FILE", "~/.bw_teamvault_secrets.cfg"))
DUMMY_MODE = environ.get("BW_TEAMVAULT_DUMMY_MODE", "0") == "1"

cache = {}
config = SafeConfigParser()
try:
    config.read([CONFIG_PATH])
except:
    io.stderr("{x} WARNING: Unable to read TeamVault config at {path}".format(
        path=CONFIG_PATH,
        x=yellow("!"),
    ))
sessions = {}


def _fetch_secret(site, secret_id):
    try:
        return cache[site][secret_id]
    except KeyError:
        pass

    session = sessions.setdefault(getpid(), Session())

    try:
        full_url = "{}/api/secrets/{}/".format(
            config.get(site, "url"),
Пример #14
0
from bundlewrap.utils.text import bold, mark_for_translation as _, yellow
from bundlewrap.utils.ui import io
from passlib.hash import apr_md5_crypt, sha512_crypt
from requests import Session

CONFIG_PATH = expanduser(
    environ.get("BW_TEAMVAULT_SECRETS_FILE", "~/.bw_teamvault_secrets.cfg"))
DUMMY_MODE = environ.get("BW_TEAMVAULT_DUMMY_MODE", "0") == "1"

cache = {}
config = ConfigParser()
try:
    config.read([CONFIG_PATH])
except:
    io.stderr("{x} WARNING: Unable to read TeamVault config at {path}".format(
        path=CONFIG_PATH,
        x=yellow("!"),
    ))
sessions = {}

for site_name, site_config in config.items():
    if (('password' not in site_config or not site_config['password'])
            and 'pass_command' in site_config):
        try:
            config[site_name]['password'] = check_output(
                site_config['pass_command'],
                shell=True).decode('UTF-8').splitlines()[0].strip()
        except (FileNotFoundError, CalledProcessError, IndexError) as e:
            io.stderr("{x} TeamVault pass_command for site {site} failed: {e}".
                      format(x=yellow('!'), site=site_name, e=repr(e)))

Пример #15
0
from bundlewrap.utils import Fault
from bundlewrap.utils.text import bold, mark_for_translation as _, yellow
from bundlewrap.utils.ui import io
from passlib.hash import apr_md5_crypt, sha512_crypt
from requests import Session

CONFIG_PATH = expanduser(environ.get("BW_TEAMVAULT_SECRETS_FILE", "~/.bw_teamvault_secrets.cfg"))
DUMMY_MODE = environ.get("BW_TEAMVAULT_DUMMY_MODE", "0") == "1"

cache = {}
config = SafeConfigParser()
try:
    config.read([CONFIG_PATH])
except:
    io.stderr("{x} WARNING: Unable to read TeamVault config at {path}".format(
        path=CONFIG_PATH,
        x=yellow("!"),
    ))
sessions = {}


def _fetch_secret(site, secret_id):
    try:
        return cache[site][secret_id]
    except KeyError:
        pass

    session = sessions.setdefault(getpid(), Session())

    try:
        full_url = "{}/api/secrets/{}/".format(
            config.get(site, "url"),