Add support to configure SCM Import for projects
Change-Id: Ic95dd313542d13381c879b11bae4c79498300f55
diff --git a/_modules/rundeck.py b/_modules/rundeck.py
index 9d53361..f47c837 100644
--- a/_modules/rundeck.py
+++ b/_modules/rundeck.py
@@ -8,6 +8,8 @@
LOG = logging.getLogger(__name__)
+# Project
+
def get_project(name):
session, make_url = get_session()
resp = session.get(make_url("/api/18/project/{}".format(name)))
@@ -39,25 +41,6 @@
LOG.debug("create_project: %s", name)
-def create_project_config(name, params, config=None):
- config = dict(config) if config else {}
- if params['description']:
- config['project.description'] = params['description']
- else:
- config.pop('project.description', None)
- config.update({
- 'resources.source.1.config.file':
- "/var/rundeck/projects/{}/etc/resources.yaml".format(name),
- 'resources.source.1.config.format': 'resourceyaml',
- 'resources.source.1.config.generateFileAutomatically': 'true',
- 'resources.source.1.config.includeServerNode': 'false',
- 'resources.source.1.config.requireFileExists': 'false',
- 'project.ssh-keypath': '/var/rundeck/.ssh/id_rsa',
- 'resources.source.1.type': 'file',
- })
- return config
-
-
def update_project_config(name, project, config):
session, make_url = get_session()
resp = session.put(
@@ -80,6 +63,251 @@
.format(name, make_url.base_url, status_code))
+# SCM
+
+def get_plugin(project_name, integration):
+ session, make_url = get_session()
+ resp = session.get(make_url("/api/18/project/{}/scm/{}/config"
+ .format(project_name, integration)))
+ if resp.status_code == 200:
+ return True, resp.json()
+ elif resp.status_code == 404:
+ return True, None
+ return False, (
+ "Could not get config for the {} plugin of the {} project"
+ .format(integration, project_name))
+
+
+def get_plugin_status(project_name, integration):
+ def get_plugin(plugins, plugin_type):
+ for plugin in plugins:
+ if plugin['type'] == plugin_type:
+ return plugin
+ raise salt.exceptions.SaltInvocationError(
+ "Could not find status for the {}/{} plugin of the {} project"
+ .format(integration, plugin_type, project_name))
+
+ session, make_url = get_session()
+ resp = session.get(make_url("/api/18/project/{}/scm/{}/plugins"
+ .format(project_name, integration)))
+ if resp.status_code == 200:
+ plugin_type = "git-{}".format(integration)
+ status = get_plugin(resp.json()['plugins'], plugin_type)
+ return True, status
+ return False, (
+ "Could not get status for the {} plugin of the {} project"
+ .format(integration, project_name))
+
+
+def get_plugin_state(project_name, integration):
+ session, make_url = get_session()
+ resp = session.get(make_url("/api/18/project/{}/scm/{}/status"
+ .format(project_name, integration)))
+ if resp.status_code == 200:
+ return True, resp.json()
+ return False, (
+ "Could not get state for the {} plugin of the {} project"
+ .format(integration, project_name))
+
+
+def disable_plugin(project_name, integration):
+ session, make_url = get_session()
+ resp = session.post(make_url(
+ "/api/15/project/{}/scm/{}/plugin/git-{}/disable"
+ .format(project_name, integration, integration)))
+ if resp.status_code == 200:
+ msg = resp.json()
+ return True, msg['message']
+ return False, (
+ "Could not disable the {} plugin for the {} project: {}"
+ .format(integration, project_name, resp.status_code))
+
+
+def enable_plugin(project_name, integration):
+ session, make_url = get_session()
+ resp = session.post(make_url(
+ "/api/15/project/{}/scm/{}/plugin/git-{}/enable"
+ .format(project_name, integration, integration)))
+ if resp.status_code == 200:
+ msg = resp.json()
+ return True, msg['message']
+ return False, (
+ "Could not enable the {} plugin for the {} project: {}"
+ .format(integration, project_name, resp.status_code))
+
+
+# SCM Import
+
+def setup_scm_import(project_name, params):
+ session, make_url = get_session()
+ config = create_scm_import_config(project_name, params)
+ resp = session.post(
+ make_url("/api/15/project/{}/scm/import/plugin/git-import/setup"
+ .format(project_name)),
+ json={
+ 'config': config,
+ },
+ allow_redirects=False,
+ )
+ if resp.status_code == 200:
+ return True, resp.json()
+ return False, (
+ "Could not configure SCM Import for the {} project: {}/{}"
+ .format(project_name, resp.status_code, resp.text))
+
+
+def update_scm_import_config(project_name, plugin, config):
+ session, make_url = get_session()
+ resp = session.post(
+ make_url("/api/15/project/{}/scm/import/plugin/git-import/setup"
+ .format(project_name)),
+ json={
+ 'config': config,
+ },
+ allow_redirects=False,
+ )
+ if resp.status_code == 200:
+ return True, resp.json()
+ return False, (
+ "Could not update SCM Import for the {} project: {}/{}"
+ .format(project_name, resp.status_code, resp.text))
+
+
+def perform_scm_import_tracking(project_name, plugin, params):
+ format = plugin['config']['format']
+ file_pattern = params.get('file_pattern')
+ if not file_pattern:
+ file_pattern = DEFAULT_FILE_PATTERNS[format]
+
+ session, make_url = get_session()
+ resp = session.post(
+ make_url("/api/15/project/{}/scm/import/action/initialize-tracking"
+ .format(project_name)),
+ json={
+ 'input': {
+ 'filePattern': file_pattern,
+ 'useFilePattern': 'true',
+ },
+ 'jobs': [],
+ 'items': [],
+ 'deleted': [],
+ },
+ allow_redirects=False,
+ )
+ if resp.status_code == 200:
+ return True, resp.json()
+ return False, (
+ "Could not update SCM Import for the {} project: {}/{}"
+ .format(project_name, resp.status_code, resp.text))
+
+DEFAULT_FILE_PATTERNS = {
+ 'yaml': r'.*\.yaml',
+ 'xml': r'.*\.xml',
+}
+
+
+def perform_scm_import_pull(project_name, plugin, params):
+ session, make_url = get_session()
+ resp = session.post(
+ make_url("/api/15/project/{}/scm/import/action/remote-pull"
+ .format(project_name)),
+ json={
+ 'input': {},
+ 'jobs': [],
+ 'items': [],
+ 'deleted': [],
+ },
+ allow_redirects=False,
+ )
+ if resp.status_code == 200:
+ return True, resp.json()
+ return False, (
+ "Could not pull remote changes for the {} project: {}/{}"
+ .format(project_name, resp.status_code, resp.text))
+
+
+def perform_scm_import(project_name, plugin, params):
+ session, make_url = get_session()
+ ok, inputs = get_plugin_action_inputs(
+ project_name, 'import', 'import-all')
+ if not ok:
+ return False, inputs
+ items = list(item['itemId'] for item in inputs['importItems'])
+ resp = session.post(
+ make_url("/api/15/project/{}/scm/import/action/import-all"
+ .format(project_name)),
+ json={
+ 'input': {},
+ 'jobs': [],
+ 'items': items,
+ 'deleted': [],
+ },
+ allow_redirects=False,
+ )
+ if resp.status_code == 200:
+ return True, resp.json()
+ return False, (
+ "Could not import jobs for the {} project: {}/{}"
+ .format(project_name, resp.status_code, resp.text))
+
+
+# Utils
+
+def create_project_config(project_name, params, config=None):
+ config = dict(config) if config else {}
+ if params['description']:
+ config['project.description'] = params['description']
+ else:
+ config.pop('project.description', None)
+ config.update({
+ 'resources.source.1.config.file':
+ "/var/rundeck/projects/{}/etc/resources.yaml".format(project_name),
+ 'resources.source.1.config.format': 'resourceyaml',
+ 'resources.source.1.config.generateFileAutomatically': 'true',
+ 'resources.source.1.config.includeServerNode': 'false',
+ 'resources.source.1.config.requireFileExists': 'false',
+ 'project.ssh-keypath': '/var/rundeck/.ssh/id_rsa',
+ 'resources.source.1.type': 'file',
+ })
+ return config
+
+
+def create_scm_import_config(project_name, params, config=None):
+ config = dict(config) if config else {}
+
+ format = params.get('format', 'yaml')
+ if format not in DEFAULT_FILE_PATTERNS:
+ supported_formats = DEFAULT_FILE_PATTERNS.keys()
+ raise salt.exceptions.SaltInvocationError(
+ "Unsupported format {} for the {} SCM import module, should be {}"
+ .format(format, project_name, ','.join(supported_formats)))
+
+ config.update({
+ 'dir': "/var/rundeck/projects/{}/scm".format(project_name),
+ 'url': params['address'],
+ 'branch': params.get('branch', 'master'),
+ 'fetchAutomatically': 'true',
+ 'format': format,
+ 'pathTemplate': params.get(
+ 'path_template', '${job.group}${job.name}.${config.format}'),
+ 'importUuidBehavior': params.get('import_uuid_behavior', 'remove'),
+ 'strictHostKeyChecking': 'yes',
+ })
+ return config
+
+
+def get_plugin_action_inputs(project_name, integration, action):
+ session, make_url = get_session()
+ resp = session.get(
+ make_url("/api/18/project/cicd/scm/import/action/import-all/input"))
+ if resp.status_code == 200:
+ return True, resp.json()
+ return False, (
+ "Could not get inputs for the {} action for the {} project: {}/{}"
+ .format(action, project_name, resp.status_code, resp.text))
+
+
+
def get_session():
def make_url(url):
return urljoin(make_url.base_url, url)