blob: 864ba7ba9a99181bda081513c19ec4a132d2a7dc [file] [log] [blame]
Dennis Dmitriev86750962017-07-11 19:44:05 +03001# Copyright 2013 - 2017 Mirantis, Inc.
Dennis Dmitrieve56c8b92017-06-16 01:53:16 +03002#
3# Licensed under the Apache License, Version 2.0 (the "License"); you may
4# not use this file except in compliance with the License. You may obtain
5# a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12# License for the specific language governing permissions and limitations
13# under the License.
14
15from __future__ import print_function
16
17import argparse
18import os
19import sys
20import yaml
21
22from reclass_tools import walk_models
23
24
Dennis Dmitriev86750962017-07-11 19:44:05 +030025class Shell(object):
26 def __init__(self, args):
27 self.args = args
28 self.params = self.get_params()
Dennis Dmitrieve56c8b92017-06-16 01:53:16 +030029
Dennis Dmitriev86750962017-07-11 19:44:05 +030030 def execute(self):
31 command_name = 'do_{}'.format(self.params.command.replace('-', '_'))
32 command_method = getattr(self, command_name)
33 command_method()
Dennis Dmitrieve56c8b92017-06-16 01:53:16 +030034
Dennis Dmitriev86750962017-07-11 19:44:05 +030035 def do_get_key(self):
36 results = walk_models.remove_reclass_parameter(
37 self.params.path,
38 self.params.key_name,
39 verbose=self.params.verbose,
40 pretend=True)
41
42 def do_del_key(self):
43 results = walk_models.remove_reclass_parameter(
44 self.params.path,
45 self.params.key_name,
46 verbose=self.params.verbose,
47 pretend=False)
48
49 def do_list_params(self):
50 results = walk_models.get_all_reclass_params(
51 self.params.path,
52 verbose=self.params.verbose)
53 print(yaml.dump(results))
54
55 def do_list_domains(self):
56 try:
57 from reclass_tools import reclass_models
58 except ImportError:
59 sys.exit("Please run this tool on the salt-master node "
60 "with installed 'reclass'")
61 inventory = reclass_models.inventory_list()
62 reclass_storage = reclass_models.reclass_storage(inventory=inventory)
63 print('\n'.join(sorted(reclass_storage.keys())))
Dennis Dmitrieve56c8b92017-06-16 01:53:16 +030064
65
Dennis Dmitriev86750962017-07-11 19:44:05 +030066 def do_list_nodes(self):
67 try:
68 from reclass_tools import reclass_models
69 except ImportError:
70 sys.exit("Please run this tool on the salt-master node "
71 "with installed 'reclass'")
72
73 inventory = reclass_models.inventory_list(domain=self.params.domain)
74 vcp_nodes = reclass_models.vcp_list(domain=self.params.domain,
75 inventory=inventory)
76 vcp_node_names = ['{0}.{1}'.format(name, domain)
77 for name, domain in vcp_nodes]
78
79 if self.params.vcp_only:
80 print('\n'.join(sorted(vcp_node_names)))
81 elif self.params.non_vcp_only:
82 print('\n'.join(sorted((node_name for node_name in inventory.keys()
83 if node_name not in vcp_node_names))))
84 else:
85 print('\n'.join(sorted(inventory.keys())))
86
87 def do_show_context(self):
88 try:
89 from reclass_tools import create_inventory
90 except ImportError:
91 sys.exit("Please run this tool on the salt-master node "
92 "with installed 'reclass'")
93
94 current_underlay_context = create_inventory.create_inventory_context(
95 domain=self.params.domain, keys=self.params.keys)
96
97 print(yaml.dump(current_underlay_context, default_flow_style=False))
98
99 def do_render(self):
100 try:
101 from reclass_tools import create_inventory
102 except ImportError:
103 sys.exit("Please run this tool on the salt-master node "
104 "with installed 'reclass'")
105
106 if not self.params.template_dir or not self.params.output_dir \
107 or not self.params.contexts:
108 sys.exit("Missing parameters, see: reclass-tools render -h")
109
110 create_inventory.render_dir(template_dir=self.params.template_dir,
111 output_dir=self.params.output_dir,
Dennis Dmitriev0cea5702017-07-17 19:03:23 +0300112 contexts=self.params.contexts,
113 env_name=self.params.env_name)
Dennis Dmitriev86750962017-07-11 19:44:05 +0300114
115 def get_params(self):
116
117 verbose_parser = argparse.ArgumentParser(add_help=False)
118 verbose_parser.add_argument('--verbose', dest='verbose',
119 action='store_const', const=True,
120 help='Show verbosed output', default=False)
121
122 key_parser = argparse.ArgumentParser(add_help=False)
123 key_parser_help = (
124 'Key name to find in reclass model files, for example:'
125 ' parameters.linux.network.interface')
126 key_parser.add_argument('key_name', help=key_parser_help, default=None)
127
128 keys_parser = argparse.ArgumentParser(add_help=False)
129 keys_parser.add_argument(
130 'keys',
131 help='Key names to find in reclass model files', nargs='*')
132
133 path_parser = argparse.ArgumentParser(add_help=False)
134 path_parser.add_argument(
135 'path',
136 help='Path to search for *.yml files.', nargs='+')
137
138 domain_parser = argparse.ArgumentParser(add_help=False)
139 domain_parser.add_argument(
140 '--domain', '-d', dest='domain',
141 help=('Show only the nodes which names are ended with the '
142 'specified domain, for example: example.local'))
143
Dennis Dmitriev0cea5702017-07-17 19:03:23 +0300144 env_name_parser = argparse.ArgumentParser(add_help=False)
145 env_name_parser.add_argument(
146 '--env-name', '-e', dest='env_name',
147 help=("Name of the 'environment' to create or use"))
148
Dennis Dmitriev86750962017-07-11 19:44:05 +0300149 vcp_only_parser = argparse.ArgumentParser(add_help=False)
150 vcp_only_parser.add_argument(
151 '--vcp-only', dest='vcp_only',
152 action='store_const', const=True,
153 help=('Show only VCP nodes (present in '
154 'parameters.salt.control.cluster.internal.node)'),
155 default=False)
156
157 non_vcp_only_parser = argparse.ArgumentParser(add_help=False)
158 non_vcp_only_parser.add_argument(
159 '--non-vcp-only', dest='non_vcp_only',
160 action='store_const', const=True, default=False,
161 help=('Show only non-VCP nodes (absent in '
162 'parameters.salt.control.cluster.internal.node)'))
163
164 render_parser = argparse.ArgumentParser(add_help=False)
165 render_parser.add_argument(
166 '--template-dir', '-t', dest='template_dir',
167 help=('Coockiecutter-based template directory'))
168 render_parser.add_argument(
169 '--output-dir', '-o', dest='output_dir',
170 help=('Path to the directory where the rendered '
171 'template will be placed'))
172 render_parser.add_argument(
173 '--context', '-c', dest='contexts', nargs='+',
174 help=('YAML/JSON files with context data to render '
175 'the template'))
176
177
178
179 parser = argparse.ArgumentParser(
180 description="Manage virtual environments. "
181 "For additional help, use with -h/--help option")
182 subparsers = parser.add_subparsers(title="Operation commands",
183 help='available commands',
184 dest='command')
185
186 # TODO: add-class NNN [to] MMM.yml # can be used with 'render'
187 subparsers.add_parser('get-key',
188 parents=[key_parser, path_parser,
189 verbose_parser],
190 help="Find a key in YAMLs found in <path>",
191 description=("Get a key collected from "
192 "different YAMLs"))
193 subparsers.add_parser('del-key',
194 parents=[key_parser, path_parser,
195 verbose_parser],
196 help="Delete a key from YAMLs found in <path>",
197 description="Delete a key from different YAMLs")
198 subparsers.add_parser('list-params',
199 parents=[path_parser, verbose_parser],
200 help=("Collect all options for "
201 "'parameters._params' keys from YAMLs "
202 "found in <path>"))
203 subparsers.add_parser('list-nodes',
204 parents=[domain_parser, vcp_only_parser,
205 non_vcp_only_parser],
206 help=("List nodes that are available for "
207 "reclass. Use on salt-master node only!"))
208 subparsers.add_parser('list-domains',
209 help=("List domains that are available from "
210 "reclass models. Use on salt-master "
211 "node only!"))
212 subparsers.add_parser('show-context',
213 parents=[domain_parser, keys_parser],
214 help=("Show domain nodes with rendered content "
215 "for specified keys. Use on salt-master "
216 "node for already generated inventory "
217 "only!"))
218 subparsers.add_parser('render',
Dennis Dmitriev0cea5702017-07-17 19:03:23 +0300219 parents=[render_parser, env_name_parser],
Dennis Dmitriev86750962017-07-11 19:44:05 +0300220 help=("Render cookiecutter template using "
221 "multiple metadata sources"))
222
223 if len(self.args) == 0:
224 self.args = ['-h']
225 return parser.parse_args(self.args)
226
227
228def main(args=None):
Dennis Dmitrieve56c8b92017-06-16 01:53:16 +0300229 if args is None:
230 args = sys.argv[1:]
231
Dennis Dmitriev86750962017-07-11 19:44:05 +0300232 shell = Shell(args)
233 shell.execute()