| |
@@ -5,6 +5,7 @@
|
| |
import hashlib
|
| |
import logging
|
| |
import os
|
| |
+ import re
|
| |
import shutil
|
| |
import subprocess
|
| |
import sys
|
| |
@@ -17,7 +18,7 @@
|
| |
import koji_cli.lib
|
| |
import pyrpkg.cli
|
| |
import utils
|
| |
- from mock import Mock, PropertyMock, call, mock_open, patch
|
| |
+ from mock import ANY, Mock, PropertyMock, call, mock_open, patch
|
| |
from pyrpkg import Commands, Modulemd, rpkgError
|
| |
from utils import CommandTestCase, FakeThreadPool
|
| |
|
| |
@@ -56,6 +57,12 @@
|
| |
# The SafeConfigParser class has been renamed to ConfigParser in Python 3.2.
|
| |
ConfigParser = configparser.ConfigParser
|
| |
|
| |
+ KOJI_UNIQUE_PATH_REGEX = r'^cli-build/\d+\.\d+\.[a-zA-Z]+$'
|
| |
+
|
| |
+
|
| |
+ def mock_get_rpm_package_name(self, rpm_file):
|
| |
+ return(os.path.basename(rpm_file)[:-len('.src.rpm')])
|
| |
+
|
| |
|
| |
class CliTestCase(CommandTestCase):
|
| |
|
| |
@@ -1936,11 +1943,52 @@
|
| |
os.path.join(cli.cmd.path, patch_file))
|
| |
|
| |
|
| |
+ class FakeKojiCreds(object):
|
| |
+
|
| |
+ @classmethod
|
| |
+ def setUpClass(cls):
|
| |
+ super(FakeKojiCreds, cls).setUpClass()
|
| |
+
|
| |
+ fake_koji_config = dict(
|
| |
+ authtype='kerberos',
|
| |
+ server='http://localhost/kojihub',
|
| |
+ weburl='http://localhost/koji',
|
| |
+ topurl='http://kojipkgs.localhost/',
|
| |
+ cert='',
|
| |
+ )
|
| |
+ cls.read_config_p = patch('koji.read_config',
|
| |
+ return_value=fake_koji_config)
|
| |
+ cls.mock_read_config = cls.read_config_p.start()
|
| |
+ cls.load_krb_user_p = patch('pyrpkg.Commands._load_krb_user')
|
| |
+ cls.mock_load_krb_user = cls.load_krb_user_p.start()
|
| |
+
|
| |
+ cls.has_krb_creds_p = patch('pyrpkg.Commands._has_krb_creds',
|
| |
+ return_value=True)
|
| |
+ cls.mock_has_krb_creds = cls.has_krb_creds_p.start()
|
| |
+
|
| |
+ @classmethod
|
| |
+ def tearDownClass(cls):
|
| |
+ cls.has_krb_creds_p.stop()
|
| |
+ cls.load_krb_user_p.stop()
|
| |
+ cls.read_config_p.stop()
|
| |
+ super(FakeKojiCreds, cls).tearDownClass()
|
| |
+
|
| |
+ def setUp(self):
|
| |
+ super(FakeKojiCreds, self).setUp()
|
| |
+
|
| |
+ self.ClientSession_p = patch('koji.ClientSession')
|
| |
+ self.mock_ClientSession = self.ClientSession_p.start()
|
| |
+
|
| |
+ def tearDown(self):
|
| |
+ self.ClientSession_p.stop()
|
| |
+ super(FakeKojiCreds, self).tearDown()
|
| |
+
|
| |
+
|
| |
@unittest.skipUnless(
|
| |
openidc_client,
|
| |
'Skip if rpkg is rebuilt for an environment where Kerberos authentication'
|
| |
'is used and python-openidc-client is not available.')
|
| |
- class TestModulesCli(CliTestCase):
|
| |
+ class TestModulesCli(FakeKojiCreds, CliTestCase):
|
| |
"""Test module commands"""
|
| |
|
| |
create_repo_per_test = False
|
| |
@@ -1995,6 +2043,17 @@
|
| |
'version': '20171010145511'
|
| |
}
|
| |
|
| |
+ @classmethod
|
| |
+ def setUpClass(cls):
|
| |
+ super(TestModulesCli, cls).setUpClass()
|
| |
+
|
| |
+ @classmethod
|
| |
+ def tearDownClass(cls):
|
| |
+ super(TestModulesCli, cls).tearDownClass()
|
| |
+
|
| |
+ def setUp(self):
|
| |
+ super(TestModulesCli, self).setUp()
|
| |
+
|
| |
def tearDown(self):
|
| |
super(TestModulesCli, self).tearDown()
|
| |
|
| |
@@ -2039,7 +2098,9 @@
|
| |
exp_json = {
|
| |
'scmurl': ('git://pkgs.fedoraproject.org/modules/testmodule?'
|
| |
'#79d87a5a'),
|
| |
- 'branch': 'master'}
|
| |
+ 'branch': 'master',
|
| |
+ 'scratch': False,
|
| |
+ }
|
| |
mock_oidc_req.assert_called_once_with(
|
| |
exp_url,
|
| |
http_method='POST',
|
| |
@@ -2091,7 +2152,9 @@
|
| |
exp_json = {
|
| |
'scmurl': ('git://pkgs.fedoraproject.org/modules/testmodule?'
|
| |
'#79d87a5a'),
|
| |
- 'branch': 'master'}
|
| |
+ 'branch': 'master',
|
| |
+ 'scratch': False,
|
| |
+ }
|
| |
mock_oidc_req.assert_called_once_with(
|
| |
exp_url,
|
| |
http_method='POST',
|
| |
@@ -2170,6 +2233,7 @@
|
| |
'scmurl': ('git://pkgs.fedoraproject.org/modules/testmodule?'
|
| |
'#79d87a5a'),
|
| |
'branch': '10-LP-f27.0.1',
|
| |
+ 'scratch': False,
|
| |
'buildrequire_overrides': {'platform': ['f27.0.1']}
|
| |
}
|
| |
exp_url = ('https://mbs.fedoraproject.org/module-build-service/2/'
|
| |
@@ -2211,6 +2275,7 @@
|
| |
'scmurl': ('git://pkgs.fedoraproject.org/modules/testmodule?'
|
| |
'#79d87a5a'),
|
| |
'branch': '10-fedora-27.0.1',
|
| |
+ 'scratch': False,
|
| |
'buildrequire_overrides': {'platform': ['f29']}
|
| |
}
|
| |
exp_url = ('https://mbs.fedoraproject.org/module-build-service/2/'
|
| |
@@ -2281,8 +2346,210 @@
|
| |
'https://mbs.fedoraproject.org/module-build-service/1/about/',
|
| |
timeout=60
|
| |
)
|
| |
- # Can't verify the calls since the SCM commit hash always changes
|
| |
- mock_oidc_req.assert_called_once()
|
| |
+ exp_url = ('https://mbs.fedoraproject.org/module-build-service/2/'
|
| |
+ 'module-builds/')
|
| |
+ exp_json = {
|
| |
+ 'scmurl': ANY,
|
| |
+ 'branch': 'master',
|
| |
+ 'scratch': False,
|
| |
+ }
|
| |
+ mock_oidc_req.assert_called_once_with(
|
| |
+ exp_url,
|
| |
+ http_method='POST',
|
| |
+ json=exp_json,
|
| |
+ scopes=self.scopes,
|
| |
+ timeout=120)
|
| |
+
|
| |
+ @patch('sys.stdout', new=StringIO())
|
| |
+ @patch('requests.get')
|
| |
+ @patch('openidc_client.OpenIDCClient.send_request')
|
| |
+ def test_module_build_scratch(self, mock_oidc_req, mock_get):
|
| |
+ """
|
| |
+ Test a scratch module build with default parameters
|
| |
+ """
|
| |
+ cli_cmd = [
|
| |
+ 'rpkg',
|
| |
+ '--path',
|
| |
+ self.cloned_repo_path,
|
| |
+ 'module-scratch-build',
|
| |
+ ]
|
| |
+ mock_get.return_value.ok = True
|
| |
+ mock_get.return_value.json.return_value = {
|
| |
+ 'auth_method': 'oidc',
|
| |
+ 'api_version': 2
|
| |
+ }
|
| |
+ mock_oidc_req.return_value.json.return_value = [{'id': 1094}]
|
| |
+
|
| |
+ with patch('sys.argv', new=cli_cmd):
|
| |
+ cli = self.new_cli()
|
| |
+ cli.module_scratch_build()
|
| |
+
|
| |
+ output = sys.stdout.getvalue().strip()
|
| |
+ expected_output = (
|
| |
+ 'Submitting the module build...',
|
| |
+ 'The build 1094 was submitted to the MBS',
|
| |
+ 'Build URLs:',
|
| |
+ cli.cmd.module_get_url(1094, verbose=False),
|
| |
+ )
|
| |
+ self.assertEqual(output, '\n'.join(expected_output))
|
| |
+ mock_get.assert_called_once_with(
|
| |
+ 'https://mbs.fedoraproject.org/module-build-service/1/about/',
|
| |
+ timeout=60
|
| |
+ )
|
| |
+ exp_url = ('https://mbs.fedoraproject.org/module-build-service/2/'
|
| |
+ 'module-builds/')
|
| |
+ exp_json = {
|
| |
+ 'scmurl': ANY,
|
| |
+ 'branch': 'master',
|
| |
+ 'scratch': True,
|
| |
+ }
|
| |
+ mock_oidc_req.assert_called_once_with(
|
| |
+ exp_url,
|
| |
+ http_method='POST',
|
| |
+ json=exp_json,
|
| |
+ scopes=self.scopes,
|
| |
+ timeout=120)
|
| |
+
|
| |
+ @patch('sys.stdout', new=StringIO())
|
| |
+ @patch('requests.get')
|
| |
+ @patch('openidc_client.OpenIDCClient.send_request')
|
| |
+ def test_module_build_with_scratch_option(self, mock_oidc_req, mock_get):
|
| |
+ """
|
| |
+ Test a scratch module build with default parameters using scratch option
|
| |
+ """
|
| |
+ cli_cmd = [
|
| |
+ 'rpkg',
|
| |
+ '--path',
|
| |
+ self.cloned_repo_path,
|
| |
+ 'module-build',
|
| |
+ '--scratch'
|
| |
+ ]
|
| |
+ mock_get.return_value.ok = True
|
| |
+ mock_get.return_value.json.return_value = {
|
| |
+ 'auth_method': 'oidc',
|
| |
+ 'api_version': 2
|
| |
+ }
|
| |
+ mock_oidc_req.return_value.json.return_value = [{'id': 1094}]
|
| |
+
|
| |
+ with patch('sys.argv', new=cli_cmd):
|
| |
+ cli = self.new_cli()
|
| |
+ cli.module_build()
|
| |
+
|
| |
+ output = sys.stdout.getvalue().strip()
|
| |
+ expected_output = (
|
| |
+ 'Submitting the module build...',
|
| |
+ 'The build 1094 was submitted to the MBS',
|
| |
+ 'Build URLs:',
|
| |
+ cli.cmd.module_get_url(1094, verbose=False),
|
| |
+ )
|
| |
+ self.assertEqual(output, '\n'.join(expected_output))
|
| |
+ mock_get.assert_called_once_with(
|
| |
+ 'https://mbs.fedoraproject.org/module-build-service/1/about/',
|
| |
+ timeout=60
|
| |
+ )
|
| |
+ exp_url = ('https://mbs.fedoraproject.org/module-build-service/2/'
|
| |
+ 'module-builds/')
|
| |
+ exp_json = {
|
| |
+ 'scmurl': ANY,
|
| |
+ 'branch': 'master',
|
| |
+ 'scratch': True,
|
| |
+ }
|
| |
+ mock_oidc_req.assert_called_once_with(
|
| |
+ exp_url,
|
| |
+ http_method='POST',
|
| |
+ json=exp_json,
|
| |
+ scopes=self.scopes,
|
| |
+ timeout=120)
|
| |
+
|
| |
+ @patch('sys.stdout', new=StringIO())
|
| |
+ @patch('pyrpkg.cli.cliClient._get_rpm_package_name', new=mock_get_rpm_package_name)
|
| |
+ @patch('requests.get')
|
| |
+ @patch('openidc_client.OpenIDCClient.send_request')
|
| |
+ def test_module_build_scratch_with_modulemd_and_srpms(self, mock_oidc_req, mock_get):
|
| |
+ """
|
| |
+ Test a scratch module build with provided modulemd and srpms
|
| |
+ """
|
| |
+
|
| |
+ file_path = os.path.join(self.cloned_repo_path, "modulemd.yaml")
|
| |
+ pkg1_path = os.path.join(self.cloned_repo_path, "package1.src.rpm")
|
| |
+ pkg2_path = os.path.join(self.cloned_repo_path, "package2.src.rpm")
|
| |
+
|
| |
+ cli_cmd = [
|
| |
+ 'rpkg',
|
| |
+ '--path',
|
| |
+ self.cloned_repo_path,
|
| |
+ 'module-scratch-build',
|
| |
+ '--srpm',
|
| |
+ pkg1_path,
|
| |
+ '--file',
|
| |
+ file_path,
|
| |
+ '--srpm',
|
| |
+ pkg2_path,
|
| |
+ ]
|
| |
+
|
| |
+ mock_get.return_value.ok = True
|
| |
+ mock_get.return_value.json.return_value = {
|
| |
+ 'auth_method': 'oidc',
|
| |
+ 'api_version': 2
|
| |
+ }
|
| |
+ mock_oidc_req.return_value.json.return_value = [{'id': 1094}]
|
| |
+
|
| |
+ with patch('sys.argv', new=cli_cmd):
|
| |
+ cli = self.new_cli()
|
| |
+ # we create empty files for the purpose of this test so we don't
|
| |
+ # raise an exception
|
| |
+ open(file_path, 'a').close()
|
| |
+ open(pkg1_path, 'a').close()
|
| |
+ open(pkg2_path, 'a').close()
|
| |
+ cli.module_scratch_build()
|
| |
+
|
| |
+ output = sys.stdout.getvalue().strip()
|
| |
+ expected_output = (
|
| |
+ 'Submitting the module build...',
|
| |
+ 'The build 1094 was submitted to the MBS',
|
| |
+ 'Build URLs:',
|
| |
+ cli.cmd.module_get_url(1094, verbose=False),
|
| |
+ )
|
| |
+ self.assertEqual(output, '\n'.join(expected_output))
|
| |
+ mock_get.assert_called_once_with(
|
| |
+ 'https://mbs.fedoraproject.org/module-build-service/1/about/',
|
| |
+ timeout=60
|
| |
+ )
|
| |
+ exp_url = ('https://mbs.fedoraproject.org/module-build-service/2/'
|
| |
+ 'module-builds/')
|
| |
+ exp_json = {
|
| |
+ 'scmurl': ANY,
|
| |
+ 'branch': 'master',
|
| |
+ 'scratch': True,
|
| |
+ 'modulemd': '',
|
| |
+ 'module_name': 'modulemd',
|
| |
+ 'srpms': ANY,
|
| |
+ }
|
| |
+ mock_oidc_req.assert_called_once_with(
|
| |
+ exp_url,
|
| |
+ http_method='POST',
|
| |
+ json=exp_json,
|
| |
+ scopes=self.scopes,
|
| |
+ timeout=120)
|
| |
+
|
| |
+ args, kwargs = mock_oidc_req.call_args
|
| |
+
|
| |
+ # verify that OIDC request srpms argument contains a list of links
|
| |
+ # exactly corresponding to the provided SRPM paths
|
| |
+ srpm_paths = [pkg1_path, pkg2_path]
|
| |
+ req_srpms = kwargs['json']['srpms']
|
| |
+ self.assertEqual(len(req_srpms), len(srpm_paths))
|
| |
+ for srpm_path in srpm_paths:
|
| |
+ filename = os.path.basename(srpm_path)
|
| |
+ srpm_link_regex = '{0}/{1}$'.format(KOJI_UNIQUE_PATH_REGEX.rstrip('$'), filename)
|
| |
+ p = re.compile(srpm_link_regex)
|
| |
+ srpm_link_found = False
|
| |
+ for srpm_link in req_srpms:
|
| |
+ if p.match(srpm_link):
|
| |
+ srpm_link_found = True
|
| |
+ break
|
| |
+ self.assertTrue(srpm_link_found,
|
| |
+ "Did not find srpm {0} amongst {1}".format(filename, req_srpms))
|
| |
|
| |
@patch('sys.stdout', new=StringIO())
|
| |
@patch('requests.get')
|
| |
@@ -2425,6 +2692,7 @@
|
| |
Name: python3-ecosystem
|
| |
Stream: master
|
| |
Version: 20171010145511
|
| |
+ Scratch: False
|
| |
Koji Tag: module-14050f52e62d955b
|
| |
Owner: torsava
|
| |
State: failed
|
| |
@@ -2698,6 +2966,45 @@
|
| |
file_path, '--stream', 'test'], env={})
|
| |
|
| |
@patch.object(Commands, '_run_command')
|
| |
+ def test_module_build_local_with_modulemd_and_srpms(self, mock_run):
|
| |
+ """
|
| |
+ Test submitting a local module build with provided modulemd and srpms
|
| |
+ """
|
| |
+
|
| |
+ file_path = os.path.join(self.cloned_repo_path, 'modulemd.yaml')
|
| |
+ pkg1_path = os.path.join(self.cloned_repo_path, "package1.src.rpm")
|
| |
+ pkg2_path = os.path.join(self.cloned_repo_path, "package2.src.rpm")
|
| |
+
|
| |
+ cli_cmd = [
|
| |
+ 'rpkg',
|
| |
+ '--path',
|
| |
+ self.cloned_repo_path,
|
| |
+ 'module-build-local',
|
| |
+ '--file',
|
| |
+ file_path,
|
| |
+ '--srpm',
|
| |
+ pkg1_path,
|
| |
+ '--srpm',
|
| |
+ pkg2_path,
|
| |
+ '--stream',
|
| |
+ 'test'
|
| |
+ ]
|
| |
+ mock_proc = Mock()
|
| |
+ mock_proc.returncode = 0
|
| |
+ mock_run.return_value = mock_proc
|
| |
+ with patch('sys.argv', new=cli_cmd):
|
| |
+ cli = self.new_cli()
|
| |
+ # we create empty files for the purpose of this test so we don't raise an exception
|
| |
+ open(file_path, 'a').close()
|
| |
+ open(pkg1_path, 'a').close()
|
| |
+ open(pkg2_path, 'a').close()
|
| |
+ cli.module_build_local()
|
| |
+
|
| |
+ mock_run.assert_called_once_with(['mbs-manager', 'build_module_locally',
|
| |
+ '--file', file_path, '--stream', 'test',
|
| |
+ '--srpm', pkg1_path, '--srpm', pkg2_path], env={})
|
| |
+
|
| |
+ @patch.object(Commands, '_run_command')
|
| |
def test_module_build_local_with_skiptests(self, mock_run):
|
| |
"""
|
| |
Test submitting a local module build with skiptests
|
| |
@@ -2931,47 +3238,23 @@
|
| |
self.assertEqual('modules', cli.cmd.ns)
|
| |
|
| |
|
| |
- class TestBuildPackage(CliTestCase):
|
| |
+ class TestBuildPackage(FakeKojiCreds, CliTestCase):
|
| |
"""Test build package, common build, scratch build and chain build"""
|
| |
|
| |
create_repo_per_test = False
|
| |
- UNIQUE_PATH_REGEX = r'^cli-build/\d+\.\d+\.[a-zA-Z]+$'
|
| |
|
| |
@classmethod
|
| |
def setUpClass(cls):
|
| |
super(TestBuildPackage, cls).setUpClass()
|
| |
cls.checkout_branch(git.Repo(cls.cloned_repo_path), 'rhel-7')
|
| |
|
| |
- fake_koji_config = dict(
|
| |
- authtype='kerberos',
|
| |
- server='http://localhost/kojihub',
|
| |
- weburl='http://localhost/koji',
|
| |
- topurl='http://kojipkgs.localhost/',
|
| |
- cert='',
|
| |
- )
|
| |
- cls.read_config_p = patch('koji.read_config',
|
| |
- return_value=fake_koji_config)
|
| |
- cls.mock_read_config = cls.read_config_p.start()
|
| |
- cls.load_krb_user_p = patch('pyrpkg.Commands._load_krb_user')
|
| |
- cls.mock_load_krb_user = cls.load_krb_user_p.start()
|
| |
-
|
| |
- cls.has_krb_creds_p = patch('pyrpkg.Commands._has_krb_creds',
|
| |
- return_value=True)
|
| |
- cls.mock_has_krb_creds = cls.has_krb_creds_p.start()
|
| |
-
|
| |
@classmethod
|
| |
def tearDownClass(cls):
|
| |
- cls.has_krb_creds_p.stop()
|
| |
- cls.load_krb_user_p.stop()
|
| |
- cls.read_config_p.stop()
|
| |
super(TestBuildPackage, cls).tearDownClass()
|
| |
|
| |
def setUp(self):
|
| |
super(TestBuildPackage, self).setUp()
|
| |
|
| |
- self.ClientSession_p = patch('koji.ClientSession')
|
| |
- self.mock_ClientSession = self.ClientSession_p.start()
|
| |
-
|
| |
session = self.mock_ClientSession.return_value
|
| |
session.getBuildTarget.return_value = {
|
| |
'id': 1,
|
| |
@@ -3006,7 +3289,6 @@
|
| |
f.write(self.gating_yaml_content)
|
| |
|
| |
def tearDown(self):
|
| |
- self.ClientSession_p.stop()
|
| |
super(TestBuildPackage, self).tearDown()
|
| |
|
| |
# Some tests might make changes in the repository for their test
|
| |
@@ -3067,7 +3349,7 @@
|
| |
else:
|
| |
filename = os.path.basename(cli_cmd[i + 1])
|
| |
match_regex = '{0}/{1}$'.format(
|
| |
- self.UNIQUE_PATH_REGEX.rstrip('$'), filename)
|
| |
+ KOJI_UNIQUE_PATH_REGEX.rstrip('$'), filename)
|
| |
six.assertRegex(self, url, match_regex)
|
| |
else:
|
| |
expected_url = '{0}#{1}'.format(
|
| |
@@ -3124,7 +3406,8 @@
|
| |
else:
|
| |
self.assertEqual(expected_srpm_file, srpm_file)
|
| |
six.assertRegex(self, unique_path, r'^cli-build/\d+\.\d+\.[a-zA-Z]+$')
|
| |
- self.assertEqual({'callback': koji_cli.lib._progress_callback}, kwargs)
|
| |
+ self.assertEqual({'name': os.path.basename(srpm_file),
|
| |
+ 'callback': koji_cli.lib._progress_callback}, kwargs)
|
| |
|
| |
def test_srpm_option_with_srpm_file(self):
|
| |
self.assert_option_srpm_use('/path/to/docpkg-0.1-1.fc28.src.rpm')
|
| |
This PR depends upon other work that is currently in progress--please do not merge it yet.
This is the
rpkg
portion of the implementation of the Proposal for Module Scratch Builds as described at https://pagure.io/modularity/working-documents/blob/master/f/module-scratch-builds/module-scratch-build-proposal.md.