Пример #1
0
def check_copr_existence(copr_username, copr_projectname) -> bool:
    try:
        client = CoprClient(copr_url=app.config.get("COPR_BASE_URL"))
        client.get_project_details(projectname=copr_projectname, username=copr_username)
        return True
    except CoprRequestException:
        return False
Пример #2
0
def check_copr_existence(copr_username, copr_projectname) -> bool:
    try:
        client = CoprClient(copr_url=app.config.get("COPR_BASE_URL"))
        client.get_project_details(projectname=copr_projectname,
                                   username=copr_username)
        return True
    except CoprRequestException:
        return False
Пример #3
0
    def __init__(self):

        try:
            self.client = CoprClient.create_from_file_config()
        except (copr_exceptions.CoprNoConfException,
                copr_exceptions.CoprConfigException):
            print(no_config_warning)
            self.client = CoprClient(copr_url=u"http://copr.fedoraproject.org",
                                     no_config=True)
Пример #4
0
 def __init__(self, config):
     self.config = config
     try:
         self.client = CoprClient.create_from_file_config(config)
     except (copr_exceptions.CoprNoConfException,
             copr_exceptions.CoprConfigException):
         sys.stderr.write(no_config_warning.format(config or "~/.config/copr"))
         self.client = CoprClient(
             copr_url=u"http://copr.fedoraproject.org",
             no_config=True
         )
Пример #5
0
 def __init__(self, config):
     self.config = config
     try:
         self.client = CoprClient.create_from_file_config(config)
     except (copr_exceptions.CoprNoConfException,
             copr_exceptions.CoprConfigException):
         print(no_config_warning.format(config or "~/.config/copr"))
         self.client = CoprClient(
             copr_url=u"http://copr.fedoraproject.org",
             no_config=True
         )
Пример #6
0
    def __init__(self):

        try:
            self.client = CoprClient.create_from_file_config()
        except (copr_exceptions.CoprNoConfException,
                copr_exceptions.CoprConfigException):
            print(no_config_warning)
            self.client = CoprClient(
                copr_url=u"http://copr.fedoraproject.org",
                no_config=True
            )
Пример #7
0
def search_coprs(query) -> List[ProjectWrapper]:
    client = CoprClient(copr_url=app.config.get("COPR_BASE_URL"))
    try:
        projects = client.search_projects(query).projects_list
    except CoprRequestException:
        log.exception("Failed to search for {}".format(query))
        raise CoprSearchError("Failed to search for {}".format(query))
    except KeyError:
        raise CoprSearchError("Found nothing for query: {}".format(query))

    if len(projects) == 0:
        raise CoprSearchError("Found nothing for query: {}".format(query))

    for project in projects:
        setattr(project, "copr_url", get_copr_url(project.username, project.projectname))
    return projects
Пример #8
0
def search_coprs(query) -> List[ProjectWrapper]:
    client = CoprClient(copr_url=app.config.get("COPR_BASE_URL"))
    try:
        projects = client.search_projects(query).projects_list
    except CoprRequestException:
        log.exception("Failed to search for {}".format(query))
        raise CoprSearchError("Failed to search for {}".format(query))
    except KeyError:
        raise CoprSearchError("Found nothing for query: {}".format(query))

    if len(projects) == 0:
        raise CoprSearchError("Found nothing for query: {}".format(query))

    for project in projects:
        setattr(project, "copr_url",
                get_copr_url(project.username, project.projectname))
    return projects
Пример #9
0
def test_projects_list(mock_request):
    mock_client = CoprClient.create_from_file_config(config_location)
    mock_request.return_value = make_mock_response("projects_list.200.json")

    test_resp = mock_client.get_projects_list()
    assert len(test_resp.projects_list) == 1
    test_project = test_resp.projects_list[0]
    assert test_project.projectname == "perl516-el7"
    assert test_project.description == "Test description"
Пример #10
0
def test_projects_list(mock_request):
    mock_client = CoprClient.create_from_file_config(config_location)
    mock_request.return_value = make_mock_response("projects_list.200.json")

    test_resp = mock_client.get_projects_list()
    assert len(test_resp.projects_list) == 1
    test_project = test_resp.projects_list[0]
    assert test_project.projectname == "perl516-el7"
    assert test_project.description == "Test description"
Пример #11
0
def test_client_from_dict():
    cl = CoprClient(login="******",
                    username="******",
                    token="api-token",
                    copr_url="http://copr-fe-dev.cloud.fedoraproject.org")

    assert isinstance(cl, CoprClient)
    assert cl.login == "api-login"
    assert cl.token == "api-token"
    assert cl.username == "user_name"
Пример #12
0
def test_get_build_status(mock_request):
    mock_client = CoprClient.create_from_file_config(config_location)

    mock_request.return_value = make_mock_response("build_details.200.json")

    test_resp = mock_client.get_build_details(27382)

    assert test_resp.status == "succeeded"
    assert test_resp.project == "atomic-next"
    assert test_resp.built_pkgs == [u'golang-github-stretchr-objx-devel 0']
    assert test_resp.submitted_on == 1408031345
Пример #13
0
def test_get_build_status(mock_request):
    mock_client = CoprClient.create_from_file_config(config_location)

    mock_request.return_value = make_mock_response("build_details.200.json")

    test_resp = mock_client.get_build_details(27382)

    assert test_resp.status == "succeeded"
    assert test_resp.project == "atomic-next"
    assert test_resp.built_pkgs == [u'golang-github-stretchr-objx-devel 0']
    assert test_resp.submitted_on == 1408031345
Пример #14
0
def test_get_build_config(mock_request):
    mock_client = CoprClient.create_from_file_config(config_location)
    mock_request.return_value = make_mock_response("build_config.200.json")
    test_resp = mock_client.get_build_config("project", "chroot")
    assert 'additional_packages' in test_resp.data
    expected_args = [
        "additional_packages", "additional_repos", "chroot", "enable_net",
        "repos", "use_bootstrap_container", "with_opts", "without_opts"
    ]
    for arg in expected_args:
        assert arg in test_resp.data
        test_resp.data.pop(arg)
    assert not test_resp.data.keys()
