draft repo module

This commit is contained in:
chris 2020-08-09 19:30:56 +02:00
parent d7040b84ad
commit 017d7409b6
1 changed files with 267 additions and 0 deletions

View File

@ -0,0 +1,267 @@
import json
import requests
ANSIBLE_METADATA = {
'metadata_version': '1.1',
'status': ['preview'],
}
DOCUMENTATION = '''
---
'''
EXAMPLES = '''
'''
RETURN = '''
'''
from ansible.module_utils.basic import AnsibleModule
def run_module():
deploy_key_spec = dict(
state=dict(type='str', default='present', choices=['present', 'absent']),
key=dict(type='str', required=True),
read_only=dict(type='bool', default=True),
title=dict(type='str', default=""),
)
module_args = dict(
state=dict(type='str', default='present', choices=['present', 'absent']),
auth_token=dict(type='str', required=True),
gitea_url=dict(type='str', required=True),
organization=dict(type="str", default=None),
user=dict(type="str", default=None),
auto_init=dict(type="bool", default=False),
description=dict(type="str", default=""),
gitignores=dict(type="str", default=""),
issue_labels=dict(type="str", default=""),
license=dict(type="str", default=""),
name=dict(type="str", default=""),
private=dict(type="bool", default=True),
readme=dict(type="str", default=""),
### TODO support multiple keys
deploy_key=dict(type="dict", default=None, options=deploy_key_spec),
)
result = dict(
changed=False,
return_code=0,
gitea_response={},
)
module = AnsibleModule(
argument_spec=module_args,
supports_check_mode=True
)
if (
('organization' in module.params and module.params['organization']) and
('user' in module.params and module.params['user'])
):
module.fail_json(msg="Either organization *or*" \
"user must be set", **result)
gitea_url = module.params['gitea_url']
reponame = module.params['name']
headers = {
"Content-Type": "application/json",
"Authorization": "token {}".format(module.params['auth_token']),
}
user_req = requests.get(gitea_url + '/api/v1/user', headers=headers)
logged_in = user_req.json().get('username')
if not logged_in == module.params['user']:
headers['Sudo'] = module.params['user']
if module.check_mode:
module.exit_json(**result)
# Prepare repo data
new_data = {
"auto_init": module.params['auto_init'],
"description": module.params['description'],
"gitignores": module.params['gitignores'],
"issue_labels": module.params['issue_labels'],
"license": module.params['license'],
"name": reponame,
"private": module.params['private'],
"readme": module.params['readme'],
}
if 'organization' in module.params and module.params['organization']:
owner = module.params['organization']
else:
owner = module.params['user']
original_repo = requests.get(
gitea_url + '/api/v1/repos/{owner}/{repo}'.format(
owner=owner,
repo=reponame,
),
headers=headers,
)
if module.params['state'] == 'present':
if original_repo.status_code == 200:
result['return_code'] = 200
result['gitea_response'] = original_repo.json()
old_data = original_repo.json()
# check if repo needs to be patched
if (
new_data['description'] != old_data['description'] or
new_data['private'] != old_data['private']
):
new_data.pop('name')
new_data.pop('auto_init')
new_data.pop('gitignores')
new_data.pop('issue_labels')
new_data.pop('readme')
req_patch = requests.patch(
gitea_url + '/api/v1/repos/{owner}/{repo}'.format(
owner=module.params['organization'],
repo=reponame,
),
headers=headers,
data=json.dumps(new_data),
)
result['return_code'] = req_patch.status_code
result['gitea_response'] = req_patch.json()
result['changed'] = True
# all is fine
result['state'] = 'present'
elif original_repo.status_code == 404:
if (
'organization' in module.params and
module.params['organization']
):
create_path = '/api/v1/org/{org}/repos'.format(
org=owner,
)
else:
create_path = '/api/v1/user/repos'
create_req = requests.post(
gitea_url + create_path,
headers=headers,
data=json.dumps(new_data),
)
result['return_code'] = create_req.status_code
result['gitea_response'] = create_req.json()
if create_req.status_code != 201:
module.fail_json(msg="Creation failed", **result)
result['changed'] = True
result['state'] = 'present'
if 'deploy_key' in module.params:
deploy_key = module.params['deploy_key']
repokeys_req = requests.get(
gitea_url + '/api/v1/repos/{owner}/{repo}/keys'.format(
owner=owner,
repo=reponame,
),
headers=headers,
)
repokeys = repokeys_req.json()
key_id = None
repokey = None
for repokey in repokeys:
if (
' '.join(repokey.get('key', '').split()[:-1]) ==
' '.join(deploy_key.get('key', '').split()[:-1])
):
key_id = repokey.get('key_id')
break
if deploy_key['state'] == "present":
if key_id:
if (
repokey.get('title', "") != deploy_key['title'] or
repokey.get('read_only') !=
deploy_key['read_only'] or
repokey.get('key', "") != deploy_key['key']
):
# there is no PATCH for keys, so delete and re-create
keydelete_req = requests.delete(
gitea_url +
'/api/v1/repos/{owner}/{repo}/keys/{id}'.format(
owner=owner,
repo=reponame,
id=key_id,
),
headers=headers,
)
requests.post(
gitea_url +
'/api/v1/repos/{owner}/{repo}/keys'.format(
owner=owner,
repo=reponame,
),
headers=headers,
data=json.dumps({
"key": deploy_key['key'],
"read_only": deploy_key['read_only'],
"title": deploy_key['title'],
}),
)
result['changed'] = True
else:
requests.post(
gitea_url +
'/api/v1/repos/{owner}/{repo}/keys'.format(
owner=owner,
repo=reponame,
),
headers=headers,
data=json.dumps({
"key": deploy_key['key'],
"read_only": deploy_key['read_only'],
"title": deploy_key['title'],
}),
)
result['changed'] = True
elif deploy_key['state'] == "absent":
if key_id:
keydelete_req = requests.delete(
gitea_url +
'/api/v1/repos/{owner}/{repo}/keys/{id}'.format(
owner=owner,
repo=reponame,
id=key_id,
),
headers=headers,
)
if keydelete_req.status_code != 204:
# deletion failed
result['gitea_response'] = keydelete_req.json()
module.fail_json(msg="Deletion failed", **result)
result['changed'] = True
if module.params['state'] == 'absent':
if original_repo.status_code == 404:
result['return_code'] = 404
result['gitea_response'] = original_repo.json()
result['state'] = 'absent'
elif original_repo.status_code == 200:
# repo should be abenst and needs to be deleted
delete_req = requests.delete(
gitea_url + '/api/v1/repos/{owner}/{repo}'.format(
owner=owner,
repo=reponame,
),
headers=headers,
)
result['return_code'] = delete_req.status_code
if delete_req.status_code != 204:
# deletion failed
result['gitea_response'] = delete_req.json()
module.fail_json(msg="Deletion failed", **result)
result['changed'] = True
result['state'] = 'absent'
module.exit_json(**result)
def main():
run_module()
if __name__ == '__main__':
main()