Blog
/
/
A Quick Migration From Backstage to Port & What You Need to Know
backstage
backstage

A Quick Migration From Backstage to Port & What You Need to Know

Aug 9, 2023
Daniel Sinai

Introduction

Building an internal developer portal often begins with some experimentation. Typically, we see users trying to build a basic software catalog and define some developer self-service actions. They then check how all of this would fit in a platform engineering initiative. In some cases, they begin by creating a “draft” internal developer portal in backstage. 

This post will cover how to move your data from Backstage to Port. We’ll show a quick and handy way of importing from backstage, and then will go deeper to discuss the more interesting stuff such as extending the data model, adding stateful objects and kubernetes data. 

The quick export

Let’s assume I’ve invested some time in creating a backstage internal developer portal and now I want to migrate all of it into Port. While I can work manually to migrate the data, the process can be tedious, which is why we developed an OSS tool that allows you to do the following at a click of a button:

  • Data model definition - from backstage to Port blueprints.
  • Ingesting data using the Backstage API
  • Extending the data model using Port’s Blueprints.

To use the automatic migration all you need to do is:

  1. Clone this repository git clone https://github.com/port-labs/backstage-import.git
  2. Create a .env file with the following values

BACKSTAGE_URL=<your backstage url i.e https://demo.backstage.io>

PORT_CLIENT_ID=<your port client id>

PORT_CLIENT_SECRET=<your port secret>

  1. Run the following command

./import.sh

For more information, you can visit our official docs for this tool.

Now that the migration is over, let’s take a deeper look at what actually happens, and use this as an opportunity to think about how Port can extend the internal developer portal built in Backstage. 

{{cta_5}}

A closer look at migration: from data model definition to adding Kubernetes resources to the internal developer portal

Let’s look at the three steps used for the migration and break them up to understand how Port extends backstage but also lets you leverage your existing backstage investment.

  • Data model definition
  • Ingesting data from Backstage API
  • Optimizing blueprints according to relation usage

Step 1: The internal developer portal data model or schema

As far as developer portals go, the first thing to do is consider what you want to pull inside the internal developer portal. Some people call this a taxonomy for the developer portal, and at Port, we call this capability “blueprints”. A Blueprint, or custom entity definition, is a data model that allows definition of the metadata associated with software catalog entities. Blueprints are the main building block of Port. Populated blueprints are catalog entities. Blueprints support the representation of any asset in Port, such as microservice, environment, package, cluster, databases etc. Port’s blueprint approach means that the product in itself is completely un-opinionated about how to build the data model, as a result of the understanding that engineering organizations want to be able to control the data model to fit their needs. 

Backstage uses the C4 model as its recommended data model (you can read more in this blog post). Port also supports a C4 model blueprint template, based on GitOps. The strength of this approach is that it goes beyond microservices and catalogs underlying cloud resources, deployments and related dependencies. Here’s a set of blueprints that would cover the C4 model:

If we were doing the migration manually, we would essentially convert “component” and “resource” objects from backstage and replace backstage’s “depends on” relation to Port relationships.

Step 2: Ingesting data - are we talking GitOps only?

Once the data model is ready - or, in other words, that the blueprints and relations exist - we need to ingest data into the developer portal. In this case we will query the backstage  Entities API and then all the entities will be formed in accordance with the blueprints.

Note that in Backstage, all the entities are managed in GitOps using a catalog-info.yaml file living inside your repository. But there are other ways to get data into an internal developer portal.

Port is an API-first platform, so the way entities are inserted can be in various ways such as GitOps, Terraform, Pulumi, CI/CD, Exporters (Such as AWS exporter, K8s exporter), and any other place that can send a simple CURL request. While managing entities backstage-style using GitOps makes a lot of sense, let’s assume we want to continue using GitOps even after we migrated from backstage to Port (which natively supports Git).

When we click on the 3 dots button next to our user profile, we can export blueprint data at GitOps.

In the following form we specify which blueprints we would like to manage via GitOps, and the format output as GitOps. You can also decide to manage it via terraform or a simple JSON if you like.


