Sign In
Sign Up
Sign In
Sign Up
Manage this list
×
Keyboard Shortcuts
Thread View
j
: Next unread message
k
: Previous unread message
j a
: Jump to all threads
j l
: Jump to MailingList overview
2024
April
March
February
January
2023
December
November
October
September
August
July
June
May
April
March
February
January
2022
December
November
October
September
August
July
June
May
April
March
February
January
2021
December
November
October
September
August
July
June
May
April
March
February
January
2020
December
November
October
September
August
July
June
May
April
March
February
January
2019
December
November
October
September
August
July
June
May
April
March
February
January
2018
December
November
October
September
August
July
June
May
April
March
February
January
2017
December
November
October
September
August
July
June
May
April
March
February
January
2016
December
November
October
September
August
July
June
May
April
March
February
January
2015
December
November
October
September
August
July
June
May
April
March
February
January
2014
December
November
October
September
August
July
June
May
April
March
February
January
2013
December
November
October
September
List overview
Download
copr-commits
September 2014
----- 2024 -----
April 2024
March 2024
February 2024
January 2024
----- 2023 -----
December 2023
November 2023
October 2023
September 2023
August 2023
July 2023
June 2023
May 2023
April 2023
March 2023
February 2023
January 2023
----- 2022 -----
December 2022
November 2022
October 2022
September 2022
August 2022
July 2022
June 2022
May 2022
April 2022
March 2022
February 2022
January 2022
----- 2021 -----
December 2021
November 2021
October 2021
September 2021
August 2021
July 2021
June 2021
May 2021
April 2021
March 2021
February 2021
January 2021
----- 2020 -----
December 2020
November 2020
October 2020
September 2020
August 2020
July 2020
June 2020
May 2020
April 2020
March 2020
February 2020
January 2020
----- 2019 -----
December 2019
November 2019
October 2019
September 2019
August 2019
July 2019
June 2019
May 2019
April 2019
March 2019
February 2019
January 2019
----- 2018 -----
December 2018
November 2018
October 2018
September 2018
August 2018
July 2018
June 2018
May 2018
April 2018
March 2018
February 2018
January 2018
----- 2017 -----
December 2017
November 2017
October 2017
September 2017
August 2017
July 2017
June 2017
May 2017
April 2017
March 2017
February 2017
January 2017
----- 2016 -----
December 2016
November 2016
October 2016
September 2016
August 2016
July 2016
June 2016
May 2016
April 2016
March 2016
February 2016
January 2016
----- 2015 -----
December 2015
November 2015
October 2015
September 2015
August 2015
July 2015
June 2015
May 2015
April 2015
March 2015
February 2015
January 2015
----- 2014 -----
December 2014
November 2014
October 2014
September 2014
August 2014
July 2014
June 2014
May 2014
April 2014
March 2014
February 2014
January 2014
----- 2013 -----
December 2013
November 2013
October 2013
September 2013
copr-commits@lists.fedorahosted.org
3 participants
58 discussions
Start a n
N
ew thread
[copr] master: rotate backend.log as well (ed3e7e2)
by Miroslav Suchý
30 Sep '14
30 Sep '14
Repository :
http://git.fedorahosted.org/cgit/copr.git
On branch : master >--------------------------------------------------------------- commit ed3e7e2ad3644c3a687362d6b0220e7188187594 Author: Miroslav Suchý <miroslav(a)suchy.cz> Date: Tue Sep 30 22:32:34 2014 +0200 rotate backend.log as well >--------------------------------------------------------------- backend/logrotate/copr-backend | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/backend/logrotate/copr-backend b/backend/logrotate/copr-backend index 54fe114..020e1cc 100644 --- a/backend/logrotate/copr-backend +++ b/backend/logrotate/copr-backend @@ -1,6 +1,6 @@ # logrotation file for Copr backend -/var/log/copr/copr.log { +/var/log/copr/*.log { weekly rotate 5 copytruncate
1
0
0
0
[copr] master: [cli, python-copr] test coverage for cli, minor fixes for testability in both cli and python (04bad80)
by vgologuz@fedoraproject.org
30 Sep '14
30 Sep '14
Repository :
http://git.fedorahosted.org/cgit/copr.git
On branch : master >--------------------------------------------------------------- commit 04bad80f64711e838e540b17c543d8e0d3849357 Author: Valentin Gologuzov <vgologuz(a)redhat.com> Date: Tue Sep 30 15:59:32 2014 +0200 [cli, python-copr] test coverage for cli, minor fixes for testability in both cli and python >--------------------------------------------------------------- cli/copr_cli/main.py | 384 +++++++++++++++++++----------------- cli/run_tests.sh | 4 + cli/tests/resources/correct.conf | 5 + cli/tests/resources/malformed.conf | 1 + cli/tests/test_cli.py | 131 ++++++++++++ python/copr/client/client.py | 19 ++- 6 files changed, 358 insertions(+), 186 deletions(-) diff --git a/cli/copr_cli/main.py b/cli/copr_cli/main.py index 3f9c97d..0a149f4 100644 --- a/cli/copr_cli/main.py +++ b/cli/copr_cli/main.py @@ -24,179 +24,186 @@ no_config_warning = """ """ -no_config = True -try: - client = CoprClient.create_from_file_config() - no_config = False -except (copr_exceptions.CoprNoConfException, - copr_exceptions.CoprConfigException) as e: - print(no_config_warning) - client = CoprClient({ - "copr_url": "
http://copr.fedoraproject.org
" - }) - -def check_username_presence(func): - def wrapper(args): - if 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 client.username is None: - print("Error: Operation requires username\n" - "Pass username to command or add it to `~/.config/copr`") - - return func(args) - - wrapper.__doc__ = func.__doc__ - wrapper.__name__ = func.__name__ - return wrapper - - -def requires_api_auth(func): - def wrapper(args): - if no_config: - print("Error: Operation requires api authentication\n" - "File `~/.config/copr` is missing or incorrect") - sys.exit(6) - - return func(args) - - wrapper.__doc__ = func.__doc__ - wrapper.__name__ = func.__name__ - return wrapper - - -def _watch_builds(builds_list): - """ - :param builds_list: list of BuildWrapper - - """ - print("Watching build(s): (this may be safely interrupted)") - prevstatus = defaultdict(lambda: None) - failed_ids = [] - watched_ids = [bw.build_id for bw in builds_list] - - try: - while True: - for build_id in watched_ids: - build_details = 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"]: - watched_ids.remove(build_id) - if build_details.status == "unknown": - raise copr_exceptions.CoprBuildException( - "Unknown status.") - - if not watched_ids: - break - time.sleep(3) - - 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(args): - """ Method called when the 'build' action has been selected by the - user. - - :param args: argparse arguments provided by the user - - """ - result = client.create_new_build( - projectname=args.copr, chroots=args.chroots, pkgs=args.pkgs, - memory=args.memory, timeout=args.timeout) - if result.output != "ok": - print(result.error) - return - print(result.message) - print("Created builds: {0}".format(" ".join(map(str, result.builds_list)))) - - if not args.nowait: - _watch_builds(result.builds_list) - - -@requires_api_auth -def action_create(args): - """ Method called when the 'create' action has been selected by the - user. - - :param args: argparse arguments provided by the user - - """ - result = 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_delete(args): - """ Method called when the 'delete' action has been selected by the - user. - - :param args: argparse arguments provided by the user - """ - result = client.delete_project(projectname=args.copr) - print(result.message) - - -@check_username_presence -def action_list(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 client.username - result = client.get_projects_list(username) - 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: '{0}'".format(username)) - return - - for prj in result.projects_list: - print(prj) - - -def action_status(args): - result = client.get_build_details(args.build_id) - print(result.status) - - -@requires_api_auth -def action_cancel(args): - """ Method called when the 'cancel' action has been selected by the - user. - :param args: argparse arguments provided by the user - """ - result = client.cancel_build(args.build_id) - print(result.status) +class Commands(object): + def __init__(self): + + self.no_config = True + try: + self.client = CoprClient.create_from_file_config() + self.no_config = False + #print("CREATED FROM CONFIG") + except (copr_exceptions.CoprNoConfException, + copr_exceptions.CoprConfigException) as e: + print(no_config_warning) + self.client = CoprClient({ + "copr_url": "
http://copr.fedoraproject.org
", + "no_config": True + }) + #print("BBBBBBBBBBBBB") + + def requires_api_auth(func): + """ Decorator that checks config presence + """ + def wrapper(self, args): + if self.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.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`") + + return func(self, args) + + wrapper.__doc__ = func.__doc__ + wrapper.__name__ = func.__name__ + return wrapper + + # def _watch_builds(sefl, builds_list): + # """ + # :param builds_list: list of BuildWrapper + # + # """ + # print("Watching build(s): (this may be safely interrupted)") + # prevstatus = defaultdict(lambda: None) + # failed_ids = [] + # watched_ids = [bw.build_id for bw in builds_list] + # + # try: + # while True: + # for build_id in watched_ids: + # build_details = 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"]: + # watched_ids.remove(build_id) + # if build_details.status == "unknown": + # raise copr_exceptions.CoprBuildException( + # "Unknown status.") + # + # if not watched_ids: + # break + # time.sleep(3) + # + # 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(args): + # """ Method called when the 'build' action has been selected by the + # user. + # + # :param args: argparse arguments provided by the user + # + # """ + # result = client.create_new_build( + # projectname=args.copr, chroots=args.chroots, pkgs=args.pkgs, + # memory=args.memory, timeout=args.timeout) + # if result.output != "ok": + # print(result.error) + # return + # print(result.message) + # print("Created builds: {0}".format(" ".join(map(str, result.builds_list)))) + # + # if not args.nowait: + # _watch_builds(result.builds_list) + # + # + # @requires_api_auth + # def action_create(args): + # """ Method called when the 'create' action has been selected by the + # user. + # + # :param args: argparse arguments provided by the user + # + # """ + # result = 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_delete(args): + # """ Method called when the 'delete' action has been selected by the + # user. + # + # :param args: argparse arguments provided by the user + # """ + # result = 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("Error: {}".format(result.error)) + #print("Un-expected data returned, please report this issue") + elif not result.projects_list: + print("No copr retrieved for user: '{0}'".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) + + @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 setup_parser(): @@ -219,7 +226,7 @@ def setup_parser(): help="The username that you would like to " "list the copr of (defaults to current user)" ) - parser_list.set_defaults(func=action_list) + parser_list.set_defaults(func="action_list") # create the parser for the "create" command parser_create = subparsers.add_parser("create", @@ -238,14 +245,14 @@ def setup_parser(): help="Description of the copr") parser_create.add_argument("--instructions", help="Instructions for the copr") - parser_create.set_defaults(func=action_create) + parser_create.set_defaults(func="action_create") # create the parser for the "delete" command parser_delete = subparsers.add_parser("delete", help="Deletes the entire project") parser_delete.add_argument("copr", help="Name of your project to be deleted.") - parser_delete.set_defaults(func=action_delete) + parser_delete.set_defaults(func="action_delete") # create the parser for the "build" command parser_build = subparsers.add_parser("build", @@ -264,7 +271,7 @@ def setup_parser(): help="") parser_build.add_argument("--nowait", action="store_true", default=False, help="Don't wait for build") - parser_build.set_defaults(func=action_build) + parser_build.set_defaults(func="action_build") # create the parser for the "status" command parser_build = subparsers.add_parser("status", @@ -272,25 +279,42 @@ def setup_parser(): " specified by its ID") parser_build.add_argument("build_id", help="Build ID") - parser_build.set_defaults(func=action_status) + parser_build.set_defaults(func="action_status") # create the parser for the "cancel" command parser_build = subparsers.add_parser("cancel", help="Cancel build specified by its ID") parser_build.add_argument("build_id", help="Build ID") - parser_build.set_defaults(func=action_cancel) + parser_build.set_defaults(func="action_cancel") return parser +import logging + +logging.basicConfig( + level=logging.DEBUG, + format= '[%(asctime)s] {%(pathname)s:%(lineno)d} %(levelname)s - %(message)s', + datefmt='%H:%M:%S' +) + +log = logging.getLogger() +log.info("Logger initiated") + def main(argv=sys.argv[1:]): try: + #print(argv) # Set up parser for global args parser = setup_parser() # Parse the commandline - arg = parser.parse_args() - arg.func(arg) + arg = parser.parse_args(argv) + #arg.func(arg) + + commands = Commands() + #print("Created client: {}".format(commands.client)) + getattr(commands, arg.func)(arg) + except KeyboardInterrupt: sys.stderr.write("\nInterrupted by user.") sys.exit(1) diff --git a/cli/run_tests.sh b/cli/run_tests.sh new file mode 100755 index 0000000..0307c4d --- /dev/null +++ b/cli/run_tests.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +PYTHONPATH=./copr_cli:$PYTHONPATH python -B -m pytest --cov-report term-missing --cov ./copr_cli/ tests +#PYTHONPATH=./src:$PYTHONPATH python3 -B -m pytest --cov-report term-missing --cov ./src tests diff --git a/cli/tests/resources/correct.conf b/cli/tests/resources/correct.conf new file mode 100644 index 0000000..fb0c227 --- /dev/null +++ b/cli/tests/resources/correct.conf @@ -0,0 +1,5 @@ +[copr-cli] +login = 123435 +username = foobar +token = asdtgshrsy24gsdft +copr_url =
http://copr-fe-dev.cloud.fedoraproject.org
diff --git a/cli/tests/resources/malformed.conf b/cli/tests/resources/malformed.conf new file mode 100644 index 0000000..acbe86c --- /dev/null +++ b/cli/tests/resources/malformed.conf @@ -0,0 +1 @@ +abcd diff --git a/cli/tests/test_cli.py b/cli/tests/test_cli.py new file mode 100644 index 0000000..64b83d1 --- /dev/null +++ b/cli/tests/test_cli.py @@ -0,0 +1,131 @@ +from collections import defaultdict +import json +from pprint import pprint +from _pytest.capture import capsys +import pytest + +import six +import copr +from copr.client.parsers import ProjectListParser, CommonMsgErrorOutParser +from copr.client.responses import CoprResponse +from copr.client.exceptions import CoprConfigException, CoprNoConfException +from copr.client import CoprClient +import copr_cli +from copr_cli.main import no_config_warning + + +if six.PY3: + from unittest import mock + from unittest.mock import MagicMock +else: + import mock + from mock import MagicMock + + +import logging + +logging.basicConfig( +level=logging.INFO, +format= '[%(asctime)s] {%(pathname)s:%(lineno)d} %(levelname)s - %(message)s', +datefmt='%H:%M:%S' +) + +log = logging.getLogger() +log.info("Logger initiated") + + +from copr_cli import main + + +(a)mock.patch('copr_cli.main.CoprClient') +def test_cancel_build_no_config(mock_cc, capsys): + #mock_from_config.return_value = CoprClient(dict(no_config=True)) + mock_cc.create_from_file_config.side_effect = CoprNoConfException() + + with pytest.raises(SystemExit) as err: + main.main(argv=["cancel", "123400"]) + + assert err.value.code == 6 + out, err = capsys.readouterr() + assert ("Error: Operation requires api authentication\n" + "File `~/.config/copr` is missing or incorrect\n") in out + + expected_warning = no_config_warning + assert expected_warning in out + + + +(a)mock.patch('copr_cli.main.CoprClient') +def test_cancel_build_response(mock_cc, capsys): + response_status = "foobar" + + mock_client = MagicMock(no_config=False,) + mock_client.cancel_build.return_value = MagicMock(status=response_status) + mock_cc.create_from_file_config.return_value = mock_client + + main.main(argv=["cancel", "123"]) + out, err = capsys.readouterr() + assert "{}\n".format(response_status) in out + + + +(a)mock.patch('copr_cli.main.CoprClient') +def test_list_project(mock_cc, capsys): + response_data = {"output": "ok", + "repos": [ + {u'additional_repos': u'
http://copr-be.cloud.fedoraproject.org/results/rhscl/httpd24/epel-6-$basear…
http://copr-be.cloud.fedoraproject.org/results/msuchy/scl-utils/epel-6-$bas…
http://people.redhat.com/~msuchy/rhscl-1.1-rhel-6-candidate-perl516/
', + u'description': u'A recent stable release of Perl with a number of additional utilities, scripts, and database connectors for MySQL and PostgreSQL. This version provides a large number of new features and enhancements, including new debugging options, improved Unicode support, and better performance.', + u'instructions': u'', + u'name': u'perl516', + u'yum_repos': {u'epel-6-x86_64': u'
http://copr-be.cloud.fedoraproject.org/results/rhscl/perl516/epel-6-x86_64/
'}}, + {u'additional_repos': u'
http://copr-be.cloud.fedoraproject.org/results/msuchy/scl-utils/epel-6-$bas…
http://copr-be.cloud.fedoraproject.org/results/rhscl/httpd24/epel-6-$basear…
http://copr-be.cloud.fedoraproject.org/results/rhscl/v8314/epel-6-$basearch/
', + u'description': u'A recent stable release of Ruby with Rails 3.2.8 and a large collection of Ruby gems. This Software Collection gives developers on Red Hat Enterprise Linux 6 access to Ruby 1.9, which provides a number of new features and enhancements, including improved Unicode support, enhanced threading, and faster load times.', + u'instructions': u'', + u'name': u'ruby193', + u'yum_repos': {u'epel-6-x86_64': u'
http://copr-be.cloud.fedoraproject.org/results/rhscl/ruby193/epel-6-x86_64/
'}}]} + + expected_output = """Name: perl516 + Description: A recent stable release of Perl with a number of additional utilities, scripts, and database connectors for MySQL and PostgreSQL. This version provides a large number of new features and enhancements, including new debugging options, improved Unicode support, and better performance. + Yum repo(s): + epel-6-x86_64:
http://copr-be.cloud.fedoraproject.org/results/rhscl/perl516/epel-6-x86_64/
+ Additional repo:
http://copr-be.cloud.fedoraproject.org/results/rhscl/httpd24/epel-6-$basear…
http://copr-be.cloud.fedoraproject.org/results/msuchy/scl-utils/epel-6-$bas…
http://people.redhat.com/~msuchy/rhscl-1.1-rhel-6-candidate-perl516/
+ +Name: ruby193 + Description: A recent stable release of Ruby with Rails 3.2.8 and a large collection of Ruby gems. This Software Collection gives developers on Red Hat Enterprise Linux 6 access to Ruby 1.9, which provides a number of new features and enhancements, including improved Unicode support, enhanced threading, and faster load times. + Yum repo(s): + epel-6-x86_64:
http://copr-be.cloud.fedoraproject.org/results/rhscl/ruby193/epel-6-x86_64/
+ Additional repo:
http://copr-be.cloud.fedoraproject.org/results/msuchy/scl-utils/epel-6-$bas…
http://copr-be.cloud.fedoraproject.org/results/rhscl/httpd24/epel-6-$basear…
http://copr-be.cloud.fedoraproject.org/results/rhscl/v8314/epel-6-$basearch/
+""" + e2 = """Name: perl516 + Description: A recent stable release of Perl with a number of additional utilities, scripts, and database connectors for MySQL and PostgreSQL. This version provides a large number of new features and enhancements, including new debugging options, improved Unicode support, and better performance. + Yum repo(s): + epel-6-x86_64:
http://copr-be.cloud.fedoraproject.org/results/rhscl/perl516/epel-6-x86_64/
+ Additional repo:
http://copr-be.cloud.fedoraproject.org/results/rhscl/httpd24/epel-6-$basear…
http://copr-be.cloud.fedoraproject.org/results/msuchy/scl-utils/epel-6-$bas…
http://people.redhat.com/~msuchy/rhscl-1.1-rhel-6-candidate-perl516/
+ +Name: ruby193 + Description: A recent stable release of Ruby with Rails 3.2.8 and a large collection of Ruby gems. This Software Collection gives developers on Red Hat Enterprise Linux 6 access to Ruby 1.9, which provides a number of new features and enhancements, including improved Unicode support, enhanced threading, and faster load times. +""" + + # no config + mock_cc.create_from_file_config.side_effect = CoprNoConfException() + mocked_client = MagicMock(CoprClient(dict(no_config=True))) + + control_response = CoprResponse(client=None, method="", data=response_data, + parsers=[ProjectListParser, CommonMsgErrorOutParser]) + mocked_client.get_projects_list.return_value = control_response + mock_cc.return_value = mocked_client + + main.main(argv=["list", "rhscl"]) + + out, err = capsys.readouterr() + assert expected_output in out + + + expected_warning = no_config_warning + assert expected_warning in out + + + + + + diff --git a/python/copr/client/client.py b/python/copr/client/client.py index 9d8c385..77b294a 100644 --- a/python/copr/client/client.py +++ b/python/copr/client/client.py @@ -74,8 +74,9 @@ class CoprClient(object): self.no_config = config.get("no_config", False) def __str__(self): - return "<Copr client. username: {0}, api url: {1}>".format( - self.username, self.api_url + return "<Copr client. username: {0}, api url: {1}, " \ + "login presents: {2}, token presents: {3}>".format( + self.username, self.api_url, bool(self.login), bool(self.token) ) @property @@ -86,13 +87,16 @@ class CoprClient(object): return "{0}/api".format(self.copr_url) @staticmethod - def create_from_file_config(filepath=None): + def create_from_file_config(filepath=None, ignore_error=False): """ Creates Copr client using the information from the config file. :param filepath: specifies config location, default: "~/.config/copr" :type filepath: `str` + :param bool ignore_error: When true creates default Client + without credentionals + :rtype: :py:class:`~.client.CoprClient` """ @@ -105,7 +109,9 @@ class CoprClient(object): log.warning( "No configuration file '~/.config/copr' found. " "See man copr-cli for more information") - config["no_config"] = True + + if not ignore_error: + raise CoprNoConfException() else: try: for field in ["username", "login", "token", "copr_url"]: @@ -115,8 +121,9 @@ class CoprClient(object): config[field] = raw_config.get("copr-cli", field, None) except configparser.Error as err: - raise CoprConfigException( - "Bad configuration file: {0}".format(err)) + if not ignore_error: + raise CoprConfigException( + "Bad configuration file: {0}".format(err)) return CoprClient(config=config) def _fetch(self, url, data=None, projectname=None, username=None,
1
0
0
0
[copr] master: [python-copr, cli] updating copr-cli to use python-copr (f44be6b)
by vgologuz@fedoraproject.org
30 Sep '14
30 Sep '14
Repository :
http://git.fedorahosted.org/cgit/copr.git
On branch : master >--------------------------------------------------------------- commit f44be6b8e9f532187e02c363bfd797f4068870d5 Author: Valentin Gologuzov <vgologuz(a)redhat.com> Date: Thu Sep 25 17:19:40 2014 +0200 [python-copr, cli] updating copr-cli to use python-copr >--------------------------------------------------------------- cli/copr_cli/README.rst | 12 +- cli/copr_cli/main.py | 123 ++++++++++++++----- cli/documentation/Makefile | 34 ------ .../how-to-generate-documentation.txt | 10 -- frontend/coprs_frontend/tests/test_helpers.py | 1 - python/copr/client/client.py | 42 +++++-- python/copr/test/test_client.py | 6 + 7 files changed, 134 insertions(+), 94 deletions(-) diff --git a/cli/copr_cli/README.rst b/cli/copr_cli/README.rst index e46f5ff..b1488f8 100644 --- a/cli/copr_cli/README.rst +++ b/cli/copr_cli/README.rst @@ -29,22 +29,24 @@ The CLI depends on: Usage: ------ -.. _test instance:
http://copr-fe.cloud.fedoraproject.org/
+.. _test instance:
http://copr-fe-dev.cloud.fedoraproject.org/
- Create an account on copr `test instance`_ -- Go to the API page:
http://copr-fe.cloud.fedoraproject.org/api
+- Go to the API page:
http://copr.fedoraproject.org/api
- Retrieve your API token - Create the file ``~/.config/copr`` - In this file add the following content +(simpler way is just to copy it from /api) :: [copr-cli] - username = <insert here your API login> + username = <insert here your login> + login = <insert here your API login> token = <insert here your API token> + copr_url =
https://copr.fedoraproject.org
- -You should then be able to use copr-cli to list, create and build on copr. +You should be able to use copr-cli to list, create and build on copr. .. note:: You can use directly copr-cli to list someone's copr repo but to create a copr or build packages into an existing repo you need to authenticate diff --git a/cli/copr_cli/main.py b/cli/copr_cli/main.py index e4c617e..3f9c97d 100644 --- a/cli/copr_cli/main.py +++ b/cli/copr_cli/main.py @@ -1,4 +1,5 @@ -#-*- coding: UTF-8 -*- +#!/usr/bin/python +# -*- coding: UTF-8 -*- __version__ = "0.3.0" __description__ = "CLI tool to run copr" @@ -14,47 +15,97 @@ from copr import CoprClient import copr.client.exceptions as copr_exceptions +no_config_warning = """ +|================ WARNING: =======================| +|File '~/.config/copr' is missing or incorrect. | +| See documentation: man copr-cli. | +| Any operation requiring credentionals will fail!| +|=================================================| + +""" + +no_config = True try: client = CoprClient.create_from_file_config() -except copr_exceptions.CoprNoConfException as e: - print(e) - sys.exit(1) + no_config = False +except (copr_exceptions.CoprNoConfException, + copr_exceptions.CoprConfigException) as e: + print(no_config_warning) + client = CoprClient({ + "copr_url": "
http://copr.fedoraproject.org
" + }) + + +def check_username_presence(func): + def wrapper(args): + if 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 client.username is None: + print("Error: Operation requires username\n" + "Pass username to command or add it to `~/.config/copr`") + + return func(args) + + wrapper.__doc__ = func.__doc__ + wrapper.__name__ = func.__name__ + return wrapper + + +def requires_api_auth(func): + def wrapper(args): + if no_config: + print("Error: Operation requires api authentication\n" + "File `~/.config/copr` is missing or incorrect") + sys.exit(6) + return func(args) -def _watch_builds(build_ids): + wrapper.__doc__ = func.__doc__ + wrapper.__name__ = func.__name__ + return wrapper + + +def _watch_builds(builds_list): + """ + :param builds_list: list of BuildWrapper + + """ print("Watching build(s): (this may be safely interrupted)") prevstatus = defaultdict(lambda: None) failed_ids = [] - watched_ids = build_ids[:] + watched_ids = [bw.build_id for bw in builds_list] try: while True: for build_id in watched_ids: - build_status = client.get_build_status(build_id) - if build_status.output != "ok": - errmsg = " Build {1}: Unable to get build status: {0}".format( - build_status.error, build_id) + build_details = 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_status.status: - prevstatus[build_id] = build_status.status + 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_status.status, build_id)) + build_details.status, build_id)) - if build_status.status in ["failed"]: + if build_details.status in ["failed"]: failed_ids.append(build_id) - if build_status.status in ["succeeded", "skipped", + if build_details.status in ["succeeded", "skipped", "failed", "canceled"]: watched_ids.remove(build_id) - if build_status.status == "unknown": + if build_details.status == "unknown": raise copr_exceptions.CoprBuildException( "Unknown status.") if not watched_ids: break - time.sleep(60) + time.sleep(3) if failed_ids: raise copr_exceptions.CoprBuildException( @@ -65,6 +116,7 @@ def _watch_builds(build_ids): pass +@requires_api_auth def action_build(args): """ Method called when the 'build' action has been selected by the user. @@ -79,12 +131,13 @@ def action_build(args): print(result.error) return print(result.message) - print("Created builds: {0}".format(" ".join(map(str, result.ids)))) + print("Created builds: {0}".format(" ".join(map(str, result.builds_list)))) if not args.nowait: - _watch_builds(result.ids) + _watch_builds(result.builds_list) +@requires_api_auth def action_create(args): """ Method called when the 'create' action has been selected by the user. @@ -96,9 +149,10 @@ def action_create(args): projectname=args.name, description=args.description, instructions=args.instructions, chroots=args.chroots, repos=args.repos, initial_pkgs=args.initial_pkgs) - print(result) + print(result.message) +@requires_api_auth def action_delete(args): """ Method called when the 'delete' action has been selected by the user. @@ -106,9 +160,10 @@ def action_delete(args): :param args: argparse arguments provided by the user """ result = client.delete_project(projectname=args.copr) - print(result) + print(result.message) +@check_username_presence def action_list(args): """ Method called when the 'list' action has been selected by the user. @@ -118,29 +173,31 @@ def action_list(args): """ username = args.username or client.username result = client.get_projects_list(username) - if result.response["output"] != "ok": + if result.output != "ok": print(result.error) print("Un-expected data returned, please report this issue") - elif not result.projects: + elif not result.projects_list: print("No copr retrieved for user: '{0}'".format(username)) return - for prj in result.projects: + for prj in result.projects_list: print(prj) def action_status(args): - result = client.get_build_status(args.build_id) - print(result) + result = client.get_build_details(args.build_id) + print(result.status) +@requires_api_auth def action_cancel(args): """ Method called when the 'cancel' action has been selected by the user. :param args: argparse arguments provided by the user """ result = client.cancel_build(args.build_id) - print(result) + print(result.status) + def setup_parser(): """ @@ -237,24 +294,24 @@ def main(argv=sys.argv[1:]): except KeyboardInterrupt: sys.stderr.write("\nInterrupted by user.") sys.exit(1) - except copr_exceptions.CoprRequestException, e: + except copr_exceptions.CoprRequestException as e: sys.stderr.write("\nSomething went wrong:") sys.stderr.write("\nError: {0}\n".format(e)) sys.exit(1) - except argparse.ArgumentTypeError, e: + except argparse.ArgumentTypeError as e: sys.stderr.write("\nError: {0}".format(e)) sys.exit(2) - except copr_exceptions.CoprException, e: + except copr_exceptions.CoprException as e: sys.stderr.write("\nError: {0}\n".format(e)) sys.exit(3) - except ConfigParser.ParsingError, e: + except ConfigParser.ParsingError as e: sys.stderr.write("\nError: {0}\n".format(e)) sys.stderr.write("Lines in INI file should not be indented.\n") sys.exit(3) - except copr_exceptions.CoprBuildException, e: + except copr_exceptions.CoprBuildException as e: sys.stderr.write("\nBuild error: {0}\n".format(e)) sys.exit(4) - except copr_exceptions.CoprUnknownResponseException, e: + except copr_exceptions.CoprUnknownResponseException as e: sys.stderr.write("\nError: {0}\n".format(e)) sys.exit(5) # except Exception as e: diff --git a/cli/documentation/Makefile b/cli/documentation/Makefile deleted file mode 100644 index d866287..0000000 --- a/cli/documentation/Makefile +++ /dev/null @@ -1,34 +0,0 @@ -# Copyright 2008, Steve 'Ashcrow' Milner <smilner(a)redhat.com> -# -# This software may be freely redistributed under the terms of the GNU -# general public license. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -BUILD_DIR := build - -# Python doc related -EPYDOC_BIN := `which epydoc` -EPYDOC_SWITCHES := --inheritance listed --graph all --html -PYTHON_DOC_DIR := python-doc -PYTHON_DIRS := ../copr_cli - -# TARGETS -# schema is not incldued here, since you need a live db -all: python - -python: - mkdir -p $(BUILD_DIR)/py-doc-build - $(SHELL ulimit -n 4096) - echo "[epydoc]" > $(BUILD_DIR)/epydoc.lst - echo -n "modules: " >> $(BUILD_DIR)/epydoc.lst - find $(PYTHON_DIRS) -type f -name '*.py' | grep -v test | xargs echo -n >> $(BUILD_DIR)/epydoc.lst - $(EPYDOC_BIN) $(EPYDOC_SWITCHES) -o $(PYTHON_DOC_DIR) --config $(BUILD_DIR)/epydoc.lst - -clean: - rm -rf build/ - -distclean: - rm -rf build/ $(PYTHON_DOC_DIR) $(JAVA_DOC_DIR) $(SCHEMA_DOC_DIR) diff --git a/cli/documentation/how-to-generate-documentation.txt b/cli/documentation/how-to-generate-documentation.txt deleted file mode 100644 index 3af5b30..0000000 --- a/cli/documentation/how-to-generate-documentation.txt +++ /dev/null @@ -1,10 +0,0 @@ -Documentation of python: - # epydoc needs to be installed, it needs texlive, ouch :-( - # graphviz needs to be installed. - # In the Copr git repo checkout, in documentation/ directory: - git rm -rf python-doc - make python - git add python-doc - rm -rf build - # update python-doc.readme - git commit -m 'Updating python documentation.' . diff --git a/frontend/coprs_frontend/tests/test_helpers.py b/frontend/coprs_frontend/tests/test_helpers.py index df019da..4e41748 100644 --- a/frontend/coprs_frontend/tests/test_helpers.py +++ b/frontend/coprs_frontend/tests/test_helpers.py @@ -99,7 +99,6 @@ class TestHelpers(CoprsTestCase): raise e app.config["ENFORCE_PROTOCOL_FOR_BACKEND_URL"] = orig - def test_fix_protocol_for_frontend(self): http_url = "
http://example.com/repo
" https_url = "
https://example.com/repo
" diff --git a/python/copr/client/client.py b/python/copr/client/client.py index 170bdd1..9d8c385 100644 --- a/python/copr/client/client.py +++ b/python/copr/client/client.py @@ -31,6 +31,22 @@ from .parsers import fabric_simple_fields_parser, ProjectListParser, \ ProjectDetailsFieldsParser +## add deco to check that login/token are provided +## and raise correct error +## +## +""" "No configuration file '~/.config/copr' found. " + "see documentation at /usr/share/doc/python-copr/ " +""" +# or +""" + "No api login and\or api token are provided" + "See man copr-cli for more information") +""" + +## + + class CoprClient(object): """ Main interface to the copr service @@ -55,6 +71,8 @@ class CoprClient(object): self.username = config.get("username") self.copr_url = config.get("copr_url", "
http://copr.fedoraproject.org/
") + self.no_config = config.get("no_config", False) + def __str__(self): return "<Copr client. username: {0}, api url: {1}>".format( self.username, self.api_url @@ -84,19 +102,21 @@ class CoprClient(object): filepath = os.path.join(os.path.expanduser("~"), ".config", "copr") config = {} if not raw_config.read(filepath): - raise CoprNoConfException( + log.warning( "No configuration file '~/.config/copr' found. " "See man copr-cli for more information") - try: - for field in ["username", "login", "token", "copr_url"]: - if six.PY3: - config[field] = raw_config["copr-cli"].get(field, None) - else: - config[field] = raw_config.get("copr-cli", field, None) - - except configparser.Error as err: - raise CoprConfigException( - "Bad configuration file: {0}".format(err)) + config["no_config"] = True + else: + try: + for field in ["username", "login", "token", "copr_url"]: + if six.PY3: + config[field] = raw_config["copr-cli"].get(field, None) + else: + config[field] = raw_config.get("copr-cli", field, None) + + except configparser.Error as err: + raise CoprConfigException( + "Bad configuration file: {0}".format(err)) return CoprClient(config=config) def _fetch(self, url, data=None, projectname=None, username=None, diff --git a/python/copr/test/test_client.py b/python/copr/test/test_client.py index bea3179..6d73f97 100644 --- a/python/copr/test/test_client.py +++ b/python/copr/test/test_client.py @@ -33,6 +33,12 @@ def test_client_from_config(): assert cl.token == "api-token" assert cl.username == "user_name" +(a)mock.patch('requests.request') +def test_list_projects(mock_request): + mock_client = CoprClient.create_from_file_config(config_location) + + + # TODO: package
https://github.com/dropbox/responses
and use it def make_mock_response(filename, status_code=None):
1
0
0
0
[copr] master: [keygen] python3 bugfix: decode Popen().communicate output [keygen] added logging, with default location /var/lib/copr-keygen/main.log (efad5eb)
by vgologuz@fedoraproject.org
30 Sep '14
30 Sep '14
Repository :
http://git.fedorahosted.org/cgit/copr.git
On branch : master >--------------------------------------------------------------- commit efad5eb925d405caed1da1312156313ad1a0690e Author: Valentin Gologuzov <vgologuz(a)redhat.com> Date: Thu Sep 25 15:51:52 2014 +0200 [keygen] python3 bugfix: decode Popen().communicate output [keygen] added logging, with default location /var/lib/copr-keygen/main.log >--------------------------------------------------------------- keygen/configs/local_settings.py.example | 3 + keygen/copr-keygen.spec | 5 ++ keygen/run/dev_run.py | 8 ++++ keygen/src/copr_keygen/__init__.py | 27 ++++++++++++ keygen/src/copr_keygen/default_settings.py | 6 ++- keygen/src/copr_keygen/logic.py | 60 ++++++++++++++++++++++----- keygen/tests/test_logic.py | 43 ++++++++++++++++---- 7 files changed, 131 insertions(+), 21 deletions(-) diff --git a/keygen/configs/local_settings.py.example b/keygen/configs/local_settings.py.example index ce83b96..bf26d68 100644 --- a/keygen/configs/local_settings.py.example +++ b/keygen/configs/local_settings.py.example @@ -7,3 +7,6 @@ GNUPG_HOMEDIR = "/var/lib/copr-keygen/gnupg" GPG_KEY_LENGTH = 2048 GPG_EXPIRE = "5y" +LOG_DIR = "/var/log/copr-keygen" +import logging +LOG_LEVEL = logging.INFO diff --git a/keygen/copr-keygen.spec b/keygen/copr-keygen.spec index 638ac3d..01fef65 100644 --- a/keygen/copr-keygen.spec +++ b/keygen/copr-keygen.spec @@ -117,6 +117,7 @@ install -d %{buildroot}%{_datadir}/copr-keygen install -d %{buildroot}%{_bindir} install -d -m 500 %{buildroot}%{_sharedstatedir}/copr-keygen/phrases install -d -m 500 %{buildroot}%{_sharedstatedir}/copr-keygen/gnupg +install -d %{buildroot}%{_localstatedir}/log/copr-keygen %{__install} -p -m 0644 run/gpg_copr.sh %{buildroot}/%{_bindir}/gpg_copr.sh @@ -158,9 +159,13 @@ service httpd condrestart %{_bindir}/gpg_copr.sh + %defattr(600, copr-signer, copr-signer, 700) %{_sharedstatedir}/copr-keygen %config(noreplace) %{_sysconfdir}/copr-keygen +%{_localstatedir}/log/copr-keygen/ +%ghost %{_localstatedir}/log/copr-keygen/main.log + %defattr(600, root, root) %config(noreplace) %{_sysconfdir}/sudoers.d/copr_signer diff --git a/keygen/run/dev_run.py b/keygen/run/dev_run.py index d6b1761..3511bc5 100755 --- a/keygen/run/dev_run.py +++ b/keygen/run/dev_run.py @@ -4,5 +4,13 @@ import sys sys.path.append("../src/") from copr_keygen import app +import logging + +logging.basicConfig( + level=logging.INFO, + format= '[%(asctime)s] {%(pathname)s:%(lineno)d} %(levelname)s - %(message)s', + datefmt='%H:%M:%S' +) + if __name__ == '__main__': app.run() diff --git a/keygen/src/copr_keygen/__init__.py b/keygen/src/copr_keygen/__init__.py index 232f12d..41f19b3 100644 --- a/keygen/src/copr_keygen/__init__.py +++ b/keygen/src/copr_keygen/__init__.py @@ -5,8 +5,12 @@ from __future__ import division from __future__ import absolute_import import json +import logging +from logging import getLogger +from logging.handlers import RotatingFileHandler from flask import Flask, request, Response +import os from copr_keygen.exceptions import BadRequestException, \ KeygenServiceBaseException @@ -15,8 +19,30 @@ app.config.from_object("copr_keygen.default_settings") app.config.from_envvar("COPR_KEYGEN_CONFIG", silent=True) +# setup logger +if not app.config["DEBUG"]: + filename = os.path.join(app.config["LOG_DIR"], "main.log") + if os.path.exists(app.config["LOG_DIR"]): + handler = RotatingFileHandler(filename, + maxBytes=50*1024*1024, + backupCount=5) + handler.setLevel(app.config["LOG_LEVEL"]) + handler.setFormatter(logging.Formatter( + '%(asctime)s %(levelname)s' + '[%(module)s:%(pathname)s:%(lineno)d]' + ': %(message)s ' + )) + logger = getLogger(__name__) + logger.addHandler(handler) + logger.setLevel(app.config["LOG_LEVEL"]) + +# end setup logger + + from .logic import create_new_key, user_exists +log = logging.getLogger(__name__) + @app.route('/ping') def ping(): @@ -112,3 +138,4 @@ def handle_invalid_usage(error): # awk -F: '$1 == "fpr" {print $10;}'" # #TODO: complete implementation + diff --git a/keygen/src/copr_keygen/default_settings.py b/keygen/src/copr_keygen/default_settings.py index 92f1f4a..db44249 100644 --- a/keygen/src/copr_keygen/default_settings.py +++ b/keygen/src/copr_keygen/default_settings.py @@ -1,4 +1,4 @@ -DEBUG = True +DEBUG = False PHRASES_DIR = "/var/lib/copr-keygen/phrases/" GPG_BINARY = "/bin/gpg2" @@ -6,3 +6,7 @@ GNUPG_HOMEDIR = "/var/lib/copr-keygen/gnupg" GPG_KEY_LENGTH = 2048 GPG_EXPIRE = "5y" + +LOG_DIR = "/var/log/copr-keygen" +import logging +LOG_LEVEL = logging.INFO diff --git a/keygen/src/copr_keygen/logic.py b/keygen/src/copr_keygen/logic.py index 779be8e..a19210c 100644 --- a/keygen/src/copr_keygen/logic.py +++ b/keygen/src/copr_keygen/logic.py @@ -1,19 +1,26 @@ +import traceback import os +import logging from subprocess import PIPE, Popen import tempfile +import sys -from .exceptions import GpgErrorException +from .exceptions import GpgErrorException, KeygenServiceBaseException + +log = logging.getLogger(__name__) def ensure_passphrase_exist(app, name_email): """ Need this to tell signd server that `name_email` available in keyring Key not protected by passphrase, so we write *something* to passphrase file. """ + def create(): with open(location, "w") as handle: handle.write("1") handle.write(os.linesep) + log.debug("created passphrase file for {}".format(name_email)) location = os.path.join(app.config["PHRASES_DIR"], name_email) try: @@ -40,18 +47,23 @@ def user_exists(app, mail): handle = Popen(cmd, stdout=PIPE, stderr=PIPE) stdout, stderr = handle.communicate() except Exception as e: + log.exception(e) raise GpgErrorException(msg="unhandled exception during gpg call", cmd=" ".join(cmd), err=e) if handle.returncode == 0: # TODO: validate that we really got exactly one line in stdout + log.debug("user {} has keys in keyring".format(mail)) ensure_passphrase_exist(app, mail) return True - elif "error reading key" in stderr: + elif "error reading key" in stderr.decode(): + log.debug("user {} not found in keyring".format(mail)) return False else: - raise GpgErrorException(msg="unhandled error", cmd=cmd, stdout=stdout, - stderr=stderr) + err = GpgErrorException(msg="unhandled error", cmd=cmd, + stdout=stdout.decode(), stderr=stderr.decode()) + log.error(err) + raise err template = """ @@ -81,12 +93,20 @@ def create_new_key( :return: (stdout, stderr) from `gpg` invocation """ - #TODO with file lock based on usermail !!! + # TODO with file lock based on usermail !!! if user_exists(app, name_email): return - with tempfile.NamedTemporaryFile() as out: + try: + # ! Don't use context manager with delete=True + # TemporaryFile deletes file on .close() not on __exit__() + out = tempfile.NamedTemporaryFile(delete=False) + except Exception as e: + raise KeygenServiceBaseException( + msg="Failed to create tmp file for gen_key", + err=e) + try: out.write(template.format( key_type="RSA", key_length=key_length or 2048, @@ -94,25 +114,43 @@ def create_new_key( comment=name_comment, name_email=name_email, expire=expire or 0).encode('utf-8')) + out.close() + except Exception as e: + raise GpgErrorException(msg="Failed to write tmp file for gen_key", + err=e) cmd = [ - app.config["GPG_BINARY"], "-v", "--batch", + app.config["GPG_BINARY"], "--batch", "--homedir", app.config["GNUPG_HOMEDIR"], "--gen-key", out.name ] + log.debug("CMD: {}".format(' '.join(map(str, cmd)))) try: handle = Popen(cmd, stdout=PIPE, stderr=PIPE) stdout, stderr = handle.communicate() except Exception as e: - raise GpgErrorException(msg="unhandled exception during gpg call", - cmd=" ".join(cmd), err=e) - + log.exception(e) + err = GpgErrorException(msg="unhandled exception during gpg call", + cmd=" ".join(map(str, cmd)), err=e) + log.error(err) + raise err + + log.debug("returncode: {}".format(handle.returncode)) + log.debug("stdout: {}".format(stdout)) + log.debug("stderr: {}".format(stderr)) if handle.returncode == 0: # TODO: validate that we really got armored gpg key if not user_exists(app, name_email): raise GpgErrorException( msg="Key was created, but not found in keyring" "this shouldn't be possible") + log.info("Created key-pair for: {} ".format(name_email)) else: - raise GpgErrorException(msg=stderr) + raise GpgErrorException(msg=stderr.decode()) + + try: + os.remove(out.name) + except Exception as e: + log.error(e) + diff --git a/keygen/tests/test_logic.py b/keygen/tests/test_logic.py index 1c80113..6cabb4f 100644 --- a/keygen/tests/test_logic.py +++ b/keygen/tests/test_logic.py @@ -7,13 +7,15 @@ import six if six.PY3: from unittest import mock + from unittest.mock import patch else: import mock + from mock import patch import pytest from copr_keygen import app -from copr_keygen.exceptions import GpgErrorException +from copr_keygen.exceptions import GpgErrorException, KeygenServiceBaseException from copr_keygen.logic import ensure_passphrase_exist import copr_keygen.logic as logic @@ -92,7 +94,7 @@ class MockPopenHandle(object): self.stderr = stderr or "mock stderr" def communicate(self): - return self.stdout, self.stderr + return self.stdout.encode(), self.stderr.encode() @mock.patch("copr_keygen.logic.ensure_passphrase_exist") @@ -129,13 +131,19 @@ class TestGenKey(TestCase): it exists """ - user_exists_returns = [False, True] - user_exists.side_effect = \ - lambda *args, **kwargs: user_exists_returns.pop(0) - popen.return_value = MockPopenHandle(0) + with mock.patch("tempfile.NamedTemporaryFile") as tmpfile: + user_exists_returns = [False, True] + user_exists.side_effect = \ + lambda *args, **kwargs: user_exists_returns.pop(0) + + def check_gpg_genkey_file_exists(*args, **kwargs): + assert tmpfile.called + return MockPopenHandle(0) + + popen.side_effect = check_gpg_genkey_file_exists - res = logic.create_new_key(app, TEST_NAME, TEST_EMAIL, TEST_KEYLENGTH) - assert res is None + res = logic.create_new_key(app, TEST_NAME, TEST_EMAIL, TEST_KEYLENGTH) + assert res is None def test_strange_situation_create(self, popen, user_exists): """ @@ -168,4 +176,21 @@ class TestGenKey(TestCase): popen.return_value = MockPopenHandle(1, stderr=err_msg) with pytest.raises(GpgErrorException) as e: logic.create_new_key(app, TEST_NAME, TEST_EMAIL, TEST_KEYLENGTH) - assert e.msg == err_msg + assert e.message == err_msg + + def test_tmpfiles_errors(self, popen, user_exists): + user_exists.return_value = False + + with mock.patch("tempfile.NamedTemporaryFile") as tmpfile: + tmpfile.side_effect = OSError() + with pytest.raises(KeygenServiceBaseException) as e: + logic.create_new_key(app, TEST_NAME, TEST_EMAIL, TEST_KEYLENGTH) + + assert not popen.called + + with mock.patch("tempfile.NamedTemporaryFile") as tmpfile: + tmpfile.return_value.write.side_effect = OSError() + with pytest.raises(KeygenServiceBaseException) as e: + logic.create_new_key(app, TEST_NAME, TEST_EMAIL, TEST_KEYLENGTH) + + assert not popen.called
1
0
0
0
[copr] tag 'copr-keygen-1.57-1' created
by vgologuz@fedoraproject.org
24 Sep '14
24 Sep '14
Repository :
http://git.fedorahosted.org/cgit/copr.git
New tag : copr-keygen-1.57-1 Referencing: f6972a0130be1b973ea52a2b4ba2f5c5ebcf9fe3
1
0
0
0
[copr] master: Automatic commit of package [copr-keygen] release [1.57-1]. (86bc329)
by vgologuz@fedoraproject.org
24 Sep '14
24 Sep '14
Repository :
http://git.fedorahosted.org/cgit/copr.git
On branch : master >--------------------------------------------------------------- commit 86bc3299e5b0291eba5a369664b1553a370b266a Author: Valentin Gologuzov <vgologuz(a)redhat.com> Date: Wed Sep 24 17:55:16 2014 +0200 Automatic commit of package [copr-keygen] release [1.57-1]. >--------------------------------------------------------------- keygen/copr-keygen.spec | 7 ++++++- rel-eng/packages/copr-keygen | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/keygen/copr-keygen.spec b/keygen/copr-keygen.spec index 914539f..638ac3d 100644 --- a/keygen/copr-keygen.spec +++ b/keygen/copr-keygen.spec @@ -7,7 +7,7 @@ # this package doesn't support rhel7- since it doesn't have python3* packages Name: copr-keygen -Version: 1.56 +Version: 1.57 Release: 1%{?dist} Summary: Part of Copr build system. Aux service that generate keys for sign. @@ -170,6 +170,11 @@ service httpd condrestart %changelog +* Wed Sep 24 2014 Valentin Gologuzov <vgologuz(a)redhat.com> 1.57-1 +- [keygen] changed shebang in run scripts to #!/usr/bin/python3, Requires: + {,python3-}mod_wsgi +- [keygen] package only python3 version, targeting f19+ + * Mon Sep 22 2014 Valentin Gologuzov <vgologuz(a)redhat.com> 1.56-1 - [keygen] .spec: run tests, build py3 version for fedora - [keygen] py3 compatibility diff --git a/rel-eng/packages/copr-keygen b/rel-eng/packages/copr-keygen index d0cc52d..b33d0b7 100644 --- a/rel-eng/packages/copr-keygen +++ b/rel-eng/packages/copr-keygen @@ -1 +1 @@ -1.56-1 keygen/ +1.57-1 keygen/
1
0
0
0
[copr] master: [keygen] changed shebang in run scripts to #!/usr/bin/python3, Requires: {, python3-}mod_wsgi (ebac49b)
by vgologuz@fedoraproject.org
24 Sep '14
24 Sep '14
Repository :
http://git.fedorahosted.org/cgit/copr.git
On branch : master >--------------------------------------------------------------- commit ebac49b971e3ed0405762cac8989bf1cf8739070 Author: Valentin Gologuzov <vgologuz(a)redhat.com> Date: Wed Sep 24 17:48:46 2014 +0200 [keygen] changed shebang in run scripts to #!/usr/bin/python3, Requires: {,python3-}mod_wsgi >--------------------------------------------------------------- keygen/copr-keygen.spec | 3 ++- keygen/run/application.py | 2 +- keygen/run/dev_run.py | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/keygen/copr-keygen.spec b/keygen/copr-keygen.spec index 01aa093..914539f 100644 --- a/keygen/copr-keygen.spec +++ b/keygen/copr-keygen.spec @@ -40,7 +40,7 @@ BuildRequires: python-sphinxcontrib-httpdomain Requires: haveged Requires: gnupg -Requires: mod_wsgi +Requires: python3-mod_wsgi Requires: httpd Requires: obs-signd Requires: passwd @@ -161,6 +161,7 @@ service httpd condrestart %defattr(600, copr-signer, copr-signer, 700) %{_sharedstatedir}/copr-keygen %config(noreplace) %{_sysconfdir}/copr-keygen +%defattr(600, root, root) %config(noreplace) %{_sysconfdir}/sudoers.d/copr_signer diff --git a/keygen/run/application.py b/keygen/run/application.py index f4ecadb..b8f79ed 100644 --- a/keygen/run/application.py +++ b/keygen/run/application.py @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/python3 import logging import os import sys diff --git a/keygen/run/dev_run.py b/keygen/run/dev_run.py index dd051d5..d6b1761 100755 --- a/keygen/run/dev_run.py +++ b/keygen/run/dev_run.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/python3 import sys sys.path.append("../src/")
1
0
0
0
[copr] tag 'copr-frontend-1.46-1' created
by vgologuz@fedoraproject.org
24 Sep '14
24 Sep '14
Repository :
http://git.fedorahosted.org/cgit/copr.git
New tag : copr-frontend-1.46-1 Referencing: f6357cd2e3997220ef8a4421ffaf05b0464f99c7
1
0
0
0
[copr] master: Automatic commit of package [copr-frontend] release [1.46-1]. (de99524)
by vgologuz@fedoraproject.org
24 Sep '14
24 Sep '14
Repository :
http://git.fedorahosted.org/cgit/copr.git
On branch : master >--------------------------------------------------------------- commit de9952431cb80ff8119cf5fe4988a183bf906f36 Author: Valentin Gologuzov <vgologuz(a)redhat.com> Date: Wed Sep 24 12:51:34 2014 +0200 Automatic commit of package [copr-frontend] release [1.46-1]. >--------------------------------------------------------------- frontend/copr-frontend.spec | 6 +++++- rel-eng/packages/copr-frontend | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/frontend/copr-frontend.spec b/frontend/copr-frontend.spec index c72ad51..30879e6 100644 --- a/frontend/copr-frontend.spec +++ b/frontend/copr-frontend.spec @@ -5,7 +5,7 @@ %endif Name: copr-frontend -Version: 1.45 +Version: 1.46 Release: 1%{?dist} Summary: Frontend for Copr @@ -167,6 +167,10 @@ service httpd condrestart %doc %{_pkgdocdir}/python-doc %changelog +* Wed Sep 24 2014 Valentin Gologuzov <vgologuz(a)redhat.com> 1.46-1 +- [frontend] added helper function and flask filter which allows to ensure that + url starts with either http or https, see config + * Thu Sep 18 2014 Miroslav Suchý <msuchy(a)redhat.com> 1.45-1 - revert f0e5c211f86cc3691fda8d4412c21ef6338a339f - [frontend] including project name diff --git a/rel-eng/packages/copr-frontend b/rel-eng/packages/copr-frontend index cb90fc7..6faf745 100644 --- a/rel-eng/packages/copr-frontend +++ b/rel-eng/packages/copr-frontend @@ -1 +1 @@ -1.45-1 frontend/ +1.46-1 frontend/
1
0
0
0
[copr] master: [keygen] changed default config options for ENFORCE_PROTOCOL_FOR_*_URL to None (5a4e53e)
by vgologuz@fedoraproject.org
24 Sep '14
24 Sep '14
Repository :
http://git.fedorahosted.org/cgit/copr.git
On branch : master >--------------------------------------------------------------- commit 5a4e53e6097b09da4ea432e0fe5658a36aaad967 Author: Valentin Gologuzov <vgologuz(a)redhat.com> Date: Wed Sep 24 12:49:20 2014 +0200 [keygen] changed default config options for ENFORCE_PROTOCOL_FOR_*_URL to None >--------------------------------------------------------------- frontend/coprs_frontend/coprs/config.py | 10 +++++----- frontend/coprs_frontend/coprs/helpers.py | 1 + 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/frontend/coprs_frontend/coprs/config.py b/frontend/coprs_frontend/coprs/config.py index 15ef753..e5abfb9 100644 --- a/frontend/coprs_frontend/coprs/config.py +++ b/frontend/coprs_frontend/coprs/config.py @@ -32,11 +32,11 @@ class Config(object): SEND_LEGAL_TO = ["root@localhost"] - # prefer http or https, default setting preserve old behaviour - USE_HTTPS_FOR_RESULTS = True - - ENFORCE_PROTOCOL_FOR_BACKEND_URL = "https" - ENFORCE_PROTOCOL_FOR_FRONTEND_URL = "https" + # post-process url leading to backend + # possible options: None, "http", "https" + ENFORCE_PROTOCOL_FOR_BACKEND_URL = None + ## post-process url leading to frontend + ENFORCE_PROTOCOL_FOR_FRONTEND_URL = None class ProductionConfig(Config): diff --git a/frontend/coprs_frontend/coprs/helpers.py b/frontend/coprs_frontend/coprs/helpers.py index 1740da3..d6da5c6 100644 --- a/frontend/coprs_frontend/coprs/helpers.py +++ b/frontend/coprs_frontend/coprs/helpers.py @@ -186,6 +186,7 @@ def fix_protocol_for_frontend(url): else: return url + class Serializer(object): def to_dict(self, options=None):
1
0
0
0
← Newer
1
2
3
4
5
6
Older →
Jump to page:
1
2
3
4
5
6
Results per page:
10
25
50
100
200