Skip to content

Commit 4016746

Browse files
authored
Merge pull request #225 from port-labs/feat/add-pattern-jq-query-to-string-props
verify contribution from hedinasr
2 parents 37a5b2a + 72bb285 commit 4016746

File tree

9 files changed

+466
-14
lines changed

9 files changed

+466
-14
lines changed

action.test

31.8 MB
Binary file not shown.

docs/resources/port_action.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -675,6 +675,7 @@ Optional:
675675
- `max_length` (Number) The max length of the string property
676676
- `min_length` (Number) The min length of the string property
677677
- `pattern` (String) The pattern of the string property
678+
- `pattern_jq_query` (String) The pattern jq query of the string property. This field accepts a JQ expression to dynamically generate either a regex pattern (as a string) or a list of allowed values (as an array). Cannot be used with `pattern`. Empty values are not allowed. Examples: `"if .env == \"prod\" then \"^[a-z]+$\" else \"^[a-zA-Z]+$\" end"` for dynamic regex patterns, or `"[\"value1\", \"value2\"]"` for a fixed list of allowed values.
678679
- `required` (Boolean) Whether the property is required, by default not required, this property can't be set at the same time if `required_jq_query` is set, and only supports true as value
679680
- `sort` (Attributes) How to sort entities when in the self service action form in the UI (see [below for nested schema](#nestedatt--self_service_trigger--user_properties--string_props--sort))
680681
- `title` (String) The title of the property
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
# Pattern JQ Query Examples
2+
3+
This example demonstrates how to use the `pattern_jq_query` attribute in different ways:
4+
5+
## Ways to Use `pattern_jq_query`
6+
7+
The `pattern_jq_query` field accepts a JQ expression that gets evaluated by the Port API at runtime. This JQ expression can produce:
8+
9+
### 1. A Regex Pattern
10+
11+
```hcl
12+
pattern_jq_query = "if .environment == \"production\" then \"^[a-z][a-z0-9-]{3,20}$\" else \"^[a-z][a-z0-9-]{2,10}$\" end"
13+
```
14+
15+
This approach generates a regex pattern dynamically based on context. It works like the static `pattern` field but allows the regex to change based on other properties.
16+
17+
### 2. A List of Allowed Values
18+
19+
```hcl
20+
pattern_jq_query = "if .team == \"platform\" then [\"dev\", \"staging\", \"production\"] else [\"dev\", \"staging\"] end"
21+
```
22+
23+
This approach generates a list of allowed values dynamically. It's similar to an enum but with values that can change based on context.
24+
25+
### 3. Direct JSON Array of Allowed Values
26+
27+
```hcl
28+
pattern_jq_query = "[\"value1\", \"value2\", \"value3\"]"
29+
```
30+
31+
This simpler format can be used to specify a fixed list of allowed values directly.
32+
33+
## Important Notes
34+
35+
- You cannot use both `pattern` and `pattern_jq_query` at the same time on the same property
36+
- The JQ query is evaluated at runtime by Port
37+
- The context available to the JQ expression depends on where the pattern is being used (entity context, action context, etc.)
38+
- For regex patterns, make sure to escape special characters properly
39+
40+
## How to Use
41+
42+
1. Choose which approach is most appropriate for your use case
43+
2. Write a JQ expression or JSON array as needed
44+
3. Apply the pattern validation to the appropriate string property in your action definition
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
# This example demonstrates different ways to use pattern_jq_query
2+
3+
# Example 1: Using pattern_jq_query to dynamically generate a regex pattern
4+
resource "port_action" "regex_pattern_example" {
5+
title = "Create Service"
6+
identifier = "create_service"
7+
self_service_trigger = {
8+
operation = "CREATE"
9+
blueprint_identifier = "service"
10+
user_properties = {
11+
string_props = {
12+
service_name = {
13+
title = "Service Name"
14+
# Dynamic regex pattern based on context
15+
pattern_jq_query = "if .environment == \"production\" then \"^[a-z][a-z0-9-]{3,20}$\" else \"^[a-z][a-z0-9-]{2,10}$\" end"
16+
description = "Name of the service (lowercase, numbers, hyphens)"
17+
}
18+
}
19+
}
20+
}
21+
description = "Create a new service"
22+
webhook_method = {
23+
url = "https://api.example.com/create-service"
24+
}
25+
}
26+
27+
# Example 2: Using pattern_jq_query to dynamically generate a list of allowed values
28+
resource "port_action" "allowed_values_example" {
29+
title = "Deploy To Environment"
30+
identifier = "deploy_to_env"
31+
self_service_trigger = {
32+
operation = "DAY-2"
33+
blueprint_identifier = "microservice"
34+
user_properties = {
35+
string_props = {
36+
target_environment = {
37+
title = "Target Environment"
38+
# Dynamic allowed values based on context
39+
pattern_jq_query = "if .team == \"platform\" then [\"dev\", \"staging\", \"production\"] else [\"dev\", \"staging\"] end"
40+
description = "Environment to deploy to (platform team can deploy to production)"
41+
}
42+
}
43+
}
44+
}
45+
description = "Deploy service to environment"
46+
webhook_method = {
47+
url = "https://api.example.com/deploy"
48+
}
49+
}
50+
51+
# Example 3: Using pattern_jq_query with a direct JSON array of allowed values
52+
resource "port_action" "direct_array_example" {
53+
title = "Select Region"
54+
identifier = "select_region"
55+
self_service_trigger = {
56+
operation = "CREATE"
57+
blueprint_identifier = "deployment"
58+
user_properties = {
59+
string_props = {
60+
region = {
61+
title = "Region"
62+
# Direct JSON array of allowed values
63+
pattern_jq_query = "[\"us-east-1\", \"us-west-1\", \"eu-west-1\", \"ap-northeast-1\"]"
64+
description = "AWS region for deployment"
65+
}
66+
}
67+
}
68+
}
69+
description = "Select deployment region"
70+
webhook_method = {
71+
url = "https://api.example.com/select-region"
72+
}
73+
}

internal/cli/models.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ type (
8888
Minimum *float64 `json:"minimum,omitempty"`
8989
Description *string `json:"description,omitempty"`
9090
Blueprint *string `json:"blueprint,omitempty"`
91-
Pattern *string `json:"pattern,omitempty"`
91+
Pattern any `json:"pattern,omitempty"`
9292
Enum any `json:"enum,omitempty"`
9393
Spec *string `json:"spec,omitempty"`
9494
SpecAuthentication *SpecAuthentication `json:"specAuthentication,omitempty"`

port/action/model.go

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -30,17 +30,18 @@ type StringPropModel struct {
3030
Visible types.Bool `tfsdk:"visible"`
3131
VisibleJqQuery types.String `tfsdk:"visible_jq_query"`
3232

33-
Default types.String `tfsdk:"default"`
34-
Blueprint types.String `tfsdk:"blueprint"`
35-
Format types.String `tfsdk:"format"`
36-
MaxLength types.Int64 `tfsdk:"max_length"`
37-
MinLength types.Int64 `tfsdk:"min_length"`
38-
Pattern types.String `tfsdk:"pattern"`
39-
Enum types.List `tfsdk:"enum"`
40-
EnumColors types.Map `tfsdk:"enum_colors"`
41-
EnumJqQuery types.String `tfsdk:"enum_jq_query"`
42-
Encryption types.String `tfsdk:"encryption"`
43-
Sort *EntitiesSortModel `tfsdk:"sort"`
33+
Default types.String `tfsdk:"default"`
34+
Blueprint types.String `tfsdk:"blueprint"`
35+
Format types.String `tfsdk:"format"`
36+
MaxLength types.Int64 `tfsdk:"max_length"`
37+
MinLength types.Int64 `tfsdk:"min_length"`
38+
Pattern types.String `tfsdk:"pattern"`
39+
PatternJqQuery types.String `tfsdk:"pattern_jq_query"`
40+
Enum types.List `tfsdk:"enum"`
41+
EnumColors types.Map `tfsdk:"enum_colors"`
42+
EnumJqQuery types.String `tfsdk:"enum_jq_query"`
43+
Encryption types.String `tfsdk:"encryption"`
44+
Sort *EntitiesSortModel `tfsdk:"sort"`
4445
}
4546

4647
// StringPropValidationModel is a model used for the validation of StringPropModel resources

0 commit comments

Comments
 (0)