Пример #15
0
class Commands(object):
    def __init__(self, config):
        self.config = config
        try:
            self.client = CoprClient.create_from_file_config(config)
        except (copr_exceptions.CoprNoConfException,
                copr_exceptions.CoprConfigException):
            print(no_config_warning.format(config or "~/.config/copr"))
            self.client = CoprClient(
                copr_url=u"http://copr.fedoraproject.org",
                no_config=True
            )

    def requires_api_auth(func):
        """ Decorator that checks config presence
        """

        def wrapper(self, args):
            if self.client.no_config:
                print("Error: Operation requires api authentication")
                print(no_config_warning.format(self.config or "~/.config/copr"))
                sys.exit(6)

            return func(self, args)

        wrapper.__doc__ = func.__doc__
        wrapper.__name__ = func.__name__
        return wrapper

    def check_username_presence(func):
        """ Decorator that checks if username was provided
        """

        def wrapper(self, args):
            if self.client.no_config and args.username is None:
                print("Error: Operation requires username\n"
                      "Pass username to command or create `~/.config/copr`")
                sys.exit(6)

            if args.username is None and self.client.username is None:
                print("Error: Operation requires username\n"
                      "Pass username to command or add it to `~/.config/copr`")
                sys.exit(6)

            return func(self, args)

        wrapper.__doc__ = func.__doc__
        wrapper.__name__ = func.__name__
        return wrapper

    def _watch_builds(self, builds_list):
        """
         :param builds_list: list of BuildWrapper
         """
        print("Watching build(s): (this may be safely interrupted)")

        prevstatus = defaultdict(lambda: None)
        failed_ids = []

        watched = set([bw.build_id for bw in builds_list])
        done = set()

        try:
            while watched != done:
                for build_id in watched:
                    if build_id in done:
                        continue

                    build_details = self.client.get_build_details(build_id)

                    if build_details.output != "ok":
                        errmsg = "  Build {1}: Unable to get build status: {0}". \
                            format(build_details.error, build_id)
                        raise copr_exceptions.CoprRequestException(errmsg)

                    now = datetime.datetime.now()
                    if prevstatus[build_id] != build_details.status:
                        prevstatus[build_id] = build_details.status
                        print("  {0} Build {2}: {1}".format(
                            now.strftime("%H:%M:%S"),
                            build_details.status, build_id))

                    if build_details.status in ["failed"]:
                        failed_ids.append(build_id)
                    if build_details.status in ["succeeded", "skipped",
                                                "failed", "canceled"]:
                        done.add(build_id)
                    if build_details.status == "unknown":
                        raise copr_exceptions.CoprBuildException(
                            "Unknown status.")

                if watched == done:
                    break

                time.sleep(30)

            if failed_ids:
                raise copr_exceptions.CoprBuildException(
                    "Build(s) {0} failed.".format(
                        ", ".join(str(x) for x in failed_ids)))

        except KeyboardInterrupt:
            pass

    @requires_api_auth
    def action_build(self, args):
        """ Method called when the 'build' action has been selected by the
        user.

        :param args: argparse arguments provided by the user

        """
        bar = None
        progress_callback = None

        if os.path.exists(args.pkgs[0]):
            bar = ProgressBar(max=os.path.getsize(args.pkgs[0]))

            def progress_callback(monitor):
                bar.next(n=8192)

            print('Uploading package {0}'.format(args.pkgs[0]))

        data = {
            "pkgs": args.pkgs,
            "progress_callback": progress_callback,
        }

        return self.process_build(args, self.client.create_new_build, data, bar=bar)

    @requires_api_auth
    def action_build_pypi(self, args):
        """
        Method called when the 'buildpypi' action has been selected by the user.

        :param args: argparse arguments provided by the user
        """
        username, copr = parse_name(args.copr)

        data = {
            "pypi_package_name": args.packagename,
            "pypi_package_version": args.packageversion,
            "python_versions": args.pythonversions,
        }
        return self.process_build(args, self.client.create_new_build_pypi, data)

    @requires_api_auth
    def action_build_tito(self, args):
        """
        Method called when the 'buildtito' action has been selected by the user.

        :param args: argparse arguments provided by the user
        """
        data = {
            "git_url": args.git_url,
            "git_dir": args.git_dir,
            "git_branch": args.git_branch,
            "tito_test": args.tito_test,
        }
        return self.process_build(args, self.client.create_new_build_tito, data)

    @requires_api_auth
    def action_build_mock(self, args):
        """
        Method called when the 'build-mock' action has been selected by the user.

        :param args: argparse arguments provided by the user
        """
        data = {
            "scm_type": args.scm_type,
            "scm_url": args.scm_url,
            "scm_branch": args.scm_branch,
            "spec": args.spec,
        }
        return self.process_build(args, self.client.create_new_build_mock, data)

    @requires_api_auth
    def action_build_rubygems(self, args):
        """
        Method called when the 'buildgem' action has been selected by the user.

        :param args: argparse arguments provided by the user
        """
        data = {"gem_name": args.gem_name}
        return self.process_build(args, self.client.create_new_build_rubygems, data)

    def process_build(self, args, build_function, data, bar=None):
        username, copr = parse_name(args.copr)

        result = build_function(username=username, projectname=copr, chroots=args.chroots,
                                            memory=args.memory, timeout= args.timeout, **data)
        if bar:
            bar.finish()

        if result.output != "ok":
            print(result.error)
            return
        print(result.message)

        build_ids = [bw.build_id for bw in result.builds_list]
        print("Created builds: {0}".format(" ".join(map(str, build_ids))))

        if not args.nowait:
            self._watch_builds(result.builds_list)


    @requires_api_auth
    def action_create(self, args):
        """ Method called when the 'create' action has been selected by the
        user.

        :param args: argparse arguments provided by the user

        """
        username, copr = parse_name(args.name)
        result = self.client.create_project(
            username=username, projectname=copr, description=args.description,
            instructions=args.instructions, chroots=args.chroots,
            repos=args.repos, initial_pkgs=args.initial_pkgs)
        print(result.message)

    @requires_api_auth
    def action_modify_project(self, args):
        """ Method called when the 'modify' action has been selected by the
        user.

        :param args: argparse arguments provided by the user
        """
        username, copr = parse_name(args.name)
        result = self.client.modify_project(
            username=username, projectname=copr,
            description=args.description, instructions=args.instructions,
            repos=args.repos, disable_createrepo=args.disable_createrepo)

    @requires_api_auth
    def action_delete(self, args):
        """ Method called when the 'delete' action has been selected by the
        user.

        :param args: argparse arguments provided by the user
        """
        username, copr = parse_name(args.copr)
        result = self.client.delete_project(username=username, projectname=copr)
        print(result.message)

    @check_username_presence
    def action_list(self, args):
        """ Method called when the 'list' action has been selected by the
        user.

        :param args: argparse arguments provided by the user

        """
        username = args.username or self.client.username
        result = self.client.get_projects_list(username)
        # import ipdb; ipdb.set_trace()
        if result.output != "ok":
            print(result.error)
            print("Un-expected data returned, please report this issue")
        elif not result.projects_list:
            print("No copr retrieved for user: '******'".format(username))
            return

        for prj in result.projects_list:
            print(prj)

    def action_status(self, args):
        result = self.client.get_build_details(args.build_id)
        print(result.status)

    def action_download_build(self, args):
        result = self.client.get_build_details(args.build_id)
        base_len = len(os.path.split(result.results))

        for chroot, url in result.results_by_chroot.items():
            if args.chroots and chroot not in args.chroots:
                continue

            cmd = "wget -r -nH --no-parent --reject 'index.html*'".split(' ')
            cmd.extend(['-P', os.path.join(args.dest, chroot)])
            cmd.extend(['--cut-dirs', str(base_len + 4)])
            cmd.append(url)
            subprocess.call(cmd)

    @requires_api_auth
    def action_cancel(self, args):
        """ Method called when the 'cancel' action has been selected by the
        user.
        :param args: argparse arguments provided by the user
        """
        result = self.client.cancel_build(args.build_id)
        print(result.status)
