Add site doc validation gate

This adds a gate which loops over all phases in all sites,
and performs an airshipctl apply --dry-run on them to ensure YAML
validity and schema adherence.  Aside from installation tasks,
the gate is run via a makefile entrypoint so that it can be
easily consumed by developers or by non-zuul CICD platforms.

Change-Id: Ie4ab246848a580ab20c3153af1e3749a27e3f770
This commit is contained in:
Matt McEuen 2020-05-27 15:43:34 -05:00
parent 3edf72eeb6
commit 958d783919
9 changed files with 312 additions and 0 deletions

View File

@ -45,6 +45,12 @@ GD_PORT ?= 8080
# Documentation location
DOCS_DIR ?= docs
# document validation options
UNAME != uname
export KIND_URL ?= https://kind.sigs.k8s.io/dl/v0.8.1/kind-$(UNAME)-amd64
KUBECTL_VERSION ?= v1.16.2
export KUBECTL_URL ?= https://storage.googleapis.com/kubernetes-release/release/${KUBECTL_VERSION}/bin/linux/amd64/kubectl
.PHONY: depend
depend:
@go mod download
@ -206,3 +212,8 @@ add-copyright:
.PHONY: check-copyright
check-copyright:
@./tools/check_copyright
# Validate YAMLs for all sites
.PHONY: validate-docs
validate-docs:
@./tools/validate_docs

View File

@ -0,0 +1,28 @@
# 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.
- hosts: primary
tasks:
- name: Ensure kubectl is present
include_role:
name: install-kubectl
- name: Ensure airshipctl is present
include_role:
name: airshipctl-systemwide-executable
- name: Validating site documents
make:
target: validate-docs
chdir: "{{ zuul.project.src_dir }}"

View File

@ -0,0 +1,46 @@
#!/bin/bash
# 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.
# Run this from the airshipctl project root
set -e
# This script builds a version of kustomize that is able to acces
# the ReplacementTransformer plugin.
# It assumes a build airshipctl binary in bin/, or if not,
# somewhere on the path.
if [ -f "bin/airshipctl" ]; then
AIRSHIPCTL="bin/airshipctl"
else
AIRSHIPCTL="$(which airshipctl)"
fi
: ${KUSTOMIZE_PLUGIN_HOME:="$HOME/.airship/kustomize-plugins"}
: ${AIRSHIP_TAG:="dev"}
# purge any previous airship plugins
rm -rf ${KUSTOMIZE_PLUGIN_HOME}/airshipit.org
# copy our plugin to the PLUGIN_ROOT, and give a kustomzie-friendly wrapper
PLUGIN_PATH=${KUSTOMIZE_PLUGIN_HOME}/airshipit.org/v1alpha1/replacementtransformer
mkdir -p ${PLUGIN_PATH}
cat > ${PLUGIN_PATH}/ReplacementTransformer <<EOF
#!/bin/bash
\$(dirname \$0)/airshipctl document plugin "\$@"
EOF
chmod +x ${PLUGIN_PATH}/ReplacementTransformer
cp -p ${AIRSHIPCTL} ${PLUGIN_PATH}/
# tell the user how to use this
echo -e "The airshipctl kustomize plugin has been installed.\nRun kustomize with:"
echo -e "KUSTOMIZE_PLUGIN_HOME=$KUSTOMIZE_PLUGIN_HOME \$GOPATH/bin/kustomize build --enable_alpha_plugins ..."

25
tools/document/get_kind.sh Executable file
View File

@ -0,0 +1,25 @@
#!/bin/bash
# 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 downloads kind, puts it in a temp directory, and prints the directory
set -e
: ${KIND_URL:="https://kind.sigs.k8s.io/dl/v0.8.1/kind-$(uname)-amd64"}
TMP=$(mktemp -d)
KIND="${TMP}/kind"
curl -sSLo ${KIND} ${KIND_URL}
chmod +x ${KIND}
echo ${TMP}

27
tools/document/start_kind.sh Executable file
View File

@ -0,0 +1,27 @@
#!/bin/bash
# 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 starts up a kubernetes cluster which is sufficient for
# assisting with tasks like `kubectl apply --dry-run` style validation
set -e
: ${KIND:="/usr/local/bin/kind"}
: ${CLUSTER:="airship"} # NB: kind prepends "kind-"
: ${KUBECONFIG:="${HOME}/.airship/kubeconfig"}
${KIND} create cluster --name ${CLUSTER} \
--kubeconfig ${KUBECONFIG}
echo "This cluster can be deleted via:"
echo "${KIND} delete cluster --name ${CLUSTER}"

View File

