SKE Backstage Generator
The SKE Backstage Generator provides automated generation of the necessary Template and Component manifests for your Promises and requested Resources.
These manifests are read by Backstage and are designed to work seamlessly with the SKE Backstage plugins.
Prerequisites
SKE Backstage plugins
The ske-backstage-generator
uses an action from the ske-backend
Backstage plugin.
This action is used within the generated Template to create a Resource Request.
The generated Components are also used by the ske-frontend
Backstage plugin to display
Promise and Resource metadata.
In order to utilise the Templates and Components, you should also install both the
ske-backend
and ske-frontend
plugins into your Backstage instance.
See Configuring the Plugins for instructions.
Backstage Destination
You must have a Destination created with the environment: backstage
label. See the
Kratix Backstage docs
for setup instructions.
How does it work?
The ske-backstage-generator
image is intended to be run as part of your
Configure Pipeline for your Promise and Resource Workflows. It will
auto-generate Backstage Template and Component manifests, and schedule them to
your Backstage Destination.
Promise Configure
In a Promise Configure workflow, two Backstage manifests will be generated:
- Promise Component: A Backstage Component representing the Promise.
- Promise Template: A Backstage Template representing the Promise API (i.e. the CRD for Resources created from this Promise).
Check the YAML File Format for examples of these manifests.
Resource Configure
In a Resource Configure workflow, a single Backstage manifest will be generated:
- Resource Component: A Backstage Component representing the Resource.
Check the YAML File Format for examples of these manifests.
Accessing the SKE Generator image
Pulling the image locally
The image is hosted in a private registry. To access the image, you will need to authenticate using the token you have been provided with. For Docker, you can run the following command, providing your token as the password when prompted:
docker login registry.syntasso.io --username syntasso-pkg
If you are using a different container engine, follow the docs for your specific tool.
Once you have authenticated, you can pull any released version of the image.
You can select your version from the releases page. Or, if you have both GH CLI and JQ CLI installed, you can fetch the most recent released version using the following command:
gh api orgs/syntasso/packages/container/ske-backstage-generator/versions | jq -r '.[0].metadata.container.tags[0]'
docker pull registry.syntasso.io/ske-backstage-generator:VERSION
Pulling the image from your cluster
Your Kubernetes cluster must have permission to pull this image from the private registry.
If you are following the quick-start guide, you can load the image directly to the Kubernetes cache. Different tools have different commands for this. For example:
# For minikube
minikube image load registry.syntasso.io/ske-backstage-generator:VERSION
# For KinD
kind load docker-image registry.syntasso.io/ske-backstage-generator:VERSION
For other tools, follow their specific documentation.
When using the image in your Workflows, you can define the secret you want to use for authentication within your Promise, see below for more details.
If your cluster is running in a secure environment, you may wish to pull this image and push it to an internal registry which your cluster has permission to pull from.
Using the image in your Workflows
To use the ske-backstage-generator
image, update your Promise definition to include the
generator as a workflow step for both the Promise Configure and Resource Configure
workflows:
# ...
workflows:
promise:
configure:
- apiVersion: platform.kratix.io/v1alpha1
kind: Pipeline
metadata:
name: promise-configure
namespace: default
spec:
containers:
- image: ghcr.io/syntasso/kratix-marketplace/jenkins-configure-pipeline:v0.1.0
name: jenkins-promise-pipeline
- image: registry.syntasso.io/ske-backstage-generator:VERSION
name: ske-backstage-generator
resource:
configure:
- apiVersion: platform.kratix.io/v1alpha1
kind: Pipeline
metadata:
name: resource-configure
namespace: default
spec:
containers:
- image: ghcr.io/syntasso/kratix-marketplace/jenkins-configure-pipeline:v0.1.0
name: jenkins-resource-pipeline
- image: registry.syntasso.io/ske-backstage-generator:VERSION
name: ske-backstage-generator
Once your Promise is updated, the generator will be run as part of your Workflows. If you install the Promise, you should see a Component automatically appearing in your Backstage instance, together with a new Template. If you use the Template to create a Resource, you should see the resource Component appearing as well as the Resource itself being created in your cluster.
In order to have the full status of your Promise or Resource request displayed in Backstage, you should place the aspect as the last image in the last pipeline of your workflow.
If the aspect needs to be used more than once in a Workflow, you should utilise the SKE Backstage Component Promise. Otherwise, you will observe only one of the components in Backstage, and Backstage will emit a warning:
{"level":"warn","message":"Detected conflicting entityRef component:default/my-request-jenkins already referenced by url:http://minio.kratix-platform-system.svc.cluster.local/kratix/backstage/resources/default/cicd/my-request/instance-configure/5cfaf/backstage/catalog-info.yaml and now also url:http://minio.kratix-platform-system.svc.cluster.local/kratix/backstage/resources/default/cicd/my-request/instance-configure-2/5cfaf/backstage/catalog-info.yaml","plugin":"catalog","service":"backstage"}
Authenticating against the image registry
If you have not loaded the image to your Kubernetes cache or pushed it to an internal registry,
you can define your authentication credentials via a docker-registry
secret and refer to this secret
in Pipeline definition in your Workflow.
You can create the secret with the following command, replacing YOUR_TOKEN
with the token you have
been provided with:
kubectl create secret docker-registry syntasso-registry \
--docker-server=registry.syntasso.io \
--docker-username=syntasso-pkg \
--docker-password=YOUR_TOKEN \
--namespace kratix-platform-system
The secret must exist in the kratix-platform-system
namespace as well as any other namespaces where users
be able to make requests
The imagePullSecrets
field in your Workflow can be used to refer to the new syntasso-registry
secret.
# ...
workflows:
promise:
configure:
- apiVersion: platform.kratix.io/v1alpha1
kind: Pipeline
metadata:
name: promise-configure
namespace: default
spec:
imagePullSecrets:
- name: syntasso-registry
containers:
- image: ghcr.io/syntasso/kratix-marketplace/jenkins-configure-pipeline:v0.1.0
name: jenkins-promise-pipeline
- image: registry.syntasso.io/ske-backstage-generator:VERSION
name: ske-backstage-generator
This ensures that, when pulling the ske-backstage-generator
image, Kubernetes will use the
syntasso-registry
secrets for authentication.
Customising the generated Components
By default, the generator will create the Backstage Promise Component
with default values for the metadata
and
spec
fields. For a Promise, for example, it will look like this:
metadata:
name: <Promise Kind>-promise
title: <Promise Kind> Promise
description: <Promise Kind> as a Service
tags:
- kratix
spec:
lifecycle: production
owner: kratix-platform
type: kratix-promise
# Other fields are left empty
You can customise these values by setting the following env
variables in the
workflow:
COMPONENT_NAME
: the value ofmetadata.name
COMPONENT_TITLE
: the value ofmetadata.title
COMPONENT_DESCRIPTION
: the value ofmetadata.description
COMPONENT_TAGS
: comma-separated list of values formetadata.tags
COMPONENT_TYPE
: the value ofspec.type
COMPONENT_LIFECYCLE
: the value ofspec.lifecycle
COMPONENT_OWNER
: the value ofspec.owner
COMPONENT_SYSTEM
: the value ofspec.system
COMPONENT_SUBCOMPONENT_OF
: the value ofspec.subcomponentOf
COMPONENT_PROVIDES_APIS
: comma-separated list of values forspec.providesApis
COMPONENT_CONSUMES_APIS
: comma-separated list of values forspec.consumesApis
COMPONENT_DEPENDS_ON
: comma-separated list of values forspec.dependsOn
You can also customise the fields by setting the following annotations in the Promise or Resource object directly:
ske.backstage.component/name
: the value ofmetadata.name
ske.backstage.component/title
: the value ofmetadata.title
ske.backstage.component/description
: the value ofmetadata.description
ske.backstage.component/tags
: comma-separated list of values formetadata.tags
ske.backstage.component/type
: the value ofspec.type
ske.backstage.component/lifecycle
: the value ofspec.lifecycle
ske.backstage.component/owner
: the value ofspec.owner
ske.backstage.component/system
: the value ofspec.system
ske.backstage.component/subcomponentOf
: the value ofspec.subcomponentOf
ske.backstage.component/providesApis
: comma-separated list of values forspec.providesApis
ske.backstage.component/consumesApis
: comma-separated list of values forspec.consumesApis
ske.backstage.component/dependsOn
: comma-separated list of values forspec.dependsOn
For example, to set spec.owner
and spec.providesApis
, you can update your
pipeline stage with the snippet below:
#...
workflows:
promise:
configure:
- apiVersion: platform.kratix.io/v1alpha1
kind: Pipeline
metadata:
name: promise-configure
namespace: default
spec:
containers:
- image: ghcr.io/syntasso/kratix-marketplace/jenkins-configure-pipeline:v0.1.0
name: jenkins-promise-pipeline
- image: registry.syntasso.io/ske-backstage-generator:VERSION
name: ske-backstage-generator
env:
- name: COMPONENT_OWNER
value: "platform-team"
- name: COMPONENT_PROVIDES_APIS
value: "component/api/v1,component/api/v2"
For any further customisation, you can directly modify the generated Component
in the /kratix/output/backstage/catalog-info.yaml
file.
Customising the generated Templates
By default, the generator will create the Backstage Template with resource namespace as a required field.
You can customise this behaviour by setting the following env
variables in the workflow:
TEMPLATE_NAMESPACE
: the default value of the resource namespaceTEMPLATE_NAMESPACE_FIELD_TITLE
: the name of the resource namespace field in Backstage UITEMPLATE_NAMESPACE_FIELD_DESCRIPTION
: the description of the resource namespace field in Backstage UITEMPLATE_HIDE_NAMESPACE
: set totrue
if you would like to hide the namespace field from the generated resource Template. Resource namespace will default toTEMPLATE_NAMESPACE
when it is set, otherwise will be set todefault
namespace.
For example, to generate the resource Template without the namespace field and set the resource namespace to my-team
for all resource requests:
#...
workflows:
promise:
configure:
- apiVersion: platform.kratix.io/v1alpha1
kind: Pipeline
metadata:
name: promise-configure
namespace: default
spec:
containers:
- image: ghcr.io/syntasso/kratix-marketplace/jenkins-configure-pipeline:v0.1.0
name: jenkins-promise-pipeline
- image: registry.syntasso.io/ske-backstage-generator:VERSION
name: ske-backstage-generator
env:
- name: TEMPLATE_NAMESPACE
value: "my-team"
- name: TEMPLATE_HIDE_NAMESPACE
value: "true"
For any further customisation, you can directly modify the generated Template
in the /kratix/output/backstage/catalog-info.yaml
file.
Providing a Resource Summary
On the Resource Component page, it's possible to include a free-form text block to provide documentation about the resource.
To do this, set the ske.backstage.component/summary
annotation on the Promise object:
apiVersion: platform.kratix.io/v1alpha1
kind: Promise
metadata:
#...
annotations:
ske.backstage.component/summary: |
Some information about this Promise.
This accepts **markdown!**
The text will be rendered on each Resource Component page in Backstage.
SKE Backstage Component Promise
The SKE Backstage Component Promise provides additional functionality to the SKE Backstage integration by offloading management of Backstage Components and Templates files from your Promises. The Promise enables the following features:
- Allow updates to the Backstage Component and Templates while a Pipeline is still running.
- Enables the combination of multiple Backstage Components and Templates into a single
catalog-info.yaml
file. For some Backstage integrations, such as GitLab, this is a requirement.
You can install the Promise via kubectl
:
kubectl apply -f https://syntasso-enterprise-releases.s3.eu-west-2.amazonaws.com/promises/ske-backstage-component-promise.yaml
Component updates with multiple Pipelines
If your Promise or Resource workflow contains multiple Pipelines, you may wish to update the associated Component in Backstage at the end of each Pipeline. For example, the Resource status could be updated in every Pipeline to convey the latest information about the Resource to the requester in Backstage.
To do this, run the SKE Backstage Generator as normal, then create a
request to the SKE Backstage Component Promise within the next pipeline container. In this example the image
ghcr.io/syntasso/kratix-marketplace/create-backstage-component-request:v0.1.0
is responsible for generating a SKE
Backstage Component Promise request:
# ...
workflows:
resource:
configure:
- apiVersion: platform.kratix.io/v1alpha1
kind: Pipeline
metadata:
name: resource-configure
namespace: default
spec:
# rbac required by new create-backstage-component-request image
rbac:
permissions:
- apiGroups: ["syntasso.io"]
verbs: ["*"]
resources: ["backstagecomponents"]
containers:
- image: ghcr.io/syntasso/kratix-marketplace/jenkins-configure-pipeline:v0.1.0
name: jenkins-resource-pipeline
- image: registry.syntasso.io/ske-backstage-generator:VERSION
name: ske-backstage-generator
- image: ghcr.io/syntasso/kratix-marketplace/create-backstage-component-request:v0.1.0
name: create-backstage-component-request
promise:
configure:
- apiVersion: platform.kratix.io/v1alpha1
kind: Pipeline
metadata:
name: promise-configure
namespace: default
spec:
rbac:
permissions:
- apiGroups: ["syntasso.io"]
verbs: ["*"]
resources: ["backstagecomponents"]
containers:
- image: ghcr.io/syntasso/kratix-marketplace/jenkins-configure-pipeline:v0.1.0
name: jenkins-promise-pipeline
- image: registry.syntasso.io/ske-backstage-generator:VERSION
name: ske-backstage-generator
- image: ghcr.io/syntasso/kratix-marketplace/create-backstage-component-request:v0.1.0
name: create-backstage-component-request
The versions of the ske-backstage-generator
image used in your Promise specification and
the ske-backstage-generator
image in the SKE Backstage Component Promise must match
Requesting Backstage Components
When creating the BackstageComponent
requests you need to ensure that you set the
correct .metadata.ownerReferences
on the resource to ensure it is deleted when the
resource/promise is deleted. An example of this is shown below:
apiVersion: syntasso.io/v1alpha1
kind: BackstageComponent
metadata:
name: <unique-name>
namespace: <same namespace as the request (kratix-platform-system for promises)>
ownerReferences:
- apiVersion: <apiVersion of the parent object>
blockOwnerDeletion: false
controller: false
kind: <kind of the parent object>
name: <name of the parent object>
uid: <uid of the parent object>
spec:
- resources: |
... # contents of /kratix/output/backstage/catalog-info.yaml
The name
apiVersion
, kind
and uid
fields under ownerReferences
must equal
the parent object for this request, which is the /kratix/input/object.yaml
.
The spec.resources
needs to be a string containing the Backstage Component/Template
YAML files.
Running in this mode, the SKE Backstage Generator will not schedule the Backstage documents itself. Instead, it will delegate this responsibility to the SKE Backstage Component Promise.
This allows the Backstage Component document to be managed per-Resource, meaning Resource metadata such as the status can be updated across multiple Pipelines.
After creating the BackstageComponent
request, you need to ensure your
pipeline does not also schedule the same document to the Backstage Destination.
To prevent this you can rm -rf /kratix/output/backstage
and remove the
dir: backstage
entry in your /kratix/metadata/destination-selectors.yaml
after
making the request.
Example bash pipeline script
- image: ghcr.io/syntasso/kratix-pipeline-utility:v0.0.1
name: make-backstage-request
command: [ "sh" ]
args:
- -c
- |
export name="$(yq eval '.metadata.name' /kratix/input/object.yaml)"
export namespace="$(yq eval '.metadata.namespace' /kratix/input/object.yaml)"
export promise_name=$KRATIX_PROMISE_NAME
kind=$(yq eval '.kind' /kratix/input/object.yaml)
api_version=$(yq eval '.apiVersion' /kratix/input/object.yaml)
uid=$(yq eval '.metadata.uid' /kratix/input/object.yaml)
concatenated_string="${promise_name}-${namespace}-${name}"
hash=$(echo -n "$concatenated_string" | sha256sum | cut -c1-5)
truncated_string=$(echo -n "$concatenated_string" | cut -c1-50)
deterministic_name="${truncated_string}-${hash}"
cd /kratix/output/
cat <<EOF > rr.yaml
apiVersion: syntasso.io/v1alpha1
kind: BackstageComponent
metadata:
name: $deterministic_name
namespace: $namespace
ownerReferences:
- apiVersion: $api_version
blockOwnerDeletion: false
controller: false
kind: $kind
name: $name
uid: $uid
spec: {}
EOF
# set .spec.resources equal to file contents of catalog-info.yaml
yq eval '.spec.resources = strload("backstage/catalog-info.yaml")' -i rr.yaml
kubectl apply -f rr.yaml
rm -rf /kratix/output/rr.yaml /kratix/output/backstage/ /kratix/metadata/destination-selectors.yaml
Scheduling Backstage Components
By default, BackstageComponent
requests are scheduled to your Backstage destination.
If you need to schedule a BackstageComponent
to a destination other than
the default Backstage destination with label environment: backstage
, you can set the
.spec.destinationSelectors
on the resource to customize its scheduling behavior.
An example of this is shown below:
apiVersion: syntasso.io/v1alpha1
kind: BackstageComponent
metadata:
name: A-NAME
namespace: NAMESPACE
spec:
destinationSelectors:
- matchLabels:
environment: backstage-instance-one
team: billing
- resources: |
... # contents of /kratix/output/backstage/catalog-info.yaml
Generate a single Backstage catalog
Using the SKE Backstage Component Promise, you can optionally choose to write a single
catalog-info.yaml
file for Backstage to read from, instead of the default behaviour of
one catalog file per Promise or resource request.
To do this, there are two steps required:
- Configuring the SKE Backstage Generator to write all of the Backstage manifests in a
single
catalog-info.yaml
. - Configuring all of your Promises to use the SKE Backstage Component Promise.
First, apply the following config map to your Platform cluster:
apiVersion: v1
data:
allInOne: "true"
kind: ConfigMap
metadata:
name: ske-backstage-component-promise-config
namespace: kratix-platform-system
Then configure all of your Promises which use the SKE Backstage Generator to make a request to the SKE Backstage Component Promise within your Pipeline, as illustrated in the section above.
To ensure that a single catalog-info.yaml
file is created, you must ensure that all
of your Promises which use the SKE Backstage Generator are set up to make a request
to the SKE Backstage Component Promise in both the Promise and Resource workflows.
Configuring the allInOne
field to true
will cause the SKE Backstage Component Promise
to aggregate the Backstage Component and Template files for all Promises and Resources
into a single catalog-info.yaml
file in the Backstage Destination.
With these changes, your SKE Backstage integration will result in a single
catalog-info.yaml
file being written to your Backstage Destination containing all of the
generated Component and Template manifests.