diff --git a/docs/resources/port_action.md b/docs/resources/port_action.md
index 050d916e..e33352ec 100644
--- a/docs/resources/port_action.md
+++ b/docs/resources/port_action.md
@@ -6,34 +6,34 @@ description: |-
Action resource
Docs for the Action resource can be found here https://docs.getport.io/create-self-service-experiences/.
Example Usage
- ```hcl
- resource "portaction" "createmicroservice" {
+ hcl
+ resource "port_action" "create_microservice" {
title = "Create Microservice"
identifier = "create-microservice"
icon = "Terraform"
- selfservicetrigger = {
+ self_service_trigger = {
operation = "CREATE"
- blueprintidentifier = portblueprint.microservice.identifier
- userproperties = {
- stringprops = {
+ blueprint_identifier = port_blueprint.microservice.identifier
+ user_properties = {
+ string_props = {
myStringIdentifier = {
title = "My String Identifier"
required = true
format = "entity"
- blueprint = portblueprint.parent.identifier
+ blueprint = port_blueprint.parent.identifier
dataset = {
combinator = "and"
rules = [{
property = "$title"
operator = "contains"
value = {
- jqquery = "\"specificValue\""
+ jq_query = "\"specificValue\""
}
}]
}
}
}
- numberprops = {
+ number_props = {
myNumberIdentifier = {
title = "My Number Identifier"
required = true
@@ -41,25 +41,25 @@ description: |-
minimum = 0
}
}
- booleanprops = {
+ boolean_props = {
myBooleanIdentifier = {
title = "My Boolean Identifier"
required = true
}
}
- objectprops = {
+ object_props = {
myObjectIdentifier = {
title = "My Object Identifier"
required = true
}
}
- arrayprops = {
+ array_props = {
myArrayIdentifier = {
title = "My Array Identifier"
required = true
- stringitems = {
+ string_items = {
format = "entity"
- blueprint = portblueprint.parent.identifier
+ blueprint = port_blueprint.parent.identifier
dataset = jsonencode({
combinator = "and"
rules = [{
@@ -79,6 +79,26 @@ description: |-
})
}
}
+
+ Example Usage with Automation trigger
+ Port allows setting an automation trigger to an action, for executing an action based on event occurred to an entity in Port.
+ ```hcl
+ resource "portaction" "deletetemporarymicroservice" {
+ title = "Delete Temporary Microservice"
+ identifier = "delete-temp-microservice"
+ icon = "Terraform"
+ automationtrigger = {
+ timerpropertyexpiredevent = {
+ blueprintidentifier = portblueprint.microservice.identifier
+ propertyidentifier = "ttl"
+ }
+ }
+ kafka_method = {
+ payload = jsonencode({
+ runId: "{{.run.id}}"
+ })
+ }
+ }
```
Example Usage With Condition
```hcl
@@ -198,6 +218,29 @@ resource "port_action" "create_microservice" {
})
}
}
+```
+
+## Example Usage with Automation trigger
+
+Port allows setting an automation trigger to an action, for executing an action based on event occurred to an entity in Port.
+
+```hcl
+resource "port_action" "delete_temporary_microservice" {
+ title = "Delete Temporary Microservice"
+ identifier = "delete-temp-microservice"
+ icon = "Terraform"
+ automation_trigger = {
+ timer_property_expired_event = {
+ blueprint_identifier = port_blueprint.microservice.identifier
+ property_identifier = "ttl"
+ }
+ }
+ kafka_method = {
+ payload = jsonencode({
+ runId: "{{.run.id}}"
+ })
+ }
+}
```
@@ -252,6 +295,7 @@ resource "port_action" "create_microservice" {
- `approval_email_notification` (Object) The email notification of the approval (see [below for nested schema](#nestedatt--approval_email_notification))
- `approval_webhook_notification` (Attributes) The webhook notification of the approval (see [below for nested schema](#nestedatt--approval_webhook_notification))
+- `automation_trigger` (Attributes) Automation trigger for the action (see [below for nested schema](#nestedatt--automation_trigger))
- `azure_method` (Attributes) Azure DevOps invocation method (see [below for nested schema](#nestedatt--azure_method))
- `blueprint` (String, Deprecated) The blueprint identifier the action relates to
- `description` (String) Description
@@ -263,6 +307,7 @@ resource "port_action" "create_microservice" {
- `required_approval` (Boolean) Require approval before invoking the action
- `self_service_trigger` (Attributes) Self service trigger for the action (see [below for nested schema](#nestedatt--self_service_trigger))
- `title` (String) Title
+- `upsert_entity_method` (Attributes) Upsert Entity invocation method (see [below for nested schema](#nestedatt--upsert_entity_method))
- `webhook_method` (Attributes) Webhook invocation method (see [below for nested schema](#nestedatt--webhook_method))
### Read-Only
@@ -288,6 +333,72 @@ Optional:
- `format` (String) The format to invoke the webhook
+
+### Nested Schema for `automation_trigger`
+
+Optional:
+
+- `any_entity_change_event` (Attributes) Any entity change event trigger (see [below for nested schema](#nestedatt--automation_trigger--any_entity_change_event))
+- `entity_created_event` (Attributes) Entity created event trigger (see [below for nested schema](#nestedatt--automation_trigger--entity_created_event))
+- `entity_deleted_event` (Attributes) Entity deleted event trigger (see [below for nested schema](#nestedatt--automation_trigger--entity_deleted_event))
+- `entity_updated_event` (Attributes) Entity updated event trigger (see [below for nested schema](#nestedatt--automation_trigger--entity_updated_event))
+- `jq_condition` (Attributes) JQ condition for automation trigger (see [below for nested schema](#nestedatt--automation_trigger--jq_condition))
+- `timer_property_expired_event` (Attributes) Timer property expired event trigger (see [below for nested schema](#nestedatt--automation_trigger--timer_property_expired_event))
+
+
+### Nested Schema for `automation_trigger.any_entity_change_event`
+
+Required:
+
+- `blueprint_identifier` (String) The blueprint identifier of the changed entity
+
+
+
+### Nested Schema for `automation_trigger.entity_created_event`
+
+Required:
+
+- `blueprint_identifier` (String) The blueprint identifier of the created entity
+
+
+
+### Nested Schema for `automation_trigger.entity_deleted_event`
+
+Required:
+
+- `blueprint_identifier` (String) The blueprint identifier of the deleted entity
+
+
+
+### Nested Schema for `automation_trigger.entity_updated_event`
+
+Required:
+
+- `blueprint_identifier` (String) The blueprint identifier of the updated entity
+
+
+
+### Nested Schema for `automation_trigger.jq_condition`
+
+Required:
+
+- `expressions` (List of String) The jq expressions of the condition
+
+Optional:
+
+- `combinator` (String) The combinator of the condition
+
+
+
+### Nested Schema for `automation_trigger.timer_property_expired_event`
+
+Required:
+
+- `blueprint_identifier` (String) The blueprint identifier of the expired timer property
+- `property_identifier` (String) The property identifier of the expired timer property
+
+
+
### Nested Schema for `azure_method`
@@ -535,6 +646,23 @@ Optional:
+
+### Nested Schema for `upsert_entity_method`
+
+Required:
+
+- `blueprint_identifier` (String) Required when selecting type Upsert Entity. The blueprint identifier of the entity for the upsert
+- `identifier` (String) Required when selecting type Upsert Entity. The entity identifier for the upsert
+
+Optional:
+
+- `icon` (String) The icon of the entity
+- `properties` (String) The properties of the entity (key-value object encoded to a string)
+- `relations` (String) The relations of the entity (key-value object encoded to a string)
+- `teams` (List of String) The teams the entity belongs to
+- `title` (String) The title of the entity
+
+
### Nested Schema for `webhook_method`
diff --git a/internal/cli/models.go b/internal/cli/models.go
index f5301b43..202442dc 100644
--- a/internal/cli/models.go
+++ b/internal/cli/models.go
@@ -146,6 +146,15 @@ type (
Required []string `json:"required,omitempty"`
}
+ MappingSchema struct {
+ Identifier *string `json:"identifier,omitempty"`
+ Title *string `json:"title,omitempty"`
+ Team any `json:"team,omitempty"`
+ Icon *string `json:"icon,omitempty"`
+ Properties map[string]any `json:"properties,omitempty"`
+ Relations map[string]any `json:"relations,omitempty"`
+ }
+
InvocationMethod struct {
Type string `json:"type"`
Payload any `json:"payload,omitempty"`
@@ -166,13 +175,8 @@ type (
DefaultRef *string `json:"defaultRef,omitempty"`
PipelineVariables map[string]any `json:"pipelineVariables,omitempty"`
Webhook *string `json:"webhook,omitempty"`
- Identifier *string `json:"identifier,omitempty"`
- Title *string `json:"title,omitempty"`
BlueprintIdentifier *string `json:"blueprintIdentifier,omitempty"`
- Team any `json:"team,omitempty"`
- Icon *string `json:"icon,omitempty"`
- Properties map[string]any `json:"properties,omitempty"`
- Relations map[string]any `json:"relations,omitempty"`
+ Mapping *MappingSchema `json:"mapping,omitempty"`
}
ApprovalNotification struct {
diff --git a/port/action/actionStateToPortBody.go b/port/action/actionStateToPortBody.go
index 49b1f33b..2ee962d5 100644
--- a/port/action/actionStateToPortBody.go
+++ b/port/action/actionStateToPortBody.go
@@ -5,6 +5,7 @@ import (
"github.com/port-labs/terraform-provider-port-labs/v2/internal/cli"
"github.com/port-labs/terraform-provider-port-labs/v2/internal/consts"
+ "github.com/port-labs/terraform-provider-port-labs/v2/internal/flex"
"github.com/port-labs/terraform-provider-port-labs/v2/internal/utils"
)
@@ -110,6 +111,58 @@ func triggerToBody(ctx context.Context, data *ActionModel) (*cli.Trigger, error)
return selfServiceTrigger, nil
}
+ if data.AutomationTrigger != nil {
+ automationTrigger := &cli.Trigger{
+ Type: consts.Automation,
+ }
+
+ if data.AutomationTrigger.JqCondition != nil {
+ automationTrigger.Condition = &cli.TriggerCondition{
+ Type: consts.JqCondition,
+ Expressions: flex.TerraformStringListToGoArray(data.AutomationTrigger.JqCondition.Expressions),
+ Combinator: data.AutomationTrigger.JqCondition.Combinator.ValueStringPointer(),
+ }
+ }
+
+ if data.AutomationTrigger.EntityCreatedEvent != nil {
+ automationTrigger.Event = &cli.TriggerEvent{
+ Type: consts.EntityCreated,
+ BlueprintIdentifier: data.AutomationTrigger.EntityCreatedEvent.BlueprintIdentifier.ValueStringPointer(),
+ }
+ }
+
+ if data.AutomationTrigger.EntityUpdatedEvent != nil {
+ automationTrigger.Event = &cli.TriggerEvent{
+ Type: consts.EntityUpdated,
+ BlueprintIdentifier: data.AutomationTrigger.EntityUpdatedEvent.BlueprintIdentifier.ValueStringPointer(),
+ }
+ }
+
+ if data.AutomationTrigger.EntityDeletedEvent != nil {
+ automationTrigger.Event = &cli.TriggerEvent{
+ Type: consts.EntityDeleted,
+ BlueprintIdentifier: data.AutomationTrigger.EntityDeletedEvent.BlueprintIdentifier.ValueStringPointer(),
+ }
+ }
+
+ if data.AutomationTrigger.AnyEntityChangeEvent != nil {
+ automationTrigger.Event = &cli.TriggerEvent{
+ Type: consts.AnyEntityChange,
+ BlueprintIdentifier: data.AutomationTrigger.AnyEntityChangeEvent.BlueprintIdentifier.ValueStringPointer(),
+ }
+ }
+
+ if data.AutomationTrigger.TimerPropertyExpiredEvent != nil {
+ automationTrigger.Event = &cli.TriggerEvent{
+ Type: consts.TimerPropertyExpired,
+ BlueprintIdentifier: data.AutomationTrigger.TimerPropertyExpiredEvent.BlueprintIdentifier.ValueStringPointer(),
+ PropertyIdentifier: data.AutomationTrigger.TimerPropertyExpiredEvent.PropertyIdentifier.ValueStringPointer(),
+ }
+ }
+
+ return automationTrigger, nil
+ }
+
return nil, nil
}
@@ -257,5 +310,41 @@ func invocationMethodToBody(ctx context.Context, data *ActionModel) (*cli.Invoca
return azureInvocation, nil
}
+ if data.UpsertEntityMethod != nil {
+ var mapping cli.MappingSchema
+ if data.UpsertEntityMethod.Mapping != nil {
+ var team interface{}
+ if data.UpsertEntityMethod.Mapping.Teams != nil {
+ team = flex.TerraformStringListToGoArray(data.UpsertEntityMethod.Mapping.Teams)
+ }
+ properties, err := utils.TerraformJsonStringToGoObject(data.UpsertEntityMethod.Mapping.Properties.ValueStringPointer())
+ if err != nil {
+ return nil, err
+ }
+
+ relations, err := utils.TerraformJsonStringToGoObject(data.UpsertEntityMethod.Mapping.Relations.ValueStringPointer())
+ if err != nil {
+ return nil, err
+ }
+
+ mapping = cli.MappingSchema{
+ Team: team,
+ Identifier: data.UpsertEntityMethod.Mapping.Identifier.ValueStringPointer(),
+ Title: data.UpsertEntityMethod.Title.ValueStringPointer(),
+ Icon: data.UpsertEntityMethod.Mapping.Icon.ValueStringPointer(),
+ Properties: *properties,
+ Relations: *relations,
+ }
+ }
+
+ upsertEntityInvocation := &cli.InvocationMethod{
+ Type: consts.UpsertEntity,
+ BlueprintIdentifier: data.UpsertEntityMethod.BlueprintIdentifier.ValueStringPointer(),
+ Mapping: &mapping,
+ }
+
+ return upsertEntityInvocation, nil
+ }
+
return nil, nil
}
diff --git a/port/action/model.go b/port/action/model.go
index 81c76a35..db7180a0 100644
--- a/port/action/model.go
+++ b/port/action/model.go
@@ -304,6 +304,15 @@ type JqConditionModel struct {
Combinator types.String `tfsdk:"combinator"`
}
+type AutomationTriggerModel struct {
+ EntityCreatedEvent *EntityCreatedEventModel `tfsdk:"entity_created_event"`
+ EntityUpdatedEvent *EntityUpdatedEventModel `tfsdk:"entity_updated_event"`
+ EntityDeletedEvent *EntityDeletedEventModel `tfsdk:"entity_deleted_event"`
+ AnyEntityChangeEvent *AnyEntityChangeEventModel `tfsdk:"any_entity_change_event"`
+ TimerPropertyExpiredEvent *TimerPropertyExpiredEventModel `tfsdk:"timer_property_expired_event"`
+ JqCondition *JqConditionModel `tfsdk:"jq_condition"`
+}
+
type KafkaMethodModel struct {
Payload types.String `tfsdk:"payload"`
}
@@ -338,6 +347,20 @@ type AzureMethodModel struct {
Payload types.String `tfsdk:"payload"`
}
+type MappingModel struct {
+ Properties types.String `tfsdk:"properties"`
+ Relations types.String `tfsdk:"relations"`
+ Identifier types.String `tfsdk:"identifier"`
+ Teams []types.String `tfsdk:"teams"`
+ Icon types.String `tfsdk:"icon"`
+}
+
+type UpsertEntityMethodModel struct {
+ Title types.String `tfsdk:"title"`
+ BlueprintIdentifier types.String `tfsdk:"blueprint_identifier"`
+ Mapping *MappingModel `tfsdk:"mapping"`
+}
+
type ApprovalWebhookNotificationModel struct {
Url types.String `tfsdk:"url"`
Format types.String `tfsdk:"format"`
@@ -351,11 +374,13 @@ type ActionModel struct {
Icon types.String `tfsdk:"icon"`
Description types.String `tfsdk:"description"`
SelfServiceTrigger *SelfServiceTriggerModel `tfsdk:"self_service_trigger"`
+ AutomationTrigger *AutomationTriggerModel `tfsdk:"automation_trigger"`
KafkaMethod *KafkaMethodModel `tfsdk:"kafka_method"`
WebhookMethod *WebhookMethodModel `tfsdk:"webhook_method"`
GithubMethod *GithubMethodModel `tfsdk:"github_method"`
GitlabMethod *GitlabMethodModel `tfsdk:"gitlab_method"`
AzureMethod *AzureMethodModel `tfsdk:"azure_method"`
+ UpsertEntityMethod *UpsertEntityMethodModel `tfsdk:"upsert_entity_method"`
RequiredApproval types.Bool `tfsdk:"required_approval"`
ApprovalWebhookNotification *ApprovalWebhookNotificationModel `tfsdk:"approval_webhook_notification"`
ApprovalEmailNotification types.Object `tfsdk:"approval_email_notification"`
@@ -371,11 +396,13 @@ type ActionValidationModel struct {
Icon types.String `tfsdk:"icon"`
Description types.String `tfsdk:"description"`
SelfServiceTrigger types.Object `tfsdk:"self_service_trigger"`
+ AutomationTrigger types.Object `tfsdk:"automation_trigger"`
KafkaMethod types.Object `tfsdk:"kafka_method"`
WebhookMethod types.Object `tfsdk:"webhook_method"`
GithubMethod types.Object `tfsdk:"github_method"`
GitlabMethod types.Object `tfsdk:"gitlab_method"`
AzureMethod types.Object `tfsdk:"azure_method"`
+ UpsertEntityMethod types.Object `tfsdk:"upsert_entity_method"`
RequiredApproval types.Bool `tfsdk:"required_approval"`
ApprovalWebhookNotification types.Object `tfsdk:"approval_webhook_notification"`
ApprovalEmailNotification types.Object `tfsdk:"approval_email_notification"`
diff --git a/port/action/refreshActionState.go b/port/action/refreshActionState.go
index 4c022952..0c45a809 100644
--- a/port/action/refreshActionState.go
+++ b/port/action/refreshActionState.go
@@ -98,6 +98,39 @@ func writeInvocationMethodToResource(ctx context.Context, a *cli.Action, state *
}
}
+ if a.InvocationMethod.Type == consts.UpsertEntity {
+ var teams []types.String
+ switch team := a.InvocationMethod.Mapping.Team.(type) {
+ case string:
+ teams = append(teams, types.StringValue(team))
+ case []interface{}:
+ teams = make([]types.String, 0)
+ for _, t := range team {
+ teams = append(teams, types.StringValue(t.(string)))
+ }
+ }
+ properties, err := utils.GoObjectToTerraformString(a.InvocationMethod.Mapping.Properties)
+ if err != nil {
+ return err
+ }
+ relations, err := utils.GoObjectToTerraformString(a.InvocationMethod.Mapping.Relations)
+ if err != nil {
+ return err
+ }
+
+ state.UpsertEntityMethod = &UpsertEntityMethodModel{
+ Title: flex.GoStringToFramework(a.InvocationMethod.Mapping.Title),
+ BlueprintIdentifier: types.StringValue(*a.InvocationMethod.BlueprintIdentifier),
+ Mapping: &MappingModel{
+ Properties: properties,
+ Relations: relations,
+ Icon: flex.GoStringToFramework(a.InvocationMethod.Mapping.Icon),
+ Teams: teams,
+ Identifier: types.StringValue(*a.InvocationMethod.Mapping.Identifier),
+ },
+ }
+ }
+
return nil
}
@@ -296,14 +329,62 @@ func writeTriggerToResource(ctx context.Context, a *cli.Action, state *ActionMod
RequiredJqQuery: requiredJqQuery,
OrderProperties: orderProperties,
}
+
+ if a.Trigger.Condition != nil {
+ triggerCondition, err := json.Marshal(a.Trigger.Condition)
+ if err != nil {
+ return err
+ }
+ state.SelfServiceTrigger.Condition = types.StringValue(string(triggerCondition))
+ }
}
- if a.Trigger.Condition != nil {
- triggerCondition, err := json.Marshal(a.Trigger.Condition)
- if err != nil {
- return err
+ if a.Trigger.Type == consts.Automation {
+ automationTrigger := &AutomationTriggerModel{}
+
+ var expressions []types.String
+ if a.Trigger.Condition != nil {
+ for _, e := range a.Trigger.Condition.Expressions {
+ expressions = append(expressions, types.StringValue(e))
+ }
+ automationTrigger.JqCondition = &JqConditionModel{
+ Expressions: expressions,
+ Combinator: flex.GoStringToFramework(a.Trigger.Condition.Combinator),
+ }
+ }
+
+ if a.Trigger.Event.Type == consts.EntityCreated {
+ automationTrigger.EntityCreatedEvent = &EntityCreatedEventModel{
+ BlueprintIdentifier: types.StringValue(*a.Trigger.Event.BlueprintIdentifier),
+ }
+ }
+
+ if a.Trigger.Event.Type == consts.EntityUpdated {
+ automationTrigger.EntityUpdatedEvent = &EntityUpdatedEventModel{
+ BlueprintIdentifier: types.StringValue(*a.Trigger.Event.BlueprintIdentifier),
+ }
+ }
+
+ if a.Trigger.Event.Type == consts.EntityDeleted {
+ automationTrigger.EntityDeletedEvent = &EntityDeletedEventModel{
+ BlueprintIdentifier: types.StringValue(*a.Trigger.Event.BlueprintIdentifier),
+ }
+ }
+
+ if a.Trigger.Event.Type == consts.AnyEntityChange {
+ automationTrigger.AnyEntityChangeEvent = &AnyEntityChangeEventModel{
+ BlueprintIdentifier: types.StringValue(*a.Trigger.Event.BlueprintIdentifier),
+ }
}
- state.SelfServiceTrigger.Condition = types.StringValue(string(triggerCondition))
+
+ if a.Trigger.Event.Type == consts.TimerPropertyExpired {
+ automationTrigger.TimerPropertyExpiredEvent = &TimerPropertyExpiredEventModel{
+ BlueprintIdentifier: types.StringValue(*a.Trigger.Event.BlueprintIdentifier),
+ PropertyIdentifier: types.StringValue(*a.Trigger.Event.PropertyIdentifier),
+ }
+ }
+
+ state.AutomationTrigger = automationTrigger
}
return nil
diff --git a/port/action/resource_test.go b/port/action/resource_test.go
index ff49b227..e3f5da52 100644
--- a/port/action/resource_test.go
+++ b/port/action/resource_test.go
@@ -398,6 +398,56 @@ func TestAccPortActionAzureInvocation(t *testing.T) {
})
}
+func TestAccPortActionUpsertEntityInvocation(t *testing.T) {
+ identifier := utils.GenID()
+ actionIdentifier := utils.GenID()
+ var testAccActionConfigCreate = testAccCreateBlueprintConfig(identifier) + fmt.Sprintf(`
+ resource "port_action" "create_microservice" {
+ title = "TF Provider Test"
+ identifier = "%s"
+ icon = "Terraform"
+ self_service_trigger = {
+ operation = "DAY-2"
+ blueprint_identifier = port_blueprint.microservice.identifier
+ }
+ upsert_entity_method = {
+ title = "Test Entity"
+ blueprint_identifier = port_blueprint.microservice.identifier
+ mapping = {
+ identifier = "test-entity"
+ teams = []
+ icon = "Terraform"
+ properties = jsonencode({"text": "test"})
+ relations = jsonencode({"test-rel": "target-bp"})
+ }
+ }
+ }`, actionIdentifier)
+
+ resource.Test(t, resource.TestCase{
+ PreCheck: func() { acctest.TestAccPreCheck(t) },
+ ProtoV6ProviderFactories: acctest.TestAccProtoV6ProviderFactories,
+ Steps: []resource.TestStep{
+ {
+ Config: acctest.ProviderConfig + testAccActionConfigCreate,
+ Check: resource.ComposeTestCheckFunc(
+ resource.TestCheckResourceAttr("port_action.create_microservice", "title", "TF Provider Test"),
+ resource.TestCheckResourceAttr("port_action.create_microservice", "identifier", actionIdentifier),
+ resource.TestCheckResourceAttr("port_action.create_microservice", "icon", "Terraform"),
+ resource.TestCheckResourceAttr("port_action.create_microservice", "self_service_trigger.blueprint_identifier", identifier),
+ resource.TestCheckResourceAttr("port_action.create_microservice", "self_service_trigger.operation", "DAY-2"),
+ resource.TestCheckResourceAttr("port_action.create_microservice", "upsert_entity_method.title", "Test Entity"),
+ resource.TestCheckResourceAttr("port_action.create_microservice", "upsert_entity_method.blueprint_identifier", identifier),
+ resource.TestCheckResourceAttr("port_action.create_microservice", "upsert_entity_method.mapping.identifier", "test-entity"),
+ resource.TestCheckResourceAttr("port_action.create_microservice", "upsert_entity_method.mapping.teams.#", "0"),
+ resource.TestCheckResourceAttr("port_action.create_microservice", "upsert_entity_method.mapping.icon", "Terraform"),
+ resource.TestCheckResourceAttr("port_action.create_microservice", "upsert_entity_method.mapping.properties", "{\"text\":\"test\"}"),
+ resource.TestCheckResourceAttr("port_action.create_microservice", "upsert_entity_method.mapping.relations", "{\"test-rel\":\"target-bp\"}"),
+ ),
+ },
+ },
+ })
+}
+
func TestAccPortActionImport(t *testing.T) {
blueprintIdentifier := utils.GenID()
actionIdentifier := utils.GenID()
@@ -1355,6 +1405,168 @@ func TestAccPortActionRequiredFalseAndNull(t *testing.T) {
})
}
+func TestAccPortAutomationEntityCreated(t *testing.T) {
+ identifier := utils.GenID()
+ actionIdentifier := utils.GenID()
+ var testAccActionConfigCreate = testAccCreateBlueprintConfig(identifier) + fmt.Sprintf(`
+ resource "port_action" "create_microservice" {
+ title = "TF Provider Test"
+ identifier = "%s"
+ icon = "Terraform"
+ automation_trigger = {
+ entity_created_event = {
+ blueprint_identifier = port_blueprint.microservice.identifier
+ }
+ }
+ kafka_method = {}
+ }`, actionIdentifier)
+ resource.Test(t, resource.TestCase{
+ PreCheck: func() { acctest.TestAccPreCheck(t) },
+ ProtoV6ProviderFactories: acctest.TestAccProtoV6ProviderFactories,
+ Steps: []resource.TestStep{
+ {
+ Config: acctest.ProviderConfig + testAccActionConfigCreate,
+ Check: resource.ComposeTestCheckFunc(
+ resource.TestCheckResourceAttr("port_action.create_microservice", "title", "TF Provider Test"),
+ resource.TestCheckResourceAttr("port_action.create_microservice", "identifier", actionIdentifier),
+ resource.TestCheckResourceAttr("port_action.create_microservice", "icon", "Terraform"),
+ resource.TestCheckResourceAttr("port_action.create_microservice", "automation_trigger.entity_created_event.blueprint_identifier", identifier),
+ ),
+ },
+ },
+ })
+}
+
+func TestAccPortAutomationEntityUpdated(t *testing.T) {
+ identifier := utils.GenID()
+ actionIdentifier := utils.GenID()
+ var testAccActionConfigCreate = testAccCreateBlueprintConfig(identifier) + fmt.Sprintf(`
+ resource "port_action" "create_microservice" {
+ title = "TF Provider Test"
+ identifier = "%s"
+ icon = "Terraform"
+ automation_trigger = {
+ entity_updated_event = {
+ blueprint_identifier = port_blueprint.microservice.identifier
+ }
+ }
+ kafka_method = {}
+ }`, actionIdentifier)
+ resource.Test(t, resource.TestCase{
+ PreCheck: func() { acctest.TestAccPreCheck(t) },
+ ProtoV6ProviderFactories: acctest.TestAccProtoV6ProviderFactories,
+ Steps: []resource.TestStep{
+ {
+ Config: acctest.ProviderConfig + testAccActionConfigCreate,
+ Check: resource.ComposeTestCheckFunc(
+ resource.TestCheckResourceAttr("port_action.create_microservice", "title", "TF Provider Test"),
+ resource.TestCheckResourceAttr("port_action.create_microservice", "identifier", actionIdentifier),
+ resource.TestCheckResourceAttr("port_action.create_microservice", "icon", "Terraform"),
+ resource.TestCheckResourceAttr("port_action.create_microservice", "automation_trigger.entity_updated_event.blueprint_identifier", identifier),
+ ),
+ },
+ },
+ })
+}
+
+func TestAccPortAutomationEntityDeleted(t *testing.T) {
+ identifier := utils.GenID()
+ actionIdentifier := utils.GenID()
+ var testAccActionConfigCreate = testAccCreateBlueprintConfig(identifier) + fmt.Sprintf(`
+ resource "port_action" "create_microservice" {
+ title = "TF Provider Test"
+ identifier = "%s"
+ icon = "Terraform"
+ automation_trigger = {
+ entity_deleted_event = {
+ blueprint_identifier = port_blueprint.microservice.identifier
+ }
+ }
+ kafka_method = {}
+ }`, actionIdentifier)
+ resource.Test(t, resource.TestCase{
+ PreCheck: func() { acctest.TestAccPreCheck(t) },
+ ProtoV6ProviderFactories: acctest.TestAccProtoV6ProviderFactories,
+ Steps: []resource.TestStep{
+ {
+ Config: acctest.ProviderConfig + testAccActionConfigCreate,
+ Check: resource.ComposeTestCheckFunc(
+ resource.TestCheckResourceAttr("port_action.create_microservice", "title", "TF Provider Test"),
+ resource.TestCheckResourceAttr("port_action.create_microservice", "identifier", actionIdentifier),
+ resource.TestCheckResourceAttr("port_action.create_microservice", "icon", "Terraform"),
+ resource.TestCheckResourceAttr("port_action.create_microservice", "automation_trigger.entity_deleted_event.blueprint_identifier", identifier),
+ ),
+ },
+ },
+ })
+}
+
+func TestAccPortAutomationAnyEntityChange(t *testing.T) {
+ identifier := utils.GenID()
+ actionIdentifier := utils.GenID()
+ var testAccActionConfigCreate = testAccCreateBlueprintConfig(identifier) + fmt.Sprintf(`
+ resource "port_action" "create_microservice" {
+ title = "TF Provider Test"
+ identifier = "%s"
+ icon = "Terraform"
+ automation_trigger = {
+ any_entity_change_event = {
+ blueprint_identifier = port_blueprint.microservice.identifier
+ }
+ }
+ kafka_method = {}
+ }`, actionIdentifier)
+ resource.Test(t, resource.TestCase{
+ PreCheck: func() { acctest.TestAccPreCheck(t) },
+ ProtoV6ProviderFactories: acctest.TestAccProtoV6ProviderFactories,
+ Steps: []resource.TestStep{
+ {
+ Config: acctest.ProviderConfig + testAccActionConfigCreate,
+ Check: resource.ComposeTestCheckFunc(
+ resource.TestCheckResourceAttr("port_action.create_microservice", "title", "TF Provider Test"),
+ resource.TestCheckResourceAttr("port_action.create_microservice", "identifier", actionIdentifier),
+ resource.TestCheckResourceAttr("port_action.create_microservice", "icon", "Terraform"),
+ resource.TestCheckResourceAttr("port_action.create_microservice", "automation_trigger.any_entity_change_event.blueprint_identifier", identifier),
+ ),
+ },
+ },
+ })
+}
+
+func TestAccPortAutomationTimerPropertyExpired(t *testing.T) {
+ identifier := utils.GenID()
+ actionIdentifier := utils.GenID()
+ var testAccActionConfigCreate = testAccCreateBlueprintConfig(identifier) + fmt.Sprintf(`
+ resource "port_action" "create_microservice" {
+ title = "TF Provider Test"
+ identifier = "%s"
+ icon = "Terraform"
+ automation_trigger = {
+ timer_property_expired_event = {
+ blueprint_identifier = port_blueprint.microservice.identifier
+ property_identifier = "timer"
+ }
+ }
+ kafka_method = {}
+ }`, actionIdentifier)
+ resource.Test(t, resource.TestCase{
+ PreCheck: func() { acctest.TestAccPreCheck(t) },
+ ProtoV6ProviderFactories: acctest.TestAccProtoV6ProviderFactories,
+ Steps: []resource.TestStep{
+ {
+ Config: acctest.ProviderConfig + testAccActionConfigCreate,
+ Check: resource.ComposeTestCheckFunc(
+ resource.TestCheckResourceAttr("port_action.create_microservice", "title", "TF Provider Test"),
+ resource.TestCheckResourceAttr("port_action.create_microservice", "identifier", actionIdentifier),
+ resource.TestCheckResourceAttr("port_action.create_microservice", "icon", "Terraform"),
+ resource.TestCheckResourceAttr("port_action.create_microservice", "automation_trigger.timer_property_expired_event.blueprint_identifier", identifier),
+ resource.TestCheckResourceAttr("port_action.create_microservice", "automation_trigger.timer_property_expired_event.property_identifier", "timer"),
+ ),
+ },
+ },
+ })
+}
+
func TestAccPortWebhookApproval(t *testing.T) {
identifier := utils.GenID()
actionIdentifier := utils.GenID()
diff --git a/port/action/schema.go b/port/action/schema.go
index fc4c8c8b..a9b2f4b6 100644
--- a/port/action/schema.go
+++ b/port/action/schema.go
@@ -5,6 +5,7 @@ import (
"fmt"
"github.com/hashicorp/terraform-plugin-framework/resource/schema/objectdefault"
+ "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringdefault"
"regexp"
@@ -136,9 +137,99 @@ func ActionSchema() map[string]schema.Attribute {
Validators: []validator.Object{
objectvalidator.ExactlyOneOf(
path.MatchRoot("self_service_trigger"),
+ path.MatchRoot("automation_trigger"),
),
},
},
+ "automation_trigger": schema.SingleNestedAttribute{
+ MarkdownDescription: "Automation trigger for the action",
+ Optional: true,
+ Attributes: map[string]schema.Attribute{
+ "entity_created_event": schema.SingleNestedAttribute{
+ MarkdownDescription: "Entity created event trigger",
+ Optional: true,
+ Attributes: map[string]schema.Attribute{
+ "blueprint_identifier": schema.StringAttribute{
+ MarkdownDescription: "The blueprint identifier of the created entity",
+ Required: true,
+ },
+ },
+ Validators: []validator.Object{
+ objectvalidator.ExactlyOneOf(
+ path.MatchRelative().AtParent().AtName("entity_created_event"),
+ path.MatchRelative().AtParent().AtName("entity_updated_event"),
+ path.MatchRelative().AtParent().AtName("entity_deleted_event"),
+ path.MatchRelative().AtParent().AtName("any_entity_change_event"),
+ path.MatchRelative().AtParent().AtName("timer_property_expired_event"),
+ ),
+ },
+ },
+ "entity_updated_event": schema.SingleNestedAttribute{
+ MarkdownDescription: "Entity updated event trigger",
+ Optional: true,
+ Attributes: map[string]schema.Attribute{
+ "blueprint_identifier": schema.StringAttribute{
+ MarkdownDescription: "The blueprint identifier of the updated entity",
+ Required: true,
+ },
+ },
+ },
+ "entity_deleted_event": schema.SingleNestedAttribute{
+ MarkdownDescription: "Entity deleted event trigger",
+ Optional: true,
+ Attributes: map[string]schema.Attribute{
+ "blueprint_identifier": schema.StringAttribute{
+ MarkdownDescription: "The blueprint identifier of the deleted entity",
+ Required: true,
+ },
+ },
+ },
+ "any_entity_change_event": schema.SingleNestedAttribute{
+ MarkdownDescription: "Any entity change event trigger",
+ Optional: true,
+ Attributes: map[string]schema.Attribute{
+ "blueprint_identifier": schema.StringAttribute{
+ MarkdownDescription: "The blueprint identifier of the changed entity",
+ Required: true,
+ },
+ },
+ },
+ "timer_property_expired_event": schema.SingleNestedAttribute{
+ MarkdownDescription: "Timer property expired event trigger",
+ Optional: true,
+ Attributes: map[string]schema.Attribute{
+ "blueprint_identifier": schema.StringAttribute{
+ MarkdownDescription: "The blueprint identifier of the expired timer property",
+ Required: true,
+ },
+ "property_identifier": schema.StringAttribute{
+ MarkdownDescription: "The property identifier of the expired timer property",
+ Required: true,
+ },
+ },
+ },
+ "jq_condition": schema.SingleNestedAttribute{
+ MarkdownDescription: "JQ condition for automation trigger",
+ Optional: true,
+ Attributes: map[string]schema.Attribute{
+ "expressions": schema.ListAttribute{
+ MarkdownDescription: "The jq expressions of the condition",
+ ElementType: types.StringType,
+ Required: true,
+ },
+ "combinator": schema.StringAttribute{
+ MarkdownDescription: "The combinator of the condition",
+ Optional: true,
+ Computed: true,
+ Default: stringdefault.StaticString("and"),
+ Validators: []validator.String{
+ stringvalidator.OneOf("and", "or"),
+ },
+ },
+ },
+ },
+ },
+ },
"kafka_method": schema.SingleNestedAttribute{
MarkdownDescription: "Kafka invocation method",
Optional: true,
@@ -155,6 +246,7 @@ func ActionSchema() map[string]schema.Attribute {
path.MatchRoot("github_method"),
path.MatchRoot("gitlab_method"),
path.MatchRoot("azure_method"),
+ path.MatchRoot("upsert_entity_method"),
),
},
},
@@ -258,6 +350,47 @@ func ActionSchema() map[string]schema.Attribute {
},
},
},
+ "upsert_entity_method": schema.SingleNestedAttribute{
+ MarkdownDescription: "Upsert Entity invocation method",
+ Optional: true,
+ Attributes: map[string]schema.Attribute{
+ "title": schema.StringAttribute{
+ MarkdownDescription: "The title of the entity",
+ Optional: true,
+ },
+ "blueprint_identifier": schema.StringAttribute{
+ MarkdownDescription: "Required when selecting type Upsert Entity. The blueprint identifier of the entity for the upsert",
+ Required: true,
+ },
+ "mapping": schema.SingleNestedAttribute{
+ MarkdownDescription: "Upsert Entity invocation method",
+ Optional: true,
+ Attributes: map[string]schema.Attribute{
+ "identifier": schema.StringAttribute{
+ MarkdownDescription: "Required when selecting type Upsert Entity. The entity identifier for the upsert",
+ Required: true,
+ },
+ "teams": schema.ListAttribute{
+ MarkdownDescription: "The teams the entity belongs to",
+ ElementType: types.StringType,
+ Optional: true,
+ },
+ "icon": schema.StringAttribute{
+ MarkdownDescription: "The icon of the entity",
+ Optional: true,
+ },
+ "properties": schema.StringAttribute{
+ MarkdownDescription: "The properties of the entity (key-value object encoded to a string)",
+ Optional: true,
+ },
+ "relations": schema.StringAttribute{
+ MarkdownDescription: "The relations of the entity (key-value object encoded to a string)",
+ Optional: true,
+ },
+ },
+ },
+ },
+ },
"required_approval": schema.BoolAttribute{
MarkdownDescription: "Require approval before invoking the action",
Optional: true,
@@ -972,6 +1105,28 @@ resource "port_action" "create_microservice" {
runId: "{{"{{.run.id}}"}}"
})
}
+}` + "\n```" + `
+
+## Example Usage with Automation trigger
+
+Port allows setting an automation trigger to an action, for executing an action based on event occurred to an entity in Port.
+
+` + "```hcl" + `
+resource "port_action" "delete_temporary_microservice" {
+ title = "Delete Temporary Microservice"
+ identifier = "delete-temp-microservice"
+ icon = "Terraform"
+ automation_trigger = {
+ timer_property_expired_event = {
+ blueprint_identifier = port_blueprint.microservice.identifier
+ property_identifier = "ttl"
+ }
+ }
+ kafka_method = {
+ payload = jsonencode({
+ runId: "{{"{{.run.id}}"}}"
+ })
+ }
}
` + "\n```" + `