diff --git a/docs/index.md b/docs/index.md index 83702f4..fe809e6 100644 --- a/docs/index.md +++ b/docs/index.md @@ -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" } ``` @@ -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. diff --git a/examples/provider/provider.tf b/examples/provider/provider.tf index 023cf62..1392434 100644 --- a/examples/provider/provider.tf +++ b/examples/provider/provider.tf @@ -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" } diff --git a/internal/provider/integration_data_source.go b/internal/provider/integration_data_source.go index ec0eef2..a721de0 100644 --- a/internal/provider/integration_data_source.go +++ b/internal/provider/integration_data_source.go @@ -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" @@ -21,7 +20,7 @@ var ( ) type integrationDataSource struct { - client *retryablehttp.Client + client *nangoClient } type nangoIntegrationResponse struct { @@ -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", @@ -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 diff --git a/internal/provider/integration_resource.go b/internal/provider/integration_resource.go index 3b65289..32ddf22 100644 --- a/internal/provider/integration_resource.go +++ b/internal/provider/integration_resource.go @@ -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. @@ -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", @@ -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", @@ -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(), @@ -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", @@ -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", @@ -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 diff --git a/internal/provider/provider.go b/internal/provider/provider.go index 3ccb964..91533bb 100644 --- a/internal/provider/provider.go +++ b/internal/provider/provider.go @@ -11,6 +11,7 @@ import ( "log" "net/http" "os" + "strings" "time" "github.com/hashicorp/go-retryablehttp" @@ -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. @@ -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.", + }, }, } } @@ -103,6 +115,15 @@ 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 @@ -110,8 +131,13 @@ func (p *nangoProvider) Configure(ctx context.Context, req provider.ConfigureReq 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.