Port Controller
Kratix supports configuring and maintaining both day 1 and day 2 integrations with Port.
This page provides information on how to:
- Install the SKE Port Controller
- Setup GitHub Actions backend for Port Actions
- Configure Kratix GitOps for requests from Port Actions
- Expose a Promise in Port
This documentation assumes both a Port account as well as a GitHub Repository with enough permissions to manage GitHub Actions. If required, please refer to the Port and GitHub sign-up pages to create accounts.
Install the SKE Port Controller
Port provides a generic controller for pushing content from Kubernetes to the Port UI. By installing this via the SKE Controller you will get configuration and management of Kratix Promises and Resources automatically managed for you, including managing the backend of your choosing for the self-service actions in Port.
Prerequisites
To install the SKE Port Controller, you will need:
- A SKE token. To request one, visit Syntasso and click "Try SKE Today".
- A Kubernetes cluster with Kratix running. The Kratix Quick Start is an easy way to get started.
Configure the integration
To configure the controller, you will need to create a configmap and a secret in the
ske-port-controller-system
namespace.
Start by creating this namespace if you have not previously installed the controller.
Then create local environment variables for the three required values:
PORT_CLIENT_ID
PORT_CLIENT_SECRET
PORT_GITHUB_ORG
And review the remaining default configurations. If you require overriding any, set those local environment variables as well.
PORT_GITHUB_REPO
(default: port-syncer)PORT_GITHUB_WORKFLOW_FILE
(default: port-action.yml)PORT_CM_NAME
(default: ske-port-k8s-exporter)PORT_CM_NAMESPACE
(default: ske-port-controller-system)PORT_SKIP_DELETE_BLUEPRINT
(default: false)
Once environment variables have been set, you can create the configmap using the following command:
kubectl create secret generic -n ske-port-controller-system ske-port-exporter-config \
--from-literal="PORT_CLIENT_ID=${PORT_CLIENT_ID}" \
--from-literal="PORT_CLIENT_SECRET=${PORT_CLIENT_SECRET}" \
--from-literal="PORT_GITHUB_ORG=${PORT_GITHUB_ORG}" \
--from-literal="PORT_GITHUB_REPO=${PORT_GITHUB_REPO:-}" \
--from-literal="PORT_GITHUB_WORKFLOW_FILE=${PORT_GITHUB_WORKFLOW_FILE:-}" \
--from-literal="PORT_CM_NAME=${PORT_CM_NAME:-}" \
--from-literal="PORT_CM_NAMESPACE=${PORT_CM_NAMESPACE:-}" \
--from-literal="PORT_SKIP_DELETE_BLUEPRINT=${PORT_SKIP_DELETE_BLUEPRINT:-}"
Access the enterprise controller image
Next you can either pre-load the required image into your cluster, or define your authentication credentials via a docker-registry secret and refer to this secret in Pipeline definition in your Workflow.
The release is set to use imagePullSecret
, to access the enterprise image. To create
the secret, replacing YOUR_TOKEN with the token you have been provided with:
kubectl create secret docker-registry syntasso-registry \
--namespace ske-port-controller-system \
--docker-server=registry.syntasso.io \
--docker-username=syntasso-pkg \
--docker-password=YOUR_TOKEN
If you prefer, you can load the image onto the Kubernetes nodes for local access.
To pull the image, select the image at the correct version from the releases page, then pull and load that image.
docker pull ghcr.io/syntasso/ske-port-controller:<VERSION>
Install the controller
Finally, to install the controller, run the command below, replacing VERSION with the target version from the releases page:
kubectl apply -f http://s3.eu-west-2.amazonaws.com/syntasso-enterprise-releases/ske-port-controller/<VERSION>/install.yaml
Setup GitHub Actions backend for Port Actions
Port is a user interface and depends on other tools to manage the platform orchestration
side of things. Port provides a number of backend integrations
to trigger this orchestration including GitHub Actions which is what this guide depends
on. Therefore, the PORT_GITHUB_REPO
must be set up to work with the Port actions.
First, your repo needs its Actions to be configured to allow commits. Follow GitHub instructions on how to manage this setting here.
Next, your Actions need both the PORT_CLIENT_ID
and PORT_CLIENT_SECRET
secrets set.
Follow GitHub instructions on how to set these up
here.
Finally, the repository must have a GitHub Action workflow file that can generate resource requests that match the Promise CRD.
Below is an example action stored in a workflow file called port-action.yml
(the file
name is configurable using the PORT_GITHUB_WORKFLOW
environment variable). This example
will support create, update, and delete flows as well as sharing log data back to Port:
Example port-action.yml
contents
name: Sync control plane gitops
permissions:
contents: write
pull-requests: write
on:
workflow_dispatch:
inputs:
operation:
required: true
description: "Delete, Update or create"
type: string
triggeringUser:
required: true
description: "The email of the triggering user"
type: string
runId:
required: true
description: "Port's Run ID"
type: string
manifest:
required: true
description: "The K8s manifest generated by Port"
type: string
folder:
required: true
description: Folder where the resource will be stored
default: "./kratix/platform/resources"
type: string
jobs:
commit-to-main:
runs-on: ubuntu-latest
steps:
- name: checkout
uses: actions/checkout@v2
- uses: actions/setup-python@v5
with:
python-version: '3.10'
- name: Update manifests folder
run: |
echo '${{ inputs.manifest }}' | jq . > temp.json
yaml_data=$(yq -p json -o yaml temp.json)
name=$(echo '${{ inputs.manifest }}' | jq -r .metadata.name)
mkdir -p ${{ inputs.folder }}
if [ "${{ inputs.operation }}" = "DELETE" ]; then
rm -f "${{ inputs.folder }}/$name.yaml"
else
echo "$yaml_data" > "${{ inputs.folder }}/$name.yaml"
fi
rm -f temp.json
- uses: port-labs/port-github-action@v1
with:
clientId: ${{ secrets.PORT_CLIENT_ID }}
clientSecret: ${{ secrets.PORT_CLIENT_SECRET }}
operation: PATCH_RUN
runId: ${{inputs.runId}}
icon: GithubActions
logMessage: "Creating a commit with the changes of the new resource in folder ${{ inputs.folder }} 🚀"
- name: create commit to main
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
git config user.name "GitHub Action"
git config user.email "github-actions[bot]@users.noreply.github.com"
git add .
if ! git diff-index --quiet HEAD; then
git commit -m "chore: ${{ inputs.operation }} resource by ${{ inputs.triggeringUser }}"
git push origin main
fi
- uses: port-labs/port-github-action@v1
if: success()
with:
clientId: ${{ secrets.PORT_CLIENT_ID }}
clientSecret: ${{ secrets.PORT_CLIENT_SECRET }}
operation: PATCH_RUN
runId: ${{inputs.runId}}
icon: GithubActions
logMessage: |
Successfully committed request to main ✅
- uses: port-labs/port-github-action@v1
if: failure()
with:
clientId: ${{ secrets.PORT_CLIENT_ID }}
clientSecret: ${{ secrets.PORT_CLIENT_SECRET }}
operation: PATCH_RUN
runId: ${{inputs.runId}}
icon: GithubActions
logMessage: |
Failed to commit request to main ❌
Resource may have been created outside of Port 🕵
Check the job run logs in Github to learn more 📜:
${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
Configure GitOps for requests from Port Actions
So far you have configured Port to use GitHub Actions as a backend for the Port self-serve actions and automations. You have then configured the GitHub Action to commit user requests to the defined repository.
Now you will need to configure a GitOps agent to pull the repository documents into the cluster where Kratix runs. This will enable Kratix to respond to resources that are created via Port.
Please refer to the guide documentation to use ArgoCD, Flux, or any other agent you prefer.
Part of the configuration is making sure that the GitOps agent is reading from the repository that Port is writing to. An example set up when using FluxCD and the defaults from above can be found below.
Example Flux Resources for Port-Syncer repository
---
apiVersion: source.toolkit.fluxcd.io/v1
kind: GitRepository
metadata:
name: kratix-port-resources
namespace: flux-system
spec:
interval: 5s
url: https://github.com/${PORT_GITHUB_ORG}/${PORT_GITHUB_REPO}
ref:
branch: main
secretRef:
name: github-creds
---
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
name: kratix-port-resources
namespace: flux-system
spec:
interval: 3s
sourceRef:
kind: GitRepository
name: kratix-port-resources
path: "kratix/platform/resources/"
prune: true
Expose a Promise in Port
While many platform APIs benefit from being available, you may not want all platform APIs in the Port UI. For this reason, Kratix uses an opt-in methodology.
To expose a Promise via the Port UI, make sure to add a label
kratix.io/get-port: "true"
in the Kratix Promise API. For example, to expose the
marketplace namespace promise,
it would look like this:
apiVersion: platform.kratix.io/v1alpha1
kind: Promise
metadata:
name: namespace
namespace: default
spec:
api:
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: namespaces.marketplace.kratix.io
labels:
kratix.io/get-port: "true"
spec:
group: marketplace.kratix.io
names:
kind: namespace
plural: namespaces
singular: namespace
scope: Namespaced
versions:
- name: v1alpha1
schema:
openAPIV3Schema:
properties:
spec:
properties:
clusterName:
description: |
The name of the cluster where the namespace should be created
type: string
namespaceName:
description: |
The name of the namespace to be created
type: string
required:
- namespaceName
type: object
type: object
served: true
storage: true
workflows:
resource:
configure:
- apiVersion: platform.kratix.io/v1alpha1
kind: Pipeline
metadata:
name: instance-configure
namespace: default
spec:
containers:
- image: ghcr.io/syntasso/kratix-marketplace/namespace-configure-pipeline:v0.1.0
name: namespace-configure-pipeline