Merge "Change "KubernetesObject" class name to "ReplicationController""
[yardstick.git] / yardstick / network_services / vnf_generic / vnfdgen.py
1 # Copyright (c) 2016-2017 Intel Corporation
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 """ Generic file to map and build vnf discriptor """
15
16 from __future__ import absolute_import
17
18 from functools import reduce
19
20 import jinja2
21 import logging
22
23 from yardstick.common.task_template import finalize_for_yaml
24 from yardstick.common.utils import try_int
25 from yardstick.common.yaml_loader import yaml_load
26
27 LOG = logging.getLogger(__name__)
28
29
30 def render(vnf_model, **kwargs):
31     """Render jinja2 VNF template
32     Do not check for missing arguments
33
34     :param vnf_model: string that contains template
35     :param kwargs: Dict with template arguments
36     :returns:rendered template str
37     """
38
39     return jinja2.Template(vnf_model, finalize=finalize_for_yaml).render(**kwargs)
40
41
42 def generate_vnfd(vnf_model, node):
43     """
44
45     :param vnf_model: VNF definition template, e.g. tg_ping_tpl.yaml
46     :param node: node configuration taken from pod.yaml
47     :return: Complete VNF Descriptor that will be taken
48              as input for GenericVNF.__init__
49     """
50     # get is unused as global method inside template
51     # node["get"] = key_flatten_get
52     node["get"] = deepgetitem
53     # Set Node details to default if not defined in pod file
54     # we CANNOT use TaskTemplate.render because it does not allow
55     # for missing variables, we need to allow password for key_filename
56     # to be undefined
57     rendered_vnfd = render(vnf_model, **node)
58     # This is done to get rid of issues with serializing node
59     del node["get"]
60     filled_vnfd = yaml_load(rendered_vnfd)
61     return filled_vnfd
62
63
64 # dict_flatten was causing recursion errors with Jinja2 so we removed and replaced
65 # which this function from stackoverflow that doesn't require generating entire dictionaries
66 # each time we query a key
67 def deepgetitem(obj, item, default=None):
68     """Steps through an item chain to get the ultimate value.
69
70     If ultimate value or path to value does not exist, does not raise
71     an exception and instead returns `fallback`.
72
73     Based on
74     https://stackoverflow.com/a/38623359
75     https://stackoverflow.com/users/1820042/donny-winston
76
77     add try_int to work with sequences
78
79     >>> d = {'snl_final': {'about': {'_icsd': {'icsd_id': 1, 'fr': [2, 3], '0': 24, 0: 4}}}}
80     >>> deepgetitem(d, 'snl_final.about._icsd.icsd_id')
81     1
82     >>> deepgetitem(d, 'snl_final.about._sandbox.sbx_id')
83     >>>
84     >>> deepgetitem(d, 'snl_final.about._icsd.fr.1')
85     3
86     >>> deepgetitem(d, 'snl_final.about._icsd.0')
87     24
88     """
89     def getitem(obj, name):
90         # try string then convert to int
91         try:
92             return obj[name]
93         except (KeyError, TypeError, IndexError):
94             name = try_int(name)
95             try:
96                 return obj[name]
97             except (KeyError, TypeError, IndexError):
98                 return default
99     return reduce(getitem, item.split('.'), obj)