Make tilt work with the supervisor app and add more uninstall testing

- Also continue renaming things related to the concierge app
- Enhance the uninstall test to also test uninstalling the supervisor
  and local-user-authenticator apps
This commit is contained in:
Ryan Richard 2020-10-09 14:25:34 -07:00
parent 72b2d02777
commit 34549b779b
13 changed files with 173 additions and 72 deletions

View File

@ -109,7 +109,7 @@ docker build .
1. Create a local Kubernetes cluster using `kind`: 1. Create a local Kubernetes cluster using `kind`:
```bash ```bash
kind create cluster --image kindest/node:v1.18.8 ./hack/kind-up.sh
``` ```
1. Install Pinniped and supporting dependencies using `tilt`: 1. Install Pinniped and supporting dependencies using `tilt`:
@ -123,11 +123,11 @@ docker build .
1. Run the Pinniped integration tests: 1. Run the Pinniped integration tests:
```bash ```bash
source ./hack/lib/tilt/integration-test.env && go test -v -count 1 ./test/integration source /tmp/integration-test-env && go test -v -count 1 ./test/integration
``` ```
To uninstall the test environment, run `./hack/tilt-down.sh`. To uninstall the test environment, run `./hack/tilt-down.sh`.
To destroy the local Kubernetes cluster, run `kind delete cluster`. To destroy the local Kubernetes cluster, run `./hack/kind-down.sh`.
### Observing Tests on the Continuous Integration Environment ### Observing Tests on the Continuous Integration Environment

View File

@ -4,8 +4,8 @@
#@data/values #@data/values
--- ---
app_name: pinniped app_name: pinniped-concierge
namespace: pinniped namespace: pinniped-concierge
#! Specify how many replicas of the Pinniped server to run. #! Specify how many replicas of the Pinniped server to run.
replicas: 2 replicas: 2

11
hack/kind-down.sh Executable file
View File

@ -0,0 +1,11 @@
#!/usr/bin/env bash
# Copyright 2020 the Pinniped contributors. All Rights Reserved.
# SPDX-License-Identifier: Apache-2.0
set -euo pipefail
ROOT="$( cd "$( dirname "${BASH_SOURCE[0]}" )/.." && pwd )"
cd "${ROOT}"
kind delete cluster --name pinniped

12
hack/kind-up.sh Executable file
View File

@ -0,0 +1,12 @@
#!/usr/bin/env bash
# Copyright 2020 the Pinniped contributors. All Rights Reserved.
# SPDX-License-Identifier: Apache-2.0
set -euo pipefail
ROOT="$( cd "$( dirname "${BASH_SOURCE[0]}" )/.." && pwd )"
cd "${ROOT}"
# To choose a specific version of kube, add this option to the command below: `--image kindest/node:v1.18.8`
kind create cluster --config "hack/lib/kind-config/single-node.yaml" --name pinniped

View File

