From 6ceaa5173f3c1b7f0d2bd8d1dfeff2aac30faebf Mon Sep 17 00:00:00 2001 From: James Munnelly Date: Mon, 10 Sep 2018 23:01:14 +0100 Subject: [PATCH] Add Kubernetes codegen Bazel rules Signed-off-by: James Munnelly --- hack/BUILD.bazel | 25 ++++++ hack/update-codegen.sh | 30 +++++-- hack/verify-codegen.sh | 29 +++--- third_party/BUILD.bazel | 1 + third_party/k8s.io/code-generator/BUILD.bazel | 63 +++++++++++++ .../k8s.io/code-generator/generate-groups.sh | 89 +++++++++++++++++++ 6 files changed, 220 insertions(+), 17 deletions(-) create mode 100644 third_party/k8s.io/code-generator/BUILD.bazel create mode 100755 third_party/k8s.io/code-generator/generate-groups.sh diff --git a/hack/BUILD.bazel b/hack/BUILD.bazel index 21fddc595..7ec4d98d4 100644 --- a/hack/BUILD.bazel +++ b/hack/BUILD.bazel @@ -1,5 +1,7 @@ package(default_visibility = ["//visibility:public"]) +# General repo verification targets + py_test( name = "verify-boilerplate", srcs = ["verify_boilerplate.py"], @@ -26,6 +28,8 @@ sh_test( tags = ["lint"], ) +# Bazel file generation rules + sh_binary( name = "update-bazel", srcs = ["update-bazel.sh"], @@ -67,6 +71,27 @@ sh_test( tags = ["manual"], ) +# Kubernetes codegen rules + +sh_binary( + name = "update-codegen", + srcs = ["update-codegen.sh"], + data = [ + "//hack/boilerplate:all-srcs", + "//third_party/k8s.io/code-generator:generate-groups", + "//third_party/k8s.io/code-generator:openapi-gen" + ], +) + +sh_test( + name = "verify-codegen", + srcs = ["verify-codegen.sh"], + data = [ + ":update-codegen", + "//:all-srcs", + ], +) + filegroup( name = "package-srcs", srcs = glob(["**"]), diff --git a/hack/update-codegen.sh b/hack/update-codegen.sh index a2e962ad1..c4943f757 100755 --- a/hack/update-codegen.sh +++ b/hack/update-codegen.sh @@ -14,17 +14,35 @@ # See the License for the specific language governing permissions and # limitations under the License. -# The only argument this script should ever be called with is '--verify-only' - set -o errexit set -o nounset set -o pipefail -SCRIPT_ROOT=$(dirname "${BASH_SOURCE}")/.. -CODEGEN_PKG=${CODEGEN_PKG:-$(CDPATH='' cd "${SCRIPT_ROOT}"; ls -d -1 ./vendor/k8s.io/code-generator 2>/dev/null || echo ../code-generator)} +# This script should be run via `bazel run //hack:update-bazel` +REPO_ROOT=${BUILD_WORKSPACE_DIRECTORY:-"$(cd "$(dirname "$0")" && pwd -P)"/..} +runfiles="$(pwd)" +export PATH="${runfiles}/third_party/k8s.io/code-generator:${runfiles}/hack:${runfiles}/hack/bin:${PATH}" +cd "${REPO_ROOT}" -"${CODEGEN_PKG}/generate-groups.sh" "deepcopy,client,informer,lister" \ +generate-groups.sh "deepcopy,client,informer,lister" \ github.com/jetstack/cert-manager/pkg/client github.com/jetstack/cert-manager/pkg/apis \ certmanager:v1alpha1 \ --output-base "${GOPATH}/src/" \ - --go-header-file "${SCRIPT_ROOT}/hack/boilerplate/boilerplate.go.txt" + --go-header-file "${runfiles}/hack/boilerplate/boilerplate.go.txt" + +OPENAPI_PATH_SEGMENT="docs/generated/reference/openapi" +OPENAPI_OUTPUT_DIR="${REPO_ROOT}/${OPENAPI_PATH_SEGMENT}" +# Create all required directories +mkdir -p "${OPENAPI_OUTPUT_DIR}" +if [ ! -f "${OPENAPI_OUTPUT_DIR}/openapi_generated.go" ]; then + # Create a placeholder .go file to prevent issues with openapi-gen + echo "package openapi" > "${OPENAPI_OUTPUT_DIR}/openapi_generated.go" +fi + +echo "+++ Generating openapi_generated.go into 'github.com/jetstack/cert-manager/${OPENAPI_PATH_SEGMENT}'" +# Generate Golang types for OpenAPI spec +openapi-gen \ + --input-dirs github.com/jetstack/cert-manager/pkg/apis/certmanager/v1alpha1,k8s.io/apimachinery/pkg/apis/meta/v1,k8s.io/apimachinery/pkg/runtime,k8s.io/apimachinery/pkg/version \ + --output-package "github.com/jetstack/cert-manager/${OPENAPI_PATH_SEGMENT}" + +update-bazel.sh diff --git a/hack/verify-codegen.sh b/hack/verify-codegen.sh index cc72f4238..c67e6d613 100755 --- a/hack/verify-codegen.sh +++ b/hack/verify-codegen.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Copyright 2018 The Jetstack cert-manager contributors. # @@ -18,31 +18,38 @@ set -o errexit set -o nounset set -o pipefail +RULE_NAME="codegen" + SCRIPT_ROOT=$(dirname "${BASH_SOURCE}")/.. -DIFFROOT="${SCRIPT_ROOT}/pkg" -TMP_DIFFROOT="${SCRIPT_ROOT}/_tmp/pkg" -_tmp="${SCRIPT_ROOT}/_tmp" +_tmp="$(mktemp -d)" +DIFFROOT="${SCRIPT_ROOT}/" cleanup() { rm -rf "${_tmp}" } trap "cleanup" EXIT SIGINT -cleanup +# Create a fake GOPATH +export GOPATH="${_tmp}" +TMP_DIFFROOT="${GOPATH}/src/github.com/jetstack/cert-manager" mkdir -p "${TMP_DIFFROOT}" -cp -a "${DIFFROOT}"/* "${TMP_DIFFROOT}" +rsync -avvL "${DIFFROOT}"/ "${TMP_DIFFROOT}" >/dev/null +# remove __main__ directory copied to tmp +rm -Rf "${TMP_DIFFROOT}/__main__" + +cd "${TMP_DIFFROOT}" +export BUILD_WORKSPACE_DIRECTORY="$(pwd)" +"hack/update-${RULE_NAME}.sh" -"${SCRIPT_ROOT}/hack/update-codegen.sh" echo "diffing ${DIFFROOT} against freshly generated codegen" ret=0 -diff -Naupr "${DIFFROOT}" "${TMP_DIFFROOT}" || ret=$? -cp -a "${TMP_DIFFROOT}"/* "${DIFFROOT}" +diff --exclude=__main__ -Naupr "${DIFFROOT}" "${TMP_DIFFROOT}" || ret=$? if [[ $ret -eq 0 ]] then echo "${DIFFROOT} up to date." else - echo "${DIFFROOT} is out of date. Please run hack/update-codegen.sh" + echo "${DIFFROOT} is out of date. Please run 'bazel run //hack:update-${RULE_NAME}'" exit 1 -fi \ No newline at end of file +fi diff --git a/third_party/BUILD.bazel b/third_party/BUILD.bazel index f9b7ac288..b6f2e7206 100644 --- a/third_party/BUILD.bazel +++ b/third_party/BUILD.bazel @@ -12,6 +12,7 @@ filegroup( srcs = [ ":package-srcs", "//third_party/crypto/acme:all-srcs", + "//third_party/k8s.io/code-generator:all-srcs", ], tags = ["automanaged"], visibility = ["//visibility:public"], diff --git a/third_party/k8s.io/code-generator/BUILD.bazel b/third_party/k8s.io/code-generator/BUILD.bazel new file mode 100644 index 000000000..baf259aa1 --- /dev/null +++ b/third_party/k8s.io/code-generator/BUILD.bazel @@ -0,0 +1,63 @@ +licenses(["notice"]) + +sh_binary( + name = "generate-groups", + srcs = ["generate-groups.sh"], + data = [ + ":client", + ":deepcopy", + ":informer", + ":lister", + ], + visibility = ["//visibility:public"], +) + +genrule( + name = "deepcopy", + srcs = ["//vendor/k8s.io/code-generator/cmd/deepcopy-gen"], + outs = ["deepcopy-gen"], + cmd = "cp $(SRCS) $@", +) + +genrule( + name = "informer", + srcs = ["//vendor/k8s.io/code-generator/cmd/informer-gen"], + outs = ["informer-gen"], + cmd = "cp $(SRCS) $@", +) + +genrule( + name = "client", + srcs = ["//vendor/k8s.io/code-generator/cmd/client-gen"], + outs = ["client-gen"], + cmd = "cp $(SRCS) $@", +) + +genrule( + name = "lister", + srcs = ["//vendor/k8s.io/code-generator/cmd/lister-gen"], + outs = ["lister-gen"], + cmd = "cp $(SRCS) $@", +) + +genrule( + name = "openapi", + srcs = ["//vendor/k8s.io/code-generator/cmd/openapi-gen"], + outs = ["openapi-gen"], + cmd = "cp $(SRCS) $@", + visibility = ["//visibility:public"], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) diff --git a/third_party/k8s.io/code-generator/generate-groups.sh b/third_party/k8s.io/code-generator/generate-groups.sh new file mode 100755 index 000000000..bfc2646db --- /dev/null +++ b/third_party/k8s.io/code-generator/generate-groups.sh @@ -0,0 +1,89 @@ +#!/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. + +# With modifications for jetstack/cert-manager under the Apache2 license detailed +# in the repo root. + +set -o errexit +set -o nounset +set -o pipefail + +# generate-groups generates everything for a project with external types only, e.g. a project based +# on CustomResourceDefinitions. + +if [ "$#" -lt 4 ] || [ "${1}" == "--help" ]; then + cat < ... + + the generators comma separated to run (deepcopy,defaulter,client,lister,informer) or "all". + the output package name (e.g. github.com/example/project/pkg/generated). + the external types dir (e.g. github.com/example/api or github.com/example/project/pkg/apis). + the groups and their versions in the format "groupA:v1,v2 groupB:v1 groupC:v2", relative + to . + ... arbitrary flags passed to all generator binaries. + + +Examples: + $(basename $0) all github.com/example/project/pkg/client github.com/example/project/pkg/apis "foo:v1 bar:v1alpha1,v1beta1" + $(basename $0) deepcopy,client github.com/example/project/pkg/client github.com/example/project/pkg/apis "foo:v1 bar:v1alpha1,v1beta1" +EOF + exit 0 +fi + +GENS="$1" +OUTPUT_PKG="$2" +APIS_PKG="$3" +GROUPS_WITH_VERSIONS="$4" +shift 4 + +function codegen::join() { local IFS="$1"; shift; echo "$*"; } + +# enumerate group versions +FQ_APIS=() # e.g. k8s.io/api/apps/v1 +for GVs in ${GROUPS_WITH_VERSIONS}; do + IFS=: read G Vs <<<"${GVs}" + + # enumerate versions + for V in ${Vs//,/ }; do + FQ_APIS+=(${APIS_PKG}/${G}/${V}) + done +done + +# Build all generator binaries +if [ "${GENS}" = "all" ] || grep -qw "deepcopy" <<<"${GENS}"; then + echo "Generating deepcopy funcs" + deepcopy-gen --input-dirs $(codegen::join , "${FQ_APIS[@]}") -O zz_generated.deepcopy --bounding-dirs ${APIS_PKG} "$@" +fi + +if [ "${GENS}" = "all" ] || grep -qw "client" <<<"${GENS}"; then + echo "Generating clientset for ${GROUPS_WITH_VERSIONS} at ${OUTPUT_PKG}/clientset" + client-gen --clientset-name versioned --input-base "" --input $(codegen::join , "${FQ_APIS[@]}") --output-package ${OUTPUT_PKG}/clientset "$@" +fi + +if [ "${GENS}" = "all" ] || grep -qw "lister" <<<"${GENS}"; then + echo "Generating listers for ${GROUPS_WITH_VERSIONS} at ${OUTPUT_PKG}/listers" + lister-gen --input-dirs $(codegen::join , "${FQ_APIS[@]}") --output-package ${OUTPUT_PKG}/listers "$@" +fi + +if [ "${GENS}" = "all" ] || grep -qw "informer" <<<"${GENS}"; then + echo "Generating informers for ${GROUPS_WITH_VERSIONS} at ${OUTPUT_PKG}/informers" + informer-gen \ + --input-dirs $(codegen::join , "${FQ_APIS[@]}") \ + --versioned-clientset-package ${OUTPUT_PKG}/clientset/versioned \ + --listers-package ${OUTPUT_PKG}/listers \ + --output-package ${OUTPUT_PKG}/informers \ + "$@" +fi