示例#1
0
def checkout_git_repo(git_uri, git_ref, git_branch=None):
    tmpdir = tempfile.mkdtemp()
    repo_path = os.path.join(tmpdir, "repo")
    try:
        try:
            # when you clone into an empty directory and cloning process fails
            # git will remove the empty directory (why?!)
            args = ['git', 'clone', git_uri]
            if git_branch:
                args += ['-b', git_branch]

            args.append(repo_path)
            run_command(args)
        except OsbsException as ex:
            raise OsbsException("Unable to clone git repo '%s' "
                                "branch '%s'" % (git_uri, git_branch),
                                cause=ex,
                                traceback=sys.exc_info()[2])

        # Find the specific ref we want
        try:
            run_command(['git', 'reset', '--hard'], cwd=repo_path)
            run_command(['git', 'checkout', git_ref], cwd=repo_path)
        except OsbsException as ex:
            raise OsbsException("Unable to reset branch to '%s'" % git_ref,
                                cause=ex,
                                traceback=sys.exc_info()[2])

        yield repo_path

    finally:
        shutil.rmtree(tmpdir)
示例#2
0
    def _check_repo_file_exists_with_expected_filename(self, expected_filename,
                                                       possible_filename_typos):
        """
        Checks if a file with given filename exists in repo

        :param str expected_filename: Expected filename to lookup in the repo
        :param set possible_filename_typos: Set of possible typos for expected_filename
        :return: boolean stating wheter expected_filename exists in repo
        :rtype bool
        :raises OsbsException: if any filename from possible_filename_typos exists in repo
        """
        expected_file_path = os.path.join(self.dir_path, expected_filename)

        wrong_filename = ''
        for possible_filename_typo in possible_filename_typos:
            path = os.path.join(self.dir_path, possible_filename_typo)
            if os.path.exists(path):
                wrong_filename = possible_filename_typo
                break

        if os.path.exists(expected_file_path) and wrong_filename:
            msg = ('This repo contains both {expected_filename} and {wrong_filename} '
                   'Please remove {wrong_filename}'
                   .format(expected_filename=expected_filename,
                           wrong_filename=wrong_filename))
            raise OsbsException(msg)
        elif wrong_filename:
            msg = ('Repo contains wrong filename: {wrong_filename}, expected: {expected_filename}'
                   .format(expected_filename=expected_filename, wrong_filename=wrong_filename))
            raise OsbsException(msg)
        elif os.path.exists(expected_file_path):
            return True

        return False
示例#3
0
    def start_pipeline_run(self):
        if not self.input_data:
            raise OsbsException(
                "No input data provided for pipeline run to start")

        run_name = self.input_data.get('metadata', {}).get('name')
        labels = self.input_data.get('metadata', {}).get('labels', {})

        if labels:
            sanitized_labels = {
                k: sanitize_strings_for_openshift(v)
                for k, v in labels.items()
            }
            self.input_data['metadata']['labels'] = sanitized_labels

        if run_name != self.pipeline_run_name:
            msg = f"Pipeline run name provided '{self.pipeline_run_name}' is different " \
                  f"than in input data '{run_name}'"
            raise OsbsException(msg)

        url = self.os.build_url(self.api_path, self.api_version,
                                "pipelineruns")
        response = self.os.post(
            url,
            data=json.dumps(self.input_data),
            headers={
                "Content-Type": "application/json",
                "Accept": "application/json"
            },
        )
        return response.json()
示例#4
0
    def get_build_config_by_labels_filtered(self, label_selectors, filter_key,
                                            filter_value):
        """
        Returns a build config matching the given label selectors, filtering against
        another predetermined value. This method will raise OsbsException
        if not exactly one build config is found after filtering.
        """
        items = self.get_all_build_configs_by_labels(label_selectors)

        if filter_value is not None:
            build_configs = []
            for build_config in items:
                match_value = graceful_chain_get(build_config,
                                                 *filter_key.split('.'))
                if filter_value == match_value:
                    build_configs.append(build_config)
            items = build_configs

        if not items:
            raise OsbsException("Build config not found for labels: %r" %
                                (label_selectors, ))
        if len(items) > 1:
            raise OsbsException(
                "More than one build config found for labels: %r" %
                (label_selectors, ))
        return items[0]
