Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(150)

Side by Side Diff: scripts/slave/kitchen_run.py

Issue 1869053002: kitchen_run: initial CL (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/tools/build
Patch Set: Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 #!/usr/bin/env python
2 # Copyright 2016 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
5
6 import argparse
7 import collections
8 import json
9 import logging
10 import os
11 import shutil
12 import subprocess
13 import sys
14 import tempfile
15
16
17 # Install Infra build environment.
18 BUILD_ROOT = os.path.dirname(os.path.dirname(os.path.dirname(
19 os.path.abspath(__file__))))
20 sys.path.insert(0, os.path.join(BUILD_ROOT, 'scripts'))
21
22 from common import chromium_utils
23 from common import env
24 from slave import infra_platform
25 from slave import update_scripts
26
27
28 LOGGER = logging.getLogger('kitchen_run')
29
30
31 # A CIPD binary description, including the package name and version, and relativ e
iannucci 2016/04/11 18:07:28 hm... why copy+paste this but not copy+paste updat
dnj 2016/04/11 18:17:15 +1 make these first-level cipd.py constructs.
Paweł Hajdan Jr. 2016/04/11 20:44:39 Well let me know what you mean by that. Our interf
dnj 2016/04/12 21:22:21 We'd define them in "cipd.py", then "import cipd"
32 # path of the binary within the package.
33 CipdBinary = collections.namedtuple('CipdBinary',
34 ('package', 'version', 'relpath'))
35
36
37 CIPD_BINARIES = {
38 ('linux', 64): CipdBinary(
39 'infra/tools/luci/kitchen/linux-amd64', 'latest', 'kitchen'),
40 }
41
42
43 def _run_command(cmd, **kwargs):
44 if kwargs.pop('dry_run', False):
dnj 2016/04/11 18:17:15 You don't actually use this option.
Paweł Hajdan Jr. 2016/04/11 20:44:40 Good point - will remove.
45 LOGGER.info('(Dry Run) Would have executed command: %s', cmd)
46 return 0, ''
47
48 LOGGER.debug('Executing command: %s', cmd)
49 kwargs.setdefault('stderr', subprocess.STDOUT)
50 proc = subprocess.Popen(cmd, **kwargs)
51 stdout, _ = proc.communicate()
52
53 LOGGER.debug('Process [%s] returned [%d] with output:\n%s',
54 cmd, proc.returncode, stdout)
55 return proc.returncode, stdout
56
57
58 def _check_command(cmd, **kwargs):
59 rv, stdout = _run_command(cmd, **kwargs)
60 if rv != 0:
61 raise subprocess.CalledProcessError(rv, cmd, output=stdout)
62 return stdout
63
64
65 def _install_cipd(path, *packages):
66 """Returns (list): The paths to the binaries in each of the packages.
67
68 This method bootstraps CIPD in "path", installing the packages specified
69 by "packages" and returning the paths to their binaries.
70
71 Args:
72 path (str): The CIPD installation root.
73 packages (CipdBinary): The set of CIPD binary packages to install.
74 """
75 verbosity = 0
76 level = logging.getLogger().level
77 if level <= logging.INFO:
nodir 2016/04/12 01:04:55 I'd use simpler == and `verbose = 1` and `verbose
78 verbosity += 1
79 if level <= logging.DEBUG:
80 verbosity += 1
81
82 packages_path = os.path.join(path, 'packages.json')
83 pmap = {}
84 cmd = [
85 sys.executable,
86 os.path.join(env.Build, 'scripts', 'slave', 'cipd.py'),
87 '--dest-directory', path,
88 '--json-output', packages_path,
89 ] + (['--verbose'] * verbosity)
90 for p in packages:
91 cmd += ['-P', '%s@%s' % (p.package, p.version)]
92 pmap[p.package] = os.path.join(path, p.relpath)
93
94 try:
95 _check_command(cmd)
96 except subprocess.CalledProcessError:
97 LOGGER.exception('Failed to install LogDog CIPD packages.')
dnj 2016/04/11 18:17:15 nit: "Kitchen".
Paweł Hajdan Jr. 2016/04/11 20:44:40 Will do.
98 raise LogDogBootstrapError()
iannucci 2016/04/11 18:07:28 especially since this is clearly raising copy/past
99
100 # Resolve installed packages.
101 return tuple(pmap[p.package] for p in packages)
nodir 2016/04/12 01:04:55 You could compute path here, no need for pmap var
102
103
104 def _bootstrap_kitchen(basedir):
105 cipd_path = os.path.join(basedir, '.kitchen_cipd')
106 #(kitchen,) = _install_cipd(cipd_path, CIPD_BINARIES[infra_platform.get()])
107 return '/usr/local/google/home/phajdan/luci-go/kitchen'
iannucci 2016/04/11 18:07:28 erm... what?
Paweł Hajdan Jr. 2016/04/11 20:44:39 See "As you see, it has some local hacks I've used
108 return kitchen
109
110
111 def main(argv):
112 print argv
113 parser = argparse.ArgumentParser()
114 parser.add_argument('--repository')
115 parser.add_argument('--revision')
116 parser.add_argument('--recipe')
117 parser.add_argument('--build-properties-gz', dest='build_properties',
118 type=chromium_utils.convert_gz_json_type, default={},
119 help='build properties in b64 gz JSON format')
120 args = parser.parse_args(argv)
121
122 basedir = os.getcwd()
123 kitchen = _bootstrap_kitchen(basedir)
124
125 rv = 1
126
127 tempdir = tempfile.mkdtemp(prefix='kitchen_run')
dnj 2016/04/11 18:17:15 I would like you to use a scheme like I did with L
Paweł Hajdan Jr. 2016/04/11 20:44:39 Could you explain more? How would one run taint an
128 try:
129 rv, _ = _run_command([
130 kitchen, 'cook',
131 '-repository', args.repository,
132 '-revision', args.revision,
133 '-recipe', args.recipe,
134 '-properties', json.dumps(args.build_properties),
dnj 2016/04/11 18:17:15 Can we have this get passed to Kitchen as JSON blo
Paweł Hajdan Jr. 2016/04/11 20:44:39 Good point. Could you explain more? Pass path to a
dnj 2016/04/12 21:22:21 Yep. 1) Create JSON blob as an array (or object w
135 ], cwd=tempdir)
dnj 2016/04/11 18:17:15 Do we actually want to run Kitchen out of a tempor
Paweł Hajdan Jr. 2016/04/11 20:44:39 I think so. That's what we do with swarmbucket. Wh
dnj 2016/04/12 21:22:21 CWD means magic things for some processes. No spec
136 finally:
137 shutil.rmtree(tempdir)
iannucci 2016/04/11 18:07:28 finally clauses like this are unreliable. tempfold
Paweł Hajdan Jr. 2016/04/11 20:44:39 Good point. I'll find some way to implement the cl
138
139 return rv
140
141
142 def shell_main(argv):
143 # TODO(phajdan.jr): re-enable update_scripts.
144 if False and update_scripts.update_scripts():
dnj 2016/04/11 18:17:15 Want to remove "False", no?
Paweł Hajdan Jr. 2016/04/11 20:44:40 "As you see, it has some local hacks I've used for
nodir 2016/04/12 01:04:55 I guess it would be easier for reviewers (4) if th
dnj 2016/04/12 21:22:21 Understood that you have local hacks, but when you
145 # Re-execute with the updated kitchen_run.py.
146 rv, _ = _run_command([sys.executable] + argv)
147 return rv
148 else:
149 return main(argv[1:])
150
151
152 if __name__ == '__main__':
153 logging.basicConfig(level=logging.INFO)
154 sys.exit(shell_main(sys.argv))
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698