@ -0,0 +1,127 @@
#!/bin/bash
# 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 -e
: ${PROJECT_ROOT:=${PWD}}
: ${SITE:="test-workload"}
: ${CONTEXT:="kind-airship"}
: ${KUBECONFIG:="${HOME}/.airship/kubeconfig"}
: ${KUBECTL:="/usr/local/bin/kubectl"}
: ${KUSTOMIZE_PLUGIN_HOME:="${HOME}/.airship/kustomize-plugins"}
TMP=$(mktemp -d)
# Use the local project airshipctl binary as the default if it exists,
# otherwise use the one on the PATH
if [ -f "bin/airshipctl" ]; then
AIRSHIPCTL_DEFAULT="bin/airshipctl"
else
AIRSHIPCTL_DEFAULT="$(which airshipctl)"
fi
: ${AIRSHIPCONFIG:="${TMP}/config"}
: ${AIRSHIPKUBECONFIG:="${TMP}/kubeconfig"}
: ${AIRSHIPCTL:="${AIRSHIPCTL_DEFAULT}"}
ACTL="${AIRSHIPCTL} --airshipconf ${AIRSHIPCONFIG} --kubeconfig ${AIRSHIPKUBECONFIG}"
export KUSTOMIZE_PLUGIN_HOME
export KUBECONFIG
# TODO: use `airshipctl config` to do this once all the needed knobs are exposed
# The non-default parts are to set the targetPath and subPath appropriately,
# and to craft up cluster/contexts to avoid the need for automatic kubectl reconciliation
function generate_airshipconf {
cluster=$1
cat <<EOL > ${AIRSHIPCONFIG}
apiVersion: airshipit.org/v1alpha1
bootstrapInfo:
default:
builder:
networkConfigFileName: network-config
outputMetadataFileName: output-metadata.yaml
userDataFileName: user-data
container:
containerRuntime: docker
image: quay.io/airshipit/isogen:latest-debian_stable
volume: /srv/iso:/config
remoteDirect:
isoUrl: http://localhost:8099/debian-custom.iso
clusters:
${CONTEXT}_${cluster}:
clusterType:
${cluster}:
bootstrapInfo: default
clusterKubeconf: ${CONTEXT}_${cluster}
managementConfiguration: default
contexts:
${CONTEXT}_${cluster}:
contextKubeconf: ${CONTEXT}_${cluster}
manifest: ${CONTEXT}_${cluster}
currentContext: ${CONTEXT}_${cluster}
kind: Config
managementConfiguration:
default:
insecure: true
systemActionRetries: 30
systemRebootDelay: 30
type: redfish
manifests:
${CONTEXT}_${cluster}:
primaryRepositoryName: primary
repositories:
primary:
checkout:
branch: master
commitHash: ""
force: false
tag: ""
url: https://opendev.org/airship/treasuremap
subPath: manifests/site/${SITE}
targetPath: .
users:
${CONTEXT}_${cluster}: {}
EOL
}
# Loop over all cluster types and phases for the given site
for cluster in ephemeral target; do
# Clear out any CRDs left from testing of a previous cluster
${KUBECTL} --context ${CONTEXT} --kubeconfig ${KUBECONFIG} delete crd --all > /dev/null
if [[ -d "manifests/site/${SITE}/${cluster}" ]]; then
# Since we'll be mucking with the kubeconfig - make a copy of it and muck with the copy
cp ${KUBECONFIG} ${AIRSHIPKUBECONFIG}
# This is a big hack to work around kubeconfig reconciliation
# change the cluster name (as well as context and user) to avoid kubeconfig reconciliation
sed -i "s/${CONTEXT}/${CONTEXT}_${cluster}/" ${AIRSHIPKUBECONFIG}
generate_airshipconf ${cluster}
for phase in $(ls manifests/site/${SITE}/${cluster}| grep -v "\.yaml$"); do
echo -e "\n*** Rendering ${cluster}/${phase}"
# step 1: actually apply all crds in the phase
# TODO: will need to loop through phases in order, eventually
# e.g., load CRDs from initinfra first, so they're present when validating later phases
${ACTL} phase render ${phase} -k CustomResourceDefinition > ${TMP}/crds.yaml
if [ -s ${TMP}/crds.yaml ]; then
${KUBECTL} --context ${CONTEXT} --kubeconfig ${KUBECONFIG} apply -f ${TMP}/crds.yaml
fi
# step 2: dry-run the entire phase
${ACTL} phase apply --dry-run ${phase}
done
fi
done

39
tools/validate_docs Executable file
View File

@ -0,0 +1,39 @@
#!/usr/bin/env bash
# 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.
# The makefile entrypoint driver for document validation
# Expected to be run from the project root
set -e
# get kind
echo "Fetching kind from ${KIND_URL}..."
TMP=$(KIND_URL=${KIND_URL} ./tools/document/get_kind.sh)
export KIND=${TMP}/kind
export KUBECTL_URL
function cleanup() {
${KIND} delete cluster --name airship
rm -rf ${TMP}
}
trap cleanup EXIT
./tools/document/build_kustomize_plugin.sh
./tools/document/start_kind.sh
for site in $(ls manifests/site); do
echo -e "\nValidating site: ${site}\n****************"
SITE=${site} ./tools/document/validate_site_docs.sh
echo "Validation of site ${site} is succesful!"
done

View File

@ -45,6 +45,13 @@
- ^.*\.md$
- ^docs/.*$
- job:
name: airship-airshipctl-validate-site-docs
pre-run:
- playbooks/airship-airshipctl-deploy-docker.yaml
run: playbooks/airship-airshipctl-validate-documents.yaml
nodeset: airship-airshipctl-single-node
- job:
name: airship-airshipctl-functional-existing-k8s
pre-run: playbooks/airship-airshipctl-deploy-existing-k8s.yaml

View File

@ -22,6 +22,7 @@
- airship-airshipctl-lint-unit
- airship-airshipctl-golint
- airship-airshipctl-build-image
- airship-airshipctl-validate-site-docs
# - airship-airshipctl-functional-existing-k8s TODO: Enable this when functional tests exist, and a cluster is up
- airship-airshipctl-gate-test
- airship-airshipctl-32GB-gate-test
@ -31,6 +32,7 @@
- airship-airshipctl-lint-unit
- airship-airshipctl-lint-unit
- airship-airshipctl-build-image
- airship-airshipctl-validate-site-docs
# - airship-airshipctl-functional-existing-k8s TODO: Enable this when functional tests exist, and a cluster is up
- airship-airshipctl-gate-test
post: