Merge "API, CLI: Allow use of tenant-scoped API URLs"
This commit is contained in:
commit
da8e50862e
@ -73,6 +73,7 @@ class TestApi(BaseTestCase):
|
||||
|
||||
client = ZuulRESTClient(url='https://fake.zuul/',
|
||||
auth_token='aiaiaiai')
|
||||
client.info_ = {}
|
||||
# test status checks
|
||||
self._test_status_check(
|
||||
client, 'post', client.autohold,
|
||||
@ -92,10 +93,24 @@ class TestApi(BaseTestCase):
|
||||
'node_hold_expiration': 3600}
|
||||
)
|
||||
self.assertEqual(True, ah)
|
||||
client.info_ = {'tenant': 'scoped'}
|
||||
ah = client.autohold(
|
||||
'tenant', 'project', 'job', 1, None, 'reason', 1, 3600)
|
||||
client.session.post.assert_called_with(
|
||||
'https://fake.zuul/api/project/project/autohold',
|
||||
json={'reason': 'reason',
|
||||
'count': 1,
|
||||
'job': 'job',
|
||||
'change': 1,
|
||||
'ref': None,
|
||||
'node_hold_expiration': 3600}
|
||||
)
|
||||
self.assertEqual(True, ah)
|
||||
|
||||
def test_autohold_list(self):
|
||||
"""Test autohold-list"""
|
||||
client = ZuulRESTClient(url='https://fake.zuul/')
|
||||
client.info_ = {}
|
||||
# test status checks
|
||||
self._test_status_check(
|
||||
client, 'get', client.autohold_list, 'tenant1')
|
||||
@ -117,16 +132,23 @@ class TestApi(BaseTestCase):
|
||||
client.session.get.assert_called_with(
|
||||
'https://fake.zuul/api/tenant/tenant1/autohold')
|
||||
self.assertEqual(fakejson, ahl)
|
||||
client.info_ = {'tenant': 'scoped'}
|
||||
ahl = client.autohold_list('tenant1')
|
||||
client.session.get.assert_called_with(
|
||||
'https://fake.zuul/api/autohold')
|
||||
self.assertEqual(fakejson, ahl)
|
||||
|
||||
def test_autohold_delete(self):
|
||||
"""Test autohold-delete"""
|
||||
client = ZuulRESTClient(url='https://fake.zuul/')
|
||||
client.info_ = {}
|
||||
# token required
|
||||
with self.assertRaisesRegex(Exception, 'Auth Token required'):
|
||||
client.autohold_delete(123, 'tenant1')
|
||||
|
||||
client = ZuulRESTClient(url='https://fake.zuul/',
|
||||
auth_token='aiaiaiai')
|
||||
client.info_ = {}
|
||||
# test status checks
|
||||
self._test_status_check(
|
||||
client, 'delete', client.autohold_delete,
|
||||
@ -140,10 +162,17 @@ class TestApi(BaseTestCase):
|
||||
'https://fake.zuul/api/tenant/tenant1/autohold/123'
|
||||
)
|
||||
self.assertEqual(True, ahd)
|
||||
client.info_ = {'tenant': 'scoped'}
|
||||
ahd = client.autohold_delete(123, 'tenant1')
|
||||
client.session.delete.assert_called_with(
|
||||
'https://fake.zuul/api/autohold/123'
|
||||
)
|
||||
self.assertEqual(True, ahd)
|
||||
|
||||
def test_autohold_info(self):
|
||||
"""Test autohold-info"""
|
||||
client = ZuulRESTClient(url='https://fake.zuul/')
|
||||
client.info_ = {}
|
||||
# test status checks
|
||||
self._test_status_check(
|
||||
client, 'get', client.autohold_info, 123, 'tenant1')
|
||||
@ -165,16 +194,23 @@ class TestApi(BaseTestCase):
|
||||
client.session.get.assert_called_with(
|
||||
'https://fake.zuul/api/tenant/tenant1/autohold/123')
|
||||
self.assertEqual(fakejson, ahl)
|
||||
client.info_ = {'tenant': 'scoped'}
|
||||
ahl = client.autohold_info(tenant='tenant1', id=123)
|
||||
client.session.get.assert_called_with(
|
||||
'https://fake.zuul/api/autohold/123')
|
||||
self.assertEqual(fakejson, ahl)
|
||||
|
||||
def test_enqueue(self):
|
||||
"""Test enqueue"""
|
||||
client = ZuulRESTClient(url='https://fake.zuul/')
|
||||
client.info_ = {}
|
||||
# token required
|
||||
with self.assertRaisesRegex(Exception, 'Auth Token required'):
|
||||
client.enqueue('tenant1', 'check', 'project1', '1,1')
|
||||
|
||||
client = ZuulRESTClient(url='https://fake.zuul/',
|
||||
auth_token='aiaiaiai')
|
||||
client.info_ = {}
|
||||
# test status checks
|
||||
self._test_status_check(
|
||||
client, 'post', client.enqueue,
|
||||
@ -190,10 +226,19 @@ class TestApi(BaseTestCase):
|
||||
'pipeline': 'check'}
|
||||
)
|
||||
self.assertEqual(True, enq)
|
||||
client.info_ = {'tenant': 'scoped'}
|
||||
enq = client.enqueue('tenant1', 'check', 'project1', '1,1')
|
||||
client.session.post.assert_called_with(
|
||||
'https://fake.zuul/api/project/project1/enqueue',
|
||||
json={'change': '1,1',
|
||||
'pipeline': 'check'}
|
||||
)
|
||||
self.assertEqual(True, enq)
|
||||
|
||||
def test_enqueue_ref(self):
|
||||
"""Test enqueue ref"""
|
||||
client = ZuulRESTClient(url='https://fake.zuul/')
|
||||
client.info_ = {}
|
||||
# token required
|
||||
with self.assertRaisesRegex(Exception, 'Auth Token required'):
|
||||
client.enqueue_ref(
|
||||
@ -201,6 +246,7 @@ class TestApi(BaseTestCase):
|
||||
|
||||
client = ZuulRESTClient(url='https://fake.zuul/',
|
||||
auth_token='aiaiaiai')
|
||||
client.info_ = {}
|
||||
# test status checks
|
||||
self._test_status_check(
|
||||
client, 'post', client.enqueue_ref,
|
||||
@ -219,16 +265,29 @@ class TestApi(BaseTestCase):
|
||||
'pipeline': 'check'}
|
||||
)
|
||||
self.assertEqual(True, enq_ref)
|
||||
client.info_ = {'tenant': 'scoped'}
|
||||
enq_ref = client.enqueue_ref(
|
||||
'tenant1', 'check', 'project1', 'refs/heads/stable', '0', '0')
|
||||
client.session.post.assert_called_with(
|
||||
'https://fake.zuul/api/project/project1/enqueue',
|
||||
json={'ref': 'refs/heads/stable',
|
||||
'oldrev': '0',
|
||||
'newrev': '0',
|
||||
'pipeline': 'check'}
|
||||
)
|
||||
self.assertEqual(True, enq_ref)
|
||||
|
||||
def test_dequeue(self):
|
||||
"""Test dequeue"""
|
||||
client = ZuulRESTClient(url='https://fake.zuul/')
|
||||
client.info_ = {}
|
||||
# token required
|
||||
with self.assertRaisesRegex(Exception, 'Auth Token required'):
|
||||
client.dequeue('tenant1', 'check', 'project1', '1,1')
|
||||
|
||||
client = ZuulRESTClient(url='https://fake.zuul/',
|
||||
auth_token='aiaiaiai')
|
||||
client.info_ = {}
|
||||
# test status checks
|
||||
self._test_status_check(
|
||||
client, 'post', client.dequeue,
|
||||
@ -257,16 +316,34 @@ class TestApi(BaseTestCase):
|
||||
'pipeline': 'check'}
|
||||
)
|
||||
self.assertEqual(True, deq)
|
||||
client.info_ = {'tenant': 'scoped'}
|
||||
deq = client.dequeue('tenant1', 'check', 'project1', change='1,1')
|
||||
client.session.post.assert_called_with(
|
||||
'https://fake.zuul/api/project/project1/dequeue',
|
||||
json={'change': '1,1',
|
||||
'pipeline': 'check'}
|
||||
)
|
||||
self.assertEqual(True, deq)
|
||||
deq = client.dequeue(
|
||||
'tenant1', 'check', 'project1', ref='refs/heads/stable')
|
||||
client.session.post.assert_called_with(
|
||||
'https://fake.zuul/api/project/project1/dequeue',
|
||||
json={'ref': 'refs/heads/stable',
|
||||
'pipeline': 'check'}
|
||||
)
|
||||
self.assertEqual(True, deq)
|
||||
|
||||
def test_promote(self):
|
||||
"""Test promote"""
|
||||
client = ZuulRESTClient(url='https://fake.zuul/')
|
||||
client.info_ = {}
|
||||
# token required
|
||||
with self.assertRaisesRegex(Exception, 'Auth Token required'):
|
||||
client.promote('tenant1', 'check', ['1,1', '2,1'])
|
||||
|
||||
client = ZuulRESTClient(url='https://fake.zuul/',
|
||||
auth_token='aiaiaiai')
|
||||
client.info_ = {}
|
||||
# test status checks
|
||||
self._test_status_check(
|
||||
client, 'post', client.promote,
|
||||
@ -282,6 +359,14 @@ class TestApi(BaseTestCase):
|
||||
'pipeline': 'check'}
|
||||
)
|
||||
self.assertEqual(True, prom)
|
||||
client.info_ = {'tenant': 'scoped'}
|
||||
prom = client.promote('tenant1', 'check', ['1,1', '2,1'])
|
||||
client.session.post.assert_called_with(
|
||||
'https://fake.zuul/api/promote',
|
||||
json={'changes': ['1,1', '2,1'],
|
||||
'pipeline': 'check'}
|
||||
)
|
||||
self.assertEqual(True, prom)
|
||||
|
||||
def test_get_key(self):
|
||||
"""Test getting a project's public key"""
|
||||
@ -302,6 +387,16 @@ GuS6/ewjS+arA1Iyeg/IxmECAwEAAQ==
|
||||
-----END PUBLIC KEY-----"""
|
||||
req = FakeRequestResponse(200, text=pubkey)
|
||||
client = ZuulRESTClient(url='https://fake.zuul/')
|
||||
client.info_ = {}
|
||||
client.session.get = MagicMock(return_value=req)
|
||||
key = client.get_key('tenant1', 'project1')
|
||||
client.session.get.assert_called_with(
|
||||
'https://fake.zuul/api/tenant/tenant1/key/project1.pub'
|
||||
)
|
||||
self.assertEqual(pubkey, key)
|
||||
client.info_ = {'tenant': 'scoped'}
|
||||
key = client.get_key('tenant1', 'project1')
|
||||
client.session.get.assert_called_with(
|
||||
'https://fake.zuul/api/key/project1.pub'
|
||||
)
|
||||
self.assertEqual(pubkey, key)
|
||||
|
@ -36,6 +36,17 @@ chunks = [
|
||||
'1tlAuq+vIhlY3iYlzVtPTiIOtF/6V+qPHnq1k6Tiv8YzJms1WyOuw106Bzl9XM=']
|
||||
|
||||
|
||||
def mock_get(func=MagicMock(return_value=None), info={}):
|
||||
|
||||
def funk(*args, **kwargs):
|
||||
if args[0].endswith('/info'):
|
||||
return FakeRequestResponse(200, info)
|
||||
else:
|
||||
return func(*args, **kwargs)
|
||||
|
||||
return funk
|
||||
|
||||
|
||||
class TestCmd(BaseTestCase):
|
||||
|
||||
def test_client_args_errors(self):
|
||||
@ -52,6 +63,54 @@ class TestCmd(BaseTestCase):
|
||||
'--reason', 'some reason',
|
||||
'--node-hold-expiration', '3600'])
|
||||
|
||||
def test_tenant_scoping_errors(self):
|
||||
"""Test the right uses of --tenant"""
|
||||
ZC = ZuulClient()
|
||||
with patch('requests.Session') as mock_sesh:
|
||||
session = mock_sesh.return_value
|
||||
test_args = [
|
||||
['autohold',
|
||||
'--project', 'project1',
|
||||
'--job', 'job1', '--change', '3',
|
||||
'--reason', 'some reason',
|
||||
'--node-hold-expiration', '3600'],
|
||||
['autohold-delete', '1234'],
|
||||
['autohold-info', '1234'],
|
||||
['enqueue',
|
||||
'--pipeline', 'check',
|
||||
'--change', '3,1',
|
||||
'--project', 'project1'],
|
||||
['enqueue-ref',
|
||||
'--pipeline', 'check',
|
||||
'--ref', 'refs/heads/stable',
|
||||
'--project', 'project1',
|
||||
'--oldrev', 'ababababab'],
|
||||
['dequeue',
|
||||
'--pipeline', 'check',
|
||||
'--change', '3,3',
|
||||
'--project', 'project1'],
|
||||
['promote',
|
||||
'--pipeline', 'gate',
|
||||
'--changes', '3,3', '4,1', '5,3'],
|
||||
['encrypt', '--project', 'project1']
|
||||
]
|
||||
for args in test_args:
|
||||
session.get = MagicMock(
|
||||
side_effect=mock_get()
|
||||
)
|
||||
with self.assertRaisesRegex(Exception,
|
||||
'--tenant argument is required'):
|
||||
ZC._main(['--zuul-url', 'https://fake.zuul',
|
||||
'--auth-token', 'aiaiaiai', ] + args)
|
||||
session.get = MagicMock(
|
||||
side_effect=mock_get(info={'tenant': 'scoped'})
|
||||
)
|
||||
with self.assertRaisesRegex(Exception,
|
||||
'scoped to tenant "scoped"'):
|
||||
ZC._main(['--zuul-url', 'https://fake.zuul',
|
||||
'--auth-token', 'aiaiaiai', ] + args +
|
||||
['--tenant', 'tenant-' + args[0]])
|
||||
|
||||
def test_autohold(self):
|
||||
"""Test autohold via CLI"""
|
||||
ZC = ZuulClient()
|
||||
@ -59,6 +118,9 @@ class TestCmd(BaseTestCase):
|
||||
session = mock_sesh.return_value
|
||||
session.post = MagicMock(
|
||||
return_value=FakeRequestResponse(200, True))
|
||||
session.get = MagicMock(
|
||||
side_effect=mock_get()
|
||||
)
|
||||
exit_code = ZC._main(
|
||||
['--zuul-url', 'https://fake.zuul',
|
||||
'--auth-token', 'aiaiaiai', 'autohold',
|
||||
@ -76,6 +138,27 @@ class TestCmd(BaseTestCase):
|
||||
'node_hold_expiration': 3600}
|
||||
)
|
||||
self.assertEqual(0, exit_code)
|
||||
# test scoped
|
||||
session.get = MagicMock(
|
||||
side_effect=mock_get(info={'tenant': 'scoped'})
|
||||
)
|
||||
exit_code = ZC._main(
|
||||
['--zuul-url', 'https://scoped.zuul',
|
||||
'--auth-token', 'aiaiaiai', 'autohold',
|
||||
'--project', 'project1',
|
||||
'--job', 'job1', '--change', '3', '--reason', 'some reason',
|
||||
'--node-hold-expiration', '3600'])
|
||||
session.post.assert_called_with(
|
||||
'https://scoped.zuul/api/'
|
||||
'project/project1/autohold',
|
||||
json={'reason': 'some reason',
|
||||
'count': 1,
|
||||
'job': 'job1',
|
||||
'change': '3',
|
||||
'ref': '',
|
||||
'node_hold_expiration': 3600}
|
||||
)
|
||||
self.assertEqual(0, exit_code)
|
||||
|
||||
def test_autohold_args_errors(self):
|
||||
"""Test wrong arguments for autohold"""
|
||||
@ -130,6 +213,9 @@ class TestCmd(BaseTestCase):
|
||||
session = mock_sesh.return_value
|
||||
session.delete = MagicMock(
|
||||
return_value=FakeRequestResponse(204))
|
||||
session.get = MagicMock(
|
||||
side_effect=mock_get()
|
||||
)
|
||||
exit_code = ZC._main(
|
||||
['--zuul-url', 'https://fake.zuul',
|
||||
'--auth-token', 'aiaiaiai', 'autohold-delete',
|
||||
@ -143,8 +229,9 @@ class TestCmd(BaseTestCase):
|
||||
ZC = ZuulClient()
|
||||
with patch('requests.Session') as mock_sesh:
|
||||
session = mock_sesh.return_value
|
||||
session.get = MagicMock(
|
||||
return_value=FakeRequestResponse(
|
||||
|
||||
def rv(*args, **kargs):
|
||||
return FakeRequestResponse(
|
||||
200,
|
||||
json={'id': 1234,
|
||||
'tenant': 'tenant1',
|
||||
@ -156,7 +243,11 @@ class TestCmd(BaseTestCase):
|
||||
'node_expiration': 0,
|
||||
'expired': 0,
|
||||
'reason': 'some_reason',
|
||||
'nodes': ['node1', 'node2']}))
|
||||
'nodes': ['node1', 'node2']})
|
||||
|
||||
session.get = MagicMock(
|
||||
side_effect=mock_get(rv)
|
||||
)
|
||||
exit_code = ZC._main(
|
||||
['--zuul-url', 'https://fake.zuul', 'autohold-info',
|
||||
'--tenant', 'tenant1', '1234'])
|
||||
@ -178,6 +269,9 @@ class TestCmd(BaseTestCase):
|
||||
session = mock_sesh.return_value
|
||||
session.post = MagicMock(
|
||||
return_value=FakeRequestResponse(200, True))
|
||||
session.get = MagicMock(
|
||||
side_effect=mock_get()
|
||||
)
|
||||
exit_code = ZC._main(
|
||||
['--zuul-url', 'https://fake.zuul',
|
||||
'--auth-token', 'aiaiaiai', 'enqueue',
|
||||
@ -199,6 +293,9 @@ class TestCmd(BaseTestCase):
|
||||
session = mock_sesh.return_value
|
||||
session.post = MagicMock(
|
||||
return_value=FakeRequestResponse(200, True))
|
||||
session.get = MagicMock(
|
||||
side_effect=mock_get()
|
||||
)
|
||||
# ensure default revs are set
|
||||
exit_code = ZC._main(
|
||||
['--zuul-url', 'https://fake.zuul',
|
||||
@ -272,6 +369,9 @@ class TestCmd(BaseTestCase):
|
||||
session = mock_sesh.return_value
|
||||
session.post = MagicMock(
|
||||
return_value=FakeRequestResponse(200, True))
|
||||
session.get = MagicMock(
|
||||
side_effect=mock_get()
|
||||
)
|
||||
exit_code = ZC._main(
|
||||
['--zuul-url', 'https://fake.zuul',
|
||||
'--auth-token', 'aiaiaiai', 'dequeue',
|
||||
@ -306,6 +406,9 @@ class TestCmd(BaseTestCase):
|
||||
session = mock_sesh.return_value
|
||||
session.post = MagicMock(
|
||||
return_value=FakeRequestResponse(200, True))
|
||||
session.get = MagicMock(
|
||||
side_effect=mock_get()
|
||||
)
|
||||
exit_code = ZC._main(
|
||||
['--zuul-url', 'https://fake.zuul',
|
||||
'--auth-token', 'aiaiaiai', 'promote',
|
||||
@ -329,8 +432,13 @@ class TestCmd(BaseTestCase):
|
||||
ZC = ZuulClient()
|
||||
with patch('requests.Session') as mock_sesh:
|
||||
session = mock_sesh.return_value
|
||||
|
||||
def rv(*args, **kwargs):
|
||||
return FakeRequestResponse(200, text='aaa')
|
||||
|
||||
session.get = MagicMock(
|
||||
return_value=FakeRequestResponse(200, text='aaa'))
|
||||
side_effect=mock_get(rv)
|
||||
)
|
||||
with patch('zuulclient.cmd.encrypt_with_openssl') as m_encrypt:
|
||||
m_encrypt.return_value = chunks
|
||||
exit_code = ZC._main(
|
||||
|
@ -51,6 +51,20 @@ class ZuulRESTClient(object):
|
||||
self.session.verify = self.verify
|
||||
if self.auth_token:
|
||||
self.session.auth = BearerAuth(self.auth_token)
|
||||
self.info_ = None
|
||||
|
||||
@property
|
||||
def info(self):
|
||||
"""Return the Zuul info data.
|
||||
Useful to get capabilities and tenant info."""
|
||||
if self.info_ is None:
|
||||
url = urllib.parse.urljoin(
|
||||
self.base_url,
|
||||
'info')
|
||||
req = self.session.get(url)
|
||||
self._check_request_status(req)
|
||||
self.info_ = req.json()
|
||||
return self.info_
|
||||
|
||||
def _check_request_status(self, req):
|
||||
try:
|
||||
@ -76,17 +90,25 @@ class ZuulRESTClient(object):
|
||||
"change": change,
|
||||
"ref": ref,
|
||||
"node_hold_expiration": node_hold_expiration}
|
||||
if self.info.get('tenant'):
|
||||
suffix = 'project/%s/autohold' % project
|
||||
else:
|
||||
suffix = 'tenant/%s/project/%s/autohold' % (tenant, project)
|
||||
url = urllib.parse.urljoin(
|
||||
self.base_url,
|
||||
'tenant/%s/project/%s/autohold' % (tenant, project))
|
||||
suffix)
|
||||
req = self.session.post(url, json=args)
|
||||
self._check_request_status(req)
|
||||
return req.json()
|
||||
|
||||
def autohold_list(self, tenant):
|
||||
if self.info.get('tenant'):
|
||||
suffix = 'autohold'
|
||||
else:
|
||||
suffix = 'tenant/%s/autohold' % tenant
|
||||
url = urllib.parse.urljoin(
|
||||
self.base_url,
|
||||
'tenant/%s/autohold' % tenant)
|
||||
suffix)
|
||||
# auth not needed here
|
||||
req = self.session.get(url)
|
||||
self._check_request_status(req)
|
||||
@ -96,18 +118,26 @@ class ZuulRESTClient(object):
|
||||
def autohold_delete(self, id, tenant):
|
||||
if not self.auth_token:
|
||||
raise Exception('Auth Token required')
|
||||
if self.info.get('tenant'):
|
||||
suffix = 'autohold/%s' % id
|
||||
else:
|
||||
suffix = 'tenant/%s/autohold/%s' % (tenant, id)
|
||||
url = urllib.parse.urljoin(
|
||||
self.base_url,
|
||||
'tenant/%s/autohold/%s' % (tenant, id))
|
||||
suffix)
|
||||
req = self.session.delete(url)
|
||||
self._check_request_status(req)
|
||||
# DELETE doesn't return a body, just the HTTP code
|
||||
return (req.status_code == 204)
|
||||
|
||||
def autohold_info(self, id, tenant):
|
||||
if self.info.get('tenant'):
|
||||
suffix = 'autohold/%s' % id
|
||||
else:
|
||||
suffix = 'tenant/%s/autohold/%s' % (tenant, id)
|
||||
url = urllib.parse.urljoin(
|
||||
self.base_url,
|
||||
'tenant/%s/autohold/%s' % (tenant, id))
|
||||
suffix)
|
||||
# auth not needed here
|
||||
req = self.session.get(url)
|
||||
self._check_request_status(req)
|
||||
@ -119,9 +149,13 @@ class ZuulRESTClient(object):
|
||||
raise Exception('Auth Token required')
|
||||
args = {"change": change,
|
||||
"pipeline": pipeline}
|
||||
if self.info.get('tenant'):
|
||||
suffix = 'project/%s/enqueue' % project
|
||||
else:
|
||||
suffix = 'tenant/%s/project/%s/enqueue' % (tenant, project)
|
||||
url = urllib.parse.urljoin(
|
||||
self.base_url,
|
||||
'tenant/%s/project/%s/enqueue' % (tenant, project))
|
||||
suffix)
|
||||
req = self.session.post(url, json=args)
|
||||
self._check_request_status(req)
|
||||
return req.json()
|
||||
@ -133,9 +167,13 @@ class ZuulRESTClient(object):
|
||||
"oldrev": oldrev,
|
||||
"newrev": newrev,
|
||||
"pipeline": pipeline}
|
||||
if self.info.get('tenant'):
|
||||
suffix = 'project/%s/enqueue' % project
|
||||
else:
|
||||
suffix = 'tenant/%s/project/%s/enqueue' % (tenant, project)
|
||||
url = urllib.parse.urljoin(
|
||||
self.base_url,
|
||||
'tenant/%s/project/%s/enqueue' % (tenant, project))
|
||||
suffix)
|
||||
req = self.session.post(url, json=args)
|
||||
self._check_request_status(req)
|
||||
return req.json()
|
||||
@ -150,9 +188,13 @@ class ZuulRESTClient(object):
|
||||
args['ref'] = ref
|
||||
else:
|
||||
raise Exception('need change OR ref')
|
||||
if self.info.get('tenant'):
|
||||
suffix = 'project/%s/dequeue' % project
|
||||
else:
|
||||
suffix = 'tenant/%s/project/%s/dequeue' % (tenant, project)
|
||||
url = urllib.parse.urljoin(
|
||||
self.base_url,
|
||||
'tenant/%s/project/%s/dequeue' % (tenant, project))
|
||||
suffix)
|
||||
req = self.session.post(url, json=args)
|
||||
self._check_request_status(req)
|
||||
return req.json()
|
||||
@ -162,17 +204,25 @@ class ZuulRESTClient(object):
|
||||
raise Exception('Auth Token required')
|
||||
args = {'pipeline': pipeline,
|
||||
'changes': change_ids}
|
||||
if self.info.get('tenant'):
|
||||
suffix = 'promote'
|
||||
else:
|
||||
suffix = 'tenant/%s/promote' % tenant
|
||||
url = urllib.parse.urljoin(
|
||||
self.base_url,
|
||||
'tenant/%s/promote' % tenant)
|
||||
suffix)
|
||||
req = self.session.post(url, json=args)
|
||||
self._check_request_status(req)
|
||||
return req.json()
|
||||
|
||||
def get_key(self, tenant, project):
|
||||
if self.info.get('tenant'):
|
||||
suffix = 'key/%s.pub' % project
|
||||
else:
|
||||
suffix = 'tenant/%s/key/%s.pub' % (tenant, project)
|
||||
url = urllib.parse.urljoin(
|
||||
self.base_url,
|
||||
'tenant/%s/key/%s.pub' % (tenant, project))
|
||||
suffix)
|
||||
req = self.session.get(url)
|
||||
self._check_request_status(req)
|
||||
return req.text
|
||||
|
@ -153,11 +153,24 @@ class ZuulClient():
|
||||
self.log.error(e)
|
||||
sys.exit(1)
|
||||
|
||||
def _check_tenant_scope(self, client):
|
||||
tenant_scope = client.info.get('tenant', None)
|
||||
if self.args.tenant != '':
|
||||
if tenant_scope is not None and tenant_scope != self.args.tenant:
|
||||
raise Exception(
|
||||
'Error: Zuul API URL %s is '
|
||||
'scoped to tenant "%s"' % (client.base_url, tenant_scope))
|
||||
else:
|
||||
if tenant_scope is None:
|
||||
raise Exception(
|
||||
"Error: the --tenant argument is required"
|
||||
)
|
||||
|
||||
def add_autohold_subparser(self, subparsers):
|
||||
cmd_autohold = subparsers.add_parser(
|
||||
'autohold', help='hold nodes for failed job')
|
||||
cmd_autohold.add_argument('--tenant', help='tenant name',
|
||||
required=True)
|
||||
required=False, default='')
|
||||
cmd_autohold.add_argument('--project', help='project name',
|
||||
required=True)
|
||||
cmd_autohold.add_argument('--job', help='job name',
|
||||
@ -188,6 +201,7 @@ class ZuulClient():
|
||||
|
||||
node_hold_expiration = self.args.node_hold_expiration
|
||||
client = self.get_client()
|
||||
self._check_tenant_scope(client)
|
||||
r = client.autohold(
|
||||
tenant=self.args.tenant,
|
||||
project=self.args.project,
|
||||
@ -204,12 +218,13 @@ class ZuulClient():
|
||||
'autohold-delete', help='delete autohold request')
|
||||
cmd_autohold_delete.set_defaults(func=self.autohold_delete)
|
||||
cmd_autohold_delete.add_argument('--tenant', help='tenant name',
|
||||
required=True, default=None)
|
||||
required=False, default='')
|
||||
cmd_autohold_delete.add_argument('id', metavar='REQUEST_ID',
|
||||
help='the hold request ID')
|
||||
|
||||
def autohold_delete(self):
|
||||
client = self.get_client()
|
||||
self._check_tenant_scope(client)
|
||||
return client.autohold_delete(self.args.id, self.args.tenant)
|
||||
|
||||
def add_autohold_info_subparser(self, subparsers):
|
||||
@ -217,12 +232,13 @@ class ZuulClient():
|
||||
'autohold-info', help='retrieve autohold request detailed info')
|
||||
cmd_autohold_info.set_defaults(func=self.autohold_info)
|
||||
cmd_autohold_info.add_argument('--tenant', help='tenant name',
|
||||
required=True, default=None)
|
||||
required=False, default='')
|
||||
cmd_autohold_info.add_argument('id', metavar='REQUEST_ID',
|
||||
help='the hold request ID')
|
||||
|
||||
def autohold_info(self):
|
||||
client = self.get_client()
|
||||
self._check_tenant_scope(client)
|
||||
request = client.autohold_info(self.args.id, self.args.tenant)
|
||||
|
||||
if not request:
|
||||
@ -247,11 +263,12 @@ class ZuulClient():
|
||||
cmd_autohold_list = subparsers.add_parser(
|
||||
'autohold-list', help='list autohold requests')
|
||||
cmd_autohold_list.add_argument('--tenant', help='tenant name',
|
||||
required=True)
|
||||
required=False, default='')
|
||||
cmd_autohold_list.set_defaults(func=self.autohold_list)
|
||||
|
||||
def autohold_list(self):
|
||||
client = self.get_client()
|
||||
self._check_tenant_scope(client)
|
||||
autohold_requests = client.autohold_list(tenant=self.args.tenant)
|
||||
|
||||
if not autohold_requests:
|
||||
@ -281,7 +298,7 @@ class ZuulClient():
|
||||
def add_enqueue_subparser(self, subparsers):
|
||||
cmd_enqueue = subparsers.add_parser('enqueue', help='enqueue a change')
|
||||
cmd_enqueue.add_argument('--tenant', help='tenant name',
|
||||
required=True)
|
||||
required=False, default='')
|
||||
cmd_enqueue.add_argument('--pipeline', help='pipeline name',
|
||||
required=True)
|
||||
cmd_enqueue.add_argument('--project', help='project name',
|
||||
@ -292,6 +309,7 @@ class ZuulClient():
|
||||
|
||||
def enqueue(self):
|
||||
client = self.get_client()
|
||||
self._check_tenant_scope(client)
|
||||
r = client.enqueue(
|
||||
tenant=self.args.tenant,
|
||||
pipeline=self.args.pipeline,
|
||||
@ -310,7 +328,7 @@ class ZuulClient():
|
||||
to manually "replay" a trigger received from an external
|
||||
source such as gerrit.'''))
|
||||
cmd_enqueue.add_argument('--tenant', help='tenant name',
|
||||
required=True)
|
||||
required=False, default='')
|
||||
cmd_enqueue.add_argument('--pipeline', help='pipeline name',
|
||||
required=True)
|
||||
cmd_enqueue.add_argument('--project', help='project name',
|
||||
@ -325,6 +343,7 @@ class ZuulClient():
|
||||
|
||||
def enqueue_ref(self):
|
||||
client = self.get_client()
|
||||
self._check_tenant_scope(client)
|
||||
r = client.enqueue_ref(
|
||||
tenant=self.args.tenant,
|
||||
pipeline=self.args.pipeline,
|
||||
@ -339,7 +358,7 @@ class ZuulClient():
|
||||
help='dequeue a buildset by its '
|
||||
'change or ref')
|
||||
cmd_dequeue.add_argument('--tenant', help='tenant name',
|
||||
required=True)
|
||||
required=False, default='')
|
||||
cmd_dequeue.add_argument('--pipeline', help='pipeline name',
|
||||
required=True)
|
||||
cmd_dequeue.add_argument('--project', help='project name',
|
||||
@ -352,6 +371,7 @@ class ZuulClient():
|
||||
|
||||
def dequeue(self):
|
||||
client = self.get_client()
|
||||
self._check_tenant_scope(client)
|
||||
r = client.dequeue(
|
||||
tenant=self.args.tenant,
|
||||
pipeline=self.args.pipeline,
|
||||
@ -364,7 +384,7 @@ class ZuulClient():
|
||||
cmd_promote = subparsers.add_parser('promote',
|
||||
help='promote one or more changes')
|
||||
cmd_promote.add_argument('--tenant', help='tenant name',
|
||||
required=True)
|
||||
required=False, default='')
|
||||
cmd_promote.add_argument('--pipeline', help='pipeline name',
|
||||
required=True)
|
||||
cmd_promote.add_argument('--changes', help='change ids',
|
||||
@ -373,6 +393,7 @@ class ZuulClient():
|
||||
|
||||
def promote(self):
|
||||
client = self.get_client()
|
||||
self._check_tenant_scope(client)
|
||||
r = client.promote(
|
||||
tenant=self.args.tenant,
|
||||
pipeline=self.args.pipeline,
|
||||
@ -420,7 +441,7 @@ class ZuulClient():
|
||||
cmd_encrypt = subparsers.add_parser(
|
||||
'encrypt', help='Encrypt a secret to be used in a project\'s jobs')
|
||||
cmd_encrypt.add_argument('--tenant', help='tenant name',
|
||||
required=True)
|
||||
required=False, default='')
|
||||
cmd_encrypt.add_argument('--project', help='project name',
|
||||
required=True)
|
||||
cmd_encrypt.add_argument('--no-strip', action='store_true',
|
||||
@ -469,6 +490,7 @@ class ZuulClient():
|
||||
pubkey_file = tempfile.NamedTemporaryFile(delete=False)
|
||||
self.log.debug('Creating temporary key file %s' % pubkey_file.name)
|
||||
client = self.get_client()
|
||||
self._check_tenant_scope(client)
|
||||
try:
|
||||
key = client.get_key(self.args.tenant, self.args.project)
|
||||
pubkey_file.write(str.encode(key))
|
||||
|
Loading…
x
Reference in New Issue
Block a user