Skip to content

Commit

Permalink
On call resources + pagination for user query (#151)
Browse files Browse the repository at this point in the history
* client: add pagination for user query

* on_call/strategy: allow custom schedule strategy

* Add start_time for custom strategy

* Simplify on-call schedule resource checks

* only filter if strategy was provided

* oncall: add test for custom strategy

* changelog: add custom on call scheduling strategy
  • Loading branch information
wilsonehusin authored Apr 12, 2024
1 parent aaeeb7c commit 22166fa
Show file tree
Hide file tree
Showing 6 changed files with 96 additions and 17 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
## 0.8.0

* `firehydrant_on_call_schedule` scheduling strategy now supports `custom` shift durations ([#151](https://github.com/firehydrant/terraform-provider-firehydrant/pull/151)).


## 0.7.1

* `firehydrant_runbook` now supports `restricted` field for private incidents runbook ([#149](https://github.com/firehydrant/terraform-provider-firehydrant/pull/149))
Expand Down
3 changes: 2 additions & 1 deletion docs/resources/on_call_schedule.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,10 @@ The following arguments are supported:

The `strategy` block supports:

* `type` - (Required) The type of strategy to use for the on-call schedule. Valid values are `weekly` and `daily`.
* `type` - (Required) The type of strategy to use for the on-call schedule. Valid values are `weekly`, `daily`, or `custom`.
* `handoff_time` - (Required) The time of day that the on-call schedule handoff occurs. Must be in `HH:MM:SS` format.
* `handoff_day` - (Required) The day of the week that the on-call schedule handoff occurs. Valid values are `sunday`, `monday`, `tuesday`, `wednesday`, `thursday`, `friday`, and `saturday`.
* `shift_duration` - (Optional) The duration of the on-call shift in ISO8601 format. Required for `custom` strategy.

The `restrictions` block supports:

Expand Down
10 changes: 7 additions & 3 deletions firehydrant/on_call_schedules.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@ var _ OnCallSchedules = &RESTOnCallSchedulesClient{}

type OnCallScheduleStrategy struct {
Type string `json:"type"`
HandoffTime string `json:"handoff_time"`
HandoffDay string `json:"handoff_day"`
ShiftDuration string `json:"shift_duration"`
HandoffTime string `json:"handoff_time,omitempty"`
HandoffDay string `json:"handoff_day,omitempty"`
ShiftDuration string `json:"shift_duration,omitempty"`
}

type OnCallScheduleMember struct {
Expand Down Expand Up @@ -54,6 +54,10 @@ type CreateOnCallScheduleRequest struct {
Strategy OnCallScheduleStrategy `json:"strategy"`
Restrictions []OnCallScheduleRestriction `json:"restrictions"`
MemberIDs []string `json:"member_ids"`

// StartTime is only required for `custom` strategy.
// ISO8601 / Go RFC3339 format.
StartTime string `json:"start_time,omitempty"`
}

type UpdateOnCallScheduleRequest struct {
Expand Down
4 changes: 3 additions & 1 deletion firehydrant/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ type ServicesResponse struct {
// URL: GET https://api.firehydrant.io/v1/users
type GetUserParams struct {
Query string `url:"query,omitempty"`
Page int `url:"page,omitempty"`
}

type User struct {
Expand All @@ -166,7 +167,8 @@ type User struct {
}

type UserResponse struct {
Users []User `json:"data"`
Users []User `json:"data"`
Pagination *Pagination `json:"pagination,omitempty"`
}

// ScheduleResponse is the payload for a schedule
Expand Down
63 changes: 51 additions & 12 deletions provider/on_call_schedule_resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,17 +70,24 @@ func resourceOnCallSchedule() *schema.Resource {
},
"handoff_time": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
Optional: true,
},
"handoff_day": {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
},
"shift_duration": {
Type: schema.TypeString,
Optional: true,
},
},
},
},
"start_time": {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
},
"color": {
Type: schema.TypeString,
Optional: true,
Expand Down Expand Up @@ -140,14 +147,43 @@ func createResourceFireHydrantOnCallSchedule(ctx context.Context, d *schema.Reso
Description: d.Get("description").(string),
TimeZone: d.Get("time_zone").(string),
Strategy: firehydrant.OnCallScheduleStrategy{
Type: d.Get("strategy.0.type").(string),
HandoffTime: d.Get("strategy.0.handoff_time").(string),
HandoffDay: d.Get("strategy.0.handoff_day").(string),
Type: d.Get("strategy.0.type").(string),
HandoffTime: d.Get("strategy.0.handoff_time").(string),
HandoffDay: d.Get("strategy.0.handoff_day").(string),
ShiftDuration: d.Get("strategy.0.shift_duration").(string),
},
StartTime: d.Get("start_time").(string),
MemberIDs: memberIDs,
Restrictions: oncallRestrictionsFromData(d),
}

if onCallSchedule.Strategy.Type != "" {
isCustomStrategy := onCallSchedule.Strategy.Type == "custom"
if isCustomStrategy {
if onCallSchedule.Strategy.ShiftDuration == "" {
return diag.Errorf("firehydrant_on_call_schedule.strategy.shift_duration is required when strategy type is 'custom'")
}
if onCallSchedule.StartTime == "" {
return diag.Errorf("firehydrant_on_call_schedule.start_time is required when strategy type is 'custom'")
}

// Discard unused values to avoid ambiguity.
onCallSchedule.Strategy.HandoffTime = ""
onCallSchedule.Strategy.HandoffDay = ""
} else {
if onCallSchedule.Strategy.HandoffTime == "" {
return diag.Errorf("firehydrant_on_call_schedule.strategy.handoff_time is required when strategy type is '%s'", onCallSchedule.Strategy.Type)
}
if onCallSchedule.Strategy.Type == "weekly" && onCallSchedule.Strategy.HandoffDay == "" {
return diag.Errorf("firehydrant_on_call_schedule.strategy.handoff_day is required when strategy type is '%s'", onCallSchedule.Strategy.Type)
}

// Discard unused values to avoid ambiguity.
onCallSchedule.Strategy.ShiftDuration = ""
onCallSchedule.StartTime = ""
}
}

// Create the on-call schedule
createdOnCallSchedule, err := firehydrantAPIClient.OnCallSchedules().Create(ctx, teamID, onCallSchedule)
if err != nil {
Expand Down Expand Up @@ -274,13 +310,16 @@ func deleteResourceFireHydrantOnCallSchedule(ctx context.Context, d *schema.Reso
}

func strategyToMap(strategy firehydrant.OnCallScheduleStrategy) []map[string]interface{} {
return []map[string]interface{}{
{
"type": strategy.Type,
"handoff_time": strategy.HandoffTime,
"handoff_day": strategy.HandoffDay,
},
m := map[string]interface{}{"type": strategy.Type}
if strategy.Type == "custom" {
m["shift_duration"] = strategy.ShiftDuration
} else {
m["handoff_time"] = strategy.HandoffTime
}
if strategy.Type == "weekly" {
m["handoff_day"] = strategy.HandoffDay
}
return []map[string]interface{}{m}
}

func oncallRestrictionsFromData(d *schema.ResourceData) []firehydrant.OnCallScheduleRestriction {
Expand Down
28 changes: 28 additions & 0 deletions provider/on_call_schedule_resource_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,34 @@ func testAccOnCallScheduleConfig_restrictions(rName string) string {
`, rName, rName, rName)
}

func testAccOnCallScheduleConfig_customStrategy(rName string) string {
return fmt.Sprintf(`
resource "firehydrant_team" "team_team" {
name = "test-team-%s"
}
resource "firehydrant_on_call_schedule" "test_on_call_schedule_custom_strategy" {
name = "test-on-call-schedule-custom-strategy-%s"
description = "test-description-%s"
team_id = firehydrant_team.team_team.id
time_zone = "America/Los_Angeles"
start_time = "2024-04-11T11:56:29-07:00"
strategy {
type = "custom"
shift_duration = "PT93600S"
}
restrictions {
start_day = "monday"
start_time = "14:00:00"
end_day = "friday"
end_time = "17:00:00"
}
}
`, rName, rName, rName)
}

func testAccCheckOnCallScheduleResourceDestroy() resource.TestCheckFunc {
return func(s *terraform.State) error {
client, err := firehydrant.NewRestClient(os.Getenv("FIREHYDRANT_API_KEY"))
Expand Down

0 comments on commit 22166fa

Please sign in to comment.