Skip to main content

ArgoCD

Our ArgoCD integration allows you to import cluster, project, application and deployment-history resources from your ArgoCD instance into Port, according to your mapping and definition.

Common use cases

  • Map your monitored Kubernetes resources in ArgoCD.
  • Watch for object changes (create/update) in real-time, and automatically apply the changes to your entities in Port.

Installation

Choose one of the following installation methods:

Using this installation option means that the integration will be able to update Port in real time using webhooks.

This table summarizes the available parameters for the installation. Set them as you wish in the script below, then copy it and run it in your terminal:

ParameterDescriptionRequired
port.clientIdYour port client id
port.clientSecretYour port client secret
port.baseUrlYour port base url, relevant only if not using the default port app
integration.identifierChange the identifier to describe your integration
integration.typeThe integration type
integration.eventListener.typeThe event listener type
integration.secrets.tokenThe ArgoCD API token token
integration.config.serverUrlThe ArgoCD server url
scheduledResyncIntervalThe number of minutes between each resync
initializePortResourcesDefault true, When set to true the integration will create default blueprints and the port App config Mapping

To install the integration using Helm, run the following command:

helm repo add --force-update port-labs https://port-labs.github.io/helm-charts
helm upgrade --install my-argocd-integration port-labs/port-ocean \
--set port.clientId="CLIENT_ID" \
--set port.clientSecret="CLIENT_SECRET" \
--set initializePortResources=true \
--set scheduledResyncInterval=60 \
--set integration.identifier="my-argocd-integration" \
--set integration.type="argocd" \
--set integration.eventListener.type="POLLING" \
--set integration.secrets.token="<your-token>" \
--set integration.config.serverUrl="<your-server-url>"

Generating ArgoCD token

  1. Navigate to <serverURL>/settings/accounts/<user>. For example, if you access your ArgoCD at https://localhost:8080, you should navigate to https://localhost:8080/settings/accounts/<user>
  2. The user should have apiKey capabilities to allow generating authentication tokens for API access. If you don't have a user created yet, follow the guide on how to create a new ArgoCD user
  3. Newly created users may have limited scope to resources by default. For that reason, You will need to configure RBAC policy for the new user by following this guide
  4. Ensure that the policy definition grants enough permission to read resources such as applications, clusters, projects, repositories etc.
  5. Under Tokens on your ArgoCD UI, Click Generate New to create a new token for the user or use the CLI:
argocd account generate-token --account <username>
Creating ArgoCD user with readonly permissions
  1. Create an argocd-user.yaml file with the below manifest to create a new user port-ocean-user
Create user manifest (click to expand)
apiVersion: v1
kind: ConfigMap
metadata:
name: argocd-cm
namespace: argocd
labels:
app.kubernetes.io/name: argocd-cm
app.kubernetes.io/part-of: argocd
data:
# add an additional local user with apiKey and login capabilities
# apiKey - allows generating API keys
# login - allows to login using UI
accounts.port-ocean-user: apiKey, login
accounts.port-ocean-user.enabled: "true"
  1. Apply the manifest with kubectl to create the user:
kubectl apply -f argocd-user.yaml
  1. Grant read only RBAC policy to the new user using the below manifest file (argocd-rbac-cm.yaml)
