Skip to content

Commit

Permalink
Merge pull request #962 from cjgajard/incident-type
Browse files Browse the repository at this point in the history
[CSGINS-1453] Add incident types resources
  • Loading branch information
cjgajard authored Jan 13, 2025
2 parents b0a2129 + c8f24da commit e751e11
Show file tree
Hide file tree
Showing 23 changed files with 2,240 additions and 17 deletions.
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ module github.com/PagerDuty/terraform-provider-pagerduty
go 1.20

require (
github.com/PagerDuty/go-pagerduty v1.8.1-0.20241111225923-0ef8f340dd3c
github.com/PagerDuty/go-pagerduty v1.8.1-0.20250113202017-9831333ebe6b
github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320
github.com/hashicorp/go-version v1.6.0
github.com/hashicorp/hc-install v0.6.2
Expand All @@ -16,7 +16,7 @@ require (
github.com/hashicorp/terraform-plugin-mux v0.13.0
github.com/hashicorp/terraform-plugin-sdk/v2 v2.31.0
github.com/hashicorp/terraform-plugin-testing v1.6.0
github.com/heimweh/go-pagerduty v0.0.0-20240731213000-b0991665ac52
github.com/heimweh/go-pagerduty v0.0.0-20250113182705-ce1f94dc30af
)

require (
Expand Down
8 changes: 4 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk=
github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow=
github.com/PagerDuty/go-pagerduty v1.8.1-0.20241111225923-0ef8f340dd3c h1:Bnw38sqsVdQVOiuTealk57GnuRb86zyd5v/XW3BcPl8=
github.com/PagerDuty/go-pagerduty v1.8.1-0.20241111225923-0ef8f340dd3c/go.mod h1:ilimTqwHSBjmvKeYA/yayDBZvzf/CX4Pwa9Qbhekzok=
github.com/PagerDuty/go-pagerduty v1.8.1-0.20250113202017-9831333ebe6b h1:Fz0h+POmFi1FkeLCWwrl7MmhPA1EFgVzi3FKzxCG/Dw=
github.com/PagerDuty/go-pagerduty v1.8.1-0.20250113202017-9831333ebe6b/go.mod h1:ilimTqwHSBjmvKeYA/yayDBZvzf/CX4Pwa9Qbhekzok=
github.com/ProtonMail/go-crypto v0.0.0-20230923063757-afb1ddc0824c h1:kMFnB0vCcX7IL/m9Y5LO+KQYv+t1CQOiFe6+SV2J7bE=
github.com/ProtonMail/go-crypto v0.0.0-20230923063757-afb1ddc0824c/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0=
github.com/agext/levenshtein v1.2.3 h1:YB2fHEn0UJagG8T1rrWknE3ZQzWM06O8AMAatNn7lmo=
Expand Down Expand Up @@ -95,8 +95,8 @@ github.com/hashicorp/terraform-svchost v0.1.1 h1:EZZimZ1GxdqFRinZ1tpJwVxxt49xc/S
github.com/hashicorp/terraform-svchost v0.1.1/go.mod h1:mNsjQfZyf/Jhz35v6/0LWcv26+X7JPS+buii2c9/ctc=
github.com/hashicorp/yamux v0.1.1 h1:yrQxtgseBDrq9Y652vSRDvsKCJKOUD+GzTS4Y0Y8pvE=
github.com/hashicorp/yamux v0.1.1/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ=
github.com/heimweh/go-pagerduty v0.0.0-20240731213000-b0991665ac52 h1:rVc7EhBQpz8+tqx8529IGB076iTXeVgE4RAl7L+mUJ8=
github.com/heimweh/go-pagerduty v0.0.0-20240731213000-b0991665ac52/go.mod h1:r59w5iyN01Qvi734yA5hZldbSeJJmsJzee/1kQ/MK7s=
github.com/heimweh/go-pagerduty v0.0.0-20250113182705-ce1f94dc30af h1:41UndNNQiIhLMxleHdJNTxmpHzT06twPUNRaqfJaSpU=
github.com/heimweh/go-pagerduty v0.0.0-20250113182705-ce1f94dc30af/go.mod h1:r59w5iyN01Qvi734yA5hZldbSeJJmsJzee/1kQ/MK7s=
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A=
github.com/jhump/protoreflect v1.15.1 h1:HUMERORf3I3ZdX05WaQ6MIpd/NJ434hTp5YiKgfCL6c=
github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4=
Expand Down
108 changes: 108 additions & 0 deletions pagerdutyplugin/data_source_pagerduty_incident_type.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
package pagerduty

import (
"context"
"fmt"
"log"
"time"

"github.com/PagerDuty/go-pagerduty"
"github.com/PagerDuty/terraform-provider-pagerduty/util"
"github.com/hashicorp/terraform-plugin-framework/datasource"
"github.com/hashicorp/terraform-plugin-framework/datasource/schema"
"github.com/hashicorp/terraform-plugin-framework/path"
"github.com/hashicorp/terraform-plugin-framework/types"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry"
)

type dataSourceIncidentType struct{ client *pagerduty.Client }

var _ datasource.DataSourceWithConfigure = (*dataSourceIncidentType)(nil)

func (*dataSourceIncidentType) Metadata(ctx context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) {
resp.TypeName = "pagerduty_incident_type"
}

func (*dataSourceIncidentType) Schema(ctx context.Context, req datasource.SchemaRequest, resp *datasource.SchemaResponse) {
resp.Schema = schema.Schema{
Attributes: map[string]schema.Attribute{
"id": schema.StringAttribute{Computed: true},
"name": schema.StringAttribute{Computed: true},
"type": schema.StringAttribute{Computed: true},
"display_name": schema.StringAttribute{Required: true},
"description": schema.StringAttribute{Computed: true},
"parent_type": schema.StringAttribute{Computed: true},
"enabled": schema.BoolAttribute{Computed: true},
},
}
}

func (d *dataSourceIncidentType) Configure(ctx context.Context, req datasource.ConfigureRequest, resp *datasource.ConfigureResponse) {
resp.Diagnostics.Append(ConfigurePagerdutyClient(&d.client, req.ProviderData)...)
}

func (d *dataSourceIncidentType) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) {
log.Println("[INFO] Reading PagerDuty incident type")

var searchName types.String
resp.Diagnostics.Append(req.Config.GetAttribute(ctx, path.Root("display_name"), &searchName)...)
if resp.Diagnostics.HasError() {
return
}

var found *pagerduty.IncidentType
err := retry.RetryContext(ctx, 2*time.Minute, func() *retry.RetryError {
response, err := d.client.ListIncidentTypes(ctx, pagerduty.ListIncidentTypesOptions{Filter: "all"})
if err != nil {
if util.IsBadRequestError(err) {
return retry.NonRetryableError(err)
}
return retry.RetryableError(err)
}
for _, it := range response.IncidentTypes {
if it.DisplayName == searchName.ValueString() {
found = &it
break
}
}
return nil
})
if err != nil {
resp.Diagnostics.AddError(
fmt.Sprintf("Error reading PagerDuty incident type %s", searchName),
err.Error(),
)
return
}

if found == nil {
resp.Diagnostics.AddError(
fmt.Sprintf("Unable to locate any incident type with the name: %s", searchName),
"",
)
return
}

model := dataSourceIncidentTypeModel{
ID: types.StringValue(found.ID),
Name: types.StringValue(found.Name),
Type: types.StringValue(found.Type),
DisplayName: types.StringValue(found.DisplayName),
Description: types.StringValue(found.Description),
Enabled: types.BoolValue(found.Enabled),
}
if found.Parent != nil {
model.ParentType = types.StringValue(found.Parent.ID)
}
resp.Diagnostics.Append(resp.State.Set(ctx, &model)...)
}

type dataSourceIncidentTypeModel struct {
ID types.String `tfsdk:"id"`
Name types.String `tfsdk:"name"`
Type types.String `tfsdk:"type"`
DisplayName types.String `tfsdk:"display_name"`
Description types.String `tfsdk:"description"`
ParentType types.String `tfsdk:"parent_type"`
Enabled types.Bool `tfsdk:"enabled"`
}
177 changes: 177 additions & 0 deletions pagerdutyplugin/data_source_pagerduty_incident_type_custom_field.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
package pagerduty

import (
"context"
"encoding/json"
"fmt"
"log"
"time"

"github.com/PagerDuty/go-pagerduty"
"github.com/PagerDuty/terraform-provider-pagerduty/util"
"github.com/hashicorp/terraform-plugin-framework-jsontypes/jsontypes"
"github.com/hashicorp/terraform-plugin-framework/attr"
"github.com/hashicorp/terraform-plugin-framework/datasource"
"github.com/hashicorp/terraform-plugin-framework/datasource/schema"
"github.com/hashicorp/terraform-plugin-framework/path"
"github.com/hashicorp/terraform-plugin-framework/types"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry"
)

type dataSourceIncidentTypeCustomField struct{ client *pagerduty.Client }

var _ datasource.DataSourceWithConfigure = (*dataSourceIncidentTypeCustomField)(nil)

func (*dataSourceIncidentTypeCustomField) Metadata(_ context.Context, _ datasource.MetadataRequest, resp *datasource.MetadataResponse) {
resp.TypeName = "pagerduty_incident_type_custom_field"
}

func (*dataSourceIncidentTypeCustomField) Schema(ctx context.Context, req datasource.SchemaRequest, resp *datasource.SchemaResponse) {
resp.Schema = schema.Schema{
Attributes: map[string]schema.Attribute{
"id": schema.StringAttribute{Computed: true},
"incident_type": schema.StringAttribute{Required: true},
"display_name": schema.StringAttribute{Required: true},
"data_type": schema.StringAttribute{Computed: true},
"default_value": schema.StringAttribute{
Computed: true,
CustomType: jsontypes.NormalizedType{},
},
"description": schema.StringAttribute{Computed: true},
"enabled": schema.BoolAttribute{Computed: true},
"field_options": schema.ListAttribute{
Computed: true,
ElementType: incidentTypeFieldOptionObjectType,
},
"field_type": schema.StringAttribute{Computed: true},
"name": schema.StringAttribute{Computed: true},
"self": schema.StringAttribute{Computed: true},
"summary": schema.StringAttribute{Computed: true},
"type": schema.StringAttribute{Computed: true},
},
}
}

func (d *dataSourceIncidentTypeCustomField) Configure(ctx context.Context, req datasource.ConfigureRequest, resp *datasource.ConfigureResponse) {
resp.Diagnostics.Append(ConfigurePagerdutyClient(&d.client, req.ProviderData)...)
}

func (d *dataSourceIncidentTypeCustomField) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) {
var searchName types.String
diags := req.Config.GetAttribute(ctx, path.Root("display_name"), &searchName)
if resp.Diagnostics.Append(diags...); diags.HasError() {
return
}

var searchIncidentType types.String
diags = req.Config.GetAttribute(ctx, path.Root("incident_type"), &searchIncidentType)
if resp.Diagnostics.Append(diags...); diags.HasError() {
return
}
incidentTypeID := searchIncidentType.ValueString()

log.Printf("[INFO] Reading PagerDuty incident type custom field %s %s", searchIncidentType, searchName)

var found *pagerduty.IncidentTypeField
err := retry.RetryContext(ctx, 2*time.Minute, func() *retry.RetryError {
response, err := d.client.ListIncidentTypeFields(ctx, incidentTypeID, pagerduty.ListIncidentTypeFieldsOptions{
Includes: []string{"field_options"},
})
if err != nil {
if util.IsBadRequestError(err) {
return retry.NonRetryableError(err)
}
return retry.RetryableError(err)
}
for _, f := range response.Fields {
if f.DisplayName == searchName.ValueString() {
found = &f
break
}
}
return nil
})
if err != nil {
resp.Diagnostics.AddError(
fmt.Sprintf("Error reading PagerDuty incident type custom field %s", searchName),
err.Error(),
)
return
}

if found == nil {
resp.Diagnostics.AddError(
fmt.Sprintf("Unable to locate any incident type custom field with the name: %s", searchName),
"",
)
return
}

defaultValue, _ := json.Marshal(found.DefaultValue)

elements := make([]attr.Value, 0, len(found.FieldOptions))
for _, opt := range found.FieldOptions {
dataObj := types.ObjectNull(incidentTypeFieldOptionDataObjectType.AttrTypes)
if opt.Data != nil {
dataObj = types.ObjectValueMust(incidentTypeFieldOptionDataObjectType.AttrTypes, map[string]attr.Value{
"value": types.StringValue(opt.Data.Value),
"data_type": types.StringValue(opt.Data.DataType),
})
}
obj := types.ObjectValueMust(incidentTypeFieldOptionObjectType.AttrTypes, map[string]attr.Value{
"id": types.StringValue(opt.ID),
"type": types.StringValue(opt.Type),
"data": dataObj,
})
elements = append(elements, obj)
}
fieldOptions := types.ListValueMust(incidentTypeFieldOptionObjectType, elements)

model := dataSourceIncidentTypeCustomFieldModel{
ID: types.StringValue(found.ID),
IncidentType: types.StringValue(found.IncidentType),
DisplayName: types.StringValue(found.DisplayName),
DataType: types.StringValue(found.DataType),
DefaultValue: jsontypes.NewNormalizedValue(string(defaultValue)),
Description: types.StringValue(found.Description),
Enabled: types.BoolValue(found.Enabled),
FieldOptions: fieldOptions,
FieldType: types.StringValue(found.FieldType),
Name: types.StringValue(found.Name),
Self: types.StringValue(found.Self),
Summary: types.StringValue(found.Summary),
Type: types.StringValue(found.Type),
}
resp.Diagnostics.Append(resp.State.Set(ctx, &model)...)
}

