In this post I want to provide you a write up of adding (Backstage) plugins to Tanzu Developer Portal. Tanzu Developer Portal is VMware’s commercial Backstage offering and is part of Tanzu Application Platform. On top of the Developer Portal, Tanzu Application Platform support a set of VMware provided (commerical) plugins as well as supply chain choreographer based on the Cartographer project. The supply chain choreographer provides a “CI/CD-like” experience for your cloud-native Kubernetes based applications, and includes capabilities that brings your cloud-native apps from idea-to-production in an automated and secure way (including unit testing/code analysis/container scanning etc.).
Backstage is an open platform to build developer portals, in case of Tanzu Application Platform VMware is providing you with a pre-packaged version Backstage. If’ve had several questions coming from customers: “Can we add Backstage plugins to Tanzu Application Platform/Tanzu Developer Platform (TDP)”. The answer to this is yes! But, because normally adding plugins requires to rebuild the actual Backstage image/executable, the approach is a bit different when with TDP. Before you can use a Backstage plugin you have to pack it inside of a tiny wrapper, that is then on its turn integrated into TDP. Since TAP 1.6.1 the TDP Configurator is provided (beta status currently) that allows you to build wrapped Backstage plugins and add these plugins to your TDP installation.
Before we continue and learn more about this process, I want to point you at two different sources that I used and were very valuable for me:
- The official documentation around the topic.
- An excellent workshop coming from my colleague Timo Salm that guides you through the process. You can do this workshop yourself on VMware’s (TAP) Developer Sandbox available on tanzu.academy.
The goal of this blogpost is to go through the whole process on a “regular” TAP environment, give a high level overview of the different steps and provide some additional context on the different steps (using screenshots) so you understand what the expected results are of the different steps.
I am running through the process on a TAP environment that is deployed by TMC as explained in previous blogposts here and here. The TAP environment is running on Azure Kubernetes Service. I am mainly following the steps as laid out in the workshop, with some customizations here and there. There is a minor change to the process as documented in the official documentation if you want to get everything to work in a TAP environment to is being deployed by TMC. More on that later in this post.
So, what do you need to get started:
- A working installation of TAP that is capable of deploying applications.
- Carvel tools on your workstation, in this blogpost both ytt and imgpkg are used.
- Docker on your local workstation make things a bit easier.
- In this example we will deploy a TDP preconfigured Backstage plugin that’s available on npmjs.com here.
So, what are the steps we’re going through?
- Create a TDP configuration file (tdp-config.yaml) that contains your (Backstage) plugin configuration.
- Identify the Configurator (container) image. This image is used as the source for your the wrapper for your Backstage plugin.
- Create an additional custom supply chain in Cartographer on Tanzu Application Platform. The input of the supply chain is the image retrieved in the previous step (2), the output of the supply chain is an image that is used to run your customized TDP (that includes the required plugin(s)).
- Build the the image using the new supply chain created in step (3).
- Identify the customized image reference that was built in the previous step (4).
- Prepare to overlay your customized image onto the currently running instance and update tap-values.yaml to include your plugin in TDP.
Create a TDP configuration file
So, let’s get started and create a configuration file for a plugin. In this example we’re going to deploy one of the validated plugins.
Validated plug-ins are Backstage plug-ins or community plug-ins that VMware has validated for use with Tanzu Developer Portal. You don’t need to create custom wrappers to integrate these plug-ins with Tanzu Developer Portal.
So – in this example we’re not going to create the actual wrapper (that’s for a follow up post) but deploy a Backstage plugin that’s already wrapped and available at npmjs.com Tanzu repository.
The TechInsights plugin is a very basic plugin and also used in the official documentation as well as Timo’s workshop. The configuration for this plugin is:
app: plugins: - name: "@vmware-tanzu/tdp-plugin-techinsights" version: "0.0.2" backend: plugins: - name: "@vmware-tanzu/tdp-plugin-techinsights-backend" version: "0.0.2"
Identify the Configurator (container) image
The next step is to identify the configurator image, we use imgpkg for this. The configurator image can be stored on three different locations depending on the kind of installation you’re running:
- On your private registry if you’ve copied the TAP installation files to a private registry
- On registry.tanzu.vmware.com registry in the tanzu-application-platform repository if you’ve installed TAP yourself either manually or through the GitOps installation option.
- On registry.tanzu.vmware.com registry in the vmware-tap-packages repository if you’ve installed TAP using Tanzu Mission Control.
The third option is applicable to my situation. In step 1 and 2 you’re logging on the registry yourself, in situation 3 a robot account is created by TMC that logs you on to the registry. You need to retrieve username + password of this robot account. The credentials are stored in the (a.o.) tap-gui-fetch-0 secret in the tap-install namespace.
Retrieve the username with:
kubectl get secret tap-gui-fetch-0 -n tap-install -o jsonpath='{.data.\.dockerconfigjson}' | base64 --decode | yq '.auths.["registry.tanzu.vmware.com"].username'
Retrieve the password with:
kubectl get secret tap-gui-fetch-0 -n tap-install -o jsonpath='{.data.\.dockerconfigjson}' | base64 --decode | yq '.auths.["registry.tanzu.vmware.com"].password'
Now use these credentials to logon to the registry.tanzu.vmware.com registry. If you’re using method 1 or 2, use either the login credentials for your private registry or your own credentials for registry.tanzu.vmware.com.
docker login registry.tanzu.vmware.com
Now use these two commands that are coming from Timo’s workshop again:
CONFIGURATOR_IMAGE_BUNDLE=$(kubectl get -n tap-install $(kubectl get package -n tap-install \ --field-selector spec.refName=tpb.tanzu.vmware.com -o name) -o \ jsonpath="{.spec.template.spec.fetch[0].imgpkgBundle.image}") && echo $CONFIGURATOR_IMAGE_BUNDLE
This will retrieve the configurator image bundle.
Now use the environment variable to retrieve the name of the image:
export CONFIGURATOR_IMAGE=$(imgpkg describe -b $CONFIGURATOR_IMAGE_BUNDLE -o yaml --tty=true | grep -A 1 \ "kbld.carvel.dev/id: harbor-repo.vmware.com/esback/configurator" | grep "image: " | sed 's/^[[:space:]]*image: //g') && echo $CONFIGURATOR_IMAGE
The result will look similar to:
Create an additional custom supply chain in Cartographer on Tanzu Application Platform
The next step is to configure an additional custom supply chain in Cartographer on TAP that will be responsible to build the custom image for your TDP.
export REGISTRY_HOSTNAME=$(kubectl get clustersupplychain source-test-scan-to-url -o jsonpath='{.spec.resources[?(@.name=="image-provider")].params[?(@.name=="registry")].value.server}') export IMAGE_REPOSITORY=$(kubectl get clustersupplychain source-test-scan-to-url -o jsonpath='{.spec.resources[?(@.name=="image-provider")].params[?(@.name=="registry")].value.repository}')
Note that depending on which OOTB supply chain you’re using, the source-test-scan-to-url can be something different. Use
kubectl get clustersupplychain
to determine which supply chain(s) are in use on your TAP installation.
REGISTRY_HOSTNAME and IMAGE_REPOSITORY will contain the registry and repository that is used for workloads that are build in your environment.
Now build the supply chain:
ytt -f tdp-sc-template.yaml -v tdp_configurator.sc.registry_server=$REGISTRY_HOSTNAME -v tdp_configurator.sc.registry_repository=$IMAGE_REPOSITORY | kubectl apply -f -
The tdp-sc-template.yaml file is available here.
And check that it’s available:
kubectl get clustersupplychain
(tdp-configurator is the new supply chain).
Build the the image using the new supply chain
Now we can build the actual image by creating and applying a workload.yaml to our new supply chain:
ytt -f tdp-workload-template.yaml -v tdp_configurator.image=$(echo $CONFIGURATOR_IMAGE) --data-value-file tdp_configurator.config=tdp-config.yaml | tanzu apps workload create -y -f -
The required file(s) are available here.
If you want to first see the contents of the workload.yaml then use:
ytt -f tdp-workload-template.yaml -v tdp_configurator.image=$(echo $CONFIGURATOR_IMAGE) --data-value-file tdp_configurator.config=tdp-config.yaml
You can follow the build process using
tanzu apps workload tail tdp-config --timestamp --since 1h
or open the TAP GUI
The actual build process will take a couple of minutes.
Identify the customized image reference
Now it’s time to identify the newly created image using this comand:
export CUSTOM_TDP_IMAGE=$(kubectl get images.kpack.io tdp-config -o jsonpath={.status.latestImage}) && echo $CUSTOM_TDP_IMAGE
This image is hosted on my private registry, that is (in this example) running on Azure.
Prepare to overlay your customized image onto the currently running instance and update tap-values.yaml
Now the last step is to create an overlay secret so TDP knows the configuration of your plugin:
ytt -f tdp-overlay-secret-template.yaml -v tdp_configurator.custom_image=$CUSTOM_TDP_IMAGE --data-value-yaml tdp_configurator.full_dependencies=false | kubectl apply -n tap-install -f -
The file tdp-overlay-secret-template.yaml is available here.
The last step is to let your TAP installation know there’s a plugin added through the tap-values.yaml file.
In case of a TMC-deployed TAP installation you can just go to your existing TAP installation in TMC, and upload the updated YAML file.
Click next, done and update to apply the updated tap-values.yaml. Wait until your deployment has reconciled and optionally monitor the process using
k get packageinstalls.packaging.carvel.dev -n tap-install
The plugin is active almost immediately, but it will take some time before the plugin is showing some useful data. After a while things will look as follows:
That’s it, I hope this was informative. Good luck with adding your own plugins. In a follow up blogpost I will explore the process to create a plugin wrapper yourself so stay tuned.