mirror of https://github.com/k3s-io/k3s
Federation build and e2e test integration
Federation components are now buildable and e2e-testable via e2e.go.pull/6/head
parent
025b017277
commit
a092fd2dd4
|
@ -98,6 +98,7 @@ kube::build::get_docker_wrapped_binaries() {
|
||||||
kube-controller-manager,busybox
|
kube-controller-manager,busybox
|
||||||
kube-scheduler,busybox
|
kube-scheduler,busybox
|
||||||
kube-proxy,gcr.io/google_containers/debian-iptables-amd64:v3
|
kube-proxy,gcr.io/google_containers/debian-iptables-amd64:v3
|
||||||
|
federation-apiserver,busybox
|
||||||
);;
|
);;
|
||||||
"arm")
|
"arm")
|
||||||
local targets=(
|
local targets=(
|
||||||
|
@ -105,6 +106,7 @@ kube::build::get_docker_wrapped_binaries() {
|
||||||
kube-controller-manager,armel/busybox
|
kube-controller-manager,armel/busybox
|
||||||
kube-scheduler,armel/busybox
|
kube-scheduler,armel/busybox
|
||||||
kube-proxy,gcr.io/google_containers/debian-iptables-arm:v3
|
kube-proxy,gcr.io/google_containers/debian-iptables-arm:v3
|
||||||
|
federation-apiserver,armel/busybox
|
||||||
);;
|
);;
|
||||||
"arm64")
|
"arm64")
|
||||||
local targets=(
|
local targets=(
|
||||||
|
@ -112,6 +114,7 @@ kube::build::get_docker_wrapped_binaries() {
|
||||||
kube-controller-manager,aarch64/busybox
|
kube-controller-manager,aarch64/busybox
|
||||||
kube-scheduler,aarch64/busybox
|
kube-scheduler,aarch64/busybox
|
||||||
kube-proxy,gcr.io/google_containers/debian-iptables-arm64:v3
|
kube-proxy,gcr.io/google_containers/debian-iptables-arm64:v3
|
||||||
|
federation-apiserver,aarch64/busybox
|
||||||
);;
|
);;
|
||||||
"ppc64le")
|
"ppc64le")
|
||||||
local targets=(
|
local targets=(
|
||||||
|
@ -119,6 +122,7 @@ kube::build::get_docker_wrapped_binaries() {
|
||||||
kube-controller-manager,ppc64le/busybox
|
kube-controller-manager,ppc64le/busybox
|
||||||
kube-scheduler,ppc64le/busybox
|
kube-scheduler,ppc64le/busybox
|
||||||
kube-proxy,gcr.io/google_containers/debian-iptables-ppc64le:v3
|
kube-proxy,gcr.io/google_containers/debian-iptables-ppc64le:v3
|
||||||
|
federation-apiserver,ppc64le/busybox
|
||||||
);;
|
);;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
|
@ -1002,6 +1006,11 @@ function kube::release::package_full_tarball() {
|
||||||
mkdir -p "${release_stage}/third_party"
|
mkdir -p "${release_stage}/third_party"
|
||||||
cp -R "${KUBE_ROOT}/third_party/htpasswd" "${release_stage}/third_party/htpasswd"
|
cp -R "${KUBE_ROOT}/third_party/htpasswd" "${release_stage}/third_party/htpasswd"
|
||||||
|
|
||||||
|
# Include only federation/cluster and federation/manifests
|
||||||
|
mkdir "${release_stage}/federation"
|
||||||
|
cp -R "${KUBE_ROOT}/federation/cluster" "${release_stage}/federation/"
|
||||||
|
cp -R "${KUBE_ROOT}/federation/manifests" "${release_stage}/federation/"
|
||||||
|
|
||||||
cp -R "${KUBE_ROOT}/examples" "${release_stage}/"
|
cp -R "${KUBE_ROOT}/examples" "${release_stage}/"
|
||||||
cp -R "${KUBE_ROOT}/docs" "${release_stage}/"
|
cp -R "${KUBE_ROOT}/docs" "${release_stage}/"
|
||||||
cp "${KUBE_ROOT}/README.md" "${release_stage}/"
|
cp "${KUBE_ROOT}/README.md" "${release_stage}/"
|
||||||
|
|
|
@ -20,20 +20,10 @@ set -o errexit
|
||||||
set -o nounset
|
set -o nounset
|
||||||
set -o pipefail
|
set -o pipefail
|
||||||
|
|
||||||
# TODO(zmerlynn): Blech, this belongs in build/common.sh, probably,
|
|
||||||
# but common.sh sets up its readonly variables when its sourced, so
|
|
||||||
# there's a chicken/egg issue getting it there and using it for
|
|
||||||
# KUBE_GCE_RELEASE_PREFIX.
|
|
||||||
function kube::release::semantic_version() {
|
|
||||||
# This takes:
|
|
||||||
# Client Version: version.Info{Major:"1", Minor:"1+", GitVersion:"v1.1.0-alpha.0.2328+3c0a05de4a38e3", GitCommit:"3c0a05de4a38e355d147dbfb4d85bad6d2d73bb9", GitTreeState:"clean"}
|
|
||||||
# and spits back the GitVersion piece in a way that is somewhat
|
|
||||||
# resilient to the other fields changing (we hope)
|
|
||||||
${KUBE_ROOT}/cluster/kubectl.sh version -c | sed "s/, */\\
|
|
||||||
/g" | egrep "^GitVersion:" | cut -f2 -d: | cut -f2 -d\"
|
|
||||||
}
|
|
||||||
|
|
||||||
KUBE_ROOT=$(dirname "${BASH_SOURCE}")/..
|
KUBE_ROOT=$(dirname "${BASH_SOURCE}")/..
|
||||||
|
|
||||||
|
source "${KUBE_ROOT}/build/util.sh"
|
||||||
|
|
||||||
LATEST=$(kube::release::semantic_version)
|
LATEST=$(kube::release::semantic_version)
|
||||||
|
|
||||||
KUBE_GCS_NO_CACHING='n'
|
KUBE_GCS_NO_CACHING='n'
|
||||||
|
@ -44,7 +34,7 @@ KUBE_GCS_DELETE_EXISTING='y'
|
||||||
KUBE_GCS_RELEASE_PREFIX="ci/${LATEST}"
|
KUBE_GCS_RELEASE_PREFIX="ci/${LATEST}"
|
||||||
KUBE_GCS_PUBLISH_VERSION="${LATEST}"
|
KUBE_GCS_PUBLISH_VERSION="${LATEST}"
|
||||||
|
|
||||||
source "$KUBE_ROOT/build/common.sh"
|
source "${KUBE_ROOT}/build/common.sh"
|
||||||
|
|
||||||
MAX_ATTEMPTS=3
|
MAX_ATTEMPTS=3
|
||||||
attempt=0
|
attempt=0
|
||||||
|
@ -53,4 +43,13 @@ while [[ ${attempt} -lt ${MAX_ATTEMPTS} ]]; do
|
||||||
attempt=$((attempt + 1))
|
attempt=$((attempt + 1))
|
||||||
sleep 5
|
sleep 5
|
||||||
done
|
done
|
||||||
[[ ${attempt} -lt ${MAX_ATTEMPTS} ]] || exit 1
|
if [[ ! ${attempt} -lt ${MAX_ATTEMPTS} ]];then
|
||||||
|
kube::log::error "Max attempts reached. Will exit."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "${FEDERATION:-}" == "true" ]];then
|
||||||
|
source "${KUBE_ROOT}/federation/cluster/common.sh"
|
||||||
|
# Docker compatiblity
|
||||||
|
FEDERATION_IMAGE_TAG="$(kube::release::semantic_image_tag_version)" push-federated-images
|
||||||
|
fi
|
||||||
|
|
|
@ -37,6 +37,14 @@ if [[ $KUBE_RELEASE_RUN_TESTS =~ ^[yY]$ ]]; then
|
||||||
kube::build::run_build_command hack/test-integration.sh
|
kube::build::run_build_command hack/test-integration.sh
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [[ "${FEDERATION:-}" == "true" ]];then
|
||||||
|
(
|
||||||
|
source "${KUBE_ROOT}/build/util.sh"
|
||||||
|
# Write federated docker image tag to workspace
|
||||||
|
kube::release::semantic_image_tag_version > "${KUBE_ROOT}/federation/manifests/federated-image.tag"
|
||||||
|
)
|
||||||
|
fi
|
||||||
|
|
||||||
kube::build::copy_output
|
kube::build::copy_output
|
||||||
kube::release::package_tarballs
|
kube::release::package_tarballs
|
||||||
kube::release::package_hyperkube
|
kube::release::package_hyperkube
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
#!/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.
|
||||||
|
|
||||||
|
# Common utility functions for build scripts
|
||||||
|
|
||||||
|
KUBE_ROOT=$(dirname "${BASH_SOURCE}")/..
|
||||||
|
|
||||||
|
function kube::release::semantic_version() {
|
||||||
|
# This takes:
|
||||||
|
# Client Version: version.Info{Major:"1", Minor:"1+", GitVersion:"v1.1.0-alpha.0.2328+3c0a05de4a38e3", GitCommit:"3c0a05de4a38e355d147dbfb4d85bad6d2d73bb9", GitTreeState:"clean"}
|
||||||
|
# and spits back the GitVersion piece in a way that is somewhat
|
||||||
|
# resilient to the other fields changing (we hope)
|
||||||
|
${KUBE_ROOT}/cluster/kubectl.sh version -c | sed "s/, */\\
|
||||||
|
/g" | egrep "^GitVersion:" | cut -f2 -d: | cut -f2 -d\"
|
||||||
|
}
|
||||||
|
|
||||||
|
function kube::release::semantic_image_tag_version() {
|
||||||
|
printf "$(kube::release::semantic_version)" | tr + _
|
||||||
|
}
|
|
@ -38,7 +38,6 @@ KUBE_RELEASE_VERSION_REGEX="^v(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*
|
||||||
# kube::release::parse_and_validate_ci_version()
|
# kube::release::parse_and_validate_ci_version()
|
||||||
KUBE_CI_VERSION_REGEX="^v(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)-(beta|alpha)\\.(0|[1-9][0-9]*)(\\.(0|[1-9][0-9]*)\\+[-0-9a-z]*)?$"
|
KUBE_CI_VERSION_REGEX="^v(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)-(beta|alpha)\\.(0|[1-9][0-9]*)(\\.(0|[1-9][0-9]*)\\+[-0-9a-z]*)?$"
|
||||||
|
|
||||||
|
|
||||||
# Generate kubeconfig data for the created cluster.
|
# Generate kubeconfig data for the created cluster.
|
||||||
# Assumed vars:
|
# Assumed vars:
|
||||||
# KUBE_USER
|
# KUBE_USER
|
||||||
|
@ -50,12 +49,23 @@ KUBE_CI_VERSION_REGEX="^v(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)-(be
|
||||||
# If the apiserver supports bearer auth, also provide:
|
# If the apiserver supports bearer auth, also provide:
|
||||||
# KUBE_BEARER_TOKEN
|
# KUBE_BEARER_TOKEN
|
||||||
#
|
#
|
||||||
|
# If the kubeconfig context being created should NOT be set as the current context
|
||||||
|
# SECONDARY_KUBECONFIG=true
|
||||||
|
#
|
||||||
|
# To explicitly name the context being created, use OVERRIDE_CONTEXT
|
||||||
|
#
|
||||||
# The following can be omitted for --insecure-skip-tls-verify
|
# The following can be omitted for --insecure-skip-tls-verify
|
||||||
# KUBE_CERT
|
# KUBE_CERT
|
||||||
# KUBE_KEY
|
# KUBE_KEY
|
||||||
# CA_CERT
|
# CA_CERT
|
||||||
function create-kubeconfig() {
|
function create-kubeconfig() {
|
||||||
local kubectl="${KUBE_ROOT}/cluster/kubectl.sh"
|
local kubectl="${KUBE_ROOT}/cluster/kubectl.sh"
|
||||||
|
SECONDARY_KUBECONFIG=${SECONDARY_KUBECONFIG:-}
|
||||||
|
OVERRIDE_CONTEXT=${OVERRIDE_CONTEXT:-}
|
||||||
|
|
||||||
|
if [[ "$OVERRIDE_CONTEXT" != "" ]];then
|
||||||
|
CONTEXT=$OVERRIDE_CONTEXT
|
||||||
|
fi
|
||||||
|
|
||||||
export KUBECONFIG=${KUBECONFIG:-$DEFAULT_KUBECONFIG}
|
export KUBECONFIG=${KUBECONFIG:-$DEFAULT_KUBECONFIG}
|
||||||
# KUBECONFIG determines the file we write to, but it may not exist yet
|
# KUBECONFIG determines the file we write to, but it may not exist yet
|
||||||
|
@ -99,7 +109,10 @@ function create-kubeconfig() {
|
||||||
"${kubectl}" config set-credentials "${CONTEXT}" "${user_args[@]}"
|
"${kubectl}" config set-credentials "${CONTEXT}" "${user_args[@]}"
|
||||||
fi
|
fi
|
||||||
"${kubectl}" config set-context "${CONTEXT}" --cluster="${CONTEXT}" --user="${CONTEXT}"
|
"${kubectl}" config set-context "${CONTEXT}" --cluster="${CONTEXT}" --user="${CONTEXT}"
|
||||||
|
|
||||||
|
if [[ "${SECONDARY_KUBECONFIG}" != "true" ]];then
|
||||||
"${kubectl}" config use-context "${CONTEXT}" --cluster="${CONTEXT}"
|
"${kubectl}" config use-context "${CONTEXT}" --cluster="${CONTEXT}"
|
||||||
|
fi
|
||||||
|
|
||||||
# If we have a bearer token, also create a credential entry with basic auth
|
# If we have a bearer token, also create a credential entry with basic auth
|
||||||
# so that it is easy to discover the basic auth password for your cluster
|
# so that it is easy to discover the basic auth password for your cluster
|
||||||
|
|
|
@ -99,3 +99,33 @@ PROVIDER_UTILS="${KUBE_ROOT}/cluster/${KUBERNETES_PROVIDER}/util.sh"
|
||||||
if [ -f ${PROVIDER_UTILS} ]; then
|
if [ -f ${PROVIDER_UTILS} ]; then
|
||||||
source "${PROVIDER_UTILS}"
|
source "${PROVIDER_UTILS}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Federation utils
|
||||||
|
|
||||||
|
# Should NOT be called within the global scope, unless setting the desired global zone vars
|
||||||
|
# This function is currently NOT USED in the global scope
|
||||||
|
function set-federated-zone-vars {
|
||||||
|
zone="$1"
|
||||||
|
export OVERRIDE_CONTEXT="federation-e2e-${KUBERNETES_PROVIDER}-$zone"
|
||||||
|
echo "Setting zone vars to: $OVERRIDE_CONTEXT"
|
||||||
|
if [[ "$KUBERNETES_PROVIDER" == "gce" ]];then
|
||||||
|
|
||||||
|
export KUBE_GCE_ZONE="$zone"
|
||||||
|
# gcloud has a 61 character limit, and for firewall rules this
|
||||||
|
# prefix gets appended to itslef, with some extra information
|
||||||
|
# need tot keep it short
|
||||||
|
export KUBE_GCE_INSTANCE_PREFIX="${USER}-${zone}"
|
||||||
|
|
||||||
|
elif [[ "$KUBERNETES_PROVIDER" == "gke" ]];then
|
||||||
|
|
||||||
|
export CLUSTER_NAME="${USER}-${zone}"
|
||||||
|
|
||||||
|
elif [[ "$KUBERNETES_PROVIDER" == "aws" ]];then
|
||||||
|
|
||||||
|
export KUBE_AWS_ZONE="$zone"
|
||||||
|
export KUBE_AWS_INSTANCE_PREFIX="${USER}-${zone}"
|
||||||
|
else
|
||||||
|
echo "Provider \"${KUBERNETES_PROVIDER}\" is not supported"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
|
@ -118,7 +118,7 @@ if ! which /usr/libexec/cockpit-ws &>/dev/null; then
|
||||||
|
|
||||||
pushd /etc/yum.repos.d
|
pushd /etc/yum.repos.d
|
||||||
curl -OL https://copr.fedorainfracloud.org/coprs/g/cockpit/cockpit-preview/repo/fedora-23/msuchy-cockpit-preview-fedora-23.repo
|
curl -OL https://copr.fedorainfracloud.org/coprs/g/cockpit/cockpit-preview/repo/fedora-23/msuchy-cockpit-preview-fedora-23.repo
|
||||||
dnf install -y cockpit cockpit-kubernetes
|
dnf install -y cockpit cockpit-kubernetes socat ethtool
|
||||||
dnf update -y docker
|
dnf update -y docker
|
||||||
popd
|
popd
|
||||||
|
|
||||||
|
|
|
@ -83,3 +83,5 @@ add-volume-support
|
||||||
|
|
||||||
run-salt
|
run-salt
|
||||||
|
|
||||||
|
dnf install -y socat ethtool
|
||||||
|
dnf update -y docker
|
||||||
|
|
|
@ -0,0 +1,189 @@
|
||||||
|
# Copyright 2014 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.
|
||||||
|
|
||||||
|
# required:
|
||||||
|
# KUBE_ROOT: path of the root of the Kubernetes reposiitory
|
||||||
|
|
||||||
|
# optional override
|
||||||
|
# FEDERATION_IMAGE_REPO_BASE: repo which federated images are tagged under (default gcr.io/google_containers)
|
||||||
|
# FEDERATION_NAMESPACE: name of the namespace will created for the federated components in the underlying cluster.
|
||||||
|
# KUBE_PLATFORM
|
||||||
|
# KUBE_ARCH
|
||||||
|
# KUBE_BUILD_STAGE
|
||||||
|
|
||||||
|
: "${KUBE_ROOT?Must set KUBE_ROOT env var}"
|
||||||
|
|
||||||
|
FEDERATION_IMAGE_REPO_BASE=${FEDERATION_IMAGE_REPO_BASE:-'gcr.io/google_containers'}
|
||||||
|
FEDERATION_NAMESPACE=${FEDERATION_NAMESPACE:-federation-e2e}
|
||||||
|
|
||||||
|
KUBE_PLATFORM=${KUBE_PLATFORM:-linux}
|
||||||
|
KUBE_ARCH=${KUBE_ARCH:-amd64}
|
||||||
|
KUBE_BUILD_STAGE=${KUBE_BUILD_STAGE:-release-stage}
|
||||||
|
|
||||||
|
source "${KUBE_ROOT}/cluster/common.sh"
|
||||||
|
|
||||||
|
host_kubectl="${KUBE_ROOT}/cluster/kubectl.sh --namespace=${FEDERATION_NAMESPACE}"
|
||||||
|
|
||||||
|
# required:
|
||||||
|
# FEDERATION_PUSH_REPO_BASE: repo to which federated container images will be pushed
|
||||||
|
|
||||||
|
# Optional
|
||||||
|
# FEDERATION_IMAGE_TAG: reference and pull all federated images with this tag. Used for ci testing
|
||||||
|
function create-federated-api-objects {
|
||||||
|
(
|
||||||
|
: "${FEDERATION_PUSH_REPO_BASE?Must set FEDERATION_PUSH_REPO_BASE env var}"
|
||||||
|
export FEDERATION_APISERVER_DEPLOYMENT_NAME="federation-apiserver"
|
||||||
|
export FEDERATION_APISERVER_IMAGE_REPO="${FEDERATION_PUSH_REPO_BASE}/federation-apiserver"
|
||||||
|
export FEDERATION_APISERVER_IMAGE_TAG="${FEDERATION_IMAGE_TAG:-$(cat ${KUBE_ROOT}/_output/${KUBE_BUILD_STAGE}/server/${KUBE_PLATFORM}-${KUBE_ARCH}/kubernetes/server/bin/federation-apiserver.docker_tag)}"
|
||||||
|
|
||||||
|
export FEDERATION_SERVICE_CIDR=${FEDERATION_SERVICE_CIDR:-"10.10.0.0/24"}
|
||||||
|
|
||||||
|
#Only used for providers that require a nodeport service (vagrant for now)
|
||||||
|
#We will use loadbalancer services where we can
|
||||||
|
export FEDERATION_API_NODEPORT=32111
|
||||||
|
export FEDERATION_NAMESPACE
|
||||||
|
|
||||||
|
template="go run ${KUBE_ROOT}/federation/cluster/template.go"
|
||||||
|
|
||||||
|
FEDERATION_KUBECONFIG_PATH="${KUBE_ROOT}/federation/cluster/kubeconfig"
|
||||||
|
|
||||||
|
federation_kubectl="${KUBE_ROOT}/cluster/kubectl.sh --context=federated-cluster --namespace=default"
|
||||||
|
|
||||||
|
manifests_root="${KUBE_ROOT}/federation/manifests/"
|
||||||
|
|
||||||
|
$template "${manifests_root}/federation-ns.yaml" | $host_kubectl apply -f -
|
||||||
|
|
||||||
|
cleanup-federated-api-objects
|
||||||
|
|
||||||
|
export FEDERATION_API_HOST=""
|
||||||
|
export KUBE_MASTER_IP=""
|
||||||
|
if [[ "$KUBERNETES_PROVIDER" == "vagrant" ]];then
|
||||||
|
# The vagrant approach is to use a nodeport service, and point kubectl at one of the nodes
|
||||||
|
$template "${manifests_root}/federation-apiserver-nodeport-service.yaml" | $host_kubectl create -f -
|
||||||
|
node_addresses=`$host_kubectl get nodes -o=jsonpath='{.items[*].status.addresses[?(@.type=="InternalIP")].address}'`
|
||||||
|
FEDERATION_API_HOST=`printf "$node_addresses" | cut -d " " -f1`
|
||||||
|
KUBE_MASTER_IP="${FEDERATION_API_HOST}:${FEDERATION_API_NODEPORT}"
|
||||||
|
elif [[ "$KUBERNETES_PROVIDER" == "gce" || "$KUBERNETES_PROVIDER" == "gke" || "$KUBERNETES_PROVIDER" == "aws" ]];then
|
||||||
|
# any capable providers should use a loadbalancer service
|
||||||
|
# we check for ingress.ip and ingress.hostname, so should work for any loadbalancer-providing provider
|
||||||
|
# allows 30x5 = 150 seconds for loadbalancer creation
|
||||||
|
$template "${manifests_root}/federation-apiserver-lb-service.yaml" | $host_kubectl create -f -
|
||||||
|
for i in {1..30};do
|
||||||
|
echo "attempting to get federation-apiserver loadbalancer hostname ($i / 30)"
|
||||||
|
for field in ip hostname;do
|
||||||
|
FEDERATION_API_HOST=`${host_kubectl} get -o=jsonpath svc/${FEDERATION_APISERVER_DEPLOYMENT_NAME} --template '{.status.loadBalancer.ingress[*].'"${field}}"`
|
||||||
|
if [[ ! -z "${FEDERATION_API_HOST// }" ]];then
|
||||||
|
break 2
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
if [[ $i -eq 30 ]];then
|
||||||
|
echo "Could not find ingress hostname for federation-apiserver loadbalancer service"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
sleep 5
|
||||||
|
done
|
||||||
|
KUBE_MASTER_IP="${FEDERATION_API_HOST}:443"
|
||||||
|
else
|
||||||
|
echo "provider ${KUBERNETES_PROVIDER} is not (yet) supported for e2e testing"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo "Found federation-apiserver host at $FEDERATION_API_HOST"
|
||||||
|
|
||||||
|
FEDERATION_API_TOKEN="$(dd if=/dev/urandom bs=128 count=1 2>/dev/null | base64 | tr -d "=+/" | dd bs=32 count=1 2>/dev/null)"
|
||||||
|
export FEDERATION_API_KNOWN_TOKENS="${FEDERATION_API_TOKEN},admin,admin"
|
||||||
|
|
||||||
|
$template "${manifests_root}/federation-apiserver-"{deployment,secrets}".yaml" | $host_kubectl create -f -
|
||||||
|
|
||||||
|
# Don't finish provisioning until federation-apiserver pod is running
|
||||||
|
for i in {1..30};do
|
||||||
|
#TODO(colhom): in the future this needs to scale out for N pods. This assumes just one pod
|
||||||
|
phase="$($host_kubectl get -o=jsonpath pods -lapp=federated-cluster,module=federation-apiserver --template '{.items[*].status.phase}')"
|
||||||
|
echo "Waiting for federation-apiserver to be running...(phase= $phase)"
|
||||||
|
if [[ "$phase" == "Running" ]];then
|
||||||
|
echo "federation-apiserver pod is running!"
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ $i -eq 30 ]];then
|
||||||
|
echo "federation-apiserver pod is not running! giving up."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
sleep 4
|
||||||
|
done
|
||||||
|
|
||||||
|
CONTEXT=federated-cluster \
|
||||||
|
KUBE_BEARER_TOKEN="$FEDERATION_API_TOKEN" \
|
||||||
|
SECONDARY_KUBECONFIG=true \
|
||||||
|
create-kubeconfig
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
# Required
|
||||||
|
# FEDERATION_PUSH_REPO_BASE: the docker repo where federated images will be pushed
|
||||||
|
|
||||||
|
# Optional
|
||||||
|
# FEDERATION_IMAGE_TAG: push all federated images with this tag. Used for ci testing
|
||||||
|
function push-federated-images {
|
||||||
|
: "${FEDERATION_PUSH_REPO_BASE?Must set FEDERATION_PUSH_REPO_BASE env var}"
|
||||||
|
local FEDERATION_BINARIES=${FEDERATION_BINARIES:-'federation-apiserver'}
|
||||||
|
|
||||||
|
local imageFolder="${KUBE_ROOT}/_output/${KUBE_BUILD_STAGE}/server/${KUBE_PLATFORM}-${KUBE_ARCH}/kubernetes/server/bin"
|
||||||
|
|
||||||
|
if [[ ! -d "$imageFolder" ]];then
|
||||||
|
echo "${imageFolder} does not exist! Run make quick-release or make release"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
for binary in $FEDERATION_BINARIES;do
|
||||||
|
local imageFile="${imageFolder}/${binary}.tar"
|
||||||
|
|
||||||
|
if [[ ! -f "$imageFile" ]];then
|
||||||
|
echo "${imageFile} does not exist!"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Load: ${imageFile}"
|
||||||
|
# Load the image. Trust we know what it's called, as docker load provides no help there :(
|
||||||
|
docker load -q < "${imageFile}"
|
||||||
|
|
||||||
|
local srcImageTag="$(cat ${imageFolder}/${binary}.docker_tag)"
|
||||||
|
local dstImageTag="${FEDERATION_IMAGE_TAG:-$srcImageTag}"
|
||||||
|
local srcImageName="${FEDERATION_IMAGE_REPO_BASE}/${binary}:${srcImageTag}"
|
||||||
|
local dstImageName="${FEDERATION_PUSH_REPO_BASE}/${binary}:${dstImageTag}"
|
||||||
|
|
||||||
|
echo "Tag: ${srcImageName} --> ${dstImageName}"
|
||||||
|
docker tag "$srcImageName" "$dstImageName"
|
||||||
|
|
||||||
|
echo "Push: $dstImageName"
|
||||||
|
if [[ "${FEDERATION_PUSH_REPO_BASE}" == "gcr.io/"* ]];then
|
||||||
|
echo " -> GCR repository detected. Using gcloud"
|
||||||
|
gcloud docker push "$dstImageName"
|
||||||
|
else
|
||||||
|
docker push "$dstImageName"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Remove: $srcImageName"
|
||||||
|
docker rmi "$srcImageName"
|
||||||
|
|
||||||
|
if [[ "$srcImageName" != "dstImageName" ]];then
|
||||||
|
echo "Remove: $dstImageName"
|
||||||
|
docker rmi "$dstImageName"
|
||||||
|
fi
|
||||||
|
|
||||||
|
done
|
||||||
|
}
|
||||||
|
function cleanup-federated-api-objects {
|
||||||
|
$host_kubectl delete pods,svc,rc,deployment,secret -lapp=federated-cluster
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Copyright 2014 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
|
||||||
|
|
||||||
|
KUBE_ROOT=$(readlink -m $(dirname "${BASH_SOURCE}")/../../)
|
||||||
|
|
||||||
|
. ${KUBE_ROOT}/federation/cluster/common.sh
|
||||||
|
|
||||||
|
cleanup-federated-api-objects
|
||||||
|
|
||||||
|
$host_kubectl delete ns/${FEDERATION_NAMESPACE}
|
|
@ -0,0 +1,32 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Copyright 2014 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.
|
||||||
|
|
||||||
|
# Bring up a Kubernetes cluster.
|
||||||
|
#
|
||||||
|
# If the full release name (gs://<bucket>/<release>) is passed in then we take
|
||||||
|
# that directly. If not then we assume we are doing development stuff and take
|
||||||
|
# the defaults in the release config.
|
||||||
|
|
||||||
|
set -o errexit
|
||||||
|
set -o nounset
|
||||||
|
set -o pipefail
|
||||||
|
|
||||||
|
KUBE_ROOT=$(readlink -m $(dirname "${BASH_SOURCE}")/../../)
|
||||||
|
|
||||||
|
. ${KUBE_ROOT}/federation/cluster/common.sh
|
||||||
|
|
||||||
|
push-federated-images
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Copyright 2014 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
|
||||||
|
|
||||||
|
KUBE_ROOT=$(readlink -m $(dirname "${BASH_SOURCE}")/../../)
|
||||||
|
|
||||||
|
. ${KUBE_ROOT}/federation/cluster/common.sh
|
||||||
|
|
||||||
|
create-federated-api-objects
|
|
@ -0,0 +1,76 @@
|
||||||
|
/*
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
This is a simple script that makes *every* environment variable available
|
||||||
|
as a go template field of the same name
|
||||||
|
|
||||||
|
$ echo "hello world, MYVAR={{.MYVAR}}" > test.txt
|
||||||
|
$ MYVAR=foobar go run template.go test.txt
|
||||||
|
> hello world, MYVAR=foobar
|
||||||
|
|
||||||
|
If you want the base64 version of any MYVAR, simple use {{.MYVAR_BASE64}}
|
||||||
|
*/
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/base64"
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
"path"
|
||||||
|
"strings"
|
||||||
|
"text/template"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
flag.Parse()
|
||||||
|
env := make(map[string]string)
|
||||||
|
envList := os.Environ()
|
||||||
|
|
||||||
|
for i := range envList {
|
||||||
|
pieces := strings.SplitN(envList[i], "=", 2)
|
||||||
|
if len(pieces) == 2 {
|
||||||
|
env[pieces[0]] = pieces[1]
|
||||||
|
env[pieces[0]+"_BASE64"] = base64.StdEncoding.EncodeToString([]byte(pieces[1]))
|
||||||
|
} else {
|
||||||
|
fmt.Fprintf(os.Stderr, "Invalid environ found: %s\n", envList[i])
|
||||||
|
os.Exit(2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < flag.NArg(); i++ {
|
||||||
|
inpath := flag.Arg(i)
|
||||||
|
|
||||||
|
if err := templateYamlFile(env, inpath, os.Stdout); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func templateYamlFile(params map[string]string, inpath string, out io.Writer) error {
|
||||||
|
if tmpl, err := template.New(path.Base(inpath)).ParseFiles(inpath); err != nil {
|
||||||
|
return err
|
||||||
|
} else {
|
||||||
|
if err := tmpl.Execute(out, params); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_, err := out.Write([]byte("\n---\n"))
|
||||||
|
return err
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
/federated-image.tag
|
|
@ -0,0 +1,42 @@
|
||||||
|
apiVersion: extensions/v1beta1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: {{.FEDERATION_APISERVER_DEPLOYMENT_NAME}}
|
||||||
|
namespace: {{.FEDERATION_NAMESPACE}}
|
||||||
|
labels:
|
||||||
|
app: federated-cluster
|
||||||
|
spec:
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
name: federation-apiserver
|
||||||
|
labels:
|
||||||
|
app: federated-cluster
|
||||||
|
module: federation-apiserver
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: apiserver
|
||||||
|
image: {{.FEDERATION_APISERVER_IMAGE_REPO}}:{{.FEDERATION_APISERVER_IMAGE_TAG}}
|
||||||
|
command:
|
||||||
|
- /usr/local/bin/federation-apiserver
|
||||||
|
- --bind-address=0.0.0.0
|
||||||
|
- --etcd-servers=http://localhost:2379
|
||||||
|
- --service-cluster-ip-range={{.FEDERATION_SERVICE_CIDR}}
|
||||||
|
- --secure-port=443
|
||||||
|
- --advertise-address={{.FEDERATION_API_HOST}}
|
||||||
|
- --admission-control=NamespaceLifecycle,LimitRanger,SecurityContextDeny,ServiceAccount,ResourceQuota
|
||||||
|
- --token-auth-file=/srv/kubernetes/known-tokens.csv
|
||||||
|
ports:
|
||||||
|
- containerPort: 443
|
||||||
|
name: https
|
||||||
|
- containerPort: 8080
|
||||||
|
name: local
|
||||||
|
volumeMounts:
|
||||||
|
- name: federation-apiserver-secrets
|
||||||
|
mountPath: /srv/kubernetes/
|
||||||
|
readOnly: true
|
||||||
|
- name: etcd
|
||||||
|
image: quay.io/coreos/etcd:v2.3.3
|
||||||
|
volumes:
|
||||||
|
- name: federation-apiserver-secrets
|
||||||
|
secret:
|
||||||
|
secretName: federation-apiserver-secrets
|
|
@ -0,0 +1,17 @@
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: {{.FEDERATION_APISERVER_DEPLOYMENT_NAME}}
|
||||||
|
namespace: {{.FEDERATION_NAMESPACE}}
|
||||||
|
labels:
|
||||||
|
app: federated-cluster
|
||||||
|
spec:
|
||||||
|
type: LoadBalancer
|
||||||
|
selector:
|
||||||
|
app: federated-cluster
|
||||||
|
module: federation-apiserver
|
||||||
|
ports:
|
||||||
|
- name: https
|
||||||
|
protocol: TCP
|
||||||
|
port: 443
|
||||||
|
targetPort: 443
|
|
@ -0,0 +1,17 @@
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: {{.FEDERATION_APISERVER_DEPLOYMENT_NAME}}
|
||||||
|
namespace: {{.FEDERATION_NAMESPACE}}
|
||||||
|
labels:
|
||||||
|
app: federated-cluster
|
||||||
|
spec:
|
||||||
|
type: NodePort
|
||||||
|
selector:
|
||||||
|
app: federated-cluster
|
||||||
|
module: federation-apiserver
|
||||||
|
ports:
|
||||||
|
- name: https
|
||||||
|
protocol: TCP
|
||||||
|
nodePort: {{.FEDERATION_API_NODEPORT}}
|
||||||
|
port: 443
|
|
@ -0,0 +1,9 @@
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Secret
|
||||||
|
metadata:
|
||||||
|
name: federation-apiserver-secrets
|
||||||
|
labels:
|
||||||
|
app: federated-cluster
|
||||||
|
type: Opaque
|
||||||
|
data:
|
||||||
|
known-tokens.csv: {{.FEDERATION_API_KNOWN_TOKENS_BASE64}}
|
|
@ -0,0 +1,4 @@
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Namespace
|
||||||
|
metadata:
|
||||||
|
name: {{.FEDERATION_NAMESPACE}}
|
|
@ -29,4 +29,5 @@ source "${KUBE_ROOT}/cluster/kube-util.sh"
|
||||||
|
|
||||||
prepare-e2e
|
prepare-e2e
|
||||||
|
|
||||||
|
#TODO(colhom): spec and implement federated version of this
|
||||||
${KUBECTL} get nodes --no-headers | wc -l
|
${KUBECTL} get nodes --no-headers | wc -l
|
||||||
|
|
|
@ -29,4 +29,16 @@ source "${KUBE_ROOT}/cluster/kube-util.sh"
|
||||||
|
|
||||||
prepare-e2e
|
prepare-e2e
|
||||||
|
|
||||||
|
if [[ "${FEDERATION:-}" == "true" ]];then
|
||||||
|
source "${KUBE_ROOT}/federation/cluster/common.sh"
|
||||||
|
for zone in ${E2E_ZONES};do
|
||||||
|
# bring up e2e cluster
|
||||||
|
(
|
||||||
|
set-federated-zone-vars "$zone"
|
||||||
|
cleanup-federated-api-objects || echo "Couldn't cleanup federated api objects"
|
||||||
test-teardown
|
test-teardown
|
||||||
|
)
|
||||||
|
done
|
||||||
|
else
|
||||||
|
test-teardown
|
||||||
|
fi
|
||||||
|
|
|
@ -29,4 +29,19 @@ source "${KUBE_ROOT}/cluster/kube-util.sh"
|
||||||
|
|
||||||
prepare-e2e
|
prepare-e2e
|
||||||
|
|
||||||
|
if [[ "${FEDERATION:-}" == "true" ]];then
|
||||||
|
FEDERATION_NAMESPACE=${FEDERATION_NAMESPACE:-federation-e2e}
|
||||||
|
#TODO(colhom): the last cluster that was created in the loop above is the current context.
|
||||||
|
# Hence, it will be the cluster that hosts the federated components.
|
||||||
|
# In the future, we will want to loop through the all the federated contexts,
|
||||||
|
# select each one and call federated-up
|
||||||
|
for zone in ${E2E_ZONES};do
|
||||||
|
(
|
||||||
|
set-federated-zone-vars "$zone"
|
||||||
|
printf "\n\tChecking version for $OVERRIDE_CONTEXT\n"
|
||||||
|
${KUBECTL} --context="$OVERRIDE_CONTEXT" version
|
||||||
|
)
|
||||||
|
done
|
||||||
|
else
|
||||||
${KUBECTL} version
|
${KUBECTL} version
|
||||||
|
fi
|
||||||
|
|
|
@ -29,4 +29,21 @@ source "${KUBE_ROOT}/cluster/kube-util.sh"
|
||||||
|
|
||||||
prepare-e2e
|
prepare-e2e
|
||||||
|
|
||||||
|
if [[ "${FEDERATION:-}" == "true" ]];then
|
||||||
|
#TODO(colhom): the last cluster that was created in the loop above is the current context.
|
||||||
|
# Hence, it will be the cluster that hosts the federated components.
|
||||||
|
# In the future, we will want to loop through the all the federated contexts,
|
||||||
|
# select each one and call federated-up
|
||||||
|
for zone in ${E2E_ZONES};do
|
||||||
|
(
|
||||||
|
set-federated-zone-vars "$zone"
|
||||||
test-setup
|
test-setup
|
||||||
|
)
|
||||||
|
done
|
||||||
|
if [[ -f "${KUBE_ROOT}/federation/manifests/federated-image.tag" ]];then
|
||||||
|
export FEDERATION_IMAGE_TAG="$(cat "${KUBE_ROOT}/federation/manifests/federated-image.tag")"
|
||||||
|
fi
|
||||||
|
"${KUBE_ROOT}/federation/cluster/federated-up.sh"
|
||||||
|
else
|
||||||
|
test-setup
|
||||||
|
fi
|
||||||
|
|
17
hack/e2e.go
17
hack/e2e.go
|
@ -155,6 +155,10 @@ func Up() bool {
|
||||||
|
|
||||||
// Ensure that the cluster is large engough to run the e2e tests.
|
// Ensure that the cluster is large engough to run the e2e tests.
|
||||||
func ValidateClusterSize() {
|
func ValidateClusterSize() {
|
||||||
|
if os.Getenv("FEDERATION") == "true" {
|
||||||
|
//TODO(colhom): federated equivalent of ValidateClusterSize
|
||||||
|
return
|
||||||
|
}
|
||||||
// Check that there are at least minNodeCount nodes running
|
// Check that there are at least minNodeCount nodes running
|
||||||
cmd := exec.Command(path.Join(*root, "hack/e2e-internal/e2e-cluster-size.sh"))
|
cmd := exec.Command(path.Join(*root, "hack/e2e-internal/e2e-cluster-size.sh"))
|
||||||
if *verbose {
|
if *verbose {
|
||||||
|
@ -189,7 +193,15 @@ func Test() bool {
|
||||||
ValidateClusterSize()
|
ValidateClusterSize()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if os.Getenv("FEDERATION") == "" {
|
||||||
return finishRunning("Ginkgo tests", exec.Command(filepath.Join(*root, "hack/ginkgo-e2e.sh"), strings.Fields(*testArgs)...))
|
return finishRunning("Ginkgo tests", exec.Command(filepath.Join(*root, "hack/ginkgo-e2e.sh"), strings.Fields(*testArgs)...))
|
||||||
|
} else {
|
||||||
|
|
||||||
|
if *testArgs == "" {
|
||||||
|
*testArgs = "--ginkgo.focus=\\[Feature:Federation\\]"
|
||||||
|
}
|
||||||
|
return finishRunning("Federated Ginkgo tests", exec.Command(filepath.Join(*root, "hack/federated-ginkgo-e2e.sh"), strings.Fields(*testArgs)...))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func finishRunning(stepName string, cmd *exec.Cmd) bool {
|
func finishRunning(stepName string, cmd *exec.Cmd) bool {
|
||||||
|
@ -212,8 +224,9 @@ func finishRunning(stepName string, cmd *exec.Cmd) bool {
|
||||||
// returns either "", or a list of args intended for appending with the
|
// returns either "", or a list of args intended for appending with the
|
||||||
// kubectl command (beginning with a space).
|
// kubectl command (beginning with a space).
|
||||||
func kubectlArgs() string {
|
func kubectlArgs() string {
|
||||||
|
args := []string{""}
|
||||||
if *checkVersionSkew {
|
if *checkVersionSkew {
|
||||||
return " --match-server-version"
|
args = append(args, "--match-server-version")
|
||||||
}
|
}
|
||||||
return ""
|
return strings.Join(args, " ")
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Copyright 2014 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
|
||||||
|
|
||||||
|
KUBE_ROOT=$(dirname "${BASH_SOURCE}")/..
|
||||||
|
|
||||||
|
source "${KUBE_ROOT}/cluster/kube-util.sh"
|
||||||
|
|
||||||
|
#A little hack to get the last zone. we always deploy federated cluster to the last zone.
|
||||||
|
#TODO(colhom): deploy federated control plane to multiple underlying clusters in robust way
|
||||||
|
lastZone=""
|
||||||
|
for zone in ${E2E_ZONES};do
|
||||||
|
lastZone="$zone"
|
||||||
|
done
|
||||||
|
(
|
||||||
|
set-federated-zone-vars "$zone"
|
||||||
|
"${KUBE_ROOT}/hack/ginkgo-e2e.sh" $@
|
||||||
|
)
|
|
@ -136,6 +136,7 @@ readonly KUBE_TEST_PORTABLE=(
|
||||||
hack/e2e-internal
|
hack/e2e-internal
|
||||||
hack/get-build.sh
|
hack/get-build.sh
|
||||||
hack/ginkgo-e2e.sh
|
hack/ginkgo-e2e.sh
|
||||||
|
hack/federated-ginkgo-e2e.sh
|
||||||
hack/lib
|
hack/lib
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -164,6 +165,7 @@ readonly KUBE_STATIC_LIBRARIES=(
|
||||||
kube-scheduler
|
kube-scheduler
|
||||||
kube-proxy
|
kube-proxy
|
||||||
kubectl
|
kubectl
|
||||||
|
federation-apiserver
|
||||||
)
|
)
|
||||||
|
|
||||||
kube::golang::is_statically_linked_library() {
|
kube::golang::is_statically_linked_library() {
|
||||||
|
|
|
@ -143,6 +143,7 @@ failure-domains
|
||||||
fake-clientset
|
fake-clientset
|
||||||
federated-api-burst
|
federated-api-burst
|
||||||
federated-api-qps
|
federated-api-qps
|
||||||
|
federated-kube-context
|
||||||
file-check-frequency
|
file-check-frequency
|
||||||
file-suffix
|
file-suffix
|
||||||
file_content_in_loop
|
file_content_in_loop
|
||||||
|
|
|
@ -17,11 +17,12 @@ limitations under the License.
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
flag "github.com/spf13/pflag"
|
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
flag "github.com/spf13/pflag"
|
||||||
|
|
||||||
"k8s.io/kubernetes/test/e2e"
|
"k8s.io/kubernetes/test/e2e"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,10 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
. "github.com/onsi/ginkgo"
|
||||||
|
. "github.com/onsi/gomega"
|
||||||
"k8s.io/kubernetes/pkg/api"
|
"k8s.io/kubernetes/pkg/api"
|
||||||
|
"k8s.io/kubernetes/pkg/api/annotations"
|
||||||
"k8s.io/kubernetes/pkg/api/errors"
|
"k8s.io/kubernetes/pkg/api/errors"
|
||||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
"k8s.io/kubernetes/pkg/apis/extensions"
|
||||||
|
@ -35,10 +38,6 @@ import (
|
||||||
"k8s.io/kubernetes/pkg/util/wait"
|
"k8s.io/kubernetes/pkg/util/wait"
|
||||||
"k8s.io/kubernetes/pkg/watch"
|
"k8s.io/kubernetes/pkg/watch"
|
||||||
"k8s.io/kubernetes/test/e2e/framework"
|
"k8s.io/kubernetes/test/e2e/framework"
|
||||||
|
|
||||||
. "github.com/onsi/ginkgo"
|
|
||||||
. "github.com/onsi/gomega"
|
|
||||||
"k8s.io/kubernetes/pkg/api/annotations"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|
|
@ -0,0 +1,64 @@
|
||||||
|
/*
|
||||||
|
Copyright 2015 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package e2e
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
. "github.com/onsi/ginkgo"
|
||||||
|
federationapi "k8s.io/kubernetes/federation/apis/federation"
|
||||||
|
"k8s.io/kubernetes/pkg/api"
|
||||||
|
"k8s.io/kubernetes/test/e2e/framework"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Create/delete cluster api objects
|
||||||
|
var _ = framework.KubeDescribe("Federation apiserver [Feature:Federation]", func() {
|
||||||
|
f := framework.NewDefaultFederatedFramework("federated-cluster")
|
||||||
|
It("should allow creation of cluster api objects", func() {
|
||||||
|
framework.SkipUnlessFederated()
|
||||||
|
|
||||||
|
contexts := f.GetUnderlyingFederatedContexts()
|
||||||
|
|
||||||
|
for _, context := range contexts {
|
||||||
|
framework.Logf("Creating cluster object: %s (%s)", context.Name, context.Cluster.Cluster.Server)
|
||||||
|
cluster := federationapi.Cluster{
|
||||||
|
ObjectMeta: api.ObjectMeta{
|
||||||
|
Name: context.Name,
|
||||||
|
},
|
||||||
|
Spec: federationapi.ClusterSpec{
|
||||||
|
ServerAddressByClientCIDRs: []federationapi.ServerAddressByClientCIDR{
|
||||||
|
{
|
||||||
|
ClientCIDR: "0.0.0.0/0",
|
||||||
|
ServerAddress: context.Cluster.Cluster.Server,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
//TODO(colhom): add SecretRef when #26132 lands
|
||||||
|
},
|
||||||
|
}
|
||||||
|
_, err := f.FederationClient.Clusters().Create(&cluster)
|
||||||
|
framework.ExpectNoError(err, fmt.Sprintf("creating cluster: %+v", err))
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, context := range contexts {
|
||||||
|
c, err := f.FederationClient.Clusters().Get(context.Name)
|
||||||
|
framework.ExpectNoError(err, fmt.Sprintf("get cluster: %+v", err))
|
||||||
|
if c.ObjectMeta.Name != context.Name {
|
||||||
|
framework.Failf("cluster name does not match input context: actual=%+v, expected=%+v", c, context)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
|
@ -19,11 +19,13 @@ package framework
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
unversionedfederation "k8s.io/kubernetes/federation/client/clientset_generated/federation_internalclientset/typed/federation/unversioned"
|
||||||
"k8s.io/kubernetes/pkg/api"
|
"k8s.io/kubernetes/pkg/api"
|
||||||
apierrs "k8s.io/kubernetes/pkg/api/errors"
|
apierrs "k8s.io/kubernetes/pkg/api/errors"
|
||||||
"k8s.io/kubernetes/pkg/client/clientset_generated/release_1_2"
|
"k8s.io/kubernetes/pkg/client/clientset_generated/release_1_2"
|
||||||
|
@ -39,6 +41,7 @@ import (
|
||||||
|
|
||||||
. "github.com/onsi/ginkgo"
|
. "github.com/onsi/ginkgo"
|
||||||
. "github.com/onsi/gomega"
|
. "github.com/onsi/gomega"
|
||||||
|
yaml "gopkg.in/yaml.v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -54,6 +57,8 @@ type Framework struct {
|
||||||
Clientset_1_2 *release_1_2.Clientset
|
Clientset_1_2 *release_1_2.Clientset
|
||||||
Clientset_1_3 *release_1_3.Clientset
|
Clientset_1_3 *release_1_3.Clientset
|
||||||
|
|
||||||
|
FederationClient *unversionedfederation.FederationClient
|
||||||
|
|
||||||
Namespace *api.Namespace // Every test has at least one namespace
|
Namespace *api.Namespace // Every test has at least one namespace
|
||||||
namespacesToDelete []*api.Namespace // Some tests have more than one.
|
namespacesToDelete []*api.Namespace // Some tests have more than one.
|
||||||
NamespaceDeletionTimeout time.Duration
|
NamespaceDeletionTimeout time.Duration
|
||||||
|
@ -75,6 +80,9 @@ type Framework struct {
|
||||||
|
|
||||||
// configuration for framework's client
|
// configuration for framework's client
|
||||||
options FrameworkOptions
|
options FrameworkOptions
|
||||||
|
|
||||||
|
// will this framework exercise a federated cluster as well
|
||||||
|
federated bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type TestDataSummary interface {
|
type TestDataSummary interface {
|
||||||
|
@ -97,6 +105,12 @@ func NewDefaultFramework(baseName string) *Framework {
|
||||||
return NewFramework(baseName, options, nil)
|
return NewFramework(baseName, options, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NewDefaultFederatedFramework(baseName string) *Framework {
|
||||||
|
f := NewDefaultFramework(baseName)
|
||||||
|
f.federated = true
|
||||||
|
return f
|
||||||
|
}
|
||||||
|
|
||||||
func NewFramework(baseName string, options FrameworkOptions, client *client.Client) *Framework {
|
func NewFramework(baseName string, options FrameworkOptions, client *client.Client) *Framework {
|
||||||
f := &Framework{
|
f := &Framework{
|
||||||
BaseName: baseName,
|
BaseName: baseName,
|
||||||
|
@ -130,9 +144,17 @@ func (f *Framework) BeforeEach() {
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
f.Client = c
|
f.Client = c
|
||||||
}
|
}
|
||||||
|
|
||||||
f.Clientset_1_2 = adapter_1_2.FromUnversionedClient(f.Client)
|
f.Clientset_1_2 = adapter_1_2.FromUnversionedClient(f.Client)
|
||||||
f.Clientset_1_3 = adapter_1_3.FromUnversionedClient(f.Client)
|
f.Clientset_1_3 = adapter_1_3.FromUnversionedClient(f.Client)
|
||||||
|
|
||||||
|
if f.federated && f.FederationClient == nil {
|
||||||
|
By("Creating a federated kubernetes client")
|
||||||
|
var err error
|
||||||
|
f.FederationClient, err = LoadFederationClient()
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
}
|
||||||
|
|
||||||
By("Building a namespace api object")
|
By("Building a namespace api object")
|
||||||
namespace, err := f.CreateNamespace(f.BaseName, map[string]string{
|
namespace, err := f.CreateNamespace(f.BaseName, map[string]string{
|
||||||
"e2e-framework": f.BaseName,
|
"e2e-framework": f.BaseName,
|
||||||
|
@ -206,6 +228,18 @@ func (f *Framework) AfterEach() {
|
||||||
f.Client = nil
|
f.Client = nil
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
if f.federated {
|
||||||
|
defer func() {
|
||||||
|
if f.FederationClient == nil {
|
||||||
|
Logf("Warning: framework is marked federated, but has no FederationClient")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err := f.FederationClient.Clusters().DeleteCollection(nil, api.ListOptions{}); err != nil {
|
||||||
|
Logf("Error: failed to delete Clusters: %+v", err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
// Print events if the test failed.
|
// Print events if the test failed.
|
||||||
if CurrentGinkgoTestDescription().Failed && TestContext.DumpLogsOnFailure {
|
if CurrentGinkgoTestDescription().Failed && TestContext.DumpLogsOnFailure {
|
||||||
DumpAllNamespaceInfo(f.Client, f.Namespace.Name)
|
DumpAllNamespaceInfo(f.Client, f.Namespace.Name)
|
||||||
|
@ -465,6 +499,97 @@ func (f *Framework) CreatePodsPerNodeForSimpleApp(appName string, podSpec func(n
|
||||||
return labels
|
return labels
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type KubeUser struct {
|
||||||
|
Name string `yaml:"name"`
|
||||||
|
User struct {
|
||||||
|
Username string `yaml:"username"`
|
||||||
|
Password string `yaml:"password"`
|
||||||
|
Token string `yaml:"token"`
|
||||||
|
} `yaml:"user"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type KubeCluster struct {
|
||||||
|
Name string `yaml:"name"`
|
||||||
|
Cluster struct {
|
||||||
|
CertificateAuthorityData string `yaml:"certificate-authority-data"`
|
||||||
|
Server string `yaml:"server"`
|
||||||
|
} `yaml:"cluster"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type KubeConfig struct {
|
||||||
|
Contexts []struct {
|
||||||
|
Name string `yaml:"name"`
|
||||||
|
Context struct {
|
||||||
|
Cluster string `yaml:"cluster"`
|
||||||
|
User string
|
||||||
|
} `yaml:"context"`
|
||||||
|
} `yaml:"contexts"`
|
||||||
|
|
||||||
|
Clusters []KubeCluster `yaml:"clusters"`
|
||||||
|
|
||||||
|
Users []KubeUser `yaml:"users"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (kc *KubeConfig) findUser(name string) *KubeUser {
|
||||||
|
for _, user := range kc.Users {
|
||||||
|
if user.Name == name {
|
||||||
|
return &user
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (kc *KubeConfig) findCluster(name string) *KubeCluster {
|
||||||
|
for _, cluster := range kc.Clusters {
|
||||||
|
if cluster.Name == name {
|
||||||
|
return &cluster
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type E2EContext struct {
|
||||||
|
Name string `yaml:"name"`
|
||||||
|
Cluster *KubeCluster `yaml:"cluster"`
|
||||||
|
User *KubeUser `yaml:"user"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *Framework) GetUnderlyingFederatedContexts() []E2EContext {
|
||||||
|
if !f.federated {
|
||||||
|
Failf("geUnderlyingFederatedContexts called on non-federated framework")
|
||||||
|
}
|
||||||
|
|
||||||
|
kubeconfig := KubeConfig{}
|
||||||
|
configBytes, err := ioutil.ReadFile(TestContext.KubeConfig)
|
||||||
|
ExpectNoError(err)
|
||||||
|
err = yaml.Unmarshal(configBytes, &kubeconfig)
|
||||||
|
ExpectNoError(err)
|
||||||
|
|
||||||
|
e2eContexts := []E2EContext{}
|
||||||
|
for _, context := range kubeconfig.Contexts {
|
||||||
|
if strings.HasPrefix(context.Name, "federation-e2e") {
|
||||||
|
|
||||||
|
user := kubeconfig.findUser(context.Context.User)
|
||||||
|
if user == nil {
|
||||||
|
Failf("Could not find user for context %+v", context)
|
||||||
|
}
|
||||||
|
|
||||||
|
cluster := kubeconfig.findCluster(context.Context.Cluster)
|
||||||
|
if cluster == nil {
|
||||||
|
Failf("Could not find cluster for context %+v", context)
|
||||||
|
}
|
||||||
|
|
||||||
|
e2eContexts = append(e2eContexts, E2EContext{
|
||||||
|
Name: context.Name,
|
||||||
|
Cluster: cluster,
|
||||||
|
User: user,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return e2eContexts
|
||||||
|
}
|
||||||
|
|
||||||
func kubectlExecWithRetry(namespace string, podName, containerName string, args ...string) ([]byte, []byte, error) {
|
func kubectlExecWithRetry(namespace string, podName, containerName string, args ...string) ([]byte, []byte, error) {
|
||||||
for numRetries := 0; numRetries < maxKubectlExecRetries; numRetries++ {
|
for numRetries := 0; numRetries < maxKubectlExecRetries; numRetries++ {
|
||||||
if numRetries > 0 {
|
if numRetries > 0 {
|
||||||
|
|
|
@ -77,10 +77,7 @@ type CloudConfig struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
var TestContext TestContextType
|
var TestContext TestContextType
|
||||||
|
var federatedKubeContext string
|
||||||
func SetTestContext(t TestContextType) {
|
|
||||||
TestContext = t
|
|
||||||
}
|
|
||||||
|
|
||||||
func RegisterFlags() {
|
func RegisterFlags() {
|
||||||
// Turn on verbose by default to get spec names
|
// Turn on verbose by default to get spec names
|
||||||
|
@ -95,6 +92,8 @@ func RegisterFlags() {
|
||||||
flag.StringVar(&TestContext.KubeConfig, clientcmd.RecommendedConfigPathFlag, os.Getenv(clientcmd.RecommendedConfigPathEnvVar), "Path to kubeconfig containing embedded authinfo.")
|
flag.StringVar(&TestContext.KubeConfig, clientcmd.RecommendedConfigPathFlag, os.Getenv(clientcmd.RecommendedConfigPathEnvVar), "Path to kubeconfig containing embedded authinfo.")
|
||||||
flag.StringVar(&TestContext.KubeContext, clientcmd.FlagContext, "", "kubeconfig context to use/override. If unset, will use value from 'current-context'")
|
flag.StringVar(&TestContext.KubeContext, clientcmd.FlagContext, "", "kubeconfig context to use/override. If unset, will use value from 'current-context'")
|
||||||
flag.StringVar(&TestContext.KubeAPIContentType, "kube-api-content-type", "", "ContentType used to communicate with apiserver")
|
flag.StringVar(&TestContext.KubeAPIContentType, "kube-api-content-type", "", "ContentType used to communicate with apiserver")
|
||||||
|
flag.StringVar(&federatedKubeContext, "federated-kube-context", "federated-cluster", "kubeconfig context for federated-cluster.")
|
||||||
|
|
||||||
flag.StringVar(&TestContext.KubeVolumeDir, "volume-dir", "/var/lib/kubelet", "Path to the directory containing the kubelet volumes.")
|
flag.StringVar(&TestContext.KubeVolumeDir, "volume-dir", "/var/lib/kubelet", "Path to the directory containing the kubelet volumes.")
|
||||||
flag.StringVar(&TestContext.CertDir, "cert-dir", "", "Path to the directory containing the certs. Default is empty, which doesn't use certs.")
|
flag.StringVar(&TestContext.CertDir, "cert-dir", "", "Path to the directory containing the certs. Default is empty, which doesn't use certs.")
|
||||||
flag.StringVar(&TestContext.Host, "host", "", "The host, or apiserver, to connect to")
|
flag.StringVar(&TestContext.Host, "host", "", "The host, or apiserver, to connect to")
|
||||||
|
|
|
@ -36,6 +36,7 @@ import (
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
unversionedfederation "k8s.io/kubernetes/federation/client/clientset_generated/federation_internalclientset/typed/federation/unversioned"
|
||||||
"k8s.io/kubernetes/pkg/api"
|
"k8s.io/kubernetes/pkg/api"
|
||||||
apierrs "k8s.io/kubernetes/pkg/api/errors"
|
apierrs "k8s.io/kubernetes/pkg/api/errors"
|
||||||
"k8s.io/kubernetes/pkg/api/resource"
|
"k8s.io/kubernetes/pkg/api/resource"
|
||||||
|
@ -325,6 +326,28 @@ func SkipUnlessServerVersionGTE(v semver.Version, c discovery.ServerVersionInter
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Detects whether the federation namespace exists in the underlying cluster
|
||||||
|
func SkipUnlessFederated() {
|
||||||
|
c, err := LoadClient()
|
||||||
|
if err != nil {
|
||||||
|
Failf("Unable to load client: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
federationNS := os.Getenv("FEDERATION_NAMESPACE")
|
||||||
|
if federationNS == "" {
|
||||||
|
federationNS = "federation-e2e"
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = c.Namespaces().Get(federationNS)
|
||||||
|
if err != nil {
|
||||||
|
if apierrs.IsNotFound(err) {
|
||||||
|
Skipf("Could not find federation namespace %s: skipping federated test", federationNS)
|
||||||
|
} else {
|
||||||
|
Failf("Unexpected error getting namespace: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ProvidersWithSSH are those providers where each node is accessible with SSH
|
// ProvidersWithSSH are those providers where each node is accessible with SSH
|
||||||
var ProvidersWithSSH = []string{"gce", "gke", "aws"}
|
var ProvidersWithSSH = []string{"gce", "gke", "aws"}
|
||||||
|
|
||||||
|
@ -1521,22 +1544,42 @@ func ServiceResponding(c *client.Client, ns, name string) error {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func LoadConfig() (*restclient.Config, error) {
|
func restclientConfig(kubeContext string) (*clientcmdapi.Config, error) {
|
||||||
switch {
|
Logf(">>> kubeConfig: %s\n", TestContext.KubeConfig)
|
||||||
case TestContext.KubeConfig != "":
|
if TestContext.KubeConfig == "" {
|
||||||
Logf(">>> TestContext.KubeConfig: %s\n", TestContext.KubeConfig)
|
return nil, fmt.Errorf("KubeConfig must be specified to load client config")
|
||||||
|
}
|
||||||
c, err := clientcmd.LoadFromFile(TestContext.KubeConfig)
|
c, err := clientcmd.LoadFromFile(TestContext.KubeConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("error loading KubeConfig: %v", err.Error())
|
return nil, fmt.Errorf("error loading KubeConfig: %v", err.Error())
|
||||||
}
|
}
|
||||||
if TestContext.KubeContext != "" {
|
if kubeContext != "" {
|
||||||
Logf(">>> TestContext.KubeContext: %s\n", TestContext.KubeContext)
|
Logf(">>> kubeContext: %s\n", kubeContext)
|
||||||
c.CurrentContext = TestContext.KubeContext
|
c.CurrentContext = kubeContext
|
||||||
}
|
}
|
||||||
|
return c, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func LoadConfig() (*restclient.Config, error) {
|
||||||
|
c, err := restclientConfig(TestContext.KubeContext)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
return clientcmd.NewDefaultClientConfig(*c, &clientcmd.ConfigOverrides{ClusterInfo: clientcmdapi.Cluster{Server: TestContext.Host}}).ClientConfig()
|
return clientcmd.NewDefaultClientConfig(*c, &clientcmd.ConfigOverrides{ClusterInfo: clientcmdapi.Cluster{Server: TestContext.Host}}).ClientConfig()
|
||||||
default:
|
|
||||||
return nil, fmt.Errorf("KubeConfig must be specified to load client config")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func LoadFederatedConfig() (*restclient.Config, error) {
|
||||||
|
c, err := restclientConfig(federatedKubeContext)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
cfg, err := clientcmd.NewDefaultClientConfig(*c, &clientcmd.ConfigOverrides{}).ClientConfig()
|
||||||
|
if cfg != nil {
|
||||||
|
//TODO(colhom): this is only here because https://github.com/kubernetes/kubernetes/issues/25422
|
||||||
|
cfg.NegotiatedSerializer = api.Codecs
|
||||||
|
}
|
||||||
|
return cfg, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadClientFromConfig(config *restclient.Config) (*client.Client, error) {
|
func loadClientFromConfig(config *restclient.Config) (*client.Client, error) {
|
||||||
|
@ -1550,6 +1593,25 @@ func loadClientFromConfig(config *restclient.Config) (*client.Client, error) {
|
||||||
return c, nil
|
return c, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func loadFederationClientFromConfig(config *restclient.Config) (*unversionedfederation.FederationClient, error) {
|
||||||
|
c, err := unversionedfederation.NewForConfig(config)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("error creating client: %v", err.Error())
|
||||||
|
}
|
||||||
|
if c.Client.Timeout == 0 {
|
||||||
|
c.Client.Timeout = SingleCallTimeout
|
||||||
|
}
|
||||||
|
return c, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func LoadFederationClient() (*unversionedfederation.FederationClient, error) {
|
||||||
|
config, err := LoadFederatedConfig()
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("error creating client: %v", err.Error())
|
||||||
|
}
|
||||||
|
return loadFederationClientFromConfig(config)
|
||||||
|
}
|
||||||
|
|
||||||
func LoadClient() (*client.Client, error) {
|
func LoadClient() (*client.Client, error) {
|
||||||
config, err := LoadConfig()
|
config, err := LoadConfig()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -22,11 +22,12 @@ import (
|
||||||
"log"
|
"log"
|
||||||
|
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
"k8s.io/kubernetes/pkg/api"
|
"k8s.io/kubernetes/pkg/api"
|
||||||
client "k8s.io/kubernetes/pkg/client/unversioned"
|
client "k8s.io/kubernetes/pkg/client/unversioned"
|
||||||
"k8s.io/kubernetes/pkg/fields"
|
"k8s.io/kubernetes/pkg/fields"
|
||||||
"k8s.io/kubernetes/pkg/labels"
|
"k8s.io/kubernetes/pkg/labels"
|
||||||
"net/http"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
|
Loading…
Reference in New Issue