Skip to content

Commit 3b1a915

Browse files
feat: add transport option to generation_config.yaml (#3052)
This PR adds a new optional entry "`transport`" to `generation_config.yaml`. The `transport` entry will only have effect in the postprocessing output (i.e. generated libraries will still have its transport inferred via BUILD.bazel). The main output file affected by this is `.repo-metadata.json` and its derived files (e.g. README.md). This addresses the [need to allow a custom transport for java-storage](googleapis/java-storage#2619 (comment)).
1 parent 6a2a17d commit 3b1a915

7 files changed

+119
-26
lines changed

library_generation/README.md

+25-23
Original file line numberDiff line numberDiff line change
@@ -105,29 +105,31 @@ The library level parameters define how to generate a (multi-versions) GAPIC
105105
library.
106106
They are shared by all GAPICs of a library.
107107

108-
| Name | Required | Notes |
109-
|:----------------------|:--------:|:-----------------------------------------------------------------------------------|
110-
| api_shortname | Yes | |
111-
| api_description | Yes | |
112-
| name_pretty | Yes | |
113-
| product_docs | Yes | |
114-
| library_type | No | `GAPIC_AUTO` if not specified |
115-
| release_level | No | `preview` if not specified |
116-
| api_id | No | `{api_shortname}.googleapis.com` if not specified |
117-
| api_reference | No | |
118-
| codeowner_team | No | |
119-
| client_documentation | No | |
120-
| distribution_name | No | `{group_id}:google-{cloud_prefix}{library_name}` if not specified |
121-
| excluded_poms | No | |
122-
| excluded_dependencies | No | |
123-
| googleapis_commitish | No | use repository level `googleapis_commitish` if not specified. |
124-
| group_id | No | `com.google.cloud` if not specified |
125-
| issue_tracker | No | |
126-
| library_name | No | `api_shortname` is not specified. This value should be unique among all libraries. |
127-
| rest_documentation | No | |
128-
| rpc_documentation | No | |
129-
| cloud_api | No | `true` if not specified |
130-
| requires-billing | No | `true` if not specified |
108+
| Name | Required | Notes |
109+
|:----------------------|:--------:|:------------------------------------------------------------------------------------------------------------------------------------------|
110+
| api_shortname | Yes | |
111+
| api_description | Yes | |
112+
| name_pretty | Yes | |
113+
| product_docs | Yes | |
114+
| library_type | No | `GAPIC_AUTO` if not specified |
115+
| release_level | No | `preview` if not specified |
116+
| api_id | No | `{api_shortname}.googleapis.com` if not specified |
117+
| api_reference | No | |
118+
| codeowner_team | No | |
119+
| client_documentation | No | |
120+
| distribution_name | No | `{group_id}:google-{cloud_prefix}{library_name}` if not specified |
121+
| excluded_poms | No | |
122+
| excluded_dependencies | No | |
123+
| googleapis_commitish | No | use repository level `googleapis_commitish` if not specified. |
124+
| group_id | No | `com.google.cloud` if not specified |
125+
| issue_tracker | No | |
126+
| library_name | No | `api_shortname` is not specified. This value should be unique among all libraries. |
127+
| rest_documentation | No | |
128+
| rpc_documentation | No | |
129+
| cloud_api | No | `true` if not specified |
130+
| requires-billing | No | `true` if not specified |
131+
| transport | No | must be one of `grpc`, `rest` or `both`. This value would only be used for generating .repo-metadata.json and relevant sections in README |
132+
131133

132134
Note that `cloud_prefix` is `cloud-` if `cloud_api` is `true`; empty otherwise.
133135

library_generation/generate_composed_library.py

+5-2
Original file line numberDiff line numberDiff line change
@@ -72,13 +72,16 @@ def generate_composed_library(
7272
gapic_inputs = parse_build_file(build_file_folder, gapic.proto_path)
7373
# generate postprocessing prerequisite files (.repo-metadata.json, .OwlBot-hermetic.yaml,
7474
# owlbot.py) here because transport is parsed from BUILD.bazel,
75-
# which lives in a versioned proto_path.
75+
# which lives in a versioned proto_path. The value of transport will be
76+
# overriden by the config object if specified. Note that this override
77+
# does not affect library generation but instead used only for
78+
# generating postprocessing files such as README.
7679
util.generate_postprocessing_prerequisite_files(
7780
config=config,
7881
library=library,
7982
proto_path=util.remove_version_from(gapic.proto_path),
80-
transport=gapic_inputs.transport,
8183
library_path=library_path,
84+
transport=library.get_transport(gapic_inputs),
8285
)
8386
temp_destination_path = f"java-{gapic.proto_path.replace('/','-')}"
8487
effective_arguments = __construct_effective_arg(

library_generation/model/generation_config.py

+1
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@ def from_yaml(path_to_yaml: str) -> GenerationConfig:
143143
),
144144
recommended_package=__optional(library, "recommended_package", None),
145145
min_java_version=__optional(library, "min_java_version", None),
146+
transport=__optional(library, "transport", None),
146147
)
147148
parsed_libraries.append(new_library)
148149

library_generation/model/library_config.py

+21
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
from hashlib import sha256
1616
from typing import Optional
1717
from library_generation.model.gapic_config import GapicConfig
18+
from library_generation.model.gapic_inputs import GapicInputs
1819

1920

2021
MAVEN_COORDINATE_SEPARATOR = ":"
@@ -52,6 +53,7 @@ def __init__(
5253
extra_versioned_modules: Optional[str] = None,
5354
recommended_package: Optional[str] = None,
5455
min_java_version: Optional[int] = None,
56+
transport: Optional[str] = None,
5557
):
5658
self.api_shortname = api_shortname
5759
self.api_description = api_description
@@ -78,6 +80,7 @@ def __init__(
7880
self.recommended_package = recommended_package
7981
self.min_java_version = min_java_version
8082
self.distribution_name = self.__get_distribution_name(distribution_name)
83+
self.transport = self.__validate_transport(transport)
8184

8285
def get_library_name(self) -> str:
8386
"""
@@ -101,6 +104,15 @@ def get_artifact_id(self) -> str:
101104
"""
102105
return self.get_maven_coordinate().split(MAVEN_COORDINATE_SEPARATOR)[-1]
103106

107+
def get_transport(self, gapic_inputs: GapicInputs) -> str:
108+
"""
109+
Returns the transport of the library. If directly set in library config, return it.
110+
Otherwise, return the transport inferred from gapic_inputs. This value is only
111+
used for postprocessing - the generation still infers the transport from BUILD
112+
files.
113+
"""
114+
return self.transport if self.transport is not None else gapic_inputs.transport
115+
104116
def __get_distribution_name(self, distribution_name: Optional[str]) -> str:
105117
LibraryConfig.__check_distribution_name(distribution_name)
106118
if distribution_name:
@@ -109,6 +121,13 @@ def __get_distribution_name(self, distribution_name: Optional[str]) -> str:
109121
library_name = self.get_library_name()
110122
return f"{self.group_id}:google-{cloud_prefix}{library_name}"
111123

124+
def __validate_transport(self, transport: str):
125+
if transport not in [None, "grpc", "rest", "both"]:
126+
raise ValueError(
127+
"allowed values for library.transport: grpc, rest, both and None"
128+
)
129+
return transport
130+
112131
@staticmethod
113132
def __check_distribution_name(distribution_name: str) -> None:
114133
if not distribution_name:
@@ -144,6 +163,7 @@ def __eq__(self, other):
144163
and self.extra_versioned_modules == other.extra_versioned_modules
145164
and self.recommended_package == other.recommended_package
146165
and self.min_java_version == other.min_java_version
166+
and self.transport == other.transport
147167
)
148168

149169
def __hash__(self):
@@ -175,6 +195,7 @@ def __hash__(self):
175195
self.extra_versioned_modules,
176196
self.recommended_package,
177197
self.min_java_version,
198+
self.transport,
178199
]
179200
+ [config.proto_path for config in self.gapic_configs]
180201
).encode("utf-8")