示例#5
0
    def _checks_for_flatpak(self, flatpak, repo_info):
        if flatpak and not repo_info.configuration.is_flatpak:
            raise OsbsException(
                "Flatpak build, "
                "but repository doesn't have a container.yaml with a flatpak: section"
            )

        if not flatpak and repo_info.configuration.is_flatpak:
            raise OsbsException(
                "Not a flatpak build, "
                "but repository has a container.yaml with a flatpak: section")
def test_orchestrate_build_failed_to_list_builds(tmpdir, fail_at):
    workflow = mock_workflow(tmpdir)
    mock_osbs()  # Current builds is a constant 2

    mock_reactor_config(
        tmpdir, {
            'x86_64': [{
                'name': 'spam',
                'max_concurrent_builds': 5
            }, {
                'name': 'eggs',
                'max_concurrent_builds': 5
            }],
        })

    flexmock_chain = flexmock(OSBS).should_receive('list_builds').and_raise(
        OsbsException("foo"))

    if fail_at == 'all':
        flexmock_chain.and_raise(OsbsException("foo"))

    if fail_at == 'first':
        flexmock_chain.and_return(['a', 'b'])

    if fail_at == 'build_canceled':
        flexmock_chain.and_raise(OsbsException(cause=BuildCanceledException()))

    runner = BuildStepPluginsRunner(
        workflow.builder.tasker, workflow, [{
            'name': OrchestrateBuildPlugin.key,
            'args': {
                'platforms': ['x86_64'],
                'build_kwargs': make_worker_build_kwargs(),
                'osbs_client_config': str(tmpdir),
                'find_cluster_retry_delay': .1,
                'max_cluster_fails': 2
            }
        }])
    if fail_at == 'first':
        build_result = runner.run()
        assert not build_result.is_failed()

        annotations = build_result.annotations
        assert annotations['worker-builds']['x86_64']['build'][
            'cluster-url'] == 'https://eggs.com/'
    else:
        build_result = runner.run()
        assert build_result.is_failed()
        if fail_at == 'all':
            assert 'Could not find appropriate cluster for worker build.' \
                in build_result.fail_reason
        elif fail_at == 'build_canceled':
            assert 'BuildCanceledException()' in str(exc)
示例#7
0
 def get_pod_for_build(self, build_id):
     """
     :return: PodResponse object for pod relating to the build
     """
     pods = self.os.list_pods(label='openshift.io/build.name=%s' % build_id)
     serialized_response = pods.json()
     pod_list = [PodResponse(pod) for pod in serialized_response["items"]]
     if not pod_list:
         raise OsbsException("No pod for build")
     elif len(pod_list) != 1:
         raise OsbsException("Only one pod expected but %d returned",
                             len(pod_list))
     return pod_list[0]
示例#8
0
def reset_git_repo(target_dir, git_reference, retry_depth=None):
    """
    hard reset git clone in target_dir to given git_reference

    :param target_dir: str, filesystem path where the repo is cloned
    :param git_reference: str, any valid git reference
    :param retry_depth: int, if the repo was cloned with --shallow, this is the expected
                        depth of the commit
    :return: str and int, commit ID of HEAD and commit depth of git_reference
    """
    deepen = retry_depth or 0
    base_commit_depth = 0
    for _ in range(GIT_FETCH_RETRY):
        try:
            if not deepen:
                cmd = ['git', 'rev-list', '--count', git_reference]
                base_commit_depth = int(
                    subprocess.check_output(cmd, cwd=target_dir)) - 1
            cmd = ["git", "reset", "--hard", git_reference]
            logger.debug("Resetting current HEAD: '%s'", cmd)
            subprocess.check_call(cmd, cwd=target_dir)
            break
        except subprocess.CalledProcessError:
            if not deepen:
                raise OsbsException('cannot find commit %s in repo %s' %
                                    (git_reference, target_dir))
            deepen *= 2
            cmd = ["git", "fetch", "--depth", str(deepen)]
            subprocess.check_call(cmd, cwd=target_dir)
            logger.debug("Couldn't find commit %s, increasing depth with '%s'",
                         git_reference, cmd)
    else:
        raise OsbsException('cannot find commit %s in repo %s' %
                            (git_reference, target_dir))

    cmd = ["git", "rev-parse", "HEAD"]
    logger.debug("getting SHA-1 of provided ref '%s'", git_reference)
    commit_id = subprocess.check_output(cmd,
                                        cwd=target_dir,
                                        universal_newlines=True)
    commit_id = commit_id.strip()
    logger.info("commit ID = %s", commit_id)

    final_commit_depth = None
    if not deepen:
        cmd = ['git', 'rev-list', '--count', 'HEAD']
        final_commit_depth = int(subprocess.check_output(
            cmd, cwd=target_dir)) - base_commit_depth

    return commit_id, final_commit_depth