Пример #16
0
distsuffix = ''
tag = args[0]
pkgstoignore = []

if config.has_section(tag) and config.has_option(tag, 'blacklist'):
    pkgstoignore = config.get(tag, 'blacklist').split(' ')

disttag = config.get(tag, 'disttag').split()
if tag.startswith('satellite'):
    tag = tag + '-candidate'

if opts.copr:
    from copr import CoprClient
    buildsystem = 'copr'
    owner, project = tag.split('/', 2)
    myclient = CoprClient.create_from_file_config()
    result = myclient.get_packages_list(ownername=owner,
                                        projectname=project,
                                        with_latest_build=True,
                                        with_latest_succeeded_build=True)
    rpmlist = []
    for pkg in result.packages_list:
        pkg_name = pkg.data['name']
        pkg_succeeded = pkg.data['latest_succeeded_build']
        if pkg_succeeded:
            pkg_version = pkg_succeeded['pkg_version']
        else:
            # packages inherited from forked repo has no latest_succeeded_build
            pkg_latest = pkg.data['latest_build']
            if pkg_latest and pkg_latest['state'] == "forked":
                pkg_version = pkg_latest['pkg_version']
Пример #17
0
class Commands(object):
    def __init__(self):

        try:
            self.client = CoprClient.create_from_file_config()
        except (copr_exceptions.CoprNoConfException,
                copr_exceptions.CoprConfigException):
            print(no_config_warning)
            self.client = CoprClient(copr_url=u"http://copr.fedoraproject.org",
                                     no_config=True)

    def requires_api_auth(func):
        """ Decorator that checks config presence
        """
        def wrapper(self, args):
            if self.client.no_config:
                print("Error: Operation requires api authentication\n"
                      "File `~/.config/copr` is missing or incorrect")
                sys.exit(6)

            return func(self, args)

        wrapper.__doc__ = func.__doc__
        wrapper.__name__ = func.__name__
        return wrapper

    def check_username_presence(func):
        """ Decorator that checks if username was provided
        """
        def wrapper(self, args):
            if self.client.no_config and args.username is None:
                print("Error: Operation requires username\n"
                      "Pass username to command or create `~/.config/copr`")
                sys.exit(6)

            if args.username is None and self.client.username is None:
                print("Error: Operation requires username\n"
                      "Pass username to command or add it to `~/.config/copr`")
                sys.exit(6)

            return func(self, args)

        wrapper.__doc__ = func.__doc__
        wrapper.__name__ = func.__name__
        return wrapper

    def _watch_builds(self, builds_list):
        """
         :param builds_list: list of BuildWrapper
         """
        print("Watching build(s): (this may be safely interrupted)")

        prevstatus = defaultdict(lambda: None)
        failed_ids = []

        watched = set([bw.build_id for bw in builds_list])
        done = set()

        try:
            while watched != done:
                for build_id in watched:
                    if build_id in done:
                        continue

                    build_details = self.client.get_build_details(build_id)

                    if build_details.output != "ok":
                        errmsg = "  Build {1}: Unable to get build status: {0}". \
                            format(build_details.error, build_id)
                        raise copr_exceptions.CoprRequestException(errmsg)

                    now = datetime.datetime.now()
                    if prevstatus[build_id] != build_details.status:
                        prevstatus[build_id] = build_details.status
                        print("  {0} Build {2}: {1}".format(
                            now.strftime("%H:%M:%S"), build_details.status,
                            build_id))

                    if build_details.status in ["failed"]:
                        failed_ids.append(build_id)
                    if build_details.status in [
                            "succeeded", "skipped", "failed", "canceled"
                    ]:
                        done.add(build_id)
                    if build_details.status == "unknown":
                        raise copr_exceptions.CoprBuildException(
                            "Unknown status.")

                if watched == done:
                    break

                time.sleep(30)

            if failed_ids:
                raise copr_exceptions.CoprBuildException(
                    "Build(s) {0} failed.".format(", ".join(
                        str(x) for x in failed_ids)))

        except KeyboardInterrupt:
            pass

    @requires_api_auth
    def action_build(self, args):
        """ Method called when the 'build' action has been selected by the
        user.

        :param args: argparse arguments provided by the user

        """
        copr = args.copr
        m = re.match(r"([^/]+)/(.*)", copr)
        if m:
            username = m.group(1)
            copr = m.group(2)
        else:
            username = None

        if os.path.exists(args.pkgs[0]):
            bar = ProgressBar(max=os.path.getsize(args.pkgs[0]))

            def progress_callback(monitor):
                bar.next(n=8192)

            print('Uploading package {}'.format(args.pkgs[0]))
        else:
            progress_callback = None

        result = self.client.create_new_build(
            projectname=copr,
            chroots=args.chroots,
            pkgs=args.pkgs,
            memory=args.memory,
            timeout=args.timeout,
            username=username,
            progress_callback=progress_callback)

        bar.finish()

        if result.output != "ok":
            print(result.error)
            return
        print(result.message)

        build_ids = [bw.build_id for bw in result.builds_list]
        print("Created builds: {}".format(" ".join(map(str, build_ids))))

        if not args.nowait:
            self._watch_builds(result.builds_list)

    @requires_api_auth
    def action_create(self, args):
        """ Method called when the 'create' action has been selected by the
        user.

        :param args: argparse arguments provided by the user

        """

        result = self.client.create_project(projectname=args.name,
                                            description=args.description,
                                            instructions=args.instructions,
                                            chroots=args.chroots,
                                            repos=args.repos,
                                            initial_pkgs=args.initial_pkgs)
        print(result.message)

    @requires_api_auth
    def action_modify_project(self, args):
        """ Method called when the 'modify' action has been selected by the
        user.

        :param args: argparse arguments provided by the user
        """

        result = self.client.modify_project(
            projectname=args.name,
            description=args.description,
            instructions=args.instructions,
            repos=args.repos,
            disable_createrepo=args.disable_createrepo)

    @requires_api_auth
    def action_delete(self, args):
        """ Method called when the 'delete' action has been selected by the
        user.

        :param args: argparse arguments provided by the user
        """
        result = self.client.delete_project(projectname=args.copr)
        print(result.message)

    @check_username_presence
    def action_list(self, args):
        """ Method called when the 'list' action has been selected by the
        user.

        :param args: argparse arguments provided by the user

        """
        username = args.username or self.client.username
        result = self.client.get_projects_list(username)
        # import ipdb; ipdb.set_trace()
        if result.output != "ok":
            print(result.error)
            print("Un-expected data returned, please report this issue")
        elif not result.projects_list:
            print("No copr retrieved for user: '******'".format(username))
            return

        for prj in result.projects_list:
            print(prj)

    def action_status(self, args):
        result = self.client.get_build_details(args.build_id)
        print(result.status)

    def action_download_build(self, args):
        result = self.client.get_build_details(args.build_id)
        # TODO: can be simplified after https://bugzilla.redhat.com/show_bug.cgi?id=1133650
        #  and addition of that paths to api

        o = urlparse(result.src_pkg)
        pkgs_name = os.path.split(o.path)[-1]
        assert pkgs_name.endswith(".src.rpm")

        base_url = result.results
        base_len = len(os.path.split(base_url))

        pkg_dir = pkgs_name[:-8]
        for chroot, status in result.data["chroots"].items():
            if args.chroots and chroot not in args.chroots:
                continue

            cmd = "wget -r -nH --no-parent --reject 'index.html*'".split(' ')

            cmd.extend(['-P', os.path.join(args.dest, chroot)])
            cmd.extend(['--cut-dirs', str(base_len + 4)])
            cmd.append("{}{}/{}/".format(base_url, chroot, pkg_dir))

            subprocess.call(cmd)

    @requires_api_auth
    def action_cancel(self, args):
        """ Method called when the 'cancel' action has been selected by the
        user.
        :param args: argparse arguments provided by the user
        """
        result = self.client.cancel_build(args.build_id)
        print(result.status)
