Example #1
0
def _run_modules(callbacks, outdir, modules_to_run, diff, no_write, no_exec, no_git):
    for module_name, callback in callbacks:
        if module_name not in modules_to_run:
            logger.debug("No action: skipping %s" % module_name)
        else:
            logger.info("Running module %s..." % module_name)
            callback(outdir, diff, no_write, no_exec, no_git)
Example #2
0
def _load_modules(modules_to_load, indir):
    config = caretakr.config.load(indir)
    for module_name in known_modules:
        if module_name in config and module_name not in modules_to_load:
            del config[module_name]
    callbacks = []
    for module_name in modules_to_load:
        if module_name in config:
            module_py = importlib.import_module('caretakr.%s' % module_name)
            logger.info("Loading module %s..." % module_name)
            callback, additional_config = module_py.load(config[module_name])
            config = caretakr.config.deepmerge(config, additional_config)
            callbacks.append((module_name, callback))
    _cleanup_dictionary(config)
    if len(config) > 0:
        logger.warning("Unrecognized options left in config: %s" % config)
    return callbacks
Example #3
0
def cmd(cmd, dry_run, stdin=None, expected_returncodes=None):
    if isinstance(stdin, list):
        stdin = "%s\n" % '\n'.join(stdin)
    if expected_returncodes is None:
        expected_returncodes = [0]
    else:
        expected_returncodes = flatten(expected_returncodes)
    if dry_run is True:
        logger.info("Would execute %s" % str(cmd))
    else:
        logger.info("Executing %s" % str(cmd))
        proc = subprocess.Popen(cmd, stdin=subprocess.PIPE,
                                stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        stdout, stderr = proc.communicate(stdin)
        if proc.returncode not in expected_returncodes:
            raise Exception("Running %s failed with exit code %s: %s" %
                            (str(cmd), proc.returncode, stderr))
        return stdout, stderr
Example #4
0
def git_commit(outdir, filenames, dry_run, module_name=None):
    filenames = flatten(filenames)
    full_filenames = [os.path.join(outdir, filename) for filename in filenames]
    git_dir = os.path.join(outdir, '.git')
    if os.path.isdir(git_dir) is False:
        logger.info("Skipping git actions for %s, no git dir %s" % (filenames, git_dir))
        return
    if os.stat(git_dir).st_uid != os.geteuid():
        logger.info("Skipping git actions for %s, git dir %s not owned by us" %
                    (filenames, git_dir))
        return

    env = os.environ.copy()
    git_env = {
        'GIT_DIR': git_dir,
        'GIT_WORK_TREE': outdir,
    }
    env.update(git_env)
    if dry_run is True:
        cmd_status = ['git', 'status', '--porcelain']
        cmd_status.extend(filenames)
        proc_status = subprocess.Popen(cmd_status, env=env,
                                       stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        stdout_status, stderr_status = proc_status.communicate()
        if proc_status.returncode != 0:
            raise Exception("Unable to do git status in %s: %s" % (outdir, stderr_status))
        logger.info("Git: changes in %s: %s" % (outdir, stdout_status.splitlines()))
    else:
        cmd_add = ['git', 'add']
        cmd_add.extend(full_filenames)
        logger.trace("Running command %s with GIT env %s" % (cmd_add, git_env))
        proc_add = subprocess.Popen(cmd_add, env=env,
                                    stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        _, stderr_add = proc_add.communicate()
        if proc_add.returncode != 0:
            raise Exception("Adding changes in %s failed: %s" % (outdir, stderr_add))

        logger.info("Git: commit %s" % filenames)
        cmd_commit = ['git', 'commit', '-m']
        if module_name is not None:
            cmd_commit.append('commiting changes after caretakr run: %s' % module_name)
        else:
            cmd_commit.append('commiting changes after caretakr run')
        cmd_commit.extend(full_filenames)
        logger.trace("Running command %s with GIT env %s" % (cmd_commit, git_env))
        proc_commit = subprocess.Popen(cmd_commit, env=env,
                                       stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        _, stderr_commit = proc_commit.communicate()
        if proc_commit.returncode != 0 and stderr_commit != '':
            raise Exception("Commiting changes in %s failed: %s" % (outdir, stderr_commit))
Example #5
0
def write_file(outdir, filename, lines, dry_run, diff=False, remove_empty=False):
    did_write_changes = False
    target_filename = os.path.join(outdir, filename)
    if len(lines) > 0:
        lines.insert(0 if not lines[0].startswith('#!') else 1, "# Managed by CARETAKR")
    new_content = "%s\n" % '\n'.join(lines)
    try:
        with open(target_filename) as f:
            current_content = f.read()
    except:
        current_content = "\n"
    if diff is True:
        if new_content != current_content:
            diff_lines = difflib.unified_diff(current_content.splitlines(), lines,
                                              fromfile='a/%s' % filename,
                                              tofile='b/%s' % filename,
                                              lineterm='')
            if sys.stdout.isatty():
                print('\n'.join(map(colorize, diff_lines)))
            else:
                map(logger.info, diff_lines)

    if dry_run is True:
        if os.path.isfile(target_filename) and len(lines) == 0 and remove_empty is True:
            logger.info("Would attempt to remove %s, because there is no new content" %
                        target_filename)
        elif ((os.path.isfile(target_filename) and os.access(target_filename, os.W_OK) is True)
              or (os.path.exists(target_filename) is False and
              os.access(os.path.dirname(target_filename), os.W_OK) is True)):
            if new_content != current_content:
                if ((os.path.isfile(target_filename)
                     and os.stat(target_filename).st_uid != os.geteuid())):
                    logger.error("Would refuse to overwrite %s, as it's not owned by us!" %
                                 target_filename)
                else:
                    logger.info("Would write %d lines to %s" % (len(lines), target_filename))
                    did_write_changes = True
            elif not (os.path.isfile(target_filename) is False and remove_empty is True):
                logger.info("No changes for %s" % target_filename)
        else:
            logger.error("Would not be able to write file at %s" % target_filename)
    else:
        if len(lines) == 0 and remove_empty is True:
            if ((os.path.isfile(target_filename)
                 and os.stat(target_filename).st_uid != os.geteuid())):
                logger.error("Refusing to remove %s, as it's not owned by us!" % target_filename)
            else:
                if os.path.isfile(target_filename):
                    logger.info("Removing %s" % target_filename)
                    os.remove(target_filename)
                    did_write_changes = True
        else:
            if new_content != current_content:
                if ((os.path.isfile(target_filename)
                     and os.stat(target_filename).st_uid != os.geteuid())):
                    logger.error("Refusing to overwrite %s, as it's not owned by us!" %
                                 target_filename)
                else:
                    logger.info("Writing %s (%d lines)" % (target_filename, len(lines)))
                    try:
                        os.makedirs(os.path.dirname(target_filename))
                    except:
                        pass
                    with open(target_filename, 'w') as f:
                        f.write(new_content)
                    did_write_changes = True
            else:
                logger.info("No changes for %s" % target_filename)
    return did_write_changes