k8s.io/kubernetes@v1.31.0-alpha.0.0.20240520171757-56147500dadc/hack/lib/protoc.sh (about) 1 #!/usr/bin/env bash 2 3 # Copyright 2017 The Kubernetes Authors. 4 # 5 # Licensed under the Apache License, Version 2.0 (the "License"); 6 # you may not use this file except in compliance with the License. 7 # You may obtain a copy of the License at 8 # 9 # http://www.apache.org/licenses/LICENSE-2.0 10 # 11 # Unless required by applicable law or agreed to in writing, software 12 # distributed under the License is distributed on an "AS IS" BASIS, 13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 # See the License for the specific language governing permissions and 15 # limitations under the License. 16 17 set -o errexit 18 set -o nounset 19 set -o pipefail 20 21 # Short-circuit if protoc.sh has already been sourced 22 [[ $(type -t kube::protoc::loaded) == function ]] && return 0 23 24 # The root of the build/dist directory 25 KUBE_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd -P)" 26 source "${KUBE_ROOT}/hack/lib/init.sh" 27 28 PROTOC_VERSION=23.4 29 30 # Generates $1/api.pb.go from the protobuf file $1/api.proto 31 # and formats it correctly 32 # $1: Full path to the directory where the api.proto file is 33 function kube::protoc::generate_proto() { 34 kube::golang::setup_env 35 GOPROXY=off go install k8s.io/code-generator/cmd/go-to-protobuf/protoc-gen-gogo 36 37 kube::protoc::check_protoc 38 39 local package=${1} 40 kube::protoc::protoc "${package}" 41 kube::protoc::format "${package}" 42 } 43 44 # Checks that the current protoc version matches the required version and 45 # exit 1 if it's not the case 46 function kube::protoc::check_protoc() { 47 if [[ -z "$(which protoc)" || "$(protoc --version)" != "libprotoc ${PROTOC_VERSION}"* ]]; then 48 echo "Generating protobuf requires protoc ${PROTOC_VERSION}." 49 echo "Run hack/install-protoc.sh or download and install the" 50 echo "platform-appropriate Protobuf package for your OS from" 51 echo "https://github.com/protocolbuffers/protobuf/releases" 52 return 1 53 fi 54 } 55 56 # Generates $1/api.pb.go from the protobuf file $1/api.proto 57 # $1: Full path to the directory where the api.proto file is 58 function kube::protoc::protoc() { 59 local package=${1} 60 gogopath=$(dirname "$(kube::util::find-binary "protoc-gen-gogo")") 61 62 ( 63 cd "${package}" 64 65 # This invocation of --gogo_out produces its output in the current 66 # directory (despite gogo docs saying it would be source-relative, it 67 # isn't). The inputs to this function do not all have a common root, so 68 # this works best for all inputs. 69 PATH="${gogopath}:${PATH}" protoc \ 70 --proto_path="$(pwd -P)" \ 71 --proto_path="${KUBE_ROOT}/vendor" \ 72 --proto_path="${KUBE_ROOT}/staging/src" \ 73 --proto_path="${KUBE_ROOT}/third_party/protobuf" \ 74 --gogo_out=paths=source_relative,plugins=grpc:. \ 75 api.proto 76 ) 77 } 78 79 # Formats $1/api.pb.go, adds the boilerplate comments and run gofmt on it 80 # $1: Full path to the directory where the api.proto file is 81 function kube::protoc::format() { 82 local package=${1} 83 84 # Update boilerplate for the generated file. 85 cat hack/boilerplate/boilerplate.generatego.txt "${package}/api.pb.go" > tmpfile && mv tmpfile "${package}/api.pb.go" 86 87 # Run gofmt to clean up the generated code. 88 kube::golang::setup_env 89 gofmt -s -w "${package}/api.pb.go" 90 } 91 92 # Compares the contents of $1 and $2 93 # Echo's $3 in case of error and exits 1 94 function kube::protoc::diff() { 95 local ret=0 96 diff -I "gzipped FileDescriptorProto" -I "0x" -Naupr "${1}" "${2}" || ret=$? 97 if [[ ${ret} -ne 0 ]]; then 98 echo "${3}" 99 exit 1 100 fi 101 } 102 103 function kube::protoc::install() { 104 # run in a subshell to isolate caller from directory changes 105 ( 106 local os 107 local arch 108 local download_folder 109 local download_file 110 111 os=$(kube::util::host_os) 112 arch=$(kube::util::host_arch) 113 download_folder="protoc-v${PROTOC_VERSION}-${os}-${arch}" 114 download_file="${download_folder}.zip" 115 116 cd "${KUBE_ROOT}/third_party" || return 1 117 if [[ $(readlink protoc) != "${download_folder}" ]]; then 118 local url 119 if [[ ${os} == "darwin" ]]; then 120 # TODO: switch to universal binary when updating to 3.20+ 121 url="https://github.com/protocolbuffers/protobuf/releases/download/v${PROTOC_VERSION}/protoc-${PROTOC_VERSION}-osx-x86_64.zip" 122 elif [[ ${os} == "linux" && ${arch} == "amd64" ]]; then 123 url="https://github.com/protocolbuffers/protobuf/releases/download/v${PROTOC_VERSION}/protoc-${PROTOC_VERSION}-linux-x86_64.zip" 124 elif [[ ${os} == "linux" && ${arch} == "arm64" ]]; then 125 url="https://github.com/protocolbuffers/protobuf/releases/download/v${PROTOC_VERSION}/protoc-${PROTOC_VERSION}-linux-aarch_64.zip" 126 else 127 kube::log::info "This install script does not support ${os}/${arch}" 128 return 1 129 fi 130 kube::util::download_file "${url}" "${download_file}" 131 unzip -o "${download_file}" -d "${download_folder}" 132 ln -fns "${download_folder}" protoc 133 mv protoc/bin/protoc protoc/protoc 134 chmod -R +rX protoc/protoc 135 rm -fr protoc/include 136 rm "${download_file}" 137 fi 138 kube::log::info "protoc v${PROTOC_VERSION} installed. To use:" 139 kube::log::info "export PATH=\"$(pwd)/protoc:\${PATH}\"" 140 ) 141 } 142 143 # Marker function to indicate protoc.sh has been fully sourced 144 kube::protoc::loaded() { 145 return 0 146 }