Пример #18
0
def test_list_projects():
    CoprClient.create_from_file_config(config_location)
Пример #19
0
import subprocess
import argparse
import time
import os
from copr import create_client2_from_params
from copr import CoprClient
import json

URL_PATTERN = 'https://pypi.python.org/pypi/{package}/json'
CONFIG = os.path.join(os.path.expanduser("~"), ".config/copr")

COPR_URL = "https://copr.fedorainfracloud.org/"
USER = "******"
COPR = "PyPI2"

cl = CoprClient.create_from_file_config(CONFIG)

parser = argparse.ArgumentParser(prog = "pypi")
parser.add_argument("-s", "--submit-pypi-modules", dest="submit_pypi_modules", metavar='PYTHON_VERSION', action="store")
parser.add_argument("-u", "--submit-unbuilt-pypi-modules", dest="submit_unbuilt_pypi_modules", metavar='PYTHON_VERSION', action="store")
parser.add_argument("-p", "--parse-succeeded-packages", dest="parse_succeeded_packages", action="store_true")
parser.add_argument("-o", "--parse-succeeded-packages-v1client", dest="parse_succeeded_packages_v1client", action="store_true")
args = parser.parse_args()


def create_package_name(module_name):
    return "python-{}".format(module_name.replace(".", "-"))


#NOT USED
def get_version(package, url_pattern=URL_PATTERN):
Пример #20
0
def test_client_from_config():
    cl = CoprClient.create_from_file_config(config_location)
    assert isinstance(cl, CoprClient)
    assert cl.login == "api-login"
    assert cl.token == "api-token"
    assert cl.username == "user_name"
Пример #21
0
def test_list_projects():
    CoprClient.create_from_file_config(config_location)
