Skip to content
Merged
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
3 changes: 2 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ require (
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.588
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/sts v1.0.588
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/tag v1.0.233
github.com/tencentyun/cos-go-sdk-v5 v0.7.29
github.com/tencentyun/cos-go-sdk-v5 v0.7.42
github.com/tombuildsstuff/giovanni v0.15.1
github.com/xanzy/ssh-agent v0.3.1
github.com/xlab/treeprint v0.0.0-20161029104018-1d6e34225557
Expand Down Expand Up @@ -138,6 +138,7 @@ require (
github.com/bmatcuk/doublestar/v4 v4.6.0 // indirect
github.com/bradleyfalzon/ghinstallation/v2 v2.1.0 // indirect
github.com/cenkalti/backoff/v4 v4.2.1 // indirect
github.com/clbanning/mxj v1.8.4 // indirect
github.com/cli/go-gh v1.0.0 // indirect
github.com/cli/safeexec v1.0.0 // indirect
github.com/cli/shurcooL-graphql v0.0.2 // indirect
Expand Down
11 changes: 7 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,8 @@ github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e h1:fY5BOSpyZCqRo5O
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1 h1:q763qf9huN11kDQavWsoZXJNW3xEE4JJyHa5Q25/sd8=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/clbanning/mxj v1.8.4 h1:HuhwZtbyvyOw+3Z1AowPkU87JkJUSv751ELWaiTpj8I=
github.com/clbanning/mxj v1.8.4/go.mod h1:BVjHeAH+rl9rs6f+QIpeRl0tfu10SXn1pUSa5PVGJng=
github.com/cli/go-gh v1.0.0 h1:zE1YUAUYqGXNZuICEBeOkIMJ5F50BS0ftvtoWGlsEFI=
github.com/cli/go-gh v1.0.0/go.mod h1:bqxLdCoTZ73BuiPEJx4olcO/XKhVZaFDchFagYRBweE=
github.com/cli/safeexec v1.0.0 h1:0VngyaIyqACHdcMNWfo6+KdUYnqEr2Sg+bSP1pdF+dI=
Expand Down Expand Up @@ -814,6 +816,7 @@ github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0Qu
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/mapstructure v1.3.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/mitchellh/mapstructure v1.4.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
Expand Down Expand Up @@ -950,16 +953,16 @@ github.com/stretchr/testify v1.7.4/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.194/go.mod h1:7sCQWVkxcsR38nffDW057DRGk8mUjK1Ing/EFOK8s8Y=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.563/go.mod h1:7sCQWVkxcsR38nffDW057DRGk8mUjK1Ing/EFOK8s8Y=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.588 h1:DYtBXB7sVc3EOW5horg8j55cLZynhsLYhHrvQ/jXKKM=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.588/go.mod h1:7sCQWVkxcsR38nffDW057DRGk8mUjK1Ing/EFOK8s8Y=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/kms v1.0.194/go.mod h1:yrBKWhChnDqNz1xuXdSbWXG56XawEq0G5j1lg4VwBD4=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/kms v1.0.563/go.mod h1:uom4Nvi9W+Qkom0exYiJ9VWJjXwyxtPYTkKkaLMlfE0=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/sts v1.0.588 h1:PlkFOALQZ9BLUyX8EalATUQD5xEn1Sz34C+Rw5VSpvk=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/sts v1.0.588/go.mod h1:vPvXNb+zBZVJfZCIKWcYxLpGzgScKKgiPUArobWZ+nU=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/tag v1.0.233 h1:5Tbi+jyZ2MojC6GK8V6hchwtnkP2IuENUTqSisbYOlA=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/tag v1.0.233/go.mod h1:sX14+NSvMjOhNFaMtP2aDy6Bss8PyFXij21gpY6+DAs=
github.com/tencentyun/cos-go-sdk-v5 v0.7.29 h1:uwRBzc70Wgtc5iQQCowqecfRT0OpCXUOZzodZHOOEDs=
github.com/tencentyun/cos-go-sdk-v5 v0.7.29/go.mod h1:4E4+bQ2gBVJcgEC9Cufwylio4mXOct2iu05WjgEBx1o=
github.com/tencentyun/cos-go-sdk-v5 v0.7.42 h1:Up1704BJjI5orycXKjpVpvuOInt9GC5pqY4knyE9Uds=
github.com/tencentyun/cos-go-sdk-v5 v0.7.42/go.mod h1:LUFnaqRmGk6pEHOaRmdn2dCZR2j0cSsM5xowWFPTPao=
github.com/thanhpk/randstr v1.0.4 h1:IN78qu/bR+My+gHCvMEXhR/i5oriVHcTB/BJJIRTsNo=
github.com/thanhpk/randstr v1.0.4/go.mod h1:M/H2P1eNLZzlDwAzpkkkUvoyNNMbzRGhESZuEQk3r0U=
github.com/thlib/go-timezone-local v0.0.0-20210907160436-ef149e42d28e h1:BuzhfgfWQbX0dWzYzT1zsORLnHRv3bcRcsaUk0VmXA8=
Expand Down
46 changes: 46 additions & 0 deletions internal/backend/remote-state/cos/backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@ package cos
import (
"context"
"fmt"
"log"
"net/http"
"net/url"
"os"
"regexp"
"strconv"
"strings"
"time"
Expand All @@ -28,6 +30,8 @@ const (
PROVIDER_SECRET_KEY = "TENCENTCLOUD_SECRET_KEY"
PROVIDER_SECURITY_TOKEN = "TENCENTCLOUD_SECURITY_TOKEN"
PROVIDER_REGION = "TENCENTCLOUD_REGION"
PROVIDER_ENDPOINT = "TENCENTCLOUD_ENDPOINT"
PROVIDER_DOMAIN = "TENCENTCLOUD_DOMAIN"
PROVIDER_ASSUME_ROLE_ARN = "TENCENTCLOUD_ASSUME_ROLE_ARN"
PROVIDER_ASSUME_ROLE_SESSION_NAME = "TENCENTCLOUD_ASSUME_ROLE_SESSION_NAME"
PROVIDER_ASSUME_ROLE_SESSION_DURATION = "TENCENTCLOUD_ASSUME_ROLE_SESSION_DURATION"
Expand All @@ -49,6 +53,7 @@ type Backend struct {
key string
encrypt bool
acl string
domain string
}

// New creates a new backend for TencentCloud cos remote state.
Expand Down Expand Up @@ -87,6 +92,18 @@ func New() backend.Backend {
Required: true,
Description: "The name of the COS bucket",
},
"endpoint": {
Type: schema.TypeString,
Optional: true,
Description: "The custom endpoint for the COS API, e.g. http://cos-internal.{Region}.tencentcos.cn. Both HTTP and HTTPS are accepted.",
DefaultFunc: schema.EnvDefaultFunc(PROVIDER_ENDPOINT, nil),
},
"domain": {
Type: schema.TypeString,
Optional: true,
DefaultFunc: schema.EnvDefaultFunc(PROVIDER_DOMAIN, nil),
Description: "The root domain of the API request. Default is tencentcloudapi.com.",
},
"prefix": {
Type: schema.TypeString,
Optional: true,
Expand Down Expand Up @@ -231,6 +248,33 @@ func (b *Backend) configure(ctx context.Context) error {
return err
}

if v, ok := data.GetOk("domain"); ok {
b.domain = v.(string)
log.Printf("[DEBUG] Backend: set domain for TencentCloud API client. Domain: [%s]", b.domain)
}
// set url as endpoint when provided
// "http://{Bucket}.cos-internal.{Region}.tencentcos.cn"
if v, ok := data.GetOk("endpoint"); ok {
endpoint := v.(string)

re := regexp.MustCompile(`^(http(s)?)://cos-internal\.([^.]+)\.tencentcos\.cn$`)
matches := re.FindStringSubmatch(endpoint)
if len(matches) != 4 {
return fmt.Errorf("Invalid URL: %v must be: %v", endpoint, "http(s)://cos-internal.{Region}.tencentcos.cn")
}

protocol := matches[1]
region := matches[3]

// URL after converting
newUrl := fmt.Sprintf("%s://%s.cos-internal.%s.tencentcos.cn", protocol, b.bucket, region)
u, err = url.Parse(newUrl)
log.Printf("[DEBUG] Backend: set COS URL as: [%s]", newUrl)
}
if err != nil {
return err
}

secretId := data.Get("secret_id").(string)
secretKey := data.Get("secret_key").(string)
securityToken := data.Get("security_token").(string)
Expand Down Expand Up @@ -333,6 +377,8 @@ func (b *Backend) NewClientProfile(timeout int) *profile.ClientProfile {
cpf.HttpProfile.ReqMethod = "POST"
// request timeout
cpf.HttpProfile.ReqTimeout = timeout
// request domain
cpf.HttpProfile.RootDomain = b.domain

return cpf
}
63 changes: 63 additions & 0 deletions internal/backend/remote-state/cos/backend_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,27 @@ func TestRemoteClientWithEncryption(t *testing.T) {
remote.TestClient(t, rs.Client)
}

func TestRemoteClientWithEndpoint(t *testing.T) {
t.Parallel()

bucket := bucketName(t)

be := setupBackendWithEndpoint(t, bucket, defaultPrefix, defaultKey, false)
defer teardownBackend(t, be)

ss, err := be.StateMgr(backend.DefaultStateName)
if err != nil {
t.Fatalf("unexpected error: %s", err)
}

rs, ok := ss.(*remote.State)
if !ok {
t.Fatalf("wrong state manager type\ngot: %T\nwant: %T", ss, rs)
}

remote.TestClient(t, rs.Client)
}

func TestRemoteLocks(t *testing.T) {
t.Parallel()

Expand Down Expand Up @@ -201,6 +222,44 @@ func TestBackendWithEncryption(t *testing.T) {
backend.TestBackendStateLocks(t, be0, be1)
}

func TestBackendWithEndpoint(t *testing.T) {
t.Parallel()

bucket := bucketName(t)

be0 := setupBackendWithEndpoint(t, bucket, defaultPrefix, defaultKey, false)
defer teardownBackend(t, be0)

be1 := setupBackendWithEndpoint(t, bucket, defaultPrefix, defaultKey, false)
defer teardownBackend(t, be1)

backend.TestBackendStates(t, be0)
backend.TestBackendStateLocks(t, be0, be1)
backend.TestBackendStateForceUnlock(t, be0, be1)
}

func setupBackendWithEndpoint(t *testing.T, bucket, prefix, key string, encrypt bool) backend.Backend {
t.Helper()

skip := os.Getenv("TF_COS_APPID") == ""
if skip {
t.Skip("This test requires setting the TF_COS_APPID environment variable")
}

if os.Getenv(PROVIDER_REGION) == "" {
os.Setenv(PROVIDER_REGION, "ap-guangzhou")
}

appId := os.Getenv("TF_COS_APPID")
region := os.Getenv(PROVIDER_REGION)

if os.Getenv(PROVIDER_ENDPOINT) == "" {
os.Setenv(PROVIDER_ENDPOINT, fmt.Sprintf("http://%s.cos-internal.%s.tencentcos.cn", bucket+appId, region))
}

return setupBackend(t, bucket, prefix, key, encrypt)
}

func setupBackend(t *testing.T, bucket, prefix, key string, encrypt bool) backend.Backend {
t.Helper()

Expand All @@ -223,6 +282,10 @@ func setupBackend(t *testing.T, bucket, prefix, key string, encrypt bool) backen
"key": key,
}

if os.Getenv(PROVIDER_ENDPOINT) != "" {
config["endpoint"] = os.Getenv(PROVIDER_ENDPOINT)
}

b := backend.TestBackendConfig(t, New(), backend.TestWrapConfig(config))
be := b.(*Backend)

Expand Down
20 changes: 20 additions & 0 deletions website/docs/language/settings/backends/cos.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ The following configuration options or environment variables are supported:
- `encrypt` - (Optional) Whether to enable server side encryption of the state file. If it is true, COS will use 'AES256' encryption algorithm to encrypt state file.
- `acl` - (Optional) Object ACL to be applied to the state file, allows `private` and `public-read`. Defaults to `private`.
- `accelerate` - (Optional) Whether to enable global Acceleration. Defaults to `false`.
- `endpoint` - (Optional) The Custom Endpoint for the COS backend. It supports the environment variable `TENCENTCLOUD_ENDPOINT`.
- `domain` - (Optional) The root domain of the API request. Defaults to `tencentcloudapi.com`. It supports the environment variable `TENCENTCLOUD_DOMAIN`.

### Assume Role
If provided with an assume role, Terraform will attempt to assume this role using the supplied credentials.
Expand Down Expand Up @@ -106,4 +108,22 @@ $ export TENCENTCLOUD_ASSUME_ROLE_ARN="qcs::cam::uin/xxx:roleName/yyy"
$ export TENCENTCLOUD_ASSUME_ROLE_SESSION_NAME="my-session-name"
$ export TENCENTCLOUD_ASSUME_ROLE_SESSION_DURATION=3600
$ terraform plan
```

### Endpoint
If provided with an endpoint URL, Terraform will attempt to access the COS backend by the `endpoint` configuration or the environment variable `TENCENTCLOUD_ENDPOINT`.

A typical endpoint looks like this: `http://cos-internal.{Region}.tencentcos.cn`. Both HTTP and HTTPS are accepted.

Usage:

```hcl
terraform {
backend "cos" {
region = "ap-guangzhou"
bucket = "bucket-for-terraform-state-1258798060"
prefix = "terraform/state"
endpoint = "http://cos-internal.ap-guangzhou.tencentcos.cn"
}
}
```