| #!/usr/bin/env bash |
| # Licensed to the Apache Software Foundation (ASF) under one |
| # or more contributor license agreements. See the NOTICE file |
| # distributed with this work for additional information |
| # regarding copyright ownership. The ASF licenses this file |
| # to you 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. |
| |
| # |
| # Copyright 2023 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. |
| |
| # This presents several functions for packages which want to use kubernetes |
| # code-generation tools. |
| |
| # These functions insist that your input IDL (commented go) files be located in |
| # go packages following the pattern $input_pkg_root/$something_sans_slash/$api_version . |
| # Those $something_sans_slash will be propagated into the output directory structure. |
| |
| set -o errexit |
| set -o nounset |
| set -o pipefail |
| |
| KUBE_CODEGEN_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd -P)" |
| |
| function kube::codegen::internal::findz() { |
| # We use `find` rather than `git ls-files` because sometimes external |
| # projects use this across repos. This is an imperfect wrapper of find, |
| # but good enough for this script. |
| find "$@" -print0 |
| } |
| |
| function kube::codegen::internal::grep() { |
| # We use `grep` rather than `git grep` because sometimes external projects |
| # use this across repos. |
| grep "$@" \ |
| --exclude-dir .git \ |
| --exclude-dir _output \ |
| --exclude-dir vendor |
| } |
| |
| # Generate tagged helper code: conversions, deepcopy, and defaults |
| # |
| # USAGE: kube::codegen::gen_helpers [FLAGS] <input-dir> |
| # |
| # <input-dir> |
| # The root directory under which to search for Go files which request code to |
| # be generated. This must be a local path, not a Go package. |
| # |
| # See note at the top about package structure below that. |
| # |
| # FLAGS: |
| # |
| # --boilerplate <string = path_to_kube_codegen_boilerplate> |
| # An optional override for the header file to insert into generated files. |
| # |
| # --extra-peer-dir <string> |
| # An optional list (this flag may be specified multiple times) of "extra" |
| # directories to consider during conversion generation. |
| # |
| function kube::codegen::gen_helpers() { |
| local in_dir="" |
| local boilerplate="${KUBE_CODEGEN_ROOT}/hack/boilerplate.go.txt" |
| local v="${KUBE_VERBOSE:-0}" |
| local extra_peers=() |
| |
| while [ "$#" -gt 0 ]; do |
| case "$1" in |
| "--boilerplate") |
| boilerplate="$2" |
| shift 2 |
| ;; |
| "--extra-peer-dir") |
| extra_peers+=("$2") |
| shift 2 |
| ;; |
| *) |
| if [[ "$1" =~ ^-- ]]; then |
| echo "unknown argument: $1" >&2 |
| return 1 |
| fi |
| if [ -n "$in_dir" ]; then |
| echo "too many arguments: $1 (already have $in_dir)" >&2 |
| return 1 |
| fi |
| in_dir="$1" |
| shift |
| ;; |
| esac |
| done |
| |
| if [ -z "${in_dir}" ]; then |
| echo "input-dir argument is required" >&2 |
| return 1 |
| fi |
| |
| ( |
| # To support running this from anywhere, first cd into this directory, |
| # and then install with forced module mode on and fully qualified name. |
| cd "${KUBE_CODEGEN_ROOT}" |
| BINS=( |
| conversion-gen |
| deepcopy-gen |
| defaulter-gen |
| ) |
| # shellcheck disable=2046 # printf word-splitting is intentional |
| GO111MODULE=on go install $(printf "k8s.io/code-generator/cmd/%s@v0.30.5 " "${BINS[@]}") |
| ) |
| # Go installs in $GOBIN if defined, and $GOPATH/bin otherwise |
| gobin="${GOBIN:-$(go env GOPATH)/bin}" |
| |
| # Deepcopy |
| # |
| local input_pkgs=() |
| while read -r dir; do |
| pkg="$(cd "${dir}" && GO111MODULE=on go list -find .)" |
| input_pkgs+=("${pkg}") |
| done < <( |
| ( kube::codegen::internal::grep -l --null \ |
| -e '^\s*//\s*+k8s:deepcopy-gen=' \ |
| -r "${in_dir}" \ |
| --include '*.go' \ |
| || true \ |
| ) | while read -r -d $'\0' F; do dirname "${F}"; done \ |
| | LC_ALL=C sort -u |
| ) |
| |
| if [ "${#input_pkgs[@]}" != 0 ]; then |
| echo "Generating deepcopy code for ${#input_pkgs[@]} targets" |
| |
| kube::codegen::internal::findz \ |
| "${in_dir}" \ |
| -type f \ |
| -name zz_generated.deepcopy.go \ |
| | xargs -0 rm -f |
| |
| "${gobin}/deepcopy-gen" \ |
| -v "${v}" \ |
| --output-file zz_generated.deepcopy.go \ |
| --go-header-file "${boilerplate}" \ |
| "${input_pkgs[@]}" |
| fi |
| |
| # Defaults |
| # |
| local input_pkgs=() |
| while read -r dir; do |
| pkg="$(cd "${dir}" && GO111MODULE=on go list -find .)" |
| input_pkgs+=("${pkg}") |
| done < <( |
| ( kube::codegen::internal::grep -l --null \ |
| -e '^\s*//\s*+k8s:defaulter-gen=' \ |
| -r "${in_dir}" \ |
| --include '*.go' \ |
| || true \ |
| ) | while read -r -d $'\0' F; do dirname "${F}"; done \ |
| | LC_ALL=C sort -u |
| ) |
| |
| if [ "${#input_pkgs[@]}" != 0 ]; then |
| echo "Generating defaulter code for ${#input_pkgs[@]} targets" |
| |
| kube::codegen::internal::findz \ |
| "${in_dir}" \ |
| -type f \ |
| -name zz_generated.defaults.go \ |
| | xargs -0 rm -f |
| |
| "${gobin}/defaulter-gen" \ |
| -v "${v}" \ |
| --output-file zz_generated.defaults.go \ |
| --go-header-file "${boilerplate}" \ |
| "${input_pkgs[@]}" |
| fi |
| |
| # Conversions |
| # |
| local input_pkgs=() |
| while read -r dir; do |
| pkg="$(cd "${dir}" && GO111MODULE=on go list -find .)" |
| input_pkgs+=("${pkg}") |
| done < <( |
| ( kube::codegen::internal::grep -l --null \ |
| -e '^\s*//\s*+k8s:conversion-gen=' \ |
| -r "${in_dir}" \ |
| --include '*.go' \ |
| || true \ |
| ) | while read -r -d $'\0' F; do dirname "${F}"; done \ |
| | LC_ALL=C sort -u |
| ) |
| |
| if [ "${#input_pkgs[@]}" != 0 ]; then |
| echo "Generating conversion code for ${#input_pkgs[@]} targets" |
| |
| kube::codegen::internal::findz \ |
| "${in_dir}" \ |
| -type f \ |
| -name zz_generated.conversion.go \ |
| | xargs -0 rm -f |
| |
| local extra_peer_args=() |
| for arg in "${extra_peers[@]:+"${extra_peers[@]}"}"; do |
| extra_peer_args+=("--extra-peer-dirs" "$arg") |
| done |
| "${gobin}/conversion-gen" \ |
| -v "${v}" \ |
| --output-file zz_generated.conversion.go \ |
| --go-header-file "${boilerplate}" \ |
| "${extra_peer_args[@]:+"${extra_peer_args[@]}"}" \ |
| "${input_pkgs[@]}" |
| fi |
| } |
| |
| # Generate openapi code |
| # |
| # USAGE: kube::codegen::gen_openapi [FLAGS] <input-dir> |
| # |
| # <input-dir> |
| # The root directory under which to search for Go files which request openapi |
| # to be generated. This must be a local path, not a Go package. |
| # |
| # See note at the top about package structure below that. |
| # |
| # FLAGS: |
| # |
| # --output-dir <string> |
| # The directory into which to emit code. |
| # |
| # --output-pkg <string> |
| # The Go package path (import path) of the --output-dir. |
| # |
| # --extra-pkgs <string> |
| # An optional list of additional packages to be imported during openapi |
| # generation. The argument must be Go package syntax, e.g. |
| # "k8s.io/foo/bar". It may be a single value or a comma-delimited list. |
| # This flag may be repeated. |
| # |
| # --report-filename <string = "/dev/null"> |
| # An optional path at which to write an API violations report. "-" means |
| # stdout. |
| # |
| # --update-report |
| # If specified, update the report file in place, rather than diffing it. |
| # |
| # --boilerplate <string = path_to_kube_codegen_boilerplate> |
| # An optional override for the header file to insert into generated files. |
| # |
| function kube::codegen::gen_openapi() { |
| local in_dir="" |
| local out_dir="" |
| local out_pkg="" |
| local extra_pkgs=() |
| local report="/dev/null" |
| local update_report="" |
| local boilerplate="${KUBE_CODEGEN_ROOT}/hack/boilerplate.go.txt" |
| local v="${KUBE_VERBOSE:-0}" |
| |
| while [ "$#" -gt 0 ]; do |
| case "$1" in |
| "--output-dir") |
| out_dir="$2" |
| shift 2 |
| ;; |
| "--output-pkg") |
| out_pkg="$2" |
| shift 2 |
| ;; |
| "--extra-pkgs") |
| extra_pkgs+=("$2") |
| shift 2 |
| ;; |
| "--report-filename") |
| report="$2" |
| shift 2 |
| ;; |
| "--update-report") |
| update_report="true" |
| shift |
| ;; |
| "--boilerplate") |
| boilerplate="$2" |
| shift 2 |
| ;; |
| *) |
| if [[ "$1" =~ ^-- ]]; then |
| echo "unknown argument: $1" >&2 |
| return 1 |
| fi |
| if [ -n "$in_dir" ]; then |
| echo "too many arguments: $1 (already have $in_dir)" >&2 |
| return 1 |
| fi |
| in_dir="$1" |
| shift |
| ;; |
| esac |
| done |
| |
| if [ -z "${in_dir}" ]; then |
| echo "input-dir argument is required" >&2 |
| return 1 |
| fi |
| if [ -z "${out_dir}" ]; then |
| echo "--output-dir is required" >&2 |
| return 1 |
| fi |
| if [ -z "${out_pkg}" ]; then |
| echo "--output-pkg is required" >&2 |
| return 1 |
| fi |
| |
| local new_report |
| new_report="$(mktemp -t "$(basename "$0").api_violations.XXXXXX")" |
| if [ -n "${update_report}" ]; then |
| new_report="${report}" |
| fi |
| |
| ( |
| # To support running this from anywhere, first cd into this directory, |
| # and then install with forced module mode on and fully qualified name. |
| cd "${KUBE_CODEGEN_ROOT}" |
| BINS=( |
| openapi-gen |
| ) |
| # shellcheck disable=2046 # printf word-splitting is intentional |
| GO111MODULE=on go install $(printf "k8s.io/kube-openapi/cmd/%s@v0.30.5 " "${BINS[@]}") |
| ) |
| # Go installs in $GOBIN if defined, and $GOPATH/bin otherwise |
| gobin="${GOBIN:-$(go env GOPATH)/bin}" |
| |
| local input_pkgs=( "${extra_pkgs[@]:+"${extra_pkgs[@]}"}") |
| while read -r dir; do |
| pkg="$(cd "${dir}" && GO111MODULE=on go list -find .)" |
| input_pkgs+=("${pkg}") |
| done < <( |
| ( kube::codegen::internal::grep -l --null \ |
| -e '^\s*//\s*+k8s:openapi-gen=' \ |
| -r "${in_dir}" \ |
| --include '*.go' \ |
| || true \ |
| ) | while read -r -d $'\0' F; do dirname "${F}"; done \ |
| | LC_ALL=C sort -u |
| ) |
| |
| if [ "${#input_pkgs[@]}" != 0 ]; then |
| echo "Generating openapi code for ${#input_pkgs[@]} targets" |
| |
| kube::codegen::internal::findz \ |
| "${in_dir}" \ |
| -type f \ |
| -name zz_generated.openapi.go \ |
| | xargs -0 rm -f |
| |
| "${gobin}/openapi-gen" \ |
| -v "${v}" \ |
| --output-file zz_generated.openapi.go \ |
| --go-header-file "${boilerplate}" \ |
| --output-dir "${out_dir}" \ |
| --output-pkg "${out_pkg}" \ |
| --report-filename "${new_report}" \ |
| "k8s.io/apimachinery/pkg/apis/meta/v1" \ |
| "k8s.io/apimachinery/pkg/runtime" \ |
| "k8s.io/apimachinery/pkg/version" \ |
| "${input_pkgs[@]}" |
| fi |
| |
| touch "${report}" # in case it doesn't exist yet |
| if ! diff -u "${report}" "${new_report}"; then |
| echo -e "ERROR:" |
| echo -e "\tAPI rule check failed for ${report}: new reported violations" |
| echo -e "\tPlease read api/api-rules/README.md" |
| return 1 |
| fi |
| } |
| |
| # Generate client code |
| # |
| # USAGE: kube::codegen::gen_client [FLAGS] <input-dir> |
| # |
| # <input-dir> |
| # The root package under which to search for Go files which request clients |
| # to be generated. This must be a local path, not a Go package. |
| # |
| # See note at the top about package structure below that. |
| # |
| # FLAGS: |
| # --one-input-api <string> |
| # A specific API (a directory) under the input-dir for which to generate a |
| # client. If this is not set, clients for all APIs under the input-dir |
| # will be generated (under the --output-pkg). |
| # |
| # --output-dir <string> |
| # The root directory under which to emit code. Each aspect of client |
| # generation will make one or more subdirectories. |
| # |
| # --output-pkg <string> |
| # The Go package path (import path) of the --output-dir. Each aspect of |
| # client generation will make one or more sub-packages. |
| # |
| # --boilerplate <string = path_to_kube_codegen_boilerplate> |
| # An optional override for the header file to insert into generated files. |
| # |
| # --clientset-name <string = "clientset"> |
| # An optional override for the leaf name of the generated "clientset" directory. |
| # |
| # --versioned-name <string = "versioned"> |
| # An optional override for the leaf name of the generated |
| # "<clientset>/versioned" directory. |
| # |
| # --with-applyconfig |
| # Enables generation of applyconfiguration files. |
| # |
| # --applyconfig-name <string = "applyconfiguration"> |
| # An optional override for the leaf name of the generated "applyconfiguration" directory. |
| # |
| # --applyconfig-externals <string = ""> |
| # An optional list of comma separated external apply configurations locations |
| # in <type-package>.<type-name>:<applyconfiguration-package> form. |
| # |
| # --with-watch |
| # Enables generation of listers and informers for APIs which support WATCH. |
| # |
| # --listers-name <string = "listers"> |
| # An optional override for the leaf name of the generated "listers" directory. |
| # |
| # --informers-name <string = "informers"> |
| # An optional override for the leaf name of the generated "informers" directory. |
| # |
| # --plural-exceptions <string = ""> |
| # An optional list of comma separated plural exception definitions in Type:PluralizedType form. |
| # |
| function kube::codegen::gen_client() { |
| local in_dir="" |
| local one_input_api="" |
| local out_dir="" |
| local out_pkg="" |
| local clientset_subdir="clientset" |
| local clientset_versioned_name="versioned" |
| local applyconfig="false" |
| local applyconfig_subdir="applyconfiguration" |
| local applyconfig_external="" |
| local applyconfig_openapi_schema="" |
| local watchable="false" |
| local listers_subdir="listers" |
| local informers_subdir="informers" |
| local boilerplate="${KUBE_CODEGEN_ROOT}/hack/boilerplate.go.txt" |
| local plural_exceptions="" |
| local v="${KUBE_VERBOSE:-0}" |
| |
| while [ "$#" -gt 0 ]; do |
| case "$1" in |
| "--one-input-api") |
| one_input_api="/$2" |
| shift 2 |
| ;; |
| "--output-dir") |
| out_dir="$2" |
| shift 2 |
| ;; |
| "--output-pkg") |
| out_pkg="$2" |
| shift 2 |
| ;; |
| "--boilerplate") |
| boilerplate="$2" |
| shift 2 |
| ;; |
| "--clientset-name") |
| clientset_subdir="$2" |
| shift 2 |
| ;; |
| "--versioned-name") |
| clientset_versioned_name="$2" |
| shift 2 |
| ;; |
| "--with-applyconfig") |
| applyconfig="true" |
| shift |
| ;; |
| "--applyconfig-name") |
| applyconfig_subdir="$2" |
| shift 2 |
| ;; |
| "--applyconfig-externals") |
| applyconfig_external="$2" |
| shift 2 |
| ;; |
| "--applyconfig-openapi-schema") |
| applyconfig_openapi_schema="$2" |
| shift 2 |
| ;; |
| "--with-watch") |
| watchable="true" |
| shift |
| ;; |
| "--listers-name") |
| listers_subdir="$2" |
| shift 2 |
| ;; |
| "--informers-name") |
| informers_subdir="$2" |
| shift 2 |
| ;; |
| "--plural-exceptions") |
| plural_exceptions="$2" |
| shift 2 |
| ;; |
| *) |
| if [[ "$1" =~ ^-- ]]; then |
| echo "unknown argument: $1" >&2 |
| return 1 |
| fi |
| if [ -n "$in_dir" ]; then |
| echo "too many arguments: $1 (already have $in_dir)" >&2 |
| return 1 |
| fi |
| in_dir="$1" |
| shift |
| ;; |
| esac |
| done |
| |
| if [ -z "${in_dir}" ]; then |
| echo "input-dir argument is required" >&2 |
| return 1 |
| fi |
| if [ -z "${out_dir}" ]; then |
| echo "--output-dir is required" >&2 |
| return 1 |
| fi |
| if [ -z "${out_pkg}" ]; then |
| echo "--output-pkg is required" >&2 |
| fi |
| |
| mkdir -p "${out_dir}" |
| |
| ( |
| # To support running this from anywhere, first cd into this directory, |
| # and then install with forced module mode on and fully qualified name. |
| cd "${KUBE_CODEGEN_ROOT}" |
| BINS=( |
| applyconfiguration-gen |
| client-gen |
| informer-gen |
| lister-gen |
| ) |
| # shellcheck disable=2046 # printf word-splitting is intentional |
| GO111MODULE=on go install $(printf "k8s.io/code-generator/cmd/%s@v0.30.5 " "${BINS[@]}") |
| ) |
| # Go installs in $GOBIN if defined, and $GOPATH/bin otherwise |
| gobin="${GOBIN:-$(go env GOPATH)/bin}" |
| |
| local group_versions=() |
| local input_pkgs=() |
| while read -r dir; do |
| pkg="$(cd "${dir}" && GO111MODULE=on go list -find .)" |
| leaf="$(basename "${dir}")" |
| if grep -E -q '^v[0-9]+((alpha|beta)[0-9]+)?$' <<< "${leaf}"; then |
| input_pkgs+=("${pkg}") |
| |
| dir2="$(dirname "${dir}")" |
| leaf2="$(basename "${dir2}")" |
| group_versions+=("${leaf2}/${leaf}") |
| fi |
| done < <( |
| ( kube::codegen::internal::grep -l --null \ |
| -e '^\s*//\s*+genclient' \ |
| -r "${in_dir}${one_input_api}" \ |
| --include '*.go' \ |
| || true \ |
| ) | while read -r -d $'\0' F; do dirname "${F}"; done \ |
| | LC_ALL=C sort -u |
| ) |
| |
| if [ "${#group_versions[@]}" == 0 ]; then |
| return 0 |
| fi |
| |
| applyconfig_pkg="" # set this for later use, iff enabled |
| if [ "${applyconfig}" == "true" ]; then |
| applyconfig_pkg="${out_pkg}/${applyconfig_subdir}" |
| |
| echo "Generating applyconfig code for ${#input_pkgs[@]} targets" |
| |
| ( kube::codegen::internal::grep -l --null \ |
| -e '^// Code generated by applyconfiguration-gen. DO NOT EDIT.$' \ |
| -r "${out_dir}/${applyconfig_subdir}" \ |
| --include '*.go' \ |
| || true \ |
| ) | xargs -0 rm -f |
| |
| "${gobin}/applyconfiguration-gen" \ |
| -v "${v}" \ |
| --go-header-file "${boilerplate}" \ |
| --output-dir "${out_dir}/${applyconfig_subdir}" \ |
| --output-pkg "${applyconfig_pkg}" \ |
| --external-applyconfigurations "${applyconfig_external}" \ |
| --openapi-schema "${applyconfig_openapi_schema}" \ |
| "${input_pkgs[@]}" |
| fi |
| |
| echo "Generating client code for ${#group_versions[@]} targets" |
| |
| ( kube::codegen::internal::grep -l --null \ |
| -e '^// Code generated by client-gen. DO NOT EDIT.$' \ |
| -r "${out_dir}/${clientset_subdir}" \ |
| --include '*.go' \ |
| || true \ |
| ) | xargs -0 rm -f |
| |
| local inputs=() |
| for arg in "${group_versions[@]}"; do |
| inputs+=("--input" "$arg") |
| done |
| "${gobin}/client-gen" \ |
| -v "${v}" \ |
| --go-header-file "${boilerplate}" \ |
| --output-dir "${out_dir}/${clientset_subdir}" \ |
| --output-pkg "${out_pkg}/${clientset_subdir}" \ |
| --clientset-name "${clientset_versioned_name}" \ |
| --apply-configuration-package "${applyconfig_pkg}" \ |
| --input-base "$(cd "${in_dir}" && pwd -P)" `# must be absolute path or Go import path"` \ |
| --plural-exceptions "${plural_exceptions}" \ |
| "${inputs[@]}" |
| |
| if [ "${watchable}" == "true" ]; then |
| echo "Generating lister code for ${#input_pkgs[@]} targets" |
| |
| ( kube::codegen::internal::grep -l --null \ |
| -e '^// Code generated by lister-gen. DO NOT EDIT.$' \ |
| -r "${out_dir}/${listers_subdir}" \ |
| --include '*.go' \ |
| || true \ |
| ) | xargs -0 rm -f |
| |
| "${gobin}/lister-gen" \ |
| -v "${v}" \ |
| --go-header-file "${boilerplate}" \ |
| --output-dir "${out_dir}/${listers_subdir}" \ |
| --output-pkg "${out_pkg}/${listers_subdir}" \ |
| --plural-exceptions "${plural_exceptions}" \ |
| "${input_pkgs[@]}" |
| |
| echo "Generating informer code for ${#input_pkgs[@]} targets" |
| |
| ( kube::codegen::internal::grep -l --null \ |
| -e '^// Code generated by informer-gen. DO NOT EDIT.$' \ |
| -r "${out_dir}/${informers_subdir}" \ |
| --include '*.go' \ |
| || true \ |
| ) | xargs -0 rm -f |
| |
| "${gobin}/informer-gen" \ |
| -v "${v}" \ |
| --go-header-file "${boilerplate}" \ |
| --output-dir "${out_dir}/${informers_subdir}" \ |
| --output-pkg "${out_pkg}/${informers_subdir}" \ |
| --versioned-clientset-package "${out_pkg}/${clientset_subdir}/${clientset_versioned_name}" \ |
| --listers-package "${out_pkg}/${listers_subdir}" \ |
| --plural-exceptions "${plural_exceptions}" \ |
| "${input_pkgs[@]}" |
| fi |
| } |
| |
| # Generate register code |
| # |
| # USAGE: kube::codegen::gen_register [FLAGS] <input-dir> |
| # |
| # <input-dir> |
| # The root directory under which to search for Go files which request code to |
| # be generated. This must be a local path, not a Go package. |
| # |
| # See note at the top about package structure below that. |
| # |
| # FLAGS: |
| # |
| # --boilerplate <string = path_to_kube_codegen_boilerplate> |
| # An optional override for the header file to insert into generated files. |
| # |
| function kube::codegen::gen_register() { |
| local in_dir="" |
| local boilerplate="${KUBE_CODEGEN_ROOT}/hack/boilerplate.go.txt" |
| local v="${KUBE_VERBOSE:-0}" |
| |
| while [ "$#" -gt 0 ]; do |
| case "$1" in |
| "--boilerplate") |
| boilerplate="$2" |
| shift 2 |
| ;; |
| *) |
| if [[ "$1" =~ ^-- ]]; then |
| echo "unknown argument: $1" >&2 |
| return 1 |
| fi |
| if [ -n "$in_dir" ]; then |
| echo "too many arguments: $1 (already have $in_dir)" >&2 |
| return 1 |
| fi |
| in_dir="$1" |
| shift |
| ;; |
| esac |
| done |
| |
| if [ -z "${in_dir}" ]; then |
| echo "input-dir argument is required" >&2 |
| return 1 |
| fi |
| |
| ( |
| # To support running this from anywhere, first cd into this directory, |
| # and then install with forced module mode on and fully qualified name. |
| cd "${KUBE_CODEGEN_ROOT}" |
| BINS=( |
| register-gen |
| ) |
| # shellcheck disable=2046 # printf word-splitting is intentional |
| GO111MODULE=on go install $(printf "k8s.io/code-generator/cmd/%s@v0.30.5 " "${BINS[@]}") |
| ) |
| # Go installs in $GOBIN if defined, and $GOPATH/bin otherwise |
| gobin="${GOBIN:-$(go env GOPATH)/bin}" |
| |
| # Register |
| # |
| local input_pkgs=() |
| while read -r dir; do |
| pkg="$(cd "${dir}" && GO111MODULE=on go list -find .)" |
| input_pkgs+=("${pkg}") |
| done < <( |
| ( kube::codegen::internal::grep -l --null \ |
| -e '^\s*//\s*+groupName' \ |
| -r "${in_dir}" \ |
| --include '*.go' \ |
| || true \ |
| ) | while read -r -d $'\0' F; do dirname "${F}"; done \ |
| | LC_ALL=C sort -u |
| ) |
| |
| if [ "${#input_pkgs[@]}" != 0 ]; then |
| echo "Generating register code for ${#input_pkgs[@]} targets" |
| |
| kube::codegen::internal::findz \ |
| "${in_dir}" \ |
| -type f \ |
| -name zz_generated.register.go \ |
| | xargs -0 rm -f |
| |
| "${gobin}/register-gen" \ |
| -v "${v}" \ |
| --output-file zz_generated.register.go \ |
| --go-header-file "${boilerplate}" \ |
| "${input_pkgs[@]}" |
| fi |
| } |