TAP 1.6 – Tanzu Developer Portal Configurator

Backstage is an amazing CNCF Project which is the base for the Tanzu Developer Portal (TDP) which was previously known as TAP GUI.

While since the initial GA of TAP, we have had a great portal, which has been enhanced with every release, the portal has not been able to take full advantage of the power of backstage.

Backstage is a highly extensible project, which is built on a plugin based model, and in the open source backstage world, more then 150 plugins have been published, allowing for integrations with many common tools present in customer environments.

Now with TAP 1.6, we have a new component called the Tanzu Developer Portal Configurator tool, which enables you to add plugins to Tanzu Developer Portal, turning it into a customized portal!

While on one hand, TDP till now has been very locked down, the experience of integrating plugins in OSS Backstage is very tedious, and is not for the light hearted, The TDP Configurator tool, is a great step in the direction of making integrating both third party plugins as well as custom in house built plugins a much more maintainable and simple task.

The TDP Configurator takes the list of the plugins that you want to add into your portal. With that list, TDP Configurator generates a developer portal customized to your specifications.

The end result of the configurator, is an OCI image which can be referenced when deploying TAP and configured the same as with the OOTB TDP image, to provide a great experience with your own custom plugin setup to meet your organizations needs.

How Plugins Get Added

One of the challenges around OSS backstage, and the integration of plugins, is that for every plugin you need to manually edit the code base of backstage itself to include your plugins.

This process is tedious and error prone, and the TDP configurator helps in this regard by introducing the concept of surfaces, and plugin wrappers.

A surface is a discrete capability that a plug-in provides. This can include:

  • The ability to show up on the sidebar
  • The ability to be accessed at a URL, such as https://YOUR_PORTAL_URL/plugin
  • The ability to show up as a Catalog Overview tab

Basically with a wrapper, we have a defined specification where we can define how a plugin should be visualized within the portal itself.

A wrapper is a method of exposing a plugin’s surfaces to the TDP Configurator so that the plugin can be integrated into the portal.

A wrapper imports a reference to the underlying plugin and defines the surfaces that the plugin should expose.

While the way to build wrapper plugins is out of scope of this blog post, keep your eyes open for some more content coming soon with some real world examples of how to do it!

Building a Custom Portal

The mechanism for building a custom portal actually uses TAP itself, which is pretty cool!

The general flow is that you need to create a configuration file where you define the backend and frontend plugins you want to have added to your portal, which are themselves wrapper plugins, as discussed above.

A sample config file may look like this:

app:
  plugins:
    - name: '@tpb/plugin-hello-world'
      version: '^1.6.0-release-1.6.x.1'
backend:
  plugins:
    - name: '@tpb/plugin-hello-world-backend'
      version: '^1.6.0-release-1.6.x.1'

As can be seen above, we are adding one backend and one frontend plugin to our portal which are already created for us by the TAP team.

These plugins are available within the configurator tool itself, which makes it extremely easy to get started and see the value of the tool!

Once we have this config file we need to base64 encode it and then pass that in to our workload. This can be done using the following command:

TDP_CONFIG_FILE_CONTENT=$(cat tdp-config.yaml | base64 -w0)

The other piece of data we need is the image reference of the builder image itself which can be retrieved with the following command:

TDP_CONFIGURATOR_IMAGE=`imgpkg pull -b $(kubectl get package -n tap-install tpb.tanzu.vmware.com.0.1.2 -o json | jq -r .spec.template.spec.fetch[0].imgpkgBundle.image) -o /tmp/tpb-bundle && yq e '.images[0].image' /tmp/tpb-bundle/.imgpkg/images.yml`

With those 2 pieces of data we can now create our workload manifest:

cat <<EOF > tdp-workload.yaml
apiVersion: carto.run/v1alpha1
kind: Workload
metadata:
  name: tdp-configurator
  labels:
    apps.tanzu.vmware.com/workload-type: web
    app.kubernetes.io/part-of: tdp-configurator
spec:
  build:
    env:
      - name: BP_NODE_RUN_SCRIPTS
        value: 'set-tpb-config,portal:pack'
      - name: TPB_CONFIG
        value: /tmp/tpb-config.yaml
      - name: TPB_CONFIG_STRING
        value: $TDP_CONFIG_FILE_CONTENT
  source:
    image: $TDP_CONFIGURATOR_IMAGE
    subPath: builder
EOF

And now you can simply apply this workload to your cluster. Once the workload finishes the image building step which is performed by TBS, you will need to retrieve the new image URI using the following command:

NEW_TDP_IMAGE=$(kubectl get cnbimage tdp-configurator -o json | jq -r .status.latestImage)

And with that value we need to create a YTT overlay secret which we will apply to our TAP GUI package, in order to configure it to use our custom portal.

cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Secret
metadata:
  name: tdp-app-image-overlay-secret
  namespace: tap-install
stringData:
  tpb-app-image-overlay.yaml: |
    #@ load("@ytt:overlay", "overlay")

    #! makes an assumption that tap-gui is deployed in the namespace: "tap-gui"
    #@overlay/match by=overlay.subset({"kind": "Deployment", "metadata": {"name": "server", "namespace": "tap-gui"}}), expects="1+"
    ---
    spec:
      template:
        spec:
          containers:
            #@overlay/match by=overlay.subset({"name": "backstage"}),expects="1+"
            #@overlay/match-child-defaults missing_ok=True
            - image: $NEW_TDP_IMAGE
            #@overlay/replace
              args:
              - -c
              - |
                export KUBERNETES_SERVICE_ACCOUNT_TOKEN="\$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)"
                exec /layers/tanzu-buildpacks_node-engine/node/bin/node portal/dist/packages/backend  \\
                --config=portal/app-config.yaml \\
                --config=portal/runtime-config.yaml \\
                --config=/etc/app-config/app-config.yaml
EOF

And the final step is to add this overlay to our tap values and to apply the changes.

The section we need in our TAP values file will look like:

package_overlays:
  - name: tap-gui
    secrets:
      - name: tdp-app-image-overlay-secret

once you update TAP with the new values file, we can access TAP and see a new icon on the left side menu for our newly added Hello World plugin!

Summary

While the process is still not 100% streamlined for adding new plugins, and it does require some typescript and backstage knowledge, the fact that this is now possible in it of itself is extremely promissing!

I’m truly excited to see the UX and feature set of this new component evolve over time, and I’m looking forward to being able to enhance our customers environments with the plugins relevant to their environments and needs, making the Tanzu Developer Portal truly a one stop shop for their developers!

Leave a Reply

%d bloggers like this: