Create managed config files yaml from config dir 89/65789/5
authorAndrew Grimberg <agrimberg@linuxfoundation.org>
Fri, 16 Oct 2020 21:53:04 +0000 (14:53 -0700)
committerAndrew Grimberg <agrimberg@linuxfoundation.org>
Wed, 28 Oct 2020 21:12:37 +0000 (14:12 -0700)
This script requires ruamel.yaml to be installed in the environment that
it is run in

Will take a configuration tree and build up the JCasC managed files
section and output to stdout the resultant yaml

Expected configuration of the tree is as follows:

top
|- config_type
    |- file-id
        |- config-params.yaml
        |- content
        |- ??CredentialMappings.yaml
        |- ??CredentialMappings.sandbox.yaml
...

The ??CredentialMappins.yaml will be used for production systems and the
sandbox version for sandbox systems (pass a -s or --sandbox)

Change-Id: I196e99f1db40223a29e892eb86efd70ecaa328f0
Signed-off-by: Andrew Grimberg <agrimberg@linuxfoundation.org>
jenkins-admin/create_jenkins_managed_files_yaml.py [new file with mode: 0755]
releasenotes/notes/create_jenkins_managed_files-3b763a3a29b862ab.yaml [new file with mode: 0644]

diff --git a/jenkins-admin/create_jenkins_managed_files_yaml.py b/jenkins-admin/create_jenkins_managed_files_yaml.py
new file mode 100755 (executable)
index 0000000..bf85a1d
--- /dev/null
@@ -0,0 +1,142 @@
+#!/usr/bin/env python
+
+"""Convert Managed Config files to JCasC YAML"""
+
+from pprint import pformat
+
+import argparse
+import configparser
+import logging
+import os
+import ruamel.yaml
+import sys
+
+yaml = ruamel.yaml.YAML()
+yaml.allow_duplicate_keys = True
+yaml.preserve_quotes = True
+
+logging.basicConfig(format="%(asctime)s %(levelname)s %(message)s",
+    level=logging.INFO)
+
+def dir_path(path):
+    """Validate that path provided exists"""
+
+    if os.path.isdir(path):
+        return path
+    else:
+        raise argparse.ArgumentTypeError(
+                "'%s' is not a valid path" % path)
+
+def getArgs():
+    """Parse the commandline arguments"""
+
+    parser = argparse.ArgumentParser(
+        description = __doc__,
+        formatter_class = argparse.ArgumentDefaultsHelpFormatter
+    )
+
+    # default argument options
+    parser.add_argument(
+        "-o", "--output", help = "Output file",
+        type = argparse.FileType("w")
+    )
+    parser.add_argument(
+        "-p", "--path", help = "Path to configuration files to read",
+        type = dir_path, required = True
+    )
+    parser.add_argument(
+        "-q", "--quiet", help = "Run quiet", dest = "quiet",
+        action = "store_true"
+    )
+    parser.add_argument(
+        "-s", "--sandbox",
+        help = "Is configuration being created for a sandbox",
+        dest = "sandbox", action = "store_true"
+    )
+    parser.add_argument(
+        "-v", "--verbose", dest = "verbose", action = "store_true",
+        help = "Enable verbose (debug) logging"
+    )
+
+    return parser.parse_args()
+
+def processConfig(path, subpath, files, sandbox):
+    """Process the configuration file and return the configuration object"""
+
+    logging.debug("In processConfig")
+    logging.debug("\n" + pformat(path) + "\n" + pformat(subpath) + "\n" + pformat(files))
+
+    ret = { subpath[0]:
+            {
+                "id": subpath[1]
+            }
+        }
+
+    for config in files:
+        # skip all hidden files
+        if '.' in config[0]:
+            continue
+
+        if '.yaml' in config:
+            loadYaml = False
+            # Only load credential mappings files if the file matches
+            # the type of jenkins silo (ie production or sandbox)
+            if 'CredentialMappings' in config:
+                if sandbox and 'sandbox' in config:
+                    loadYaml = True
+                elif not sandbox and 'sandbox' not in config:
+                    loadYaml = True
+            else:
+                loadYaml = True
+
+            if loadYaml:
+                stream = open(os.path.join(path, config), 'r')
+                ret[subpath[0]].update(yaml.load(stream))
+
+        if 'content' in config:
+            stream = open(os.path.join(path, config), 'r')
+            ret[subpath[0]].update({'content': stream.read()})
+
+            # custom files need to have ${ prefixed with ^ for some reason
+            if 'custom' in subpath[0] or 'properties' in subpath[0]:
+                ret[subpath[0]]['content'] = \
+                        ret[subpath[0]]['content'].replace('${', '^${')
+
+    return ret
+
+def _main():
+    args = getArgs()
+
+    if args.verbose:
+        logging.getLogger().setLevel(logging.DEBUG)
+
+    if args.quiet:
+        logging.getLogger().setLevel(logging.ERROR)
+
+    output = { 'unclassified':
+                { 'globalConfigFiles':
+                    { 'configs': [] }
+                }
+            }
+
+    configs = []
+
+    pathsplit = args.path.split('/')
+
+    for (dirpath, dirnames, filenames) in os.walk(args.path):
+        logging.debug("\n" + pformat((dirpath, dirnames, filenames)))
+
+        curpath = [x for x in dirpath.split('/') if x not in pathsplit]
+        if len(curpath) > 1:
+            configs.append(processConfig(dirpath, curpath, filenames, args.sandbox))
+
+
+    output['unclassified']['globalConfigFiles']['configs'] = configs
+
+    if args.output:
+        yaml.dump(output, args.output)
+    else:
+        yaml.dump(output, sys.stdout)
+
+if __name__ == "__main__":
+    sys.exit(_main())
diff --git a/releasenotes/notes/create_jenkins_managed_files-3b763a3a29b862ab.yaml b/releasenotes/notes/create_jenkins_managed_files-3b763a3a29b862ab.yaml
new file mode 100644 (file)
index 0000000..f39231f
--- /dev/null
@@ -0,0 +1,6 @@
+---
+features:
+  - |
+    Adds a create_jenkins_managed_files_yaml.py administrative script for
+    generating JCasC yaml files from a directory for control of the Managed
+    Configuration Files plugin