b3da7c339e3943b4caece356f21bcd57bb885c31
[osm/devops.git] / descriptor-packages / tools / charm-generator / generator / generators / actions_generator.py
1 # Copyright 2019 Whitestack, LLC
2 #
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 #
15 # For those usages not covered by the Apache License, Version 2.0 please
16 # contact: esousa@whitestack.com or glavado@whitestack.com
17 ##
18
19 import functools
20 import logging
21 import os
22 import stat
23
24 from jinja2 import Environment, PackageLoader
25
26
27 class ActionsGenerator:
28 LOGGER = logging.getLogger()
29 ENV = Environment(loader=PackageLoader('generator.actions', 'templates'))
30
31 def __init__(self, metadata, actions, license=None, options=None):
32 """
33 Creates the object to generate the actions folder, actions files and actions.yaml.
34
35 Usage should be:
36
37 1) Create the object.
38 2) Run the generate method.
39
40 :param metadata: metadata information about the charm being generated.
41 :param actions: actions to be included in the charm.
42 :param license: information license to included in the charm being generated.
43 :param options: options to override the normal flow.
44 """
45 self.path = os.getcwd()
46 self.metadata = metadata
47 self.actions = actions
48 self.license = license
49 self.options = options
50
51 def generate(self):
52 """
53 Generates the actions folder, actions files and actions.yaml.
54 """
55 ActionsGenerator.LOGGER.info('Generating the actions...')
56
57 self._create_actions_folder()
58
59 for action in self.actions:
60 self._generate_action_file(action)
61
62 self._generate_actions_yaml_file()
63
64 ActionsGenerator.LOGGER.info('Generated the actions.')
65
66 def _create_actions_folder(self):
67 """
68 Creates the actions folder, where all the action files are placed.
69 These files are the entry point for the execution of the actions.
70 """
71 ActionsGenerator.LOGGER.debug('Creating the actions folder...')
72
73 actions_path = self.path + '/actions'
74
75 if not os.path.isdir(actions_path):
76 os.mkdir(actions_path)
77 else:
78 ActionsGenerator.LOGGER.warning('Actions folder already exists.')
79 return
80
81 ActionsGenerator.LOGGER.debug('Created actions folder.')
82
83 def _generate_action_file(self, action):
84 """
85 Generates the action file to act as entry point for a specific action.
86
87 Note: the action file is made executable during this function.
88
89 :param action: dictionary with information about the action
90 """
91 ActionsGenerator.LOGGER.debug('Creating action file: %s...', action['action_name'])
92
93 playbook_path = self.path + ('/actions/%s' % action['action_name'])
94 action_file_template = ActionsGenerator.ENV.get_template('action.j2')
95
96 with open(playbook_path, "w") as f:
97 f.write(action_file_template.render(license=self.license))
98 mode = os.fstat(f.fileno()).st_mode
99 mode |= stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH
100 os.fchmod(f.fileno(), stat.S_IMODE(mode))
101
102 ActionsGenerator.LOGGER.debug('Created action file: %s.', action['action_name'])
103
104 def _generate_actions_yaml_file(self):
105 """
106 Generates the actions.yaml file from a template.
107 It takes all the playbook information and fills in the templates.
108
109 Note: renames the old actions.yaml file with a .bkp extension, so the history is preserved.
110 """
111 ActionsGenerator.LOGGER.debug('Creating actions.yaml...')
112
113 actions_yaml_path = self.path + '/actions.yaml'
114 actions_template = ActionsGenerator.ENV.get_template('actions.yaml.j2')
115
116 if os.path.isfile(actions_yaml_path):
117 ids = [int(f.split('.')[-1]) for f in os.listdir(self.path) if f.startswith('actions.yaml.bkp')]
118
119 id = 0
120 if ids:
121 id = functools.reduce(lambda x, y: x if (x > y) else y, ids)
122 id += 1
123
124 backup_actions_yaml_path = self.path + ('/actions.yaml.bkp.%02d' % id)
125 os.rename(actions_yaml_path, backup_actions_yaml_path)
126
127 with open(actions_yaml_path, 'w') as f:
128 f.write(actions_template.render(actions=self.actions, license=self.license))
129
130 ActionsGenerator.LOGGER.debug('Created actions.yaml.')