blob: 23c0040438055dc50b5dac6c5fd38e22f478dd0b [file] [log] [blame]
Alex Klein69339cc2019-07-22 14:08:35 -06001# Copyright 2019 The Chromium OS Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
Alex Klein2008aee2019-08-20 16:25:27 -06005"""API config object and related helper functionality."""
Alex Klein69339cc2019-07-22 14:08:35 -06006
Alex Kleind815ca62020-01-10 12:21:30 -07007from chromite.api.gen.chromite.api import build_api_config_pb2
8
9
10class Error(Exception):
11 """Base error class for the module."""
12
13
14class UnknownCallTypeEnumValue(Error):
15 """Thrown when the call type enum value in proto is not configured here."""
16
Alex Klein69339cc2019-07-22 14:08:35 -060017
Alex Klein2008aee2019-08-20 16:25:27 -060018class ApiConfig(object):
19 """API Config class."""
Alex Kleind815ca62020-01-10 12:21:30 -070020 # Call type constants.
21 CALL_TYPE_EXECUTE = 1
22 CALL_TYPE_VALIDATE_ONLY = 2
23 CALL_TYPE_MOCK_SUCCESS = 3
24 CALL_TYPE_MOCK_FAILURE = 4
25 CALL_TYPE_MOCK_INVALID = 5
Alex Klein69339cc2019-07-22 14:08:35 -060026
Alex Kleind815ca62020-01-10 12:21:30 -070027 # Maps the proto enum to the type constants.
28 TYPE_ENUM_MAP = {
29 build_api_config_pb2.CALL_TYPE_NONE: CALL_TYPE_EXECUTE,
30 build_api_config_pb2.CALL_TYPE_EXECUTE: CALL_TYPE_EXECUTE,
31 build_api_config_pb2.CALL_TYPE_VALIDATE_ONLY: CALL_TYPE_VALIDATE_ONLY,
32 build_api_config_pb2.CALL_TYPE_MOCK_SUCCESS: CALL_TYPE_MOCK_SUCCESS,
33 build_api_config_pb2.CALL_TYPE_MOCK_FAILURE: CALL_TYPE_MOCK_FAILURE,
34 build_api_config_pb2.CALL_TYPE_MOCK_INVALID: CALL_TYPE_MOCK_INVALID,
35 }
36
37 # Maps the type constants to the proto enums.
38 ENUM_TYPE_MAP = {
39 CALL_TYPE_EXECUTE: build_api_config_pb2.CALL_TYPE_EXECUTE,
40 CALL_TYPE_VALIDATE_ONLY: build_api_config_pb2.CALL_TYPE_VALIDATE_ONLY,
41 CALL_TYPE_MOCK_SUCCESS: build_api_config_pb2.CALL_TYPE_MOCK_SUCCESS,
42 CALL_TYPE_MOCK_FAILURE: build_api_config_pb2.CALL_TYPE_MOCK_FAILURE,
43 CALL_TYPE_MOCK_INVALID: build_api_config_pb2.CALL_TYPE_MOCK_INVALID,
44 }
45
46 # The valid call types.
47 _VALID_CALL_TYPES = tuple(ENUM_TYPE_MAP.keys())
48
49 def __init__(self, call_type=CALL_TYPE_EXECUTE, log_path=None):
50 assert call_type in self._VALID_CALL_TYPES
51 self._call_type = call_type
52 # Explicit `or None` to simplify proto default empty string.
53 self.log_path = log_path or None
Alex Klein2008aee2019-08-20 16:25:27 -060054
55 def __eq__(self, other):
56 if self.__class__ is other.__class__:
Alex Kleind815ca62020-01-10 12:21:30 -070057 return self.__dict__ == other.__dict__
Alex Klein2008aee2019-08-20 16:25:27 -060058
59 return NotImplemented
60
61 __hash__ = NotImplemented
62
63 @property
64 def do_validation(self):
Alex Kleind815ca62020-01-10 12:21:30 -070065 # We skip validation for all mock calls, so do validation when it's
66 # anything but a mocked call.
67 return not (self.mock_call or self.mock_error or self.mock_invalid)
68
69 @property
70 def validate_only(self):
71 return self._call_type == self.CALL_TYPE_VALIDATE_ONLY
72
73 @property
74 def mock_call(self):
75 return self._call_type == self.CALL_TYPE_MOCK_SUCCESS
76
77 @property
78 def mock_error(self):
79 return self._call_type == self.CALL_TYPE_MOCK_FAILURE
80
81 @property
82 def mock_invalid(self):
83 return self._call_type == self.CALL_TYPE_MOCK_INVALID
84
Alex Kleind1e9e5c2020-12-14 12:32:32 -070085 @property
86 def run_endpoint(self) -> bool:
87 """Run the endpoint when none of the special calls are invoked."""
88 return (not self.validate_only and not self.mock_call and
89 not self.mock_error and not self.mock_invalid)
90
Alex Kleind815ca62020-01-10 12:21:30 -070091 def get_proto(self, for_inside_execution=True):
92 """Get the config as a proto.
93
94 Args:
95 for_inside_execution (bool): Allows avoiding propagating configs that are
96 irrelevant for the build api process executed inside the chroot.
97 Enabled by default.
98
99 Returns:
100 build_api_config_pb2.BuildApiConfig
101 """
102 config = build_api_config_pb2.BuildApiConfig()
103 config.call_type = self.ENUM_TYPE_MAP[self._call_type]
104
105 if not for_inside_execution:
106 # Add values not needed when reexecuting.
107 config.log_path = self.log_path
108
109 return config
110
111
112def build_config_from_proto(config_proto):
113 """Build an ApiConfig instance from a BuildApiConfig message.
114
115 Args:
116 config_proto (build_api_config_pb2.BuildApiConfig): The proto config.
117
118 Returns:
119 ApiConfig
120 """
121 assert isinstance(config_proto, build_api_config_pb2.BuildApiConfig)
122
123 if config_proto.call_type not in ApiConfig.TYPE_ENUM_MAP:
124 raise UnknownCallTypeEnumValue('The given protobuf call_type value is not '
125 'configured in api_config.')
126 return ApiConfig(call_type=ApiConfig.TYPE_ENUM_MAP[config_proto.call_type],
127 log_path=config_proto.log_path)
Alex Klein69339cc2019-07-22 14:08:35 -0600128
129
130class ApiConfigMixin(object):
131 """Mixin to add an API Config factory properties.
132
133 This is meant to be used for tests to make these configs more uniform across
Alex Kleine191ed62020-02-27 15:59:55 -0700134 all the tests since there's very little to change anyway.
Alex Klein69339cc2019-07-22 14:08:35 -0600135 """
136
137 @property
138 def api_config(self):
Alex Klein2008aee2019-08-20 16:25:27 -0600139 return ApiConfig()
Alex Klein69339cc2019-07-22 14:08:35 -0600140
141 @property
142 def validate_only_config(self):
Alex Kleind815ca62020-01-10 12:21:30 -0700143 return ApiConfig(call_type=ApiConfig.CALL_TYPE_VALIDATE_ONLY)
Alex Klein2008aee2019-08-20 16:25:27 -0600144
145 @property
146 def no_validate_config(self):
147 return self.mock_call_config
148
149 @property
150 def mock_call_config(self):
Alex Kleind815ca62020-01-10 12:21:30 -0700151 return ApiConfig(call_type=ApiConfig.CALL_TYPE_MOCK_SUCCESS)
Alex Klein2008aee2019-08-20 16:25:27 -0600152
153 @property
154 def mock_error_config(self):
Alex Kleind815ca62020-01-10 12:21:30 -0700155 return ApiConfig(call_type=ApiConfig.CALL_TYPE_MOCK_FAILURE)