#5 support for `copr-cli mock-config USER/PROJECT CHROOT`
Merged 7 years ago by clime. Opened 7 years ago by praiskup.
Unknown source praiskup-mock-profiles  into  master

@@ -150,6 +150,22 @@

          rlRun "copr-cli create --chroot fedora-24-x86_64 ${NAME_PREFIX}ProjectDistGitBuilds"

          rlRun "copr-cli buildfedpkg --clone-url http://pkgs.fedoraproject.org/git/rpms/389-admin-console.git --branch f24 ${NAME_PREFIX}ProjectDistGitBuilds"

  

+ 

+         ## test mock-config feature

+         mc_project=${NAME_PREFIX}MockConfig

+         mc_parent_project=${mc_project}Parent

+         mc_output=`mktemp`

+         mc_chroot=fedora-rawhide-x86_64

+ 

+         rlRun "copr-cli create --chroot $mc_chroot $mc_parent_project"

+         create_opts="--repo copr://$mc_parent_project"

+         rlRun "copr-cli create --chroot $mc_chroot $create_opts $mc_project"

+         rlRun "copr-cli mock-config $mc_project $mc_chroot > $mc_output"

+         rlRun "grep results/$mc_parent_project $mc_output"

+         # Non-existent project/chroot.

+         rlRun "copr-cli mock-config notexistent/notexistent $mc_chroot" 1

+         rlRun "copr-cli mock-config $mc_project fedora-14-x86_64" 1

+ 

          ## test background builds

  

          # non-background build should be imported first

@@ -0,0 +1,45 @@

+ # coding: utf-8

+ 

+ from jinja2 import Environment

+ 

+ template_string = """\

+ # This is development/testing only mock profile, not exactly the same as

+ # is used on copr builders;  but it is basically similar.  If you need an

+ # exact mock configuration (because you e.g. try to reproduce failed

+ # build), such configuration is put alongside the built RPMs.

+ 

+ include('/etc/mock/{{chroot}}.cfg')

+ 

+ config_opts['root'] = '{{project_id}}_{{chroot}}'

+ config_opts['chroot_additional_packages'] = '

+ {%- for pkg in additional_packages -%}

+ {%- if loop.last -%}

+ {{ pkg }}

+ {%- else -%}

+ {{ pkg }} {% endif -%}

+ {%- endfor -%}'

+ 

+ {% if repos %}

+ config_opts['yum.conf'] += \"\"\"

+ {% for repo in repos %}

+ [{{ repo.id }}]

+ name="{{ repo.name }}"

+ baseurl={{ repo.url }}

+ skip_if_unavailable=False

+ gpgcheck=0

+ enabled=1

+ {% endfor %}

+ \"\"\"

+ {% endif %}

+ """

+ 

+ class MockProfile(object):

+     def __init__(self, data):

+         self.data = data

+ 

+     def __str__(self):

+         template = Environment().from_string(template_string)

+         return template.render(self.data)

+ 

+ 

+ 

file modified
+36
@@ -32,6 +32,7 @@

  import copr.exceptions as copr_exceptions

  

  from .util import ProgressBar

+ from .build_config import MockProfile

  

  

  no_config_warning = """
@@ -321,6 +322,27 @@

          result = self.client.fork_project(source=args.src, username=username, projectname=copr, confirm=args.confirm)

          print(result.message)

  

+ 

+     def action_mock_config(self, args):

+         """ Method called when the 'list' action has been selected by the

+         user.

+ 

+         :param args: argparse arguments provided by the user

+ 

+         """

+         username = self.client.username

+         project = args.project.split("/")

+         if len(project) != 2:

+             args.project = username + "/" + args.project

+ 

+         result = self.client.get_build_config(args.project, args.chroot)

+         if result.output != "ok":

+             print(result.error)

+             print("Un-expected data returned, please report this issue")

+ 

+         print(MockProfile(result.build_config))

+ 

+ 

      @check_username_presence

      def action_list(self, args):

          """ Method called when the 'list' action has been selected by the
@@ -541,6 +563,20 @@

      )

      parser_list.set_defaults(func="action_list")

  

+     parser_mock_config = subparsers.add_parser(

+         "mock-config",

+         help="Get the mock profile (similar to koji mock-config)"

+     )

+     parser_mock_config.add_argument(

+         "project",

+         help="Expected format is <user>/<project>, <group>/<project> (including '@') or <project> (name of project you own)."

+     )

