Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

post: Introducing Quarkus Backstage #2277

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
335 changes: 335 additions & 0 deletions _posts/2025-04-07-introducing-quarkus-backstage.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,335 @@
---
layout: post
title: 'Introducing Quarkus Backstage'
date: 2025-04-07
tags: backstage, platform engineering
synopsis: An introduction to the Quarkus extension for Backstage
author: iocanel
---
:imagesdir: /assets/images/posts/quarkus-backstage/

ifdef::env-github,env-browser,env-vscode[:imagesdir: ../assets/images/posts/similarity-search-using-vector-dbs]

== Introduction ==
DevOps, for many, has been more of a linguistic rebranding than a true cultural shift. All too often, organizations stop at renaming their Ops team to DevOps and call it a day.
But without real collaboration, without mutual understanding between developers and operators there is no actual DevOps.
Today, we witness the rise of Platform Engineering which is supposed to improve developer experience and productivity and act as an enabler for DevOps.

The question is can this gap be bridged without tools that facilitate this collaboration?
Since, its early days Quarkus provided tools for developers that help them get closer to the Ops side of the house, but also communicate to the Ops what the
dev actually needs. In this category we could classify the Quarkus Kubernetes and Helm extension. The latest addtion to this family of exntesion is now
the https://docs.quarkiverse.io/quarkus-backstage/dev/index.html[Quarkus Backstage] extension that simplifies the integration of Quarkus and https://backstage.io[Backstage], one of the most prominent projects in the Platform Engineering space.


=== What is Backstage ? ===
https://backstage.io[Backstage] is an open framework for building developer portals. It was originally created by Spotify to help their engineers manage the complexity of Microservices and cloud-native architectures.
It builds developer portals that act as software component registries, allowing teams to easily

* Track component ownership
* Discover, explore and document services
* Communicate API changes
* Create and instantiate Software Templates (materializing DevOps practices)
* Aggregate all developer consoles in one place
and more


=== Backstage Challenges ===
The idea is not new. I've seen similar tools come and go throughout my whole professional life. What makes https://backstage.io[Backstage] more relevant is the adoption of Microservice Architecture, which increases the
amplifies the need for a developer portal. What's also not new is the challenge of using such a tool and making in it an integral part of the developer workflow.

As always the challenge is the maintenance cost.
Maintenance, in terms of keeping the information served by https://backstage.io[Backstage] up to date.

What happens when a Service adds / removes an API ?
What happens when an API is migrated to new transport protocol ?
What happens when we need to use a new framework version in our templates ?

A development practice is as good as the tools that make it stick.


=== Quarkus Backstage Features ===
How does https://docs.quarkiverse.io/quarkus-backstage/dev/index.html[Quarkus Backstage] help with the challenges above ?

Short answer: By making Quarkus the Platform Engineers favorite application framework.
Long answer: While it's out of scope to solve all the challenges of https://backstage.io[Backstage], Quarkus aids the Platform Engineer in the following ways:

* Generates Component and API entities for Quarkus applications
* Reverse engineers Templates from existing Quarkus applications
* Provides CLI for managing https://backstage.io[Backstage] entities
* Provides Dev Services for https://backstage.io[Backstage]
* Acts as a coordinator for all Quarkus DevOps extensions


=== Using Quarkus Backstage ===
https://docs.quarkiverse.io/quarkus-backstage/dev/index.html[Quarkus Backstage] comes in two shapes that can be used independently:

* Quarkus CLI plugin
* Quarkus extension


==== As a CLI plugin ====
Let's see how to use the https://docs.quarkiverse.io/quarkus-backstage/dev/index.html[Quarkus Backstage] CLI plguin in order to generate https://backstage.io[Backstage] entities for your Quarkus application.

First, let's create a new Quarkus project:
[source,shell]
----
quarkus create app hello-backstage -x rest
----

....
Looking for the newly published extensions in registry.quarkus.io
-----------
selected extensions:
- io.quarkus:quarkus-rest


applying codestarts...
📚 java
🔨 maven
📦 quarkus
📝 config-properties
🔧 tooling-dockerfiles
🔧 tooling-maven-wrapper
🚀 rest-codestart

-----------
[SUCCESS] ✅ quarkus project has been successfully generated in:
--> /home/iocanel/blog/hello-backstage
-----------
Navigate into this directory and get started: quarkus dev
....



Then, navigate to the project directory:

From within your Quarkus project, run the following command:

[source,shell]
----
quarkus plugin add io.quarkiverse.backstage:quarkus-backstage-cli:0.6.0
----

....
Looking for the newly published extensions in registry.quarkus.io
Added plugin:
Name Type Scope Location Description
* backstage maven project io.quarkiverse.backstage:quarkus-backstage-cli:0.6.0
....


If you want to install it globally and make it available for all your Quarkus projects, run the following command:

[source,shell]
----
quarkus plugin add io.quarkiverse.backstage:quarkus-backstage-cli:0.6.0 --user
----

....
Added plugin:
Name Type Scope Location Description
* backstage maven user io.quarkiverse.backstage:quarkus-backstage-cli:0.6.0

[WARN] 🔥 Plugin was added in the user scope, but another with the same name exists in the project scope!
The project scoped one will take precedence when invoked from within the project!
....


To get an idea of the available commands, run:
[source,shell]
----
quarkus backstage --help
----

....
Backstage CLI
Usage: backstage [-h] [COMMAND]
-h, --help Display this help message.
Commands:
entities Backstage Entities
location Backstage Location
template Backstage Template
mcp Start backstage MCP server.
....


To generate a https://backstage.io[Backstage] entities for your Quarkus application, run the following command:

