Skip to content

Commit

Permalink
Feature/add trigger patterns (#502)
Browse files Browse the repository at this point in the history
* Add trigger-patterns to data source
* Use client to create workspace in order to test datasource
* Update go-tfe version
* Update documentation
* Add Changelog entry
  • Loading branch information
matejrisek committed Jul 8, 2022
1 parent 664b9d0 commit 33de91d
Show file tree
Hide file tree
Showing 7 changed files with 328 additions and 17 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -2,6 +2,7 @@

FEATURES:
* **New Resource**: `tfe_workspace_variable_set` ([#537](https://github.com/hashicorp/terraform-provider-tfe/pull/537)) adds the ability to assign a variable set to a workspace in a single, flexible resource.
* r/tfe_workspace, d/tfe_workspace: `trigger-patterns` ([#502](https://github.com/hashicorp/terraform-provider-tfe/pull/502)) attribute is introduced to support specifying a set of [glob patterns](https://www.terraform.io/cloud-docs/workspaces/settings/vcs#glob-patterns-for-automatic-run-triggering) for automatic VCS run triggering.

DEPRECATION NOTICE: The `workspace_ids` argument on `tfe_variable_set` has been labelled as deprecated and should not be used in conjunction with `tfe_workspace_variable_set`.

Expand Down
7 changes: 7 additions & 0 deletions tfe/data_source_workspace.go
Expand Up @@ -117,6 +117,12 @@ func dataSourceTFEWorkspace() *schema.Resource {
Elem: &schema.Schema{Type: schema.TypeString},
},

"trigger_patterns": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Schema{Type: schema.TypeString},
},

"working_directory": {
Type: schema.TypeString,
Computed: true,
Expand Down Expand Up @@ -183,6 +189,7 @@ func dataSourceTFEWorkspaceRead(d *schema.ResourceData, meta interface{}) error
d.Set("structured_run_output_enabled", workspace.StructuredRunOutputEnabled)
d.Set("terraform_version", workspace.TerraformVersion)
d.Set("trigger_prefixes", workspace.TriggerPrefixes)
d.Set("trigger_patterns", workspace.TriggerPatterns)
d.Set("working_directory", workspace.WorkingDirectory)

// Set remote_state_consumer_ids if global_remote_state is false
Expand Down
80 changes: 78 additions & 2 deletions tfe/data_source_workspace_test.go
Expand Up @@ -2,6 +2,7 @@ package tfe

import (
"fmt"
"github.com/hashicorp/go-tfe"
"math/rand"
"strconv"
"testing"
Expand Down Expand Up @@ -112,6 +113,51 @@ func TestAccTFEWorkspaceDataSource_basic(t *testing.T) {
})
}

func TestAccTFEWorkspaceDataSourceWithTriggerPatterns(t *testing.T) {
tfeClient, err := getClientUsingEnv()
if err != nil {
t.Fatalf("error getting client %v", err)
}
rInt := rand.New(rand.NewSource(time.Now().UnixNano())).Int()
organization, orgCleanup := givenOrganization(t, tfeClient, fmt.Sprintf("tst-terraform-%d-ff-on", rInt))
defer orgCleanup()

workspaceName := fmt.Sprintf("workspace-%d", rInt)
_, err = tfeClient.Workspaces.Create(ctx, organization.Name, tfe.WorkspaceCreateOptions{
Name: &workspaceName,
FileTriggersEnabled: tfe.Bool(true),
TriggerPatterns: []string{"/modules/**/*", "/**/networking/*"},
})
if err != nil {
t.Fatal(err)
}

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
{
Config: testAccTFEWorkspaceDataSourceConfigWithTriggerPatterns(workspaceName, organization.Name),
Check: resource.ComposeAggregateTestCheckFunc(
resource.TestCheckResourceAttrSet("data.tfe_workspace.foobar", "id"),
resource.TestCheckResourceAttr(
"data.tfe_workspace.foobar", "name", workspaceName),
resource.TestCheckResourceAttr(
"data.tfe_workspace.foobar", "organization", organization.Name),
resource.TestCheckResourceAttr(
"data.tfe_workspace.foobar", "file_triggers_enabled", "true"),
resource.TestCheckResourceAttr(
"data.tfe_workspace.foobar", "trigger_patterns.#", "2"),
resource.TestCheckResourceAttr(
"data.tfe_workspace.foobar", "trigger_patterns.0", "/modules/**/*"),
resource.TestCheckResourceAttr(
"data.tfe_workspace.foobar", "trigger_patterns.1", "/**/networking/*"),
),
},
},
})
}

func testAccTFEWorkspaceDataSourceConfig(rInt int) string {
return fmt.Sprintf(`
resource "tfe_organization" "foobar" {
Expand All @@ -132,16 +178,24 @@ resource "tfe_workspace" "foobar" {
terraform_version = "0.11.1"
trigger_prefixes = ["/modules", "/shared"]
working_directory = "terraform/test"
global_remote_state = true
global_remote_state = true
}
data "tfe_workspace" "foobar" {
name = tfe_workspace.foobar.name
organization = tfe_workspace.foobar.organization
depends_on = [tfe_workspace.foobar]
depends_on = [tfe_workspace.foobar]
}`, rInt, rInt)
}

func testAccTFEWorkspaceDataSourceConfigWithTriggerPatterns(workspaceName string, organizationName string) string {
return fmt.Sprintf(`
data "tfe_workspace" "foobar" {
name = "%s"
organization = "%s"
}`, workspaceName, organizationName)
}

func testAccTFEWorkspaceDataSourceConfig_remoteStateConsumers(rInt1, rInt2 int) string {
return fmt.Sprintf(`
resource "tfe_organization" "foobar" {
Expand All @@ -167,3 +221,25 @@ data "tfe_workspace" "foobar" {
depends_on = [tfe_workspace.foobar]
}`, rInt1, rInt2, rInt1)
}

func givenOrganization(t *testing.T, tfeClient *tfe.Client, organizationName string) (*tfe.Organization, func()) {
var orgCleanup func()

dummyEmail := "test@test.test"
org, err := tfeClient.Organizations.Create(ctx, tfe.OrganizationCreateOptions{
Name: tfe.String(organizationName),
Email: &dummyEmail,
})
if err != nil {
t.Fatal(err)
}
orgCleanup = func() {
if err := tfeClient.Organizations.Delete(ctx, org.Name); err != nil {
t.Errorf("Error destroying organization! WARNING: Dangling resources\n"+
"may exist! The full error is shown below.\n\n"+
"Organization: %s\nError: %s", org.Name, err)
}
}

return org, orgCleanup
}
56 changes: 46 additions & 10 deletions tfe/resource_tfe_workspace.go
Expand Up @@ -44,6 +44,8 @@ func resourceTFEWorkspace() *schema.Resource {
return err
}

validateVcsTriggers(d)

return nil
},

Expand Down Expand Up @@ -161,10 +163,19 @@ func resourceTFEWorkspace() *schema.Resource {
},

"trigger_prefixes": {
Type: schema.TypeList,
Optional: true,
Computed: true,
Elem: &schema.Schema{Type: schema.TypeString},
Type: schema.TypeList,
Optional: true,
Computed: true,
Elem: &schema.Schema{Type: schema.TypeString},
ConflictsWith: []string{"trigger_patterns"},
},

"trigger_patterns": {
Type: schema.TypeList,
Optional: true,
Computed: true,
Elem: &schema.Schema{Type: schema.TypeString},
ConflictsWith: []string{"trigger_prefixes"},
},

"working_directory": {
Expand Down Expand Up @@ -252,10 +263,18 @@ func resourceTFEWorkspaceCreate(d *schema.ResourceData, meta interface{}) error

if tps, ok := d.GetOk("trigger_prefixes"); ok {
for _, tp := range tps.([]interface{}) {
if t, ok := tp.(string); ok {
options.TriggerPrefixes = append(options.TriggerPrefixes, t)
}
options.TriggerPrefixes = append(options.TriggerPrefixes, tp.(string))
}
} else {
options.TriggerPrefixes = []string{}
}

if tps, ok := d.GetOk("trigger_patterns"); ok {
for _, tp := range tps.([]interface{}) {
options.TriggerPatterns = append(options.TriggerPatterns, tp.(string))
}
} else {
options.TriggerPatterns = []string{}
}

// Get and assert the VCS repo configuration block.
Expand Down Expand Up @@ -345,6 +364,7 @@ func resourceTFEWorkspaceRead(d *schema.ResourceData, meta interface{}) error {
d.Set("structured_run_output_enabled", workspace.StructuredRunOutputEnabled)
d.Set("terraform_version", workspace.TerraformVersion)
d.Set("trigger_prefixes", workspace.TriggerPrefixes)
d.Set("trigger_patterns", workspace.TriggerPatterns)
d.Set("working_directory", workspace.WorkingDirectory)
d.Set("organization", workspace.Organization.Name)

Expand Down Expand Up @@ -400,8 +420,9 @@ func resourceTFEWorkspaceUpdate(d *schema.ResourceData, meta interface{}) error
id := d.Id()

if d.HasChange("name") || d.HasChange("auto_apply") || d.HasChange("queue_all_runs") ||
d.HasChange("terraform_version") || d.HasChange("working_directory") || d.HasChange("vcs_repo") ||
d.HasChange("file_triggers_enabled") || d.HasChange("trigger_prefixes") ||
d.HasChange("terraform_version") || d.HasChange("working_directory") ||
d.HasChange("vcs_repo") || d.HasChange("file_triggers_enabled") ||
d.HasChange("trigger_prefixes") || d.HasChange("trigger_patterns") ||
d.HasChange("allow_destroy_plan") || d.HasChange("speculative_enabled") ||
d.HasChange("operations") || d.HasChange("execution_mode") ||
d.HasChange("description") || d.HasChange("agent_pool_id") ||
Expand Down Expand Up @@ -450,10 +471,17 @@ func resourceTFEWorkspaceUpdate(d *schema.ResourceData, meta interface{}) error
}
}
} else {
// Reset trigger prefixes when none are present in the config.
options.TriggerPrefixes = []string{}
}

if tps, ok := d.GetOk("trigger_patterns"); ok {
for _, tp := range tps.([]interface{}) {
options.TriggerPatterns = append(options.TriggerPatterns, tp.(string))
}
} else {
options.TriggerPatterns = []string{}
}

if workingDir, ok := d.GetOk("working_directory"); ok {
options.WorkingDirectory = tfe.String(workingDir.(string))
}
Expand Down Expand Up @@ -655,6 +683,14 @@ func validateRemoteState(_ context.Context, d *schema.ResourceDiff) error {
return nil
}

func validateVcsTriggers(d *schema.ResourceDiff) {
if d.HasChange("trigger_patterns") {
d.SetNewComputed("trigger_prefixes")
} else if d.HasChange("trigger_prefixes") {
d.SetNewComputed("trigger_patterns")
}
}

func resourceTFEWorkspaceImporter(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) {
tfeClient := meta.(*tfe.Client)

Expand Down

0 comments on commit 33de91d

Please sign in to comment.