+     parser_mock_config.add_argument(

+         "chroot",

+         help="chroot id, e.g. 'fedora-rawhide-x86_64'"

+     )

+     parser_mock_config.set_defaults(func="action_mock_config")

+ 

      # create the parser for the "create" command

      parser_create = subparsers.add_parser("create", help="Create a new copr")

      parser_create.add_argument("name",

@@ -84,6 +84,9 @@

  build-package::

  Build package from its source definition

  

+ mock-config::

+ Get the mock profile (similar to koji mock-config)

+ 

  

  PROJECT ACTIONS

  ---------------
@@ -534,6 +537,15 @@

  

  For the rest of the arguments, see `copr-cli build` command above.

  

+ `copr-cli mock-config [options]`

+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

+ usage: copr mock-config [-h] project chroot

+ 

+ Get the mock profile (similar to koji mock-config), print it to standard

+ output.  The configuration can be slightly different from the real mock

+ configuration used by Copr Builders, but should be similar enough for basic

+ debugging (e.g. by mock --shell).

+ 

  

  EXAMPLES

  --------
@@ -545,6 +557,8 @@

  

    copr-cli delete-package myproject --name pkgname

  

+   copr-cli mock-config myproject fedora-rawhide-x86_64

+ 

  

  EXIT STATUS

  -----------

@@ -3,7 +3,10 @@

  import string

  

  from six import with_metaclass

- from six.moves.urllib.parse import urljoin

+ from six.moves.urllib.parse import urljoin, urlparse

+ import pipes

+ from textwrap import dedent

+ import re

  

  import flask

  from flask import url_for
@@ -548,3 +551,62 @@

      rv = t.stream(context)

      rv.enable_buffering(2)

      return rv

+ 

+ 

+ def generate_repo_name(repo_url):

+     """ based on url, generate repo name """

+     repo_url = re.sub("[^a-zA-Z0-9]", '_', repo_url)

+     repo_url = re.sub("(__*)", '_', repo_url)

+     repo_url = re.sub("(_*$)|^_*", '', repo_url)

+     return repo_url

+ 

+ 

+ def pre_process_repo_url(chroot, repo_url):

+     """

+     Expands variables and sanitize repo url to be used for mock config

+     """

+     parsed_url = urlparse(repo_url)

+     if parsed_url.scheme == "copr":

+         user = parsed_url.netloc

+         prj = parsed_url.path.split("/")[1]

+         repo_url = "/".join([

+             flask.current_app.config["BACKEND_BASE_URL"],

+             "results", user, prj, chroot

+         ]) + "/"

+ 

+     repo_url = repo_url.replace("$chroot", chroot)

+     repo_url = repo_url.replace("$distname", chroot.split("-")[0])

+ 

+     return pipes.quote(repo_url)

+ 

+ 

+ def generate_build_config(copr, chroot_id):

+     """ Return dict with proper build config contents """

+     chroot = None

+     for i in copr.copr_chroots:

+         if i.mock_chroot.name == chroot_id:

+             chroot = i

+     if not chroot:

+         return ""

+ 

+     packages = "" if not chroot.buildroot_pkgs else chroot.buildroot_pkgs

+ 

+     repos = [{

+         "id": "copr_base",

+         "url": copr.repo_url + "/{}/".format(chroot_id),

+         "name": "Copr repository",

+     }]

+     for repo in copr.repos_list:

+         repo_view = {

+             "id": generate_repo_name(repo),

+             "url": pre_process_repo_url(chroot_id, repo),

+             "name": "Additional repo " + generate_repo_name(repo),

+         }

+         repos.append(repo_view)

+ 

+     return {

+         'project_id': copr.repo_id,

+         'additional_packages': packages.split(),

+         'repos': repos,

+         'chroot': chroot_id,

+     }

@@ -41,7 +41,7 @@

          <tr>

            <th>Release</th>

            <th>Architectures</th>

-           <th>Repo Download </th>

+           <th>Repo Download</th>

          </tr>

        </thead>

        <tbody>

@@ -13,7 +13,7 @@

  from coprs import forms

  from coprs import helpers

  from coprs import models

- from coprs.helpers import fix_protocol_for_backend

+ from coprs.helpers import fix_protocol_for_backend, generate_build_config

  from coprs.logic.api_logic import MonitorWrapper

  from coprs.logic.builds_logic import BuildsLogic

  from coprs.logic.complex_logic import ComplexLogic
@@ -884,3 +884,21 @@

  

      except sqlalchemy.exc.IntegrityError:

          raise LegacyApiError({"nvr": ["Module {} already exists".format(module.nvr)]})

+ 

+ 

+ @api_ns.route("/coprs/<username>/<coprname>/build-config/<chroot>/", methods=["GET"])

+ @api_ns.route("/g/<group_name>/<coprname>/build-config/<chroot>/", methods=["GET"])

+ @api_req_with_copr

+ def copr_build_config(copr, chroot):

+     """

+     Generate build configuration.

+     """

+     output = {

+         "output": "ok",

+         "build_config": generate_build_config(copr, chroot),

+     }

+ 

+     if not output['build_config']:

+         raise LegacyApiError('Chroot not found.')

+ 

+     return flask.jsonify(output)

file modified
+28 -1
@@ -44,7 +44,8 @@

  

  from .parsers import fabric_simple_fields_parser, ProjectListParser, \

      CommonMsgErrorOutParser, NewBuildListParser, ProjectChrootsParser, \

-     ProjectDetailsFieldsParser, PackageListParser, PackageParser

+     ProjectDetailsFieldsParser, PackageListParser, PackageParser, \

+     BuildConfigParser

  

  from ..util import UnicodeMixin

  
@@ -1317,3 +1318,29 @@

          )

          response.handle = BaseHandle(client=self, response=response)

          return response

+ 

+     def get_build_config(self, project, chroot):

+         """

+         Return build configuration for given project/chroot.

+         :param project: project name, e.g. USER/PROJ, or @GROUP/PROJ.

+         :param chroot: chroot name, e.g. fedora-rawhide-x86_64

+         :return: :py:class:`~.responses.CoprResponse`

+             with additional fields:

+             - **build_config**: generated build config contents (dict)

+         """

+         url = "{0}/coprs/{1}/build-config/{2}".format(

+             self.api_url,

+             project,

+             chroot,

+         )

+         data = self._fetch(url, skip_auth=True)

+         response = CoprResponse(

+             client=self,

+             method="get_build_config",

+             data=data,

+             parsers=[

+                 CommonMsgErrorOutParser,

+                 BuildConfigParser,

+             ]

+         )

+         return response

@@ -46,6 +46,10 @@

      ["output", "message", "error"], "CommonMsgErrorOutParser"

  )

  

+ BuildConfigParser = fabric_simple_fields_parser(

+     ["build_config"], "BuildConfigParser"

+ )

+ 

  

  class ProjectDetailsFieldsParser(IParser):

      provided_fields = set(["description", "instructions", "last_modified", "name"])

rebased

7 years ago

Could you, please, create a simple test in beaker-tests/sanity showing the use-case?

Note that there is copr.repo_id exactly for this purpose.

Could you make the comment relevant to the method? :)

The help here is ok but could you also update man-pages, please?

Argh, no email notification after @clime comments.

Could you, please, create a simple test in beaker-tests/sanity showing the use-case?

Dunno, I'm not familiar with beaker too much. Are you asking for regression test or for example showing use-case?

I'll fix the man page, definitely.

Dunno, I'm not familiar with beaker too much. Are you asking for regression test or for example showing use-case?

Basically any of that. It is nice if you can provide some kind of a test but If you notice, e.g. here I basically did only a use-case (there is an implicit test that copr-cli buildfedpkg exits with 0 but that's it):

    rlRun "copr-cli create --chroot fedora-24-x86_64 ${NAME_PREFIX}ProjectDistGitBuilds"
    rlRun "copr-cli buildfedpkg --clone-url http://pkgs.fedoraproject.org/git/rpms/389-admin-console.git --branch f24 ${NAME_PREFIX}ProjectDistGitBuilds"

Basic working use-case is enough for now. We can add some real testing later.

1 new commit added

  • [cli] fix manual page for mock-config action
7 years ago

1 new commit added

  • [cli] add beaker test for mock-config
7 years ago

Please have a look, are those beaker tests run somewhere automatically? Or am I supposed to run it manually?

Fixed the last remark with copr.repo_id, PTAL.

rebased

7 years ago

Pull-Request has been merged by clime

7 years ago