@ -15,6 +15,10 @@ local_resource(
deps=['../../../cmd', '../../../internal', '../../../pkg', '../../../generated'], deps=['../../../cmd', '../../../internal', '../../../pkg', '../../../generated'],
) )
#
# local-user-authenticator app
#
# Build a container image for local-user-authenticator, with live-update enabled. # Build a container image for local-user-authenticator, with live-update enabled.
docker_build_with_restart('image/local-user-auth', '.', docker_build_with_restart('image/local-user-auth', '.',
dockerfile='local-user-authenticator.Dockerfile', dockerfile='local-user-authenticator.Dockerfile',
@ -39,59 +43,106 @@ k8s_resource(
'local-user-authenticator:namespace', 'local-user-authenticator:namespace',
'local-user-authenticator:serviceaccount', 'local-user-authenticator:serviceaccount',
'local-user-authenticator:role', 'local-user-authenticator:role',
'local-user-authenticator:rolebinding', 'local-user-authenticator:rolebinding'
], ],
) )
# Build a container image for the Pinniped server, with live-update enabled. #
docker_build_with_restart('image/pinniped', '.', # Supervisor app
dockerfile='pinniped.Dockerfile', #
entrypoint=['/usr/local/bin/pinniped-server'],
live_update=[sync('./build/pinniped-server', '/usr/local/bin/pinniped-server')], # Build a container image for supervisor, with live-update enabled.
only=['./build/pinniped-server'], docker_build_with_restart('image/supervisor', '.',
dockerfile='supervisor.Dockerfile',
entrypoint=['/usr/local/bin/pinniped-supervisor'],
live_update=[sync('./build/pinniped-supervisor', '/usr/local/bin/pinniped-supervisor')],
only=['./build/pinniped-supervisor'],
) )
# Render the Pinniped server installation manifest using ytt. # Render the supervisor installation manifest using ytt.
k8s_yaml(local([
'ytt',
'--file', '../../../deploy/supervisor',
'--data-value', 'image_repo=image/supervisor',
'--data-value', 'image_tag=tilt-dev',
'--data-value-yaml', 'replicas=1'
]))
# Collect all the deployed supervisor resources under a "supervisor" resource tab.
k8s_resource(
workload='pinniped-supervisor',
new_name='supervisor',
objects=[
'oidcproviderconfigs.config.pinniped.dev:customresourcedefinition',
'pinniped-supervisor-static-config:configmap',
'pinniped-supervisor:namespace',
'pinniped-supervisor:role',
'pinniped-supervisor:rolebinding',
'pinniped-supervisor:serviceaccount',
],
)
# Build a container image for the Concierge server, with live-update enabled.
docker_build_with_restart('image/concierge', '.',
dockerfile='concierge.Dockerfile',
entrypoint=['/usr/local/bin/pinniped-concierge'],
live_update=[sync('./build/pinniped-concierge', '/usr/local/bin/pinniped-concierge')],
only=['./build/pinniped-concierge'],
)
k8s_yaml('nodeport.yaml')
#
# Concierge app
#
# Render the Concierge server installation manifest using ytt.
k8s_yaml(local([ k8s_yaml(local([
'sh', '-c', 'sh', '-c',
'ytt --file ../../../deploy/concierge ' + 'ytt --file ../../../deploy/concierge ' +
'--data-value app_name=pinniped-concierge ' +
'--data-value namespace=integration ' + '--data-value namespace=integration ' +
'--data-value image_repo=image/pinniped ' + '--data-value image_repo=image/concierge ' +
'--data-value image_tag=tilt-dev ' + '--data-value image_tag=tilt-dev ' +
'--data-value kube_cert_agent_image=debian:10.5-slim ' + '--data-value kube_cert_agent_image=debian:10.5-slim ' +
'--data-value discovery_url=$(TERM=dumb kubectl cluster-info | awk \'/Kubernetes master/ {print $NF}\') ' + '--data-value discovery_url=$(TERM=dumb kubectl cluster-info | awk \'/Kubernetes master/ {print $NF}\') ' +
'--data-value-yaml replicas=1' '--data-value-yaml replicas=1'
])) ]))
# Collect all the deployed local-user-authenticator resources under a "deploy/pinniped" resource tab. # Collect all the deployed local-user-authenticator resources under a "concierge" resource tab.
k8s_resource( k8s_resource(
workload='pinniped', workload='pinniped-concierge',
new_name='concierge',
objects=[ objects=[
'integration:namespace', 'integration:namespace',
'pinniped-concierge-aggregated-api-server:clusterrole',
'pinniped-concierge-aggregated-api-server:clusterrolebinding',
'pinniped-concierge-aggregated-api-server:role',
'pinniped-concierge-aggregated-api-server:rolebinding',
'pinniped-concierge-cluster-info-lister-watcher:role',
'pinniped-concierge-cluster-info-lister-watcher:rolebinding',
'pinniped-concierge-config:configmap',
'pinniped-concierge-create-token-credential-requests:clusterrole',
'pinniped-concierge-create-token-credential-requests:clusterrolebinding',
'pinniped-concierge-extension-apiserver-authentication-reader:rolebinding',
'pinniped-concierge-kube-system-pod-read:role',
'pinniped-concierge-kube-system-pod-read:rolebinding',
'pinniped-concierge:clusterrolebinding',
'pinniped-concierge:serviceaccount',
'credentialissuerconfigs.config.pinniped.dev:customresourcedefinition', 'credentialissuerconfigs.config.pinniped.dev:customresourcedefinition',
'webhookidentityproviders.idp.pinniped.dev:customresourcedefinition', 'webhookidentityproviders.idp.pinniped.dev:customresourcedefinition',
'pinniped:serviceaccount',
'pinniped-aggregated-api-server:role',
'pinniped-kube-system-pod-read:role',
'pinniped-cluster-info-lister-watcher:role',
'pinniped-aggregated-api-server:clusterrole',
'pinniped-create-token-credential-requests:clusterrole',
'pinniped-aggregated-api-server:rolebinding',
'pinniped-kube-system-pod-read:rolebinding',
'pinniped-extension-apiserver-authentication-reader:rolebinding',
'pinniped-cluster-info-lister-watcher:rolebinding',
'pinniped-aggregated-api-server:clusterrolebinding',
'pinniped-create-token-credential-requests:clusterrolebinding',
'pinniped:clusterrolebinding',
'pinniped-config:configmap',
'v1alpha1.login.pinniped.dev:apiservice', 'v1alpha1.login.pinniped.dev:apiservice',
], ],
) )
#
# Finish setting up cluster and creating integration test env file
#
# Collect environment variables needed to run our integration test suite. # Collect environment variables needed to run our integration test suite.
local_resource( local_resource(
'test-env', 'test-env',
'TILT_MODE=yes ../../prepare-for-integration-tests.sh', 'TILT_MODE=yes ../../prepare-for-integration-tests.sh',
resource_deps=['local-user-auth', 'pinniped'], resource_deps=['local-user-auth', 'concierge', 'supervisor'],
deps=['../../prepare-for-integration-tests.sh'], deps=['../../prepare-for-integration-tests.sh'],
) )

View File

@ -5,10 +5,10 @@
FROM debian:10.5-slim FROM debian:10.5-slim
# Copy the binary which was built outside the container. # Copy the binary which was built outside the container.
COPY build/pinniped-server /usr/local/bin/pinniped-server COPY build/pinniped-concierge /usr/local/bin/pinniped-concierge
# Document the port # Document the port
EXPOSE 443 EXPOSE 443
# Set the entrypoint # Set the entrypoint
ENTRYPOINT ["/usr/local/bin/pinniped-server"] ENTRYPOINT ["/usr/local/bin/pinniped-concierge"]

View File

@ -0,0 +1,13 @@
apiVersion: v1
kind: Service
metadata:
name: pinniped-supervisor-node-port
namespace: pinniped-supervisor
spec:
type: NodePort
selector:
app: pinniped-supervisor
ports:
- port: 80
targetPort: 80
nodePort: 31234

View File

@ -0,0 +1,14 @@
# Copyright 2020 VMware, Inc.
# SPDX-License-Identifier: Apache-2.0
# Use a runtime image based on Debian slim
FROM debian:10.5-slim
# Copy the binary which was built outside the container.
COPY build/pinniped-supervisor /usr/local/bin/pinniped-supervisor
# Document the port
EXPOSE 443
# Set the entrypoint
ENTRYPOINT ["/usr/local/bin/pinniped-supervisor"]

View File

