Skip to content
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
5 changes: 5 additions & 0 deletions GNUmakefile
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,10 @@ test:
testacc:
TF_ACC=1 go test $(TEST) -v $(TESTARGS) -timeout 120m

sweeper:
@echo "WARNING: This will destroy infrastructure. Use only in development accounts."
go test ./internal/provider -v -tags=sweep -sweep=all -sweep-allow-failures -timeout 120m

codegen:
curl $(SWAGGER_URL) -o schema/swagger.json
node tools/clean-swagger.js schema/swagger.json
Expand Down Expand Up @@ -127,6 +131,7 @@ help:
@echo " make docs - Generate documentation"
@echo " make test - Run unit tests"
@echo " make testacc - Run acceptance tests"
@echo " make sweeper - Delete resources created by acceptance tests. They have names starting with tf-"
@echo " make install - Install provider locally"
@echo " make release - Create local snapshot build"
@echo ""
Expand Down
3 changes: 2 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,14 @@ require (
github.com/hashicorp/logutils v1.0.0 // indirect
github.com/hashicorp/terraform-exec v0.23.1 // indirect
github.com/hashicorp/terraform-json v0.27.0 // indirect
github.com/hashicorp/terraform-plugin-framework v1.16.1 // indirect
github.com/hashicorp/terraform-plugin-framework v1.16.1
github.com/hashicorp/terraform-plugin-testing v1.13.3
github.com/hashicorp/terraform-registry-address v0.4.0 // indirect
github.com/hashicorp/terraform-svchost v0.1.1 // indirect
github.com/hashicorp/yamux v0.1.2 // indirect
github.com/huandu/xstrings v1.5.0 // indirect
github.com/invopop/yaml v0.3.1 // indirect
github.com/jianyuan/go-utils v0.0.0-20250223213401-62c93a9e0b6c
github.com/josharian/intern v1.0.0 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/mattn/go-colorable v0.1.14 // indirect
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,8 @@ github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOl
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
github.com/jhump/protoreflect v1.17.0 h1:qOEr613fac2lOuTgWN4tPAtLL7fUSbuJL5X5XumQh94=
github.com/jhump/protoreflect v1.17.0/go.mod h1:h9+vUUL38jiBzck8ck+6G/aeMX8Z4QUY/NiJPwPNi+8=
github.com/jianyuan/go-utils v0.0.0-20250223213401-62c93a9e0b6c h1:VG+sd6t1wnle1Rc9Z52CmsYuwhBkXcW+aPIHqcw9e0I=
github.com/jianyuan/go-utils v0.0.0-20250223213401-62c93a9e0b6c/go.mod h1:D1O+WiG+p0g3LExvWtPEn6+UDTKJoUxTfJxyM6Ya6+k=
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
github.com/juju/gnuflag v0.0.0-20171113085948-2ce1bb71843d/go.mod h1:2PavIy+JPciBPrBUjwbNvtwB6RQlve+hkpll6QSNmOE=
Expand Down
36 changes: 36 additions & 0 deletions internal/acctest/shared_client.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package acctest

import (
"log"
"os"

"github.com/rootlyhq/terraform-provider-rootly/v2/internal/apiclient"
"github.com/rootlyhq/terraform-provider-rootly/v2/meta"
rootly "github.com/rootlyhq/terraform-provider-rootly/v2/schema"
)

var (
TestApiHost string
TestApiToken string

SharedClient *rootly.ClientWithResponses
)

func init() {
if v := os.Getenv("ROOTLY_API_URL"); v != "" {
TestApiHost = v
} else {
TestApiHost = "https://api.rootly.com"
}

if v := os.Getenv("ROOTLY_API_TOKEN"); v != "" {
TestApiToken = v
}

_, client, err := apiclient.New(TestApiHost, TestApiToken, meta.GetVersion())
if err != nil {
log.Fatalln(err.Error())
}

SharedClient = client
}
27 changes: 27 additions & 0 deletions internal/apiclient/apiclient.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package apiclient

import (
"fmt"

"github.com/rootlyhq/terraform-provider-rootly/v2/client"
sdkv2_provider "github.com/rootlyhq/terraform-provider-rootly/v2/provider"
rootly "github.com/rootlyhq/terraform-provider-rootly/v2/schema"
)

func New(apiHost string, apiToken string, version string) (*client.Client, *rootly.ClientWithResponses, error) {
legacyClient, err := client.NewClient(apiHost, apiToken, sdkv2_provider.RootlyUserAgent(version))
if err != nil {
return nil, nil, fmt.Errorf("unable to create Rootly client: %v", err)
}

client, err := rootly.NewClientWithResponses(
apiHost,
// Piggyback on the legacy client's HTTP client. Inherits the same headers, authentication, and retry logic.
rootly.WithHTTPClient(legacyClient),
)
if err != nil {
return nil, nil, fmt.Errorf("unable to create Rootly client: %v", err)
}

return legacyClient, client, nil
}
16 changes: 3 additions & 13 deletions internal/provider/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import (
"github.com/hashicorp/terraform-plugin-framework/resource"
"github.com/hashicorp/terraform-plugin-framework/types"
"github.com/rootlyhq/terraform-provider-rootly/v2/client"
sdkv2_provider "github.com/rootlyhq/terraform-provider-rootly/v2/provider"
"github.com/rootlyhq/terraform-provider-rootly/v2/internal/apiclient"
rootly "github.com/rootlyhq/terraform-provider-rootly/v2/schema"
)

Expand Down Expand Up @@ -75,19 +75,9 @@ func (p *RootlyProvider) Configure(ctx context.Context, req provider.ConfigureRe
apiToken = v
}

legacyClient, err := client.NewClient(apiHost, apiToken, sdkv2_provider.RootlyUserAgent(p.version))
legacyClient, client, err := apiclient.New(apiHost, apiToken, p.version)
if err != nil {
resp.Diagnostics.AddError("Unable to create Rootly client", "Unable to authenticate user for authenticated Rootly client")
return
}

client, err := rootly.NewClientWithResponses(
apiHost,
// Piggyback on the legacy client's HTTP client. Inherits the same headers, authentication, and retry logic.
rootly.WithHTTPClient(legacyClient),
)
if err != nil {
resp.Diagnostics.AddError("Unable to create Rootly client", "Unable to authenticate user for authenticated Rootly client")
resp.Diagnostics.AddError("Unable to create Rootly client", err.Error())
return
}

Expand Down
5 changes: 5 additions & 0 deletions internal/provider/provider_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,15 @@ import (
"github.com/hashicorp/terraform-plugin-go/tfprotov6"
"github.com/hashicorp/terraform-plugin-mux/tf5to6server"
"github.com/hashicorp/terraform-plugin-mux/tf6muxserver"
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
"github.com/rootlyhq/terraform-provider-rootly/v2/meta"
sdkv2_provider "github.com/rootlyhq/terraform-provider-rootly/v2/provider"
)

func TestMain(m *testing.M) {
resource.TestMain(m)
}

var testAccProtoV6ProviderFactories = map[string]func() (tfprotov6.ProviderServer, error){
"rootly": func() (tfprotov6.ProviderServer, error) {
ctx := context.Background()
Expand Down
59 changes: 59 additions & 0 deletions internal/provider/resource_alert_route_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package provider

import (
"context"
"fmt"
"log"
"net/http"
"strings"

"github.com/hashicorp/terraform-plugin-testing/helper/resource"
"github.com/jianyuan/go-utils/ptr"
"github.com/rootlyhq/terraform-provider-rootly/v2/internal/acctest"
rootly "github.com/rootlyhq/terraform-provider-rootly/v2/schema"
)

func init() {
resource.AddTestSweepers("rootly_alert_route", &resource.Sweeper{
Name: "rootly_alert_route",
F: func(region string) error {
ctx := context.Background()

params := &rootly.ListAlertRoutesParams{
PageNumber: ptr.Ptr(1),
}

for {
httpResp, err := acctest.SharedClient.ListAlertRoutesWithResponse(ctx, params)
if err != nil {
return fmt.Errorf("Error getting alert routes, got error: %s", err)
} else if httpResp.StatusCode() != http.StatusOK {
return fmt.Errorf("Error getting alert routes, got status code: %d", httpResp.StatusCode())
} else if httpResp.ApplicationvndApiJSON200 == nil {
return fmt.Errorf("Error getting alert routes, got empty response")
}

for _, alertRoute := range httpResp.ApplicationvndApiJSON200.Data {
if strings.HasPrefix(alertRoute.Attributes.Name, "tf-") {
httpResp, err := acctest.SharedClient.DeleteAlertRouteWithResponse(ctx, alertRoute.Id)
if err != nil {
return fmt.Errorf("Error deleting alert route: %s", err)
} else if httpResp.StatusCode() != http.StatusOK {
return fmt.Errorf("Error deleting alert route, got status code: %d", httpResp.StatusCode())
}

log.Printf("[INFO] Deleted alert route %s", alertRoute.Attributes.Name)
}
}

if httpResp.ApplicationvndApiJSON200.Links.Next == nil {
break
}

params.PageNumber = ptr.Ptr(ptr.Value(params.PageNumber) + 1)
}

return nil
},
})
}
105 changes: 105 additions & 0 deletions internal/provider/resource_alert_urgency_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
package provider

import (
"context"
"fmt"
"log"
"net/http"
"strings"
"testing"

"github.com/hashicorp/terraform-plugin-testing/helper/resource"
"github.com/hashicorp/terraform-plugin-testing/knownvalue"
"github.com/hashicorp/terraform-plugin-testing/statecheck"
"github.com/hashicorp/terraform-plugin-testing/tfjsonpath"
"github.com/jianyuan/go-utils/ptr"
"github.com/rootlyhq/terraform-provider-rootly/v2/internal/acctest"
rootly "github.com/rootlyhq/terraform-provider-rootly/v2/schema"
)

func init() {
resource.AddTestSweepers("rootly_alert_urgency", &resource.Sweeper{
Name: "rootly_alert_urgency",
F: func(region string) error {
ctx := context.Background()

params := &rootly.ListAlertUrgenciesParams{
PageNumber: ptr.Ptr(1),
}

for {
httpResp, err := acctest.SharedClient.ListAlertUrgenciesWithResponse(ctx, params)
if err != nil {
return fmt.Errorf("Error getting alert urgencies, got error: %s", err)
} else if httpResp.StatusCode() != http.StatusOK {
return fmt.Errorf("Error getting alert urgencies, got status code: %d", httpResp.StatusCode())
} else if httpResp.ApplicationvndApiJSON200 == nil {
return fmt.Errorf("Error getting alert urgencies, got empty response")
}

for _, alertUrgency := range httpResp.ApplicationvndApiJSON200.Data {
if strings.HasPrefix(alertUrgency.Attributes.Name, "tf-") {
httpResp, err := acctest.SharedClient.DeleteAlertUrgencyWithResponse(ctx, alertUrgency.Id)
if err != nil {
return fmt.Errorf("Error deleting alert urgency: %s", err)
} else if httpResp.StatusCode() != http.StatusOK {
return fmt.Errorf("Error deleting alert urgency, got status code: %d", httpResp.StatusCode())
}

log.Printf("[INFO] Deleted alert urgency %s", alertUrgency.Attributes.Name)
}
}

if httpResp.ApplicationvndApiJSON200.Links.Next == nil {
break
}

params.PageNumber = ptr.Ptr(ptr.Value(params.PageNumber) + 1)
}

return nil
},
})
}

func TestAccResourceAlertUrgency(t *testing.T) {
resName := "rootly_alert_urgency.test"
alertUrgencyName := acctest.RandomWithPrefix("tf-alert-urgency")

configStateChecks := []statecheck.StateCheck{
statecheck.ExpectKnownValue(resName, tfjsonpath.New("id"), knownvalue.NotNull()),
statecheck.ExpectKnownValue(resName, tfjsonpath.New("position"), knownvalue.NotNull()),
}

resource.UnitTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
ProtoV6ProviderFactories: testAccProtoV6ProviderFactories,
Steps: []resource.TestStep{
{
Config: testAccResourceAlertUrgency(alertUrgencyName, "description"),
ConfigStateChecks: append(
configStateChecks,
statecheck.ExpectKnownValue(resName, tfjsonpath.New("name"), knownvalue.StringExact(alertUrgencyName)),
statecheck.ExpectKnownValue(resName, tfjsonpath.New("description"), knownvalue.StringExact("description")),
),
},
{
Config: testAccResourceAlertUrgency(alertUrgencyName+"-updated", "updated description"),
ConfigStateChecks: append(
configStateChecks,
statecheck.ExpectKnownValue(resName, tfjsonpath.New("name"), knownvalue.StringExact(alertUrgencyName+"-updated")),
statecheck.ExpectKnownValue(resName, tfjsonpath.New("description"), knownvalue.StringExact("updated description")),
),
},
},
})
}

func testAccResourceAlertUrgency(alertUrgencyName, alertUrgencyDescription string) string {
return fmt.Sprintf(`
resource "rootly_alert_urgency" "test" {
name = "%s"
description = "%s"
}
`, alertUrgencyName, alertUrgencyDescription)
}
59 changes: 59 additions & 0 deletions internal/provider/resource_alerts_source_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package provider

import (
"context"
"fmt"
"log"
"net/http"
"strings"

"github.com/hashicorp/terraform-plugin-testing/helper/resource"
"github.com/jianyuan/go-utils/ptr"
"github.com/rootlyhq/terraform-provider-rootly/v2/internal/acctest"
rootly "github.com/rootlyhq/terraform-provider-rootly/v2/schema"
)

func init() {
resource.AddTestSweepers("rootly_alerts_source", &resource.Sweeper{
Name: "rootly_alerts_source",
F: func(region string) error {
ctx := context.Background()

params := &rootly.ListAlertsSourcesParams{
PageNumber: ptr.Ptr(1),
}

for {
httpResp, err := acctest.SharedClient.ListAlertsSourcesWithResponse(ctx, params)
if err != nil {
return fmt.Errorf("Error getting alerts sources, got error: %s", err)
} else if httpResp.StatusCode() != http.StatusOK {
return fmt.Errorf("Error getting alerts sources, got status code: %d", httpResp.StatusCode())
} else if httpResp.ApplicationvndApiJSON200 == nil {
return fmt.Errorf("Error getting alerts sources, got empty response")
}

for _, alertSource := range httpResp.ApplicationvndApiJSON200.Data {
if strings.HasPrefix(alertSource.Attributes.Name, "tf-") {
httpResp, err := acctest.SharedClient.DeleteAlertsSourceWithResponse(ctx, alertSource.Id)
if err != nil {
return fmt.Errorf("Error deleting alerts source: %s", err)
} else if httpResp.StatusCode() != http.StatusOK {
return fmt.Errorf("Error deleting alerts source, got status code: %d", httpResp.StatusCode())
}

log.Printf("[INFO] Deleted alerts source %s", alertSource.Attributes.Name)
}
}

if httpResp.ApplicationvndApiJSON200.Links.Next == nil {
break
}

params.PageNumber = ptr.Ptr(ptr.Value(params.PageNumber) + 1)
}

return nil
},
})
}
Loading