def SetReviewers(self, change, add=(), remove=(), project=None): """Adjust the reviewers list for a given change. Arguments: change: Either the ChangeId, or preferably, the gerrit change number. If you use a ChangeId be aware that this command will fail if multiple changes match. Can be either a string or an integer. add: Either this or removes must be given. If given, it must be a either a single email address/group name, or a sequence of email addresses or group names to add as reviewers. Note it's not considered an error if you attempt to add a reviewer that already is marked as a reviewer for the change. remove: Same rules as 'add', just is the list of reviewers to remove. project: If given, the project to find the given change w/in. Unnecessary if passing a gerrit number for change; if passing a ChangeId, strongly advised that a project be specified. Raises: RunCommandError if the attempt to modify the reviewers list fails. If the command fails, no changes to the reviewer list occurs. """ if not add and not remove: raise ValueError('Either add or remove must be non empty') command = self.ssh_prefix + ['gerrit', 'set-reviewers'] command.extend(cros_build_lib.iflatten_instance( [('--add', x) for x in cros_build_lib.iflatten_instance(add)] + [('--remove', x) for x in cros_build_lib.iflatten_instance(remove)])) if project is not None: command += ['--project', project] # Always set the change last; else --project may not take hold by that # point, with gerrit complaining of duplicates when there aren't. # Yes kiddies, gerrit can be retarded; this being one of those cases. command.append(str(change)) cros_build_lib.RunCommandCaptureOutput(command, print_cmd=self.print_cmd)
def test_it(self): f = lambda *a: list(cros_build_lib.iflatten_instance(*a)) self.assertEqual([1, 2], f([1, 2])) self.assertEqual([1, '2a'], f([1, '2a'])) self.assertEqual([1, 2, 'b'], f([1, [2, 'b']])) self.assertEqual([1, 2, 'f', 'd', 'a', 's'], f([1, 2, ('fdas',)], int)) self.assertEqual([''], f(''))
def WriteFile(path, content, mode='w', atomic=False, makedirs=False): """Write the given content to disk. Args: path: Pathway to write the content to. content: Content to write. May be either an iterable, or a string. mode: Optional; if binary mode is necessary, pass 'wb'. If appending is desired, 'w+', etc. atomic: If the updating of the file should be done atomically. Note this option is incompatible w/ append mode. makedirs: If True, create missing leading directories in the path. """ write_path = path if atomic: write_path = path + '.tmp' if makedirs: SafeMakedirs(os.path.dirname(path)) with open(write_path, mode) as f: f.writelines(cros_build_lib.iflatten_instance(content)) if not atomic: return try: os.rename(write_path, path) except EnvironmentError: SafeUnlink(write_path) raise
def _CheckArgs(self, cliargs, expected): """Check |cliargs| produces |expected|.""" parser = commandline.ArgumentParser() parser.add_argument('-x', action='split_extend', default=[]) opts = parser.parse_args( cros_build_lib.iflatten_instance(['-x', x] for x in cliargs)) self.assertEqual(opts.x, expected)
def AddDeviceArgument(cls, parser, schemes=commandline.DEVICE_SCHEME_SSH, optional=None): """Add a device argument to the parser. This has a few advantages over adding a device argument directly: - Standardizes the device --help message for all tools. - May allow `brillo` and `cros` to use the same source. The device argument is normally positional in cros but optional in brillo. If that is the only difference between a cros and brillo tool, this function allows the same source be shared for both. Args: parser: The parser to add the device argument to. schemes: List of device schemes or single scheme to allow. optional: Whether the device is an optional or positional argument; None to auto-determine based on toolset. """ if optional is None: optional = (GetToolset() == 'brillo') help_strings = [] schemes = list(cros_build_lib.iflatten_instance(schemes)) if commandline.DEVICE_SCHEME_SSH in schemes: help_strings.append('Target a device with [user@]hostname[:port].') if commandline.DEVICE_SCHEME_USB in schemes: help_strings.append('Target removable media with usb://[path].') if commandline.DEVICE_SCHEME_FILE in schemes: help_strings.append('Target a local file with file://path.') parser.add_argument('--device' if optional else 'device', type=commandline.DeviceParser(schemes), help=' '.join(help_strings))
def test_it(self): f = lambda x, **kwargs: list( cros_build_lib.iflatten_instance(x, **kwargs)) self.assertEqual([1, 2], f([1, 2])) self.assertEqual([1, '2a'], f([1, '2a'])) self.assertEqual([1, 2, 'b'], f([1, [2, 'b']])) self.assertEqual([1, 2, 'f', 'd', 'a', 's'], f([1, 2, ('fdas', )], terminate_on_kls=int)) self.assertEqual([''], f('')) self.assertEqual([b''], f(b'')) self.assertEqual([b'1234'], f(b'1234')) self.assertEqual([b'12', b'34'], f([b'12', b'34']))
def SetReviewers(self, change, add=(), remove=(), project=None): """Adjust the reviewers list for a given change. Arguments: change: Either the ChangeId, or preferably, the gerrit change number. If you use a ChangeId be aware that this command will fail if multiple changes match. Can be either a string or an integer. add: Either this or removes must be given. If given, it must be a either a single email address/group name, or a sequence of email addresses or group names to add as reviewers. Note it's not considered an error if you attempt to add a reviewer that already is marked as a reviewer for the change. remove: Same rules as 'add', just is the list of reviewers to remove. project: If given, the project to find the given change w/in. Unnecessary if passing a gerrit number for change; if passing a ChangeId, strongly advised that a project be specified. Raises: RunCommandError if the attempt to modify the reviewers list fails. If the command fails, no changes to the reviewer list occurs. """ if not add and not remove: raise ValueError('Either add or remove must be non empty') command = self.ssh_prefix + ['gerrit', 'set-reviewers'] command.extend( cros_build_lib.iflatten_instance( [('--add', x) for x in cros_build_lib.iflatten_instance(add)] + [('--remove', x) for x in cros_build_lib.iflatten_instance(remove)])) if project is not None: command += ['--project', project] # Always set the change last; else --project may not take hold by that # point, with gerrit complaining of duplicates when there aren't. # Yes kiddies, gerrit can be retarded; this being one of those cases. command.append(str(change)) cros_build_lib.RunCommandCaptureOutput(command, print_cmd=self.print_cmd)
def _StoreLog(self, log): """Store any log related to the payload. Write out the log to a known file name. Mostly in its own function to simplify unittest mocks. Args: log: The delta logs as a single string. """ try: osutils.WriteFile(self.log_file, log, mode='a') except TypeError as e: logging.error('crbug.com/1023497 osutils.WriteFile failed: %s', e) logging.error('log (type %s): %r', type(log), log) flat = cros_build_lib.iflatten_instance(log) logging.error('flattened: %r', flat) logging.error('expanded: %r', list(flat))
def AddDeviceArgument(cls, parser, schemes=commandline.DEVICE_SCHEME_SSH): """Add a device argument to the parser. This standardizes the help message across all subcommands. Args: parser: The parser to add the device argument to. schemes: List of device schemes or single scheme to allow. """ help_strings = [] schemes = list(cros_build_lib.iflatten_instance(schemes)) if commandline.DEVICE_SCHEME_SSH in schemes: help_strings.append('Target a device with [user@]hostname[:port].') if commandline.DEVICE_SCHEME_USB in schemes: help_strings.append('Target removable media with usb://[path].') if commandline.DEVICE_SCHEME_FILE in schemes: help_strings.append('Target a local file with file://path.') parser.add_argument('device', type=commandline.DeviceParser(schemes), help=' '.join(help_strings))
def CreateMockOverlay(self, overlay, build_root=None): """Helper for creating an overlay in the fake buildroot. Args: overlay: The overlay name to create. Usually the board name. build_root: The buildroot in which to create the mock overlay. """ if not build_root: build_root = self.build_root layout_path = os.path.join(build_root, 'src', 'overlays', 'overlay-%s' % overlay, 'metadata', 'layout.conf') layout_content = 'repo-name = %s\n' % overlay # Don't use osutils.WriteFile, some tests mock it out. osutils.SafeMakedirs(os.path.dirname(layout_path)) with open(layout_path, 'w') as f: f.writelines(cros_build_lib.iflatten_instance(layout_content))
def AddDeviceArgument(cls, parser, schemes=commandline.DEVICE_SCHEME_SSH, positional=False): """Add a device argument to the parser. This standardizes the help message across all subcommands. Args: parser: The parser to add the device argument to. schemes: List of device schemes or single scheme to allow. positional: Whether it should be a positional or named argument. """ help_strings = [] schemes = list(cros_build_lib.iflatten_instance(schemes)) if commandline.DEVICE_SCHEME_SSH in schemes: help_strings.append( 'Target a device with [user@]hostname[:port]. ' 'IPv4/IPv6 addresses are allowed, but IPv6 must ' 'use brackets (e.g. [::1]).') if commandline.DEVICE_SCHEME_USB in schemes: help_strings.append('Target removable media with usb://[path].') if commandline.DEVICE_SCHEME_SERVO in schemes: help_strings.append( 'Target a servo by port or serial number with ' 'servo:port[:port] or servo:serial:serial-number. ' 'e.g. servo:port:1234 or servo:serial:C1230024192.') if commandline.DEVICE_SCHEME_FILE in schemes: help_strings.append('Target a local file with file://path.') if positional: parser.add_argument('device', type=commandline.DeviceParser(schemes), help=' '.join(help_strings)) else: parser.add_argument('-d', '--device', type=commandline.DeviceParser(schemes), help=' '.join(help_strings))
def _GetIdValuesForRow(self, row, id_columns): """Return a dict with values from |row| in |id_columns|.""" id_values = dict((col, row[col]) for col in cros_build_lib.iflatten_instance(id_columns)) return id_values
def _GetIdValuesForRow(self, row, id_columns): """Return a dict with values from |row| in |id_columns|.""" id_values = dict( (col, row[col]) for col in cros_build_lib.iflatten_instance(id_columns)) return id_values
# Supported targets. TARGETS = ( 'instances', 'images', 'disks', ) # Supported operations. OPERATIONS = { 'instances': ('create', 'delete', 'list', 'ssh',), 'images': ('create', 'delete', 'list',), 'disks': ('list',), } # All supported operations. ALL_OPERATIONS = set(cros_build_lib.iflatten_instance(OPERATIONS.values())) def BotifyInstance(instance, project, zone, testing=False): """Transforms the |instance| to a Chrome OS bot. Perform necessary tasks to clone the chromite repostority on the |instance| and run setup scripts as BUILDBOT_USER. The majority the setup logic is (and should be) in the scripts that run directly on the |instance| because `gcloud compute ssh` incurs addtional overhead on every invocation. (e.g. instance name to IP lookup, copying public key if needed, etc). Args: instance: Name of the GCE instance.