@ -110,17 +110,17 @@ fi
if ! tilt_mode; then if ! tilt_mode; then
if [[ "$clean_kind" == "yes" ]]; then if [[ "$clean_kind" == "yes" ]]; then
log_note "Deleting running kind clusters to prepare from a clean slate..." log_note "Deleting running kind clusters to prepare from a clean slate..."
kind delete cluster kind delete cluster --name pinniped
fi fi
# #
# Setup kind and build the app # Setup kind and build the app
# #
log_note "Checking for running kind clusters..." log_note "Checking for running kind clusters..."
if ! kind get clusters | grep -q -e '^kind$'; then if ! kind get clusters | grep -q -e '^pinniped$'; then
log_note "Creating a kind cluster..." log_note "Creating a kind cluster..."
# single-node.yaml exposes node port 31234 as localhost:12345 # single-node.yaml exposes node port 31234 as localhost:12345
kind create cluster --config "$pinniped_path/hack/lib/kind-config/single-node.yaml" kind create cluster --config "$pinniped_path/hack/lib/kind-config/single-node.yaml" --name pinniped
else else
if ! kubectl cluster-info | grep master | grep -q 127.0.0.1; then if ! kubectl cluster-info | grep master | grep -q 127.0.0.1; then
log_error "Seems like your kubeconfig is not targeting a local cluster." log_error "Seems like your kubeconfig is not targeting a local cluster."
@ -157,7 +157,7 @@ if ! tilt_mode; then
# Load it into the cluster # Load it into the cluster
log_note "Loading the app's container image into the kind cluster..." log_note "Loading the app's container image into the kind cluster..."
kind load docker-image "$registry_repo_tag" kind load docker-image "$registry_repo_tag" --name pinniped
manifest=/tmp/manifest.yaml manifest=/tmp/manifest.yaml
@ -178,7 +178,6 @@ if ! tilt_mode; then
fi fi
test_username="test-username" test_username="test-username"
test_groups="test-group-0,test-group-1" test_groups="test-group-0,test-group-1"
set +o pipefail set +o pipefail
@ -203,18 +202,19 @@ kubectl create secret generic "$test_username" \
supervisor_app_name="pinniped-supervisor" supervisor_app_name="pinniped-supervisor"
supervisor_namespace="pinniped-supervisor" supervisor_namespace="pinniped-supervisor"
pushd deploy/supervisor >/dev/null if ! tilt_mode; then
pushd deploy/supervisor >/dev/null
log_note "Deploying the Pinniped Supervisor app to the cluster..." log_note "Deploying the Pinniped Supervisor app to the cluster..."
ytt --file . \ ytt --file . \
--data-value "app_name=$supervisor_app_name" \ --data-value "app_name=$supervisor_app_name" \
--data-value "namespace=$supervisor_namespace" \ --data-value "namespace=$supervisor_namespace" \
--data-value "image_repo=$registry_repo" \ --data-value "image_repo=$registry_repo" \
--data-value "image_tag=$tag" >"$manifest" --data-value "image_tag=$tag" >"$manifest"
kapp deploy --yes --app "pinniped-supervisor" --diff-changes --file "$manifest" kapp deploy --yes --app "$supervisor_app_name" --diff-changes --file "$manifest"
log_note "Adding NodePort service to expose the Pinniped Supervisor app on the kind node..." log_note "Adding NodePort service to expose the Pinniped Supervisor app on the kind node..."
cat <<EOF | kubectl apply -f - cat <<EOF | kubectl apply -f -
apiVersion: v1 apiVersion: v1
kind: Service kind: Service
@ -231,32 +231,30 @@ spec:
nodePort: 31234 nodePort: 31234
EOF EOF
popd >/dev/null popd >/dev/null
fi
# #
# Deploy Pinniped # Deploy Pinniped
# #
app_name="pinniped" concierge_app_name="pinniped-concierge"
namespace="integration" concierge_namespace="integration"
webhook_url="https://local-user-authenticator.local-user-authenticator.svc/authenticate" webhook_url="https://local-user-authenticator.local-user-authenticator.svc/authenticate"
webhook_ca_bundle="$(kubectl get secret local-user-authenticator-tls-serving-certificate --namespace local-user-authenticator -o 'jsonpath={.data.caCertificate}')" webhook_ca_bundle="$(kubectl get secret local-user-authenticator-tls-serving-certificate --namespace local-user-authenticator -o 'jsonpath={.data.caCertificate}')"
discovery_url="$(TERM=dumb kubectl cluster-info | awk '/Kubernetes master/ {print $NF}')" discovery_url="$(TERM=dumb kubectl cluster-info | awk '/Kubernetes master/ {print $NF}')"
if ! tilt_mode; then if ! tilt_mode; then
#
# Deploy Pinniped
#
pushd deploy/concierge >/dev/null pushd deploy/concierge >/dev/null
log_note "Deploying the Pinniped app to the cluster..." log_note "Deploying the Pinniped app to the cluster..."
ytt --file . \ ytt --file . \
--data-value "app_name=$app_name" \ --data-value "app_name=$concierge_app_name" \
--data-value "namespace=$namespace" \ --data-value "namespace=$concierge_namespace" \
--data-value "image_repo=$registry_repo" \ --data-value "image_repo=$registry_repo" \
--data-value "image_tag=$tag" \ --data-value "image_tag=$tag" \
--data-value "discovery_url=$discovery_url" >"$manifest" --data-value "discovery_url=$discovery_url" >"$manifest"
kapp deploy --yes --app "$app_name" --diff-changes --file "$manifest" kapp deploy --yes --app "$concierge_app_name" --diff-changes --file "$manifest"
popd >/dev/null popd >/dev/null
fi fi
@ -269,8 +267,8 @@ pinniped_cluster_capability_file_content=$(cat "$kind_capabilities_file")
cat <<EOF >/tmp/integration-test-env cat <<EOF >/tmp/integration-test-env
# The following env vars should be set before running 'go test -v -count 1 ./test/...' # The following env vars should be set before running 'go test -v -count 1 ./test/...'
export PINNIPED_TEST_CONCIERGE_NAMESPACE=${namespace} export PINNIPED_TEST_CONCIERGE_NAMESPACE=${concierge_namespace}
export PINNIPED_TEST_CONCIERGE_APP_NAME=${app_name} export PINNIPED_TEST_CONCIERGE_APP_NAME=${concierge_app_name}
export PINNIPED_TEST_USER_USERNAME=${test_username} export PINNIPED_TEST_USER_USERNAME=${test_username}
export PINNIPED_TEST_USER_GROUPS=${test_groups} export PINNIPED_TEST_USER_GROUPS=${test_groups}
export PINNIPED_TEST_USER_TOKEN=${test_username}:${test_password} export PINNIPED_TEST_USER_TOKEN=${test_username}:${test_password}
@ -304,6 +302,7 @@ log_note
if ! tilt_mode; then if ! tilt_mode; then
log_note "You can rerun this script to redeploy local production code changes while you are working." log_note "You can rerun this script to redeploy local production code changes while you are working."
log_note log_note
log_note "To delete the deployments, run 'kapp delete -a local-user-authenticator -y && kapp delete -a pinniped -y'." log_note "To delete the deployments, run:"
log_note "When you're finished, use 'kind delete cluster' to tear down the cluster." log_note " kapp delete -a local-user-authenticator -y && kapp delete -a $concierge_app_name -y && kapp delete -a $supervisor_app_name -y"
log_note "When you're finished, use 'kind delete cluster --name pinniped' to tear down the cluster."
fi fi