示例#9
0
    def request(self, url, *args, **kwargs):
        try:
            stream = HttpStream(url, *args, verbose=self.verbose, **kwargs)
            if kwargs.get('stream', False):
                return stream

            with stream as s:
                # joining at once is much faster than doing += in a loop
                all_chunks = list(s.iter_chunks())
                content = ''.join(all_chunks)
                return HttpResponse(s.status_code, s.headers, content)
        except pycurl.error as ex:
            code = ex.args[0]
            try:
                message = ex.args[1]
            except IndexError:
                # happened on rhel 6
                message = ""
            if code in PYCURL_NETWORK_CODES:
                raise OsbsNetworkException(url,
                                           message,
                                           code,
                                           *ex.args[2:],
                                           cause=ex,
                                           traceback=sys.exc_info()[2])

            raise OsbsException(cause=ex, traceback=sys.exc_info()[2])
示例#10
0
    def update_labels(self, labels):
        data = copy.deepcopy(self.minimal_data)

        sanitized_labels = {
            k: sanitize_strings_for_openshift(v)
            for k, v in labels.items()
        }
        data['metadata']['labels'] = sanitized_labels

        response = self.os.patch(
            self.pipeline_run_url,
            data=json.dumps(data),
            headers={
                "Content-Type": "application/merge-patch+json",
                "Accept": "application/json",
            },
        )

        msg = f"update labels on pipeline run '{self.pipeline_run_name}'"
        exc_msg = f"Can't update labels on pipeline run '{self.pipeline_run_name}', " \
                  f"because it doesn't exist"
        response_json = self._check_response(response, msg)
        if not response_json:
            raise OsbsException(exc_msg)
        return response_json
示例#11
0
    def create_build(self, **kwargs):
        """
        take input args, create build request from provided build type and submit the build

        :param kwargs: keyword args for build
        :return: instance of BuildRequest
        """
        build_type = self.build_conf.get_build_type()
        if build_type in (PROD_BUILD_TYPE,
                          PROD_WITHOUT_KOJI_BUILD_TYPE,
                          PROD_WITH_SECRET_BUILD_TYPE):
            kwargs.setdefault('git_branch', None)
            kwargs.setdefault('target', None)
            return self.create_prod_build(**kwargs)
        elif build_type == SIMPLE_BUILD_TYPE:
            # Only Prod Build type cares about potential koji scratch builds
            try:
                kwargs.pop("scratch")
            except KeyError:
                pass
            return self.create_simple_build(**kwargs)
        elif build_type == PROD_WITH_SECRET_BUILD_TYPE:
            return self.create_prod_with_secret_build(**kwargs)
        else:
            raise OsbsException("Unknown build type: '%s'" % build_type)
示例#12
0
def test_orchestrate_build_failed_waiting(tmpdir, pod_available,
                                          pod_failure_reason, cancel_fails,
                                          expected):
    workflow = mock_workflow(tmpdir)
    mock_osbs()

    class MockPodResponse(object):
        def __init__(self, pod_failure_reason):
            self.pod_failure_reason = pod_failure_reason

        def get_failure_reason(self):
            if isinstance(self.pod_failure_reason, Exception):
                raise self.pod_failure_reason

            return self.pod_failure_reason

    def mock_wait_for_build_to_finish(build_name):
        if build_name == 'worker-build-ppc64le':
            raise OsbsException('it happens')
        return make_build_response(build_name, 'Failed')

    (flexmock(OSBS).should_receive('wait_for_build_to_finish').replace_with(
        mock_wait_for_build_to_finish))

    cancel_build_expectation = flexmock(OSBS).should_receive('cancel_build')
    if cancel_fails:
        cancel_build_expectation.and_raise(OsbsException)

    cancel_build_expectation.once()

    expectation = flexmock(OSBS).should_receive('get_pod_for_build')
    if pod_available:
        expectation.and_return(MockPodResponse(pod_failure_reason))
    else:
        expectation.and_raise(OsbsException())

    mock_reactor_config(tmpdir)

    runner = BuildStepPluginsRunner(
        workflow.builder.tasker, workflow, [{
            'name': OrchestrateBuildPlugin.key,
            'args': {
                'platforms': ['x86_64', 'ppc64le'],
                'build_kwargs': make_worker_build_kwargs(),
                'osbs_client_config': str(tmpdir),
            }
        }])

    build_result = runner.run()
    assert build_result.is_failed()

    annotations = build_result.annotations
    assert set(annotations['worker-builds'].keys()) == {'x86_64', 'ppc64le'}
    fail_reason = json.loads(build_result.fail_reason)['ppc64le']

    if expected is KeyError:
        assert 'pod' not in fail_reason
    else:
        assert fail_reason['pod'] == expected
示例#13
0
    def get_build_config_by_labels(self, label_selectors):
        """
        Returns a build config matching the given label
        selectors. This method will raise OsbsException
        if not exactly one build config is found.
        """
        items = self.get_all_build_configs_by_labels(label_selectors)

        if not items:
            raise OsbsException("Build config not found for labels: %r" %
                                (label_selectors, ))
        if len(items) > 1:
            raise OsbsException(
                "More than one build config found for labels: %r" %
                (label_selectors, ))

        return items[0]
示例#14
0
 def _select(self):
     sel = self.curl_multi.select(SELECT_TIMEOUT)
     if sel == -1:
         raise OsbsException("CurlMulti.select() timed out")
     elif sel == 0:
         # sel==0 means curl_multi_fdset returned -1
         # manual page suggests sleeping >100ms when this happens:(
         time.sleep(0.1)
示例#15
0
def clone_git_repo(git_url,
                   target_dir=None,
                   commit=None,
                   retry_times=GIT_MAX_RETRIES,
                   branch=None,
                   depth=None):
    """
    clone provided git repo to target_dir, optionally checkout provided commit

    :param git_url: str, git repo to clone
    :param target_dir: str, filesystem path where the repo should be cloned
    :param commit: str, commit to checkout, SHA-1 or ref
    :param retry_times: int, number of retries for git clone
    :param branch: str, optional branch of the commit, required if depth is provided
    :param depth: int, optional expected depth
    :return: str, int, commit ID of HEAD
    """
    retry_delay = GIT_BACKOFF_FACTOR
    target_dir = target_dir or os.path.join(tempfile.mkdtemp(), "repo")
    commit = commit or "master"
    logger.info("cloning git repo '%s'", git_url)
    logger.debug("url = '%s', dir = '%s', commit = '%s'", git_url, target_dir,
                 commit)

    cmd = ["git", "clone"]
    if branch:
        cmd += ["-b", branch, "--single-branch"]
        if depth:
            cmd += ["--depth", str(depth)]
    elif depth:
        logger.warning("branch not provided for %s, depth setting ignored",
                       git_url)
        depth = None

    cmd += [git_url, target_dir]

    logger.debug("cloning '%s'", cmd)
    repo_commit = ''
    repo_depth = None
    for counter in range(retry_times + 1):
        try:
            # we are using check_output, even though we aren't using
            # the return value, but we will get 'output' in exception
            subprocess.check_output(cmd, stderr=subprocess.STDOUT)
            repo_commit, repo_depth = reset_git_repo(target_dir, commit, depth)
            break
        except subprocess.CalledProcessError as exc:
            if counter != retry_times:
                logger.info("retrying command '%s':\n '%s'", cmd, exc.output)
                time.sleep(retry_delay * (2**counter))
            else:
                raise OsbsException("Unable to clone git repo '%s' "
                                    "branch '%s'" % (git_url, branch),
                                    cause=exc,
                                    traceback=sys.exc_info()[2])

    return ClonedRepoData(target_dir, repo_commit, repo_depth)
示例#16
0
 def wait_for_build_to_get_scheduled(self, build_id):
     for _ in range(WAIT_RETRY):
         try:
             build_response = self.wait(build_id, BUILD_FINISHED_STATES + BUILD_RUNNING_STATES)
             return build_response
         except OsbsWatchBuildNotFound:
             continue
     raise OsbsException('Failed to schedule a build in {} attempts: {}'.format(WAIT_RETRY,
                                                                                build_id))
