Skip to content

Commit

Permalink
Merge pull request #104 from planetscale/joem/fix-remaining-docs-on-s…
Browse files Browse the repository at this point in the history
…ervice-token-env-vars

chore: fix remaining service token environment variable docs
  • Loading branch information
joemiller authored Jan 24, 2025
2 parents bca1710 + badc3b1 commit 5b4dcac
Show file tree
Hide file tree
Showing 3 changed files with 113 additions and 7 deletions.
6 changes: 3 additions & 3 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ page_title: "planetscale Provider"
subcategory: ""
description: |-
The PlanetScale provider allows using the OpenAPI surface of our public API. To use this provider, one of the following are required:
access token credentials, configured or stored in the environment variable PLANETSCALE_ACCESS_TOKENservice token credentials, configured or stored in the environment variables PLANETSCALE_SERVICE_TOKEN_NAME and PLANETSCALE_SERVICE_TOKEN
access token credentials, configured or stored in the environment variable PLANETSCALE_ACCESS_TOKENservice token credentials, configured or stored in the environment variables PLANETSCALE_SERVICE_TOKEN_ID and PLANETSCALE_SERVICE_TOKEN
Note that the provider is not production ready and only for early testing at this time.
Known limitations:
Support for deployments, deploy queues, deploy requests and reverts is not implemented at this time. If you have a use case for it, please let us know in the repository issues.When using service tokens (recommended), ensure the token has the create_databases organization-level permission. This allows terraform to create new databases and automatically grants the token all other permissions on the databases created by the token.
Expand All @@ -15,7 +15,7 @@ description: |-
The PlanetScale provider allows using the OpenAPI surface of our public API. To use this provider, one of the following are required:

- access token credentials, configured or stored in the environment variable `PLANETSCALE_ACCESS_TOKEN`
- service token credentials, configured or stored in the environment variables `PLANETSCALE_SERVICE_TOKEN_NAME` and `PLANETSCALE_SERVICE_TOKEN`
- service token credentials, configured or stored in the environment variables `PLANETSCALE_SERVICE_TOKEN_ID` and `PLANETSCALE_SERVICE_TOKEN`

Note that the provider is not production ready and only for early testing at this time.

