Skip to main content

Check out Port for yourselfย 

Advanced input configurations

Advanced input settings allow you to create more customizable experiences for users who perform self-service actions. This is done by creating adaptive inputs that change according to data about the entity, the user, and other inputs.

Common use-casesโ€‹

  • Filter the available options in a dropdown input.
  • Create a dependency between inputs to allow the user to select a value based on the value of another input.
  • Define dynamic default values based on the logged-in user properties(such as teams, email, role) or the entity that the action is being executed on (for day-2 or delete actions only).
Pulumi Examples' Language

Unless otherwise specified, all Pulumi configuration examples are provided in Python. For usage in other languages, please see the Pulumi provider documentation here.

Usageโ€‹

Defining advanced inputs is currently supported in JSON-mode only.

When creating an action, the second step is defining its inputs. After defining at least one input, an Advanced configuration section will appear in the bottom of the form. Click on Edit JSON, then add your configuration in JSON format.

Writing your configuration schemaโ€‹

Port provides a jqQuery property that can be used to extract data from the entity, the logged-in user, or the current action's form inputs. It can also be used to perform data manipulations.

For example, the following jqQuery checks the value of another property (language) and determines the possible values of the SDK property accordingly:

{
"properties": {
"language": {
"type": "string",
"enum": ["javascript", "python"]
},
"SDK": {
"type": "string",
"enum": {
"jqQuery": "if .form.language == \"javascript\" then [\"Node 16\", \"Node 18\"] else [\"Python 3.8\"] end"
}
}
}
}

The properties you can access using the "jqQuery" objectโ€‹

The values of the inputs in the current action form.

Usage:

{
"jqQuery": ".form.input1"
}

