1
|
|
|
# Licensed to the StackStorm, Inc ('StackStorm') under one or more |
2
|
|
|
# contributor license agreements. See the NOTICE file distributed with |
3
|
|
|
# this work for additional information regarding copyright ownership. |
4
|
|
|
# The ASF licenses this file to You under the Apache License, Version 2.0 |
5
|
|
|
# (the "License"); you may not use this file except in compliance with |
6
|
|
|
# the License. You may obtain a copy of the License at |
7
|
|
|
# |
8
|
|
|
# http://www.apache.org/licenses/LICENSE-2.0 |
9
|
|
|
# |
10
|
|
|
# Unless required by applicable law or agreed to in writing, software |
11
|
|
|
# distributed under the License is distributed on an "AS IS" BASIS, |
12
|
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
13
|
|
|
# See the License for the specific language governing permissions and |
14
|
|
|
# limitations under the License. |
15
|
|
|
|
16
|
|
|
import os |
17
|
|
|
|
18
|
|
|
from oslo_config import cfg |
19
|
|
|
|
20
|
|
|
from st2common import log as logging |
21
|
|
|
from st2common.content import utils as content_utils |
22
|
|
|
from st2common.constants.meta import ALLOWED_EXTS |
23
|
|
|
from st2common.bootstrap.base import ResourceRegistrar |
24
|
|
|
from st2common.models.api.pack import ConfigAPI |
25
|
|
|
from st2common.persistence.pack import Config |
26
|
|
|
from st2common.exceptions.db import StackStormDBObjectNotFoundError |
27
|
|
|
|
28
|
|
|
__all__ = [ |
29
|
|
|
'ConfigsRegistrar' |
30
|
|
|
] |
31
|
|
|
|
32
|
|
|
|
33
|
|
|
LOG = logging.getLogger(__name__) |
34
|
|
|
|
35
|
|
|
|
36
|
|
|
class ConfigsRegistrar(ResourceRegistrar): |
37
|
|
|
""" |
38
|
|
|
Class for loading and registering pack configs located in |
39
|
|
|
/opt/stackstorm/configs/<pack name>.yaml |
40
|
|
|
""" |
41
|
|
|
|
42
|
|
|
ALLOWED_EXTENSIONS = ALLOWED_EXTS |
43
|
|
|
|
44
|
|
|
def __init__(self, use_pack_cache=True, fail_on_failure=False, validate_configs=True): |
45
|
|
|
super(ConfigsRegistrar, self).__init__(use_pack_cache=use_pack_cache, |
46
|
|
|
fail_on_failure=fail_on_failure) |
47
|
|
|
|
48
|
|
|
self._validate_configs = validate_configs |
49
|
|
|
|
50
|
|
|
def register_configs_for_all_packs(self, base_dirs): |
51
|
|
|
""" |
52
|
|
|
Register configs for all the available packs. |
53
|
|
|
""" |
54
|
|
|
# Register packs first |
55
|
|
|
self.register_packs(base_dirs=base_dirs) |
56
|
|
|
|
57
|
|
|
registered_count = 0 |
58
|
|
|
packs = self._pack_loader.get_packs(base_dirs=base_dirs) |
59
|
|
|
pack_names = packs.keys() |
60
|
|
|
|
61
|
|
|
for pack_name in pack_names: |
62
|
|
|
config_path = self._get_config_path_for_pack(pack_name=pack_name) |
63
|
|
|
|
64
|
|
|
if not os.path.isfile(config_path): |
65
|
|
|
# Config for that pack doesn't exist |
66
|
|
|
LOG.debug('No config found for pack "%s" (file "%s" is not present).', pack_name, |
67
|
|
|
config_path) |
68
|
|
|
continue |
69
|
|
|
|
70
|
|
|
try: |
71
|
|
|
self._register_config_for_pack(pack=pack_name, config_path=config_path) |
72
|
|
|
except Exception as e: |
73
|
|
|
if self._fail_on_failure: |
74
|
|
|
raise e |
75
|
|
|
|
76
|
|
|
LOG.exception('Failed to register config for pack "%s": %s', pack_name, str(e)) |
77
|
|
|
else: |
78
|
|
|
registered_count += 1 |
79
|
|
|
|
80
|
|
|
return registered_count |
81
|
|
|
|
82
|
|
|
def register_config_for_pack(self, pack_dir): |
83
|
|
|
""" |
84
|
|
|
Register config for a provided pack. |
85
|
|
|
""" |
86
|
|
|
pack_dir = pack_dir[:-1] if pack_dir.endswith('/') else pack_dir |
87
|
|
|
_, pack_name = os.path.split(pack_dir) |
88
|
|
|
|
89
|
|
|
# Register pack first |
90
|
|
|
self.register_pack(pack_name=pack_name, pack_dir=pack_dir) |
91
|
|
|
|
92
|
|
|
config_path = self._get_config_path_for_pack(pack_name=pack_name) |
93
|
|
|
if not os.path.isfile(config_path): |
94
|
|
|
return 0 |
95
|
|
|
|
96
|
|
|
self._register_config_for_pack(pack=pack_name, config_path=config_path) |
97
|
|
|
return 1 |
98
|
|
|
|
99
|
|
|
def _get_config_path_for_pack(self, pack_name): |
100
|
|
|
configs_path = os.path.join(cfg.CONF.system.base_path, 'configs/') |
101
|
|
|
config_path = os.path.join(configs_path, '%s.yaml' % (pack_name)) |
102
|
|
|
|
103
|
|
|
return config_path |
104
|
|
|
|
105
|
|
|
def _register_config_for_pack(self, pack, config_path): |
106
|
|
|
content = {} |
107
|
|
|
values = self._meta_loader.load(config_path) |
108
|
|
|
|
109
|
|
|
content['pack'] = pack |
110
|
|
|
content['values'] = values |
111
|
|
|
|
112
|
|
|
config_api = ConfigAPI(**content) |
113
|
|
|
config_api.validate(validate_against_schema=self._validate_configs) |
114
|
|
|
config_db = ConfigAPI.to_model(config_api) |
115
|
|
|
|
116
|
|
|
try: |
117
|
|
|
config_db.id = Config.get_by_pack(config_api.pack).id |
118
|
|
|
except StackStormDBObjectNotFoundError: |
119
|
|
|
LOG.debug('Config for pack "%s" not found. Creating new entry.', pack) |
120
|
|
|
|
121
|
|
|
try: |
122
|
|
|
config_db = Config.add_or_update(config_db) |
123
|
|
|
extra = {'config_db': config_db} |
124
|
|
|
LOG.audit('Config for pack "%s" is updated.', config_db.pack, extra=extra) |
125
|
|
|
except Exception: |
126
|
|
|
LOG.exception('Failed to config for pack %s.', pack) |
127
|
|
|
raise |
128
|
|
|
|
129
|
|
|
return config_db |
130
|
|
|
|
131
|
|
|
|
132
|
|
|
def register_configs(packs_base_paths=None, pack_dir=None, use_pack_cache=True, |
133
|
|
|
fail_on_failure=False, validate_configs=True): |
134
|
|
|
|
135
|
|
|
if packs_base_paths: |
136
|
|
|
assert isinstance(packs_base_paths, list) |
137
|
|
|
|
138
|
|
|
if not packs_base_paths: |
139
|
|
|
packs_base_paths = content_utils.get_packs_base_paths() |
140
|
|
|
|
141
|
|
|
registrar = ConfigsRegistrar(use_pack_cache=use_pack_cache, |
142
|
|
|
fail_on_failure=fail_on_failure, |
143
|
|
|
validate_configs=validate_configs) |
144
|
|
|
|
145
|
|
|
if pack_dir: |
146
|
|
|
result = registrar.register_config_for_pack(pack_dir=pack_dir) |
147
|
|
|
else: |
148
|
|
|
result = registrar.register_configs_for_all_packs(base_dirs=packs_base_paths) |
149
|
|
|
|
150
|
|
|
return result |
151
|
|
|
|