Coverage for /builds/BuildGrid/buildgrid/buildgrid/server/capabilities/instance.py: 100.00%

35 statements  

« prev     ^ index     » next       coverage.py v7.4.1, created at 2024-10-04 17:48 +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. 

14from typing import Optional, Union 

15 

16from buildgrid._protos.build.bazel.remote.execution.v2.remote_execution_pb2 import DESCRIPTOR as RE_DESCRIPTOR 

17from buildgrid._protos.build.bazel.remote.execution.v2.remote_execution_pb2 import ( 

18 ActionCacheUpdateCapabilities, 

19 CacheCapabilities, 

20 ExecutionCapabilities, 

21 ServerCapabilities, 

22 SymlinkAbsolutePathStrategy, 

23) 

24from buildgrid._protos.build.bazel.semver.semver_pb2 import SemVer 

25from buildgrid.server.actioncache.caches.action_cache_abc import ActionCacheABC 

26from buildgrid.server.actioncache.instance import ActionCache 

27from buildgrid.server.cas.instance import ContentAddressableStorageInstance 

28from buildgrid.server.execution.instance import ExecutionInstance 

29from buildgrid.server.servicer import Instance 

30from buildgrid.server.settings import HIGH_REAPI_VERSION, LOW_REAPI_VERSION, MAX_REQUEST_SIZE 

31from buildgrid.server.utils.digests import get_hash_type 

32 

33ActionCacheInstance = Union[ActionCache, ActionCacheABC] 

34 

35 

36class CapabilitiesInstance(Instance): 

37 SERVICE_NAME = RE_DESCRIPTOR.services_by_name["Capabilities"].full_name 

38 

39 def __init__( 

40 self, 

41 cas_instance: Optional["ContentAddressableStorageInstance"] = None, 

42 action_cache_instance: Optional["ActionCacheInstance"] = None, 

43 execution_instance: Optional["ExecutionInstance"] = None, 

44 ) -> None: 

45 self._cas_instance = cas_instance 

46 self._action_cache_instance = action_cache_instance 

47 self._execution_instance = execution_instance 

48 self._high_api_version = _split_semantic_version(HIGH_REAPI_VERSION) 

49 self._low_api_version = _split_semantic_version(LOW_REAPI_VERSION) 

50 

51 def add_cas_instance(self, cas_instance: "ContentAddressableStorageInstance") -> None: 

52 self._cas_instance = cas_instance 

53 

54 def add_action_cache_instance(self, action_cache_instance: "ActionCacheInstance") -> None: 

55 self._action_cache_instance = action_cache_instance 

56 

57 def add_execution_instance(self, execution_instance: "ExecutionInstance") -> None: 

58 self._execution_instance = execution_instance 

59 

60 def get_capabilities(self) -> ServerCapabilities: 

61 # The caching capabilities are VERY hardcoded by the buildgrid server components. 

62 # Simply forwarding abilities from remote storage or local components does more 

63 # harm than good, as the remote capabilities do not feed into usage by most components. 

64 # 

65 # The most sane way to override these values would be via server configuration, 

66 # not by dynamically fetching the capabilities remotely. 

67 # 

68 # If we want to properly support this functionality, a large refactor would be needed. 

69 return ServerCapabilities( 

70 cache_capabilities=CacheCapabilities( 

71 digest_functions=[get_hash_type()], 

72 max_batch_total_size_bytes=MAX_REQUEST_SIZE, 

73 symlink_absolute_path_strategy=SymlinkAbsolutePathStrategy.DISALLOWED, 

74 action_cache_update_capabilities=ActionCacheUpdateCapabilities( 

75 update_enabled=bool(self._action_cache_instance and self._action_cache_instance.allow_updates) 

76 ), 

77 ), 

78 execution_capabilities=ExecutionCapabilities( 

79 exec_enabled=self._execution_instance is not None, 

80 digest_function=get_hash_type(), 

81 digest_functions=[get_hash_type()], 

82 ), 

83 low_api_version=self._low_api_version, 

84 high_api_version=self._high_api_version, 

85 ) 

86 

87 

88def _split_semantic_version(version_string: str) -> SemVer: 

89 major_version, minor_version, patch_version = version_string.split(".") 

90 

91 semantic_version = SemVer() 

92 semantic_version.major = int(major_version) 

93 semantic_version.minor = int(minor_version) 

94 semantic_version.patch = int(patch_version) 

95 

96 return semantic_version