Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions test/OWNERS
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# The OWNERS file is used by prow to automatically merge approved PRs.

approvers:
- adrcunha
- bobcatfish
- jessiezcc
- srinivashegde86
- steuhs
28 changes: 28 additions & 0 deletions test/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Test

This directory contains tests and testing docs.

* [Unit tests](#running-unit-tests) currently reside in the codebase alongside the code they test
* [End-to-end tests](#running-end-to-end-tests)

## Running unit tests

Use `go test`:

```shell
go test -v ./pkg/...
```

## Running end-to-end tests

Simply run the `e2e-tests.sh` script. It will run the end-to-end tests against the
eventing system built from source.

If you already have the `*_OVERRIDE` environment variables set, call
the script with the `--run-tests arguments` and it will use the cluster
and run the tests.

Otherwise, calling this script without arguments will create a new cluster in
project `$PROJECT_ID`, start Elafros and the eventing system, run the
tests and delete the cluster. In this case, it's required that `$KO_DOCKER_REPO`
point to a valid writable docker repo.
232 changes: 232 additions & 0 deletions test/e2e-tests.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,232 @@
#!/bin/bash

# Copyright 2018 Google, Inc. 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.

# This script runs the end-to-end tests against the eventing
# built from source.

# If you already have the *_OVERRIDE environment variables set, call
# this script with the --run-tests arguments and it will use the cluster
# and run the tests.

# Calling this script without arguments will create a new cluster in
# project $PROJECT_ID, start elafros and the eventing system, run the
# tests and delete the cluster.
# $KO_DOCKER_REPO must point to a valid writable docker repo.

source "$(dirname $(readlink -f ${BASH_SOURCE}))/library.sh"

# Test cluster parameters and location of test files
readonly E2E_CLUSTER_NAME=eventing-e2e-cluster${BUILD_NUMBER}
readonly E2E_NETWORK_NAME=eventing-e2e-net${BUILD_NUMBER}
readonly E2E_CLUSTER_ZONE=us-central1-a
readonly E2E_CLUSTER_NODES=2
readonly E2E_CLUSTER_MACHINE=n1-standard-2
readonly TEST_RESULT_FILE=/tmp/eventing-e2e-result
readonly ISTIO_VERSION=0.6.0
readonly ELAFROS_RELEASE=https://storage.googleapis.com/elafros-releases/latest/release.yaml
export ISTIO_VERSION

# This script.
readonly SCRIPT_CANONICAL_PATH="$(readlink -f ${BASH_SOURCE})"

# Helper functions.

function teardown() {
header "Tearing down test environment"
# Free resources in GCP project.
if (( ! USING_EXISTING_CLUSTER )); then
ko delete --ignore-not-found=true -f config/
fi

# Delete images when using prow.
if (( IS_PROW )); then
echo "Images in ${KO_DOCKER_REPO}:"
gcloud container images list --repository=${KO_DOCKER_REPO}
delete_gcr_images ${KO_DOCKER_REPO}
else
restore_override_vars
fi
}

function exit_if_test_failed() {
[[ $? -eq 0 ]] && return 0
[[ -n $1 ]] && echo "ERROR: $1"
echo "***************************************"
echo "*** TEST FAILED ***"
echo "*** Start of information dump ***"
echo "***************************************"
if (( IS_PROW )) || [[ $PROJECT_ID != "" ]]; then
echo ">>> Project info:"
gcloud compute project-info describe
fi
echo ">>> All resources:"
kubectl get all --all-namespaces
echo "***************************************"
echo "*** TEST FAILED ***"
echo "*** End of information dump ***"
echo "***************************************"
exit 1
}

# Script entry point.

cd ${EVENTING_ROOT_DIR}

# Show help if bad arguments are passed.
if [[ -n $1 && $1 != "--run-tests" ]]; then
echo "usage: $0 [--run-tests]"
exit 1
fi

# No argument provided, create the test cluster.

if [[ -z $1 ]]; then
header "Creating test cluster"
# Smallest cluster required to run the end-to-end-tests
CLUSTER_CREATION_ARGS=(
--gke-create-args="--enable-autoscaling --min-nodes=1 --max-nodes=${E2E_CLUSTER_NODES} --scopes=cloud-platform"
--gke-shape={\"default\":{\"Nodes\":${E2E_CLUSTER_NODES}\,\"MachineType\":\"${E2E_CLUSTER_MACHINE}\"}}
--provider=gke
--deployment=gke
--gcp-node-image=cos
--cluster="${E2E_CLUSTER_NAME}"
--gcp-zone="${E2E_CLUSTER_ZONE}"
--gcp-network="${E2E_NETWORK_NAME}"
--gke-environment=prod
)
if (( ! IS_PROW )); then
CLUSTER_CREATION_ARGS+=(--gcp-project=${PROJECT_ID:?"PROJECT_ID must be set to the GCP project where the tests are run."})
else
# On prow, set bogus SSH keys for kubetest, we're not using them.
touch $HOME/.ssh/google_compute_engine.pub
touch $HOME/.ssh/google_compute_engine
fi
# Clear user and cluster variables, so they'll be set to the test cluster.
# KO_DOCKER_REPO is not touched because when running locally it must
# be a writeable docker repo.
export K8S_USER_OVERRIDE=
export K8S_CLUSTER_OVERRIDE=
# Assume test failed (see more details at the end of this script).
echo -n "1"> ${TEST_RESULT_FILE}
kubetest "${CLUSTER_CREATION_ARGS[@]}" \
--up \
--down \
--extract "v${EVENTING_GKE_VERSION}" \
--test-cmd "${SCRIPT_CANONICAL_PATH}" \
--test-cmd-args --run-tests
result="$(cat ${TEST_RESULT_FILE})"
echo "Test result code is $result"
exit $result
fi

# --run-tests passed as first argument, run the tests.

# Set the required variables if necessary.

if [[ -z ${K8S_USER_OVERRIDE} ]]; then
export K8S_USER_OVERRIDE=$(gcloud config get-value core/account)
fi

USING_EXISTING_CLUSTER=1
if [[ -z ${K8S_CLUSTER_OVERRIDE} ]]; then
USING_EXISTING_CLUSTER=0
export K8S_CLUSTER_OVERRIDE=$(kubectl config current-context)
acquire_cluster_admin_role ${K8S_USER_OVERRIDE} ${E2E_CLUSTER_NAME} ${E2E_CLUSTER_ZONE}
# Make sure we're in the default namespace
kubectl config set-context $K8S_CLUSTER_OVERRIDE --namespace=default
fi
readonly USING_EXISTING_CLUSTER

if [[ -z ${KO_DOCKER_REPO} ]]; then
export KO_DOCKER_REPO=gcr.io/$(gcloud config get-value project)/eventing-e2e-img
fi

# Start Elafros.

header "Starting Elafros"

echo "- Cluster is ${K8S_CLUSTER_OVERRIDE}"
echo "- User is ${K8S_USER_OVERRIDE}"
echo "- Docker is ${KO_DOCKER_REPO}"

trap teardown EXIT

install_ko

subheader "Fetching istio ${ISTIO_VERSION}"
rm -fr istio-${ISTIO_VERSION}
curl -L https://git.io/getLatestIstio | sh -

pushd istio-${ISTIO_VERSION}/install/kubernetes

subheader "Installing istio"
kubectl apply -f istio.yaml
wait_until_pods_running istio-system

subheader "Enabling automatic sidecar injection in Istio"
./webhook-create-signed-cert.sh \
--service istio-sidecar-injector \
--namespace istio-system \
--secret sidecar-injector-certs
kubectl apply -f istio-sidecar-injector-configmap-release.yaml
cat ./istio-sidecar-injector.yaml | \
./webhook-patch-ca-bundle.sh > istio-sidecar-injector-with-ca-bundle.yaml
kubectl apply -f istio-sidecar-injector-with-ca-bundle.yaml
rm ./istio-sidecar-injector-with-ca-bundle.yaml
kubectl label namespace default istio-injection=enabled
wait_until_pods_running istio-system

popd

subheader "Installing Elafros"
# Install might fail before succeding, so we retry a few times.
# For details, see https://github.com/elafros/install/issues/13
installed=0
for i in {1..10}; do
kubectl apply -f ${ELAFROS_RELEASE} && installed=1 && break
sleep 30
done
(( installed ))
exit_if_test_failed "could not install Elafros"

wait_until_pods_running ela-system
wait_until_pods_running build-system

(( IS_PROW )) && gcr_auth

if (( USING_EXISTING_CLUSTER )); then
echo "Deleting any previous eventing instance"
ko delete --ignore-not-found=true -f config/
fi

header "Standing up Elafros Binding"
ko apply -f config/
exit_if_test_failed
wait_until_pods_running bind-system
exit_if_test_failed

# TODO: Add tests.

# kubetest teardown might fail and thus incorrectly report failure of the
# script, even if the tests pass.
# We store the real test result to return it later, ignoring any teardown
# failure in kubetest.
# TODO(adrcunha): Get rid of this workaround.
echo -n "0"> ${TEST_RESULT_FILE}
echo "**************************************"
echo "*** ALL TESTS PASSED ***"
echo "**************************************"
exit 0
122 changes: 122 additions & 0 deletions test/library.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
#!/bin/bash

# Copyright 2018 Google, Inc. 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.

# This is a collection of useful bash functions and constants, intended
# to be used in test scripts and the like. It doesn't do anything when
# called from command line.

# Default GKE version to be used with eventing
readonly EVENTING_GKE_VERSION=1.9.6-gke.1

# Useful environment variables
[[ -n "${PROW_JOB_ID}" ]] && IS_PROW=1 || IS_PROW=0
readonly IS_PROW
readonly EVENTING_ROOT_DIR="$(dirname $(readlink -f ${BASH_SOURCE}))/.."
readonly OUTPUT_GOBIN="${EVENTING_ROOT_DIR}/_output/bin"

# Copy of *_OVERRIDE variables
readonly OG_DOCKER_REPO="${DOCKER_REPO_OVERRIDE}"
readonly OG_K8S_CLUSTER="${K8S_CLUSTER_OVERRIDE}"
readonly OG_K8S_USER="${K8S_USER_OVERRIDE}"
readonly OG_KO_DOCKER_REPO="${KO_DOCKER_REPO}"

# Returns a UUID
function uuid() {
# uuidgen is not available in kubekins images
cat /proc/sys/kernel/random/uuid
}

# Simple header for logging purposes.
function header() {
echo "================================================="
echo ${1^^}
echo "================================================="
}

# Simple subheader for logging purposes.
function subheader() {
echo "-------------------------------------------------"
echo $1
echo "-------------------------------------------------"
}

# Restores the *_OVERRIDE variables to their original value.
function restore_override_vars() {
export DOCKER_REPO_OVERRIDE="${OG_DOCKER_REPO}"
export K8S_CLUSTER_OVERRIDE="${OG_K8S_CLUSTER}"
export K8S_USER_OVERRIDE="${OG_K8S_CLUSTER}"
export KO_DOCKER_REPO="${OG_KO_DOCKER_REPO}"
}

# Waits until all pods are running in the given namespace.
# Parameters: $1 - namespace.
function wait_until_pods_running() {
echo -n "Waiting until all pods in namespace $1 are up"
for i in {1..150}; do # timeout after 5 minutes
local pods="$(kubectl get pods -n $1 | grep -v NAME)"
local not_running=$(echo "${pods}" | grep -v Running | wc -l)
if [[ -n "${pods}" && ${not_running} == 0 ]]; then
echo -e "\nAll pods are up:"
kubectl get pods -n $1
return 0
fi
echo -n "."
sleep 2
done
echo -e "\n\nERROR: timeout waiting for pods to come up"
kubectl get pods -n $1
return 1
}

# Sets the given user as cluster admin.
# Parameters: $1 - user
# $2 - cluster name
# $3 - cluster zone
function acquire_cluster_admin_role() {
# Get the password of the admin and use it, as the service account (or the user)
# might not have the necessary permission.
local password=$(gcloud --format="value(masterAuth.password)" \
container clusters describe $2 --zone=$3)
kubectl --username=admin --password=$password \
create clusterrolebinding cluster-admin-binding \
--clusterrole=cluster-admin \
--user=$1
}

# Authenticates the current user to GCR in the current project.
function gcr_auth() {
echo "Authenticating to GCR"
# kubekins-e2e images lack docker-credential-gcr, install it manually.
# TODO(adrcunha): Remove this step once docker-credential-gcr is available.
gcloud components install docker-credential-gcr
docker-credential-gcr configure-docker
echo "Successfully authenticated"
}

# Installs ko in $OUTPUT_GOBIN
function install_ko() {
GOBIN="${OUTPUT_GOBIN}" go install ./vendor/github.com/google/go-containerregistry/cmd/ko
}

# Runs ko; prefers using the one installed by install_ko().
# Parameters: $1..$n - arguments to ko
function ko() {
if [[ -e "${OUTPUT_GOBIN}/ko" ]]; then
"${OUTPUT_GOBIN}/ko" $@
else
ko $@
fi
}
Loading