diff --git a/.circleci/config.yml b/.circleci/config.yml index 0bc2afac815e..c1a2128db277 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,13 +1,16 @@ version: 2 jobs: - build: - docker: - - image: circleci/python:3.6.4 - steps: - - checkout - - run: - name: install tools - command: test/circle/install.sh - - run: - name: lint - command: test/circle/lint.sh + build: + docker: + - image: unguiculus/chart-testing + steps: + - checkout + - run: + name: environment + command: env && ls -al /testing + - run: + name: lint + command: | + git remote add k8s https://github.com/kubernetes/charts + git fetch k8s master + chart_test.sh --config test/.testenv --no-install diff --git a/.gitignore b/.gitignore index 9a7c416b0bdd..92a43e018993 100644 --- a/.gitignore +++ b/.gitignore @@ -32,4 +32,6 @@ Session.vim .netrwhist # Chart dependencies -**/charts/*.tgz \ No newline at end of file +**/charts/*.tgz + +.history diff --git a/stable/dummy/.helmignore b/stable/dummy/.helmignore new file mode 100644 index 000000000000..f0c131944441 --- /dev/null +++ b/stable/dummy/.helmignore @@ -0,0 +1,21 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*~ +# Various IDEs +.project +.idea/ +*.tmproj diff --git a/stable/dummy/Chart.yaml b/stable/dummy/Chart.yaml new file mode 100644 index 000000000000..4688ca3f156b --- /dev/null +++ b/stable/dummy/Chart.yaml @@ -0,0 +1,8 @@ +apiVersion: v1 +appVersion: "1.0" +description: A Helm chart for Kubernetes +name: dummy +version: 0.1.0 +home: https://github.com/kubernetes/charts +maintainers: + - name: unguiculus diff --git a/stable/dummy/ci/ci-values.yaml b/stable/dummy/ci/ci-values.yaml new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/stable/dummy/templates/NOTES.txt b/stable/dummy/templates/NOTES.txt new file mode 100644 index 000000000000..19a64c26d535 --- /dev/null +++ b/stable/dummy/templates/NOTES.txt @@ -0,0 +1,19 @@ +1. Get the application URL by running these commands: +{{- if .Values.ingress.enabled }} +{{- range .Values.ingress.hosts }} + http{{ if $.Values.ingress.tls }}s{{ end }}://{{ . }}{{ $.Values.ingress.path }} +{{- end }} +{{- else if contains "NodePort" .Values.service.type }} + export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ template "dummy.fullname" . }}) + export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") + echo http://$NODE_IP:$NODE_PORT +{{- else if contains "LoadBalancer" .Values.service.type }} + NOTE: It may take a few minutes for the LoadBalancer IP to be available. + You can watch the status of by running 'kubectl get svc -w {{ template "dummy.fullname" . }}' + export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ template "dummy.fullname" . }} -o jsonpath='{.status.loadBalancer.ingress[0].ip}') + echo http://$SERVICE_IP:{{ .Values.service.port }} +{{- else if contains "ClusterIP" .Values.service.type }} + export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app={{ template "dummy.name" . }},release={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") + echo "Visit http://127.0.0.1:8080 to use your application" + kubectl port-forward $POD_NAME 8080:80 +{{- end }} diff --git a/stable/dummy/templates/_helpers.tpl b/stable/dummy/templates/_helpers.tpl new file mode 100644 index 000000000000..590935a2b3aa --- /dev/null +++ b/stable/dummy/templates/_helpers.tpl @@ -0,0 +1,32 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "dummy.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "dummy.fullname" -}} +{{- if .Values.fullnameOverride -}} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- $name := default .Chart.Name .Values.nameOverride -}} +{{- if contains $name .Release.Name -}} +{{- .Release.Name | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "dummy.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} +{{- end -}} diff --git a/stable/dummy/templates/deployment.yaml b/stable/dummy/templates/deployment.yaml new file mode 100644 index 000000000000..65eb067c7e67 --- /dev/null +++ b/stable/dummy/templates/deployment.yaml @@ -0,0 +1,51 @@ +apiVersion: apps/v1beta2 +kind: Deployment +metadata: + name: {{ template "dummy.fullname" . }} + labels: + app: {{ template "dummy.name" . }} + chart: {{ template "dummy.chart" . }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} +spec: + replicas: {{ .Values.replicaCount }} + selector: + matchLabels: + app: {{ template "dummy.name" . }} + release: {{ .Release.Name }} + template: + metadata: + labels: + app: {{ template "dummy.name" . }} + release: {{ .Release.Name }} + spec: + containers: + - name: {{ .Chart.Name }} + image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + ports: + - name: http + containerPort: 80 + protocol: TCP + livenessProbe: + httpGet: + path: / + port: http + readinessProbe: + httpGet: + path: / + port: http + resources: +{{ toYaml .Values.resources | indent 12 }} + {{- with .Values.nodeSelector }} + nodeSelector: +{{ toYaml . | indent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: +{{ toYaml . | indent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: +{{ toYaml . | indent 8 }} + {{- end }} diff --git a/stable/dummy/templates/ingress.yaml b/stable/dummy/templates/ingress.yaml new file mode 100644 index 000000000000..819988c180be --- /dev/null +++ b/stable/dummy/templates/ingress.yaml @@ -0,0 +1,39 @@ +{{- if .Values.ingress.enabled -}} +{{- $fullName := include "dummy.fullname" . -}} +{{- $servicePort := .Values.service.port -}} +{{- $ingressPath := .Values.ingress.path -}} +apiVersion: extensions/v1beta1 +kind: Ingress +metadata: + name: {{ $fullName }} + labels: + app: {{ template "dummy.name" . }} + chart: {{ template "dummy.chart" . }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} +{{- with .Values.ingress.annotations }} + annotations: +{{ toYaml . | indent 4 }} +{{- end }} +spec: +{{- if .Values.ingress.tls }} + tls: + {{- range .Values.ingress.tls }} + - hosts: + {{- range .hosts }} + - {{ . }} + {{- end }} + secretName: {{ .secretName }} + {{- end }} +{{- end }} + rules: + {{- range .Values.ingress.hosts }} + - host: {{ . }} + http: + paths: + - path: {{ $ingressPath }} + backend: + serviceName: {{ $fullName }} + servicePort: http + {{- end }} +{{- end }} diff --git a/stable/dummy/templates/service.yaml b/stable/dummy/templates/service.yaml new file mode 100644 index 000000000000..2cab706655fd --- /dev/null +++ b/stable/dummy/templates/service.yaml @@ -0,0 +1,19 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ template "dummy.fullname" . }} + labels: + app: {{ template "dummy.name" . }} + chart: {{ template "dummy.chart" . }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} +spec: + type: {{ .Values.service.type }} + ports: + - port: {{ .Values.service.port }} + targetPort: http + protocol: TCP + name: http + selector: + app: {{ template "dummy.name" . }} + release: {{ .Release.Name }} diff --git a/stable/dummy/values.yaml b/stable/dummy/values.yaml new file mode 100644 index 000000000000..3834aef95253 --- /dev/null +++ b/stable/dummy/values.yaml @@ -0,0 +1,45 @@ +# Default values for dummy. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +replicaCount: 1 + +image: + repository: nginx + tag: stable + pullPolicy: IfNotPresent + +service: + type: ClusterIP + port: 80 + +ingress: + enabled: false + annotations: {} + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + path: / + hosts: + - chart-example.local + tls: [] + # - secretName: chart-example-tls + # hosts: + # - chart-example.local + +resources: {} + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + # limits: + # cpu: 100m + # memory: 128Mi + # requests: + # cpu: 100m + # memory: 128Mi + +nodeSelector: {} + +tolerations: [] + +affinity: {} diff --git a/test/.dockerignore b/test/.dockerignore new file mode 100644 index 000000000000..676decd558d5 --- /dev/null +++ b/test/.dockerignore @@ -0,0 +1,2 @@ +* +! .testenv diff --git a/test/.testenv b/test/.testenv new file mode 100644 index 000000000000..84be0fc1ec30 --- /dev/null +++ b/test/.testenv @@ -0,0 +1,17 @@ +# The name of the Git remote +REMOTE=k8s + +# The name of the Git target branch +TARGET_BRANCH=master + +# Chart directories separated by a space +CHART_DIRS="stable incubator" + +# Charts the should be skipped +EXCLUDED_CHART_DIRS= + +# Additional chart repos to add (=), separated by a space +CHART_REPOS=incubator=https://kubernetes-charts-incubator.storage.googleapis.com/ + +TIMEOUT=600 + diff --git a/test/Dockerfile b/test/Dockerfile index ed0aa4a962f4..0634cf90273f 100644 --- a/test/Dockerfile +++ b/test/Dockerfile @@ -1,4 +1,4 @@ -# Copyright 2016 The Kubernetes Authors All rights reserved. +# Copyright 2018 The Kubernetes Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -12,45 +12,24 @@ # See the License for the specific language governing permissions and # limitations under the License. -FROM debian:8.5 +FROM gcr.io/kubernetes-charts-ci/chart-testing:v1.0.0-alpha.1 -ENV CLOUDSDK_CORE_DISABLE_PROMPTS=1 \ - PATH=/opt/google-cloud-sdk/bin:$PATH \ - GOOGLE_CLOUD_SDK_VERSION=154.0.0 \ - GOOGLE_PROJECT=kubernetes-charts-ci +USER root -RUN set -x \ - && cd /opt \ - && echo 'debconf debconf/frontend select Noninteractive' | debconf-set-selections \ - && apt-get update \ - && apt-get install --no-install-recommends -y jq wget python git localepurge ca-certificates \ - && wget -q https://dl.google.com/dl/cloudsdk/channels/rapid/downloads/google-cloud-sdk-${GOOGLE_CLOUD_SDK_VERSION}-linux-x86_64.tar.gz \ - && tar zxfv google-cloud-sdk-${GOOGLE_CLOUD_SDK_VERSION}-linux-x86_64.tar.gz \ - && ./google-cloud-sdk/install.sh \ - && gcloud components install kubectl \ - && gcloud config set project ${GOOGLE_PROJECT} -RUN apt-get -y purge localepurge \ - && apt-get clean \ - && cd / \ - && rm -rf \ - /opt/google-cloud-sdk-${GOOGLE_CLOUD_SDK_VERSION}-linux-x86_64.tar.gz \ - /opt/helm-${HELM_VERSION}-linux-amd64.tar.gz \ - doc \ - man \ - info \ - locale \ - /var/lib/apt/lists/* \ - /var/log/* \ - /var/cache/debconf/* \ - common-licenses \ - ~/.bashrc \ - /etc/systemd \ - /lib/lsb \ - /lib/udev \ - /usr/share/doc/ \ - /usr/share/doc-base/ \ - /usr/share/man/ \ - /tmp/* +ENV PATH /google-cloud-sdk/bin:$PATH +ARG CLOUD_SDK_VERSION=198.0.0 +RUN curl -LO "https://dl.google.com/dl/cloudsdk/channels/rapid/downloads/google-cloud-sdk-$CLOUD_SDK_VERSION-linux-x86_64.tar.gz" && \ + tar xzf "google-cloud-sdk-$CLOUD_SDK_VERSION-linux-x86_64.tar.gz" && \ + rm "google-cloud-sdk-$CLOUD_SDK_VERSION-linux-x86_64.tar.gz" && \ + ln -s /lib /lib64 && \ + rm -rf /google-cloud-sdk/.install/.backup && \ + gcloud version -VOLUME "/src" -WORKDIR "/src" +USER testing + +RUN gcloud config set core/disable_usage_reporting true && \ + gcloud config set component_manager/disable_update_check true && \ + gcloud config set metrics/environment github_docker_image + +WORKDIR /workdir +COPY .testenv /workdir/ diff --git a/test/README.md b/test/README.md index ce88b528beb4..f97f1ee9ceec 100644 --- a/test/README.md +++ b/test/README.md @@ -27,19 +27,10 @@ The configuration of the Pull Request trigger is [in the config.json](https://gi This snippet tells Test Infra to run the [test/e2e.sh](https://github.com/kubernetes/charts/blob/master/test/e2e.sh) when testing is triggered on a pull request. The e2e.sh script will use the [Charts test image](https://github.com/kubernetes/charts/blob/master/test/Dockerfile) -to run the [test/changed.sh](https://github.com/kubernetes/charts/blob/master/test/changed.sh) script. This script +to run the [chart_test.sh](https://github.com/kubernetes-helm/chart-testing/blob/master/chart_test.sh) script. This script is the main logic for validation of a pull request. It intends to only test charts that have changed in this PR. -The logic is as follows: - -1. [Get credentials for the Kubernetes cluster used for testing.](https://github.com/kubernetes/charts/blob/master/test/changed.sh#L128) -1. [Install and initialize Helm](https://github.com/kubernetes/charts/blob/master/test/changed.sh#L143) -1. [For any charts that have changed](https://github.com/kubernetes/charts/blob/master/test/changed.sh#L161): - - Download dependent charts, if any, with `helm dep build` - - Run `helm install` in a new namespace for this PR build - - Use the [test/verify-release.sh](https://github.com/kubernetes/charts/blob/master/test/verify-release.sh) to ensure that if any pods were launched that they get to the `Running` state - - Run `helm test` on the release - - Delete the release +The testing logic has been extrated to the [chart-testing](https://github.com/kubernetes-helm/chart-testing) project. A bash library provides the required logic to lint, install, and test charts. It is provided as a Docker image and can be run by anyone on their own charts. #### Providing Custom Test Values diff --git a/test/build.sh b/test/build.sh new file mode 100755 index 000000000000..88908eb52344 --- /dev/null +++ b/test/build.sh @@ -0,0 +1,74 @@ +#!/usr/bin/env bash + +# Copyright 2018 The Kubernetes Authors. All rights reserved. +# +# 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 -o errexit +set -o nounset +set -o pipefail + +readonly IMAGE_TAG=v2.0.0-alpha.1 +readonly IMAGE_REPOSITORY="gcr.io/kubernetes-charts-ci/test-image" +readonly SCRIPT_DIR=$(dirname "$(readlink -f "$0")") + +show_help() { +cat << EOF +Usage: ${0##*/} + -h, --help Display help + -v, --verbose Display verbose output + -p, --push Push image to registry +EOF +} + +main() { + local verbose= + local push= + + while :; do + case "${1:-}" in + -h|--help) + show_help + exit + ;; + -v|--verbose) + verbose=true + ;; + -p|--push) + push=true + ;; + -?*) + printf 'WARN: Unknown option (ignored): %s\n' "$1" >&2 + ;; + *) + break + ;; + esac + + shift + done + + [[ -n "$verbose" ]] && set -o xtrace + + pushd "$SCRIPT_DIR" + + docker build --tag "$IMAGE_REPOSITORY:$IMAGE_TAG" . + + if [[ -n "$push" ]]; then + docker push "$IMAGE_REPOSITORY:$IMAGE_TAG" + fi + + popd +} + +main "$@" diff --git a/test/changed.sh b/test/changed.sh deleted file mode 100755 index 3ea5cdce0761..000000000000 --- a/test/changed.sh +++ /dev/null @@ -1,197 +0,0 @@ -#!/bin/bash -# Copyright 2016 The Kubernetes Authors All rights reserved. -# -# 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 -o errexit -set -o nounset -set -o pipefail -set -o xtrace -shopt -s nullglob - -git remote add k8s https://github.com/kubernetes/charts -git fetch k8s master - -readonly NAMESPACE="${JOB_TYPE}-${PULL_INFO}-${BUILD_ID}" -readonly CHANGED_FOLDERS=$(git diff --find-renames --name-only "$(git merge-base k8s/master HEAD)" stable/ incubator/ | awk -F/ '{ print $1"/"$2 }' | uniq) - -# Exit early if no charts have changed -if [[ -z "$CHANGED_FOLDERS" ]]; then - exit 0 -fi - -# include the semvercompare function -readonly CURRENT_DIR="$(dirname "$0")" -source "$CURRENT_DIR/semvercompare.sh" - -release_index=1 -exitCode=0 -current_release="" - -# Cleanup any releases and namespaces left over from the test -cleanup_release() { - if [[ -n "$current_release" ]]; then - - # Before reporting the logs from all pods provide a helm status for - # the release - helm status "${current_release}" || true - - # List all logs for all containers in all pods for the namespace which was - # created for this PR test run - kubectl get pods --show-all --no-headers --namespace "$NAMESPACE" | awk '{ print $1 }' | while read -r pod; do - if [[ -n "$pod" ]]; then - printf '===Details from pod %s:===\n' "$pod" - - printf '...Description of pod %s:...\n' "$pod" - kubectl describe pod --namespace "$NAMESPACE" "$pod" || true - printf '...End of description for pod %s...\n\n' "$pod" - - # There can be multiple containers within a pod. We need to iterate - # over each of those - containers=$(kubectl get pods --show-all -o jsonpath="{.spec.containers[*].name}" --namespace "$NAMESPACE" "$pod") - for container in $containers; do - printf -- '---Logs from container %s in pod %s:---\n' "$container" "$pod" - kubectl logs --namespace "$NAMESPACE" -c "$container" "$pod" || true - printf -- '---End of logs for container %s in pod %s---\n\n' "$container" "$pod" - done - - printf '===End of details for pod %s===\n' "$pod" - fi - done - - helm delete --purge "$current_release" > cleanup_log 2>&1 || true - fi -} - -# Cleanup any namespace left over from the test -cleanup_namespace() { - kubectl delete ns "$NAMESPACE" >> cleanup_log 2>&1 || true -} - -trap 'cleanup_release; cleanup_namespace' EXIT - -dosemvercompare() { - # Note, the trap and automatic exiting are disabled for the semver comparison - # because it catches its own errors. If the comparison fails exitCode is set - # to 1. So, trapping and exiting is re-enabled and then the exit is handled - trap - EXIT - set +e - semvercompare "$1" - trap 'cleanup_release; cleanup_namespace' EXIT - set -e - if [[ "$exitCode" == 1 ]]; then - exit 1 - fi -} - -test_release() { - values_file="${1:-}" - current_release="$release_name-$release_index" - release_index=$((release_index + 1)) - - if [[ -n "$values_file" ]]; then - echo "Testing chart with values file: $values_file..." - helm install --timeout 600 --name "$current_release" --namespace "$NAMESPACE" --values "$values_file" . | tee install_output - else - echo "Chart does not provide test values. Testing chart with defaults..." - helm install --timeout 600 --name "$current_release" --namespace "$NAMESPACE" . | tee install_output - fi - - "$CURRENT_DIR/verify-release.sh" "$NAMESPACE" - - kubectl get pods --namespace "$NAMESPACE" - kubectl get svc --namespace "$NAMESPACE" - kubectl get deployments --namespace "$NAMESPACE" - kubectl get endpoints --namespace "$NAMESPACE" - - helm test "$current_release" - - if [[ -n "${VERIFICATION_PAUSE:-}" ]]; then - cat install_output - sleep "$VERIFICATION_PAUSE" - fi - - cleanup_release - - # Setting the current release to none to avoid the cleanup and error - # handling for a release that no longer exists. - current_release="" -} - -if [ ! -f "${KUBECONFIG:=}" ];then - # Get credentials for test cluster - gcloud auth activate-service-account --key-file="$GOOGLE_APPLICATION_CREDENTIALS" - gcloud container clusters get-credentials jenkins --project kubernetes-charts-ci --zone us-west1-a -fi - -# Install and initialize helm/tiller -readonly HELM_URL=https://storage.googleapis.com/kubernetes-helm -readonly HELM_TARBALL=helm-v2.8.2-linux-amd64.tar.gz -readonly INCUBATOR_REPO_URL=https://kubernetes-charts-incubator.storage.googleapis.com/ - -pushd /opt - wget -q "$HELM_URL/$HELM_TARBALL" - tar xzfv "$HELM_TARBALL" - PATH="/opt/linux-amd64/:$PATH" -popd - -helm init --client-only -helm repo add incubator "$INCUBATOR_REPO_URL" - -mkdir /opt/bin -pushd /opt/bin - # Install tools to check chart versions - # Install YAML Command line reader - wget -q -O yaml https://github.com/mikefarah/yaml/releases/download/1.13.1/yaml_linux_amd64 - chmod +x yaml - - # Install SemVer testing tool - wget -q -O vert https://github.com/Masterminds/vert/releases/download/v0.1.0/vert-v0.1.0-linux-amd64 - chmod +x vert -popd -PATH="/opt/bin/:$PATH" - -# Iterate over each of the changed charts -# Install, install and delete -for directory in $CHANGED_FOLDERS; do - if [[ "$directory" == "incubator/common" ]]; then - continue - elif [[ -d "$directory" ]]; then - chart_name=$(echo "$directory" | cut -d '/' -f2) - - # A semver comparison is here as well as in the circleci tests. The circleci - # tests provide almost immediate feedback to chart authors. This test is also - # re-run right before the bot merges a PR so we can make sure the chart - # version is always incremented. - dosemvercompare "$directory" - - helm dep build "$directory" - - release_name="${chart_name:0:7}-${BUILD_ID}" - - pushd "$directory" - has_test_values= - - for values_file in ./ci/*-values.yaml; do - test_release "$values_file" - has_test_values=true - done - - if [[ -z "$has_test_values" ]]; then - test_release - fi - popd - fi -done - -cleanup_namespace diff --git a/test/circle/README.md b/test/circle/README.md deleted file mode 100644 index fee138461efa..000000000000 --- a/test/circle/README.md +++ /dev/null @@ -1,4 +0,0 @@ -# CircleCI Testing - -This directory contains scripts tailored to run on CircleCI. For more information -see the test documentation. \ No newline at end of file diff --git a/test/circle/install.sh b/test/circle/install.sh deleted file mode 100755 index 000fb29b23bc..000000000000 --- a/test/circle/install.sh +++ /dev/null @@ -1,47 +0,0 @@ -#!/bin/bash -e -# Copyright 2017 The Kubernetes Authors All rights reserved. -# -# 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. - -# Install Helm -HELM_LATEST_VERSION="v2.8.2" - -wget http://storage.googleapis.com/kubernetes-helm/helm-${HELM_LATEST_VERSION}-linux-amd64.tar.gz -tar -xvf helm-${HELM_LATEST_VERSION}-linux-amd64.tar.gz -sudo mv linux-amd64/helm /usr/local/bin -rm -f helm-${HELM_LATEST_VERSION}-linux-amd64.tar.gz -rm -rf linux-amd64 - -# Setup Helm so that it will work with helm dep commands. Only the client -# needs to be setup. In addition, the incubator repo needs to be -# available for charts that depend on it. -helm init -c -helm repo add incubator https://kubernetes-charts-incubator.storage.googleapis.com/ - -# Install A YAML Linter -# Pinning to a version for consistency -sudo pip install yamllint==1.8.1 - -# Install a Yamale. yaml schema validator -# Pinning to a version for consistency -sudo pip install yamale==1.7.0 - -# Install YAML Command line reader -wget https://github.com/mikefarah/yaml/releases/download/1.13.1/yaml_linux_amd64 -chmod +x yaml_linux_amd64 -sudo mv yaml_linux_amd64 /usr/local/bin/yaml - -# Install SemVer testing tool -wget https://github.com/Masterminds/vert/releases/download/v0.1.0/vert-v0.1.0-linux-amd64 -chmod +x vert-v0.1.0-linux-amd64 -sudo mv vert-v0.1.0-linux-amd64 /usr/local/bin/vert \ No newline at end of file diff --git a/test/circle/lint.sh b/test/circle/lint.sh deleted file mode 100755 index 7bae353cb70b..000000000000 --- a/test/circle/lint.sh +++ /dev/null @@ -1,116 +0,0 @@ -#!/bin/bash -# Copyright 2017 The Kubernetes Authors All rights reserved. -# -# 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. - -# Compare to the merge-base rather than master to limit scanning to changes -# this PR/changeset is introducing. Making sure the comparison is to the -# upstream charts repo rather than a fork. - -exitCode=0 - -# Run is a wrapper around the execution of functions. It captures non-zero exit -# codes and remembers an error happened. This enables running all the linters -# and capturing if any of them failed. -run() { - $@ - local ret=$? - if [ $ret -ne 0 ]; then - exitCode=1 - fi -} - -# Lint the Chart.yaml and values.yaml files for Helm -yamllinter() { - printf "\nLinting the Chart.yaml and values.yaml files at ${1}\n" - - # If a Chart.yaml file is present lint it. Otherwise report an error - # because one should exist - if [ -e $1/Chart.yaml ]; then - run yamllint -c test/circle/lintconf.yml $1/Chart.yaml - else - echo "Error $1/Chart.yaml file is missing" - exitCode=1 - fi - - # If a values.yaml file is present lint it. Otherwise report an error - # because one should exist - if [ -e $1/values.yaml ]; then - run yamllint -c test/circle/lintconf.yml $1/values.yaml - else - echo "Error $1/values.yaml file is missing" - exitCode=1 - fi -} - -# Validate the Chart.yaml -validate_chart_yaml() { - - run yamale -s test/circle/yaml-schemas/Chart.yaml ${1}/Chart.yaml - - echo "Validating maintainers names" - - for name in $(yaml r ${1}/Chart.yaml maintainers.[*].name|cut -d " " -f2); do - if [ $(curl -s -o /dev/null -w "%{http_code}\n" -If https://github.com/${name}) -ne 200 ]; then - echo "Error: Sorry ${name} is not a valid GitHub account. Please use a valid GitHub account to help us communicate with you in PR/issues." - exitCode=1 - fi - done -} - -# include the semvercompare function -curDir="$(dirname "$0")" -source "$curDir/../semvercompare.sh" -if [[ -z ${1} ]]; then - git remote add k8s https://github.com/kubernetes/charts - git fetch k8s master - CHANGED_FOLDERS=`git diff --find-renames --name-only $(git merge-base k8s/master HEAD) stable/ incubator/ | awk -F/ '{print $1"/"$2}' | uniq` -else - CHANGED_FOLDERS=( ${1} "" ) -fi - -# Exit early if no charts have changed -if [ -z "$CHANGED_FOLDERS" ]; then - echo "No changes to charts found" - exit 0 -fi - -for directory in ${CHANGED_FOLDERS}; do - if [ "$directory" == "incubator/common" ]; then - continue - elif [ -d $directory ]; then - printf "\nRunning helm dep build on the chart at ${directory}\n" - run helm dep build ${directory} - - printf "\nRunning helm lint on the chart at ${directory}\n" - run helm lint ${directory} - - yamllinter ${directory} - - validate_chart_yaml ${directory} - - semvercompare ${directory} - - # Check for the existence of the NOTES.txt file. This is required for charts - # in this repo. - if [ ! -f ${directory}/templates/NOTES.txt ]; then - echo "Error NOTES.txt template not found. Please create one." - echo "For more information see https://docs.helm.sh/developing_charts/#chart-license-readme-and-notes" - exitCode=1 - fi - - fi -done - -exit $exitCode - diff --git a/test/circle/lintconf.yml b/test/circle/lintconf.yml deleted file mode 100644 index 90f48c889bbc..000000000000 --- a/test/circle/lintconf.yml +++ /dev/null @@ -1,42 +0,0 @@ ---- -rules: - braces: - min-spaces-inside: 0 - max-spaces-inside: 0 - min-spaces-inside-empty: -1 - max-spaces-inside-empty: -1 - brackets: - min-spaces-inside: 0 - max-spaces-inside: 0 - min-spaces-inside-empty: -1 - max-spaces-inside-empty: -1 - colons: - max-spaces-before: 0 - max-spaces-after: 1 - commas: - max-spaces-before: 0 - min-spaces-after: 1 - max-spaces-after: 1 - comments: - require-starting-space: true - min-spaces-from-content: 2 - document-end: disable - document-start: disable # No --- to start a file - empty-lines: - max: 2 - max-start: 0 - max-end: 0 - hyphens: - max-spaces-after: 1 - indentation: - spaces: consistent - indent-sequences: whatever # - list indentation will handle both indentation and without - check-multi-line-strings: false - key-duplicates: enable - line-length: disable # Lines can be any length - new-line-at-end-of-file: enable - new-lines: - type: unix - trailing-spaces: enable - truthy: - level: warning diff --git a/test/circle/yaml-schemas/Chart.yaml b/test/circle/yaml-schemas/Chart.yaml deleted file mode 100644 index e75022365581..000000000000 --- a/test/circle/yaml-schemas/Chart.yaml +++ /dev/null @@ -1,20 +0,0 @@ -name: str() -home: str() -version: str() -appVersion: any(str(), num()) -description: str() -keywords: list(str(), required=False) -sources: list(str(), required=False) -maintainers: list(include('maintainer'), required=False) -icon: str(required=False) -engine: str(required=False) -condition: str(required=False) -tags: str(required=False) -deprecated: bool(required=False) -kubeVersion: str(required=False) -annotations: map(str(), str(), required=False) ---- -maintainer: - name: str() - email: str(required=False) - url: str(required=False) diff --git a/test/e2e.sh b/test/e2e.sh index 1f59a024bdde..485b25d86be1 100755 --- a/test/e2e.sh +++ b/test/e2e.sh @@ -1,5 +1,6 @@ -#!/bin/bash -# Copyright 2016 The Kubernetes Authors All rights reserved. +#!/usr/bin/env bash + +# Copyright 2018 The Kubernetes Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -16,40 +17,39 @@ set -o errexit set -o nounset set -o pipefail -set -o xtrace - -# TODO should we inject this. This is creating problems bumping the Docker version -IMAGE_VERSION="test-image:v1.11" -CHART_ROOT=${CHART_ROOT:-$(git rev-parse --show-toplevel)} -IMAGE_NAME=${IMAGE_NAME:-"gcr.io/kubernetes-charts-ci/${IMAGE_VERSION}"} - -VOLUMES="-v ${CHART_ROOT}:/src -v ${KUBECONFIG:=${HOME}/.kube/config}:/.kube/config" - -GKE_CREDS="" -if [ -f $HOME/.config/gcloud/application_default_credentials.json ];then - GKE_CREDS="-v $HOME/.config/gcloud/application_default_credentials.json:/service-account.json:ro" - GKE_CREDS="${GKE_CREDS} -e KUBECONFIG=/.kube/config" -elif [ -n ${GOOGLE_APPLICATION_CREDENTIALS:=} ];then - GKE_CREDS="-v ${GOOGLE_APPLICATION_CREDENTIALS}:/service-account.json:ro" -else - echo "Unable to find a suitable value for GOOGLE_APPLICATION_CREDENTIALS" - exit 1 -fi + +readonly IMAGE_TAG=v2.0.0-alpha.1 +readonly IMAGE_REPOSITORY="gcr.io/kubernetes-charts-ci/test-image" +readonly REPO_ROOT="${REPO_ROOT:-$(git rev-parse --show-toplevel)}" # Pull numbers are only available on presubmit jobs. When the tests are run as # part of a batch job (e.g., batch merge) the PULL_NUMBER is not available. Pull # numbers are useful for some debugging. When no PULL_NUMBER is supplied we build # from other info. -PULL_INFO=${PULL_NUMBER:-} +PULL_INFO="${PULL_NUMBER:-}" if [ -z "$PULL_INFO" ]; then - PULL_INFO=${PULL_BASE_SHA} + PULL_INFO="${PULL_BASE_SHA:-}" fi +readonly PULL_INFO + +main() { + git remote add k8s https://github.com/kubernetes/charts + git fetch k8s master + + local config_container_id + config_container_id=$(docker run -ti -d -v "$GOOGLE_APPLICATION_CREDENTIALS:/service-account.json" -v "$REPO_ROOT:/workdir" \ + -e "BUILD_ID=$JOB_TYPE-$PULL_INFO-$BUILD_ID" \ + "$IMAGE_REPOSITORY:$IMAGE_TAG" cat) + + # shellcheck disable=SC2064 + trap "docker rm -f $config_container_id" EXIT + + docker exec "$config_container_id" gcloud auth activate-service-account --key-file /service-account.json + docker exec "$config_container_id" gcloud container clusters get-credentials jenkins --project kubernetes-charts-ci --zone us-west1-a + docker exec "$config_container_id" kubectl cluster-info + docker exec "$config_container_id" chart_test.sh --config /workdir/test/.testenv + + echo "Done Testing!" +} -docker run ${VOLUMES} ${GKE_CREDS} \ - -e GOOGLE_APPLICATION_CREDENTIALS=/service-account.json \ - -e "JOB_TYPE=$JOB_TYPE" \ - -e "PULL_INFO=$PULL_INFO" \ - -e "BUILD_ID=$BUILD_ID" \ - -e "VERIFICATION_PAUSE=${VERIFICATION_PAUSE:=0}" \ - ${IMAGE_NAME} /src/test/changed.sh -echo "Done Testing!" +main diff --git a/test/helm-test-e2e.sh b/test/helm-test-e2e.sh index 905561fb62c7..a00f69977b01 100755 --- a/test/helm-test-e2e.sh +++ b/test/helm-test-e2e.sh @@ -1,28 +1,41 @@ #!/usr/bin/env bash +# Copyright 2018 The Kubernetes Authors. All rights reserved. +# +# 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 -o errexit set -o nounset set -o pipefail set -o xtrace # Install and initialize helm/tiller -HELM_URL=https://storage.googleapis.com/kubernetes-helm -HELM_TARBALL=helm-v2.8.2-linux-amd64.tar.gz +readonly HELM_URL=https://storage.googleapis.com/kubernetes-helm +readonly HELM_TARBALL=helm-v2.8.2-linux-amd64.tar.gz -wget -q ${HELM_URL}/${HELM_TARBALL} -P ${WORKSPACE} -tar xzfv ${WORKSPACE}/${HELM_TARBALL} -C ${WORKSPACE} +wget -q "$HELM_URL/$HELM_TARBALL" -P "$WORKSPACE" +tar xzfv "$WORKSPACE/$HELM_TARBALL" -C "$WORKSPACE" # Housekeeping +pushd "$WORKSPACE/linux-amd64" + kubectl -n kube-system create sa tiller kubectl create clusterrolebinding tiller --clusterrole cluster-admin --serviceaccount=kube-system:tiller -${WORKSPACE}/linux-amd64/helm init --service-account tiller --upgrade +./helm init --service-account tiller --upgrade +./helm repo add incubator https://kubernetes-charts-incubator.storage.googleapis.com/ -${WORKSPACE}/linux-amd64/helm repo add stable https://kubernetes-charts.storage.googleapis.com/ -${WORKSPACE}/linux-amd64/helm repo add incubator https://kubernetes-charts-incubator.storage.googleapis.com/ +popd # Run test framework -pushd . -cd $GOPATH go get github.com/ghodss/yaml -popd -go run $GOPATH/src/k8s.io/charts/test/helm-test/main.go +go run "$GOPATH/src/k8s.io/charts/test/helm-test/main.go" diff --git a/test/pr-review.sh b/test/pr-review.sh deleted file mode 100755 index 65af07175e2c..000000000000 --- a/test/pr-review.sh +++ /dev/null @@ -1,35 +0,0 @@ -#!/bin/bash -xe - -set -o errexit -set -o nounset -set -o pipefail -set -o xtrace - -usage() { - echo "Usage: $0 PR_NUMBER" 1>&2; - exit 1; -} - -if [ -z "${PULL_NUMBER}" ]; then - if [ -z "$1" ];then - usage - fi - PR_NUMBER=$1 -fi - -export VERIFICATION_PAUSE=${VERIFICATION_PAUSE:=180} - -BRANCH_NAME=pr-${PULL_NUMBER} -CURRENT_BRANCH_NAME=`git rev-parse --abbrev-ref HEAD` -if [ "${BRANCH_NAME}" = "$CURRENT_BRANCH_NAME" ];then - echo "Checking out master so that we can overwrite the current branch" - git checkout master -fi - -git fetch -f origin pull/${PULL_NUMBER}/head:${BRANCH_NAME} -git checkout ${BRANCH_NAME} -git rebase master -export BUILD_ID=0 -./test/e2e.sh -git checkout master -git branch -D ${BRANCH_NAME} diff --git a/test/publish-docker.sh b/test/publish-docker.sh deleted file mode 100755 index b498496f67de..000000000000 --- a/test/publish-docker.sh +++ /dev/null @@ -1,63 +0,0 @@ -#!/bin/bash -# Copyright 2016 The Kubernetes Authors All rights reserved. -# -# 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. -VERSION=v1.10 -CONTAINER_NAME=test-image - -usage() { - echo "Usage: $0 [-p]" 1>&2; - echo " -p PROJECT_ID" - echo " -d will deploy to gcr.io" - echo " -r REPO_IP will override gcr.io and deploy docker to local repo" - exit 1; -} - -if [ $? != 0 ] ; then usage ; fi - -while getopts "p:hd" o; do - case "${o}" in - p) - PROJECT_ID=${OPTARG} - ;; - d) - DEPLOY=true - ;; - r) - REPO_URL=${OPTARG} - ;; - h) - usage - ;; - *) - usage - ;; - esac -done -shift $((OPTIND-1)) -if [ -z "$PROJECT_ID" ]; then - usage -fi - -REPO=gcr.io/$PROJECT_ID -DOCKER="${REPO}/${CONTAINER_NAME}:${VERSION}" - -docker build -t ${DOCKER} . - -if [ "${DEPLOY}" ]; then - if [ -z $REPO_URL ]; then - gcloud docker push ${DOCKER} - else - docker push ${DOCKER} - fi -fi diff --git a/test/repo-sync.sh b/test/repo-sync.sh deleted file mode 100644 index fccaf611fb20..000000000000 --- a/test/repo-sync.sh +++ /dev/null @@ -1,59 +0,0 @@ -#!/bin/bash -xe -# Copyright 2016 The Kubernetes Authors All rights reserved. -# -# 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. - -# Setup Helm -HELM_URL=https://storage.googleapis.com/kubernetes-helm -HELM_TARBALL=helm-v2.8.2-linux-amd64.tar.gz -STABLE_REPO_URL=https://kubernetes-charts.storage.googleapis.com/ -INCUBATOR_REPO_URL=https://kubernetes-charts-incubator.storage.googleapis.com/ -wget -q ${HELM_URL}/${HELM_TARBALL} -tar xzfv ${HELM_TARBALL} -PATH=`pwd`/linux-amd64/:$PATH -helm init --client-only -helm repo add incubator ${INCUBATOR_REPO_URL} - -# Authenticate before uploading to Google Cloud Storage -cat > sa.json < /tmp/Chart.yaml 2> /dev/null) - - ## If the chart is new git cannot checkout the chart. In that case return - if [ $? -ne 0 ]; then - echo "Unable to find Chart on master. New chart detected." - return - fi - - semvercompareOldVer=`yaml r /tmp/Chart.yaml version` - semvercompareNewVer=`yaml r $1/Chart.yaml version` - - # Pre-releases may not be API compatible. So, when tools compare versions - # they often skip pre-releases. vert can force looking at pre-releases by - # adding a dash on the end followed by pre-release. -0 on the end will force - # looking for all valid pre-releases since a prerelease cannot start with a 0. - # For example, 1.2.3-0 will include looking for pre-releases. - local ret - local out - if [[ $semvercompareOldVer == *"-"* ]]; then # Found the - to denote it has a pre-release - out=$(vert ">$semvercompareOldVer" $semvercompareNewVer) - ret=$? - else - # No pre-release was found so we increment the patch version and attach a - # -0 to enable pre-releases being found. - local ov=( ${semvercompareOldVer//./ } ) # Turn the version into an array - ((ov[2]+=1)) # Increment the patch release - out=$(vert ">${ov[0]}.${ov[1]}.${ov[2]}-0" $semvercompareNewVer) - ret=$? - fi - - if [ $ret -ne 0 ]; then - echo "Error please increment the new chart version to be greater than the existing version of $semvercompareOldVer" - exitCode=1 - else - echo "New higher version $semvercompareNewVer found" - fi - - # Clean up - rm /tmp/Chart.yaml -} \ No newline at end of file diff --git a/test/verify-release.sh b/test/verify-release.sh deleted file mode 100755 index 985688d6b1fa..000000000000 --- a/test/verify-release.sh +++ /dev/null @@ -1,79 +0,0 @@ -#!/bin/bash - -set -o errexit -set -o nounset -set -o pipefail -set -o xtrace - -NAMESPACE="${1:-}" -if [[ -z "$NAMESPACE" ]];then - echo "ERROR: No namespace specified" - exit 1 -fi - -# Ensure all pods in the namespace entered a Running state -PODS_FOUND=0 -POD_RETRY_COUNT=0 -RETRY=54 -RETRY_DELAY=10 - -while (("$POD_RETRY_COUNT" < "$RETRY")); do - POD_RETRY_COUNT=$((POD_RETRY_COUNT + 1)) - POD_STATUS=$(kubectl get pods --no-headers --namespace "$NAMESPACE") - - if [[ -z "$POD_STATUS" ]];then - echo "INFO: No pods found for this release, retrying after sleep" - - sleep "$RETRY_DELAY" - continue - else - PODS_FOUND=1 - fi - - if ! echo "$POD_STATUS" | grep -v Running; then - echo "INFO: All pods entered the Running state" - - CONTAINER_RETRY_COUNT=0 - READINESS_RETRY_COUNT=0 - READINESS_RETRY_DELAY=2 - - while (("$CONTAINER_RETRY_COUNT" < "$RETRY")); do - JSON_PATH="{.items[*].status.containerStatuses[?(@.ready!=true)].name}" - UNREADY_CONTAINERS=$(kubectl get pods --namespace "$NAMESPACE" -o "jsonpath=$JSON_PATH") - - if [[ -n "$UNREADY_CONTAINERS" ]]; then - echo "INFO: Some containers are not yet ready; retrying after sleep" - - CONTAINER_RETRY_COUNT=$((CONTAINER_RETRY_COUNT + 1)) - READINESS_RETRY_COUNT=0 - - sleep "$RETRY_DELAY" - continue - else - echo "INFO: All containers are ready" - - if (("$READINESS_RETRY_COUNT" < 3)); then - echo "INFO: Double-checking readiness again" - - READINESS_RETRY_COUNT=$((READINESS_RETRY_COUNT + 1)) - - sleep "$READINESS_RETRY_DELAY" - continue - fi - - exit 0 - fi - done - else - echo "INFO: Waiting for pods to enter running state" - sleep "$RETRY_DELAY" - fi -done - -if (("$PODS_FOUND" == 0)); then - echo "WARN: No pods launched by this chart's default settings" - exit 0 -else - echo "ERROR: Some containers failed to reach the ready state" - exit 1 -fi