Exemplo n.º 1
0
def setupContext(args, require_editable=True, require_own_suite=False):
    bundle = Bundle(args.bundleName[0], basedir=PROJECT_DIR)
    if require_editable and not bundle.isEditable():
        raise BundleError("Not allowed to modify bundle '{}' as it is readonly!".format(bundle.bundleName))
    if not os.path.isdir(bundle.getTemplateDir()):
        raise BundleError("No template folder found for distribution '{}'!".format(bundle.distribution))
    logger.info("You are now using bundle '{}'".format(bundle.bundleName))
    apt_repos.setAptReposBaseDir(bundle.getAptReposBasedir())
    try:
        bundle.setOwnSuite(args.own_suite)
    except BundleError as e:
        if require_own_suite:
            raise e
        logger.warning(e)
    return bundle
Exemplo n.º 2
0
def cmd_seal(args):
    '''
        Subcommand seal: Mark the bundle as ReadOnly and change a suite's tag from 'staging' to 'deploy'.
    '''
    bundle = setupContext(args, require_own_suite=True)
    sourcesInReprepro = set([
        list(p.getData())[0]
        for p in bundle.queryBinaryPackages(packageFields="C")
    ])
    if len(sourcesInReprepro) == 0:
        raise BundleError(
            "Sorry, the bundle {} is empty and you can't seal an empty bundle!"
            .format(bundle))
    (applied, not_applied) = bundle.getApplicationStatus()
    applied_diff = sourcesInReprepro.symmetric_difference(applied)
    if len(applied_diff) > 0 or len(not_applied) > 0:
        raise BundleError(
            "Sorry, the sources_control.list is not (yet?) fully applied to the reprepro-repository! Differences found for "
            + ", ".join(sorted(applied_diff | not_applied)))
    with choose_commit_context(bundle, args,
                               "SEALED bundle '{bundleName}'") as (bundle,
                                                                   git_add,
                                                                   cwd):
        infofile = edit_meta(bundle, CANCEL_REMARK.format(action="seal"))
        if not infofile:
            return
        git_add.append(infofile)
        git_add.append(bundle.updateInfofile(rollout=True))
        git_add.append(create_reprepro_config(bundle, readOnly=True))
        git_add.append(updateReposConfig(cwd=cwd))
    sealedHook = reprepro_bundle.getHooksConfig(cwd=cwd).get(
        'bundle_sealed', None)
    if sealedHook:
        info = bundle.getInfo()
        target = "{}".format(info.get("Target", "no-target"))
        subject = info.get("Releasenotes", "--no-subject--").split("\n")[0]
        cmd = [
            arg.format(bundleName=bundle.bundleName,
                       bundleSuiteName=bundle.getOwnSuiteName(),
                       subject=subject,
                       target=target) for arg in sealedHook.split()
        ]
        logger.info("Calling bundle_sealed hook '{}'".format(" ".join(cmd)))
        try:
            subprocess.check_call(cmd, cwd=cwd)
        except Exception as e:
            logger.warning("Hook execution failed in folder {}: {}".format(
                cwd, e))
Exemplo n.º 3
0
def git_clean_commit_and_push_context(git_repo_url, git_branch, bundle, own_suite, commit_msg, bundleName=None):
    if not git_repo_url:
        raise BundleError("Could not determine the git repository url. Use --git-repo-url to set one explicitely.")
    # clone to temp dir
    tmpDir = tempfile.mkdtemp()
    basedir = os.path.join(tmpDir, 'local_repo')
    logger.debug("Cloning {} to {}".format(git_repo_url, basedir))
    subprocess.check_call(('git', 'clone', git_repo_url, basedir))
    subprocess.check_call(('git', 'checkout', git_branch), cwd=basedir)

    if bundle:
        bundle = Bundle(bundle.bundleName, basedir)
    elif bundleName:
        bundle = Bundle(bundleName, basedir)
    try:
        if bundle and own_suite:
            bundle.setOwnSuite(own_suite)
    except BundleError as e:
        logger.warning(str(e))
    git_add_list = list() # of filenames

    yield (bundle, git_add_list, basedir)

    bundleName = bundle.bundleName if bundle else None
    git_commit(git_add_list, commit_msg.format(bundleName=bundleName), cwd=basedir)
    git_push(git_branch, cwd=basedir)
    shutil.rmtree(tmpDir)
