Skip to content
Open
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
8 changes: 8 additions & 0 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ terraform {

provider "nango" {
environment_key = "your-nango-environment-key"

# Optional: Set the base URL for self-hosted Nango instances.
# Defaults to https://api.nango.dev. Can also be set via the NANGO_HOST environment variable.
# host = "https://nango.example.com"
}
```

Expand All @@ -33,3 +37,7 @@ provider "nango" {
### Required

- `environment_key` (String)

### Optional

- `host` (String) The base URL for the Nango API. Defaults to `https://api.nango.dev`. Can also be set via the `NANGO_HOST` environment variable.
4 changes: 4 additions & 0 deletions examples/provider/provider.tf
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,8 @@ terraform {

provider "nango" {
environment_key = "your-nango-environment-key"

# Optional: Set the base URL for self-hosted Nango instances.
# Defaults to https://api.nango.dev. Can also be set via the NANGO_HOST environment variable.
# host = "https://nango.example.com"
}
9 changes: 4 additions & 5 deletions internal/provider/integration_data_source.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import (
"encoding/json"
"fmt"

"github.com/hashicorp/go-retryablehttp"
"github.com/hashicorp/terraform-plugin-framework/datasource"
"github.com/hashicorp/terraform-plugin-framework/datasource/schema"
"github.com/hashicorp/terraform-plugin-framework/types"
Expand All @@ -21,7 +20,7 @@ var (
)

type integrationDataSource struct {
client *retryablehttp.Client
client *nangoClient
}

type nangoIntegrationResponse struct {
Expand Down Expand Up @@ -131,7 +130,7 @@ func (d *integrationDataSource) Schema(_ context.Context, _ datasource.SchemaReq
func (d *integrationDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) {
var state integrationDataSourceModel

integrationsResponse, err := d.client.Get("https://api.nango.dev/integrations")
integrationsResponse, err := d.client.client.Get(d.client.baseURL + "/integrations")
if err != nil {
resp.Diagnostics.AddError(
"Unable to Read Integrations",
Expand Down Expand Up @@ -178,11 +177,11 @@ func (d *integrationDataSource) Configure(_ context.Context, req datasource.Conf
return
}

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

return
Expand Down
21 changes: 11 additions & 10 deletions internal/provider/integration_resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ type integrationCredentialsRequestModel struct {

// integrationResource is the resource implementation.
type integrationResource struct {
client *retryablehttp.Client
client *nangoClient
}

// Metadata returns the resource type name.
Expand Down Expand Up @@ -139,7 +139,7 @@ func (r *integrationResource) Create(ctx context.Context, req resource.CreateReq
}

// Create a new request with the JSON body
_, err = r.client.Post("https://api.nango.dev/integrations", "application/json", requestBody)
_, err = r.client.client.Post(r.client.baseURL+"/integrations", "application/json", requestBody)
if err != nil {
resp.Diagnostics.AddError(
"Unable to Create Integration",
Expand All @@ -148,7 +148,7 @@ func (r *integrationResource) Create(ctx context.Context, req resource.CreateReq
return
}

getResponse, gErr := r.client.Get("https://api.nango.dev/integrations/" + plan.UniqueKey.ValueString() + "?include=webhook&include=credentials")
getResponse, gErr := r.client.client.Get(r.client.baseURL + "/integrations/" + plan.UniqueKey.ValueString() + "?include=webhook&include=credentials")
if gErr != nil {
resp.Diagnostics.AddError(
"Unable to Get Integration",
Expand Down Expand Up @@ -191,8 +191,9 @@ func (r *integrationResource) Read(ctx context.Context, req resource.ReadRequest
}

// Get refreshed integration value from Nango, including credentials/scopes
integrationResponse, err := r.client.Get("https://api.nango.dev/integrations/" + state.UniqueKey.ValueString() + "?include=credentials")
if err != nil {
integrationResponse, err := r.client.client.Get(r.client.baseURL + "/integrations/" + state.UniqueKey.ValueString() + "?include=credentials")

if err != nil {
resp.Diagnostics.AddError(
"Error Reading Nango Integration",
"Could not read Nango integration "+state.UniqueKey.ValueString()+": "+err.Error(),
Expand Down Expand Up @@ -275,7 +276,7 @@ func (r *integrationResource) Update(ctx context.Context, req resource.UpdateReq
}

// Create a PATCH request to update the integration
req2, err := retryablehttp.NewRequest("PATCH", "https://api.nango.dev/integrations/"+plan.UniqueKey.ValueString(), requestBody)
req2, err := retryablehttp.NewRequest("PATCH", r.client.baseURL+"/integrations/"+plan.UniqueKey.ValueString(), requestBody)
if err != nil {
resp.Diagnostics.AddError(
"Unable to Create Request",
Expand All @@ -285,7 +286,7 @@ func (r *integrationResource) Update(ctx context.Context, req resource.UpdateReq
}
req2.Header.Set("Content-Type", "application/json")

response, err := r.client.Do(req2)
response, err := r.client.client.Do(req2)
if err != nil {
resp.Diagnostics.AddError(
"Unable to Update Integration",
Expand Down Expand Up @@ -344,12 +345,12 @@ func (r *integrationResource) Configure(_ context.Context, req resource.Configur
return
}

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

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

return
Expand Down
30 changes: 28 additions & 2 deletions internal/provider/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"log"
"net/http"
"os"
"strings"
"time"

"github.com/hashicorp/go-retryablehttp"
Expand All @@ -37,6 +38,13 @@ func New(version string) func() provider.Provider {

type nangoProviderMdoel struct {
EnvironmentKey types.String `tfsdk:"environment_key"`
Host types.String `tfsdk:"host"`
}

// nangoClient wraps the HTTP client and base URL for the Nango API.
type nangoClient struct {
client *retryablehttp.Client
baseURL string
}

// nangoProvider is the provider implementation.
Expand All @@ -60,6 +68,10 @@ func (p *nangoProvider) Schema(_ context.Context, _ provider.SchemaRequest, resp
"environment_key": schema.StringAttribute{
Required: true,
},
"host": schema.StringAttribute{
Optional: true,
MarkdownDescription: "The base URL for the Nango API. Defaults to `https://api.nango.dev`. Can also be set via the `NANGO_HOST` environment variable.",
},
},
}
}
Expand Down Expand Up @@ -103,15 +115,29 @@ func (p *nangoProvider) Configure(ctx context.Context, req provider.ConfigureReq
return
}

host := os.Getenv("NANGO_HOST")
if !config.Host.IsNull() && !config.Host.IsUnknown() {
host = config.Host.ValueString()
}
if host == "" {
host = "https://api.nango.dev"
}
host = strings.TrimRight(host, "/")

retryClient := retryablehttp.NewClient()
retryClient.RetryMax = 3 // Maximum retry attempts
retryClient.RetryWaitMin = 1 * time.Second // Minimum wait time between retries
retryClient.RetryWaitMax = 5 * time.Second // Maximum wait time between retries
retryClient.HTTPClient.Timeout = 30 * time.Second // Set the timeout for the HTTP client
retryClient.HTTPClient.Transport = &myTransport{authKey: environmentKey, next: retryClient.HTTPClient.Transport}

resp.DataSourceData = retryClient
resp.ResourceData = retryClient
nc := &nangoClient{
client: retryClient,
baseURL: host,
}

resp.DataSourceData = nc
resp.ResourceData = nc
}

// DataSources defines the data sources implemented in the provider.
Expand Down