├── .gitignore ├── 00-validate-clis-are-installed.sh ├── 01-validate-registry-access-and-credentials.sh ├── 02-install-cluster-essentials.sh ├── 03-configure-tap-install-namespace.sh ├── 04-install-tap.sh ├── 05-proxy-traffic.sh ├── 06-install-spring-cloud-gateway.sh ├── 07-install-application-configuration-service.sh ├── 08-install-spring-cloud-service-registry.sh ├── 09-install-tas-adapter.sh ├── 20-debug-watch-package-installs.sh ├── 21-debug-dump-all-kuberentes-objects.sh ├── 22-debug-dump-package-bundles.sh ├── 23-debug-dump-package-repository.sh ├── 24-debug-dump-cartographer-objects.sh ├── 30-delete-tap.sh ├── README.md ├── config ├── acs-overlay.yaml ├── contour-overlay.yaml ├── settings-template.sh ├── tanzu-cluster-essentials-bundle-1.7.2.yml ├── tap-values-template.yaml └── tas-adapter-values-template.yaml ├── dev ├── namespace.yaml └── workload.yaml └── workspace └── readme.txt /.gitignore: -------------------------------------------------------------------------------- 1 | config/settings.sh 2 | workspace 3 | .DS_Store -------------------------------------------------------------------------------- /00-validate-clis-are-installed.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Check if required CLIs are installed 4 | required_clis=("imgpkg" "ytt" "kbld" "kapp" "kubectl" "jq" "socat" "tanzu") 5 | missing_clis=() 6 | 7 | echo "Checking for required CLIs..." 8 | 9 | for cli in "${required_clis[@]}"; do 10 | if command -v "$cli" &> /dev/null; then 11 | echo "$cli found." 12 | else 13 | missing_clis+=("$cli") 14 | fi 15 | done 16 | 17 | if [ ${#missing_clis[@]} -ne 0 ]; then 18 | echo "The following required CLIs are missing:" 19 | for cli in "${missing_clis[@]}"; do 20 | echo "- $cli" 21 | done 22 | echo "Please install the missing CLIs before running the script." 23 | exit 1 24 | fi 25 | 26 | echo "All required CLIs are available." 27 | -------------------------------------------------------------------------------- /01-validate-registry-access-and-credentials.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -euo pipefail 3 | 4 | # 5 | # read the install settings 6 | # 7 | readonly GIT_REPO_ROOT=$(git rev-parse --show-toplevel) 8 | source ${GIT_REPO_ROOT}/config/settings.sh 9 | 10 | # 11 | # Check that the registry that we will be pulling TAP images from is accessible 12 | # 13 | docker login ${TANZU_NET_REGISTRY_HOST} \ 14 | --username ${TANZU_NET_USERNAME} \ 15 | --password-stdin <<<"${TANZU_NET_PASSWORD}" 16 | 17 | # 18 | # Check that the registry we will be publishing workload container images to is accessible 19 | # 20 | docker login ${WORKLOAD_REGISTRY_HOST} \ 21 | --username ${WORKLOAD_REGISTRY_USERNAME} \ 22 | --password-stdin <<<"${WORKLOAD_REGISTRY_PASSWORD}" 23 | -------------------------------------------------------------------------------- /02-install-cluster-essentials.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # This script deploys tanzu cluster essentials to a kuberentes cluster 4 | # by using the cluster essentials bundle lock distributed on tanzunet 5 | # to pull the configuration of cluster essentials and apply to the current 6 | # kuberentes context 7 | # 8 | 9 | set -euo pipefail 10 | 11 | # Load the install settings.sh file 12 | readonly GIT_REPO_ROOT=$(git rev-parse --show-toplevel) 13 | source ${GIT_REPO_ROOT}/config/settings.sh 14 | 15 | readonly WORKSPACE_DIR=${GIT_REPO_ROOT}/workspace 16 | 17 | # The place to put extract culster essentials packages into 18 | readonly CLUSTER_ESSENTIALS_DIR=${WORKSPACE_DIR}/cluster-essentials 19 | 20 | # Clean up existing cluster essentials directory 21 | if [ -d "${CLUSTER_ESSENTIALS_DIR}" ]; then 22 | echo "Directory ${CLUSTER_ESSENTIALS_DIR} exists. Deleting..." 23 | rm -rf "${CLUSTER_ESSENTIALS_DIR}" 24 | fi 25 | 26 | # 27 | # Pull cluster essentials bundle 28 | # 29 | imgpkg pull --lock config/${CLUSTER_ESSENTIALS_LOCK_FILE} \ 30 | --output ${CLUSTER_ESSENTIALS_DIR} 31 | 32 | # 33 | # Create the namespace 34 | # 35 | readonly NS_NAME=tanzu-cluster-essentials 36 | echo "## Creating namespace ${NS_NAME}" 37 | cat < ${KAPP_CONTROLLER_FILE} 62 | 63 | readonly KAPP_CONTROLLER_RESOLVED_FILE=${WORKSPACE_DIR}/generated/kapp-controller-resolved.yaml 64 | kbld --file ${KAPP_CONTROLLER_FILE} \ 65 | --file ${CLUSTER_ESSENTIALS_DIR}/.imgpkg/images.yml \ 66 | > ${KAPP_CONTROLLER_RESOLVED_FILE} 67 | 68 | kapp deploy --app kapp-controller \ 69 | --namespace ${NS_NAME} \ 70 | --file ${KAPP_CONTROLLER_RESOLVED_FILE} \ 71 | --yes 72 | 73 | # 74 | # Deploy secret-gen controller 75 | # 76 | echo "## Deploying secretgen-controller" 77 | readonly SECRETGEN_CONTROLLER_FILE=${WORKSPACE_DIR}/generated/secretgen-controller.yaml 78 | ytt --file ${CLUSTER_ESSENTIALS_DIR}/secretgen-controller/config \ 79 | --file ${CLUSTER_ESSENTIALS_DIR}/registry-creds \ 80 | --data-values-env YTT \ 81 | > ${SECRETGEN_CONTROLLER_FILE} 82 | 83 | readonly SECRETGEN_CONTROLLER_RESOLVED_FILE=${WORKSPACE_DIR}/generated/secretgen-controller-resolved.yaml 84 | kbld --file ${SECRETGEN_CONTROLLER_FILE} \ 85 | --file ${CLUSTER_ESSENTIALS_DIR}/.imgpkg/images.yml \ 86 | > ${SECRETGEN_CONTROLLER_RESOLVED_FILE} 87 | 88 | kapp deploy --app secretgen-controller \ 89 | --namespace ${NS_NAME} \ 90 | --file ${SECRETGEN_CONTROLLER_RESOLVED_FILE} \ 91 | --yes 92 | -------------------------------------------------------------------------------- /03-configure-tap-install-namespace.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -euo pipefail 3 | 4 | # read the settings.sh file 5 | readonly GIT_REPO_ROOT=$(git rev-parse --show-toplevel) 6 | source ${GIT_REPO_ROOT}/config/settings.sh 7 | 8 | echo "" 9 | echo "## Creating namespace tap-install" 10 | cat < ${VALUES_FILE} 28 | 29 | # 30 | # Install tap 31 | # 32 | tanzu package install tap \ 33 | --package tap.tanzu.vmware.com \ 34 | --version "${TAP_VERSION}" \ 35 | --values-file "${VALUES_FILE}" \ 36 | --namespace tap-install 37 | -------------------------------------------------------------------------------- /05-proxy-traffic.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Specify the Kubernetes service and namespace 4 | SERVICE_NAME="envoy" 5 | NAMESPACE="tanzu-system-ingress" 6 | 7 | # Get the NodePort for the HTTP service 8 | HTTP_TARGET=$(kubectl get service -n "$NAMESPACE" "$SERVICE_NAME" -o json | jq -r '.spec.ports[] | select(.name == "http" and .nodePort) | .nodePort') 9 | 10 | # Get the NodePort for the HTTPS service 11 | HTTPS_TARGET=$(kubectl get service -n "$NAMESPACE" "$SERVICE_NAME" -o json | jq -r '.spec.ports[] | select(.name == "https" and .nodePort) | .nodePort') 12 | 13 | # Print the NodePort targets 14 | echo "HTTP mapping port 80 to NodePort : $HTTP_TARGET" 15 | echo "HTTPS mapping port 443 to NodePort: $HTTPS_TARGET" 16 | 17 | # Set up socat forwarding for port 80 to HTTP target 18 | sudo socat TCP-LISTEN:80,fork TCP:localhost:"$HTTP_TARGET" & 19 | 20 | # Set up socat forwarding for port 443 to HTTPS target 21 | sudo socat TCP-LISTEN:443,fork TCP:localhost:"$HTTPS_TARGET" & 22 | 23 | # Wait for socat processes to finish 24 | echo "use ctrl+c to stop the port mapping" 25 | wait 26 | 27 | -------------------------------------------------------------------------------- /06-install-spring-cloud-gateway.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -euo pipefail 3 | 4 | # read the settings.sh file 5 | readonly GIT_REPO_ROOT=$(git rev-parse --show-toplevel) 6 | source ${GIT_REPO_ROOT}/config/settings.sh 7 | 8 | 9 | readonly VERSION=$(tanzu package available list spring-cloud-gateway.tanzu.vmware.com --namespace tap-install --column version -o json | jq -r '.[0].version') 10 | 11 | # 12 | # Install Spring Cloud Gateway 13 | # 14 | 15 | tanzu package install spring-cloud-gateway \ 16 | --package spring-cloud-gateway.tanzu.vmware.com \ 17 | --version ${VERSION} \ 18 | --namespace tap-install 19 | -------------------------------------------------------------------------------- /07-install-application-configuration-service.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -euo pipefail 3 | 4 | # read the settings.sh file 5 | readonly GIT_REPO_ROOT=$(git rev-parse --show-toplevel) 6 | source ${GIT_REPO_ROOT}/config/settings.sh 7 | 8 | 9 | readonly VERSION=$(tanzu package available list application-configuration-service.tanzu.vmware.com --namespace tap-install --column version -o json | jq -r '.[0].version') 10 | 11 | # 12 | # Install Application Configuration Service 13 | # 14 | 15 | tanzu package install application-configuration-service \ 16 | --package application-configuration-service.tanzu.vmware.com \ 17 | --version ${VERSION} \ 18 | --namespace tap-install \ 19 | --ytt-overlay-file ${GIT_REPO_ROOT}/config/acs-overlay.yaml 20 | -------------------------------------------------------------------------------- /08-install-spring-cloud-service-registry.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -euo pipefail 3 | 4 | # read the settings.sh file 5 | readonly GIT_REPO_ROOT=$(git rev-parse --show-toplevel) 6 | source ${GIT_REPO_ROOT}/config/settings.sh 7 | 8 | 9 | # https://docs.vmware.com/en/VMware-Tanzu-Application-Platform/1.7/tap/service-registry-install-service-registry.html 10 | readonly VERSION=$(tanzu package available list service-registry.spring.apps.tanzu.vmware.com --namespace tap-install --column version -o json | jq -r '.[0].version') 11 | 12 | # 13 | # Install Spring Cloud Service Registry 14 | # 15 | 16 | tanzu package install service-registry \ 17 | --package service-registry.spring.apps.tanzu.vmware.com \ 18 | --version ${VERSION} \ 19 | --namespace tap-install \ 20 | 21 | -------------------------------------------------------------------------------- /09-install-tas-adapter.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -euo pipefail 3 | 4 | # read the settings.sh file 5 | readonly GIT_REPO_ROOT=$(git rev-parse --show-toplevel) 6 | source ${GIT_REPO_ROOT}/config/settings.sh 7 | 8 | 9 | # https://docs.vmware.com/en/Application-Service-Adapter-for-VMware-Tanzu-Application-Platform/1.3/tas-adapter/install.html 10 | readonly VERSION=$(tanzu package available list application-service-adapter.tanzu.vmware.com --namespace tap-install --column version -o json | jq -r '.[0].version') 11 | 12 | 13 | set -x 14 | # 15 | # Setup env vars that will be passed to ytt 16 | # 17 | export TAP_WORKLOAD_REPO=${WORKLOAD_REGISTRY_REPO} 18 | export TAP_BASE_DOMAIN=${BASE_DOMAIN} 19 | export TAP_INGRESS_DOMAIN=${TAP_BASE_DOMAIN} 20 | 21 | # 22 | # Generate tas-adapter-values.yaml file 23 | # 24 | readonly VALUES_FILE_TEMPLATE=${GIT_REPO_ROOT}/config/tas-adapter-values-template.yaml 25 | readonly VALUES_FILE="${GIT_REPO_ROOT}/workspace/generated/tas-adapter-values.yaml" 26 | ytt -f ${VALUES_FILE_TEMPLATE} --data-values-env TAP > ${VALUES_FILE} 27 | 28 | # 29 | # Install the TAS adapter 30 | # 31 | 32 | tanzu package install tas-adapter \ 33 | --package application-service-adapter.tanzu.vmware.com \ 34 | --version ${VERSION} \ 35 | --namespace tap-install \ 36 | --values-file ${VALUES_FILE} 37 | 38 | -------------------------------------------------------------------------------- /20-debug-watch-package-installs.sh: -------------------------------------------------------------------------------- 1 | watch kubectl get pkgi -n tap-install -------------------------------------------------------------------------------- /21-debug-dump-all-kuberentes-objects.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Function to get and filter API resources based on namespaced status 4 | get_filtered_api_resources() { 5 | local is_namespaced=${1} 6 | shift 7 | local exclude_types=("$@") 8 | 9 | #local namespaced_flag=$([ "${is_namespaced}" = true ] && echo "--namespaced=true" || echo "--namespaced=false") 10 | local all_resources=$(kubectl api-resources ${namespaced_flag} --verbs=list -o name | grep -v events) 11 | local filtered_resources=() 12 | 13 | for resource in ${all_resources}; do 14 | local exclude=false 15 | for exclude_type in "${exclude_types[@]}"; do 16 | echo ${resource} 17 | echo ${exclude_type} 18 | if [[ "${resource}" == "${exclude_type}" ]]; then 19 | exclude=true 20 | break 21 | fi 22 | done 23 | if [[ "${exclude}" = false ]]; then 24 | filtered_resources+=("${resource}") 25 | fi 26 | done 27 | 28 | echo "${filtered_resources[@]}" 29 | } 30 | 31 | # Function to list resources in a namespace in wide format 32 | list_namespace_resources() { 33 | local namespace=${1} 34 | local namespaced_resources=$(kubectl api-resources ${namespaced_flag} --verbs=list -o name --namespaced=true | grep -v events) 35 | 36 | 37 | echo -e "\n\n====================================================================================================" 38 | echo "Listing objects in Namespace: ${namespace}" 39 | echo "====================================================================================================" 40 | 41 | 42 | for resource in ${namespaced_resources[@]}; do 43 | local command="kubectl get ${resource} -n ${namespace} -o wide" 44 | local output=$(${command} 2>/dev/null) 45 | if [ -n "${output}" ]; then 46 | echo "Executing: ${command}" 47 | echo "${output}" 48 | echo "" 49 | fi 50 | done 51 | } 52 | 53 | # Function to list cluster-wide resources in wide format 54 | list_cluster_resources() { 55 | local cluster_resources=$(kubectl api-resources ${namespaced_flag} --verbs=list -o name --namespaced=false | grep -v events) 56 | 57 | 58 | echo -e "\n\n====================================================================================================" 59 | echo "Listing cluster-wide resources (excluding events)" 60 | echo "====================================================================================================" 61 | 62 | for resource in ${cluster_resources[@]}; do 63 | local command="kubectl get ${resource} -o wide" 64 | local output=$(${command} 2>/dev/null) 65 | if [ -n "${output}" ]; then 66 | echo "Executing: ${command}" 67 | echo "${output}" 68 | echo "" 69 | fi 70 | done 71 | } 72 | 73 | # Function to get and list resources in all non-system namespaces 74 | list_all_non_system_namespaces_resources() { 75 | local system_namespaces=("kube-system" "kube-public" "kube-node-lease") 76 | local namespaces=$(kubectl get ns -o jsonpath="{.items[*].metadata.name}") 77 | 78 | for namespace in ${namespaces}; do 79 | if [[ ! " ${system_namespaces[@]} " =~ " ${namespace} " ]]; then 80 | list_namespace_resources "${namespace}" 81 | fi 82 | done 83 | } 84 | 85 | # List cluster-wide resources 86 | list_cluster_resources 87 | 88 | # List resources in all non-system namespaces 89 | list_all_non_system_namespaces_resources 90 | -------------------------------------------------------------------------------- /22-debug-dump-package-bundles.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # 4 | # This script dumps out all the Package definitions for TAP that are 5 | # installed in the cluster, each package is put into a folder under 6 | # cluster director tmp/packages 7 | # 8 | # This script is useful to better understand how TAP packages are installed 9 | # 10 | 11 | set -euo pipefail 12 | 13 | # 14 | # read the install settings.sh 15 | # 16 | readonly GIT_REPO_ROOT=$(git rev-parse --show-toplevel) 17 | source ${GIT_REPO_ROOT}/config/settings.sh 18 | 19 | function dump-package() { 20 | local NAME_SPACE=${1} 21 | local PACKAGE_NAME=${2} 22 | local OUTPUT_DIR=${3}/${PACKAGE_NAME} 23 | local IMAGE_BUNDLE=$( \ 24 | kubectl get package ${PACKAGE_NAME} \ 25 | -n ${NAME_SPACE} \ 26 | -o=jsonpath='{.spec.template.spec.fetch[0].imgpkgBundle.image}' 27 | ) 28 | 29 | mkdir -p ${OUTPUT_DIR} 30 | imgpkg pull -b ${IMAGE_BUNDLE} -o ${OUTPUT_DIR} 31 | } 32 | 33 | function dump-all-packages() { 34 | local NAME_SPACE=${1} 35 | local OUTPUT_DIR=${2} 36 | 37 | local PACKAGE_NAMES=$( 38 | kubectl get package -n ${NAME_SPACE} -o custom-columns=":metadata.name" 39 | ) 40 | 41 | for PACKAGE_NAME in ${PACKAGE_NAMES} 42 | do 43 | dump-package ${NAME_SPACE} ${PACKAGE_NAME} ${OUTPUT_DIR} 44 | done 45 | } 46 | 47 | dump-all-packages tap-install ${GIT_REPO_ROOT}/workspace/packages -------------------------------------------------------------------------------- /23-debug-dump-package-repository.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # 4 | # This scripts dumps out the contents of the tap-packages repositories 5 | # allowing for the ispection of the Package and PackageMetadata objects 6 | # 7 | 8 | set -euo pipefail 9 | 10 | # 11 | # read the install settings.sh 12 | # 13 | readonly GIT_REPO_ROOT=$(git rev-parse --show-toplevel) 14 | source ${GIT_REPO_ROOT}/config/settings.sh 15 | 16 | # 17 | # Dump the package repo 18 | # 19 | imgpkg pull -b \ 20 | ${TANZU_NET_REGISTRY_HOST}/tanzu-application-platform/tap-packages:${TAP_VERSION} \ 21 | -o ${GIT_REPO_ROOT}/workspace/repositories/tap-packages-${TAP_VERSION} -------------------------------------------------------------------------------- /24-debug-dump-cartographer-objects.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # 4 | # This scripts dumps out all the Cartogarpher Custom Resources that are used 5 | # to define supply chains and cluster Tekton objects because they might be 6 | # used by the runnable tasks in the supply chains 7 | # 8 | 9 | set -euo pipefail 10 | 11 | # 12 | # helper functions to dump out all instances of a particular type of 13 | # Kuberentes object as YAML file into a directory structure named after 14 | # the type of object 15 | # 16 | dump-object() { 17 | local TYPE=${1} 18 | local NAME=${2} 19 | local OUTPUT_DIR=${3} 20 | 21 | kubectl get ${TYPE} ${NAME} --ignore-not-found=true -o YAML > ${OUTPUT_DIR}/${NAME}.yaml 22 | } 23 | 24 | dump-all-objects() { 25 | local TYPE=${1} 26 | local OUTPUT_DIR=${2}/${TYPE} 27 | 28 | mkdir -p ${OUTPUT_DIR} 29 | 30 | echo "" 31 | echo "Dumping objects from cluster" 32 | 33 | for name in $(kubectl get ${TYPE} --ignore-not-found=true --no-headers -o custom-columns=":metadata.name") 34 | do 35 | echo "Extracting ${TYPE} ${name}" 36 | dump-object ${TYPE} ${name} ${OUTPUT_DIR} 37 | done 38 | } 39 | 40 | 41 | # 42 | # Dump objects needed to understand what the supply chain is doing 43 | # 44 | function dump-cartographer-objects() { 45 | local DUMP_DIR=workspace/cartographer/ 46 | dump-all-objects ClusterSupplyChain ${DUMP_DIR} 47 | dump-all-objects ClusterDelivery ${DUMP_DIR} 48 | dump-all-objects ClusterSourceTemplate ${DUMP_DIR} 49 | dump-all-objects ClusterImageTemplate ${DUMP_DIR} 50 | dump-all-objects ClusterConfigTemplate ${DUMP_DIR} 51 | dump-all-objects ClusterDeploymentTemplate ${DUMP_DIR} 52 | dump-all-objects ClusterTemplate ${DUMP_DIR} 53 | dump-all-objects ClusterRunTemplate ${DUMP_DIR} 54 | dump-all-objects ClusterTask ${DUMP_DIR} 55 | } 56 | 57 | dump-cartographer-objects 58 | 59 | -------------------------------------------------------------------------------- /30-delete-tap.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -euo pipefail 3 | 4 | # read the settings.sh file 5 | readonly GIT_REPO_ROOT=$(git rev-parse --show-toplevel) 6 | source ${GIT_REPO_ROOT}/config/settings.sh 7 | 8 | # 9 | # Display a warning message and prompt the user for confirmation 10 | # 11 | readonly WARNING="WARNING: The following items will be deleted: 12 | 1. All workload namespaces configured by namespace provisioner apps.tanzu.vmware.com/tap-ns 13 | 2. Spring Cloud Gateway package 14 | 3. Application Configuration Service package 15 | 4. Tanzu Application Platform (tap) package 16 | 5. tap-install namespace 17 | 6. Secret-gen controller 18 | 7. kapp-controller 19 | 8. tanzu-cluster-essentials namespace 20 | 9. crossplane provisioned resources 21 | 22 | Are you sure you want to proceed? (y/N): " 23 | 24 | echo "${WARNING}" 25 | read -r -p "" RESPONSE 26 | 27 | case "$RESPONSE" in 28 | [yY][eE][sS]|[yY]) 29 | # Proceed with deletion 30 | ;; 31 | *) 32 | echo "Delete operation aborted." 33 | exit 1 34 | ;; 35 | esac 36 | 37 | # 38 | # Delete all the parts of a tap instalation in reverse order from which they created 39 | # 40 | 41 | # Delete all workload namespaces configured by namespace provisioner apps.tanzu.vmware.com/tap-ns 42 | kubectl delete namespaces -l apps.tanzu.vmware.com/tap-ns 43 | 44 | # Delete Spring Cloud Gateway package 45 | tanzu package installed delete spring-cloud-gateway --namespace tap-install --yes 46 | 47 | # Delete Application Configuration Service package 48 | tanzu package installed delete application-configuration-service --namespace tap-install --yes 49 | 50 | # Delete Tanzu Application Platform (tap) package 51 | tanzu package installed delete tap --namespace tap-install --yes 52 | 53 | # Delete tap-install namespace 54 | kubectl delete namespace tap-install --ignore-not-found 55 | 56 | # Delete secret-gen controller 57 | kapp delete -a secretgen-controller -n tanzu-cluster-essentials --yes 58 | 59 | # Delete kapp-controller 60 | kapp delete -a kapp-controller -n tanzu-cluster-essentials --yes 61 | 62 | # Delete tanzu-cluster-essentials namespace 63 | kubectl delete namespace tanzu-cluster-essentials --ignore-not-found 64 | 65 | # 66 | # Crosspalne was installed and tap values has been configured to make 67 | # sure all crossplane objects are deleted, but it seems one object is forgotten 68 | kubectl delete validatingwebhookconfigurations.admissionregistration.k8s.io crossplane --ignore-not-found 69 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # local-tap 2 | This repository contains scripts to install Tanzu Application Platform (TAP) on 3 | Docker Desktop Kubernetes. It enables a single-user TAP deployment for experimentation 4 | and educational purposes. 5 | 6 | ## Prerequisites 7 | 8 | To complete the installation, you need to have the following ready: 9 | 10 | 0. Docker Desktop with Kubernetes turned on. You can probably use Minikube 11 | if you wish. Contributions documenting how to use the scripts 12 | in this repository with Minikube are welcome. 13 | 14 | 1. Username and password for the Tanzu Network that can be used to access the Tanzu 15 | container registry where all the container images for TAP are stored. You need 16 | to accept the EULA (see [docs](https://docs.vmware.com/en/VMware-Tanzu-Application-Platform/1.7/tap/install-tanzu-cli.html)) 17 | otherwise, your container image pulls will fail. 18 | 19 | 2. A container registry where you can publish container images, such as 20 | [GitHub Packages](ghcr.io), [Google Artifact Registry](https://cloud.google.com/artifact-registry), 21 | [Azure Container Registry](https://azure.microsoft.com/en-us/products/container-registry), 22 | or [Harbor](https://goharbor.io/). 23 | 24 | 3. A GitHub OAuth application configured to allow login to the TAP deployment. 25 | You will need the client ID and client secret. 26 | 27 | 4. A variety of common CLI tools installed. You probably have them. If not, you can 28 | easily install them. `00-validate-clis-are-installed.sh` script checks your 29 | system to see if it has the right CLIs installed. 30 | 31 | 5. (Optional) A DNS domain that points to 127.0.0.1. You can use *.local.tanzu.ca 32 | if you don't have your own domain. By having a wildcard DNS entry that points back 33 | to localhost, we can end up with a domain name such as tap-gui.tap.local.tanzu.ca 34 | that works on the laptop running TAP on Docker Desktop. If you don't have 35 | a DNS server, you can just use local.tanzu.ca. 36 | 37 | ### Common CLI Tools used in this repository 38 | 39 | * [Carvel Tools](https://carvel.dev) 40 | * [imgpkg](https://carvel.dev/imgpkg/docs/latest) - image packaging utility 41 | * [ytt](https://carvel.dev/ytt/docs/latest) - templating and patching YAML 42 | * [kbld](https://carvel.dev/kbld/docs/latest) - image building and packing using SHA references 43 | * [kapp](https://carvel.dev/kapp/docs/latest) - k8s applications 44 | * [Tanzu CLI](https://docs.vmware.com/en/VMware-Tanzu-Application-Platform/1.7/tap/install-tanzu-cli.html) - Tanzu CLI tool 45 | * [kubectl](https://kubernetes.io/docs/reference/kubectl/) - k8s CLI tool 46 | * [jq](https://jqlang.github.io/jq/) - JSON CLI processor (querying and parsing) 47 | * [socat](https://linux.die.net/man/1/socat) - SOcket CAT, multipurpose relay 48 | 49 | ### Installing CLI Tools on Mac using `brew` 50 | 51 | ```shell 52 | brew tap vmware-tanzu/carvel 53 | brew install ytt kbld kapp kwt imgpkg vendir kctrl 54 | ``` 55 | 56 | ```shell 57 | brew install kubernetes-cli 58 | ``` 59 | 60 | ```shell 61 | brew install jq 62 | ``` 63 | 64 | ```shell 65 | brew install socat 66 | ``` 67 | 68 | ```shell 69 | brew tap vmware-tanzu/carvel 70 | brew install tanzu-cli 71 | tanzu plugin install --group vmware-tap/default 72 | ``` 73 | 74 | ## How Networking Works When Deploying on Docker Desktop Kubernetes 75 | 76 | By default, TAP deploys the Contour ingress controller using a Kubernetes LoadBalancer service. 77 | To avoid problems with the LoadBalancer service on a dev machine running Docker Desktop or Minikube, 78 | we change the configuration of TAP to use a NodePort Service instead. 79 | 80 | Once TAP is up and running, it will be exposed on two random port numbers selected by 81 | Kubernetes. You can run the script `05-proxy-traffic.sh`, which maps ports 80 and 443 82 | on your machine to the NodePort values selected by Kubernetes. The script uses 83 | the `socat` utility. 84 | 85 | If you use the default `tap.local.tanzu.ca` base domain, then you can find the TAP GUI 86 | at [https://tap-gui.tap.local.tanzu.ca](https://tap-gui.tap.local.tanzu.ca). 87 | 88 | ## Deploy TAP on Docker Desktop Kubernetes 89 | 90 | The installation process is done via a series of scripts located at the root of 91 | the repository. The scripts are idempotent; you can run them multiple times, and they 92 | should pick up where they left off. 93 | 94 | 1. Run the script `00-validate-clis-are-installed.sh` to check that all 95 | the required CLIs are installed on your machine. 96 | 97 | 2. Copy the `config/settings-template.sh` file to `config/settings.sh`. 98 | 99 | 3. Edit the `config/settings.sh` file with your own values. There are many 100 | comments in `settings.sh` to guide you along. 101 | 102 | 4. Run the script `01-validate-registry-access-and-credentials.sh` to check 103 | that the TAP registry and the workload registry can be accessed from your machine. 104 | 105 | 5. Run the script `02-install-cluster-essentials.sh` to install kapp-controller 106 | and SecretGen controller on your cluster. 107 | 108 | 6. Run the script `03-configure-tap-install-namespace.sh` to prepare the tap-install namespace. 109 | 110 | 7. Run the script `04-install-tap.sh` to install all the TAP packages. This will take 111 | 5 to 15 minutes depending on your internet connection speed and the amount of resources 112 | available to your Docker Desktop Kubernetes. You can monitor progress by running the script 113 | `20-debug-watch-package-installs.sh`. 114 | 115 | 8. When all the TAP packages are reconciled, run the script `05-proxy-traffic.sh` to 116 | map ports 80 and 443 to the Contour ingress node ports. 117 | 118 | 9. Optionally, install Spring Cloud Gateway using the scripts `06-install-spring-cloud-gateway.sh` and 119 | `07-install-application-configuration-service.sh`. 120 | 121 | ## Validate the Installation of TAP 122 | 123 | 1. Using your web browser, go to [https://tap-gui.tap.local.tanzu.ca](https://tap-gui.tap.local.tanzu.ca). 124 | If you picked a different base domain, use that. You will receive a warning from the browser because the 125 | installation is using a self-signed certificate; ignore those warnings. 126 | 127 | 2. Log in to the TAP GUI using your GitHub ID. If you have issues here, it is probably because the 128 | GitHub OAuth app is misconfigured, or you don't have the correct client ID and secret. Check those 129 | settings and try again. 130 | 131 | 3. The `dev` folder contains a namespace labeled for TAP namespace provisioner. Run 132 | `kubectl apply -f dev/namespace.yaml` to create the namespace. 133 | 134 | 4. To deploy a demo workload, open the file `dev/workload.yaml` and follow the instructions in the comments 135 | at the bottom of the file. The first time you deploy a workload, it will take more time while things 136 | are initialized and warmed up. 137 | 138 | 5. When the deployment is done, you can register the software catalog entity for it using the URL 139 | `https://github.com/asaikali/tanzu-java-web-app/blob/main/catalog/catalog-info.yaml` or your own 140 | catalog entry. After registration, you can navigate to the app in the software catalog, and everything 141 | should work just fine, such as app live view, etc. 142 | 143 | 144 | ## Install TAS Adapter 145 | 146 | 1. run the command `09-install-tas-adapter.sh` to install the TAS Adapter 147 | 148 | 2. run the command `cf api api.tap.local.tanzu.ca --skip-ssl-validation` to point the cf cli at the TAS adapter 149 | 150 | 3. run the command `cf login` and it will log you in 151 | 152 | 4. create an org using the command `cf create-org test` 153 | 154 | 5. target the org with `cf target -o test` 155 | 156 | 6. create a dev space `cf create-space -o test dev` 157 | 158 | 7. cf target -s dev 159 | 160 | 8. Clone the default cf sample app `git clone https://github.com/cloudfoundry-samples/spring-music` 161 | 162 | 9. Compile the app with `./gradlew build` 163 | 164 | 10. deploy the app with `cf push` 165 | 166 | 167 | ## Debug the Installation 168 | 169 | There is a set of scripts starting in the 20 range that you can use to debug the state of the 170 | installation. 171 | 172 | 1. `20-debug-watch-package-installs.sh` puts a watch on the package installs; you can use it to monitor 173 | the progress or deletion of a TAP cluster. 174 | 175 | 2. `21-debug-dump-all-kubernetes-objects.sh` prints out every Kubernetes object in the cluster other than 176 | events and objects in the system namespaces that start with `kube` in their name. 177 | 178 | 3. `22-debug-dump-package-bundles.sh` will dump out all the Carvel packages that are part of the TAP 179 | package repository or any other package repository in the `tap-install` namespace. The packages are 180 | written to the `workspace/packages` folder. When you run into issues during the install, inspecting the 181 | source code in the Carvel package can help you understand the root cause of the issue you are 182 | troubleshooting. 183 | 184 | 4. `23-debug-dump-cartographer-objects.sh` will dump out all the components of the supply chain 185 | configured on the TAP installation. You can also look at the source code of the supply chains 186 | in the `workspace/packages` folder by locating the packages of the supply chain you are 187 | interested in. 188 | 189 | ## Delete the Installation 190 | 191 | 1. You can delete the installation by running the script `30-delete-tap.sh`, or if you prefer, you can 192 | just reset the Kubernetes cluster in Docker Desktop. 193 | 194 | ## Directory layout 195 | 196 | * `config/` contains configuration files for deploying tap 197 | * `dev/` contains sample workload and k8s yaml file to get started 198 | * `workspace/` used by the scripts to store temporary state, you will find many interesting things in this folder as you run the scripts 199 | 200 | ## Resources 201 | 202 | * [Tanzu Application Platform Docs](https://docs.vmware.com/en/VMware-Tanzu-Application-Platform/index.html) 203 | * [Tanzu CLI Docs](https://docs.vmware.com/en/VMware-Tanzu-CLI/index.html) 204 | * [Carvel Website](https://carvel.dev/) 205 | * [Cartographer](https://cartographer.sh/) 206 | * [Crossplane](https://www.crossplane.io/) 207 | * [Backstage](https://backstage.io/) 208 | -------------------------------------------------------------------------------- /config/acs-overlay.yaml: -------------------------------------------------------------------------------- 1 | #@ load("@ytt:overlay", "overlay") 2 | 3 | #@overlay/match by=overlay.subset({"kind": "Deployment", "metadata": {"name": "application-configuration-service"}}) 4 | --- 5 | spec: 6 | template: 7 | spec: 8 | containers: 9 | #@overlay/match by="name" 10 | - name: application-configuration-service 11 | resources: 12 | limits: 13 | #@overlay/remove 14 | cpu: null 15 | #@overlay/replace 16 | memory: 768Mi 17 | requests: 18 | #@overlay/replace 19 | memory: 768Mi 20 | #@overlay/match missing_ok=True 21 | livenessProbe: 22 | #@overlay/match missing_ok=True 23 | initialDelaySeconds: 30 24 | #@overlay/match missing_ok=True 25 | readinessProbe: 26 | #@overlay/match missing_ok=True 27 | initialDelaySeconds: 30 28 | #@overlay/match missing_ok=True 29 | startupProbe: 30 | #@overlay/match missing_ok=True 31 | initialDelaySeconds: 30 32 | -------------------------------------------------------------------------------- /config/contour-overlay.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Secret 3 | metadata: 4 | name: contour-overlay 5 | namespace: tap-install 6 | stringData: 7 | custom-package-overlay.yml: | 8 | #@ load("@ytt:overlay", "overlay") 9 | 10 | #! Overlay for the "contour" Deployment we don't need two deployments since we are using a simple test install on docker desktop 11 | #@overlay/match by=overlay.subset({"kind": "Deployment", "metadata": {"name": "contour"}}) 12 | --- 13 | spec: 14 | #@overlay/replace 15 | replicas: 1 16 | 17 | #! Overlay for the "envoy" Deployment, we are deploying on a single node requiring more than one replica means that the package will never reconcile 18 | #@overlay/match by=overlay.subset({"kind": "Deployment", "metadata": {"name": "envoy"}}) 19 | --- 20 | spec: 21 | #@overlay/replace 22 | replicas: 1 23 | -------------------------------------------------------------------------------- /config/settings-template.sh: -------------------------------------------------------------------------------- 1 | # Settigs file to deploy a local TAP on docker desktop kubernetes 2 | 3 | #---- DNS Settings -------------------------------------- 4 | # 5 | # This domain should be mapped to 127.0.0.1 in public DNS server 6 | # using a wildcard for example in this case below *.local.tanzu.ca returns 7 | # 127.0.0.1 you can use the base domain below without changing this value 8 | # 9 | readonly BASE_DOMAIN="tap.local.tanzu.ca" 10 | 11 | #---- tanzu net settings --------- 12 | # 13 | # Tanzu container registry is used as the source of the all the packages 14 | # to deploy tap. configure the creds to access tanzu net. 15 | # 16 | readonly TANZU_NET_REGISTRY_HOST=registry.tanzu.vmware.com 17 | readonly TANZU_NET_USERNAME= 18 | readonly TANZU_NET_PASSWORD= 19 | 20 | #----- workload registry settings --- 21 | # 22 | # Tanzu Build Service and the supply chain publish workload container images 23 | # to a container registry. Settings below are where workload images will be 24 | # published to 25 | # 26 | readonly WORKLOAD_REGISTRY_HOST= 27 | readonly WORKLOAD_REGISTRY_USERNAME= 28 | readonly WORKLOAD_REGISTRY_PASSWORD= 29 | readonly WORKLOAD_REGISTRY_REPO=${WORKLOAD_REGISTRY_HOST}/tap 30 | 31 | #---- TAP GUI Auth with GitHub Settings -------------------------------------- 32 | 33 | # 34 | # Backstage based TAP GUI can login users with OpenID Connect, the scripts 35 | # in this deployment configure TAP GUI to login users using thier GitHUB 36 | # IDs you will need to provision a GitHub App in your developer settings 37 | # on the https://github.com/settings/developers page. On the App setting 38 | # page set the app home page and callback urls to point the URL of where 39 | # TAP GUI is running for example "https://tap-guit.tap.local.tanzu.ca" works 40 | # if you are using the localhost based domain name from above. You will 41 | # need to copy and paste the client id and secret from the Github settings 42 | # page into these env vars so that TAP GUI can be configured correctly. 43 | # 44 | 45 | readonly GITHUB_CLIENT_ID= 46 | readonly GITHUB_CLIENT_SECRET= 47 | 48 | #---- Software Versions to install ----------------------- 49 | readonly CLUSTER_ESSENTIALS_LOCK_FILE=tanzu-cluster-essentials-bundle-1.7.2.yml 50 | readonly TAP_VERSION=1.7.2 51 | 52 | 53 | -------------------------------------------------------------------------------- /config/tanzu-cluster-essentials-bundle-1.7.2.yml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: imgpkg.carvel.dev/v1alpha1 3 | bundle: 4 | image: registry.tanzu.vmware.com/tanzu-cluster-essentials/cluster-essentials-bundle@sha256:c75374a9162b379a05d7852f8d98b6dcb5fe17e706b27bf736cdcdebf25f0804 5 | tag: 1.7.2 6 | kind: BundleLock 7 | -------------------------------------------------------------------------------- /config/tap-values-template.yaml: -------------------------------------------------------------------------------- 1 | #@ load("@ytt:data", "data") 2 | 3 | profile: full 4 | 5 | #! Installation fails if this is not set to true. Not a string. 6 | ceip_policy_disclosed: true 7 | 8 | package_overlays: 9 | - name: contour 10 | secrets: 11 | - name: contour-overlay 12 | 13 | shared: 14 | ingress_domain: #@ data.values.INGRESS_DOMAIN 15 | image_registry: 16 | #! To be used by Build Service by appending "/buildservice" and used by Supply chain by appending "/workloads". 17 | project_path: #@ data.values.WORKLOAD_REPO 18 | secret: 19 | name: "workload-registry" 20 | namespace: "tap-install" 21 | 22 | contour: 23 | envoy: 24 | service: 25 | type: NodePort 26 | 27 | supply_chain: basic 28 | 29 | #@ baseUrl = "https://tap-gui." + data.values.INGRESS_DOMAIN 30 | tap_gui: 31 | service_type: ClusterIP 32 | app_config: 33 | app: 34 | baseUrl: #@ baseUrl 35 | catalog: 36 | locations: 37 | - type: url 38 | target: #@ data.values.CATALOG_INFO 39 | backend: 40 | baseUrl: #@ baseUrl 41 | cors: 42 | origin: #@ baseUrl 43 | auth: 44 | environment: development 45 | providers: 46 | github: 47 | development: 48 | clientId: #@ data.values.GITHUB_CLIENT_ID 49 | clientSecret: #@ data.values.GITHUB_CLIENT_SECRET 50 | 51 | #! this will mean that when tap package is delete it deletes all the components of crossplane 52 | #! see docs at https://docs.vmware.com/en/VMware-Tanzu-Application-Platform/1.7/tap/crossplane-how-to-guides-delete-resources.html 53 | crossplane: 54 | orphan_resources: false -------------------------------------------------------------------------------- /config/tas-adapter-values-template.yaml: -------------------------------------------------------------------------------- 1 | #@ load("@ytt:data", "data") 2 | 3 | ceip_policy_disclosed: true 4 | app_registry: 5 | credentials: 6 | secret_name: "workload-registry" 7 | namespace: "tap-install" 8 | repository_prefix: #@ data.values.WORKLOAD_REPO 9 | 10 | api_ingress: 11 | fqdn: #@ "api." + data.values.INGRESS_DOMAIN 12 | app_ingress: 13 | default_domain: #@ "cfapps." + data.values.INGRESS_DOMAIN 14 | 15 | admin: 16 | users: 17 | - docker-desktop 18 | - docker-for-desktop -------------------------------------------------------------------------------- /dev/namespace.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Namespace 3 | metadata: 4 | name: dev 5 | labels: 6 | apps.tanzu.vmware.com/tap-ns: "" -------------------------------------------------------------------------------- /dev/workload.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: carto.run/v1alpha1 2 | kind: Workload 3 | metadata: 4 | name: tanzu-java-web-app 5 | labels: 6 | apps.tanzu.vmware.com/workload-type: web 7 | app.kubernetes.io/part-of: tanzu-java-web-app 8 | spec: 9 | params: 10 | - name: annotations 11 | value: 12 | autoscaling.knative.dev/minScale: "1" 13 | source: 14 | git: 15 | url: https://github.com/asaikali/tanzu-java-web-app.git 16 | ref: 17 | branch: main 18 | 19 | 20 | 21 | # tanzu apps workload list -n dev 22 | # tanzu apps workload apply -f workload.yaml -n dev 23 | # tanzu apps workload update -f workload.yaml -n dev 24 | # tanzu apps workload get tanzu-java-web-app -n dev 25 | # tanzu apps workload tail tanzu-java-web-app -n dev --since 1h 26 | # tanzu apps workload delete tanzu-java-web-app -n dev 27 | 28 | # kubectl tree workload tanzu-java-web-app -n dev 29 | -------------------------------------------------------------------------------- /workspace/readme.txt: -------------------------------------------------------------------------------- 1 | this folder is a temporary working folder used by the install scripts --------------------------------------------------------------------------------