blucon.sh: Allow validation/results dir override
[validation.git] / bluval / blucon.py
1 #!/usr/bin/python3
2 ##############################################################################
3 # Copyright (c) 2019 AT&T Intellectual Property.                             #
4 # Copyright (c) 2019 Nokia.                                                  #
5 #                                                                            #
6 # Licensed under the Apache License, Version 2.0 (the "License"); you may    #
7 # not use this file except in compliance with the License.                   #
8 #                                                                            #
9 # You may obtain a copy of the License at                                    #
10 #       http://www.apache.org/licenses/LICENSE-2.0                           #
11 #                                                                            #
12 # Unless required by applicable law or agreed to in writing, software        #
13 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT  #
14 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.           #
15 # See the License for the specific language governing permissions and        #
16 # limitations under the License.                                             #
17 ##############################################################################
18 """This module parses yaml file, reads layers runs container for each layer.
19 """
20
21 import subprocess
22 import sys
23 import traceback
24 from pathlib import Path
25
26 import click
27 import yaml
28
29 from bluutil import BluvalError
30 from bluutil import ShowStopperError
31
32 _OPTIONAL_ALSO = False
33 _SUBNET = ""
34
35 def get_volumes(layer):
36     """Create a list with volumes to mount in the container for given layer
37     """
38     mypath = Path(__file__).absolute()
39     volume_yaml = yaml.safe_load(mypath.parents[0].joinpath("volumes.yaml").open())
40
41     if layer not in volume_yaml['layers']:
42         return ''
43     if volume_yaml['layers'][layer] is None:
44         return ''
45
46     volume_list = ''
47     for vol in volume_yaml['layers'][layer]:
48         if volume_yaml['volumes'][vol]['local'] == '':
49             continue
50         volume_list = (volume_list + ' -v ' +
51                        volume_yaml['volumes'][vol]['local'] + ':' +
52                        volume_yaml['volumes'][vol]['target'])
53     return volume_list
54
55
56 def invoke_docker(bluprint, layer, tag):
57     """Start docker container for given layer
58     """
59     volume_list = get_volumes('common') + get_volumes(layer)
60     cmd = ("docker run --rm" + volume_list + _SUBNET +
61            " akraino/validation:{0}-{3}"
62            " /bin/sh -c"
63            " 'cd /opt/akraino/validation "
64            "&& python -B bluval/bluval.py -l {0} {1} {2}'"
65            .format(layer, ("-o" if _OPTIONAL_ALSO else ""), bluprint, tag))
66
67     args = [cmd]
68     try:
69         print('\nInvoking {}'.format(args), flush=True)
70         subprocess.call(args, shell=True)
71     except OSError:
72         #print('Error while executing {}'.format(args))
73         raise BluvalError(OSError)
74
75
76 def invoke_dockers(yaml_loc, layer, blueprint_name, tag):
77     """Parses yaml file and starts docker container for one/all layers
78     """
79     with open(str(yaml_loc)) as yaml_file:
80         yamldoc = yaml.safe_load(yaml_file)
81     blueprint = yamldoc['blueprint']
82     if layer is None or layer == "all":
83         for each_layer in blueprint['layers']:
84             invoke_docker(blueprint_name, each_layer, tag)
85     else:
86         invoke_docker(blueprint_name, layer, tag)
87
88
89 @click.command()
90 @click.argument('blueprint')
91 @click.option('--layer', '-l')
92 @click.option('--network', '-n')
93 @click.option('--tag', '-t')
94 @click.option('--optional_also', '-o', is_flag=True)
95 def main(blueprint, layer, network, tag, optional_also):
96     """Takes blueprint name and optional layer. Validates inputs and derives
97     yaml location from blueprint name. Invokes validate on blueprint.
98     """
99     global _OPTIONAL_ALSO  # pylint: disable=global-statement
100     global _SUBNET # pylint: disable=global-statement
101     mypath = Path(__file__).absolute()
102     yaml_loc = mypath.parents[0].joinpath('bluval-{}.yaml'.format(blueprint))
103     if layer is not None:
104         layer = layer.lower()
105     if optional_also:
106         _OPTIONAL_ALSO = True
107         print("_OPTIONAL_ALSO {}".format(_OPTIONAL_ALSO))
108     if network is not None:
109         _SUBNET = " --net=" + network
110         print("Using", _SUBNET)
111     if tag is None:
112         tag = 'latest'
113     print("Using tag {}".format(tag))
114     try:
115         invoke_dockers(yaml_loc, layer, blueprint, tag)
116     except ShowStopperError as err:
117         print('ShowStopperError:', err)
118     except BluvalError as err:
119         print('Unexpected BluvalError', err)
120         raise
121     except:
122         print("Exception in user code:")
123         print("-"*60)
124         traceback.print_exc(file=sys.stdout)
125         print("-"*60)
126         raise
127
128
129 if __name__ == "__main__":
130     # pylint: disable=no-value-for-parameter
131     main()