1 # Licensed to the Apache Software Foundation (ASF) 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
8 # http://www.apache.org/licenses/LICENSE-2.0
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.
17 Common code for contexts.
21 from contextlib import contextmanager
22 from functools import partial
27 logger as aria_logger,
30 from aria.storage import exceptions
32 from ...utils.uuid import generate_uuid
35 class BaseContext(object):
37 Base class for contexts.
40 INSTRUMENTATION_FIELDS = (
41 modeling.models.Service.inputs,
42 modeling.models.ServiceTemplate.inputs,
43 modeling.models.Policy.properties,
44 modeling.models.PolicyTemplate.properties,
45 modeling.models.Node.attributes,
46 modeling.models.Node.properties,
47 modeling.models.NodeTemplate.attributes,
48 modeling.models.NodeTemplate.properties,
49 modeling.models.Group.properties,
50 modeling.models.GroupTemplate.properties,
51 modeling.models.Capability.properties,
52 # TODO ARIA-279: modeling.models.Capability.attributes,
53 modeling.models.CapabilityTemplate.properties,
54 # TODO ARIA-279: modeling.models.CapabilityTemplate.attributes
55 modeling.models.Relationship.properties,
56 modeling.models.Artifact.properties,
57 modeling.models.ArtifactTemplate.properties,
58 modeling.models.Interface.inputs,
59 modeling.models.InterfaceTemplate.inputs,
60 modeling.models.Operation.inputs,
61 modeling.models.OperationTemplate.inputs
64 class PrefixedLogger(object):
65 def __init__(self, base_logger, task_id=None):
66 self._logger = base_logger
67 self._task_id = task_id
69 def __getattr__(self, attribute):
70 if attribute.upper() in logging._levelNames:
71 return partial(self._logger_with_task_id, _level=attribute)
73 return getattr(self._logger, attribute)
75 def _logger_with_task_id(self, *args, **kwargs):
76 level = kwargs.pop('_level')
77 kwargs.setdefault('extra', {})['task_id'] = self._task_id
78 return getattr(self._logger, level)(*args, **kwargs)
88 super(BaseContext, self).__init__(**kwargs)
90 self._id = generate_uuid(variant='uuid')
91 self._model = model_storage
92 self._resource = resource_storage
93 self._service_id = service_id
94 self._workdir = workdir
95 self._execution_id = execution_id
98 def _register_logger(self, level=None, task_id=None):
99 self.logger = self.PrefixedLogger(
100 logging.getLogger(aria_logger.TASK_LOGGER_NAME), task_id=task_id)
101 self.logger.setLevel(level or logging.DEBUG)
102 if not self.logger.handlers:
103 self.logger.addHandler(self._get_sqla_handler())
105 def _get_sqla_handler(self):
106 return aria_logger.create_sqla_log_handler(model=self._model,
107 log_cls=modeling.models.Log,
108 execution_id=self._execution_id)
112 '{name}(name={self.name}, '
113 'deployment_id={self._service_id}, '
114 .format(name=self.__class__.__name__, self=self))
117 def logging_handlers(self, handlers=None):
118 handlers = handlers or []
120 for handler in handlers:
121 self.logger.addHandler(handler)
124 for handler in handlers:
125 self.logger.removeHandler(handler)
130 Storage model API ("MAPI").
137 Storage resource API ("RAPI").
139 return self._resource
142 def service_template(self):
144 Service template model.
146 return self.service.service_template
151 Service instance model.
153 return self.model.service.get(self._service_id)
169 def download_resource(self, destination, path=None):
171 Download a service template resource from the storage resource API ("RAPI").
174 self.resource.service.download(entry_id=str(self.service.id),
175 destination=destination,
177 except exceptions.StorageError:
178 self.resource.service_template.download(entry_id=str(self.service_template.id),
179 destination=destination,
182 def download_resource_and_render(self, destination, path=None, variables=None):
184 Downloads a service template resource from the resource storage and renders its content as a
185 Jinja template using the provided variables. ``ctx`` is available to the template without
186 providing it explicitly.
188 resource_content = self.get_resource(path=path)
189 resource_content = self._render_resource(resource_content=resource_content,
191 with open(destination, 'wb') as f:
192 f.write(resource_content)
194 def get_resource(self, path=None):
196 Reads a service instance resource as string from the resource storage.
199 return self.resource.service.read(entry_id=str(self.service.id), path=path)
200 except exceptions.StorageError:
201 return self.resource.service_template.read(entry_id=str(self.service_template.id),
204 def get_resource_and_render(self, path=None, variables=None):
206 Reads a service instance resource as string from the resource storage and renders it as a
207 Jinja template using the provided variables. ``ctx`` is available to the template without
208 providing it explicitly.
210 resource_content = self.get_resource(path=path)
211 return self._render_resource(resource_content=resource_content, variables=variables)
213 def _render_resource(self, resource_content, variables):
214 variables = variables or {}
215 variables.setdefault('ctx', self)
216 resource_template = jinja2.Template(resource_content)
217 return resource_template.render(variables)