Step 3: extending the data model to Kubernetes and stateful objects

Now, once all the entities exist in Port, let’s begin extending the data model.

For example, in Backstage, because of its opinionated approach, there is a relation between Component -> User, and a Component -> Team, which reflects the ownership of the Component.

While this might be true for some organizations, it doesn’t work for all of them, for instance when organizations would like to enforce assigning ownership only to teams. Once we’ve migrated into Port, cleaning this up through the blueprints should be fairly easy. 

Another thing we can do is add stateful objects. A Running Service blueprint reflects the service as it appears in a specific environment, for example, staging, production, etc…

We can also add data about our runtime environment from Kubernetes, as is described here

Happy migration!


{{cta_4}}

{{cta}}

Book a demo right now to check out Port's developer portal yourself

Book a demo
{{jenkins}}

It's a Trap - Jenkins as Self service UI

Read more
{{gitops}}

How do GitOps affect developer experience?

Read more
{{ebook}}

It's a Trap - Jenkins as Self service UI. Click her to download the eBook

Download eBook
{{cyberark}}

Learning from CyberArk - building an internal developer platform in-house

Read more
{{dropdown}}

Example JSON block

{
  "foo": "bar"
}

Order Domain

{
  "properties": {},
  "relations": {},
  "title": "Orders",
  "identifier": "Orders"
}

Cart System

{
  "properties": {},
  "relations": {
    "domain": "Orders"
  },
  "identifier": "Cart",
  "title": "Cart"
}

Products System

{
  "properties": {},
  "relations": {
    "domain": "Orders"
  },
  "identifier": "Products",
  "title": "Products"
}

Cart Resource

{
  "properties": {
    "type": "postgress"
  },
  "relations": {},
  "icon": "GPU",
  "title": "Cart SQL database",
  "identifier": "cart-sql-sb"
}

Cart API

{
 "identifier": "CartAPI",
 "title": "Cart API",
 "blueprint": "API",
 "properties": {
   "type": "Open API"
 },
 "relations": {
   "provider": "CartService"
 },
 "icon": "Link"
}

Core Kafka Library

{
  "properties": {
    "type": "library"
  },
  "relations": {
    "system": "Cart"
  },
  "title": "Core Kafka Library",
  "identifier": "CoreKafkaLibrary"
}

Core Payment Library

{
  "properties": {
    "type": "library"
  },
  "relations": {
    "system": "Cart"
  },
  "title": "Core Payment Library",
  "identifier": "CorePaymentLibrary"
}

Cart Service JSON

{
 "identifier": "CartService",
 "title": "Cart Service",
 "blueprint": "Component",
 "properties": {
   "type": "service"
 },
 "relations": {
   "system": "Cart",
   "resources": [
     "cart-sql-sb"
   ],
   "consumesApi": [],
   "components": [
     "CorePaymentLibrary",
     "CoreKafkaLibrary"
   ]
 },
 "icon": "Cloud"
}

Products Service JSON

{
  "identifier": "ProductsService",
  "title": "Products Service",
  "blueprint": "Component",
  "properties": {
    "type": "service"
  },
  "relations": {
    "system": "Products",
    "consumesApi": [
      "CartAPI"
    ],
    "components": []
  }
}

Component Blueprint

{
 "identifier": "Component",
 "title": "Component",
 "icon": "Cloud",
 "schema": {
   "properties": {
     "type": {
       "enum": [
         "service",
         "library"
       ],
       "icon": "Docs",
       "type": "string",
       "enumColors": {
         "service": "blue",
         "library": "green"
       }
     }
   },
   "required": []
 },
 "mirrorProperties": {},
 "formulaProperties": {},
 "calculationProperties": {},
 "relations": {
   "system": {
     "target": "System",
     "required": false,
     "many": false
   },
   "resources": {
     "target": "Resource",
     "required": false,
     "many": true
   },
   "consumesApi": {
     "target": "API",
     "required": false,
     "many": true
   },
   "components": {
     "target": "Component",
     "required": false,
     "many": true
   },
   "providesApi": {
     "target": "API",
     "required": false,
     "many": false
   }
 }
}