示例#17
0
 def _validate_container_config_file(self):
     try:
         container_config_path = os.path.join(self.dir_path, REPO_CONTAINER_CONFIG)
         self.container = read_yaml_from_file_path(container_config_path,
                                                   'schemas/container.json') or {}
     except Exception as e:
         msg = ('Failed to load or validate container file "{file}": {reason}'
                .format(file=container_config_path, reason=e))
         raise OsbsException(msg)
示例#18
0
    def import_image(self, name):
        """
        Import image tags from a Docker registry into an ImageStream

        :return: bool, whether new tags were imported
        """

        # Get the JSON for the ImageStream
        url = self._build_url("imagestreams/%s" % name)
        imagestream_json = self._get(url).json()
        logger.debug("imagestream: %r", imagestream_json)
        spec = imagestream_json.get('spec', {})
        if 'dockerImageRepository' not in spec:
            raise OsbsException('No dockerImageRepository for image import')

        # Note the tags before import
        oldtags = imagestream_json.get('status', {}).get('tags', [])
        logger.debug("tags before import: %r", oldtags)

        # Mark it as needing import
        imagestream_json['metadata'].setdefault('annotations', {})
        check_annotation = "openshift.io/image.dockerRepositoryCheck"
        imagestream_json['metadata']['annotations'][check_annotation] = ''
        response = self._put(url,
                             data=json.dumps(imagestream_json),
                             use_json=True)
        check_response(response)

        # Watch for it to be updated
        resource_version = imagestream_json['metadata']['resourceVersion']
        for changetype, obj in self.watch_resource(
                "imagestreams", name, resourceVersion=resource_version):
            logger.info("Change type: %r", changetype)
            if changetype == WATCH_DELETED:
                logger.info("Watched ImageStream was deleted")
                break

            if changetype == WATCH_ERROR:
                logger.error("Error watching ImageStream")
                break

            if changetype == WATCH_MODIFIED:
                logger.info("ImageStream modified")
                metadata = obj.get('metadata', {})
                annotations = metadata.get('annotations', {})
                logger.info("ImageStream annotations: %r", annotations)
                if annotations.get(check_annotation, False):
                    logger.info("ImageStream updated")

                    # Find out if there are new tags
                    status = obj.get('status', {})
                    newtags = status.get('tags', [])
                    logger.debug("tags after import: %r", newtags)
                    return newtags != oldtags

        return False
示例#19
0
 def wait_for_build_to_finish(self, build_id):
     for retry in range(1, 10):
         try:
             build_response = self.wait(build_id, BUILD_FINISHED_STATES)
             return build_response
         except OsbsWatchBuildNotFound:
             # this is woraround for https://github.com/openshift/origin/issues/2348
             logger.error("I'm going to wait again. Retry #%d.", retry)
             continue
     raise OsbsException("Failed to wait for a build: %s" % build_id)
示例#20
0
    def __init__(self,
                 dir_path='',
                 file_name=REPO_CONFIG_FILE,
                 depth=None,
                 git_uri=None,
                 git_branch=None,
                 git_ref=None):
        self._config_parser = ConfigParser()
        self.container = {}
        self.depth = depth or 0
        self.autorebuild = {}
        # Keep track of the repo metadata in the repo configuration
        self.git_uri = git_uri
        self.git_branch = git_branch
        self.git_ref = git_ref

        # Set default options
        self._config_parser.readfp(StringIO(self.DEFAULT_CONFIG))  # pylint: disable=W1505; py2

        config_path = os.path.join(dir_path, file_name)
        if os.path.exists(config_path):
            self._config_parser.read(config_path)

        file_path = os.path.join(dir_path, REPO_CONTAINER_CONFIG)
        if os.path.exists(file_path):
            try:
                self.container = read_yaml_from_file_path(
                    file_path, 'schemas/container.json') or {}
            except Exception as e:
                msg = (
                    'Failed to load or validate container file "{file}": {reason}'
                    .format(file=file_path, reason=e))
                raise OsbsException(msg)

        # container values may be set to None
        container_compose = self.container.get('compose') or {}
        modules = container_compose.get('modules') or []

        self.autorebuild = self.container.get('autorebuild') or {}

        self.container_module_specs = []
        value_errors = []
        for module in modules:
            try:
                self.container_module_specs.append(ModuleSpec.from_str(module))
            except ValueError as e:
                value_errors.append(e)
        if value_errors:
            raise ValueError(value_errors)

        flatpak = self.container.get('flatpak') or {}
        self.is_flatpak = bool(flatpak)
        self.flatpak_base_image = flatpak.get('base_image')
        self.flatpak_component = flatpak.get('component')
        self.flatpak_name = flatpak.get('name')
示例#21
0
    def get_build_config_by_labels(self, label_selectors):
        """
        Returns a build config matching the given label
        selectors. This method will raise OsbsException
        if not exactly one build config is found.
        """
        labels = ['%s=%s' % (field, value) for field, value in label_selectors]
        labels = ','.join(labels)
        url = self._build_url("buildconfigs/", labelSelector=labels)
        items = self._get(url).json()['items']

        if not items:
            raise OsbsException("Build config not found for labels: %r" %
                                (label_selectors, ))
        if len(items) > 1:
            raise OsbsException(
                "More than one build config found for labels: %r" %
                (label_selectors, ))

        return items[0]
示例#22
0
 def template(self):
     if self._template is None:
         path = os.path.join(self.build_json_store, DEFAULT_OUTER_TEMPLATE)
         logger.debug("loading template from path %s", path)
         try:
             with open(path, "r") as fp:
                 self._template = json.load(fp)
         except (IOError, OSError) as ex:
             raise OsbsException("Can't open template '%s': %s" %
                                 (path, repr(ex)))
     return self._template
示例#23
0
 def template(self):
     if self._template is None:
         path = os.path.join(self.user_params.build_json_dir,
                             self._outer_template_path)
         logger.debug("loading template from path %s", path)
         try:
             with open(path, "r") as fp:
                 self._template = json.load(fp)
         except (IOError, OSError) as ex:
             raise OsbsException("Can't open template '%s': %s" %
                                 (path, repr(ex)))
     return self._template
示例#24
0
    def _verify_no_running_builds(self, build_config_name):
        running_builds = self._get_running_builds_for_build_config(build_config_name)
        rb_len = len(running_builds)

        if rb_len > 0:
            if rb_len == 1:
                rb = running_builds[0]
                msg = "Build %s for %s in state %s, can't proceed." % \
                    (rb.get_build_name(), build_config_name, rb.status)
            else:
                msg = self._panic_msg_for_more_running_builds(build_config_name, running_builds)
            raise OsbsException(msg)
示例#25
0
    def _create_build_config_and_build(self, build_request):
        # TODO: test this method more thoroughly
        build_json = build_request.render()
        api_version = build_json['apiVersion']
        if api_version != self.os_conf.get_openshift_api_version():
            raise OsbsValidationException("BuildConfig template has incorrect apiVersion (%s)" %
                                          api_version)

        build_config_name = build_json['metadata']['name']

        # check if a build already exists for this config; if so then raise
        running_builds = self._get_running_builds_for_build_config(build_config_name)
        rb_len = len(running_builds)
        if rb_len > 0:
            if rb_len == 1:
                rb = running_builds[0]
                msg = 'Build %s for %s in state %s, can\'t proceed.' % \
                    (rb.get_build_name(), build_config_name, rb.status)
            else:
                msg = self._panic_msg_for_more_running_builds(build_config_name, running_builds)
            raise OsbsException(msg)

        try:
            # see if there's already a build config
            existing_bc = self.os.get_build_config(build_config_name)
        except OsbsException:
            # doesn't exist
            existing_bc = None

        build = None
        if existing_bc is not None:
            utils.buildconfig_update(existing_bc, build_json)
            logger.debug('build config for %s already exists, updating...', build_config_name)
            self.os.update_build_config(build_config_name, json.dumps(existing_bc))
        else:
            # if it doesn't exist, then create it
            logger.debug('build config for %s doesn\'t exist, creating...', build_config_name)
            bc = self.os.create_build_config(json.dumps(build_json)).json()
            # if there's an "ImageChangeTrigger" on the BuildConfig and "From" is of type
            #  "ImageStreamTag", the build will be scheduled automatically
            #  see https://github.com/projectatomic/osbs-client/issues/205
            if build_request.is_auto_instantiated():
                prev_version = bc['status']['lastVersion']
                build_id = self.os.wait_for_new_build_config_instance(build_config_name,
                                                                      prev_version)
                build = BuildResponse(self.os.get_build(build_id).json())

        if build is None:
            response = self.os.start_build(build_config_name)
            build = BuildResponse(response.json())
        return build