Expand Down Expand Up @@ -44,7 +44,7 @@ provider "planetscale" {

### Optional

- `access_token` (String, Sensitive) Name of the service token to use. Alternatively, use `PLANETSCALE_SERVICE_TOKEN_NAME`. Mutually exclusive with `service_token_name` and `service_token`.
- `access_token` (String, Sensitive) Name of the service token to use. Alternatively, use `PLANETSCALE_SERVICE_TOKEN_ID`. Mutually exclusive with `service_token_id` and `service_token`.
- `endpoint` (String) If set, points the API client to a different endpoint than `https:://api.planetscale.com/v1`.
- `service_token` (String, Sensitive) Value of the service token to use. Alternatively, use `PLANETSCALE_SERVICE_TOKEN`. Mutually exclusive with `access_token`.
- `service_token_id` (String) ID of the service token to use. Alternatively, use `PLANETSCALE_SERVICE_TOKEN_ID`. Mutually exclusive with `access_token`.
Expand Down
9 changes: 5 additions & 4 deletions internal/provider/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@ func (p *PlanetScaleProvider) Metadata(ctx context.Context, req provider.Metadat
func (p *PlanetScaleProvider) ConfigValidators(context.Context) []provider.ConfigValidator {
return []provider.ConfigValidator{
providervalidator.Conflicting(path.MatchRoot("access_token"), path.MatchRoot("service_token")),
providervalidator.Conflicting(path.MatchRoot("access_token"), path.MatchRoot("service_token_name")),
providervalidator.Conflicting(path.MatchRoot("access_token"), path.MatchRoot("service_token_id")),
providervalidator.Conflicting(path.MatchRoot("access_token"), path.MatchRoot("service_token_name")), // service_token_name is deprecated
}
}

Expand All @@ -57,7 +58,7 @@ func (p *PlanetScaleProvider) Schema(ctx context.Context, req provider.SchemaReq
MarkdownDescription: `The PlanetScale provider allows using the OpenAPI surface of our public API. To use this provider, one of the following are required:
- access token credentials, configured or stored in the environment variable ` + "`PLANETSCALE_ACCESS_TOKEN`" + `
- service token credentials, configured or stored in the environment variables ` + "`PLANETSCALE_SERVICE_TOKEN_NAME`" + ` and ` + "`PLANETSCALE_SERVICE_TOKEN`" + `
- service token credentials, configured or stored in the environment variables ` + "`PLANETSCALE_SERVICE_TOKEN_ID`" + ` and ` + "`PLANETSCALE_SERVICE_TOKEN`" + `
Note that the provider is not production ready and only for early testing at this time.
Expand All @@ -70,7 +71,7 @@ Known limitations:
Optional: true,
},
"access_token": schema.StringAttribute{
MarkdownDescription: "Name of the service token to use. Alternatively, use `PLANETSCALE_SERVICE_TOKEN_NAME`. Mutually exclusive with `service_token_name` and `service_token`.",
MarkdownDescription: "Name of the service token to use. Alternatively, use `PLANETSCALE_SERVICE_TOKEN_ID`. Mutually exclusive with `service_token_id` and `service_token`.",
Optional: true,
Sensitive: true,
Validators: []validator.String{
Expand Down Expand Up @@ -149,7 +150,7 @@ func (p *PlanetScaleProvider) Configure(ctx context.Context, req provider.Config
// Adding this to `resp.Diagnostics` ensures it will be printed during typical
// terraform operations, whereas logging with `tflog.Warn()` will only show if the
// users specifies the `TF_LOG` env var.
if serviceTokenName != "" && serviceTokenID == "" {
if serviceTokenName != "" {
resp.Diagnostics.AddWarning(
"Deprecated Configuration",
"PLANETSCALE_SERVICE_TOKEN_NAME is deprecated. Please use PLANETSCALE_SERVICE_TOKEN_ID instead.",
Expand Down
105 changes: 105 additions & 0 deletions internal/provider/provider_test.go
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
package provider

import (
"context"
"fmt"
"net/http"
"os"
"strconv"
"strings"
"testing"

"github.com/hashicorp/terraform-plugin-framework/provider"
"github.com/hashicorp/terraform-plugin-framework/providerserver"
"github.com/hashicorp/terraform-plugin-framework/tfsdk"
"github.com/hashicorp/terraform-plugin-go/tfprotov6"
"github.com/hashicorp/terraform-plugin-go/tftypes"
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
"github.com/planetscale/terraform-provider-planetscale/internal/client/planetscale"
"golang.org/x/oauth2"
Expand Down Expand Up @@ -86,3 +90,104 @@ func checkOneOf(values ...string) resource.CheckResourceAttrWithFunc {
return fmt.Errorf("value %q is not one of %s", value, strings.Join(values, ", "))
}
}

func TestProviderConfigure(t *testing.T) {
cases := map[string]struct {
config map[string]tftypes.Value
expectWarn bool
expectError bool
}{
"service_token_id only": {
config: map[string]tftypes.Value{
"service_token_name": tftypes.NewValue(tftypes.String, nil), // deprecated
"service_token_id": tftypes.NewValue(tftypes.String, "token123"),
"service_token": tftypes.NewValue(tftypes.String, "secret"),
"endpoint": tftypes.NewValue(tftypes.String, nil),
"access_token": tftypes.NewValue(tftypes.String, nil),
},
expectWarn: false,
expectError: false,
},

"both access_token and service_token specified": {
config: map[string]tftypes.Value{
"service_token_name": tftypes.NewValue(tftypes.String, nil), // deprecated
"service_token_id": tftypes.NewValue(tftypes.String, "token123"),
"service_token": tftypes.NewValue(tftypes.String, "secret"),
"endpoint": tftypes.NewValue(tftypes.String, nil),
"access_token": tftypes.NewValue(tftypes.String, "acctoken123"),
},
expectWarn: false,
expectError: true,
},

"deprecated service_token_name used": {
config: map[string]tftypes.Value{
"service_token_name": tftypes.NewValue(tftypes.String, "token123"), // deprecated
"service_token_id": tftypes.NewValue(tftypes.String, nil),
"service_token": tftypes.NewValue(tftypes.String, "secret"),
"endpoint": tftypes.NewValue(tftypes.String, nil),
"access_token": tftypes.NewValue(tftypes.String, nil),
},
expectWarn: true,
expectError: false,
},

"deprecated service_token_name is used with service_token_id": {
config: map[string]tftypes.Value{
"service_token_name": tftypes.NewValue(tftypes.String, "token123"), // deprecated
"service_token_id": tftypes.NewValue(tftypes.String, nil),
"service_token": tftypes.NewValue(tftypes.String, "secret"),
"endpoint": tftypes.NewValue(tftypes.String, nil),
"access_token": tftypes.NewValue(tftypes.String, nil),
},
expectWarn: true,
expectError: false,
},
}

for name, tc := range cases {
t.Run(name, func(t *testing.T) {
ctx := context.Background()
p := New("test", false)()

var schemaResp provider.SchemaResponse
p.Schema(ctx, provider.SchemaRequest{}, &schemaResp)

objectType := tftypes.Object{
AttributeTypes: map[string]tftypes.Type{
"endpoint": tftypes.String,
"access_token": tftypes.String,
"service_token_id": tftypes.String,
"service_token_name": tftypes.String,
"service_token": tftypes.String,
},
}

var req provider.ConfigureRequest
req.Config = tfsdk.Config{
Raw: tftypes.NewValue(objectType, tc.config),
Schema: schemaResp.Schema,
}
var resp provider.ConfigureResponse

p.Configure(ctx, req, &resp)

// t.Logf("Diagnostics: %v", resp.Diagnostics)

if tc.expectWarn && resp.Diagnostics.WarningsCount() == 0 {
t.Error("expected warning but got none")
}
if !tc.expectWarn && resp.Diagnostics.WarningsCount() != 0 {
t.Errorf("unexpected warning: %v", resp.Diagnostics)
}

if tc.expectError && !resp.Diagnostics.HasError() {
t.Error("expected error but got none")
}
if !tc.expectError && resp.Diagnostics.HasError() {
t.Errorf("unexpected error: %v", resp.Diagnostics)
}
})
}
}

0 comments on commit 5b4dcac

Please sign in to comment.