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
5 changes: 5 additions & 0 deletions GNUmakefile
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ OS := $(shell uname | tr '[:upper:]' '[:lower:]')
VERSION := $(shell go run ${PKG_NAME}/version.go)
SHA := $(shell git rev-parse --short HEAD)
FILE_NAME=terraform-provider-${PKG_NAME}_v${VERSION}
GOPATH := $(shell go env GOPATH)

default: build

Expand All @@ -15,6 +16,7 @@ build: fmtcheck
install: fmtcheck
make fmt
make build
mkdir -p ~/.terraform.d/plugins/${OS}_amd64/
cp ${GOPATH}/bin/terraform-provider-${PKG_NAME} ~/.terraform.d/plugins/${OS}_amd64/${FILE_NAME}

release: fmtcheck
Expand All @@ -28,6 +30,9 @@ test: fmtcheck
testacc: fmtcheck
TF_ACC=1 go test $(TEST) -v $(TESTARGS) -timeout 120m -ldflags="-X=github.com/davidji99/terraform-provider-${PKG_NAME}/version.ProviderVersion=test"

testaccseq: fmtcheck
TF_ACC=1 go test $(TEST) -v $(TESTARGS) -timeout 120m -parallel=1 -ldflags="-X=github.com/davidji99/terraform-provider-${PKG_NAME}/version.ProviderVersion=test"

vet:
@echo "go vet ."
@go vet $$(go list ./... | grep -v vendor/) ; if [ $$? -eq 1 ]; then \
Expand Down
22 changes: 22 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,31 @@ Usage
```hcl
provider "split" {
version = "~> 0.1.0"

# Use either api_key (default) for Bearer token authentication
api_key = "YOUR_API_KEY"

# OR use harness_token for x-api-key header authentication
# harness_token = "YOUR_HARNESS_TOKEN"
}
```

### Authentication Options

This provider supports two authentication methods:

1. **API Key Authentication (Default)**: Uses a Bearer token in the Authorization header.
- Set via the `api_key` parameter or the `SPLIT_API_KEY` environment variable.

2. **Harness Token Authentication**: Uses the `x-api-key` header for authentication.
- Set via the `harness_token` parameter or the `HARNESS_TOKEN` environment variable.
- When this authentication method is used, the following resources are deprecated and cannot be used:
- `split_user`
- `split_group`
- `split_workspace`
- `split_api_key` (only when `type = "admin"`)


Releases
------------

