Skip to content

Commit

Permalink
add instrumentation to inject user-agent header;
Browse files Browse the repository at this point in the history
update changelog;
update neon sdk.

Signed-off-by: Dmitry Kisler <admin@dkisler.com>
  • Loading branch information
kislerdm committed Nov 3, 2024
2 parents 9407da7 + b884880 commit f1662ae
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 56 deletions.
2 changes: 1 addition & 1 deletion GNUmakefile
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ help: ## Prints help message.
default: help

build:
@ go build -a -gcflags=all="-l -B -C" -ldflags="-w -s" -o ${BINARY} .
@ go build -a -gcflags=all="-l -B -C" -ldflags="-w -s -X main.version=$(VERSION)" -o ${BINARY} .

install: build ## Builds and installs the provider.
@ mkdir -p ~/.terraform.d/plugins/local/${NAMESPACE}/${NAME}/${VERSION}/${OS_ARCH}
Expand Down
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,10 @@ make build
make install
```

## Updating the Provider

When updating your provider version, avoid using `terraform init -upgrade` in CI pipelines and auto-approved pull requests, as this can lead to unintended resource replacements and data loss. Instead, use `terraform init` in your automated workflows. Running `terraform init -upgrade` should always be done manually, followed by plan reviews. For additional guidance, see [Important usage notes](https://neon.tech/docs/reference/terraform#important-usage-notes) in the Neon documentation.

## Local development

### Requirements
Expand Down
2 changes: 0 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -122,8 +122,6 @@ github.com/jhump/protoreflect v1.15.1 h1:HUMERORf3I3ZdX05WaQ6MIpd/NJ434hTp5YiKgf
github.com/jhump/protoreflect v1.15.1/go.mod h1:jD/2GMKKE6OqX8qTjhADU1e6DShO+gavG9e0Q693nKo=
github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4=
github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
github.com/kislerdm/neon-sdk-go v0.6.1 h1:ILnqrZzRsjbAnxXOx3wb9HKUGR21pv14Y7U3yibUN00=
github.com/kislerdm/neon-sdk-go v0.6.1/go.mod h1:WSwEZ7oeR5KfQoCuDh/04LZxnSKDcvfsZyfG/QicDb8=
github.com/kislerdm/neon-sdk-go v0.7.0 h1:Xboh1mZO0jM8ss6u6iuVBkgBk9rXeq0PyoNisxi/fUA=
github.com/kislerdm/neon-sdk-go v0.7.0/go.mod h1:WSwEZ7oeR5KfQoCuDh/04LZxnSKDcvfsZyfG/QicDb8=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
Expand Down
97 changes: 49 additions & 48 deletions internal/provider/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ import (
neon "github.com/kislerdm/neon-sdk-go"
)

const PluginName = "kislerdm/neon"

type delay struct {
delay time.Duration
maxCnt uint8
Expand Down Expand Up @@ -64,16 +66,55 @@ func init() {
schema.DescriptionKind = schema.StringMarkdown
}

func newDev() *schema.Provider {
return New("dev")
func configureSDK(version string) schema.ConfigureContextFunc {
return func(ctx context.Context, d *schema.ResourceData) (interface{}, diag.Diagnostics) {
cfg := neon.Config{
Key: d.Get("api_key").(string),
}

switch version {
case "dev":
cfg.HTTPClient = neon.NewMockHTTPClient()

default:
cfg.HTTPClient = httpClientWithUserAgent{
// The default timeout is set arbitrary to ensure the connection is shut during resources state update
httpClient: &http.Client{Timeout: 2 * time.Minute},
telemetryHeader: newTelemetryHeader(version, p.TerraformVersion),
}
}

c, err := neon.NewClient(cfg)

return c, diag.FromErr(err)
}
}

func newTelemetryHeader(version string, platformVersion string) string {
const platform = "terraform"
return fmt.Sprintf("tfProvider-%s@%s (%s@%s)", PluginName, version, platform, platformVersion)
}

type httpClientWithUserAgent struct {
httpClient neon.HTTPClient
telemetryHeader string
}

func New(version string) *schema.Provider {
return newWithClient(version, nil)
func (h httpClientWithUserAgent) Do(r *http.Request) (*http.Response, error) {
if r.Header == nil {
r.Header = make(http.Header)
}

r.Header.Set("User-Agent", h.telemetryHeader)

return h.httpClient.Do(r)
}

func newWithClient(version string, customHTTPClient neon.HTTPClient) *schema.Provider {
return &schema.Provider{
// singletons to be able to configure telemetry headers when GRPCProviderServer.ConfigureProvider is called.
var p *schema.Provider

func NewFactory(version string) func() *schema.Provider {
p = &schema.Provider{
Schema: map[string]*schema.Schema{
"api_key": {
Type: schema.TypeString,
Expand All @@ -97,48 +138,8 @@ func newWithClient(version string, customHTTPClient neon.HTTPClient) *schema.Pro
"neon_branch_roles": dataSourceBranchRoles(),
"neon_branch_role_password": dataSourceBranchRolePassword(),
},
ConfigureContextFunc: configure(version, customHTTPClient),
ConfigureContextFunc: configureSDK(version),
}
}

func configure(version string, httpClient neon.HTTPClient) schema.ConfigureContextFunc {
return func(ctx context.Context, d *schema.ResourceData) (interface{}, diag.Diagnostics) {
cfg := neon.Config{
Key: d.Get("api_key").(string),
}

switch version {
case "dev":
cfg.HTTPClient = neon.NewMockHTTPClient()

default:
if httpClient == nil {
// The default timeout is set arbitrary to ensure the connection is shut during resources state update
httpClient = &http.Client{Timeout: 2 * time.Minute}
}

// Wrap the HTTP client into the client which injects the User-Agent header for tracing.
cfg.HTTPClient = httpClientWithUserAgent{httpClient: httpClient, providerVersion: version}
}

c, err := neon.NewClient(cfg)

return c, diag.FromErr(err)
}
}

type httpClientWithUserAgent struct {
httpClient neon.HTTPClient

providerVersion string
}

const DefaultApplicationName = "kislerdm/neon"

func (h httpClientWithUserAgent) Do(r *http.Request) (*http.Response, error) {
if r.Header == nil {
r.Header = make(http.Header)
}
r.Header.Set("User-Agent", fmt.Sprintf("tfProvider-%s@%s", DefaultApplicationName, h.providerVersion))
return h.httpClient.Do(r)
return func() *schema.Provider { return p }
}
7 changes: 2 additions & 5 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package main
import (
"flag"

"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/v2/plugin"
"github.com/kislerdm/terraform-provider-neon/internal/provider"
)
Expand Down Expand Up @@ -33,11 +32,9 @@ func main() {
opts := &plugin.ServeOpts{
Debug: debugMode,

ProviderAddr: "registry.terraform.io/" + provider.DefaultApplicationName,
ProviderAddr: "registry.terraform.io/" + provider.PluginName,

ProviderFunc: func() *schema.Provider {
return provider.New(version)
},
ProviderFunc: provider.NewFactory(version),
}

plugin.Serve(opts)
Expand Down

0 comments on commit f1662ae

Please sign in to comment.