Beispiel #1
0
    def fix(self, status):
        if status.info['exists']:
            if self.attributes['delete']:
                msg = _("{node}:{item}: deleting...")
            else:
                msg = _("{node}:{item}: updating...")
        else:
            msg = _("{node}:{item}: creating...")
        LOG.info(msg.format(item=self.id, node=self.node.name))

        if self.attributes['delete']:
            self.node.run("userdel {}".format(self.name))
        else:
            self.node.run("{command} "
                "-d {home} "
                "-g {gid} "
                "-G {groups} "
                "-p {password_hash} "
                "-s {shell} "
                "-u {uid} "
                "{username}".format(
                    command="useradd" if not status.info['exists'] else "usermod",
                    home=quote(self.attributes['home']),
                    gid=self.attributes['gid'],
                    groups=quote(",".join(self.attributes['groups'])),
                    password_hash=quote(self.attributes['password_hash']),
                    shell=quote(self.attributes['shell']),
                    uid=self.attributes['uid'],
                    username=self.name,
                )
            )
    def fix(self, status):
        if not status.info['exists']:
            LOG.info(_("{}:{}: creating...").format(self.node.name, self.id))
        else:
            LOG.info(_("{}:{}: updating...").format(self.node.name, self.id))

        self.node.run("echo '{} {} {}' | debconf-set-selections".format(
            self.attributes['pkg_name'],
            self.name,  
            self.attributes['value'],
        ))
        sleep(1)
Beispiel #3
0
 def fix(self, status):
     if self.attributes['installed'] is False:
         LOG.info(_("{node}:{item}: removing...").format(
             item=self.id,
             node=self.node.name,
         ))
         pkg_remove(self.node, self.name)
     else:
         LOG.info(_("{node}:{item}: installing...").format(
             item=self.id,
             node=self.node.name,
         ))
         pkg_install(self.node, self.name)
Beispiel #4
0
 def fix(self, status):
     if self.attributes['running'] is False:
         LOG.info(_("{node}:{item}: stopping...").format(
             item=self.id,
             node=self.node.name,
         ))
         svc_stop(self.node, self.name)
     else:
         LOG.info(_("{node}:{item}: starting...").format(
             item=self.id,
             node=self.node.name,
         ))
         svc_start(self.node, self.name)
Beispiel #5
0
    def run(self, interactive=False):
        result = self.bundle.node.run(
            self.attributes['command'],
            may_fail=True,
        )

        if self.attributes['expected_return_code'] is not None and \
                not result.return_code == self.attributes['expected_return_code']:
            if not interactive:
                LOG.error("{}:{}: {}".format(
                    self.bundle.node.name,
                    self.id,
                    red(_("FAILED")),
                ))
            raise ActionFailure(_(
                "wrong return code for action '{action}' in bundle '{bundle}': "
                "expected {ecode}, but was {rcode}"
            ).format(
                action=self.name,
                bundle=self.bundle.name,
                ecode=self.attributes['expected_return_code'],
                rcode=result.return_code,
            ))

        if self.attributes['expected_stderr'] is not None and \
                result.stderr != self.attributes['expected_stderr']:
            LOG.error("{}:{}: {}".format(
                self.bundle.node.name,
                self.id,
                red(_("FAILED")),
            ))
            raise ActionFailure(_(
                "wrong stderr for action '{action}' in bundle '{bundle}'"
            ).format(
                action=self.name,
                bundle=self.bundle.name,
            ))

        if self.attributes['expected_stdout'] is not None and \
                result.stdout != self.attributes['expected_stdout']:
            LOG.error("{}:{}: {}".format(
                self.bundle.node.name,
                self.id,
                red(_("FAILED")),
            ))
            raise ActionFailure(_(
                "wrong stdout for action '{action}' in bundle '{bundle}'"
            ).format(
                action=self.name,
                bundle=self.bundle.name,
            ))

        LOG.info("{}:{}: {}".format(
            self.bundle.node.name,
            self.id,
            green(_("OK")),
        ))

        return result