示例#26
0
    def start_pipeline_run(self):
        if not self.input_data:
            raise OsbsException(
                "No input data provided for pipeline run to start")

        run_name = self.input_data.get('metadata', {}).get('name')

        if run_name != self.pipeline_run_name:
            msg = f"Pipeline run name provided '{self.pipeline_run_name}' is different " \
                  f"than in input data '{run_name}'"
            raise OsbsException(msg)

        url = self.os.build_url(self.api_path, self.api_version,
                                "pipelineruns")
        response = self.os.post(
            url,
            data=json.dumps(self.input_data),
            headers={
                "Content-Type": "application/json",
                "Accept": "application/json"
            },
        )
        return response.json()
示例#27
0
    def catch_exceptions(*args, **kwargs):
        # XXX: remove this in the future
        if kwargs.pop("namespace", None):
            warnings.warn("OSBS.%s: the 'namespace' argument is no longer supported" % func.__name__)
        try:
            return func(*args, **kwargs)
        except OsbsException:
            # Re-raise OsbsExceptions
            raise
        except Exception as ex:
            # Convert anything else to OsbsException

            # Python 3 has implicit exception chaining and enhanced
            # reporting, so you get the original traceback as well as
            # the one originating here.
            # For Python 2, let's do that explicitly.
            raise OsbsException(cause=ex, traceback=sys.exc_info()[2])
示例#28
0
def kerberos_ccache_init(principal, keytab_file, ccache_file=None):
    """
    Checks whether kerberos credential cache has ticket-granting ticket that is valid for at least
    an hour.

    Default ccache is used unless ccache_file is provided. In that case, KRB5CCNAME environment
    variable is set to the value of ccache_file if we successfully obtain the ticket.
    """
    tgt_valid = False
    env = {"LC_ALL": "C"}  # klist uses locales to format date on RHEL7+
    if ccache_file:
        env["KRB5CCNAME"] = ccache_file

    # check if we have tgt that is valid more than one hour
    rc, klist, _ = run(["klist"], extraenv=env)
    if rc == 0:
        for line in klist.splitlines():
            m = re.match(KLIST_TGT_RE, line)
            if m:
                year = m.group("year")
                if len(year) == 2:
                    year = "20" + year

                expires = datetime.datetime(int(year), int(m.group("month")),
                                            int(m.group("day")),
                                            int(m.group("hour")),
                                            int(m.group("minute")),
                                            int(m.group("second")))

                if expires - datetime.datetime.now() > datetime.timedelta(
                        hours=1):
                    logger.debug("Valid TGT found, not renewing")
                    tgt_valid = True
                    break

    if not tgt_valid:
        logger.debug("Retrieving kerberos TGT")
        rc, out, err = run(["kinit", "-k", "-t", keytab_file, principal],
                           extraenv=env)
        if rc != 0:
            raise OsbsException("kinit returned %s:\nstdout: %s\nstderr: %s" %
                                (rc, out, err))

    if ccache_file:
        os.environ["KRB5CCNAME"] = ccache_file
示例#29
0
def run_command(*popenargs, **kwargs):
    """
    Run command with arguments and return its output as a byte string.

    This is originally taken from subprocess.py of python 2.7
    """
    process = subprocess.Popen(stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
                               *popenargs, **kwargs)
    output, _ = process.communicate()
    retcode = process.poll()
    if retcode:
        cmd = kwargs.get("args")
        if cmd is None:
            cmd = popenargs[0]
        raise OsbsException(
            message="Command %s returned %s\n\n%s" % (cmd, retcode, output)
        )
    return output
示例#30
0
    def request(self, url, *args, **kwargs):
        try:
            stream = HttpStream(url, *args, verbose=self.verbose, **kwargs)
            if kwargs.get('stream', False):
                return stream

            with stream as s:
                content = s.req.content
                return HttpResponse(s.status_code, s.headers, content)
        # Timeout will catch both ConnectTimout and ReadTimeout
        except (RetryError, Timeout) as ex:
            raise OsbsNetworkException(url, str(ex), '',
                                       cause=ex, traceback=sys.exc_info()[2])
        except HTTPError as ex:
            raise OsbsNetworkException(url, str(ex), ex.response.status_code,
                                       cause=ex, traceback=sys.exc_info()[2])
        except Exception as ex:
            raise OsbsException(cause=ex, traceback=sys.exc_info()[2])