def test_multiple_files(self): """Test multiple files.""" self.response.artifact.path = self.source_file1_inside self.response.artifact.location = common_pb2.Path.INSIDE self.response.nested_artifact.path.path = self.source_file2_inside self.response.nested_artifact.path.location = common_pb2.Path.INSIDE artifact3 = self.response.artifacts.add() artifact3.path = self.source_file3_inside artifact3.location = common_pb2.Path.INSIDE field_handler.extract_results(self.request, self.response, self.chroot) self._path_checks(self.response.artifact.path, self.dest_dir, contents=self.file1_contents) self._path_checks(self.response.nested_artifact.path.path, self.dest_dir, contents=self.file2_contents) self.assertEqual(1, len(self.response.artifacts)) for artifact in self.response.artifacts: self._path_checks(artifact.path, self.dest_dir, contents=self.file3_contents)
def _ReexecuteInside(self, input_msg, output_msg, output_path, service_name, method_name, config): """Re-execute the service inside the chroot. Args: input_msg (Message): The parsed input message. output_msg (Message): The empty output message instance. output_path (str): The path for the serialized output. service_name (str): The name of the service to run. method_name (str): The name of the method to run. config (api_config.ApiConfig): The optional call configs. """ # Parse the chroot and clear the chroot field in the input message. chroot = field_handler.handle_chroot(input_msg) with field_handler.copy_paths_in(input_msg, chroot.tmp, prefix=chroot.path): with chroot.tempdir() as tempdir: new_input = os.path.join(tempdir, self.REEXEC_INPUT_FILE) chroot_input = '/%s' % os.path.relpath(new_input, chroot.path) new_output = os.path.join(tempdir, self.REEXEC_OUTPUT_FILE) chroot_output = '/%s' % os.path.relpath(new_output, chroot.path) logging.info('Writing input message to: %s', new_input) osutils.WriteFile(new_input, json_format.MessageToJson(input_msg)) osutils.Touch(new_output) cmd = ['build_api', '%s/%s' % (service_name, method_name), '--input-json', chroot_input, '--output-json', chroot_output] if config.validate_only: cmd.append('--validate-only') try: result = cros_build_lib.run( cmd, enter_chroot=True, chroot_args=chroot.get_enter_args(), error_code_ok=True, extra_env=chroot.env) except cros_build_lib.RunCommandError: # A non-zero return code will not result in an error, but one is still # thrown when the command cannot be run in the first place. This is # known to happen at least when the PATH does not include the chromite # bin dir. raise CrosSdkNotRunError('Unable to enter the chroot.') logging.info('Endpoint execution completed, return code: %d', result.returncode) # Transfer result files out of the chroot. output_content = osutils.ReadFile(new_output) if output_content: json_format.Parse(output_content, output_msg) field_handler.extract_results(input_msg, output_msg, chroot) osutils.WriteFile(output_path, json_format.MessageToJson(output_msg)) return result.returncode
def test_single_file(self): """Test a single file.""" self.response.artifact.path = self.source_file1_inside self.response.artifact.location = common_pb2.Path.INSIDE field_handler.extract_results(self.request, self.response, self.chroot) self._path_checks(self.response.artifact.path, self.dest_dir, contents=self.file1_contents)
def test_single_directory(self): """Test a single directory.""" self.response.artifact.path = self.source_dir self.response.artifact.location = common_pb2.Path.INSIDE field_handler.extract_results(self.request, self.response, self.chroot) self._path_checks(self.response.artifact.path, self.dest_dir) self.assertCountEqual(os.listdir(self.chroot_source), os.listdir(self.response.artifact.path))
def test_multiple_directories(self): """Test multiple directories.""" self.response.artifact.path = self.source_dir self.response.artifact.location = common_pb2.Path.INSIDE self.response.nested_artifact.path.path = self.source_dir2 self.response.nested_artifact.path.location = common_pb2.Path.INSIDE field_handler.extract_results(self.request, self.response, self.chroot) self._path_checks(self.response.artifact.path, self.dest_dir) self._path_checks(self.response.nested_artifact.path.path, self.dest_dir) expected = os.listdir(self.chroot_source) expected.extend(os.listdir(self.chroot_source2)) self.assertCountEqual(expected, os.listdir(self.response.artifact.path))
def _ReexecuteInside(self, input_msg, output_msg, config, input_handler, output_handlers, config_handler, service_name, method_name): """Re-execute the service inside the chroot. Args: input_msg (Message): The parsed input message. output_msg (Message): The empty output message instance. config (api_config.ApiConfig): The call configs. input_handler (MessageHandler): Input message handler. output_handlers (list[MessageHandler]): Output message handlers. config_handler (MessageHandler): Config message handler. service_name (str): The name of the service to run. method_name (str): The name of the method to run. """ # Parse the chroot and clear the chroot field in the input message. chroot = field_handler.handle_chroot(input_msg) if not chroot.exists(): raise InvalidSdkError('Chroot does not exist.') # Use a ContextManagerStack to avoid the deep nesting this many # context managers introduces. with cros_build_lib.ContextManagerStack() as stack: # TempDirs setup. tempdir = stack.Add(chroot.tempdir).tempdir sync_tempdir = stack.Add(chroot.tempdir).tempdir # The copy-paths-in context manager to handle Path messages. stack.Add( field_handler.copy_paths_in, input_msg, chroot.tmp, prefix=chroot.path) # The sync-directories context manager to handle SyncedDir messages. stack.Add( field_handler.sync_dirs, input_msg, sync_tempdir, prefix=chroot.path) # Parse goma. chroot.goma = field_handler.handle_goma(input_msg, chroot.path) # Build inside-chroot paths for the input, output, and config messages. new_input = os.path.join(tempdir, self.REEXEC_INPUT_FILE) chroot_input = '/%s' % os.path.relpath(new_input, chroot.path) new_output = os.path.join(tempdir, self.REEXEC_OUTPUT_FILE) chroot_output = '/%s' % os.path.relpath(new_output, chroot.path) new_config = os.path.join(tempdir, self.REEXEC_CONFIG_FILE) chroot_config = '/%s' % os.path.relpath(new_config, chroot.path) # Setup the inside-chroot message files. logging.info('Writing input message to: %s', new_input) input_handler.write_from(input_msg, path=new_input) osutils.Touch(new_output) logging.info('Writing config message to: %s', new_config) config_handler.write_from(config.get_proto(), path=new_config) # We can use a single output to write the rest of them. Use the # first one as the reexec output and just translate its output in # the rest of the handlers after. output_handler = output_handlers[0] cmd = [ 'build_api', '%s/%s' % (service_name, method_name), input_handler.input_arg, chroot_input, output_handler.output_arg, chroot_output, config_handler.config_arg, chroot_config, '--debug', ] try: result = cros_build_lib.run( cmd, enter_chroot=True, chroot_args=chroot.get_enter_args(), check=False, extra_env=chroot.env) except cros_build_lib.RunCommandError: # A non-zero return code will not result in an error, but one # is still thrown when the command cannot be run in the first # place. This is known to happen at least when the PATH does # not include the chromite bin dir. raise CrosSdkNotRunError('Unable to enter the chroot.') logging.info('Endpoint execution completed, return code: %d', result.returncode) # Transfer result files out of the chroot. output_handler.read_into(output_msg, path=new_output) field_handler.extract_results(input_msg, output_msg, chroot) # Write out all of the response formats. for handler in output_handlers: handler.write_from(output_msg) return result.returncode