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

Side by Side Diff: client/run_isolated.py

Issue 2443663002: Pass args in file from task_runner to run_isolated (Closed)
Patch Set: More review feedback Created 4 years, 1 month 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
OLDNEW
1 #!/usr/bin/env python 1 #!/usr/bin/env python
2 # Copyright 2012 The LUCI Authors. All rights reserved. 2 # Copyright 2012 The LUCI Authors. All rights reserved.
3 # Use of this source code is governed under the Apache License, Version 2.0 3 # Use of this source code is governed under the Apache License, Version 2.0
4 # that can be found in the LICENSE file. 4 # that can be found in the LICENSE file.
5 5
6 """Runs a command with optional isolated input/output. 6 """Runs a command with optional isolated input/output.
7 7
8 Despite name "run_isolated", can run a generic non-isolated command specified as 8 Despite name "run_isolated", can run a generic non-isolated command specified as
9 args. 9 args.
10 10
11 If input isolated hash is provided, fetches it, creates a tree of hard links, 11 If input isolated hash is provided, fetches it, creates a tree of hard links,
12 appends args to the command in the fetched isolated and runs it. 12 appends args to the command in the fetched isolated and runs it.
13 To improve performance, keeps a local cache. 13 To improve performance, keeps a local cache.
14 The local cache can safely be deleted. 14 The local cache can safely be deleted.
15 15
16 Any ${EXECUTABLE_SUFFIX} on the command line will be replaced with ".exe" string 16 Any ${EXECUTABLE_SUFFIX} on the command line will be replaced with ".exe" string
17 on Windows and "" on other platforms. 17 on Windows and "" on other platforms.
18 18
19 Any ${ISOLATED_OUTDIR} on the command line will be replaced by the location of a 19 Any ${ISOLATED_OUTDIR} on the command line will be replaced by the location of a
20 temporary directory upon execution of the command specified in the .isolated 20 temporary directory upon execution of the command specified in the .isolated
21 file. All content written to this directory will be uploaded upon termination 21 file. All content written to this directory will be uploaded upon termination
22 and the .isolated file describing this directory will be printed to stdout. 22 and the .isolated file describing this directory will be printed to stdout.
23 23
24 Any ${SWARMING_BOT_FILE} on the command line will be replaced by the value of 24 Any ${SWARMING_BOT_FILE} on the command line will be replaced by the value of
25 the --bot-file parameter. This file is used by a swarming bot to communicate 25 the --bot-file parameter. This file is used by a swarming bot to communicate
26 state of the host to tasks. It is written to by the swarming bot's 26 state of the host to tasks. It is written to by the swarming bot's
27 on_before_task() hook in the swarming server's custom bot_config.py. 27 on_before_task() hook in the swarming server's custom bot_config.py.
28 """ 28 """
29 29
30 __version__ = '0.8.5' 30 __version__ = '0.8.6'
31 31
32 import argparse
32 import base64 33 import base64
33 import collections 34 import collections
35 import json
34 import logging 36 import logging
35 import optparse 37 import optparse
36 import os 38 import os
37 import sys 39 import sys
38 import tempfile 40 import tempfile
39 import time 41 import time
40 42
41 from third_party.depot_tools import fix_encoding 43 from third_party.depot_tools import fix_encoding
42 44
43 from utils import file_path 45 from utils import file_path
(...skipping 680 matching lines...) Expand 10 before | Expand all | Expand 10 after
724 'non-zero only on internal failure') 726 'non-zero only on internal failure')
725 parser.add_option( 727 parser.add_option(
726 '--hard-timeout', type='float', help='Enforce hard timeout in execution') 728 '--hard-timeout', type='float', help='Enforce hard timeout in execution')
727 parser.add_option( 729 parser.add_option(
728 '--grace-period', type='float', 730 '--grace-period', type='float',
729 help='Grace period between SIGTERM and SIGKILL') 731 help='Grace period between SIGTERM and SIGKILL')
730 parser.add_option( 732 parser.add_option(
731 '--bot-file', 733 '--bot-file',
732 help='Path to a file describing the state of the host. The content is ' 734 help='Path to a file describing the state of the host. The content is '
733 'defined by on_before_task() in bot_config.') 735 'defined by on_before_task() in bot_config.')
736 parser.add_option(
737 '-a', '--argsfile',
738 # This is actually handled in parse_args; it's included here purely so it
739 # can make it into the help text.
740 help='Specify a file containing a JSON array of arguments to this '
741 'script. If --argsfile is provided, no other argument may be '
742 'provided on the command line.')
734 data_group = optparse.OptionGroup(parser, 'Data source') 743 data_group = optparse.OptionGroup(parser, 'Data source')
735 data_group.add_option( 744 data_group.add_option(
736 '-s', '--isolated', 745 '-s', '--isolated',
737 help='Hash of the .isolated to grab from the isolate server.') 746 help='Hash of the .isolated to grab from the isolate server.')
738 isolateserver.add_isolate_server_options(data_group) 747 isolateserver.add_isolate_server_options(data_group)
739 parser.add_option_group(data_group) 748 parser.add_option_group(data_group)
740 749
741 isolateserver.add_cache_options(parser) 750 isolateserver.add_cache_options(parser)
742 751
743 cipd.add_cipd_options(parser) 752 cipd.add_cipd_options(parser)
744 753
745 debug_group = optparse.OptionGroup(parser, 'Debugging') 754 debug_group = optparse.OptionGroup(parser, 'Debugging')
746 debug_group.add_option( 755 debug_group.add_option(
747 '--leak-temp-dir', 756 '--leak-temp-dir',
748 action='store_true', 757 action='store_true',
749 help='Deliberately leak isolate\'s temp dir for later examination. ' 758 help='Deliberately leak isolate\'s temp dir for later examination. '
750 'Default: %default') 759 'Default: %default')
751 debug_group.add_option( 760 debug_group.add_option(
752 '--root-dir', help='Use a directory instead of a random one') 761 '--root-dir', help='Use a directory instead of a random one')
753 parser.add_option_group(debug_group) 762 parser.add_option_group(debug_group)
754 763
755 auth.add_auth_options(parser) 764 auth.add_auth_options(parser)
756 765
757 parser.set_defaults(cache='cache', cipd_cache='cipd_cache') 766 parser.set_defaults(cache='cache', cipd_cache='cipd_cache')
758 return parser 767 return parser
759 768
760 769
761 def main(args): 770 def parse_args(args):
771 # Create a fake mini-parser just to get out the "-a" command. Note that
772 # it's not documented here; instead, it's documented in create_option_parser
773 # even though that parser will never actually get to parse it. This is
774 # because -f is exclusive with all other options and arguments.
M-A Ruel 2016/10/24 21:19:28 -f?
aludwin 2016/10/24 21:27:00 Now --argsfile; fixed.
775 file_argparse = argparse.ArgumentParser(add_help=False)
776 file_argparse.add_argument("-a", "--argsfile")
M-A Ruel 2016/10/24 21:19:28 single quotes
aludwin 2016/10/24 21:27:00 Done.
777 (file_args, nonfile_args) = file_argparse.parse_known_args(args)
778 if not file_args.argsfile == None:
M-A Ruel 2016/10/24 21:19:28 don't use this pattern, do: if file_args.argsfile:
aludwin 2016/10/24 21:27:00 Done.
779 if len(nonfile_args) > 0:
M-A Ruel 2016/10/24 21:19:28 if nonfile_args:
aludwin 2016/10/24 21:27:00 Done, didn't realize [] was falsy.
780 file_argparse.error('Can\'t specify --argsfile with'
781 'any other arguments (%s)' % nonfile_args)
782 try:
783 with open(file_args.argsfile, 'r') as f:
784 args = json.loads(f.read())
M-A Ruel 2016/10/24 21:19:28 args = json.load(f)
785 except (IOError, OSError, ValueError) as e:
786 # We don't need to error out here - "args" is now empty,
787 # so the call below to parser.parse_args(args) will fail
788 # and print the full help text.
789 print >> sys.stderr, "Couldn't read arguments: %s" % e
M-A Ruel 2016/10/24 21:19:28 use single quote and escape \'
aludwin 2016/10/24 21:27:00 Done.
790
791 # Even if we failed to read the args, just call the normal parser now since it
792 # will print the correct help message.
762 parser = create_option_parser() 793 parser = create_option_parser()
763 options, args = parser.parse_args(args) 794 options, args = parser.parse_args(args)
795 return (parser, options, args)
796
797
798 def main(args):
799 (parser, options, args) = parse_args(args)
764 800
765 isolated_cache = isolateserver.process_cache_options(options) 801 isolated_cache = isolateserver.process_cache_options(options)
766 if options.clean: 802 if options.clean:
767 if options.isolated: 803 if options.isolated:
768 parser.error('Can\'t use --isolated with --clean.') 804 parser.error('Can\'t use --isolated with --clean.')
769 if options.isolate_server: 805 if options.isolate_server:
770 parser.error('Can\'t use --isolate-server with --clean.') 806 parser.error('Can\'t use --isolate-server with --clean.')
771 if options.json: 807 if options.json:
772 parser.error('Can\'t use --json with --clean.') 808 parser.error('Can\'t use --json with --clean.')
773 isolated_cache.cleanup() 809 isolated_cache.cleanup()
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
822 except cipd.Error as ex: 858 except cipd.Error as ex:
823 print >> sys.stderr, ex.message 859 print >> sys.stderr, ex.message
824 return 1 860 return 1
825 861
826 862
827 if __name__ == '__main__': 863 if __name__ == '__main__':
828 subprocess42.inhibit_os_error_reporting() 864 subprocess42.inhibit_os_error_reporting()
829 # Ensure that we are always running with the correct encoding. 865 # Ensure that we are always running with the correct encoding.
830 fix_encoding.fix_encoding() 866 fix_encoding.fix_encoding()
831 file_path.enable_symlink() 867 file_path.enable_symlink()
868
832 sys.exit(main(sys.argv[1:])) 869 sys.exit(main(sys.argv[1:]))
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698