type dataSourceIncidentTypeCustomFieldModel struct {
ID types.String `tfsdk:"id"`
IncidentType types.String `tfsdk:"incident_type"`
DisplayName types.String `tfsdk:"display_name"`
DataType types.String `tfsdk:"data_type"`
DefaultValue jsontypes.Normalized `tfsdk:"default_value"`
Description types.String `tfsdk:"description"`
Enabled types.Bool `tfsdk:"enabled"`
FieldOptions types.List `tfsdk:"field_options"`
FieldType types.String `tfsdk:"field_type"`
Name types.String `tfsdk:"name"`
Self types.String `tfsdk:"self"`
Summary types.String `tfsdk:"summary"`
Type types.String `tfsdk:"type"`
}

var incidentTypeFieldOptionDataObjectType = types.ObjectType{
AttrTypes: map[string]attr.Type{
"value": types.StringType,
"data_type": types.StringType,
},
}

var incidentTypeFieldOptionObjectType = types.ObjectType{
AttrTypes: map[string]attr.Type{
"id": types.StringType,
"type": types.StringType,
"data": incidentTypeFieldOptionDataObjectType,
},
}
4 changes: 4 additions & 0 deletions pagerdutyplugin/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ func (p *Provider) DataSources(_ context.Context) [](func() datasource.DataSourc
func() datasource.DataSource { return &dataSourceAlertGroupingSetting{} },
func() datasource.DataSource { return &dataSourceBusinessService{} },
func() datasource.DataSource { return &dataSourceExtensionSchema{} },
func() datasource.DataSource { return &dataSourceIncidentTypeCustomField{} },
func() datasource.DataSource { return &dataSourceIncidentType{} },
func() datasource.DataSource { return &dataSourceIntegration{} },
func() datasource.DataSource { return &dataSourceJiraCloudAccountMapping{} },
func() datasource.DataSource { return &dataSourceLicenses{} },
Expand All @@ -76,6 +78,8 @@ func (p *Provider) Resources(_ context.Context) [](func() resource.Resource) {
func() resource.Resource { return &resourceBusinessService{} },
func() resource.Resource { return &resourceExtensionServiceNow{} },
func() resource.Resource { return &resourceExtension{} },
func() resource.Resource { return &resourceIncidentTypeCustomField{} },
func() resource.Resource { return &resourceIncidentType{} },
func() resource.Resource { return &resourceJiraCloudAccountMappingRule{} },
func() resource.Resource { return &resourceServiceDependency{} },
func() resource.Resource { return &resourceTagAssignment{} },
Expand Down
Loading

0 comments on commit e751e11

Please sign in to comment.