View File

@ -5,5 +5,7 @@
set -euo pipefail set -euo pipefail
ROOT="$( cd "$( dirname "${BASH_SOURCE[0]}" )/.." && pwd )" ROOT="$( cd "$( dirname "${BASH_SOURCE[0]}" )/.." && pwd )"
cd "${ROOT}" cd "${ROOT}"
exec tilt up -f ./hack/lib/tilt/Tiltfile --stream
exec tilt up -f ./hack/lib/tilt/Tiltfile

View File

@ -32,7 +32,7 @@ func TestFromPath(t *testing.T) {
durationSeconds: 3600 durationSeconds: 3600
renewBeforeSeconds: 2400 renewBeforeSeconds: 2400
names: names:
servingCertificateSecret: pinniped-api-tls-serving-certificate servingCertificateSecret: pinniped-concierge-api-tls-serving-certificate
credentialIssuerConfig: pinniped-config credentialIssuerConfig: pinniped-config
apiService: pinniped-api apiService: pinniped-api
kubeCertAgentPrefix: kube-cert-agent-prefix kubeCertAgentPrefix: kube-cert-agent-prefix
@ -52,7 +52,7 @@ func TestFromPath(t *testing.T) {
}, },
}, },
NamesConfig: api.NamesConfigSpec{ NamesConfig: api.NamesConfigSpec{
ServingCertificateSecret: "pinniped-api-tls-serving-certificate", ServingCertificateSecret: "pinniped-concierge-api-tls-serving-certificate",
CredentialIssuerConfig: "pinniped-config", CredentialIssuerConfig: "pinniped-config",
APIService: "pinniped-api", APIService: "pinniped-api",
}, },
@ -68,7 +68,7 @@ func TestFromPath(t *testing.T) {
yaml: here.Doc(` yaml: here.Doc(`
--- ---
names: names:
servingCertificateSecret: pinniped-api-tls-serving-certificate servingCertificateSecret: pinniped-concierge-api-tls-serving-certificate
credentialIssuerConfig: pinniped-config credentialIssuerConfig: pinniped-config
apiService: pinniped-api apiService: pinniped-api
`), `),
@ -83,7 +83,7 @@ func TestFromPath(t *testing.T) {
}, },
}, },
NamesConfig: api.NamesConfigSpec{ NamesConfig: api.NamesConfigSpec{
ServingCertificateSecret: "pinniped-api-tls-serving-certificate", ServingCertificateSecret: "pinniped-concierge-api-tls-serving-certificate",
CredentialIssuerConfig: "pinniped-config", CredentialIssuerConfig: "pinniped-config",
APIService: "pinniped-api", APIService: "pinniped-api",
}, },
@ -103,7 +103,7 @@ func TestFromPath(t *testing.T) {
yaml: here.Doc(` yaml: here.Doc(`
--- ---
names: names:
servingCertificateSecret: pinniped-api-tls-serving-certificate servingCertificateSecret: pinniped-concierge-api-tls-serving-certificate
credentialIssuerConfig: pinniped-config credentialIssuerConfig: pinniped-config
`), `),
wantError: "validate names: missing required names: apiService", wantError: "validate names: missing required names: apiService",
@ -113,7 +113,7 @@ func TestFromPath(t *testing.T) {
yaml: here.Doc(` yaml: here.Doc(`
--- ---
names: names:
servingCertificateSecret: pinniped-api-tls-serving-certificate servingCertificateSecret: pinniped-concierge-api-tls-serving-certificate
apiService: pinniped-api apiService: pinniped-api
`), `),
wantError: "validate names: missing required names: credentialIssuerConfig", wantError: "validate names: missing required names: credentialIssuerConfig",
@ -137,7 +137,7 @@ func TestFromPath(t *testing.T) {
durationSeconds: 2400 durationSeconds: 2400
renewBeforeSeconds: 3600 renewBeforeSeconds: 3600
names: names:
servingCertificateSecret: pinniped-api-tls-serving-certificate servingCertificateSecret: pinniped-concierge-api-tls-serving-certificate
credentialIssuerConfig: pinniped-config credentialIssuerConfig: pinniped-config
apiService: pinniped-api apiService: pinniped-api
`), `),
@ -152,7 +152,7 @@ func TestFromPath(t *testing.T) {
durationSeconds: 2400 durationSeconds: 2400
renewBeforeSeconds: -10 renewBeforeSeconds: -10
names: names:
servingCertificateSecret: pinniped-api-tls-serving-certificate servingCertificateSecret: pinniped-concierge-api-tls-serving-certificate
credentialIssuerConfig: pinniped-config credentialIssuerConfig: pinniped-config
apiService: pinniped-api apiService: pinniped-api
`), `),
@ -167,7 +167,7 @@ func TestFromPath(t *testing.T) {
durationSeconds: 2400 durationSeconds: 2400
renewBeforeSeconds: -10 renewBeforeSeconds: -10
names: names:
servingCertificateSecret: pinniped-api-tls-serving-certificate servingCertificateSecret: pinniped-concierge-api-tls-serving-certificate
credentialIssuerConfig: pinniped-config credentialIssuerConfig: pinniped-config
apiService: pinniped-api apiService: pinniped-api
`), `),

View File

@ -20,8 +20,7 @@ import (
func TestAPIServingCertificateAutoCreationAndRotation(t *testing.T) { func TestAPIServingCertificateAutoCreationAndRotation(t *testing.T) {
env := library.IntegrationEnv(t) env := library.IntegrationEnv(t)
defaultServingCertResourceName := env.ConciergeAppName + "-api-tls-serving-certificate"
const defaultServingCertResourceName = "pinniped-api-tls-serving-certificate"
tests := []struct { tests := []struct {
name string name string