[source,shell]
----
quarkus backstage entities generate
----

....
Backstage entities generated:
API Version Kind Name UUID
backstage.io/v1alpha1 Component hello-backstage

....



[source,shell]
----
cat catalog-info.yaml
----

....

apiVersion: backstage.io/v1alpha1
kind: Component
spec:
type: application
lifecycle: production
owner: user:guest
metadata:
name: hello-backstage
labels:
app.kubernetes.io/name: hello-backstage
app.kubernetes.io/version: 1.0.0-SNAPSHOT
app.quarkus.io/version: 3.18.3
tags:
- java
- quarkus
....

The generated component is available under the `catalog-info.yaml`. The file can
be added to git, pushed to a git repository and then registered in Backstage.

Pretty much any Backstage installation should be able to read the component from github.
To do the registration, starting from the Home screen:

* Click on the "Create" button
* Click on "Register existing component"
* Paste the link to the `catalog-info.yaml` file in the git repository
* Click on "Analyze"
* Click on "Register"

The registered component should look like:

image::hello-backstage-component-view.png[scaledwidth=100%]

This is not very impressive given that the file could be generated by Backstage itself.
However, that would be the last thing that Backstage would do for you.
What would happen next time your application changes and changes need to be reflected in Backstage ?

Let's expose an API for our application. We'll add the openapi extension and we'll configure it so
that it generates the openapi schema in the same directory as the `catalog-info.yaml` file.

[source,shell]
----
quarkus ext add smallrye-openapi
echo "quarkus.smallrye-openapi.store-schema-directory=." >> src/main/resources/application.properties
----

....
Looking for the newly published extensions in registry.quarkus.io
[SUCCESS] ✅ Extension io.quarkus:quarkus-smallrye-openapi has been installed
....


Let's rebuild the application and see how our `catalog-info.yaml` file looks like:

[source,shell]
----
cat catalog-info.yaml
----

....

apiVersion: backstage.io/v1alpha1
kind: API
spec:
type: openapi
lifecycle: production
owner: user:guest
definition:
$text: ./openapi.yaml
metadata:
name: hello-backstage-api
---
apiVersion: backstage.io/v1alpha1
kind: Component
spec:
type: application
lifecycle: production
owner: user:guest
providesApis:
- hello-backstage-api
metadata:
name: hello-backstage
labels:
app.kubernetes.io/name: hello-backstage
app.kubernetes.io/version: 1.0.0-SNAPSHOT
app.quarkus.io/version: 3.18.3
tags:
- java
- quarkus
....

The refreshed component now looks like:

image::hello-backstage-component-with-api-view.png[scaledwidth=100%]


==== As an extension ====
An alternative to using the https://docs.quarkiverse.io/quarkus-backstage/dev/index.html[Quarkus Backstage] CLI plugin is to use the https://docs.quarkiverse.io/quarkus-backstage/dev/index.html[Quarkus Backstage] extension.
Usually, an extension is needed when the application itself requires a library, a framework, or a code
generator. In this case, the extension adds the Backstage entity generation to the application build process.

To add the extension to the project:

[source,shell]
----
quarkus ext add io.quarkiverse.backstage:quarkus-backstage:0.6.0
----

....
[SUCCESS] ✅ Extension io.quarkiverse.backstage:quarkus-backstage:0.6.0 has been installed
....


At the time of writing the extension is not part of the Extension catalog, and thus it needs to be added using
its full maven coordinates.

Now, let's remove the existing `catalog-info.yaml` file and let's generate a new one using the extension:

[source,shell]
----
rm catalog-info.yaml
ls -al
----

....
total 76
drwxr-xr-x 7 iocanel users 4096 Apr 3 19:29 .
drwxr-xr-x 3 iocanel users 4096 Apr 3 16:38 ..
-rw-r--r-- 1 iocanel users 75 Apr 3 16:38 .dockerignore
drwxr-xr-x 8 iocanel users 4096 Apr 3 19:21 .git
-rw-r--r-- 1 iocanel users 423 Apr 3 16:38 .gitignore
drwxr-xr-x 3 iocanel users 4096 Apr 3 16:38 .mvn
-rwxr-xr-x 1 iocanel users 11172 Apr 3 16:38 mvnw
-rw-r--r-- 1 iocanel users 7697 Apr 3 16:38 mvnw.cmd
-rw-r--r-- 1 iocanel users 710 Apr 3 19:19 openapi.json
-rw-r--r-- 1 iocanel users 454 Apr 3 19:19 openapi.yaml
-rw-r--r-- 1 iocanel users 5332 Apr 3 19:31 pom.xml
drwxr-xr-x 3 iocanel users 4096 Apr 3 16:39 .quarkus
-rw-r--r-- 1 iocanel users 2053 Apr 3 16:38 README.md
drwxr-xr-x 4 iocanel users 4096 Apr 3 16:38 src
drwxr-xr-x 4 iocanel users 4096 Apr 3 19:21 target
....


Finally, let's rebuild:

And check that the file is properly generated. The generated resources should the same as the ones generated by the CLI plugin.
There is still value in using the extension, but that's a subject for another blog post.


=== Conclusion ===
https://backstage.io[Backstage] is a great tool for organizations to survive the Microservice Architecture chaos.
A tool, can't help if it's not used nor if it's feed with stale data.
The https://docs.quarkiverse.io/quarkus-backstage/dev/index.html[Quarkus Backstage] project was created to leverage the power of the Quarkus build system in order to keep
the catalog entities of Quarkus components up to day. In Quarkus lingo, to bring "Platform Engineer joy".

A video walk-through on the basics of the extension is available at https://www.youtube.com/watch?v=XAiF-opDtpw[here].
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.