Skip to content

Commit

Permalink
Merge pull request #916 from hashicorp/filtering-run-by-date
Browse files Browse the repository at this point in the history
Add CreatedBefore and CreatedAfter Filters for `AdminRunsListOptions`
  • Loading branch information
Maed223 authored Jun 18, 2024
2 parents d981486 + 6128458 commit 45ad9da
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 2 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

* Adds the `IsUnified` field to `Project`, `Organization` and `Team` by @roncodingenthusiast [#915](https://github.com/hashicorp/go-tfe/pull/915)
* Adds Workspace auto-destroy notification types to `NotificationTriggerType` by @notchairmk [#918](https://github.com/hashicorp/go-tfe/pull/918)
* Adds `CreatedAfter` and `CreatedBefore` Date Time filters to `AdminRunsListOptions` by @maed223 [#916](https://github.com/hashicorp/go-tfe/pull/916)

# v1.56.0

Expand Down
28 changes: 26 additions & 2 deletions admin_run.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,10 @@ const (
type AdminRunsListOptions struct {
ListOptions

RunStatus string `url:"filter[status],omitempty"`
Query string `url:"q,omitempty"`
RunStatus string `url:"filter[status],omitempty"`
CreatedBefore string `url:"filter[to],omitempty"`
CreatedAfter string `url:"filter[from],omitempty"`
Query string `url:"q,omitempty"`
// Optional: A list of relations to include. See available resources
// https://developer.hashicorp.com/terraform/enterprise/api-docs/admin/runs#available-related-resources
Include []AdminRunIncludeOpt `url:"include,omitempty"`
Expand Down Expand Up @@ -123,13 +125,35 @@ func (o *AdminRunsListOptions) valid() error {
return nil
}

if err := validateAdminRunDateRanges(o.CreatedBefore, o.CreatedAfter); err != nil {
return err
}

if err := validateAdminRunFilterParams(o.RunStatus); err != nil {
return err
}

return nil
}

func validateAdminRunDateRanges(before, after string) error {
if validString(&before) {
_, err := time.Parse(time.RFC3339, before)
if err != nil {
return fmt.Errorf("invalid date format for CreatedBefore: '%s', must be in RFC3339 format", before)
}
}

if validString(&after) {
_, err := time.Parse(time.RFC3339, after)
if err != nil {
return fmt.Errorf("invalid date format for CreatedAfter: '%s', must be in RFC3339 format", after)
}
}

return nil
}

func validateAdminRunFilterParams(runStatus string) error {
// For the platform, an invalid filter value is a semantically understood query that returns an empty set, no error, no warning. But for go-tfe, an invalid value is good enough reason to error prior to a network call to the platform:
if validString(&runStatus) {
Expand Down
54 changes: 54 additions & 0 deletions admin_run_integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,60 @@ func TestAdminRuns_ForceCancel(t *testing.T) {
})
}

func TestAdminRuns_ListFilterByDates(t *testing.T) {
skipUnlessEnterprise(t)

client := testClient(t)
ctx := context.Background()

org, orgCleanup := createOrganization(t, client)
defer orgCleanup()

wTest, wTestCleanup := createWorkspace(t, client, org)
defer wTestCleanup()

timestamp1 := time.Now().Format(time.RFC3339)
rTest1, rCleanup1 := createRun(t, client, wTest)
defer rCleanup1()

rTest2, rCleanup2 := createRun(t, client, wTest)
defer rCleanup2()
timestamp2 := time.Now().Format(time.RFC3339)

_, rCleanup3 := createRun(t, client, wTest)
defer rCleanup3()
timestamp3 := time.Now().Format(time.RFC3339)

t.Run("has valid date ranges", func(t *testing.T) {
rl, err := client.Admin.Runs.List(ctx, &AdminRunsListOptions{
CreatedAfter: timestamp1,
CreatedBefore: timestamp2,
})

require.NoError(t, err)
assert.Equal(t, 2, len(rl.Items))
assert.Equal(t, adminRunItemsContainsID(rl.Items, rTest1.ID), true)
assert.Equal(t, adminRunItemsContainsID(rl.Items, rTest2.ID), true)
})

t.Run("has no items when CreatedAfter and CreatedBefore datetimes has no overlap", func(t *testing.T) {
rl, err := client.Admin.Runs.List(ctx, &AdminRunsListOptions{
CreatedAfter: timestamp3,
CreatedBefore: timestamp2,
})

require.NoError(t, err)
assert.Equal(t, 0, len(rl.Items))
})

t.Run("errors with invalid input for CreatedAfter", func(t *testing.T) {
_, err := client.Admin.Runs.List(ctx, &AdminRunsListOptions{
CreatedAfter: "invalid",
})
assert.Error(t, err)
})
}

func TestAdminRuns_AdminRunsListOptions_valid(t *testing.T) {
skipUnlessEnterprise(t)

Expand Down

0 comments on commit 45ad9da

Please sign in to comment.