Backstage Templates

11.05.2022 Stefan Welsch
Cloud DevOps backstage typescript nodejs

Backstage

backstage Backstage bezeichnet sich selbst als eine offene Plattform um Entwickler-Portale zu bauen. Die Software wurde von Spotify 2020 unter den Open Source Projects entwickelt und ist in Typescript geschrieben. Spotify selbst setzt die Software für die interne Entwicklung von Software ein.

Heute wollen wir uns Backstage mal genauer anschauen und werden versuchen, ein eigenes Template zu entwerfen.

Backstage bietet out-of-the-box einen Software Catalog, mit dem wir all unsere Software managen können. Hierzu gehören beispielsweise Microservices, Libraries, Websites, Data Pipelines usw. Wir können basierend auf Software Templates neue Entitäten im Software Katalog erstellen, oder vorhandene Software registrieren. Dies ist wichtig, damit man bereits vorhandene Software in Backstage auch importieren kann.

Software Templates bieten uns einen standardisierten Weg Software zu erstellen. So können Best-Practices und Toolsets im Template hinterlegt werden, welche von allen Entwicklern genutzt werden können. Auch Automatisierungen von Build und Deploymentprozessen können direkt in den Software Templates eingebaut werden.

Backstage bietet uns ausserdem TechDocs. Hier können technische Dokumentationen einfach erstellt und gewartet werden. So hat man die technischen Dokumentationen zentral an einem Platz und immer nah an der Software, zu der sie gehört.

Um zu verstehen, was Backstage nun genau macht, ist es am einfachsten, einen lokalen Server zu starten. Backstage bietet hierfür eine CLI, mit der wir uns eine App anlegen können. Eine App beinhaltet ein Backend und Frontend, welches wir nach unseren Wünschen konfigurieren können.

Get started

Bevor wir Backstage lokal laufen lassen können, müssen bestimmte Vorbedingungen erfüllt sein. Sobald wir alle Programme installiert haben, können wir mit dem folgenden Befehl eine App erstellen. Als Name wähle ich dev-manager und als Datenbank nutzen wir für die lokale Entwicklung eine SQLite.

~ ❯ npx @backstage/create-app
? Enter a name for the app [required] dev-manager
? Select database for the backend [required] (Use arrow keys)
❯ SQLite
  PostgreSQL

Unsere App wird nun erstellt. Nachdem die Erstellung durch ist, können wir diese mit dem folgenden Befehl starten.

cd dev-manager
yarn dev

Es sollte sich nun ein Browser-Fenster mit der Applikation öffnen. backstage-dashboard Schauen wir uns die Applikation mal im Detail an. Auf der Startseite finden wir eine Übersicht aller unserer Components. Eine Komponente kann vom Typ library, website oder service sein. Anhand der Komponenten wird später die spezifische View aufgebaut.

Unter APIs finden wir einen API-Katalog. In diesem sind, wie der Name sagt, alle APIs zu finden. Auch hier gibt es verschiedene Typen (grpc, openapi, graphql und asyncapi), welche die Detailansicht beeinflussen. image-20220324110217575 In der Docs Ansicht finden wir Technische Dokumentationen zu unseren Komponenten. So befinden sich die Dokumentation, die API als auch die Implementierung an einer zentralen Stelle. image-20220324110241814 Unter dem Menupunkt Create... finden wir verschiedene Templates, mit denen wir eine neue Komponente, API oder Dokumentation erstellen können. image-20220324110405321 Der Menüpunkt TechRadar bietet eine Übersicht der meist gebrauchten oder neuesten Technologien. Dies ist ganz praktisch, wenn man sicherstellen will, dass bei neuen Projekten die Technologien verwendet werden, welche auch aktuell sind. image-20220401073248268 Wie wir sehen können bietet Backstage out-of-the-box schon eine gute Übersicht der eingesetzten Softwarekomponenten.

Templates

Wie bereits im Intro erwähnt, wollen wir uns die Templates anschauen. Templates, wie der Name schon sagt, sind Vorlagen für Softwareprojekte. Aber wofür braucht man diese Templates überhaupt?

In Zeiten von Microservices hat die Quantität von Softwareprojekten extrem zugenommen. Früher hatte man noch "Eierlegene-Wollmilchsau-Applikationen", welche möglichst viele Funktionalitäten bieten mussten. Alle Komponenten der Software wurden in dieser einen Applikation entwickelt. So wurde beispielsweise ein Benutzer authentifiziert, danach wurde ein Service aufgerufen, welcher aus dem LDAP bestimmte Benutzerrollen zur Authentifizierung abrief. Danach wurde dann wiederum ein Service aufgerufen, welcher aus einer Datenbank Informationen über diesen User ausgelesen hat, usw.

Heute wird diese eine Applikation in einer Microservice-Architektur aufgebaut, so gibt es einen Service zur Authentifizierung des Benutzers, einen weiteren um die Rollen aus dem LDAP auszulesen und einen anderen, um den Datenbankzugriff zu machen. Hierbei handelt es sich lediglich um ein stark vereinfachtes Beispiel. In der Realität gibt es oft dutzende Microservices, welche dann auch noch durch verschiedene Teams innerhalb einer Organisation, oder sogar mehrerer Organisationen verwaltet werden.