Пример #22
0
def test_client_from_config():
    cl = CoprClient.create_from_file_config(config_location)
    assert isinstance(cl, CoprClient)
    assert cl.login == "api-login"
    assert cl.token == "api-token"
    assert cl.username == "user_name"
Пример #23
0
distsuffix = ''
tag = args[0]
pkgstoignore = []

if config.has_section(tag) and config.has_option(tag, 'blacklist'):
    pkgstoignore = config.get(tag, 'blacklist').split(' ')

disttag = config.get(tag, 'disttag').split()
if tag.startswith('satellite'):
    tag = tag + '-candidate'

if opts.copr:
    from copr import CoprClient
    buildsystem='copr'
    owner, project = tag.split('/',2)
    myclient = CoprClient.create_from_file_config()
    result = myclient.get_packages_list(ownername=owner, projectname=project,
                                         with_latest_build=True,
                                         with_latest_succeeded_build=True)
    rpmlist = []
    for pkg in result.packages_list:
                pkg_name = pkg.data['name']
                pkg_succeeded = pkg.data['latest_succeeded_build']
                if pkg_succeeded:
                    pkg_version = pkg_succeeded['pkg_version']
                else:
                    # packages inherited from forked repo has no latest_succeeded_build
                    pkg_latest = pkg.data['latest_build']
                    if pkg_latest and pkg_latest['state'] == "forked":
                       pkg_version = pkg_latest['pkg_version']
                    else:
Пример #24
0
def test_list_projects(mock_request):
    mock_client = CoprClient.create_from_file_config(config_location)
