diff --git a/.gitignore b/.gitignore index 63f337e5..efd0d5e6 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,5 @@ .env local/ __debug_bin* -terraform-provider-port-labs \ No newline at end of file +terraform-provider-port-labs +.idea diff --git a/docs/resources/port_action.md b/docs/resources/port_action.md index b1daa57c..419f23b5 100644 --- a/docs/resources/port_action.md +++ b/docs/resources/port_action.md @@ -3,375 +3,165 @@ page_title: "port_action Resource - terraform-provider-port-labs" subcategory: "" description: |- - Action - This resource allows you to manage self-service action. - See the Port documentation https://docs.getport.io/create-self-service-experiences/ for more information about self-service actions. + Action resource + Docs for the Action resource can be found here https://docs.getport.io/create-self-service-experiences/. Example Usage - Create a blueprint and an action relating to that blueprint which triggers a github workflow: - ```hcl - resource "portblueprint" "myBlueprint" { - icon = "Terraform" - identifier = "myBlueprint" - title = "My Blueprint" - properties = { - numberprops = { - "numberProp" = { - title = "Number Property" - required = false - } - } - } - } - resource "portaction" "myAction" { - title = "My Action" - blueprint = portblueprint.myBlueprint.identifier - identifier = "myAction" - trigger = "CREATE" - requiredapproval = false - githubmethod = { - org = "your-org" - repo = "your-repo" - workflow = "your-workflow" - } - userproperties = { - stringprops = { - stringValue = { - title = "String Value" - } - } - number_props = { - "numberProp" = { - title = "Number Value" - required = true - } - } - } - } - ``` - Create related "parent" and "child" blueprints and a CREATE action for the child blueprint with user inputs to select entities from the parent blueprint and triggers a github workflow: - ```hcl - resource "port_blueprint" "parent" { - icon = "Terraform" - title = "Parent" - identifier = "parent" - properties = {} - } - resource "portblueprint" "child" { - icon = "Terraform" - title = "Child" - identifier = "child" - properties = {} - relations = { - "childOf" = { - title = "Child Of" - many = true - required = false - target = portblueprint.parent.identifier - } - } - } - resource "portaction" "myAction" { - title = "My Action" - blueprint = portblueprint.child.identifier - identifier = "myAction" - trigger = "CREATE" - requiredapproval = false - githubmethod = { - org = "your-org" - repo = "your-repo" - workflow = "your-workflow" - } - userproperties = { - stringprops = { - singleParent = { - title = "Single Parent Entity Selection" - format = "entity" - blueprint = portblueprint.parent.identifier - } - } - arrayprops = { - miltipleParents = { - title = "Single Parent Entity Selection" - stringitems = { - format = "entity" - blueprint = portblueprint.parent.identifier - } - } - } - } - } - ``` - Create the same resources as in the previous example, but the action's entity selection properties will only allow entities which pass the datasets: - ```hcl - resource "port_blueprint" "parent" { - icon = "Terraform" - title = "Parent" - identifier = "parent" - properties = {} - } - resource "portblueprint" "child" { - icon = "Terraform" - title = "Child" - identifier = "child" - properties = {} - relations = { - "childOf" = { - title = "Child Of" - many = true - required = false - target = portblueprint.parent.identifier - } - } - } - resource "portaction" "myAction" { - title = "My Action" - blueprint = portblueprint.child.identifier - identifier = "myAction" - trigger = "CREATE" - requiredapproval = false - githubmethod = { - org = "your-org" - repo = "your-repo" - workflow = "your-workflow" - omitpayload = true - omituserinputs = true - reportworkflowstatus = true - } - userproperties = { - stringprops = { - singleParent = { - title = "Single Parent Entity Selection" - format = "entity" - blueprint = portblueprint.parent.identifier - dataset = { - combinator = "and" - rules = [{ - property = "$title" - operator = "contains" - value = { - jqquery = "\"specificValue\"" + hcl + resource "port_action" "create_microservice" { + title = "Create Microservice" + identifier = "create-microservice" + icon = "Terraform" + self_service_trigger = { + operation = "CREATE" + blueprint_identifier = port_blueprint.microservice.identifier + user_properties = { + string_props = { + myStringIdentifier = { + title = "My String Identifier" + required = true + format = "entity" + blueprint = port_blueprint.parent.identifier + dataset = { + combinator = "and" + rules = [{ + property = "$title" + operator = "contains" + value = { + jq_query = "\"specificValue\"" + } + }] + } + } + } + number_props = { + myNumberIdentifier = { + title = "My Number Identifier" + required = true + maximum = 100 + minimum = 0 + } + } + boolean_props = { + myBooleanIdentifier = { + title = "My Boolean Identifier" + required = true + } + } + object_props = { + myObjectIdentifier = { + title = "My Object Identifier" + required = true + } + } + array_props = { + myArrayIdentifier = { + title = "My Array Identifier" + required = true + string_items = { + format = "entity" + blueprint = port_blueprint.parent.identifier + dataset = jsonencode({ + combinator = "and" + rules = [{ + property = "$title" + operator = "contains" + value = "specificValue" + }] + }) + } + } } - }] } - } } - arrayprops = { - miltipleParents = { - title = "Single Parent Entity Selection" - stringitems = { - format = "entity" - blueprint = portblueprint.parent.identifier - dataset = jsonencode({ - combinator = "and" - rules = [{ - property = "$title" - operator = "contains" - value = "specificValue" - }] - }) - } - } + kafka_method = { + payload = jsonencode({ + runId: "{{.run.id}}" + }) } - } } - ``` --- # port_action (Resource) -# Action - -This resource allows you to manage self-service action. +# Action resource -See the [Port documentation](https://docs.getport.io/create-self-service-experiences/) for more information about self-service actions. +Docs for the Action resource can be found [here](https://docs.getport.io/create-self-service-experiences/). ## Example Usage -Create a blueprint and an action relating to that blueprint which triggers a github workflow: - -```hcl - -resource "port_blueprint" "myBlueprint" { - icon = "Terraform" - identifier = "myBlueprint" - title = "My Blueprint" - properties = { - number_props = { - "numberProp" = { - title = "Number Property" - required = false - } - } - } -} - -resource "port_action" "myAction" { - title = "My Action" - blueprint = port_blueprint.myBlueprint.identifier - identifier = "myAction" - trigger = "CREATE" - required_approval = false - github_method = { - org = "your-org" - repo = "your-repo" - workflow = "your-workflow" - } - user_properties = { - string_props = { - stringValue = { - title = "String Value" - } - } - number_props = { - "numberProp" = { - title = "Number Value" - required = true - } - } - } -} - -``` - -Create related "parent" and "child" blueprints and a CREATE action for the child blueprint with user inputs to select entities from the parent blueprint and triggers a github workflow: - ```hcl - - -resource "port_blueprint" "parent" { - icon = "Terraform" - title = "Parent" - identifier = "parent" - properties = {} -} - -resource "port_blueprint" "child" { - icon = "Terraform" - title = "Child" - identifier = "child" - properties = {} - relations = { - "childOf" = { - title = "Child Of" - many = true - required = false - target = port_blueprint.parent.identifier - } - } -} - -resource "port_action" "myAction" { - title = "My Action" - blueprint = port_blueprint.child.identifier - identifier = "myAction" - trigger = "CREATE" - required_approval = false - github_method = { - org = "your-org" - repo = "your-repo" - workflow = "your-workflow" - } - user_properties = { - string_props = { - singleParent = { - title = "Single Parent Entity Selection" - format = "entity" - blueprint = port_blueprint.parent.identifier - } - } - array_props = { - miltipleParents = { - title = "Single Parent Entity Selection" - string_items = { - format = "entity" - blueprint = port_blueprint.parent.identifier - } - } - } - } -} - -``` - - -Create the same resources as in the previous example, but the action's entity selection properties will only allow entities which pass the `dataset`s: - -```hcl - -resource "port_blueprint" "parent" { - icon = "Terraform" - title = "Parent" - identifier = "parent" - properties = {} -} - -resource "port_blueprint" "child" { - icon = "Terraform" - title = "Child" - identifier = "child" - properties = {} - relations = { - "childOf" = { - title = "Child Of" - many = true - required = false - target = port_blueprint.parent.identifier - } - } -} - -resource "port_action" "myAction" { - title = "My Action" - blueprint = port_blueprint.child.identifier - identifier = "myAction" - trigger = "CREATE" - required_approval = false - github_method = { - org = "your-org" - repo = "your-repo" - workflow = "your-workflow" - omit_payload = true - omit_user_inputs = true - report_workflow_status = true - } - user_properties = { - string_props = { - singleParent = { - title = "Single Parent Entity Selection" - format = "entity" - blueprint = port_blueprint.parent.identifier - dataset = { - combinator = "and" - rules = [{ - property = "$title" - operator = "contains" - value = { - jq_query = "\"specificValue\"" +resource "port_action" "create_microservice" { + title = "Create Microservice" + identifier = "create-microservice" + icon = "Terraform" + self_service_trigger = { + operation = "CREATE" + blueprint_identifier = port_blueprint.microservice.identifier + user_properties = { + string_props = { + myStringIdentifier = { + title = "My String Identifier" + required = true + format = "entity" + blueprint = port_blueprint.parent.identifier + dataset = { + combinator = "and" + rules = [{ + property = "$title" + operator = "contains" + value = { + jq_query = "\"specificValue\"" + } + }] + } + } + } + number_props = { + myNumberIdentifier = { + title = "My Number Identifier" + required = true + maximum = 100 + minimum = 0 + } + } + boolean_props = { + myBooleanIdentifier = { + title = "My Boolean Identifier" + required = true + } + } + object_props = { + myObjectIdentifier = { + title = "My Object Identifier" + required = true + } + } + array_props = { + myArrayIdentifier = { + title = "My Array Identifier" + required = true + string_items = { + format = "entity" + blueprint = port_blueprint.parent.identifier + dataset = jsonencode({ + combinator = "and" + rules = [{ + property = "$title" + operator = "contains" + value = "specificValue" + }] + }) + } + } } - }] } - } } - array_props = { - miltipleParents = { - title = "Single Parent Entity Selection" - string_items = { - format = "entity" - blueprint = port_blueprint.parent.identifier - dataset = jsonencode({ - combinator = "and" - rules = [{ - property = "$title" - operator = "contains" - value = "specificValue" - }] - }) - } - } + kafka_method = { + payload = jsonencode({ + runId: "{{.run.id}}" + }) } - } } - ``` @@ -381,26 +171,24 @@ resource "port_action" "myAction" { ### Required -- `blueprint` (String) The blueprint identifier the action relates to - `identifier` (String) Identifier -- `title` (String) Title -- `trigger` (String) The trigger type of the action ### Optional - `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)) -- `azure_method` (Attributes) The invocation method of the action (see [below for nested schema](#nestedatt--azure_method)) +- `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 -- `github_method` (Attributes) The invocation method of the action (see [below for nested schema](#nestedatt--github_method)) -- `gitlab_method` (Attributes) The invocation method of the action (see [below for nested schema](#nestedatt--gitlab_method)) +- `github_method` (Attributes) GitHub invocation method (see [below for nested schema](#nestedatt--github_method)) +- `gitlab_method` (Attributes) Gitlab invocation method (see [below for nested schema](#nestedatt--gitlab_method)) - `icon` (String) Icon -- `kafka_method` (Object) The invocation method of the action (see [below for nested schema](#nestedatt--kafka_method)) -- `order_properties` (List of String) Order properties +- `kafka_method` (Attributes) Kafka invocation method (see [below for nested schema](#nestedatt--kafka_method)) +- `publish` (Boolean) Publish action - `required_approval` (Boolean) Require approval before invoking the action -- `required_jq_query` (String) The required jq query of the property -- `user_properties` (Attributes) User properties (see [below for nested schema](#nestedatt--user_properties)) -- `webhook_method` (Attributes) The invocation method of the action (see [below for nested schema](#nestedatt--webhook_method)) +- `self_service_trigger` (Attributes) Self service trigger for the action (see [below for nested schema](#nestedatt--self_service_trigger)) +- `title` (String) Title +- `webhook_method` (Attributes) Webhook invocation method (see [below for nested schema](#nestedatt--webhook_method)) ### Read-Only @@ -433,6 +221,10 @@ Required: - `org` (String) Required when selecting type AZURE. The Azure org that the workflow belongs to - `webhook` (String) Required when selecting type AZURE. The Azure webhook that the workflow belongs to +Optional: + +- `payload` (String) The Azure Devops workflow payload (array or object encoded to a string) + ### Nested Schema for `github_method` @@ -445,9 +237,8 @@ Required: Optional: -- `omit_payload` (Boolean) Omit the payload when invoking the action -- `omit_user_inputs` (Boolean) Omit the user inputs when invoking the action -- `report_workflow_status` (Boolean) Report the workflow status when invoking the action +- `report_workflow_status` (String) Report the workflow status when invoking the action +- `workflow_inputs` (String) The GitHub workflow inputs (key-value object encoded to a string) @@ -460,10 +251,8 @@ Required: Optional: -- `agent` (Boolean) Use the agent to invoke the action - `default_ref` (String) The default ref of the action -- `omit_payload` (Boolean) Omit the payload when invoking the action -- `omit_user_inputs` (Boolean) Omit the user inputs when invoking the action +- `pipeline_variables` (String) The Gitlab pipeline variables (key-value object encoded to a string) @@ -471,49 +260,64 @@ Optional: Optional: +- `payload` (String) The Kafka message payload (array or object encoded to a string) + + +### Nested Schema for `self_service_trigger` - -### Nested Schema for `user_properties` +Required: + +- `operation` (String) The operation type of the action Optional: -- `array_props` (Attributes Map) The array property of the action (see [below for nested schema](#nestedatt--user_properties--array_props)) -- `boolean_props` (Attributes Map) The boolean property of the action (see [below for nested schema](#nestedatt--user_properties--boolean_props)) -- `number_props` (Attributes Map) The number property of the action (see [below for nested schema](#nestedatt--user_properties--number_props)) -- `object_props` (Attributes Map) The object property of the action (see [below for nested schema](#nestedatt--user_properties--object_props)) -- `string_props` (Attributes Map) The string property of the action (see [below for nested schema](#nestedatt--user_properties--string_props)) +- `blueprint_identifier` (String) The ID of the blueprint +- `order_properties` (List of String) Order properties +- `required_jq_query` (String) The required jq query of the property +- `user_properties` (Attributes) User properties (see [below for nested schema](#nestedatt--self_service_trigger--user_properties)) - -### Nested Schema for `user_properties.array_props` + +### Nested Schema for `self_service_trigger.user_properties` Optional: -- `boolean_items` (Attributes) The items of the array property (see [below for nested schema](#nestedatt--user_properties--array_props--boolean_items)) +- `array_props` (Attributes Map) The array property of the action (see [below for nested schema](#nestedatt--self_service_trigger--user_properties--array_props)) +- `boolean_props` (Attributes Map) The boolean property of the action (see [below for nested schema](#nestedatt--self_service_trigger--user_properties--boolean_props)) +- `number_props` (Attributes Map) The number property of the action (see [below for nested schema](#nestedatt--self_service_trigger--user_properties--number_props)) +- `object_props` (Attributes Map) The object property of the action (see [below for nested schema](#nestedatt--self_service_trigger--user_properties--object_props)) +- `string_props` (Attributes Map) The string property of the action (see [below for nested schema](#nestedatt--self_service_trigger--user_properties--string_props)) + + +### Nested Schema for `self_service_trigger.user_properties.array_props` + +Optional: + +- `boolean_items` (Attributes) The items of the array property (see [below for nested schema](#nestedatt--self_service_trigger--user_properties--array_props--boolean_items)) - `default_jq_query` (String) The default jq query of the array property - `depends_on` (List of String) The properties that this property depends on - `description` (String) The description of the property - `icon` (String) The icon of the property - `max_items` (Number) The max items of the array property - `min_items` (Number) The min items of the array property -- `number_items` (Attributes) The items of the array property (see [below for nested schema](#nestedatt--user_properties--array_props--number_items)) -- `object_items` (Attributes) The items of the array property (see [below for nested schema](#nestedatt--user_properties--array_props--object_items)) +- `number_items` (Attributes) The items of the array property (see [below for nested schema](#nestedatt--self_service_trigger--user_properties--array_props--number_items)) +- `object_items` (Attributes) The items of the array property (see [below for nested schema](#nestedatt--self_service_trigger--user_properties--array_props--object_items)) - `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 -- `string_items` (Attributes) The items of the array property (see [below for nested schema](#nestedatt--user_properties--array_props--string_items)) +- `string_items` (Attributes) The items of the array property (see [below for nested schema](#nestedatt--self_service_trigger--user_properties--array_props--string_items)) - `title` (String) The title of the property - `visible` (Boolean) The visibility of the array property - `visible_jq_query` (String) The visibility condition jq query of the array property - -### Nested Schema for `user_properties.array_props.boolean_items` + +### Nested Schema for `self_service_trigger.user_properties.array_props.visible_jq_query` Optional: - `default` (List of Boolean) The default of the items - -### Nested Schema for `user_properties.array_props.number_items` + +### Nested Schema for `self_service_trigger.user_properties.array_props.visible_jq_query` Optional: @@ -522,16 +326,16 @@ Optional: - `enum_jq_query` (String) The enum jq query of the number items - -### Nested Schema for `user_properties.array_props.object_items` + +### Nested Schema for `self_service_trigger.user_properties.array_props.visible_jq_query` Optional: - `default` (List of Map of String) The default of the items - -### Nested Schema for `user_properties.array_props.string_items` + +### Nested Schema for `self_service_trigger.user_properties.array_props.visible_jq_query` Optional: @@ -544,8 +348,8 @@ Optional: - -### Nested Schema for `user_properties.boolean_props` + +### Nested Schema for `self_service_trigger.user_properties.boolean_props` Optional: @@ -560,8 +364,8 @@ Optional: - `visible_jq_query` (String) The visibility condition jq query of the boolean property - -### Nested Schema for `user_properties.number_props` + +### Nested Schema for `self_service_trigger.user_properties.number_props` Optional: @@ -580,8 +384,8 @@ Optional: - `visible_jq_query` (String) The visibility condition jq query of the number property - -### Nested Schema for `user_properties.object_props` + +### Nested Schema for `self_service_trigger.user_properties.object_props` Optional: @@ -597,13 +401,13 @@ Optional: - `visible_jq_query` (String) The visibility condition jq query of the object property - -### Nested Schema for `user_properties.string_props` + +### Nested Schema for `self_service_trigger.user_properties.string_props` Optional: - `blueprint` (String) The blueprint identifier the string property relates to -- `dataset` (Attributes) The dataset of an the entity-format property (see [below for nested schema](#nestedatt--user_properties--string_props--dataset)) +- `dataset` (Attributes) The dataset of an the entity-format property (see [below for nested schema](#nestedatt--self_service_trigger--user_properties--string_props--dataset)) - `default` (String) The default of the string property - `default_jq_query` (String) The default jq query of the string property - `depends_on` (List of String) The properties that this property depends on @@ -621,29 +425,29 @@ Optional: - `visible` (Boolean) The visibility of the string property - `visible_jq_query` (String) The visibility condition jq query of the string property - -### Nested Schema for `user_properties.string_props.dataset` + +### Nested Schema for `self_service_trigger.user_properties.string_props.visible_jq_query` Required: - `combinator` (String) The combinator of the dataset -- `rules` (Attributes List) The rules of the dataset (see [below for nested schema](#nestedatt--user_properties--string_props--dataset--rules)) +- `rules` (Attributes List) The rules of the dataset (see [below for nested schema](#nestedatt--self_service_trigger--user_properties--string_props--visible_jq_query--rules)) - -### Nested Schema for `user_properties.string_props.dataset.rules` + +### Nested Schema for `self_service_trigger.user_properties.string_props.visible_jq_query.rules` Required: - `operator` (String) The operator of the rule -- `value` (Object) The value of the rule (see [below for nested schema](#nestedatt--user_properties--string_props--dataset--rules--value)) +- `value` (Object) The value of the rule (see [below for nested schema](#nestedatt--self_service_trigger--user_properties--string_props--visible_jq_query--rules--value)) Optional: - `blueprint` (String) The blueprint identifier of the rule - `property` (String) The property identifier of the rule - -### Nested Schema for `user_properties.string_props.dataset.rules.value` + +### Nested Schema for `self_service_trigger.user_properties.string_props.visible_jq_query.rules.property` Optional: @@ -654,6 +458,7 @@ Optional: + ### Nested Schema for `webhook_method` @@ -663,6 +468,10 @@ Required: Optional: -- `agent` (Boolean) Use the agent to invoke the action +- `agent` (String) Use the agent to invoke the action +- `body` (String) The Webhook body (array or object encoded to a string) +- `headers` (Map of String) The HTTP method to invoke the action - `method` (String) The HTTP method to invoke the action -- `synchronized` (Boolean) Synchronize the action +- `synchronized` (String) Synchronize the action + + diff --git a/docs/resources/port_action_permissions.md b/docs/resources/port_action_permissions.md index b92aac46..9b500155 100644 --- a/docs/resources/port_action_permissions.md +++ b/docs/resources/port_action_permissions.md @@ -8,8 +8,7 @@ description: |- Example Usage hcl resource "port_action_permissions" "restart_microservice_permissions" { - action_identifier = port_action.restart_microservice.identifier - blueprint_identifier = port_blueprint.microservice.identifier + action_identifier = port_action.restart_microservice.identifier permissions = { "execute" : { "roles" : [ @@ -34,8 +33,7 @@ description: |- To pass a JSON string to Terraform, you can use the jsonencode https://developer.hashicorp.com/terraform/language/functions/jsonencode function. ```hcl resource "portactionpermissions" "restartmicroservicepermissions" { - actionidentifier = portaction.restartmicroservice.identifier - blueprintidentifier = portblueprint.microservice.identifier + actionidentifier = portaction.restartmicroservice.identifier permissions = { "execute" : { "roles" : [ @@ -93,8 +91,7 @@ Docs for the Action Permissions resource can be found [here](https://docs.getpor ```hcl resource "port_action_permissions" "restart_microservice_permissions" { - action_identifier = port_action.restart_microservice.identifier - blueprint_identifier = port_blueprint.microservice.identifier + action_identifier = port_action.restart_microservice.identifier permissions = { "execute" : { "roles" : [ @@ -124,8 +121,7 @@ To pass a JSON string to Terraform, you can use the [jsonencode](https://develop ```hcl resource "port_action_permissions" "restart_microservice_permissions" { - action_identifier = port_action.restart_microservice.identifier - blueprint_identifier = port_blueprint.microservice.identifier + action_identifier = port_action.restart_microservice.identifier permissions = { "execute" : { "roles" : [ @@ -183,9 +179,12 @@ resource "port_action_permissions" "restart_microservice_permissions" { ### Required - `action_identifier` (String) The ID of the action -- `blueprint_identifier` (String) The ID of the blueprint - `permissions` (Attributes) The permissions for the action (see [below for nested schema](#nestedatt--permissions)) +### Optional + +- `blueprint_identifier` (String, Deprecated) The ID of the blueprint + ### Read-Only - `id` (String) The ID of this resource. @@ -219,3 +218,5 @@ Optional: - `roles` (List of String) The roles with execution permission - `teams` (List of String) The teams with execution permission - `users` (List of String) The users with execution permission + + diff --git a/docs/resources/port_aggregation_properties.md b/docs/resources/port_aggregation_properties.md index 9e7bb42c..35175153 100644 --- a/docs/resources/port_aggregation_properties.md +++ b/docs/resources/port_aggregation_properties.md @@ -645,3 +645,5 @@ Optional: - `average_of` (String) The time periods to calculate the average of, e.g. hour, day, week, month - `measure_time_by` (String) The property name on which to calculate the the time periods, e.g. $createdAt, $updated_at or any other date property + + diff --git a/docs/resources/port_blueprint.md b/docs/resources/port_blueprint.md index 13f0431e..e5b76d2d 100644 --- a/docs/resources/port_blueprint.md +++ b/docs/resources/port_blueprint.md @@ -498,3 +498,5 @@ Required: Optional: - `agent` (Boolean) The agent of the webhook changelog destination + + diff --git a/docs/resources/port_entity.md b/docs/resources/port_entity.md index 5c1535ea..a5524c46 100644 --- a/docs/resources/port_entity.md +++ b/docs/resources/port_entity.md @@ -67,3 +67,5 @@ Optional: - `many_relations` (Map of List of String) The many relation of the entity - `single_relations` (Map of String) The single relation of the entity + + diff --git a/docs/resources/port_page.md b/docs/resources/port_page.md index 13893a43..b8aadbaa 100644 --- a/docs/resources/port_page.md +++ b/docs/resources/port_page.md @@ -474,3 +474,5 @@ terraform import port_page.home_page "\$home" - `id` (String) The ID of this resource. - `updated_at` (String) The last update date of the page - `updated_by` (String) The last updater of the page + + diff --git a/docs/resources/port_page_permissions.md b/docs/resources/port_page_permissions.md index 68a62550..394ee512 100644 --- a/docs/resources/port_page_permissions.md +++ b/docs/resources/port_page_permissions.md @@ -121,3 +121,5 @@ Optional: - `roles` (List of String) The roles with read permission - `teams` (List of String) The teams with read permission - `users` (List of String) The users with read permission + + diff --git a/docs/resources/port_scorecard.md b/docs/resources/port_scorecard.md index bc13c874..dd78c955 100644 --- a/docs/resources/port_scorecard.md +++ b/docs/resources/port_scorecard.md @@ -243,3 +243,5 @@ Required: - `combinator` (String) The combinator of the query - `conditions` (List of String) The conditions of the query. Each condition object should be encoded to a string + + diff --git a/docs/resources/port_team.md b/docs/resources/port_team.md index 518df378..59f9484b 100644 --- a/docs/resources/port_team.md +++ b/docs/resources/port_team.md @@ -30,3 +30,5 @@ Team resource - `id` (String) The ID of this resource. - `provider_name` (String) The provider of the team - `updated_at` (String) The last update date of the team + + diff --git a/docs/resources/port_webhook.md b/docs/resources/port_webhook.md index 89654c52..0e5c06ca 100644 --- a/docs/resources/port_webhook.md +++ b/docs/resources/port_webhook.md @@ -75,3 +75,5 @@ Optional: - `signature_algorithm` (String) The signature algorithm of the webhook - `signature_header_name` (String) The signature header name of the webhook - `signature_prefix` (String) The signature prefix of the webhook + + diff --git a/internal/cli/action.go b/internal/cli/action.go index 69ab5e45..9cb6bbd1 100644 --- a/internal/cli/action.go +++ b/internal/cli/action.go @@ -6,14 +6,13 @@ import ( "fmt" ) -func (c *PortClient) ReadAction(ctx context.Context, blueprintID, id string) (*Action, int, error) { +func (c *PortClient) ReadAction(ctx context.Context, id string) (*Action, int, error) { pb := &PortBody{} - url := "v1/blueprints/{blueprint_identifier}/actions/{action_identifier}" + url := "v1/actions/{action_identifier}" resp, err := c.Client.R(). SetContext(ctx). SetHeader("Accept", "application/json"). SetResult(pb). - SetPathParam("blueprint_identifier", blueprintID). SetPathParam("action_identifier", id). Get(url) if err != nil { @@ -25,11 +24,10 @@ func (c *PortClient) ReadAction(ctx context.Context, blueprintID, id string) (*A return &pb.Action, resp.StatusCode(), nil } -func (c *PortClient) CreateAction(ctx context.Context, blueprintID string, action *Action) (*Action, error) { - url := "v1/blueprints/{blueprint_identifier}/actions" +func (c *PortClient) CreateAction(ctx context.Context, action *Action) (*Action, error) { + url := "v1/actions" resp, err := c.Client.R(). SetBody(action). - SetPathParam("blueprint_identifier", blueprintID). SetContext(ctx). Post(url) if err != nil { @@ -46,12 +44,11 @@ func (c *PortClient) CreateAction(ctx context.Context, blueprintID string, actio return &pb.Action, nil } -func (c *PortClient) UpdateAction(ctx context.Context, blueprintID, actionID string, action *Action) (*Action, error) { - url := "v1/blueprints/{blueprint_identifier}/actions/{action_identifier}" +func (c *PortClient) UpdateAction(ctx context.Context, actionID string, action *Action) (*Action, error) { + url := "v1/actions/{action_identifier}" resp, err := c.Client.R(). SetBody(action). SetContext(ctx). - SetPathParam("blueprint_identifier", blueprintID). SetPathParam("action_identifier", actionID). Put(url) if err != nil { @@ -68,12 +65,11 @@ func (c *PortClient) UpdateAction(ctx context.Context, blueprintID, actionID str return &pb.Action, nil } -func (c *PortClient) DeleteAction(ctx context.Context, blueprintID string, actionID string) error { - url := "v1/blueprints/{blueprint_identifier}/actions/{action_identifier}" +func (c *PortClient) DeleteAction(ctx context.Context, actionID string) error { + url := "v1/actions/{action_identifier}" resp, err := c.Client.R(). SetContext(ctx). SetHeader("Accept", "application/json"). - SetPathParam("blueprint_identifier", blueprintID). SetPathParam("action_identifier", actionID). Delete(url) if err != nil { diff --git a/internal/cli/actionPermissions.go b/internal/cli/actionPermissions.go index 4d34a1e1..d249d581 100644 --- a/internal/cli/actionPermissions.go +++ b/internal/cli/actionPermissions.go @@ -6,14 +6,13 @@ import ( "fmt" ) -func (c *PortClient) GetActionPermissions(ctx context.Context, blueprintID string, actionID string) (*ActionPermissions, int, error) { +func (c *PortClient) GetActionPermissions(ctx context.Context, actionID string) (*ActionPermissions, int, error) { pb := &PortBody{} - url := "v1/blueprints/{blueprint_identifier}/actions/{action_identifier}/permissions" + url := "v1/actions/{action_identifier}/permissions" resp, err := c.Client.R(). SetContext(ctx). SetHeader("Accept", "application/json"). SetResult(pb). - SetPathParam("blueprint_identifier", blueprintID). SetPathParam("action_identifier", actionID). Get(url) if err != nil { @@ -26,13 +25,12 @@ func (c *PortClient) GetActionPermissions(ctx context.Context, blueprintID strin } -func (c *PortClient) UpdateActionPermissions(ctx context.Context, blueprintID string, actionID string, permissions *ActionPermissions) (*ActionPermissions, error) { - url := "v1/blueprints/{blueprint_identifier}/actions/{action_identifier}/permissions" +func (c *PortClient) UpdateActionPermissions(ctx context.Context, actionID string, permissions *ActionPermissions) (*ActionPermissions, error) { + url := "v1/actions/{action_identifier}/permissions" resp, err := c.Client.R(). SetBody(permissions). SetContext(ctx). - SetPathParam("blueprint_identifier", blueprintID). SetPathParam("action_identifier", actionID). Patch(url) if err != nil { diff --git a/internal/cli/models.go b/internal/cli/models.go index 9293af4b..6ec4e185 100644 --- a/internal/cli/models.go +++ b/internal/cli/models.go @@ -134,22 +134,32 @@ type ( } InvocationMethod struct { - Type string `json:"type,omitempty"` - Url *string `json:"url,omitempty"` - Agent *bool `json:"agent,omitempty"` - Synchronized *bool `json:"synchronized,omitempty"` - Method *string `json:"method,omitempty"` - Org *string `json:"org,omitempty"` - Repo *string `json:"repo,omitempty"` - Webhook *string `json:"webhook,omitempty"` - Workflow *string `json:"workflow,omitempty"` - OmitPayload *bool `json:"omitPayload,omitempty"` - OmitUserInputs *bool `json:"omitUserInputs,omitempty"` - ReportWorkflowStatus *bool `json:"reportWorkflowStatus,omitempty"` - Branch *string `json:"branch,omitempty"` - ProjectName *string `json:"projectName,omitempty"` - GroupName *string `json:"groupName,omitempty"` - DefaultRef *string `json:"defaultRef,omitempty"` + Type string `json:"type"` + Payload any `json:"payload,omitempty"` + Url *string `json:"url,omitempty"` + Agent any `json:"agent,omitempty"` + Synchronized any `json:"synchronized,omitempty"` + Method *string `json:"method,omitempty"` + Headers map[string]string `json:"headers,omitempty"` + Body any `json:"body,omitempty"` + Org *string `json:"org,omitempty"` + Repo *string `json:"repo,omitempty"` + Workflow *string `json:"workflow,omitempty"` + WorkflowInputs map[string]any `json:"workflowInputs,omitempty"` + ReportWorkflowStatus any `json:"reportWorkflowStatus,omitempty"` + Branch *string `json:"branch,omitempty"` + ProjectName *string `json:"projectName,omitempty"` + GroupName *string `json:"groupName,omitempty"` + 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"` } ApprovalNotification struct { @@ -174,6 +184,27 @@ type ( Order []string `json:"order,omitempty"` } + TriggerEvent struct { + Type string `json:"type"` + BlueprintIdentifier *string `json:"blueprintIdentifier,omitempty"` + PropertyIdentifier *string `json:"propertyIdentifier,omitempty"` + } + + TriggerCondition struct { + Type string `json:"type"` + Expressions []string `json:"expressions"` + Combinator *string `json:"combinator,omitempty"` + } + + Trigger struct { + Type string `json:"type"` + BlueprintIdentifier *string `json:"blueprintIdentifier,omitempty"` + Operation *string `json:"operation,omitempty"` + UserInputs *ActionUserInputs `json:"userInputs,omitempty"` + Event *TriggerEvent `json:"event,omitempty"` + Condition *TriggerCondition `json:"condition,omitempty"` + } + Blueprint struct { Meta Identifier string `json:"identifier,omitempty"` @@ -191,15 +222,15 @@ type ( Action struct { ID string `json:"id,omitempty"` - Identifier string `json:"identifier,omitempty"` - Description *string `json:"description,omitempty"` - Title string `json:"title,omitempty"` + Identifier string `json:"identifier"` + Title *string `json:"title,omitempty"` Icon *string `json:"icon,omitempty"` - UserInputs ActionUserInputs `json:"userInputs"` - Trigger string `json:"trigger"` - RequiredApproval *bool `json:"requiredApproval,omitempty"` + Description *string `json:"description,omitempty"` + Trigger *Trigger `json:"trigger"` InvocationMethod *InvocationMethod `json:"invocationMethod,omitempty"` + RequiredApproval *bool `json:"requiredApproval,omitempty"` ApprovalNotification *ApprovalNotification `json:"approvalNotification,omitempty"` + Publish *bool `json:"publish,omitempty"` } ActionExecutePermissions struct { diff --git a/internal/consts/provider.go b/internal/consts/provider.go index c472f1eb..828c4c0c 100644 --- a/internal/consts/provider.go +++ b/internal/consts/provider.go @@ -1,11 +1,20 @@ package consts const ( - ProviderName = "port" - DefaultBaseUrl = "https://api.getport.io" - Webhook = "WEBHOOK" - Kafka = "KAFKA" - AzureDevops = "AZURE-DEVOPS" - Github = "GITHUB" - Gitlab = "GITLAB" + ProviderName = "port" + DefaultBaseUrl = "https://api.getport.io" + Kafka = "KAFKA" + Webhook = "WEBHOOK" + Github = "GITHUB" + Gitlab = "GITLAB" + AzureDevops = "AZURE_DEVOPS" + UpsertEntity = "UPSERT_ENTITY" + SelfService = "self-service" + Automation = "automation" + EntityCreated = "ENTITY_CREATED" + EntityUpdated = "ENTITY_UPDATED" + EntityDeleted = "ENTITY_DELETED" + TimerPropertyExpired = "TIMER_PROPERTY_EXPIRED" + AnyEntityChange = "ANY_ENTITY_CHANGE" + JqCondition = "JQ" ) diff --git a/internal/utils/utils.go b/internal/utils/utils.go index f1407731..7db25504 100644 --- a/internal/utils/utils.go +++ b/internal/utils/utils.go @@ -5,6 +5,7 @@ import ( "encoding/json" "fmt" "math/big" + "reflect" "github.com/hashicorp/go-uuid" "github.com/hashicorp/terraform-plugin-framework/resource/schema" @@ -76,6 +77,14 @@ func GoObjectToTerraformString(v interface{}) (types.String, error) { if v == nil { return types.StringNull(), nil } + + switch reflect.TypeOf(v).Kind() { + case reflect.Ptr, reflect.Map, reflect.Array, reflect.Chan, reflect.Slice: + if reflect.ValueOf(v).IsNil() { + return types.StringNull(), nil + } + } + js, err := json.Marshal(v) if err != nil { return types.StringNull(), err @@ -85,6 +94,19 @@ func GoObjectToTerraformString(v interface{}) (types.String, error) { return types.StringValue(value), nil } +func TerraformStringToGoObject(s types.String) (interface{}, error) { + if s.IsNull() { + return nil, nil + } + + var obj interface{} + if err := json.Unmarshal([]byte(s.ValueString()), &obj); err != nil { + return nil, err + } + + return obj, nil +} + func TerraformJsonStringToGoObject(v *string) (*map[string]any, error) { if v == nil || *v == "" { return nil, nil diff --git a/port/action-permissions/refreshActionPermissionsToState.go b/port/action-permissions/refreshActionPermissionsToState.go index cef62252..791c27d7 100644 --- a/port/action-permissions/refreshActionPermissionsToState.go +++ b/port/action-permissions/refreshActionPermissionsToState.go @@ -3,16 +3,15 @@ package action_permissions import ( "context" "encoding/json" - "fmt" "github.com/hashicorp/terraform-plugin-framework/types" "github.com/port-labs/terraform-provider-port-labs/internal/cli" "github.com/port-labs/terraform-provider-port-labs/internal/flex" ) -func refreshActionPermissionsState(ctx context.Context, state *ActionPermissionsModel, a *cli.ActionPermissions, blueprintId string, actionId string) error { - state.ID = types.StringValue(fmt.Sprintf("%s:%s", blueprintId, actionId)) +func refreshActionPermissionsState(ctx context.Context, state *ActionPermissionsModel, a *cli.ActionPermissions, actionId string) error { + state.ID = types.StringValue(actionId) state.ActionIdentifier = types.StringValue(actionId) - state.BlueprintIdentifier = types.StringValue(blueprintId) + state.BlueprintIdentifier = types.StringNull() state.Permissions = &PermissionsModel{} state.Permissions.Execute = &ExecuteModel{} diff --git a/port/action-permissions/resource.go b/port/action-permissions/resource.go index f0278258..6e829e91 100644 --- a/port/action-permissions/resource.go +++ b/port/action-permissions/resource.go @@ -7,7 +7,6 @@ import ( "github.com/hashicorp/terraform-plugin-framework/resource" "github.com/hashicorp/terraform-plugin-framework/types" "github.com/port-labs/terraform-provider-port-labs/internal/cli" - "strings" ) var _ resource.Resource = &ActionPermissionsResource{} @@ -34,15 +33,7 @@ func (r *ActionPermissionsResource) Configure(ctx context.Context, req resource. } func (r *ActionPermissionsResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) { - idParts := strings.Split(req.ID, ":") - - if len(idParts) != 2 || idParts[0] == "" || idParts[1] == "" { - resp.Diagnostics.AddError("invalid import ID", "import ID must be in the format :") - return - } - - resp.Diagnostics.Append(resp.State.SetAttribute(ctx, path.Root("blueprint_identifier"), idParts[0])...) - resp.Diagnostics.Append(resp.State.SetAttribute(ctx, path.Root("action_identifier"), idParts[1])...) + resp.Diagnostics.Append(resp.State.SetAttribute(ctx, path.Root("action_identifier"), req.ID)...) } func (r *ActionPermissionsResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) { @@ -56,8 +47,12 @@ func (r *ActionPermissionsResource) Read(ctx context.Context, req resource.ReadR blueprintIdentifier := state.BlueprintIdentifier.ValueString() actionIdentifier := state.ActionIdentifier.ValueString() + // For the first time a user is migrating from action v1 to v2 + if blueprintIdentifier != "" { + actionIdentifier = fmt.Sprintf("%s_%s", blueprintIdentifier, actionIdentifier) + } - a, statusCode, err := r.portClient.GetActionPermissions(ctx, blueprintIdentifier, actionIdentifier) + a, statusCode, err := r.portClient.GetActionPermissions(ctx, actionIdentifier) if err != nil { resp.Diagnostics.AddError("failed to read action permissions", err.Error()) return @@ -68,7 +63,7 @@ func (r *ActionPermissionsResource) Read(ctx context.Context, req resource.ReadR return } - err = refreshActionPermissionsState(ctx, state, a, blueprintIdentifier, actionIdentifier) + err = refreshActionPermissionsState(ctx, state, a, actionIdentifier) if err != nil { resp.Diagnostics.AddError("failed to refresh action permissions state", err.Error()) return @@ -89,6 +84,9 @@ func (r *ActionPermissionsResource) Update(ctx context.Context, req resource.Upd blueprintIdentifier := state.BlueprintIdentifier.ValueString() actionIdentifier := state.ActionIdentifier.ValueString() + if blueprintIdentifier != "" { + actionIdentifier = fmt.Sprintf("%s_%s", blueprintIdentifier, actionIdentifier) + } permissions, err := actionPermissionsToPortBody(state.Permissions) if err != nil { @@ -96,16 +94,16 @@ func (r *ActionPermissionsResource) Update(ctx context.Context, req resource.Upd return } - _, err = r.portClient.UpdateActionPermissions(ctx, blueprintIdentifier, actionIdentifier, permissions) + _, err = r.portClient.UpdateActionPermissions(ctx, actionIdentifier, permissions) if err != nil { resp.Diagnostics.AddError("failed to update action permissions", err.Error()) return } - state.ID = types.StringValue(fmt.Sprintf("%s:%s", blueprintIdentifier, actionIdentifier)) + state.ID = types.StringValue(actionIdentifier) state.ActionIdentifier = types.StringValue(actionIdentifier) - state.BlueprintIdentifier = types.StringValue(blueprintIdentifier) + state.BlueprintIdentifier = types.StringNull() resp.Diagnostics.Append(resp.State.Set(ctx, &state)...) } @@ -131,6 +129,9 @@ func (r *ActionPermissionsResource) Create(ctx context.Context, req resource.Cre blueprintIdentifier := state.BlueprintIdentifier.ValueString() actionIdentifier := state.ActionIdentifier.ValueString() + if blueprintIdentifier != "" { + actionIdentifier = fmt.Sprintf("%s_%s", blueprintIdentifier, actionIdentifier) + } permissions, err := actionPermissionsToPortBody(state.Permissions) if err != nil { @@ -138,16 +139,16 @@ func (r *ActionPermissionsResource) Create(ctx context.Context, req resource.Cre return } - _, err = r.portClient.UpdateActionPermissions(ctx, blueprintIdentifier, actionIdentifier, permissions) + _, err = r.portClient.UpdateActionPermissions(ctx, actionIdentifier, permissions) if err != nil { resp.Diagnostics.AddError("failed to update action permissions", err.Error()) return } - state.ID = types.StringValue(fmt.Sprintf("%s:%s", blueprintIdentifier, actionIdentifier)) + state.ID = types.StringValue(actionIdentifier) state.ActionIdentifier = types.StringValue(actionIdentifier) - state.BlueprintIdentifier = types.StringValue(blueprintIdentifier) + state.BlueprintIdentifier = types.StringNull() resp.Diagnostics.Append(resp.State.Set(ctx, &state)...) diff --git a/port/action-permissions/resource_test.go b/port/action-permissions/resource_test.go index 06b5fcfc..67f92f8f 100644 --- a/port/action-permissions/resource_test.go +++ b/port/action-permissions/resource_test.go @@ -29,8 +29,10 @@ func testAccCreateBlueprintAndActionConfig(blueprintIdentifier string, actionIde title = "TF Provider Test" identifier = "%s" icon = "Terraform" - blueprint = port_blueprint.microservice.identifier - trigger = "DAY-2" + self_service_trigger = { + operation = "DAY-2" + blueprint_identifier = port_blueprint.microservice.identifier + } kafka_method = {} }`, blueprintIdentifier, actionIdentifier) } @@ -40,7 +42,6 @@ func TestAccPortActionPermissionsBasic(t *testing.T) { var testAccActionPermissionsConfigCreate = testAccCreateBlueprintAndActionConfig(blueprintIdentifier, actionIdentifier) + ` resource "port_action_permissions" "create_microservice_permissions" { action_identifier = port_action.create_microservice.identifier - blueprint_identifier = port_blueprint.microservice.identifier permissions = { "execute": { "roles": [ @@ -65,7 +66,6 @@ func TestAccPortActionPermissionsBasic(t *testing.T) { Config: testAccActionPermissionsConfigCreate, Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr("port_action_permissions.create_microservice_permissions", "action_identifier", actionIdentifier), - resource.TestCheckResourceAttr("port_action_permissions.create_microservice_permissions", "blueprint_identifier", blueprintIdentifier), resource.TestCheckResourceAttr("port_action_permissions.create_microservice_permissions", "permissions.execute.roles.#", "1"), resource.TestCheckResourceAttr("port_action_permissions.create_microservice_permissions", "permissions.execute.roles.0", "Member"), resource.TestCheckResourceAttr("port_action_permissions.create_microservice_permissions", "permissions.execute.users.#", "0"), @@ -87,7 +87,6 @@ func TestAccPortActionPermissionsUpdate(t *testing.T) { var testAccActionPermissionsConfigCreate = testAccCreateBlueprintAndActionConfig(blueprintIdentifier, actionIdentifier) + ` resource "port_action_permissions" "create_microservice_permissions" { action_identifier = port_action.create_microservice.identifier - blueprint_identifier = port_blueprint.microservice.identifier permissions = { "execute": { "roles": [ @@ -113,13 +112,12 @@ func TestAccPortActionPermissionsUpdate(t *testing.T) { resource "port_action_permissions" "create_microservice_permissions" { action_identifier = port_action.create_microservice.identifier - blueprint_identifier = port_blueprint.microservice.identifier permissions = { "execute": { "roles": [ "Member", ], - "users": ["devops-port@port-test.io"], + "users": [], "teams": [port_team.team.name], "owned_by_team": false }, @@ -141,7 +139,6 @@ func TestAccPortActionPermissionsUpdate(t *testing.T) { Config: testAccActionPermissionsConfigCreate, Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr("port_action_permissions.create_microservice_permissions", "action_identifier", actionIdentifier), - resource.TestCheckResourceAttr("port_action_permissions.create_microservice_permissions", "blueprint_identifier", blueprintIdentifier), resource.TestCheckResourceAttr("port_action_permissions.create_microservice_permissions", "permissions.execute.roles.#", "1"), resource.TestCheckResourceAttr("port_action_permissions.create_microservice_permissions", "permissions.execute.roles.0", "Member"), resource.TestCheckResourceAttr("port_action_permissions.create_microservice_permissions", "permissions.execute.users.#", "0"), @@ -156,11 +153,9 @@ func TestAccPortActionPermissionsUpdate(t *testing.T) { Config: testAccActionPermissionsConfigUpdate, Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr("port_action_permissions.create_microservice_permissions", "action_identifier", actionIdentifier), - resource.TestCheckResourceAttr("port_action_permissions.create_microservice_permissions", "blueprint_identifier", blueprintIdentifier), resource.TestCheckResourceAttr("port_action_permissions.create_microservice_permissions", "permissions.execute.roles.#", "1"), resource.TestCheckResourceAttr("port_action_permissions.create_microservice_permissions", "permissions.execute.roles.0", "Member"), - resource.TestCheckResourceAttr("port_action_permissions.create_microservice_permissions", "permissions.execute.users.#", "1"), - resource.TestCheckResourceAttr("port_action_permissions.create_microservice_permissions", "permissions.execute.users.0", "devops-port@port-test.io"), + resource.TestCheckResourceAttr("port_action_permissions.create_microservice_permissions", "permissions.execute.users.#", "0"), resource.TestCheckResourceAttr("port_action_permissions.create_microservice_permissions", "permissions.execute.teams.#", "1"), resource.TestCheckResourceAttr("port_action_permissions.create_microservice_permissions", "permissions.execute.teams.0", teamName), resource.TestCheckResourceAttr("port_action_permissions.create_microservice_permissions", "permissions.execute.owned_by_team", "false"), @@ -180,7 +175,6 @@ func TestAccPortActionPermissionsWithPolicy(t *testing.T) { var testAccActionPermissionsConfigCreate = testAccCreateBlueprintAndActionConfig(blueprintIdentifier, actionIdentifier) + ` resource "port_action_permissions" "create_microservice_permissions" { action_identifier = port_action.create_microservice.identifier - blueprint_identifier = port_blueprint.microservice.identifier permissions = { "execute": { "roles": [ @@ -229,7 +223,6 @@ func TestAccPortActionPermissionsWithPolicy(t *testing.T) { var testAccActionPermissionsConfigUpdate = testAccCreateBlueprintAndActionConfig(blueprintIdentifier, actionIdentifier) + ` resource "port_action_permissions" "create_microservice_permissions" { action_identifier = port_action.create_microservice.identifier - blueprint_identifier = port_blueprint.microservice.identifier permissions = { "execute": { "roles": [ @@ -255,7 +248,6 @@ func TestAccPortActionPermissionsWithPolicy(t *testing.T) { Config: testAccActionPermissionsConfigCreate, Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr("port_action_permissions.create_microservice_permissions", "action_identifier", actionIdentifier), - resource.TestCheckResourceAttr("port_action_permissions.create_microservice_permissions", "blueprint_identifier", blueprintIdentifier), resource.TestCheckResourceAttr("port_action_permissions.create_microservice_permissions", "permissions.execute.roles.#", "1"), resource.TestCheckResourceAttr("port_action_permissions.create_microservice_permissions", "permissions.execute.roles.0", "Member"), resource.TestCheckResourceAttr("port_action_permissions.create_microservice_permissions", "permissions.execute.users.#", "0"), @@ -271,7 +263,6 @@ func TestAccPortActionPermissionsWithPolicy(t *testing.T) { Config: testAccActionPermissionsConfigUpdate, Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr("port_action_permissions.create_microservice_permissions", "action_identifier", actionIdentifier), - resource.TestCheckResourceAttr("port_action_permissions.create_microservice_permissions", "blueprint_identifier", blueprintIdentifier), resource.TestCheckResourceAttr("port_action_permissions.create_microservice_permissions", "permissions.execute.roles.#", "1"), resource.TestCheckResourceAttr("port_action_permissions.create_microservice_permissions", "permissions.execute.roles.0", "Member"), resource.TestCheckResourceAttr("port_action_permissions.create_microservice_permissions", "permissions.execute.users.#", "0"), @@ -292,7 +283,6 @@ func TestAccPortActionPermissionsWithPolicyUpdate(t *testing.T) { var testAccActionPermissionsConfigCreate = testAccCreateBlueprintAndActionConfig(blueprintIdentifier, actionIdentifier) + ` resource "port_action_permissions" "create_microservice_permissions" { action_identifier = port_action.create_microservice.identifier - blueprint_identifier = port_blueprint.microservice.identifier permissions = { "execute": { "roles": [ @@ -341,7 +331,6 @@ func TestAccPortActionPermissionsWithPolicyUpdate(t *testing.T) { var testAccActionPermissionsConfigUpdate = testAccCreateBlueprintAndActionConfig(blueprintIdentifier, actionIdentifier) + ` resource "port_action_permissions" "create_microservice_permissions" { action_identifier = port_action.create_microservice.identifier - blueprint_identifier = port_blueprint.microservice.identifier permissions = { "execute": { "roles": [ @@ -394,7 +383,6 @@ func TestAccPortActionPermissionsWithPolicyUpdate(t *testing.T) { Config: testAccActionPermissionsConfigCreate, Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr("port_action_permissions.create_microservice_permissions", "action_identifier", actionIdentifier), - resource.TestCheckResourceAttr("port_action_permissions.create_microservice_permissions", "blueprint_identifier", blueprintIdentifier), resource.TestCheckResourceAttr("port_action_permissions.create_microservice_permissions", "permissions.execute.roles.#", "1"), resource.TestCheckResourceAttr("port_action_permissions.create_microservice_permissions", "permissions.execute.roles.0", "Member"), resource.TestCheckResourceAttr("port_action_permissions.create_microservice_permissions", "permissions.execute.users.#", "0"), @@ -410,7 +398,6 @@ func TestAccPortActionPermissionsWithPolicyUpdate(t *testing.T) { Config: testAccActionPermissionsConfigUpdate, Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr("port_action_permissions.create_microservice_permissions", "action_identifier", actionIdentifier), - resource.TestCheckResourceAttr("port_action_permissions.create_microservice_permissions", "blueprint_identifier", blueprintIdentifier), resource.TestCheckResourceAttr("port_action_permissions.create_microservice_permissions", "permissions.execute.roles.#", "1"), resource.TestCheckResourceAttr("port_action_permissions.create_microservice_permissions", "permissions.execute.roles.0", "Member"), resource.TestCheckResourceAttr("port_action_permissions.create_microservice_permissions", "permissions.execute.users.#", "0"), @@ -432,7 +419,6 @@ func TestAccPortActionPermissionsImportState(t *testing.T) { var testAccActionPermissionsConfigCreate = testAccCreateBlueprintAndActionConfig(blueprintIdentifier, actionIdentifier) + ` resource "port_action_permissions" "create_microservice_permissions" { action_identifier = port_action.create_microservice.identifier - blueprint_identifier = port_blueprint.microservice.identifier permissions = { "execute": { "roles": [ @@ -484,7 +470,6 @@ func TestAccPortActionPermissionsImportState(t *testing.T) { Config: testAccActionPermissionsConfigCreate, Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr("port_action_permissions.create_microservice_permissions", "action_identifier", actionIdentifier), - resource.TestCheckResourceAttr("port_action_permissions.create_microservice_permissions", "blueprint_identifier", blueprintIdentifier), resource.TestCheckResourceAttr("port_action_permissions.create_microservice_permissions", "permissions.execute.roles.#", "1"), resource.TestCheckResourceAttr("port_action_permissions.create_microservice_permissions", "permissions.execute.roles.0", "Member"), resource.TestCheckResourceAttr("port_action_permissions.create_microservice_permissions", "permissions.execute.users.#", "0"), @@ -511,7 +496,6 @@ func TestAccPortActionWithEmptyFieldsExpectDefaultsToApply(t *testing.T) { var testAccActionPermissionsConfigCreate = testAccCreateBlueprintAndActionConfig(blueprintIdentifier, actionIdentifier) + ` resource "port_action_permissions" "create_microservice_permissions" { action_identifier = port_action.create_microservice.identifier - blueprint_identifier = port_blueprint.microservice.identifier permissions = { "execute": {} "approve": {} @@ -526,7 +510,6 @@ func TestAccPortActionWithEmptyFieldsExpectDefaultsToApply(t *testing.T) { Config: testAccActionPermissionsConfigCreate, Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr("port_action_permissions.create_microservice_permissions", "action_identifier", actionIdentifier), - resource.TestCheckResourceAttr("port_action_permissions.create_microservice_permissions", "blueprint_identifier", blueprintIdentifier), resource.TestCheckResourceAttr("port_action_permissions.create_microservice_permissions", "permissions.execute.roles.#", "0"), resource.TestCheckResourceAttr("port_action_permissions.create_microservice_permissions", "permissions.execute.users.#", "0"), resource.TestCheckResourceAttr("port_action_permissions.create_microservice_permissions", "permissions.execute.teams.#", "0"), diff --git a/port/action-permissions/schema.go b/port/action-permissions/schema.go index f64c7718..ce6ec905 100644 --- a/port/action-permissions/schema.go +++ b/port/action-permissions/schema.go @@ -2,11 +2,13 @@ package action_permissions import ( "context" + "github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator" "github.com/hashicorp/terraform-plugin-framework/attr" "github.com/hashicorp/terraform-plugin-framework/resource" "github.com/hashicorp/terraform-plugin-framework/resource/schema" "github.com/hashicorp/terraform-plugin-framework/resource/schema/booldefault" "github.com/hashicorp/terraform-plugin-framework/resource/schema/listdefault" + "github.com/hashicorp/terraform-plugin-framework/schema/validator" "github.com/hashicorp/terraform-plugin-framework/types" ) @@ -15,14 +17,16 @@ func ActionPermissionsSchema() map[string]schema.Attribute { "id": schema.StringAttribute{ Computed: true, }, - "blueprint_identifier": schema.StringAttribute{ - Description: "The ID of the blueprint", - Required: true, - }, "action_identifier": schema.StringAttribute{ Description: "The ID of the action", Required: true, }, + "blueprint_identifier": schema.StringAttribute{ + Description: "The ID of the blueprint", + Optional: true, + DeprecationMessage: "Action is not attached to blueprint anymore. This value is ignored", + Validators: []validator.String{stringvalidator.OneOf("")}, + }, "permissions": schema.SingleNestedAttribute{ MarkdownDescription: "The permissions for the action", Required: true, @@ -116,8 +120,7 @@ Docs for the Action Permissions resource can be found [here](https://docs.getpor ` + "```hcl" + ` resource "port_action_permissions" "restart_microservice_permissions" { - action_identifier = port_action.restart_microservice.identifier - blueprint_identifier = port_blueprint.microservice.identifier + action_identifier = port_action.restart_microservice.identifier permissions = { "execute" : { "roles" : [ @@ -146,8 +149,7 @@ To pass a JSON string to Terraform, you can use the [jsonencode](https://develop ` + "```hcl" + ` resource "port_action_permissions" "restart_microservice_permissions" { - action_identifier = port_action.restart_microservice.identifier - blueprint_identifier = port_blueprint.microservice.identifier + action_identifier = port_action.restart_microservice.identifier permissions = { "execute" : { "roles" : [ diff --git a/port/action/actionStateToPortBody.go b/port/action/actionStateToPortBody.go index 156ddda9..5d4228ec 100644 --- a/port/action/actionStateToPortBody.go +++ b/port/action/actionStateToPortBody.go @@ -2,7 +2,6 @@ package action import ( "context" - "github.com/port-labs/terraform-provider-port-labs/internal/cli" "github.com/port-labs/terraform-provider-port-labs/internal/consts" "github.com/port-labs/terraform-provider-port-labs/internal/utils" @@ -35,26 +34,25 @@ func actionDataSetToPortBody(dataSet *DatasetModel) *cli.Dataset { return cliDateSet } -func actionStateToPortBody(ctx context.Context, data *ActionModel, bp *cli.Blueprint) (*cli.Action, error) { +func actionStateToPortBody(ctx context.Context, data *ActionModel) (*cli.Action, error) { + var err error action := &cli.Action{ - Identifier: data.Identifier.ValueString(), - Title: data.Title.ValueString(), - Trigger: data.Trigger.ValueString(), - } - - if !data.Icon.IsNull() { - icon := data.Icon.ValueString() - action.Icon = &icon + Identifier: data.Identifier.ValueString(), + Title: data.Title.ValueStringPointer(), + Icon: data.Icon.ValueStringPointer(), + Description: data.Description.ValueStringPointer(), + RequiredApproval: data.RequiredApproval.ValueBoolPointer(), + Publish: data.Publish.ValueBoolPointer(), } - if !data.Description.IsNull() { - description := data.Description.ValueString() - action.Description = &description + action.Trigger, err = triggerToBody(ctx, data) + if err != nil { + return nil, err } - if !data.RequiredApproval.IsNull() { - requiredApproval := data.RequiredApproval.ValueBool() - action.RequiredApproval = &requiredApproval + action.InvocationMethod, err = invocationMethodToBody(ctx, data) + if err != nil { + return nil, err } if !data.ApprovalEmailNotification.IsNull() { @@ -62,43 +60,51 @@ func actionStateToPortBody(ctx context.Context, data *ActionModel, bp *cli.Bluep Type: "email", } } - if data.ApprovalWebhookNotification != nil { action.ApprovalNotification = &cli.ApprovalNotification{ - Type: "webhook", - Url: data.ApprovalWebhookNotification.Url.ValueString(), - } - - if !data.ApprovalWebhookNotification.Format.IsNull() { - format := data.ApprovalWebhookNotification.Format.ValueString() - action.ApprovalNotification.Format = &format + Type: "webhook", + Url: data.ApprovalWebhookNotification.Url.ValueString(), + Format: data.ApprovalWebhookNotification.Format.ValueStringPointer(), } } - action.InvocationMethod = invocationMethodToBody(data) + return action, nil +} - if data.UserProperties != nil { - err := actionPropertiesToBody(ctx, action, data) - if err != nil { - return nil, err +func triggerToBody(ctx context.Context, data *ActionModel) (*cli.Trigger, error) { + if data.SelfServiceTrigger != nil { + selfServiceTrigger := &cli.Trigger{ + Type: consts.SelfService, + BlueprintIdentifier: data.SelfServiceTrigger.BlueprintIdentifier.ValueStringPointer(), + Operation: data.SelfServiceTrigger.Operation.ValueStringPointer(), + UserInputs: &cli.ActionUserInputs{ + Properties: make(map[string]cli.ActionProperty), + }, } - } else { - action.UserInputs.Properties = make(map[string]cli.ActionProperty) - } - if !data.OrderProperties.IsNull() { - order, err := utils.TerraformListToGoArray(ctx, data.OrderProperties, "string") - if err != nil { - return nil, err + if data.SelfServiceTrigger.UserProperties != nil { + err := actionPropertiesToBody(ctx, selfServiceTrigger, data.SelfServiceTrigger) + if err != nil { + return nil, err + } + } + + if !data.SelfServiceTrigger.OrderProperties.IsNull() { + order, err := utils.TerraformListToGoArray(ctx, data.SelfServiceTrigger.OrderProperties, "string") + if err != nil { + return nil, err + } + orderString := utils.InterfaceToStringArray(order) + selfServiceTrigger.UserInputs.Order = orderString } - orderString := utils.InterfaceToStringArray(order) - action.UserInputs.Order = orderString + + return selfServiceTrigger, nil } - return action, nil + return nil, nil } -func actionPropertiesToBody(ctx context.Context, action *cli.Action, data *ActionModel) error { +func actionPropertiesToBody(ctx context.Context, actionTrigger *cli.Trigger, data *SelfServiceTriggerModel) error { required := []string{} props := map[string]cli.ActionProperty{} var err error @@ -123,118 +129,124 @@ func actionPropertiesToBody(ctx context.Context, action *cli.Action, data *Actio return err } - action.UserInputs.Properties = props + actionTrigger.UserInputs.Properties = props // if requiredJqQuery is set, required shouldn't be set and vice versa if !data.RequiredJqQuery.IsNull() { RequiredJqQueryMap := map[string]string{ "jqQuery": data.RequiredJqQuery.ValueString(), } - action.UserInputs.Required = RequiredJqQueryMap + actionTrigger.UserInputs.Required = RequiredJqQueryMap } else { - action.UserInputs.Required = required + actionTrigger.UserInputs.Required = required } return nil } -func invocationMethodToBody(data *ActionModel) *cli.InvocationMethod { - if data.AzureMethod != nil { - org := data.AzureMethod.Org.ValueString() - webhook := data.AzureMethod.Webhook.ValueString() - return &cli.InvocationMethod{ - Type: consts.AzureDevops, - Org: &org, - Webhook: &webhook, + +func invocationMethodToBody(ctx context.Context, data *ActionModel) (*cli.InvocationMethod, error) { + if data.KafkaMethod != nil { + payload, err := utils.TerraformStringToGoObject(data.KafkaMethod.Payload) + if err != nil { + return nil, err } + + return &cli.InvocationMethod{Type: consts.Kafka, Payload: payload}, nil } - if data.GithubMethod != nil { - org := data.GithubMethod.Org.ValueString() - repo := data.GithubMethod.Repo.ValueString() - workflow := data.GithubMethod.Workflow.ValueString() - githubInvocation := &cli.InvocationMethod{ - Type: consts.Github, - Org: &org, - Repo: &repo, - Workflow: &workflow, + if data.WebhookMethod != nil { + agent, err := utils.TerraformStringToGoObject(data.WebhookMethod.Agent) + if err != nil { + return nil, err } - - if !data.GithubMethod.OmitPayload.IsNull() { - omitPayload := data.GithubMethod.OmitPayload.ValueBool() - githubInvocation.OmitPayload = &omitPayload + synchronized, err := utils.TerraformStringToGoObject(data.WebhookMethod.Synchronized) + if err != nil { + return nil, err } - - if !data.GithubMethod.OmitUserInputs.IsNull() { - omitUserInputs := data.GithubMethod.OmitUserInputs.ValueBool() - githubInvocation.OmitUserInputs = &omitUserInputs + headers := make(map[string]string) + for key, value := range data.WebhookMethod.Headers.Elements() { + tv, _ := value.ToTerraformValue(ctx) + var keyValue string + err = tv.As(&keyValue) + if err != nil { + return nil, err + } + headers[key] = keyValue + } + body, err := utils.TerraformStringToGoObject(data.WebhookMethod.Body) + if err != nil { + return nil, err } - if !data.GithubMethod.ReportWorkflowStatus.IsNull() { - reportWorkflowStatus := data.GithubMethod.ReportWorkflowStatus.ValueBool() - githubInvocation.ReportWorkflowStatus = &reportWorkflowStatus + webhookInvocation := &cli.InvocationMethod{ + Type: consts.Webhook, + Url: data.WebhookMethod.Url.ValueStringPointer(), + Agent: agent, + Synchronized: synchronized, + Method: data.WebhookMethod.Method.ValueStringPointer(), + Headers: headers, + Body: body, } - return githubInvocation - } - if !data.KafkaMethod.IsNull() { - return &cli.InvocationMethod{ - Type: consts.Kafka, - } + return webhookInvocation, nil } - if data.WebhookMethod != nil { - url := data.WebhookMethod.Url.ValueString() - webhookInvocation := &cli.InvocationMethod{ - Type: consts.Webhook, - Url: &url, - } - if !data.WebhookMethod.Agent.IsNull() { - agent := data.WebhookMethod.Agent.ValueBool() - webhookInvocation.Agent = &agent + if data.GithubMethod != nil { + reportWorkflowStatus, err := utils.TerraformStringToGoObject(data.GithubMethod.ReportWorkflowStatus) + if err != nil { + return nil, err } - if !data.WebhookMethod.Synchronized.IsNull() { - synchronized := data.WebhookMethod.Synchronized.ValueBool() - webhookInvocation.Synchronized = &synchronized + wi, err := utils.TerraformStringToGoObject(data.GithubMethod.WorkflowInputs) + if err != nil { + return nil, err } - if !data.WebhookMethod.Method.IsNull() { - method := data.WebhookMethod.Method.ValueString() - webhookInvocation.Method = &method + workflowInputs, _ := wi.(map[string]interface{}) + + githubInvocation := &cli.InvocationMethod{ + Type: consts.Github, + Org: data.GithubMethod.Org.ValueStringPointer(), + Repo: data.GithubMethod.Repo.ValueStringPointer(), + Workflow: data.GithubMethod.Workflow.ValueStringPointer(), + WorkflowInputs: workflowInputs, + ReportWorkflowStatus: reportWorkflowStatus, } - return webhookInvocation + return githubInvocation, nil } if data.GitlabMethod != nil { - projectName := data.GitlabMethod.ProjectName.ValueString() - groupName := data.GitlabMethod.GroupName.ValueString() - gitlabInvocation := &cli.InvocationMethod{ - Type: consts.Gitlab, - ProjectName: &projectName, - GroupName: &groupName, + pv, err := utils.TerraformStringToGoObject(data.GitlabMethod.PipelineVariables) + if err != nil { + return nil, err } + pipelineVariables, _ := pv.(map[string]interface{}) - if !data.GitlabMethod.OmitPayload.IsNull() { - omitPayload := data.GitlabMethod.OmitPayload.ValueBool() - gitlabInvocation.OmitPayload = &omitPayload + gitlabInvocation := &cli.InvocationMethod{ + Type: consts.Gitlab, + ProjectName: data.GitlabMethod.ProjectName.ValueStringPointer(), + GroupName: data.GitlabMethod.GroupName.ValueStringPointer(), + DefaultRef: data.GitlabMethod.DefaultRef.ValueStringPointer(), + PipelineVariables: pipelineVariables, } - if !data.GitlabMethod.OmitUserInputs.IsNull() { - omitUserInputs := data.GitlabMethod.OmitUserInputs.ValueBool() - gitlabInvocation.OmitUserInputs = &omitUserInputs - } + return gitlabInvocation, nil + } - if !data.GitlabMethod.DefaultRef.IsNull() { - defaultRef := data.GitlabMethod.DefaultRef.ValueString() - gitlabInvocation.DefaultRef = &defaultRef + if data.AzureMethod != nil { + payload, err := utils.TerraformStringToGoObject(data.AzureMethod.Payload) + if err != nil { + return nil, err } - if !data.GitlabMethod.Agent.IsNull() { - agent := data.GitlabMethod.Agent.ValueBool() - gitlabInvocation.Agent = &agent + azureInvocation := &cli.InvocationMethod{ + Type: consts.AzureDevops, + Org: data.AzureMethod.Org.ValueStringPointer(), + Webhook: data.AzureMethod.Webhook.ValueStringPointer(), + Payload: payload, } - return gitlabInvocation + return azureInvocation, nil } - return nil + return nil, nil } diff --git a/port/action/array.go b/port/action/array.go index c4149107..d14bd323 100644 --- a/port/action/array.go +++ b/port/action/array.go @@ -126,7 +126,7 @@ func handleArrayItemsToBody(ctx context.Context, property *cli.ActionProperty, p return nil } -func arrayPropResourceToBody(ctx context.Context, d *ActionModel, props map[string]cli.ActionProperty, required *[]string) error { +func arrayPropResourceToBody(ctx context.Context, d *SelfServiceTriggerModel, props map[string]cli.ActionProperty, required *[]string) error { for propIdentifier, prop := range d.UserProperties.ArrayProps { props[propIdentifier] = cli.ActionProperty{ Type: "array", diff --git a/port/action/boolean.go b/port/action/boolean.go index 51a95457..eb03609e 100644 --- a/port/action/boolean.go +++ b/port/action/boolean.go @@ -7,7 +7,7 @@ import ( "github.com/port-labs/terraform-provider-port-labs/internal/utils" ) -func booleanPropResourceToBody(ctx context.Context, d *ActionModel, props map[string]cli.ActionProperty, required *[]string) error { +func booleanPropResourceToBody(ctx context.Context, d *SelfServiceTriggerModel, props map[string]cli.ActionProperty, required *[]string) error { for propIdentifier, prop := range d.UserProperties.BooleanProps { props[propIdentifier] = cli.ActionProperty{ Type: "boolean", diff --git a/port/action/model.go b/port/action/model.go index eeeeba38..8ace9dc9 100644 --- a/port/action/model.go +++ b/port/action/model.go @@ -5,13 +5,6 @@ import ( "github.com/hashicorp/terraform-plugin-go/tftypes" ) -type WebhookMethodModel struct { - Url types.String `tfsdk:"url"` - Agent types.Bool `tfsdk:"agent"` - Synchronized types.Bool `tfsdk:"synchronized"` - Method types.String `tfsdk:"method"` -} - type Value struct { JqQuery types.String `tfsdk:"jq_query"` } @@ -26,29 +19,6 @@ type DatasetModel struct { Rules []Rule `tfsdk:"rules"` } -type GithubMethodModel struct { - Org types.String `tfsdk:"org"` - Repo types.String `tfsdk:"repo"` - Workflow types.String `tfsdk:"workflow"` - OmitPayload types.Bool `tfsdk:"omit_payload"` - OmitUserInputs types.Bool `tfsdk:"omit_user_inputs"` - ReportWorkflowStatus types.Bool `tfsdk:"report_workflow_status"` -} - -type AzureMethodModel struct { - Org types.String `tfsdk:"org"` - Webhook types.String `tfsdk:"webhook"` -} - -type GitlabMethodModel struct { - ProjectName types.String `tfsdk:"project_name"` - GroupName types.String `tfsdk:"group_name"` - OmitPayload types.Bool `tfsdk:"omit_payload"` - OmitUserInputs types.Bool `tfsdk:"omit_user_inputs"` - DefaultRef types.String `tfsdk:"default_ref"` - Agent types.Bool `tfsdk:"agent"` -} - type StringPropModel struct { Title types.String `tfsdk:"title"` Icon types.String `tfsdk:"icon"` @@ -299,6 +269,74 @@ type UserPropertiesModel struct { ObjectProps map[string]ObjectPropModel `tfsdk:"object_props"` } +type SelfServiceTriggerModel struct { + BlueprintIdentifier types.String `tfsdk:"blueprint_identifier"` + Operation types.String `tfsdk:"operation"` + UserProperties *UserPropertiesModel `tfsdk:"user_properties"` + RequiredJqQuery types.String `tfsdk:"required_jq_query"` + OrderProperties types.List `tfsdk:"order_properties"` +} + +type EntityCreatedEventModel struct { + BlueprintIdentifier types.String `tfsdk:"blueprint_identifier"` +} + +type EntityUpdatedEventModel struct { + BlueprintIdentifier types.String `tfsdk:"blueprint_identifier"` +} + +type EntityDeletedEventModel struct { + BlueprintIdentifier types.String `tfsdk:"blueprint_identifier"` +} + +type AnyEntityChangeEventModel struct { + BlueprintIdentifier types.String `tfsdk:"blueprint_identifier"` +} + +type TimerPropertyExpiredEventModel struct { + BlueprintIdentifier types.String `tfsdk:"blueprint_identifier"` + PropertyIdentifier types.String `tfsdk:"property_identifier"` +} + +type JqConditionModel struct { + Expressions []types.String `tfsdk:"expressions"` + Combinator types.String `tfsdk:"combinator"` +} + +type KafkaMethodModel struct { + Payload types.String `tfsdk:"payload"` +} + +type WebhookMethodModel struct { + Url types.String `tfsdk:"url"` + Agent types.String `tfsdk:"agent"` + Synchronized types.String `tfsdk:"synchronized"` + Method types.String `tfsdk:"method"` + Headers types.Map `tfsdk:"headers"` + Body types.String `tfsdk:"body"` +} + +type GithubMethodModel struct { + Org types.String `tfsdk:"org"` + Repo types.String `tfsdk:"repo"` + Workflow types.String `tfsdk:"workflow"` + WorkflowInputs types.String `tfsdk:"workflow_inputs"` + ReportWorkflowStatus types.String `tfsdk:"report_workflow_status"` +} + +type GitlabMethodModel struct { + ProjectName types.String `tfsdk:"project_name"` + GroupName types.String `tfsdk:"group_name"` + DefaultRef types.String `tfsdk:"default_ref"` + PipelineVariables types.String `tfsdk:"pipeline_variables"` +} + +type AzureMethodModel struct { + Org types.String `tfsdk:"org"` + Webhook types.String `tfsdk:"webhook"` + Payload types.String `tfsdk:"payload"` +} + type ApprovalWebhookNotificationModel struct { Url types.String `tfsdk:"url"` Format types.String `tfsdk:"format"` @@ -311,18 +349,16 @@ type ActionModel struct { Title types.String `tfsdk:"title"` Icon types.String `tfsdk:"icon"` Description types.String `tfsdk:"description"` - RequiredApproval types.Bool `tfsdk:"required_approval"` - Trigger types.String `tfsdk:"trigger"` - KafkaMethod types.Object `tfsdk:"kafka_method"` + SelfServiceTrigger *SelfServiceTriggerModel `tfsdk:"self_service_trigger"` + KafkaMethod *KafkaMethodModel `tfsdk:"kafka_method"` WebhookMethod *WebhookMethodModel `tfsdk:"webhook_method"` GithubMethod *GithubMethodModel `tfsdk:"github_method"` - AzureMethod *AzureMethodModel `tfsdk:"azure_method"` GitlabMethod *GitlabMethodModel `tfsdk:"gitlab_method"` - UserProperties *UserPropertiesModel `tfsdk:"user_properties"` + AzureMethod *AzureMethodModel `tfsdk:"azure_method"` + RequiredApproval types.Bool `tfsdk:"required_approval"` ApprovalWebhookNotification *ApprovalWebhookNotificationModel `tfsdk:"approval_webhook_notification"` ApprovalEmailNotification types.Object `tfsdk:"approval_email_notification"` - OrderProperties types.List `tfsdk:"order_properties"` - RequiredJqQuery types.String `tfsdk:"required_jq_query"` + Publish types.Bool `tfsdk:"publish"` } // ActionValidationModel is a model used for the validation of ActionModel resources @@ -333,16 +369,14 @@ type ActionValidationModel struct { Title types.String `tfsdk:"title"` Icon types.String `tfsdk:"icon"` Description types.String `tfsdk:"description"` - RequiredApproval types.Bool `tfsdk:"required_approval"` - Trigger types.String `tfsdk:"trigger"` + SelfServiceTrigger types.Object `tfsdk:"self_service_trigger"` KafkaMethod types.Object `tfsdk:"kafka_method"` WebhookMethod types.Object `tfsdk:"webhook_method"` GithubMethod types.Object `tfsdk:"github_method"` - AzureMethod types.Object `tfsdk:"azure_method"` GitlabMethod types.Object `tfsdk:"gitlab_method"` - UserProperties types.Object `tfsdk:"user_properties"` + AzureMethod types.Object `tfsdk:"azure_method"` + RequiredApproval types.Bool `tfsdk:"required_approval"` ApprovalWebhookNotification types.Object `tfsdk:"approval_webhook_notification"` ApprovalEmailNotification types.Object `tfsdk:"approval_email_notification"` - OrderProperties types.List `tfsdk:"order_properties"` - RequiredJqQuery types.String `tfsdk:"required_jq_query"` + Publish types.Bool `tfsdk:"publish"` } diff --git a/port/action/number.go b/port/action/number.go index 4bd30cfe..c361d478 100644 --- a/port/action/number.go +++ b/port/action/number.go @@ -12,7 +12,7 @@ import ( "github.com/port-labs/terraform-provider-port-labs/internal/utils" ) -func numberPropResourceToBody(ctx context.Context, state *ActionModel, props map[string]cli.ActionProperty, required *[]string) error { +func numberPropResourceToBody(ctx context.Context, state *SelfServiceTriggerModel, props map[string]cli.ActionProperty, required *[]string) error { for propIdentifier, prop := range state.UserProperties.NumberProps { props[propIdentifier] = cli.ActionProperty{ Type: "number", diff --git a/port/action/object.go b/port/action/object.go index 2c2f2d6d..d9680439 100644 --- a/port/action/object.go +++ b/port/action/object.go @@ -9,7 +9,7 @@ import ( "github.com/port-labs/terraform-provider-port-labs/internal/utils" ) -func objectPropResourceToBody(ctx context.Context, d *ActionModel, props map[string]cli.ActionProperty, required *[]string) error { +func objectPropResourceToBody(ctx context.Context, d *SelfServiceTriggerModel, props map[string]cli.ActionProperty, required *[]string) error { for propIdentifier, prop := range d.UserProperties.ObjectProps { props[propIdentifier] = cli.ActionProperty{ Type: "object", diff --git a/port/action/refreshActionState.go b/port/action/refreshActionState.go index 1eb37d17..c2b50637 100644 --- a/port/action/refreshActionState.go +++ b/port/action/refreshActionState.go @@ -14,48 +14,90 @@ import ( "github.com/port-labs/terraform-provider-port-labs/internal/utils" ) -func writeInvocationMethodToResource(a *cli.Action, state *ActionModel) { +func writeInvocationMethodToResource(ctx context.Context, a *cli.Action, state *ActionModel) error { if a.InvocationMethod.Type == consts.Kafka { - state.KafkaMethod, _ = types.ObjectValue(nil, nil) + payload, err := utils.GoObjectToTerraformString(a.InvocationMethod.Payload) + if err != nil { + return err + } + + state.KafkaMethod = &KafkaMethodModel{ + Payload: payload, + } } if a.InvocationMethod.Type == consts.Webhook { + agent, err := utils.GoObjectToTerraformString(a.InvocationMethod.Agent) + if err != nil { + return err + } + synchronized, err := utils.GoObjectToTerraformString(a.InvocationMethod.Synchronized) + if err != nil { + return err + } + headers, _ := types.MapValueFrom(ctx, types.StringType, a.InvocationMethod.Headers) + body, err := utils.GoObjectToTerraformString(a.InvocationMethod.Body) + if err != nil { + return err + } + state.WebhookMethod = &WebhookMethodModel{ Url: types.StringValue(*a.InvocationMethod.Url), - Agent: flex.GoBoolToFramework(a.InvocationMethod.Agent), - Synchronized: flex.GoBoolToFramework(a.InvocationMethod.Synchronized), + Agent: agent, + Synchronized: synchronized, Method: flex.GoStringToFramework(a.InvocationMethod.Method), + Headers: headers, + Body: body, } } if a.InvocationMethod.Type == consts.Github { + workflowInputs, err := utils.GoObjectToTerraformString(a.InvocationMethod.WorkflowInputs) + if err != nil { + return err + } + reportWorkflowStatus, err := utils.GoObjectToTerraformString(a.InvocationMethod.ReportWorkflowStatus) + if err != nil { + return err + } + state.GithubMethod = &GithubMethodModel{ - Repo: types.StringValue(*a.InvocationMethod.Repo), Org: types.StringValue(*a.InvocationMethod.Org), - OmitPayload: flex.GoBoolToFramework(a.InvocationMethod.OmitPayload), - OmitUserInputs: flex.GoBoolToFramework(a.InvocationMethod.OmitUserInputs), - Workflow: flex.GoStringToFramework(a.InvocationMethod.Workflow), - ReportWorkflowStatus: flex.GoBoolToFramework(a.InvocationMethod.ReportWorkflowStatus), + Repo: types.StringValue(*a.InvocationMethod.Repo), + Workflow: types.StringValue(*a.InvocationMethod.Workflow), + WorkflowInputs: workflowInputs, + ReportWorkflowStatus: reportWorkflowStatus, + } + } + + if a.InvocationMethod.Type == consts.Gitlab { + pipelineVariables, err := utils.GoObjectToTerraformString(a.InvocationMethod.PipelineVariables) + if err != nil { + return err + } + + state.GitlabMethod = &GitlabMethodModel{ + ProjectName: types.StringValue(*a.InvocationMethod.ProjectName), + GroupName: types.StringValue(*a.InvocationMethod.GroupName), + DefaultRef: flex.GoStringToFramework(a.InvocationMethod.DefaultRef), + PipelineVariables: pipelineVariables, } } if a.InvocationMethod.Type == consts.AzureDevops { + payload, err := utils.GoObjectToTerraformString(a.InvocationMethod.Payload) + if err != nil { + return err + } + state.AzureMethod = &AzureMethodModel{ Org: types.StringValue(*a.InvocationMethod.Org), Webhook: types.StringValue(*a.InvocationMethod.Webhook), + Payload: payload, } } - if a.InvocationMethod.Type == consts.Gitlab { - state.GitlabMethod = &GitlabMethodModel{ - ProjectName: types.StringValue(*a.InvocationMethod.ProjectName), - GroupName: types.StringValue(*a.InvocationMethod.GroupName), - OmitPayload: flex.GoBoolToFramework(a.InvocationMethod.OmitPayload), - OmitUserInputs: flex.GoBoolToFramework(a.InvocationMethod.OmitUserInputs), - DefaultRef: types.StringValue(*a.InvocationMethod.DefaultRef), - Agent: flex.GoBoolToFramework(a.InvocationMethod.Agent), - } - } + return nil } func writeDatasetToResource(ds *cli.Dataset) *DatasetModel { @@ -102,7 +144,7 @@ func writeVisibleToResource(v cli.ActionProperty) (types.Bool, types.String) { return types.BoolNull(), types.StringNull() } -func writeRequiredToResource(v cli.ActionUserInputs) (types.String, []string) { +func buildRequired(v *cli.ActionUserInputs) (types.String, []string) { // If required is nil, return an empty string and nil if v.Required == nil { return types.StringNull(), nil @@ -129,11 +171,11 @@ func writeRequiredToResource(v cli.ActionUserInputs) (types.String, []string) { return types.StringNull(), nil } -func writeInputsToResource(ctx context.Context, a *cli.Action, state *ActionModel) error { - if len(a.UserInputs.Properties) > 0 { - properties := &UserPropertiesModel{} - requiredJq, required := writeRequiredToResource(a.UserInputs) - for k, v := range a.UserInputs.Properties { +func buildUserProperties(ctx context.Context, a *cli.Action) (*UserPropertiesModel, error) { + properties := &UserPropertiesModel{} + if len(a.Trigger.UserInputs.Properties) > 0 { + requiredJq, required := buildRequired(a.Trigger.UserInputs) + for k, v := range a.Trigger.UserInputs.Properties { switch v.Type { case "string": if properties.StringProps == nil { @@ -147,7 +189,7 @@ func writeInputsToResource(ctx context.Context, a *cli.Action, state *ActionMode err := setCommonProperties(ctx, v, stringProp) if err != nil { - return err + return nil, err } properties.StringProps[k] = *stringProp @@ -165,7 +207,7 @@ func writeInputsToResource(ctx context.Context, a *cli.Action, state *ActionMode err := setCommonProperties(ctx, v, numberProp) if err != nil { - return err + return nil, err } properties.NumberProps[k] = *numberProp @@ -177,7 +219,7 @@ func writeInputsToResource(ctx context.Context, a *cli.Action, state *ActionMode arrayProp, err := addArrayPropertiesToResource(&v) if err != nil { - return err + return nil, err } if requiredJq.IsNull() && lo.Contains(required, k) { @@ -186,7 +228,7 @@ func writeInputsToResource(ctx context.Context, a *cli.Action, state *ActionMode err = setCommonProperties(ctx, v, arrayProp) if err != nil { - return err + return nil, err } properties.ArrayProps[k] = *arrayProp @@ -200,7 +242,7 @@ func writeInputsToResource(ctx context.Context, a *cli.Action, state *ActionMode err := setCommonProperties(ctx, v, booleanProp) if err != nil { - return err + return nil, err } if requiredJq.IsNull() && lo.Contains(required, k) { @@ -222,32 +264,61 @@ func writeInputsToResource(ctx context.Context, a *cli.Action, state *ActionMode err := setCommonProperties(ctx, v, objectProp) if err != nil { - return err + return nil, err } properties.ObjectProps[k] = *objectProp } } - state.UserProperties = properties - if len(a.UserInputs.Order) > 0 { - state.OrderProperties = flex.GoArrayStringToTerraformList(ctx, a.UserInputs.Order) + } + + return properties, nil +} + +func writeTriggerToResource(ctx context.Context, a *cli.Action, state *ActionModel) error { + if a.Trigger.Type == consts.SelfService { + userProperties, err := buildUserProperties(ctx, a) + if err != nil { + return err + } + requiredJqQuery, _ := buildRequired(a.Trigger.UserInputs) + orderProperties := types.ListNull(types.StringType) + if len(a.Trigger.UserInputs.Order) > 0 { + orderProperties = flex.GoArrayStringToTerraformList(ctx, a.Trigger.UserInputs.Order) + } + + state.SelfServiceTrigger = &SelfServiceTriggerModel{ + BlueprintIdentifier: flex.GoStringToFramework(a.Trigger.BlueprintIdentifier), + Operation: types.StringValue(*a.Trigger.Operation), + UserProperties: userProperties, + RequiredJqQuery: requiredJqQuery, + OrderProperties: orderProperties, } } + return nil } -func refreshActionState(ctx context.Context, state *ActionModel, a *cli.Action, blueprintIdentifier string) error { - state.ID = types.StringValue(fmt.Sprintf("%s:%s", blueprintIdentifier, a.Identifier)) +func refreshActionState(ctx context.Context, state *ActionModel, a *cli.Action) error { + state.ID = types.StringValue(a.Identifier) state.Identifier = types.StringValue(a.Identifier) - state.Blueprint = types.StringValue(blueprintIdentifier) - state.Title = types.StringValue(a.Title) - state.Trigger = types.StringValue(a.Trigger) - + state.Blueprint = types.StringNull() + state.Title = flex.GoStringToFramework(a.Title) state.Icon = flex.GoStringToFramework(a.Icon) state.Description = flex.GoStringToFramework(a.Description) - state.RequiredApproval = flex.GoBoolToFramework(a.RequiredApproval) + err := writeTriggerToResource(ctx, a, state) + if err != nil { + return err + } + + err = writeInvocationMethodToResource(ctx, a, state) + if err != nil { + return err + } + + state.RequiredApproval = flex.GoBoolToFramework(a.RequiredApproval) if a.ApprovalNotification != nil { if a.ApprovalNotification.Type == "email" { state.ApprovalEmailNotification, _ = types.ObjectValue(nil, nil) @@ -262,17 +333,8 @@ func refreshActionState(ctx context.Context, state *ActionModel, a *cli.Action, } } + state.Publish = flex.GoBoolToFramework(a.Publish) - requiredJq, _ := writeRequiredToResource(a.UserInputs) - - state.RequiredJqQuery = requiredJq - - writeInvocationMethodToResource(a, state) - - err := writeInputsToResource(ctx, a, state) - if err != nil { - return err - } return nil } diff --git a/port/action/resource.go b/port/action/resource.go index 31585256..da12a3c5 100644 --- a/port/action/resource.go +++ b/port/action/resource.go @@ -3,7 +3,6 @@ package action import ( "context" "fmt" - "strings" "github.com/hashicorp/terraform-plugin-framework/path" "github.com/hashicorp/terraform-plugin-framework/resource" @@ -35,16 +34,7 @@ func (r *ActionResource) Configure(ctx context.Context, req resource.ConfigureRe } func (r *ActionResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) { - idParts := strings.Split(req.ID, ":") - - if len(idParts) != 2 || idParts[0] == "" || idParts[1] == "" { - resp.Diagnostics.AddError("invalid import ID", "import ID must be in the format :") - return - } - - resp.Diagnostics.Append(resp.State.SetAttribute(ctx, path.Root("blueprint"), idParts[0])...) - resp.Diagnostics.Append(resp.State.SetAttribute(ctx, path.Root("identifier"), idParts[1])...) - + resp.Diagnostics.Append(resp.State.SetAttribute(ctx, path.Root("identifier"), req.ID)...) } func (r *ActionResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) { @@ -57,7 +47,12 @@ func (r *ActionResource) Read(ctx context.Context, req resource.ReadRequest, res } blueprintIdentifier := state.Blueprint.ValueString() - a, statusCode, err := r.portClient.ReadAction(ctx, blueprintIdentifier, state.Identifier.ValueString()) + actionIdentifier := state.Identifier.ValueString() + if blueprintIdentifier != "" { + actionIdentifier = fmt.Sprintf("%s_%s", blueprintIdentifier, actionIdentifier) + } + + a, statusCode, err := r.portClient.ReadAction(ctx, actionIdentifier) if err != nil { if statusCode == 404 { resp.State.RemoveResource(ctx) @@ -67,7 +62,7 @@ func (r *ActionResource) Read(ctx context.Context, req resource.ReadRequest, res return } - err = refreshActionState(ctx, state, a, blueprintIdentifier) + err = refreshActionState(ctx, state, a) if err != nil { resp.Diagnostics.AddError("failed writing action fields to resource", err.Error()) return @@ -84,7 +79,13 @@ func (r *ActionResource) Delete(ctx context.Context, req resource.DeleteRequest, return } - err := r.portClient.DeleteAction(ctx, state.Blueprint.ValueString(), state.Identifier.ValueString()) + blueprintIdentifier := state.Blueprint.ValueString() + actionIdentifier := state.Identifier.ValueString() + if blueprintIdentifier != "" { + actionIdentifier = fmt.Sprintf("%s_%s", blueprintIdentifier, actionIdentifier) + } + + err := r.portClient.DeleteAction(ctx, actionIdentifier) if err != nil { resp.Diagnostics.AddError("failed to delete action", err.Error()) return @@ -101,25 +102,19 @@ func (r *ActionResource) Create(ctx context.Context, req resource.CreateRequest, return } - bp, _, err := r.portClient.ReadBlueprint(ctx, state.Blueprint.ValueString()) - if err != nil { - resp.Diagnostics.AddError("failed to read blueprint", err.Error()) - return - } - - action, err := actionStateToPortBody(ctx, state, bp) + action, err := actionStateToPortBody(ctx, state) if err != nil { resp.Diagnostics.AddError("failed to convert action resource to body", err.Error()) return } - a, err := r.portClient.CreateAction(ctx, bp.Identifier, action) + a, err := r.portClient.CreateAction(ctx, action) if err != nil { resp.Diagnostics.AddError("failed to create action", err.Error()) return } - state.ID = types.StringValue(fmt.Sprintf("%s:%s", bp.Identifier, a.Identifier)) + state.ID = types.StringValue(a.Identifier) state.Identifier = types.StringValue(a.Identifier) resp.Diagnostics.Append(resp.State.Set(ctx, &state)...) @@ -136,30 +131,30 @@ func (r *ActionResource) Update(ctx context.Context, req resource.UpdateRequest, return } - bp, _, err := r.portClient.ReadBlueprint(ctx, state.Blueprint.ValueString()) + action, err := actionStateToPortBody(ctx, state) if err != nil { - resp.Diagnostics.AddError("failed to read blueprint", err.Error()) + resp.Diagnostics.AddError("failed to convert entity resource to body", err.Error()) return } - action, err := actionStateToPortBody(ctx, state, bp) - if err != nil { - resp.Diagnostics.AddError("failed to convert entity resource to body", err.Error()) - return + blueprintIdentifier := previousState.Blueprint.ValueString() + actionIdentifier := previousState.Identifier.ValueString() + if blueprintIdentifier != "" { + actionIdentifier = fmt.Sprintf("%s_%s", blueprintIdentifier, actionIdentifier) } var a *cli.Action if previousState.Identifier.IsNull() { - a, err = r.portClient.CreateAction(ctx, bp.Identifier, action) + a, err = r.portClient.CreateAction(ctx, action) } else { - a, err = r.portClient.UpdateAction(ctx, bp.Identifier, previousState.Identifier.ValueString(), action) + a, err = r.portClient.UpdateAction(ctx, actionIdentifier, action) } if err != nil { resp.Diagnostics.AddError("failed to create action", err.Error()) return } - state.ID = types.StringValue(fmt.Sprintf("%s:%s", bp.Identifier, a.Identifier)) + state.ID = types.StringValue(a.Identifier) state.Identifier = types.StringValue(a.Identifier) resp.Diagnostics.Append(resp.State.Set(ctx, &state)...) diff --git a/port/action/resource_test.go b/port/action/resource_test.go index d1c18622..20fd2c4e 100644 --- a/port/action/resource_test.go +++ b/port/action/resource_test.go @@ -18,9 +18,10 @@ func testAccCreateBlueprintConfig(identifier string) string { identifier = "%s" properties = { string_props = { - "text" = { - type = "string" - title = "text" + "timer" = { + type = "string" + title = "timer" + format = "timer" } } } @@ -35,8 +36,10 @@ func TestAccPortActionBasic(t *testing.T) { title = "TF Provider Test" identifier = "%s" icon = "Terraform" - blueprint = port_blueprint.microservice.id - trigger = "DAY-2" + self_service_trigger = { + operation = "DAY-2" + blueprint_identifier = port_blueprint.microservice.identifier + } kafka_method = {} }`, actionIdentifier) resource.Test(t, resource.TestCase{ @@ -49,8 +52,8 @@ func TestAccPortActionBasic(t *testing.T) { 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", "blueprint", identifier), - resource.TestCheckResourceAttr("port_action.create_microservice", "trigger", "DAY-2"), + resource.TestCheckResourceAttr("port_action.create_microservice", "self_service_trigger.blueprint_identifier", identifier), + resource.TestCheckResourceAttr("port_action.create_microservice", "self_service_trigger.operation", "DAY-2"), ), }, }, @@ -65,48 +68,99 @@ func TestAccPortAction(t *testing.T) { title = "TF Provider Test" identifier = "%s" icon = "Terraform" - blueprint = port_blueprint.microservice.id - trigger = "DAY-2" - kafka_method = {} - user_properties = { - "string_props" = { - "myStringIdentifier" = { - "title" = "My String Identifier" - "required" = true - + self_service_trigger = { + operation = "DAY-2" + blueprint_identifier = port_blueprint.microservice.identifier + user_properties = { + "string_props" = { + "myStringIdentifier" = { + "title" = "My String Identifier" + "required" = true + + } } - } - "number_props" = { - "myNumberIdentifier" = { - "title" = "My Number Identifier" - "required" = true - maximum = 100 - minimum = 0 + "number_props" = { + "myNumberIdentifier" = { + "title" = "My Number Identifier" + "required" = true + maximum = 100 + minimum = 0 + } } - } - "boolean_props" = { - "myBooleanIdentifier" = { - "title" = "My Boolean Identifier" - "required" = true + "boolean_props" = { + "myBooleanIdentifier" = { + "title" = "My Boolean Identifier" + "required" = true + } } - } - "object_props" = { - "myObjectIdentifier" = { - "title" = "My Object Identifier" - "required" = true + "object_props" = { + "myObjectIdentifier" = { + "title" = "My Object Identifier" + "required" = true + } } - } - "array_props" = { - "myArrayIdentifier" = { - "title" = "My Array Identifier" - "required" = true - string_items = { - format = "email" + "array_props" = { + "myArrayIdentifier" = { + "title" = "My Array Identifier" + "required" = true + string_items = { + format = "email" + } } } } } + 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", "self_service_trigger.blueprint_identifier", identifier), + resource.TestCheckResourceAttr("port_action.create_microservice", "self_service_trigger.operation", "DAY-2"), + resource.TestCheckResourceAttr("port_action.create_microservice", "self_service_trigger.user_properties.string_props.myStringIdentifier.title", "My String Identifier"), + resource.TestCheckResourceAttr("port_action.create_microservice", "self_service_trigger.user_properties.string_props.myStringIdentifier.required", "true"), + resource.TestCheckResourceAttr("port_action.create_microservice", "self_service_trigger.user_properties.number_props.myNumberIdentifier.title", "My Number Identifier"), + resource.TestCheckResourceAttr("port_action.create_microservice", "self_service_trigger.user_properties.number_props.myNumberIdentifier.required", "true"), + resource.TestCheckResourceAttr("port_action.create_microservice", "self_service_trigger.user_properties.number_props.myNumberIdentifier.maximum", "100"), + resource.TestCheckResourceAttr("port_action.create_microservice", "self_service_trigger.user_properties.number_props.myNumberIdentifier.minimum", "0"), + resource.TestCheckResourceAttr("port_action.create_microservice", "self_service_trigger.user_properties.boolean_props.myBooleanIdentifier.title", "My Boolean Identifier"), + resource.TestCheckResourceAttr("port_action.create_microservice", "self_service_trigger.user_properties.boolean_props.myBooleanIdentifier.required", "true"), + resource.TestCheckResourceAttr("port_action.create_microservice", "self_service_trigger.user_properties.object_props.myObjectIdentifier.title", "My Object Identifier"), + resource.TestCheckResourceAttr("port_action.create_microservice", "self_service_trigger.user_properties.object_props.myObjectIdentifier.required", "true"), + resource.TestCheckResourceAttr("port_action.create_microservice", "self_service_trigger.user_properties.array_props.myArrayIdentifier.title", "My Array Identifier"), + resource.TestCheckResourceAttr("port_action.create_microservice", "self_service_trigger.user_properties.array_props.myArrayIdentifier.required", "true"), + resource.TestCheckResourceAttr("port_action.create_microservice", "self_service_trigger.user_properties.array_props.myArrayIdentifier.string_items.format", "email"), + ), + }, + }, + }) +} +func TestAccPortActionKafkaInvocation(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 + } + kafka_method = { + payload = jsonencode({ + "runId": "{{run.id}}" + }) + } }`, actionIdentifier) resource.Test(t, resource.TestCase{ @@ -119,21 +173,9 @@ func TestAccPortAction(t *testing.T) { 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", "blueprint", identifier), - resource.TestCheckResourceAttr("port_action.create_microservice", "trigger", "DAY-2"), - resource.TestCheckResourceAttr("port_action.create_microservice", "user_properties.string_props.myStringIdentifier.title", "My String Identifier"), - resource.TestCheckResourceAttr("port_action.create_microservice", "user_properties.string_props.myStringIdentifier.required", "true"), - resource.TestCheckResourceAttr("port_action.create_microservice", "user_properties.number_props.myNumberIdentifier.title", "My Number Identifier"), - resource.TestCheckResourceAttr("port_action.create_microservice", "user_properties.number_props.myNumberIdentifier.required", "true"), - resource.TestCheckResourceAttr("port_action.create_microservice", "user_properties.number_props.myNumberIdentifier.maximum", "100"), - resource.TestCheckResourceAttr("port_action.create_microservice", "user_properties.number_props.myNumberIdentifier.minimum", "0"), - resource.TestCheckResourceAttr("port_action.create_microservice", "user_properties.boolean_props.myBooleanIdentifier.title", "My Boolean Identifier"), - resource.TestCheckResourceAttr("port_action.create_microservice", "user_properties.boolean_props.myBooleanIdentifier.required", "true"), - resource.TestCheckResourceAttr("port_action.create_microservice", "user_properties.object_props.myObjectIdentifier.title", "My Object Identifier"), - resource.TestCheckResourceAttr("port_action.create_microservice", "user_properties.object_props.myObjectIdentifier.required", "true"), - resource.TestCheckResourceAttr("port_action.create_microservice", "user_properties.array_props.myArrayIdentifier.title", "My Array Identifier"), - resource.TestCheckResourceAttr("port_action.create_microservice", "user_properties.array_props.myArrayIdentifier.required", "true"), - resource.TestCheckResourceAttr("port_action.create_microservice", "user_properties.array_props.myArrayIdentifier.string_items.format", "email"), + 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", "kafka_method.payload", "{\"runId\":\"{{run.id}}\"}"), ), }, }, @@ -148,11 +190,17 @@ func TestAccPortActionWebhookInvocation(t *testing.T) { title = "TF Provider Test" identifier = "%s" icon = "Terraform" - blueprint = port_blueprint.microservice.id - trigger = "DAY-2" + self_service_trigger = { + operation = "DAY-2" + blueprint_identifier = port_blueprint.microservice.identifier + } webhook_method = { url = "https://example.com" agent = true + synchronized = false + method = "PUT" + headers = {"X-HEADER-TEST": "{{action.identifier}}"} + body = jsonencode({"runId": "{{run.id}}"}) } }`, actionIdentifier) @@ -166,10 +214,14 @@ func TestAccPortActionWebhookInvocation(t *testing.T) { 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", "blueprint", identifier), - resource.TestCheckResourceAttr("port_action.create_microservice", "trigger", "DAY-2"), + 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", "webhook_method.url", "https://example.com"), resource.TestCheckResourceAttr("port_action.create_microservice", "webhook_method.agent", "true"), + resource.TestCheckResourceAttr("port_action.create_microservice", "webhook_method.synchronized", "false"), + resource.TestCheckResourceAttr("port_action.create_microservice", "webhook_method.method", "PUT"), + resource.TestCheckResourceAttr("port_action.create_microservice", "webhook_method.headers.X-HEADER-TEST", "{{action.identifier}}"), + resource.TestCheckResourceAttr("port_action.create_microservice", "webhook_method.body", "{\"runId\":\"{{run.id}}\"}"), ), }, }, @@ -183,13 +235,17 @@ func TestAccPortActionWebhookSyncInvocation(t *testing.T) { title = "TF Provider Test" identifier = "%s" icon = "Terraform" - blueprint = port_blueprint.microservice.id - trigger = "DAY-2" + self_service_trigger = { + operation = "DAY-2" + blueprint_identifier = port_blueprint.microservice.identifier + } webhook_method = { url = "https://example.com" synchronized = true agent = true method = "POST" + headers = {"X-HEADER-TEST": "{{action.identifier}}"} + body = jsonencode({"runId": "{{run.id}}"}) } }`, actionIdentifier) @@ -203,19 +259,21 @@ func TestAccPortActionWebhookSyncInvocation(t *testing.T) { 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", "blueprint", identifier), - resource.TestCheckResourceAttr("port_action.create_microservice", "trigger", "DAY-2"), + 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", "webhook_method.url", "https://example.com"), resource.TestCheckResourceAttr("port_action.create_microservice", "webhook_method.synchronized", "true"), resource.TestCheckResourceAttr("port_action.create_microservice", "webhook_method.method", "POST"), resource.TestCheckResourceAttr("port_action.create_microservice", "webhook_method.agent", "true"), + resource.TestCheckResourceAttr("port_action.create_microservice", "webhook_method.headers.X-HEADER-TEST", "{{action.identifier}}"), + resource.TestCheckResourceAttr("port_action.create_microservice", "webhook_method.body", "{\"runId\":\"{{run.id}}\"}"), ), }, }, }) } -func TestAccPortActionGitlabInvocation(t *testing.T) { +func TestAccPortActionGithubInvocation(t *testing.T) { identifier := utils.GenID() actionIdentifier := utils.GenID() var testAccActionConfigCreate = testAccCreateBlueprintConfig(identifier) + fmt.Sprintf(` @@ -223,15 +281,16 @@ func TestAccPortActionGitlabInvocation(t *testing.T) { title = "TF Provider Test" identifier = "%s" icon = "Terraform" - blueprint = port_blueprint.microservice.id - trigger = "DAY-2" - gitlab_method = { - project_name = "terraform-provider-port" - group_name = "port" - omit_payload = true - omit_user_inputs = true - default_ref = "main" - agent = true + self_service_trigger = { + operation = "DAY-2" + blueprint_identifier = port_blueprint.microservice.identifier + } + github_method = { + org = "port", + repo = "terraform-provider-port", + workflow = "main.yml" + workflow_inputs = jsonencode({"test-array-param": [1, true, "a", {"a": []}, null, [2]]}) + report_workflow_status = false } }`, actionIdentifier) @@ -245,20 +304,20 @@ func TestAccPortActionGitlabInvocation(t *testing.T) { 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", "blueprint", identifier), - resource.TestCheckResourceAttr("port_action.create_microservice", "trigger", "DAY-2"), - resource.TestCheckResourceAttr("port_action.create_microservice", "gitlab_method.project_name", "terraform-provider-port"), - resource.TestCheckResourceAttr("port_action.create_microservice", "gitlab_method.group_name", "port"), - resource.TestCheckResourceAttr("port_action.create_microservice", "gitlab_method.omit_payload", "true"), - resource.TestCheckResourceAttr("port_action.create_microservice", "gitlab_method.omit_user_inputs", "true"), - resource.TestCheckResourceAttr("port_action.create_microservice", "gitlab_method.default_ref", "main"), - resource.TestCheckResourceAttr("port_action.create_microservice", "gitlab_method.agent", "true"), + 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", "github_method.org", "port"), + resource.TestCheckResourceAttr("port_action.create_microservice", "github_method.repo", "terraform-provider-port"), + resource.TestCheckResourceAttr("port_action.create_microservice", "github_method.workflow", "main.yml"), + resource.TestCheckResourceAttr("port_action.create_microservice", "github_method.workflow_inputs", "{\"test-array-param\":[1,true,\"a\",{\"a\":[]},null,[2]]}"), + resource.TestCheckResourceAttr("port_action.create_microservice", "github_method.report_workflow_status", "false"), ), }, }, }) } -func TestAccPortActionAzureInvocation(t *testing.T) { + +func TestAccPortActionGitlabInvocation(t *testing.T) { identifier := utils.GenID() actionIdentifier := utils.GenID() var testAccActionConfigCreate = testAccCreateBlueprintConfig(identifier) + fmt.Sprintf(` @@ -266,11 +325,15 @@ func TestAccPortActionAzureInvocation(t *testing.T) { title = "TF Provider Test" identifier = "%s" icon = "Terraform" - blueprint = port_blueprint.microservice.id - trigger = "DAY-2" - azure_method = { - org = "port", - webhook = "https://getport.io" + self_service_trigger = { + operation = "DAY-2" + blueprint_identifier = port_blueprint.microservice.identifier + } + gitlab_method = { + project_name = "terraform-provider-port" + group_name = "port" + default_ref = "test" + pipeline_variables = jsonencode({"test-array-param": [1, true, "a", {"a": []}, null, [2]]}) } }`, actionIdentifier) @@ -284,17 +347,18 @@ func TestAccPortActionAzureInvocation(t *testing.T) { 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", "blueprint", identifier), - resource.TestCheckResourceAttr("port_action.create_microservice", "trigger", "DAY-2"), - resource.TestCheckResourceAttr("port_action.create_microservice", "azure_method.org", "port"), - resource.TestCheckResourceAttr("port_action.create_microservice", "azure_method.webhook", "https://getport.io"), + 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", "gitlab_method.project_name", "terraform-provider-port"), + resource.TestCheckResourceAttr("port_action.create_microservice", "gitlab_method.group_name", "port"), + resource.TestCheckResourceAttr("port_action.create_microservice", "gitlab_method.default_ref", "test"), + resource.TestCheckResourceAttr("port_action.create_microservice", "gitlab_method.pipeline_variables", "{\"test-array-param\":[1,true,\"a\",{\"a\":[]},null,[2]]}"), ), }, }, }) } - -func TestAccPortActionGithubInvocation(t *testing.T) { +func TestAccPortActionAzureInvocation(t *testing.T) { identifier := utils.GenID() actionIdentifier := utils.GenID() var testAccActionConfigCreate = testAccCreateBlueprintConfig(identifier) + fmt.Sprintf(` @@ -302,15 +366,14 @@ func TestAccPortActionGithubInvocation(t *testing.T) { title = "TF Provider Test" identifier = "%s" icon = "Terraform" - blueprint = port_blueprint.microservice.id - trigger = "DAY-2" - github_method = { + self_service_trigger = { + operation = "DAY-2" + blueprint_identifier = port_blueprint.microservice.identifier + } + azure_method = { org = "port", - repo = "terraform-provider-port", - workflow = "main.yml" - omit_payload = true - omit_user_inputs = true - report_workflow_status = false + webhook = "https://getport.io" + payload = jsonencode({"runId": "{{run.id}}"}) } }`, actionIdentifier) @@ -324,14 +387,11 @@ func TestAccPortActionGithubInvocation(t *testing.T) { 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", "blueprint", identifier), - resource.TestCheckResourceAttr("port_action.create_microservice", "trigger", "DAY-2"), - resource.TestCheckResourceAttr("port_action.create_microservice", "github_method.org", "port"), - resource.TestCheckResourceAttr("port_action.create_microservice", "github_method.repo", "terraform-provider-port"), - resource.TestCheckResourceAttr("port_action.create_microservice", "github_method.workflow", "main.yml"), - resource.TestCheckResourceAttr("port_action.create_microservice", "github_method.omit_payload", "true"), - resource.TestCheckResourceAttr("port_action.create_microservice", "github_method.omit_user_inputs", "true"), - resource.TestCheckResourceAttr("port_action.create_microservice", "github_method.report_workflow_status", "false"), + 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", "azure_method.org", "port"), + resource.TestCheckResourceAttr("port_action.create_microservice", "azure_method.webhook", "https://getport.io"), + resource.TestCheckResourceAttr("port_action.create_microservice", "azure_method.payload", "{\"runId\":\"{{run.id}}\"}"), ), }, }, @@ -346,19 +406,21 @@ func TestAccPortActionImport(t *testing.T) { title = "TF Provider Test" identifier = "%s" icon = "Terraform" - blueprint = port_blueprint.microservice.id - trigger = "DAY-2" - webhook_method = { - url = "https://getport.io" - } - user_properties = { - "string_props" = { - "myStringIdentifier" = { - "title" = "My String Identifier" - "required" = true + self_service_trigger = { + operation = "DAY-2" + blueprint_identifier = port_blueprint.microservice.identifier + user_properties = { + "string_props" = { + "myStringIdentifier" = { + "title" = "My String Identifier" + "required" = true + } } } } + webhook_method = { + url = "https://getport.io" + } }`, actionIdentifier) resource.Test(t, resource.TestCase{ @@ -372,18 +434,18 @@ func TestAccPortActionImport(t *testing.T) { 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", "blueprint", blueprintIdentifier), - resource.TestCheckResourceAttr("port_action.create_microservice", "trigger", "DAY-2"), + resource.TestCheckResourceAttr("port_action.create_microservice", "self_service_trigger.blueprint_identifier", blueprintIdentifier), + resource.TestCheckResourceAttr("port_action.create_microservice", "self_service_trigger.operation", "DAY-2"), resource.TestCheckResourceAttr("port_action.create_microservice", "webhook_method.url", "https://getport.io"), - resource.TestCheckResourceAttr("port_action.create_microservice", "user_properties.string_props.myStringIdentifier.title", "My String Identifier"), - resource.TestCheckResourceAttr("port_action.create_microservice", "user_properties.string_props.myStringIdentifier.required", "true"), + resource.TestCheckResourceAttr("port_action.create_microservice", "self_service_trigger.user_properties.string_props.myStringIdentifier.title", "My String Identifier"), + resource.TestCheckResourceAttr("port_action.create_microservice", "self_service_trigger.user_properties.string_props.myStringIdentifier.required", "true"), ), }, { ResourceName: "port_action.create_microservice", ImportState: true, ImportStateVerify: true, - ImportStateId: fmt.Sprintf("%s:%s", blueprintIdentifier, actionIdentifier), + ImportStateId: actionIdentifier, }, }, }) @@ -397,19 +459,21 @@ func TestAccPortActionUpdate(t *testing.T) { title = "TF Provider Test" identifier = "%s" icon = "Terraform" - blueprint = port_blueprint.microservice.id - trigger = "DAY-2" - webhook_method = { - url = "https://getport.io" - } - user_properties = { - "string_props" = { - "myStringIdentifier" = { - "title" = "My String Identifier" - "required" = true + self_service_trigger = { + operation = "DAY-2" + blueprint_identifier = port_blueprint.microservice.identifier + user_properties = { + "string_props" = { + "myStringIdentifier" = { + "title" = "My String Identifier" + "required" = true + } } } } + webhook_method = { + url = "https://getport.io" + } }`, actionIdentifier) var testAccActionConfigUpdate = testAccCreateBlueprintConfig(identifier) + fmt.Sprintf(` @@ -417,18 +481,20 @@ func TestAccPortActionUpdate(t *testing.T) { title = "TF Provider Test" identifier = "%s" icon = "Terraform" - blueprint = port_blueprint.microservice.id - trigger = "DAY-2" - webhook_method = { - url = "https://getport.io" - } - user_properties = { - "string_props" = { - "myStringIdentifier2" = { - "title" = "My String Identifier" + self_service_trigger = { + operation = "DAY-2" + blueprint_identifier = port_blueprint.microservice.identifier + user_properties = { + "string_props" = { + "myStringIdentifier2" = { + "title" = "My String Identifier" + } } } } + webhook_method = { + url = "https://getport.io" + } }`, actionIdentifier) resource.Test(t, resource.TestCase{ @@ -442,11 +508,11 @@ func TestAccPortActionUpdate(t *testing.T) { 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", "blueprint", identifier), - resource.TestCheckResourceAttr("port_action.create_microservice", "trigger", "DAY-2"), + 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", "webhook_method.url", "https://getport.io"), - resource.TestCheckResourceAttr("port_action.create_microservice", "user_properties.string_props.myStringIdentifier.title", "My String Identifier"), - resource.TestCheckResourceAttr("port_action.create_microservice", "user_properties.string_props.myStringIdentifier.required", "true"), + resource.TestCheckResourceAttr("port_action.create_microservice", "self_service_trigger.user_properties.string_props.myStringIdentifier.title", "My String Identifier"), + resource.TestCheckResourceAttr("port_action.create_microservice", "self_service_trigger.user_properties.string_props.myStringIdentifier.required", "true"), ), }, { @@ -455,11 +521,11 @@ func TestAccPortActionUpdate(t *testing.T) { 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", "blueprint", identifier), - resource.TestCheckResourceAttr("port_action.create_microservice", "trigger", "DAY-2"), + 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", "webhook_method.url", "https://getport.io"), - resource.TestCheckResourceAttr("port_action.create_microservice", "user_properties.string_props.myStringIdentifier2.title", "My String Identifier"), - resource.TestCheckNoResourceAttr("port_action.create_microservice", "user_properties.string_props.myStringIdentifier2.required"), + resource.TestCheckResourceAttr("port_action.create_microservice", "self_service_trigger.user_properties.string_props.myStringIdentifier2.title", "My String Identifier"), + resource.TestCheckNoResourceAttr("port_action.create_microservice", "self_service_trigger.user_properties.string_props.myStringIdentifier2.required"), ), }, }, @@ -470,72 +536,73 @@ func TestAccPortActionAdvancedFormConfigurations(t *testing.T) { identifier := utils.GenID() actionIdentifier := utils.GenID() var testAccActionConfigCreate = testAccCreateBlueprintConfig(identifier) + fmt.Sprintf(` - -resource "port_action" "action1" { - title = "Action 1" - blueprint = port_blueprint.microservice.id - identifier = "%s" - trigger = "DAY-2" - description = "This is a test action" - required_approval = true - github_method = { - org = "port-labs" - repo = "Port" - workflow = "lint" - } - user_properties = { - string_props = { - myStringIdentifier = { - title = "myStringIdentifier" - default = "default" - } - myStringIdentifier2 = { - title = "myStringIdentifier2" - default = "default" - depends_on = ["myStringIdentifier"] - } - myStringIdentifier3 = { - title = "myStringIdentifier3" - required = true - format = "entity" - blueprint = port_blueprint.microservice.id - dataset = { - "combinator" : "and", - "rules" : [ - { - "property" : "$team", - "operator" : "containsAny", - "value" : { - "jq_query" : "Test" + resource "port_action" "action1" { + title = "Action 1" + identifier = "%s" + self_service_trigger = { + operation = "DAY-2" + blueprint_identifier = port_blueprint.microservice.identifier + user_properties = { + string_props = { + myStringIdentifier = { + title = "myStringIdentifier" + default = "default" + } + myStringIdentifier2 = { + title = "myStringIdentifier2" + default = "default" + depends_on = ["myStringIdentifier"] + } + myStringIdentifier3 = { + title = "myStringIdentifier3" + required = true + format = "entity" + blueprint = port_blueprint.microservice.id + dataset = { + "combinator" : "and", + "rules" : [ + { + "property" : "$team", + "operator" : "containsAny", + "value" : { + "jq_query" : "Test" + } + } + ] + } } } - ] - } + array_props = { + myArrayPropIdentifier = { + title = "myArrayPropIdentifier" + required = true + blueprint = port_blueprint.microservice.id + string_items = { + blueprint = port_blueprint.microservice.id + format = "entity" + dataset = jsonencode({ + "combinator" : "and", + "rules" : [ + { + "property" : "$identifier", + "operator" : "containsAny", + "value" : "Test" + } + ] + }) + } + } + } + } } - } - array_props = { - myArrayPropIdentifier = { - title = "myArrayPropIdentifier" - required = true - blueprint = port_blueprint.microservice.id - string_items = { - blueprint = port_blueprint.microservice.id - format = "entity" - dataset = jsonencode({ - "combinator" : "and", - "rules" : [ - { - "property" : "$identifier", - "operator" : "containsAny", - "value" : "Test" - } - ] - }) - } + description = "This is a test action" + required_approval = true + github_method = { + org = "port-labs" + repo = "Port" + workflow = "lint" } - } - } - }`, actionIdentifier) + }`, actionIdentifier) resource.Test(t, resource.TestCase{ PreCheck: func() { acctest.TestAccPreCheck(t) }, @@ -547,26 +614,27 @@ resource "port_action" "action1" { Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr("port_action.action1", "title", "Action 1"), resource.TestCheckResourceAttr("port_action.action1", "identifier", actionIdentifier), - resource.TestCheckResourceAttr("port_action.action1", "trigger", "DAY-2"), + resource.TestCheckResourceAttr("port_action.action1", "self_service_trigger.operation", "DAY-2"), resource.TestCheckResourceAttr("port_action.action1", "description", "This is a test action"), resource.TestCheckResourceAttr("port_action.action1", "required_approval", "true"), resource.TestCheckResourceAttr("port_action.action1", "github_method.org", "port-labs"), resource.TestCheckResourceAttr("port_action.action1", "github_method.repo", "Port"), resource.TestCheckResourceAttr("port_action.action1", "github_method.workflow", "lint"), - resource.TestCheckResourceAttr("port_action.action1", "user_properties.string_props.myStringIdentifier.title", "myStringIdentifier"), - resource.TestCheckResourceAttr("port_action.action1", "user_properties.string_props.myStringIdentifier.default", "default"), - resource.TestCheckNoResourceAttr("port_action.action1", "user_properties.string_props.myStringIdentifier.required"), - resource.TestCheckResourceAttr("port_action.action1", "user_properties.string_props.myStringIdentifier2.title", "myStringIdentifier2"), - resource.TestCheckResourceAttr("port_action.action1", "user_properties.string_props.myStringIdentifier2.default", "default"), - resource.TestCheckNoResourceAttr("port_action.action1", "user_properties.string_props.myStringIdentifier2.required"), - resource.TestCheckResourceAttr("port_action.action1", "user_properties.string_props.myStringIdentifier2.depends_on.0", "myStringIdentifier"), - resource.TestCheckResourceAttr("port_action.action1", "user_properties.string_props.myStringIdentifier3.title", "myStringIdentifier3"), - resource.TestCheckResourceAttr("port_action.action1", "user_properties.string_props.myStringIdentifier3.required", "true"), - resource.TestCheckResourceAttr("port_action.action1", "user_properties.string_props.myStringIdentifier3.dataset.combinator", "and"), - resource.TestCheckResourceAttr("port_action.action1", "user_properties.string_props.myStringIdentifier3.dataset.rules.0.property", "$team"), - resource.TestCheckResourceAttr("port_action.action1", "user_properties.string_props.myStringIdentifier3.dataset.rules.0.operator", "containsAny"), - resource.TestCheckResourceAttr("port_action.action1", "user_properties.string_props.myStringIdentifier3.dataset.rules.0.value.jq_query", "Test"), - resource.TestCheckResourceAttr("port_action.action1", "user_properties.array_props.myArrayPropIdentifier.string_items.dataset", "{\"combinator\":\"and\",\"rules\":[{\"operator\":\"containsAny\",\"property\":\"$identifier\",\"value\":\"Test\"}]}")), + resource.TestCheckResourceAttr("port_action.action1", "self_service_trigger.user_properties.string_props.myStringIdentifier.title", "myStringIdentifier"), + resource.TestCheckResourceAttr("port_action.action1", "self_service_trigger.user_properties.string_props.myStringIdentifier.default", "default"), + resource.TestCheckNoResourceAttr("port_action.action1", "self_service_trigger.user_properties.string_props.myStringIdentifier.required"), + resource.TestCheckResourceAttr("port_action.action1", "self_service_trigger.user_properties.string_props.myStringIdentifier2.title", "myStringIdentifier2"), + resource.TestCheckResourceAttr("port_action.action1", "self_service_trigger.user_properties.string_props.myStringIdentifier2.default", "default"), + resource.TestCheckNoResourceAttr("port_action.action1", "self_service_trigger.user_properties.string_props.myStringIdentifier2.required"), + resource.TestCheckResourceAttr("port_action.action1", "self_service_trigger.user_properties.string_props.myStringIdentifier2.depends_on.0", "myStringIdentifier"), + resource.TestCheckResourceAttr("port_action.action1", "self_service_trigger.user_properties.string_props.myStringIdentifier3.title", "myStringIdentifier3"), + resource.TestCheckResourceAttr("port_action.action1", "self_service_trigger.user_properties.string_props.myStringIdentifier3.required", "true"), + resource.TestCheckResourceAttr("port_action.action1", "self_service_trigger.user_properties.string_props.myStringIdentifier3.dataset.combinator", "and"), + resource.TestCheckResourceAttr("port_action.action1", "self_service_trigger.user_properties.string_props.myStringIdentifier3.dataset.rules.0.property", "$team"), + resource.TestCheckResourceAttr("port_action.action1", "self_service_trigger.user_properties.string_props.myStringIdentifier3.dataset.rules.0.operator", "containsAny"), + resource.TestCheckResourceAttr("port_action.action1", "self_service_trigger.user_properties.string_props.myStringIdentifier3.dataset.rules.0.value.jq_query", "Test"), + resource.TestCheckResourceAttr("port_action.action1", "self_service_trigger.user_properties.array_props.myArrayPropIdentifier.string_items.dataset", "{\"combinator\":\"and\",\"rules\":[{\"operator\":\"containsAny\",\"property\":\"$identifier\",\"value\":\"Test\"}]}"), + ), }, }, }) @@ -578,43 +646,45 @@ func TestAccPortActionJqDefault(t *testing.T) { var testAccActionConfigCreate = testAccCreateBlueprintConfig(identifier) + fmt.Sprintf(` resource "port_action" "create_microservice" { title = "Action 1" - blueprint = port_blueprint.microservice.id identifier = "%s" - trigger = "DAY-2" - description = "This is a test action" - kafka_method = {} - user_properties = { - string_props = { - myStringIdentifier = { - title = "myStringIdentifier" - default_jq_query = "'Test'" + self_service_trigger = { + operation = "DAY-2" + blueprint_identifier = port_blueprint.microservice.identifier + user_properties = { + string_props = { + myStringIdentifier = { + title = "myStringIdentifier" + default_jq_query = "'Test'" + } } - } - number_props = { - myNumberIdentifier = { - title = "myNumberIdentifier" - default_jq_query = "1" + number_props = { + myNumberIdentifier = { + title = "myNumberIdentifier" + default_jq_query = "1" + } } - } - boolean_props = { - myBooleanIdentifier = { - title = "myBooleanIdentifier" - default_jq_query = "true" + boolean_props = { + myBooleanIdentifier = { + title = "myBooleanIdentifier" + default_jq_query = "true" + } } - } - object_props = { - myObjectIdentifier = { - title = "myObjectIdentifier" - default_jq_query = "{ \"test\": \"test\" }" + object_props = { + myObjectIdentifier = { + title = "myObjectIdentifier" + default_jq_query = "{ \"test\": \"test\" }" + } } - } - array_props = { - myArrayIdentifier = { - title = "myArrayIdentifier" - default_jq_query = "[ \"test\" ]" + array_props = { + myArrayIdentifier = { + title = "myArrayIdentifier" + default_jq_query = "[ \"test\" ]" + } } } } + description = "This is a test action" + kafka_method = {} }`, actionIdentifier) resource.Test(t, resource.TestCase{ @@ -627,18 +697,18 @@ func TestAccPortActionJqDefault(t *testing.T) { Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr("port_action.create_microservice", "title", "Action 1"), resource.TestCheckResourceAttr("port_action.create_microservice", "identifier", actionIdentifier), - resource.TestCheckResourceAttr("port_action.create_microservice", "trigger", "DAY-2"), + resource.TestCheckResourceAttr("port_action.create_microservice", "self_service_trigger.operation", "DAY-2"), resource.TestCheckResourceAttr("port_action.create_microservice", "description", "This is a test action"), - resource.TestCheckResourceAttr("port_action.create_microservice", "user_properties.string_props.myStringIdentifier.title", "myStringIdentifier"), - resource.TestCheckResourceAttr("port_action.create_microservice", "user_properties.string_props.myStringIdentifier.default_jq_query", "'Test'"), - resource.TestCheckResourceAttr("port_action.create_microservice", "user_properties.number_props.myNumberIdentifier.title", "myNumberIdentifier"), - resource.TestCheckResourceAttr("port_action.create_microservice", "user_properties.number_props.myNumberIdentifier.default_jq_query", "1"), - resource.TestCheckResourceAttr("port_action.create_microservice", "user_properties.boolean_props.myBooleanIdentifier.title", "myBooleanIdentifier"), - resource.TestCheckResourceAttr("port_action.create_microservice", "user_properties.boolean_props.myBooleanIdentifier.default_jq_query", "true"), - resource.TestCheckResourceAttr("port_action.create_microservice", "user_properties.object_props.myObjectIdentifier.title", "myObjectIdentifier"), - resource.TestCheckResourceAttr("port_action.create_microservice", "user_properties.object_props.myObjectIdentifier.default_jq_query", "{ \"test\": \"test\" }"), - resource.TestCheckResourceAttr("port_action.create_microservice", "user_properties.array_props.myArrayIdentifier.title", "myArrayIdentifier"), - resource.TestCheckResourceAttr("port_action.create_microservice", "user_properties.array_props.myArrayIdentifier.default_jq_query", "[ \"test\" ]"), + resource.TestCheckResourceAttr("port_action.create_microservice", "self_service_trigger.user_properties.string_props.myStringIdentifier.title", "myStringIdentifier"), + resource.TestCheckResourceAttr("port_action.create_microservice", "self_service_trigger.user_properties.string_props.myStringIdentifier.default_jq_query", "'Test'"), + resource.TestCheckResourceAttr("port_action.create_microservice", "self_service_trigger.user_properties.number_props.myNumberIdentifier.title", "myNumberIdentifier"), + resource.TestCheckResourceAttr("port_action.create_microservice", "self_service_trigger.user_properties.number_props.myNumberIdentifier.default_jq_query", "1"), + resource.TestCheckResourceAttr("port_action.create_microservice", "self_service_trigger.user_properties.boolean_props.myBooleanIdentifier.title", "myBooleanIdentifier"), + resource.TestCheckResourceAttr("port_action.create_microservice", "self_service_trigger.user_properties.boolean_props.myBooleanIdentifier.default_jq_query", "true"), + resource.TestCheckResourceAttr("port_action.create_microservice", "self_service_trigger.user_properties.object_props.myObjectIdentifier.title", "myObjectIdentifier"), + resource.TestCheckResourceAttr("port_action.create_microservice", "self_service_trigger.user_properties.object_props.myObjectIdentifier.default_jq_query", "{ \"test\": \"test\" }"), + resource.TestCheckResourceAttr("port_action.create_microservice", "self_service_trigger.user_properties.array_props.myArrayIdentifier.title", "myArrayIdentifier"), + resource.TestCheckResourceAttr("port_action.create_microservice", "self_service_trigger.user_properties.array_props.myArrayIdentifier.default_jq_query", "[ \"test\" ]"), ), }, }, @@ -652,40 +722,42 @@ func TestAccPortActionEnumJqQuery(t *testing.T) { var testAccActionConfigCreate = testAccCreateBlueprintConfig(identifier) + fmt.Sprintf(` resource "port_action" "create_microservice" { title = "Action 1" - blueprint = port_blueprint.microservice.id identifier = "%s" - trigger = "DAY-2" - description = "This is a test action" - kafka_method = {} - user_properties = { - string_props = { - myStringIdentifier = { - title = "myStringIdentifier" - enum_jq_query = "[\"test1\", \"test2\"]" - } - } - number_props = { - myNumberIdentifier = { - title = "myNumberIdentifier" - enum_jq_query = "[1, 2]" - } - } - array_props = { - myStringArrayIdentifier = { - title = "myStringArrayIdentifier" - string_items = { - enum_jq_query = "'example' | [ . ]" + self_service_trigger = { + operation = "DAY-2" + blueprint_identifier = port_blueprint.microservice.identifier + user_properties = { + string_props = { + myStringIdentifier = { + title = "myStringIdentifier" + enum_jq_query = "[\"test1\", \"test2\"]" } } - myNumberArrayIdentifier = { - title = "myNumberArrayIdentifier" - number_items = { + number_props = { + myNumberIdentifier = { + title = "myNumberIdentifier" enum_jq_query = "[1, 2]" } } - + array_props = { + myStringArrayIdentifier = { + title = "myStringArrayIdentifier" + string_items = { + enum_jq_query = "'example' | [ . ]" + } + } + myNumberArrayIdentifier = { + title = "myNumberArrayIdentifier" + number_items = { + enum_jq_query = "[1, 2]" + } + } + + } } } + description = "This is a test action" + kafka_method = {} }`, actionIdentifier) resource.Test(t, resource.TestCase{ @@ -698,16 +770,16 @@ func TestAccPortActionEnumJqQuery(t *testing.T) { Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr("port_action.create_microservice", "title", "Action 1"), resource.TestCheckResourceAttr("port_action.create_microservice", "identifier", actionIdentifier), - resource.TestCheckResourceAttr("port_action.create_microservice", "trigger", "DAY-2"), + resource.TestCheckResourceAttr("port_action.create_microservice", "self_service_trigger.operation", "DAY-2"), resource.TestCheckResourceAttr("port_action.create_microservice", "description", "This is a test action"), - resource.TestCheckResourceAttr("port_action.create_microservice", "user_properties.string_props.myStringIdentifier.title", "myStringIdentifier"), - resource.TestCheckResourceAttr("port_action.create_microservice", "user_properties.string_props.myStringIdentifier.enum_jq_query", "[\"test1\", \"test2\"]"), - resource.TestCheckResourceAttr("port_action.create_microservice", "user_properties.number_props.myNumberIdentifier.title", "myNumberIdentifier"), - resource.TestCheckResourceAttr("port_action.create_microservice", "user_properties.number_props.myNumberIdentifier.enum_jq_query", "[1, 2]"), - resource.TestCheckResourceAttr("port_action.create_microservice", "user_properties.array_props.myStringArrayIdentifier.title", "myStringArrayIdentifier"), - resource.TestCheckResourceAttr("port_action.create_microservice", "user_properties.array_props.myStringArrayIdentifier.string_items.enum_jq_query", "'example' | [ . ]"), - resource.TestCheckResourceAttr("port_action.create_microservice", "user_properties.array_props.myNumberArrayIdentifier.title", "myNumberArrayIdentifier"), - resource.TestCheckResourceAttr("port_action.create_microservice", "user_properties.array_props.myNumberArrayIdentifier.number_items.enum_jq_query", "[1, 2]"), + resource.TestCheckResourceAttr("port_action.create_microservice", "self_service_trigger.user_properties.string_props.myStringIdentifier.title", "myStringIdentifier"), + resource.TestCheckResourceAttr("port_action.create_microservice", "self_service_trigger.user_properties.string_props.myStringIdentifier.enum_jq_query", "[\"test1\", \"test2\"]"), + resource.TestCheckResourceAttr("port_action.create_microservice", "self_service_trigger.user_properties.number_props.myNumberIdentifier.title", "myNumberIdentifier"), + resource.TestCheckResourceAttr("port_action.create_microservice", "self_service_trigger.user_properties.number_props.myNumberIdentifier.enum_jq_query", "[1, 2]"), + resource.TestCheckResourceAttr("port_action.create_microservice", "self_service_trigger.user_properties.array_props.myStringArrayIdentifier.title", "myStringArrayIdentifier"), + resource.TestCheckResourceAttr("port_action.create_microservice", "self_service_trigger.user_properties.array_props.myStringArrayIdentifier.string_items.enum_jq_query", "'example' | [ . ]"), + resource.TestCheckResourceAttr("port_action.create_microservice", "self_service_trigger.user_properties.array_props.myNumberArrayIdentifier.title", "myNumberArrayIdentifier"), + resource.TestCheckResourceAttr("port_action.create_microservice", "self_service_trigger.user_properties.array_props.myNumberArrayIdentifier.number_items.enum_jq_query", "[1, 2]"), ), }, }, @@ -720,33 +792,35 @@ func TestAccPortActionEnum(t *testing.T) { var testAccActionConfigCreate = testAccCreateBlueprintConfig(identifier) + fmt.Sprintf(` resource "port_action" "create_microservice" { title = "Action 1" - blueprint = port_blueprint.microservice.id identifier = "%s" - trigger = "DAY-2" - description = "This is a test action" - kafka_method = {} - user_properties = { - string_props = { - myStringIdentifier = { - title = "myStringIdentifier" - enum = ["test1", "test2"] + self_service_trigger = { + operation = "DAY-2" + blueprint_identifier = port_blueprint.microservice.identifier + user_properties = { + string_props = { + myStringIdentifier = { + title = "myStringIdentifier" + enum = ["test1", "test2"] + } } - } - number_props = { - myNumberIdentifier = { - title = "myNumberIdentifier" - enum = [1, 2] + number_props = { + myNumberIdentifier = { + title = "myNumberIdentifier" + enum = [1, 2] + } } - } - array_props = { - myStringArrayIdentifier = { - title = "myStringArrayIdentifier" - string_items = { - enum = ["example"] + array_props = { + myStringArrayIdentifier = { + title = "myStringArrayIdentifier" + string_items = { + enum = ["example"] + } } } } } + description = "This is a test action" + kafka_method = {} }`, actionIdentifier) resource.Test(t, resource.TestCase{ @@ -759,14 +833,14 @@ func TestAccPortActionEnum(t *testing.T) { Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr("port_action.create_microservice", "title", "Action 1"), resource.TestCheckResourceAttr("port_action.create_microservice", "identifier", actionIdentifier), - resource.TestCheckResourceAttr("port_action.create_microservice", "trigger", "DAY-2"), + resource.TestCheckResourceAttr("port_action.create_microservice", "self_service_trigger.operation", "DAY-2"), resource.TestCheckResourceAttr("port_action.create_microservice", "description", "This is a test action"), - resource.TestCheckResourceAttr("port_action.create_microservice", "user_properties.string_props.myStringIdentifier.title", "myStringIdentifier"), - resource.TestCheckResourceAttr("port_action.create_microservice", "user_properties.string_props.myStringIdentifier.enum.0", "test1"), - resource.TestCheckResourceAttr("port_action.create_microservice", "user_properties.string_props.myStringIdentifier.enum.1", "test2"), - resource.TestCheckResourceAttr("port_action.create_microservice", "user_properties.number_props.myNumberIdentifier.title", "myNumberIdentifier"), - resource.TestCheckResourceAttr("port_action.create_microservice", "user_properties.number_props.myNumberIdentifier.enum.0", "1"), - resource.TestCheckResourceAttr("port_action.create_microservice", "user_properties.number_props.myNumberIdentifier.enum.1", "2"), + resource.TestCheckResourceAttr("port_action.create_microservice", "self_service_trigger.user_properties.string_props.myStringIdentifier.title", "myStringIdentifier"), + resource.TestCheckResourceAttr("port_action.create_microservice", "self_service_trigger.user_properties.string_props.myStringIdentifier.enum.0", "test1"), + resource.TestCheckResourceAttr("port_action.create_microservice", "self_service_trigger.user_properties.string_props.myStringIdentifier.enum.1", "test2"), + resource.TestCheckResourceAttr("port_action.create_microservice", "self_service_trigger.user_properties.number_props.myNumberIdentifier.title", "myNumberIdentifier"), + resource.TestCheckResourceAttr("port_action.create_microservice", "self_service_trigger.user_properties.number_props.myNumberIdentifier.enum.0", "1"), + resource.TestCheckResourceAttr("port_action.create_microservice", "self_service_trigger.user_properties.number_props.myNumberIdentifier.enum.1", "2"), ), }, }, @@ -780,20 +854,22 @@ func TestAccPortActionOrderProperties(t *testing.T) { title = "Action 1" identifier = "%s" icon = "Terraform" - blueprint = port_blueprint.microservice.id - trigger = "DAY-2" - kafka_method = {} - order_properties = ["myStringIdentifier2", "myStringIdentifier1"] - user_properties = { - string_props = { - myStringIdentifier1 = { - title = "myStringIdentifier1" - } - myStringIdentifier2 = { - title = "myStringIdentifier2" + self_service_trigger = { + operation = "DAY-2" + blueprint_identifier = port_blueprint.microservice.identifier + order_properties = ["myStringIdentifier2", "myStringIdentifier1"] + user_properties = { + string_props = { + myStringIdentifier1 = { + title = "myStringIdentifier1" + } + myStringIdentifier2 = { + title = "myStringIdentifier2" + } } } } + kafka_method = {} }`, actionIdentifier) resource.Test(t, resource.TestCase{ @@ -806,11 +882,11 @@ func TestAccPortActionOrderProperties(t *testing.T) { Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr("port_action.action1", "title", "Action 1"), resource.TestCheckResourceAttr("port_action.action1", "identifier", actionIdentifier), - resource.TestCheckResourceAttr("port_action.action1", "trigger", "DAY-2"), - resource.TestCheckResourceAttr("port_action.action1", "user_properties.string_props.myStringIdentifier1.title", "myStringIdentifier1"), - resource.TestCheckResourceAttr("port_action.action1", "user_properties.string_props.myStringIdentifier2.title", "myStringIdentifier2"), - resource.TestCheckResourceAttr("port_action.action1", "order_properties.0", "myStringIdentifier2"), - resource.TestCheckResourceAttr("port_action.action1", "order_properties.1", "myStringIdentifier1"), + resource.TestCheckResourceAttr("port_action.action1", "self_service_trigger.operation", "DAY-2"), + resource.TestCheckResourceAttr("port_action.action1", "self_service_trigger.user_properties.string_props.myStringIdentifier1.title", "myStringIdentifier1"), + resource.TestCheckResourceAttr("port_action.action1", "self_service_trigger.user_properties.string_props.myStringIdentifier2.title", "myStringIdentifier2"), + resource.TestCheckResourceAttr("port_action.action1", "self_service_trigger.order_properties.0", "myStringIdentifier2"), + resource.TestCheckResourceAttr("port_action.action1", "self_service_trigger.order_properties.1", "myStringIdentifier1"), ), }, }, @@ -825,27 +901,29 @@ func TestAccPortActionEncryption(t *testing.T) { title = "TF Provider Test" identifier = "%s" icon = "Terraform" - blueprint = port_blueprint.microservice.id - trigger = "DAY-2" - webhook_method = { - url = "https://getport.io" - } - user_properties = { - "string_props" = { - "encryptedStringProp" = { - "title" = "Encrypted string" - "required" = true - "encryption" = "aes256-gcm" + self_service_trigger = { + operation = "DAY-2" + blueprint_identifier = port_blueprint.microservice.identifier + user_properties = { + "string_props" = { + "encryptedStringProp" = { + "title" = "Encrypted string" + "required" = true + "encryption" = "aes256-gcm" + } } - } - "object_props" = { - "encryptedObjectProp" = { - "title" = "Encrypted object" - "required" = true - "encryption" = "aes256-gcm" + "object_props" = { + "encryptedObjectProp" = { + "title" = "Encrypted object" + "required" = true + "encryption" = "aes256-gcm" + } } } } + webhook_method = { + url = "https://getport.io" + } }`, actionIdentifier) resource.Test(t, resource.TestCase{ @@ -859,15 +937,15 @@ func TestAccPortActionEncryption(t *testing.T) { resource.TestCheckResourceAttr("port_action.action1", "title", "TF Provider Test"), resource.TestCheckResourceAttr("port_action.action1", "identifier", actionIdentifier), resource.TestCheckResourceAttr("port_action.action1", "icon", "Terraform"), - resource.TestCheckResourceAttr("port_action.action1", "blueprint", blueprintIdentifier), - resource.TestCheckResourceAttr("port_action.action1", "trigger", "DAY-2"), + resource.TestCheckResourceAttr("port_action.action1", "self_service_trigger.blueprint_identifier", blueprintIdentifier), + resource.TestCheckResourceAttr("port_action.action1", "self_service_trigger.operation", "DAY-2"), resource.TestCheckResourceAttr("port_action.action1", "webhook_method.url", "https://getport.io"), - resource.TestCheckResourceAttr("port_action.action1", "user_properties.string_props.encryptedStringProp.title", "Encrypted string"), - resource.TestCheckResourceAttr("port_action.action1", "user_properties.string_props.encryptedStringProp.required", "true"), - resource.TestCheckResourceAttr("port_action.action1", "user_properties.string_props.encryptedStringProp.encryption", "aes256-gcm"), - resource.TestCheckResourceAttr("port_action.action1", "user_properties.object_props.encryptedObjectProp.title", "Encrypted object"), - resource.TestCheckResourceAttr("port_action.action1", "user_properties.object_props.encryptedObjectProp.required", "true"), - resource.TestCheckResourceAttr("port_action.action1", "user_properties.object_props.encryptedObjectProp.encryption", "aes256-gcm"), + resource.TestCheckResourceAttr("port_action.action1", "self_service_trigger.user_properties.string_props.encryptedStringProp.title", "Encrypted string"), + resource.TestCheckResourceAttr("port_action.action1", "self_service_trigger.user_properties.string_props.encryptedStringProp.required", "true"), + resource.TestCheckResourceAttr("port_action.action1", "self_service_trigger.user_properties.string_props.encryptedStringProp.encryption", "aes256-gcm"), + resource.TestCheckResourceAttr("port_action.action1", "self_service_trigger.user_properties.object_props.encryptedObjectProp.title", "Encrypted object"), + resource.TestCheckResourceAttr("port_action.action1", "self_service_trigger.user_properties.object_props.encryptedObjectProp.required", "true"), + resource.TestCheckResourceAttr("port_action.action1", "self_service_trigger.user_properties.object_props.encryptedObjectProp.encryption", "aes256-gcm"), ), }, }, @@ -883,19 +961,21 @@ func TestAccPortActionUpdateIdentifier(t *testing.T) { title = "TF Provider Test" identifier = "%s" icon = "Terraform" - blueprint = port_blueprint.microservice.id - trigger = "DAY-2" - webhook_method = { - url = "https://getport.io" - } - user_properties = { - "string_props" = { - "myStringIdentifier" = { - "title" = "My String Identifier" - "required" = true + self_service_trigger = { + operation = "DAY-2" + blueprint_identifier = port_blueprint.microservice.identifier + user_properties = { + "string_props" = { + "myStringIdentifier" = { + "title" = "My String Identifier" + "required" = true + } } } } + webhook_method = { + url = "https://getport.io" + } }`, actionIdentifier) var testAccActionConfigUpdate = testAccCreateBlueprintConfig(identifier) + fmt.Sprintf(` @@ -903,19 +983,21 @@ func TestAccPortActionUpdateIdentifier(t *testing.T) { title = "TF Provider Test" identifier = "%s" icon = "Terraform" - blueprint = port_blueprint.microservice.id - trigger = "DAY-2" - webhook_method = { - url = "https://getport.io" - } - user_properties = { - "string_props" = { - "myStringIdentifier" = { - "title" = "My String Identifier" - "required" = true + self_service_trigger = { + operation = "DAY-2" + blueprint_identifier = port_blueprint.microservice.identifier + user_properties = { + "string_props" = { + "myStringIdentifier" = { + "title" = "My String Identifier" + "required" = true + } } } } + webhook_method = { + url = "https://getport.io" + } }`, actionUpdatedIdentifier) resource.Test(t, resource.TestCase{ @@ -929,11 +1011,11 @@ func TestAccPortActionUpdateIdentifier(t *testing.T) { 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", "blueprint", identifier), - resource.TestCheckResourceAttr("port_action.create_microservice", "trigger", "DAY-2"), + 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", "webhook_method.url", "https://getport.io"), - resource.TestCheckResourceAttr("port_action.create_microservice", "user_properties.string_props.myStringIdentifier.title", "My String Identifier"), - resource.TestCheckResourceAttr("port_action.create_microservice", "user_properties.string_props.myStringIdentifier.required", "true"), + resource.TestCheckResourceAttr("port_action.create_microservice", "self_service_trigger.user_properties.string_props.myStringIdentifier.title", "My String Identifier"), + resource.TestCheckResourceAttr("port_action.create_microservice", "self_service_trigger.user_properties.string_props.myStringIdentifier.required", "true"), ), }, { @@ -942,11 +1024,11 @@ func TestAccPortActionUpdateIdentifier(t *testing.T) { resource.TestCheckResourceAttr("port_action.create_microservice", "title", "TF Provider Test"), resource.TestCheckResourceAttr("port_action.create_microservice", "identifier", actionUpdatedIdentifier), resource.TestCheckResourceAttr("port_action.create_microservice", "icon", "Terraform"), - resource.TestCheckResourceAttr("port_action.create_microservice", "blueprint", identifier), - resource.TestCheckResourceAttr("port_action.create_microservice", "trigger", "DAY-2"), + 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", "webhook_method.url", "https://getport.io"), - resource.TestCheckResourceAttr("port_action.create_microservice", "user_properties.string_props.myStringIdentifier.title", "My String Identifier"), - resource.TestCheckResourceAttr("port_action.create_microservice", "user_properties.string_props.myStringIdentifier.required", "true"), + resource.TestCheckResourceAttr("port_action.create_microservice", "self_service_trigger.user_properties.string_props.myStringIdentifier.title", "My String Identifier"), + resource.TestCheckResourceAttr("port_action.create_microservice", "self_service_trigger.user_properties.string_props.myStringIdentifier.required", "true"), ), }, }, @@ -961,98 +1043,100 @@ func TestAccPortActionVisibility(t *testing.T) { title = "TF Provider Test" identifier = "%s" icon = "Terraform" - blueprint = port_blueprint.microservice.id - trigger = "DAY-2" - webhook_method = { - url = "https://getport.io" - } - user_properties = { - "string_props" = { - "visibleStringProp" = { - "title" = "visible string" - "required" = true - "visible" = true - } - "invisibleStringProp" = { - "title" = "invisible string" - "required" = true - "visible" = false - } - "jqQueryStringProp" = { - "title" = "jq based visibilty string" - "required" = true - "visible_jq_query" = "1==1" - } - } - "number_props" = { - "visibleNumberProp" = { - "title" = "visible number" - "required" = true - "visible" = true - } - "invisibleNumberProp" = { - "title" = "invisible number" - "required" = true - "visible" = false - } - "jqQueryNumberProp" = { - "title" = "jq based visibilty number" - "required" = true - "visible_jq_query" = "1==1" - } - } - "boolean_props" = { - "visibleBooleanProp" = { - "title" = "visible boolean" - "required" = true - "visible" = true - } - "invisibleBooleanProp" = { - "title" = "invisible boolean" - "required" = true - "visible" = false - } - "jqQueryBooleanProp" = { - "title" = "jq based visibilty boolean" - "required" = true - "visible_jq_query" = "1==1" - } - } - "array_props" = { - "visibleArrayProp" = { - "title" = "visible array" - "required" = true - "visible" = true - } - "invisibleArrayProp" = { - "title" = "invisible array" - "required" = true - "visible" = false + self_service_trigger = { + operation = "DAY-2" + blueprint_identifier = port_blueprint.microservice.identifier + user_properties = { + "string_props" = { + "visibleStringProp" = { + "title" = "visible string" + "required" = true + "visible" = true + } + "invisibleStringProp" = { + "title" = "invisible string" + "required" = true + "visible" = false + } + "jqQueryStringProp" = { + "title" = "jq based visibilty string" + "required" = true + "visible_jq_query" = "1==1" + } } - "jqQueryArrayProp" = { - "title" = "jq based visibilty array" - "required" = true - "visible_jq_query" = "1==1" + "number_props" = { + "visibleNumberProp" = { + "title" = "visible number" + "required" = true + "visible" = true + } + "invisibleNumberProp" = { + "title" = "invisible number" + "required" = true + "visible" = false + } + "jqQueryNumberProp" = { + "title" = "jq based visibilty number" + "required" = true + "visible_jq_query" = "1==1" + } } - } - "object_props" = { - "visibleObjectProp" = { - "title" = "visible array" - "required" = true - "visible" = true + "boolean_props" = { + "visibleBooleanProp" = { + "title" = "visible boolean" + "required" = true + "visible" = true + } + "invisibleBooleanProp" = { + "title" = "invisible boolean" + "required" = true + "visible" = false + } + "jqQueryBooleanProp" = { + "title" = "jq based visibilty boolean" + "required" = true + "visible_jq_query" = "1==1" + } } - "invisibleObjectProp" = { - "title" = "invisible array" - "required" = true - "visible" = false + "array_props" = { + "visibleArrayProp" = { + "title" = "visible array" + "required" = true + "visible" = true + } + "invisibleArrayProp" = { + "title" = "invisible array" + "required" = true + "visible" = false + } + "jqQueryArrayProp" = { + "title" = "jq based visibilty array" + "required" = true + "visible_jq_query" = "1==1" + } } - "jqQueryObjectProp" = { - "title" = "jq based visibilty array" - "required" = true - "visible_jq_query" = "1==1" + "object_props" = { + "visibleObjectProp" = { + "title" = "visible array" + "required" = true + "visible" = true + } + "invisibleObjectProp" = { + "title" = "invisible array" + "required" = true + "visible" = false + } + "jqQueryObjectProp" = { + "title" = "jq based visibilty array" + "required" = true + "visible_jq_query" = "1==1" + } } } } + webhook_method = { + url = "https://getport.io" + } }`, actionIdentifier) resource.Test(t, resource.TestCase{ @@ -1066,25 +1150,25 @@ func TestAccPortActionVisibility(t *testing.T) { resource.TestCheckResourceAttr("port_action.action1", "title", "TF Provider Test"), resource.TestCheckResourceAttr("port_action.action1", "identifier", actionIdentifier), resource.TestCheckResourceAttr("port_action.action1", "icon", "Terraform"), - resource.TestCheckResourceAttr("port_action.action1", "blueprint", blueprintIdentifier), - resource.TestCheckResourceAttr("port_action.action1", "trigger", "DAY-2"), + resource.TestCheckResourceAttr("port_action.action1", "self_service_trigger.blueprint_identifier", blueprintIdentifier), + resource.TestCheckResourceAttr("port_action.action1", "self_service_trigger.operation", "DAY-2"), resource.TestCheckResourceAttr("port_action.action1", "webhook_method.url", "https://getport.io"), - resource.TestCheckResourceAttr("port_action.action1", "user_properties.string_props.visibleStringProp.visible", "true"), - resource.TestCheckResourceAttr("port_action.action1", "user_properties.string_props.invisibleStringProp.visible", "false"), - resource.TestCheckResourceAttr("port_action.action1", "user_properties.string_props.jqQueryStringProp.visible_jq_query", "1==1"), - resource.TestCheckResourceAttr("port_action.action1", "user_properties.number_props.visibleNumberProp.visible", "true"), - resource.TestCheckResourceAttr("port_action.action1", "user_properties.number_props.invisibleNumberProp.visible", "false"), - resource.TestCheckResourceAttr("port_action.action1", "user_properties.number_props.jqQueryNumberProp.visible_jq_query", "1==1"), - resource.TestCheckResourceAttr("port_action.action1", "user_properties.boolean_props.visibleBooleanProp.visible", "true"), - resource.TestCheckResourceAttr("port_action.action1", "user_properties.boolean_props.invisibleBooleanProp.visible", "false"), - resource.TestCheckResourceAttr("port_action.action1", "user_properties.boolean_props.jqQueryBooleanProp.visible_jq_query", "1==1"), - resource.TestCheckResourceAttr("port_action.action1", "user_properties.array_props.visibleArrayProp.visible", "true"), - resource.TestCheckResourceAttr("port_action.action1", "user_properties.array_props.invisibleArrayProp.visible", "false"), - resource.TestCheckResourceAttr("port_action.action1", "user_properties.array_props.jqQueryArrayProp.visible_jq_query", "1==1"), - resource.TestCheckResourceAttr("port_action.action1", "user_properties.object_props.visibleObjectProp.visible", "true"), - resource.TestCheckResourceAttr("port_action.action1", "user_properties.object_props.invisibleObjectProp.visible", "false"), - resource.TestCheckResourceAttr("port_action.action1", "user_properties.object_props.jqQueryObjectProp.visible_jq_query", "1==1"), + resource.TestCheckResourceAttr("port_action.action1", "self_service_trigger.user_properties.string_props.visibleStringProp.visible", "true"), + resource.TestCheckResourceAttr("port_action.action1", "self_service_trigger.user_properties.string_props.invisibleStringProp.visible", "false"), + resource.TestCheckResourceAttr("port_action.action1", "self_service_trigger.user_properties.string_props.jqQueryStringProp.visible_jq_query", "1==1"), + resource.TestCheckResourceAttr("port_action.action1", "self_service_trigger.user_properties.number_props.visibleNumberProp.visible", "true"), + resource.TestCheckResourceAttr("port_action.action1", "self_service_trigger.user_properties.number_props.invisibleNumberProp.visible", "false"), + resource.TestCheckResourceAttr("port_action.action1", "self_service_trigger.user_properties.number_props.jqQueryNumberProp.visible_jq_query", "1==1"), + resource.TestCheckResourceAttr("port_action.action1", "self_service_trigger.user_properties.boolean_props.visibleBooleanProp.visible", "true"), + resource.TestCheckResourceAttr("port_action.action1", "self_service_trigger.user_properties.boolean_props.invisibleBooleanProp.visible", "false"), + resource.TestCheckResourceAttr("port_action.action1", "self_service_trigger.user_properties.boolean_props.jqQueryBooleanProp.visible_jq_query", "1==1"), + resource.TestCheckResourceAttr("port_action.action1", "self_service_trigger.user_properties.array_props.visibleArrayProp.visible", "true"), + resource.TestCheckResourceAttr("port_action.action1", "self_service_trigger.user_properties.array_props.invisibleArrayProp.visible", "false"), + resource.TestCheckResourceAttr("port_action.action1", "self_service_trigger.user_properties.array_props.jqQueryArrayProp.visible_jq_query", "1==1"), + resource.TestCheckResourceAttr("port_action.action1", "self_service_trigger.user_properties.object_props.visibleObjectProp.visible", "true"), + resource.TestCheckResourceAttr("port_action.action1", "self_service_trigger.user_properties.object_props.invisibleObjectProp.visible", "false"), + resource.TestCheckResourceAttr("port_action.action1", "self_service_trigger.user_properties.object_props.jqQueryObjectProp.visible_jq_query", "1==1"), ), }, }, @@ -1099,23 +1183,25 @@ func TestAccPortActionRequiredConflictsWithRequiredJQ(t *testing.T) { title = "TF Provider Test" identifier = "%s" icon = "Terraform" - blueprint = port_blueprint.microservice.id - trigger = "DAY-2" - webhook_method = { - url = "https://getport.io" - } - user_properties = { - "string_props" = { - "equalsOne" = { - "title" = "equalsOne" - "required" = true - } - "notEqualsOne" = { - "title" = "notEqualsOne" - "required" = true + self_service_trigger = { + operation = "DAY-2" + blueprint_identifier = port_blueprint.microservice.identifier + user_properties = { + "string_props" = { + "equalsOne" = { + "title" = "equalsOne" + "required" = true + } + "notEqualsOne" = { + "title" = "notEqualsOne" + "required" = true + } } } } + webhook_method = { + url = "https://getport.io" + } }`, actionIdentifier) var testAccActionConfigUpdate = testAccCreateBlueprintConfig(blueprintIdentifier) + fmt.Sprintf(` @@ -1123,24 +1209,26 @@ func TestAccPortActionRequiredConflictsWithRequiredJQ(t *testing.T) { title = "TF Provider Test" identifier = "%s" icon = "Terraform" - blueprint = port_blueprint.microservice.id - trigger = "DAY-2" - webhook_method = { - url = "https://getport.io" - } - user_properties = { - "string_props" = { - "equalsOne" = { - "title" = "equalsOne" - "required" = true - } - "notEqualsOne" = { - "title" = "notEqualsOne" - "required" = true + self_service_trigger = { + operation = "DAY-2" + blueprint_identifier = port_blueprint.microservice.identifier + user_properties = { + "string_props" = { + "equalsOne" = { + "title" = "equalsOne" + "required" = true + } + "notEqualsOne" = { + "title" = "notEqualsOne" + "required" = true + } } } + required_jq_query = "1==1" + } + webhook_method = { + url = "https://getport.io" } - required_jq_query = "1==1" }`, actionIdentifier) var testAccActionConfigUpdate2 = testAccCreateBlueprintConfig(blueprintIdentifier) + fmt.Sprintf(` @@ -1148,22 +1236,24 @@ func TestAccPortActionRequiredConflictsWithRequiredJQ(t *testing.T) { title = "TF Provider Test" identifier = "%s" icon = "Terraform" - blueprint = port_blueprint.microservice.id - trigger = "DAY-2" - webhook_method = { - url = "https://getport.io" - } - user_properties = { - "string_props" = { - "equalsOne" = { - "title" = "equalsOne" - } - "notEqualsOne" = { - "title" = "notEqualsOne" + self_service_trigger = { + operation = "DAY-2" + blueprint_identifier = port_blueprint.microservice.identifier + user_properties = { + "string_props" = { + "equalsOne" = { + "title" = "equalsOne" + } + "notEqualsOne" = { + "title" = "notEqualsOne" + } } } + required_jq_query = "1==1" + } + webhook_method = { + url = "https://getport.io" } - required_jq_query = "1==1" }`, actionIdentifier) // expect a failure when applying the update @@ -1179,13 +1269,13 @@ func TestAccPortActionRequiredConflictsWithRequiredJQ(t *testing.T) { resource.TestCheckResourceAttr("port_action.action1", "title", "TF Provider Test"), resource.TestCheckResourceAttr("port_action.action1", "identifier", actionIdentifier), resource.TestCheckResourceAttr("port_action.action1", "icon", "Terraform"), - resource.TestCheckResourceAttr("port_action.action1", "blueprint", blueprintIdentifier), - resource.TestCheckResourceAttr("port_action.action1", "trigger", "DAY-2"), + resource.TestCheckResourceAttr("port_action.action1", "self_service_trigger.blueprint_identifier", blueprintIdentifier), + resource.TestCheckResourceAttr("port_action.action1", "self_service_trigger.operation", "DAY-2"), resource.TestCheckResourceAttr("port_action.action1", "webhook_method.url", "https://getport.io"), - resource.TestCheckResourceAttr("port_action.action1", "user_properties.string_props.equalsOne.title", "equalsOne"), - resource.TestCheckResourceAttr("port_action.action1", "user_properties.string_props.equalsOne.required", "true"), - resource.TestCheckResourceAttr("port_action.action1", "user_properties.string_props.notEqualsOne.title", "notEqualsOne"), - resource.TestCheckResourceAttr("port_action.action1", "user_properties.string_props.notEqualsOne.required", "true"), + resource.TestCheckResourceAttr("port_action.action1", "self_service_trigger.user_properties.string_props.equalsOne.title", "equalsOne"), + resource.TestCheckResourceAttr("port_action.action1", "self_service_trigger.user_properties.string_props.equalsOne.required", "true"), + resource.TestCheckResourceAttr("port_action.action1", "self_service_trigger.user_properties.string_props.notEqualsOne.title", "notEqualsOne"), + resource.TestCheckResourceAttr("port_action.action1", "self_service_trigger.user_properties.string_props.notEqualsOne.required", "true"), ), }, { @@ -1198,14 +1288,14 @@ func TestAccPortActionRequiredConflictsWithRequiredJQ(t *testing.T) { resource.TestCheckResourceAttr("port_action.action1", "title", "TF Provider Test"), resource.TestCheckResourceAttr("port_action.action1", "identifier", actionIdentifier), resource.TestCheckResourceAttr("port_action.action1", "icon", "Terraform"), - resource.TestCheckResourceAttr("port_action.action1", "blueprint", blueprintIdentifier), - resource.TestCheckResourceAttr("port_action.action1", "trigger", "DAY-2"), + resource.TestCheckResourceAttr("port_action.action1", "self_service_trigger.blueprint_identifier", blueprintIdentifier), + resource.TestCheckResourceAttr("port_action.action1", "self_service_trigger.operation", "DAY-2"), resource.TestCheckResourceAttr("port_action.action1", "webhook_method.url", "https://getport.io"), - resource.TestCheckResourceAttr("port_action.action1", "user_properties.string_props.equalsOne.title", "equalsOne"), - resource.TestCheckNoResourceAttr("port_action.action1", "user_properties.string_props.equalsOne.required"), - resource.TestCheckResourceAttr("port_action.action1", "user_properties.string_props.notEqualsOne.title", "notEqualsOne"), - resource.TestCheckNoResourceAttr("port_action.action1", "user_properties.string_props.notEqualsOne.required"), - resource.TestCheckResourceAttr("port_action.action1", "required_jq_query", "1==1"), + resource.TestCheckResourceAttr("port_action.action1", "self_service_trigger.user_properties.string_props.equalsOne.title", "equalsOne"), + resource.TestCheckNoResourceAttr("port_action.action1", "self_service_trigger.user_properties.string_props.equalsOne.required"), + resource.TestCheckResourceAttr("port_action.action1", "self_service_trigger.user_properties.string_props.notEqualsOne.title", "notEqualsOne"), + resource.TestCheckNoResourceAttr("port_action.action1", "self_service_trigger.user_properties.string_props.notEqualsOne.required"), + resource.TestCheckResourceAttr("port_action.action1", "self_service_trigger.required_jq_query", "1==1"), ), }, }, @@ -1220,22 +1310,24 @@ func TestAccPortActionRequiredFalseAndNull(t *testing.T) { title = "TF Provider Test" identifier = "%s" icon = "Terraform" - blueprint = port_blueprint.microservice.id - trigger = "DAY-2" - webhook_method = { - url = "https://getport.io" - } - user_properties = { - "string_props" = { - "notRequiredExist" = { - "title" = "notEqualsOne" - } - "requiredTrue" = { - "title" = "notEqualsOne" - "required" = true + self_service_trigger = { + operation = "DAY-2" + blueprint_identifier = port_blueprint.microservice.identifier + user_properties = { + "string_props" = { + "notRequiredExist" = { + "title" = "notEqualsOne" + } + "requiredTrue" = { + "title" = "notEqualsOne" + "required" = true + } } } } + webhook_method = { + url = "https://getport.io" + } }`, actionIdentifier) resource.Test(t, resource.TestCase{ @@ -1250,13 +1342,13 @@ func TestAccPortActionRequiredFalseAndNull(t *testing.T) { resource.TestCheckResourceAttr("port_action.action1", "title", "TF Provider Test"), resource.TestCheckResourceAttr("port_action.action1", "identifier", actionIdentifier), resource.TestCheckResourceAttr("port_action.action1", "icon", "Terraform"), - resource.TestCheckResourceAttr("port_action.action1", "blueprint", blueprintIdentifier), - resource.TestCheckResourceAttr("port_action.action1", "trigger", "DAY-2"), + resource.TestCheckResourceAttr("port_action.action1", "self_service_trigger.blueprint_identifier", blueprintIdentifier), + resource.TestCheckResourceAttr("port_action.action1", "self_service_trigger.operation", "DAY-2"), resource.TestCheckResourceAttr("port_action.action1", "webhook_method.url", "https://getport.io"), - resource.TestCheckResourceAttr("port_action.action1", "user_properties.string_props.notRequiredExist.title", "notEqualsOne"), - resource.TestCheckNoResourceAttr("port_action.action1", "user_properties.string_props.notRequiredExist.required"), - resource.TestCheckResourceAttr("port_action.action1", "user_properties.string_props.requiredTrue.title", "notEqualsOne"), - resource.TestCheckResourceAttr("port_action.action1", "user_properties.string_props.requiredTrue.required", "true"), + resource.TestCheckResourceAttr("port_action.action1", "self_service_trigger.user_properties.string_props.notRequiredExist.title", "notEqualsOne"), + resource.TestCheckNoResourceAttr("port_action.action1", "self_service_trigger.user_properties.string_props.notRequiredExist.required"), + resource.TestCheckResourceAttr("port_action.action1", "self_service_trigger.user_properties.string_props.requiredTrue.title", "notEqualsOne"), + resource.TestCheckResourceAttr("port_action.action1", "self_service_trigger.user_properties.string_props.requiredTrue.required", "true"), ), }, }, @@ -1271,8 +1363,10 @@ func TestAccPortWebhookApproval(t *testing.T) { title = "TF Provider Test" identifier = "%s" icon = "Terraform" - blueprint = port_blueprint.microservice.id - trigger = "DAY-2" + self_service_trigger = { + operation = "DAY-2" + blueprint_identifier = port_blueprint.microservice.identifier + } kafka_method = {} required_approval = true approval_webhook_notification = { @@ -1290,8 +1384,8 @@ func TestAccPortWebhookApproval(t *testing.T) { 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", "blueprint", identifier), - resource.TestCheckResourceAttr("port_action.create_microservice", "trigger", "DAY-2"), + 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", "required_approval", "true"), resource.TestCheckResourceAttr("port_action.create_microservice", "approval_webhook_notification.url", "https://example.com"), resource.TestCheckResourceAttr("port_action.create_microservice", "approval_webhook_notification.format", "json"), @@ -1309,8 +1403,10 @@ func TestAccPortEmailApproval(t *testing.T) { title = "TF Provider Test" identifier = "%s" icon = "Terraform" - blueprint = port_blueprint.microservice.id - trigger = "DAY-2" + self_service_trigger = { + operation = "DAY-2" + blueprint_identifier = port_blueprint.microservice.identifier + } kafka_method = {} required_approval = true approval_email_notification = {} @@ -1325,8 +1421,8 @@ func TestAccPortEmailApproval(t *testing.T) { 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", "blueprint", identifier), - resource.TestCheckResourceAttr("port_action.create_microservice", "trigger", "DAY-2"), + 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", "required_approval", "true"), resource.TestCheckResourceAttr("port_action.create_microservice", "approval_email_notification.%", "0"), ), @@ -1339,18 +1435,19 @@ func TestAccPortActionStringGitlabMethodSetConditionally(t *testing.T) { identifier := utils.GenID() actionIdentifier := utils.GenID() var testAccActionConfigCreate = testAccCreateBlueprintConfig(identifier) + fmt.Sprintf(` -resource "port_action" "action1" { - title = "Action 1" - blueprint = port_blueprint.microservice.id - identifier = "%s" - trigger = "CREATE" - required_approval = false - webhook_method = port_blueprint.microservice.identifier == "%s" ? { - url = "https://getport.io" - } : null - user_properties = {} -} - `, actionIdentifier, identifier) + resource "port_action" "action1" { + title = "Action 1" + identifier = "%s" + required_approval = false + self_service_trigger = { + operation = "CREATE" + blueprint_identifier = port_blueprint.microservice.identifier + user_properties = {} + } + webhook_method = port_blueprint.microservice.identifier == "%s" ? { + url = "https://getport.io" + } : null + }`, actionIdentifier, identifier) resource.Test(t, resource.TestCase{ PreCheck: func() { acctest.TestAccPreCheck(t) }, @@ -1362,7 +1459,7 @@ resource "port_action" "action1" { Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr("port_action.action1", "title", "Action 1"), resource.TestCheckResourceAttr("port_action.action1", "identifier", actionIdentifier), - resource.TestCheckResourceAttr("port_action.action1", "trigger", "CREATE"), + resource.TestCheckResourceAttr("port_action.action1", "self_service_trigger.operation", "CREATE"), resource.TestCheckResourceAttr("port_action.action1", "webhook_method.url", "https://getport.io"), ), }, @@ -1374,22 +1471,23 @@ func TestAccPortActionStringUserPropertiesConditional(t *testing.T) { identifier := utils.GenID() actionIdentifier := utils.GenID() var testAccActionConfigCreate = testAccCreateBlueprintConfig(identifier) + fmt.Sprintf(` -resource "port_action" "action1" { - title = "Action 1" - blueprint = port_blueprint.microservice.id - identifier = "%s" - trigger = "CREATE" - required_approval = false - kafka_method = {} - user_properties = { - string_props = port_blueprint.microservice.identifier == "%s" ? { - strProp = { - title = "Prop" + resource "port_action" "action1" { + title = "Action 1" + identifier = "%s" + required_approval = false + self_service_trigger = { + operation = "CREATE" + blueprint_identifier = port_blueprint.microservice.identifier + user_properties = { + string_props = port_blueprint.microservice.identifier == "%s" ? { + strProp = { + title = "Prop" + } + } : null + } } - } : null - } -} - `, actionIdentifier, identifier) + kafka_method = {} + }`, actionIdentifier, identifier) resource.Test(t, resource.TestCase{ PreCheck: func() { acctest.TestAccPreCheck(t) }, @@ -1401,8 +1499,8 @@ resource "port_action" "action1" { Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr("port_action.action1", "title", "Action 1"), resource.TestCheckResourceAttr("port_action.action1", "identifier", actionIdentifier), - resource.TestCheckResourceAttr("port_action.action1", "trigger", "CREATE"), - resource.TestCheckResourceAttr("port_action.action1", "user_properties.string_props.strProp.title", "Prop"), + resource.TestCheckResourceAttr("port_action.action1", "self_service_trigger.operation", "CREATE"), + resource.TestCheckResourceAttr("port_action.action1", "self_service_trigger.user_properties.string_props.strProp.title", "Prop"), ), }, }, @@ -1413,22 +1511,23 @@ func TestAccPortActionNumberUserPropertiesConditional(t *testing.T) { identifier := utils.GenID() actionIdentifier := utils.GenID() var testAccActionConfigCreate = testAccCreateBlueprintConfig(identifier) + fmt.Sprintf(` -resource "port_action" "action1" { - title = "Action 1" - blueprint = port_blueprint.microservice.id - identifier = "%s" - trigger = "CREATE" - required_approval = false - kafka_method = {} - user_properties = { - number_props = port_blueprint.microservice.identifier == "%s" ? { - numProp = { - title = "Prop" + resource "port_action" "action1" { + title = "Action 1" + identifier = "%s" + required_approval = false + self_service_trigger = { + operation = "CREATE" + blueprint_identifier = port_blueprint.microservice.identifier + user_properties = { + number_props = port_blueprint.microservice.identifier == "%s" ? { + numProp = { + title = "Prop" + } + } : null + } } - } : null - } -} - `, actionIdentifier, identifier) + kafka_method = {} + }`, actionIdentifier, identifier) resource.Test(t, resource.TestCase{ PreCheck: func() { acctest.TestAccPreCheck(t) }, @@ -1440,8 +1539,8 @@ resource "port_action" "action1" { Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr("port_action.action1", "title", "Action 1"), resource.TestCheckResourceAttr("port_action.action1", "identifier", actionIdentifier), - resource.TestCheckResourceAttr("port_action.action1", "trigger", "CREATE"), - resource.TestCheckResourceAttr("port_action.action1", "user_properties.number_props.numProp.title", "Prop"), + resource.TestCheckResourceAttr("port_action.action1", "self_service_trigger.operation", "CREATE"), + resource.TestCheckResourceAttr("port_action.action1", "self_service_trigger.user_properties.number_props.numProp.title", "Prop"), ), }, }, @@ -1452,22 +1551,23 @@ func TestAccPortActionBoolUserPropertiesConditional(t *testing.T) { identifier := utils.GenID() actionIdentifier := utils.GenID() var testAccActionConfigCreate = testAccCreateBlueprintConfig(identifier) + fmt.Sprintf(` -resource "port_action" "action1" { - title = "Action 1" - blueprint = port_blueprint.microservice.id - identifier = "%s" - trigger = "CREATE" - required_approval = false - kafka_method = {} - user_properties = { - boolean_props = port_blueprint.microservice.identifier == "%s" ? { - boolProp = { - title = "Prop" + resource "port_action" "action1" { + title = "Action 1" + identifier = "%s" + required_approval = false + self_service_trigger = { + operation = "CREATE" + blueprint_identifier = port_blueprint.microservice.identifier + user_properties = { + boolean_props = port_blueprint.microservice.identifier == "%s" ? { + boolProp = { + title = "Prop" + } + } : null + } } - } : null - } -} - `, actionIdentifier, identifier) + kafka_method = {} + }`, actionIdentifier, identifier) resource.Test(t, resource.TestCase{ PreCheck: func() { acctest.TestAccPreCheck(t) }, @@ -1479,8 +1579,8 @@ resource "port_action" "action1" { Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr("port_action.action1", "title", "Action 1"), resource.TestCheckResourceAttr("port_action.action1", "identifier", actionIdentifier), - resource.TestCheckResourceAttr("port_action.action1", "trigger", "CREATE"), - resource.TestCheckResourceAttr("port_action.action1", "user_properties.boolean_props.boolProp.title", "Prop"), + resource.TestCheckResourceAttr("port_action.action1", "self_service_trigger.operation", "CREATE"), + resource.TestCheckResourceAttr("port_action.action1", "self_service_trigger.user_properties.boolean_props.boolProp.title", "Prop"), ), }, }, @@ -1491,22 +1591,23 @@ func TestAccPortActionObjectUserPropertiesConditional(t *testing.T) { identifier := utils.GenID() actionIdentifier := utils.GenID() var testAccActionConfigCreate = testAccCreateBlueprintConfig(identifier) + fmt.Sprintf(` -resource "port_action" "action1" { - title = "Action 1" - blueprint = port_blueprint.microservice.id - identifier = "%s" - trigger = "CREATE" - required_approval = false - kafka_method = {} - user_properties = { - object_props = port_blueprint.microservice.identifier == "%s" ? { - objProp = { - title = "Prop" + resource "port_action" "action1" { + title = "Action 1" + identifier = "%s" + required_approval = false + self_service_trigger = { + operation = "CREATE" + blueprint_identifier = port_blueprint.microservice.identifier + user_properties = { + object_props = port_blueprint.microservice.identifier == "%s" ? { + objProp = { + title = "Prop" + } + } : null + } } - } : null - } -} - `, actionIdentifier, identifier) + kafka_method = {} + }`, actionIdentifier, identifier) resource.Test(t, resource.TestCase{ PreCheck: func() { acctest.TestAccPreCheck(t) }, @@ -1518,8 +1619,8 @@ resource "port_action" "action1" { Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr("port_action.action1", "title", "Action 1"), resource.TestCheckResourceAttr("port_action.action1", "identifier", actionIdentifier), - resource.TestCheckResourceAttr("port_action.action1", "trigger", "CREATE"), - resource.TestCheckResourceAttr("port_action.action1", "user_properties.object_props.objProp.title", "Prop"), + resource.TestCheckResourceAttr("port_action.action1", "self_service_trigger.operation", "CREATE"), + resource.TestCheckResourceAttr("port_action.action1", "self_service_trigger.user_properties.object_props.objProp.title", "Prop"), ), }, }, @@ -1530,22 +1631,23 @@ func TestAccPortActionArrayUserPropertiesConditional(t *testing.T) { identifier := utils.GenID() actionIdentifier := utils.GenID() var testAccActionConfigCreate = testAccCreateBlueprintConfig(identifier) + fmt.Sprintf(` -resource "port_action" "action1" { - title = "Action 1" - blueprint = port_blueprint.microservice.id - identifier = "%s" - trigger = "CREATE" - required_approval = false - kafka_method = {} - user_properties = { - array_props = port_blueprint.microservice.identifier == "%s" ? { - arrProp = { - title = "Prop" + resource "port_action" "action1" { + title = "Action 1" + identifier = "%s" + required_approval = false + self_service_trigger = { + operation = "CREATE" + blueprint_identifier = port_blueprint.microservice.identifier + user_properties = { + array_props = port_blueprint.microservice.identifier == "%s" ? { + arrProp = { + title = "Prop" + } + } : null + } } - } : null - } -} - `, actionIdentifier, identifier) + kafka_method = {} + }`, actionIdentifier, identifier) resource.Test(t, resource.TestCase{ PreCheck: func() { acctest.TestAccPreCheck(t) }, @@ -1557,8 +1659,8 @@ resource "port_action" "action1" { Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr("port_action.action1", "title", "Action 1"), resource.TestCheckResourceAttr("port_action.action1", "identifier", actionIdentifier), - resource.TestCheckResourceAttr("port_action.action1", "trigger", "CREATE"), - resource.TestCheckResourceAttr("port_action.action1", "user_properties.array_props.arrProp.title", "Prop"), + resource.TestCheckResourceAttr("port_action.action1", "self_service_trigger.operation", "CREATE"), + resource.TestCheckResourceAttr("port_action.action1", "self_service_trigger.user_properties.array_props.arrProp.title", "Prop"), ), }, }, @@ -1569,46 +1671,47 @@ func TestAccPortActionNoUserPropertiesConditional(t *testing.T) { identifier := utils.GenID() actionIdentifier := utils.GenID() var testAccActionConfigCreate = testAccCreateBlueprintConfig(identifier) + fmt.Sprintf(` -resource "port_action" "action1" { - title = "Action 1" - blueprint = port_blueprint.microservice.id - identifier = "%s" - trigger = "CREATE" - required_approval = false - kafka_method = {} - user_properties = { - string_props = port_blueprint.microservice.identifier == "notTheRealIdentifier" ? { - strProp = { - title = "Prop" - } - } : null - - number_props = port_blueprint.microservice.identifier == "notTheRealIdentifier" ? { - numProp = { - title = "Prop" - } - } : null - - boolean_props = port_blueprint.microservice.identifier == "notTheRealIdentifier" ? { - boolProp = { - title = "Prop" - } - } : null - - object_props = port_blueprint.microservice.identifier == "notTheRealIdentifier" ? { - objProp = { - title = "Prop" - } - } : null - - array_props = port_blueprint.microservice.identifier == "notTheRealIdentifier" ? { - arrProp = { - title = "Prop" + resource "port_action" "action1" { + title = "Action 1" + identifier = "%s" + required_approval = false + self_service_trigger = { + operation = "CREATE" + blueprint_identifier = port_blueprint.microservice.identifier + user_properties = { + string_props = port_blueprint.microservice.identifier == "notTheRealIdentifier" ? { + strProp = { + title = "Prop" + } + } : null + + number_props = port_blueprint.microservice.identifier == "notTheRealIdentifier" ? { + numProp = { + title = "Prop" + } + } : null + + boolean_props = port_blueprint.microservice.identifier == "notTheRealIdentifier" ? { + boolProp = { + title = "Prop" + } + } : null + + object_props = port_blueprint.microservice.identifier == "notTheRealIdentifier" ? { + objProp = { + title = "Prop" + } + } : null + + array_props = port_blueprint.microservice.identifier == "notTheRealIdentifier" ? { + arrProp = { + title = "Prop" + } + } : null + } } - } : null - } -} - `, actionIdentifier) + kafka_method = {} + }`, actionIdentifier) resource.Test(t, resource.TestCase{ PreCheck: func() { acctest.TestAccPreCheck(t) }, @@ -1620,12 +1723,12 @@ resource "port_action" "action1" { Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr("port_action.action1", "title", "Action 1"), resource.TestCheckResourceAttr("port_action.action1", "identifier", actionIdentifier), - resource.TestCheckResourceAttr("port_action.action1", "trigger", "CREATE"), - resource.TestCheckNoResourceAttr("port_action.action1", "user_properties.string_props"), - resource.TestCheckNoResourceAttr("port_action.action1", "user_properties.number_props"), - resource.TestCheckNoResourceAttr("port_action.action1", "user_properties.boolean_props"), - resource.TestCheckNoResourceAttr("port_action.action1", "user_properties.object_props"), - resource.TestCheckNoResourceAttr("port_action.action1", "user_properties.array_props"), + resource.TestCheckResourceAttr("port_action.action1", "self_service_trigger.operation", "CREATE"), + resource.TestCheckNoResourceAttr("port_action.action1", "self_service_trigger.user_properties.string_props"), + resource.TestCheckNoResourceAttr("port_action.action1", "self_service_trigger.user_properties.number_props"), + resource.TestCheckNoResourceAttr("port_action.action1", "self_service_trigger.user_properties.boolean_props"), + resource.TestCheckNoResourceAttr("port_action.action1", "self_service_trigger.user_properties.object_props"), + resource.TestCheckNoResourceAttr("port_action.action1", "self_service_trigger.user_properties.array_props"), ), }, }, diff --git a/port/action/schema.go b/port/action/schema.go index ecb45604..a1eec1ca 100644 --- a/port/action/schema.go +++ b/port/action/schema.go @@ -3,10 +3,12 @@ package action import ( "context" "fmt" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/objectdefault" "github.com/hashicorp/terraform-plugin-framework-validators/boolvalidator" "github.com/hashicorp/terraform-plugin-framework-validators/int64validator" "github.com/hashicorp/terraform-plugin-framework-validators/listvalidator" + "github.com/hashicorp/terraform-plugin-framework-validators/objectvalidator" "github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator" "github.com/hashicorp/terraform-plugin-framework/attr" "github.com/hashicorp/terraform-plugin-framework/path" @@ -17,6 +19,7 @@ import ( "github.com/hashicorp/terraform-plugin-framework/types" "github.com/hashicorp/terraform-plugin-go/tftypes" "github.com/port-labs/terraform-provider-port-labs/internal/utils" + "regexp" ) func MetadataProperties() map[string]schema.Attribute { @@ -33,7 +36,7 @@ func MetadataProperties() map[string]schema.Attribute { MarkdownDescription: "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", Optional: true, Validators: []validator.Bool{ - boolvalidator.ConflictsWith(path.MatchRoot("required_jq_query")), + boolvalidator.ConflictsWith(path.MatchRoot("self_service_trigger").AtName("required_jq_query")), }, }, "description": schema.StringAttribute{ @@ -48,6 +51,17 @@ func MetadataProperties() map[string]schema.Attribute { } } +func StringBooleanOrJQTemplateValidator() []validator.String { + return []validator.String{ + stringvalidator.Any( + stringvalidator.OneOf("true", "false"), + stringvalidator.RegexMatches( + regexp.MustCompile(`^[\n\r\s]*{{.*}}[\n\r\s]*$`), + "must be a valid jq template: {{JQ_EXPRESSION}}", + )), + } +} + func ActionSchema() map[string]schema.Attribute { return map[string]schema.Attribute{ "id": schema.StringAttribute{ @@ -59,11 +73,13 @@ func ActionSchema() map[string]schema.Attribute { }, "blueprint": schema.StringAttribute{ MarkdownDescription: "The blueprint identifier the action relates to", - Required: true, + Optional: true, + DeprecationMessage: "Action is not attached to blueprint anymore. This value is ignored", + Validators: []validator.String{stringvalidator.OneOf("")}, }, "title": schema.StringAttribute{ MarkdownDescription: "Title", - Required: true, + Optional: true, }, "icon": schema.StringAttribute{ MarkdownDescription: "Icon", @@ -73,71 +89,104 @@ func ActionSchema() map[string]schema.Attribute { MarkdownDescription: "Description", Optional: true, }, - "required_approval": schema.BoolAttribute{ - MarkdownDescription: "Require approval before invoking the action", - Optional: true, - }, - "approval_webhook_notification": schema.SingleNestedAttribute{ - MarkdownDescription: "The webhook notification of the approval", + "self_service_trigger": schema.SingleNestedAttribute{ + MarkdownDescription: "Self service trigger for the action", Optional: true, Attributes: map[string]schema.Attribute{ - "url": schema.StringAttribute{ - MarkdownDescription: "The URL to invoke the webhook", + "blueprint_identifier": schema.StringAttribute{ + Description: "The ID of the blueprint", + Optional: true, + }, + "operation": schema.StringAttribute{ + MarkdownDescription: "The operation type of the action", Required: true, + Validators: []validator.String{ + stringvalidator.OneOf("CREATE", "DAY-2", "DELETE"), + }, }, - "format": schema.StringAttribute{ - MarkdownDescription: "The format to invoke the webhook", + "user_properties": schema.SingleNestedAttribute{ + MarkdownDescription: "User properties", Optional: true, - Validators: []validator.String{ - stringvalidator.OneOf("json", "slack"), + Computed: true, + Default: objectdefault.StaticValue(types.ObjectValueMust(map[string]attr.Type{}, map[string]attr.Value{})), + Attributes: map[string]schema.Attribute{ + "string_props": StringPropertySchema(), + "number_props": NumberPropertySchema(), + "boolean_props": BooleanPropertySchema(), + "object_props": ObjectPropertySchema(), + "array_props": ArrayPropertySchema(), }, }, + "required_jq_query": schema.StringAttribute{ + MarkdownDescription: "The required jq query of the property", + Optional: true, + }, + "order_properties": schema.ListAttribute{ + MarkdownDescription: "Order properties", + Optional: true, + ElementType: types.StringType, + }, }, - }, - "approval_email_notification": schema.ObjectAttribute{ - MarkdownDescription: "The email notification of the approval", - Optional: true, - AttributeTypes: map[string]attr.Type{}, - }, - "trigger": schema.StringAttribute{ - MarkdownDescription: "The trigger type of the action", - Required: true, - Validators: []validator.String{ - stringvalidator.OneOf("CREATE", "DAY-2", "DELETE"), + Validators: []validator.Object{ + objectvalidator.ExactlyOneOf( + path.MatchRoot("self_service_trigger"), + ), }, }, - "kafka_method": schema.ObjectAttribute{ - MarkdownDescription: "The invocation method of the action", + "kafka_method": schema.SingleNestedAttribute{ + MarkdownDescription: "Kafka invocation method", Optional: true, - AttributeTypes: map[string]attr.Type{}, + Attributes: map[string]schema.Attribute{ + "payload": schema.StringAttribute{ + MarkdownDescription: "The Kafka message payload (array or object encoded to a string)", + Optional: true, + }, + }, + Validators: []validator.Object{ + objectvalidator.ExactlyOneOf( + path.MatchRoot("kafka_method"), + path.MatchRoot("webhook_method"), + path.MatchRoot("github_method"), + path.MatchRoot("gitlab_method"), + path.MatchRoot("azure_method"), + ), + }, }, "webhook_method": schema.SingleNestedAttribute{ - MarkdownDescription: "The invocation method of the action", + MarkdownDescription: "Webhook invocation method", Optional: true, Attributes: map[string]schema.Attribute{ "url": schema.StringAttribute{ MarkdownDescription: "Required when selecting type WEBHOOK. The URL to invoke the action", Required: true, }, - "agent": schema.BoolAttribute{ + "agent": schema.StringAttribute{ MarkdownDescription: "Use the agent to invoke the action", Optional: true, + Validators: StringBooleanOrJQTemplateValidator(), }, - "synchronized": schema.BoolAttribute{ + "synchronized": schema.StringAttribute{ MarkdownDescription: "Synchronize the action", Optional: true, + Validators: StringBooleanOrJQTemplateValidator(), }, "method": schema.StringAttribute{ MarkdownDescription: "The HTTP method to invoke the action", Optional: true, - Validators: []validator.String{ - stringvalidator.OneOf("POST", "PUT", "PATCH", "DELETE"), - }, + }, + "headers": schema.MapAttribute{ + MarkdownDescription: "The HTTP method to invoke the action", + ElementType: types.StringType, + Optional: true, + }, + "body": schema.StringAttribute{ + MarkdownDescription: "The Webhook body (array or object encoded to a string)", + Optional: true, }, }, }, "github_method": schema.SingleNestedAttribute{ - MarkdownDescription: "The invocation method of the action", + MarkdownDescription: "GitHub invocation method", Optional: true, Attributes: map[string]schema.Attribute{ "org": schema.StringAttribute{ @@ -152,26 +201,19 @@ func ActionSchema() map[string]schema.Attribute { MarkdownDescription: "The GitHub workflow that the action belongs to", Required: true, }, - "omit_payload": schema.BoolAttribute{ - MarkdownDescription: "Omit the payload when invoking the action", + "workflow_inputs": schema.StringAttribute{ + MarkdownDescription: "The GitHub workflow inputs (key-value object encoded to a string)", Optional: true, - Computed: true, - Default: booldefault.StaticBool(false), - }, - "omit_user_inputs": schema.BoolAttribute{ - MarkdownDescription: "Omit the user inputs when invoking the action", - Optional: true, - Computed: true, - Default: booldefault.StaticBool(false), }, - "report_workflow_status": schema.BoolAttribute{ + "report_workflow_status": schema.StringAttribute{ MarkdownDescription: "Report the workflow status when invoking the action", Optional: true, + Validators: StringBooleanOrJQTemplateValidator(), }, }, }, "gitlab_method": schema.SingleNestedAttribute{ - MarkdownDescription: "The invocation method of the action", + MarkdownDescription: "Gitlab invocation method", Optional: true, Attributes: map[string]schema.Attribute{ "project_name": schema.StringAttribute{ @@ -182,32 +224,18 @@ func ActionSchema() map[string]schema.Attribute { MarkdownDescription: "Required when selecting type GITLAB. The GitLab group name that the workflow belongs to", Required: true, }, - "omit_payload": schema.BoolAttribute{ - MarkdownDescription: "Omit the payload when invoking the action", - Optional: true, - Computed: true, - Default: booldefault.StaticBool(false), - }, - "omit_user_inputs": schema.BoolAttribute{ - MarkdownDescription: "Omit the user inputs when invoking the action", - Optional: true, - Computed: true, - Default: booldefault.StaticBool(false), - }, "default_ref": schema.StringAttribute{ MarkdownDescription: "The default ref of the action", Optional: true, }, - "agent": schema.BoolAttribute{ - MarkdownDescription: "Use the agent to invoke the action", + "pipeline_variables": schema.StringAttribute{ + MarkdownDescription: "The Gitlab pipeline variables (key-value object encoded to a string)", Optional: true, - Computed: true, - Default: booldefault.StaticBool(true), }, }, }, "azure_method": schema.SingleNestedAttribute{ - MarkdownDescription: "The invocation method of the action", + MarkdownDescription: "Azure DevOps invocation method", Optional: true, Attributes: map[string]schema.Attribute{ "org": schema.StringAttribute{ @@ -218,30 +246,48 @@ func ActionSchema() map[string]schema.Attribute { MarkdownDescription: "Required when selecting type AZURE. The Azure webhook that the workflow belongs to", Required: true, }, + "payload": schema.StringAttribute{ + MarkdownDescription: "The Azure Devops workflow payload (array or object encoded to a string)", + Optional: true, + }, }, }, - "order_properties": schema.ListAttribute{ - MarkdownDescription: "Order properties", + "required_approval": schema.BoolAttribute{ + MarkdownDescription: "Require approval before invoking the action", Optional: true, - ElementType: types.StringType, }, - "user_properties": schema.SingleNestedAttribute{ - MarkdownDescription: "User properties", + "approval_webhook_notification": schema.SingleNestedAttribute{ + MarkdownDescription: "The webhook notification of the approval", Optional: true, Attributes: map[string]schema.Attribute{ - "string_props": StringPropertySchema(), - "number_props": NumberPropertySchema(), - "boolean_props": BooleanPropertySchema(), - "object_props": ObjectPropertySchema(), - "array_props": ArrayPropertySchema(), + "url": schema.StringAttribute{ + MarkdownDescription: "The URL to invoke the webhook", + Required: true, + }, + "format": schema.StringAttribute{ + MarkdownDescription: "The format to invoke the webhook", + Optional: true, + Validators: []validator.String{ + stringvalidator.OneOf("json", "slack"), + }, + }, + }, + }, + "approval_email_notification": schema.ObjectAttribute{ + MarkdownDescription: "The email notification of the approval", + Optional: true, + AttributeTypes: map[string]attr.Type{}, + Validators: []validator.Object{ + objectvalidator.ConflictsWith(path.MatchRoot("approval_webhook_notification")), }, }, - "required_jq_query": schema.StringAttribute{ - MarkdownDescription: "The required jq query of the property", + "publish": schema.BoolAttribute{ + MarkdownDescription: "Publish action", Optional: true, + Computed: true, + Default: booldefault.StaticBool(true), }, } - } func StringPropertySchema() schema.Attribute { @@ -646,7 +692,7 @@ func ArrayPropertySchema() schema.Attribute { func (r *ActionResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { resp.Schema = schema.Schema{ - MarkdownDescription: actionResourceMarkdownDescription, + MarkdownDescription: ResourceMarkdownDescription, Attributes: ActionSchema(), } } @@ -668,381 +714,256 @@ func validateUserInputRequiredNotSetToFalse(ctx context.Context, state *ActionVa // supported anymore const errorString = "required is set to false, this is not supported anymore, if you don't want to make the stringProp required, remove the required stringProp" - if state.UserProperties.IsNull() { + if state.SelfServiceTrigger.IsNull() { return } - var userProperties = state.UserProperties.Attributes() - if userProperties != nil { - var stringProperties, _ = userProperties["string_props"] + var sst = state.SelfServiceTrigger.Attributes() + if sst == nil { + return + } - if stringProperties != nil { - var val, err = stringProperties.ToTerraformValue(ctx) - if err != nil { - return - } + var up, _ = sst["user_properties"] + if up == nil { + return + } - v := map[string]tftypes.Value{} + var val, err = up.ToTerraformValue(ctx) + if err != nil { + return + } - err = val.As(&v) - if err != nil { - return - } + userProperties := map[string]tftypes.Value{} - stringPropValidationsObjects := make(map[string]StringPropValidationModel, len(v)) - for key := range v { - var val StringPropValidationModel - err = v[key].As(&val) + err = val.As(&userProperties) + if err != nil { + return + } - if err != nil { - return - } + var stringProperties, _ = userProperties["string_props"] - stringPropValidationsObjects[key] = val - } + if !stringProperties.IsNull() { + v := map[string]tftypes.Value{} - for _, stringProp := range stringPropValidationsObjects { - if stringProp.Required != nil && !*stringProp.Required { - resp.Diagnostics.AddError(errorString, fmt.Sprint(`Error in User Property: `, stringProp.Title, ` in action: `, state.Identifier)) - } - } + err = val.As(&v) + if err != nil { + return } - var numberProperties, _ = userProperties["number_props"] + stringPropValidationsObjects := make(map[string]StringPropValidationModel, len(v)) + for key := range v { + var val StringPropValidationModel + err = v[key].As(&val) - if numberProperties != nil { - var val, err = numberProperties.ToTerraformValue(ctx) if err != nil { return } - v := map[string]tftypes.Value{} + stringPropValidationsObjects[key] = val + } - err = val.As(&v) - if err != nil { - return + for _, stringProp := range stringPropValidationsObjects { + if stringProp.Required != nil && !*stringProp.Required { + resp.Diagnostics.AddError(errorString, fmt.Sprint(`Error in User Property: `, stringProp.Title, ` in action: `, state.Identifier)) } + } + } - numberPropValidationsObjects := make(map[string]NumberPropValidationModel, len(v)) - for key := range v { - var val NumberPropValidationModel - err = v[key].As(&val) + var numberProperties, _ = userProperties["number_props"] - if err != nil { - return - } + if !numberProperties.IsNull() { + v := map[string]tftypes.Value{} - numberPropValidationsObjects[key] = val - } - - for _, numberProp := range numberPropValidationsObjects { - if numberProp.Required != nil && !*numberProp.Required { - resp.Diagnostics.AddError(errorString, fmt.Sprint(`Error in User Property: `, numberProp.Title, ` in action: `, state.Identifier)) - } - } + err = val.As(&v) + if err != nil { + return } - var booleanProperties, _ = userProperties["boolean_props"] + numberPropValidationsObjects := make(map[string]NumberPropValidationModel, len(v)) + for key := range v { + var val NumberPropValidationModel + err = v[key].As(&val) - if booleanProperties != nil { - var val, err = booleanProperties.ToTerraformValue(ctx) if err != nil { return } - v := map[string]tftypes.Value{} + numberPropValidationsObjects[key] = val + } - err = val.As(&v) - if err != nil { - return + for _, numberProp := range numberPropValidationsObjects { + if numberProp.Required != nil && !*numberProp.Required { + resp.Diagnostics.AddError(errorString, fmt.Sprint(`Error in User Property: `, numberProp.Title, ` in action: `, state.Identifier)) } + } + } - booleanPropValidationsObjects := make(map[string]BooleanPropValidationModel, len(v)) - for key := range v { - var val BooleanPropValidationModel - err = v[key].As(&val) - - if err != nil { - return - } + var booleanProperties, _ = userProperties["boolean_props"] - booleanPropValidationsObjects[key] = val - } + if !booleanProperties.IsNull() { + v := map[string]tftypes.Value{} - for _, booleanProp := range booleanPropValidationsObjects { - if booleanProp.Required != nil && !*booleanProp.Required { - resp.Diagnostics.AddError(errorString, fmt.Sprint(`Error in User Property: `, booleanProp.Title, ` in action: `, state.Identifier)) - } - } + err = val.As(&v) + if err != nil { + return } - var objectProperties, _ = userProperties["object_props"] + booleanPropValidationsObjects := make(map[string]BooleanPropValidationModel, len(v)) + for key := range v { + var val BooleanPropValidationModel + err = v[key].As(&val) - if objectProperties != nil { - var val, err = objectProperties.ToTerraformValue(ctx) if err != nil { return } - v := map[string]tftypes.Value{} + booleanPropValidationsObjects[key] = val + } - err = val.As(&v) - if err != nil { - return + for _, booleanProp := range booleanPropValidationsObjects { + if booleanProp.Required != nil && !*booleanProp.Required { + resp.Diagnostics.AddError(errorString, fmt.Sprint(`Error in User Property: `, booleanProp.Title, ` in action: `, state.Identifier)) } + } + } - objectPropValidationsObjects := make(map[string]ObjectPropValidationModel, len(v)) - for key := range v { - var val ObjectPropValidationModel - err = v[key].As(&val) - - if err != nil { - return - } + var objectProperties, _ = userProperties["object_props"] - objectPropValidationsObjects[key] = val - } + if !objectProperties.IsNull() { + v := map[string]tftypes.Value{} - for _, objectProp := range objectPropValidationsObjects { - if objectProp.Required != nil && !*objectProp.Required { - resp.Diagnostics.AddError(errorString, fmt.Sprint(`Error in User Property: `, objectProp.Title, ` in action: `, state.Identifier)) - } - } + err = val.As(&v) + if err != nil { + return } - var arrayProperties, _ = userProperties["array_props"] - - if arrayProperties != nil { - var val, err = arrayProperties.ToTerraformValue(ctx) - if err != nil { - return - } + objectPropValidationsObjects := make(map[string]ObjectPropValidationModel, len(v)) + for key := range v { + var val ObjectPropValidationModel + err = v[key].As(&val) - v := map[string]tftypes.Value{} - - err = val.As(&v) if err != nil { return } - arrayPropValidationsObjects := make(map[string]ArrayPropValidationModel, len(v)) - for key := range v { - var val ArrayPropValidationModel - err = v[key].As(&val) - - if err != nil { - return - } - - arrayPropValidationsObjects[key] = val - } + objectPropValidationsObjects[key] = val + } - for _, arrayProp := range arrayPropValidationsObjects { - if arrayProp.Required != nil && !*arrayProp.Required { - resp.Diagnostics.AddError(errorString, fmt.Sprint(`Error in User Property: `, arrayProp.Title, ` in action: `, state.Identifier)) - } + for _, objectProp := range objectPropValidationsObjects { + if objectProp.Required != nil && !*objectProp.Required { + resp.Diagnostics.AddError(errorString, fmt.Sprint(`Error in User Property: `, objectProp.Title, ` in action: `, state.Identifier)) } } } -} - -var actionResourceMarkdownDescription = ` - -# Action - -This resource allows you to manage self-service action. - -See the [Port documentation](https://docs.getport.io/create-self-service-experiences/) for more information about self-service actions. - -## Example Usage - -Create a blueprint and an action relating to that blueprint which triggers a github workflow: - -` + "```hcl" + ` - -resource "port_blueprint" "myBlueprint" { - icon = "Terraform" - identifier = "myBlueprint" - title = "My Blueprint" - properties = { - number_props = { - "numberProp" = { - title = "Number Property" - required = false - } - } - } -} -resource "port_action" "myAction" { - title = "My Action" - blueprint = port_blueprint.myBlueprint.identifier - identifier = "myAction" - trigger = "CREATE" - required_approval = false - github_method = { - org = "your-org" - repo = "your-repo" - workflow = "your-workflow" - } - user_properties = { - string_props = { - stringValue = { - title = "String Value" - } - } - number_props = { - "numberProp" = { - title = "Number Value" - required = true - } - } - } -} - -` + "```" + ` + var arrayProperties, _ = userProperties["array_props"] -Create related "parent" and "child" blueprints and a CREATE action for the child blueprint with user inputs to select entities from the parent blueprint and triggers a github workflow: + if !arrayProperties.IsNull() { + v := map[string]tftypes.Value{} -` + "```hcl" + ` + err = val.As(&v) + if err != nil { + return + } + arrayPropValidationsObjects := make(map[string]ArrayPropValidationModel, len(v)) + for key := range v { + var val ArrayPropValidationModel + err = v[key].As(&val) -resource "port_blueprint" "parent" { - icon = "Terraform" - title = "Parent" - identifier = "parent" - properties = {} -} + if err != nil { + return + } -resource "port_blueprint" "child" { - icon = "Terraform" - title = "Child" - identifier = "child" - properties = {} - relations = { - "childOf" = { - title = "Child Of" - many = true - required = false - target = port_blueprint.parent.identifier - } - } -} + arrayPropValidationsObjects[key] = val + } -resource "port_action" "myAction" { - title = "My Action" - blueprint = port_blueprint.child.identifier - identifier = "myAction" - trigger = "CREATE" - required_approval = false - github_method = { - org = "your-org" - repo = "your-repo" - workflow = "your-workflow" - } - user_properties = { - string_props = { - singleParent = { - title = "Single Parent Entity Selection" - format = "entity" - blueprint = port_blueprint.parent.identifier - } - } - array_props = { - miltipleParents = { - title = "Single Parent Entity Selection" - string_items = { - format = "entity" - blueprint = port_blueprint.parent.identifier + for _, arrayProp := range arrayPropValidationsObjects { + if arrayProp.Required != nil && !*arrayProp.Required { + resp.Diagnostics.AddError(errorString, fmt.Sprint(`Error in User Property: `, arrayProp.Title, ` in action: `, state.Identifier)) + } } - } } - } } -` + "```" + ` - - -Create the same resources as in the previous example, but the action's entity selection properties will only allow entities which pass the ` + "`dataset`s" + `: +var ResourceMarkdownDescription = ` -` + "```hcl" + ` +# Action resource -resource "port_blueprint" "parent" { - icon = "Terraform" - title = "Parent" - identifier = "parent" - properties = {} -} +Docs for the Action resource can be found [here](https://docs.getport.io/create-self-service-experiences/). -resource "port_blueprint" "child" { - icon = "Terraform" - title = "Child" - identifier = "child" - properties = {} - relations = { - "childOf" = { - title = "Child Of" - many = true - required = false - target = port_blueprint.parent.identifier - } - } -} +## Example Usage -resource "port_action" "myAction" { - title = "My Action" - blueprint = port_blueprint.child.identifier - identifier = "myAction" - trigger = "CREATE" - required_approval = false - github_method = { - org = "your-org" - repo = "your-repo" - workflow = "your-workflow" - omit_payload = true - omit_user_inputs = true - report_workflow_status = true - } - user_properties = { - string_props = { - singleParent = { - title = "Single Parent Entity Selection" - format = "entity" - blueprint = port_blueprint.parent.identifier - dataset = { - combinator = "and" - rules = [{ - property = "$title" - operator = "contains" - value = { - jq_query = "\"specificValue\"" +` + "```hcl" + ` +resource "port_action" "create_microservice" { + title = "Create Microservice" + identifier = "create-microservice" + icon = "Terraform" + self_service_trigger = { + operation = "CREATE" + blueprint_identifier = port_blueprint.microservice.identifier + user_properties = { + string_props = { + myStringIdentifier = { + title = "My String Identifier" + required = true + format = "entity" + blueprint = port_blueprint.parent.identifier + dataset = { + combinator = "and" + rules = [{ + property = "$title" + operator = "contains" + value = { + jq_query = "\"specificValue\"" + } + }] + } + } + } + number_props = { + myNumberIdentifier = { + title = "My Number Identifier" + required = true + maximum = 100 + minimum = 0 + } + } + boolean_props = { + myBooleanIdentifier = { + title = "My Boolean Identifier" + required = true + } + } + object_props = { + myObjectIdentifier = { + title = "My Object Identifier" + required = true + } + } + array_props = { + myArrayIdentifier = { + title = "My Array Identifier" + required = true + string_items = { + format = "entity" + blueprint = port_blueprint.parent.identifier + dataset = jsonencode({ + combinator = "and" + rules = [{ + property = "$title" + operator = "contains" + value = "specificValue" + }] + }) + } + } } - }] } - } } - array_props = { - miltipleParents = { - title = "Single Parent Entity Selection" - string_items = { - format = "entity" - blueprint = port_blueprint.parent.identifier - dataset = jsonencode({ - combinator = "and" - rules = [{ - property = "$title" - operator = "contains" - value = "specificValue" - }] - }) - } - } + kafka_method = { + payload = jsonencode({ + runId: "{{"{{.run.id}}"}}" + }) } - } -} - -` + "```" + ` - - - -` +}` + "\n```" diff --git a/port/action/string.go b/port/action/string.go index dd7442d1..bdca3bec 100644 --- a/port/action/string.go +++ b/port/action/string.go @@ -12,7 +12,7 @@ import ( "github.com/port-labs/terraform-provider-port-labs/internal/utils" ) -func stringPropResourceToBody(ctx context.Context, d *ActionModel, props map[string]cli.ActionProperty, required *[]string) error { +func stringPropResourceToBody(ctx context.Context, d *SelfServiceTriggerModel, props map[string]cli.ActionProperty, required *[]string) error { for propIdentifier, prop := range d.UserProperties.StringProps { property := cli.ActionProperty{ Type: "string",