|
|
|
|
@ -524,7 +524,6 @@ func (b *Backend) Configure(obj cty.Value) tfdiags.Diagnostics {
|
|
|
|
|
CallerName: "S3 Backend",
|
|
|
|
|
CredsFilename: stringAttr(obj, "shared_credentials_file"),
|
|
|
|
|
DebugLogging: logging.IsDebugOrHigher(),
|
|
|
|
|
IamEndpoint: stringAttrDefaultEnvVar(obj, "iam_endpoint", "AWS_ENDPOINT_URL_IAM", "AWS_IAM_ENDPOINT"),
|
|
|
|
|
MaxRetries: intAttrDefault(obj, "max_retries", 5),
|
|
|
|
|
Profile: stringAttr(obj, "profile"),
|
|
|
|
|
Region: stringAttr(obj, "region"),
|
|
|
|
|
@ -540,6 +539,15 @@ func (b *Backend) Configure(obj cty.Value) tfdiags.Diagnostics {
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if v, ok := retrieveArgument(&diags,
|
|
|
|
|
newAttributeRetriever(obj, cty.GetAttrPath("endpoints").GetAttr("iam")),
|
|
|
|
|
newAttributeRetriever(obj, cty.GetAttrPath("iam_endpoint")),
|
|
|
|
|
newEnvvarRetriever("AWS_ENDPOINT_URL_IAM"),
|
|
|
|
|
newEnvvarRetriever("AWS_IAM_ENDPOINT"),
|
|
|
|
|
); ok {
|
|
|
|
|
cfg.IamEndpoint = v
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if assumeRole := obj.GetAttr("assume_role"); !assumeRole.IsNull() {
|
|
|
|
|
if val, ok := stringAttrOk(assumeRole, "role_arn"); ok {
|
|
|
|
|
cfg.AssumeRoleARN = val
|
|
|
|
|
@ -598,55 +606,114 @@ func (b *Backend) Configure(obj cty.Value) tfdiags.Diagnostics {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var dynamoConfig aws.Config
|
|
|
|
|
var dynamoEndpoint string
|
|
|
|
|
if val := obj.GetAttr("endpoints"); !val.IsNull() {
|
|
|
|
|
if v := val.GetAttr("dynamodb"); !v.IsNull() {
|
|
|
|
|
dynamoEndpoint = v.AsString()
|
|
|
|
|
}
|
|
|
|
|
if v, ok := retrieveArgument(&diags,
|
|
|
|
|
newAttributeRetriever(obj, cty.GetAttrPath("endpoints").GetAttr("dynamodb")),
|
|
|
|
|
newAttributeRetriever(obj, cty.GetAttrPath("dynamodb_endpoint")),
|
|
|
|
|
newEnvvarRetriever("AWS_ENDPOINT_URL_DYNAMODB"),
|
|
|
|
|
newEnvvarRetriever("AWS_DYNAMODB_ENDPOINT"),
|
|
|
|
|
); ok {
|
|
|
|
|
dynamoConfig.Endpoint = aws.String(v)
|
|
|
|
|
}
|
|
|
|
|
if dynamoEndpoint == "" {
|
|
|
|
|
if val := obj.GetAttr("dynamodb_endpoint"); !val.IsNull() {
|
|
|
|
|
dynamoEndpoint = val.AsString()
|
|
|
|
|
}
|
|
|
|
|
b.dynClient = dynamodb.New(sess.Copy(&dynamoConfig))
|
|
|
|
|
|
|
|
|
|
var s3Config aws.Config
|
|
|
|
|
if v, ok := retrieveArgument(&diags,
|
|
|
|
|
newAttributeRetriever(obj, cty.GetAttrPath("endpoints").GetAttr("s3")),
|
|
|
|
|
newAttributeRetriever(obj, cty.GetAttrPath("endpoint")),
|
|
|
|
|
newEnvvarRetriever("AWS_ENDPOINT_URL_S3"),
|
|
|
|
|
newEnvvarRetriever("AWS_S3_ENDPOINT"),
|
|
|
|
|
); ok {
|
|
|
|
|
s3Config.Endpoint = aws.String(v)
|
|
|
|
|
}
|
|
|
|
|
if dynamoEndpoint == "" {
|
|
|
|
|
dynamoEndpoint = os.Getenv("AWS_ENDPOINT_URL_DYNAMODB")
|
|
|
|
|
if v, ok := boolAttrOk(obj, "force_path_style"); ok {
|
|
|
|
|
s3Config.S3ForcePathStyle = aws.Bool(v)
|
|
|
|
|
}
|
|
|
|
|
if dynamoEndpoint == "" {
|
|
|
|
|
dynamoEndpoint = os.Getenv("AWS_DYNAMODB_ENDPOINT")
|
|
|
|
|
b.s3Client = s3.New(sess.Copy(&s3Config))
|
|
|
|
|
|
|
|
|
|
return diags
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type argumentRetriever interface {
|
|
|
|
|
Retrieve(diags *tfdiags.Diagnostics) (string, bool)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type attributeRetriever struct {
|
|
|
|
|
obj cty.Value
|
|
|
|
|
objPath cty.Path
|
|
|
|
|
attrPath cty.Path
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var _ argumentRetriever = attributeRetriever{}
|
|
|
|
|
|
|
|
|
|
func newAttributeRetriever(obj cty.Value, attrPath cty.Path) attributeRetriever {
|
|
|
|
|
return attributeRetriever{
|
|
|
|
|
obj: obj,
|
|
|
|
|
objPath: cty.Path{}, // Assumes that we're working relative to the root object
|
|
|
|
|
attrPath: attrPath,
|
|
|
|
|
}
|
|
|
|
|
if dynamoEndpoint != "" {
|
|
|
|
|
dynamoConfig.Endpoint = aws.String(dynamoEndpoint)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (r attributeRetriever) Retrieve(diags *tfdiags.Diagnostics) (string, bool) {
|
|
|
|
|
val, err := pathSafeApply(r.attrPath, r.obj)
|
|
|
|
|
if err != nil {
|
|
|
|
|
*diags = diags.Append(attributeErrDiag(
|
|
|
|
|
"Invalid Path for Schema",
|
|
|
|
|
"The S3 Backend unexpectedly provided a path that does not match the schema. "+
|
|
|
|
|
"Please report this to the developers.\n\n"+
|
|
|
|
|
"Path: "+pathString(r.attrPath)+"\n\n"+
|
|
|
|
|
"Error: "+err.Error(),
|
|
|
|
|
r.objPath,
|
|
|
|
|
))
|
|
|
|
|
}
|
|
|
|
|
b.dynClient = dynamodb.New(sess.Copy(&dynamoConfig))
|
|
|
|
|
return stringValueOk(val)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var s3Config aws.Config
|
|
|
|
|
var s3Endpoint string
|
|
|
|
|
if val := obj.GetAttr("endpoints"); !val.IsNull() {
|
|
|
|
|
if v := val.GetAttr("s3"); !v.IsNull() {
|
|
|
|
|
s3Endpoint = v.AsString()
|
|
|
|
|
}
|
|
|
|
|
// pathSafeApply applies a `cty.Path` to a `cty.Value`.
|
|
|
|
|
// Unlike `path.Apply`, it does not return an error if it encounters a Null value
|
|
|
|
|
func pathSafeApply(path cty.Path, obj cty.Value) (cty.Value, error) {
|
|
|
|
|
if obj == cty.NilVal || obj.IsNull() {
|
|
|
|
|
return obj, nil
|
|
|
|
|
}
|
|
|
|
|
if s3Endpoint == "" {
|
|
|
|
|
if val := obj.GetAttr("endpoint"); !val.IsNull() {
|
|
|
|
|
s3Endpoint = val.AsString()
|
|
|
|
|
val := obj
|
|
|
|
|
var err error
|
|
|
|
|
for _, step := range path {
|
|
|
|
|
val, err = step.Apply(val)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return cty.NilVal, err
|
|
|
|
|
}
|
|
|
|
|
if val == cty.NilVal || val.IsNull() {
|
|
|
|
|
return val, nil
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if s3Endpoint == "" {
|
|
|
|
|
s3Endpoint = os.Getenv("AWS_ENDPOINT_URL_S3")
|
|
|
|
|
}
|
|
|
|
|
if s3Endpoint == "" {
|
|
|
|
|
s3Endpoint = os.Getenv("AWS_S3_ENDPOINT")
|
|
|
|
|
}
|
|
|
|
|
if s3Endpoint != "" {
|
|
|
|
|
s3Config.Endpoint = aws.String(s3Endpoint)
|
|
|
|
|
return val, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type envvarRetriever struct {
|
|
|
|
|
name string
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var _ argumentRetriever = envvarRetriever{}
|
|
|
|
|
|
|
|
|
|
func newEnvvarRetriever(name string) envvarRetriever {
|
|
|
|
|
return envvarRetriever{
|
|
|
|
|
name: name,
|
|
|
|
|
}
|
|
|
|
|
if v, ok := boolAttrOk(obj, "force_path_style"); ok {
|
|
|
|
|
s3Config.S3ForcePathStyle = aws.Bool(v)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (r envvarRetriever) Retrieve(_ *tfdiags.Diagnostics) (string, bool) {
|
|
|
|
|
if v := os.Getenv(r.name); v != "" {
|
|
|
|
|
return v, true
|
|
|
|
|
}
|
|
|
|
|
b.s3Client = s3.New(sess.Copy(&s3Config))
|
|
|
|
|
return "", false
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return diags
|
|
|
|
|
func retrieveArgument(diags *tfdiags.Diagnostics, retrievers ...argumentRetriever) (string, bool) {
|
|
|
|
|
for _, retriever := range retrievers {
|
|
|
|
|
if v, ok := retriever.Retrieve(diags); ok {
|
|
|
|
|
return v, true
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return "", false
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func stringValue(val cty.Value) string {
|
|
|
|
|
|