library_generation/model/repo_config.py

+6
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,12 @@ def get_library_version(self, artifact_id: str) -> str:
5757
return self.library_versions.get(artifact_id, NEW_CLIENT_VERSION)
5858

5959
def __parse_versions(self) -> dict[str, str]:
60+
"""
61+
For a given versions.txt file (defined in self.versions_file)
62+
creates a map of artifact-id to its version
63+
64+
:return: a map "artifact-id -> version"
65+
"""
6066
library_versions = dict()
6167
with open(self.versions_file) as f:
6268
for line in f.readlines():
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
{
2+
"api_shortname": "secretmanager",
3+
"name_pretty": "Secret Management",
4+
"product_documentation": "https://cloud.google.com/solutions/secrets-management/",
5+
"api_description": "allows you to encrypt, store, manage, and audit infrastructure and application-level secrets.",
6+
"client_documentation": "https://cloud.google.com/java/docs/reference/google-cloud-secretmanager/latest/overview",
7+
"release_level": "preview",
8+
"transport": "http",
9+
"language": "java",
10+
"repo": "googleapis/google-cloud-java",
11+
"repo_short": "java-secretmanager",
12+
"distribution_name": "com.google.cloud:google-cloud-secretmanager",
13+
"api_id": "secretmanager.googleapis.com",
14+
"library_type": "GAPIC_AUTO",
15+
"requires_billing": true
16+
}

