implement gitlab project get/create/delete
This commit is contained in:
parent
b0bf115f64
commit
60ba328469
|
@ -4,6 +4,8 @@ import os
|
||||||
import requests
|
import requests
|
||||||
import time
|
import time
|
||||||
|
|
||||||
|
from fedeproxy.common.retry import retry
|
||||||
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
@ -38,8 +40,8 @@ class GitLab(object):
|
||||||
def set_token(self, token):
|
def set_token(self, token):
|
||||||
self.s.headers['Authorization'] = f'Bearer {token}'
|
self.s.headers['Authorization'] = f'Bearer {token}'
|
||||||
|
|
||||||
def get_namespace(self, user):
|
def get_namespace_id(self, name):
|
||||||
r = self.s.get(self.s.api + '/namespaces?search=' + user)
|
r = self.s.get(self.s.api + '/namespaces?search=' + name)
|
||||||
r.raise_for_status()
|
r.raise_for_status()
|
||||||
return r.json()[0]['id']
|
return r.json()[0]['id']
|
||||||
|
|
||||||
|
@ -57,23 +59,47 @@ class GitLab(object):
|
||||||
user = r.json()
|
user = r.json()
|
||||||
return self.is_member_of_group(group, user['username'])
|
return self.is_member_of_group(group, user['username'])
|
||||||
|
|
||||||
def recreate_project(self, user, project):
|
def project_delete(self, namespace, project):
|
||||||
namespace_id = self.get_namespace(user)
|
info = self.project_get(namespace, project)
|
||||||
r = self.s.get(self.s.api + '/projects/' + user + '%2F' + project)
|
if info is None:
|
||||||
if r.status_code == requests.codes.ok:
|
return False
|
||||||
r = self.s.delete(self.s.api + '/projects/' + user + '%2F' + project)
|
r = self.s.delete(f'{self.s.api}/projects/{info["id"]}')
|
||||||
r.raise_for_status()
|
|
||||||
for _ in range(10):
|
|
||||||
r = self.s.post(self.s.api + '/projects', data={
|
|
||||||
"name": project,
|
|
||||||
"namespace_id": int(namespace_id),
|
|
||||||
"visibility": "public",
|
|
||||||
})
|
|
||||||
time.sleep(5)
|
|
||||||
if r.status_code == 201:
|
|
||||||
break
|
|
||||||
print(str(r.text))
|
|
||||||
r.raise_for_status()
|
r.raise_for_status()
|
||||||
|
while self.project_get(namespace, project) is not None:
|
||||||
|
time.sleep(1)
|
||||||
|
return True
|
||||||
|
|
||||||
|
def project_get(self, namespace, project):
|
||||||
|
r = self.s.get(f'{self.s.api}/projects/{namespace}%2F{project}')
|
||||||
|
if r.status_code == requests.codes.ok:
|
||||||
|
return r.json()
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
|
class DeletionInProgress(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@retry(DeletionInProgress, tries=5)
|
||||||
|
def _project_create(self, namespace, project):
|
||||||
|
namespace_id = self.get_namespace_id(namespace)
|
||||||
|
data = {
|
||||||
|
"name": project,
|
||||||
|
"namespace_id": int(namespace_id),
|
||||||
|
"visibility": "public",
|
||||||
|
}
|
||||||
|
r = self.s.post(f'{self.s.api}/projects', data=data)
|
||||||
|
if r.status_code == 201:
|
||||||
|
return r.json()
|
||||||
|
if r.status_code == 400 and 'still being deleted' in r.text:
|
||||||
|
raise GitLab.DeletionInProgress()
|
||||||
|
r.raise_for_status()
|
||||||
|
|
||||||
|
def project_create(self, namespace, project):
|
||||||
|
info = self.project_get(namespace, project)
|
||||||
|
if info is None:
|
||||||
|
return self._project_create(namespace, project)
|
||||||
|
else:
|
||||||
|
return info
|
||||||
|
|
||||||
def create_api_application(self, domain):
|
def create_api_application(self, domain):
|
||||||
callbacks = [
|
callbacks = [
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
import logging
|
||||||
|
import time
|
||||||
|
from functools import wraps
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class RetryException(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def retry(exceptions, tries=2, delay=1):
|
||||||
|
def deco_retry(f):
|
||||||
|
@wraps(f)
|
||||||
|
def f_retry(*args, **kwargs):
|
||||||
|
mtries, mdelay = tries + 1, delay
|
||||||
|
while mtries > 0:
|
||||||
|
try:
|
||||||
|
return f(*args, **kwargs)
|
||||||
|
except exceptions as e:
|
||||||
|
logger.info('%s: %s, Retrying in %s seconds...', f.__qualname__, e, mdelay)
|
||||||
|
if mtries == tries + 1:
|
||||||
|
logger.debug("", exc_info=True)
|
||||||
|
time.sleep(mdelay)
|
||||||
|
mtries -= 1
|
||||||
|
mdelay *= 2
|
||||||
|
raise RetryException("Number of retries exceeded for function " + f.__name__)
|
||||||
|
return f_retry
|
||||||
|
return deco_retry
|
|
@ -0,0 +1,2 @@
|
||||||
|
def pytest_configure(config):
|
||||||
|
config.addinivalue_line("markers", "gitlab: mark tests which require live GitLab instances")
|
|
@ -5,8 +5,11 @@ from fedeproxy.common.gitlab import GitLab
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.gitlab
|
@pytest.mark.gitlab
|
||||||
def test_recreate_project(tmpdir):
|
def test_create_project(tmpdir):
|
||||||
ip = os.environ.get('FEDEPROXY_IP', '0.0.0.0')
|
ip = os.environ.get('FEDEPROXY_IP', '0.0.0.0')
|
||||||
gitlab = GitLab(f'http://{ip}:8181')
|
gitlab = GitLab(f'http://{ip}:8181')
|
||||||
gitlab.login('root', 'Wrobyak4')
|
gitlab.login('root', 'Wrobyak4')
|
||||||
gitlab.recreate_project('root', 'testproject')
|
gitlab.project_delete('root', 'testproject')
|
||||||
|
assert gitlab.project_get('root', 'testproject') is None
|
||||||
|
p = gitlab.project_create('root', 'testproject')
|
||||||
|
assert p['id'] == gitlab.project_create('root', 'testproject')['id']
|
||||||
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
import pytest
|
||||||
|
from enough.common import retry
|
||||||
|
|
||||||
|
|
||||||
|
def test_that_retry_works_on_simple_function():
|
||||||
|
|
||||||
|
@retry.retry(Exception)
|
||||||
|
def f():
|
||||||
|
return True
|
||||||
|
|
||||||
|
assert f()
|
||||||
|
|
||||||
|
|
||||||
|
def test_that_retry_fails():
|
||||||
|
|
||||||
|
@retry.retry(AssertionError)
|
||||||
|
def f():
|
||||||
|
assert 0
|
||||||
|
|
||||||
|
with pytest.raises(retry.RetryException):
|
||||||
|
f()
|
||||||
|
|
||||||
|
|
||||||
|
def test_that_retry_works_on_complex_function():
|
||||||
|
class C():
|
||||||
|
fail = 2
|
||||||
|
|
||||||
|
@retry.retry(Exception, tries=3)
|
||||||
|
def f(self):
|
||||||
|
self.fail -= 1
|
||||||
|
assert self.fail == 0
|
||||||
|
return True
|
||||||
|
|
||||||
|
c = C()
|
||||||
|
assert c.f()
|
||||||
|
assert c.fail == 0
|
Loading…
Reference in New Issue