Resource Blueprint

{
 “identifier”: “Resource”,
 “title”: “Resource”,
 “icon”: “DevopsTool”,
 “schema”: {
   “properties”: {
     “type”: {
       “enum”: [
         “postgress”,
         “kafka-topic”,
         “rabbit-queue”,
         “s3-bucket”
       ],
       “icon”: “Docs”,
       “type”: “string”
     }
   },
   “required”: []
 },
 “mirrorProperties”: {},
 “formulaProperties”: {},
 “calculationProperties”: {},
 “relations”: {}
}

API Blueprint

{
 "identifier": "API",
 "title": "API",
 "icon": "Link",
 "schema": {
   "properties": {
     "type": {
       "type": "string",
       "enum": [
         "Open API",
         "grpc"
       ]
     }
   },
   "required": []
 },
 "mirrorProperties": {},
 "formulaProperties": {},
 "calculationProperties": {},
 "relations": {
   "provider": {
     "target": "Component",
     "required": true,
     "many": false
   }
 }
}

Domain Blueprint

{
 "identifier": "Domain",
 "title": "Domain",
 "icon": "Server",
 "schema": {
   "properties": {},
   "required": []
 },
 "mirrorProperties": {},
 "formulaProperties": {},
 "calculationProperties": {},
 "relations": {}
}

System Blueprint

{
 "identifier": "System",
 "title": "System",
 "icon": "DevopsTool",
 "schema": {
   "properties": {},
   "required": []
 },
 "mirrorProperties": {},
 "formulaProperties": {},
 "calculationProperties": {},
 "relations": {
   "domain": {
     "target": "Domain",
     "required": true,
     "many": false
   }
 }
}
{{tabel-1}}

Microservices SDLC

  • Scaffold a new microservice

  • Deploy (canary or blue-green)

  • Feature flagging

  • Revert

  • Lock deployments

  • Add Secret

  • Force merge pull request (skip tests on crises)

  • Add environment variable to service

  • Add IaC to the service

  • Upgrade package version

Development environments

  • Spin up a developer environment for 5 days

  • ETL mock data to environment

  • Invite developer to the environment

  • Extend TTL by 3 days

Cloud resources

  • Provision a cloud resource

  • Modify a cloud resource

  • Get permissions to access cloud resource

SRE actions

  • Update pod count

  • Update auto-scaling group

  • Execute incident response runbook automation

Data Engineering

  • Add / Remove / Update Column to table

  • Run Airflow DAG

  • Duplicate table

Backoffice

  • Change customer configuration

  • Update customer software version

  • Upgrade - Downgrade plan tier

  • Create - Delete customer

Machine learning actions

  • Train model

  • Pre-process dataset

  • Deploy

  • A/B testing traffic route

  • Revert

  • Spin up remote Jupyter notebook

{{tabel-2}}

Engineering tools

  • Observability

  • Tasks management

  • CI/CD

  • On-Call management

  • Troubleshooting tools

  • DevSecOps

  • Runbooks

Infrastructure

  • Cloud Resources

  • K8S

  • Containers & Serverless

  • IaC

  • Databases

  • Environments

  • Regions

Software and more

  • Microservices

  • Docker Images

  • Docs

  • APIs

  • 3rd parties

  • Runbooks

  • Cron jobs

Check out Port's pre-populated demo and see what it's all about.

Check live demo

No email required

Contact sales for a technical product walkthrough

Let’s start

Open a free Port account. No credit card required

Let’s start

Watch Port live coding videos - setting up an internal developer portal & platform

Let’s start

Check out Port's pre-populated demo and see what it's all about.

(no email required)

Let’s start

Contact sales for a technical product walkthrough

Let’s start

Open a free Port account. No credit card required

Let’s start

Watch Port live coding videos - setting up an internal developer portal & platform

Let’s start

Let us walk you through the platform and catalog the assets of your choice.

I’m ready, let’s start