diff --git a/.github/workflows/showcaseTests.yaml b/.github/workflows/showcaseTests.yaml index c26760f4a9..bf8dc53f64 100644 --- a/.github/workflows/showcaseTests.yaml +++ b/.github/workflows/showcaseTests.yaml @@ -1,18 +1,17 @@ name: Generator - Showcase Tests on: -# Disable auto-triggering until this issue is fixed -# https://github.com/GoogleCloudPlatform/spring-cloud-gcp/issues/2214 -# push: -# branches: -# - main -# pull_request: -# paths: -# - 'spring-cloud-generator/**' + push: + branches: + - main + pull_request: + paths: + - 'spring-cloud-generator/**' workflow_dispatch: jobs: showcaseTests: + runs-on: ubuntu-20.04 steps: - uses: actions/checkout@v2 @@ -20,11 +19,6 @@ jobs: uses: actions/setup-java@v1 with: java-version: 17 - - name: Install buildozer - run: | - go install github.com/bazelbuild/buildtools/buildozer@latest - export PATH=$PATH:$(go env GOPATH)/bin - buildozer --version - name: Install spring-cloud-gcp # Installs spring-cloud-gcp from root, # including spring-cloud-generator module @@ -44,8 +38,6 @@ jobs: run: | set -x set -e - export PATH=$PATH:$(go env GOPATH)/bin - buildozer --version bash scripts/generate-showcase.sh - name: Unit tests for showcase-spring-starter # Runs showcase-spring-starter unit tests diff --git a/.gitignore b/.gitignore index 4fd66ddf59..277f56d94d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,37 +1,39 @@ -# Ignore folders -target/ -bin/ -/config -/.idea -/out - -# Do not ignore them -!.idea/copyright -!.idea/inspectionProfiles -!.idea/scopes -!.idea/codeStyleSettings.xml -!.idea/vcs.xml - -# Ignore files -access.properties -mail.properties -*.iml -*.ipr -*.iws -.project -.classpath -.settings/ -.sts4-cache/ - -# Ignore to avoid pushing maven wrapper jar as binary artifact -.mvn/wrapper/maven-wrapper.jar - -# Because re-configuring the directory in the share plugin leads to side effect we ignore the file -dependency-reduced-pom.xml -.factorypath - -# Ignore OSX autogenerated files -.DS_Store - -.flattened-pom.xml -*.versionsBackup +# Ignore folders +target/ +bin/ +/config +/.idea +/out + +# Do not ignore them +!.idea/copyright +!.idea/inspectionProfiles +!.idea/scopes +!.idea/codeStyleSettings.xml +!.idea/vcs.xml + +# Ignore files +access.properties +mail.properties +*.iml +*.ipr +*.iws +*.swp +*.swo +.project +.classpath +.settings/ +.sts4-cache/ + +# Ignore to avoid pushing maven wrapper jar as binary artifact +.mvn/wrapper/maven-wrapper.jar + +# Because re-configuring the directory in the share plugin leads to side effect we ignore the file +dependency-reduced-pom.xml +.factorypath + +# Ignore OSX autogenerated files +.DS_Store + +.flattened-pom.xml +*.versionsBackup diff --git a/spring-cloud-generator/pom.xml b/spring-cloud-generator/pom.xml index 211d5794de..d34e133fbe 100644 --- a/spring-cloud-generator/pom.xml +++ b/spring-cloud-generator/pom.xml @@ -110,7 +110,28 @@ + + maven-assembly-plugin + + + + com.google.cloud.generator.spring.Main + + + + jar-with-dependencies + + + + + make-assembly + package + + single + + + + - \ No newline at end of file diff --git a/spring-cloud-generator/scripts/generate-showcase-utilities.sh b/spring-cloud-generator/scripts/generate-showcase-utilities.sh new file mode 100644 index 0000000000..4102db6110 --- /dev/null +++ b/spring-cloud-generator/scripts/generate-showcase-utilities.sh @@ -0,0 +1,160 @@ +#!/usr/bin/env bash + +set -eo pipefail +utilities_script_dir=$(dirname "$(realpath "${BASH_SOURCE[0]}")") + +# gets the output folder where all sources and dependencies will be located. +get_output_folder() { + if [[ $(basename $(pwd)) != "output" ]]; then + echo "$(pwd)/output" + else + echo $(pwd) + fi +} + +get_protoc_version() { + local gapic_generator_version=$1 + local protoc_version + pushd "${output_folder}" > /dev/null + # get protobuf version from gapic-generator-java-pom-parent/pom.xml + download_gapic_generator_pom_parent "${gapic_generator_version}" + protoc_version=$(grep protobuf.version "gapic-generator-java-pom-parent-${gapic_generator_version}.pom" | sed 's/\(.*\)<\/protobuf\.version>/\1/' | sed 's/^[[:space:]]*//;s/[[:space:]]*$//' | cut -d "." -f2-) + popd > /dev/null + echo "${protoc_version}" +} + +detect_os_architecture() { + local os_type + local os_architecture + os_type=$(uname -sm) + case "${os_type}" in + *"Linux x86_64"*) + os_architecture="linux-x86_64" + ;; + *"Darwin x86_64"*) + os_architecture="osx-x86_64" + ;; + "MINGW64"*) + os_architecture="win64" + ;; + *) + os_architecture="osx-aarch_64" + ;; + esac + echo "${os_architecture}" +} + +download_protoc() { + local protoc_version=$1 + local os_architecture=$2 + if [ ! -d "protoc-${protoc_version}" ]; then + # pull proto files and protoc from protobuf repository as maven central + # doesn't have proto files + download_from \ + "https://github.com/protocolbuffers/protobuf/releases/download/v${protoc_version}/protoc-${protoc_version}-${os_architecture}.zip" \ + "protoc-${protoc_version}.zip" \ + "GitHub" + unzip -o -q "protoc-${protoc_version}.zip" -d "protoc-${protoc_version}" + cp -r "protoc-${protoc_version}/include/google" . + rm "protoc-${protoc_version}.zip" + fi + + protoc_path="${output_folder}/protoc-${protoc_version}/bin" +} + +# get gapic options from .yaml and .json files from proto_path. +get_gapic_opts() { + local transport=$1 + local rest_numeric_enums=$2 + local gapic_yaml=$3 + local service_config=$4 + local service_yaml=$5 + if [ "${rest_numeric_enums}" == "true" ]; then + rest_numeric_enums="rest-numeric-enums" + else + rest_numeric_enums="" + fi + # If any of the gapic options is empty (default value), try to search for + # it in proto_path. + if [[ "${gapic_yaml}" == "" ]]; then + gapic_yaml=$(find "${proto_path}" -type f -name "*gapic.yaml") + fi + + if [[ "${service_config}" == "" ]]; then + service_config=$(find "${proto_path}" -type f -name "*service_config.json") + fi + + if [[ "${service_yaml}" == "" ]]; then + service_yaml=$(find "${proto_path}" -maxdepth 1 -type f \( -name "*.yaml" ! -name "*gapic*.yaml" \)) + fi + echo "transport=${transport},${rest_numeric_enums},grpc-service-config=${service_config},gapic-config=${gapic_yaml},api-service-config=${service_yaml}" +} + +download_from() { + local url=$1 + local save_as=$2 + local repo=$3 + # fail-fast, 30 seconds at most, retry 2 times + curl -LJ -o "${save_as}" --fail -m 30 --retry 2 "$url" || download_fail "${save_as}" "${repo}" +} + +download_gapic_generator_pom_parent() { + local gapic_generator_version=$1 + download_generator_artifact "${gapic_generator_version}" "gapic-generator-java-pom-parent-${gapic_generator_version}.pom" "gapic-generator-java-pom-parent" +} + +download_generator_artifact() { + local gapic_generator_version=$1 + local artifact=$2 + local project=${3:-"gapic-generator-java"} + if [ ! -f "${artifact}" ]; then + # first, try to fetch the generator locally + local local_fetch_successful + local_fetch_successful=$(copy_from "$HOME/.m2/repository/com/google/api/${project}/${gapic_generator_version}/${artifact}" \ + "${artifact}") + if [[ "${local_fetch_successful}" == "false" ]];then + # download gapic-generator-java artifact from Google maven central mirror if not + # found locally + >&2 echo "${artifact} not found locally. Attempting a download from Maven Central" + download_from \ + "https://maven-central.storage-download.googleapis.com/maven2/com/google/api/${project}/${gapic_generator_version}/${artifact}" \ + "${artifact}" + >&2 echo "${artifact} found and downloaded from Maven Central" + else + >&2 echo "${artifact} found copied from local repository (~/.m2)" + fi + fi +} + +download_fail() { + local artifact=$1 + local repo=${2:-"maven central mirror"} + >&2 echo "Fail to download ${artifact} from ${repo} repository. Please install ${artifact} first if you want to use a non-published artifact." + exit 1 +} + +# copies the specified file in $1 to $2 +# will return "true" if the copy was successful +copy_from() { + local local_repo=$1 + local save_as=$2 + copy_successful=$(cp "${local_repo}" "${save_as}" && echo "true" || echo "false") + echo "${copy_successful}" +} + +# Convenience function to clone only the necessary folders from a git repository +sparse_clone() { + repo_url=$1 + paths=$2 + commitish=$3 + clone_dir=$(basename "${repo_url%.*}") + rm -rf "${clone_dir}" + git clone -n --depth=1 --no-single-branch --filter=tree:0 "${repo_url}" + pushd "${clone_dir}" + if [ -n "${commitish}" ]; then + git checkout "${commitish}" + fi + git sparse-checkout set --no-cone ${paths} + git checkout + popd +} diff --git a/spring-cloud-generator/scripts/generate-showcase.sh b/spring-cloud-generator/scripts/generate-showcase.sh index cc91c03b04..12d5fcb7ee 100644 --- a/spring-cloud-generator/scripts/generate-showcase.sh +++ b/spring-cloud-generator/scripts/generate-showcase.sh @@ -1,47 +1,45 @@ -#!/bin/bash -set -e +set -ex -# To VERIFY: ./scripts/generate-showcase.sh -# To UPDATE: /scripts/generate-showcase.sh -u -UPDATE=0 +# To verify: ./scripts/generate-showcase.sh +# To update: /scripts/generate-showcase.sh -u +update="false" while getopts u flag do case "${flag}" in - u) UPDATE=1;; + u) update="true";; esac done # For reusing bazel setup modifications and post-processing steps -source ./scripts/generate-steps.sh +script_dir=$(dirname "$(realpath "${BASH_SOURCE[0]}")") +source "${script_dir}/generate-showcase-utilities.sh" +source "${script_dir}/generate-steps.sh" -# If not set, assume working directory is spring-cloud-generator -if [[ -z "$SPRING_GENERATOR_DIR" ]]; then - SPRING_GENERATOR_DIR=`pwd` -fi -SPRING_ROOT_DIR=${SPRING_GENERATOR_DIR}/.. -SHOWCASE_STARTER_OLD_DIR=${SPRING_GENERATOR_DIR}/showcase/showcase-spring-starter -SHOWCASE_STARTER_NEW_DIR=${SPRING_GENERATOR_DIR}/showcase/showcase-spring-starter-generated +spring_generator_dir="${script_dir}/.." +spring_root_dir=${spring_generator_dir}/.. +showcase_starter_old_dir=${spring_generator_dir}/showcase/showcase-spring-starter +showcase_starter_new_dir=${spring_generator_dir}/showcase/showcase-spring-starter-generated # Verifies newly generated showcase-spring-starter against goldens # # $1 - directory containing existing showcase-spring-starter (golden) # $2 - directory containing newly generated showcase-spring-starter function verify(){ - OLD_DIR=$1 - NEW_DIR=$2 - SHOWCASE_STARTER_DIFF=$(diff -r ${NEW_DIR}/src/main ${OLD_DIR}/src/main) - SHOWCASE_STARTER_POM_DIFF=$(diff -r ${NEW_DIR}/pom.xml ${OLD_DIR}/pom.xml) - if [ "$SHOWCASE_STARTER_DIFF" != "" ] || [ "$SHOWCASE_STARTER_POM_DIFF" != "" ] + old_dir=$1 + new_dir=$2 + showcase_starter_diff=$(diff -r ${new_dir}/src/main ${old_dir}/src/main) + showcase_starter_pom_diff=$(diff -r ${new_dir}/pom.xml ${old_dir}/pom.xml) + if [ "${showcase_starter_diff}" != "" ] || [ "${showcase_starter_pom_diff}" != "" ] then echo "Differences detected in generated showcase starter module: " echo "Diff from src/main: " - echo $SHOWCASE_STARTER_DIFF + echo "${showcase_starter_diff}" echo "Diff from pom.xml: " - echo $SHOWCASE_STARTER_POM_DIFF + echo "${showcase_starter_pom_diff}" exit 1; else echo "No differences found in showcase-spring-starter" - rm -r ${NEW_DIR} + rm -r "${new_dir}" fi } @@ -49,63 +47,121 @@ function verify(){ # # $1 - target directory for generated starter function generate_showcase_spring_starter(){ - SHOWCASE_STARTER_DIR=$1 + showcase_starter_dir=$1 # Compute the parent project version. - cd ${SPRING_ROOT_DIR} - PROJECT_VERSION=$(mvn help:evaluate -Dexpression=project.version -q -DforceStdout) - cd ${SPRING_GENERATOR_DIR} - GAPIC_GENERATOR_JAVA_VERSION=$(mvn help:evaluate -Dexpression=gapic-generator-java-bom.version -q -DforceStdout) + pushd "${spring_root_dir}" + export project_version=$(mvn help:evaluate -Dexpression=project.version -q -DforceStdout) + cd "${spring_generator_dir}" + gapic_generator_java_version=$(mvn help:evaluate -Dexpression=gapic-generator-java-bom.version -q -DforceStdout) - if [[ -z "$GAPIC_GENERATOR_JAVA_VERSION" ]]; then + if [[ -z "${gapic_generator_java_version}" ]]; then echo "Missing sdk-platform-java commitish to checkout" exit 1 fi # Clone sdk-platform-java (with showcase library) - git clone https://github.com/googleapis/sdk-platform-java.git - cd sdk-platform-java && git checkout "v${GAPIC_GENERATOR_JAVA_VERSION}" + if [[ ! -d "./sdk-platform-java" ]]; then + git clone https://github.com/googleapis/sdk-platform-java.git + fi + pushd sdk-platform-java + git checkout "v${gapic_generator_java_version}" # Install showcase client libraries locally - cd showcase && mvn clean install - GAPIC_SHOWCASE_CLIENT_VERSION=$(mvn help:evaluate -Dexpression=project.version -q -DforceStdout) + pushd showcase + # For local development, we cleanup any traces of previous runs + rm -rdf "${output_folder}" + mvn clean install + gapic_showcase_client_version=$(mvn help:evaluate -Dexpression=project.version -q -DforceStdout) + + pushd gapic-showcase + gapic_showcase_server_version=$(mvn help:evaluate -Dexpression=gapic-showcase.version -q -DforceStdout) + popd #showcase/gapic-showcase + + output_folder=$(get_output_folder) + mkdir "${output_folder}" + pushd "${output_folder}" + protoc_version=$(get_protoc_version "${gapic_generator_java_version}") + os_architecture=$(detect_os_architecture) + download_protoc "${protoc_version}" "${os_architecture}" + + # We now copy the spring-cloud-generator jar with dependencies + # into the output_folder the sdk-platform-java generation + # scripts work with. + spring_generator_jar_name="spring-cloud-generator-${project_version}-jar-with-dependencies.jar" + cp ~/.m2/repository/com/google/cloud/spring-cloud-generator/"${project_version}/${spring_generator_jar_name}" \ + "${output_folder}" + chmod 555 ${output_folder}/*.jar + + # We download gapic-showcase and prepare the protos in output_folder + sparse_clone https://github.com/googleapis/gapic-showcase.git "schema/google/showcase/v1beta1" + pushd gapic-showcase + git checkout "v${gapic_showcase_server_version}" + cp -r schema "${output_folder}" + popd #gapic-showcase + + # We download googleapis and prepare the protos in output_folder + if [[ ! -d "./googleapis" ]]; then + sparse_clone https://github.com/googleapis/googleapis.git "google/iam/v1 google/cloud/location google/api google/longrunning google/rpc google/type" + fi + pushd googleapis + cp -r google "${output_folder}" + popd #googleapis + + # Now we call protoc with a series of arguments we obtain from + # sdk-platform-java's utilities.sh and others that are hardcoded (and stable). + # Note that --java_gapic_spring_opt uses `get_gapic_opts` which will work + # since the BUILD rules take similar arguments + + proto_path="schema/google/showcase/v1beta1" + proto_files=$(find "${proto_path}" -type f -name "*.proto" | LC_COLLATE=C sort) + gapic_additional_protos="google/iam/v1/iam_policy.proto google/cloud/location/locations.proto" + rest_numeric_enums="false" + transport="grpc+rest" + service_config="schema/google/showcase/v1beta1/showcase_grpc_service_config.json" + service_yaml="schema/google/showcase/v1beta1/showcase_v1beta1.yaml" + output_srcjar_zip_name="showcase_java_gapic_spring_raw.srcjar.zip" + + "${protoc_path}"/protoc \ + "--experimental_allow_proto3_optional" \ + "--plugin=protoc-gen-java_gapic_spring=${spring_generator_dir}/spring-cloud-generator-wrapper" \ + "--java_gapic_spring_out=${output_folder}/${output_srcjar_zip_name}" \ + "--java_gapic_spring_opt=$(get_gapic_opts "${transport}" "${rest_numeric_enums}" "" "${service_config}" "${service_yaml}")" \ + ${proto_files} ${gapic_additional_protos} # Do not quote because this variable should not be treated as one long string. - # Alternative: if showcase client library is available on Maven Central, - # Instead of downloading sdk-platform-java/showcase (for client library, and generation setup), - # Can instead download googleapis (for generation setup) and gapic-showcase (for protos) - # Modify sdk-platform-java/WORKSPACE - modify_workspace_file "../WORKSPACE" ".." "../../scripts/resources/googleapis_modification_string.txt" - # Modify sdk-platform-java/showcase/BUILD.bazel - buildozer 'new_load @spring_cloud_generator//:java_gapic_spring.bzl java_gapic_spring_library' BUILD.bazel:__pkg__ - modify_build_file "BUILD.bazel" - # Invoke bazel target for generating showcase-spring-starter - bazelisk build --tool_java_language_version=17 --tool_java_runtime_version=remotejdk_17 //showcase:showcase_java_gapic_spring # Post-process generated modules - copy_and_unzip "../bazel-bin/showcase/showcase_java_gapic_spring-spring.srcjar" "showcase_java_gapic_spring-spring.srcjar" "${SPRING_GENERATOR_DIR}/showcase" ${SHOWCASE_STARTER_DIR} - modify_starter_pom ${SHOWCASE_STARTER_DIR}/pom.xml "com.google.cloud" "gapic-showcase" $PROJECT_VERSION + unzip "${output_srcjar_zip_name}" + copy_and_unzip "${output_folder}/temp-codegen-spring.srcjar" "temp-codegen-spring.srcjar" "${spring_generator_dir}/showcase" ${showcase_starter_dir} + modify_starter_pom "${showcase_starter_dir}/pom.xml" "com.google.cloud" "gapic-showcase" "${project_version}" + + popd #output_folder # Additional pom.xml modifications for showcase starter # Add explicit gapic-showcase version - sed -i'' '/^ *gapic-showcase<\/artifactId>*/a \ \ \ \ \ \ '"$GAPIC_SHOWCASE_CLIENT_VERSION"'' ${SHOWCASE_STARTER_DIR}/pom.xml + sed -i'' '/^ *gapic-showcase<\/artifactId>*/a \ \ \ \ \ \ '"${gapic_showcase_client_version}"'' "${showcase_starter_dir}/pom.xml" # Update relative path to parent pom (different repo structure from starters) - RELATIVE_PATH="\ \ \ \ ..\/..\/..\/spring-cloud-gcp-starters\/pom.xml<\/relativePath>" - sed -i'' 's/^ *.*/'"$RELATIVE_PATH"'/g' ${SHOWCASE_STARTER_DIR}/pom.xml + relative_path="\ \ \ \ ..\/..\/..\/spring-cloud-gcp-starters\/pom.xml<\/relativePath>" + sed -i'' 's/^ *.*/'"${relative_path}"'/g' ${showcase_starter_dir}/pom.xml # Run google-java-format on generated code - run_formatter ${SHOWCASE_STARTER_DIR} + run_formatter "${showcase_starter_dir}" # Remove downloaded repos - rm -rf ${SPRING_GENERATOR_DIR}/sdk-platform-java + popd #showcase + popd #sdk-platform-java + rm -rdf "${spring_generator_dir}/sdk-platform-java" + rm -rdf gapic-showcase + popd #spring_root_dir } -if [[ UPDATE -ne 0 ]]; then +if [[ "${update}" == "true" ]]; then echo "Running script to perform showcase-spring-starter update" - generate_showcase_spring_starter ${SHOWCASE_STARTER_OLD_DIR} + generate_showcase_spring_starter ${showcase_starter_old_dir} else echo "Running script to perform showcase-spring-starter verification" - generate_showcase_spring_starter ${SHOWCASE_STARTER_NEW_DIR} - verify ${SHOWCASE_STARTER_OLD_DIR} ${SHOWCASE_STARTER_NEW_DIR} + generate_showcase_spring_starter ${showcase_starter_new_dir} + verify ${showcase_starter_old_dir} ${showcase_starter_new_dir} fi diff --git a/spring-cloud-generator/showcase/showcase-spring-starter/src/main/java/com/google/showcase/v1beta1/spring/ComplianceSpringAutoConfiguration.java b/spring-cloud-generator/showcase/showcase-spring-starter/src/main/java/com/google/showcase/v1beta1/spring/ComplianceSpringAutoConfiguration.java index 0ce3b417bb..4a8849ca3c 100644 --- a/spring-cloud-generator/showcase/showcase-spring-starter/src/main/java/com/google/showcase/v1beta1/spring/ComplianceSpringAutoConfiguration.java +++ b/spring-cloud-generator/showcase/showcase-spring-starter/src/main/java/com/google/showcase/v1beta1/spring/ComplianceSpringAutoConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2023 Google LLC + * Copyright 2024 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -134,6 +134,7 @@ public ComplianceSettings complianceSettings( clientSettingsBuilder .setCredentialsProvider(this.credentialsProvider) .setTransportChannelProvider(defaultTransportChannelProvider) + .setEndpoint(ComplianceSettings.getDefaultEndpoint()) .setHeaderProvider(this.userAgentHeaderProvider()); if (this.clientProperties.getQuotaProjectId() != null) { clientSettingsBuilder.setQuotaProjectId(this.clientProperties.getQuotaProjectId()); diff --git a/spring-cloud-generator/showcase/showcase-spring-starter/src/main/java/com/google/showcase/v1beta1/spring/ComplianceSpringProperties.java b/spring-cloud-generator/showcase/showcase-spring-starter/src/main/java/com/google/showcase/v1beta1/spring/ComplianceSpringProperties.java index 718f65f7ce..efaf536aeb 100644 --- a/spring-cloud-generator/showcase/showcase-spring-starter/src/main/java/com/google/showcase/v1beta1/spring/ComplianceSpringProperties.java +++ b/spring-cloud-generator/showcase/showcase-spring-starter/src/main/java/com/google/showcase/v1beta1/spring/ComplianceSpringProperties.java @@ -1,5 +1,5 @@ /* - * Copyright 2023 Google LLC + * Copyright 2024 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/spring-cloud-generator/showcase/showcase-spring-starter/src/main/java/com/google/showcase/v1beta1/spring/EchoSpringAutoConfiguration.java b/spring-cloud-generator/showcase/showcase-spring-starter/src/main/java/com/google/showcase/v1beta1/spring/EchoSpringAutoConfiguration.java index bbfb2c5f1a..8a3602ca90 100644 --- a/spring-cloud-generator/showcase/showcase-spring-starter/src/main/java/com/google/showcase/v1beta1/spring/EchoSpringAutoConfiguration.java +++ b/spring-cloud-generator/showcase/showcase-spring-starter/src/main/java/com/google/showcase/v1beta1/spring/EchoSpringAutoConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2023 Google LLC + * Copyright 2024 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -130,6 +130,7 @@ public EchoSettings echoSettings( clientSettingsBuilder .setCredentialsProvider(this.credentialsProvider) .setTransportChannelProvider(defaultTransportChannelProvider) + .setEndpoint(EchoSettings.getDefaultEndpoint()) .setHeaderProvider(this.userAgentHeaderProvider()); if (this.clientProperties.getQuotaProjectId() != null) { clientSettingsBuilder.setQuotaProjectId(this.clientProperties.getQuotaProjectId()); @@ -159,6 +160,13 @@ public EchoSettings echoSettings( clientSettingsBuilder.echoSettings().getRetrySettings(), serviceRetry); clientSettingsBuilder.echoSettings().setRetrySettings(echoRetrySettings); + RetrySettings echoErrorDetailsRetrySettings = + RetryUtil.updateRetrySettings( + clientSettingsBuilder.echoErrorDetailsSettings().getRetrySettings(), serviceRetry); + clientSettingsBuilder + .echoErrorDetailsSettings() + .setRetrySettings(echoErrorDetailsRetrySettings); + RetrySettings pagedExpandRetrySettings = RetryUtil.updateRetrySettings( clientSettingsBuilder.pagedExpandSettings().getRetrySettings(), serviceRetry); @@ -225,6 +233,20 @@ public EchoSettings echoSettings( LOGGER.trace("Configured method-level retry settings for echo from properties."); } } + Retry echoErrorDetailsRetry = clientProperties.getEchoErrorDetailsRetry(); + if (echoErrorDetailsRetry != null) { + RetrySettings echoErrorDetailsRetrySettings = + RetryUtil.updateRetrySettings( + clientSettingsBuilder.echoErrorDetailsSettings().getRetrySettings(), + echoErrorDetailsRetry); + clientSettingsBuilder + .echoErrorDetailsSettings() + .setRetrySettings(echoErrorDetailsRetrySettings); + if (LOGGER.isTraceEnabled()) { + LOGGER.trace( + "Configured method-level retry settings for echoErrorDetails from properties."); + } + } Retry pagedExpandRetry = clientProperties.getPagedExpandRetry(); if (pagedExpandRetry != null) { RetrySettings pagedExpandRetrySettings = diff --git a/spring-cloud-generator/showcase/showcase-spring-starter/src/main/java/com/google/showcase/v1beta1/spring/EchoSpringProperties.java b/spring-cloud-generator/showcase/showcase-spring-starter/src/main/java/com/google/showcase/v1beta1/spring/EchoSpringProperties.java index a4df4c2a24..3a0a47e719 100644 --- a/spring-cloud-generator/showcase/showcase-spring-starter/src/main/java/com/google/showcase/v1beta1/spring/EchoSpringProperties.java +++ b/spring-cloud-generator/showcase/showcase-spring-starter/src/main/java/com/google/showcase/v1beta1/spring/EchoSpringProperties.java @@ -1,5 +1,5 @@ /* - * Copyright 2023 Google LLC + * Copyright 2024 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -45,6 +45,11 @@ public class EchoSpringProperties implements CredentialsSupplier { * over service-level retry configurations for that RPC method. */ @NestedConfigurationProperty private Retry echoRetry; + /** + * Allow override of retry settings at method-level for echoErrorDetails. If defined, this takes + * precedence over service-level retry configurations for that RPC method. + */ + @NestedConfigurationProperty private Retry echoErrorDetailsRetry; /** * Allow override of retry settings at method-level for pagedExpand. If defined, this takes * precedence over service-level retry configurations for that RPC method. @@ -136,6 +141,14 @@ public void setEchoRetry(Retry echoRetry) { this.echoRetry = echoRetry; } + public Retry getEchoErrorDetailsRetry() { + return this.echoErrorDetailsRetry; + } + + public void setEchoErrorDetailsRetry(Retry echoErrorDetailsRetry) { + this.echoErrorDetailsRetry = echoErrorDetailsRetry; + } + public Retry getPagedExpandRetry() { return this.pagedExpandRetry; } diff --git a/spring-cloud-generator/showcase/showcase-spring-starter/src/main/java/com/google/showcase/v1beta1/spring/IdentitySpringAutoConfiguration.java b/spring-cloud-generator/showcase/showcase-spring-starter/src/main/java/com/google/showcase/v1beta1/spring/IdentitySpringAutoConfiguration.java index b545e4c783..a56b0a2a1d 100644 --- a/spring-cloud-generator/showcase/showcase-spring-starter/src/main/java/com/google/showcase/v1beta1/spring/IdentitySpringAutoConfiguration.java +++ b/spring-cloud-generator/showcase/showcase-spring-starter/src/main/java/com/google/showcase/v1beta1/spring/IdentitySpringAutoConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2023 Google LLC + * Copyright 2024 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -132,6 +132,7 @@ public IdentitySettings identitySettings( clientSettingsBuilder .setCredentialsProvider(this.credentialsProvider) .setTransportChannelProvider(defaultTransportChannelProvider) + .setEndpoint(IdentitySettings.getDefaultEndpoint()) .setHeaderProvider(this.userAgentHeaderProvider()); if (this.clientProperties.getQuotaProjectId() != null) { clientSettingsBuilder.setQuotaProjectId(this.clientProperties.getQuotaProjectId()); diff --git a/spring-cloud-generator/showcase/showcase-spring-starter/src/main/java/com/google/showcase/v1beta1/spring/IdentitySpringProperties.java b/spring-cloud-generator/showcase/showcase-spring-starter/src/main/java/com/google/showcase/v1beta1/spring/IdentitySpringProperties.java index 2162fa1997..675c697367 100644 --- a/spring-cloud-generator/showcase/showcase-spring-starter/src/main/java/com/google/showcase/v1beta1/spring/IdentitySpringProperties.java +++ b/spring-cloud-generator/showcase/showcase-spring-starter/src/main/java/com/google/showcase/v1beta1/spring/IdentitySpringProperties.java @@ -1,5 +1,5 @@ /* - * Copyright 2023 Google LLC + * Copyright 2024 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/spring-cloud-generator/showcase/showcase-spring-starter/src/main/java/com/google/showcase/v1beta1/spring/MessagingSpringAutoConfiguration.java b/spring-cloud-generator/showcase/showcase-spring-starter/src/main/java/com/google/showcase/v1beta1/spring/MessagingSpringAutoConfiguration.java index 491bccb950..489416c612 100644 --- a/spring-cloud-generator/showcase/showcase-spring-starter/src/main/java/com/google/showcase/v1beta1/spring/MessagingSpringAutoConfiguration.java +++ b/spring-cloud-generator/showcase/showcase-spring-starter/src/main/java/com/google/showcase/v1beta1/spring/MessagingSpringAutoConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2023 Google LLC + * Copyright 2024 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -132,6 +132,7 @@ public MessagingSettings messagingSettings( clientSettingsBuilder .setCredentialsProvider(this.credentialsProvider) .setTransportChannelProvider(defaultTransportChannelProvider) + .setEndpoint(MessagingSettings.getDefaultEndpoint()) .setHeaderProvider(this.userAgentHeaderProvider()); if (this.clientProperties.getQuotaProjectId() != null) { clientSettingsBuilder.setQuotaProjectId(this.clientProperties.getQuotaProjectId()); diff --git a/spring-cloud-generator/showcase/showcase-spring-starter/src/main/java/com/google/showcase/v1beta1/spring/MessagingSpringProperties.java b/spring-cloud-generator/showcase/showcase-spring-starter/src/main/java/com/google/showcase/v1beta1/spring/MessagingSpringProperties.java index b99ee36abb..9c61201611 100644 --- a/spring-cloud-generator/showcase/showcase-spring-starter/src/main/java/com/google/showcase/v1beta1/spring/MessagingSpringProperties.java +++ b/spring-cloud-generator/showcase/showcase-spring-starter/src/main/java/com/google/showcase/v1beta1/spring/MessagingSpringProperties.java @@ -1,5 +1,5 @@ /* - * Copyright 2023 Google LLC + * Copyright 2024 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/spring-cloud-generator/showcase/showcase-spring-starter/src/main/java/com/google/showcase/v1beta1/spring/SequenceServiceSpringAutoConfiguration.java b/spring-cloud-generator/showcase/showcase-spring-starter/src/main/java/com/google/showcase/v1beta1/spring/SequenceServiceSpringAutoConfiguration.java index b200a3fd94..5587f3a942 100644 --- a/spring-cloud-generator/showcase/showcase-spring-starter/src/main/java/com/google/showcase/v1beta1/spring/SequenceServiceSpringAutoConfiguration.java +++ b/spring-cloud-generator/showcase/showcase-spring-starter/src/main/java/com/google/showcase/v1beta1/spring/SequenceServiceSpringAutoConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2023 Google LLC + * Copyright 2024 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -135,6 +135,7 @@ public SequenceServiceSettings sequenceServiceSettings( clientSettingsBuilder .setCredentialsProvider(this.credentialsProvider) .setTransportChannelProvider(defaultTransportChannelProvider) + .setEndpoint(SequenceServiceSettings.getDefaultEndpoint()) .setHeaderProvider(this.userAgentHeaderProvider()); if (this.clientProperties.getQuotaProjectId() != null) { clientSettingsBuilder.setQuotaProjectId(this.clientProperties.getQuotaProjectId()); diff --git a/spring-cloud-generator/showcase/showcase-spring-starter/src/main/java/com/google/showcase/v1beta1/spring/SequenceServiceSpringProperties.java b/spring-cloud-generator/showcase/showcase-spring-starter/src/main/java/com/google/showcase/v1beta1/spring/SequenceServiceSpringProperties.java index 7ac7a9ce3f..b4e0beb04f 100644 --- a/spring-cloud-generator/showcase/showcase-spring-starter/src/main/java/com/google/showcase/v1beta1/spring/SequenceServiceSpringProperties.java +++ b/spring-cloud-generator/showcase/showcase-spring-starter/src/main/java/com/google/showcase/v1beta1/spring/SequenceServiceSpringProperties.java @@ -1,5 +1,5 @@ /* - * Copyright 2023 Google LLC + * Copyright 2024 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/spring-cloud-generator/showcase/showcase-spring-starter/src/main/java/com/google/showcase/v1beta1/spring/TestingSpringAutoConfiguration.java b/spring-cloud-generator/showcase/showcase-spring-starter/src/main/java/com/google/showcase/v1beta1/spring/TestingSpringAutoConfiguration.java index 0e0bbe227e..e70a3c7229 100644 --- a/spring-cloud-generator/showcase/showcase-spring-starter/src/main/java/com/google/showcase/v1beta1/spring/TestingSpringAutoConfiguration.java +++ b/spring-cloud-generator/showcase/showcase-spring-starter/src/main/java/com/google/showcase/v1beta1/spring/TestingSpringAutoConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2023 Google LLC + * Copyright 2024 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -130,6 +130,7 @@ public TestingSettings testingSettings( clientSettingsBuilder .setCredentialsProvider(this.credentialsProvider) .setTransportChannelProvider(defaultTransportChannelProvider) + .setEndpoint(TestingSettings.getDefaultEndpoint()) .setHeaderProvider(this.userAgentHeaderProvider()); if (this.clientProperties.getQuotaProjectId() != null) { clientSettingsBuilder.setQuotaProjectId(this.clientProperties.getQuotaProjectId()); diff --git a/spring-cloud-generator/showcase/showcase-spring-starter/src/main/java/com/google/showcase/v1beta1/spring/TestingSpringProperties.java b/spring-cloud-generator/showcase/showcase-spring-starter/src/main/java/com/google/showcase/v1beta1/spring/TestingSpringProperties.java index c7e20def88..03e3bf8b99 100644 --- a/spring-cloud-generator/showcase/showcase-spring-starter/src/main/java/com/google/showcase/v1beta1/spring/TestingSpringProperties.java +++ b/spring-cloud-generator/showcase/showcase-spring-starter/src/main/java/com/google/showcase/v1beta1/spring/TestingSpringProperties.java @@ -1,5 +1,5 @@ /* - * Copyright 2023 Google LLC + * Copyright 2024 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/spring-cloud-generator/showcase/showcase-spring-starter/src/main/java/com/google/showcase/v1beta1/spring/package-info.java b/spring-cloud-generator/showcase/showcase-spring-starter/src/main/java/com/google/showcase/v1beta1/spring/package-info.java index 27730b3d94..6907d12b6c 100644 --- a/spring-cloud-generator/showcase/showcase-spring-starter/src/main/java/com/google/showcase/v1beta1/spring/package-info.java +++ b/spring-cloud-generator/showcase/showcase-spring-starter/src/main/java/com/google/showcase/v1beta1/spring/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright 2023 Google LLC + * Copyright 2024 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/spring-cloud-generator/showcase/showcase-spring-starter/src/test/java/com/google/showcase/v1beta1/spring/EchoAutoConfigurationTests.java b/spring-cloud-generator/showcase/showcase-spring-starter/src/test/java/com/google/showcase/v1beta1/spring/EchoAutoConfigurationTests.java index 78a528e7e0..3e728c95cf 100644 --- a/spring-cloud-generator/showcase/showcase-spring-starter/src/test/java/com/google/showcase/v1beta1/spring/EchoAutoConfigurationTests.java +++ b/spring-cloud-generator/showcase/showcase-spring-starter/src/test/java/com/google/showcase/v1beta1/spring/EchoAutoConfigurationTests.java @@ -198,6 +198,7 @@ void testCustomTransportChannelProviderUsedWhenProvided() throws IOException { when(mockApiCallContext.withTransportChannel(any())).thenReturn(mockApiCallContext); when(mockApiCallContext.withStreamWaitTimeout(any())).thenReturn(mockApiCallContext); when(mockApiCallContext.withStreamIdleTimeout(any())).thenReturn(mockApiCallContext); + when(mockApiCallContext.withEndpointContext(any())).thenReturn(mockApiCallContext); contextRunner .withBean( @@ -218,6 +219,7 @@ void testCustomServiceSettingsUsedWhenProvided() throws IOException { EchoSettings.newBuilder() .setCredentialsProvider(mockCredentialsProvider) .setQuotaProjectId(SERVICE_OVERRIDE_CLIENT_ID) + .setEndpoint(EchoSettings.getDefaultEndpoint()) .build(); contextRunner .withBean("echoSettings", EchoSettings.class, () -> customEchoSettings) diff --git a/spring-cloud-generator/spring-cloud-generator-wrapper b/spring-cloud-generator/spring-cloud-generator-wrapper new file mode 100755 index 0000000000..cf22d001b9 --- /dev/null +++ b/spring-cloud-generator/spring-cloud-generator-wrapper @@ -0,0 +1,6 @@ +#!/usr/bin/env bash + +set -ex + +# Wrap spring-cloud-generator.jar because protoc requires the plugin to be executable. +exec java -classpath "spring-cloud-generator-${project_version}-jar-with-dependencies.jar" com.google.cloud.generator.spring.Main diff --git a/spring-cloud-generator/src/main/java/com/google/cloud/generator/spring/composer/SpringAutoConfigClassComposer.java b/spring-cloud-generator/src/main/java/com/google/cloud/generator/spring/composer/SpringAutoConfigClassComposer.java index 649c10d5eb..9f52ee3382 100644 --- a/spring-cloud-generator/src/main/java/com/google/cloud/generator/spring/composer/SpringAutoConfigClassComposer.java +++ b/spring-cloud-generator/src/main/java/com/google/cloud/generator/spring/composer/SpringAutoConfigClassComposer.java @@ -465,6 +465,12 @@ private static MethodDefinition createSettingsBeanMethod( .setName("defaultTransportChannelProvider") .setType(STATIC_TYPES.get("TransportChannelProvider")) .build()); + MethodInvocationExpr defaultEnpointMethodInvocationExpr = + MethodInvocationExpr.builder() + .setStaticReferenceType(types.get("ServiceSettings")) + .setMethodName("getDefaultEndpoint") + .setReturnType(TypeNode.STRING) + .build(); List bodyStatements = new ArrayList<>(); @@ -577,6 +583,12 @@ private static MethodDefinition createSettingsBeanMethod( .setMethodName("setTransportChannelProvider") .setArguments(transportChannelProviderVariableExpr) .build(); + settingsBuilderExpr = + MethodInvocationExpr.builder() + .setExprReferenceExpr(settingsBuilderExpr) + .setMethodName("setEndpoint") + .setArguments(defaultEnpointMethodInvocationExpr) + .build(); MethodInvocationExpr userAgentHeaderProviderInvocation = MethodInvocationExpr.builder() .setExprReferenceExpr(thisExpr) diff --git a/spring-cloud-generator/src/test/java/com/google/cloud/generator/spring/composer/goldens/EchoSpringAutoConfigurationFull.golden b/spring-cloud-generator/src/test/java/com/google/cloud/generator/spring/composer/goldens/EchoSpringAutoConfigurationFull.golden index 9d3862027d..66d2536758 100644 --- a/spring-cloud-generator/src/test/java/com/google/cloud/generator/spring/composer/goldens/EchoSpringAutoConfigurationFull.golden +++ b/spring-cloud-generator/src/test/java/com/google/cloud/generator/spring/composer/goldens/EchoSpringAutoConfigurationFull.golden @@ -120,6 +120,7 @@ public class EchoSpringAutoConfiguration { clientSettingsBuilder .setCredentialsProvider(this.credentialsProvider) .setTransportChannelProvider(defaultTransportChannelProvider) + .setEndpoint(EchoSettings.getDefaultEndpoint()) .setHeaderProvider(this.userAgentHeaderProvider()); if (this.clientProperties.getQuotaProjectId() != null) { clientSettingsBuilder.setQuotaProjectId(this.clientProperties.getQuotaProjectId()); diff --git a/spring-cloud-generator/src/test/java/com/google/cloud/generator/spring/composer/goldens/EchoSpringAutoConfigurationGrpc.golden b/spring-cloud-generator/src/test/java/com/google/cloud/generator/spring/composer/goldens/EchoSpringAutoConfigurationGrpc.golden index 327fa50bf6..270f496f87 100644 --- a/spring-cloud-generator/src/test/java/com/google/cloud/generator/spring/composer/goldens/EchoSpringAutoConfigurationGrpc.golden +++ b/spring-cloud-generator/src/test/java/com/google/cloud/generator/spring/composer/goldens/EchoSpringAutoConfigurationGrpc.golden @@ -100,6 +100,7 @@ public class EchoSpringAutoConfiguration { clientSettingsBuilder .setCredentialsProvider(this.credentialsProvider) .setTransportChannelProvider(defaultTransportChannelProvider) + .setEndpoint(EchoSettings.getDefaultEndpoint()) .setHeaderProvider(this.userAgentHeaderProvider()); if (this.clientProperties.getQuotaProjectId() != null) { clientSettingsBuilder.setQuotaProjectId(this.clientProperties.getQuotaProjectId()); diff --git a/spring-cloud-generator/src/test/java/com/google/cloud/generator/spring/composer/goldens/EchoSpringAutoConfigurationGrpcRest.golden b/spring-cloud-generator/src/test/java/com/google/cloud/generator/spring/composer/goldens/EchoSpringAutoConfigurationGrpcRest.golden index 2d53a7ecc9..008bfa24b6 100644 --- a/spring-cloud-generator/src/test/java/com/google/cloud/generator/spring/composer/goldens/EchoSpringAutoConfigurationGrpcRest.golden +++ b/spring-cloud-generator/src/test/java/com/google/cloud/generator/spring/composer/goldens/EchoSpringAutoConfigurationGrpcRest.golden @@ -112,6 +112,7 @@ public class EchoSpringAutoConfiguration { clientSettingsBuilder .setCredentialsProvider(this.credentialsProvider) .setTransportChannelProvider(defaultTransportChannelProvider) + .setEndpoint(EchoSettings.getDefaultEndpoint()) .setHeaderProvider(this.userAgentHeaderProvider()); if (this.clientProperties.getQuotaProjectId() != null) { clientSettingsBuilder.setQuotaProjectId(this.clientProperties.getQuotaProjectId()); diff --git a/spring-cloud-generator/src/test/java/com/google/cloud/generator/spring/composer/goldens/EchoSpringAutoConfigurationRest.golden b/spring-cloud-generator/src/test/java/com/google/cloud/generator/spring/composer/goldens/EchoSpringAutoConfigurationRest.golden index 327fa50bf6..270f496f87 100644 --- a/spring-cloud-generator/src/test/java/com/google/cloud/generator/spring/composer/goldens/EchoSpringAutoConfigurationRest.golden +++ b/spring-cloud-generator/src/test/java/com/google/cloud/generator/spring/composer/goldens/EchoSpringAutoConfigurationRest.golden @@ -100,6 +100,7 @@ public class EchoSpringAutoConfiguration { clientSettingsBuilder .setCredentialsProvider(this.credentialsProvider) .setTransportChannelProvider(defaultTransportChannelProvider) + .setEndpoint(EchoSettings.getDefaultEndpoint()) .setHeaderProvider(this.userAgentHeaderProvider()); if (this.clientProperties.getQuotaProjectId() != null) { clientSettingsBuilder.setQuotaProjectId(this.clientProperties.getQuotaProjectId()); diff --git a/spring-cloud-generator/src/test/java/com/google/cloud/generator/spring/composer/goldens/WickedSpringAutoConfigurationNoRestRpcs.golden b/spring-cloud-generator/src/test/java/com/google/cloud/generator/spring/composer/goldens/WickedSpringAutoConfigurationNoRestRpcs.golden index 7f4903693c..a73cf1f30b 100644 --- a/spring-cloud-generator/src/test/java/com/google/cloud/generator/spring/composer/goldens/WickedSpringAutoConfigurationNoRestRpcs.golden +++ b/spring-cloud-generator/src/test/java/com/google/cloud/generator/spring/composer/goldens/WickedSpringAutoConfigurationNoRestRpcs.golden @@ -100,6 +100,7 @@ public class WickedSpringAutoConfiguration { clientSettingsBuilder .setCredentialsProvider(this.credentialsProvider) .setTransportChannelProvider(defaultTransportChannelProvider) + .setEndpoint(WickedSettings.getDefaultEndpoint()) .setHeaderProvider(this.userAgentHeaderProvider()); if (this.clientProperties.getQuotaProjectId() != null) { clientSettingsBuilder.setQuotaProjectId(this.clientProperties.getQuotaProjectId());