| #!/usr/bin/env bash |
| |
| # Copyright 2017 The Kubernetes Authors. |
| # |
| # Licensed under the Apache License, Version 2.0 (the "License"); |
| # you may not use this file except in compliance with the License. |
| # You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, software |
| # distributed under the License is distributed on an "AS IS" BASIS, |
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| # See the License for the specific language governing permissions and |
| # limitations under the License. |
| |
| set -o errexit |
| set -o nounset |
| set -o pipefail |
| |
| # Short-circuit if protoc.sh has already been sourced |
| [[ $(type -t kube::protoc::loaded) == function ]] && return 0 |
| |
| # The root of the build/dist directory |
| KUBE_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd -P)" |
| source "${KUBE_ROOT}/hack/lib/init.sh" |
| |
| PROTOC_VERSION=23.4 |
| |
| # Generates $1/api.pb.go from the protobuf file $1/api.proto |
| # and formats it correctly |
| # $1: Full path to the directory where the api.proto file is |
| function kube::protoc::generate_proto() { |
| kube::golang::setup_env |
| GOPROXY=off go install k8s.io/code-generator/cmd/go-to-protobuf/protoc-gen-gogo |
| |
| kube::protoc::check_protoc |
| |
| local package=${1} |
| kube::protoc::protoc "${package}" |
| kube::protoc::format "${package}" |
| } |
| |
| # Checks that the current protoc version matches the required version and |
| # exit 1 if it's not the case |
| function kube::protoc::check_protoc() { |
| if [[ -z "$(which protoc)" || "$(protoc --version)" != "libprotoc ${PROTOC_VERSION}"* ]]; then |
| echo "Generating protobuf requires protoc ${PROTOC_VERSION}." |
| echo "Run hack/install-protoc.sh or download and install the" |
| echo "platform-appropriate Protobuf package for your OS from" |
| echo "https://github.com/protocolbuffers/protobuf/releases" |
| return 1 |
| fi |
| } |
| |
| # Generates $1/api.pb.go from the protobuf file $1/api.proto |
| # $1: Full path to the directory where the api.proto file is |
| function kube::protoc::protoc() { |
| local package=${1} |
| gogopath=$(dirname "$(kube::util::find-binary "protoc-gen-gogo")") |
| |
| ( |
| cd "${package}" |
| |
| # This invocation of --gogo_out produces its output in the current |
| # directory (despite gogo docs saying it would be source-relative, it |
| # isn't). The inputs to this function do not all have a common root, so |
| # this works best for all inputs. |
| PATH="${gogopath}:${PATH}" protoc \ |
| --proto_path="$(pwd -P)" \ |
| --proto_path="${KUBE_ROOT}/vendor" \ |
| --proto_path="${KUBE_ROOT}/staging/src" \ |
| --proto_path="${KUBE_ROOT}/third_party/protobuf" \ |
| --gogo_out=paths=source_relative,plugins=grpc:. \ |
| api.proto |
| ) |
| } |
| |
| # Formats $1/api.pb.go, adds the boilerplate comments and run gofmt on it |
| # $1: Full path to the directory where the api.proto file is |
| function kube::protoc::format() { |
| local package=${1} |
| |
| # Update boilerplate for the generated file. |
| cat hack/boilerplate/boilerplate.generatego.txt "${package}/api.pb.go" > tmpfile && mv tmpfile "${package}/api.pb.go" |
| |
| # Run gofmt to clean up the generated code. |
| kube::golang::setup_env |
| gofmt -s -w "${package}/api.pb.go" |
| } |
| |
| # Compares the contents of $1 and $2 |
| # Echo's $3 in case of error and exits 1 |
| function kube::protoc::diff() { |
| local ret=0 |
| diff -I "gzipped FileDescriptorProto" -I "0x" -Naupr "${1}" "${2}" || ret=$? |
| if [[ ${ret} -ne 0 ]]; then |
| echo "${3}" |
| exit 1 |
| fi |
| } |
| |
| function kube::protoc::install() { |
| # run in a subshell to isolate caller from directory changes |
| ( |
| local os |
| local arch |
| local download_folder |
| local download_file |
| |
| os=$(kube::util::host_os) |
| arch=$(kube::util::host_arch) |
| download_folder="protoc-v${PROTOC_VERSION}-${os}-${arch}" |
| download_file="${download_folder}.zip" |
| |
| cd "${KUBE_ROOT}/third_party" || return 1 |
| if [[ $(readlink protoc) != "${download_folder}" ]]; then |
| local url |
| if [[ ${os} == "darwin" ]]; then |
| # TODO: switch to universal binary when updating to 3.20+ |
| url="https://github.com/protocolbuffers/protobuf/releases/download/v${PROTOC_VERSION}/protoc-${PROTOC_VERSION}-osx-x86_64.zip" |
| elif [[ ${os} == "linux" && ${arch} == "amd64" ]]; then |
| url="https://github.com/protocolbuffers/protobuf/releases/download/v${PROTOC_VERSION}/protoc-${PROTOC_VERSION}-linux-x86_64.zip" |
| elif [[ ${os} == "linux" && ${arch} == "arm64" ]]; then |
| url="https://github.com/protocolbuffers/protobuf/releases/download/v${PROTOC_VERSION}/protoc-${PROTOC_VERSION}-linux-aarch_64.zip" |
| else |
| kube::log::info "This install script does not support ${os}/${arch}" |
| return 1 |
| fi |
| kube::util::download_file "${url}" "${download_file}" |
| unzip -o "${download_file}" -d "${download_folder}" |
| ln -fns "${download_folder}" protoc |
| mv protoc/bin/protoc protoc/protoc |
| chmod -R +rX protoc/protoc |
| rm -fr protoc/include |
| rm "${download_file}" |
| fi |
| kube::log::info "protoc v${PROTOC_VERSION} installed. To use:" |
| kube::log::info "export PATH=\"$(pwd)/protoc:\${PATH}\"" |
| ) |
| } |
| |
| # Marker function to indicate protoc.sh has been fully sourced |
| kube::protoc::loaded() { |
| return 0 |
| } |