Пример #25
0
class Commands(object):
    def __init__(self, config):
        self.config = config
        try:
            self.client = CoprClient.create_from_file_config(config)
        except (copr_exceptions.CoprNoConfException,
                copr_exceptions.CoprConfigException):
            sys.stderr.write(no_config_warning.format(config or "~/.config/copr"))
            self.client = CoprClient(
                copr_url=u"http://copr.fedoraproject.org",
                no_config=True
            )

    def requires_api_auth(func):
        """ Decorator that checks config presence
        """

        def wrapper(self, args):
            if self.client.no_config:
                sys.stderr.write("Error: Operation requires api authentication\n")
                sys.exit(6)

            return func(self, args)

        wrapper.__doc__ = func.__doc__
        wrapper.__name__ = func.__name__
        return wrapper

    def check_username_presence(func):
        """ Decorator that checks if username was provided
        """

        def wrapper(self, args):
            if self.client.no_config and args.username is None:
                sys.stderr.write(
                    "Error: Operation requires username\n"
                    "Pass username to command or create `~/.config/copr`\n")
                sys.exit(6)

            if args.username is None and self.client.username is None:
                sys.stderr.write(
                    "Error: Operation requires username\n"
                    "Pass username to command or add it to `~/.config/copr`\n")
                sys.exit(6)

            return func(self, args)

        wrapper.__doc__ = func.__doc__
        wrapper.__name__ = func.__name__
        return wrapper

    def _watch_builds(self, build_ids):
        """
         :param build_ids: list of build IDs
         """
        print("Watching build(s): (this may be safely interrupted)")

        prevstatus = defaultdict(lambda: None)
        failed_ids = []

        watched = set(build_ids)
        done = set()

        try:
            while watched != done:
                for build_id in watched:
                    if build_id in done:
                        continue

                    build_details = self.client.get_build_details(build_id)

                    if build_details.output != "ok":
                        errmsg = "  Build {1}: Unable to get build status: {0}". \
                            format(build_details.error, build_id)
                        raise copr_exceptions.CoprRequestException(errmsg)

                    now = datetime.datetime.now()
                    if prevstatus[build_id] != build_details.status:
                        prevstatus[build_id] = build_details.status
                        print("  {0} Build {2}: {1}".format(
                            now.strftime("%H:%M:%S"),
                            build_details.status, build_id))

                    if build_details.status in ["failed"]:
                        failed_ids.append(build_id)
                    if build_details.status in ["succeeded", "skipped",
                                                "failed", "canceled"]:
                        done.add(build_id)
                    if build_details.status == "unknown":
                        raise copr_exceptions.CoprBuildException(
                            "Unknown status.")

                if watched == done:
                    break

                time.sleep(30)

            if failed_ids:
                raise copr_exceptions.CoprBuildException(
                    "Build(s) {0} failed.".format(
                        ", ".join(str(x) for x in failed_ids)))

        except KeyboardInterrupt:
            pass

    def action_whoami(self, args):
        """
        Simply print out the current user as defined in copr config.
        """
        print(self.client.username)

    @requires_api_auth
    def action_build(self, args):
        """ Method called when the 'build' action has been selected by the
        user.

        :param args: argparse arguments provided by the user
        """
        self.client.authentication_check()

        bar = None
        progress_callback = None
        builds = []

        for pkg in args.pkgs:
            if os.path.exists(pkg):
                bar = ProgressBar(max=os.path.getsize(pkg))

                # pylint: disable=function-redefined
                def progress_callback(monitor):
                    bar.next(n=8192)

                print('Uploading package {0}'.format(pkg))

            data = {
                "pkgs": [pkg],
                "progress_callback": progress_callback,
            }

            builds.append(self.process_build(args, self.client.create_new_build, data, bar=bar))

        return builds

    @requires_api_auth
    def action_build_pypi(self, args):
        """
        Method called when the 'buildpypi' action has been selected by the user.

        :param args: argparse arguments provided by the user
        """
        username, copr = parse_name(args.copr)

        data = {
            "pypi_package_name": args.packagename,
            "pypi_package_version": args.packageversion,
            "python_versions": args.pythonversions,
        }
        return self.process_build(args, self.client.create_new_build_pypi, data)

    @requires_api_auth
    def action_build_tito(self, args):
        """
        Method called when the 'buildtito' action has been selected by the user.

        :param args: argparse arguments provided by the user
        """
        data = {
            "git_url": args.git_url,
            "git_dir": args.git_dir,
            "git_branch": args.git_branch,
            "tito_test": args.tito_test,
        }
        return self.process_build(args, self.client.create_new_build_tito, data)

    @requires_api_auth
    def action_build_mock(self, args):
        """
        Method called when the 'build-mock' action has been selected by the user.

        :param args: argparse arguments provided by the user
        """
        data = {
            "scm_type": args.scm_type,
            "scm_url": args.scm_url,
            "scm_branch": args.scm_branch,
            "spec": args.spec,
        }
        return self.process_build(args, self.client.create_new_build_mock, data)

    @requires_api_auth
    def action_build_rubygems(self, args):
        """
        Method called when the 'buildgem' action has been selected by the user.

        :param args: argparse arguments provided by the user
        """
        data = {"gem_name": args.gem_name}
        return self.process_build(args, self.client.create_new_build_rubygems, data)

    @requires_api_auth
    def action_build_distgit(self, args):
        """
        Method called when the 'buildfedpkg' action has been selected by the user.

        :param args: argparse arguments provided by the user
        """
        data = {"clone_url": args.clone_url, "branch": args.branch}
        return self.process_build(args, self.client.create_new_build_distgit, data)

    def process_build(self, args, build_function, data, bar=None):
        username, copr = parse_name(args.copr)

        result = build_function(username=username, projectname=copr, chroots=args.chroots, memory=args.memory,
                                timeout=args.timeout, background=args.background, **data)
        if bar:
            bar.finish()

        if result.output != "ok":
            sys.stderr.write(result.error + "\n")
            return
        print(result.message)

        build_ids = [bw.build_id for bw in result.builds_list]
        print("Created builds: {0}".format(" ".join(map(str, build_ids))))

        if not args.nowait:
            self._watch_builds(build_ids)


    @requires_api_auth
    def action_create(self, args):
        """ Method called when the 'create' action has been selected by the
        user.

        :param args: argparse arguments provided by the user

        """
        username, copr = parse_name(args.name)
        result = self.client.create_project(
            username=username, projectname=copr, description=args.description,
            instructions=args.instructions, chroots=args.chroots,
            repos=args.repos, initial_pkgs=args.initial_pkgs,
            disable_createrepo=args.disable_createrepo,
            unlisted_on_hp=ON_OFF_MAP[args.unlisted_on_hp],
            enable_net=ON_OFF_MAP[args.enable_net],
            persistent=args.persistent,
            auto_prune=ON_OFF_MAP[args.auto_prune]
        )
        print(result.message)

    @requires_api_auth
    def action_modify_project(self, args):
        """ Method called when the 'modify' action has been selected by the
        user.

        :param args: argparse arguments provided by the user
        """
        username, copr = parse_name(args.name)
        result = self.client.modify_project(
            username=username, projectname=copr,
            description=args.description, instructions=args.instructions,
            repos=args.repos, disable_createrepo=args.disable_createrepo,
            unlisted_on_hp=ON_OFF_MAP[args.unlisted_on_hp],
            enable_net=ON_OFF_MAP[args.enable_net],
            auto_prune=ON_OFF_MAP[args.auto_prune],
            chroots=args.chroots,
        )

    @requires_api_auth
    def action_delete(self, args):
        """ Method called when the 'delete' action has been selected by the
        user.

        :param args: argparse arguments provided by the user
        """
        username, copr = parse_name(args.copr)
        result = self.client.delete_project(username=username, projectname=copr)
        print(result.message)

    @requires_api_auth
    def action_fork(self, args):
        """ Method called when the 'fork' action has been selected by the
        user.

        :param args: argparse arguments provided by the user
        """
        username, copr = parse_name(args.dst)
        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":
            sys.stderr.write(result.error + "\n")
            sys.stderr.write("Un-expected data returned, please report this issue\n")

        print(MockProfile(result.build_config))


    @check_username_presence
    def action_list(self, args):
        """ Method called when the 'list' action has been selected by the
        user.

        :param args: argparse arguments provided by the user

        """
        username = args.username or self.client.username
        result = self.client.get_projects_list(username)
        # import ipdb; ipdb.set_trace()
        if result.output != "ok":
            sys.stderr.write(result.error + "\n")
            sys.stderr.write("Un-expected data returned, please report this issue\n")
        elif not result.projects_list:
            sys.stderr.write("No copr retrieved for user: '******'\n".format(username))
            return

        for prj in result.projects_list:
            print(prj)

    def action_status(self, args):
        result = self.client.get_build_details(args.build_id)
        print(result.status)

    def action_download_build(self, args):
        result = self.client.get_build_details(args.build_id)
        base_len = len(os.path.split(result.results))

        for chroot, url in result.results_by_chroot.items():
            if args.chroots and chroot not in args.chroots:
                continue

            cmd = "wget -r -nH --no-parent --reject 'index.html*'".split(' ')
            cmd.extend(['-P', os.path.join(args.dest, chroot)])
            cmd.extend(['--cut-dirs', str(base_len + 4)])
            cmd.append(url)
            subprocess.call(cmd)

    @requires_api_auth
    def action_cancel(self, args):
        """ Method called when the 'cancel' action has been selected by the
        user.
        :param args: argparse arguments provided by the user
        """
        result = self.client.cancel_build(args.build_id)
        print(result.status)

    def action_watch_build(self, args):
        self._watch_builds(args.build_id)

    def action_delete_build(self, args):
        result = self.client.delete_build(args.build_id)
        print(result.status)

    #########################################################
    ###                   Chroot actions                  ###
    #########################################################

    @requires_api_auth
    def action_edit_chroot(self, args):
        """ Method called when the 'edit-chroot' action has been selected by the
        user.

        :param args: argparse arguments provided by the user
        """
        owner, copr, chroot = parse_chroot_path(args.coprchroot)
        result = self.client.edit_chroot(
            ownername=owner, projectname=copr, chrootname=chroot,
            upload_comps=args.upload_comps, delete_comps=args.delete_comps,
            packages=args.packages, repos=args.repos
        )
        print(result.message)

    def action_get_chroot(self, args):
        """ Method called when the 'get-chroot' action has been selected by the
        user.

        :param args: argparse arguments provided by the user
        """
        owner, copr, chroot = parse_chroot_path(args.coprchroot)
        result = self.client.get_chroot(
            ownername=owner, projectname=copr, chrootname=chroot
        )
        print(simplejson.dumps(result.chroot, indent=4, sort_keys=True, for_json=True))

    #########################################################
    ###                   Package actions                 ###
    #########################################################

    @requires_api_auth
    def action_add_or_edit_package_tito(self, args):
        ownername, projectname = parse_name(args.copr)
        data = {
            "package_name": args.name,
            "git_url": args.git_url,
            "git_dir": args.git_dir,
            "git_branch": args.git_branch,
            "tito_test": ON_OFF_MAP[args.tito_test],
            "webhook_rebuild": ON_OFF_MAP[args.webhook_rebuild],
        }
        if args.create:
            result = self.client.add_package_tito(ownername=ownername, projectname=projectname, **data)
        else:
            result = self.client.edit_package_tito(ownername=ownername, projectname=projectname, **data)
        print(result.message)

    @requires_api_auth
    def action_add_or_edit_package_pypi(self, args):
        ownername, projectname = parse_name(args.copr)
        data = {
            "package_name": args.name,
            "pypi_package_name": args.packagename,
            "pypi_package_version": args.packageversion,
            "python_versions": args.pythonversions,
            "webhook_rebuild": ON_OFF_MAP[args.webhook_rebuild],
        }
        if args.create:
            result = self.client.add_package_pypi(ownername=ownername, projectname=projectname, **data)
        else:
            result = self.client.edit_package_pypi(ownername=ownername, projectname=projectname, **data)
        print(result.message)

    @requires_api_auth
    def action_add_or_edit_package_mockscm(self, args):
        ownername, projectname = parse_name(args.copr)
        data = {
            "package_name": args.name,
            "scm_type": args.scm_type,
            "scm_url": args.scm_url,
            "scm_branch": args.scm_branch,
            "spec": args.spec,
            "webhook_rebuild": ON_OFF_MAP[args.webhook_rebuild],
        }
        if args.create:
            result = self.client.add_package_mockscm(ownername=ownername, projectname=projectname, **data)
        else:
            result = self.client.edit_package_mockscm(ownername=ownername, projectname=projectname, **data)
        print(result.message)

    @requires_api_auth
    def action_add_or_edit_package_rubygems(self, args):
        ownername, projectname = parse_name(args.copr)
        data = {
            "package_name": args.name,
            "gem_name": args.gem_name,
            "webhook_rebuild": ON_OFF_MAP[args.webhook_rebuild],
        }
        if args.create:
            result = self.client.add_package_rubygems(ownername=ownername, projectname=projectname, **data)
        else:
            result = self.client.edit_package_rubygems(ownername=ownername, projectname=projectname, **data)
        print(result.message)

    def action_list_packages(self, args):
        ownername, projectname = parse_name(args.copr)
        data = {
            "with_latest_build": args.with_latest_build,
            "with_latest_succeeded_build": args.with_latest_succeeded_build,
            "with_all_builds": args.with_all_builds,
        }
        result = self.client.get_packages_list(ownername=ownername, projectname=projectname, **data)
        print(simplejson.dumps(result.packages_list, indent=4, sort_keys=True, for_json=True))

    def action_list_package_names(self, args):
        ownername, projectname = parse_name(args.copr)
        result = self.client.get_packages_list(ownername=ownername, projectname=projectname)
        for package in result.packages_list:
            print(package.name)

    def action_get_package(self, args):
        ownername, projectname = parse_name(args.copr)
        data = {
            "pkg_name": args.name,
            "with_latest_build": args.with_latest_build,
            "with_latest_succeeded_build": args.with_latest_succeeded_build,
            "with_all_builds": args.with_all_builds,
        }
        result = self.client.get_package(ownername=ownername, projectname=projectname, **data)
        print(simplejson.dumps(result.package, indent=4, sort_keys=True, for_json=True))

    def action_delete_package(self, args):
        ownername, projectname = parse_name(args.copr)
        data = { "pkg_name": args.name }
        result = self.client.delete_package(ownername=ownername, projectname=projectname, **data)
        print(result.message)

    def action_reset_package(self, args):
        ownername, projectname = parse_name(args.copr)
        data = { "pkg_name": args.name }
        result = self.client.reset_package(ownername=ownername, projectname=projectname, **data)
        print(result.message)

    def action_build_package(self, args):
        ownername, projectname = parse_name(args.copr)
        data = {
            "pkg_name": args.name,
            "chroots": args.chroots,
            #"memory": args.memory,
            "timeout": args.timeout
        }

        result = self.client.build_package(ownername=ownername, projectname=projectname, **data)

        if result.output != "ok":
            sys.stderr.write(result.error + "\n")
            return
        print(result.message)

        build_ids = [bw.build_id for bw in result.builds_list]
        print("Created builds: {0}".format(" ".join(map(str, build_ids))))

        if not args.nowait:
            self._watch_builds(build_ids)

    def action_build_module(self, args):
        """
        Build module via Copr MBS
        """
        ownername, projectname = parse_name(args.copr or "")
        modulemd = open(args.yaml, "rb") if args.yaml else args.url
        response = self.client.build_module(modulemd, ownername, projectname)
        print(response.message if response.output == "ok" else response.error)
