Skip to content

Commit 4490d4a

Browse files
authored
Port 13920 support for search query relations in webhook resource (#263)
Added support for search query in webhook resource
1 parent c1b5028 commit 4490d4a

File tree

6 files changed

+885
-10
lines changed

6 files changed

+885
-10
lines changed

docs/resources/port_webhook.md

Lines changed: 207 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,216 @@ page_title: "port_webhook Resource - terraform-provider-port-labs"
44
subcategory: ""
55
description: |-
66
Webhook resource
7+
Webhook resource can be used to create webhooks integrations in Port.
8+
Example Usage
9+
```hcl
10+
resource "portblueprint" "author" {
11+
title = "Author"
12+
icon = "User"
13+
identifier = "author"
14+
properties = {
15+
stringprops = {
16+
"name" = {
17+
type = "string"
18+
title = "Name"
19+
}
20+
}
21+
}
22+
}
23+
resource "portblueprint" "team" {
24+
title = "Team"
25+
icon = "Team"
26+
identifier = "team"
27+
properties = {
28+
stringprops = {
29+
"name" = {
30+
type = "string"
31+
title = "Team Name"
32+
}
33+
}
34+
}
35+
}
36+
resource "portblueprint" "microservice" {
37+
title = "TF test microservice"
38+
icon = "Terraform"
39+
identifier = "microservice"
40+
properties = {
41+
stringprops = {
42+
"url" = {
43+
type = "string"
44+
title = "URL"
45+
}
46+
}
47+
}
48+
relations = {
49+
"author" = {
50+
title = "Author"
51+
target = portblueprint.author.identifier
52+
}
53+
"team" = {
54+
title = "Team"
55+
target = portblueprint.team.identifier
56+
}
57+
}
58+
}
59+
resource "portwebhook" "createpr" {
60+
identifier = "pr_webhook"
61+
title = "Webhook with mixed relations"
62+
icon = "Terraform"
63+
enabled = true
64+
mappings = [
65+
{
66+
blueprint = port_blueprint.microservice.identifier
67+
operation = { "type" = "create" }
68+
filter = ".headers.\"x-github-event\" == \"pull_request\""
69+
entity = {
70+
identifier = ".body.pull_request.id | tostring"
71+
title = ".body.pull_request.title"
72+
properties = {
73+
url = ".body.pull_request.html_url"
74+
}
75+
relations = {
76+
# Complex object relation with search query
77+
author = jsonencode({
78+
combinator = "'and'",
79+
rules = [
80+
{
81+
property = "'$identifier'"
82+
operator = "'='"
83+
value = ".body.pull_request.user.login | tostring"
84+
}
85+
]
86+
})
87+
88+
# Simple string relation
89+
team = ".body.repository.owner.login | tostring"
90+
}
91+
}
92+
}
93+
]
94+
95+
depends_on = [
96+
port_blueprint.microservice,
97+
port_blueprint.author,
98+
port_blueprint.team
99+
]
100+
101+
}
102+
```
103+
Notes
104+
When using object format for relations, combinator, property and operator fields should be enclosed in single quotes, while value should not have quotes as it's a JQ expression. The single quotes are required because these fields contain literal string values that must be passed as-is to the Port API, whereas value contains a JQ expression that should be evaluated dynamically.For all available operators, see the Port comparison operators documentation https://docs.port.io/search-and-query/comparison-operators.
7105
---
8106

9107
# port_webhook (Resource)
10108

11-
Webhook resource
109+
# Webhook resource
110+
Webhook resource can be used to create webhooks integrations in Port.
111+
112+
## Example Usage
113+
114+
```hcl
115+
resource "port_blueprint" "author" {
116+
title = "Author"
117+
icon = "User"
118+
identifier = "author"
119+
properties = {
120+
string_props = {
121+
"name" = {
122+
type = "string"
123+
title = "Name"
124+
}
125+
}
126+
}
127+
}
128+
129+
resource "port_blueprint" "team" {
130+
title = "Team"
131+
icon = "Team"
132+
identifier = "team"
133+
properties = {
134+
string_props = {
135+
"name" = {
136+
type = "string"
137+
title = "Team Name"
138+
}
139+
}
140+
}
141+
}
142+
143+
resource "port_blueprint" "microservice" {
144+
title = "TF test microservice"
145+
icon = "Terraform"
146+
identifier = "microservice"
147+
properties = {
148+
string_props = {
149+
"url" = {
150+
type = "string"
151+
title = "URL"
152+
}
153+
}
154+
}
155+
relations = {
156+
"author" = {
157+
title = "Author"
158+
target = port_blueprint.author.identifier
159+
}
160+
"team" = {
161+
title = "Team"
162+
target = port_blueprint.team.identifier
163+
}
164+
}
165+
}
166+
167+
resource "port_webhook" "create_pr" {
168+
identifier = "pr_webhook"
169+
title = "Webhook with mixed relations"
170+
icon = "Terraform"
171+
enabled = true
172+
173+
mappings = [
174+
{
175+
blueprint = port_blueprint.microservice.identifier
176+
operation = { "type" = "create" }
177+
filter = ".headers.\"x-github-event\" == \"pull_request\""
178+
entity = {
179+
identifier = ".body.pull_request.id | tostring"
180+
title = ".body.pull_request.title"
181+
properties = {
182+
url = ".body.pull_request.html_url"
183+
}
184+
relations = {
185+
# Complex object relation with search query
186+
author = jsonencode({
187+
combinator = "'and'",
188+
rules = [
189+
{
190+
property = "'$identifier'"
191+
operator = "'='"
192+
value = ".body.pull_request.user.login | tostring"
193+
}
194+
]
195+
})
196+
197+
# Simple string relation
198+
team = ".body.repository.owner.login | tostring"
199+
}
200+
}
201+
}
202+
]
203+
204+
depends_on = [
205+
port_blueprint.microservice,
206+
port_blueprint.author,
207+
port_blueprint.team
208+
]
209+
}
210+
211+
```
212+
213+
## Notes
214+
215+
- When using object format for relations, `combinator`, `property` and `operator` fields should be enclosed in single quotes, while `value` should not have quotes as it's a JQ expression. The single quotes are required because these fields contain literal string values that must be passed as-is to the Port API, whereas `value` contains a JQ expression that should be evaluated dynamically.
216+
- For all available operators, see the [Port comparison operators documentation](https://docs.port.io/search-and-query/comparison-operators).
12217

13218

14219

@@ -60,7 +265,7 @@ Optional:
60265

61266
- `icon` (String) The icon of the entity
62267
- `properties` (Map of String) The properties of the entity
63-
- `relations` (Map of String) The relations of the entity
268+
- `relations` (Map of String) The relations of the entity. Relations can be defined as either simple JQ expressions (strings) or search query objects. When using objects, the rules array must be encoded with jsonencode().
64269
- `team` (String) The team of the entity
65270
- `title` (String) The title of the entity
66271

internal/cli/models.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -412,7 +412,7 @@ type (
412412
Icon *string `json:"icon,omitempty"`
413413
Team *string `json:"team,omitempty"`
414414
Properties map[string]string `json:"properties,omitempty"`
415-
Relations map[string]string `json:"relations,omitempty"`
415+
Relations map[string]any `json:"relations,omitempty"`
416416
}
417417

418418
Mappings struct {

port/webhook/refreshWebhookState.go

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package webhook
22

33
import (
44
"context"
5+
"encoding/json"
56
"fmt"
67

78
"github.com/hashicorp/terraform-plugin-framework/types"
@@ -58,8 +59,19 @@ func refreshWebhookState(ctx context.Context, state *WebhookModel, w *cli.Webhoo
5859

5960
if v.Entity.Relations != nil {
6061
mapping.Entity.Relations = map[string]string{}
61-
for k, v := range v.Entity.Relations {
62-
mapping.Entity.Relations[k] = v
62+
for k, relationValue := range v.Entity.Relations {
63+
switch val := relationValue.(type) {
64+
case string:
65+
mapping.Entity.Relations[k] = val
66+
case map[string]interface{}:
67+
if jsonBytes, err := json.Marshal(val); err == nil {
68+
mapping.Entity.Relations[k] = string(jsonBytes)
69+
} else {
70+
return fmt.Errorf("failed to marshal relation '%s' to JSON: %w", k, err)
71+
}
72+
default:
73+
return fmt.Errorf("invalid relation type for key '%s': expected string or object, got %T", k, val)
74+
}
6375
}
6476
}
6577

0 commit comments

Comments
 (0)