RBAC policy to grant readonly role to the new user (click to expand)
apiVersion: v1
kind: ConfigMap
metadata:
name: argocd-rbac-cm
namespace: argocd
data:
policy.default: role:readonly
policy.csv: |
p, role:read-only-role, applications, *, */*, allow
p, role:read-only-role, clusters, get, *, allow
p, role:read-only-role, repositories, get, *, allow
p, role:read-only-role, projects, get, *, allow
p, role:read-only-role, logs, get, *, allow

g, port-ocean-user, role:read-only-role
  1. Apply the argocd-rbac-cm.yaml manifest with kubectl:
kubectl apply -f argocd-rbac-cm.yaml
  1. Go to your ArgoCD UI to generate a new token for the user or use the CLI
argocd account generate-token --account <username>

Ingesting ArgoCD objects

The ArgoCD integration uses a YAML configuration to describe the process of loading data into the developer portal.

Here is an example snippet from the config which demonstrates the process for getting application data from ArgoCD:

createMissingRelatedEntities: true
deleteDependentEntities: true
resources:
- kind: application
selector:
query: "true"
port:
entity:
mappings:
identifier: .metadata.uid
title: .metadata.name
blueprint: '"argocdApplication"'
properties:
gitRepo: .spec.source.repoURL
gitPath: .spec.source.path
destinationServer: .spec.destination.server
namespace: .metadata.namespace
syncStatus: .status.sync.status
healthStatus: .status.health.status
createdAt: .metadata.creationTimestamp
relations:
project: .spec.project

The integration makes use of the JQ JSON processor to select, modify, concatenate, transform and perform other operations on existing fields and values from ArgoCD's API events.

Configuration structure

The integration configuration determines which resources will be queried from ArgoCD, and which entities and properties will be created in Port.

Supported resources

The following resources can be used to map data from ArgoCD, it is possible to reference any field that appears in the API responses linked below for the mapping configuration.

  • The root key of the integration configuration is the resources key:

    resources:
    - kind: application
    selector:
    ...
  • The kind key is a specifier for an ArgoCD object:

      resources:
    - kind: application
    selector:
    ...
  • The selector and the query keys allow you to filter which objects of the specified kind will be ingested into your software catalog:

    resources:
    - kind: application
    selector:
    query: "true" # JQ boolean expression. If evaluated to false - this object will be skipped.
    port:
  • The port, entity and the mappings keys are used to map the ArgoCD object fields to Port entities. To create multiple mappings of the same kind, you can add another item in the resources array;

    resources:
    - kind: application
    selector:
    query: "true"
    port:
    entity:
    mappings: # Mappings between one ArgoCD object to a Port entity. Each value is a JQ query.
    identifier: .metadata.uid
    title: .metadata.name
    blueprint: '"argocdApplication"'
    properties:
    gitRepo: .spec.source.repoURL
    gitPath: .spec.source.path
    destinationServer: .spec.destination.server
    namespace: .metadata.namespace
    syncStatus: .status.sync.status
    healthStatus: .status.health.status
    createdAt: .metadata.creationTimestamp
    relations:
    project: .spec.project
    - kind: application # In this instance application is mapped again with a different filter
    selector:
    query: '.metadata.name == "MyApplicationName"'
    port:
    entity:
    mappings: ...
    Blueprint key

    Note the value of the blueprint key - if you want to use a hardcoded string, you need to encapsulate it in 2 sets of quotes, for example use a pair of single-quotes (') and then another pair of double-quotes (")

Configuring real-time updates

Currently, the ArgoCD REST API lacks support for programmatic webhook creation. To set up a webhook configuration in ArgoCD for sending notifications to the Ocean integration, follow these steps:

Prerequisite

  1. You have access to a Kubernetes cluster where ArgoCD is deployed.
  2. You have kubectl installed and configured to access your cluster.

Steps

  1. Install ArgoCD notifications manifest;
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj-labs/argocd-notifications/release-1.0/manifests/install.yaml
  1. Install ArgoCD triggers and templates manifest;
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj-labs/argocd-notifications/release-1.0/catalog/install.yaml
  1. Use kubectl to connect to the Kubernetes cluster where your ArgoCD instance is deployed;
kubectl config use-context <your-cluster-context>
  1. Set the current namespace to your ArgoCD namespace, use the following command;
kubectl config set-context --current --namespace=<your-namespace>
  1. Create a YAML file (e.g. argocd-webhook-config.yaml) that configures the webhook notification service. The example below shows how to set up a webhook to send real-time events whenever ArgoCD applications are updated. The YAML file includes the following components:

    1. Notification service definition;
    2. Template for the webhook message body;
    3. Trigger definitions;
    4. Subscriptions to the notifications.

    Here's an example YAML. Make sure to replace <WEBHOOK_URL> with the actual URL of the ingress or service where the ocean integration will be deployed. By default, incoming webhook events are sent to /integration/webhook path in Ocean so do not replace the path parameter.

    webhook manifest file
    apiVersion: v1
    kind: ConfigMap
    metadata:
    name: argocd-notifications-cm
    data:
    trigger.on-sync-operation-change: |
    - description: Application syncing has updated
    send:
    - app-status-change
    when: app.status.operationState.phase in ['Error', 'Failed', 'Succeeded', 'Running']
    trigger.on-deployed: |
    - description: Application is synced and healthy
    send:
    - app-status-change
    when: app.status.operationState.phase in ['Succeeded'] and app.status.health.status == 'Healthy'
    trigger.on-health-degraded: |
    - description: Application has degraded
    send:
    - app-status-change
    when: app.status.health.status == 'Degraded'
    service.webhook.port-ocean: |
    url: <WEBHOOK_URL>
    headers:
    - name: Content-Type
    value: application/json
    template.app-status-change: |
    webhook:
    port-ocean:
    method: POST
    path: /integration/webhook
    body: |
    {
    "action": "upsert",
    "application_name": "{{.app.metadata.name}}"
    }
    subscriptions: |
    - recipients:
    - port-ocean
    triggers:
    - on-deployed
    - on-health-degraded
    - on-sync-operation-change
  2. Use kubectl to apply the YAML file to your cluster. Run the following command, replacing <your-namespace> with your ArgoCD namespace and <path-to-yaml-file> with the actual path to your YAML file:

kubectl apply -n <your-namespace> -f <path-to-yaml-file>

This command deploys the webhook notification configuration to your ArgoCD notification configmap (argocd-notifications-cm), allowing Ocean to receive real-time events.

Ingest data into Port

To ingest ArgoCD objects using the integration configuration, you can follow the steps below:

  1. Go to the DevPortal Builder page.
  2. Select a blueprint you want to ingest using ArgoCD.
  3. Choose the Ingest Data option from the menu.
  4. Select ArgoCD under the Kubernetes Stack providers category.
  5. Modify the configuration according to your needs.
  6. Click Resync.

Examples

Examples of blueprints and the relevant integration configurations:

Cluster

Cluster blueprint
  {
"identifier": "argocdCluster",
"description": "This blueprint represents an ArgoCD cluster",
"title": "ArgoCD Cluster",
"icon": "Argo",
"schema": {
"properties": {
"applicationsCount": {
"title": "Applications Count",
"type": "number",
"description": "The number of applications managed by Argo CD on the cluster",
"icon": "DefaultProperty"
},
"serverVersion": {
"title": "Server Version",
"type": "string",
"description": "Contains information about the Kubernetes version of the cluster",
"icon": "DefaultProperty"
},
"labels": {
"title": "Labels",
"type": "object",
"description": "Contains information about cluster metadata",
"icon": "DefaultProperty"
},
"updatedAt": {
"icon": "DefaultProperty",
"title": "Updated At",
"type": "string",
"format": "date-time"
},
"server": {
"title": "Server",
"description": "The API server URL of the Kubernetes cluster",
"type": "string",
"icon": "DefaultProperty"
}
},
"required": []
},
"mirrorProperties": {},
"calculationProperties": {},
"relations": {}
}
Integration configuration
createMissingRelatedEntities: true
deleteDependentEntities: true
resources:
- kind: cluster
selector:
query: "true"
port:
entity:
mappings:
identifier: .name
title: .name
blueprint: '"argocdCluster"'
properties:
applicationsCount: .info.applicationsCount
serverVersion: .serverVersion
labels: .labels
updatedAt: .connectionState.attemptedAt
server: .server

Namespace

Namespace blueprint
  {
"identifier": "argocdNamespace",
"description": "This blueprint represents an ArgoCD namespace",
"title": "ArgoCD Namespace",
"icon": "Argo",
"schema": {
"properties": {},
"required": []
},
"aggregationProperties": {},
"mirrorProperties": {},
"calculationProperties": {},
"relations": {
"cluster": {
"title": "ArgoCD Cluster",
"target": "argocdCluster",
"required": false,
"many": false
}
}
}
Integration configuration
createMissingRelatedEntities: true
deleteDependentEntities: true
resources:
- kind: cluster
selector:
query: "true"
port:
itemsToParse: .namespaces
entity:
mappings:
identifier: .name + "-" + .item | tostring
title: .name + "-" + .item
blueprint: '"argocdNamespace"'
properties: {}
relations:
cluster: .name

Project

Project blueprint
  {
"identifier": "argocdProject",
"description": "This blueprint represents an ArgoCD Project",
"title": "ArgoCD Project",
"icon": "Argo",
"schema": {
"properties": {
"createdAt": {
"title": "Created At",
"type": "string",
"format": "date-time",
"icon": "DefaultProperty"
},
"description": {
"title": "Description",
"description": "Project description",
"type": "string",
"icon": "DefaultProperty"
}
},
"required": []
},
"mirrorProperties": {},
"calculationProperties": {},
"relations": {}
}
Integration configuration
createMissingRelatedEntities: true
deleteDependentEntities: true
resources:
- kind: project
selector:
query: "true"
port:
entity:
mappings:
identifier: .metadata.name
title: .metadata.name
blueprint: '"argocdProject"'
properties:
createdAt: .metadata.creationTimestamp
description: .spec.description

Application

Application blueprint
  {
"identifier": "argocdApplication",
"description": "This blueprint represents an ArgoCD Application",
"title": "Running Service",
"icon": "Argo",
"schema": {
"properties": {
"gitRepo": {
"type": "string",
"icon": "Git",
"title": "Repository URL",
"description": "The URL of the Git repository containing the application source code"
},
"gitPath": {
"type": "string",
"title": "Path",
"description": "The path within the Git repository where the application manifests are located"
},
"destinationServer": {
"type": "string",
"title": "Destination Server",
"description": "The URL of the target cluster's Kubernetes control plane API"
},
"revision": {
"type": "string",
"title": "Revision",
"description": "Revision contains information about the revision the comparison has been performed to"
},
"targetRevision": {
"type": "string",
"title": "Target Revision",
"description": "Target Revision defines the revision of the source to sync the application to. In case of Git, this can be commit, tag, or branch"
},
"syncStatus": {
"type": "string",
"title": "Sync Status",
"enum": [
"Synced",
"OutOfSync",
"Unknown"
],
"enumColors": {
"Synced": "green",
"OutOfSync": "red",
"Unknown": "lightGray"
},
"description": "Status is the sync state of the comparison"
},
"healthStatus": {
"type": "string",
"title": "Health Status",
"enum": [
"Healthy",
"Missing",
"Suspended",
"Degraded",
"Progressing",
"Unknown"
],
"enumColors": {
"Healthy": "green",
"Missing": "yellow",
"Suspended": "purple",
"Degraded": "red",
"Progressing": "blue",
"Unknown": "lightGray"
},
"description": "Status holds the status code of the application or resource"
},
"createdAt": {
"title": "Created At",
"type": "string",
"format": "date-time",
"description": "The created timestamp of the application"
},
"labels": {
"type": "object",
"title": "Labels",
"description": "Map of string keys and values that can be used to organize and categorize object"
},
"annotations": {
"type": "object",
"title": "Annotations",
"description": "Annotations are unstructured key value map stored with a resource that may be set by external tools to store and retrieve arbitrary metadata"
}
},
"required": []
},
"mirrorProperties": {},
"calculationProperties": {},
"relations": {
"project": {
"title": "ArgoCD Project",
"target": "argocdProject",
"required": false,
"many": false
},
"cluster": {
"title": "ArgoCD Cluster",
"target": "argocdCluster",
"required": false,
"many": false
},
"namespace": {
"title": "ArgoCD Namespace",
"target": "argocdNamespace",
"required": false,
"many": false
}
}
}
Integration configuration
createMissingRelatedEntities: true
deleteDependentEntities: true
resources:
- kind: application
selector:
query: "true"
port:
entity:
mappings:
identifier: .metadata.uid
title: .metadata.name
blueprint: '"argocdApplication"'
properties:
gitRepo: .spec.source.repoURL
gitPath: .spec.source.path
destinationServer: .spec.destination.server
revision: .status.sync.revision
targetRevision: .spec.source.targetRevision
syncStatus: .status.sync.status
healthStatus: .status.health.status
createdAt: .metadata.creationTimestamp
labels: .metadata.labels
annotations: .metadata.annotations
relations:
project: .spec.project
namespace: .metadata.namespace
cluster: .spec.destination.name

Deployment history

Deployment history blueprint
  {
"identifier": "argocdDeploymentHistory",
"description": "This blueprint represents an ArgoCD deployment history",
"title": "ArgoCD Deployment History",
"icon": "Argo",
"schema": {
"properties": {
"deployedAt": {
"title": "Deployed At",
"type": "string",
"format": "date-time"
},
"deployStartedAt": {
"title": "Deploy Started At",
"type": "string",
"format": "date-time"
},
"revision": {
"title": "Revision",
"type": "string"
},
"initiatedBy": {
"title": "Initiated By",
"type": "string"
},
"repoURL": {
"title": "Repository URL",
"type": "string"
},
"sourcePath": {
"title": "Source Path",
"type": "string"
}
},
"required": []
},
"mirrorProperties": {},
"calculationProperties": {},
"aggregationProperties": {},
"relations": {
"application": {
"title": "Application",
"target": "argocdApplication",
"required": false,
"many": false
}
}
}
Integration configuration
createMissingRelatedEntities: true
deleteDependentEntities: true
resources:
- kind: application
selector:
query: "true"
port:
itemsToParse: .status.history
entity:
mappings:
identifier: .metadata.uid + "-" + (.item.id | tostring)
title: .metadata.name + "-" + (.item.id | tostring)
blueprint: '"argocdDeploymentHistory"'
properties:
deployedAt: .item.deployedAt
deployStartedAt: .item.deployStartedAt
revision: .item.source.repoURL + "/commit/" + .item.revision
initiatedBy: .item.initiatedBy.username
repoURL: .item.source.repoURL
sourcePath: .item.source.path
relations:
application: .metadata.uid

Kubernetes Resource

Kubernetes resource blueprint
  {
"identifier": "argocdKubernetesResource",
"description": "This blueprint represents an ArgoCD kubernetes resource",
"title": "Kubernetes Resource",
"icon": "Argo",
"schema": {
"properties": {
"kind": {
"title": "Kind",
"type": "string"
},
"version": {
"title": "Version",
"type": "string"
},
"namespace": {
"title": "Namespace",
"type": "string"
},
"labels": {
"type": "object",
"title": "Labels"
},
"annotations": {
"type": "object",
"title": "Annotations"
}
},
"required": []
},
"mirrorProperties": {
"healthStatus": {
"title": "Health Status",
"path": "application.healthStatus"
},
"syncStatus": {
"title": "Sync Status",
"path": "application.syncStatus"
}
},
"calculationProperties": {},
"aggregationProperties": {},
"relations": {
"application": {
"title": "Application",
"target": "argocdApplication",
"required": false,
"many": false
}
}
}
Integration configuration
createMissingRelatedEntities: true
deleteDependentEntities: true
resources:
- kind: managed-resource
selector:
query: "true"
port:
entity:
mappings:
identifier: .__application.metadata.uid + "-" + .name
title: .__application.metadata.name + "-" + .name
blueprint: '"argocdKubernetesResource"'
properties:
kind: .kind
namespace: .namespace
version: .resourceVersion
annotations: .liveState | fromjson | .metadata.annotations
labels: .liveState | fromjson | .metadata.labels
relations:
application: .__application.metadata.uid

Alternative installation via webhook

While the Ocean integration described above is the recommended installation method, you may prefer to use a webhook to ingest data from ArgoCD. If so, use the following instructions:

Webhook installation (click to expand)

In this example you are going to create a webhook integration between ArgoCD and Port, which will ingest application entities and map them to your ArgoCD projects.

Port configuration

Create the following blueprint definition:

Project blueprint
{
"identifier": "argocdProject",
"description": "This blueprint represents an ArgoCD Project",
"title": "ArgoCD Project",
"icon": "Argo",
"schema": {
"properties": {
"description": {
"title": "Description",
"description": "Project description",
"type": "string",
"icon": "DefaultProperty"
}
},
"required": []
},
"mirrorProperties": {},
"calculationProperties": {},
"relations": {}
}
Application blueprint
{
"identifier": "argocdApplication",
"description": "This blueprint represents an ArgoCD Application",
"title": "ArgoCD Application",
"icon": "Argo",
"schema": {
"properties": {
"gitRepo": {
"type": "string",
"format": "url",
"icon": "Git",
"title": "Repository URL",
"description": "The URL of the Git repository containing the application source code"
},
"gitPath": {
"type": "string",
"title": "Path",
"description": "The path within the Git repository where the application manifests are located"
},
"destinationServer": {
"type": "string",
"title": "Destination Server",
"format": "url"
},
"namespace": {
"type": "string",
"title": "Namespace"
},
"syncStatus": {
"type": "string",
"title": "Sync Status",
"enum": ["Synced", "OutOfSync", "Unknown"],
"enumColors": {
"Synced": "green",
"OutOfSync": "red",
"Unknown": "lightGray"
},
"description": "The sync status of the application"
},
"healthStatus": {
"type": "string",
"title": "Health Status",
"enum": [
"Healthy",
"Missing",
"Suspended",
"Degraded",
"Progressing",
"Unknown"
],
"enumColors": {
"Healthy": "green",
"Missing": "yellow",
"Suspended": "purple",
"Degraded": "red",
"Progressing": "blue",
"Unknown": "lightGray"
},
"description": "The health status of the application"
},
"createdAt": {
"title": "Created At",
"type": "string",
"format": "date-time"
}
},
"required": []
},
"mirrorProperties": {},
"calculationProperties": {},
"relations": {
"project": {
"title": "Project",
"target": "argocdProject",
"required": false,
"many": false
}
}
}

Create the following webhook configuration using Port UI

Application webhook configuration
  1. Basic details tab - fill the following details:

    1. Title : ArgoCD Application Mapper;
    2. Identifier : argocd_application_mapper;
    3. Description : A webhook configuration to map ArgoCD applications to Port;
    4. Icon : Argo;
  2. Integration configuration tab - fill the following JQ mapping:

    [
    {
    "blueprint": "argocdApplication",
    "filter": "true",
    "entity": {
    "identifier": ".body.uid | tostring",
    "title": ".body.name | tostring",
    "properties": {
    "gitRepo": ".body.git_repo",
    "gitPath": ".body.git_path",
    "destinationServer": ".body.destination_server",
    "namespace": ".body.namespace",
    "syncStatus": ".body.sync_status",
    "healthStatus": ".body.health_status",
    "createdAt": ".body.created_at"
    },
    "relations": {
    "project": ".body.project"
    }
    }
    }
    ]
  3. Click Save at the bottom of the page.

Create a webhook in ArgoCD

To set up a webhook configuration in ArgoCD for sending notifications to Port, follow these steps:

Prerequisite

  1. You have access to a Kubernetes cluster where ArgoCD is deployed.
  2. You have kubectl installed and configured to access your cluster.

Steps

  1. Install ArgoCD notifications manifest;
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj-labs/argocd-notifications/release-1.0/manifests/install.yaml
  1. Install ArgoCD triggers and templates manifest;
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj-labs/argocd-notifications/release-1.0/catalog/install.yaml
  1. Use kubectl to connect to the Kubernetes cluster where your ArgoCD instance is deployed;
kubectl config use-context <your-cluster-context>
  1. Set the current namespace to your ArgoCD namespace, use the following command;
kubectl config set-context --current --namespace=<your-namespace>
  1. Create a YAML file (e.g. argocd-webhook-config.yaml) that configures the webhook notification service. The example below shows how to set up a webhook to send real-time events whenever ArgoCD applications are updated. The YAML file includes the following components:

    1. Notification service definition;
    2. Template for the webhook message body;
    3. Trigger definitions;
    4. Subscriptions to the notifications.

    Here's an example YAML. Make sure to replace <YOUR_WEBHOOK_URL> with the value of url key you received after creating the webhook configuration.

    webhook manifest file
    apiVersion: v1
    kind: ConfigMap
    metadata:
    name: argocd-notifications-cm
    data:
    trigger.on-sync-operation-change: |
    - description: Application syncing has updated
    send:
    - app-status-change
    when: app.status.operationState.phase in ['Error', 'Failed', 'Succeeded', 'Running']
    trigger.on-deployed: |
    - description: Application is synced and healthy
    send:
    - app-status-change
    when: app.status.operationState.phase in ['Succeeded'] and app.status.health.status == 'Healthy'
    trigger.on-health-degraded: |
    - description: Application has degraded
    send:
    - app-status-change
    when: app.status.health.status == 'Degraded'
    service.webhook.port-webhook: |
    url: <YOUR_WEBHOOK_URL>
    headers:
    - name: Content-Type
    value: application/json
    template.app-status-change: |
    webhook:
    port-webhook:
    method: POST
    body: |
    {
    "uid": "{{.app.metadata.uid}}",
    "name": "{{.app.metadata.name}}",
    "namespace": "{{.app.metadata.namespace}}",
    "sync_status": "{{.app.status.sync.status}}",
    "health_status": "{{.app.status.health.status}}",
    "git_repo": "{{.app.spec.source.repoURL}}",
    "git_path": "{{.app.spec.source.path}}",
    "destination_server": "{{.app.spec.destination.server}}",
    "created_at": "{{.app.metadata.creationTimestamp}}",
    "project": "{{.app.spec.project}}"
    }
    subscriptions: |
    - recipients:
    - port-webhook
    triggers:
    - on-deployed
    - on-health-degraded
    - on-sync-operation-change
  2. Use kubectl to apply the YAML file to your cluster. Run the following command, replacing <your-namespace> with your ArgoCD namespace and <path-to-yaml-file> with the actual path to your YAML file:

kubectl apply -n <your-namespace> -f <path-to-yaml-file>

This command deploys the webhook notification configuration to your ArgoCD notification configmap (argocd-notifications-cm), allowing Port to receive real-time events.

Done! any change that happens to your applications in ArgoCD will trigger a webhook event to the webhook URL provided by Port. Port will parse the events according to the mapping and update the catalog entities accordingly.

Argocd Events

In this example you are going to create a webhook integration between ArgoCD and Port, which will ingest all events entities and map them to your ArgoCD applications.

Port configuration

Create the following blueprint definition:

Events blueprint
{
"identifier": "argocdEvent",
"description": "This blueprint represents ArgoCD events",
"title": "ArgoCD Events",
"icon": "Argo",
"schema": {
"properties": {
"event": {
"type": "string",
"title": "Event Name"
},
"namespace": {
"type": "string",
"title": "Namespace"
},
"description": {
"type": "string",
"title": "Description"
}
},
"required": []
},
"mirrorProperties": {},
"calculationProperties": {},
"aggregationProperties": {},
"relations": {
"application": {
"title": "Application",
"target": "argocdApplication",
"required": false,
"many": false
}
}
}

Create the following webhook configuration using Port UI

Application webhook configuration
  1. Basic details tab - fill the following details:

    1. Title : ArgoCD Event Mapper;
    2. Identifier : argocd_event_mapper;
    3. Description : A webhook configuration to map ArgoCD events to Port;
    4. Icon : Argo;
  2. Integration configuration tab - fill the following JQ mapping:

    [
    {
    "blueprint": "argocdEvent",
    "filter": "true",
    "entity": {
    "identifier": ".body.app_name + \"-\" + .body.event_name | tostring",
    "title": ".body.event_name | tostring",
    "properties": {
    "event": ".body.event_name",
    "namespace": ".body.namespace",
    "description": ".body.description"
    },
    "relations": {
    "application": ".body.uid"
    }
    }
    }
    ]
  3. Click Save at the bottom of the page.

Create a webhook in ArgoCD

To set up a webhook configuration in ArgoCD for sending notifications to Port, follow these steps:

Prerequisite

  1. You have access to a Kubernetes cluster where ArgoCD is deployed.
  2. You have kubectl installed and configured to access your cluster.

Steps

  1. Install ArgoCD notifications manifest;
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj-labs/argocd-notifications/release-1.0/manifests/install.yaml
  1. Install ArgoCD triggers and templates manifest;
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj-labs/argocd-notifications/release-1.0/catalog/install.yaml
  1. Use kubectl to connect to the Kubernetes cluster where your ArgoCD instance is deployed;
kubectl config use-context <your-cluster-context>
  1. Set the current namespace to your ArgoCD namespace, use the following command;
kubectl config set-context --current --namespace=<your-namespace>
  1. Create a YAML file (e.g. argocd-events-config.yaml) that configures the webhook notification service. The example below shows how to set up a webhook to send real-time events from ArgoCD. The YAML file includes the following components:

    1. Notification service definition;
    2. Template for the webhook message body;
    3. Trigger definitions;
    4. Subscriptions to the notifications.

    Here's an example YAML. Make sure to replace <YOUR_WEBHOOK_URL> with the value of url key you received after creating the webhook configuration.

    event manifest file
    apiVersion: v1
    kind: ConfigMap
    metadata:
    name: argocd-notifications-cm
    data:
    trigger.on-created: |
    - description: Application is created
    send:
    - app-created
    when: true
    oncePer: app.metadata.name
    trigger.on-sync-running: |
    - description: Application is being synced
    send:
    - app-sync-running
    when: app.status.operationState.phase in ['Running']
    trigger.on-sync-succeeded: |
    - description: Application syncing has succeeded
    send:
    - app-sync-succeeded
    when: app.status.operationState.phase in ['Succeeded']
    trigger.on-sync-failed: |
    - description: Application syncing has failed
    send:
    - app-sync-failed
    when: app.status.operationState.phase in ['Error', 'Failed']
    trigger.on-sync-status-unknown: |
    - description: Application status is Unknown
    send:
    - app-sync-status-unknown
    when: app.status.sync.status == 'Unknown'
    trigger.on-deployed: |
    - description: Application is synced and healthy
    send:
    - app-deployed
    when: app.status.operationState.phase in ['Succeeded'] and app.status.health.status == 'Healthy'
    trigger.on-health-degraded: |
    - description: Application has degraded
    send:
    - app-health-degraded
    when: app.status.health.status == 'Degraded'
    trigger.on-deleted: |
    - description: Application is deleted
    send:
    - app-deleted
    when: app.metadata.deletionTimestamp != nil
    oncePer: app.metadata.name
    service.webhook.port-webhook: |
    url: YOUR_WEBHOOK_URL
    headers:
    - name: Content-Type
    value: application/json
    template.app-created: |
    webhook:
    port-webhook:
    method: POST
    body: |
    {
    "uid": "{{.app.metadata.uid}}",
    "event_name": "on-created",
    "app_name": "{{.app.metadata.name}}",
    "namespace": "{{.app.metadata.namespace}}",
    "description": "Application is created"
    }
    template.app-sync-succeeded: |
    webhook:
    port-webhook:
    method: POST
    body: |
    {
    "uid": "{{.app.metadata.uid}}",
    "event_name": "on-sync-succeeded",
    "app_name": "{{.app.metadata.name}}",
    "namespace": "{{.app.metadata.namespace}}",
    "description": "Application syncing has succeeded"
    }
    template.app-sync-running: |
    webhook:
    port-webhook:
    method: POST
    body: |
    {
    "uid": "{{.app.metadata.uid}}",
    "event_name": "on-sync-running",
    "app_name": "{{.app.metadata.name}}",
    "namespace": "{{.app.metadata.namespace}}",
    "description": "Application is being synced"
    }
    template.app-sync-failed: |
    webhook:
    port-webhook:
    method: POST
    body: |
    {
    "uid": "{{.app.metadata.uid}}",
    "event_name": "on-sync-failed",
    "app_name": "{{.app.metadata.name}}",
    "namespace": "{{.app.metadata.namespace}}",
    "description": "Application syncing has failed"
    }
    template.app-health-degraded: |
    webhook:
    port-webhook:
    method: POST
    body: |
    {
    "uid": "{{.app.metadata.uid}}",
    "event_name": "on-health-degraded",
    "app_name": "{{.app.metadata.name}}",
    "namespace": "{{.app.metadata.namespace}}",
    "description": "Application has degraded"
    }
    template.app-deployed: |
    webhook:
    port-webhook:
    method: POST
    body: |
    {
    "uid": "{{.app.metadata.uid}}",
    "event_name": "on-deployed",
    "app_name": "{{.app.metadata.name}}",
    "namespace": "{{.app.metadata.namespace}}",
    "description": "Application is synced healthy"
    }
    template.app-sync-status-unknown: |
    webhook:
    port-webhook:
    method: POST
    body: |
    {
    "uid": "{{.app.metadata.uid}}",
    "event_name": "on-sync-status-unknown",
    "app_name": "{{.app.metadata.name}}",
    "namespace": "{{.app.metadata.namespace}}",
    "description": "Application status is Unknown"
    }
    template.app-deleted: |
    webhook:
    port-webhook:
    method: POST
    body: |
    {
    "uid": "{{.app.metadata.uid}}",
    "event_name": "on-deleted",
    "app_name": "{{.app.metadata.name}}",
    "namespace": "{{.app.metadata.namespace}}",
    "description": "Application deleted"
    }
    subscriptions: |
    - recipients:
    - port-webhook
    triggers:
    - on-created
    - on-deployed
    - on-health-degraded
    - on-sync-failed
    - on-sync-status-unknown
    - on-sync-succeeded
    - on-sync-running
    - on-deleted
  2. Use kubectl to apply the YAML file to your cluster. Run the following command, replacing <your-namespace> with your ArgoCD namespace and <path-to-yaml-file> with the actual path to your YAML file:

kubectl apply -n <your-namespace> -f <path-to-yaml-file>

This command deploys the webhook notification configuration to your ArgoCD notification configmap (argocd-notifications-cm), allowing Port to receive real-time events.

Done! any change that happens to your applications in ArgoCD will trigger a webhook event to the webhook URL provided by Port. Port will parse the events according to the mapping and update the catalog entities accordingly.

More relevant guides and examples: