7c31df5973d0c42a7ec56e0de5733e35b858f3d1
[osm/SO.git] / common / python / rift / mano / yang_translator / rwmano / syntax / tosca_template.py
1 # Copyright 2016 RIFT.io Inc
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain 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,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14
15 from collections import OrderedDict
16
17 import textwrap
18
19 from rift.mano.yang_translator.common.utils import _
20 from rift.mano.yang_translator.rwmano.syntax.tosca_resource \
21 import ToscaResource
22
23 import yaml
24
25
26 class ToscaTemplate(object):
27 '''Container for full RIFT.io TOSCA template.'''
28
29 KEYS = (TOSCA, FILES) = ('tosca', 'files')
30
31 def __init__(self, log):
32 self.log = log
33 self.resources = []
34
35 def output_to_tosca(self):
36 self.log.debug(_('Converting translated output to tosca template.'))
37
38 templates = {}
39
40 for resource in self.resources:
41 # Each NSD should generate separate templates
42 if resource.type == 'nsd':
43 tmpl = resource.generate_tosca_type()
44 tmpl = resource.generate_tosca_template(tmpl)
45 self.log.debug(_("TOSCA template generated for {0}:\n{1}").
46 format(resource.name, tmpl))
47 templates[resource.name] = {self.TOSCA: self.output_to_yaml(tmpl)}
48 files = resource.get_supporting_files()
49 if len(files):
50 templates[resource.name][self.FILES] = files
51
52 return templates
53
54 def represent_ordereddict(self, dumper, data):
55 nodes = []
56 for key, value in data.items():
57 node_key = dumper.represent_data(key)
58 node_value = dumper.represent_data(value)
59 nodes.append((node_key, node_value))
60 return yaml.nodes.MappingNode(u'tag:yaml.org,2002:map', nodes)
61
62 def ordered_node(self, node):
63 order = [ToscaResource.TYPE, ToscaResource.DERIVED_FROM,
64 ToscaResource.DESC, ToscaResource.MEMBERS,
65 ToscaResource.PROPERTIES, ToscaResource.CAPABILITIES,
66 ToscaResource.REQUIREMENTS,ToscaResource.ARTIFACTS,
67 ToscaResource.INTERFACES]
68 new_node = OrderedDict()
69 for ent in order:
70 if ent in node:
71 new_node.update({ent: node.pop(ent)})
72
73 # Check if we missed any entry
74 if len(node):
75 self.log.warn(_("Did not sort these entries: {0}").
76 format(node))
77 new_node.update(node)
78
79 return new_node
80
81 def ordered_nodes(self, nodes):
82 new_nodes = OrderedDict()
83 if isinstance(nodes, dict):
84 for name, node in nodes.items():
85 new_nodes.update({name: self.ordered_node(node)})
86 return new_nodes
87 else:
88 return nodes
89
90 def output_to_yaml(self, tosca):
91 self.log.debug(_('Converting translated output to yaml format.'))
92 dict_output = OrderedDict()
93
94 dict_output.update({'tosca_definitions_version':
95 tosca['tosca_definitions_version']})
96 # Description
97 desc_str = ""
98 if ToscaResource.DESC in tosca:
99 # Wrap the text to a new line if the line exceeds 80 characters.
100 wrapped_txt = "\n ". \
101 join(textwrap.wrap(tosca[ToscaResource.DESC], 80))
102 desc_str = ToscaResource.DESC + ": >\n " + \
103 wrapped_txt + "\n\n"
104 dict_output.update({ToscaResource.DESC: tosca[ToscaResource.DESC]})
105
106 if ToscaResource.METADATA in tosca:
107 dict_output.update({ToscaResource.METADATA:
108 tosca[ToscaResource.METADATA]})
109
110 # Add all types
111 types_list = [ToscaResource.DATA_TYPES, ToscaResource.CAPABILITY_TYPES,
112 ToscaResource.NODE_TYPES,
113 ToscaResource.GROUP_TYPES, ToscaResource.POLICY_TYPES]
114 for typ in types_list:
115 if typ in tosca:
116 dict_output.update({typ: self.ordered_nodes(tosca[typ])})
117
118 # Add topology template
119 topo_list = [ToscaResource.INPUTS, ToscaResource.NODE_TMPL,
120 ToscaResource.GROUPS, ToscaResource.POLICIES,
121 ToscaResource.OUTPUTS]
122 if ToscaResource.TOPOLOGY_TMPL in tosca:
123 tmpl = OrderedDict()
124 for typ in tosca[ToscaResource.TOPOLOGY_TMPL]:
125 tmpl.update({typ:
126 self.ordered_nodes(
127 tosca[ToscaResource.TOPOLOGY_TMPL][typ])})
128 dict_output.update({ToscaResource.TOPOLOGY_TMPL: tmpl})
129
130 yaml.add_representer(OrderedDict, self.represent_ordereddict)
131 yaml_string = yaml.dump(dict_output, default_flow_style=False)
132 # get rid of the '' from yaml.dump around numbers
133 yaml_string = yaml_string.replace('\'', '')
134 self.log.debug(_("YAML output:\n{0}").format(yaml_string))
135 return yaml_string