Merge ~mthaddon/charm-test/+git/charm-test:python3 into charm-test:master
- Git
- lp:~mthaddon/charm-test/+git/charm-test
- python3
- Merge into master
Proposed by
Tom Haddon
Status: | Merged |
---|---|
Approved by: | Tom Haddon |
Approved revision: | b14673a92e1676f35cab077296022381075e5774 |
Merged at revision: | d882026f697f9aaac50ec38c0c946cc6c913c6e6 |
Proposed branch: | ~mthaddon/charm-test/+git/charm-test:python3 |
Merge into: | charm-test:master |
Diff against target: |
282 lines (+153/-108) 3 files modified
Makefile (+2/-0) charm-test (+150/-108) charm-test.py (+1/-0) |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Stuart Bishop (community) | Approve | ||
Review via email: mp+345155@code.launchpad.net |
Commit message
Rewrite in python3
Description of the change
Rewrite in python3
To post a comment you must log in.
Revision history for this message
🤖 Canonical IS Merge Bot (canonical-is-mergebot) wrote : | # |
Revision history for this message
Stuart Bishop (stub) wrote : | # |
Comments inline.
All landable as is, with tweaks from comments in future branches.
review:
Approve
Revision history for this message
Tom Haddon (mthaddon) : | # |
Revision history for this message
🤖 Canonical IS Merge Bot (canonical-is-mergebot) wrote : | # |
Change successfully merged at revision d882026f697f9aa
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | diff --git a/Makefile b/Makefile |
2 | new file mode 100644 |
3 | index 0000000..f8db829 |
4 | --- /dev/null |
5 | +++ b/Makefile |
6 | @@ -0,0 +1,2 @@ |
7 | +lint: |
8 | + @find . -name \*.py -exec python /usr/bin/flake8 --config=/dev/null --max-line-length=120 --max-complexity=10 --hang-closing {} + |
9 | diff --git a/charm-test b/charm-test |
10 | index e290ccb..97be0ca 100755 |
11 | --- a/charm-test |
12 | +++ b/charm-test |
13 | @@ -1,111 +1,153 @@ |
14 | -#!/bin/bash |
15 | - |
16 | -# Script to run lint and test suite inside LXC. Expects to be run from the |
17 | -# root of a charm directory. |
18 | - |
19 | -function usage() { |
20 | - echo "$0 [controller-name] [container-name] [juju-model-name]" |
21 | - echo "" |
22 | - echo " controller-name: the name of a pre-configured Juju 2 controller to" |
23 | - echo " run tests against (defaults to currently selected)" |
24 | - echo " container-name: optional name of LXC container to create (defaults" |
25 | - echo " to charm-test)" |
26 | - echo " juju-model-name: optional name of juju model to create and use" |
27 | - echo " (defaults to charm-test)" |
28 | - echo "" |
29 | - echo " Examples:" |
30 | - echo " $0" |
31 | - echo " $0 my-aws-controller" |
32 | - echo " $0 my-aws-controller my-graylog-container" |
33 | - echo " $0 my-aws-controller my-graylog-container my-juju-model" |
34 | - echo "" |
35 | - echo "This script will:" |
36 | - echo " 1. Create an LXC, install all bundletester dependencies." |
37 | - echo " 2. Copy charm source into LXC." |
38 | - echo " 3. Run charm build in LXC." |
39 | - echo " 4. Copy Juju credentials into the LXC." |
40 | - echo " 5. Run bundletester tests on the specified Juju controller from" |
41 | - echo " within the LXC. This includes creating a Juju model to run" |
42 | - echo " tests against." |
43 | - echo "" |
44 | - exit 1 |
45 | -} |
46 | - |
47 | -if [[ "$1" == "--help" ]] || [[ "$1" == "-h" ]]; then |
48 | - usage |
49 | -fi |
50 | - |
51 | -set -eu |
52 | - |
53 | -CONTROLLER_NAME=${1:-$(juju switch | cut -d: -f1)} |
54 | -CONTAINER_NAME=${2:-charm-test} |
55 | -JUJU_MODEL_NAME=${3:-charm-test} |
56 | - |
57 | -function log_info() { |
58 | - echo "$(date '+%Y-%m-%d %H:%M:%S') INFO: $1" |
59 | -} |
60 | - |
61 | -function lxc_run() { |
62 | - cmd=$1 |
63 | - log_info "Running command \"${cmd}\" in container \"${CONTAINER_NAME}\" as root" |
64 | - lxc exec ${CONTAINER_NAME} -- bash -c "${cmd}" |
65 | -} |
66 | - |
67 | -function lxc_run_as_ubuntu() { |
68 | - cmd=$1 |
69 | - log_info "Running command \"${cmd}\" in container \"${CONTAINER_NAME}\" as ubuntu" |
70 | - lxc exec ${CONTAINER_NAME} -- sudo -u ubuntu -i -- ${cmd} |
71 | -} |
72 | - |
73 | -function recreate_lxc() { |
74 | - set +e |
75 | - log_info "Checking if container exists" |
76 | - lxc list | grep ${CONTAINER_NAME} |
77 | - if [ $? -eq 0 ]; then |
78 | - log_info "Found old container, deleting" |
79 | - lxc delete --force ${CONTAINER_NAME} |
80 | - fi |
81 | - set -e |
82 | - lxc launch ubuntu:16.04 ${CONTAINER_NAME} |
83 | - # We shouldn't need to just wait here, but there doesn't appear to be an |
84 | - # lxc wait command. |
85 | - log_info "Sleeping for 20 seconds while LXC comes up with networking" |
86 | - sleep 20 |
87 | - # First of all, copy the current charm directory into the LXC. |
88 | - lxc_run_as_ubuntu "mkdir -p /home/ubuntu/charmsrc" |
89 | - tar cf - . | lxc exec ${CONTAINER_NAME} -- tar xvf - -C /home/ubuntu/charmsrc |
90 | +#!/usr/bin/python3 |
91 | + |
92 | +# Copyright (c) 2018 Canonical Ltd |
93 | +# License: GPLv3 |
94 | +# Author: Tom Haddon <tom.haddon@canonical.com> |
95 | + |
96 | +import argparse |
97 | +import datetime |
98 | +import os |
99 | +import subprocess |
100 | +import time |
101 | +import yaml |
102 | + |
103 | +# Script to run lint and test suite inside LXC in a stanardized way. |
104 | +# This script will: |
105 | +# 1. Create an LXC, install test dependencies as defined by the charm's |
106 | +# Makefile. |
107 | +# 2. Copy charm source into the LXC. |
108 | +# 3. Run charm build in the LXC. |
109 | +# 4. Copy Juju credentials into the LXC. |
110 | +# 5. Run make test. Any Juju operations will use the specified Juju contoller. |
111 | + |
112 | + |
113 | +def _get_default_controller(): |
114 | + """If we don't specify a controller, return currently selected""" |
115 | + output_list = subprocess.check_output(['juju', 'switch'], universal_newlines=True).split(":") |
116 | + if len(output_list) != 2: |
117 | + raise Exception("Unexpected output from juju switch: {}".format(":".join(output_list))) |
118 | + return output_list[0] |
119 | + |
120 | + |
121 | +def print_log(msg, level="INFO"): |
122 | + print("{} {} {}".format(level, datetime.datetime.now(), msg)) |
123 | + |
124 | + |
125 | +def find_charm(args): |
126 | + metadata_yaml = os.path.join(args.charm_directory, 'metadata.yaml') |
127 | + if not os.path.exists(metadata_yaml): |
128 | + raise Exception("Unable to find metadata.yaml in directory, got: {}".format(metadata_yaml)) |
129 | + parsed_metadata = yaml.safe_load(open(metadata_yaml, 'r').read()) |
130 | + return parsed_metadata["name"] |
131 | + |
132 | + |
133 | +def lxc_run(cmd, args): |
134 | + print_log('Running command "{}" in container "{}" as root'.format(" ".join(cmd), args.container_name)) |
135 | + lxc_cmd = ['lxc', 'exec', args.container_name, '--'] + cmd |
136 | + lxc_run = subprocess.check_output(lxc_cmd, universal_newlines=True) |
137 | + if lxc_run: |
138 | + print_log("Output of command: {}".format(lxc_run)) |
139 | + |
140 | + |
141 | +def lxc_run_as_ubuntu(cmd, args): |
142 | + print_log('Running command "{}" in container "{}" as ubuntu'.format(" ".join(cmd), args.container_name)) |
143 | + lxc_cmd = ['lxc', 'exec', args.container_name, '--', 'sudo', '-u', 'ubuntu', '-i', '--'] + cmd |
144 | + lxc_run = subprocess.check_output(lxc_cmd, universal_newlines=True) |
145 | + if lxc_run: |
146 | + print_log("Output of command: {}".format(lxc_run)) |
147 | + |
148 | + |
149 | +def recreate_lxc(args): |
150 | + print_log("Checking if container exists") |
151 | + lxc_list = subprocess.check_output(['lxc', 'list', args.container_name], universal_newlines=True) |
152 | + if args.container_name in lxc_list: |
153 | + print_log("Found old container, deleting...") |
154 | + deleted = subprocess.check_output(['lxc', 'delete', '--force', args.container_name], universal_newlines=True) |
155 | + if deleted: |
156 | + print_log("Output from deletion: {}".format(deleted)) |
157 | + lxc_launch = subprocess.check_output(['lxc', 'launch', 'ubuntu:16.04', args.container_name], |
158 | + universal_newlines=True) |
159 | + if lxc_launch: |
160 | + print_log("Output from LXC creation: {}".format(lxc_launch)) |
161 | + print_log("Sleeping for 20 seconds while LXC comes up with networking") |
162 | + time.sleep(20) |
163 | + # Copy the charm directory into the LXC |
164 | + os.chdir(args.charm_directory) |
165 | + lxc_run_as_ubuntu(["mkdir", "-p", "/home/ubuntu/charmsrc"], args) |
166 | + copy_charm_cmd = "tar cf - . | lxc exec {} -- tar xvf - -C /home/ubuntu/charmsrc".format(args.container_name) |
167 | + copy_charm = subprocess.Popen(copy_charm_cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, |
168 | + universal_newlines=True) |
169 | + output = copy_charm.communicate()[0] |
170 | + print_log("Output from charm copy: {}".format(output)) |
171 | # Install test dependencies. |
172 | - lxc_run "apt-get update" |
173 | - lxc_run "apt-get install make" |
174 | - lxc_run_as_ubuntu "make -C /home/ubuntu/charmsrc testdeps" |
175 | + lxc_run(["apt-get", "update"], args) |
176 | + lxc_run(["apt-get", "install", "make"], args) |
177 | + lxc_run_as_ubuntu(["make", "-C", "/home/ubuntu/charmsrc", "testdeps"], args) |
178 | # Build the charm inside the LXC. |
179 | - lxc_run_as_ubuntu "make -C /home/ubuntu/charmsrc charmbuild BUILDDEST=/home/ubuntu/charmbuilt" |
180 | + lxc_run_as_ubuntu(["make", "-C", "/home/ubuntu/charmsrc", "charmbuild", "BUILDDEST=/home/ubuntu/charmbuilt"], |
181 | + args) |
182 | # Copy config for Juju access. |
183 | - lxc_run "mkdir -p /home/ubuntu/.local/share/juju/" |
184 | - cd ~/.local/share/juju && tar cf - . | lxc exec ${CONTAINER_NAME} -- tar xvf - -C /home/ubuntu/.local/share/juju |
185 | - lxc_run "chown -R ubuntu:ubuntu /home/ubuntu/.local/share/juju" |
186 | -} |
187 | - |
188 | -FOUND_CHARM=$(find . -maxdepth 1 -name metadata.yaml | xargs grep '^name' | awk '{print $2}') |
189 | -log_info "About to run charm-test against the \"${FOUND_CHARM}\" charm" |
190 | - |
191 | -log_info "Recreating container \"${CONTAINER_NAME}\"" |
192 | -recreate_lxc |
193 | - |
194 | -# Provide a visual break so it's more obvious set up has finished and you're |
195 | -# now looking at output you care about |
196 | -log_info "" |
197 | -log_info "--------------------------------------------" |
198 | -log_info "Set up complete, about to run lint and tests" |
199 | -log_info "--------------------------------------------" |
200 | -log_info "" |
201 | - |
202 | -lxc_run_as_ubuntu "juju add-model -c ${CONTROLLER_NAME} ${JUJU_MODEL_NAME}" |
203 | -# Even though we're running this in the charmsrc directory, because we're |
204 | -# passing in the BUILDDEST variable it'll run tests inside the charm we've |
205 | -# built above. |
206 | -lxc_run_as_ubuntu "make -C /home/ubuntu/charmsrc test BUILDDEST=/home/ubuntu/charmbuilt JUJU_MODEL=${CONTROLLER_NAME}:${JUJU_MODEL_NAME}" |
207 | - |
208 | -log_info "Cleaning up" |
209 | -lxc_run_as_ubuntu "juju destroy-model -y ${CONTROLLER_NAME}:${JUJU_MODEL_NAME}" |
210 | -lxc delete --force ${CONTAINER_NAME} |
211 | + lxc_run(["mkdir", "-p", "/home/ubuntu/.local/share/juju/"], args) |
212 | + os.chdir(os.path.expanduser('~/.local/share/juju')) |
213 | + copy_juju_config_cmd = "tar cf - . | lxc exec {} -- tar xvf - -C /home/ubuntu/.local/share/juju".format( |
214 | + args.container_name) |
215 | + copy_juju_config = subprocess.Popen(copy_juju_config_cmd, shell=True, stdout=subprocess.PIPE, |
216 | + stderr=subprocess.STDOUT, universal_newlines=True) |
217 | + output = copy_juju_config.communicate()[0] |
218 | + print_log("Output from Juju config copy: {}".format(output)) |
219 | + lxc_run(["chown", "-R", "ubuntu:ubuntu", "/home/ubuntu/.local/share/juju"], args) |
220 | + |
221 | + |
222 | +def visual_break(): |
223 | + print_log("") |
224 | + print_log("--------------------------------------------") |
225 | + print_log("Set up complete, about to run lint and tests") |
226 | + print_log("--------------------------------------------") |
227 | + print_log("") |
228 | + |
229 | + |
230 | +def add_juju_model(args): |
231 | + lxc_run_as_ubuntu(["juju", "add-model", "-c", args.controller_name, args.juju_model_name], args) |
232 | + |
233 | + |
234 | +def run_tests(args): |
235 | + lxc_run_as_ubuntu(["make", "-C", "/home/ubuntu/charmsrc", "test", "BUILDDEST=/home/ubuntu/charmbuilt", |
236 | + "JUJU_MODEL={}:{}".format(args.controller_name, args.juju_model_name)], args) |
237 | + |
238 | + |
239 | +def clean_up(args): |
240 | + print_log("Cleaning up") |
241 | + lxc_run_as_ubuntu(["juju", "destroy-model", "-y" "{}:{}".format(args.controller_name, args.juju_model_name)], |
242 | + args) |
243 | + lxc_delete = subprocess.check_output(['lxc', 'delete', '--force', args.container_name], universal_newlines=True) |
244 | + if lxc_delete: |
245 | + print_log("Output of LXC delete: {}".format(lxc_delete)) |
246 | + |
247 | + |
248 | +def parse_args(): |
249 | + parser = argparse.ArgumentParser() |
250 | + parser.add_argument("-d", "--charm-directory", default=".", help="Directory of charm to run tests from (defaults to" |
251 | + "current working directory).") |
252 | + parser.add_argument("--controller-name", default=_get_default_controller(), |
253 | + help="The name of a pre-configured Juju 2 controller to run tests against (defaults to " |
254 | + "currently selected).") |
255 | + parser.add_argument("--container-name", default="charm-test", help="optional name of LXC container to create " |
256 | + "(defaults to 'charm-test')") |
257 | + parser.add_argument("-j", "--juju-model-name", default="charm-test", |
258 | + help="optional name of juju model to create and use (defaults to 'charm-test')") |
259 | + return parser.parse_args() |
260 | + |
261 | + |
262 | +def main(): |
263 | + args = parse_args() |
264 | + charm = find_charm(args) |
265 | + print_log("About to run charm-test against the '{}' charm".format(charm)) |
266 | + recreate_lxc(args) |
267 | + visual_break() |
268 | + add_juju_model(args) |
269 | + run_tests(args) |
270 | + clean_up(args) |
271 | + |
272 | + |
273 | +if __name__ == "__main__": |
274 | + main() |
275 | diff --git a/charm-test.py b/charm-test.py |
276 | new file mode 120000 |
277 | index 0000000..a024413 |
278 | --- /dev/null |
279 | +++ b/charm-test.py |
280 | @@ -0,0 +1 @@ |
281 | +charm-test |
282 | \ No newline at end of file |
This merge proposal is being monitored by mergebot. Change the status to Approved to merge.