Beispiel #6
0
def diff(content_old, content_new, filename, encoding_hint=None):
    output = ""
    LOG.debug("diffing {filename}: {len_before} B before, {len_after} B after".format(
        filename=filename,
        len_before=len(content_old),
        len_after=len(content_new),
    ))
    start = datetime.now()
    for line in unified_diff(
        content_old.splitlines(True),
        content_new.splitlines(True),
        fromfile=filename,
        tofile=_("<blockwart content>"),
    ):
        suffix = ""
        try:
            line = line.decode('UTF-8')
        except UnicodeDecodeError:
            if encoding_hint and encoding_hint.lower() != "utf-8":
                try:
                    line = line.decode(encoding_hint)
                    suffix += _(" (line encoded in {})").format(encoding_hint)
                except UnicodeDecodeError:
                    line = line[0]
                    suffix += _(" (line not encoded in UTF-8 or {})").format(encoding_hint)
            else:
                line = line[0]
                suffix += _(" (line not encoded in UTF-8)")

        line = line.rstrip("\n")
        if len(line) > DIFF_MAX_LINE_LENGTH:
            line = line[:DIFF_MAX_LINE_LENGTH]
            suffix += _(" (line truncated after {} characters)").format(DIFF_MAX_LINE_LENGTH)
        if line.startswith("+"):
            line = green(line)
        elif line.startswith("-"):
            line = red(line)
        output += line + suffix + "\n"
    duration = datetime.now() - start
    LOG.debug("diffing {file}: complete after {time}s".format(
        file=filename,
        time=duration.total_seconds(),
    ))
    return output
Beispiel #7
0
    def fix(self, status):
        if 'type' in status.info['needs_fixing']:
            # fixing the type fixes everything
            if status.info['path_info'].exists:
                LOG.info(_("{node}:{item}: fixing type...").format(
                    item=self.id,
                    node=self.node.name,
                ))
            else:
                LOG.info(_("{node}:{item}: creating...").format(
                    item=self.id,
                    node=self.node.name,
                ))
            self._fix_type(status)
            return

        for fix_type in ('owner', 'group'):
            if fix_type in status.info['needs_fixing']:
                if fix_type == 'group' and \
                        'owner' in status.info['needs_fixing']:
                    # owner and group are fixed with a single chown
                    continue
                LOG.info(_("{node}:{item}: fixing {type}...").format(
                    item=self.id,
                    node=self.node.name,
                    type=fix_type,
                ))
                getattr(self, "_fix_" + fix_type)(status)
Beispiel #8
0
    def get_result(self, interactive=False, interactive_default=True):
        if interactive is False and self.attributes['interactive'] is True:
            return self.STATUS_ACTION_SKIPPED

        if self.triggered and not self.has_been_triggered:
            LOG.debug(_("skipping {} because it wasn't triggered").format(self.id))
            return self.STATUS_ACTION_SKIPPED

        if self.unless:
            unless_result = self.bundle.node.run(
                self.unless,
                may_fail=True,
            )
            if unless_result.return_code == 0:
                LOG.debug(_("{node}:action:{name}: failed 'unless', not running").format(
                    name=self.name,
                    node=self.bundle.node.name,
                ))
                return self.STATUS_ACTION_SKIPPED

        if (
            interactive and
            self.attributes['interactive'] is not False
            and not ask_interactively(
                wrap_question(
                    self.id,
                    self.attributes['command'],
                    _("Run action {}?").format(
                        bold(self.name),
                    ),
                ),
                interactive_default,
            )
        ):
            return self.STATUS_ACTION_SKIPPED
        try:
            self.run(interactive=interactive)
            return self.STATUS_ACTION_OK
        except ActionFailure:
            return self.STATUS_ACTION_FAILED
