| |
@@ -0,0 +1,165 @@
|
| |
+ #!/bin/env python3
|
| |
+
|
| |
+ import os
|
| |
+ import sys
|
| |
+ import logging
|
| |
+ import argparse
|
| |
+ import requests
|
| |
+ import yaml
|
| |
+
|
| |
+
|
| |
+ BASE_WH_URL = "https://softwarefactory-project.io/zuul/api/connection/%s/payload"
|
| |
+ ZUUL_WH_SRC_F_O = BASE_WH_URL % "src.fedoraproject.io"
|
| |
+ ZUUL_WH_PAGURE_IO = BASE_WH_URL % "pagure.io"
|
| |
+
|
| |
+
|
| |
+ class PagureAPIClientException(Exception):
|
| |
+ pass
|
| |
+
|
| |
+
|
| |
+ class PagureAPIClient():
|
| |
+ log = logging.getLogger("zuul.PagureAPIClient")
|
| |
+
|
| |
+ def __init__(
|
| |
+ self, baseurl, api_token):
|
| |
+ self.session = requests.Session()
|
| |
+ self.base_url = '%s/api/0/' % baseurl
|
| |
+ self.api_token = api_token
|
| |
+ self.headers = {'Authorization': 'token %s' % self.api_token}
|
| |
+
|
| |
+ def _manage_error(self, data, code, url, verb):
|
| |
+ if code < 400:
|
| |
+ return
|
| |
+ else:
|
| |
+ raise PagureAPIClientException(
|
| |
+ "Unable to %s on %s (code: %s) due to: %s" % (
|
| |
+ verb, url, code, data
|
| |
+ ))
|
| |
+
|
| |
+ def get(self, url):
|
| |
+ self.log.debug("Getting resource %s ..." % url)
|
| |
+ ret = self.session.get(url, headers=self.headers)
|
| |
+ self.log.debug("GET returned (code: %s): %s" % (
|
| |
+ ret.status_code, ret.text))
|
| |
+ return ret.json(), ret.status_code, ret.url, 'GET'
|
| |
+
|
| |
+ def post(self, url, params=None):
|
| |
+ self.log.debug(
|
| |
+ "Posting on resource %s, params (%s) ..." % (url, params))
|
| |
+ ret = self.session.post(url, data=params, headers=self.headers)
|
| |
+ self.log.debug("POST returned (code: %s): %s" % (
|
| |
+ ret.status_code, ret.text))
|
| |
+ return ret.json(), ret.status_code, ret.url, 'POST'
|
| |
+
|
| |
+ def get_config(self, project):
|
| |
+ path = '%s/options' % project
|
| |
+ resp = self.get(self.base_url + path)
|
| |
+ self._manage_error(*resp)
|
| |
+ return resp[0]
|
| |
+
|
| |
+ def set_config(self, project, params):
|
| |
+ path = '%s/options/update' % project
|
| |
+ resp = self.post(self.base_url + path, params)
|
| |
+ self._manage_error(*resp)
|
| |
+ return resp[0]
|
| |
+
|
| |
+ def set_acl(self, project, params):
|
| |
+ path = '%s/git/modifyacls' % project
|
| |
+ resp = self.post(self.base_url + path, params)
|
| |
+ self._manage_error(*resp)
|
| |
+ return resp[0]
|
| |
+
|
| |
+ def set_tags(self, project, params):
|
| |
+ # This endpoint does not exists yet
|
| |
+ # https://pagure.io/pagure/issue/4663
|
| |
+ pass
|
| |
+ # path = '%s/tags/update' % project
|
| |
+ # resp = self.post(self.base_url + path, params)
|
| |
+ # self._manage_error(*resp)
|
| |
+ # return resp[0]
|
| |
+
|
| |
+
|
| |
+ def set_zuul_settings(client, project, gating):
|
| |
+ logging.debug("Get settings config on %s" % project)
|
| |
+ config = client.get_config(project)
|
| |
+ config['Web-hooks'] = ZUUL_WH_SRC_F_O
|
| |
+ config['pull_requests'] = True
|
| |
+ config['notify_on_pull-request_flag'] = True
|
| |
+ if gating:
|
| |
+ config['open_metadata_access_to_all'] = False
|
| |
+ # Cannot set 0 by the API so let's force it to -1
|
| |
+ # Then https://review.opendev.org/#/c/691254/ is needed asap.
|
| |
+ config['Minimum_score_to_merge_pull-request'] = -1
|
| |
+ client.set_tags(project, ['gateit'])
|
| |
+ client.set_config(project, config)
|
| |
+ logging.debug("Applying new setting set on %s" % project)
|
| |
+ acls = {
|
| |
+ 'user_type': 'user',
|
| |
+ 'name': 'zuul',
|
| |
+ 'acl': 'admin'
|
| |
+ }
|
| |
+ client.set_acl(project, acls)
|
| |
+ logging.debug("Adding zuul user as admin on %s" % project)
|
| |
+
|
| |
+
|
| |
+ def process(client, projects, gating):
|
| |
+ count = 1
|
| |
+ for project in projects:
|
| |
+ logging.info('[%s/%s] Applying setting for %s' % (
|
| |
+ count, len(projects), project))
|
| |
+ try:
|
| |
+ set_zuul_settings(client, project, gating)
|
| |
+ count += 1
|
| |
+ except Exception:
|
| |
+ logging.exception("Unable to set settings for %s" % project)
|
| |
+
|
| |
+
|
| |
+ def load_projects_from_yaml(path):
|
| |
+ path = os.path.expanduser(path)
|
| |
+ if not os.path.isfile(path):
|
| |
+ logging.error("Unable to access %s" % path)
|
| |
+ sys.exit(1)
|
| |
+ with open(path) as fd:
|
| |
+ projects = yaml.load(fd, Loader=yaml.FullLoader)
|
| |
+ return projects
|
| |
+
|
| |
+
|
| |
+ if __name__ == "__main__":
|
| |
+ parser = argparse.ArgumentParser()
|
| |
+ parser.add_argument(
|
| |
+ '--host', help='Pagure instance',
|
| |
+ default='pagure.io')
|
| |
+ parser.add_argument(
|
| |
+ '--projects',
|
| |
+ help='Projects to set settings on (comma separated)')
|
| |
+ parser.add_argument(
|
| |
+ '--from-yaml',
|
| |
+ help='Projects to set settings on (from a yaml file)')
|
| |
+ parser.add_argument(
|
| |
+ '--apikey', help='API key with modify project ACL',
|
| |
+ required=True)
|
| |
+ parser.add_argument(
|
| |
+ '--gating', help='Set settings for gating',
|
| |
+ action="store_true")
|
| |
+ parser.add_argument(
|
| |
+ '--loglevel', help='Log level',
|
| |
+ default="INFO")
|
| |
+ args = parser.parse_args()
|
| |
+
|
| |
+ logging.basicConfig(
|
| |
+ level=getattr(logging, args.loglevel.upper()))
|
| |
+
|
| |
+ client = PagureAPIClient(
|
| |
+ 'https://%s' % args.host,
|
| |
+ args.apikey)
|
| |
+ if not(args.projects or args.from_yaml):
|
| |
+ logging.info("Missing argument --projects or --from-yaml")
|
| |
+ parser.print_help()
|
| |
+ sys.exit(1)
|
| |
+
|
| |
+ if args.projects:
|
| |
+ projects = args.projects.split(',')
|
| |
+ if args.from_yaml:
|
| |
+ projects = load_projects_from_yaml(
|
| |
+ args.from_yaml)
|
| |
+ process(client, projects, args.gating)
|
| |