blucon: Add argument '-p' for pulling latest tag
[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 _PULL = False
33 _OPTIONAL_ALSO = False
34 _SUBNET = ""
35
36 def get_volumes(layer):
37     """Create a list with volumes to mount in the container for given layer
38     """
39     mypath = Path(__file__).absolute()
40     volume_yaml = yaml.safe_load(mypath.parents[0].joinpath("volumes.yaml").open())
41
42     if layer not in volume_yaml['layers']:
43         return ''
44     if volume_yaml['layers'][layer] is None:
45         return ''
46
47     volume_list = ''
48     for vol in volume_yaml['layers'][layer]:
49         if volume_yaml['volumes'][vol]['local'] == '':
50             continue
51         volume_list = (volume_list + ' -v ' +
52                        volume_yaml['volumes'][vol]['local'] + ':' +
53                        volume_yaml['volumes'][vol]['target'])
54     return volume_list
55
56
57 def pull_docker(layer, tag):
58     """Pull docker image for given layer
59     """
60     cmd = ("docker pull akraino/validation:{0}-{1}"
61            .format(layer, tag))
62
63     args = [cmd]
64     try:
65         print('\nPulling image using {}'.format(args), flush=True)
66         subprocess.call(args, shell=True)
67     except OSError:
68         raise BluvalError(OSError)
69
70
71 def invoke_docker(bluprint, layer, tag):
72     """Start docker container for given layer
73     """
74     if _PULL:
75         pull_docker(layer, tag)
76     volume_list = get_volumes('common') + get_volumes(layer)
77     cmd = ("docker run --rm" + volume_list + _SUBNET +
78            " akraino/validation:{0}-{3}"
79            " /bin/sh -c"
80            " 'cd /opt/akraino/validation "
81            "&& python -B bluval/bluval.py -l {0} {1} {2}'"
82            .format(layer, ("-o" if _OPTIONAL_ALSO else ""), bluprint, tag))
83
84     args = [cmd]
85     try:
86         print('\nInvoking {}'.format(args), flush=True)
87         subprocess.call(args, shell=True)
88     except OSError:
89         #print('Error while executing {}'.format(args))
90         raise BluvalError(OSError)
91
92
93 def invoke_dockers(yaml_loc, layer, blueprint_name, tag):
94     """Parses yaml file and starts docker container for one/all layers
95     """
96     with open(str(yaml_loc)) as yaml_file:
97         yamldoc = yaml.safe_load(yaml_file)
98     blueprint = yamldoc['blueprint']
99     if layer is None or layer == "all":
100         for each_layer in blueprint['layers']:
101             invoke_docker(blueprint_name, each_layer, tag)
102     else:
103         invoke_docker(blueprint_name, layer, tag)
104
105
106 @click.command()
107 @click.argument('blueprint')
108 @click.option('--layer', '-l')
109 @click.option('--network', '-n')
110 @click.option('--tag', '-t')
111 @click.option('--optional_also', '-o', is_flag=True)
112 @click.option('--pull', '-p', is_flag=True)
113 # pylint: disable=too-many-arguments
114 def main(blueprint, layer, network, tag, optional_also, pull):
115     """Takes blueprint name and optional layer. Validates inputs and derives
116     yaml location from blueprint name. Invokes validate on blueprint.
117     """
118     global _PULL # pylint: disable=global-statement
119     global _OPTIONAL_ALSO  # pylint: disable=global-statement
120     global _SUBNET # pylint: disable=global-statement
121     mypath = Path(__file__).absolute()
122     yaml_loc = mypath.parents[0].joinpath('bluval-{}.yaml'.format(blueprint))
123     if layer is not None:
124         layer = layer.lower()
125     if pull:
126         _PULL = True
127         print("_PULL {}".format(_PULL))
128     if optional_also:
129         _OPTIONAL_ALSO = True
130         print("_OPTIONAL_ALSO {}".format(_OPTIONAL_ALSO))
131     if network is not None:
132         _SUBNET = " --net=" + network
133         print("Using", _SUBNET)
134     if tag is None:
135         tag = 'latest'
136     print("Using tag {}".format(tag))
137     try:
138         invoke_dockers(yaml_loc, layer, blueprint, tag)
139     except ShowStopperError as err:
140         print('ShowStopperError:', err)
141     except BluvalError as err:
142         print('Unexpected BluvalError', err)
143         raise
144     except:
145         print("Exception in user code:")
146         print("-"*60)
147         traceback.print_exc(file=sys.stdout)
148         print("-"*60)
149         raise
150
151
152 if __name__ == "__main__":
153     # pylint: disable=no-value-for-parameter
154     main()