Um die Wartung dieser Applikationen sicherzustellen, macht es Sinn, dass jedes Team sich an bestimmte Vorgaben und Regeln bei der Erstellung und Entwicklung dieser Applikationen hält. Genau hier helfen uns Templates weiter. Wir können in Templates Vorgaben bezüglich Naming, Ordnerstrukturen, Tools und Best-Practises machen. Schauen wir uns ein Template doch mal anhand einer Quarkus Applikation an. Hierzu erstellen wir uns mit dem Quarkus Configurator eine neue Applikation mit den gewünschten Tools. image-20220401080946386 Wir wollen in unserer Applikation also gRPC Services nutzen, die Konfiguration soll immer in YAML sein. Damit wir ein einheitliches Logging Output haben, nutzen wir das Logging JSON. Als Programmiersprache setzen wir auf Kotlin, anstatt standardmässig Java zu nutzen und zu guter Letzt wollen wir noch Gradle als Buildtool nutzen.

Über den Button "Generate your application" können wir uns nun ein .zip mit dem Quellcode herunterladen und das Projekt entpacken. Um nun ein Backstage Template zu erstellen, erstellen wir uns einen Ordner quarkus-template und innerhalb dieses Ordners wiederum einen Ordner template.

mkdir -p quarkus-template/template

Nun schieben wir den gesamten Inhalt unseres erstellten Quarkus Projekts in den template Ordner. Die Ordnerstruktur sollte also folgendermassen aussehen.

image-20220401084438228

Jetzt wollen wir uns ans Werk machen und aus unserer Applikation ein Template erstellen. Als erstes erstellen wir uns im root eine Datei namens template.yaml. Diese Datei definiert die Metadaten unseres Templates wie Name, Beschreibung, Parameter und welche Aktionen ausgeführt werden sollen. Der Inhalt dieser Datei sieht folgendermassen aus:

apiVersion: scaffolder.backstage.io/v1beta3
kind: Template
metadata:
  name: quarkus-template # name of the template
  title: Quarkus Application 
  description: Create a quarkus application
  tags: # you can configure tags for the service
    - recommended
    - quarkus
    - microservice
    - kotlin
    
spec:
  owner: stefan.welsch@b-nova.com # the owner of this 
  type: service # backstage type of this template
  
  # these are the steps which are rendered in the frontend with the form input
  parameters:
    - title: Provide some simple information
      required:
        - name
        - package
      properties:
        name:
          title: Name
          type: string
          description: Unique name of the component
          ui:field: EntityNamePicker
        package:
          title: Package
          type: string
          description: Package name
    - title: Choose a location
      required:
        - repoUrl
      properties:
        repoUrl:
          title: Repository Location
          type: string
          ui:field: RepoUrlPicker
          ui:options:
            allowedHosts:
              - github.com    
	# here are the steps that are executed in series in the scaffolder backend
  steps:
    - id: template
      name: Fetch Skeleton + Template
      action: fetch:template
      input:
        url: ./template
        values:
          name: ${{ parameters.name }}
          package: ${{ parameters.package }}
          
    - id: publish
      name: Publish
      action: publish:github
      input:
        allowedHosts: ["github.com"]
        description: This is ${{ parameters.name }}
        repoUrl: ${{ parameters.repoUrl }}
        defaultBranch: main

    - id: register
      name: Register
      action: catalog:register
      input:
        repoContentsUrl: ${{ steps.publish.output.repoContentsUrl }}
        catalogInfoPath: "/catalog-info.yaml"

  output:
    remoteUrl: ${{ steps.publish.output.remoteUrl }}
    entityRef: ${{ steps.register.output.entityRef }}

Nun wollen wir als erstes den Namen unserer Applikation konfigurierbar machen. Dazu suchen wir in unserem Projekt nach code-with-quarkus (jetziger Name) und ersetzen diesen mit dem Platzhalter ${{values.name}}. Anschliessend wollen wir noch den Package-Name konfigurierbar machen. Aktuell ist dieser org.acme. Wir suchen also wieder im ganzen Projekt nach org.acme und ersetzen diesen mit ${{values.package}}. Nun müssen wir nur noch im Ordner src/main/kotlin den Package Name zu ${{values.package}} ändern.

image-20220401085340354

Unser Template ist jetzt soweit fertig. Nun wollen wir das Template im Backstage verfügbar machen. Dazu müssen wir das Template erstmal in ein Git-Verzeichnis umwandeln. Dazu wechseln wir in unser dev-manager Projekt und öffnen die Datei app-config.yaml. Unter dem Punkt catalog finden wir verschiedene Locations. Hierbei handelt es sich um die Beispieldaten, welche wir weiter oben gesehen haben. Wir löschen erstmal alle Templates aus den Locations raus und ergänzen unser eigenes. image-20220401091539749