Пример #26
0
class Commands(object):
    def __init__(self):

        try:
            self.client = CoprClient.create_from_file_config()
        except (copr_exceptions.CoprNoConfException,
                copr_exceptions.CoprConfigException):
            print(no_config_warning)
            self.client = CoprClient(
                copr_url=u"http://copr.fedoraproject.org",
                no_config=True
            )

    def requires_api_auth(func):
        """ Decorator that checks config presence
        """

        def wrapper(self, args):
            if self.client.no_config:
                print("Error: Operation requires api authentication\n"
                      "File `~/.config/copr` is missing or incorrect")
                sys.exit(6)

            return func(self, args)

        wrapper.__doc__ = func.__doc__
        wrapper.__name__ = func.__name__
        return wrapper

    def check_username_presence(func):
        """ Decorator that checks if username was provided
        """

        def wrapper(self, args):
            if self.client.no_config and args.username is None:
                print("Error: Operation requires username\n"
                      "Pass username to command or create `~/.config/copr`")
                sys.exit(6)

            if args.username is None and self.client.username is None:
                print("Error: Operation requires username\n"
                      "Pass username to command or add it to `~/.config/copr`")
                sys.exit(6)

            return func(self, args)

        wrapper.__doc__ = func.__doc__
        wrapper.__name__ = func.__name__
        return wrapper

    def _watch_builds(self, builds_list):
        """
         :param builds_list: list of BuildWrapper
         """
        print("Watching build(s): (this may be safely interrupted)")

        prevstatus = defaultdict(lambda: None)
        failed_ids = []

        watched = set([bw.build_id for bw in builds_list])
        done = set()

        try:
            while watched != done:
                for build_id in watched:
                    if build_id in done:
                        continue

                    build_details = self.client.get_build_details(build_id)

                    if build_details.output != "ok":
                        errmsg = "  Build {1}: Unable to get build status: {0}". \
                            format(build_details.error, build_id)
                        raise copr_exceptions.CoprRequestException(errmsg)

                    now = datetime.datetime.now()
                    if prevstatus[build_id] != build_details.status:
                        prevstatus[build_id] = build_details.status
                        print("  {0} Build {2}: {1}".format(
                            now.strftime("%H:%M:%S"),
                            build_details.status, build_id))

                    if build_details.status in ["failed"]:
                        failed_ids.append(build_id)
                    if build_details.status in ["succeeded", "skipped",
                                                "failed", "canceled"]:
                        done.add(build_id)
                    if build_details.status == "unknown":
                        raise copr_exceptions.CoprBuildException(
                            "Unknown status.")

                if watched == done:
                    break

                time.sleep(30)

            if failed_ids:
                raise copr_exceptions.CoprBuildException(
                    "Build(s) {0} failed.".format(
                        ", ".join(str(x) for x in failed_ids)))

        except KeyboardInterrupt:
            pass

    @requires_api_auth
    def action_build(self, args):
        """ Method called when the 'build' action has been selected by the
        user.

        :param args: argparse arguments provided by the user

        """
        copr = args.copr
        m = re.match(r"(\w+)/(.*)", copr)
        if m:
            username = m.group(1)
            copr = m.group(2)
        else:
            username = None
        result = self.client.create_new_build(
            projectname=copr, chroots=args.chroots, pkgs=args.pkgs,
            memory=args.memory, timeout=args.timeout,
            username=username)
        if result.output != "ok":
            print(result.error)
            return
        print(result.message)

        build_ids = [bw.build_id for bw in result.builds_list]
        print("Created builds: {}".format(" ".join(map(str, build_ids))))

        if not args.nowait:
            self._watch_builds(result.builds_list)

    @requires_api_auth
    def action_create(self, args):
        """ Method called when the 'create' action has been selected by the
        user.

        :param args: argparse arguments provided by the user

        """

        result = self.client.create_project(
            projectname=args.name, description=args.description,
            instructions=args.instructions, chroots=args.chroots,
            repos=args.repos, initial_pkgs=args.initial_pkgs)
        print(result.message)

    @requires_api_auth
    def action_modify_project(self, args):
        """ Method called when the 'modify' action has been selected by the
        user.

        :param args: argparse arguments provided by the user
        """

        result = self.client.modify_project(
            projectname=args.name,
            description=args.description, instructions=args.instructions,
            repos=args.repos, disable_createrepo=args.disable_createrepo)

    @requires_api_auth
    def action_delete(self, args):
        """ Method called when the 'delete' action has been selected by the
        user.

        :param args: argparse arguments provided by the user
        """
        result = self.client.delete_project(projectname=args.copr)
        print(result.message)

    @check_username_presence
    def action_list(self, args):
        """ Method called when the 'list' action has been selected by the
        user.

        :param args: argparse arguments provided by the user

        """
        username = args.username or self.client.username
        result = self.client.get_projects_list(username)
        # import ipdb; ipdb.set_trace()
        if result.output != "ok":
            print(result.error)
            print("Un-expected data returned, please report this issue")
        elif not result.projects_list:
            print("No copr retrieved for user: '******'".format(username))
            return

        for prj in result.projects_list:
            print(prj)

    def action_status(self, args):
        result = self.client.get_build_details(args.build_id)
        print(result.status)

    def action_download_build(self, args):
        result = self.client.get_build_details(args.build_id)
        # TODO: can be simplified after https://bugzilla.redhat.com/show_bug.cgi?id=1133650
        #  and addition of that paths to api

        o = urlparse(result.src_pkg)
        pkgs_name = os.path.split(o.path)[-1]
        assert pkgs_name.endswith(".src.rpm")

        base_url = result.results
        base_len = len(os.path.split(base_url))

        pkg_dir = pkgs_name[:-8]
        for chroot, status in result.data["chroots"].items():
            if args.chroots and chroot not in args.chroots:
                continue

            cmd = "wget -r -nH --no-parent --reject 'index.html*'".split(' ')

            cmd.extend(['-P', os.path.join(args.dest, chroot)])
            cmd.extend(['--cut-dirs', str(base_len + 4)])
            cmd.append("{}{}/{}/".format(base_url, chroot, pkg_dir))

            subprocess.call(cmd)

    @requires_api_auth
    def action_cancel(self, args):
        """ Method called when the 'cancel' action has been selected by the
        user.
        :param args: argparse arguments provided by the user
        """
        result = self.client.cancel_build(args.build_id)
        print(result.status)