diff --git a/docs/resources/deployment_process.md b/docs/resources/deployment_process.md index db150de2e..837a86f97 100644 --- a/docs/resources/deployment_process.md +++ b/docs/resources/deployment_process.md @@ -208,6 +208,10 @@ Optional: - `worker_pool_id` (String) The worker pool associated with this deployment action. - `worker_pool_variable` (String) The worker pool variable associated with this deployment action. +Read-Only: + +- `slug` (String) The human-readable unique identifier for this resource. + ### Nested Schema for `step.action.action_template` @@ -317,6 +321,10 @@ Optional: - `worker_pool_id` (String) The worker pool associated with this deployment action. - `worker_pool_variable` (String) The worker pool variable associated with this deployment action. +Read-Only: + +- `slug` (String) The human-readable unique identifier for this resource. + ### Nested Schema for `step.apply_terraform_template_action.advanced_options` @@ -486,6 +494,10 @@ Optional: - `worker_pool_id` (String) The worker pool associated with this deployment action. - `worker_pool_variable` (String) The worker pool variable associated with this deployment action. +Read-Only: + +- `slug` (String) The human-readable unique identifier for this resource. + ### Nested Schema for `step.deploy_kubernetes_secret_action.action_template` @@ -569,6 +581,10 @@ Optional: - `tenant_tags` (List of String) A list of tenant tags associated with this resource. - `windows_service` (Block Set, Max: 1) Deploy a windows service feature (see [below for nested schema](#nestedblock--step--deploy_package_action--windows_service)) +Read-Only: + +- `slug` (String) The human-readable unique identifier for this resource. + ### Nested Schema for `step.deploy_package_action.primary_package` @@ -699,6 +715,10 @@ Optional: - `start_mode` (String) When will the service start. Can be auto, delayed-auto, manual, unchanged or an expression - `tenant_tags` (List of String) A list of tenant tags associated with this resource. +Read-Only: + +- `slug` (String) The human-readable unique identifier for this resource. + ### Nested Schema for `step.deploy_windows_service_action.primary_package` @@ -798,6 +818,10 @@ Optional: - `sort_order` (Number) Order used by terraform to ensure correct ordering of actions. This property must be either omitted from all actions, or provided on all actions - `tenant_tags` (List of String) A list of tenant tags associated with this resource. +Read-Only: + +- `slug` (String) The human-readable unique identifier for this resource. + ### Nested Schema for `step.manual_intervention_action.action_template` @@ -890,6 +914,10 @@ Optional: - `worker_pool_id` (String) The worker pool associated with this deployment action. - `worker_pool_variable` (String) The worker pool variable associated with this deployment action. +Read-Only: + +- `slug` (String) The human-readable unique identifier for this resource. + ### Nested Schema for `step.run_kubectl_script_action.action_template` @@ -998,6 +1026,10 @@ Optional: - `worker_pool_id` (String) The worker pool associated with this deployment action. - `worker_pool_variable` (String) The worker pool variable associated with this deployment action. +Read-Only: + +- `slug` (String) The human-readable unique identifier for this resource. + ### Nested Schema for `step.run_script_action.action_template` diff --git a/docs/resources/external_feed_create_release_trigger.md b/docs/resources/external_feed_create_release_trigger.md index e6b02d6c1..e45666b70 100644 --- a/docs/resources/external_feed_create_release_trigger.md +++ b/docs/resources/external_feed_create_release_trigger.md @@ -34,13 +34,14 @@ resource "octopusdeploy_external_feed_create_release_trigger" "my_trigger" { - `channel_id` (String) The ID of the channel in which the release will be created if the action type is CreateRelease. - `name` (String) The name of this resource. -- `package` (Block List, Min: 1) List of package references that will cause the trigger to fire. The triggering condition is if any of the packages are updated. (see [below for nested schema](#nestedblock--package)) - `project_id` (String) The ID of the project to attach the trigger. -- `space_id` (String) The space ID associated with the project to attach the trigger. ### Optional - `is_disabled` (Boolean) Disables the trigger from being run when set. +- `package` (Block List) List of referenced packages that will cause the trigger to fire. New versions of any of the packages you select will trigger release creation. (see [below for nested schema](#nestedblock--package)) +- `primary_package` (Block List) List of deployment actions for which the primary packages will cause the trigger to fire. New versions of any of the packages you select will trigger release creation. (see [below for nested schema](#nestedblock--primary_package)) +- `space_id` (String) The space ID associated with the project to attach the trigger. ### Read-Only @@ -49,11 +50,19 @@ resource "octopusdeploy_external_feed_create_release_trigger" "my_trigger" { ### Nested Schema for `package` -Optional: +Required: -- `deployment_action` (String) +- `deployment_action_slug` (String) - `package_reference` (String) + + +### Nested Schema for `primary_package` + +Required: + +- `deployment_action_slug` (String) + ## Import Import is supported using the following syntax: diff --git a/docs/resources/runbook_process.md b/docs/resources/runbook_process.md index a49235552..01a940899 100644 --- a/docs/resources/runbook_process.md +++ b/docs/resources/runbook_process.md @@ -86,6 +86,10 @@ Optional: - `worker_pool_id` (String) The worker pool associated with this deployment action. - `worker_pool_variable` (String) The worker pool variable associated with this deployment action. +Read-Only: + +- `slug` (String) The human-readable unique identifier for this resource. + ### Nested Schema for `step.action.action_template` @@ -195,6 +199,10 @@ Optional: - `worker_pool_id` (String) The worker pool associated with this deployment action. - `worker_pool_variable` (String) The worker pool variable associated with this deployment action. +Read-Only: + +- `slug` (String) The human-readable unique identifier for this resource. + ### Nested Schema for `step.apply_terraform_template_action.advanced_options` @@ -364,6 +372,10 @@ Optional: - `worker_pool_id` (String) The worker pool associated with this deployment action. - `worker_pool_variable` (String) The worker pool variable associated with this deployment action. +Read-Only: + +- `slug` (String) The human-readable unique identifier for this resource. + ### Nested Schema for `step.deploy_kubernetes_secret_action.action_template` @@ -447,6 +459,10 @@ Optional: - `tenant_tags` (List of String) A list of tenant tags associated with this resource. - `windows_service` (Block Set, Max: 1) Deploy a windows service feature (see [below for nested schema](#nestedblock--step--deploy_package_action--windows_service)) +Read-Only: + +- `slug` (String) The human-readable unique identifier for this resource. + ### Nested Schema for `step.deploy_package_action.primary_package` @@ -577,6 +593,10 @@ Optional: - `start_mode` (String) When will the service start. Can be auto, delayed-auto, manual, unchanged or an expression - `tenant_tags` (List of String) A list of tenant tags associated with this resource. +Read-Only: + +- `slug` (String) The human-readable unique identifier for this resource. + ### Nested Schema for `step.deploy_windows_service_action.primary_package` @@ -676,6 +696,10 @@ Optional: - `sort_order` (Number) Order used by terraform to ensure correct ordering of actions. This property must be either omitted from all actions, or provided on all actions - `tenant_tags` (List of String) A list of tenant tags associated with this resource. +Read-Only: + +- `slug` (String) The human-readable unique identifier for this resource. + ### Nested Schema for `step.manual_intervention_action.action_template` @@ -768,6 +792,10 @@ Optional: - `worker_pool_id` (String) The worker pool associated with this deployment action. - `worker_pool_variable` (String) The worker pool variable associated with this deployment action. +Read-Only: + +- `slug` (String) The human-readable unique identifier for this resource. + ### Nested Schema for `step.run_kubectl_script_action.action_template` @@ -876,6 +904,10 @@ Optional: - `worker_pool_id` (String) The worker pool associated with this deployment action. - `worker_pool_variable` (String) The worker pool variable associated with this deployment action. +Read-Only: + +- `slug` (String) The human-readable unique identifier for this resource. + ### Nested Schema for `step.run_script_action.action_template` @@ -944,5 +976,3 @@ Optional: - `id` (String) The unique ID for this resource. - `name` (String) The name of this resource. - `properties` (Map of String) A list of properties associated with this package. - - diff --git a/docs/resources/variable.md b/docs/resources/variable.md index 514743f1b..31c956c10 100644 --- a/docs/resources/variable.md +++ b/docs/resources/variable.md @@ -36,6 +36,14 @@ resource "octopusdeploy_variable" "google_cloud_account_variable" { value = "Accounts-123" } +# Create a UsernamePassword account variable +resource "octopusdeploy_variable" "usernamepassword_account_variable" { + owner_id = "Projects-123" + type = "UsernamePasswordAccount" + name = "UsernamePasswordVariable" + value = octopusdeploy_username_password_account.account_user_pass.id +} + # create a Certificate variable resource "octopusdeploy_variable" "certificate_variable" { owner_id = "Projects-123" @@ -88,7 +96,7 @@ resource "octopusdeploy_variable" "prompted_variable" { ### Required - `name` (String) The name of this resource. -- `type` (String) The type of variable represented by this resource. Valid types are `AmazonWebServicesAccount`, `AzureAccount`, `GoogleCloudAccount`, `Certificate`, `Sensitive`, `String`, or `WorkerPool`. +- `type` (String) The type of variable represented by this resource. Valid types are `AmazonWebServicesAccount`, `AzureAccount`, `GoogleCloudAccount`, `UsernamePasswordAccount`, `Certificate`, `Sensitive`, `String`, or `WorkerPool`. ### Optional diff --git a/examples/resources/octopusdeploy_variable/resource.tf b/examples/resources/octopusdeploy_variable/resource.tf index 57e70fef7..693e90d20 100644 --- a/examples/resources/octopusdeploy_variable/resource.tf +++ b/examples/resources/octopusdeploy_variable/resource.tf @@ -22,6 +22,14 @@ resource "octopusdeploy_variable" "google_cloud_account_variable" { value = "Accounts-123" } +# Create a UsernamePassword account variable +resource "octopusdeploy_variable" "usernamepassword_account_variable" { + owner_id = "Projects-123" + type = "UsernamePasswordAccount" + name = "UsernamePasswordVariable" + value = octopusdeploy_username_password_account.account_user_pass.id +} + # create a Certificate variable resource "octopusdeploy_variable" "certificate_variable" { owner_id = "Projects-123" diff --git a/go.mod b/go.mod index a2d773c0a..9d3587260 100644 --- a/go.mod +++ b/go.mod @@ -3,8 +3,8 @@ module github.com/OctopusDeploy/terraform-provider-octopusdeploy go 1.21 require ( - github.com/OctopusDeploy/go-octopusdeploy/v2 v2.40.3 - github.com/OctopusSolutionsEngineering/OctopusTerraformTestFramework v0.0.0-20240409225949-b27d14ff2bcb + github.com/OctopusDeploy/go-octopusdeploy/v2 v2.42.0 + github.com/OctopusSolutionsEngineering/OctopusTerraformTestFramework v0.0.0-20240502041300-f71244db277d github.com/google/uuid v1.6.0 github.com/gruntwork-io/terratest v0.41.11 github.com/hashicorp/go-cty v1.4.1-0.20200723130312-85980079f637 diff --git a/go.sum b/go.sum index e65a0f128..9e284d411 100644 --- a/go.sum +++ b/go.sum @@ -68,10 +68,10 @@ github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migc github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= github.com/Microsoft/hcsshim v0.11.4 h1:68vKo2VN8DE9AdN4tnkWnmdhqdbpUFM8OF3Airm7fz8= github.com/Microsoft/hcsshim v0.11.4/go.mod h1:smjE4dvqPX9Zldna+t5FG3rnoHhaB7QYxPRqGcpAD9w= -github.com/OctopusDeploy/go-octopusdeploy/v2 v2.40.3 h1:Gi3tlcwFJPQe9mmdIV0NcScnHGvOcTFcoM67L+dx6gE= -github.com/OctopusDeploy/go-octopusdeploy/v2 v2.40.3/go.mod h1:GZmFu6LmN8Yg0tEoZx3ytk9FnaH+84cWm7u5TdWZC6E= -github.com/OctopusSolutionsEngineering/OctopusTerraformTestFramework v0.0.0-20240409225949-b27d14ff2bcb h1:4Lzs6TsvSZkahw99VlIDP5aAihQiJZPoCQKTw1A9el4= -github.com/OctopusSolutionsEngineering/OctopusTerraformTestFramework v0.0.0-20240409225949-b27d14ff2bcb/go.mod h1:Nyg+7cyTrSQ/lMIy5YY1UdJekRuoMWf4uHIPfaGmgTM= +github.com/OctopusDeploy/go-octopusdeploy/v2 v2.42.0 h1:LZ8qWUHrUhnG1TLT0c38o2/22T0JspvO1zK7Ha+eXgs= +github.com/OctopusDeploy/go-octopusdeploy/v2 v2.42.0/go.mod h1:GZmFu6LmN8Yg0tEoZx3ytk9FnaH+84cWm7u5TdWZC6E= +github.com/OctopusSolutionsEngineering/OctopusTerraformTestFramework v0.0.0-20240502041300-f71244db277d h1:E0Rm52/XBlVzdkHET/+Js1FVVgf5/0oRk1tNkI4jcyk= +github.com/OctopusSolutionsEngineering/OctopusTerraformTestFramework v0.0.0-20240502041300-f71244db277d/go.mod h1:Nyg+7cyTrSQ/lMIy5YY1UdJekRuoMWf4uHIPfaGmgTM= github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7 h1:YoJbenK9C67SkzkDfmQuVln04ygHj3vjZfd9FL+GmQQ= github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo= github.com/acomagu/bufpipe v1.0.3 h1:fxAGrHZTgQ9w5QqVItgzwj235/uYZYgbXitB+dLupOk= diff --git a/integration_test.go b/integration_test.go index 79808fcfb..4a3ba30e0 100644 --- a/integration_test.go +++ b/integration_test.go @@ -3553,22 +3553,22 @@ func TestPackageFeedCreateReleaseTriggerResources(t *testing.T) { return err } - if len(project_triggers) != 2 { - t.Fatal("There must be exactly 2 project triggers") - } - tr1Name := "My first trigger" tr2Name := "My second trigger" + tr3Name := "My third trigger" tr1Index := stdslices.IndexFunc(project_triggers, func(t *triggers.ProjectTrigger) bool { return t.Name == tr1Name }) tr2Index := stdslices.IndexFunc(project_triggers, func(t *triggers.ProjectTrigger) bool { return t.Name == tr2Name }) + tr3Index := stdslices.IndexFunc(project_triggers, func(t *triggers.ProjectTrigger) bool { return t.Name == tr3Name }) - if tr1Index == -1 || tr2Index == -1 { - t.Fatalf("Unable to find both triggers. Expecting there to be \"%s\" and \"%s\".", tr1Name, tr2Name) + if tr1Index == -1 || tr2Index == -1 || tr3Index == -1 { + t.Fatalf("Unable to find all triggers. Expecting there to be \"%s\", \"%s\", and \"%s\".", tr1Name, tr2Name, tr3Name) } - if project_triggers[0].Filter.GetFilterType() != filters.FeedFilter || project_triggers[1].Filter.GetFilterType() != filters.FeedFilter { - t.Fatal("The project triggers must all be of \"FeedFilter\" type") + for _, triggerIndex := range []int{tr1Index, tr2Index, tr3Index} { + if project_triggers[triggerIndex].Filter.GetFilterType() != filters.FeedFilter { + t.Fatal("The project triggers must all be of \"FeedFilter\" type") + } } if project_triggers[tr1Index].IsDisabled { @@ -3579,8 +3579,13 @@ func TestPackageFeedCreateReleaseTriggerResources(t *testing.T) { t.Fatalf("The trigger \"%s\" should be disabled", tr2Name) } + if project_triggers[tr3Index].IsDisabled { + t.Fatalf("The trigger \"%s\" should not be disabled", tr3Name) + } + tr1Filter := project_triggers[tr1Index].Filter.(*filters.FeedTriggerFilter) tr2Filter := project_triggers[tr2Index].Filter.(*filters.FeedTriggerFilter) + tr3Filter := project_triggers[tr3Index].Filter.(*filters.FeedTriggerFilter) if len(tr1Filter.Packages) != 2 { t.Fatalf("The trigger \"%s\" should have 2 package references", tr1Name) @@ -3590,6 +3595,10 @@ func TestPackageFeedCreateReleaseTriggerResources(t *testing.T) { t.Fatalf("The trigger \"%s\" should have 1 package reference", tr2Name) } + if len(tr3Filter.Packages) != 3 { + t.Fatalf("The trigger \"%s\" should have 3 package reference", tr3Name) + } + return nil }) } diff --git a/octopusdeploy/resource_external_feed_create_release_trigger.go b/octopusdeploy/resource_external_feed_create_release_trigger.go index 28e01c6a4..8d998d08e 100644 --- a/octopusdeploy/resource_external_feed_create_release_trigger.go +++ b/octopusdeploy/resource_external_feed_create_release_trigger.go @@ -37,7 +37,12 @@ func buildExternalFeedCreateReleaseTriggerResource(d *schema.ResourceData, clien } flattenedPackages := d.Get("package") - packages := expandDeploymentActionPackages(flattenedPackages) + packages := expandDeploymentActionSlugPackages(flattenedPackages) + + flattenedPrimaryPackages := d.Get("primary_package") + primaryPackages := expandDeploymentActionSlugPrimaryPackages(flattenedPrimaryPackages) + + packages = append(packages, primaryPackages...) action := actions.NewCreateReleaseAction(channelId) filter := filters.NewFeedTriggerFilter(packages) @@ -95,7 +100,8 @@ func resourceExternalFeedCreateReleaseTriggerRead(ctx context.Context, d *schema d.Set("project_id", projectTrigger.ProjectID) d.Set("is_disabled", projectTrigger.IsDisabled) d.Set("channel_id", action.ChannelID) - d.Set("package", flattenDeploymentActionPackages(filter.Packages)) + d.Set("package", flattenDeploymentActionSlugPackages(filter.Packages)) + d.Set("primary_package", flattenDeploymentActionSlugPrimaryPackages(filter.Packages)) return nil } diff --git a/octopusdeploy/schema_deployment_action.go b/octopusdeploy/schema_deployment_action.go index 33ccea1a5..efe4e32bb 100644 --- a/octopusdeploy/schema_deployment_action.go +++ b/octopusdeploy/schema_deployment_action.go @@ -78,6 +78,10 @@ func flattenAction(action *deployments.DeploymentAction) map[string]interface{} flattenedAction["name"] = action.Name } + if len(action.Slug) > 0 { + flattenedAction["slug"] = action.Slug + } + if len(action.Notes) > 0 { flattenedAction["notes"] = action.Notes } @@ -257,6 +261,7 @@ func getActionSchema() (*schema.Schema, *schema.Resource) { Optional: true, Default: -1, }, + "slug": getSlugSchema(), "tenant_tags": getTenantTagsSchema(), }, } @@ -448,6 +453,10 @@ func expandAction(flattenedAction map[string]interface{}) *deployments.Deploymen action.Properties["Octopus.Action.RunOnServer"] = core.NewPropertyValue(cases.Title(language.Und, cases.NoLower).String(strconv.FormatBool(runOnServer)), false) } + if v, ok := flattenedAction["slug"]; ok { + action.Slug = v.(string) + } + if v, ok := flattenedAction["action_template"]; ok { templateList := v.(*schema.Set).List() if len(templateList) > 0 { diff --git a/octopusdeploy/schema_deployment_action_slug_package.go b/octopusdeploy/schema_deployment_action_slug_package.go new file mode 100644 index 000000000..9419b77a5 --- /dev/null +++ b/octopusdeploy/schema_deployment_action_slug_package.go @@ -0,0 +1,94 @@ +package octopusdeploy + +import ( + "github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/packages" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" +) + +func expandDeploymentActionSlugPackages(values interface{}) []packages.DeploymentActionSlugPackage { + if values == nil { + return nil + } + + actionPackages := []packages.DeploymentActionSlugPackage{} + for _, v := range values.([]interface{}) { + flattenedMap := v.(map[string]interface{}) + actionPackages = append(actionPackages, packages.DeploymentActionSlugPackage{ + DeploymentActionSlug: flattenedMap["deployment_action_slug"].(string), + PackageReference: flattenedMap["package_reference"].(string), + }) + } + return actionPackages +} + +func expandDeploymentActionSlugPrimaryPackages(values interface{}) []packages.DeploymentActionSlugPackage { + if values == nil { + return nil + } + + actionPackages := []packages.DeploymentActionSlugPackage{} + for _, v := range values.([]interface{}) { + flattenedMap := v.(map[string]interface{}) + actionPackages = append(actionPackages, packages.DeploymentActionSlugPackage{ + DeploymentActionSlug: flattenedMap["deployment_action_slug"].(string), + }) + } + return actionPackages +} + +func flattenDeploymentActionSlugPackages(deploymentActionSlugPackages []packages.DeploymentActionSlugPackage) []interface{} { + if len(deploymentActionSlugPackages) == 0 { + return nil + } + + flattenedDeploymentActionSlugPackages := []interface{}{} + for _, v := range deploymentActionSlugPackages { + if v.PackageReference != "" { + flattenedDeploymentActionSlugPackage := map[string]interface{}{ + "deployment_action_slug": v.DeploymentActionSlug, + "package_reference": v.PackageReference, + } + flattenedDeploymentActionSlugPackages = append(flattenedDeploymentActionSlugPackages, flattenedDeploymentActionSlugPackage) + } + } + return flattenedDeploymentActionSlugPackages +} + +func flattenDeploymentActionSlugPrimaryPackages(deploymentActionSlugPackages []packages.DeploymentActionSlugPackage) []interface{} { + if len(deploymentActionSlugPackages) == 0 { + return nil + } + + flattenedDeploymentActionSlugPackages := []interface{}{} + for _, v := range deploymentActionSlugPackages { + if v.PackageReference == "" { + flattenedDeploymentActionSlugPackage := map[string]interface{}{ + "deployment_action_slug": v.DeploymentActionSlug, + } + flattenedDeploymentActionSlugPackages = append(flattenedDeploymentActionSlugPackages, flattenedDeploymentActionSlugPackage) + } + } + return flattenedDeploymentActionSlugPackages +} + +func getDeploymentActionSlugPackageSchema() map[string]*schema.Schema { + return map[string]*schema.Schema{ + "deployment_action_slug": { + Required: true, + Type: schema.TypeString, + }, + "package_reference": { + Required: true, + Type: schema.TypeString, + }, + } +} + +func getDeploymentActionSlugPrimaryPackageSchema() map[string]*schema.Schema { + return map[string]*schema.Schema{ + "deployment_action_slug": { + Required: true, + Type: schema.TypeString, + }, + } +} diff --git a/octopusdeploy/schema_deployment_action_slug_package_test.go b/octopusdeploy/schema_deployment_action_slug_package_test.go new file mode 100644 index 000000000..37c26d145 --- /dev/null +++ b/octopusdeploy/schema_deployment_action_slug_package_test.go @@ -0,0 +1,161 @@ +package octopusdeploy + +import ( + "testing" + + "github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/packages" + "github.com/stretchr/testify/require" +) + +func TestExpandDeploymentActionSlugPackages_NilExpandsToNil(t *testing.T) { + actual := expandDeploymentActionSlugPackages(nil) + require.Nil(t, actual) +} + +func TestExpandDeploymentActionSlugPackages_EmptyExpandsToEmpty(t *testing.T) { + actual := expandDeploymentActionSlugPackages([]interface{}{}) + expected := []packages.DeploymentActionSlugPackage{} + require.Equal(t, expected, actual) +} + +func TestExpandDeploymentActionSlugPackages_ArrayExpandsCorrectly(t *testing.T) { + flattened := []interface{}{ + map[string]interface{}{ + "deployment_action_slug": "", + "package_reference": "", + }, + map[string]interface{}{ + "deployment_action_slug": "test-deployment_action", + "package_reference": "test-package_reference", + }, + } + expected := []packages.DeploymentActionSlugPackage{ + {DeploymentActionSlug: "", PackageReference: ""}, + {DeploymentActionSlug: "test-deployment_action", PackageReference: "test-package_reference"}, + } + actual := expandDeploymentActionSlugPackages(flattened) + require.Equal(t, expected, actual) +} + +func TestExpandDeploymentActionSlugPrimaryPackages_NilExpandsToNil(t *testing.T) { + actual := expandDeploymentActionSlugPrimaryPackages(nil) + require.Nil(t, actual) +} + +func TestExpandDeploymentActionSlugPrimaryPackages_EmptyExpandsToEmpty(t *testing.T) { + actual := expandDeploymentActionSlugPrimaryPackages([]interface{}{}) + expected := []packages.DeploymentActionSlugPackage{} + require.Equal(t, expected, actual) +} + +func TestExpandDeploymentActionSlugPrimaryPackages_ArrayExpandsCorrectly(t *testing.T) { + flattened := []interface{}{ + map[string]interface{}{ + "deployment_action_slug": "", + }, + map[string]interface{}{ + "deployment_action_slug": "test-deployment_action", + "package_reference": "should_be_ignored", + }, + } + expected := []packages.DeploymentActionSlugPackage{ + {DeploymentActionSlug: "", PackageReference: ""}, + {DeploymentActionSlug: "test-deployment_action", PackageReference: ""}, + } + actual := expandDeploymentActionSlugPrimaryPackages(flattened) + require.Equal(t, expected, actual) +} + +func TestFlattenDeploymentActionSlugPackages_NilFlattensToNil(t *testing.T) { + actual := flattenDeploymentActionSlugPackages(nil) + require.Nil(t, actual) +} + +func TestFlattenDeploymentActionSlugPackages_EmptyFlattensToNil(t *testing.T) { + actual := flattenDeploymentActionSlugPackages([]packages.DeploymentActionSlugPackage{}) + require.Nil(t, actual) +} + +func TestFlattenDeploymentActionSlugPackages_IgnoresPrimaryPackages_NoPackagesAfterFlattening(t *testing.T) { + expanded := []packages.DeploymentActionSlugPackage{ + { + DeploymentActionSlug: "action-one", + PackageReference: "", + }, + { + DeploymentActionSlug: "action-two", + PackageReference: "", + }, + } + actual := flattenDeploymentActionSlugPackages(expanded) + expected := []interface{}{} + require.Equal(t, expected, actual) +} + +func TestFlattenDeploymentActionSlugPackages_IgnoresPrimaryPackages_ArrayFlattensCorrectly(t *testing.T) { + expanded := getCommonExpandedPackages() + actual := flattenDeploymentActionSlugPackages(expanded) + expected := []interface{}{ + map[string]interface{}{ + "deployment_action_slug": "action-one", + "package_reference": "some-package", + }, + } + require.Equal(t, expected, actual) +} + +func TestFlattenDeploymentActionSlugPrimaryPackages_NilFlattensToNil(t *testing.T) { + actual := flattenDeploymentActionSlugPrimaryPackages(nil) + require.Nil(t, actual) +} + +func TestFlattenDeploymentActionSlugPrimaryPackages_EmptyFlattensToNil(t *testing.T) { + actual := flattenDeploymentActionSlugPrimaryPackages([]packages.DeploymentActionSlugPackage{}) + require.Nil(t, actual) +} + +func TestFlattenDeploymentActionSlugPrimaryPackages_IgnoresPackages_NoPrimaryPackagesAfterFlattening(t *testing.T) { + expanded := []packages.DeploymentActionSlugPackage{ + { + DeploymentActionSlug: "action-one", + PackageReference: "some-package", + }, + { + DeploymentActionSlug: "action-two", + PackageReference: "some-other-package", + }, + } + actual := flattenDeploymentActionSlugPrimaryPackages(expanded) + expected := []interface{}{} + require.Equal(t, expected, actual) +} + +func TestFlattenDeploymentActionSlugPrimaryPackages_IgnoresPackages_ArrayFlattensCorrectly(t *testing.T) { + expanded := getCommonExpandedPackages() + actual := flattenDeploymentActionSlugPrimaryPackages(expanded) + expected := []interface{}{ + map[string]interface{}{ + "deployment_action_slug": "action-two", + }, + map[string]interface{}{ + "deployment_action_slug": "action-three", + }, + } + require.Equal(t, expected, actual) +} + +func getCommonExpandedPackages() []packages.DeploymentActionSlugPackage { + return []packages.DeploymentActionSlugPackage{ + { + DeploymentActionSlug: "action-one", + PackageReference: "some-package", + }, + { + DeploymentActionSlug: "action-two", + PackageReference: "", + }, + { + DeploymentActionSlug: "action-three", + }, + } +} diff --git a/octopusdeploy/schema_external_feed_create_release_trigger.go b/octopusdeploy/schema_external_feed_create_release_trigger.go index d04f199ce..8bf072325 100644 --- a/octopusdeploy/schema_external_feed_create_release_trigger.go +++ b/octopusdeploy/schema_external_feed_create_release_trigger.go @@ -9,7 +9,7 @@ func getExternalFeedCreateReleaseTriggerSchema() map[string]*schema.Schema { return map[string]*schema.Schema{ "name": getNameSchema(true), "space_id": { - Required: true, + Optional: true, Description: "The space ID associated with the project to attach the trigger.", Type: schema.TypeString, ValidateDiagFunc: validation.ToDiagFunc(validation.StringIsNotWhiteSpace), @@ -27,10 +27,16 @@ func getExternalFeedCreateReleaseTriggerSchema() map[string]*schema.Schema { ValidateDiagFunc: validation.ToDiagFunc(validation.StringIsNotWhiteSpace), }, "package": { - Description: "List of package references that will cause the trigger to fire. The triggering condition is if any of the packages are updated.", - Required: true, + Description: "List of referenced packages that will cause the trigger to fire. New versions of any of the packages you select will trigger release creation.", + Optional: true, + Type: schema.TypeList, + Elem: &schema.Resource{Schema: getDeploymentActionSlugPackageSchema()}, + }, + "primary_package": { + Description: "List of deployment actions for which the primary packages will cause the trigger to fire. New versions of any of the packages you select will trigger release creation.", + Optional: true, Type: schema.TypeList, - Elem: &schema.Resource{Schema: getDeploymentActionPackageSchema()}, + Elem: &schema.Resource{Schema: getDeploymentActionSlugPrimaryPackageSchema()}, }, "is_disabled": { Description: "Disables the trigger from being run when set.", diff --git a/octopusdeploy/schema_utilities.go b/octopusdeploy/schema_utilities.go index 9950c656b..50294a90c 100644 --- a/octopusdeploy/schema_utilities.go +++ b/octopusdeploy/schema_utilities.go @@ -185,6 +185,14 @@ func getIDSchema() *schema.Schema { } } +func getSlugSchema() *schema.Schema { + return &schema.Schema{ + Computed: true, + Description: "The human-readable unique identifier for this resource.", + Type: schema.TypeString, + } +} + func getIsSensitiveSchema() *schema.Schema { return &schema.Schema{ Default: false, diff --git a/terraform/52-packagefeedcreatereleasetrigger/deployment_process.tf b/terraform/52-packagefeedcreatereleasetrigger/deployment_process.tf index 48b0aac30..be2e90124 100644 --- a/terraform/52-packagefeedcreatereleasetrigger/deployment_process.tf +++ b/terraform/52-packagefeedcreatereleasetrigger/deployment_process.tf @@ -65,4 +65,82 @@ resource "octopusdeploy_deployment_process" "example" { } } } + step { + condition = "Success" + name = "Helm one" + package_requirement = "LetOctopusDecide" + start_trigger = "StartAfterPrevious" + + action { + action_type = "Octopus.HelmChartUpgrade" + name = "Helm one" + condition = "Success" + run_on_server = true + is_disabled = false + can_be_used_for_project_versioning = true + is_required = false + worker_pool_id = "" + properties = { + "Octopus.Action.Helm.ClientVersion" = "V3" + "Octopus.Action.Helm.Namespace" = "dev" + "Octopus.Action.Package.DownloadOnTentacle" = "False" + "Octopus.Action.Helm.ResetValues" = "True" + } + environments = [] + excluded_environments = [] + channels = [] + tenant_tags = [] + + primary_package { + package_id = "redis" + acquisition_location = "Server" + feed_id = "${octopusdeploy_helm_feed.feed_helm_charts.id}" + properties = { SelectionMode = "immediate" } + } + + features = [] + } + + properties = {} + target_roles = ["k8s"] + } + step { + condition = "Success" + name = "Helm two" + package_requirement = "LetOctopusDecide" + start_trigger = "StartAfterPrevious" + + action { + action_type = "Octopus.HelmChartUpgrade" + name = "Helm two" + condition = "Success" + run_on_server = true + is_disabled = false + can_be_used_for_project_versioning = true + is_required = false + worker_pool_id = "" + properties = { + "Octopus.Action.Helm.ClientVersion" = "V3" + "Octopus.Action.Helm.Namespace" = "dev" + "Octopus.Action.Package.DownloadOnTentacle" = "False" + "Octopus.Action.Helm.ResetValues" = "True" + } + environments = [] + excluded_environments = [] + channels = [] + tenant_tags = [] + + primary_package { + package_id = "prometheus" + acquisition_location = "Server" + feed_id = "${octopusdeploy_helm_feed.feed_helm_charts.id}" + properties = { SelectionMode = "immediate" } + } + + features = [] + } + + properties = {} + target_roles = ["k8s"] + } } diff --git a/terraform/52-packagefeedcreatereleasetrigger/feed.tf b/terraform/52-packagefeedcreatereleasetrigger/feed.tf index bef8fdfeb..aae2d7f88 100644 --- a/terraform/52-packagefeedcreatereleasetrigger/feed.tf +++ b/terraform/52-packagefeedcreatereleasetrigger/feed.tf @@ -1,4 +1,10 @@ resource "octopusdeploy_docker_container_registry" "docker_feed" { feed_uri = "https://index.docker.io" name = "Test Docker Container Registry" -} \ No newline at end of file +} + +resource "octopusdeploy_helm_feed" "feed_helm_charts" { + name = "Test Helm Charts" + feed_uri = "https://charts.helm.sh/stable" + package_acquisition_location_options = ["ExecutionTarget", "NotAcquired"] +} diff --git a/terraform/52-packagefeedcreatereleasetrigger/project.tf b/terraform/52-packagefeedcreatereleasetrigger/project.tf index 494b9526c..3a62b322c 100644 --- a/terraform/52-packagefeedcreatereleasetrigger/project.tf +++ b/terraform/52-packagefeedcreatereleasetrigger/project.tf @@ -10,8 +10,22 @@ resource "octopusdeploy_project_group" "project_group_test" { description = "Test Description" } -resource "octopusdeploy_channel" "test_channel" { - name = "Test Channel" +resource "octopusdeploy_channel" "test_channel_1" { + name = "Test Channel 1" + project_id = "${octopusdeploy_project.deploy_frontend_project.id}" + space_id = var.octopus_space_id + lifecycle_id = data.octopusdeploy_lifecycles.lifecycle_default_lifecycle.lifecycles[0].id +} + +resource "octopusdeploy_channel" "test_channel_2" { + name = "Test Channel 2" + project_id = "${octopusdeploy_project.deploy_frontend_project.id}" + space_id = var.octopus_space_id + lifecycle_id = data.octopusdeploy_lifecycles.lifecycle_default_lifecycle.lifecycles[0].id +} + +resource "octopusdeploy_channel" "test_channel_3" { + name = "Test Channel 3" project_id = "${octopusdeploy_project.deploy_frontend_project.id}" space_id = var.octopus_space_id lifecycle_id = data.octopusdeploy_lifecycles.lifecycle_default_lifecycle.lifecycles[0].id diff --git a/terraform/52-packagefeedcreatereleasetrigger/project_triggers.tf b/terraform/52-packagefeedcreatereleasetrigger/project_triggers.tf index 50a98acb4..703d5e23d 100644 --- a/terraform/52-packagefeedcreatereleasetrigger/project_triggers.tf +++ b/terraform/52-packagefeedcreatereleasetrigger/project_triggers.tf @@ -3,14 +3,18 @@ resource "octopusdeploy_external_feed_create_release_trigger" "external_feed_tri space_id = var.octopus_space_id project_id = "${octopusdeploy_project.deploy_frontend_project.id}" package { - deployment_action = octopusdeploy_deployment_process.example.step[0].run_script_action[0].name + deployment_action_slug = octopusdeploy_deployment_process.example.step[0].run_script_action[0].slug package_reference = "busybox" } package { - deployment_action = octopusdeploy_deployment_process.example.step[0].run_script_action[0].name + deployment_action_slug = octopusdeploy_deployment_process.example.step[0].run_script_action[0].slug package_reference = "nginx" } - channel_id = octopusdeploy_channel.test_channel.id + channel_id = octopusdeploy_channel.test_channel_1.id + + depends_on = [ + octopusdeploy_deployment_process.example + ] } resource "octopusdeploy_external_feed_create_release_trigger" "external_feed_trigger_2" { @@ -19,8 +23,34 @@ resource "octopusdeploy_external_feed_create_release_trigger" "external_feed_tri project_id = "${octopusdeploy_project.deploy_frontend_project.id}" is_disabled = true package { - deployment_action = octopusdeploy_deployment_process.example.step[1].run_script_action[0].name + deployment_action_slug = octopusdeploy_deployment_process.example.step[1].run_script_action[0].slug package_reference = "scratch" } - channel_id = octopusdeploy_channel.test_channel.id + channel_id = octopusdeploy_channel.test_channel_2.id + + depends_on = [ + octopusdeploy_deployment_process.example + ] +} + +resource "octopusdeploy_external_feed_create_release_trigger" "external_feed_trigger_3" { + name = "My third trigger" + space_id = var.octopus_space_id + project_id = "${octopusdeploy_project.deploy_frontend_project.id}" + is_disabled = false + package { + deployment_action_slug = octopusdeploy_deployment_process.example.step[0].run_script_action[0].slug + package_reference = "busybox" + } + primary_package { + deployment_action_slug = octopusdeploy_deployment_process.example.step[2].action[0].slug + } + primary_package { + deployment_action_slug = octopusdeploy_deployment_process.example.step[3].action[0].slug + } + channel_id = octopusdeploy_channel.test_channel_3.id + + depends_on = [ + octopusdeploy_deployment_process.example + ] } \ No newline at end of file