-
Notifications
You must be signed in to change notification settings - Fork 27
S3 support #7
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
S3 support #7
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,192 @@ | ||||||||||||||||||||||||||||
| package cachers | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| import ( | ||||||||||||||||||||||||||||
| "bytes" | ||||||||||||||||||||||||||||
| "context" | ||||||||||||||||||||||||||||
| "encoding/json" | ||||||||||||||||||||||||||||
| "errors" | ||||||||||||||||||||||||||||
| "fmt" | ||||||||||||||||||||||||||||
| "io" | ||||||||||||||||||||||||||||
| "log" | ||||||||||||||||||||||||||||
| "runtime" | ||||||||||||||||||||||||||||
| "strings" | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| "github.com/aws/smithy-go" | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| "github.com/aws/aws-sdk-go-v2/aws" | ||||||||||||||||||||||||||||
| "github.com/aws/aws-sdk-go-v2/service/s3" | ||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| type S3Cache struct { | ||||||||||||||||||||||||||||
| Bucket string | ||||||||||||||||||||||||||||
| cfg *aws.Config | ||||||||||||||||||||||||||||
| // diskCache is where to write the output files to local disk, as required by the | ||||||||||||||||||||||||||||
| // cache protocol. | ||||||||||||||||||||||||||||
| diskCache *DiskCache | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| prefix string | ||||||||||||||||||||||||||||
| // verbose optionally specifies whether to log verbose messages. | ||||||||||||||||||||||||||||
| verbose bool | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| s3Client *s3.Client | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| func NewS3Cache(bucketName string, cfg *aws.Config, cacheKey string, disk *DiskCache, verbose bool) *S3Cache { | ||||||||||||||||||||||||||||
| // get current architecture | ||||||||||||||||||||||||||||
| arc := runtime.GOARCH | ||||||||||||||||||||||||||||
| // get current operating system | ||||||||||||||||||||||||||||
| os := runtime.GOOS | ||||||||||||||||||||||||||||
| // get current version of Go | ||||||||||||||||||||||||||||
| ver := strings.ReplaceAll(strings.ReplaceAll(runtime.Version(), " ", "-"), ":", "-") | ||||||||||||||||||||||||||||
| prefix := fmt.Sprintf("cache/%s/%s/%s/%s", cacheKey, arc, os, ver) | ||||||||||||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Consider There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It would be good behavior to make the
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||||||||||||||||||||||||||||
| log.Printf("S3Cache: configured to s3://%s/%s", bucketName, prefix) | ||||||||||||||||||||||||||||
| return &S3Cache{ | ||||||||||||||||||||||||||||
| Bucket: bucketName, | ||||||||||||||||||||||||||||
| cfg: cfg, | ||||||||||||||||||||||||||||
| diskCache: disk, | ||||||||||||||||||||||||||||
| prefix: prefix, | ||||||||||||||||||||||||||||
| verbose: verbose, | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| func (c *S3Cache) client(ctx context.Context) (*s3.Client, error) { | ||||||||||||||||||||||||||||
| if c.s3Client != nil { | ||||||||||||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is not thread safe. I don't know if upstream guarantees to only have one caller, but consider A) Doing the initial assignment in a
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||||||||||||||||||||||||||||
| return c.s3Client, nil | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
| c.s3Client = s3.NewFromConfig(*c.cfg) | ||||||||||||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Pretty much everybody that aren't connecting to AWS S3 will want to use path-style: Making it an option seems reasonable, though.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Feel free to open a PR for this feature to my fork 🙏 |
||||||||||||||||||||||||||||
| return c.s3Client, nil | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| func isNotFoundError(err error) bool { | ||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||
| var ae smithy.APIError | ||||||||||||||||||||||||||||
| if errors.As(err, &ae) { | ||||||||||||||||||||||||||||
| code := ae.ErrorCode() | ||||||||||||||||||||||||||||
| return code == "AccessDenied" || code == "NoSuchKey" | ||||||||||||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. AccessDenied?
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good question. Not sure why I chose AccessDenied, maybe my original permissions were only to |
||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
| return false | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| func (c *S3Cache) Get(ctx context.Context, actionID string) (outputID, diskPath string, err error) { | ||||||||||||||||||||||||||||
| outputID, diskPath, err = c.diskCache.Get(ctx, actionID) | ||||||||||||||||||||||||||||
| if err == nil && outputID != "" { | ||||||||||||||||||||||||||||
| return outputID, diskPath, nil | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
| client, err := c.client(ctx) | ||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||
| if c.verbose { | ||||||||||||||||||||||||||||
| log.Printf("error getting S3 client: %v", err) | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
| return "", "", err | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
| actionKey := c.actionKey(actionID) | ||||||||||||||||||||||||||||
| result, err := client.GetObject(ctx, &s3.GetObjectInput{ | ||||||||||||||||||||||||||||
| Bucket: &c.Bucket, | ||||||||||||||||||||||||||||
| Key: &actionKey, | ||||||||||||||||||||||||||||
| }) | ||||||||||||||||||||||||||||
| // handle object not found | ||||||||||||||||||||||||||||
| if isNotFoundError(err) { | ||||||||||||||||||||||||||||
| return "", "", nil | ||||||||||||||||||||||||||||
| } else if err != nil { | ||||||||||||||||||||||||||||
| if c.verbose { | ||||||||||||||||||||||||||||
| log.Printf("error S3 get for %s: %v", actionKey, err) | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
| return "", "", fmt.Errorf("unexpected S3 get for %s: %v", actionKey, err) | ||||||||||||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
| defer result.Body.Close() | ||||||||||||||||||||||||||||
| var av ActionValue | ||||||||||||||||||||||||||||
| body, err := io.ReadAll(result.Body) | ||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||
| return "", "", err | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
| if err := json.Unmarshal(body, &av); err != nil { | ||||||||||||||||||||||||||||
|
Comment on lines
+99
to
+103
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let's stream the response:
Suggested change
(but maybe drop, see later)
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. changed implementation here - or-shachar@0bc8aa9#diff-3996ec7951ff9218f18b180f064a24e55ee57da5f81810fcb063e37f339896caR69 |
||||||||||||||||||||||||||||
| if c.verbose { | ||||||||||||||||||||||||||||
| log.Printf("error unmarshalling JSON for %s: %v", actionKey, err) | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
| return "", "", err | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| outputID = av.OutputID | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| var putBody io.Reader | ||||||||||||||||||||||||||||
| if av.Size == 0 { | ||||||||||||||||||||||||||||
| putBody = bytes.NewReader(nil) | ||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||
| outputKey := c.outputKey(outputID) | ||||||||||||||||||||||||||||
| outputResult, getOutputErr := client.GetObject(ctx, &s3.GetObjectInput{ | ||||||||||||||||||||||||||||
| Bucket: &c.Bucket, | ||||||||||||||||||||||||||||
| Key: &outputKey, | ||||||||||||||||||||||||||||
| }) | ||||||||||||||||||||||||||||
| if isNotFoundError(getOutputErr) { | ||||||||||||||||||||||||||||
| // handle object not found | ||||||||||||||||||||||||||||
| return "", "", nil | ||||||||||||||||||||||||||||
| } else if getOutputErr != nil { | ||||||||||||||||||||||||||||
| if c.verbose { | ||||||||||||||||||||||||||||
| log.Printf("error S3 get for %s: %v", outputKey, getOutputErr) | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
| return "", "", fmt.Errorf("unexpected S3 get for %s: %v", outputKey, getOutputErr) | ||||||||||||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
| defer outputResult.Body.Close() | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| putBody = outputResult.Body | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
| diskPath, err = c.diskCache.Put(ctx, actionID, outputID, av.Size, putBody) | ||||||||||||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Need help: Documentation indicates that modtime of the file is used for "something". You may need some way to set the mod-time to the object write time. This should be available from S3.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you please reference the relevant documentation? |
||||||||||||||||||||||||||||
| return outputID, diskPath, err | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
| func (c *S3Cache) actionKey(actionID string) string { | ||||||||||||||||||||||||||||
| return fmt.Sprintf("%s/actions/%s", c.prefix, actionID) | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| func (c *S3Cache) outputKey(outputID string) string { | ||||||||||||||||||||||||||||
| return fmt.Sprintf("%s/output/%s", c.prefix, outputID) | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| func (c *S3Cache) Put(ctx context.Context, actionID, outputID string, size int64, body io.Reader) (diskPath string, _ error) { | ||||||||||||||||||||||||||||
| // Write to disk locally as we write it remotely, as we need to guarantee | ||||||||||||||||||||||||||||
| // it's on disk locally for the caller. | ||||||||||||||||||||||||||||
| var readerForDisk io.Reader | ||||||||||||||||||||||||||||
| var readerForS3 bytes.Buffer | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| if size == 0 { | ||||||||||||||||||||||||||||
| // Special case the empty file so NewRequest sets "Content-Length: 0", | ||||||||||||||||||||||||||||
| // as opposed to thinking we didn't set it and not being able to sniff its size | ||||||||||||||||||||||||||||
| // from the type. | ||||||||||||||||||||||||||||
| readerForDisk = bytes.NewReader(nil) | ||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||
| readerForDisk = io.TeeReader(body, &readerForS3) | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| diskPath, err := c.diskCache.Put(ctx, actionID, outputID, size, readerForDisk) | ||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||
| return "", err | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| client, err := c.client(ctx) | ||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||
| return "", err | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
| av := ActionValue{ | ||||||||||||||||||||||||||||
| OutputID: outputID, | ||||||||||||||||||||||||||||
| Size: size, | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
| avj, err := json.Marshal(av) | ||||||||||||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 2 PutObject calls per write seems like one to many. And a place where inconsistencies could creep in. Having 1 write will make it atomic, so probably that is a win here. I suggest you store the object using the There is a 2KB limit on metadata, so maybe check if that is likely to be exceeded.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This was done on the main branch of my fork |
||||||||||||||||||||||||||||
| if err == nil { | ||||||||||||||||||||||||||||
| actionKey := c.actionKey(actionID) | ||||||||||||||||||||||||||||
| _, err = client.PutObject(ctx, &s3.PutObjectInput{ | ||||||||||||||||||||||||||||
| Bucket: &c.Bucket, | ||||||||||||||||||||||||||||
| Key: &actionKey, | ||||||||||||||||||||||||||||
| Body: bytes.NewReader(avj), | ||||||||||||||||||||||||||||
| }) | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
| if size > 0 && err == nil { | ||||||||||||||||||||||||||||
| outputKey := c.outputKey(outputID) | ||||||||||||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||||||||||
| _, err = client.PutObject(ctx, &s3.PutObjectInput{ | ||||||||||||||||||||||||||||
| Bucket: &c.Bucket, | ||||||||||||||||||||||||||||
| Key: &outputKey, | ||||||||||||||||||||||||||||
| Body: &readerForS3, | ||||||||||||||||||||||||||||
| ContentLength: size, | ||||||||||||||||||||||||||||
| }) | ||||||||||||||||||||||||||||
|
Comment on lines
+184
to
+189
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
| return | ||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -6,37 +6,97 @@ | |||||||||||
| package main | ||||||||||||
|
|
||||||||||||
| import ( | ||||||||||||
| "context" | ||||||||||||
| "flag" | ||||||||||||
| "log" | ||||||||||||
| "os" | ||||||||||||
| "path/filepath" | ||||||||||||
|
|
||||||||||||
| "github.com/aws/aws-sdk-go-v2/config" | ||||||||||||
| "github.com/aws/aws-sdk-go-v2/credentials" | ||||||||||||
|
|
||||||||||||
| "github.com/aws/aws-sdk-go-v2/aws" | ||||||||||||
|
|
||||||||||||
| "github.com/bradfitz/go-tool-cache/cacheproc" | ||||||||||||
| "github.com/bradfitz/go-tool-cache/cachers" | ||||||||||||
| ) | ||||||||||||
|
|
||||||||||||
| const defaultCacheKey = "v1" | ||||||||||||
|
|
||||||||||||
| var ( | ||||||||||||
| dir = flag.String("cache-dir", "", "cache directory; empty means automatic") | ||||||||||||
| serverBase = flag.String("cache-server", "", "optional cache server HTTP prefix (scheme and authority only); should be low latency. empty means to not use one.") | ||||||||||||
| verbose = flag.Bool("verbose", false, "be verbose") | ||||||||||||
| ) | ||||||||||||
|
|
||||||||||||
| func getAwsConfigFromEnv() (*aws.Config, error) { | ||||||||||||
| // read from env | ||||||||||||
| awsRegion, awsRegionOk := os.LookupEnv("GOCACHE_AWS_REGION") | ||||||||||||
| if !awsRegionOk { | ||||||||||||
| return nil, nil | ||||||||||||
| } | ||||||||||||
| accessKey, accessKeyOk := os.LookupEnv("GOCACHE_AWS_ACCESS_KEY") | ||||||||||||
| secretAccessKey, secretKeyOk := os.LookupEnv("GOCACHE_AWS_SECRET_ACCESS_KEY") | ||||||||||||
| if accessKeyOk && secretKeyOk { | ||||||||||||
| cfg, err := config.LoadDefaultConfig(context.TODO(), | ||||||||||||
| config.WithRegion(awsRegion), | ||||||||||||
| config.WithCredentialsProvider(credentials.StaticCredentialsProvider{ | ||||||||||||
| Value: aws.Credentials{ | ||||||||||||
| AccessKeyID: accessKey, | ||||||||||||
| SecretAccessKey: secretAccessKey, | ||||||||||||
| }, | ||||||||||||
| })) | ||||||||||||
| if err != nil { | ||||||||||||
| return nil, err | ||||||||||||
| } | ||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Many will want to use a custom endpoint:
Suggested change
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. feel free to open a PR to my fork :) |
||||||||||||
| return &cfg, nil | ||||||||||||
| } | ||||||||||||
| credsProfile, credsProfileOk := os.LookupEnv("GOCACHE_CREDS_PROFILE") | ||||||||||||
| if credsProfileOk { | ||||||||||||
| cfg, err := config.LoadDefaultConfig(context.TODO(), config.WithRegion(awsRegion), config.WithSharedConfigProfile(credsProfile)) | ||||||||||||
| if err != nil { | ||||||||||||
| return nil, err | ||||||||||||
| } | ||||||||||||
| return &cfg, nil | ||||||||||||
| } | ||||||||||||
| return nil, nil | ||||||||||||
| } | ||||||||||||
|
|
||||||||||||
| func maybeS3Cache(dc *cachers.DiskCache) (*cachers.S3Cache, error) { | ||||||||||||
| awsConfig, err := getAwsConfigFromEnv() | ||||||||||||
| if err != nil { | ||||||||||||
| return nil, err | ||||||||||||
| } | ||||||||||||
| bucket, ok := os.LookupEnv("GOCACHE_S3_BUCKET") | ||||||||||||
| if !ok || awsConfig == nil { | ||||||||||||
| // We need at least name of bucket and valid aws config | ||||||||||||
| return nil, nil | ||||||||||||
| } | ||||||||||||
| cacheKey := os.Getenv("GOCACHE_CACHE_KEY") | ||||||||||||
| if cacheKey == "" { | ||||||||||||
| cacheKey = defaultCacheKey | ||||||||||||
| } | ||||||||||||
|
|
||||||||||||
| s3Cache := cachers.NewS3Cache(bucket, awsConfig, cacheKey, dc, *verbose) | ||||||||||||
| return s3Cache, nil | ||||||||||||
| } | ||||||||||||
|
|
||||||||||||
| func main() { | ||||||||||||
| flag.Parse() | ||||||||||||
| if *dir == "" { | ||||||||||||
| dir := os.Getenv("GOCACHE_DISK_DIR") | ||||||||||||
| if dir == "" { | ||||||||||||
| d, err := os.UserCacheDir() | ||||||||||||
| if err != nil { | ||||||||||||
| log.Fatal(err) | ||||||||||||
| } | ||||||||||||
| d = filepath.Join(d, "go-cacher") | ||||||||||||
| log.Printf("Defaulting to cache dir %v ...", d) | ||||||||||||
| *dir = d | ||||||||||||
| dir = d | ||||||||||||
| } | ||||||||||||
| if err := os.MkdirAll(*dir, 0755); err != nil { | ||||||||||||
| log.Printf("cache dir %v ...", dir) | ||||||||||||
| if err := os.MkdirAll(dir, 0755); err != nil { | ||||||||||||
| log.Fatal(err) | ||||||||||||
| } | ||||||||||||
|
|
||||||||||||
| dc := &cachers.DiskCache{Dir: *dir} | ||||||||||||
| dc := &cachers.DiskCache{Dir: dir} | ||||||||||||
|
|
||||||||||||
| var p *cacheproc.Process | ||||||||||||
| p = &cacheproc.Process{ | ||||||||||||
|
|
@@ -61,6 +121,15 @@ func main() { | |||||||||||
| p.Put = hc.Put | ||||||||||||
| } | ||||||||||||
|
|
||||||||||||
| s3Cache, err := maybeS3Cache(dc) | ||||||||||||
| if err != nil { | ||||||||||||
| log.Fatal(err) | ||||||||||||
| } | ||||||||||||
| if s3Cache != nil { | ||||||||||||
| p.Get = s3Cache.Get | ||||||||||||
| p.Put = s3Cache.Put | ||||||||||||
| } | ||||||||||||
|
|
||||||||||||
| if err := p.Run(); err != nil { | ||||||||||||
| log.Fatal(err) | ||||||||||||
| } | ||||||||||||
|
|
||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,27 @@ | ||
| module github.com/bradfitz/go-tool-cache | ||
|
|
||
| go 1.20 | ||
| go 1.21 | ||
|
|
||
| require ( | ||
| github.com/aws/aws-sdk-go-v2 v1.22.2 | ||
| github.com/aws/aws-sdk-go-v2/config v1.23.0 | ||
| github.com/aws/aws-sdk-go-v2/credentials v1.15.2 | ||
| github.com/aws/aws-sdk-go-v2/service/s3 v1.42.1 | ||
| ) | ||
|
|
||
| require ( | ||
| github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.5.0 // indirect | ||
| github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.14.3 // indirect | ||
| github.com/aws/aws-sdk-go-v2/internal/configsources v1.2.2 // indirect | ||
| github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.5.2 // indirect | ||
| github.com/aws/aws-sdk-go-v2/internal/ini v1.6.0 // indirect | ||
| github.com/aws/aws-sdk-go-v2/internal/v4a v1.2.2 // indirect | ||
| github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.10.0 // indirect | ||
| github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.2.2 // indirect | ||
| github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.10.2 // indirect | ||
| github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.16.2 // indirect | ||
| github.com/aws/aws-sdk-go-v2/service/sso v1.17.1 // indirect | ||
| github.com/aws/aws-sdk-go-v2/service/ssooidc v1.19.1 // indirect | ||
| github.com/aws/aws-sdk-go-v2/service/sts v1.25.1 // indirect | ||
| github.com/aws/smithy-go v1.16.0 // indirect | ||
| ) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,39 @@ | ||
| github.com/aws/aws-sdk-go-v2 v1.22.2 h1:lV0U8fnhAnPz8YcdmZVV60+tr6CakHzqA6P8T46ExJI= | ||
| github.com/aws/aws-sdk-go-v2 v1.22.2/go.mod h1:Kd0OJtkW3Q0M0lUWGszapWjEvrXDzRW+D21JNsroB+c= | ||
| github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.5.0 h1:hHgLiIrTRtddC0AKcJr5s7i/hLgcpTt+q/FKxf1Zayk= | ||
| github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.5.0/go.mod h1:w4I/v3NOWgD+qvs1NPEwhd++1h3XPHFaVxasfY6HlYQ= | ||
| github.com/aws/aws-sdk-go-v2/config v1.23.0 h1:kqzEfGGDIrRJpfJckgwuZfFTbU9NB1jZnRcaO9MpOqE= | ||
| github.com/aws/aws-sdk-go-v2/config v1.23.0/go.mod h1:p7wbxKXXjS1GGQOss7VXOazVMFF9bjUGq85/4wR/fSw= | ||
| github.com/aws/aws-sdk-go-v2/credentials v1.15.2 h1:rKH7khRMxPdD0u3dHecd0Q7NOVw3EUe7AqdkUOkiOGI= | ||
| github.com/aws/aws-sdk-go-v2/credentials v1.15.2/go.mod h1:tXM8wmaeAhfC7nZoCxb0FzM/aRaB1m1WQ7x0qlBLq80= | ||
| github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.14.3 h1:G5KawTAkyHH6WyKQCdHiW4h3PmAXNJpOgwKg3H7sDRE= | ||
| github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.14.3/go.mod h1:hugKmSFnZB+HgNI1sYGT14BUPZkO6alC/e0AWu+0IAQ= | ||
| github.com/aws/aws-sdk-go-v2/internal/configsources v1.2.2 h1:AaQsr5vvGR7rmeSWBtTCcw16tT9r51mWijuCQhzLnq8= | ||
| github.com/aws/aws-sdk-go-v2/internal/configsources v1.2.2/go.mod h1:o1IiRn7CWocIFTXJjGKJDOwxv1ibL53NpcvcqGWyRBA= | ||
| github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.5.2 h1:UZx8SXZ0YtzRiALzYAWcjb9Y9hZUR7MBKaBQ5ouOjPs= | ||
| github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.5.2/go.mod h1:ipuRpcSaklmxR6C39G187TpBAO132gUfleTGccUPs8c= | ||
| github.com/aws/aws-sdk-go-v2/internal/ini v1.6.0 h1:hwZB07/beLiCopuRKF0t+dEHmP39iN4YtDh3X5d3hrg= | ||
| github.com/aws/aws-sdk-go-v2/internal/ini v1.6.0/go.mod h1:rdAuXeHWhI/zkpYcO5n8WCpaIgY9MUxFyBsuqq3kjyA= | ||
| github.com/aws/aws-sdk-go-v2/internal/v4a v1.2.2 h1:pyVrNAf7Hwz0u39dLKN5t+n0+K/3rMYKuiOoIum3AsU= | ||
| github.com/aws/aws-sdk-go-v2/internal/v4a v1.2.2/go.mod h1:mydrfOb9uiOYCxuCPR8YHQNQyGQwUQ7gPMZGBKbH8NY= | ||
| github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.10.0 h1:CJxo7ZBbaIzmXfV3hjcx36n9V87gJsIUPJflwqEHl3Q= | ||
| github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.10.0/go.mod h1:yjVfjuY4nD1EW9i387Kau+I6V5cBA5YnC/mWNopjZrI= | ||
| github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.2.2 h1:f2LhPofnjcdOQKRtumKjMvIHkfSQ8aH/rwKUDEQ/SB4= | ||
| github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.2.2/go.mod h1:q+xX0H4OfuWDuBy7y/LDi4v8IBOWuF+vtp8Z6ex+lw4= | ||
| github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.10.2 h1:h7j73yuAVVjic8pqswh+L/7r2IHP43QwRyOu6zcCDDE= | ||
| github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.10.2/go.mod h1:H07AHdK5LSy8F7EJUQhoxyiCNkePoHj2D8P2yGTWafo= | ||
| github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.16.2 h1:gbIaOzpXixUpoPK+js/bCBK1QBDXM22SigsnzGZio0U= | ||
| github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.16.2/go.mod h1:p+S7RNbdGN8qgHDSg2SCQJ9FeMAmvcETQiVpeGhYnNM= | ||
| github.com/aws/aws-sdk-go-v2/service/s3 v1.42.1 h1:o6MCcX1rJW8Y3g+hvg2xpjF6JR6DftuYhfl3Nc1WV9Q= | ||
| github.com/aws/aws-sdk-go-v2/service/s3 v1.42.1/go.mod h1:UDtxEWbREX6y4KREapT+jjtjoH0TiVSS6f5nfaY1UaM= | ||
| github.com/aws/aws-sdk-go-v2/service/sso v1.17.1 h1:km+ZNjtLtpXYf42RdaDZnNHm9s7SYAuDGTafy6nd89A= | ||
| github.com/aws/aws-sdk-go-v2/service/sso v1.17.1/go.mod h1:aHBr3pvBSD5MbzOvQtYutyPLLRPbl/y9x86XyJJnUXQ= | ||
| github.com/aws/aws-sdk-go-v2/service/ssooidc v1.19.1 h1:iRFNqZH4a67IqPvK8xxtyQYnyrlsvwmpHOe9r55ggBA= | ||
| github.com/aws/aws-sdk-go-v2/service/ssooidc v1.19.1/go.mod h1:pTy5WM+6sNv2tB24JNKFtn6EvciQ5k40ZJ0pq/Iaxj0= | ||
| github.com/aws/aws-sdk-go-v2/service/sts v1.25.1 h1:txgVXIXWPXyqdiVn92BV6a/rgtpX31HYdsOYj0sVQQQ= | ||
| github.com/aws/aws-sdk-go-v2/service/sts v1.25.1/go.mod h1:VAiJiNaoP1L89STFlEMgmHX1bKixY+FaP+TpRFrmyZ4= | ||
| github.com/aws/smithy-go v1.16.0 h1:gJZEH/Fqh+RsvlJ1Zt4tVAtV6bKkp3cC+R6FCZMNzik= | ||
| github.com/aws/smithy-go v1.16.0/go.mod h1:NukqUGpCZIILqqiV0NIjeFh24kd/FAa4beRb6nbIUPE= | ||
| github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= | ||
| github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= | ||
| github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think having the same prefix makes it clearer. I suggest using the service name rather than the vendor name. (same goes for other env vars)