Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ref: Migrate organization integration data source to plugin framework #351

Merged
merged 2 commits into from
Dec 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions docs/data-sources/organization_integration.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@
page_title: "sentry_organization_integration Data Source - terraform-provider-sentry"
subcategory: ""
description: |-
Sentry Organization Integration data source.
Sentry Organization Integration data source. See the Sentry documentation https://docs.sentry.io/api/integrations/list-an-organizations-available-integrations/ for more information.
---

# sentry_organization_integration (Data Source)

Sentry Organization Integration data source.
Sentry Organization Integration data source. See the [Sentry documentation](https://docs.sentry.io/api/integrations/list-an-organizations-available-integrations/) for more information.

## Example Usage

Expand All @@ -35,13 +35,13 @@ data "sentry_organization_integration" "slack" {

### Required

- `name` (String) The name of the organization integration.
- `organization` (String) The slug of the organization the integration belongs to.
- `provider_key` (String) The key of the organization integration provider.
- `name` (String) The name of the integration.
- `organization` (String) The slug of the organization.
- `provider_key` (String) Specific integration provider to filter by such as `slack`. See [the list of supported providers](https://docs.sentry.io/product/integrations/).

### Read-Only

- `id` (String) The ID of this resource.
- `internal_id` (String) The internal ID for this organization integration.
- `internal_id` (String, Deprecated) The internal ID for this organization integration. **Deprecated** Use `id` instead.


141 changes: 141 additions & 0 deletions internal/provider/data_source_organization_integration.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
package provider

import (
"context"
"fmt"

"github.com/hashicorp/terraform-plugin-framework/datasource"
"github.com/hashicorp/terraform-plugin-framework/datasource/schema"
"github.com/hashicorp/terraform-plugin-framework/types"
"github.com/jianyuan/go-sentry/v2/sentry"
)

var _ datasource.DataSource = &OrganizationIntegrationDataSource{}

func NewOrganizationIntegrationDataSource() datasource.DataSource {
return &OrganizationIntegrationDataSource{}
}

type OrganizationIntegrationDataSource struct {
client *sentry.Client
}

type OrganizationIntegrationDataSourceModel struct {
Id types.String `tfsdk:"id"`
InternalId types.String `tfsdk:"internal_id"`
Organization types.String `tfsdk:"organization"`
ProviderKey types.String `tfsdk:"provider_key"`
Name types.String `tfsdk:"name"`
}

func (m *OrganizationIntegrationDataSourceModel) Fill(organizationSlug string, d sentry.OrganizationIntegration) error {
m.Id = types.StringValue(d.ID)
m.InternalId = types.StringValue(d.ID)
m.Organization = types.StringValue(organizationSlug)
m.ProviderKey = types.StringValue(d.Provider.Key)
m.Name = types.StringValue(d.Name)

return nil
}

func (d *OrganizationIntegrationDataSource) Metadata(ctx context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) {
resp.TypeName = req.ProviderTypeName + "_organization_integration"
}

func (d *OrganizationIntegrationDataSource) Schema(ctx context.Context, req datasource.SchemaRequest, resp *datasource.SchemaResponse) {
resp.Schema = schema.Schema{
MarkdownDescription: "Sentry Organization Integration data source. See the [Sentry documentation](https://docs.sentry.io/api/integrations/list-an-organizations-available-integrations/) for more information.",

Attributes: map[string]schema.Attribute{
"id": schema.StringAttribute{
Description: "The ID of this resource.",
Computed: true,
},
"internal_id": schema.StringAttribute{
MarkdownDescription: "The internal ID for this organization integration. **Deprecated** Use `id` instead.",
Computed: true,
DeprecationMessage: "This field is deprecated and will be removed in a future version. Use `id` instead.",
},
"organization": schema.StringAttribute{
Description: "The slug of the organization.",
Required: true,
},
"provider_key": schema.StringAttribute{
Description: "Specific integration provider to filter by such as `slack`. See [the list of supported providers](https://docs.sentry.io/product/integrations/).",
Required: true,
},
"name": schema.StringAttribute{
Description: "The name of the integration.",
Required: true,
},
},
}
}

func (d *OrganizationIntegrationDataSource) Configure(ctx context.Context, req datasource.ConfigureRequest, resp *datasource.ConfigureResponse) {
// Prevent panic if the provider has not been configured.
if req.ProviderData == nil {
return
}

client, ok := req.ProviderData.(*sentry.Client)

if !ok {
resp.Diagnostics.AddError(
"Unexpected Data Source Configure Type",
fmt.Sprintf("Expected *sentry.Client, got: %T. Please report this issue to the provider developers.", req.ProviderData),
)

return
}

d.client = client
}

func (d *OrganizationIntegrationDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) {
var data OrganizationIntegrationDataSourceModel

resp.Diagnostics.Append(req.Config.Get(ctx, &data)...)
if resp.Diagnostics.HasError() {
return
}

var matchedIntegrations []*sentry.OrganizationIntegration
params := &sentry.ListOrganizationIntegrationsParams{
ListCursorParams: sentry.ListCursorParams{},
ProviderKey: data.ProviderKey.ValueString(),
}
for {
integrations, apiResp, err := d.client.OrganizationIntegrations.List(ctx, data.Organization.ValueString(), params)
if err != nil {
resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to read organization integrations, got error: %s", err))
return
}

for _, integration := range integrations {
if integration.Name == data.Name.ValueString() {
matchedIntegrations = append(matchedIntegrations, integration)
}
}

if apiResp.Cursor == "" {
break
}
params.ListCursorParams.Cursor = apiResp.Cursor
}

if len(matchedIntegrations) == 0 {
resp.Diagnostics.AddError("Not Found", "No matching organization integrations found")
return
} else if len(matchedIntegrations) > 1 {
resp.Diagnostics.AddError("Not Unique", "More than one matching organization integration found")
return
}

if err := data.Fill(data.Organization.ValueString(), *matchedIntegrations[0]); err != nil {
resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to read organization integration, got error: %s", err))
return
}

resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
}
68 changes: 68 additions & 0 deletions internal/provider/data_source_organization_integration_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package provider

import (
"testing"

"github.com/hashicorp/terraform-plugin-testing/helper/resource"
"github.com/jianyuan/terraform-provider-sentry/internal/acctest"
)

func TestAccOrganizationIntegrationDataSource(t *testing.T) {
dsn := "data.sentry_organization_integration.test"

resource.Test(t, resource.TestCase{
PreCheck: func() { acctest.PreCheck(t) },
ProtoV6ProviderFactories: testAccProtoV6ProviderFactories,
Steps: []resource.TestStep{
{
Config: testAccOrganizationIntegrationDataSourceConfig,
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttrSet(dsn, "id"),
resource.TestCheckResourceAttrPair(dsn, "internal_id", dsn, "id"),
resource.TestCheckResourceAttr(dsn, "organization", acctest.TestOrganization),
resource.TestCheckResourceAttr(dsn, "provider_key", "github"),
resource.TestCheckResourceAttr(dsn, "name", "jianyuan"),
),
},
},
})
}

func TestAccOrganizationIntegrationDataSource_MigrateFromPluginSDK(t *testing.T) {
dsn := "data.sentry_organization_integration.test"

resource.Test(t, resource.TestCase{
PreCheck: func() { acctest.PreCheck(t) },
Steps: []resource.TestStep{
{
ExternalProviders: map[string]resource.ExternalProvider{
acctest.ProviderName: {
Source: "jianyuan/sentry",
VersionConstraint: "0.11.2",
},
},
Config: testAccOrganizationIntegrationDataSourceConfig,
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttrSet(dsn, "id"),
resource.TestCheckResourceAttrPair(dsn, "internal_id", dsn, "id"),
resource.TestCheckResourceAttr(dsn, "organization", acctest.TestOrganization),
resource.TestCheckResourceAttr(dsn, "provider_key", "github"),
resource.TestCheckResourceAttr(dsn, "name", "jianyuan"),
),
},
{
ProtoV6ProviderFactories: testAccProtoV6ProviderFactories,
Config: testAccOrganizationIntegrationDataSourceConfig,
PlanOnly: true,
},
},
})
}

var testAccOrganizationIntegrationDataSourceConfig = testAccOrganizationDataSourceConfig + `
data "sentry_organization_integration" "test" {
organization = data.sentry_organization.test.id
provider_key = "github"
name = "jianyuan"
}
`
4 changes: 3 additions & 1 deletion internal/provider/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,9 @@ func (p *SentryProvider) Resources(ctx context.Context) []func() resource.Resour
}