The available form object(each input is a key in the action's userInputs object):

{
"input1": "...",
"input2": "...",
"input3": "..."
}

Keys that are supported with jqQuery expressions:

KeyDescription
enumany enum of a property
defaultthe default value of any property
requiredthe properties which will be required in the form
valuethe value inside a "dataset" rule
visiblethe condition to display any property in the form

Additional available propertiesโ€‹

You can use these additional properties to create more complex inputs:

The visible property is used to dynamically hide/show inputs in the form. The visible value could be set to either a boolean (true value is always shown, false value is always hidden), or to a jqQuery which evaluates to a boolean.

In this example, the runArguments properties are configured with visible so that they only show up in the form when the matching value is selected in the language input:

{
"properties": {
"language": {
"type": "string",
"enum": ["javascript", "python"]
},
"pythonRunArguments": {
"type": "string",
"visible": {
"jqQuery": ".form.language == \"python\""
}
},
"nodeRunArguments": {
"type": "string",
"visible": {
"jqQuery": ".form.language == \"javascript\""
}
}
}
}

Schema examplesโ€‹

Creating a dependency between two form inputsโ€‹

This example contains a dependency between the language input and the SDK input. The SDK input's available options are defined according to the selected language (see the jqQuery key).

{
"properties": {
"language": {
"type": "string",
"enum": ["javascript", "python"]
},
"SDK": {
"type": "string",
"enum": {
"jqQuery": "if .form.language == \"javascript\" then [\"Node 16\", \"Node 18\"] else [\"Python 3.8\"] end"
},
"dependsOn": ["language"]
}
}
}

Cluster And Namespace Action

Hiding property based on the executing user's rolesโ€‹

In this example, the visible checks if the executing user has the "admin" role, and if they don't have this role then the advanced option will be hidden for them. The default value will still be filled in and sent to the backend:

{
"properties": {
"simpleOption": {
"type": "string",
"enum": ["option1", "option2"]
},
"advancedOption": {
"type": "string",
"default": "default advanced value",
"visible": {
"jqQuery": ".user.roles | any(.name == \"Admin\")"
}
}
}
}

This is how the run form would show up for non-admin users: What Non-Admins See

And this is how the form would show up for admin users: What Admins See

Filter the dropdown's available options based on a propertyโ€‹

This example contains a filter that will only display the namespaces that are related to the cluster that was selected in the Cluster input:

{
"properties": {
"env": {
"type": "string",
"format": "entity",
"blueprint": "environment",
"dataset": {
"combinator": "and",
"rules": [
{
"property": "type",
"operator": "!=",
"value": "production"
}
]
}
}
}
}

Only Production Envs

โ˜ only the environments whose type is not production will appear in the dropdown. โ˜

Filter the dropdown's available options based on a previous inputโ€‹

This example contains a filter that will only display the namespaces that are related to the cluster that was selected in the Cluster input:

{
"properties": {
"Cluster": {
"type": "string",
"format": "entity",
"blueprint": "Cluster",
"title": "Cluster",
"description": "The cluster to create the namespace in"
},
"namespace": {
"type": "string",
"format": "entity",
"blueprint": "namespace",
"dependsOn": ["Cluster"],
"dataset": {
"combinator": "and",
"rules": [
{
"operator": "relatedTo",
"blueprint": "Cluster",
"value": {
"jqQuery": ".form.Cluster.identifier"
}
}
]
},
"title": "namespace",
"description": "The namespace to create the cluster in"
}
}
}

Cluster And Namespace Action

โ˜ The user will be required to choose a cluster, then the namespace input list will be populated with namespace entities related to the chosen cluster. โ˜

Filter the dropdown's available options based on properties of the user that executes the actionโ€‹

This example contains a filter that will only display the namespaces that belong to the user's teams (note the value key in the rules object):

{
"properties": {
"namespace": {
"type": "string",
"format": "entity",
"blueprint": "namespace",
"dataset": {
"combinator": "and",
"rules": [
{
"property": "$team",
"operator": "containsAny",
"value": {
"jqQuery": "[.user.teams[].name]"
}
}
]
}
}
}
}

โ˜ These are the only namespaces that are associated with the logged-in user's teams. โ˜

Filter the dropdown's available options based on the properties of the entity on which the action is performedโ€‹

This example contains a filter that will only display the namespaces that have similar tags to those of the entity on which the action is performed:

{
"properties": {
"namespace": {
"type": "string",
"format": "entity",
"blueprint": "namespace",
"dataset": {
"combinator": "and",
"rules": [
{
"property": "tags",
"operator": "containsAny",
"value": {
"jqQuery": "[.entity.properties.tags[]]"
}
}
]
}
}
}
}

Setting a default value with the jqQueryโ€‹

This example contains an array input with a default value that will be equal to the tags of the entity on which the action is performed:

{
"properties": {
"some_input": {
"type": "array",
"default": {
"jqQuery": ".entity.properties.tags"
}
}
}
}

entity tags action

โ˜ The namespace tags are already inserted into the form. โ˜

Setting required inputs with the jqQueryโ€‹

This example contains two user inputs: one will always be required, and the other will be required based on the entity's properties.

{
"properties": {
"alwaysRequiredInput": {
"type": "string"
},
"inputRequiredBasedOnData": {
"type": "string"
}
},
"required": {
"jqQuery": "if .entity.properties.conditionBooleanProperty then [\"alwaysRequiredInput\", \"inputRequiredBasedOnData\"] else [\"alwaysRequiredInput\"] end"
}
}

Complete Exampleโ€‹

In this example, we will create an action that lets the user select a cluster and a namespace in that cluster. The user will also be able to select a service that is already running in the cluster. The action will then deploy the selected service to the selected namespace in the cluster. The user will only be able to select a service that is linked to his team.

the existing model in Port:โ€‹

Developer PortalCreate New Blueprint

the action's configuration:โ€‹

{
"identifier": "createRunningService",
"title": "Deploy running service to a cluster",
"icon": "Cluster",
"trigger": {
"type": "self-service",
"operation": "CREATE",
"userInputs": {
"properties": {
"Cluster": {
"type": "string",
"format": "entity",
"blueprint": "Cluster",
"title": "Cluster",
"description": "The cluster to create the namespace in"
},
"namespace": {
"type": "string",
"format": "entity",
"blueprint": "namespace",
"dependsOn": ["Cluster"],
"dataset": {
"combinator": "and",
"rules": [
{
"operator": "relatedTo",
"blueprint": "Cluster",
"value": {
"jqQuery": ".form.Cluster.identifier"
}
}
]
},
"title": "namespace",
"description": "The namespace to create the cluster in"
},
"service": {
"type": "string",
"format": "entity",
"blueprint": "Service",
"dataset": {
"combinator": "and",
"rules": [
{
"property": "$team",
"operator": "containsAny",
"value": {
"jqQuery": "[.user.teams[].name]"
}
}
]
},
"title": "Service"
}
},
"required": ["Cluster", "namespace", "service"]
},
},
"invocationMethod": {
"type": "WEBHOOK",
"url": "https://example.com"
},
"description": "This will deploy a running service to a cluster"
}

The action in the developer portal:โ€‹

Cluster And Namespace Action

โ˜ The user will be required to choose a cluster, and then the namespace input list will be populated with namespace entities related to the chosen cluster. The user will only be able to deploy services associated with his team.
Note the $ before team, this indicates that this is a metadata property.