package host import ( "bytes" "context" "strings" "github.com/aws/aws-sdk-go-v2/aws" awsconfig "github.com/aws/aws-sdk-go-v2/config" "github.com/aws/aws-sdk-go-v2/service/s3" "github.com/carlosframework/platform/internal/hostbox" "github.com/carlosframework/platform/internal/hostwrite" "github.com/carlosframework/platform/internal/rootaws" ) type productionClaimMarkers struct { Client *s3.Client Bucket string } func newProductionClaimMarkers(ctx context.Context, bucket, region string) (ClaimMarkerStore, error) { cfg, err := rootaws.LoadDefaultConfig(ctx, awsconfig.WithRegion(region), awsconfig.WithRetryMaxAttempts(1)) if err != nil { return nil, err } return productionClaimMarkers{Client: s3.NewFromConfig(cfg), Bucket: bucket}, nil } func (m productionClaimMarkers) PutMarker(ctx context.Context, bucket, key string, body []byte, expected string, check func(context.Context) error) (string, error) { if m.Client == nil || bucket != m.Bucket || check == nil || !strings.HasPrefix(key, "instances/") || !strings.HasSuffix(key, "/generation.json") { return "", hostwrite.ErrUnavailable } bounded, cancel := context.WithTimeout(ctx, hostbox.RequestLimit) defer cancel() if err := check(bounded); err != nil { return "", err } in := &s3.PutObjectInput{Bucket: aws.String(bucket), Key: aws.String(key), Body: bytes.NewReader(body)} if expected == "" { in.IfNoneMatch = aws.String("*") } else { in.IfMatch = aws.String(expected) } out, err := m.Client.PutObject(bounded, in) if err != nil { return "", err } if out.VersionId == nil || *out.VersionId == "" || *out.VersionId == "null" { return "", hostwrite.ErrUnavailable } return *out.VersionId, nil }