Vasyl Saienko | 71547e6 | 2017-07-14 09:27:04 +0300 | [diff] [blame^] | 1 | #!/usr/bin/python |
| 2 | |
| 3 | from __future__ import print_function |
| 4 | |
| 5 | import argparse |
| 6 | import os |
| 7 | import sys |
| 8 | import yaml |
| 9 | |
| 10 | def _merge_items(a, b, path=None): |
| 11 | """Merge b into a""" |
| 12 | if path is None: path = [] |
| 13 | for key in b: |
| 14 | if key in a: |
| 15 | if isinstance(a[key], dict) and isinstance(b[key], dict): |
| 16 | _merge_items(a[key], b[key], path + [str(key)]) |
| 17 | elif a[key] == b[key]: |
| 18 | pass # same leaf value |
| 19 | else: |
| 20 | raise Exception('Conflict at %s' % '.'.join(path + [str(key)])) |
| 21 | else: |
| 22 | a[key] = b[key] |
| 23 | return a |
| 24 | |
| 25 | def repo_add(content, name, source, pin_priority=None): |
| 26 | """Adds repo dict to provided content""" |
| 27 | t = {} |
| 28 | r = {name: {'architectures': 'amd64', |
| 29 | 'source': source}} |
| 30 | if pin_priority: |
| 31 | r[name]['pin'] = [{'package': '*', |
| 32 | 'priority': pin_priority, |
| 33 | 'pin': 'release o=Ubuntu'}] |
| 34 | t['parameters'] = {'linux': {'system': {'repo': r}}} |
| 35 | _merge_items(content, t) |
| 36 | |
| 37 | def main(): |
| 38 | parser = argparse.ArgumentParser(description='Update reclass model for specific node') |
| 39 | parser.add_argument('--node', |
| 40 | type=str, |
| 41 | help='FQDN of the node to update.') |
| 42 | parser.add_argument('--node-path', |
| 43 | type=str, |
| 44 | default='/srv/salt/reclass/nodes/_generated', |
| 45 | help='Path to directory with the nodes.') |
| 46 | subparsers = parser.add_subparsers() |
| 47 | |
| 48 | |
| 49 | # create the parser for the "add" command |
| 50 | parser_add = subparsers.add_parser('repo_add', help='Add a new repo.') |
| 51 | parser_add.set_defaults(command='repo_add') |
| 52 | parser_add.add_argument('--repo-name', |
| 53 | type=str, |
| 54 | required=True, |
| 55 | help='The name of the repo to add.') |
| 56 | parser_add.add_argument('--source', |
| 57 | type=str, |
| 58 | required=True, |
| 59 | help='The source link of the repo. For example: ' |
| 60 | 'deb http://my.repo.com/xenial ocata main') |
| 61 | parser_add.add_argument('--priority', |
| 62 | type=int, |
| 63 | help='The pin priority of the repo.') |
| 64 | args = parser.parse_args() |
| 65 | |
| 66 | if args.node: |
| 67 | node_files = ['%s/%s.yml' % (args.node_path, args.node)] |
| 68 | else: |
| 69 | |
| 70 | node_files = ['%s/%s' % (args.node_path, f) for f in os.listdir(args.node_path) if f.endswith('.yml')] |
| 71 | |
| 72 | # check we can read the file |
| 73 | for node_file in node_files: |
| 74 | node_name = os.path.basename(node_file)[:-4] |
| 75 | if not os.access(node_file, os.W_OK): |
| 76 | print("Can not write to nodes file %s" % node_file, file=sys.stderr) |
| 77 | sys.exit(1) |
| 78 | |
| 79 | try: |
| 80 | content = {} |
| 81 | with open(node_file) as f: |
| 82 | content = yaml.load(f) |
| 83 | |
| 84 | if args.command == 'repo_add': |
| 85 | print("Adding repo to the node: %s" % node_name) |
| 86 | repo_add(content, args.repo_name, args.source, args.priority) |
| 87 | |
| 88 | with open(node_file, "w") as f: |
| 89 | yaml.dump(content, f, default_flow_style=False) |
| 90 | print("Node: %s has been updated successfully." % node_name) |
| 91 | |
| 92 | except Exception as e: |
| 93 | print(e, file=sys.stderr) |
| 94 | sys.exit(1) |
| 95 | |
| 96 | if __name__ == '__main__': |
| 97 | main() |