Monty Taylor caebf387b4 Translate gitea project creation to python
Sadly, as readable as the use of the uri module to do the interactions
with gitea is, more reent ansible changed how subprocesses are forked
and this makes iterating over all the projects in projects.yaml take
an incredibly long amount of time.

Instead of doing it in yaml, make a python module that takes the list
one time and does looping and requests calls. This should make it be
possible to run the actual gitea creation playbook in integration tests.

Change-Id: Ifff3291c1092e6df09ae339c9e7dddb5ee692685
2019-07-11 08:21:35 -04:00

178 lines
6.0 KiB
Python
Executable File

#!/usr/bin/env python3
#
# Copyright 2019 Red Hat, Inc
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import time
import requests
import urllib.parse
from ansible.module_utils.basic import AnsibleModule
SB_REPO = 'https://storyboard.openstack.org/#!/project/{org}/{repo}'
SB_FORMAT = 'https://storyboard.openstack.org/#!/story/{{index}}'
LP_REPO = 'https://bugs.launchpad.net/{repo}'
LP_FORMAT = 'https://bugs.launchpad.net/{repo}/+bug/{{index}}'
class Gitea(object):
def __init__(self, url, password, always_update, projects):
self.url = url
self.password = password
self.always_update = always_update
self.projects = projects
self.orgs = { f['project'].split('/')[0] for f in self.projects }
def request(self, method, endpoint, *args, **kwargs):
resp = requests.request(
method,
urllib.parse.urljoin(self.url, endpoint),
auth=('root', self.password),
verify=False,
*args, **kwargs)
resp.raise_for_status()
return resp
def get(self, endpoint, *args, **kwargs):
return self.request('GET', endpoint, *args, **kwargs)
def post(self, endpoint, *args, **kwargs):
return self.request('POST', endpoint, *args, **kwargs)
def put(self, endpoint, *args, **kwargs):
return self.request('PUT', endpoint, *args, **kwargs)
def get_gitea_orgs(self):
orgs = self.get("/api/v1/user/orgs").json()
return [f['username'] for f in orgs]
def make_gitea_org(self, org):
self.post(
'/api/v1/admin/users/root/orgs',
json=dict(username=org))
def ensure_gitea_teams(self, org):
team_list = self.get('/api/v1/orgs/{org}/teams'.format(org=org)).json()
owner_id = [f['id'] for f in team_list if f['name'] == 'Owners'][0]
org_owners = self.get(
'/api/v1/teams/{owner_id}/members'.format(owner_id=owner_id))
if 'gerrit' not in [f['username'] for f in org_owners.json()]:
self.put('/api/v1/teams/{owner_id}/members/gerrit'.format(
owner_id=owner_id))
def get_org_repo_list(self, org):
return self.get('/api/v1/orgs/{org}/repos'.format(org=org)).json()
def get_csrf_token(self):
resp = self.get('/')
return urllib.parse.unquote(resp.cookies.get('_csrf'))
def make_gitea_project(self, project, csrf_token):
org, repo = project['project'].split('/', 1)
resp = self.post(
'/api/v1/org/{org}/repos'.format(org=org),
json=dict(
auto_init=True,
description=project.get('description', '')[:255],
name=repo,
private=False,
readme='Default'))
if project.get('use-storyboard'):
external_tracker_url = SB_REPO.format(org=org, repo=repo)
tracker_url_format = SB_FORMAT
elif project.get('groups'):
external_tracker_url = LP_REPO.format(repo=project['groups'][0])
tracker_url_format = LP_FORMAT.format(repo=project['groups'][0])
else:
external_tracker_url = LP_REPO.format(repo=repo)
tracker_url_format = LP_FORMAT.format(repo=repo)
self.post(
'/{org}/{repo}/settings'.format(org=org, repo=repo),
data=dict(
_csrf=csrf_token,
action='advanced',
# enable_pulls is not provided, which disables it
# enable_wiki is not provided, which disables it
enable_external_wiki=False,
external_wiki_url='',
# enable_issues is on so that issue links work
enable_issues='on',
enable_external_tracker=True,
external_tracker_url=external_tracker_url,
tracker_url_format=tracker_url_format,
tracker_issue_style='numeric',
))
for count in range(0, 5):
try:
return self.post(
'/{org}/{repo}/settings/branches'.format(
org=org, repo=repo),
data=dict(
_csrf=csrf_token,
action='default_branch',
branch='master',
))
except requests.exceptions.HTTPError as e:
time.sleep(3)
raise Exception("Could not update branch settings")
def run(self):
gitea_orgs = self.get_gitea_orgs()
gitea_repos = []
for org in self.orgs:
if org not in gitea_orgs:
self.make_gitea_org(org)
self.ensure_gitea_teams(org)
gitea_repos.extend(self.get_org_repo_list(org))
csrf_token = self.get_csrf_token()
for project in self.projects:
if project['project'] not in gitea_repos or self.always_update:
self.make_gitea_project(project, csrf_token)
def ansible_main():
module = AnsibleModule(
argument_spec=dict(
url=dict(required=True),
password=dict(required=True),
projects=dict(required=True, type='list'),
always_update=dict(type='bool', default=True),
)
)
p = module.params
gitea = Gitea(
url=p.get('url'),
password=p.get('password'),
always_update=p.get('always_update'),
projects=p.get('projects'),
)
try:
gitea.run()
except Exception as e:
module.fail_json(msg=str(e), changed=True)
module.exit_json(changed=True)
if __name__ == '__main__':
ansible_main()