Skip to main content

Check out Port for yourselfย 

Set up automatic discovery

As part of the onboarding process, Port provides you with a set of self-service actions to create new services, workloads, environments, users, and teams.
These actions involve manually selecting the components related to the new entity.

These are routine tasks that most organizations perform on a regular basis, which is why the manual process of using these actions is not efficient or scalable.

This guide will walk you through automating the process of creating and updating these entities in a way that suits your organization's standards.

Component definitions

Not sure what these entities mean? See their definitions here.

Discovery methodsโ€‹

This page describes two steps you can take to automatically discover and update entities in your catalog:

  1. Define one of your external tools as a "source of truth" for the resources you want to ingest.
  2. Use metadata from your external tools (e.g. labels, naming conventions) to identify and update an entity in Port.

Both steps require modifying the mapping configuration of the relevant integration.

How to modify a mapping configuration (click to expand)
  1. Go to the data sources page of your portal.
  2. Under "Exporters", find the relevant integration and click on it.
  3. A window will open, containing the mapping configuration. Use the editor in the bottom-left corner to update the configuration.
  4. Click on the "Save & Resync" button to save the changes and resync the integration.

Step 1: Define a source of truthโ€‹

This approach is useful when you want to create entities of a specific type (e.g. services, environments, teams, users) based on resources from a specific external tool.

Full exampleโ€‹

One example that works for many organizations is to define a Git repository as a source of truth for services, and automatically create a new service in Port for each repository in your Git provider.

To achieve this, we need to update the mapping configuration of the Git integration to include an entry for the service blueprint.
Here is an example using the GitHub integration:

- kind: repository
selector:
query: 'true'
teams: true
port:
entity:
mappings:
identifier: .full_name
title: .name
blueprint: '"githubRepository"'
properties:
readme: file://README.md
url: .html_url
defaultBranch: .default_branch
relations:
githubTeams: '[.teams[].id | tostring]'
- kind: repository
selector:
query: 'true'
port:
entity:
mappings:
identifier: .full_name
title: .full_name
blueprint: '"service"'
relations:
repository: .full_name

The first kind block is the default mapping when installing the GitHub integration. The meaning of this block is:
For every repository in the GitHub organization, create a new githubRepository entity in Port with the specified properties.

The second kind block is the one we need to add. The meaning of this block is:
For every repository in the GitHub organization, create a new service entity in Port, and relate it to the relevant githubRepository entity.

With this approach, services will always have a related repository upon creation, and can later be enriched with additional data from other assets in your catalog.

Additional examples by integrationโ€‹

Just like the example above, the blocks in the examples below can be added to the mapping configuration of the relevant integration to automatically create entities in your catalog.

Common examples for resources that can be used as a source of truth for services:

GitHub repository (click to expand)
- kind: repository
selector:
query: 'true'
port:
entity:
mappings:
identifier: .full_name
title: .full_name
blueprint: '"service"'
relations:
repository: .full_name

Monorepo support

If you are using a monorepo, see the working with monorepos page to learn how to tweak the mapping configuration to create entities for each folder in the repository.

Once you have done this, you can add the following block to the mapping configuration to create a service entity for each folder in the repository, and relate it to the relevant githubRepository entity:

# Be sure to change the `path` and `repos` values to match your monorepo structure
- kind: folder
selector:
query: "true"
folders: # Specify the repositories and folders to include under this relative path
- path: apps/* # Relative path to the folders within the repositories
repos: # List of repositories to include folders from
- backend-service
- frontend-service
port:
entity:
mappings:
identifier: ".folder.name"
title: ".folder.name"
blueprint: '"service"'
relations:
repository: ".folder.name"
GitLab project (click to expand)
- kind: project
selector:
query: 'true'
port:
entity:
mappings:
identifier: .path_with_namespace | gsub(" "; "")
title: .name
blueprint: '"service"'
relations:
git_lab_repositry: .path_with_namespace | gsub(" "; "")

Monorepo support

If you are using a monorepo, see the working with monorepos page to learn how to tweak the mapping configuration to create entities for each folder in the repository.

Once you have done this, you can add the following block to the mapping configuration to create a service entity for each folder in the repository, and relate it to the relevant gitlabRepository entity:

# Be sure to change the `path` and `repos` values to match your monorepo structure
- kind: folder
selector:
query: "true"
folders: # Specify the repositories and folders to include under this relative path
- path: "apps/" # Relative path to the folders within the repositories
repos: # List of repositories to include folders from
- backend-service
- frontend-service
port:
entity:
mappings:
identifier: .folder.name
title: .folder.name
blueprint: '"service"'
relations:
git_lab_repositry: .folder.name
Bitbucket repository (click to expand)
- kind: repository
selector:
query: 'true'
port:
entity:
mappings:
identifier: .name
title: .name
blueprint: '"service"'
relations:
bitbucketRepository: .name

Monorepo support

If you are using a monorepo, see the working with monorepos page to learn how to tweak the mapping configuration to create entities for each folder in the repository.

Once you have done this, you can add the following block to the mapping configuration to create a service entity for each folder in the repository, and relate it to the relevant bitbucketRepository entity:

# Be sure to change the `path` and `repos` values to match your monorepo structure
- kind: folder
selector:
query: "true"
folders: # Specify the repositories and folders to include under this relative path
- path: apps/* # Relative path to the folders within the repositories
repos: # List of repositories to include folders from
- backend-service
- frontend-service
port:
entity:
mappings:
identifier: .folder.name
blueprint: '"service"'
relations:
bitbucketRepository: .folder.name
Azure DevOps repository (click to expand)
- kind: repository
selector:
query: 'true'
port:
entity:
mappings:
identifier: .project.name + "/" + .name | gsub(" "; "")
title: .name
blueprint: '"service"'
relations:
azureDevopsRepository: .project.name + "/" + .name | gsub(" "; "")
SonarQube project (click to expand)
- kind: projects_ga
selector:
query: 'true'
apiFilters:
qualifier:
- TRK
metrics:
- code_smells
- coverage
- bugs
- vulnerabilities
- duplicated_files
- security_hotspots
- new_violations
- new_coverage
- new_duplicated_lines_density
port:
entity:
mappings:
identifier: .key
title: .name
blueprint: '"service"'
relations:
sonar_project: .key
Snyk target (click to expand)
- kind: target
selector:
query: 'true'
port:
entity:
mappings:
identifier: .id
title: .attributes.display_name
blueprint: '"service"'
relations:
snyk_target: .id
PagerDuty service (click to expand)
- kind: services
selector:
query: 'true'
port:
entity:
mappings:
identifier: .id
title: .name
blueprint: '"service"'
relations:
pager_duty_service: .id
OpsGenie service (click to expand)
- kind: service
selector:
query: 'true'
port:
entity:
mappings:
identifier: .id
title: .name
blueprint: '"service"'
relations:
_opsGenieService: .id

Step 2: Use predefined metadataโ€‹

In addition to defining "sources of truth", you can use data from your external tools to identify and update entities in Port.
This is useful when you want to update entities of a specific type (e.g. services, environments, teams, users) based on a label, naming convention, or other piece of metadata in a specific external tool.

See below for various examples of how to implement this.

Identifier is knownโ€‹

The most straightforward way to identify and update an entity is to have its identifier somewhere in the metadata of the external tool, for instance:

  • In a label/tag.
  • Using a naming convention, e.g. naming all PagerDuty services with the prefix service-<identifier>.

Here are some examples:

After installing the PagerDuty integration and ingesting our PagerDuty services, we may want to automatically connect them to their corresponding service entities.

To achieve this, we need to update the mapping configuration of the PagerDuty integration to include an entry for the service blueprint.

This example assumes that each PagerDuty service has a label named portService with the value being the identifier of the relevant service entity in Port.

- kind: services
selector:
query: 'true'
port:
entity:
mappings:
identifier: .metadata.labels.portService
blueprint: '"service"'
relations:
pager_duty_service: .id

The meaning of this configuration is:
For every PagerDuty service ingested from PagerDuty, update the service entity with the identifier matching the portService label, relating it to this pagerdutyService entity.

Identifier is unknownโ€‹

If the metadata in your external tool is not an identifier, but some other property of the entity you want to update, you can use a query rule to find the relevant entity and update it.

Let's see some examples:

The following example assumes that each PagerDuty service has a label named portService with the value being the title of the service entity in Port:

- kind: application
selector:
query: 'true'
port:
entity:
mappings:
identifier:
combinator: '"and"'
rules:
- operator: '"="'
property: '"$title"'
value: .metadata.labels.portService
blueprint: '"service"'
relations:
pager_duty_service: .id

The meaning of this configuration is:
For every PagerDuty service ingested from PagerDuty, update the service entity with the title matching the portService label, relating it to this pagerdutyService entity.