-
Notifications
You must be signed in to change notification settings - Fork 216
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Migrate datasource and resource
pagerduty_tag
- Loading branch information
Showing
7 changed files
with
490 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
package pagerduty | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"log" | ||
|
||
"github.com/PagerDuty/go-pagerduty" | ||
"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" | ||
) | ||
|
||
type dataSourceTag struct { | ||
client *pagerduty.Client | ||
} | ||
|
||
var _ datasource.DataSourceWithConfigure = (*dataSourceStandards)(nil) | ||
|
||
func (d *dataSourceTag) Configure(ctx context.Context, req datasource.ConfigureRequest, resp *datasource.ConfigureResponse) { | ||
resp.Diagnostics.Append(ConfigurePagerdutyClient(&d.client, req.ProviderData)...) | ||
} | ||
|
||
func (d *dataSourceTag) Metadata(ctx context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) { | ||
resp.TypeName = "pagerduty_tag" | ||
} | ||
|
||
func (d *dataSourceTag) Schema(ctx context.Context, req datasource.SchemaRequest, resp *datasource.SchemaResponse) { | ||
resp.Schema = schema.Schema{ | ||
Attributes: map[string]schema.Attribute{ | ||
"label": schema.StringAttribute{ | ||
Required: true, | ||
Description: "The label of the tag to find in the PagerDuty API", | ||
}, | ||
"id": schema.StringAttribute{Computed: true}, | ||
}, | ||
} | ||
} | ||
|
||
func (d *dataSourceTag) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) { | ||
var searchTag string | ||
if d := req.Config.GetAttribute(ctx, path.Root("label"), &searchTag); d.HasError() { | ||
resp.Diagnostics.Append(d...) | ||
return | ||
} | ||
|
||
log.Printf("[INFO] Reading PagerDuty tag") | ||
|
||
// TODO: retry | ||
list, err := d.client.ListTags(pagerduty.ListTagOptions{Query: searchTag}) | ||
if err != nil { | ||
// TODO: if 400 non retryable | ||
resp.Diagnostics.AddError("Error calling ListTags", err.Error()) | ||
// TODO: wait 30 + retry | ||
return | ||
} | ||
|
||
var found *pagerduty.Tag | ||
|
||
for _, tag := range list.Tags { | ||
if tag.Label == searchTag { | ||
found = tag | ||
break | ||
} | ||
} | ||
|
||
if found == nil { | ||
// return retry.NonRetryableError( | ||
resp.Diagnostics.AddError( | ||
fmt.Sprintf("Unable to locate any tag with label: %s", searchTag), | ||
"", | ||
) | ||
return | ||
} | ||
|
||
model := dataSourceTagModel{ | ||
ID: types.StringValue(found.ID), | ||
Label: types.StringValue(found.Label), | ||
} | ||
resp.Diagnostics.Append(resp.State.Set(ctx, &model)...) | ||
} | ||
|
||
type dataSourceTagModel struct { | ||
ID types.String `tfsdk:"id"` | ||
Label types.String `tfsdk:"label"` | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
package pagerduty | ||
|
||
import ( | ||
"fmt" | ||
"testing" | ||
|
||
"github.com/hashicorp/terraform-plugin-testing/helper/acctest" | ||
"github.com/hashicorp/terraform-plugin-testing/helper/resource" | ||
"github.com/hashicorp/terraform-plugin-testing/terraform" | ||
) | ||
|
||
func TestAccDataSourcePagerDutyTag_Basic(t *testing.T) { | ||
tag := fmt.Sprintf("tf-%s", acctest.RandString(5)) | ||
|
||
resource.Test(t, resource.TestCase{ | ||
PreCheck: func() { testAccPreCheck(t) }, | ||
ProtoV5ProviderFactories: testAccProtoV5ProviderFactories(), | ||
Steps: []resource.TestStep{ | ||
{ | ||
Config: testAccDataSourcePagerDutyTagConfig(tag), | ||
Check: resource.ComposeTestCheckFunc( | ||
testAccDataSourcePagerDutyTag("pagerduty_tag.test", "data.pagerduty_tag.by_label"), | ||
), | ||
}, | ||
}, | ||
}) | ||
} | ||
|
||
func testAccDataSourcePagerDutyTag(src, n string) resource.TestCheckFunc { | ||
return func(s *terraform.State) error { | ||
srcR := s.RootModule().Resources[src] | ||
srcA := srcR.Primary.Attributes | ||
|
||
r := s.RootModule().Resources[n] | ||
a := r.Primary.Attributes | ||
|
||
if a["id"] == "" { | ||
return fmt.Errorf("Expected to get a tag ID from PagerDuty") | ||
} | ||
|
||
testAtts := []string{"id", "label"} | ||
|
||
for _, att := range testAtts { | ||
if a[att] != srcA[att] { | ||
return fmt.Errorf("Expected the tag %s to be: %s, but got: %s", att, srcA[att], a[att]) | ||
} | ||
} | ||
|
||
return nil | ||
} | ||
} | ||
|
||
func testAccDataSourcePagerDutyTagConfig(tag string) string { | ||
return fmt.Sprintf(` | ||
resource "pagerduty_tag" "test" { | ||
label = "%s" | ||
} | ||
data "pagerduty_tag" "by_label" { | ||
label = pagerduty_tag.test.label | ||
} | ||
`, tag) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,167 @@ | ||
package pagerduty | ||
|
||
import ( | ||
"context" | ||
"errors" | ||
"log" | ||
"time" | ||
|
||
"github.com/PagerDuty/go-pagerduty" | ||
"github.com/hashicorp/terraform-plugin-framework/path" | ||
"github.com/hashicorp/terraform-plugin-framework/resource" | ||
"github.com/hashicorp/terraform-plugin-framework/resource/schema" | ||
"github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier" | ||
"github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier" | ||
"github.com/hashicorp/terraform-plugin-framework/types" | ||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry" | ||
"github.com/terraform-providers/terraform-provider-pagerduty/util" | ||
) | ||
|
||
type resourceTag struct { | ||
client *pagerduty.Client | ||
} | ||
|
||
var ( | ||
_ resource.ResourceWithConfigure = (*resourceTag)(nil) | ||
_ resource.ResourceWithImportState = (*resourceTag)(nil) | ||
) | ||
|
||
func (r *resourceTag) Configure(ctx context.Context, req resource.ConfigureRequest, resp *resource.ConfigureResponse) { | ||
resp.Diagnostics.Append(ConfigurePagerdutyClient(&r.client, req.ProviderData)...) | ||
} | ||
|
||
func (r *resourceTag) Metadata(ctx context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) { | ||
resp.TypeName = "pagerduty_tag" | ||
} | ||
|
||
func (r *resourceTag) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { | ||
resp.Schema = schema.Schema{ | ||
Attributes: map[string]schema.Attribute{ | ||
"label": schema.StringAttribute{ | ||
Required: true, | ||
PlanModifiers: []planmodifier.String{ | ||
stringplanmodifier.RequiresReplace(), | ||
}, | ||
}, | ||
"html_url": schema.StringAttribute{Computed: true}, | ||
"id": schema.StringAttribute{Computed: true}, | ||
"summary": schema.StringAttribute{Computed: true}, | ||
}, | ||
} | ||
} | ||
|
||
func (r *resourceTag) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) { | ||
var model resourceTagModel | ||
if d := req.Config.Get(ctx, &model); d.HasError() { | ||
resp.Diagnostics.Append(d...) | ||
} | ||
tagBody := buildTag(&model) | ||
log.Printf("[INFO] Creating PagerDuty tag %s", tagBody.Label) | ||
|
||
err := retry.RetryContext(ctx, 2*time.Minute, func() *retry.RetryError { | ||
tag, err := r.client.CreateTagWithContext(ctx, tagBody) | ||
if err != nil { | ||
var apiErr pagerduty.APIError | ||
if errors.As(err, &apiErr) && apiErr.StatusCode == 400 { | ||
return retry.NonRetryableError(err) | ||
} | ||
return retry.RetryableError(err) | ||
} | ||
model = flattenTag(tag) | ||
return nil | ||
}) | ||
if err != nil { | ||
resp.Diagnostics.AddError("Error calling CreateTagWithContext", err.Error()) | ||
} | ||
resp.State.Set(ctx, &model) | ||
} | ||
|
||
func (r *resourceTag) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) { | ||
var tagID types.String | ||
if d := req.State.GetAttribute(ctx, path.Root("id"), &tagID); d.HasError() { | ||
resp.Diagnostics.Append(d...) | ||
} | ||
log.Printf("[INFO] Reading PagerDuty tag %s", tagID) | ||
|
||
var model resourceTagModel | ||
err := retry.RetryContext(ctx, 2*time.Minute, func() *retry.RetryError { | ||
tag, err := r.client.GetTagWithContext(ctx, tagID.ValueString()) | ||
if err != nil { | ||
if util.IsBadRequestError(err) { | ||
return retry.NonRetryableError(err) | ||
} | ||
if util.IsNotFoundError(err) { | ||
log.Printf("[WARN] Removing %s because it's gone", tagID.String()) | ||
resp.State.RemoveResource(ctx) | ||
return nil | ||
} | ||
return retry.RetryableError(err) | ||
} | ||
model = flattenTag(tag) | ||
return nil | ||
}) | ||
if err != nil { | ||
resp.Diagnostics.AddError("Error calling GetTagWithContext", err.Error()) | ||
} | ||
resp.State.Set(ctx, &model) | ||
} | ||
|
||
func (r *resourceTag) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) { | ||
} | ||
|
||
func (r *resourceTag) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) { | ||
var model resourceTagModel | ||
if d := req.State.Get(ctx, &model); d.HasError() { | ||
resp.Diagnostics.Append(d...) | ||
} | ||
log.Printf("[INFO] Removing PagerDuty tag %s", model.ID) | ||
|
||
err := retry.RetryContext(ctx, 2*time.Minute, func() *retry.RetryError { | ||
err := r.client.DeleteTagWithContext(ctx, model.ID.ValueString()) | ||
if err != nil { | ||
if util.IsBadRequestError(err) { | ||
return retry.NonRetryableError(err) | ||
} | ||
if util.IsNotFoundError(err) { | ||
resp.State.RemoveResource(ctx) | ||
return nil | ||
} | ||
return retry.RetryableError(err) | ||
} | ||
return nil | ||
}) | ||
if err != nil { | ||
resp.Diagnostics.AddError("Error calling DeleteTagWithContext", err.Error()) | ||
return | ||
} | ||
resp.State.RemoveResource(ctx) | ||
} | ||
|
||
func (r *resourceTag) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) { | ||
resource.ImportStatePassthroughID(ctx, path.Root("id"), req, resp) | ||
} | ||
|
||
type resourceTagModel struct { | ||
ID types.String `tfsdk:"id"` | ||
HtmlUrl types.String `tfsdk:"html_url"` | ||
Label types.String `tfsdk:"label"` | ||
Summary types.String `tfsdk:"summary"` | ||
} | ||
|
||
func buildTag(model *resourceTagModel) *pagerduty.Tag { | ||
tag := &pagerduty.Tag{ | ||
Label: model.Label.ValueString(), | ||
} | ||
tag.Type = "tag" | ||
return tag | ||
} | ||
|
||
func flattenTag(tag *pagerduty.Tag) resourceTagModel { | ||
model := resourceTagModel{ | ||
ID: types.StringValue(tag.ID), | ||
HtmlUrl: types.StringValue(tag.HTMLURL), | ||
Label: types.StringValue(tag.Label), | ||
Summary: types.StringValue(tag.Summary), | ||
} | ||
return model | ||
} |
Oops, something went wrong.