mirror of
https://github.com/opentffoundation/opentf.git
synced 2025-12-25 01:00:16 -05:00
Lock object writing is configured the same with the state object writing (#2606)
Signed-off-by: yottta <andrei.ciobanu@opentofu.org>
This commit is contained in:
@@ -351,6 +351,23 @@ func (c *RemoteClient) s3Lock(info *statemgr.LockInfo) error {
|
||||
IfNoneMatch: aws.String("*"),
|
||||
}
|
||||
|
||||
if !c.skipS3Checksum {
|
||||
putParams.ChecksumAlgorithm = types.ChecksumAlgorithmSha256
|
||||
|
||||
// There is a conflict in the aws-go-sdk-v2 that prevents it from working with many s3 compatible services
|
||||
// Since we can pre-compute the hash here, we can work around it.
|
||||
// ref: https://github.com/aws/aws-sdk-go-v2/issues/1689
|
||||
algo := sha256.New()
|
||||
algo.Write(lInfo)
|
||||
sum64str := base64.StdEncoding.EncodeToString(algo.Sum(nil))
|
||||
putParams.ChecksumSHA256 = &sum64str
|
||||
}
|
||||
|
||||
if c.acl != "" {
|
||||
putParams.ACL = types.ObjectCannedACL(c.acl)
|
||||
}
|
||||
|
||||
log.Printf("[DEBUG] Uploading s3 locking object: %#v", putParams)
|
||||
ctx := context.TODO()
|
||||
ctx, _ = attachLoggerToContext(ctx)
|
||||
_, err := c.s3Client.PutObject(ctx, putParams, s3optDisableDefaultChecksum(c.skipS3Checksum))
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"slices"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
@@ -900,6 +901,68 @@ func TestS3ChecksumsHeaders(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestS3LockingWritingHeaders is double-checking that the configuration for writing the lock object is the same
|
||||
// with the state writing configuration
|
||||
func TestS3LockingWritingHeaders(t *testing.T) {
|
||||
ignoredValues := []string{"Amz-Sdk-Invocation-Id", "Authorization", "X-Amz-Checksum-Sha256"}
|
||||
// Configured the aws config the same way it is done for the backend to ensure a similar setup as the actual main logic.
|
||||
_, awsCfg, _ := awsbase.GetAwsConfig(context.Background(), &awsbase.Config{Region: "us-east-1", AccessKey: "test", SecretKey: "key"})
|
||||
httpCl := &mockHttpClient{resp: &http.Response{StatusCode: http.StatusOK, Body: io.NopCloser(strings.NewReader(""))}}
|
||||
s3Cl := s3.NewFromConfig(awsCfg, func(options *s3.Options) {
|
||||
options.HTTPClient = httpCl
|
||||
})
|
||||
rc := RemoteClient{
|
||||
s3Client: s3Cl,
|
||||
bucketName: "test-bucket",
|
||||
path: "state-file",
|
||||
useLockfile: true,
|
||||
}
|
||||
var (
|
||||
stateWritingReq, lockWritingReq *http.Request
|
||||
)
|
||||
// get the request from state writing
|
||||
{
|
||||
err := rc.Put([]byte("test"))
|
||||
if err != nil {
|
||||
t.Fatalf("expected to have no error writing the state object but got one: %s", err)
|
||||
}
|
||||
if httpCl.receivedReq == nil {
|
||||
t.Fatal("request didn't reach the mock http client")
|
||||
}
|
||||
stateWritingReq = httpCl.receivedReq
|
||||
}
|
||||
// get the request from lock object writing
|
||||
{
|
||||
err := rc.s3Lock(&statemgr.LockInfo{Info: "test"})
|
||||
if err != nil {
|
||||
t.Fatalf("expected to have no error writing the lock object but got one: %s", err)
|
||||
}
|
||||
if httpCl.receivedReq == nil {
|
||||
t.Fatal("request didn't reach the mock http client")
|
||||
}
|
||||
lockWritingReq = httpCl.receivedReq
|
||||
}
|
||||
|
||||
// compare headers
|
||||
for k, v := range stateWritingReq.Header {
|
||||
got := lockWritingReq.Header.Values(k)
|
||||
if len(got) == 0 {
|
||||
t.Errorf("found a header that is missing from the request for locking: %s", k)
|
||||
continue
|
||||
}
|
||||
// do not compare header values that are meant to be different since are generated but ensure that there are values in those
|
||||
if slices.Contains(ignoredValues, k) {
|
||||
if len(got[0]) == 0 {
|
||||
t.Errorf("header %q from lock request is having an empty value: %#v", k, got)
|
||||
}
|
||||
continue
|
||||
}
|
||||
if !slices.Equal(got, v) {
|
||||
t.Errorf("found a header %q in lock request that is having a different value from the state one\nin-state-req: %#v\nin-lock-req: %#v", k, v, got)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// mockHttpClient is used to test the interaction of the s3 backend with the aws-sdk.
|
||||
// This is meant to be configured with a response that will be returned to the aws-sdk.
|
||||
// The receivedReq is going to contain the last request received by it.
|
||||
|
||||
Reference in New Issue
Block a user