blob: 65a4bb027c06ab52daba3f0a4d7f1cdd3d712b82 [file] [log] [blame]
Alex Klein69339cc2019-07-22 14:08:35 -06001# -*- coding: utf-8 -*-
2# Copyright 2019 The Chromium OS Authors. All rights reserved.
3# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5
Alex Klein2008aee2019-08-20 16:25:27 -06006"""API config object and related helper functionality."""
Alex Klein69339cc2019-07-22 14:08:35 -06007
8from __future__ import print_function
9
Alex Kleind815ca62020-01-10 12:21:30 -070010from chromite.api.gen.chromite.api import build_api_config_pb2
11
12
13class Error(Exception):
14 """Base error class for the module."""
15
16
17class UnknownCallTypeEnumValue(Error):
18 """Thrown when the call type enum value in proto is not configured here."""
19
Alex Klein69339cc2019-07-22 14:08:35 -060020
Alex Klein2008aee2019-08-20 16:25:27 -060021class ApiConfig(object):
22 """API Config class."""
Alex Kleind815ca62020-01-10 12:21:30 -070023 # Call type constants.
24 CALL_TYPE_EXECUTE = 1
25 CALL_TYPE_VALIDATE_ONLY = 2
26 CALL_TYPE_MOCK_SUCCESS = 3
27 CALL_TYPE_MOCK_FAILURE = 4
28 CALL_TYPE_MOCK_INVALID = 5
Alex Klein69339cc2019-07-22 14:08:35 -060029
Alex Kleind815ca62020-01-10 12:21:30 -070030 # Maps the proto enum to the type constants.
31 TYPE_ENUM_MAP = {
32 build_api_config_pb2.CALL_TYPE_NONE: CALL_TYPE_EXECUTE,
33 build_api_config_pb2.CALL_TYPE_EXECUTE: CALL_TYPE_EXECUTE,
34 build_api_config_pb2.CALL_TYPE_VALIDATE_ONLY: CALL_TYPE_VALIDATE_ONLY,
35 build_api_config_pb2.CALL_TYPE_MOCK_SUCCESS: CALL_TYPE_MOCK_SUCCESS,
36 build_api_config_pb2.CALL_TYPE_MOCK_FAILURE: CALL_TYPE_MOCK_FAILURE,
37 build_api_config_pb2.CALL_TYPE_MOCK_INVALID: CALL_TYPE_MOCK_INVALID,
38 }
39
40 # Maps the type constants to the proto enums.
41 ENUM_TYPE_MAP = {
42 CALL_TYPE_EXECUTE: build_api_config_pb2.CALL_TYPE_EXECUTE,
43 CALL_TYPE_VALIDATE_ONLY: build_api_config_pb2.CALL_TYPE_VALIDATE_ONLY,
44 CALL_TYPE_MOCK_SUCCESS: build_api_config_pb2.CALL_TYPE_MOCK_SUCCESS,
45 CALL_TYPE_MOCK_FAILURE: build_api_config_pb2.CALL_TYPE_MOCK_FAILURE,
46 CALL_TYPE_MOCK_INVALID: build_api_config_pb2.CALL_TYPE_MOCK_INVALID,
47 }
48
49 # The valid call types.
50 _VALID_CALL_TYPES = tuple(ENUM_TYPE_MAP.keys())
51
52 def __init__(self, call_type=CALL_TYPE_EXECUTE, log_path=None):
53 assert call_type in self._VALID_CALL_TYPES
54 self._call_type = call_type
55 # Explicit `or None` to simplify proto default empty string.
56 self.log_path = log_path or None
Alex Klein2008aee2019-08-20 16:25:27 -060057
58 def __eq__(self, other):
59 if self.__class__ is other.__class__:
Alex Kleind815ca62020-01-10 12:21:30 -070060 return self.__dict__ == other.__dict__
Alex Klein2008aee2019-08-20 16:25:27 -060061
62 return NotImplemented
63
64 __hash__ = NotImplemented
65
66 @property
67 def do_validation(self):
Alex Kleind815ca62020-01-10 12:21:30 -070068 # We skip validation for all mock calls, so do validation when it's
69 # anything but a mocked call.
70 return not (self.mock_call or self.mock_error or self.mock_invalid)
71
72 @property
73 def validate_only(self):
74 return self._call_type == self.CALL_TYPE_VALIDATE_ONLY
75
76 @property
77 def mock_call(self):
78 return self._call_type == self.CALL_TYPE_MOCK_SUCCESS
79
80 @property
81 def mock_error(self):
82 return self._call_type == self.CALL_TYPE_MOCK_FAILURE
83
84 @property
85 def mock_invalid(self):
86 return self._call_type == self.CALL_TYPE_MOCK_INVALID
87
88 def get_proto(self, for_inside_execution=True):
89 """Get the config as a proto.
90
91 Args:
92 for_inside_execution (bool): Allows avoiding propagating configs that are
93 irrelevant for the build api process executed inside the chroot.
94 Enabled by default.
95
96 Returns:
97 build_api_config_pb2.BuildApiConfig
98 """
99 config = build_api_config_pb2.BuildApiConfig()
100 config.call_type = self.ENUM_TYPE_MAP[self._call_type]
101
102 if not for_inside_execution:
103 # Add values not needed when reexecuting.
104 config.log_path = self.log_path
105
106 return config
107
108
109def build_config_from_proto(config_proto):
110 """Build an ApiConfig instance from a BuildApiConfig message.
111
112 Args:
113 config_proto (build_api_config_pb2.BuildApiConfig): The proto config.
114
115 Returns:
116 ApiConfig
117 """
118 assert isinstance(config_proto, build_api_config_pb2.BuildApiConfig)
119
120 if config_proto.call_type not in ApiConfig.TYPE_ENUM_MAP:
121 raise UnknownCallTypeEnumValue('The given protobuf call_type value is not '
122 'configured in api_config.')
123 return ApiConfig(call_type=ApiConfig.TYPE_ENUM_MAP[config_proto.call_type],
124 log_path=config_proto.log_path)
Alex Klein69339cc2019-07-22 14:08:35 -0600125
126
127class ApiConfigMixin(object):
128 """Mixin to add an API Config factory properties.
129
130 This is meant to be used for tests to make these configs more uniform across
131 all of the tests since there's very little to change anyway.
132 """
133
134 @property
135 def api_config(self):
Alex Klein2008aee2019-08-20 16:25:27 -0600136 return ApiConfig()
Alex Klein69339cc2019-07-22 14:08:35 -0600137
138 @property
139 def validate_only_config(self):
Alex Kleind815ca62020-01-10 12:21:30 -0700140 return ApiConfig(call_type=ApiConfig.CALL_TYPE_VALIDATE_ONLY)
Alex Klein2008aee2019-08-20 16:25:27 -0600141
142 @property
143 def no_validate_config(self):
144 return self.mock_call_config
145
146 @property
147 def mock_call_config(self):
Alex Kleind815ca62020-01-10 12:21:30 -0700148 return ApiConfig(call_type=ApiConfig.CALL_TYPE_MOCK_SUCCESS)
Alex Klein2008aee2019-08-20 16:25:27 -0600149
150 @property
151 def mock_error_config(self):
Alex Kleind815ca62020-01-10 12:21:30 -0700152 return ApiConfig(call_type=ApiConfig.CALL_TYPE_MOCK_FAILURE)