library_generation/test/utilities_unit_tests.py

+45-1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
from pathlib import Path
2424
from library_generation.utils import utilities as util
2525
from library_generation.model.gapic_config import GapicConfig
26+
from library_generation.model.gapic_inputs import GapicInputs
2627
from library_generation.model.generation_config import GenerationConfig
2728
from library_generation.model.library_config import LibraryConfig
2829
from library_generation.test.test_utils import FileComparator
@@ -57,6 +58,14 @@
5758
api_description="example description",
5859
gapic_configs=list(),
5960
)
61+
test_library_with_custom_transport = LibraryConfig(
62+
api_shortname="secretmanager",
63+
name_pretty="Secret Management",
64+
product_documentation="https://cloud.google.com/solutions/secrets-management/",
65+
api_description="allows you to encrypt, store, manage, and audit infrastructure and application-level secrets.",
66+
gapic_configs=list(),
67+
transport="rest",
68+
)
6069

6170

6271
class UtilitiesTest(unittest.TestCase):
@@ -225,6 +234,40 @@ def test_generate_postprocessing_prerequisite_files_proto_only_repo_success(self
225234
)
226235
self.__remove_postprocessing_prerequisite_files(path=library_path)
227236

237+
def test_generate_postprocessing_prerequisite_files__custom_transport_set_in_config__success(
238+
self,
239+
):
240+
"""
241+
This test generates files for `test_library_with_custom_transport`, which
242+
has an explicit value for transport declared (http). This is expected to
243+
override the value obtained in BUILD.bazel via gapic_inputs.parse(). For
244+
testing purposes, we test with a default GapicInputs object, whose transport
245+
is set to "grpc".
246+
"""
247+
library_path = self.__setup_postprocessing_prerequisite_files(
248+
combination=2, library=test_library_with_custom_transport
249+
)
250+
251+
file_comparator.compare_files(
252+
f"{library_path}/.repo-metadata.json",
253+
f"{library_path}/.repo-metadata-custom-transport-golden.json",
254+
)
255+
self.__remove_postprocessing_prerequisite_files(path=library_path)
256+
257+
def test_create__library_invalid_transport__fails(
258+
self,
259+
):
260+
261+
with self.assertRaises(ValueError):
262+
test_library_with_invalid_transport = LibraryConfig(
263+
api_shortname="secretmanager",
264+
name_pretty="Secret Management",
265+
product_documentation="https://cloud.google.com/solutions/secrets-management/",
266+
api_description="allows you to encrypt, store, manage, and audit infrastructure and application-level secrets.",
267+
gapic_configs=list(),
268+
transport="http",
269+
)
270+
228271
def test_prepare_repo_monorepo_success(self):
229272
gen_config = self.__get_a_gen_config(2)
230273
repo_config = util.prepare_repo(
@@ -276,7 +319,8 @@ def __setup_postprocessing_prerequisite_files(
276319
library.library_type = library_type
277320
config = self.__get_a_gen_config(combination, library_type=library_type)
278321
proto_path = "google/cloud/baremetalsolution/v2"
279-
transport = "grpc"
322+
gapic_inputs = GapicInputs() # defaults to transport=grpc
323+
transport = library.get_transport(gapic_inputs)
280324
util.generate_postprocessing_prerequisite_files(
281325
config=config,
282326
library=library,

0 commit comments

Comments
 (0)