Merge pull request #29307 from hayorov/main
Flatten `assume_role` block for OSS backend
This commit is contained in:
commit
2ebdc099ac
|
@ -24,155 +24,22 @@ import (
|
|||
"github.com/aliyun/aliyun-oss-go-sdk/oss"
|
||||
"github.com/aliyun/aliyun-tablestore-go-sdk/tablestore"
|
||||
"github.com/hashicorp/go-cleanhttp"
|
||||
"github.com/jmespath/go-jmespath"
|
||||
"github.com/mitchellh/go-homedir"
|
||||
|
||||
"github.com/hashicorp/terraform/internal/backend"
|
||||
"github.com/hashicorp/terraform/internal/legacy/helper/schema"
|
||||
"github.com/hashicorp/terraform/version"
|
||||
"github.com/jmespath/go-jmespath"
|
||||
"github.com/mitchellh/go-homedir"
|
||||
)
|
||||
|
||||
// New creates a new backend for OSS remote state.
|
||||
func New() backend.Backend {
|
||||
s := &schema.Backend{
|
||||
Schema: map[string]*schema.Schema{
|
||||
"access_key": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
Description: "Alibaba Cloud Access Key ID",
|
||||
DefaultFunc: schema.EnvDefaultFunc("ALICLOUD_ACCESS_KEY", os.Getenv("ALICLOUD_ACCESS_KEY_ID")),
|
||||
},
|
||||
|
||||
"secret_key": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
Description: "Alibaba Cloud Access Secret Key",
|
||||
DefaultFunc: schema.EnvDefaultFunc("ALICLOUD_SECRET_KEY", os.Getenv("ALICLOUD_ACCESS_KEY_SECRET")),
|
||||
},
|
||||
|
||||
"security_token": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
Description: "Alibaba Cloud Security Token",
|
||||
DefaultFunc: schema.EnvDefaultFunc("ALICLOUD_SECURITY_TOKEN", ""),
|
||||
},
|
||||
|
||||
"ecs_role_name": {
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
DefaultFunc: schema.EnvDefaultFunc("ALICLOUD_ECS_ROLE_NAME", os.Getenv("ALICLOUD_ECS_ROLE_NAME")),
|
||||
Description: "The RAM Role Name attached on a ECS instance for API operations. You can retrieve this from the 'Access Control' section of the Alibaba Cloud console.",
|
||||
},
|
||||
|
||||
"region": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
Description: "The region of the OSS bucket.",
|
||||
DefaultFunc: schema.EnvDefaultFunc("ALICLOUD_REGION", os.Getenv("ALICLOUD_DEFAULT_REGION")),
|
||||
},
|
||||
"tablestore_endpoint": {
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
Description: "A custom endpoint for the TableStore API",
|
||||
DefaultFunc: schema.EnvDefaultFunc("ALICLOUD_TABLESTORE_ENDPOINT", ""),
|
||||
},
|
||||
"endpoint": {
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
Description: "A custom endpoint for the OSS API",
|
||||
DefaultFunc: schema.EnvDefaultFunc("ALICLOUD_OSS_ENDPOINT", os.Getenv("OSS_ENDPOINT")),
|
||||
},
|
||||
|
||||
"bucket": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
Description: "The name of the OSS bucket",
|
||||
},
|
||||
|
||||
"prefix": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
Description: "The directory where state files will be saved inside the bucket",
|
||||
Default: "env:",
|
||||
ValidateFunc: func(v interface{}, s string) ([]string, []error) {
|
||||
prefix := v.(string)
|
||||
if strings.HasPrefix(prefix, "/") || strings.HasPrefix(prefix, "./") {
|
||||
return nil, []error{fmt.Errorf("workspace_key_prefix must not start with '/' or './'")}
|
||||
}
|
||||
return nil, nil
|
||||
},
|
||||
},
|
||||
|
||||
"key": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
Description: "The path of the state file inside the bucket",
|
||||
ValidateFunc: func(v interface{}, s string) ([]string, []error) {
|
||||
if strings.HasPrefix(v.(string), "/") || strings.HasSuffix(v.(string), "/") {
|
||||
return nil, []error{fmt.Errorf("key can not start and end with '/'")}
|
||||
}
|
||||
return nil, nil
|
||||
},
|
||||
Default: "terraform.tfstate",
|
||||
},
|
||||
|
||||
"tablestore_table": {
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
Description: "TableStore table for state locking and consistency",
|
||||
Default: "",
|
||||
},
|
||||
|
||||
"encrypt": &schema.Schema{
|
||||
Type: schema.TypeBool,
|
||||
Optional: true,
|
||||
Description: "Whether to enable server side encryption of the state file",
|
||||
Default: false,
|
||||
},
|
||||
|
||||
"acl": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
Description: "Object ACL to be applied to the state file",
|
||||
Default: "",
|
||||
ValidateFunc: func(v interface{}, k string) ([]string, []error) {
|
||||
if value := v.(string); value != "" {
|
||||
acls := oss.ACLType(value)
|
||||
if acls != oss.ACLPrivate && acls != oss.ACLPublicRead && acls != oss.ACLPublicReadWrite {
|
||||
return nil, []error{fmt.Errorf(
|
||||
"%q must be a valid ACL value , expected %s, %s or %s, got %q",
|
||||
k, oss.ACLPrivate, oss.ACLPublicRead, oss.ACLPublicReadWrite, acls)}
|
||||
}
|
||||
}
|
||||
return nil, nil
|
||||
},
|
||||
},
|
||||
|
||||
"assume_role": assumeRoleSchema(),
|
||||
"shared_credentials_file": {
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
DefaultFunc: schema.EnvDefaultFunc("ALICLOUD_SHARED_CREDENTIALS_FILE", ""),
|
||||
Description: "This is the path to the shared credentials file. If this is not set and a profile is specified, `~/.aliyun/config.json` will be used.",
|
||||
},
|
||||
"profile": {
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
Description: "This is the Alibaba Cloud profile name as set in the shared credentials file. It can also be sourced from the `ALICLOUD_PROFILE` environment variable.",
|
||||
DefaultFunc: schema.EnvDefaultFunc("ALICLOUD_PROFILE", ""),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
result := &Backend{Backend: s}
|
||||
result.Backend.ConfigureFunc = result.configure
|
||||
return result
|
||||
}
|
||||
|
||||
func assumeRoleSchema() *schema.Schema {
|
||||
// Deprecated in favor of flattening assume_role_* options
|
||||
func deprecatedAssumeRoleSchema() *schema.Schema {
|
||||
return &schema.Schema{
|
||||
Type: schema.TypeSet,
|
||||
Optional: true,
|
||||
MaxItems: 1,
|
||||
Type: schema.TypeSet,
|
||||
Optional: true,
|
||||
ConflictsWith: []string{"assume_role_role_arn", "assume_role_session_name", "assume_role_policy", "assume_role_session_expiration"},
|
||||
MaxItems: 1,
|
||||
Deprecated: "use assume_role_* options instead",
|
||||
Elem: &schema.Resource{
|
||||
Schema: map[string]*schema.Schema{
|
||||
"role_arn": {
|
||||
|
@ -216,6 +83,182 @@ func assumeRoleSchema() *schema.Schema {
|
|||
}
|
||||
}
|
||||
|
||||
// New creates a new backend for OSS remote state.
|
||||
func New() backend.Backend {
|
||||
s := &schema.Backend{
|
||||
Schema: map[string]*schema.Schema{
|
||||
"access_key": {
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
Description: "Alibaba Cloud Access Key ID",
|
||||
DefaultFunc: schema.EnvDefaultFunc("ALICLOUD_ACCESS_KEY", os.Getenv("ALICLOUD_ACCESS_KEY_ID")),
|
||||
},
|
||||
|
||||
"secret_key": {
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
Description: "Alibaba Cloud Access Secret Key",
|
||||
DefaultFunc: schema.EnvDefaultFunc("ALICLOUD_SECRET_KEY", os.Getenv("ALICLOUD_ACCESS_KEY_SECRET")),
|
||||
},
|
||||
|
||||
"security_token": {
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
Description: "Alibaba Cloud Security Token",
|
||||
DefaultFunc: schema.EnvDefaultFunc("ALICLOUD_SECURITY_TOKEN", ""),
|
||||
},
|
||||
|
||||
"ecs_role_name": {
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
DefaultFunc: schema.EnvDefaultFunc("ALICLOUD_ECS_ROLE_NAME", os.Getenv("ALICLOUD_ECS_ROLE_NAME")),
|
||||
Description: "The RAM Role Name attached on a ECS instance for API operations. You can retrieve this from the 'Access Control' section of the Alibaba Cloud console.",
|
||||
},
|
||||
|
||||
"region": {
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
Description: "The region of the OSS bucket.",
|
||||
DefaultFunc: schema.EnvDefaultFunc("ALICLOUD_REGION", os.Getenv("ALICLOUD_DEFAULT_REGION")),
|
||||
},
|
||||
"tablestore_endpoint": {
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
Description: "A custom endpoint for the TableStore API",
|
||||
DefaultFunc: schema.EnvDefaultFunc("ALICLOUD_TABLESTORE_ENDPOINT", ""),
|
||||
},
|
||||
"endpoint": {
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
Description: "A custom endpoint for the OSS API",
|
||||
DefaultFunc: schema.EnvDefaultFunc("ALICLOUD_OSS_ENDPOINT", os.Getenv("OSS_ENDPOINT")),
|
||||
},
|
||||
|
||||
"bucket": {
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
Description: "The name of the OSS bucket",
|
||||
},
|
||||
|
||||
"prefix": {
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
Description: "The directory where state files will be saved inside the bucket",
|
||||
Default: "env:",
|
||||
ValidateFunc: func(v interface{}, s string) ([]string, []error) {
|
||||
prefix := v.(string)
|
||||
if strings.HasPrefix(prefix, "/") || strings.HasPrefix(prefix, "./") {
|
||||
return nil, []error{fmt.Errorf("workspace_key_prefix must not start with '/' or './'")}
|
||||
}
|
||||
return nil, nil
|
||||
},
|
||||
},
|
||||
|
||||
"key": {
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
Description: "The path of the state file inside the bucket",
|
||||
ValidateFunc: func(v interface{}, s string) ([]string, []error) {
|
||||
if strings.HasPrefix(v.(string), "/") || strings.HasSuffix(v.(string), "/") {
|
||||
return nil, []error{fmt.Errorf("key can not start and end with '/'")}
|
||||
}
|
||||
return nil, nil
|
||||
},
|
||||
Default: "terraform.tfstate",
|
||||
},
|
||||
|
||||
"tablestore_table": {
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
Description: "TableStore table for state locking and consistency",
|
||||
Default: "",
|
||||
},
|
||||
|
||||
"encrypt": {
|
||||
Type: schema.TypeBool,
|
||||
Optional: true,
|
||||
Description: "Whether to enable server side encryption of the state file",
|
||||
Default: false,
|
||||
},
|
||||
|
||||
"acl": {
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
Description: "Object ACL to be applied to the state file",
|
||||
Default: "",
|
||||
ValidateFunc: func(v interface{}, k string) ([]string, []error) {
|
||||
if value := v.(string); value != "" {
|
||||
acls := oss.ACLType(value)
|
||||
if acls != oss.ACLPrivate && acls != oss.ACLPublicRead && acls != oss.ACLPublicReadWrite {
|
||||
return nil, []error{fmt.Errorf(
|
||||
"%q must be a valid ACL value , expected %s, %s or %s, got %q",
|
||||
k, oss.ACLPrivate, oss.ACLPublicRead, oss.ACLPublicReadWrite, acls)}
|
||||
}
|
||||
}
|
||||
return nil, nil
|
||||
},
|
||||
},
|
||||
"shared_credentials_file": {
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
DefaultFunc: schema.EnvDefaultFunc("ALICLOUD_SHARED_CREDENTIALS_FILE", ""),
|
||||
Description: "This is the path to the shared credentials file. If this is not set and a profile is specified, `~/.aliyun/config.json` will be used.",
|
||||
},
|
||||
"profile": {
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
Description: "This is the Alibaba Cloud profile name as set in the shared credentials file. It can also be sourced from the `ALICLOUD_PROFILE` environment variable.",
|
||||
DefaultFunc: schema.EnvDefaultFunc("ALICLOUD_PROFILE", ""),
|
||||
},
|
||||
"assume_role": deprecatedAssumeRoleSchema(),
|
||||
"assume_role_role_arn": {
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
ConflictsWith: []string{"assume_role"},
|
||||
Description: "The ARN of a RAM role to assume prior to making API calls.",
|
||||
DefaultFunc: schema.EnvDefaultFunc("ALICLOUD_ASSUME_ROLE_ARN", ""),
|
||||
},
|
||||
"assume_role_session_name": {
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
ConflictsWith: []string{"assume_role"},
|
||||
Description: "The session name to use when assuming the role.",
|
||||
DefaultFunc: schema.EnvDefaultFunc("ALICLOUD_ASSUME_ROLE_SESSION_NAME", ""),
|
||||
},
|
||||
"assume_role_policy": {
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
ConflictsWith: []string{"assume_role"},
|
||||
Description: "The permissions applied when assuming a role. You cannot use this policy to grant permissions which exceed those of the role that is being assumed.",
|
||||
},
|
||||
"assume_role_session_expiration": {
|
||||
Type: schema.TypeInt,
|
||||
Optional: true,
|
||||
ConflictsWith: []string{"assume_role"},
|
||||
Description: "The time after which the established session for assuming role expires.",
|
||||
ValidateFunc: func(v interface{}, k string) ([]string, []error) {
|
||||
min := 900
|
||||
max := 3600
|
||||
value, ok := v.(int)
|
||||
if !ok {
|
||||
return nil, []error{fmt.Errorf("expected type of %s to be int", k)}
|
||||
}
|
||||
|
||||
if value < min || value > max {
|
||||
return nil, []error{fmt.Errorf("expected %s to be in the range (%d - %d), got %d", k, min, max, v)}
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
result := &Backend{Backend: s}
|
||||
result.Backend.ConfigureFunc = result.configure
|
||||
return result
|
||||
}
|
||||
|
||||
type Backend struct {
|
||||
*schema.Backend
|
||||
|
||||
|
@ -228,7 +271,6 @@ type Backend struct {
|
|||
stateKey string
|
||||
serverSideEncryption bool
|
||||
acl string
|
||||
endpoint string
|
||||
otsEndpoint string
|
||||
otsTable string
|
||||
}
|
||||
|
@ -275,6 +317,7 @@ func (b *Backend) configure(ctx context.Context) error {
|
|||
}
|
||||
|
||||
if v, ok := d.GetOk("assume_role"); ok {
|
||||
// deprecated assume_role block
|
||||
for _, v := range v.(*schema.Set).List() {
|
||||
assumeRole := v.(map[string]interface{})
|
||||
if assumeRole["role_arn"].(string) != "" {
|
||||
|
@ -283,22 +326,28 @@ func (b *Backend) configure(ctx context.Context) error {
|
|||
if assumeRole["session_name"].(string) != "" {
|
||||
sessionName = assumeRole["session_name"].(string)
|
||||
}
|
||||
if sessionName == "" {
|
||||
sessionName = "terraform"
|
||||
}
|
||||
policy = assumeRole["policy"].(string)
|
||||
sessionExpiration = assumeRole["session_expiration"].(int)
|
||||
if sessionExpiration == 0 {
|
||||
if v := os.Getenv("ALICLOUD_ASSUME_ROLE_SESSION_EXPIRATION"); v != "" {
|
||||
if expiredSeconds, err := strconv.Atoi(v); err == nil {
|
||||
sessionExpiration = expiredSeconds
|
||||
}
|
||||
}
|
||||
if sessionExpiration == 0 {
|
||||
sessionExpiration = 3600
|
||||
}
|
||||
}
|
||||
} else {
|
||||
roleArn = d.Get("assume_role_role_arn").(string)
|
||||
sessionName = d.Get("assume_role_session_name").(string)
|
||||
policy = d.Get("assume_role_policy").(string)
|
||||
sessionExpiration = d.Get("assume_role_session_expiration").(int)
|
||||
}
|
||||
|
||||
if sessionName == "" {
|
||||
sessionName = "terraform"
|
||||
}
|
||||
if sessionExpiration == 0 {
|
||||
if v := os.Getenv("ALICLOUD_ASSUME_ROLE_SESSION_EXPIRATION"); v != "" {
|
||||
if expiredSeconds, err := strconv.Atoi(v); err == nil {
|
||||
sessionExpiration = expiredSeconds
|
||||
}
|
||||
}
|
||||
if sessionExpiration == 0 {
|
||||
sessionExpiration = 3600
|
||||
}
|
||||
}
|
||||
|
||||
if accessKey == "" {
|
||||
|
@ -372,13 +421,13 @@ func (b *Backend) getOSSEndpointByRegion(access_key, secret_key, security_token,
|
|||
|
||||
locationClient, err := location.NewClientWithOptions(region, getSdkConfig(), credentials.NewStsTokenCredential(access_key, secret_key, security_token))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Unable to initialize the location client: %#v", err)
|
||||
return nil, fmt.Errorf("unable to initialize the location client: %#v", err)
|
||||
|
||||
}
|
||||
locationClient.AppendUserAgent(TerraformUA, TerraformVersion)
|
||||
endpointsResponse, err := locationClient.DescribeEndpoints(args)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Describe oss endpoint using region: %#v got an error: %#v.", region, err)
|
||||
return nil, fmt.Errorf("describe oss endpoint using region: %#v got an error: %#v", region, err)
|
||||
}
|
||||
return endpointsResponse, nil
|
||||
}
|
||||
|
@ -468,7 +517,7 @@ func (a *Invoker) Run(f func() error) error {
|
|||
catcher.RetryCount--
|
||||
|
||||
if catcher.RetryCount <= 0 {
|
||||
return fmt.Errorf("Retry timeout and got an error: %#v.", err)
|
||||
return fmt.Errorf("retry timeout and got an error: %#v", err)
|
||||
} else {
|
||||
time.Sleep(time.Duration(catcher.RetryWaitSeconds) * time.Second)
|
||||
return a.Run(f)
|
||||
|
@ -578,7 +627,7 @@ func getAuthCredentialByEcsRoleName(ecsRoleName string) (accessKey, secretKey, t
|
|||
response := responses.NewCommonResponse()
|
||||
err = responses.Unmarshal(response, httpResponse, "")
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Unmarshal Ecs sts token response err : %s", err.Error())
|
||||
err = fmt.Errorf("unmarshal Ecs sts token response err : %s", err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
@ -3,19 +3,18 @@ package oss
|
|||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"path"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/aliyun/aliyun-oss-go-sdk/oss"
|
||||
"github.com/aliyun/aliyun-tablestore-go-sdk/tablestore"
|
||||
|
||||
"github.com/hashicorp/terraform/internal/backend"
|
||||
"github.com/hashicorp/terraform/internal/states"
|
||||
"github.com/hashicorp/terraform/internal/states/remote"
|
||||
"github.com/hashicorp/terraform/internal/states/statemgr"
|
||||
|
||||
"log"
|
||||
"path"
|
||||
|
||||
"github.com/aliyun/aliyun-tablestore-go-sdk/tablestore"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -43,7 +42,7 @@ func (b *Backend) remoteClient(name string) (*RemoteClient, error) {
|
|||
TableName: b.otsTable,
|
||||
})
|
||||
if err != nil {
|
||||
return client, fmt.Errorf("Error describing table store %s: %#v", b.otsTable, err)
|
||||
return client, fmt.Errorf("error describing table store %s: %#v", b.otsTable, err)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -53,7 +52,7 @@ func (b *Backend) remoteClient(name string) (*RemoteClient, error) {
|
|||
func (b *Backend) Workspaces() ([]string, error) {
|
||||
bucket, err := b.ossClient.Bucket(b.bucketName)
|
||||
if err != nil {
|
||||
return []string{""}, fmt.Errorf("Error getting bucket: %#v", err)
|
||||
return []string{""}, fmt.Errorf("error getting bucket: %#v", err)
|
||||
}
|
||||
|
||||
var options []oss.Option
|
||||
|
@ -135,7 +134,7 @@ func (b *Backend) StateMgr(name string) (statemgr.Full, error) {
|
|||
lockInfo.Operation = "init"
|
||||
lockId, err := client.Lock(lockInfo)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Failed to lock OSS state: %s", err)
|
||||
return nil, fmt.Errorf("failed to lock OSS state: %s", err)
|
||||
}
|
||||
|
||||
// Local helper function so we can call it multiple places
|
||||
|
|
|
@ -3,22 +3,21 @@ package oss
|
|||
import (
|
||||
"bytes"
|
||||
"crypto/md5"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"encoding/hex"
|
||||
"log"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/aliyun/aliyun-oss-go-sdk/oss"
|
||||
"github.com/aliyun/aliyun-tablestore-go-sdk/tablestore"
|
||||
"github.com/hashicorp/go-multierror"
|
||||
uuid "github.com/hashicorp/go-uuid"
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/hashicorp/terraform/internal/states/remote"
|
||||
"github.com/hashicorp/terraform/internal/states/statemgr"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -48,8 +47,6 @@ type RemoteClient struct {
|
|||
lockFile string
|
||||
serverSideEncryption bool
|
||||
acl string
|
||||
info *statemgr.LockInfo
|
||||
mu sync.Mutex
|
||||
otsTable string
|
||||
}
|
||||
|
||||
|
@ -99,7 +96,7 @@ func (c *RemoteClient) Get() (payload *remote.Payload, err error) {
|
|||
func (c *RemoteClient) Put(data []byte) error {
|
||||
bucket, err := c.ossClient.Bucket(c.bucketName)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error getting bucket: %#v", err)
|
||||
return fmt.Errorf("error getting bucket: %#v", err)
|
||||
}
|
||||
|
||||
body := bytes.NewReader(data)
|
||||
|
@ -116,7 +113,7 @@ func (c *RemoteClient) Put(data []byte) error {
|
|||
|
||||
if body != nil {
|
||||
if err := bucket.PutObject(c.stateFile, body, options...); err != nil {
|
||||
return fmt.Errorf("Failed to upload state %s: %#v", c.stateFile, err)
|
||||
return fmt.Errorf("failed to upload state %s: %#v", c.stateFile, err)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -124,7 +121,7 @@ func (c *RemoteClient) Put(data []byte) error {
|
|||
if err := c.putMD5(sum[:]); err != nil {
|
||||
// if this errors out, we unfortunately have to error out altogether,
|
||||
// since the next Get will inevitably fail.
|
||||
return fmt.Errorf("Failed to store state MD5: %s", err)
|
||||
return fmt.Errorf("failed to store state MD5: %s", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -132,13 +129,13 @@ func (c *RemoteClient) Put(data []byte) error {
|
|||
func (c *RemoteClient) Delete() error {
|
||||
bucket, err := c.ossClient.Bucket(c.bucketName)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error getting bucket %s: %#v", c.bucketName, err)
|
||||
return fmt.Errorf("error getting bucket %s: %#v", c.bucketName, err)
|
||||
}
|
||||
|
||||
log.Printf("[DEBUG] Deleting remote state from OSS: %#v", c.stateFile)
|
||||
|
||||
if err := bucket.DeleteObject(c.stateFile); err != nil {
|
||||
return fmt.Errorf("Error deleting state %s: %#v", c.stateFile, err)
|
||||
return fmt.Errorf("error deleting state %s: %#v", c.stateFile, err)
|
||||
}
|
||||
|
||||
if err := c.deleteMD5(); err != nil {
|
||||
|
@ -413,11 +410,11 @@ func (c *RemoteClient) lockPath() string {
|
|||
func (c *RemoteClient) getObj() (*remote.Payload, error) {
|
||||
bucket, err := c.ossClient.Bucket(c.bucketName)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Error getting bucket %s: %#v", c.bucketName, err)
|
||||
return nil, fmt.Errorf("error getting bucket %s: %#v", c.bucketName, err)
|
||||
}
|
||||
|
||||
if exist, err := bucket.IsObjectExist(c.stateFile); err != nil {
|
||||
return nil, fmt.Errorf("Estimating object %s is exist got an error: %#v", c.stateFile, err)
|
||||
return nil, fmt.Errorf("estimating object %s is exist got an error: %#v", c.stateFile, err)
|
||||
} else if !exist {
|
||||
return nil, nil
|
||||
}
|
||||
|
@ -425,12 +422,12 @@ func (c *RemoteClient) getObj() (*remote.Payload, error) {
|
|||
var options []oss.Option
|
||||
output, err := bucket.GetObject(c.stateFile, options...)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Error getting object: %#v", err)
|
||||
return nil, fmt.Errorf("error getting object: %#v", err)
|
||||
}
|
||||
|
||||
buf := bytes.NewBuffer(nil)
|
||||
if _, err := io.Copy(buf, output); err != nil {
|
||||
return nil, fmt.Errorf("Failed to read remote state: %s", err)
|
||||
return nil, fmt.Errorf("failed to read remote state: %s", err)
|
||||
}
|
||||
sum := md5.Sum(buf.Bytes())
|
||||
payload := &remote.Payload{
|
||||
|
@ -452,5 +449,4 @@ This may be caused by unusually long delays in OSS processing a previous state
|
|||
update. Please wait for a minute or two and try again. If this problem
|
||||
persists, and neither OSS nor TableStore are experiencing an outage, you may need
|
||||
to manually verify the remote state and update the Digest value stored in the
|
||||
TableStore table to the following value: %x
|
||||
`
|
||||
TableStore table to the following value: %x`
|
||||
|
|
|
@ -77,36 +77,41 @@ data "terraform_remote_state" "network" {
|
|||
|
||||
The following configuration options or environment variables are supported:
|
||||
|
||||
* `access_key` - (Optional) Alibaba Cloud access key. It supports environment variables `ALICLOUD_ACCESS_KEY` and `ALICLOUD_ACCESS_KEY_ID`.
|
||||
* `secret_key` - (Optional) Alibaba Cloud secret access key. It supports environment variables `ALICLOUD_SECRET_KEY` and `ALICLOUD_ACCESS_KEY_SECRET`.
|
||||
* `security_token` - (Optional) STS access token. It supports environment variable `ALICLOUD_SECURITY_TOKEN`.
|
||||
* `ecs_role_name` - (Optional, Available in 0.12.14+) The RAM Role Name attached on a ECS instance for API operations. You can retrieve this from the 'Access Control' section of the Alibaba Cloud console.
|
||||
* `region` - (Optional) The region of the OSS bucket. It supports environment variables `ALICLOUD_REGION` and `ALICLOUD_DEFAULT_REGION`.
|
||||
* `endpoint` - (Optional) A custom endpoint for the OSS API. It supports environment variables `ALICLOUD_OSS_ENDPOINT` and `OSS_ENDPOINT`.
|
||||
* `bucket` - (Required) The name of the OSS bucket.
|
||||
* `prefix` - (Opeional) The path directory of the state file will be stored. Default to "env:".
|
||||
* `key` - (Optional) The name of the state file. Defaults to `terraform.tfstate`.
|
||||
* `tablestore_endpoint` / `ALICLOUD_TABLESTORE_ENDPOINT` - (Optional) A custom endpoint for the TableStore API.
|
||||
* `tablestore_table` - (Optional) A TableStore table for state locking and consistency. The table must have a primary key named `LockID` of type `String`.
|
||||
* `encrypt` - (Optional) Whether to enable server side
|
||||
encryption of the state file. If it is true, OSS will use 'AES256' encryption algorithm to encrypt state file.
|
||||
* `acl` - (Optional) [Object
|
||||
ACL](https://www.alibabacloud.com/help/doc-detail/52284.htm)
|
||||
to be applied to the state file.
|
||||
* `shared_credentials_file` - (Optional, Available in 0.12.8+) This is the path to the shared credentials file. It can also be sourced from the `ALICLOUD_SHARED_CREDENTIALS_FILE` environment variable. If this is not set and a profile is specified, `~/.aliyun/config.json` will be used.
|
||||
* `profile` - (Optional, Available in 0.12.8+) This is the Alibaba Cloud profile name as set in the shared credentials file. It can also be sourced from the `ALICLOUD_PROFILE` environment variable.
|
||||
* `assume_role` - (Optional, Available in 0.12.6+) If provided with a role ARN, will attempt to assume this role using the supplied credentials.
|
||||
|
||||
The nested `assume_role` block supports the following:
|
||||
|
||||
* `role_arn` - (Required) The ARN of the role to assume. If ARN is set to an empty string, it does not perform role switching. It supports environment variable `ALICLOUD_ASSUME_ROLE_ARN`.
|
||||
* `access_key` - (Optional) Alibaba Cloud access key. It supports environment variables `ALICLOUD_ACCESS_KEY` and `ALICLOUD_ACCESS_KEY_ID`.
|
||||
* `secret_key` - (Optional) Alibaba Cloud secret access key. It supports environment variables `ALICLOUD_SECRET_KEY` and `ALICLOUD_ACCESS_KEY_SECRET`.
|
||||
* `security_token` - (Optional) STS access token. It supports environment variable `ALICLOUD_SECURITY_TOKEN`.
|
||||
* `ecs_role_name` - (Optional, Available in 0.12.14+) The RAM Role Name attached on a ECS instance for API operations. You can retrieve this from the 'Access Control' section of the Alibaba Cloud console.
|
||||
* `region` - (Optional) The region of the OSS bucket. It supports environment variables `ALICLOUD_REGION` and `ALICLOUD_DEFAULT_REGION`.
|
||||
* `endpoint` - (Optional) A custom endpoint for the OSS API. It supports environment variables `ALICLOUD_OSS_ENDPOINT` and `OSS_ENDPOINT`.
|
||||
* `bucket` - (Required) The name of the OSS bucket.
|
||||
* `prefix` - (Opeional) The path directory of the state file will be stored. Default to "env:".
|
||||
* `key` - (Optional) The name of the state file. Defaults to `terraform.tfstate`.
|
||||
* `tablestore_endpoint` / `ALICLOUD_TABLESTORE_ENDPOINT` - (Optional) A custom endpoint for the TableStore API.
|
||||
* `tablestore_table` - (Optional) A TableStore table for state locking and consistency. The table must have a primary key named `LockID` of type `String`.
|
||||
* `encrypt` - (Optional) Whether to enable server side
|
||||
encryption of the state file. If it is true, OSS will use 'AES256' encryption algorithm to encrypt state file.
|
||||
* `acl` - (Optional) [Object
|
||||
ACL](https://www.alibabacloud.com/help/doc-detail/52284.htm)
|
||||
to be applied to the state file.
|
||||
* `shared_credentials_file` - (Optional, Available in 0.12.8+) This is the path to the shared credentials file. It can also be sourced from the `ALICLOUD_SHARED_CREDENTIALS_FILE` environment variable. If this is not set and a profile is specified, `~/.aliyun/config.json` will be used.
|
||||
* `profile` - (Optional, Available in 0.12.8+) This is the Alibaba Cloud profile name as set in the shared credentials file. It can also be sourced from the `ALICLOUD_PROFILE` environment variable.
|
||||
* `assume_role_role_arn` - (Optional, Available in 1.1.0+) The ARN of the role to assume. If ARN is set to an empty string, it does not perform role switching. It supports the environment variable `ALICLOUD_ASSUME_ROLE_ARN`.
|
||||
Terraform executes configuration on account with provided credentials.
|
||||
* `assume_role_policy` - (Optional, Available in 1.1.0+ A more restrictive policy to apply to the temporary credentials. This gives you a way to further restrict the permissions for the resulting temporary security credentials. You cannot use this policy to grant permissions that exceed those of the role that is being assumed.
|
||||
* `assume_role_session_name` - (Optional, Available in 1.1.0+) The session name to use when assuming the role. If omitted, 'terraform' is passed to the AssumeRole call as session name. It supports environment variable `ALICLOUD_ASSUME_ROLE_SESSION_NAME`.
|
||||
* `assume_role_session_expiration` - (Optional, Available in 1.1.0+ The time after which the established session for assuming role expires. Valid value range: [900-3600] seconds. Default to 3600 (in this case Alibaba Cloud uses its own default value). It supports environment variable `ALICLOUD_ASSUME_ROLE_SESSION_EXPIRATION`.
|
||||
|
||||
* `policy` - (Optional) A more restrictive policy to apply to the temporary credentials. This gives you a way to further restrict the permissions for the resulting temporary
|
||||
security credentials. You cannot use this policy to grant permissions which exceed those of the role that is being assumed.
|
||||
* `assume_role` - (**Deprecated as of 1.1.0+**, Available in 0.12.6+) If provided with a role ARN, will attempt to assume this role using the supplied credentials.
|
||||
|
||||
* `session_name` - (Optional) The session name to use when assuming the role. If omitted, 'terraform' is passed to the AssumeRole call as session name. It supports environment variable `ALICLOUD_ASSUME_ROLE_SESSION_NAME`.
|
||||
**Deprecated in favor of flattening assume_role_\* options**
|
||||
|
||||
* `session_expiration` - (Optional) The time after which the established session for assuming role expires. Valid value range: [900-3600] seconds. Default to 3600 (in this case Alibaba Cloud use own default value). It supports environment variable `ALICLOUD_ASSUME_ROLE_SESSION_EXPIRATION`.
|
||||
* `role_arn` - (Required) The ARN of the role to assume. If ARN is set to an empty string, it does not perform role switching. It supports the environment variable `ALICLOUD_ASSUME_ROLE_ARN`.
|
||||
Terraform executes configuration on account with provided credentials.
|
||||
|
||||
-> **Note:** If you want to store state in the custom OSS endpoint, you can specify a environment variable `OSS_ENDPOINT`, like "oss-cn-beijing-internal.aliyuncs.com"
|
||||
* `policy` - (Optional) A more restrictive policy to apply to the temporary credentials. This gives you a way to further restrict the permissions for the resulting temporary security credentials. You cannot use this policy to grant permissions that exceed those of the role that is being assumed.
|
||||
|
||||
* `session_name` - (Optional) The session name to use when assuming the role. If omitted, 'terraform' is passed to the AssumeRole call as session name. It supports environment variable `ALICLOUD_ASSUME_ROLE_SESSION_NAME`.
|
||||
|
||||
* `session_expiration` - (Optional) The time after which the established session for assuming role expires. Valid value range: [900-3600] seconds. Default to 3600 (in this case Alibaba Cloud uses its own default value). It supports environment variable `ALICLOUD_ASSUME_ROLE_SESSION_EXPIRATION`.
|
||||
|
||||
-> **Note:** If you want to store state in the custom OSS endpoint, you can specify an environment variable `OSS_ENDPOINT`, like "oss-cn-beijing-internal.aliyuncs.com"
|
||||
|
|
Loading…
Reference in New Issue