Beispiel #9
0
 def fix(self, status):
     if not status.info['exists']:
         LOG.info(_("{node}:{item}: creating...").format(node=self.node.name, item=self.id))
         self.node.run("groupadd -g {gid} {groupname}".format(
             gid=self.attributes['gid'],
             groupname=self.name,
         ))
     elif self.attributes['delete']:
         LOG.info(_("{node}:{item}: deleting...").format(node=self.node.name, item=self.id))
         self.node.run("groupdel {}".format(self.name))
     else:
         LOG.info(_("{node}:{item}: updating...").format(node=self.node.name, item=self.id))
         self.node.run("groupmod -g {gid} {groupname}".format(
             gid=self.attributes['gid'],
             groupname=self.name,
         ))
Beispiel #10
0
 def fix(self, status):
     for fix_type in ('type', 'content', 'mode', 'owner', 'group'):
         if fix_type in status.info['needs_fixing']:
             if fix_type == 'group' and \
                     'owner' in status.info['needs_fixing']:
                 # owner and group are fixed with a single chown
                 continue
             if fix_type in ('mode', 'owner', 'group') and \
                     'content' in status.info['needs_fixing']:
                 # fixing content implies settings mode and owner/group
                 continue
             if status.info['path_info'].exists:
                 if self.attributes['delete']:
                     LOG.info(_("{node}:{item}: deleting...").format(
                         node=self.node.name, item=self.id))
                 else:
                     LOG.info(_("{node}:{item}: fixing {type}...").format(
                         node=self.node.name, item=self.id, type=fix_type))
             else:
                 LOG.info(_("{node}:{item}: creating...").format(
                     node=self.node.name, item=self.id))
             getattr(self, "_fix_" + fix_type)(status)
Beispiel #11
0
def content_processor_mako(item):
    from mako.template import Template
    template = Template(
        item._template_content,
        input_encoding='utf-8',
        output_encoding=item.attributes['encoding'],
    )
    LOG.debug("{}:{}: rendering with Mako...".format(item.node.name, item.id))
    start = datetime.now()
    try:
        content = template.render(
            item=item,
            bundle=item.bundle,
            node=item.node,
            repo=item.node.repo,
            **item.attributes['context']
        )
    except Exception as e:
        LOG.debug("".join(format_exception(*exc_info())))
        if isinstance(e, NameError) and e.message == "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 '${...}')")
        raise TemplateError(_(
            "Error while rendering template for {node}:{item}: {error}"
        ).format(
            error=e,
            item=item.id,
            node=item.node.name,
        ))
    duration = datetime.now() - start
    LOG.debug("{node}:{item}: rendered in {time}s".format(
        item=item.id,
        node=item.node.name,
        time=duration.total_seconds(),
    ))
    return content
Beispiel #12
0
    def apply(self, interactive=False, interactive_default=True):
        self.node.repo.hooks.item_apply_start(
            self.node.repo,
            self.node,
            self,
        )
        status_code = None
        status_before = None
        status_after = None
        start_time = datetime.now()

        if self.triggered and not self.has_been_triggered:
            LOG.debug(_("skipping {} because it wasn't triggered").format(self.id))
            status_code = self.STATUS_SKIPPED

        if status_code is None:
            status_before = self.get_status()
            if self.unless and not status_before.correct:
                unless_result = self.node.run(self.unless, may_fail=True)
                if unless_result.return_code == 0:
                    LOG.debug(_("'unless' for {} succeeded, not fixing").format(self.id))
                    status_code = self.STATUS_SKIPPED

        if status_code is None:
            if status_before.correct:
                status_code = self.STATUS_OK

        if status_code is None:
            if not interactive:
                self.fix(status_before)
                status_after = self.get_status()
            else:
                question = wrap_question(
                    self.id,
                    self.ask(status_before),
                    _("Fix {}?").format(bold(self.id)),
                )
                if ask_interactively(question,
                                     interactive_default):
                    self.fix(status_before)
                    status_after = self.get_status()
                else:
                    status_code = self.STATUS_SKIPPED

        if status_code is None:
            if status_after.correct:
                status_code = self.STATUS_FIXED
            else:
                status_code = self.STATUS_FAILED

        self.node.repo.hooks.item_apply_end(
            self.node.repo,
            self.node,
            self,
            duration=datetime.now() - start_time,
            status_code=status_code,
            status_before=status_before,
            status_after=status_after,
        )

        return status_code