func (p *SentryProvider) DataSources(ctx context.Context) []func() datasource.DataSource {
return []func() datasource.DataSource{}
return []func() datasource.DataSource{
NewOrganizationIntegrationDataSource,
}
}

func New(version string) func() provider.Provider {
Expand Down
85 changes: 0 additions & 85 deletions sentry/data_source_sentry_organization_integration.go

This file was deleted.

15 changes: 7 additions & 8 deletions sentry/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,14 +53,13 @@ func NewProvider(version string) func() *schema.Provider {
},

DataSourcesMap: map[string]*schema.Resource{
"sentry_dashboard": dataSourceSentryDashboard(),
"sentry_issue_alert": dataSourceSentryIssueAlertSentryIssueAlert(),
"sentry_key": dataSourceSentryKey(),
"sentry_metric_alert": dataSourceSentryMetricAlert(),
"sentry_organization": dataSourceSentryOrganization(),
"sentry_organization_integration": dataSourceSentryOrganizationIntegration(),
"sentry_team": dataSourceSentryTeam(),
"sentry_project": dataSourceSentryProject(),
"sentry_dashboard": dataSourceSentryDashboard(),
"sentry_issue_alert": dataSourceSentryIssueAlertSentryIssueAlert(),
"sentry_key": dataSourceSentryKey(),
"sentry_metric_alert": dataSourceSentryMetricAlert(),
"sentry_organization": dataSourceSentryOrganization(),
"sentry_team": dataSourceSentryTeam(),
"sentry_project": dataSourceSentryProject(),
},
}

Expand Down
Loading