INFO

Wenn du den folgenden Fehler im Log siehst,

[1] 2022-04-01T07:12:53.576Z catalog warn Entity template:default/quarkus-template at file:/Users/swelsch/quarkus-template/template.yaml, originated at file:/Users/swelsch/quarkus-template/template.yaml, is not of an allowed kind for that location type=plugin entity=location:default/generated-6fcbb905406738fb7c50408b044fc21e09da61c7

musst du noch Template zu den Catalog Rules hinzufügen.

image-20220401091802313

Wenn wir die Backstage-Applikation nun starten, sollten wir unter dem Menupunkt "Create" nun unser eigenes Template sehen. image-20220401092056039 Bevor wir unsere erste eigene Applikation erstellen können, brauche wir erst noch ein Repository, in welchem wir unseren Code später publishen. Wir nutzen in unserem Beispiel Github. Dazu müssen wir uns in Github erstmal einen Developer Token erstellen. Unter https://github.com/settings/tokens/new können wir uns solch einen Token erstellen (Ein Account ist Voraussetzung). Die folgenden Berechtigungen sind dafür erforderlich.
image-20220401093527176
Den Github Token können wir dann in der app-config.yaml unter der Github Integration einfügen. Der Token sollte nicht in Plaintext eingefügt werden. Verwende bitte deinen entsprechenden Secrets-Management-Mechanismus, um den Token zur Laufzeit aus den Umgebungsvariablen auszulesen.

Screenshot 2022-04-01 at 09.37.58

Nachdem unsere Github-Anbindung konfiguriert ist, wollen wir aus unserem Template nun unsere erste eigene Applikation erstellen. Dazu klicken wir auf "Choose" und geben im folgenden Dialog Name und Package des Projekts an.

image-20220401092330030

Im nächsten Schritt müssen wir noch angeben, in welchem Repository das Projekt abgelegt werden soll. Als Owner geben wir einfach unseren Github-Benutzernamen an, und als Repository den Namen.

image-20220401094657956

Mit einem Klick auf "Next Step" sehen wir noch eine Zusammenfassung. Wenn alles ok ist, können wir auf "Create" klicken, um das Projekt zu erstellen. image-20220401094858922

Nun sehen wir das die Schritte "Fetch Skeleton + Template" und "Publish" erfolgreich ausgeführt worden sind. Beim Schritt "Register" gibt es jedoch noch einen Fehler, um den wir uns später kümmern.

image-20220401100214430 Jetzt schauen wir nach, wie das Projekt im Github angelegt wurde, und ob die Ersetzung der Variablen funktioniert hat. image-20220401100532871 Das Projekt wurde richtig als Test angelegt und in der Readme wurde auch alles korrekt ersetzt. Wir haben also erfolgreich unser erstes eigenes Template erstellt und daraus unsere erste Applikation erstellt. :-)

Katalog-Registrierung

Nun wollen wir uns noch anschauen, wieso die Komponente nicht im Backstage Software-Katalog registriert wurde. image-20220401100214430 Wie wir der Fehlermeldung entnehmen können, fehlt eine Datei namens catalog-info.yaml. Diese ist erforderlich, damit man neue, aber auch bestehende Komponenten im Software-Katalog registrieren können. Wir müssen also in unserem Template diese Datei noch ergänzen. Der Inhalt der Datei ist recht simpel. Wir müssen lediglich ein paar Metadaten angeben.

apiVersion: backstage.io/v1alpha1
kind: Component
metadata:
  name: ${{values.name | dump}}
  description: ${{values.description | dump}}
spec:
  type: service
  lifecycle: experimental
  owner: ${{values.owner | dump}}

Wenn wir unser bereits erstelltes Projekt nun in den Software-Katalog aufnehmen wollen, so reicht es diese Datei einfach in das Repository hinzuzufügen.

Wir können dies direkt im Github über "Add File" machen image-20220401101404107

Nun können wir im Backstage die Komponente direkt hinzufügen. Dazu gehen wir im Menupunkt "Create" und klicken dort "Register Existing Component". Als Pfad geben wir einfach den kompletten Pfad zur catalog-info an. image-20220401101616138 Bei Klick auf "Analyze" sollte nun die catalog-info gefunden werden und man kann diese über den Button "Import" importieren. Unter "Home" sollten wir diese neue Komponente nun sehen. image-20220401101755336

Fazit

Du hast nun Backstage kennengelernt und gesehen, wie du einfach und sehr elegant Software Templates in deinem Unternehmen zur Verfügung stellen kannst. Backstage ist ein guter Einstieg, damit sich Entwickler wieder auf ihre Kernkompetenz konzentrieren können, nämlich die Programmierung.

Stefan Welsch – Pionier, Stuntman, Mentor. Als Gründer von b-nova ist Stefan immer auf der Suche nach neuen und vielversprechenden Entwicklungsfeldern. Er ist durch und durch Pragmatiker und schreibt daher auch am liebsten Beiträge die sich möglichst nahe an 'real-world' Szenarien anlehnen.