Exemplo n.º 4
0
def choose_commit_context(bundle, args, commit_msg, bundleName=None):
    '''
        This context manager evaluates the properties args.clean_commit and args.commit to decide
        how change tracking should be handled. Possible ways are:

        a) Don't track and commit changes
        b) track and commit changes inside the current project-folder
        c) clone the git project into a temporary folder, track and commit changes and push
           the results back to the git server.

        in case ob c), the arguments args.git_repo_url, args.git_branch and args.own_suite are
        required.

        bundle could be None. In this case, a bundleName has to be specified and a new Bundle is
        initialized inside the commit_context using bundleName
    '''
    if args.clean_commit and args.commit:
        raise BundleError("The command line switches --clean-commit and --commit can't be used together!")
    if args.clean_commit:
        with git_clean_commit_and_push_context(args.git_repo_url, args.git_branch, bundle, args.own_suite, commit_msg, bundleName) as (bundle, git_add_list, cwd):
            yield (bundle, git_add_list, cwd)
    elif args.commit:
        with git_local_commit_context(bundle, commit_msg, bundleName) as (bundle, git_add_list, cwd):
            yield (bundle, git_add_list, cwd)
    else:
        if (not bundle) and bundleName:
            bundle = Bundle(bundleName, basedir=PROJECT_DIR)
        yield (bundle, list(), PROJECT_DIR)
Exemplo n.º 5
0
 def __init__(self, suiteName, packages):
     suites = sorted(apt_repos.getSuites([suiteName]))
     if len(suites) != 1:
         raise BundleError(
             "Can't create UpdateRule for suite selector '{}' since it doesn't select exactly one suite."
             .format(suiteName))
     self.suite = suites[0]
     self.packages = packages
Exemplo n.º 6
0
def cmd_seal(args):
    '''
        Subcommand seal: Mark the bundle as ReadOnly and change a suite's tag from 'staging' to 'deploy'.
    '''
    ## pre seal checks ##
    bundle = setupContext(args, require_own_suite=True)
    packages = bundle.queryBinaryPackages(packageFields="pC")
    binariesInReprepro = set([list(p.getData())[0] for p in packages])
    sourcesInReprepro = set([list(p.getData())[1] for p in packages])
    if len(sourcesInReprepro) == 0:
        raise BundleError("Sorry, the bundle {} is empty and you can't seal an empty bundle!".format(bundle))
    (applied, not_applied) = bundle.getApplicationStatus()
    applied_diff = sourcesInReprepro.symmetric_difference(applied)
    if len(applied_diff) > 0 or len(not_applied) > 0:
        raise BundleError("Sorry, the sources_control.list is not (yet?) fully applied to the reprepro-repository! Differences found for " + ", ".join(sorted(applied_diff | not_applied)))
    globalBlacklistFile = args.global_blacklist_file or ""
    globalBlacklistFile = os.path.join(PROJECT_DIR, globalBlacklistFile.format(distribution=bundle.distribution))
    if os.path.isfile(globalBlacklistFile):
        globalBlacklist = parseBlacklist(globalBlacklistFile)
        blacklistedBinaries = binariesInReprepro.intersection(globalBlacklist)
        if len(blacklistedBinaries) > 0:
            raise BundleError("The following binary packages contained in this bundle are blacklisted:\n\n- {}\n\nPlease adjust the file {}\nor use '{} blacklist {}' to remove those packages from the bundle!".format("\n- ".join(sorted(blacklistedBinaries)), globalBlacklistFile, reprepro_bundle.PROGNAME, bundle))

    with choose_commit_context(bundle, args, "SEALED bundle '{bundleName}'") as (bundle, git_add, cwd):
        infofile = edit_meta(bundle, CANCEL_REMARK.format(action="seal"))
        if not infofile:
            return
        git_add.append(infofile)
        git_add.append(bundle.updateInfofile(rollout=True))
        git_add.append(create_reprepro_config(bundle, readOnly=True))
        git_add.append(updateReposConfig(cwd=cwd))
    sealedHook = reprepro_bundle.getHooksConfig(cwd=cwd).get('bundle_sealed', None)
    if sealedHook:
        info = bundle.getInfo()
        target = "{}".format(info.get("Target", "no-target"))
        subject = info.get("Releasenotes", "--no-subject--").split("\n")[0]
        cmd = [arg.format(bundleName=bundle.bundleName, bundleSuiteName=bundle.getOwnSuiteName(), subject=subject, target=target) for arg in sealedHook.split()]
        logger.info("Calling bundle_sealed hook '{}'".format(" ".join(cmd)))
        try:
            subprocess.check_call(cmd, cwd=cwd)
        except Exception as e:
            logger.warning("Hook execution failed in folder {}: {}".format(cwd, e))
Exemplo n.º 7
0
 def setOwnSuite(self, ownSuiteStr):
     '''
         Sets the bundles `ownSuite` to a apt_repos.RepoSuite object derived from `ownSuiteStr`.
         `ownSuiteStr` could be a template string that after filling in the templates should
         describe the apt-repos suite identifier of the (typically server side) apt-repository
         representing the bundle's content.
     '''
     selector = ownSuiteStr
     if ownSuiteStr:
         (suites, selector) = self.parseSuitesStr(ownSuiteStr)
         if len(suites) > 0:
             self._ownSuite = sorted(suites)[0]
     if not self._ownSuite:
         raise BundleError(
             "Could not connect bundle '{}' to it's own apt-repos suite '{}'."
             .format(self.bundleName, selector))
Exemplo n.º 8
0
 def __init__(self, bundleName, basedir):
     '''
         Parses `bundleName` which could be in the form [repo/bundle/]<distribution>[/<bundleID>]
         and either uses the specified bundleID or creates a new bundleID (after scanning the
         already exising bundles for <distribution>).
     '''
     regex = re.compile(r"^(repo/bundle/)?([\w\.]+)(/(\d+))?$")
     m = regex.match(bundleName)
     if not m:
         raise BundleError(
             "bundleName '{}' doesn't match the pattern '{}'".format(
                 bundleName, regex.pattern))
     else:
         (_, distribution, _, number) = m.groups()
     if not number:  # create a new one
         highest = 0
         mydir = os.path.join(basedir, "repo", "bundle", distribution)
         if os.path.isdir(mydir):
             for f in os.listdir(mydir):
                 f = os.path.join(distribution, f)
                 m = regex.match(f)
                 if m:
                     number = int(m.group(4))
                     if number > highest:
                         highest = number
         number = highest + 1
     self.basedir = basedir
     self.distribution = distribution
     self.bundleName = "{}/{:04d}".format(distribution, int(number))
     self.__confDir = os.path.join(self.basedir, "repo", "bundle",
                                   self.bundleName, "conf")
     self.scl = os.path.join(self.__confDir, "sources_control.list")
     self._blacklist = "FilterList-blacklisted-binary-packages"
     self._infofile = "info"
     self._updatesfile = "updates"
     self._ownSuite = None
     self._templateEnv = Environment(
         loader=FileSystemLoader(self.getTemplateDir()))
 def getByName(name):
     for p in PackageStatus:
         if name.upper() == p.name:
             return p
     raise BundleError("Unknown Package-Status {}".format(name))
Exemplo n.º 10
0
 def getByAction(strVal):
     for p in PackageStatus:
         if strVal.upper() == p.value[1]:
             return p
     raise BundleError("Unknown Package-Status {}".format(strVal))