| #!/usr/bin/env bash |
| |
| # Copyright 2016 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. |
| |
| # Script to fetch latest openapi spec. |
| # Puts the updated spec at api/openapi-spec/ |
| |
| set -o errexit |
| set -o nounset |
| set -o pipefail |
| |
| KUBE_ROOT=$(dirname "${BASH_SOURCE[0]}")/.. |
| DISCOVERY_ROOT_DIR="${KUBE_ROOT}/api/discovery" |
| OPENAPI_ROOT_DIR="${KUBE_ROOT}/api/openapi-spec" |
| source "${KUBE_ROOT}/hack/lib/init.sh" |
| |
| kube::util::require-jq |
| kube::golang::setup_env |
| kube::etcd::install |
| |
| # We need to call `make` here because that includes all of the compile and link |
| # flags that we use for a production build, which we need for this script. |
| make -C "${KUBE_ROOT}" WHAT=cmd/kube-apiserver |
| |
| function cleanup() |
| { |
| if [[ -n ${APISERVER_PID-} ]]; then |
| kill "${APISERVER_PID}" 1>&2 2>/dev/null |
| wait "${APISERVER_PID}" || true |
| fi |
| unset APISERVER_PID |
| |
| kube::etcd::cleanup |
| |
| kube::log::status "Clean up complete" |
| } |
| |
| trap cleanup EXIT SIGINT |
| |
| TMP_DIR=${TMP_DIR:-$(kube::realpath "$(mktemp -d -t "$(basename "$0").XXXXXX")")} |
| ETCD_HOST=${ETCD_HOST:-127.0.0.1} |
| ETCD_PORT=${ETCD_PORT:-2379} |
| API_PORT=${API_PORT:-8050} |
| API_HOST=${API_HOST:-127.0.0.1} |
| API_LOGFILE=${API_LOGFILE:-${TMP_DIR}/openapi-api-server.log} |
| |
| kube::etcd::start |
| |
| echo "dummy_token,admin,admin" > "${TMP_DIR}/tokenauth.csv" |
| |
| # setup envs for TokenRequest required flags |
| SERVICE_ACCOUNT_LOOKUP=${SERVICE_ACCOUNT_LOOKUP:-true} |
| SERVICE_ACCOUNT_KEY=${SERVICE_ACCOUNT_KEY:-${TMP_DIR}/kube-serviceaccount.key} |
| # Generate ServiceAccount key if needed |
| if [[ ! -f "${SERVICE_ACCOUNT_KEY}" ]]; then |
| mkdir -p "$(dirname "${SERVICE_ACCOUNT_KEY}")" |
| openssl genrsa -out "${SERVICE_ACCOUNT_KEY}" 2048 2>/dev/null |
| fi |
| |
| # Start kube-apiserver |
| # omit enums from static openapi snapshots used to generate clients until #109177 is resolved |
| # TODO(aojea) remove ConsistentListFromCache after https://issues.k8s.io/123674 |
| kube::log::status "Starting kube-apiserver" |
| kube-apiserver \ |
| --bind-address="${API_HOST}" \ |
| --secure-port="${API_PORT}" \ |
| --etcd-servers="http://${ETCD_HOST}:${ETCD_PORT}" \ |
| --advertise-address="10.10.10.10" \ |
| --cert-dir="${TMP_DIR}/certs" \ |
| --feature-gates=AllAlpha=true,OpenAPIEnums=false,ConsistentListFromCache=false \ |
| --runtime-config="api/all=true" \ |
| --token-auth-file="${TMP_DIR}/tokenauth.csv" \ |
| --authorization-mode=RBAC \ |
| --service-account-key-file="${SERVICE_ACCOUNT_KEY}" \ |
| --service-account-lookup="${SERVICE_ACCOUNT_LOOKUP}" \ |
| --service-account-issuer="https://kubernetes.default.svc" \ |
| --service-account-signing-key-file="${SERVICE_ACCOUNT_KEY}" \ |
| --v=2 \ |
| --service-cluster-ip-range="10.0.0.0/24" >"${API_LOGFILE}" 2>&1 & |
| APISERVER_PID=$! |
| |
| if ! kube::util::wait_for_url "https://${API_HOST}:${API_PORT}/healthz" "apiserver: "; then |
| kube::log::error "Here are the last 10 lines from kube-apiserver (${API_LOGFILE})" |
| kube::log::error "=== BEGIN OF LOG ===" |
| tail -10 "${API_LOGFILE}" >&2 || : |
| kube::log::error "=== END OF LOG ===" |
| exit 1 |
| fi |
| |
| kube::log::status "Updating aggregated discovery" |
| |
| rm -fr "${DISCOVERY_ROOT_DIR}" |
| mkdir -p "${DISCOVERY_ROOT_DIR}" |
| curl -kfsS -H 'Authorization: Bearer dummy_token' -H 'Accept: application/json;g=apidiscovery.k8s.io;v=v2beta1;as=APIGroupDiscoveryList' "https://${API_HOST}:${API_PORT}/apis" | jq -S . > "${DISCOVERY_ROOT_DIR}/aggregated_v2beta1.json" |
| |
| kube::log::status "Updating " "${OPENAPI_ROOT_DIR} for OpenAPI v2" |
| |
| rm -f "${OPENAPI_ROOT_DIR}/swagger.json" |
| curl -w "\n" -kfsS -H 'Authorization: Bearer dummy_token' \ |
| "https://${API_HOST}:${API_PORT}/openapi/v2" \ |
| | jq -S '.info.version="unversioned"' \ |
| > "${OPENAPI_ROOT_DIR}/swagger.json" |
| |
| kube::log::status "Updating " "${OPENAPI_ROOT_DIR}/v3 for OpenAPI v3" |
| |
| mkdir -p "${OPENAPI_ROOT_DIR}/v3" |
| # clean up folder, note that some files start with dot like |
| # ".well-known__openid-configuration_openapi.json" |
| rm -r "${OPENAPI_ROOT_DIR}"/v3/{*,.*} || true |
| |
| rm -rf "${OPENAPI_ROOT_DIR}/v3/*" |
| curl -w "\n" -kfsS -H 'Authorization: Bearer dummy_token' \ |
| "https://${API_HOST}:${API_PORT}/openapi/v3" \ |
| | jq -r '.paths | to_entries | .[].key' \ |
| | while read -r group; do |
| kube::log::status "Updating OpenAPI spec and discovery for group ${group}" |
| OPENAPI_FILENAME="${group}_openapi.json" |
| OPENAPI_FILENAME_ESCAPED="${OPENAPI_FILENAME//\//__}" |
| OPENAPI_PATH="${OPENAPI_ROOT_DIR}/v3/${OPENAPI_FILENAME_ESCAPED}" |
| curl -w "\n" -kfsS -H 'Authorization: Bearer dummy_token' \ |
| "https://${API_HOST}:${API_PORT}/openapi/v3/{$group}" \ |
| | jq -S '.info.version="unversioned"' \ |
| > "$OPENAPI_PATH" |
| |
| if [[ "${group}" == "api"* ]]; then |
| DISCOVERY_FILENAME="${group}.json" |
| DISCOVERY_FILENAME_ESCAPED="${DISCOVERY_FILENAME//\//__}" |
| DISCOVERY_PATH="${DISCOVERY_ROOT_DIR}/${DISCOVERY_FILENAME_ESCAPED}" |
| curl -kfsS -H 'Authorization: Bearer dummy_token' "https://${API_HOST}:${API_PORT}/{$group}" | jq -S . > "$DISCOVERY_PATH" |
| fi |
| done |
| |
| kube::log::status "SUCCESS" |
| |
| # ex: ts=2 sw=2 et filetype=sh |