Matt Keeler 326c0ecfbe
In-Memory gRPC (#19942)
* Implement In-Process gRPC for use by controller caching/indexing

This replaces the pipe base listener implementation we were previously using. The new style CAN avoid cloning resources which our controller caching/indexing is taking advantage of to not duplicate resource objects in memory.

To maintain safety for controllers and for them to be able to modify data they get back from the cache and the resource service, the client they are presented in their runtime will be wrapped with an autogenerated client which clones request and response messages as they pass through the client.

Another sizable change in this PR is to consolidate how server specific gRPC services get registered and managed. Before this was in a bunch of different methods and it was difficult to track down how gRPC services were registered. Now its all in one place.

* Fix race in tests

* Ensure the resource service is registered to the multiplexed handler for forwarding from client agents

* Expose peer streaming on the internal handler
2024-01-12 11:54:07 -05:00

344 lines
9.8 KiB
Bash
Executable File

#!/usr/bin/env bash
# Copyright (c) HashiCorp, Inc.
# SPDX-License-Identifier: BUSL-1.1
readonly SCRIPT_NAME="$(basename ${BASH_SOURCE[0]})"
readonly SCRIPT_DIR="$(dirname "${BASH_SOURCE[0]}")"
readonly SOURCE_DIR="$(dirname "$(dirname "${SCRIPT_DIR}")")"
readonly FN_DIR="$(dirname "${SCRIPT_DIR}")/functions"
source "${SCRIPT_DIR}/functions.sh"
unset CDPATH
set -euo pipefail
usage() {
cat <<-EOF
Usage: ${SCRIPT_NAME} [<options ...>]
Description:
Installs various supporting Go tools.
Options:
-protobuf Just install tools for protobuf.
-lint Just install tools for linting.
-codegen Just install tools for codegen.
-pre-commit Just install pre-commit.
-h | --help Print this help text.
EOF
}
function err_usage {
err "$1"
err ""
err "$(usage)"
}
function main {
while test $# -gt 0
do
case "$1" in
-protobuf )
proto_tools_install
return 0
;;
-lint )
lint_install
return 0
;;
-codegen )
codegen_install
return 0
;;
-pre-commit )
pre_commit_install
return 0
;;
-h | --help )
usage
return 0
;;
esac
done
# ensure these tools are installed
tools_install
}
function proto_tools_install {
local protoc_gen_go_version
local protoc_gen_go_grpc_version
local buf_version
local mog_version
local protoc_go_inject_tag_version
local mockery_version
mockery_version="$(make --no-print-directory print-MOCKERY_VERSION)"
protoc_gen_go_version="$(grep google.golang.org/protobuf go.mod | awk '{print $2}')"
protoc_gen_go_grpc_version="$(make --no-print-directory print-PROTOC_GEN_GO_GRPC_VERSION)"
mog_version="$(make --no-print-directory print-MOG_VERSION)"
protoc_go_inject_tag_version="$(make --no-print-directory print-PROTOC_GO_INJECT_TAG_VERSION)"
buf_version="$(make --no-print-directory print-BUF_VERSION)"
protoc_gen_go_binary_version="$(make --no-print-directory print-PROTOC_GEN_GO_BINARY_VERSION)"
# echo "go: ${protoc_gen_go_version}"
# echo "mog: ${mog_version}"
# echo "tag: ${protoc_go_inject_tag_version}"
install_versioned_tool \
'mockery' \
'github.com/vektra/mockery/v2' \
"${mockery_version}" \
'github.com/vektra/mockery/v2'
install_versioned_tool \
'buf' \
'github.com/bufbuild/buf' \
"${buf_version}" \
'github.com/bufbuild/buf/cmd/buf'
install_versioned_tool \
'protoc-gen-go' \
'google.golang.org/protobuf' \
"${protoc_gen_go_version}" \
'google.golang.org/protobuf/cmd/protoc-gen-go'
install_versioned_tool \
'protoc-gen-go-grpc' \
'google.golang.org/grpc/cmd/protoc-gen-go-grpc' \
"${protoc_gen_go_grpc_version}" \
'google.golang.org/grpc/cmd/protoc-gen-go-grpc'
install_versioned_tool \
protoc-gen-go-binary \
'github.com/hashicorp/protoc-gen-go-binary' \
"${protoc_gen_go_binary_version}" \
'github.com/hashicorp/protoc-gen-go-binary'
install_versioned_tool \
'protoc-go-inject-tag' \
'github.com/favadi/protoc-go-inject-tag' \
"${protoc_go_inject_tag_version}" \
'github.com/favadi/protoc-go-inject-tag'
install_versioned_tool \
'mog' \
'github.com/hashicorp/mog' \
"${mog_version}" \
'github.com/hashicorp/mog'
install_local_protoc_generator "${SOURCE_DIR}/internal/tools/protoc-gen-consul-rate-limit"
install_local_protoc_generator "${SOURCE_DIR}/internal/resource/protoc-gen-resource-types"
install_local_protoc_generator "${SOURCE_DIR}/internal/tools/protoc-gen-grpc-clone"
install_local_protoc_generator "${SOURCE_DIR}/internal/resource/protoc-gen-json-shim"
install_local_protoc_generator "${SOURCE_DIR}/internal/resource/protoc-gen-deepcopy"
return 0
}
function lint_install {
local lint_consul_retry_version
lint_consul_retry_version="$(make --no-print-directory print-LINT_CONSUL_RETRY_VERSION)"
local golangci_lint_version
golangci_lint_version="$(make --no-print-directory print-GOLANGCI_LINT_VERSION)"
local gci_version
gci_version="$(make --no-print-directory print-GCI_VERSION)"
install_versioned_tool \
'lint-consul-retry' \
'github.com/hashicorp/lint-consul-retry' \
"${lint_consul_retry_version}" \
'github.com/hashicorp/lint-consul-retry'
install_unversioned_tool \
'enumcover' \
'github.com/reillywatson/enumcover/cmd/enumcover@master'
install_versioned_tool \
'golangci-lint' \
'github.com/golangci/golangci-lint' \
"${golangci_lint_version}" \
'github.com/golangci/golangci-lint/cmd/golangci-lint'
install_versioned_tool \
'gci' \
'github.com/daixiang0/gci' \
"${gci_version}" \
'github.com/daixiang0/gci'
}
function codegen_install {
deepcopy_install
copywrite_install
}
function deepcopy_install {
local deep_copy_version
deep_copy_version="$(make --no-print-directory print-DEEP_COPY_VERSION)"
install_versioned_tool \
'deep-copy' \
'github.com/globusdigital/deep-copy' \
"${deep_copy_version}" \
'github.com/globusdigital/deep-copy'
}
function copywrite_install {
local copywrite_version
copywrite_version="$(make --no-print-directory print-COPYWRITE_TOOL_VERSION)"
install_versioned_tool \
'copywrite' \
'github.com/hashicorp/copywrite' \
"${copywrite_version}" \
'github.com/hashicorp/copywrite'
}
function pre_commit_install {
# if already installed make sure the hook is also installed
if command -v "pre-commit" &>/dev/null; then
# Not to be confused with installing the tool, this installs
# the git hook locally (.git/hooks/pre-commit) which pre-commit
# uses as a vector to run checks on `git commit`. This hook is
# generated based on the local environment hence not source
# controlled.
pre-commit install
return 0
fi
# Install options based on https://pre-commit.com/#installation
if command -v "brew" &>/dev/null; then
brew install pre-commit && pre-commit install
return 0
fi
# Try python regardless of platform (mac, linux, etc)
if command -v "pip3" &>/dev/null; then
pip3 install pre-commit && pre-commit install
return 0
fi
# Can't disappoint the linux/debian folks
if command -v "apt" &>/dev/null; then
sudo apt-get install -yq pre-commit && pre-commit install
return 0
fi
if [[ "$(uname)" == "Darwin" ]]; then
echo "ERROR: Install homebrew from https://brew.sh/ so that pre-commit (https://pre-commit.com) can be installed."
return 1
fi
echo "ERROR: Install python3 and pip3 so that pre-commit (https://pre-commit.com) can be installed."
return 1
}
function tools_install {
lint_install
proto_tools_install
codegen_install
pre_commit_install
copywrite_install
return 0
}
function install_unversioned_tool {
local command="$1"
local install="$2"
if ! command -v "${command}" &>/dev/null ; then
echo "installing tool: ${install}"
go install "${install}"
else
echo "skipping tool: ${install} (installed)"
fi
return 0
}
function install_versioned_tool {
local command="$1"
local module="$2"
local version="$3"
local installbase="$4"
local should_install=
local install_reason=
local got
local vgot
local vneed
local expect="${module}@${version}"
local install="${installbase}@${version}"
if [[ -z "$version" ]]; then
err "cannot install '${command}' no version selected"
return 1
fi
if [[ "$version" = "@DEV" ]]; then
if ! command -v "${command}" &>/dev/null ; then
err "dev version of '${command}' requested but not installed"
return 1
fi
echo "skipping tool: ${installbase} (using development version)"
return 0
fi
if command -v "${command}" &>/dev/null ; then
mod_line="$(go version -m "$(which "${command}")" | grep '\smod\s')"
act_mod=$(echo "${mod_line}" | awk '{print $2}')
if [[ "$module" != "$act_mod" ]]; then
err "${command} is already installed by module \"${act_mod}\" but should be installed by module \"${module}\". Delete it and re-run to re-install."
return 1
fi
got="$(echo "${mod_line}" | grep "${module}" | awk '{print $2 "@" $3}')"
if [[ "$expect" != "$got" ]]; then
should_install=1
install_reason="upgrade"
fi
# check that they were compiled with the current version of go
set +o pipefail
vgot="$(go version -m $(which "${command}") | head -n 1 | grep -o 'go[0-9.]\+')"
vneed="$(go version | head -n 1 | awk '{print $3}')"
set -o pipefail
if [[ "$vgot" != "$vneed" ]]; then
should_install=1
install_reason="go toolchain upgrade"
fi
else
should_install=1
install_reason="install"
fi
if [[ -n $should_install ]]; then
echo "installing tool (${install_reason}): ${install}"
go install "${install}"
else
echo "skipping tool: ${install} (installed)"
fi
return 0
}
function install_local_protoc_generator {
local src=$1
echo "installing tool $(basename $src) from local source"
pushd -- "$src" > /dev/null
go install
popd > /dev/null
}
main "$@"
exit $?