Expand Down
12 changes: 11 additions & 1 deletion api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,10 +131,20 @@ func (c *Client) setHeaders() {
c.http.SetHeader("Content-type", c.config.ContentTypeHeader).
SetHeader("Accept", c.config.AcceptHeader).
SetHeader("User-Agent", c.config.UserAgent).
SetHeader("Authorization", fmt.Sprintf("Bearer %s", c.config.APIKey)).
SetTimeout(2 * time.Minute).
SetAllowGetMethodPayload(true)

// Add authentication headers based on what's available
if c.config.HarnessToken != "" {
// Use x-api-key header with harness_token when it's provided
log.Printf("[DEBUG] Using x-api-key header for authentication")
c.http.SetHeader("x-api-key", c.config.HarnessToken)
} else if c.config.APIKey != "" {
// Otherwise use Bearer token with API key
log.Printf("[DEBUG] Using Bearer token for authentication")
c.http.SetHeader("Authorization", fmt.Sprintf("Bearer %s", c.config.APIKey))
}

// Set additional headers
if c.config.CustomHTTPHeaders != nil {
c.http.SetHeaders(c.config.CustomHTTPHeaders)
Expand Down
3 changes: 3 additions & 0 deletions api/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ type Config struct {
// APIKey
APIKey string

// HarnessToken is used for x-api-key header authentication
HarnessToken string

// ClientTimeout
ClientTimeout int
}
Expand Down
8 changes: 8 additions & 0 deletions api/config_option.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,3 +75,11 @@ func AcceptHeader(s string) Option {
return nil
}
}

// HarnessToken sets the Harness token for x-api-key header authentication.
func HarnessToken(token string) Option {
return func(c *Config) error {
c.HarnessToken = token
return nil
}
}
2 changes: 2 additions & 0 deletions helper/test/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ const (
TestConfigSplitEnvironmentID
TestConfigSplitTrafficTypeID
TestConfigSplitUserEmail
TestConfigSplitHarnessToken
TestConfigAcceptanceTestKey
)

Expand All @@ -28,6 +29,7 @@ var testConfigKeyToEnvName = map[TestConfigKey]string{
TestConfigSplitWorkspaceName: "SPLIT_WORKSPACE_NAME",
TestConfigSplitEnvironmentID: "SPLIT_ENVIRONMENT_ID",
TestConfigSplitUserEmail: "SPLIT_USER_EMAIL",
TestConfigSplitHarnessToken: "HARNESS_TOKEN",
TestConfigAcceptanceTestKey: resource.EnvTfAcc,
}

Expand Down
30 changes: 25 additions & 5 deletions split/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,9 @@ type Config struct {
API *api.Client
Headers map[string]string

apiKey string
apiBaseURL string
apiKey string
harnessToken string
apiBaseURL string

clientTimeout int

Expand All @@ -32,9 +33,23 @@ func NewConfig() *Config {
}

func (c *Config) initializeAPI() error {
api, clientInitErr := api.New(api.APIKey(c.apiKey),
api.APIBaseURL(c.apiBaseURL), api.UserAgent(UserAgent),
api.CustomHTTPHeaders(c.Headers), api.ClientTimeout(c.clientTimeout))
opts := []api.Option{
api.APIBaseURL(c.apiBaseURL),
api.UserAgent(UserAgent),
api.CustomHTTPHeaders(c.Headers),
api.ClientTimeout(c.clientTimeout),
}

// Use harness_token if provided, otherwise use api_key
if c.harnessToken != "" {
log.Printf("[INFO] Using harness_token for authentication")
opts = append(opts, api.HarnessToken(c.harnessToken))
} else if c.apiKey != "" {
log.Printf("[INFO] Using api_key for authentication")
opts = append(opts, api.APIKey(c.apiKey))
}

api, clientInitErr := api.New(opts...)
if clientInitErr != nil {
return clientInitErr
}
Expand Down Expand Up @@ -63,6 +78,11 @@ func (c *Config) applySchema(d *schema.ResourceData) (err error) {
c.apiBaseURL = vs
}

if v, ok := d.GetOk("harness_token"); ok {
vs := v.(string)
c.harnessToken = vs
}

if v, ok := d.GetOk("remove_environment_from_state_only"); ok {
c.RemoveEnvFromStateOnly = v.(bool)
}
Expand Down
3 changes: 3 additions & 0 deletions split/import_split_group_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ import (
)

func TestAccSplitGroup_importBasic(t *testing.T) {
// Skip test if using harness_token as this resource is deprecated with harness_token
skipIfUsingHarnessToken(t, "split_group")

name := fmt.Sprintf("tftest-%s", acctest.RandString(8))

resource.Test(t, resource.TestCase{
Expand Down
5 changes: 3 additions & 2 deletions split/import_split_traffic_type_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,16 @@ package split

import (
"fmt"
"testing"

"github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
"testing"
)

func TestAccSplitTrafficType_importBasic(t *testing.T) {
workspaceID := testAccConfig.GetWorkspaceIDorSkip(t)
name := fmt.Sprintf("tt-tftest-%s", acctest.RandString(10))
name := fmt.Sprintf("tftest_%s", acctest.RandString(10))

resource.Test(t, resource.TestCase{
PreCheck: func() {
Expand Down
3 changes: 3 additions & 0 deletions split/import_split_user_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ import (
)

func TestAccSplitUser_importBasic(t *testing.T) {
// Skip test if using harness_token as this resource is deprecated with harness_token
skipIfUsingHarnessToken(t, "split_user")

email := testAccConfig.GetUserEmailorSkip(t)
emailSplit := strings.Split(email, "@")
emailFormatted := fmt.Sprintf("%s+%s@%s", emailSplit[0], acctest.RandString(8), emailSplit[1])
Expand Down
3 changes: 3 additions & 0 deletions split/import_split_workspace_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ import (
)

func TestAccSplitWorkspace_importBasic(t *testing.T) {
// Skip test if using harness_token as this resource is deprecated with harness_token
skipIfUsingHarnessToken(t, "split_workspace")

name := fmt.Sprintf("w-tftest-%s", acctest.RandString(10))

resource.Test(t, resource.TestCase{
Expand Down
19 changes: 15 additions & 4 deletions split/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,13 @@ func New() *schema.Provider {
DefaultFunc: schema.EnvDefaultFunc("SPLIT_API_KEY", nil),
},

"harness_token": {
Type: schema.TypeString,
Optional: true,
DefaultFunc: schema.EnvDefaultFunc("HARNESS_TOKEN", nil),
Description: "Harness token for authentication. When set, uses 'x-api-key' header authentication instead of Bearer token.",
},

"base_url": {
Type: schema.TypeString,
Optional: true,
Expand Down Expand Up @@ -50,18 +57,18 @@ func New() *schema.Provider {
},

ResourcesMap: map[string]*schema.Resource{
"split_api_key": resourceSplitApiKey(),
"split_api_key": resourceSplitApiKeyWithDeprecation(),
"split_environment": resourceSplitEnvironment(),
"split_environment_segment_keys": resourceSplitEnvironmentSegmentKeys(),
"split_group": resourceSplitGroup(),
"split_group": resourceSplitGroupWithDeprecation(),
"split_segment": resourceSplitSegment(),
"split_segment_environment_association": resourceSplitSegmentEnvironmentAssociation(),
"split_split": resourceSplitSplit(),
"split_split_definition": resourceSplitSplitDefinition(),
"split_traffic_type": resourceSplitTrafficType(),
"split_traffic_type_attribute": resourceSplitTrafficTypeAttribute(),
"split_user": resourceSplitUser(),
"split_workspace": resourceSplitWorkspace(),
"split_user": resourceSplitUserWithDeprecation(),
"split_workspace": resourceSplitWorkspaceWithDeprecation(),
},

ConfigureContextFunc: providerConfigure,
Expand Down Expand Up @@ -89,6 +96,10 @@ func providerConfigure(_ context.Context, d *schema.ResourceData) (interface{},
config.apiKey = apiKey.(string)
}

if harnessToken, ok := d.GetOk("harness_token"); ok {
config.harnessToken = harnessToken.(string)
}

if clientTimeout, ok := d.GetOk("client_timeout"); ok {
config.clientTimeout = clientTimeout.(int)
}
Expand Down
Loading