diff --git a/docs/resources/zenduty_post_incident_tasks.md b/docs/resources/zenduty_post_incident_tasks.md
new file mode 100644
index 0000000..80af4e4
--- /dev/null
+++ b/docs/resources/zenduty_post_incident_tasks.md
@@ -0,0 +1,67 @@
+---
+# generated by https://github.com/hashicorp/terraform-plugin-docs
+page_title: "Zenduty: PostIncidentTasks"
+subcategory: ""
+description: |-
+ Provides a Zenduty PostIncidentTasks Resource. This allows PostIncidentTasks to be created, updated, and deleted.
+
+---
+
+# Resource : zenduty_post_incident_tasks
+Provides a Zenduty PostIncidentTasks Resource. This allows PostIncidentTasks to be created, updated, and deleted.
+## Example Usage
+```hcl
+resource "zenduty_teams" "exampleteam" {
+ name = "exmaple team"
+}
+```
+
+
+```hcl
+resource "zenduty_post_incident_tasks" "demotask" {
+ title = "demo task template"
+ description = "this is a description of demo task"
+ team_id = zenduty_teams.exampleteam.id
+ due_in_time = "YYYY-MM-DD HH:MM"
+ status = 0
+}
+```
+
+
+## Argument Reference
+
+* `team_id` - (Required) The unique_id of team.
+* `title` - (Required) The title of the task.
+* `description` - (Required) The description of the task.
+* `status` - (Optional) the status of the task choices are `0` is To-Do,`1` is In-Progress, `2`- Done
+* `due_in_time` - (Optional) The due time of the task in format YYYY-MM-DD HH:MM.
+* `assigned_to` - (Optional) username of the user to assign the task
+## Attributes Reference
+
+The following attributes are exported:
+
+* `id` - The ID of the Zenduty PostIncidentTasks.
+
+## Import
+
+Team PostIncidentTask can be imported using the `team_id`(ie. unique_id of the team) and `task_id`(ie. unique_id of the task template)
+
+```hcl
+resource "zenduty_post_incident_tasks" "demotask" {
+
+
+}
+```
+
+`$ terraform import zenduty_post_incident_tasks.demotask team_id/task_id`
+
+`$ terraform state show zenduty_post_incident_tasks.demotask`
+
+`* copy the output data and paste inside zenduty_post_incident_tasks.demotask resource block and remove the id attribute`
+
+`$ terraform plan` to verify the import
+
+
+
+
+
diff --git a/docs/resources/zenduty_sla.md b/docs/resources/zenduty_sla.md
new file mode 100644
index 0000000..84a6c49
--- /dev/null
+++ b/docs/resources/zenduty_sla.md
@@ -0,0 +1,120 @@
+---
+# generated by https://github.com/hashicorp/terraform-plugin-docs
+page_title: "Zenduty: SLAs"
+subcategory: ""
+description: |-
+ Provides a Zenduty SLAs Resource. This allows SLAs to be created, updated, and deleted.
+
+---
+
+# Resource : zenduty_sla
+Provides a Zenduty SLAs Resource. This allows SLAs to be created, updated, and deleted.
+## Example Usage
+```hcl
+resource "zenduty_teams" "exampleteam" {
+ name = "exmaple team"
+}
+
+data "zenduty_user" "user1" {
+ email = "demouser@gmail.com"
+}
+```
+
+```hcl
+
+resource "zenduty_sla" "example_sla" {
+ name = "demo sla"
+ description = "this is a demo sla"
+ team_id = zenduty_teams.exampleteam.id
+ acknowledge_time = 5
+ resolve_time = 10
+ escalations {
+ time = 30
+ type = 1
+ responders {
+ user = data.zenduty_user.user1.users[0].username
+ }
+ }
+ escalations {
+ time = -10
+ type = 2
+ responders {
+ user = data.zenduty_user.user1.users[0].username
+ }
+ }
+}
+
+```
+
+
+## Argument Reference
+
+* `team_id` - (Required) The unique_id of team to create the sla in.
+* `name` - (Required) The name of the sla.
+* `description` - (Required) The description of the sla
+* `acknowledge_time` - (Required) time in seconds to trigger SLA if not acknowledged.
+* `resolve_time` - (Required) Time in seconds to trigger SLA if not resolved.
+* `escalations` - (Required) Reminders when an SLA is breached or about to breach. (see [below for nested schema](#nestedblock--escalation))
+
+```hcl
+
+escalations {
+ time = 30
+ type = 1
+ responders {
+ user = data.zenduty_user.user1.users[0].username
+ }
+ }
+
+```
+
+
+
+* `type`: It is an integer field that determines the type of notification behavior. `1` signifies that notifications are sent when the SLA breach is acknowledged, while `2` indicates notifications for resolution SLA breaches.
+* `time`: This field specifies the time duration in seconds when notifications should be sent. If time is positive, it means notifications will be sent x seconds after the SLA breach, and if it's negative, notifications will be sent x seconds before the breach.
+* `responders` - users who need to be paged when an SLA is breached. (see [below for nested schema](#nestedblock--responders))
+
+
+
+
+```hcl
+responders {
+ user = data.zenduty_user.user1.users[0].username
+}
+```
+* `user` - Username of the user who will be notified if sla is breached
+
+
+
+
+
+
+## Attributes Reference
+
+The following attributes are exported:
+
+* `id` - The ID of the Zenduty SlA.
+
+## Import
+
+Team SLAs can be imported using the `team_id`(ie. unique_id of the team) and `sla_id`(ie. unique_id of the sla), e.g.
+
+```hcl
+resource "zenduty_sla" "sla1" {
+
+
+}
+```
+
+`$ terraform import zenduty_sla.sla1 team_id/sla_id`
+
+`$ terraform state show zenduty_sla.sla1`
+
+`* copy the output data and paste inside zenduty_sla.sla1 resource block and remove the id attribute`
+
+`$ terraform plan` to verify the import
+
+
+
+
+
diff --git a/docs/resources/zenduty_task_template_tasks.md b/docs/resources/zenduty_task_template_tasks.md
new file mode 100644
index 0000000..46abe9f
--- /dev/null
+++ b/docs/resources/zenduty_task_template_tasks.md
@@ -0,0 +1,81 @@
+---
+# generated by https://github.com/hashicorp/terraform-plugin-docs
+page_title: "Zenduty: TaskTemplateTasks"
+subcategory: ""
+description: |-
+ Provides a Zenduty TaskTemplateTasks Resource. This allows TaskTemplateTasks to be created, updated, and deleted.
+
+---
+
+# Resource : zenduty_task_template_tasks
+Provides a Zenduty TaskTemplateTasks Resource. This allows TaskTemplateTasks to be created, updated, and deleted.
+## Example Usage
+```hcl
+resource "zenduty_teams" "exampleteam" {
+ name = "exmaple team"
+}
+
+resource "zenduty_task_template_tasks" "demotemplate" {
+ name = "example template"
+ summary = "this is an example template"
+ team_id = zenduty_teams.exampleteam.id
+}
+
+resource "zenduty_roles" "example_role" {
+ team = zenduty_teams.exampleteam.id
+ title = "Example Role"
+ description = "Role Description"
+}
+
+```
+
+
+```hcl
+resource "zenduty_task_template_tasks" "demotask" {
+ team_id = "af0e6c8a-c895-434c-b667-2f44833e15b6"
+ task_template_id = zenduty_task_template_tasks.demotemplate.id
+ title = "demo task"
+ description = "this is a description of demo task"
+ role = zenduty_roles.example_role.id
+}
+```
+
+
+## Argument Reference
+
+* `team_id` - (Required) The unique_id of team.
+* `task_template_id` - (Required) The unique_id of tasktemplate to create the tasktemplatetasks in.
+* `title` - (Required) The title of the task.
+* `description` - (Required) The description of the task.
+* `role` - (Optional) The unique_id of incident role attached to the task
+* `due_in` - (Optional) Time in minutes to complete the task `-1` => no due time
+
+## Attributes Reference
+
+The following attributes are exported:
+
+* `id` - The ID of the Zenduty TaskTemplateTask.
+
+## Import
+
+Team TaskTemplate can be imported using the `team_id`(ie. unique_id of the team) and `task_template_id`(ie. unique_id of the task template), and `task_template_task_id` (ie. unique_id of the task template task id) .
+
+```hcl
+resource "zenduty_task_template_tasks" "demotemplatetask" {
+
+
+}
+```
+
+`$ terraform import zenduty_task_template_tasks.demotemplatetask team_id/task_template_id/task_template_task_id`
+
+`$ terraform state show zenduty_task_template_tasks.demotemplatetask`
+
+`* copy the output data and paste inside zenduty_task_template_tasks.demotemplatetask resource block and remove the id attribute`
+
+`$ terraform plan` to verify the import
+
+
+
+
+
diff --git a/docs/resources/zenduty_task_templates.md b/docs/resources/zenduty_task_templates.md
new file mode 100644
index 0000000..67a06b6
--- /dev/null
+++ b/docs/resources/zenduty_task_templates.md
@@ -0,0 +1,62 @@
+---
+# generated by https://github.com/hashicorp/terraform-plugin-docs
+page_title: "Zenduty: TaskTemplates"
+subcategory: ""
+description: |-
+ Provides a Zenduty TaskTemplates Resource. This allows TaskTemplates to be created, updated, and deleted.
+
+---
+
+# Resource : zenduty_task_templates
+Provides a Zenduty TaskTemplates Resource. This allows TaskTemplates to be created, updated, and deleted.
+## Example Usage
+```hcl
+resource "zenduty_teams" "exampleteam" {
+ name = "exmaple team"
+}
+```
+
+```hcl
+resource "zenduty_task_templates" "demotemplate" {
+ name = "example template"
+ summary = "this is an example template"
+ team_id = zenduty_teams.exampleteam.id
+}
+```
+
+
+## Argument Reference
+
+* `team_id` - (Required) The unique_id of team to create the tasktemplate in.
+* `name` - (Required) The name of the tasktemplate.
+* `summary` - (Required) The summary of the tasktemplate.
+
+## Attributes Reference
+
+The following attributes are exported:
+
+* `id` - The ID of the Zenduty TaskTemplate.
+
+## Import
+
+Team TaskTemplate can be imported using the `team_id`(ie. unique_id of the team) and `task_template_id`(ie. unique_id of the task template), e.g.
+
+```hcl
+resource "zenduty_task_templates" "demotemplate" {
+
+
+}
+```
+
+`$ terraform import zenduty_task_templates.demotemplate team_id/task_template_id`
+
+`$ terraform state show zenduty_task_templates.demotemplate`
+
+`* copy the output data and paste inside zenduty_task_templates.demotemplate resource block and remove the id attribute`
+
+`$ terraform plan` to verify the import
+
+
+
+
+
diff --git a/go.mod b/go.mod
index 852d001..e1651c6 100644
--- a/go.mod
+++ b/go.mod
@@ -3,7 +3,7 @@ module terraform-provider-zenduty
go 1.17
require (
- github.com/Zenduty/zenduty-go-sdk v0.1.7
+ github.com/Zenduty/zenduty-go-sdk v0.1.8
github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320
github.com/hashicorp/terraform-plugin-sdk/v2 v2.10.1
)
@@ -16,6 +16,7 @@ require (
github.com/fatih/color v1.7.0 // indirect
github.com/golang/protobuf v1.4.2 // indirect
github.com/google/go-cmp v0.5.6 // indirect
+ github.com/google/uuid v1.3.1
github.com/hashicorp/errwrap v1.0.0 // indirect
github.com/hashicorp/go-checkpoint v0.5.0 // indirect
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
diff --git a/go.sum b/go.sum
index 4b7ee55..c0591b5 100644
--- a/go.sum
+++ b/go.sum
@@ -44,6 +44,8 @@ github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7 h1:YoJbenK9C6
github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo=
github.com/Zenduty/zenduty-go-sdk v0.1.7 h1:IojKvlQAKI6/5GnicYCFLtz7+J6vnG+PsHlUB5aZAGk=
github.com/Zenduty/zenduty-go-sdk v0.1.7/go.mod h1:XnK1p2uyFpBUwbW+xecKSww0klZOSKKoywobqGDlFE8=
+github.com/Zenduty/zenduty-go-sdk v0.1.8 h1:vREmE/XO+nVR7oZ0JLp2W18QTl8r3a6ymsYY7BwDAIg=
+github.com/Zenduty/zenduty-go-sdk v0.1.8/go.mod h1:XnK1p2uyFpBUwbW+xecKSww0klZOSKKoywobqGDlFE8=
github.com/acomagu/bufpipe v1.0.3 h1:fxAGrHZTgQ9w5QqVItgzwj235/uYZYgbXitB+dLupOk=
github.com/acomagu/bufpipe v1.0.3/go.mod h1:mxdxdup/WdsKVreO5GpW4+M/1CE2sMG4jeGJ2sYmHc4=
github.com/agext/levenshtein v1.2.1/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558=
@@ -150,6 +152,8 @@ github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hf
github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4=
+github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/googleapis/gax-go/v2 v2.0.5 h1:sjZBwGj9Jlw33ImPtvFviGYvseOtDM7hkSKB7+Tv3SM=
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
diff --git a/zenduty/helpers.go b/zenduty/helpers.go
index 9969638..81e6dba 100644
--- a/zenduty/helpers.go
+++ b/zenduty/helpers.go
@@ -6,6 +6,7 @@ import (
"regexp"
"strings"
+ "github.com/google/uuid"
"github.com/hashicorp/go-cty/cty"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
@@ -113,3 +114,9 @@ func ValidateRequired() schema.SchemaValidateDiagFunc {
}
}
+
+func genrateUUID() string {
+ id := uuid.New()
+ uuidString := id.String()
+ return uuidString
+}
diff --git a/zenduty/provider.go b/zenduty/provider.go
index f8812f3..46db6dd 100644
--- a/zenduty/provider.go
+++ b/zenduty/provider.go
@@ -42,6 +42,10 @@ func Provider() *schema.Provider {
"zenduty_assign_account_role": resourceAssignAccountRole(),
"zenduty_globalrouter": resourceGlobalRouter(),
"zenduty_globalrouting_rule": resourceGlobalRoutingRules(),
+ "zenduty_sla": resourceSLA(),
+ "zenduty_post_incident_tasks": resourcePostIncidentTasks(),
+ "zenduty_task_templates": resourceTaskTemplates(),
+ "zenduty_task_template_tasks": resourceTaskTemplateTaskTasks(),
},
DataSourcesMap: map[string]*schema.Resource{
diff --git a/zenduty/resource_post_incident_tasks.go b/zenduty/resource_post_incident_tasks.go
new file mode 100644
index 0000000..a720116
--- /dev/null
+++ b/zenduty/resource_post_incident_tasks.go
@@ -0,0 +1,217 @@
+package zenduty
+
+import (
+ "context"
+ "errors"
+ "fmt"
+ "strings"
+ "time"
+
+ "github.com/Zenduty/zenduty-go-sdk/client"
+
+ "github.com/hashicorp/terraform-plugin-sdk/v2/diag"
+
+ "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
+ "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
+)
+
+func resourcePostIncidentTasks() *schema.Resource {
+ return &schema.Resource{
+ CreateContext: resourceCreatePostIncidentTasks,
+ UpdateContext: resourceUpdatePostIncidentTasks,
+ DeleteContext: resourceDeletePostIncidentTasks,
+ ReadContext: resourceReadPostIncidentTasks,
+ Importer: &schema.ResourceImporter{
+ State: resourcePostIncidentTasksImporter,
+ },
+ Schema: map[string]*schema.Schema{
+ "team_id": {
+ Type: schema.TypeString,
+ Required: true,
+ ValidateDiagFunc: ValidateUUID(),
+ },
+ "unique_id": {
+ Type: schema.TypeString,
+ Computed: true,
+ },
+ "title": {
+ Type: schema.TypeString,
+ Required: true,
+ },
+ "description": {
+ Type: schema.TypeString,
+ Required: true,
+ },
+ "assigned_to": {
+ Type: schema.TypeString,
+ Optional: true,
+ },
+ "status": {
+ Type: schema.TypeInt,
+ Optional: true,
+ ValidateFunc: validation.IntBetween(0, 2),
+ Default: 0,
+ },
+ "due_in_time": {
+ Type: schema.TypeString,
+ Optional: true,
+ },
+ "creation_date": {
+ Type: schema.TypeString,
+ Computed: true,
+ },
+ },
+ }
+}
+
+func parseDueInTime(timestamp string) string {
+ RFC3339local := "2006-01-02T15:04:05Z"
+ t, parseErr := time.Parse(RFC3339local, timestamp)
+ if parseErr != nil {
+ return timestamp
+ }
+ return t.Format("2006-01-02 15:04")
+
+}
+
+func CreatePostIncidentTask(Ctx context.Context, d *schema.ResourceData, m interface{}) (*client.PostIncidentTaskObj, diag.Diagnostics) {
+
+ newpostincidenttask := &client.PostIncidentTaskObj{}
+
+ if v, ok := d.GetOk("team_id"); ok {
+ newpostincidenttask.Team = v.(string)
+
+ }
+ if v, ok := d.GetOk("description"); ok {
+ newpostincidenttask.Description = v.(string)
+
+ }
+ if v, ok := d.GetOk("title"); ok {
+ newpostincidenttask.Title = v.(string)
+ }
+ if v, ok := d.GetOk("rank"); ok {
+ newpostincidenttask.Status = v.(int)
+ }
+ if v, ok := d.GetOk("assigned_to"); ok {
+ newpostincidenttask.AssignedTo = v.(string)
+ }
+ if v, ok := d.GetOk("status"); ok {
+ newpostincidenttask.Status = v.(int)
+ }
+ if v, ok := d.GetOk("due_in_time"); ok {
+ DueInTime := v.(string)
+ newpostincidenttask.DueInTime = &DueInTime
+ parsedTime, parsedErr := time.Parse("2006-01-02 15:04", v.(string))
+ if parsedErr == nil {
+ formattedTime := parsedTime.In(time.UTC).Format(time.RFC3339)
+ newpostincidenttask.DueInTime = &formattedTime
+ } else {
+ return nil, diag.FromErr(parsedErr)
+ }
+ }
+
+ return newpostincidenttask, nil
+
+}
+
+func resourceCreatePostIncidentTasks(Ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
+ apiclient, _ := m.(*Config).Client()
+
+ teamID := d.Get("team_id").(string)
+ if teamID == "" {
+ return diag.FromErr(errors.New("team_id is required"))
+ }
+
+ task, createErr := CreatePostIncidentTask(Ctx, d, m)
+ if createErr != nil {
+ return createErr
+ }
+
+ var diags diag.Diagnostics
+ incidenttask, err := apiclient.PostIncidentTask.CreatePostIncidentTask(teamID, task)
+ if err != nil {
+ return diag.FromErr(err)
+ }
+
+ d.SetId(incidenttask.UniqueID)
+
+ return diags
+}
+
+func resourceUpdatePostIncidentTasks(Ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
+ apiclient, _ := m.(*Config).Client()
+
+ teamID := d.Get("team_id").(string)
+ id := d.Id()
+ if teamID == "" {
+ return diag.FromErr(errors.New("team_id is required"))
+ }
+ task, createErr := CreatePostIncidentTask(Ctx, d, m)
+ if createErr != nil {
+ return createErr
+
+ }
+
+ _, err := apiclient.PostIncidentTask.UpdatePostIncidentTaskByID(teamID, id, task)
+ if err != nil {
+ return diag.FromErr(err)
+ }
+ return resourceReadPostIncidentTasks(Ctx, d, m)
+}
+
+func resourceDeletePostIncidentTasks(Ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
+ apiclient, _ := m.(*Config).Client()
+
+ teamID := d.Get("team_id").(string)
+ id := d.Id()
+ if teamID == "" {
+ return diag.FromErr(errors.New("team_id is required"))
+ }
+ var diags diag.Diagnostics
+ err := apiclient.PostIncidentTask.DeletePostIncidentTaskByID(teamID, id)
+ if err != nil {
+ return diag.FromErr(err)
+ }
+ return diags
+}
+
+func resourceReadPostIncidentTasks(Ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
+ apiclient, _ := m.(*Config).Client()
+
+ teamID := d.Get("team_id").(string)
+ id := d.Id()
+ if emptyString(teamID) {
+ return diag.FromErr(errors.New("team_id is required"))
+ }
+ var diags diag.Diagnostics
+ postincidenttask, err := apiclient.PostIncidentTask.GetPostIncidentTaskByID(teamID, id)
+ if err != nil {
+ return diag.FromErr(err)
+ }
+
+ d.Set("title", postincidenttask.Title)
+ d.Set("description", postincidenttask.Description)
+ d.Set("assigned_to", postincidenttask.AssignedTo)
+ d.Set("status", postincidenttask.Status)
+ d.Set("team_id", teamID)
+ if postincidenttask.DueInTime != nil {
+ d.Set("due_in_time", parseDueInTime(*postincidenttask.DueInTime))
+ }
+ d.Set("creation_date", postincidenttask.CreationDate)
+
+ return diags
+}
+
+func resourcePostIncidentTasksImporter(d *schema.ResourceData, m interface{}) ([]*schema.ResourceData, error) {
+ parts := strings.Split(d.Id(), "/")
+ if len(parts) != 2 {
+ return nil, fmt.Errorf("unexpected format of id (%q), expected /", d.Id())
+ } else if !IsValidUUID(parts[0]) {
+ return nil, fmt.Errorf("invalid team_id (%q)", parts[0])
+ } else if !IsValidUUID(parts[1]) {
+ return nil, fmt.Errorf("invalid task_id (%q)", parts[1])
+ }
+ d.Set("team_id", parts[0])
+ d.SetId(parts[1])
+ return []*schema.ResourceData{d}, nil
+}
diff --git a/zenduty/resource_sla.go b/zenduty/resource_sla.go
new file mode 100644
index 0000000..7add0fc
--- /dev/null
+++ b/zenduty/resource_sla.go
@@ -0,0 +1,302 @@
+package zenduty
+
+import (
+ "context"
+ "errors"
+ "fmt"
+ "log"
+ "strings"
+
+ "github.com/Zenduty/zenduty-go-sdk/client"
+
+ "github.com/hashicorp/terraform-plugin-sdk/v2/diag"
+ "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
+ "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
+)
+
+func resourceSLA() *schema.Resource {
+ return &schema.Resource{
+ CreateContext: resourceCreateSLA,
+ UpdateContext: resourceUpdateSLA,
+ DeleteContext: resourceDeleteSLA,
+ ReadContext: resourceReadSLA,
+ Importer: &schema.ResourceImporter{
+ State: resourceSLAImporter,
+ },
+
+ Schema: map[string]*schema.Schema{
+ "name": {
+ Type: schema.TypeString,
+ Required: true,
+ },
+ "description": {
+ Type: schema.TypeString,
+ Optional: true,
+ },
+ "team_id": {
+ Type: schema.TypeString,
+ Required: true,
+ },
+ "escalations": &schema.Schema{
+ Type: schema.TypeList,
+ Required: true,
+ Elem: &schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "unique_id": {
+ Type: schema.TypeString,
+ Computed: true,
+ },
+ "time": {
+ Type: schema.TypeInt,
+ Required: true,
+ ValidateFunc: validation.IntBetween(-432000, 432000),
+ },
+ "type": {
+ Type: schema.TypeInt,
+ Required: true,
+ ValidateFunc: validation.IntBetween(1, 2),
+ },
+ "responders": {
+ Type: schema.TypeList,
+ Optional: true,
+ Elem: &schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "user": {
+ Type: schema.TypeString,
+ Required: true,
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ "acknowledge_time": {
+ Type: schema.TypeInt,
+ Required: true,
+ ValidateFunc: validation.IntBetween(1, 432000),
+ },
+ "resolve_time": {
+ Type: schema.TypeInt,
+ Required: true,
+ ValidateFunc: validation.IntBetween(1, 432000),
+ },
+ "is_active": {
+ Type: schema.TypeBool,
+ Optional: true,
+ Default: true,
+ },
+ },
+ }
+}
+
+func CreateSLA(Ctx context.Context, d *schema.ResourceData, m interface{}) (*client.SLAObj, diag.Diagnostics) {
+ newSLA := &client.SLAObj{}
+ escalations := d.Get("escalations").([]interface{})
+ if v, ok := d.GetOk("name"); ok {
+ newSLA.Name = v.(string)
+ }
+ if v, ok := d.GetOk("description"); ok {
+ newSLA.Description = v.(string)
+ if emptyString(newSLA.Description) {
+ return nil, diag.FromErr(errors.New("description is empty"))
+ }
+ }
+ if v, ok := d.GetOk("acknowledge_time"); ok {
+ newSLA.AcknowledgeTime = v.(int)
+ }
+ if v, ok := d.GetOk("resolve_time"); ok {
+ newSLA.ResolveTime = v.(int)
+ }
+ if v, ok := d.GetOk("is_active"); ok {
+ newSLA.IsActive = v.(bool)
+ }
+
+ newSLA.Escalations = make([]client.SLAEscalations, len(escalations))
+
+ for i, escalation := range escalations {
+ escalationMap := escalation.(map[string]interface{})
+ newEscalation := client.SLAEscalations{}
+
+ if v, ok := escalationMap["time"]; ok {
+ newEscalation.Time = v.(int)
+
+ }
+ if v, ok := escalationMap["type"]; ok {
+ newEscalation.Type = v.(int)
+ }
+ if v, ok := escalationMap["unique_id"]; ok {
+ newEscalation.UniqueID = v.(string)
+ if emptyString(newEscalation.UniqueID) {
+ newEscalation.UniqueID = genrateUUID()
+ }
+ }
+
+ if v, ok := escalationMap["responders"]; ok {
+ responderusers := v.([]interface{})
+ newEscalation.Responders = make([]client.ResponderUser, len(responderusers))
+ for j, responder := range responderusers {
+ resonderMap := responder.(map[string]interface{})
+ responderuser := client.ResponderUser{}
+ if v, ok := resonderMap["user"]; ok {
+ responderuser.User = v.(string)
+ }
+ newEscalation.Responders[j] = responderuser
+ }
+ }
+ newSLA.Escalations[i] = newEscalation
+ }
+ return newSLA, nil
+
+}
+
+func flattenEscalation(escalations []client.SLAEscalations) []map[string]interface{} {
+ result := make([]map[string]interface{}, len(escalations))
+ for i, escalation := range escalations {
+ result[i] = map[string]interface{}{
+ "time": escalation.Time,
+ "type": escalation.Type,
+ "unique_id": escalation.UniqueID,
+ "responders": flattenResponderUser(escalation.Responders),
+ }
+ }
+ return result
+}
+
+func flattenResponderUser(responders []client.ResponderUser) []map[string]interface{} {
+ result := make([]map[string]interface{}, len(responders))
+ for i, responder := range responders {
+ result[i] = map[string]interface{}{
+ "user": responder.User,
+ }
+ }
+ return result
+}
+
+func resourceCreateSLA(Ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
+ apiclient, _ := m.(*Config).Client()
+ var teamID string
+ if v, ok := d.GetOk("team_id"); ok {
+ if emptyString(v.(string)) {
+ return diag.FromErr(errors.New("team_id must not be empty"))
+ }
+ teamID = v.(string)
+ }
+
+ var diags diag.Diagnostics
+ newSLA, createErr := CreateSLA(Ctx, d, m)
+ if createErr != nil {
+ return createErr
+ }
+
+ sla, err := apiclient.Sla.CreateSLA(teamID, newSLA)
+
+ if err != nil {
+ return diag.FromErr(err)
+ }
+
+ for i, escalation := range sla.Escalations {
+ log.Printf("SLAEscalation %d: %v", i, escalation)
+ }
+ log.Printf("%+v\n", sla.Escalations)
+ d.SetId(sla.UniqueID)
+ if err := d.Set("escalations", flattenEscalation(sla.Escalations)); err != nil {
+ return diag.FromErr(err)
+ }
+
+ return diags
+
+}
+
+func resourceUpdateSLA(Ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
+ apiclient, _ := m.(*Config).Client()
+ var teamID string
+ if v, ok := d.GetOk("team_id"); ok {
+ if emptyString(v.(string)) {
+ return diag.FromErr(errors.New("team_id must not be empty"))
+ }
+ teamID = v.(string)
+ }
+
+ newSLA, createErr := CreateSLA(Ctx, d, m)
+ if createErr != nil {
+ return createErr
+ }
+ id := d.Id()
+ var diags diag.Diagnostics
+
+ sla, err := apiclient.Sla.UpdateSLAByID(teamID, id, newSLA)
+
+ if err != nil {
+ return diag.FromErr(err)
+ }
+
+ if err := d.Set("escalations", flattenEscalation(sla.Escalations)); err != nil {
+ return diag.FromErr(err)
+ }
+ return diags
+}
+
+func resourceDeleteSLA(Ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
+ apiclient, _ := m.(*Config).Client()
+
+ var teamID string
+ if v, ok := d.GetOk("team_id"); ok {
+ if emptyString(v.(string)) {
+ return diag.FromErr(errors.New("team_id must not be empty"))
+ }
+ teamID = v.(string)
+ }
+
+ id := d.Id()
+
+ var diags diag.Diagnostics
+ err := apiclient.Sla.DeleteSLAByID(teamID, id)
+ if err != nil {
+ return diag.FromErr(err)
+ }
+ return diags
+}
+
+func resourceReadSLA(Ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
+ apiclient, _ := m.(*Config).Client()
+
+ teamID := d.Get("team_id").(string)
+ if v, ok := d.GetOk("team_id"); ok {
+ teamID = v.(string)
+ }
+
+ id := d.Id()
+ if teamID == "" {
+ return diag.FromErr(errors.New("team_id is required "))
+ }
+ var diags diag.Diagnostics
+ sla, err := apiclient.Sla.GetSLAByID(teamID, id)
+ if err != nil {
+ return diag.FromErr(err)
+ }
+ d.Set("name", sla.Name)
+ d.Set("description", sla.Description)
+ d.Set("acknowledge_time", sla.AcknowledgeTime)
+ d.Set("resolve_time", sla.ResolveTime)
+ d.Set("is_active", sla.IsActive)
+ if err := d.Set("escalations", flattenEscalation(sla.Escalations)); err != nil {
+ return diag.FromErr(err)
+ }
+
+ return diags
+}
+
+func resourceSLAImporter(d *schema.ResourceData, m interface{}) ([]*schema.ResourceData, error) {
+ parts := strings.Split(d.Id(), "/")
+ if len(parts) != 2 {
+ return nil, fmt.Errorf("unexpected format of id (%q), expected /", d.Id())
+ } else if !IsValidUUID(parts[0]) {
+ return nil, fmt.Errorf("invalid team_id (%q)", parts[0])
+ } else if !IsValidUUID(parts[1]) {
+ return nil, fmt.Errorf("invalid sla id (%q)", parts[1])
+ }
+ d.Set("team_id", parts[0])
+ d.SetId(parts[1])
+ return []*schema.ResourceData{d}, nil
+}
diff --git a/zenduty/resource_task_template_tasks.go b/zenduty/resource_task_template_tasks.go
new file mode 100644
index 0000000..73e357c
--- /dev/null
+++ b/zenduty/resource_task_template_tasks.go
@@ -0,0 +1,203 @@
+package zenduty
+
+import (
+ "context"
+ "errors"
+ "fmt"
+ "strings"
+
+ "github.com/Zenduty/zenduty-go-sdk/client"
+
+ "github.com/hashicorp/terraform-plugin-sdk/v2/diag"
+
+ "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
+ "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
+)
+
+func resourceTaskTemplateTaskTasks() *schema.Resource {
+ return &schema.Resource{
+ CreateContext: resourceCreateTaskTemplateTaskTasks,
+ UpdateContext: resourceUpdateTaskTemplateTaskTasks,
+ DeleteContext: resourceDeleteTaskTemplateTaskTasks,
+ ReadContext: resourceReadTaskTemplateTaskTasks,
+ Importer: &schema.ResourceImporter{
+ State: resourceTaskTemplateTaskTasksImporter,
+ },
+ Schema: map[string]*schema.Schema{
+ "team_id": {
+ Type: schema.TypeString,
+ Required: true,
+ ValidateDiagFunc: ValidateUUID(),
+ },
+ "task_template_id": {
+ Type: schema.TypeString,
+ Required: true,
+ ValidateDiagFunc: ValidateUUID(),
+ },
+ "unique_id": {
+ Type: schema.TypeString,
+ Computed: true,
+ },
+ "role": {
+ Type: schema.TypeString,
+ Optional: true,
+ ValidateDiagFunc: ValidateUUID(),
+ },
+ "title": {
+ Type: schema.TypeString,
+ Required: true,
+ },
+ "description": {
+ Type: schema.TypeString,
+ Required: true,
+ },
+ "due_in": {
+ Type: schema.TypeInt,
+ Optional: true,
+ Default: -1,
+ ValidateFunc: validation.IntBetween(-1, 10080),
+ },
+ "creation_date": {
+ Type: schema.TypeString,
+ Computed: true,
+ },
+ "position": {
+ Type: schema.TypeInt,
+ Computed: true,
+ },
+ },
+ }
+}
+
+func CreateTaskTemplateTask(Ctx context.Context, d *schema.ResourceData, m interface{}) (*client.TaskTemplateTaskObj, diag.Diagnostics) {
+
+ newTaskTemplateTask := &client.TaskTemplateTaskObj{}
+
+ if v, ok := d.GetOk("role"); ok {
+ newTaskTemplateTask.Role = v.(string)
+
+ }
+ if v, ok := d.GetOk("description"); ok {
+ newTaskTemplateTask.Description = v.(string)
+
+ }
+ if v, ok := d.GetOk("title"); ok {
+ newTaskTemplateTask.Title = v.(string)
+ }
+ if v, ok := d.GetOk("due_in"); ok {
+ newTaskTemplateTask.DueIn = v.(int)
+ }
+ if v, ok := d.GetOk("task_template_id"); ok {
+ newTaskTemplateTask.TaskTemplate = v.(string)
+ }
+ position := d.Get("position").(int)
+ newTaskTemplateTask.Positon = position
+
+ return newTaskTemplateTask, nil
+
+}
+
+func resourceCreateTaskTemplateTaskTasks(Ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
+ apiclient, _ := m.(*Config).Client()
+
+ teamID := d.Get("team_id").(string)
+ if teamID == "" {
+ return diag.FromErr(errors.New("team_id is required"))
+ }
+
+ task, createErr := CreateTaskTemplateTask(Ctx, d, m)
+ if createErr != nil {
+ return createErr
+ }
+
+ var diags diag.Diagnostics
+ incidenttask, err := apiclient.TaskTemplate.CreateTaskTemplateTask(teamID, task.TaskTemplate, task)
+ if err != nil {
+ return diag.FromErr(err)
+ }
+
+ d.SetId(incidenttask.UniqueID)
+
+ return diags
+}
+
+func resourceUpdateTaskTemplateTaskTasks(Ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
+ apiclient, _ := m.(*Config).Client()
+
+ teamID := d.Get("team_id").(string)
+ id := d.Id()
+ if teamID == "" {
+ return diag.FromErr(errors.New("team_id is required"))
+ }
+ task, createErr := CreateTaskTemplateTask(Ctx, d, m)
+ if createErr != nil {
+ return createErr
+
+ }
+
+ _, err := apiclient.TaskTemplate.UpdateTaskTemplateTaskByID(teamID, task.TaskTemplate, id, task)
+ if err != nil {
+ return diag.FromErr(err)
+ }
+ return resourceReadTaskTemplateTaskTasks(Ctx, d, m)
+}
+
+func resourceDeleteTaskTemplateTaskTasks(Ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
+ apiclient, _ := m.(*Config).Client()
+
+ teamID := d.Get("team_id").(string)
+ task_id := d.Get("task_template_id").(string)
+
+ id := d.Id()
+ if teamID == "" {
+ return diag.FromErr(errors.New("team_id is required"))
+ }
+
+ var diags diag.Diagnostics
+ err := apiclient.TaskTemplate.DeleteTaskTemplateTaskByID(teamID, task_id, id)
+ if err != nil {
+ return diag.FromErr(err)
+ }
+ return diags
+}
+
+func resourceReadTaskTemplateTaskTasks(Ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
+ apiclient, _ := m.(*Config).Client()
+
+ teamID := d.Get("team_id").(string)
+ task_id := d.Get("task_template_id").(string)
+ id := d.Id()
+ if emptyString(teamID) {
+ return diag.FromErr(errors.New("team_id is required"))
+ }
+ var diags diag.Diagnostics
+ tasktemplatetask, err := apiclient.TaskTemplate.GetTaskTemplateTaskByID(teamID, task_id, id)
+ if err != nil {
+ return diag.FromErr(err)
+ }
+ d.Set("title", tasktemplatetask.Title)
+ d.Set("description", tasktemplatetask.Description)
+ d.Set("creation_date", tasktemplatetask.CreationDate)
+ d.Set("team_id", teamID)
+ d.Set("role", tasktemplatetask.Role)
+ d.Set("task_template_id", tasktemplatetask.TaskTemplate)
+ d.Set("position", tasktemplatetask.Positon)
+ d.Set("due_in", tasktemplatetask.DueIn)
+ return diags
+}
+
+func resourceTaskTemplateTaskTasksImporter(d *schema.ResourceData, m interface{}) ([]*schema.ResourceData, error) {
+ parts := strings.Split(d.Id(), "/")
+ if len(parts) != 3 {
+ return nil, fmt.Errorf("unexpected format of id (%q), expected //", d.Id())
+ } else if !IsValidUUID(parts[0]) {
+ return nil, fmt.Errorf("invalid team_id (%q)", parts[0])
+ } else if !IsValidUUID(parts[1]) {
+ return nil, fmt.Errorf("invalid task_template_id (%q)", parts[1])
+ } else if !IsValidUUID(parts[1]) {
+ return nil, fmt.Errorf("invalid task_id (%q)", parts[2])
+ }
+ d.Set("team_id", parts[0])
+ d.SetId(parts[1])
+ return []*schema.ResourceData{d}, nil
+}
diff --git a/zenduty/resource_task_templates.go b/zenduty/resource_task_templates.go
new file mode 100644
index 0000000..57af93d
--- /dev/null
+++ b/zenduty/resource_task_templates.go
@@ -0,0 +1,166 @@
+package zenduty
+
+import (
+ "context"
+ "errors"
+ "fmt"
+ "strings"
+
+ "github.com/Zenduty/zenduty-go-sdk/client"
+
+ "github.com/hashicorp/terraform-plugin-sdk/v2/diag"
+
+ "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
+)
+
+func resourceTaskTemplates() *schema.Resource {
+ return &schema.Resource{
+ CreateContext: resourceCreateTaskTemplates,
+ UpdateContext: resourceUpdateTaskTemplates,
+ DeleteContext: resourceDeleteTaskTemplates,
+ ReadContext: resourceReadTaskTemplates,
+ Importer: &schema.ResourceImporter{
+ State: resourceTaskTemplatesImporter,
+ },
+ Schema: map[string]*schema.Schema{
+ "team_id": {
+ Type: schema.TypeString,
+ Required: true,
+ ValidateDiagFunc: ValidateUUID(),
+ },
+ "unique_id": {
+ Type: schema.TypeString,
+ Computed: true,
+ },
+ "name": {
+ Type: schema.TypeString,
+ Required: true,
+ },
+ "summary": {
+ Type: schema.TypeString,
+ Required: true,
+ },
+ "creation_date": {
+ Type: schema.TypeString,
+ Computed: true,
+ },
+ },
+ }
+}
+
+func CreateTaskTemplate(Ctx context.Context, d *schema.ResourceData, m interface{}) (*client.TaskTemplateObj, diag.Diagnostics) {
+
+ newtasktemplate := &client.TaskTemplateObj{}
+
+ if v, ok := d.GetOk("team_id"); ok {
+ newtasktemplate.Team = v.(string)
+
+ }
+ if v, ok := d.GetOk("summary"); ok {
+ newtasktemplate.Summary = v.(string)
+
+ }
+ if v, ok := d.GetOk("name"); ok {
+ newtasktemplate.Name = v.(string)
+
+ }
+
+ return newtasktemplate, nil
+
+}
+
+func resourceCreateTaskTemplates(Ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
+ apiclient, _ := m.(*Config).Client()
+
+ teamID := d.Get("team_id").(string)
+ if teamID == "" {
+ return diag.FromErr(errors.New("team_id is required"))
+ }
+
+ task, createErr := CreateTaskTemplate(Ctx, d, m)
+ if createErr != nil {
+ return createErr
+ }
+
+ var diags diag.Diagnostics
+ incidenttask, err := apiclient.TaskTemplate.CreateTaskTemplate(teamID, task)
+ if err != nil {
+ return diag.FromErr(err)
+ }
+
+ d.SetId(incidenttask.UniqueID)
+
+ return diags
+}
+
+func resourceUpdateTaskTemplates(Ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
+ apiclient, _ := m.(*Config).Client()
+
+ teamID := d.Get("team_id").(string)
+ id := d.Id()
+ if teamID == "" {
+ return diag.FromErr(errors.New("team_id is required"))
+ }
+ task, createErr := CreateTaskTemplate(Ctx, d, m)
+ if createErr != nil {
+ return createErr
+
+ }
+
+ _, err := apiclient.TaskTemplate.UpdateTaskTemplateByID(teamID, id, task)
+ if err != nil {
+ return diag.FromErr(err)
+ }
+ return resourceReadTaskTemplates(Ctx, d, m)
+}
+
+func resourceDeleteTaskTemplates(Ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
+ apiclient, _ := m.(*Config).Client()
+
+ teamID := d.Get("team_id").(string)
+ id := d.Id()
+ if teamID == "" {
+ return diag.FromErr(errors.New("team_id is required"))
+ }
+ var diags diag.Diagnostics
+ err := apiclient.TaskTemplate.DeleteTaskTemplateByID(teamID, id)
+ if err != nil {
+ return diag.FromErr(err)
+ }
+ return diags
+}
+
+func resourceReadTaskTemplates(Ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
+ apiclient, _ := m.(*Config).Client()
+
+ teamID := d.Get("team_id").(string)
+ id := d.Id()
+ if emptyString(teamID) {
+ return diag.FromErr(errors.New("team_id is required"))
+ }
+ var diags diag.Diagnostics
+ postincidenttask, err := apiclient.TaskTemplate.GetTaskTemplateByID(teamID, id)
+ if err != nil {
+ return diag.FromErr(err)
+ }
+ d.Set("name", postincidenttask.Name)
+ d.Set("summary", postincidenttask.Summary)
+ d.Set("creation_date", postincidenttask.CreationDate)
+ d.Set("team_id", teamID)
+
+ return diags
+}
+
+func resourceTaskTemplatesImporter(d *schema.ResourceData, m interface{}) ([]*schema.ResourceData, error) {
+ parts := strings.Split(d.Id(), "/")
+ if len(parts) != 2 {
+ return nil, fmt.Errorf("unexpected format of id (%q), expected /", d.Id())
+ } else if !IsValidUUID(parts[0]) {
+ return nil, fmt.Errorf("invalid team_id (%q)", parts[0])
+ } else if !IsValidUUID(parts[1]) {
+ return nil, fmt.Errorf("invalid task_template_id (%q)", parts[1])
+ }
+ d.Set("team_id", parts[0])
+ d.SetId(parts[1])
+ return []*schema.ResourceData{d}, nil
+}