Coverage for /builds/BuildGrid/buildgrid/buildgrid/server/operations/instance.py: 98.00%

50 statements  

« prev     ^ index     » next       coverage.py v7.4.1, created at 2025-02-11 15:07 +0000

1# Copyright (C) 2018 Bloomberg LP 

2# 

3# Licensed under the Apache License, Version 2.0 (the "License"); 

4# you may not use this file except in compliance with the License. 

5# You may obtain a copy of the License at 

6# 

7# <http://www.apache.org/licenses/LICENSE-2.0> 

8# 

9# Unless required by applicable law or agreed to in writing, software 

10# distributed under the License is distributed on an "AS IS" BASIS, 

11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 

12# See the License for the specific language governing permissions and 

13# limitations under the License. 

14 

15 

16""" 

17OperationsInstance 

18================== 

19An instance of the LongRunningOperations Service. 

20""" 

21 

22from buildgrid._protos.build.bazel.remote.execution.v2.remote_execution_pb2 import RequestMetadata 

23from buildgrid._protos.buildgrid.v2.identity_pb2 import ClientIdentity 

24from buildgrid._protos.google.longrunning.operations_pb2 import DESCRIPTOR as OPS_DESCRIPTOR 

25from buildgrid._protos.google.longrunning.operations_pb2 import ListOperationsResponse, Operation 

26from buildgrid.server.exceptions import InvalidArgumentError, NotFoundError 

27from buildgrid.server.logging import buildgrid_logger 

28from buildgrid.server.operations.filtering import DEFAULT_OPERATION_FILTERS, FilterParser 

29from buildgrid.server.scheduler import Scheduler 

30from buildgrid.server.servicer import Instance 

31from buildgrid.server.settings import DEFAULT_MAX_LIST_OPERATION_PAGE_SIZE 

32 

33LOGGER = buildgrid_logger(__name__) 

34 

35 

36class OperationsInstance(Instance): 

37 SERVICE_NAME = OPS_DESCRIPTOR.services_by_name["Operations"].full_name 

38 

39 def __init__( 

40 self, scheduler: Scheduler, max_list_operations_page_size: int = DEFAULT_MAX_LIST_OPERATION_PAGE_SIZE 

41 ) -> None: 

42 self.scheduler = scheduler 

43 self._max_list_operations_page_size = max_list_operations_page_size 

44 

45 # --- Public API --- 

46 

47 def start(self) -> None: 

48 self.scheduler.start() 

49 

50 def stop(self) -> None: 

51 self.scheduler.stop() 

52 LOGGER.info("Stopped Operations.") 

53 

54 def get_operation(self, operation_name: str) -> tuple[Operation, RequestMetadata | None, ClientIdentity | None]: 

55 try: 

56 operation = self.scheduler.load_operation(operation_name) 

57 

58 except NotFoundError: 

59 raise InvalidArgumentError(f"Operation name does not exist: [{operation_name}]") 

60 

61 metadata = self.scheduler.get_operation_request_metadata_by_name(operation_name) 

62 client_identity = self.scheduler.get_client_identity_by_operation(operation_name) 

63 return operation, metadata, client_identity 

64 

65 def list_operations( 

66 self, filter_string: str, page_size: int | None, page_token: str | None 

67 ) -> ListOperationsResponse: 

68 if page_size and page_size > self._max_list_operations_page_size: 

69 raise InvalidArgumentError(f"The maximum page size is {self._max_list_operations_page_size}.") 

70 if not page_size: 

71 page_size = self._max_list_operations_page_size 

72 

73 operation_filters = FilterParser.parse_listoperations_filters(filter_string) 

74 if not operation_filters: 

75 operation_filters = DEFAULT_OPERATION_FILTERS 

76 

77 response = ListOperationsResponse() 

78 

79 results, next_token = self.scheduler.list_operations(operation_filters, page_size, page_token) 

80 response.operations.extend(results) 

81 response.next_page_token = next_token 

82 

83 return response 

84 

85 def delete_operation(self, job_name: str) -> None: 

86 """DeleteOperation is not supported in BuildGrid.""" 

87 pass 

88 

89 def cancel_operation(self, operation_name: str) -> None: 

90 try: 

91 self.scheduler.cancel_operation(operation_name) 

92 

93 except NotFoundError: 

94 raise InvalidArgumentError(f"Operation name does not exist: [{operation_name}]")