feat(train): add new command to interact with aws and train models
@ -1,20 +1,24 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"fmt"
|
||||
"github.com/cyrilix/robocar-base/cli"
|
||||
"github.com/cyrilix/robocar-tools/data"
|
||||
"github.com/cyrilix/robocar-tools/dkimpt"
|
||||
"github.com/cyrilix/robocar-tools/part"
|
||||
"github.com/cyrilix/robocar-tools/pkg/data"
|
||||
"github.com/cyrilix/robocar-tools/pkg/train"
|
||||
"github.com/cyrilix/robocar-tools/record"
|
||||
"github.com/cyrilix/robocar-tools/video"
|
||||
mqtt "github.com/eclipse/paho.mqtt.golang"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"go.uber.org/zap"
|
||||
"log"
|
||||
"os"
|
||||
)
|
||||
|
||||
const (
|
||||
DefaultClientId = "robocar-tools"
|
||||
DefaultClientId = "robocar-tools"
|
||||
DefaultTrainSliceSize = 0
|
||||
)
|
||||
|
||||
@ -27,6 +31,8 @@ func main() {
|
||||
var recordsPath string
|
||||
var trainArchiveName string
|
||||
var trainSliceSize int
|
||||
var bucket, ociImage string
|
||||
var debug bool
|
||||
|
||||
mqttQos := cli.InitIntFlag("MQTT_QOS", 0)
|
||||
_, mqttRetain := os.LookupEnv("MQTT_RETAIN")
|
||||
@ -35,9 +41,20 @@ func main() {
|
||||
fmt.Printf("Usage of %s:\n", os.Args[0])
|
||||
fmt.Printf(" display\n \tDisplay events on live frames\n")
|
||||
fmt.Printf(" record \n \tRecord event for tensorflow training\n")
|
||||
fmt.Printf(" train-archive \n \tGenerate zip archive for training \n")
|
||||
fmt.Printf(" training \n \tManage training\n")
|
||||
fmt.Printf(" import-donkey-records \n \tCopy donkeycar records to new format\n")
|
||||
}
|
||||
|
||||
err := cli.SetIntDefaultValueFromEnv(&trainSliceSize, "RC_TRAIN_SLICE_SIZE", DefaultTrainSliceSize)
|
||||
if err != nil {
|
||||
log.Printf("unable to init TRAIN_SLICE_SIZE: %v", err)
|
||||
}
|
||||
cli.SetDefaultValueFromEnv(&ociImage, "TRAIN_OCI_IMAGE", "")
|
||||
cli.SetDefaultValueFromEnv(&bucket, "TRAIN_BUCKET", "")
|
||||
|
||||
|
||||
flag.BoolVar(&debug, "debug", false, "Display debug logs")
|
||||
|
||||
displayFlags := flag.NewFlagSet("display", flag.ExitOnError)
|
||||
cli.InitMqttFlagSet(displayFlags, DefaultClientId, &mqttBroker, &username, &password, &clientId, &mqttQos, &mqttRetain)
|
||||
displayFlags.StringVar(&frameTopic, "mqtt-topic-frame", os.Getenv("MQTT_TOPIC_FRAME"), "Mqtt topic that contains frame to display, use MQTT_TOPIC_FRAME if args not set")
|
||||
@ -55,17 +72,57 @@ func main() {
|
||||
recordFlags.StringVar(&recordTopic, "mqtt-topic-records", os.Getenv("MQTT_TOPIC_RECORDS"), "Mqtt topic that contains record data for training, use MQTT_TOPIC_RECORDS if args not set")
|
||||
recordFlags.StringVar(&recordsPath, "record-path", os.Getenv("RECORD_PATH"), "Path where to write records files, use RECORD_PATH if args not set")
|
||||
|
||||
trainArchiveFlags := flag.NewFlagSet("train-archive", flag.ExitOnError)
|
||||
err := cli.SetIntDefaultValueFromEnv(&trainSliceSize, "TRAIN_SLICE_SIZE", DefaultTrainSliceSize)
|
||||
if err != nil {
|
||||
log.Printf("unable to parse horizon value arg: %v", err)
|
||||
|
||||
var basedir, destdir string
|
||||
impdkFlags := flag.NewFlagSet("import-donkey-records", flag.ExitOnError)
|
||||
impdkFlags.StringVar(&basedir, "from", "", "source directory")
|
||||
impdkFlags.StringVar(&destdir, "to", "", "destination directory")
|
||||
|
||||
|
||||
trainingFlags := flag.NewFlagSet("training", flag.ExitOnError)
|
||||
trainingFlags.Usage = func(){
|
||||
fmt.Printf("Usage of %s %s:\n", os.Args[0], trainingFlags.Name())
|
||||
fmt.Printf(" list\n \tList existing training jobs\n")
|
||||
fmt.Printf(" archive\n \tBuild tar.gz archive for training\n")
|
||||
fmt.Printf(" run\n \tRun training job\n")
|
||||
}
|
||||
|
||||
var modelPath, roleArn, trainJobName string
|
||||
trainingRunFlags := flag.NewFlagSet("run", flag.ExitOnError)
|
||||
trainingRunFlags.StringVar(&bucket, "bucket", os.Getenv("RC_TRAIN_BUCKET"), "AWS bucket where store data required, use RC_TRAIN_BUCKET if arg not set")
|
||||
trainingRunFlags.StringVar(&recordsPath, "record-path", os.Getenv("RECORD_PATH"), "Input data path where records and img files are stored, use RECORD_PATH if arg not set")
|
||||
trainingRunFlags.StringVar(&modelPath, "output-model-path", "", "Path where to write output model archive")
|
||||
trainingRunFlags.IntVar(&trainSliceSize, "slice-size", trainSliceSize, "Number of record to shift with image, use RC_TRAIN_SLICE_SIZE if args not set")
|
||||
trainingRunFlags.StringVar(&ociImage, "oci-image", os.Getenv("RC_TRAIN_OCI_IMAGE"), "OCI image to run (required), use RC_TRAIN_OCI_IMAGE if args not set")
|
||||
trainingRunFlags.StringVar(&roleArn, "role-arn", os.Getenv("RC_TRAIN_ROLE"), "AWS ARN role to use to run training (required), use RC_TRAIN_ROLE if arg not set")
|
||||
trainingRunFlags.StringVar(&trainJobName, "job-name", "", "Training job name (required)")
|
||||
|
||||
trainingListJobFlags := flag.NewFlagSet("list", flag.ExitOnError)
|
||||
|
||||
trainArchiveFlags := flag.NewFlagSet("archive", flag.ExitOnError)
|
||||
trainArchiveFlags.StringVar(&recordsPath, "record-path", os.Getenv("RECORD_PATH"), "Path where records files are stored, use RECORD_PATH if args not set")
|
||||
trainArchiveFlags.StringVar(&trainArchiveName, "output", os.Getenv("TRAIN_ARCHIVE_NAME"), "Zip archive file name, use TRAIN_ARCHIVE_NAME if args not set")
|
||||
trainArchiveFlags.IntVar(&trainSliceSize, "slice-size", trainSliceSize, "Number of record to shift with image, use TRAIN_SLICE_SIZE if args not set")
|
||||
|
||||
flag.Parse()
|
||||
|
||||
config := zap.NewDevelopmentConfig()
|
||||
if debug {
|
||||
config.Level = zap.NewAtomicLevelAt(zap.DebugLevel)
|
||||
} else {
|
||||
config.Level = zap.NewAtomicLevelAt(zap.InfoLevel)
|
||||
}
|
||||
lgr, err := config.Build()
|
||||
if err != nil {
|
||||
log.Fatalf("unable to init logger: %v", err)
|
||||
}
|
||||
defer func() {
|
||||
if err := lgr.Sync(); err != nil {
|
||||
log.Printf("unable to Sync logger: %v\n", err)
|
||||
}
|
||||
}()
|
||||
zap.ReplaceGlobals(lgr)
|
||||
|
||||
// Switch on the subcommand
|
||||
// Parse the flags for appropriate FlagSet
|
||||
// FlagSet.Parse() requires a set of arguments to parse as input
|
||||
@ -78,7 +135,7 @@ func main() {
|
||||
}
|
||||
client, err := cli.Connect(mqttBroker, username, password, clientId)
|
||||
if err != nil {
|
||||
log.Fatalf("unable to connect to mqtt bus: %v", err)
|
||||
zap.S().Fatalf("unable to connect to mqtt bus: %v", err)
|
||||
}
|
||||
defer client.Disconnect(50)
|
||||
runDisplay(client, framePath, frameTopic, fps, objectsTopic, roadTopic, withObjects, withRoad)
|
||||
@ -93,12 +150,43 @@ func main() {
|
||||
}
|
||||
defer client.Disconnect(50)
|
||||
runRecord(client, recordsPath, recordTopic)
|
||||
case trainArchiveFlags.Name():
|
||||
if err := trainArchiveFlags.Parse(os.Args[2:]); err == flag.ErrHelp {
|
||||
trainArchiveFlags.PrintDefaults()
|
||||
case impdkFlags.Name():
|
||||
if err := impdkFlags.Parse(os.Args[2:]); err == flag.ErrHelp {
|
||||
impdkFlags.PrintDefaults()
|
||||
os.Exit(0)
|
||||
}
|
||||
runTrainArchive(recordsPath, trainArchiveName, 2)
|
||||
runImportDonkeyRecords(basedir, destdir)
|
||||
case trainingFlags.Name():
|
||||
if err := trainingFlags.Parse(os.Args[2:]); err == flag.ErrHelp {
|
||||
trainingFlags.PrintDefaults()
|
||||
os.Exit(0)
|
||||
}
|
||||
switch trainingFlags.Arg(0) {
|
||||
case trainingListJobFlags.Name():
|
||||
if err:= trainingListJobFlags.Parse(os.Args[3:]); err == flag.ErrHelp {
|
||||
trainingListJobFlags.PrintDefaults()
|
||||
os.Exit(0)
|
||||
}
|
||||
runTrainList()
|
||||
case trainingRunFlags.Name():
|
||||
if err := trainingRunFlags.Parse(os.Args[3:]); err == flag.ErrHelp {
|
||||
trainingRunFlags.PrintDefaults()
|
||||
os.Exit(0)
|
||||
}
|
||||
runTraining(bucket, ociImage, roleArn, trainJobName, recordsPath, trainSliceSize, modelPath)
|
||||
case trainArchiveFlags.Name():
|
||||
if err := trainArchiveFlags.Parse(os.Args[3:]); err == flag.ErrHelp {
|
||||
trainArchiveFlags.PrintDefaults()
|
||||
os.Exit(0)
|
||||
}
|
||||
runTrainArchive(recordsPath, trainArchiveName, trainSliceSize)
|
||||
|
||||
|
||||
default:
|
||||
trainingFlags.PrintDefaults()
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
default:
|
||||
flag.PrintDefaults()
|
||||
os.Exit(1)
|
||||
@ -110,7 +198,7 @@ func runRecord(client mqtt.Client, recordsDir, recordTopic string) {
|
||||
|
||||
r, err := record.New(client, recordsDir, recordTopic)
|
||||
if err != nil {
|
||||
log.Fatalf("unable to init record part: %v", err)
|
||||
zap.S().Fatalf("unable to init record part: %v", err)
|
||||
}
|
||||
defer r.Stop()
|
||||
|
||||
@ -118,15 +206,25 @@ func runRecord(client mqtt.Client, recordsDir, recordTopic string) {
|
||||
|
||||
err = r.Start()
|
||||
if err != nil {
|
||||
log.Fatalf("unable to start service: %v", err)
|
||||
zap.S().Fatalf("unable to start service: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func runTrainArchive(basedir, archiveName string, sliceSize int) {
|
||||
|
||||
err := data.BuildArchive(basedir, archiveName, sliceSize)
|
||||
err := data.WriteArchive(basedir, archiveName, sliceSize)
|
||||
if err != nil {
|
||||
log.Fatalf("unable to build archive file %v: %v", archiveName, err)
|
||||
zap.S().Fatalf("unable to build archive file %v: %v", archiveName, err)
|
||||
}
|
||||
}
|
||||
|
||||
func runImportDonkeyRecords(basedir, destdir string) {
|
||||
if destdir == "" || basedir == "" {
|
||||
zap.S().Fatal("invalid arg")
|
||||
}
|
||||
err := dkimpt.ImportDonkeyRecords(basedir, destdir)
|
||||
if err != nil {
|
||||
zap.S().Fatalf("unable to import files from %v to %v: %v", basedir, destdir, err)
|
||||
}
|
||||
}
|
||||
|
||||
@ -152,6 +250,43 @@ func runDisplay(client mqtt.Client, framePath string, frameTopic string, fps int
|
||||
|
||||
err := p.Start()
|
||||
if err != nil {
|
||||
log.Fatalf("unable to start service: %v", err)
|
||||
zap.S().Fatalf("unable to start service: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func runTraining(bucketName string, ociImage string, roleArn string, jobName, dataDir string, sliceSize int, outputModel string) {
|
||||
l := zap.S()
|
||||
if bucketName == "" {
|
||||
l.Fatalf("no bucket define, see help")
|
||||
}
|
||||
if ociImage == "" {
|
||||
l.Fatalf("no oci image define, see help")
|
||||
}
|
||||
if jobName == "" {
|
||||
l.Fatalf("no job name define, see help")
|
||||
}
|
||||
if dataDir == "" {
|
||||
l.Fatalf("no training data define, see help")
|
||||
}
|
||||
if outputModel == "" {
|
||||
l.Fatalf("no output model path define, see help")
|
||||
}
|
||||
|
||||
if sliceSize != 0 && sliceSize != 2 {
|
||||
l.Fatalf("invalid value for sie-slice, only '0' or '2' are allowed")
|
||||
}
|
||||
|
||||
training := train.New(bucketName, ociImage, roleArn)
|
||||
err := training.TrainDir(context.Background(), jobName, dataDir, sliceSize, outputModel)
|
||||
|
||||
if err != nil {
|
||||
l.Fatalf("unable to run training: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func runTrainList() {
|
||||
err := train.ListJob(context.Background())
|
||||
if err != nil {
|
||||
zap.S().Fatalf("unable to list training jobs: %w", err)
|
||||
}
|
||||
}
|
1
dkimpt/testdata/20191012_122633/record_000000007.json
vendored
Normal file
@ -0,0 +1 @@
|
||||
{"road/ellipse": [[79, 83], [126.231689453125, 159.87911987304688], 74.92227172851562, 1.0], "cfg/throttle/min": 0.4, "pilot/angle": -0.2857142857142858, "cfg/throttle/max": 0.6, "recording": [0.0, 0.0, "user", false], "user/angle": -1.0, "cfg/throttle/compute_from_steering": true, "angle": -1.0, "rate_htz": 20, "sleep_time": -0.15691800117492677, "captor/distance": 3164, "cam/image_array": "cam-image_array_7_.jpg", "ctrl/record": true, "throttle": 1.0, "cfg/throttle/angle/dangerous": 0.8, "road/contour": [[0, 41], [0, 99], [156, 96], [133, 84], [140, 72], [159, 73], [156, 58], [141, 60], [146, 42], [157, 47], [152, 41], [43, 41], [53, 53], [33, 64], [22, 51], [28, 41]], "pilot/throttle": 0.4, "img/road_ellipse": "img-road_ellipse_7_.jpg", "user/mode": "user", "cfg/throttle/angle/safe": 0.3, "user/throttle": 1.0}
|
21
go.mod
@ -3,20 +3,35 @@ module github.com/cyrilix/robocar-tools
|
||||
go 1.17
|
||||
|
||||
require (
|
||||
github.com/aws/aws-sdk-go v1.40.35
|
||||
github.com/aws/aws-sdk-go-v2 v1.9.1
|
||||
github.com/aws/aws-sdk-go-v2/config v1.8.2
|
||||
github.com/aws/aws-sdk-go-v2/service/s3 v1.16.0
|
||||
github.com/aws/aws-sdk-go-v2/service/sagemaker v1.15.0
|
||||
github.com/cyrilix/robocar-base v0.1.4
|
||||
github.com/cyrilix/robocar-protobuf/go v1.0.3
|
||||
github.com/eclipse/paho.mqtt.golang v1.3.5
|
||||
github.com/golang/protobuf v1.5.2
|
||||
github.com/sirupsen/logrus v1.8.1
|
||||
go.uber.org/zap v1.19.1
|
||||
gocv.io/x/gocv v0.28.0
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.4.2 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.5.1 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.2.3 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.3.0 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.3.1 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.7.1 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.4.1 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.7.1 // indirect
|
||||
github.com/aws/smithy-go v1.8.0 // indirect
|
||||
github.com/gorilla/websocket v1.4.2 // indirect
|
||||
github.com/jmespath/go-jmespath v0.4.0 // indirect
|
||||
github.com/stretchr/testify v1.6.1 // indirect
|
||||
github.com/stretchr/testify v1.7.0 // indirect
|
||||
go.uber.org/atomic v1.7.0 // indirect
|
||||
go.uber.org/multierr v1.6.0 // indirect
|
||||
golang.org/x/net v0.0.0-20210614182718-04defd469f4e // indirect
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da // indirect
|
||||
golang.org/x/sys v0.0.0-20210510120138-977fb7262007 // indirect
|
||||
google.golang.org/protobuf v1.26.0 // indirect
|
||||
)
|
||||
|
65
go.sum
@ -2,8 +2,33 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT
|
||||
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8=
|
||||
github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA=
|
||||
github.com/Microsoft/hcsshim v0.8.6/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg=
|
||||
github.com/aws/aws-sdk-go v1.40.35 h1:ofWh1LlWaSbOpAsl8EHlg96PZXqgCGKKi8YgrdU2Z+I=
|
||||
github.com/aws/aws-sdk-go v1.40.35/go.mod h1:585smgzpB/KqRA+K3y/NL/oYRqQvpNJYvLm+LY1U59Q=
|
||||
github.com/aws/aws-sdk-go-v2 v1.9.1 h1:ZbovGV/qo40nrOJ4q8G33AGICzaPI45FHQWJ9650pF4=
|
||||
github.com/aws/aws-sdk-go-v2 v1.9.1/go.mod h1:cK/D0BBs0b/oWPIcX/Z/obahJK1TT7IPVjy53i/mX/4=
|
||||
github.com/aws/aws-sdk-go-v2/config v1.8.2 h1:Dqy4ySXFmulRmZhfynm/5CD4Y6aXiTVhDtXLIuUe/r0=
|
||||
github.com/aws/aws-sdk-go-v2/config v1.8.2/go.mod h1:r0bkX9NyuCuf28qVcsEMtpAQibT7gA1Q0gzkjvgJdLU=
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.4.2 h1:8kVE4Og6wlhVrMGiORQ3p9gRj2exjzhFRB+QzWBUa5Q=
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.4.2/go.mod h1:9Sp6u121/f0NnvHyhG7dgoYeUTEFC2vsvJqJ6wXpkaI=
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.5.1 h1:Nm+BxqBtT0r+AnD6byGMCGT4Km0QwHBy8mAYptNPXY4=
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.5.1/go.mod h1:W1ldHfsgeGlKpJ4xZMKZUI6Wmp6EAstU7PxnhbXWWrI=
|
||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.2.3 h1:NnXJXUz7oihrSlPKEM0yZ19b+7GQ47MX/LluLlEyE/Y=
|
||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.2.3/go.mod h1:EES9ToeC3h063zCFDdqWGnARExNdULPaBvARm1FLwxA=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.3.0 h1:gceOysEWNNwLd6cki65IMBZ4WAM0MwgBQq2n7kejoT8=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.3.0/go.mod h1:v8ygadNyATSm6elwJ/4gzJwcFhri9RqS8skgHKiwXPU=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.3.1 h1:APEjhKZLFlNVLATnA/TJyA+w1r/xd5r5ACWBDZ9aIvc=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.3.1/go.mod h1:Ve+eJOx9UWaT/lMVebnFhDhO49fSLVedHoA82+Rqme0=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.7.1 h1:YEz2KMyqK2zyG3uOa0l2xBc/H6NUVJir8FhwHQHF3rc=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.7.1/go.mod h1:yg4EN/BKoc7+DLhNOxxdvoO3+iyW2FuynvaKqLcLDUM=
|
||||
github.com/aws/aws-sdk-go-v2/service/s3 v1.16.0 h1:dt1JQFj/135ozwGIWeCM3aQ8N/kB3Xu3Uu4r9zuOIyc=
|
||||
github.com/aws/aws-sdk-go-v2/service/s3 v1.16.0/go.mod h1:Tk23mCmfL3wb3tNIeMk/0diUZ0W4R6uZtjYKguMLW2s=
|
||||
github.com/aws/aws-sdk-go-v2/service/sagemaker v1.15.0 h1:BMYMo3YNF6bloF2oVqHnuFRzKSXqwpTLia+NzstYyAA=
|
||||
github.com/aws/aws-sdk-go-v2/service/sagemaker v1.15.0/go.mod h1:PtyDNWfMqp/8BKJj1mzVAdSTuNDtj60wboRxykveIQg=
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.4.1 h1:RfgQyv3bFT2Js6XokcrNtTjQ6wAVBRpoCgTFsypihHA=
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.4.1/go.mod h1:ycPdbJZlM0BLhuBnd80WX9PucWPG88qps/2jl9HugXs=
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.7.1 h1:7ce9ugapSgBapwLhg7AJTqKW5U92VRX3vX65k2tsB+g=
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.7.1/go.mod h1:r1i8QwKPzwByXqZb3POQfBs7jozrdnHz8PVbsvyx73w=
|
||||
github.com/aws/smithy-go v1.8.0 h1:AEwwwXQZtUwP5Mz506FeXXrKBe0jA8gVM+1gEcSRooc=
|
||||
github.com/aws/smithy-go v1.8.0/go.mod h1:SObp3lf9smib00L/v3U2eAKG8FyQ7iLrJnQiAmR5n+E=
|
||||
github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
|
||||
github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/containerd/containerd v1.4.1/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
|
||||
@ -39,8 +64,10 @@ github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaS
|
||||
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
|
||||
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
|
||||
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ=
|
||||
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
|
||||
@ -72,6 +99,7 @@ github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zM
|
||||
github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
|
||||
github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
|
||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
@ -86,42 +114,70 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/testcontainers/testcontainers-go v0.9.0/go.mod h1:b22BFXhRbg4PJmeMVWh6ftqjyZHgiIl3w274e9r3C2E=
|
||||
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
|
||||
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
|
||||
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||
go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw=
|
||||
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
||||
go.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
|
||||
go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4=
|
||||
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
|
||||
go.uber.org/zap v1.19.1 h1:ue41HOKd1vGURxrmeKIgELGb3jPW9DMUDGtsinblHwI=
|
||||
go.uber.org/zap v1.19.1/go.mod h1:j3DNczoxDZroyBnOT1L/Q79cfUMGZxlv/9dzN7SM1rI=
|
||||
gocv.io/x/gocv v0.28.0 h1:hweRS9Js60YEZPZzjhU5I+0E2ngazquLlO78zwnrFvY=
|
||||
gocv.io/x/gocv v0.28.0/go.mod h1:oc6FvfYqfBp99p+yOEzs9tbYF9gOrAQSeL/dyIPefJU=
|
||||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200425230154-ff2c4b7c35a0/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
||||
golang.org/x/net v0.0.0-20210614182718-04defd469f4e h1:XpT3nA5TvE525Ne3hInMh6+GETgn27Zfm9dxsThnX2Q=
|
||||
golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da h1:b3NXsE2LusjYGGjL5bxEVZZORm/YEFFrWFjR8eFrw/c=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210510120138-977fb7262007 h1:gG67DSER+11cZvqIMb8S8bt0vZtiN6xWYARwirrOSfE=
|
||||
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/tools v0.0.0-20180810170437-e96c4e24768d/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
|
||||
@ -139,5 +195,6 @@ gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
|
||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gotest.tools v0.0.0-20181223230014-1083505acf35/go.mod h1:R//lfYlUuTOTfblYI3lGoAAAebUdzjvbmQsuB7Ykd90=
|
||||
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
|
20
part/part.go
@ -6,10 +6,11 @@ import (
|
||||
"github.com/cyrilix/robocar-protobuf/go/events"
|
||||
mqtt "github.com/eclipse/paho.mqtt.golang"
|
||||
"github.com/golang/protobuf/proto"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"go.uber.org/zap"
|
||||
"gocv.io/x/gocv"
|
||||
"image"
|
||||
"image/color"
|
||||
"log"
|
||||
)
|
||||
|
||||
func NewPart(client mqtt.Client, frameTopic, objectsTopic, roadTopic string, withObjects, withRoad bool) *FramePart {
|
||||
@ -18,7 +19,7 @@ func NewPart(client mqtt.Client, frameTopic, objectsTopic, roadTopic string, wit
|
||||
frameTopic: frameTopic,
|
||||
objectsTopic: objectsTopic,
|
||||
roadTopic: roadTopic,
|
||||
window: gocv.NewWindow(frameTopic),
|
||||
window: gocv.NewWindow("frameTopic"),
|
||||
withObjects: withObjects,
|
||||
withRoad: withRoad,
|
||||
imgChan: make(chan gocv.Mat),
|
||||
@ -81,16 +82,17 @@ func (p *FramePart) onFrame(_ mqtt.Client, message mqtt.Message) {
|
||||
var msg events.FrameMessage
|
||||
err := proto.Unmarshal(message.Payload(), &msg)
|
||||
if err != nil {
|
||||
log.Errorf("unable to unmarshal protobuf FrameMessage: %v", err)
|
||||
zap.S().Errorf("unable to unmarshal protobuf FrameMessage: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
zap.S().Infow("new frame", zap.String("topic", message.Topic()), zap.String("frameId", msg.GetId().GetId()))
|
||||
|
||||
img, err := gocv.IMDecode(msg.Frame, gocv.IMReadUnchanged)
|
||||
if err != nil {
|
||||
log.Errorf("unable to decode image: %v", err)
|
||||
zap.S().Errorf("unable to decode image: %v", err)
|
||||
return
|
||||
}
|
||||
log.Infof("[%v] frame %v", message.Topic(), msg.GetId())
|
||||
p.imgChan <- img
|
||||
}
|
||||
|
||||
@ -99,7 +101,7 @@ func (p *FramePart) onObjects(_ mqtt.Client, message mqtt.Message) {
|
||||
|
||||
err := proto.Unmarshal(message.Payload(), &msg)
|
||||
if err != nil {
|
||||
log.Errorf("unable to unmarshal msg %T: %v", msg, err)
|
||||
zap.S().Errorf("unable to unmarshal msg %T: %v", msg, err)
|
||||
return
|
||||
}
|
||||
|
||||
@ -111,7 +113,7 @@ func (p *FramePart) onRoad(_ mqtt.Client, message mqtt.Message) {
|
||||
|
||||
err := proto.Unmarshal(message.Payload(), &msg)
|
||||
if err != nil {
|
||||
log.Errorf("unable to unmarshal msg %T: %v", msg, err)
|
||||
zap.S().Errorf("unable to unmarshal msg %T: %v", msg, err)
|
||||
return
|
||||
}
|
||||
|
||||
@ -182,11 +184,11 @@ func (p *FramePart) drawRoad(img *gocv.Mat, road *events.RoadMessage) {
|
||||
}
|
||||
|
||||
func StopService(name string, client mqtt.Client, topics ...string) {
|
||||
log.Printf("Stop %s service", name)
|
||||
zap.S().Infof("Stop %s service", name)
|
||||
token := client.Unsubscribe(topics...)
|
||||
token.Wait()
|
||||
if token.Error() != nil {
|
||||
log.Printf("unable to unsubscribe service: %v", token.Error())
|
||||
zap.S().Errorf("unable to unsubscribe service: %v", token.Error())
|
||||
}
|
||||
client.Disconnect(50)
|
||||
}
|
||||
|
@ -15,10 +15,26 @@ import (
|
||||
|
||||
var camSubDir = "cam"
|
||||
|
||||
func BuildArchive(basedir string, archiveName string, sliceSize int) error {
|
||||
func WriteArchive(basedir string, archiveName string, sliceSize int) error {
|
||||
content, err := BuildArchive(basedir, sliceSize)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to build archive: %w", err)
|
||||
}
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to build archive: %w", err)
|
||||
}
|
||||
err = ioutil.WriteFile(archiveName, content, os.FileMode(0755))
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to write archive content to disk: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func BuildArchive(basedir string, sliceSize int) ([]byte, error) {
|
||||
log.Printf("build zip archive from %s\n", basedir)
|
||||
dirItems, err := ioutil.ReadDir(basedir)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to list directory in %v dir: %v", basedir, err)
|
||||
return nil, fmt.Errorf("unable to list directory in %v dir: %w", basedir, err)
|
||||
}
|
||||
|
||||
imgCams := make([]string, 0)
|
||||
@ -29,34 +45,30 @@ func BuildArchive(basedir string, archiveName string, sliceSize int) error {
|
||||
imgDir := path.Join(basedir, dirItem.Name(), camSubDir)
|
||||
imgs, err := ioutil.ReadDir(imgDir)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to list cam images in directory %v: %v", imgDir, err)
|
||||
return nil, fmt.Errorf("unable to list cam images in directory %v: %w", imgDir, err)
|
||||
}
|
||||
|
||||
for _, img := range imgs {
|
||||
idx, err := indexFromFile(img.Name())
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to find index in cam image name %v: %v", img.Name(), err)
|
||||
return nil, fmt.Errorf("unable to find index in cam image name %v: %w", img.Name(), err)
|
||||
}
|
||||
log.Debugf("found image with index %v", idx)
|
||||
records = append(records, path.Join(basedir, dirItem.Name(), fmt.Sprintf(record.RecorNameFormat, idx)))
|
||||
imgCams = append(imgCams, path.Join(basedir, dirItem.Name(), camSubDir, img.Name()))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if sliceSize > 0{
|
||||
if sliceSize > 0 {
|
||||
imgCams, records, err = applySlice(imgCams, records, sliceSize)
|
||||
}
|
||||
|
||||
content, err := buildArchiveContent(&imgCams, &records)
|
||||
content, err := buildArchiveContent(imgCams, records)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to build archive: %v", err)
|
||||
return nil , fmt.Errorf("unable to generate archive content: %w", err)
|
||||
}
|
||||
err = ioutil.WriteFile(archiveName, *content, os.FileMode(0755))
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to write archive content to disk: %v", err)
|
||||
}
|
||||
return nil
|
||||
log.Printf("archive built\n")
|
||||
return content, nil
|
||||
}
|
||||
|
||||
func applySlice(imgCams []string, records []string, sliceSize int) ([]string, []string, error) {
|
||||
@ -95,7 +107,7 @@ func findNamedMatches(regex *regexp.Regexp, str string) map[string]string {
|
||||
return results
|
||||
}
|
||||
|
||||
func buildArchiveContent(imgFiles *[]string, recordFiles *[]string) (*[]byte, error) {
|
||||
func buildArchiveContent(imgFiles []string, recordFiles []string) ([]byte, error) {
|
||||
// Create a buffer to write our archive to.
|
||||
buf := new(bytes.Buffer)
|
||||
|
||||
@ -104,76 +116,76 @@ func buildArchiveContent(imgFiles *[]string, recordFiles *[]string) (*[]byte, er
|
||||
|
||||
err := addJsonFiles(recordFiles, imgFiles, w)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to write json files in zip archive: %v", err)
|
||||
return nil, fmt.Errorf("unable to write json files in zip archive: %w", err)
|
||||
}
|
||||
|
||||
err = addCamImages(imgFiles, w)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to cam files in zip archive: %v", err)
|
||||
return nil, fmt.Errorf("unable to cam files in zip archive: %w", err)
|
||||
}
|
||||
|
||||
err = w.Close()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to build archive: %v", err)
|
||||
return nil, fmt.Errorf("unable to build archive: %w", err)
|
||||
}
|
||||
|
||||
content, err := ioutil.ReadAll(buf)
|
||||
return &content, err
|
||||
return content, err
|
||||
}
|
||||
|
||||
func addCamImages(imgFiles *[]string, w *zip.Writer) error {
|
||||
for _, img := range *imgFiles {
|
||||
func addCamImages(imgFiles []string, w *zip.Writer) error {
|
||||
for _, img := range imgFiles {
|
||||
imgContent, err := ioutil.ReadFile(img)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to read img: %v", err)
|
||||
return fmt.Errorf("unable to read img: %w", err)
|
||||
}
|
||||
|
||||
_, imgName := path.Split(img)
|
||||
err = addToArchive(w, imgName, &imgContent)
|
||||
err = addToArchive(w, imgName, imgContent)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to create new img entry in archive: %v", err)
|
||||
return fmt.Errorf("unable to create new img entry in archive: %w", err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func addJsonFiles(recordFiles *[]string, imgCam *[]string, w *zip.Writer) error {
|
||||
for idx, r := range *recordFiles {
|
||||
func addJsonFiles(recordFiles []string, imgCam []string, w *zip.Writer) error {
|
||||
for idx, r := range recordFiles {
|
||||
content, err := ioutil.ReadFile(r)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to read json content: %v", err)
|
||||
return fmt.Errorf("unable to read json content: %w", err)
|
||||
}
|
||||
var rcd record.Record
|
||||
err = json.Unmarshal(content, &rcd)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to unmarshal record: %v", err)
|
||||
return fmt.Errorf("unable to unmarshal record: %w", err)
|
||||
}
|
||||
_, camName := path.Split((*imgCam)[idx])
|
||||
_, camName := path.Split((imgCam)[idx])
|
||||
rcd.CamImageArray = camName
|
||||
|
||||
recordBytes, err := json.Marshal(&rcd)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to marshal %v record: %v", rcd, err)
|
||||
return fmt.Errorf("unable to marshal %v record: %w", rcd, err)
|
||||
}
|
||||
|
||||
_, recordName := path.Split(r)
|
||||
err = addToArchive(w, recordName, &recordBytes)
|
||||
err = addToArchive(w, recordName, recordBytes)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to create new record in archive: %v", err)
|
||||
return fmt.Errorf("unable to create new record in archive: %w", err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func addToArchive(w *zip.Writer, name string, content *[]byte) error {
|
||||
func addToArchive(w *zip.Writer, name string, content []byte) error {
|
||||
recordWriter, err := w.Create(name)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to create new entry %v in archive: %v", name, err)
|
||||
return fmt.Errorf("unable to create new entry %v in archive: %w", name, err)
|
||||
}
|
||||
|
||||
_, err = recordWriter.Write(*content)
|
||||
_, err = recordWriter.Write(content)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to add content in %v zip archive: %v", name, err)
|
||||
return fmt.Errorf("unable to add content in %v zip archive: %w", name, err)
|
||||
}
|
||||
return nil
|
||||
}
|
@ -29,7 +29,7 @@ func TestBuildArchive(t *testing.T) {
|
||||
|
||||
expectedRecordFiles, expectedImgFiles := expectedFiles()
|
||||
|
||||
err = BuildArchive("testdata", archive, 0)
|
||||
err = WriteArchive("testdata", archive, 0)
|
||||
if err != nil {
|
||||
t.Errorf("unable to build archive: %v", err)
|
||||
}
|
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 2.5 KiB |
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 2.5 KiB |
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 2.5 KiB |
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 2.5 KiB |
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 2.5 KiB |
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 2.5 KiB |
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 2.5 KiB |
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 2.5 KiB |
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 2.5 KiB |
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 2.5 KiB |
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 2.5 KiB |
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 2.5 KiB |
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 2.5 KiB |
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 2.5 KiB |
47
pkg/train/archives.go
Normal file
@ -0,0 +1,47 @@
|
||||
package train
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/aws/aws-sdk-go-v2/aws"
|
||||
"github.com/aws/aws-sdk-go-v2/service/s3"
|
||||
"github.com/aws/aws-sdk-go-v2/service/s3/types"
|
||||
"log"
|
||||
)
|
||||
|
||||
func ListArchives(ctx context.Context, bucket string) error {
|
||||
client := s3.NewFromConfig(mustLoadConfig())
|
||||
|
||||
prefix := aws.String("input/data/train/train.zip")
|
||||
objects, err := client.ListObjectsV2(ctx, &s3.ListObjectsV2Input{
|
||||
Bucket: aws.String(bucket),
|
||||
Prefix: prefix,
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to list objects in bucket %v: %w", bucket, err)
|
||||
}
|
||||
fmt.Printf("objects: %v\n", objects)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t Training) UploadArchive(ctx context.Context, archive []byte) error {
|
||||
client := s3.NewFromConfig(t.config)
|
||||
key := aws.String("input/data/train/train.zip")
|
||||
|
||||
log.Printf("upload archive to bucket '%s/%s'\n", t.bucketName, *key)
|
||||
_, err := client.PutObject(
|
||||
ctx,
|
||||
&s3.PutObjectInput{
|
||||
ACL: types.ObjectCannedACLPrivate,
|
||||
Body: bytes.NewReader(archive),
|
||||
Bucket: aws.String(t.bucketName),
|
||||
Key: key,
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to upload archive: %w", err)
|
||||
}
|
||||
log.Println("archive uploaded")
|
||||
return nil
|
||||
}
|
@ -1,6 +1,8 @@
|
||||
package training
|
||||
package train
|
||||
|
||||
import "testing"
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestListArchives(t *testing.T) {
|
||||
err := ListArchives()
|
22
pkg/train/config.go
Normal file
@ -0,0 +1,22 @@
|
||||
package train
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/aws/aws-sdk-go-v2/aws"
|
||||
"github.com/aws/aws-sdk-go-v2/config"
|
||||
"log"
|
||||
)
|
||||
|
||||
const (
|
||||
prefixInput = "input/data/train/"
|
||||
)
|
||||
|
||||
func mustLoadConfig() aws.Config {
|
||||
|
||||
c, err := config.LoadDefaultConfig(context.Background())
|
||||
if err != nil {
|
||||
log.Panicf("unable to load aws default config: %v", err)
|
||||
|
||||
}
|
||||
return c
|
||||
}
|
210
pkg/train/train.go
Normal file
@ -0,0 +1,210 @@
|
||||
package train
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/aws/aws-sdk-go-v2/aws"
|
||||
"github.com/aws/aws-sdk-go-v2/service/s3"
|
||||
"github.com/aws/aws-sdk-go-v2/service/sagemaker"
|
||||
"github.com/aws/aws-sdk-go-v2/service/sagemaker/types"
|
||||
"github.com/cyrilix/robocar-tools/pkg/data"
|
||||
"io/fs"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
func New(bucketName string, ociImage, roleArn string) *Training {
|
||||
return &Training{
|
||||
config: mustLoadConfig(),
|
||||
bucketName: bucketName,
|
||||
ociImage: ociImage,
|
||||
roleArn: roleArn,
|
||||
prefixInput: prefixInput,
|
||||
outputBucket: fmt.Sprintf("s3://%s/output", bucketName),
|
||||
}
|
||||
}
|
||||
|
||||
type Training struct {
|
||||
config aws.Config
|
||||
bucketName string
|
||||
ociImage string
|
||||
roleArn string
|
||||
prefixInput string
|
||||
outputBucket string
|
||||
}
|
||||
|
||||
func (t *Training) TrainDir(ctx context.Context, jobName, basedir string, sliceSize int, outputModelFile string) error {
|
||||
log.Printf("run training with data from %s\n", basedir)
|
||||
archive, err := data.BuildArchive(basedir, sliceSize)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to build data archive: %w", err)
|
||||
}
|
||||
log.Println("")
|
||||
|
||||
err = t.UploadArchive(ctx, archive)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to upload data arrchive: %w", err)
|
||||
}
|
||||
log.Println("")
|
||||
|
||||
err = t.runTraining(
|
||||
ctx,
|
||||
jobName,
|
||||
sliceSize,
|
||||
120,
|
||||
160,
|
||||
)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to run training: %w", err)
|
||||
}
|
||||
|
||||
err = t.GetTrainingOutput(ctx, jobName, outputModelFile)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to get output model file '%s': %w", outputModelFile, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func List(bucketName string) error {
|
||||
|
||||
pfxInput := prefixInput
|
||||
|
||||
// Create an Amazon S3 service client
|
||||
client := s3.NewFromConfig(mustLoadConfig())
|
||||
|
||||
// Get the first page of results for ListObjectsV2 for a bucket
|
||||
output, err := client.ListObjectsV2(context.TODO(), &s3.ListObjectsV2Input{
|
||||
Bucket: aws.String(bucketName),
|
||||
Prefix: &pfxInput,
|
||||
})
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
log.Println("first page results:")
|
||||
for _, object := range output.Contents {
|
||||
if *object.Key == pfxInput {
|
||||
continue
|
||||
}
|
||||
log.Printf("key=%s size=%d", aws.ToString(object.Key), object.Size)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *Training) runTraining(ctx context.Context, jobName string, slideSize int, imgHeight, imgWidth int) error {
|
||||
client := sagemaker.NewFromConfig(mustLoadConfig())
|
||||
log.Printf("Start training job '%s'\n", jobName)
|
||||
// TODO: check train data exist
|
||||
jobOutput, err := client.CreateTrainingJob(
|
||||
ctx,
|
||||
&sagemaker.CreateTrainingJobInput{
|
||||
EnableManagedSpotTraining: true,
|
||||
AlgorithmSpecification: &types.AlgorithmSpecification{
|
||||
TrainingInputMode: types.TrainingInputModeFile,
|
||||
TrainingImage: aws.String(t.ociImage),
|
||||
},
|
||||
OutputDataConfig: &types.OutputDataConfig{
|
||||
S3OutputPath: aws.String(t.outputBucket),
|
||||
},
|
||||
ResourceConfig: &types.ResourceConfig{
|
||||
InstanceCount: 1,
|
||||
InstanceType: types.TrainingInstanceTypeMlP2Xlarge,
|
||||
VolumeSizeInGB: 1,
|
||||
},
|
||||
RoleArn: aws.String(t.roleArn),
|
||||
StoppingCondition: &types.StoppingCondition{
|
||||
MaxRuntimeInSeconds: 1800,
|
||||
MaxWaitTimeInSeconds: aws.Int32(3600),
|
||||
},
|
||||
TrainingJobName: aws.String(jobName),
|
||||
HyperParameters: map[string]string{
|
||||
"sagemaker_region": "eu-west-1",
|
||||
"slide_size": strconv.Itoa(slideSize),
|
||||
"img_height": strconv.Itoa(imgHeight),
|
||||
"img_width": strconv.Itoa(imgWidth),
|
||||
},
|
||||
InputDataConfig: []types.Channel{
|
||||
{
|
||||
ChannelName: aws.String("train"),
|
||||
DataSource: &types.DataSource{
|
||||
S3DataSource: &types.S3DataSource{
|
||||
S3DataType: types.S3DataTypeS3Prefix,
|
||||
S3Uri: aws.String(fmt.Sprintf("s3://%s/%s", t.bucketName, t.prefixInput)),
|
||||
S3DataDistributionType: types.S3DataDistributionFullyReplicated,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to run sagemeker job: %w", err)
|
||||
}
|
||||
|
||||
for {
|
||||
time.Sleep(30 * time.Second)
|
||||
|
||||
status, err := client.DescribeTrainingJob(
|
||||
ctx,
|
||||
&sagemaker.DescribeTrainingJobInput{
|
||||
TrainingJobName: aws.String(jobName),
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
log.Printf("unable to get status from ob %v: %v\n", jobOutput.TrainingJobArn, err)
|
||||
continue
|
||||
}
|
||||
switch status.TrainingJobStatus {
|
||||
case types.TrainingJobStatusInProgress:
|
||||
log.Printf("job in progress: %v - %v - %v\n", status.TrainingJobStatus, status.SecondaryStatus, *status.SecondaryStatusTransitions[len(status.SecondaryStatusTransitions) - 1].StatusMessage)
|
||||
continue
|
||||
case types.TrainingJobStatusFailed:
|
||||
return fmt.Errorf("job %s finished with status %v\n", jobName, status.TrainingJobStatus)
|
||||
default:
|
||||
log.Printf("job %s finished with status %v\n", jobName, status.TrainingJobStatus)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (t *Training) GetTrainingOutput(ctx context.Context, jobName, outputFile string) error {
|
||||
// Create an Amazon S3 service client
|
||||
client := s3.NewFromConfig(t.config)
|
||||
|
||||
// Get the first page of results for ListObjectsV2 for a bucket
|
||||
output, err := client.GetObject(
|
||||
ctx,
|
||||
&s3.GetObjectInput{
|
||||
Bucket: aws.String(t.bucketName),
|
||||
Key: aws.String(fmt.Sprintf("output/%s/model.tar.gz", jobName)),
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to get resource: %w", err)
|
||||
}
|
||||
content, err := ioutil.ReadAll(output.Body)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable read output content: %w", err)
|
||||
}
|
||||
err = ioutil.WriteFile(outputFile, content, fs.ModePerm)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to write content to '%v': %w", outputFile, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func ListJob(ctx context.Context) error {
|
||||
|
||||
client := sagemaker.NewFromConfig(mustLoadConfig())
|
||||
jobs, err := client.ListTrainingJobs(ctx, &sagemaker.ListTrainingJobsInput{})
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to list trainings jobs: %w", err)
|
||||
}
|
||||
for _, job := range jobs.TrainingJobSummaries {
|
||||
fmt.Printf("%s\t\t%s\n", *job.TrainingJobName, job.TrainingJobStatus)
|
||||
}
|
||||
return nil
|
||||
}
|
22
pkg/train/train_test.go
Normal file
@ -0,0 +1,22 @@
|
||||
package train
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestList(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "default",
|
||||
wantErr: false,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if err := List(); (err != nil) != tt.wantErr {
|
||||
t.Errorf("List() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
@ -1,57 +0,0 @@
|
||||
package training
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/aws/endpoints"
|
||||
"github.com/aws/aws-sdk-go/aws/session"
|
||||
"github.com/aws/aws-sdk-go/service/s3"
|
||||
)
|
||||
|
||||
var sess = session.Must(session.NewSession(&aws.Config{
|
||||
Region: aws.String(endpoints.EuWest1RegionID),
|
||||
}))
|
||||
|
||||
func ListArchives() error {
|
||||
srv := s3.New(sess)
|
||||
input := s3.ListBucketsInput{}
|
||||
buckets, err := srv.ListBuckets(&input)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to list buckets: %v", err)
|
||||
}
|
||||
|
||||
for _, b := range buckets.Buckets {
|
||||
fmt.Printf("bucket: %v\n", b)
|
||||
}
|
||||
bucketName := aws.String("robocars-cyrilix-learning")
|
||||
prefix := aws.String("input/data/train/train.zip")
|
||||
listObjectInput := s3.ListObjectsV2Input{
|
||||
Bucket: bucketName,
|
||||
Prefix: prefix,
|
||||
}
|
||||
objects, err := srv.ListObjectsV2(&listObjectInput)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to list objects in bucket %v: %v", *bucketName, err)
|
||||
}
|
||||
fmt.Printf("objects: %v\n", objects)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func UploadArchive(archive *[]byte){
|
||||
bucketName := aws.String("robocars-cyrilix-learning")
|
||||
key := aws.String("input/data/train/train.zip")
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
svc := s3.New(sess)
|
||||
output, err := svc.PutObjectWithContext(ctx, s3.PutObjectInput{
|
||||
ACL: aws.String(s3.ObjectCannedACLPrivate),
|
||||
Body: bytes.NewReader(*archive),
|
||||
Bucket: bucketName,
|
||||
Key: key,
|
||||
}
|
||||
svc.PutObject(input)
|
||||
}
|
11
vendor/github.com/aws/aws-sdk-go-v2/.gitignore
generated
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
dist
|
||||
/doc
|
||||
/doc-staging
|
||||
.yardoc
|
||||
Gemfile.lock
|
||||
/internal/awstesting/integration/smoke/**/importmarker__.go
|
||||
/internal/awstesting/integration/smoke/_test/
|
||||
/vendor
|
||||
/private/model/cli/gen-api/gen-api
|
||||
.gradle/
|
||||
build/
|
27
vendor/github.com/aws/aws-sdk-go-v2/.golangci.toml
generated
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
[run]
|
||||
concurrency = 4
|
||||
timeout = "1m"
|
||||
issues-exit-code = 0
|
||||
modules-download-mode = "readonly"
|
||||
allow-parallel-runners = true
|
||||
skip-dirs = ["internal/repotools"]
|
||||
skip-dirs-use-default = true
|
||||
|
||||
[output]
|
||||
format = "github-actions"
|
||||
|
||||
[linters-settings.cyclop]
|
||||
skip-tests = false
|
||||
|
||||
[linters-settings.errcheck]
|
||||
check-blank = true
|
||||
|
||||
[linters]
|
||||
disable-all = true
|
||||
enable = ["errcheck"]
|
||||
fast = false
|
||||
|
||||
[issues]
|
||||
exclude-use-default = false
|
||||
|
||||
# Refer config definitions at https://golangci-lint.run/usage/configuration/#config-file
|
31
vendor/github.com/aws/aws-sdk-go-v2/.travis.yml
generated
vendored
Normal file
@ -0,0 +1,31 @@
|
||||
language: go
|
||||
sudo: true
|
||||
dist: bionic
|
||||
|
||||
branches:
|
||||
only:
|
||||
- main
|
||||
|
||||
os:
|
||||
- linux
|
||||
- osx
|
||||
# Travis doesn't work with windows and Go tip
|
||||
#- windows
|
||||
|
||||
go:
|
||||
- tip
|
||||
|
||||
matrix:
|
||||
allow_failures:
|
||||
- go: tip
|
||||
|
||||
before_install:
|
||||
- if [ "$TRAVIS_OS_NAME" = "windows" ]; then choco install make; fi
|
||||
- (cd /tmp/; go get golang.org/x/lint/golint)
|
||||
|
||||
env:
|
||||
- EACHMODULE_CONCURRENCY=4
|
||||
|
||||
script:
|
||||
- make ci-test-no-generate;
|
||||
|
1937
vendor/github.com/aws/aws-sdk-go-v2/CHANGELOG.md
generated
vendored
Normal file
4
vendor/github.com/aws/aws-sdk-go-v2/CODE_OF_CONDUCT.md
generated
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
## Code of Conduct
|
||||
This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct).
|
||||
For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact
|
||||
opensource-codeofconduct@amazon.com with any additional questions or comments.
|
178
vendor/github.com/aws/aws-sdk-go-v2/CONTRIBUTING.md
generated
vendored
Normal file
@ -0,0 +1,178 @@
|
||||
# Contributing to the AWS SDK for Go
|
||||
|
||||
Thank you for your interest in contributing to the AWS SDK for Go!
|
||||
We work hard to provide a high-quality and useful SDK, and we greatly value
|
||||
feedback and contributions from our community. Whether it's a bug report,
|
||||
new feature, correction, or additional documentation, we welcome your issues
|
||||
and pull requests. Please read through this document before submitting any
|
||||
[issues] or [pull requests][pr] to ensure we have all the necessary information to
|
||||
effectively respond to your bug report or contribution.
|
||||
|
||||
Jump To:
|
||||
|
||||
* [Bug Reports](#bug-reports)
|
||||
* [Feature Requests](#feature-requests)
|
||||
* [Code Contributions](#code-contributions)
|
||||
|
||||
|
||||
## How to contribute
|
||||
|
||||
*Before you send us a pull request, please be sure that:*
|
||||
|
||||
1. You're working from the latest source on the master branch.
|
||||
2. You check existing open, and recently closed, pull requests to be sure
|
||||
that someone else hasn't already addressed the problem.
|
||||
3. You create an issue before working on a contribution that will take a
|
||||
significant amount of your time.
|
||||
|
||||
*Creating a Pull Request*
|
||||
|
||||
1. Fork the repository.
|
||||
2. In your fork, make your change in a branch that's based on this repo's master branch.
|
||||
3. Commit the change to your fork, using a clear and descriptive commit message.
|
||||
4. Create a pull request, answering any questions in the pull request form.
|
||||
|
||||
For contributions that will take a significant amount of time, open a new
|
||||
issue to pitch your idea before you get started. Explain the problem and
|
||||
describe the content you want to see added to the documentation. Let us know
|
||||
if you'll write it yourself or if you'd like us to help. We'll discuss your
|
||||
proposal with you and let you know whether we're likely to accept it.
|
||||
|
||||
## Bug Reports
|
||||
|
||||
You can file bug reports against the SDK on the [GitHub issues][issues] page.
|
||||
|
||||
If you are filing a report for a bug or regression in the SDK, it's extremely
|
||||
helpful to provide as much information as possible when opening the original
|
||||
issue. This helps us reproduce and investigate the possible bug without having
|
||||
to wait for this extra information to be provided. Please read the following
|
||||
guidelines prior to filing a bug report.
|
||||
|
||||
1. Search through existing [issues][] to ensure that your specific issue has
|
||||
not yet been reported. If it is a common issue, it is likely there is
|
||||
already a bug report for your problem.
|
||||
|
||||
2. Ensure that you have tested the latest version of the SDK. Although you
|
||||
may have an issue against an older version of the SDK, we cannot provide
|
||||
bug fixes for old versions. It's also possible that the bug may have been
|
||||
fixed in the latest release.
|
||||
|
||||
3. Provide as much information about your environment, SDK version, and
|
||||
relevant dependencies as possible. For example, let us know what version
|
||||
of Go you are using, which and version of the operating system, and the
|
||||
the environment your code is running in. e.g Container.
|
||||
|
||||
4. Provide a minimal test case that reproduces your issue or any error
|
||||
information you related to your problem. We can provide feedback much
|
||||
more quickly if we know what operations you are calling in the SDK. If
|
||||
you cannot provide a full test case, provide as much code as you can
|
||||
to help us diagnose the problem. Any relevant information should be provided
|
||||
as well, like whether this is a persistent issue, or if it only occurs
|
||||
some of the time.
|
||||
|
||||
## Feature Requests
|
||||
|
||||
Open an [issue][issues] with the following:
|
||||
|
||||
* A short, descriptive title. Ideally, other community members should be able
|
||||
to get a good idea of the feature just from reading the title.
|
||||
* A detailed description of the the proposed feature.
|
||||
* Why it should be added to the SDK.
|
||||
* If possible, example code to illustrate how it should work.
|
||||
* Use Markdown to make the request easier to read;
|
||||
* If you intend to implement this feature, indicate that you'd like to the issue to be assigned to you.
|
||||
|
||||
## Code Contributions
|
||||
|
||||
We are always happy to receive code and documentation contributions to the SDK.
|
||||
Please be aware of the following notes prior to opening a pull request:
|
||||
|
||||
1. The SDK is released under the [Apache license][license]. Any code you submit
|
||||
will be released under that license. For substantial contributions, we may
|
||||
ask you to sign a [Contributor License Agreement (CLA)][cla].
|
||||
|
||||
2. If you would like to implement support for a significant feature that is not
|
||||
yet available in the SDK, please talk to us beforehand to avoid any
|
||||
duplication of effort.
|
||||
|
||||
3. Wherever possible, pull requests should contain tests as appropriate.
|
||||
Bugfixes should contain tests that exercise the corrected behavior (i.e., the
|
||||
test should fail without the bugfix and pass with it), and new features
|
||||
should be accompanied by tests exercising the feature.
|
||||
|
||||
4. Pull requests that contain failing tests will not be merged until the test
|
||||
failures are addressed. Pull requests that cause a significant drop in the
|
||||
SDK's test coverage percentage are unlikely to be merged until tests have
|
||||
been added.
|
||||
|
||||
5. The JSON files under the SDK's `models` folder are sourced from outside the SDK.
|
||||
Such as `models/apis/ec2/2016-11-15/api.json`. We will not accept pull requests
|
||||
directly on these models. If you discover an issue with the models please
|
||||
create a [GitHub issue][issues] describing the issue.
|
||||
|
||||
### Testing
|
||||
|
||||
To run the tests locally, running the `make unit` command will `go get` the
|
||||
SDK's testing dependencies, and run vet, link and unit tests for the SDK.
|
||||
|
||||
```
|
||||
make unit
|
||||
```
|
||||
|
||||
Standard go testing functionality is supported as well. To test SDK code that
|
||||
is tagged with `codegen` you'll need to set the build tag in the go test
|
||||
command. The `make unit` command will do this automatically.
|
||||
|
||||
```
|
||||
go test -tags codegen ./private/...
|
||||
```
|
||||
|
||||
See the `Makefile` for additional testing tags that can be used in testing.
|
||||
|
||||
To test on multiple platform the SDK includes several DockerFiles under the
|
||||
`awstesting/sandbox` folder, and associated make recipes to to execute
|
||||
unit testing within environments configured for specific Go versions.
|
||||
|
||||
```
|
||||
make sandbox-test-go18
|
||||
```
|
||||
|
||||
To run all sandbox environments use the following make recipe
|
||||
|
||||
```
|
||||
# Optionally update the Go tip that will be used during the batch testing
|
||||
make update-aws-golang-tip
|
||||
|
||||
# Run all SDK tests for supported Go versions in sandboxes
|
||||
make sandbox-test
|
||||
```
|
||||
|
||||
In addition the sandbox environment include make recipes for interactive modes
|
||||
so you can run command within the Docker container and context of the SDK.
|
||||
|
||||
```
|
||||
make sandbox-go18
|
||||
```
|
||||
|
||||
### Changelog Documents
|
||||
|
||||
You can see all release changes in the `CHANGELOG.md` file at the root of the
|
||||
repository. The release notes added to this file will contain service client
|
||||
updates, and major SDK changes. When submitting a pull request please include an entry in `CHANGELOG_PENDING.md` under the appropriate changelog type so your changelog entry is included on the following release.
|
||||
|
||||
#### Changelog Types
|
||||
|
||||
* `SDK Features` - For major additive features, internal changes that have
|
||||
outward impact, or updates to the SDK foundations. This will result in a minor
|
||||
version change.
|
||||
* `SDK Enhancements` - For minor additive features or incremental sized changes.
|
||||
This will result in a patch version change.
|
||||
* `SDK Bugs` - For minor changes that resolve an issue. This will result in a
|
||||
patch version change.
|
||||
|
||||
[issues]: https://github.com/aws/aws-sdk-go/issues
|
||||
[pr]: https://github.com/aws/aws-sdk-go/pulls
|
||||
[license]: http://aws.amazon.com/apache2.0/
|
||||
[cla]: http://en.wikipedia.org/wiki/Contributor_License_Agreement
|
||||
[releasenotes]: https://github.com/aws/aws-sdk-go/releases
|
||||
|
15
vendor/github.com/aws/aws-sdk-go-v2/DESIGN.md
generated
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
Open Discussions
|
||||
---
|
||||
The following issues are currently open for community feedback.
|
||||
All discourse must adhere to the [Code of Conduct] policy.
|
||||
|
||||
* [Refactoring API Client Paginators](https://github.com/aws/aws-sdk-go-v2/issues/439)
|
||||
* [Refactoring API Client Waiters](https://github.com/aws/aws-sdk-go-v2/issues/442)
|
||||
* [Refactoring API Client Enums and Types to Discrete Packages](https://github.com/aws/aws-sdk-go-v2/issues/445)
|
||||
* [SDK Modularization](https://github.com/aws/aws-sdk-go-v2/issues/444)
|
||||
|
||||
Past Discussions
|
||||
---
|
||||
The issues listed here are for documentation purposes, and is used to capture issues and their associated discussions.
|
||||
|
||||
[Code of Conduct]: https://github.com/aws/aws-sdk-go-v2/blob/master/CODE_OF_CONDUCT.md
|
465
vendor/github.com/aws/aws-sdk-go-v2/Makefile
generated
vendored
Normal file
@ -0,0 +1,465 @@
|
||||
# Lint rules to ignore
|
||||
LINTIGNORESINGLEFIGHT='internal/sync/singleflight/singleflight.go:.+error should be the last type'
|
||||
|
||||
UNIT_TEST_TAGS=
|
||||
BUILD_TAGS=-tags "example,codegen,integration,ec2env,perftest"
|
||||
|
||||
SMITHY_GO_SRC ?= $(shell pwd)/../smithy-go
|
||||
|
||||
SDK_MIN_GO_VERSION ?= 1.15
|
||||
|
||||
EACHMODULE_FAILFAST ?= true
|
||||
EACHMODULE_FAILFAST_FLAG=-fail-fast=${EACHMODULE_FAILFAST}
|
||||
|
||||
EACHMODULE_CONCURRENCY ?= 1
|
||||
EACHMODULE_CONCURRENCY_FLAG=-c ${EACHMODULE_CONCURRENCY}
|
||||
|
||||
EACHMODULE_SKIP ?=
|
||||
EACHMODULE_SKIP_FLAG=-skip="${EACHMODULE_SKIP}"
|
||||
|
||||
EACHMODULE_FLAGS=${EACHMODULE_CONCURRENCY_FLAG} ${EACHMODULE_FAILFAST_FLAG} ${EACHMODULE_SKIP_FLAG}
|
||||
|
||||
# SDK's Core and client packages that are compatable with Go 1.9+.
|
||||
SDK_CORE_PKGS=./aws/... ./internal/...
|
||||
SDK_CLIENT_PKGS=./service/...
|
||||
SDK_COMPA_PKGS=${SDK_CORE_PKGS} ${SDK_CLIENT_PKGS}
|
||||
|
||||
# SDK additional packages that are used for development of the SDK.
|
||||
SDK_EXAMPLES_PKGS=
|
||||
SDK_ALL_PKGS=${SDK_COMPA_PKGS} ${SDK_EXAMPLES_PKGS}
|
||||
|
||||
RUN_NONE=-run NONE
|
||||
RUN_INTEG=-run '^TestInteg_'
|
||||
|
||||
CODEGEN_RESOURCES_PATH=$(shell pwd)/codegen/smithy-aws-go-codegen/src/main/resources/software/amazon/smithy/aws/go/codegen
|
||||
CODEGEN_API_MODELS_PATH=$(shell pwd)/codegen/sdk-codegen/aws-models
|
||||
ENDPOINTS_JSON=${CODEGEN_RESOURCES_PATH}/endpoints.json
|
||||
ENDPOINT_PREFIX_JSON=${CODEGEN_RESOURCES_PATH}/endpoint-prefix.json
|
||||
|
||||
LICENSE_FILE=$(shell pwd)/LICENSE.txt
|
||||
|
||||
RELEASE_MANIFEST_FILE ?=
|
||||
RELEASE_CHGLOG_DESC_FILE ?=
|
||||
|
||||
.PHONY: all
|
||||
all: generate unit
|
||||
|
||||
###################
|
||||
# Code Generation #
|
||||
###################
|
||||
.PHONY: generate smithy-generate smithy-build smithy-build-% smithy-clean smithy-go-publish-local format \
|
||||
gen-config-asserts gen-repo-mod-replace gen-mod-replace-smithy gen-mod-dropreplace-smithy gen-aws-ptrs tidy-modules-% \
|
||||
add-module-license-files sync-models sync-endpoints-model sync-endpoints.json clone-v1-models gen-endpoint-prefix.json \
|
||||
sync-api-models copy-attributevalue-feature min-go-version-% update-requires smithy-annotate-stable \
|
||||
update-module-metadata download-modules-%
|
||||
|
||||
generate: smithy-generate update-requires gen-repo-mod-replace update-module-metadata smithy-annotate-stable \
|
||||
gen-config-asserts copy-attributevalue-feature gen-mod-dropreplace-smithy min-go-version-. tidy-modules-. \
|
||||
add-module-license-files gen-aws-ptrs format
|
||||
|
||||
smithy-generate:
|
||||
cd codegen && ./gradlew clean build -Plog-tests && ./gradlew clean
|
||||
|
||||
smithy-build: gen-repo-mod-replace
|
||||
cd codegen && ./gradlew clean build -Plog-tests
|
||||
|
||||
smithy-build-%: gen-repo-mod-replace
|
||||
@# smithy-build- command that uses the pattern to define build filter that
|
||||
@# the smithy API model service id starts with. Strips off the
|
||||
@# "smithy-build-".
|
||||
@#
|
||||
@# e.g. smithy-build-com.amazonaws.rds
|
||||
@# e.g. smithy-build-com.amazonaws.rds#AmazonRDSv19
|
||||
cd codegen && \
|
||||
SMITHY_GO_BUILD_API="$(subst smithy-build-,,$@)" ./gradlew clean build -Plog-tests
|
||||
|
||||
smithy-annotate-stable:
|
||||
cd ./internal/repotools && \
|
||||
go run ./cmd/annotatestablegen
|
||||
|
||||
smithy-clean:
|
||||
cd codegen && ./gradlew clean
|
||||
|
||||
smithy-go-publish-local:
|
||||
rm -rf /tmp/smithy-go-local
|
||||
git clone https://github.com/aws/smithy-go /tmp/smithy-go-local
|
||||
make -C /tmp/smithy-go-local smithy-clean smithy-publish-local
|
||||
|
||||
format:
|
||||
gofmt -w -s .
|
||||
|
||||
gen-config-asserts:
|
||||
@echo "Generating SDK config package implementor assertions"
|
||||
cd config \
|
||||
&& go mod tidy \
|
||||
&& go generate
|
||||
|
||||
gen-repo-mod-replace:
|
||||
@echo "Generating go.mod replace for repo modules"
|
||||
cd internal/repotools/cmd/makerelative && go run ./
|
||||
|
||||
gen-mod-replace-smithy:
|
||||
cd ./internal/repotools/cmd/eachmodule \
|
||||
&& go run . "go mod edit -replace github.com/aws/smithy-go=${SMITHY_GO_SRC}"
|
||||
|
||||
gen-mod-dropreplace-smithy:
|
||||
cd ./internal/repotools/cmd/eachmodule \
|
||||
&& go run . "go mod edit -dropreplace github.com/aws/smithy-go"
|
||||
|
||||
gen-aws-ptrs:
|
||||
cd aws && go generate
|
||||
|
||||
tidy-modules-%:
|
||||
@# tidy command that uses the pattern to define the root path that the
|
||||
@# module testing will start from. Strips off the "tidy-modules-" and
|
||||
@# replaces all "_" with "/".
|
||||
@#
|
||||
@# e.g. tidy-modules-internal_protocoltest
|
||||
cd ./internal/repotools/cmd/eachmodule \
|
||||
&& go run . -p $(subst _,/,$(subst tidy-modules-,,$@)) ${EACHMODULE_FLAGS} \
|
||||
"go mod tidy"
|
||||
|
||||
download-modules-%:
|
||||
@# download command that uses the pattern to define the root path that the
|
||||
@# module testing will start from. Strips off the "download-modules-" and
|
||||
@# replaces all "_" with "/".
|
||||
@#
|
||||
@# e.g. download-modules-internal_protocoltest
|
||||
cd ./internal/repotools/cmd/eachmodule \
|
||||
&& go run . -p $(subst _,/,$(subst download-modules-,,$@)) ${EACHMODULE_FLAGS} \
|
||||
"go mod download all"
|
||||
|
||||
add-module-license-files:
|
||||
cd internal/repotools/cmd/eachmodule && \
|
||||
go run . -skip-root \
|
||||
"cp $(LICENSE_FILE) ."
|
||||
|
||||
sync-models: sync-endpoints-model sync-api-models
|
||||
|
||||
sync-endpoints-model: sync-endpoints.json gen-endpoint-prefix.json
|
||||
|
||||
sync-endpoints.json:
|
||||
[[ ! -z "${ENDPOINTS_MODEL}" ]] && cp ${ENDPOINTS_MODEL} ${ENDPOINTS_JSON} || echo "ENDPOINTS_MODEL not set, must not be empty"
|
||||
|
||||
clone-v1-models:
|
||||
rm -rf /tmp/aws-sdk-go-model-sync
|
||||
git clone https://github.com/aws/aws-sdk-go.git --depth 1 /tmp/aws-sdk-go-model-sync
|
||||
|
||||
gen-endpoint-prefix.json: clone-v1-models
|
||||
cd internal/repotools/cmd/endpointPrefix && \
|
||||
go run . \
|
||||
-m '/tmp/aws-sdk-go-model-sync/models/apis/*/*/api-2.json' \
|
||||
-o ${ENDPOINT_PREFIX_JSON}
|
||||
|
||||
sync-api-models:
|
||||
cd internal/repotools/cmd/syncAPIModels && \
|
||||
go run . \
|
||||
-m ${API_MODELS} \
|
||||
-o ${CODEGEN_API_MODELS_PATH}
|
||||
|
||||
copy-attributevalue-feature:
|
||||
cd ./feature/dynamodbstreams/attributevalue && \
|
||||
find . -name "*.go" | grep -v "doc.go" | xargs -I % rm % && \
|
||||
find ../../dynamodb/attributevalue -name "*.go" | grep -v "doc.go" | xargs -I % cp % . && \
|
||||
ls *.go | grep -v "convert.go" | grep -v "doc.go" | \
|
||||
xargs -I % sed -i.bk -E 's:github.com/aws/aws-sdk-go-v2/(service|feature)/dynamodb:github.com/aws/aws-sdk-go-v2/\1/dynamodbstreams:g' % && \
|
||||
ls *.go | grep -v "convert.go" | grep -v "doc.go" | \
|
||||
xargs -I % sed -i.bk 's:DynamoDB:DynamoDBStreams:g' % && \
|
||||
ls *.go | grep -v "doc.go" | \
|
||||
xargs -I % sed -i.bk 's:dynamodb\.:dynamodbstreams.:g' % && \
|
||||
sed -i.bk 's:streams\.:ddbtypes.:g' "convert.go" && \
|
||||
sed -i.bk 's:ddb\.:streams.:g' "convert.go" && \
|
||||
sed -i.bk 's:ddbtypes\.:ddb.:g' "convert.go" &&\
|
||||
sed -i.bk 's:Streams::g' "convert.go" && \
|
||||
rm -rf ./*.bk && \
|
||||
go mod tidy && \
|
||||
gofmt -w -s . && \
|
||||
go test .
|
||||
|
||||
min-go-version-%:
|
||||
cd ./internal/repotools/cmd/eachmodule \
|
||||
&& go run . -p $(subst _,/,$(subst min-go-version-,,$@)) ${EACHMODULE_FLAGS} \
|
||||
"go mod edit -go=${SDK_MIN_GO_VERSION}"
|
||||
|
||||
update-requires:
|
||||
cd ./internal/repotools && \
|
||||
go run ./cmd/updaterequires
|
||||
|
||||
update-module-metadata:
|
||||
cd ./internal/repotools && \
|
||||
go run ./cmd/updatemodulemeta
|
||||
|
||||
################
|
||||
# Unit Testing #
|
||||
################
|
||||
.PHONY: unit unit-race unit-test unit-race-test unit-race-modules-% unit-modules-% build build-modules-% \
|
||||
go-build-modules-% test test-race-modules-% test-modules-% cachedep cachedep-modules-% api-diff-modules-%
|
||||
|
||||
unit: lint unit-modules-.
|
||||
unit-race: lint unit-race-modules-.
|
||||
|
||||
unit-test: test-modules-.
|
||||
unit-race-test: test-race-modules-.
|
||||
|
||||
unit-race-modules-%:
|
||||
@# unit command that uses the pattern to define the root path that the
|
||||
@# module testing will start from. Strips off the "unit-race-modules-" and
|
||||
@# replaces all "_" with "/".
|
||||
@#
|
||||
@# e.g. unit-race-modules-internal_protocoltest
|
||||
cd ./internal/repotools/cmd/eachmodule \
|
||||
&& go run . -p $(subst _,/,$(subst unit-race-modules-,,$@)) ${EACHMODULE_FLAGS} \
|
||||
"go vet ${BUILD_TAGS} --all ./..." \
|
||||
"go test ${BUILD_TAGS} ${RUN_NONE} ./..." \
|
||||
"go test -timeout=1m ${UNIT_TEST_TAGS} -race -cpu=4 ./..."
|
||||
|
||||
|
||||
unit-modules-%:
|
||||
@# unit command that uses the pattern to define the root path that the
|
||||
@# module testing will start from. Strips off the "unit-modules-" and
|
||||
@# replaces all "_" with "/".
|
||||
@#
|
||||
@# e.g. unit-modules-internal_protocoltest
|
||||
cd ./internal/repotools/cmd/eachmodule \
|
||||
&& go run . -p $(subst _,/,$(subst unit-modules-,,$@)) ${EACHMODULE_FLAGS} \
|
||||
"go vet ${BUILD_TAGS} --all ./..." \
|
||||
"go test ${BUILD_TAGS} ${RUN_NONE} ./..." \
|
||||
"go test -timeout=1m ${UNIT_TEST_TAGS} ./..."
|
||||
|
||||
build: build-modules-.
|
||||
|
||||
build-modules-%:
|
||||
@# build command that uses the pattern to define the root path that the
|
||||
@# module testing will start from. Strips off the "build-modules-" and
|
||||
@# replaces all "_" with "/".
|
||||
@#
|
||||
@# e.g. build-modules-internal_protocoltest
|
||||
cd ./internal/repotools/cmd/eachmodule \
|
||||
&& go run . -p $(subst _,/,$(subst build-modules-,,$@)) ${EACHMODULE_FLAGS} \
|
||||
"go test ${BUILD_TAGS} ${RUN_NONE} ./..."
|
||||
|
||||
go-build-modules-%:
|
||||
@# build command that uses the pattern to define the root path that the
|
||||
@# module testing will start from. Strips off the "build-modules-" and
|
||||
@# replaces all "_" with "/".
|
||||
@#
|
||||
@# Validates that all modules in the repo have buildable Go files.
|
||||
@#
|
||||
@# e.g. go-build-modules-internal_protocoltest
|
||||
cd ./internal/repotools/cmd/eachmodule \
|
||||
&& go run . -p $(subst _,/,$(subst go-build-modules-,,$@)) ${EACHMODULE_FLAGS} \
|
||||
"go build ${BUILD_TAGS} ./..."
|
||||
|
||||
test: test-modules-.
|
||||
|
||||
test-race-modules-%:
|
||||
@# Test command that uses the pattern to define the root path that the
|
||||
@# module testing will start from. Strips off the "test-race-modules-" and
|
||||
@# replaces all "_" with "/".
|
||||
@#
|
||||
@# e.g. test-race-modules-internal_protocoltest
|
||||
cd ./internal/repotools/cmd/eachmodule \
|
||||
&& go run . -p $(subst _,/,$(subst test-race-modules-,,$@)) ${EACHMODULE_FLAGS} \
|
||||
"go test -timeout=1m ${UNIT_TEST_TAGS} -race -cpu=4 ./..."
|
||||
|
||||
test-modules-%:
|
||||
@# Test command that uses the pattern to define the root path that the
|
||||
@# module testing will start from. Strips off the "test-modules-" and
|
||||
@# replaces all "_" with "/".
|
||||
@#
|
||||
@# e.g. test-modules-internal_protocoltest
|
||||
cd ./internal/repotools/cmd/eachmodule \
|
||||
&& go run . -p $(subst _,/,$(subst test-modules-,,$@)) ${EACHMODULE_FLAGS} \
|
||||
"go test -timeout=1m ${UNIT_TEST_TAGS} ./..."
|
||||
|
||||
cachedep: cachedep-modules-.
|
||||
|
||||
cachedep-modules-%:
|
||||
@# build command that uses the pattern to define the root path that the
|
||||
@# module caching will start from. Strips off the "cachedep-modules-" and
|
||||
@# replaces all "_" with "/".
|
||||
@#
|
||||
@# e.g. cachedep-modules-internal_protocoltest
|
||||
cd ./internal/repotools/cmd/eachmodule \
|
||||
&& go run . -p $(subst _,/,$(subst cachedep-modules-,,$@)) ${EACHMODULE_FLAGS} \
|
||||
"go mod download"
|
||||
|
||||
api-diff-modules-%:
|
||||
@# Command that uses the pattern to define the root path that the
|
||||
@# module testing will start from. Strips off the "api-diff-modules-" and
|
||||
@# replaces all "_" with "/".
|
||||
@#
|
||||
@# Requires golang.org/x/exp/cmd/gorelease to be available in the GOPATH.
|
||||
@#
|
||||
@# e.g. api-diff-modules-internal_protocoltest
|
||||
cd ./internal/repotools/cmd/eachmodule \
|
||||
&& go run . -p $(subst _,/,$(subst api-diff-modules-,,$@)) \
|
||||
-fail-fast=true \
|
||||
-c 1 \
|
||||
-skip="internal/repotools" \
|
||||
"$$(go env GOPATH)/bin/gorelease"
|
||||
|
||||
##############
|
||||
# CI Testing #
|
||||
##############
|
||||
.PHONY: ci-test ci-test-no-generate ci-test-generate-validate
|
||||
|
||||
ci-test: generate unit-race ci-test-generate-validate
|
||||
ci-test-no-generate: unit-race
|
||||
|
||||
ci-test-generate-validate:
|
||||
@echo "CI test validate no generated code changes"
|
||||
git update-index --assume-unchanged go.mod go.sum
|
||||
git add . -A
|
||||
gitstatus=`git diff --cached --ignore-space-change`; \
|
||||
echo "$$gitstatus"; \
|
||||
if [ "$$gitstatus" != "" ] && [ "$$gitstatus" != "skipping validation" ]; then echo "$$gitstatus"; exit 1; fi
|
||||
git update-index --no-assume-unchanged go.mod go.sum
|
||||
|
||||
ci-lint: ci-lint-.
|
||||
|
||||
ci-lint-%:
|
||||
@# Run golangci-lint command that uses the pattern to define the root path that the
|
||||
@# module check will start from. Strips off the "ci-lint-" and
|
||||
@# replaces all "_" with "/".
|
||||
@#
|
||||
@# e.g. ci-lint-internal_protocoltest
|
||||
cd ./internal/repotools/cmd/eachmodule \
|
||||
&& go run . -p $(subst _,/,$(subst ci-lint-,,$@)) \
|
||||
-fail-fast=false \
|
||||
-c 1 \
|
||||
-skip="internal/repotools" \
|
||||
"golangci-lint run"
|
||||
|
||||
ci-lint-install:
|
||||
@# Installs golangci-lint at GoPATH.
|
||||
@# This should be used to run golangci-lint locally.
|
||||
@#
|
||||
go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest
|
||||
|
||||
#######################
|
||||
# Integration Testing #
|
||||
#######################
|
||||
.PHONY: integration integ-modules-% cleanup-integ-buckets
|
||||
|
||||
integration: integ-modules-service
|
||||
|
||||
integ-modules-%:
|
||||
@# integration command that uses the pattern to define the root path that
|
||||
@# the module testing will start from. Strips off the "integ-modules-" and
|
||||
@# replaces all "_" with "/".
|
||||
@#
|
||||
@# e.g. test-modules-service_dynamodb
|
||||
cd ./internal/repotools/cmd/eachmodule \
|
||||
&& go run . -p $(subst _,/,$(subst integ-modules-,,$@)) ${EACHMODULE_FLAGS} \
|
||||
"go test -timeout=10m -tags "integration" -v ${RUN_INTEG} -count 1 ./..."
|
||||
|
||||
cleanup-integ-buckets:
|
||||
@echo "Cleaning up SDK integration resources"
|
||||
go run -tags "integration" ./internal/awstesting/cmd/bucket_cleanup/main.go "aws-sdk-go-integration"
|
||||
|
||||
##############
|
||||
# Benchmarks #
|
||||
##############
|
||||
.PHONY: bench bench-modules-%
|
||||
|
||||
bench: bench-modules-.
|
||||
|
||||
bench-modules-%:
|
||||
@# benchmark command that uses the pattern to define the root path that
|
||||
@# the module testing will start from. Strips off the "bench-modules-" and
|
||||
@# replaces all "_" with "/".
|
||||
@#
|
||||
@# e.g. bench-modules-service_dynamodb
|
||||
cd ./internal/repotools/cmd/eachmodule \
|
||||
&& go run . -p $(subst _,/,$(subst bench-modules-,,$@)) ${EACHMODULE_FLAGS} \
|
||||
"go test -timeout=10m -bench . --benchmem ${BUILD_TAGS} ${RUN_NONE} ./..."
|
||||
|
||||
|
||||
#####################
|
||||
# Release Process #
|
||||
#####################
|
||||
.PHONY: preview-release pre-release-validation release
|
||||
|
||||
preview-release:
|
||||
@cd ./internal/repotools && \
|
||||
go run ./cmd/calculaterelease
|
||||
|
||||
pre-release-validation:
|
||||
@if [[ -z "${RELEASE_MANIFEST_FILE}" ]]; then \
|
||||
echo "RELEASE_MANIFEST_FILE is required to specify the file to write the release manifest" && false; \
|
||||
fi
|
||||
@if [[ -z "${RELEASE_CHGLOG_DESC_FILE}" ]]; then \
|
||||
echo "RELEASE_CHGLOG_DESC_FILE is required to specify the file to write the release notes" && false; \
|
||||
fi
|
||||
|
||||
release: pre-release-validation
|
||||
cd ./internal/repotools && \
|
||||
go run ./cmd/calculaterelease -o ${RELEASE_MANIFEST_FILE} && \
|
||||
go run ./cmd/updaterequires -release ${RELEASE_MANIFEST_FILE} && \
|
||||
go run ./cmd/updatemodulemeta -release ${RELEASE_MANIFEST_FILE} && \
|
||||
go run ./cmd/generatechangelog -release ${RELEASE_MANIFEST_FILE} -o ${RELEASE_CHGLOG_DESC_FILE} && \
|
||||
go run ./cmd/changelog rm -all && \
|
||||
go run ./cmd/tagrelease -release ${RELEASE_MANIFEST_FILE}
|
||||
|
||||
##############
|
||||
# Repo Tools #
|
||||
##############
|
||||
.PHONY: install-repotools
|
||||
|
||||
install-repotools:
|
||||
cd ./internal/repotools && \
|
||||
go install ./cmd/changelog
|
||||
|
||||
##################
|
||||
# Linting/Verify #
|
||||
##################
|
||||
.PHONY: verify lint vet vet-modules-% sdkv1check
|
||||
|
||||
verify: lint vet sdkv1check
|
||||
|
||||
lint:
|
||||
@echo "go lint SDK and vendor packages"
|
||||
@lint=`golint ./...`; \
|
||||
dolint=`echo "$$lint" | grep -E -v \
|
||||
-e ${LINTIGNORESINGLEFIGHT}`; \
|
||||
echo "$$dolint"; \
|
||||
if [ "$$dolint" != "" ]; then exit 1; fi
|
||||
|
||||
vet: vet-modules-.
|
||||
|
||||
vet-modules-%:
|
||||
cd ./internal/repotools/cmd/eachmodule \
|
||||
&& go run . -p $(subst _,/,$(subst vet-modules-,,$@)) ${EACHMODULE_FLAGS} \
|
||||
"go vet ${BUILD_TAGS} --all ./..."
|
||||
|
||||
sdkv1check:
|
||||
@echo "Checking for usage of AWS SDK for Go v1"
|
||||
@sdkv1usage=`go list -test -f '''{{ if not .Standard }}{{ range $$_, $$name := .Imports }} * {{ $$.ImportPath }} -> {{ $$name }}{{ print "\n" }}{{ end }}{{ range $$_, $$name := .TestImports }} *: {{ $$.ImportPath }} -> {{ $$name }}{{ print "\n" }}{{ end }}{{ end}}''' ./... | sort -u | grep '''/aws-sdk-go/'''`; \
|
||||
echo "$$sdkv1usage"; \
|
||||
if [ "$$sdkv1usage" != "" ]; then exit 1; fi
|
||||
|
||||
###################
|
||||
# Sandbox Testing #
|
||||
###################
|
||||
.PHONY: sandbox-tests sandbox-build-% sandbox-run-% sandbox-test-% update-aws-golang-tip
|
||||
|
||||
sandbox-tests: sandbox-test-go1.15 sandbox-test-go1.16 sandbox-test-go1.17 sandbox-test-gotip
|
||||
|
||||
sandbox-build-%:
|
||||
@# sandbox-build-go1.17
|
||||
@# sandbox-build-gotip
|
||||
docker build \
|
||||
-f ./internal/awstesting/sandbox/Dockerfile.test.$(subst sandbox-build-,,$@) \
|
||||
-t "aws-sdk-go-$(subst sandbox-build-,,$@)" .
|
||||
sandbox-run-%: sandbox-build-%
|
||||
@# sandbox-run-go1.17
|
||||
@# sandbox-run-gotip
|
||||
docker run -i -t "aws-sdk-go-$(subst sandbox-run-,,$@)" bash
|
||||
sandbox-test-%: sandbox-build-%
|
||||
@# sandbox-test-go1.17
|
||||
@# sandbox-test-gotip
|
||||
docker run -t "aws-sdk-go-$(subst sandbox-test-,,$@)"
|
||||
|
||||
update-aws-golang-tip:
|
||||
docker build --no-cache=true -f ./internal/awstesting/sandbox/Dockerfile.golang-tip -t "aws-golang:tip" .
|
@ -1,3 +1,3 @@
|
||||
AWS SDK for Go
|
||||
Copyright 2015 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
Copyright 2015 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
Copyright 2014-2015 Stripe, Inc.
|
155
vendor/github.com/aws/aws-sdk-go-v2/README.md
generated
vendored
Normal file
@ -0,0 +1,155 @@
|
||||
# AWS SDK for Go v2
|
||||
|
||||
[](https://github.com/aws/aws-sdk-go-v2/actions/workflows/go.yml)[](https://github.com/aws/aws-sdk-go-v2/actions/workflows/codegen.yml) [](https://aws.github.io/aws-sdk-go-v2/docs/) [](https://aws.github.io/aws-sdk-go-v2/docs/migrating/) [](https://pkg.go.dev/mod/github.com/aws/aws-sdk-go-v2) [](https://github.com/aws/aws-sdk-go/blob/master/LICENSE.txt)
|
||||
|
||||
|
||||
`aws-sdk-go-v2` is the v2 AWS SDK for the Go programming language.
|
||||
|
||||
The v2 SDK requires a minimum version of `Go 1.15`.
|
||||
|
||||
Checkout out the [release notes](https://github.com/aws/aws-sdk-go-v2/blob/main/CHANGELOG.md) for information about the latest bug
|
||||
fixes, updates, and features added to the SDK.
|
||||
|
||||
Jump To:
|
||||
* [Getting Started](#getting-started)
|
||||
* [Getting Help](#getting-help)
|
||||
* [Contributing](#feedback-and-contributing)
|
||||
* [More Resources](#resources)
|
||||
|
||||
## Maintenance and support for SDK major versions
|
||||
|
||||
For information about maintenance and support for SDK major versions and their underlying dependencies, see the
|
||||
following in the AWS SDKs and Tools Shared Configuration and Credentials Reference Guide:
|
||||
|
||||
* [AWS SDKs and Tools Maintenance Policy](https://docs.aws.amazon.com/credref/latest/refdocs/maint-policy.html)
|
||||
* [AWS SDKs and Tools Version Support Matrix](https://docs.aws.amazon.com/credref/latest/refdocs/version-support-matrix.html)
|
||||
|
||||
## Getting started
|
||||
To get started working with the SDK setup your project for Go modules, and retrieve the SDK dependencies with `go get`.
|
||||
This example shows how you can use the v2 SDK to make an API request using the SDK's [Amazon DynamoDB] client.
|
||||
|
||||
###### Initialize Project
|
||||
```sh
|
||||
$ mkdir ~/helloaws
|
||||
$ cd ~/helloaws
|
||||
$ go mod init helloaws
|
||||
```
|
||||
###### Add SDK Dependencies
|
||||
```sh
|
||||
$ go get github.com/aws/aws-sdk-go-v2/aws
|
||||
$ go get github.com/aws/aws-sdk-go-v2/config
|
||||
$ go get github.com/aws/aws-sdk-go-v2/service/dynamodb
|
||||
```
|
||||
|
||||
###### Write Code
|
||||
In your preferred editor add the following content to `main.go`
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"github.com/aws/aws-sdk-go-v2/aws"
|
||||
"github.com/aws/aws-sdk-go-v2/config"
|
||||
"github.com/aws/aws-sdk-go-v2/service/dynamodb"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// Using the SDK's default configuration, loading additional config
|
||||
// and credentials values from the environment variables, shared
|
||||
// credentials, and shared configuration files
|
||||
cfg, err := config.LoadDefaultConfig(context.TODO(), config.WithRegion("us-west-2"))
|
||||
if err != nil {
|
||||
log.Fatalf("unable to load SDK config, %v", err)
|
||||
}
|
||||
|
||||
// Using the Config value, create the DynamoDB client
|
||||
svc := dynamodb.NewFromConfig(cfg)
|
||||
|
||||
// Build the request with its input parameters
|
||||
resp, err := svc.ListTables(context.TODO(), &dynamodb.ListTablesInput{
|
||||
Limit: aws.Int32(5),
|
||||
})
|
||||
if err != nil {
|
||||
log.Fatalf("failed to list tables, %v", err)
|
||||
}
|
||||
|
||||
fmt.Println("Tables:")
|
||||
for _, tableName := range resp.TableNames {
|
||||
fmt.Println(tableName)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
###### Compile and Execute
|
||||
```sh
|
||||
$ go run .
|
||||
Table:
|
||||
tableOne
|
||||
tableTwo
|
||||
```
|
||||
|
||||
## Getting Help
|
||||
|
||||
Please use these community resources for getting help. We use the GitHub issues
|
||||
for tracking bugs and feature requests.
|
||||
|
||||
* Ask a question on [StackOverflow](http://stackoverflow.com/) and tag it with the [`aws-sdk-go`](http://stackoverflow.com/questions/tagged/aws-sdk-go) tag.
|
||||
* Open a support ticket with [AWS Support](http://docs.aws.amazon.com/awssupport/latest/user/getting-started.html).
|
||||
* If you think you may have found a bug, please open an [issue](https://github.com/aws/aws-sdk-go-v2/issues/new/choose).
|
||||
|
||||
This SDK implements AWS service APIs. For general issues regarding the AWS services and their limitations, you may also take a look at the [Amazon Web Services Discussion Forums](https://forums.aws.amazon.com/).
|
||||
|
||||
### Opening Issues
|
||||
|
||||
If you encounter a bug with the AWS SDK for Go we would like to hear about it.
|
||||
Search the [existing issues][Issues] and see
|
||||
if others are also experiencing the issue before opening a new issue. Please
|
||||
include the version of AWS SDK for Go, Go language, and OS you’re using. Please
|
||||
also include reproduction case when appropriate.
|
||||
|
||||
The GitHub issues are intended for bug reports and feature requests. For help
|
||||
and questions with using AWS SDK for Go please make use of the resources listed
|
||||
in the [Getting Help](#getting-help) section.
|
||||
Keeping the list of open issues lean will help us respond in a timely manner.
|
||||
|
||||
## Feedback and contributing
|
||||
|
||||
The v2 SDK will use GitHub [Issues] to track feature requests and issues with the SDK. In addition, we'll use GitHub [Projects] to track large tasks spanning multiple pull requests, such as refactoring the SDK's internal request lifecycle. You can provide feedback to us in several ways.
|
||||
|
||||
**GitHub issues**. To provide feedback or report bugs, file GitHub [Issues] on the SDK. This is the preferred mechanism to give feedback so that other users can engage in the conversation, +1 issues, etc. Issues you open will be evaluated, and included in our roadmap for the GA launch.
|
||||
|
||||
**Contributing**. You can open pull requests for fixes or additions to the AWS SDK for Go 2.0. All pull requests must be submitted under the Apache 2.0 license and will be reviewed by an SDK team member before being merged in. Accompanying unit tests, where possible, are appreciated.
|
||||
|
||||
## Resources
|
||||
|
||||
[SDK Developer Guide](https://aws.github.io/aws-sdk-go-v2/docs/) - Use this document to learn how to get started and
|
||||
use the AWS SDK for Go V2.
|
||||
|
||||
[SDK API Reference Documentation](https://pkg.go.dev/mod/github.com/aws/aws-sdk-go-v2) - Use this
|
||||
document to look up all API operation input and output parameters for AWS
|
||||
services supported by the SDK. The API reference also includes documentation of
|
||||
the SDK, and examples how to using the SDK, service client API operations, and
|
||||
API operation require parameters.
|
||||
|
||||
[Service Documentation](https://aws.amazon.com/documentation/) - Use this
|
||||
documentation to learn how to interface with AWS services. These guides are
|
||||
great for getting started with a service, or when looking for more
|
||||
information about a service. While this document is not required for coding,
|
||||
services may supply helpful samples to look out for.
|
||||
|
||||
[Forum](https://forums.aws.amazon.com/forum.jspa?forumID=293) - Ask questions, get help, and give feedback
|
||||
|
||||
[Issues] - Report issues, submit pull requests, and get involved
|
||||
(see [Apache 2.0 License][license])
|
||||
|
||||
[Dep]: https://github.com/golang/dep
|
||||
[Issues]: https://github.com/aws/aws-sdk-go-v2/issues
|
||||
[Projects]: https://github.com/aws/aws-sdk-go-v2/projects
|
||||
[CHANGELOG]: https://github.com/aws/aws-sdk-go-v2/blob/master/CHANGELOG.md
|
||||
[Amazon DynamoDB]: https://aws.amazon.com/dynamodb/
|
||||
[design]: https://github.com/aws/aws-sdk-go-v2/blob/master/DESIGN.md
|
||||
[license]: http://aws.amazon.com/apache2.0/
|
@ -75,9 +75,8 @@ func Parse(arn string) (ARN, error) {
|
||||
}, nil
|
||||
}
|
||||
|
||||
// IsARN returns whether the given string is an ARN by looking for
|
||||
// whether the string starts with "arn:" and contains the correct number
|
||||
// of sections delimited by colons(:).
|
||||
// IsARN returns whether the given string is an arn
|
||||
// by looking for whether the string starts with arn:
|
||||
func IsARN(arn string) bool {
|
||||
return strings.HasPrefix(arn, arnPrefix) && strings.Count(arn, ":") >= arnSections-1
|
||||
}
|
119
vendor/github.com/aws/aws-sdk-go-v2/aws/config.go
generated
vendored
Normal file
@ -0,0 +1,119 @@
|
||||
package aws
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/aws/smithy-go/logging"
|
||||
"github.com/aws/smithy-go/middleware"
|
||||
)
|
||||
|
||||
// HTTPClient provides the interface to provide custom HTTPClients. Generally
|
||||
// *http.Client is sufficient for most use cases. The HTTPClient should not
|
||||
// follow redirects.
|
||||
type HTTPClient interface {
|
||||
Do(*http.Request) (*http.Response, error)
|
||||
}
|
||||
|
||||
// A Config provides service configuration for service clients.
|
||||
type Config struct {
|
||||
// The region to send requests to. This parameter is required and must
|
||||
// be configured globally or on a per-client basis unless otherwise
|
||||
// noted. A full list of regions is found in the "Regions and Endpoints"
|
||||
// document.
|
||||
//
|
||||
// See http://docs.aws.amazon.com/general/latest/gr/rande.html for
|
||||
// information on AWS regions.
|
||||
Region string
|
||||
|
||||
// The credentials object to use when signing requests. Defaults to a
|
||||
// chain of credential providers to search for credentials in environment
|
||||
// variables, shared credential file, and EC2 Instance Roles.
|
||||
Credentials CredentialsProvider
|
||||
|
||||
// The HTTP Client the SDK's API clients will use to invoke HTTP requests.
|
||||
// The SDK defaults to a BuildableClient allowing API clients to create
|
||||
// copies of the HTTP Client for service specific customizations.
|
||||
//
|
||||
// Use a (*http.Client) for custom behavior. Using a custom http.Client
|
||||
// will prevent the SDK from modifying the HTTP client.
|
||||
HTTPClient HTTPClient
|
||||
|
||||
// An endpoint resolver that can be used to provide or override an endpoint for the given
|
||||
// service and region Please see the `aws.EndpointResolver` documentation on usage.
|
||||
EndpointResolver EndpointResolver
|
||||
|
||||
// Retryer is a function that provides a Retryer implementation. A Retryer guides how HTTP requests should be
|
||||
// retried in case of recoverable failures. When nil the API client will use a default
|
||||
// retryer.
|
||||
//
|
||||
// In general, the provider function should return a new instance of a Retyer if you are attempting
|
||||
// to provide a consistent Retryer configuration across all clients. This will ensure that each client will be
|
||||
// provided a new instance of the Retryer implementation, and will avoid issues such as sharing the same retry token
|
||||
// bucket across services.
|
||||
Retryer func() Retryer
|
||||
|
||||
// ConfigSources are the sources that were used to construct the Config.
|
||||
// Allows for additional configuration to be loaded by clients.
|
||||
ConfigSources []interface{}
|
||||
|
||||
// APIOptions provides the set of middleware mutations modify how the API
|
||||
// client requests will be handled. This is useful for adding additional
|
||||
// tracing data to a request, or changing behavior of the SDK's client.
|
||||
APIOptions []func(*middleware.Stack) error
|
||||
|
||||
// The logger writer interface to write logging messages to. Defaults to
|
||||
// standard error.
|
||||
Logger logging.Logger
|
||||
|
||||
// Configures the events that will be sent to the configured logger.
|
||||
// This can be used to configure the logging of signing, retries, request, and responses
|
||||
// of the SDK clients.
|
||||
//
|
||||
// See the ClientLogMode type documentation for the complete set of logging modes and available
|
||||
// configuration.
|
||||
ClientLogMode ClientLogMode
|
||||
}
|
||||
|
||||
// NewConfig returns a new Config pointer that can be chained with builder
|
||||
// methods to set multiple configuration values inline without using pointers.
|
||||
func NewConfig() *Config {
|
||||
return &Config{}
|
||||
}
|
||||
|
||||
// Copy will return a shallow copy of the Config object. If any additional
|
||||
// configurations are provided they will be merged into the new config returned.
|
||||
func (c Config) Copy() Config {
|
||||
cp := c
|
||||
return cp
|
||||
}
|
||||
|
||||
// EndpointDiscoveryEnableState indicates if endpoint discovery is
|
||||
// enabled, disabled, auto or unset state.
|
||||
//
|
||||
// Default behavior (Auto or Unset) indicates operations that require endpoint
|
||||
// discovery will use Endpoint Discovery by default. Operations that
|
||||
// optionally use Endpoint Discovery will not use Endpoint Discovery
|
||||
// unless EndpointDiscovery is explicitly enabled.
|
||||
type EndpointDiscoveryEnableState uint
|
||||
|
||||
// Enumeration values for EndpointDiscoveryEnableState
|
||||
const (
|
||||
// EndpointDiscoveryUnset represents EndpointDiscoveryEnableState is unset.
|
||||
// Users do not need to use this value explicitly. The behavior for unset
|
||||
// is the same as for EndpointDiscoveryAuto.
|
||||
EndpointDiscoveryUnset EndpointDiscoveryEnableState = iota
|
||||
|
||||
// EndpointDiscoveryAuto represents an AUTO state that allows endpoint
|
||||
// discovery only when required by the api. This is the default
|
||||
// configuration resolved by the client if endpoint discovery is neither
|
||||
// enabled or disabled.
|
||||
EndpointDiscoveryAuto // default state
|
||||
|
||||
// EndpointDiscoveryDisabled indicates client MUST not perform endpoint
|
||||
// discovery even when required.
|
||||
EndpointDiscoveryDisabled
|
||||
|
||||
// EndpointDiscoveryEnabled indicates client MUST always perform endpoint
|
||||
// discovery if supported for the operation.
|
||||
EndpointDiscoveryEnabled
|
||||
)
|
22
vendor/github.com/aws/aws-sdk-go-v2/aws/context.go
generated
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
package aws
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
)
|
||||
|
||||
type suppressedContext struct {
|
||||
context.Context
|
||||
}
|
||||
|
||||
func (s *suppressedContext) Deadline() (deadline time.Time, ok bool) {
|
||||
return time.Time{}, false
|
||||
}
|
||||
|
||||
func (s *suppressedContext) Done() <-chan struct{} {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *suppressedContext) Err() error {
|
||||
return nil
|
||||
}
|
139
vendor/github.com/aws/aws-sdk-go-v2/aws/credential_cache.go
generated
vendored
Normal file
@ -0,0 +1,139 @@
|
||||
package aws
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
sdkrand "github.com/aws/aws-sdk-go-v2/internal/rand"
|
||||
"github.com/aws/aws-sdk-go-v2/internal/sync/singleflight"
|
||||
)
|
||||
|
||||
// CredentialsCacheOptions are the options
|
||||
type CredentialsCacheOptions struct {
|
||||
|
||||
// ExpiryWindow will allow the credentials to trigger refreshing prior to
|
||||
// the credentials actually expiring. This is beneficial so race conditions
|
||||
// with expiring credentials do not cause request to fail unexpectedly
|
||||
// due to ExpiredTokenException exceptions.
|
||||
//
|
||||
// An ExpiryWindow of 10s would cause calls to IsExpired() to return true
|
||||
// 10 seconds before the credentials are actually expired. This can cause an
|
||||
// increased number of requests to refresh the credentials to occur.
|
||||
//
|
||||
// If ExpiryWindow is 0 or less it will be ignored.
|
||||
ExpiryWindow time.Duration
|
||||
|
||||
// ExpiryWindowJitterFrac provides a mechanism for randomizing the expiration of credentials
|
||||
// within the configured ExpiryWindow by a random percentage. Valid values are between 0.0 and 1.0.
|
||||
//
|
||||
// As an example if ExpiryWindow is 60 seconds and ExpiryWindowJitterFrac is 0.5 then credentials will be set to
|
||||
// expire between 30 to 60 seconds prior to their actual expiration time.
|
||||
//
|
||||
// If ExpiryWindow is 0 or less then ExpiryWindowJitterFrac is ignored.
|
||||
// If ExpiryWindowJitterFrac is 0 then no randomization will be applied to the window.
|
||||
// If ExpiryWindowJitterFrac < 0 the value will be treated as 0.
|
||||
// If ExpiryWindowJitterFrac > 1 the value will be treated as 1.
|
||||
ExpiryWindowJitterFrac float64
|
||||
}
|
||||
|
||||
// CredentialsCache provides caching and concurrency safe credentials retrieval
|
||||
// via the provider's retrieve method.
|
||||
type CredentialsCache struct {
|
||||
// provider is the CredentialProvider implementation to be wrapped by the CredentialCache.
|
||||
provider CredentialsProvider
|
||||
|
||||
options CredentialsCacheOptions
|
||||
creds atomic.Value
|
||||
sf singleflight.Group
|
||||
}
|
||||
|
||||
// NewCredentialsCache returns a CredentialsCache that wraps provider. Provider is expected to not be nil. A variadic
|
||||
// list of one or more functions can be provided to modify the CredentialsCache configuration. This allows for
|
||||
// configuration of credential expiry window and jitter.
|
||||
func NewCredentialsCache(provider CredentialsProvider, optFns ...func(options *CredentialsCacheOptions)) *CredentialsCache {
|
||||
options := CredentialsCacheOptions{}
|
||||
|
||||
for _, fn := range optFns {
|
||||
fn(&options)
|
||||
}
|
||||
|
||||
if options.ExpiryWindow < 0 {
|
||||
options.ExpiryWindow = 0
|
||||
}
|
||||
|
||||
if options.ExpiryWindowJitterFrac < 0 {
|
||||
options.ExpiryWindowJitterFrac = 0
|
||||
} else if options.ExpiryWindowJitterFrac > 1 {
|
||||
options.ExpiryWindowJitterFrac = 1
|
||||
}
|
||||
|
||||
return &CredentialsCache{
|
||||
provider: provider,
|
||||
options: options,
|
||||
}
|
||||
}
|
||||
|
||||
// Retrieve returns the credentials. If the credentials have already been
|
||||
// retrieved, and not expired the cached credentials will be returned. If the
|
||||
// credentials have not been retrieved yet, or expired the provider's Retrieve
|
||||
// method will be called.
|
||||
//
|
||||
// Returns and error if the provider's retrieve method returns an error.
|
||||
func (p *CredentialsCache) Retrieve(ctx context.Context) (Credentials, error) {
|
||||
if creds := p.getCreds(); creds != nil {
|
||||
return *creds, nil
|
||||
}
|
||||
|
||||
resCh := p.sf.DoChan("", func() (interface{}, error) {
|
||||
return p.singleRetrieve(&suppressedContext{ctx})
|
||||
})
|
||||
select {
|
||||
case res := <-resCh:
|
||||
return res.Val.(Credentials), res.Err
|
||||
case <-ctx.Done():
|
||||
return Credentials{}, &RequestCanceledError{Err: ctx.Err()}
|
||||
}
|
||||
}
|
||||
|
||||
func (p *CredentialsCache) singleRetrieve(ctx context.Context) (interface{}, error) {
|
||||
if creds := p.getCreds(); creds != nil {
|
||||
return *creds, nil
|
||||
}
|
||||
|
||||
creds, err := p.provider.Retrieve(ctx)
|
||||
if err == nil {
|
||||
if creds.CanExpire {
|
||||
randFloat64, err := sdkrand.CryptoRandFloat64()
|
||||
if err != nil {
|
||||
return Credentials{}, err
|
||||
}
|
||||
jitter := time.Duration(randFloat64 * p.options.ExpiryWindowJitterFrac * float64(p.options.ExpiryWindow))
|
||||
creds.Expires = creds.Expires.Add(-(p.options.ExpiryWindow - jitter))
|
||||
}
|
||||
|
||||
p.creds.Store(&creds)
|
||||
}
|
||||
|
||||
return creds, err
|
||||
}
|
||||
|
||||
func (p *CredentialsCache) getCreds() *Credentials {
|
||||
v := p.creds.Load()
|
||||
if v == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
c := v.(*Credentials)
|
||||
if c != nil && c.HasKeys() && !c.Expired() {
|
||||
return c
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Invalidate will invalidate the cached credentials. The next call to Retrieve
|
||||
// will cause the provider's Retrieve method to be called.
|
||||
func (p *CredentialsCache) Invalidate() {
|
||||
p.creds.Store((*Credentials)(nil))
|
||||
}
|
127
vendor/github.com/aws/aws-sdk-go-v2/aws/credentials.go
generated
vendored
Normal file
@ -0,0 +1,127 @@
|
||||
package aws
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/aws/aws-sdk-go-v2/internal/sdk"
|
||||
)
|
||||
|
||||
// AnonymousCredentials provides a sentinel CredentialsProvider that should be
|
||||
// used to instruct the SDK's signing middleware to not sign the request.
|
||||
//
|
||||
// Using `nil` credentials when configuring an API client will achieve the same
|
||||
// result. The AnonymousCredentials type allows you to configure the SDK's
|
||||
// external config loading to not attempt to source credentials from the shared
|
||||
// config or environment.
|
||||
//
|
||||
// For example you can use this CredentialsProvider with an API client's
|
||||
// Options to instruct the client not to sign a request for accessing public
|
||||
// S3 bucket objects.
|
||||
//
|
||||
// The following example demonstrates using the AnonymousCredentials to prevent
|
||||
// SDK's external config loading attempt to resolve credentials.
|
||||
//
|
||||
// cfg, err := config.LoadDefaultConfig(context.TODO(),
|
||||
// config.WithCredentialsProvider(aws.AnonymousCredentials{}),
|
||||
// )
|
||||
// if err != nil {
|
||||
// log.Fatalf("failed to load config, %v", err)
|
||||
// }
|
||||
//
|
||||
// client := s3.NewFromConfig(cfg)
|
||||
//
|
||||
// Alternatively you can leave the API client Option's `Credential` member to
|
||||
// nil. If using the `NewFromConfig` constructor you'll need to explicitly set
|
||||
// the `Credentials` member to nil, if the external config resolved a
|
||||
// credential provider.
|
||||
//
|
||||
// client := s3.New(s3.Options{
|
||||
// // Credentials defaults to a nil value.
|
||||
// })
|
||||
//
|
||||
// This can also be configured for specific operations calls too.
|
||||
//
|
||||
// cfg, err := config.LoadDefaultConfig(context.TODO())
|
||||
// if err != nil {
|
||||
// log.Fatalf("failed to load config, %v", err)
|
||||
// }
|
||||
//
|
||||
// client := s3.NewFromConfig(config)
|
||||
//
|
||||
// result, err := client.GetObject(context.TODO(), s3.GetObject{
|
||||
// Bucket: aws.String("example-bucket"),
|
||||
// Key: aws.String("example-key"),
|
||||
// }, func(o *s3.Options) {
|
||||
// o.Credentials = nil
|
||||
// // Or
|
||||
// o.Credentials = aws.AnonymousCredentials{}
|
||||
// })
|
||||
type AnonymousCredentials struct{}
|
||||
|
||||
// Retrieve implements the CredentialsProvider interface, but will always
|
||||
// return error, and cannot be used to sign a request. The AnonymousCredentials
|
||||
// type is used as a sentinel type instructing the AWS request signing
|
||||
// middleware to not sign a request.
|
||||
func (AnonymousCredentials) Retrieve(context.Context) (Credentials, error) {
|
||||
return Credentials{Source: "AnonymousCredentials"},
|
||||
fmt.Errorf("the AnonymousCredentials is not a valid credential provider, and cannot be used to sign AWS requests with")
|
||||
}
|
||||
|
||||
// A Credentials is the AWS credentials value for individual credential fields.
|
||||
type Credentials struct {
|
||||
// AWS Access key ID
|
||||
AccessKeyID string
|
||||
|
||||
// AWS Secret Access Key
|
||||
SecretAccessKey string
|
||||
|
||||
// AWS Session Token
|
||||
SessionToken string
|
||||
|
||||
// Source of the credentials
|
||||
Source string
|
||||
|
||||
// Time the credentials will expire.
|
||||
CanExpire bool
|
||||
Expires time.Time
|
||||
}
|
||||
|
||||
// Expired returns if the credentials have expired.
|
||||
func (v Credentials) Expired() bool {
|
||||
if v.CanExpire {
|
||||
// Calling Round(0) on the current time will truncate the monotonic reading only. Ensures credential expiry
|
||||
// time is always based on reported wall-clock time.
|
||||
return !v.Expires.After(sdk.NowTime().Round(0))
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// HasKeys returns if the credentials keys are set.
|
||||
func (v Credentials) HasKeys() bool {
|
||||
return len(v.AccessKeyID) > 0 && len(v.SecretAccessKey) > 0
|
||||
}
|
||||
|
||||
// A CredentialsProvider is the interface for any component which will provide
|
||||
// credentials Credentials. A CredentialsProvider is required to manage its own
|
||||
// Expired state, and what to be expired means.
|
||||
//
|
||||
// A credentials provider implementation can be wrapped with a CredentialCache
|
||||
// to cache the credential value retrieved. Without the cache the SDK will
|
||||
// attempt to retrieve the credentials for every request.
|
||||
type CredentialsProvider interface {
|
||||
// Retrieve returns nil if it successfully retrieved the value.
|
||||
// Error is returned if the value were not obtainable, or empty.
|
||||
Retrieve(ctx context.Context) (Credentials, error)
|
||||
}
|
||||
|
||||
// CredentialsProviderFunc provides a helper wrapping a function value to
|
||||
// satisfy the CredentialsProvider interface.
|
||||
type CredentialsProviderFunc func(context.Context) (Credentials, error)
|
||||
|
||||
// Retrieve delegates to the function value the CredentialsProviderFunc wraps.
|
||||
func (fn CredentialsProviderFunc) Retrieve(ctx context.Context) (Credentials, error) {
|
||||
return fn(ctx)
|
||||
}
|
@ -26,7 +26,7 @@
|
||||
// strPtr = aws.String("my string")
|
||||
//
|
||||
// // Convert *string to string value
|
||||
// str = aws.StringValue(strPtr)
|
||||
// str = aws.ToString(strPtr)
|
||||
//
|
||||
// In addition to scalars the aws package also includes conversion utilities for
|
||||
// map and slice for commonly types used in API parameters. The map and slice
|
||||
@ -40,7 +40,7 @@
|
||||
// strPtrs = aws.StringSlice(strs)
|
||||
//
|
||||
// // Convert []*string to []string
|
||||
// strs = aws.StringValueSlice(strPtrs)
|
||||
// strs = aws.ToStringSlice(strPtrs)
|
||||
//
|
||||
// SDK Default HTTP Client
|
||||
//
|
||||
@ -54,3 +54,9 @@
|
||||
// configure the SDK to use the custom HTTP Client by setting the HTTPClient
|
||||
// value of the SDK's Config type when creating a Session or service client.
|
||||
package aws
|
||||
|
||||
// generate.go uses a build tag of "ignore", go run doesn't need to specify
|
||||
// this because go run ignores all build flags when running a go file directly.
|
||||
//go:generate go run -tags codegen generate.go
|
||||
//go:generate go run -tags codegen logging_generate.go
|
||||
//go:generate gofmt -w -s .
|
113
vendor/github.com/aws/aws-sdk-go-v2/aws/endpoints.go
generated
vendored
Normal file
@ -0,0 +1,113 @@
|
||||
package aws
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// Endpoint represents the endpoint a service client should make API operation
|
||||
// calls to.
|
||||
//
|
||||
// The SDK will automatically resolve these endpoints per API client using an
|
||||
// internal endpoint resolvers. If you'd like to provide custom endpoint
|
||||
// resolving behavior you can implement the EndpointResolver interface.
|
||||
type Endpoint struct {
|
||||
// The base URL endpoint the SDK API clients will use to make API calls to.
|
||||
// The SDK will suffix URI path and query elements to this endpoint.
|
||||
URL string
|
||||
|
||||
// Specifies if the endpoint's hostname can be modified by the SDK's API
|
||||
// client.
|
||||
//
|
||||
// If the hostname is mutable the SDK API clients may modify any part of
|
||||
// the hostname based on the requirements of the API, (e.g. adding, or
|
||||
// removing content in the hostname). Such as, Amazon S3 API client
|
||||
// prefixing "bucketname" to the hostname, or changing the
|
||||
// hostname service name component from "s3." to "s3-accesspoint.dualstack."
|
||||
// for the dualstack endpoint of an S3 Accesspoint resource.
|
||||
//
|
||||
// Care should be taken when providing a custom endpoint for an API. If the
|
||||
// endpoint hostname is mutable, and the client cannot modify the endpoint
|
||||
// correctly, the operation call will most likely fail, or have undefined
|
||||
// behavior.
|
||||
//
|
||||
// If hostname is immutable, the SDK API clients will not modify the
|
||||
// hostname of the URL. This may cause the API client not to function
|
||||
// correctly if the API requires the operation specific hostname values
|
||||
// to be used by the client.
|
||||
//
|
||||
// This flag does not modify the API client's behavior if this endpoint
|
||||
// will be used instead of Endpoint Discovery, or if the endpoint will be
|
||||
// used to perform Endpoint Discovery. That behavior is configured via the
|
||||
// API Client's Options.
|
||||
HostnameImmutable bool
|
||||
|
||||
// The AWS partition the endpoint belongs to.
|
||||
PartitionID string
|
||||
|
||||
// The service name that should be used for signing the requests to the
|
||||
// endpoint.
|
||||
SigningName string
|
||||
|
||||
// The region that should be used for signing the request to the endpoint.
|
||||
SigningRegion string
|
||||
|
||||
// The signing method that should be used for signing the requests to the
|
||||
// endpoint.
|
||||
SigningMethod string
|
||||
|
||||
// The source of the Endpoint. By default, this will be EndpointSourceServiceMetadata.
|
||||
// When providing a custom endpoint, you should set the source as EndpointSourceCustom.
|
||||
// If source is not provided when providing a custom endpoint, the SDK may not
|
||||
// perform required host mutations correctly. Source should be used along with
|
||||
// HostnameImmutable property as per the usage requirement.
|
||||
Source EndpointSource
|
||||
}
|
||||
|
||||
// EndpointSource is the endpoint source type.
|
||||
type EndpointSource int
|
||||
|
||||
const (
|
||||
// EndpointSourceServiceMetadata denotes service modeled endpoint metadata is used as Endpoint Source.
|
||||
EndpointSourceServiceMetadata EndpointSource = iota
|
||||
|
||||
// EndpointSourceCustom denotes endpoint is a custom endpoint. This source should be used when
|
||||
// user provides a custom endpoint to be used by the SDK.
|
||||
EndpointSourceCustom
|
||||
)
|
||||
|
||||
// EndpointNotFoundError is a sentinel error to indicate that the
|
||||
// EndpointResolver implementation was unable to resolve an endpoint for the
|
||||
// given service and region. Resolvers should use this to indicate that an API
|
||||
// client should fallback and attempt to use it's internal default resolver to
|
||||
// resolve the endpoint.
|
||||
type EndpointNotFoundError struct {
|
||||
Err error
|
||||
}
|
||||
|
||||
// Error is the error message.
|
||||
func (e *EndpointNotFoundError) Error() string {
|
||||
return fmt.Sprintf("endpoint not found, %v", e.Err)
|
||||
}
|
||||
|
||||
// Unwrap returns the underlying error.
|
||||
func (e *EndpointNotFoundError) Unwrap() error {
|
||||
return e.Err
|
||||
}
|
||||
|
||||
// EndpointResolver is an endpoint resolver that can be used to provide or
|
||||
// override an endpoint for the given service and region. API clients will
|
||||
// attempt to use the EndpointResolver first to resolve an endpoint if
|
||||
// available. If the EndpointResolver returns an EndpointNotFoundError error,
|
||||
// API clients will fallback to attempting to resolve the endpoint using its
|
||||
// internal default endpoint resolver.
|
||||
type EndpointResolver interface {
|
||||
ResolveEndpoint(service, region string) (Endpoint, error)
|
||||
}
|
||||
|
||||
// EndpointResolverFunc wraps a function to satisfy the EndpointResolver interface.
|
||||
type EndpointResolverFunc func(service, region string) (Endpoint, error)
|
||||
|
||||
// ResolveEndpoint calls the wrapped function and returns the results.
|
||||
func (e EndpointResolverFunc) ResolveEndpoint(service, region string) (Endpoint, error) {
|
||||
return e(service, region)
|
||||
}
|
9
vendor/github.com/aws/aws-sdk-go-v2/aws/errors.go
generated
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
package aws
|
||||
|
||||
// MissingRegionError is an error that is returned if region configuration
|
||||
// value was not found.
|
||||
type MissingRegionError struct{}
|
||||
|
||||
func (*MissingRegionError) Error() string {
|
||||
return "an AWS region is required, but was not found"
|
||||
}
|
344
vendor/github.com/aws/aws-sdk-go-v2/aws/from_ptr.go
generated
vendored
Normal file
@ -0,0 +1,344 @@
|
||||
// Code generated by aws/generate.go DO NOT EDIT.
|
||||
|
||||
package aws
|
||||
|
||||
import (
|
||||
"github.com/aws/smithy-go/ptr"
|
||||
"time"
|
||||
)
|
||||
|
||||
// ToBool returns bool value dereferenced if the passed
|
||||
// in pointer was not nil. Returns a bool zero value if the
|
||||
// pointer was nil.
|
||||
func ToBool(p *bool) (v bool) {
|
||||
return ptr.ToBool(p)
|
||||
}
|
||||
|
||||
// ToBoolSlice returns a slice of bool values, that are
|
||||
// dereferenced if the passed in pointer was not nil. Returns a bool
|
||||
// zero value if the pointer was nil.
|
||||
func ToBoolSlice(vs []*bool) []bool {
|
||||
return ptr.ToBoolSlice(vs)
|
||||
}
|
||||
|
||||
// ToBoolMap returns a map of bool values, that are
|
||||
// dereferenced if the passed in pointer was not nil. The bool
|
||||
// zero value is used if the pointer was nil.
|
||||
func ToBoolMap(vs map[string]*bool) map[string]bool {
|
||||
return ptr.ToBoolMap(vs)
|
||||
}
|
||||
|
||||
// ToByte returns byte value dereferenced if the passed
|
||||
// in pointer was not nil. Returns a byte zero value if the
|
||||
// pointer was nil.
|
||||
func ToByte(p *byte) (v byte) {
|
||||
return ptr.ToByte(p)
|
||||
}
|
||||
|
||||
// ToByteSlice returns a slice of byte values, that are
|
||||
// dereferenced if the passed in pointer was not nil. Returns a byte
|
||||
// zero value if the pointer was nil.
|
||||
func ToByteSlice(vs []*byte) []byte {
|
||||
return ptr.ToByteSlice(vs)
|
||||
}
|
||||
|
||||
// ToByteMap returns a map of byte values, that are
|
||||
// dereferenced if the passed in pointer was not nil. The byte
|
||||
// zero value is used if the pointer was nil.
|
||||
func ToByteMap(vs map[string]*byte) map[string]byte {
|
||||
return ptr.ToByteMap(vs)
|
||||
}
|
||||
|
||||
// ToString returns string value dereferenced if the passed
|
||||
// in pointer was not nil. Returns a string zero value if the
|
||||
// pointer was nil.
|
||||
func ToString(p *string) (v string) {
|
||||
return ptr.ToString(p)
|
||||
}
|
||||
|
||||
// ToStringSlice returns a slice of string values, that are
|
||||
// dereferenced if the passed in pointer was not nil. Returns a string
|
||||
// zero value if the pointer was nil.
|
||||
func ToStringSlice(vs []*string) []string {
|
||||
return ptr.ToStringSlice(vs)
|
||||
}
|
||||
|
||||
// ToStringMap returns a map of string values, that are
|
||||
// dereferenced if the passed in pointer was not nil. The string
|
||||
// zero value is used if the pointer was nil.
|
||||
func ToStringMap(vs map[string]*string) map[string]string {
|
||||
return ptr.ToStringMap(vs)
|
||||
}
|
||||
|
||||
// ToInt returns int value dereferenced if the passed
|
||||
// in pointer was not nil. Returns a int zero value if the
|
||||
// pointer was nil.
|
||||
func ToInt(p *int) (v int) {
|
||||
return ptr.ToInt(p)
|
||||
}
|
||||
|
||||
// ToIntSlice returns a slice of int values, that are
|
||||
// dereferenced if the passed in pointer was not nil. Returns a int
|
||||
// zero value if the pointer was nil.
|
||||
func ToIntSlice(vs []*int) []int {
|
||||
return ptr.ToIntSlice(vs)
|
||||
}
|
||||
|
||||
// ToIntMap returns a map of int values, that are
|
||||
// dereferenced if the passed in pointer was not nil. The int
|
||||
// zero value is used if the pointer was nil.
|
||||
func ToIntMap(vs map[string]*int) map[string]int {
|
||||
return ptr.ToIntMap(vs)
|
||||
}
|
||||
|
||||
// ToInt8 returns int8 value dereferenced if the passed
|
||||
// in pointer was not nil. Returns a int8 zero value if the
|
||||
// pointer was nil.
|
||||
func ToInt8(p *int8) (v int8) {
|
||||
return ptr.ToInt8(p)
|
||||
}
|
||||
|
||||
// ToInt8Slice returns a slice of int8 values, that are
|
||||
// dereferenced if the passed in pointer was not nil. Returns a int8
|
||||
// zero value if the pointer was nil.
|
||||
func ToInt8Slice(vs []*int8) []int8 {
|
||||
return ptr.ToInt8Slice(vs)
|
||||
}
|
||||
|
||||
// ToInt8Map returns a map of int8 values, that are
|
||||
// dereferenced if the passed in pointer was not nil. The int8
|
||||
// zero value is used if the pointer was nil.
|
||||
func ToInt8Map(vs map[string]*int8) map[string]int8 {
|
||||
return ptr.ToInt8Map(vs)
|
||||
}
|
||||
|
||||
// ToInt16 returns int16 value dereferenced if the passed
|
||||
// in pointer was not nil. Returns a int16 zero value if the
|
||||
// pointer was nil.
|
||||
func ToInt16(p *int16) (v int16) {
|
||||
return ptr.ToInt16(p)
|
||||
}
|
||||
|
||||
// ToInt16Slice returns a slice of int16 values, that are
|
||||
// dereferenced if the passed in pointer was not nil. Returns a int16
|
||||
// zero value if the pointer was nil.
|
||||
func ToInt16Slice(vs []*int16) []int16 {
|
||||
return ptr.ToInt16Slice(vs)
|
||||
}
|
||||
|
||||
// ToInt16Map returns a map of int16 values, that are
|
||||
// dereferenced if the passed in pointer was not nil. The int16
|
||||
// zero value is used if the pointer was nil.
|
||||
func ToInt16Map(vs map[string]*int16) map[string]int16 {
|
||||
return ptr.ToInt16Map(vs)
|
||||
}
|
||||
|
||||
// ToInt32 returns int32 value dereferenced if the passed
|
||||
// in pointer was not nil. Returns a int32 zero value if the
|
||||
// pointer was nil.
|
||||
func ToInt32(p *int32) (v int32) {
|
||||
return ptr.ToInt32(p)
|
||||
}
|
||||
|
||||
// ToInt32Slice returns a slice of int32 values, that are
|
||||
// dereferenced if the passed in pointer was not nil. Returns a int32
|
||||
// zero value if the pointer was nil.
|
||||
func ToInt32Slice(vs []*int32) []int32 {
|
||||
return ptr.ToInt32Slice(vs)
|
||||
}
|
||||
|
||||
// ToInt32Map returns a map of int32 values, that are
|
||||
// dereferenced if the passed in pointer was not nil. The int32
|
||||
// zero value is used if the pointer was nil.
|
||||
func ToInt32Map(vs map[string]*int32) map[string]int32 {
|
||||
return ptr.ToInt32Map(vs)
|
||||
}
|
||||
|
||||
// ToInt64 returns int64 value dereferenced if the passed
|
||||
// in pointer was not nil. Returns a int64 zero value if the
|
||||
// pointer was nil.
|
||||
func ToInt64(p *int64) (v int64) {
|
||||
return ptr.ToInt64(p)
|
||||
}
|
||||
|
||||
// ToInt64Slice returns a slice of int64 values, that are
|
||||
// dereferenced if the passed in pointer was not nil. Returns a int64
|
||||
// zero value if the pointer was nil.
|
||||
func ToInt64Slice(vs []*int64) []int64 {
|
||||
return ptr.ToInt64Slice(vs)
|
||||
}
|
||||
|
||||
// ToInt64Map returns a map of int64 values, that are
|
||||
// dereferenced if the passed in pointer was not nil. The int64
|
||||
// zero value is used if the pointer was nil.
|
||||
func ToInt64Map(vs map[string]*int64) map[string]int64 {
|
||||
return ptr.ToInt64Map(vs)
|
||||
}
|
||||
|
||||
// ToUint returns uint value dereferenced if the passed
|
||||
// in pointer was not nil. Returns a uint zero value if the
|
||||
// pointer was nil.
|
||||
func ToUint(p *uint) (v uint) {
|
||||
return ptr.ToUint(p)
|
||||
}
|
||||
|
||||
// ToUintSlice returns a slice of uint values, that are
|
||||
// dereferenced if the passed in pointer was not nil. Returns a uint
|
||||
// zero value if the pointer was nil.
|
||||
func ToUintSlice(vs []*uint) []uint {
|
||||
return ptr.ToUintSlice(vs)
|
||||
}
|
||||
|
||||
// ToUintMap returns a map of uint values, that are
|
||||
// dereferenced if the passed in pointer was not nil. The uint
|
||||
// zero value is used if the pointer was nil.
|
||||
func ToUintMap(vs map[string]*uint) map[string]uint {
|
||||
return ptr.ToUintMap(vs)
|
||||
}
|
||||
|
||||
// ToUint8 returns uint8 value dereferenced if the passed
|
||||
// in pointer was not nil. Returns a uint8 zero value if the
|
||||
// pointer was nil.
|
||||
func ToUint8(p *uint8) (v uint8) {
|
||||
return ptr.ToUint8(p)
|
||||
}
|
||||
|
||||
// ToUint8Slice returns a slice of uint8 values, that are
|
||||
// dereferenced if the passed in pointer was not nil. Returns a uint8
|
||||
// zero value if the pointer was nil.
|
||||
func ToUint8Slice(vs []*uint8) []uint8 {
|
||||
return ptr.ToUint8Slice(vs)
|
||||
}
|
||||
|
||||
// ToUint8Map returns a map of uint8 values, that are
|
||||
// dereferenced if the passed in pointer was not nil. The uint8
|
||||
// zero value is used if the pointer was nil.
|
||||
func ToUint8Map(vs map[string]*uint8) map[string]uint8 {
|
||||
return ptr.ToUint8Map(vs)
|
||||
}
|
||||
|
||||
// ToUint16 returns uint16 value dereferenced if the passed
|
||||
// in pointer was not nil. Returns a uint16 zero value if the
|
||||
// pointer was nil.
|
||||
func ToUint16(p *uint16) (v uint16) {
|
||||
return ptr.ToUint16(p)
|
||||
}
|
||||
|
||||
// ToUint16Slice returns a slice of uint16 values, that are
|
||||
// dereferenced if the passed in pointer was not nil. Returns a uint16
|
||||
// zero value if the pointer was nil.
|
||||
func ToUint16Slice(vs []*uint16) []uint16 {
|
||||
return ptr.ToUint16Slice(vs)
|
||||
}
|
||||
|
||||
// ToUint16Map returns a map of uint16 values, that are
|
||||
// dereferenced if the passed in pointer was not nil. The uint16
|
||||
// zero value is used if the pointer was nil.
|
||||
func ToUint16Map(vs map[string]*uint16) map[string]uint16 {
|
||||
return ptr.ToUint16Map(vs)
|
||||
}
|
||||
|
||||
// ToUint32 returns uint32 value dereferenced if the passed
|
||||
// in pointer was not nil. Returns a uint32 zero value if the
|
||||
// pointer was nil.
|
||||
func ToUint32(p *uint32) (v uint32) {
|
||||
return ptr.ToUint32(p)
|
||||
}
|
||||
|
||||
// ToUint32Slice returns a slice of uint32 values, that are
|
||||
// dereferenced if the passed in pointer was not nil. Returns a uint32
|
||||
// zero value if the pointer was nil.
|
||||
func ToUint32Slice(vs []*uint32) []uint32 {
|
||||
return ptr.ToUint32Slice(vs)
|
||||
}
|
||||
|
||||
// ToUint32Map returns a map of uint32 values, that are
|
||||
// dereferenced if the passed in pointer was not nil. The uint32
|
||||
// zero value is used if the pointer was nil.
|
||||
func ToUint32Map(vs map[string]*uint32) map[string]uint32 {
|
||||
return ptr.ToUint32Map(vs)
|
||||
}
|
||||
|
||||
// ToUint64 returns uint64 value dereferenced if the passed
|
||||
// in pointer was not nil. Returns a uint64 zero value if the
|
||||
// pointer was nil.
|
||||
func ToUint64(p *uint64) (v uint64) {
|
||||
return ptr.ToUint64(p)
|
||||
}
|
||||
|
||||
// ToUint64Slice returns a slice of uint64 values, that are
|
||||
// dereferenced if the passed in pointer was not nil. Returns a uint64
|
||||
// zero value if the pointer was nil.
|
||||
func ToUint64Slice(vs []*uint64) []uint64 {
|
||||
return ptr.ToUint64Slice(vs)
|
||||
}
|
||||
|
||||
// ToUint64Map returns a map of uint64 values, that are
|
||||
// dereferenced if the passed in pointer was not nil. The uint64
|
||||
// zero value is used if the pointer was nil.
|
||||
func ToUint64Map(vs map[string]*uint64) map[string]uint64 {
|
||||
return ptr.ToUint64Map(vs)
|
||||
}
|
||||
|
||||
// ToFloat32 returns float32 value dereferenced if the passed
|
||||
// in pointer was not nil. Returns a float32 zero value if the
|
||||
// pointer was nil.
|
||||
func ToFloat32(p *float32) (v float32) {
|
||||
return ptr.ToFloat32(p)
|
||||
}
|
||||
|
||||
// ToFloat32Slice returns a slice of float32 values, that are
|
||||
// dereferenced if the passed in pointer was not nil. Returns a float32
|
||||
// zero value if the pointer was nil.
|
||||
func ToFloat32Slice(vs []*float32) []float32 {
|
||||
return ptr.ToFloat32Slice(vs)
|
||||
}
|
||||
|
||||
// ToFloat32Map returns a map of float32 values, that are
|
||||
// dereferenced if the passed in pointer was not nil. The float32
|
||||
// zero value is used if the pointer was nil.
|
||||
func ToFloat32Map(vs map[string]*float32) map[string]float32 {
|
||||
return ptr.ToFloat32Map(vs)
|
||||
}
|
||||
|
||||
// ToFloat64 returns float64 value dereferenced if the passed
|
||||
// in pointer was not nil. Returns a float64 zero value if the
|
||||
// pointer was nil.
|
||||
func ToFloat64(p *float64) (v float64) {
|
||||
return ptr.ToFloat64(p)
|
||||
}
|
||||
|
||||
// ToFloat64Slice returns a slice of float64 values, that are
|
||||
// dereferenced if the passed in pointer was not nil. Returns a float64
|
||||
// zero value if the pointer was nil.
|
||||
func ToFloat64Slice(vs []*float64) []float64 {
|
||||
return ptr.ToFloat64Slice(vs)
|
||||
}
|
||||
|
||||
// ToFloat64Map returns a map of float64 values, that are
|
||||
// dereferenced if the passed in pointer was not nil. The float64
|
||||
// zero value is used if the pointer was nil.
|
||||
func ToFloat64Map(vs map[string]*float64) map[string]float64 {
|
||||
return ptr.ToFloat64Map(vs)
|
||||
}
|
||||
|
||||
// ToTime returns time.Time value dereferenced if the passed
|
||||
// in pointer was not nil. Returns a time.Time zero value if the
|
||||
// pointer was nil.
|
||||
func ToTime(p *time.Time) (v time.Time) {
|
||||
return ptr.ToTime(p)
|
||||
}
|
||||
|
||||
// ToTimeSlice returns a slice of time.Time values, that are
|
||||
// dereferenced if the passed in pointer was not nil. Returns a time.Time
|
||||
// zero value if the pointer was nil.
|
||||
func ToTimeSlice(vs []*time.Time) []time.Time {
|
||||
return ptr.ToTimeSlice(vs)
|
||||
}
|
||||
|
||||
// ToTimeMap returns a map of time.Time values, that are
|
||||
// dereferenced if the passed in pointer was not nil. The time.Time
|
||||
// zero value is used if the pointer was nil.
|
||||
func ToTimeMap(vs map[string]*time.Time) map[string]time.Time {
|
||||
return ptr.ToTimeMap(vs)
|
||||
}
|
6
vendor/github.com/aws/aws-sdk-go-v2/aws/go_module_metadata.go
generated
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
// Code generated by internal/repotools/cmd/updatemodulemeta DO NOT EDIT.
|
||||
|
||||
package aws
|
||||
|
||||
// goModuleVersion is the tagged release for this module
|
||||
const goModuleVersion = "1.9.1"
|
84
vendor/github.com/aws/aws-sdk-go-v2/aws/logging.go
generated
vendored
Normal file
@ -0,0 +1,84 @@
|
||||
// Code generated by aws/logging_generate.go DO NOT EDIT.
|
||||
|
||||
package aws
|
||||
|
||||
// ClientLogMode represents the logging mode of SDK clients. The client logging mode is a bit-field where
|
||||
// each bit is a flag that describes the logging behavior for one or more client components.
|
||||
// The entire 64-bit group is reserved for later expansion by the SDK.
|
||||
//
|
||||
// Example: Setting ClientLogMode to enable logging of retries and requests
|
||||
// clientLogMode := aws.LogRetries | aws.LogRequest
|
||||
//
|
||||
// Example: Adding an additional log mode to an existing ClientLogMode value
|
||||
// clientLogMode |= aws.LogResponse
|
||||
type ClientLogMode uint64
|
||||
|
||||
// Supported ClientLogMode bits that can be configured to toggle logging of specific SDK events.
|
||||
const (
|
||||
LogSigning ClientLogMode = 1 << (64 - 1 - iota)
|
||||
LogRetries
|
||||
LogRequest
|
||||
LogRequestWithBody
|
||||
LogResponse
|
||||
LogResponseWithBody
|
||||
)
|
||||
|
||||
// IsSigning returns whether the Signing logging mode bit is set
|
||||
func (m ClientLogMode) IsSigning() bool {
|
||||
return m&LogSigning != 0
|
||||
}
|
||||
|
||||
// IsRetries returns whether the Retries logging mode bit is set
|
||||
func (m ClientLogMode) IsRetries() bool {
|
||||
return m&LogRetries != 0
|
||||
}
|
||||
|
||||
// IsRequest returns whether the Request logging mode bit is set
|
||||
func (m ClientLogMode) IsRequest() bool {
|
||||
return m&LogRequest != 0
|
||||
}
|
||||
|
||||
// IsRequestWithBody returns whether the RequestWithBody logging mode bit is set
|
||||
func (m ClientLogMode) IsRequestWithBody() bool {
|
||||
return m&LogRequestWithBody != 0
|
||||
}
|
||||
|
||||
// IsResponse returns whether the Response logging mode bit is set
|
||||
func (m ClientLogMode) IsResponse() bool {
|
||||
return m&LogResponse != 0
|
||||
}
|
||||
|
||||
// IsResponseWithBody returns whether the ResponseWithBody logging mode bit is set
|
||||
func (m ClientLogMode) IsResponseWithBody() bool {
|
||||
return m&LogResponseWithBody != 0
|
||||
}
|
||||
|
||||
// ClearSigning clears the Signing logging mode bit
|
||||
func (m *ClientLogMode) ClearSigning() {
|
||||
*m &^= LogSigning
|
||||
}
|
||||
|
||||
// ClearRetries clears the Retries logging mode bit
|
||||
func (m *ClientLogMode) ClearRetries() {
|
||||
*m &^= LogRetries
|
||||
}
|
||||
|
||||
// ClearRequest clears the Request logging mode bit
|
||||
func (m *ClientLogMode) ClearRequest() {
|
||||
*m &^= LogRequest
|
||||
}
|
||||
|
||||
// ClearRequestWithBody clears the RequestWithBody logging mode bit
|
||||
func (m *ClientLogMode) ClearRequestWithBody() {
|
||||
*m &^= LogRequestWithBody
|
||||
}
|
||||
|
||||
// ClearResponse clears the Response logging mode bit
|
||||
func (m *ClientLogMode) ClearResponse() {
|
||||
*m &^= LogResponse
|
||||
}
|
||||
|
||||
// ClearResponseWithBody clears the ResponseWithBody logging mode bit
|
||||
func (m *ClientLogMode) ClearResponseWithBody() {
|
||||
*m &^= LogResponseWithBody
|
||||
}
|
78
vendor/github.com/aws/aws-sdk-go-v2/aws/logging_generate.go
generated
vendored
Normal file
@ -0,0 +1,78 @@
|
||||
//go:build clientlogmode
|
||||
// +build clientlogmode
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
"os"
|
||||
"text/template"
|
||||
)
|
||||
|
||||
var config = struct {
|
||||
ModeBits []string
|
||||
}{
|
||||
// Items should be appended only to keep bit-flag positions stable
|
||||
ModeBits: []string{
|
||||
"Signing",
|
||||
"Retries",
|
||||
"Request",
|
||||
"RequestWithBody",
|
||||
"Response",
|
||||
"ResponseWithBody",
|
||||
},
|
||||
}
|
||||
|
||||
var tmpl = template.Must(template.New("ClientLogMode").Funcs(map[string]interface{}{
|
||||
"symbolName": func(name string) string {
|
||||
return "Log" + name
|
||||
},
|
||||
}).Parse(`// Code generated by aws/logging_generate.go DO NOT EDIT.
|
||||
|
||||
package aws
|
||||
|
||||
// ClientLogMode represents the logging mode of SDK clients. The client logging mode is a bit-field where
|
||||
// each bit is a flag that describes the logging behavior for one or more client components.
|
||||
// The entire 64-bit group is reserved for later expansion by the SDK.
|
||||
//
|
||||
// Example: Setting ClientLogMode to enable logging of retries and requests
|
||||
// clientLogMode := aws.LogRetries | aws.LogRequest
|
||||
//
|
||||
// Example: Adding an additional log mode to an existing ClientLogMode value
|
||||
// clientLogMode |= aws.LogResponse
|
||||
type ClientLogMode uint64
|
||||
|
||||
// Supported ClientLogMode bits that can be configured to toggle logging of specific SDK events.
|
||||
const (
|
||||
{{- range $index, $field := .ModeBits }}
|
||||
{{ (symbolName $field) }}{{- if (eq 0 $index) }} ClientLogMode = 1 << (64 - 1 - iota){{- end }}
|
||||
{{- end }}
|
||||
)
|
||||
|
||||
{{ range $_, $field := .ModeBits }}
|
||||
// Is{{- $field }} returns whether the {{ $field }} logging mode bit is set
|
||||
func (m ClientLogMode) Is{{- $field }}() bool {
|
||||
return m&{{- (symbolName $field) }} != 0
|
||||
}
|
||||
{{ end }}
|
||||
|
||||
{{ range $_, $field := .ModeBits }}
|
||||
// Clear{{- $field }} clears the {{ $field }} logging mode bit
|
||||
func (m *ClientLogMode) Clear{{- $field }}() {
|
||||
*m &^= {{- (symbolName $field) }}
|
||||
}
|
||||
{{ end }}
|
||||
`))
|
||||
|
||||
func main() {
|
||||
file, err := os.Create("logging.go")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
err = tmpl.Execute(file, config)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
167
vendor/github.com/aws/aws-sdk-go-v2/aws/middleware/metadata.go
generated
vendored
Normal file
@ -0,0 +1,167 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/aws/aws-sdk-go-v2/aws"
|
||||
|
||||
"github.com/aws/smithy-go/middleware"
|
||||
)
|
||||
|
||||
// RegisterServiceMetadata registers metadata about the service and operation into the middleware context
|
||||
// so that it is available at runtime for other middleware to introspect.
|
||||
type RegisterServiceMetadata struct {
|
||||
ServiceID string
|
||||
SigningName string
|
||||
Region string
|
||||
OperationName string
|
||||
}
|
||||
|
||||
// ID returns the middleware identifier.
|
||||
func (s *RegisterServiceMetadata) ID() string {
|
||||
return "RegisterServiceMetadata"
|
||||
}
|
||||
|
||||
// HandleInitialize registers service metadata information into the middleware context, allowing for introspection.
|
||||
func (s RegisterServiceMetadata) HandleInitialize(
|
||||
ctx context.Context, in middleware.InitializeInput, next middleware.InitializeHandler,
|
||||
) (out middleware.InitializeOutput, metadata middleware.Metadata, err error) {
|
||||
if len(s.ServiceID) > 0 {
|
||||
ctx = SetServiceID(ctx, s.ServiceID)
|
||||
}
|
||||
if len(s.SigningName) > 0 {
|
||||
ctx = SetSigningName(ctx, s.SigningName)
|
||||
}
|
||||
if len(s.Region) > 0 {
|
||||
ctx = setRegion(ctx, s.Region)
|
||||
}
|
||||
if len(s.OperationName) > 0 {
|
||||
ctx = setOperationName(ctx, s.OperationName)
|
||||
}
|
||||
return next.HandleInitialize(ctx, in)
|
||||
}
|
||||
|
||||
// service metadata keys for storing and lookup of runtime stack information.
|
||||
type (
|
||||
serviceIDKey struct{}
|
||||
signingNameKey struct{}
|
||||
signingRegionKey struct{}
|
||||
regionKey struct{}
|
||||
operationNameKey struct{}
|
||||
partitionIDKey struct{}
|
||||
)
|
||||
|
||||
// GetServiceID retrieves the service id from the context.
|
||||
//
|
||||
// Scoped to stack values. Use github.com/aws/smithy-go/middleware#ClearStackValues
|
||||
// to clear all stack values.
|
||||
func GetServiceID(ctx context.Context) (v string) {
|
||||
v, _ = middleware.GetStackValue(ctx, serviceIDKey{}).(string)
|
||||
return v
|
||||
}
|
||||
|
||||
// GetSigningName retrieves the service signing name from the context.
|
||||
//
|
||||
// Scoped to stack values. Use github.com/aws/smithy-go/middleware#ClearStackValues
|
||||
// to clear all stack values.
|
||||
func GetSigningName(ctx context.Context) (v string) {
|
||||
v, _ = middleware.GetStackValue(ctx, signingNameKey{}).(string)
|
||||
return v
|
||||
}
|
||||
|
||||
// GetSigningRegion retrieves the region from the context.
|
||||
//
|
||||
// Scoped to stack values. Use github.com/aws/smithy-go/middleware#ClearStackValues
|
||||
// to clear all stack values.
|
||||
func GetSigningRegion(ctx context.Context) (v string) {
|
||||
v, _ = middleware.GetStackValue(ctx, signingRegionKey{}).(string)
|
||||
return v
|
||||
}
|
||||
|
||||
// GetRegion retrieves the endpoint region from the context.
|
||||
//
|
||||
// Scoped to stack values. Use github.com/aws/smithy-go/middleware#ClearStackValues
|
||||
// to clear all stack values.
|
||||
func GetRegion(ctx context.Context) (v string) {
|
||||
v, _ = middleware.GetStackValue(ctx, regionKey{}).(string)
|
||||
return v
|
||||
}
|
||||
|
||||
// GetOperationName retrieves the service operation metadata from the context.
|
||||
//
|
||||
// Scoped to stack values. Use github.com/aws/smithy-go/middleware#ClearStackValues
|
||||
// to clear all stack values.
|
||||
func GetOperationName(ctx context.Context) (v string) {
|
||||
v, _ = middleware.GetStackValue(ctx, operationNameKey{}).(string)
|
||||
return v
|
||||
}
|
||||
|
||||
// GetPartitionID retrieves the endpoint partition id from the context.
|
||||
//
|
||||
// Scoped to stack values. Use github.com/aws/smithy-go/middleware#ClearStackValues
|
||||
// to clear all stack values.
|
||||
func GetPartitionID(ctx context.Context) string {
|
||||
v, _ := middleware.GetStackValue(ctx, partitionIDKey{}).(string)
|
||||
return v
|
||||
}
|
||||
|
||||
// SetSigningName set or modifies the signing name on the context.
|
||||
//
|
||||
// Scoped to stack values. Use github.com/aws/smithy-go/middleware#ClearStackValues
|
||||
// to clear all stack values.
|
||||
func SetSigningName(ctx context.Context, value string) context.Context {
|
||||
return middleware.WithStackValue(ctx, signingNameKey{}, value)
|
||||
}
|
||||
|
||||
// SetSigningRegion sets or modifies the region on the context.
|
||||
//
|
||||
// Scoped to stack values. Use github.com/aws/smithy-go/middleware#ClearStackValues
|
||||
// to clear all stack values.
|
||||
func SetSigningRegion(ctx context.Context, value string) context.Context {
|
||||
return middleware.WithStackValue(ctx, signingRegionKey{}, value)
|
||||
}
|
||||
|
||||
// SetServiceID sets the service id on the context.
|
||||
//
|
||||
// Scoped to stack values. Use github.com/aws/smithy-go/middleware#ClearStackValues
|
||||
// to clear all stack values.
|
||||
func SetServiceID(ctx context.Context, value string) context.Context {
|
||||
return middleware.WithStackValue(ctx, serviceIDKey{}, value)
|
||||
}
|
||||
|
||||
// setRegion sets the endpoint region on the context.
|
||||
//
|
||||
// Scoped to stack values. Use github.com/aws/smithy-go/middleware#ClearStackValues
|
||||
// to clear all stack values.
|
||||
func setRegion(ctx context.Context, value string) context.Context {
|
||||
return middleware.WithStackValue(ctx, regionKey{}, value)
|
||||
}
|
||||
|
||||
// setOperationName sets the service operation on the context.
|
||||
//
|
||||
// Scoped to stack values. Use github.com/aws/smithy-go/middleware#ClearStackValues
|
||||
// to clear all stack values.
|
||||
func setOperationName(ctx context.Context, value string) context.Context {
|
||||
return middleware.WithStackValue(ctx, operationNameKey{}, value)
|
||||
}
|
||||
|
||||
// SetPartitionID sets the partition id of a resolved region on the context
|
||||
//
|
||||
// Scoped to stack values. Use github.com/aws/smithy-go/middleware#ClearStackValues
|
||||
// to clear all stack values.
|
||||
func SetPartitionID(ctx context.Context, value string) context.Context {
|
||||
return middleware.WithStackValue(ctx, partitionIDKey{}, value)
|
||||
}
|
||||
|
||||
// EndpointSource key
|
||||
type endpointSourceKey struct{}
|
||||
|
||||
// GetEndpointSource returns an endpoint source if set on context
|
||||
func GetEndpointSource(ctx context.Context) (v aws.EndpointSource) {
|
||||
v, _ = middleware.GetStackValue(ctx, endpointSourceKey{}).(aws.EndpointSource)
|
||||
return v
|
||||
}
|
||||
|
||||
// SetEndpointSource sets endpoint source on context
|
||||
func SetEndpointSource(ctx context.Context, value aws.EndpointSource) context.Context {
|
||||
return middleware.WithStackValue(ctx, endpointSourceKey{}, value)
|
||||
}
|
168
vendor/github.com/aws/aws-sdk-go-v2/aws/middleware/middleware.go
generated
vendored
Normal file
@ -0,0 +1,168 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/aws/aws-sdk-go-v2/internal/rand"
|
||||
"github.com/aws/aws-sdk-go-v2/internal/sdk"
|
||||
"github.com/aws/smithy-go/logging"
|
||||
"github.com/aws/smithy-go/middleware"
|
||||
smithyrand "github.com/aws/smithy-go/rand"
|
||||
smithyhttp "github.com/aws/smithy-go/transport/http"
|
||||
)
|
||||
|
||||
// ClientRequestID is a Smithy BuildMiddleware that will generate a unique ID for logical API operation
|
||||
// invocation.
|
||||
type ClientRequestID struct{}
|
||||
|
||||
// ID the identifier for the ClientRequestID
|
||||
func (r *ClientRequestID) ID() string {
|
||||
return "ClientRequestID"
|
||||
}
|
||||
|
||||
// HandleBuild attaches a unique operation invocation id for the operation to the request
|
||||
func (r ClientRequestID) HandleBuild(ctx context.Context, in middleware.BuildInput, next middleware.BuildHandler) (
|
||||
out middleware.BuildOutput, metadata middleware.Metadata, err error,
|
||||
) {
|
||||
req, ok := in.Request.(*smithyhttp.Request)
|
||||
if !ok {
|
||||
return out, metadata, fmt.Errorf("unknown transport type %T", req)
|
||||
}
|
||||
|
||||
invocationID, err := smithyrand.NewUUID(rand.Reader).GetUUID()
|
||||
if err != nil {
|
||||
return out, metadata, err
|
||||
}
|
||||
|
||||
const invocationIDHeader = "Amz-Sdk-Invocation-Id"
|
||||
req.Header[invocationIDHeader] = append(req.Header[invocationIDHeader][:0], invocationID)
|
||||
|
||||
return next.HandleBuild(ctx, in)
|
||||
}
|
||||
|
||||
// RecordResponseTiming records the response timing for the SDK client requests.
|
||||
type RecordResponseTiming struct{}
|
||||
|
||||
// ID is the middleware identifier
|
||||
func (a *RecordResponseTiming) ID() string {
|
||||
return "RecordResponseTiming"
|
||||
}
|
||||
|
||||
// HandleDeserialize calculates response metadata and clock skew
|
||||
func (a RecordResponseTiming) HandleDeserialize(ctx context.Context, in middleware.DeserializeInput, next middleware.DeserializeHandler) (
|
||||
out middleware.DeserializeOutput, metadata middleware.Metadata, err error,
|
||||
) {
|
||||
out, metadata, err = next.HandleDeserialize(ctx, in)
|
||||
responseAt := sdk.NowTime()
|
||||
setResponseAt(&metadata, responseAt)
|
||||
|
||||
var serverTime time.Time
|
||||
|
||||
switch resp := out.RawResponse.(type) {
|
||||
case *smithyhttp.Response:
|
||||
respDateHeader := resp.Header.Get("Date")
|
||||
if len(respDateHeader) == 0 {
|
||||
break
|
||||
}
|
||||
var parseErr error
|
||||
serverTime, parseErr = smithyhttp.ParseTime(respDateHeader)
|
||||
if parseErr != nil {
|
||||
logger := middleware.GetLogger(ctx)
|
||||
logger.Logf(logging.Warn, "failed to parse response Date header value, got %v",
|
||||
parseErr.Error())
|
||||
break
|
||||
}
|
||||
setServerTime(&metadata, serverTime)
|
||||
}
|
||||
|
||||
if !serverTime.IsZero() {
|
||||
attemptSkew := serverTime.Sub(responseAt)
|
||||
setAttemptSkew(&metadata, attemptSkew)
|
||||
}
|
||||
|
||||
return out, metadata, err
|
||||
}
|
||||
|
||||
type responseAtKey struct{}
|
||||
|
||||
// GetResponseAt returns the time response was received at.
|
||||
func GetResponseAt(metadata middleware.Metadata) (v time.Time, ok bool) {
|
||||
v, ok = metadata.Get(responseAtKey{}).(time.Time)
|
||||
return v, ok
|
||||
}
|
||||
|
||||
// setResponseAt sets the response time on the metadata.
|
||||
func setResponseAt(metadata *middleware.Metadata, v time.Time) {
|
||||
metadata.Set(responseAtKey{}, v)
|
||||
}
|
||||
|
||||
type serverTimeKey struct{}
|
||||
|
||||
// GetServerTime returns the server time for response.
|
||||
func GetServerTime(metadata middleware.Metadata) (v time.Time, ok bool) {
|
||||
v, ok = metadata.Get(serverTimeKey{}).(time.Time)
|
||||
return v, ok
|
||||
}
|
||||
|
||||
// setServerTime sets the server time on the metadata.
|
||||
func setServerTime(metadata *middleware.Metadata, v time.Time) {
|
||||
metadata.Set(serverTimeKey{}, v)
|
||||
}
|
||||
|
||||
type attemptSkewKey struct{}
|
||||
|
||||
// GetAttemptSkew returns Attempt clock skew for response from metadata.
|
||||
func GetAttemptSkew(metadata middleware.Metadata) (v time.Duration, ok bool) {
|
||||
v, ok = metadata.Get(attemptSkewKey{}).(time.Duration)
|
||||
return v, ok
|
||||
}
|
||||
|
||||
// setAttemptSkew sets the attempt clock skew on the metadata.
|
||||
func setAttemptSkew(metadata *middleware.Metadata, v time.Duration) {
|
||||
metadata.Set(attemptSkewKey{}, v)
|
||||
}
|
||||
|
||||
// AddClientRequestIDMiddleware adds ClientRequestID to the middleware stack
|
||||
func AddClientRequestIDMiddleware(stack *middleware.Stack) error {
|
||||
return stack.Build.Add(&ClientRequestID{}, middleware.After)
|
||||
}
|
||||
|
||||
// AddRecordResponseTiming adds RecordResponseTiming middleware to the
|
||||
// middleware stack.
|
||||
func AddRecordResponseTiming(stack *middleware.Stack) error {
|
||||
return stack.Deserialize.Add(&RecordResponseTiming{}, middleware.After)
|
||||
}
|
||||
|
||||
// rawResponseKey is the accessor key used to store and access the
|
||||
// raw response within the response metadata.
|
||||
type rawResponseKey struct{}
|
||||
|
||||
// addRawResponse middleware adds raw response on to the metadata
|
||||
type addRawResponse struct{}
|
||||
|
||||
// ID the identifier for the ClientRequestID
|
||||
func (m *addRawResponse) ID() string {
|
||||
return "AddRawResponseToMetadata"
|
||||
}
|
||||
|
||||
// HandleDeserialize adds raw response on the middleware metadata
|
||||
func (m addRawResponse) HandleDeserialize(ctx context.Context, in middleware.DeserializeInput, next middleware.DeserializeHandler) (
|
||||
out middleware.DeserializeOutput, metadata middleware.Metadata, err error,
|
||||
) {
|
||||
out, metadata, err = next.HandleDeserialize(ctx, in)
|
||||
metadata.Set(rawResponseKey{}, out.RawResponse)
|
||||
return out, metadata, err
|
||||
}
|
||||
|
||||
// AddRawResponseToMetadata adds middleware to the middleware stack that
|
||||
// store raw response on to the metadata.
|
||||
func AddRawResponseToMetadata(stack *middleware.Stack) error {
|
||||
return stack.Deserialize.Add(&addRawResponse{}, middleware.Before)
|
||||
}
|
||||
|
||||
// GetRawResponse returns raw response set on metadata
|
||||
func GetRawResponse(metadata middleware.Metadata) interface{} {
|
||||
return metadata.Get(rawResponseKey{})
|
||||
}
|
24
vendor/github.com/aws/aws-sdk-go-v2/aws/middleware/osname.go
generated
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
//go:build go1.16
|
||||
// +build go1.16
|
||||
|
||||
package middleware
|
||||
|
||||
import "runtime"
|
||||
|
||||
func getNormalizedOSName() (os string) {
|
||||
switch runtime.GOOS {
|
||||
case "android":
|
||||
os = "android"
|
||||
case "linux":
|
||||
os = "linux"
|
||||
case "windows":
|
||||
os = "windows"
|
||||
case "darwin":
|
||||
os = "macos"
|
||||
case "ios":
|
||||
os = "ios"
|
||||
default:
|
||||
os = "other"
|
||||
}
|
||||
return os
|
||||
}
|
24
vendor/github.com/aws/aws-sdk-go-v2/aws/middleware/osname_go115.go
generated
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
//go:build !go1.16
|
||||
// +build !go1.16
|
||||
|
||||
package middleware
|
||||
|
||||
import "runtime"
|
||||
|
||||
func getNormalizedOSName() (os string) {
|
||||
switch runtime.GOOS {
|
||||
case "android":
|
||||
os = "android"
|
||||
case "linux":
|
||||
os = "linux"
|
||||
case "windows":
|
||||
os = "windows"
|
||||
case "darwin":
|
||||
// Due to Apple M1 we can't distinguish between macOS and iOS when GOOS/GOARCH is darwin/amd64
|
||||
// For now declare this as "other" until we have a better detection mechanism.
|
||||
fallthrough
|
||||
default:
|
||||
os = "other"
|
||||
}
|
||||
return os
|
||||
}
|
27
vendor/github.com/aws/aws-sdk-go-v2/aws/middleware/request_id.go
generated
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"github.com/aws/smithy-go/middleware"
|
||||
)
|
||||
|
||||
// requestIDKey is used to retrieve request id from response metadata
|
||||
type requestIDKey struct{}
|
||||
|
||||
// SetRequestIDMetadata sets the provided request id over middleware metadata
|
||||
func SetRequestIDMetadata(metadata *middleware.Metadata, id string) {
|
||||
metadata.Set(requestIDKey{}, id)
|
||||
}
|
||||
|
||||
// GetRequestIDMetadata retrieves the request id from middleware metadata
|
||||
// returns string and bool indicating value of request id, whether request id was set.
|
||||
func GetRequestIDMetadata(metadata middleware.Metadata) (string, bool) {
|
||||
if !metadata.Has(requestIDKey{}) {
|
||||
return "", false
|
||||
}
|
||||
|
||||
v, ok := metadata.Get(requestIDKey{}).(string)
|
||||
if !ok {
|
||||
return "", true
|
||||
}
|
||||
return v, true
|
||||
}
|
49
vendor/github.com/aws/aws-sdk-go-v2/aws/middleware/request_id_retriever.go
generated
vendored
Normal file
@ -0,0 +1,49 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/aws/smithy-go/middleware"
|
||||
smithyhttp "github.com/aws/smithy-go/transport/http"
|
||||
)
|
||||
|
||||
// AddRequestIDRetrieverMiddleware adds request id retriever middleware
|
||||
func AddRequestIDRetrieverMiddleware(stack *middleware.Stack) error {
|
||||
// add error wrapper middleware before operation deserializers so that it can wrap the error response
|
||||
// returned by operation deserializers
|
||||
return stack.Deserialize.Insert(&requestIDRetriever{}, "OperationDeserializer", middleware.Before)
|
||||
}
|
||||
|
||||
type requestIDRetriever struct {
|
||||
}
|
||||
|
||||
// ID returns the middleware identifier
|
||||
func (m *requestIDRetriever) ID() string {
|
||||
return "RequestIDRetriever"
|
||||
}
|
||||
|
||||
func (m *requestIDRetriever) HandleDeserialize(ctx context.Context, in middleware.DeserializeInput, next middleware.DeserializeHandler) (
|
||||
out middleware.DeserializeOutput, metadata middleware.Metadata, err error,
|
||||
) {
|
||||
out, metadata, err = next.HandleDeserialize(ctx, in)
|
||||
|
||||
resp, ok := out.RawResponse.(*smithyhttp.Response)
|
||||
if !ok {
|
||||
// No raw response to wrap with.
|
||||
return out, metadata, err
|
||||
}
|
||||
|
||||
// Different header which can map to request id
|
||||
requestIDHeaderList := []string{"X-Amzn-Requestid", "X-Amz-RequestId"}
|
||||
|
||||
for _, h := range requestIDHeaderList {
|
||||
// check for headers known to contain Request id
|
||||
if v := resp.Header.Get(h); len(v) != 0 {
|
||||
// set reqID on metadata for successful responses.
|
||||
SetRequestIDMetadata(&metadata, v)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return out, metadata, err
|
||||
}
|
241
vendor/github.com/aws/aws-sdk-go-v2/aws/middleware/user_agent.go
generated
vendored
Normal file
@ -0,0 +1,241 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"runtime"
|
||||
"strings"
|
||||
|
||||
"github.com/aws/aws-sdk-go-v2/aws"
|
||||
"github.com/aws/smithy-go/middleware"
|
||||
smithyhttp "github.com/aws/smithy-go/transport/http"
|
||||
)
|
||||
|
||||
var languageVersion = strings.TrimPrefix(runtime.Version(), "go")
|
||||
|
||||
// SDKAgentKeyType is the metadata type to add to the SDK agent string
|
||||
type SDKAgentKeyType int
|
||||
|
||||
// The set of valid SDKAgentKeyType constants. If an unknown value is assigned for SDKAgentKeyType it will
|
||||
// be mapped to AdditionalMetadata.
|
||||
const (
|
||||
_ SDKAgentKeyType = iota
|
||||
APIMetadata
|
||||
OperatingSystemMetadata
|
||||
LanguageMetadata
|
||||
EnvironmentMetadata
|
||||
FeatureMetadata
|
||||
ConfigMetadata
|
||||
FrameworkMetadata
|
||||
AdditionalMetadata
|
||||
ApplicationIdentifier
|
||||
)
|
||||
|
||||
func (k SDKAgentKeyType) string() string {
|
||||
switch k {
|
||||
case APIMetadata:
|
||||
return "api"
|
||||
case OperatingSystemMetadata:
|
||||
return "os"
|
||||
case LanguageMetadata:
|
||||
return "lang"
|
||||
case EnvironmentMetadata:
|
||||
return "exec-env"
|
||||
case FeatureMetadata:
|
||||
return "ft"
|
||||
case ConfigMetadata:
|
||||
return "cfg"
|
||||
case FrameworkMetadata:
|
||||
return "lib"
|
||||
case ApplicationIdentifier:
|
||||
return "app"
|
||||
case AdditionalMetadata:
|
||||
fallthrough
|
||||
default:
|
||||
return "md"
|
||||
}
|
||||
}
|
||||
|
||||
const execEnvVar = `AWS_EXECUTION_ENV`
|
||||
|
||||
// requestUserAgent is a build middleware that set the User-Agent for the request.
|
||||
type requestUserAgent struct {
|
||||
sdkAgent, userAgent *smithyhttp.UserAgentBuilder
|
||||
}
|
||||
|
||||
// newRequestUserAgent returns a new requestUserAgent which will set the User-Agent and X-Amz-User-Agent for the
|
||||
// request.
|
||||
//
|
||||
// User-Agent example:
|
||||
// aws-sdk-go-v2/1.2.3
|
||||
//
|
||||
// X-Amz-User-Agent example:
|
||||
// aws-sdk-go-v2/1.2.3 md/GOOS/linux md/GOARCH/amd64 lang/go/1.15
|
||||
func newRequestUserAgent() *requestUserAgent {
|
||||
userAgent, sdkAgent := smithyhttp.NewUserAgentBuilder(), smithyhttp.NewUserAgentBuilder()
|
||||
addProductName(userAgent)
|
||||
addProductName(sdkAgent)
|
||||
|
||||
r := &requestUserAgent{
|
||||
sdkAgent: sdkAgent,
|
||||
userAgent: userAgent,
|
||||
}
|
||||
|
||||
addSDKMetadata(r)
|
||||
|
||||
return r
|
||||
}
|
||||
|
||||
func addSDKMetadata(r *requestUserAgent) {
|
||||
r.AddSDKAgentKey(OperatingSystemMetadata, getNormalizedOSName())
|
||||
r.AddSDKAgentKeyValue(LanguageMetadata, "go", languageVersion)
|
||||
r.AddSDKAgentKeyValue(AdditionalMetadata, "GOOS", runtime.GOOS)
|
||||
r.AddSDKAgentKeyValue(AdditionalMetadata, "GOARCH", runtime.GOARCH)
|
||||
if ev := os.Getenv(execEnvVar); len(ev) > 0 {
|
||||
r.AddSDKAgentKey(EnvironmentMetadata, ev)
|
||||
}
|
||||
}
|
||||
|
||||
func addProductName(builder *smithyhttp.UserAgentBuilder) {
|
||||
builder.AddKeyValue(aws.SDKName, aws.SDKVersion)
|
||||
}
|
||||
|
||||
// AddUserAgentKey retrieves a requestUserAgent from the provided stack, or initializes one.
|
||||
func AddUserAgentKey(key string) func(*middleware.Stack) error {
|
||||
return func(stack *middleware.Stack) error {
|
||||
requestUserAgent, err := getOrAddRequestUserAgent(stack)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
requestUserAgent.AddUserAgentKey(key)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// AddUserAgentKeyValue retrieves a requestUserAgent from the provided stack, or initializes one.
|
||||
func AddUserAgentKeyValue(key, value string) func(*middleware.Stack) error {
|
||||
return func(stack *middleware.Stack) error {
|
||||
requestUserAgent, err := getOrAddRequestUserAgent(stack)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
requestUserAgent.AddUserAgentKeyValue(key, value)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// AddSDKAgentKey retrieves a requestUserAgent from the provided stack, or initializes one.
|
||||
func AddSDKAgentKey(keyType SDKAgentKeyType, key string) func(*middleware.Stack) error {
|
||||
return func(stack *middleware.Stack) error {
|
||||
requestUserAgent, err := getOrAddRequestUserAgent(stack)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
requestUserAgent.AddSDKAgentKey(keyType, key)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// AddSDKAgentKeyValue retrieves a requestUserAgent from the provided stack, or initializes one.
|
||||
func AddSDKAgentKeyValue(keyType SDKAgentKeyType, key, value string) func(*middleware.Stack) error {
|
||||
return func(stack *middleware.Stack) error {
|
||||
requestUserAgent, err := getOrAddRequestUserAgent(stack)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
requestUserAgent.AddSDKAgentKeyValue(keyType, key, value)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// AddRequestUserAgentMiddleware registers a requestUserAgent middleware on the stack if not present.
|
||||
func AddRequestUserAgentMiddleware(stack *middleware.Stack) error {
|
||||
_, err := getOrAddRequestUserAgent(stack)
|
||||
return err
|
||||
}
|
||||
|
||||
func getOrAddRequestUserAgent(stack *middleware.Stack) (*requestUserAgent, error) {
|
||||
id := (*requestUserAgent)(nil).ID()
|
||||
bm, ok := stack.Build.Get(id)
|
||||
if !ok {
|
||||
bm = newRequestUserAgent()
|
||||
err := stack.Build.Add(bm, middleware.After)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
requestUserAgent, ok := bm.(*requestUserAgent)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("%T for %s middleware did not match expected type", bm, id)
|
||||
}
|
||||
|
||||
return requestUserAgent, nil
|
||||
}
|
||||
|
||||
// AddUserAgentKey adds the component identified by name to the User-Agent string.
|
||||
func (u *requestUserAgent) AddUserAgentKey(key string) {
|
||||
u.userAgent.AddKey(key)
|
||||
}
|
||||
|
||||
// AddUserAgentKeyValue adds the key identified by the given name and value to the User-Agent string.
|
||||
func (u *requestUserAgent) AddUserAgentKeyValue(key, value string) {
|
||||
u.userAgent.AddKeyValue(key, value)
|
||||
}
|
||||
|
||||
// AddUserAgentKey adds the component identified by name to the User-Agent string.
|
||||
func (u *requestUserAgent) AddSDKAgentKey(keyType SDKAgentKeyType, key string) {
|
||||
// TODO: should target sdkAgent
|
||||
u.userAgent.AddKey(keyType.string() + "/" + key)
|
||||
}
|
||||
|
||||
// AddUserAgentKeyValue adds the key identified by the given name and value to the User-Agent string.
|
||||
func (u *requestUserAgent) AddSDKAgentKeyValue(keyType SDKAgentKeyType, key, value string) {
|
||||
// TODO: should target sdkAgent
|
||||
u.userAgent.AddKeyValue(keyType.string()+"/"+key, value)
|
||||
}
|
||||
|
||||
// ID the name of the middleware.
|
||||
func (u *requestUserAgent) ID() string {
|
||||
return "UserAgent"
|
||||
}
|
||||
|
||||
// HandleBuild adds or appends the constructed user agent to the request.
|
||||
func (u *requestUserAgent) HandleBuild(ctx context.Context, in middleware.BuildInput, next middleware.BuildHandler) (
|
||||
out middleware.BuildOutput, metadata middleware.Metadata, err error,
|
||||
) {
|
||||
switch req := in.Request.(type) {
|
||||
case *smithyhttp.Request:
|
||||
u.addHTTPUserAgent(req)
|
||||
// TODO: To be re-enabled
|
||||
// u.addHTTPSDKAgent(req)
|
||||
default:
|
||||
return out, metadata, fmt.Errorf("unknown transport type %T", in)
|
||||
}
|
||||
|
||||
return next.HandleBuild(ctx, in)
|
||||
}
|
||||
|
||||
func (u *requestUserAgent) addHTTPUserAgent(request *smithyhttp.Request) {
|
||||
const userAgent = "User-Agent"
|
||||
updateHTTPHeader(request, userAgent, u.userAgent.Build())
|
||||
}
|
||||
|
||||
func (u *requestUserAgent) addHTTPSDKAgent(request *smithyhttp.Request) {
|
||||
const sdkAgent = "X-Amz-User-Agent"
|
||||
updateHTTPHeader(request, sdkAgent, u.sdkAgent.Build())
|
||||
}
|
||||
|
||||
func updateHTTPHeader(request *smithyhttp.Request, header string, value string) {
|
||||
var current string
|
||||
if v := request.Header[header]; len(v) > 0 {
|
||||
current = v[0]
|
||||
}
|
||||
if len(current) > 0 {
|
||||
current = value + " " + current
|
||||
} else {
|
||||
current = value
|
||||
}
|
||||
request.Header[header] = append(request.Header[header][:0], current)
|
||||
}
|
61
vendor/github.com/aws/aws-sdk-go-v2/aws/protocol/query/array.go
generated
vendored
Normal file
@ -0,0 +1,61 @@
|
||||
package query
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/url"
|
||||
)
|
||||
|
||||
// Array represents the encoding of Query lists and sets. A Query array is a
|
||||
// representation of a list of values of a fixed type. A serialized array might
|
||||
// look like the following:
|
||||
//
|
||||
// ListName.member.1=foo
|
||||
// &ListName.member.2=bar
|
||||
// &Listname.member.3=baz
|
||||
type Array struct {
|
||||
// The query values to add the array to.
|
||||
values url.Values
|
||||
// The array's prefix, which includes the names of all parent structures
|
||||
// and ends with the name of the list. For example, the prefix might be
|
||||
// "ParentStructure.ListName". This prefix will be used to form the full
|
||||
// keys for each element in the list. For example, an entry might have the
|
||||
// key "ParentStructure.ListName.member.MemberName.1".
|
||||
//
|
||||
// While this is currently represented as a string that gets added to, it
|
||||
// could also be represented as a stack that only gets condensed into a
|
||||
// string when a finalized key is created. This could potentially reduce
|
||||
// allocations.
|
||||
prefix string
|
||||
// Whether the list is flat or not. A list that is not flat will produce the
|
||||
// following entry to the url.Values for a given entry:
|
||||
// ListName.MemberName.1=value
|
||||
// A list that is flat will produce the following:
|
||||
// ListName.1=value
|
||||
flat bool
|
||||
// The location name of the member. In most cases this should be "member".
|
||||
memberName string
|
||||
// Elements are stored in values, so we keep track of the list size here.
|
||||
size int32
|
||||
}
|
||||
|
||||
func newArray(values url.Values, prefix string, flat bool, memberName string) *Array {
|
||||
return &Array{
|
||||
values: values,
|
||||
prefix: prefix,
|
||||
flat: flat,
|
||||
memberName: memberName,
|
||||
}
|
||||
}
|
||||
|
||||
// Value adds a new element to the Query Array. Returns a Value type used to
|
||||
// encode the array element.
|
||||
func (a *Array) Value() Value {
|
||||
// Query lists start a 1, so adjust the size first
|
||||
a.size++
|
||||
prefix := a.prefix
|
||||
if !a.flat {
|
||||
prefix = fmt.Sprintf("%s.%s", prefix, a.memberName)
|
||||
}
|
||||
// Lists can't have flat members
|
||||
return newValue(a.values, fmt.Sprintf("%s.%d", prefix, a.size), false)
|
||||
}
|
80
vendor/github.com/aws/aws-sdk-go-v2/aws/protocol/query/encoder.go
generated
vendored
Normal file
@ -0,0 +1,80 @@
|
||||
package query
|
||||
|
||||
import (
|
||||
"io"
|
||||
"net/url"
|
||||
"sort"
|
||||
)
|
||||
|
||||
// Encoder is a Query encoder that supports construction of Query body
|
||||
// values using methods.
|
||||
type Encoder struct {
|
||||
// The query values that will be built up to manage encoding.
|
||||
values url.Values
|
||||
// The writer that the encoded body will be written to.
|
||||
writer io.Writer
|
||||
Value
|
||||
}
|
||||
|
||||
// NewEncoder returns a new Query body encoder
|
||||
func NewEncoder(writer io.Writer) *Encoder {
|
||||
values := url.Values{}
|
||||
return &Encoder{
|
||||
values: values,
|
||||
writer: writer,
|
||||
Value: newBaseValue(values),
|
||||
}
|
||||
}
|
||||
|
||||
// Encode returns the []byte slice representing the current
|
||||
// state of the Query encoder.
|
||||
func (e Encoder) Encode() error {
|
||||
ws, ok := e.writer.(interface{ WriteString(string) (int, error) })
|
||||
if !ok {
|
||||
// Fall back to less optimal byte slice casting if WriteString isn't available.
|
||||
ws = &wrapWriteString{writer: e.writer}
|
||||
}
|
||||
|
||||
// Get the keys and sort them to have a stable output
|
||||
keys := make([]string, 0, len(e.values))
|
||||
for k := range e.values {
|
||||
keys = append(keys, k)
|
||||
}
|
||||
sort.Strings(keys)
|
||||
isFirstEntry := true
|
||||
for _, key := range keys {
|
||||
queryValues := e.values[key]
|
||||
escapedKey := url.QueryEscape(key)
|
||||
for _, value := range queryValues {
|
||||
if !isFirstEntry {
|
||||
if _, err := ws.WriteString(`&`); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
isFirstEntry = false
|
||||
}
|
||||
if _, err := ws.WriteString(escapedKey); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := ws.WriteString(`=`); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := ws.WriteString(url.QueryEscape(value)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// wrapWriteString wraps an io.Writer to provide a WriteString method
|
||||
// where one is not available.
|
||||
type wrapWriteString struct {
|
||||
writer io.Writer
|
||||
}
|
||||
|
||||
// WriteString writes a string to the wrapped writer by casting it to
|
||||
// a byte array first.
|
||||
func (w wrapWriteString) WriteString(v string) (int, error) {
|
||||
return w.writer.Write([]byte(v))
|
||||
}
|
78
vendor/github.com/aws/aws-sdk-go-v2/aws/protocol/query/map.go
generated
vendored
Normal file
@ -0,0 +1,78 @@
|
||||
package query
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/url"
|
||||
)
|
||||
|
||||
// Map represents the encoding of Query maps. A Query map is a representation
|
||||
// of a mapping of arbitrary string keys to arbitrary values of a fixed type.
|
||||
// A Map differs from an Object in that the set of keys is not fixed, in that
|
||||
// the values must all be of the same type, and that map entries are ordered.
|
||||
// A serialized map might look like the following:
|
||||
//
|
||||
// MapName.entry.1.key=Foo
|
||||
// &MapName.entry.1.value=spam
|
||||
// &MapName.entry.2.key=Bar
|
||||
// &MapName.entry.2.value=eggs
|
||||
type Map struct {
|
||||
// The query values to add the map to.
|
||||
values url.Values
|
||||
// The map's prefix, which includes the names of all parent structures
|
||||
// and ends with the name of the object. For example, the prefix might be
|
||||
// "ParentStructure.MapName". This prefix will be used to form the full
|
||||
// keys for each key-value pair of the map. For example, a value might have
|
||||
// the key "ParentStructure.MapName.1.value".
|
||||
//
|
||||
// While this is currently represented as a string that gets added to, it
|
||||
// could also be represented as a stack that only gets condensed into a
|
||||
// string when a finalized key is created. This could potentially reduce
|
||||
// allocations.
|
||||
prefix string
|
||||
// Whether the map is flat or not. A map that is not flat will produce the
|
||||
// following entries to the url.Values for a given key-value pair:
|
||||
// MapName.entry.1.KeyLocationName=mykey
|
||||
// MapName.entry.1.ValueLocationName=myvalue
|
||||
// A map that is flat will produce the following:
|
||||
// MapName.1.KeyLocationName=mykey
|
||||
// MapName.1.ValueLocationName=myvalue
|
||||
flat bool
|
||||
// The location name of the key. In most cases this should be "key".
|
||||
keyLocationName string
|
||||
// The location name of the value. In most cases this should be "value".
|
||||
valueLocationName string
|
||||
// Elements are stored in values, so we keep track of the list size here.
|
||||
size int32
|
||||
}
|
||||
|
||||
func newMap(values url.Values, prefix string, flat bool, keyLocationName string, valueLocationName string) *Map {
|
||||
return &Map{
|
||||
values: values,
|
||||
prefix: prefix,
|
||||
flat: flat,
|
||||
keyLocationName: keyLocationName,
|
||||
valueLocationName: valueLocationName,
|
||||
}
|
||||
}
|
||||
|
||||
// Key adds the given named key to the Query map.
|
||||
// Returns a Value encoder that should be used to encode a Query value type.
|
||||
func (m *Map) Key(name string) Value {
|
||||
// Query lists start a 1, so adjust the size first
|
||||
m.size++
|
||||
var key string
|
||||
var value string
|
||||
if m.flat {
|
||||
key = fmt.Sprintf("%s.%d.%s", m.prefix, m.size, m.keyLocationName)
|
||||
value = fmt.Sprintf("%s.%d.%s", m.prefix, m.size, m.valueLocationName)
|
||||
} else {
|
||||
key = fmt.Sprintf("%s.entry.%d.%s", m.prefix, m.size, m.keyLocationName)
|
||||
value = fmt.Sprintf("%s.entry.%d.%s", m.prefix, m.size, m.valueLocationName)
|
||||
}
|
||||
|
||||
// The key can only be a string, so we just go ahead and set it here
|
||||
newValue(m.values, key, false).String(name)
|
||||
|
||||
// Maps can't have flat members
|
||||
return newValue(m.values, value, false)
|
||||
}
|
62
vendor/github.com/aws/aws-sdk-go-v2/aws/protocol/query/middleware.go
generated
vendored
Normal file
@ -0,0 +1,62 @@
|
||||
package query
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
|
||||
"github.com/aws/smithy-go/middleware"
|
||||
smithyhttp "github.com/aws/smithy-go/transport/http"
|
||||
)
|
||||
|
||||
// AddAsGetRequestMiddleware adds a middleware to the Serialize stack after the
|
||||
// operation serializer that will convert the query request body to a GET
|
||||
// operation with the query message in the HTTP request querystring.
|
||||
func AddAsGetRequestMiddleware(stack *middleware.Stack) error {
|
||||
return stack.Serialize.Insert(&asGetRequest{}, "OperationSerializer", middleware.After)
|
||||
}
|
||||
|
||||
type asGetRequest struct{}
|
||||
|
||||
func (*asGetRequest) ID() string { return "Query:AsGetRequest" }
|
||||
|
||||
func (m *asGetRequest) HandleSerialize(
|
||||
ctx context.Context, input middleware.SerializeInput, next middleware.SerializeHandler,
|
||||
) (
|
||||
out middleware.SerializeOutput, metadata middleware.Metadata, err error,
|
||||
) {
|
||||
req, ok := input.Request.(*smithyhttp.Request)
|
||||
if !ok {
|
||||
return out, metadata, fmt.Errorf("expect smithy HTTP Request, got %T", input.Request)
|
||||
}
|
||||
|
||||
req.Method = "GET"
|
||||
|
||||
// If the stream is not set, nothing else to do.
|
||||
stream := req.GetStream()
|
||||
if stream == nil {
|
||||
return next.HandleSerialize(ctx, input)
|
||||
}
|
||||
|
||||
// Clear the stream since there will not be any body.
|
||||
req.Header.Del("Content-Type")
|
||||
req, err = req.SetStream(nil)
|
||||
if err != nil {
|
||||
return out, metadata, fmt.Errorf("unable update request body %w", err)
|
||||
}
|
||||
input.Request = req
|
||||
|
||||
// Update request query with the body's query string value.
|
||||
delim := ""
|
||||
if len(req.URL.RawQuery) != 0 {
|
||||
delim = "&"
|
||||
}
|
||||
|
||||
b, err := ioutil.ReadAll(stream)
|
||||
if err != nil {
|
||||
return out, metadata, fmt.Errorf("unable to get request body %w", err)
|
||||
}
|
||||
req.URL.RawQuery += delim + string(b)
|
||||
|
||||
return next.HandleSerialize(ctx, input)
|
||||
}
|
56
vendor/github.com/aws/aws-sdk-go-v2/aws/protocol/query/object.go
generated
vendored
Normal file
@ -0,0 +1,56 @@
|
||||
package query
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/url"
|
||||
)
|
||||
|
||||
// Object represents the encoding of Query structures and unions. A Query
|
||||
// object is a representation of a mapping of string keys to arbitrary
|
||||
// values where there is a fixed set of keys whose values each have their
|
||||
// own known type. A serialized object might look like the following:
|
||||
//
|
||||
// ObjectName.Foo=value
|
||||
// &ObjectName.Bar=5
|
||||
type Object struct {
|
||||
// The query values to add the object to.
|
||||
values url.Values
|
||||
// The object's prefix, which includes the names of all parent structures
|
||||
// and ends with the name of the object. For example, the prefix might be
|
||||
// "ParentStructure.ObjectName". This prefix will be used to form the full
|
||||
// keys for each member of the object. For example, a member might have the
|
||||
// key "ParentStructure.ObjectName.MemberName".
|
||||
//
|
||||
// While this is currently represented as a string that gets added to, it
|
||||
// could also be represented as a stack that only gets condensed into a
|
||||
// string when a finalized key is created. This could potentially reduce
|
||||
// allocations.
|
||||
prefix string
|
||||
}
|
||||
|
||||
func newObject(values url.Values, prefix string) *Object {
|
||||
return &Object{
|
||||
values: values,
|
||||
prefix: prefix,
|
||||
}
|
||||
}
|
||||
|
||||
// Key adds the given named key to the Query object.
|
||||
// Returns a Value encoder that should be used to encode a Query value type.
|
||||
func (o *Object) Key(name string) Value {
|
||||
return o.key(name, false)
|
||||
}
|
||||
|
||||
// FlatKey adds the given named key to the Query object.
|
||||
// Returns a Value encoder that should be used to encode a Query value type. The
|
||||
// value will be flattened if it is a map or array.
|
||||
func (o *Object) FlatKey(name string) Value {
|
||||
return o.key(name, true)
|
||||
}
|
||||
|
||||
func (o *Object) key(name string, flatValue bool) Value {
|
||||
if o.prefix != "" {
|
||||
return newValue(o.values, fmt.Sprintf("%s.%s", o.prefix, name), flatValue)
|
||||
}
|
||||
return newValue(o.values, name, flatValue)
|
||||
}
|
106
vendor/github.com/aws/aws-sdk-go-v2/aws/protocol/query/value.go
generated
vendored
Normal file
@ -0,0 +1,106 @@
|
||||
package query
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
"net/url"
|
||||
|
||||
"github.com/aws/smithy-go/encoding/httpbinding"
|
||||
)
|
||||
|
||||
// Value represents a Query Value type.
|
||||
type Value struct {
|
||||
// The query values to add the value to.
|
||||
values url.Values
|
||||
// The value's key, which will form the prefix for complex types.
|
||||
key string
|
||||
// Whether the value should be flattened or not if it's a flattenable type.
|
||||
flat bool
|
||||
queryValue httpbinding.QueryValue
|
||||
}
|
||||
|
||||
func newValue(values url.Values, key string, flat bool) Value {
|
||||
return Value{
|
||||
values: values,
|
||||
key: key,
|
||||
flat: flat,
|
||||
queryValue: httpbinding.NewQueryValue(values, key, false),
|
||||
}
|
||||
}
|
||||
|
||||
func newBaseValue(values url.Values) Value {
|
||||
return Value{
|
||||
values: values,
|
||||
queryValue: httpbinding.NewQueryValue(nil, "", false),
|
||||
}
|
||||
}
|
||||
|
||||
// Array returns a new Array encoder.
|
||||
func (qv Value) Array(locationName string) *Array {
|
||||
return newArray(qv.values, qv.key, qv.flat, locationName)
|
||||
}
|
||||
|
||||
// Object returns a new Object encoder.
|
||||
func (qv Value) Object() *Object {
|
||||
return newObject(qv.values, qv.key)
|
||||
}
|
||||
|
||||
// Map returns a new Map encoder.
|
||||
func (qv Value) Map(keyLocationName string, valueLocationName string) *Map {
|
||||
return newMap(qv.values, qv.key, qv.flat, keyLocationName, valueLocationName)
|
||||
}
|
||||
|
||||
// Base64EncodeBytes encodes v as a base64 query string value.
|
||||
// This is intended to enable compatibility with the JSON encoder.
|
||||
func (qv Value) Base64EncodeBytes(v []byte) {
|
||||
qv.queryValue.Blob(v)
|
||||
}
|
||||
|
||||
// Boolean encodes v as a query string value
|
||||
func (qv Value) Boolean(v bool) {
|
||||
qv.queryValue.Boolean(v)
|
||||
}
|
||||
|
||||
// String encodes v as a query string value
|
||||
func (qv Value) String(v string) {
|
||||
qv.queryValue.String(v)
|
||||
}
|
||||
|
||||
// Byte encodes v as a query string value
|
||||
func (qv Value) Byte(v int8) {
|
||||
qv.queryValue.Byte(v)
|
||||
}
|
||||
|
||||
// Short encodes v as a query string value
|
||||
func (qv Value) Short(v int16) {
|
||||
qv.queryValue.Short(v)
|
||||
}
|
||||
|
||||
// Integer encodes v as a query string value
|
||||
func (qv Value) Integer(v int32) {
|
||||
qv.queryValue.Integer(v)
|
||||
}
|
||||
|
||||
// Long encodes v as a query string value
|
||||
func (qv Value) Long(v int64) {
|
||||
qv.queryValue.Long(v)
|
||||
}
|
||||
|
||||
// Float encodes v as a query string value
|
||||
func (qv Value) Float(v float32) {
|
||||
qv.queryValue.Float(v)
|
||||
}
|
||||
|
||||
// Double encodes v as a query string value
|
||||
func (qv Value) Double(v float64) {
|
||||
qv.queryValue.Double(v)
|
||||
}
|
||||
|
||||
// BigInteger encodes v as a query string value
|
||||
func (qv Value) BigInteger(v *big.Int) {
|
||||
qv.queryValue.BigInteger(v)
|
||||
}
|
||||
|
||||
// BigDecimal encodes v as a query string value
|
||||
func (qv Value) BigDecimal(v *big.Float) {
|
||||
qv.queryValue.BigDecimal(v)
|
||||
}
|
85
vendor/github.com/aws/aws-sdk-go-v2/aws/protocol/restjson/decoder_util.go
generated
vendored
Normal file
@ -0,0 +1,85 @@
|
||||
package restjson
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io"
|
||||
"strings"
|
||||
|
||||
"github.com/aws/smithy-go"
|
||||
)
|
||||
|
||||
// GetErrorInfo util looks for code, __type, and message members in the
|
||||
// json body. These members are optionally available, and the function
|
||||
// returns the value of member if it is available. This function is useful to
|
||||
// identify the error code, msg in a REST JSON error response.
|
||||
func GetErrorInfo(decoder *json.Decoder) (errorType string, message string, err error) {
|
||||
var errInfo struct {
|
||||
Code string
|
||||
Type string `json:"__type"`
|
||||
Message string
|
||||
}
|
||||
|
||||
err = decoder.Decode(&errInfo)
|
||||
if err != nil {
|
||||
if err == io.EOF {
|
||||
return errorType, message, nil
|
||||
}
|
||||
return errorType, message, err
|
||||
}
|
||||
|
||||
// assign error type
|
||||
if len(errInfo.Code) != 0 {
|
||||
errorType = errInfo.Code
|
||||
} else if len(errInfo.Type) != 0 {
|
||||
errorType = errInfo.Type
|
||||
}
|
||||
|
||||
// assign error message
|
||||
if len(errInfo.Message) != 0 {
|
||||
message = errInfo.Message
|
||||
}
|
||||
|
||||
// sanitize error
|
||||
if len(errorType) != 0 {
|
||||
errorType = SanitizeErrorCode(errorType)
|
||||
}
|
||||
|
||||
return errorType, message, nil
|
||||
}
|
||||
|
||||
// SanitizeErrorCode sanitizes the errorCode string .
|
||||
// The rule for sanitizing is if a `:` character is present, then take only the
|
||||
// contents before the first : character in the value.
|
||||
// If a # character is present, then take only the contents after the
|
||||
// first # character in the value.
|
||||
func SanitizeErrorCode(errorCode string) string {
|
||||
if strings.ContainsAny(errorCode, ":") {
|
||||
errorCode = strings.SplitN(errorCode, ":", 2)[0]
|
||||
}
|
||||
|
||||
if strings.ContainsAny(errorCode, "#") {
|
||||
errorCode = strings.SplitN(errorCode, "#", 2)[1]
|
||||
}
|
||||
|
||||
return errorCode
|
||||
}
|
||||
|
||||
// GetSmithyGenericAPIError returns smithy generic api error and an error interface.
|
||||
// Takes in json decoder, and error Code string as args. The function retrieves error message
|
||||
// and error code from the decoder body. If errorCode of length greater than 0 is passed in as
|
||||
// an argument, it is used instead.
|
||||
func GetSmithyGenericAPIError(decoder *json.Decoder, errorCode string) (*smithy.GenericAPIError, error) {
|
||||
errorType, message, err := GetErrorInfo(decoder)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(errorCode) == 0 {
|
||||
errorCode = errorType
|
||||
}
|
||||
|
||||
return &smithy.GenericAPIError{
|
||||
Code: errorCode,
|
||||
Message: message,
|
||||
}, nil
|
||||
}
|
56
vendor/github.com/aws/aws-sdk-go-v2/aws/protocol/xml/error_utils.go
generated
vendored
Normal file
@ -0,0 +1,56 @@
|
||||
package xml
|
||||
|
||||
import (
|
||||
"encoding/xml"
|
||||
"fmt"
|
||||
"io"
|
||||
)
|
||||
|
||||
// ErrorComponents represents the error response fields
|
||||
// that will be deserialized from an xml error response body
|
||||
type ErrorComponents struct {
|
||||
Code string
|
||||
Message string
|
||||
RequestID string
|
||||
}
|
||||
|
||||
// GetErrorResponseComponents returns the error fields from an xml error response body
|
||||
func GetErrorResponseComponents(r io.Reader, noErrorWrapping bool) (ErrorComponents, error) {
|
||||
if noErrorWrapping {
|
||||
var errResponse noWrappedErrorResponse
|
||||
if err := xml.NewDecoder(r).Decode(&errResponse); err != nil && err != io.EOF {
|
||||
return ErrorComponents{}, fmt.Errorf("error while deserializing xml error response: %w", err)
|
||||
}
|
||||
return ErrorComponents{
|
||||
Code: errResponse.Code,
|
||||
Message: errResponse.Message,
|
||||
RequestID: errResponse.RequestID,
|
||||
}, nil
|
||||
}
|
||||
|
||||
var errResponse wrappedErrorResponse
|
||||
if err := xml.NewDecoder(r).Decode(&errResponse); err != nil && err != io.EOF {
|
||||
return ErrorComponents{}, fmt.Errorf("error while deserializing xml error response: %w", err)
|
||||
}
|
||||
return ErrorComponents{
|
||||
Code: errResponse.Code,
|
||||
Message: errResponse.Message,
|
||||
RequestID: errResponse.RequestID,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// noWrappedErrorResponse represents the error response body with
|
||||
// no internal <Error></Error wrapping
|
||||
type noWrappedErrorResponse struct {
|
||||
Code string `xml:"Code"`
|
||||
Message string `xml:"Message"`
|
||||
RequestID string `xml:"RequestId"`
|
||||
}
|
||||
|
||||
// wrappedErrorResponse represents the error response body
|
||||
// wrapped within <Error>...</Error>
|
||||
type wrappedErrorResponse struct {
|
||||
Code string `xml:"Error>Code"`
|
||||
Message string `xml:"Error>Message"`
|
||||
RequestID string `xml:"RequestId"`
|
||||
}
|
51
vendor/github.com/aws/aws-sdk-go-v2/aws/ratelimit/token_bucket.go
generated
vendored
Normal file
@ -0,0 +1,51 @@
|
||||
package ratelimit
|
||||
|
||||
import (
|
||||
"sync"
|
||||
)
|
||||
|
||||
// TokenBucket provides a concurrency safe utility for adding and removing
|
||||
// tokens from the available token bucket.
|
||||
type TokenBucket struct {
|
||||
capacity uint
|
||||
maxCapacity uint
|
||||
mu sync.Mutex
|
||||
}
|
||||
|
||||
// NewTokenBucket returns an initialized TokenBucket with the capacity
|
||||
// specified.
|
||||
func NewTokenBucket(i uint) *TokenBucket {
|
||||
return &TokenBucket{
|
||||
capacity: i,
|
||||
maxCapacity: i,
|
||||
}
|
||||
}
|
||||
|
||||
// Retrieve attempts to reduce the available tokens by the amount requested. If
|
||||
// there are tokens available true will be returned along with the number of
|
||||
// available tokens remaining. If amount requested is larger than the available
|
||||
// capacity, false will be returned along with the available capacity. If the
|
||||
// amount is less than the available capacity
|
||||
func (t *TokenBucket) Retrieve(amount uint) (available uint, retrieved bool) {
|
||||
t.mu.Lock()
|
||||
defer t.mu.Unlock()
|
||||
|
||||
if amount > t.capacity {
|
||||
return t.capacity, false
|
||||
}
|
||||
|
||||
t.capacity -= amount
|
||||
return t.capacity, true
|
||||
}
|
||||
|
||||
// Refund returns the amount of tokens back to the available token bucket, up
|
||||
// to the initial capacity.
|
||||
func (t *TokenBucket) Refund(amount uint) {
|
||||
t.mu.Lock()
|
||||
defer t.mu.Unlock()
|
||||
|
||||
t.capacity += amount
|
||||
if t.capacity > t.maxCapacity {
|
||||
t.capacity = t.maxCapacity
|
||||
}
|
||||
}
|
82
vendor/github.com/aws/aws-sdk-go-v2/aws/ratelimit/token_rate_limit.go
generated
vendored
Normal file
@ -0,0 +1,82 @@
|
||||
package ratelimit
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type rateToken struct {
|
||||
tokenCost uint
|
||||
bucket *TokenBucket
|
||||
}
|
||||
|
||||
func (t rateToken) release() error {
|
||||
t.bucket.Refund(t.tokenCost)
|
||||
return nil
|
||||
}
|
||||
|
||||
// TokenRateLimit provides a Token Bucket RateLimiter implementation
|
||||
// that limits the overall number of retry attempts that can be made across
|
||||
// operation invocations.
|
||||
type TokenRateLimit struct {
|
||||
bucket *TokenBucket
|
||||
}
|
||||
|
||||
// NewTokenRateLimit returns an TokenRateLimit with default values.
|
||||
// Functional options can configure the retry rate limiter.
|
||||
func NewTokenRateLimit(tokens uint) *TokenRateLimit {
|
||||
return &TokenRateLimit{
|
||||
bucket: NewTokenBucket(tokens),
|
||||
}
|
||||
}
|
||||
|
||||
func isTimeoutError(error) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
type canceledError struct {
|
||||
Err error
|
||||
}
|
||||
|
||||
func (c canceledError) CanceledError() bool { return true }
|
||||
func (c canceledError) Unwrap() error { return c.Err }
|
||||
func (c canceledError) Error() string {
|
||||
return fmt.Sprintf("canceled, %v", c.Err)
|
||||
}
|
||||
|
||||
// GetToken may cause a available pool of retry quota to be
|
||||
// decremented. Will return an error if the decremented value can not be
|
||||
// reduced from the retry quota.
|
||||
func (l *TokenRateLimit) GetToken(ctx context.Context, cost uint) (func() error, error) {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return nil, canceledError{Err: ctx.Err()}
|
||||
default:
|
||||
}
|
||||
if avail, ok := l.bucket.Retrieve(cost); !ok {
|
||||
return nil, QuotaExceededError{Available: avail, Requested: cost}
|
||||
}
|
||||
|
||||
return rateToken{
|
||||
tokenCost: cost,
|
||||
bucket: l.bucket,
|
||||
}.release, nil
|
||||
}
|
||||
|
||||
// AddTokens increments the token bucket by a fixed amount.
|
||||
func (l *TokenRateLimit) AddTokens(v uint) error {
|
||||
l.bucket.Refund(v)
|
||||
return nil
|
||||
}
|
||||
|
||||
// QuotaExceededError provides the SDK error when the retries for a given
|
||||
// token bucket have been exhausted.
|
||||
type QuotaExceededError struct {
|
||||
Available uint
|
||||
Requested uint
|
||||
}
|
||||
|
||||
func (e QuotaExceededError) Error() string {
|
||||
return fmt.Sprintf("retry quota exceeded, %d available, %d requested",
|
||||
e.Available, e.Requested)
|
||||
}
|
25
vendor/github.com/aws/aws-sdk-go-v2/aws/request.go
generated
vendored
Normal file
@ -0,0 +1,25 @@
|
||||
package aws
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// TODO remove replace with smithy.CanceledError
|
||||
|
||||
// RequestCanceledError is the error that will be returned by an API request
|
||||
// that was canceled. Requests given a Context may return this error when
|
||||
// canceled.
|
||||
type RequestCanceledError struct {
|
||||
Err error
|
||||
}
|
||||
|
||||
// CanceledError returns true to satisfy interfaces checking for canceled errors.
|
||||
func (*RequestCanceledError) CanceledError() bool { return true }
|
||||
|
||||
// Unwrap returns the underlying error, if there was one.
|
||||
func (e *RequestCanceledError) Unwrap() error {
|
||||
return e.Err
|
||||
}
|
||||
func (e *RequestCanceledError) Error() string {
|
||||
return fmt.Sprintf("request canceled, %v", e.Err)
|
||||
}
|
80
vendor/github.com/aws/aws-sdk-go-v2/aws/retry/doc.go
generated
vendored
Normal file
@ -0,0 +1,80 @@
|
||||
// Package retry provides interfaces and implementations for SDK request retry behavior.
|
||||
//
|
||||
// Retryer Interface and Implementations
|
||||
//
|
||||
// This packages defines Retryer interface that is used to either implement custom retry behavior
|
||||
// or to extend the existing retry implementations provided by the SDK. This packages provides a single
|
||||
// retry implementations: Standard.
|
||||
//
|
||||
// Standard
|
||||
//
|
||||
// Standard is the default retryer implementation used by service clients. The standard retryer is a rate limited
|
||||
// retryer that has a configurable max attempts to limit the number of retry attempts when a retryable error occurs.
|
||||
// In addition, the retryer uses a configurable token bucket to rate limit the retry attempts across the client,
|
||||
// and uses an additional delay policy to limit the time between a requests subsequent attempts.
|
||||
//
|
||||
// By default the standard retryer uses the DefaultRetryables slice of IsErrorRetryable types to determine whether
|
||||
// a given error is retryable. By default this list of retryables includes the following:
|
||||
// - Retrying errors that implement the RetryableError method, and return true.
|
||||
// - Connection Errors
|
||||
// - Errors that implement a ConnectionError, Temporary, or Timeout method that return true.
|
||||
// - Connection Reset Errors.
|
||||
// - net.OpErr types that are dialing errors or are temporary.
|
||||
// - HTTP Status Codes: 500, 502, 503, and 504.
|
||||
// - API Error Codes
|
||||
// - RequestTimeout, RequestTimeoutException
|
||||
// - Throttling, ThrottlingException, ThrottledException, RequestThrottledException, TooManyRequestsException,
|
||||
// RequestThrottled, SlowDown, EC2ThrottledException
|
||||
// - ProvisionedThroughputExceededException, RequestLimitExceeded, BandwidthLimitExceeded, LimitExceededException
|
||||
// - TransactionInProgressException, PriorRequestNotComplete
|
||||
//
|
||||
// The standard retryer will not retry a request in the event if the context associated with the request
|
||||
// has been cancelled. Applications must handle this case explicitly if they wish to retry with a different context
|
||||
// value.
|
||||
//
|
||||
// You can configure the standard retryer implementation to fit your applications by constructing a standard retryer
|
||||
// using the NewStandard function, and providing one more functional arguments that mutate the StandardOptions
|
||||
// structure. StandardOptions provides the ability to modify the token bucket rate limiter, retryable error conditions,
|
||||
// and the retry delay policy.
|
||||
//
|
||||
// For example to modify the default retry attempts for the standard retryer:
|
||||
//
|
||||
// // configure the custom retryer
|
||||
// customRetry := retry.NewStandard(func(o *retry.StandardOptions) {
|
||||
// o.MaxAttempts = 5
|
||||
// })
|
||||
//
|
||||
// // create a service client with the retryer
|
||||
// s3.NewFromConfig(cfg, func(o *s3.Options) {
|
||||
// o.Retryer = customRetry
|
||||
// })
|
||||
//
|
||||
// Utilities
|
||||
//
|
||||
// A number of package functions have been provided to easily wrap retryer implementations in an implementation agnostic
|
||||
// way. These are:
|
||||
//
|
||||
// AddWithErrorCodes - Provides the ability to add additional API error codes that should be considered retryable
|
||||
// in addition to those considered retryable by the provided retryer.
|
||||
//
|
||||
// AddWithMaxAttempts - Provides the ability to set the max number of attempts for retrying a request by wrapping
|
||||
// a retryer implementation.
|
||||
//
|
||||
// AddWithMaxBackoffDelay - Provides the ability to set the max back off delay that can occur before retrying a
|
||||
// request by wrapping a retryer implementation.
|
||||
//
|
||||
// The following package functions have been provided to easily satisfy different retry interfaces to further customize
|
||||
// a given retryer's behavior:
|
||||
//
|
||||
// BackoffDelayerFunc - Can be used to wrap a function to satisfy the BackoffDelayer interface. For example,
|
||||
// you can use this method to easily create custom back off policies to be used with the
|
||||
// standard retryer.
|
||||
//
|
||||
// IsErrorRetryableFunc - Can be used to wrap a function to satisfy the IsErrorRetryable interface. For example,
|
||||
// this can be used to extend the standard retryer to add additional logic ot determine if a
|
||||
// error should be retried.
|
||||
//
|
||||
// IsErrorTimeoutFunc - Can be used to wrap a function to satisfy IsErrorTimeout interface. For example,
|
||||
// this can be used to extend the standard retryer to add additional logic to determine if an
|
||||
// error should be considered a timeout.
|
||||
package retry
|
20
vendor/github.com/aws/aws-sdk-go-v2/aws/retry/errors.go
generated
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
package retry
|
||||
|
||||
import "fmt"
|
||||
|
||||
// MaxAttemptsError provides the error when the maximum number of attempts have
|
||||
// been exceeded.
|
||||
type MaxAttemptsError struct {
|
||||
Attempt int
|
||||
Err error
|
||||
}
|
||||
|
||||
func (e *MaxAttemptsError) Error() string {
|
||||
return fmt.Sprintf("exceeded maximum number of attempts, %d, %v", e.Attempt, e.Err)
|
||||
}
|
||||
|
||||
// Unwrap returns the nested error causing the max attempts error. Provides the
|
||||
// implementation for errors.Is and errors.As to unwrap nested errors.
|
||||
func (e *MaxAttemptsError) Unwrap() error {
|
||||
return e.Err
|
||||
}
|
49
vendor/github.com/aws/aws-sdk-go-v2/aws/retry/jitter_backoff.go
generated
vendored
Normal file
@ -0,0 +1,49 @@
|
||||
package retry
|
||||
|
||||
import (
|
||||
"math"
|
||||
"time"
|
||||
|
||||
"github.com/aws/aws-sdk-go-v2/internal/rand"
|
||||
"github.com/aws/aws-sdk-go-v2/internal/timeconv"
|
||||
)
|
||||
|
||||
// ExponentialJitterBackoff provides backoff delays with jitter based on the
|
||||
// number of attempts.
|
||||
type ExponentialJitterBackoff struct {
|
||||
maxBackoff time.Duration
|
||||
// precomputed number of attempts needed to reach max backoff.
|
||||
maxBackoffAttempts float64
|
||||
|
||||
randFloat64 func() (float64, error)
|
||||
}
|
||||
|
||||
// NewExponentialJitterBackoff returns an ExponentialJitterBackoff configured
|
||||
// for the max backoff.
|
||||
func NewExponentialJitterBackoff(maxBackoff time.Duration) *ExponentialJitterBackoff {
|
||||
return &ExponentialJitterBackoff{
|
||||
maxBackoff: maxBackoff,
|
||||
maxBackoffAttempts: math.Log2(
|
||||
float64(maxBackoff) / float64(time.Second)),
|
||||
randFloat64: rand.CryptoRandFloat64,
|
||||
}
|
||||
}
|
||||
|
||||
// BackoffDelay returns the duration to wait before the next attempt should be
|
||||
// made. Returns an error if unable get a duration.
|
||||
func (j *ExponentialJitterBackoff) BackoffDelay(attempt int, err error) (time.Duration, error) {
|
||||
if attempt > int(j.maxBackoffAttempts) {
|
||||
return j.maxBackoff, nil
|
||||
}
|
||||
|
||||
b, err := j.randFloat64()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
// [0.0, 1.0) * 2 ^ attempts
|
||||
ri := int64(1 << uint64(attempt))
|
||||
delaySeconds := b * float64(ri)
|
||||
|
||||
return timeconv.FloatSecondsDur(delaySeconds), nil
|
||||
}
|
52
vendor/github.com/aws/aws-sdk-go-v2/aws/retry/metadata.go
generated
vendored
Normal file
@ -0,0 +1,52 @@
|
||||
package retry
|
||||
|
||||
import (
|
||||
awsmiddle "github.com/aws/aws-sdk-go-v2/aws/middleware"
|
||||
"github.com/aws/smithy-go/middleware"
|
||||
)
|
||||
|
||||
// attemptResultsKey is a metadata accessor key to retrieve metadata
|
||||
// for all request attempts.
|
||||
type attemptResultsKey struct {
|
||||
}
|
||||
|
||||
// GetAttemptResults retrieves attempts results from middleware metadata.
|
||||
func GetAttemptResults(metadata middleware.Metadata) (AttemptResults, bool) {
|
||||
m, ok := metadata.Get(attemptResultsKey{}).(AttemptResults)
|
||||
return m, ok
|
||||
}
|
||||
|
||||
// AttemptResults represents struct containing metadata returned by all request attempts.
|
||||
type AttemptResults struct {
|
||||
|
||||
// Results is a slice consisting attempt result from all request attempts.
|
||||
// Results are stored in order request attempt is made.
|
||||
Results []AttemptResult
|
||||
}
|
||||
|
||||
// AttemptResult represents attempt result returned by a single request attempt.
|
||||
type AttemptResult struct {
|
||||
|
||||
// Err is the error if received for the request attempt.
|
||||
Err error
|
||||
|
||||
// Retryable denotes if request may be retried. This states if an
|
||||
// error is considered retryable.
|
||||
Retryable bool
|
||||
|
||||
// Retried indicates if this request was retried.
|
||||
Retried bool
|
||||
|
||||
// ResponseMetadata is any existing metadata passed via the response middlewares.
|
||||
ResponseMetadata middleware.Metadata
|
||||
}
|
||||
|
||||
// addAttemptResults adds attempt results to middleware metadata
|
||||
func addAttemptResults(metadata *middleware.Metadata, v AttemptResults) {
|
||||
metadata.Set(attemptResultsKey{}, v)
|
||||
}
|
||||
|
||||
// GetRawResponse returns raw response recorded for the attempt result
|
||||
func (a AttemptResult) GetRawResponse() interface{} {
|
||||
return awsmiddle.GetRawResponse(a.ResponseMetadata)
|
||||
}
|
277
vendor/github.com/aws/aws-sdk-go-v2/aws/retry/middleware.go
generated
vendored
Normal file
@ -0,0 +1,277 @@
|
||||
package retry
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/aws/aws-sdk-go-v2/aws"
|
||||
awsmiddle "github.com/aws/aws-sdk-go-v2/aws/middleware"
|
||||
"github.com/aws/aws-sdk-go-v2/internal/sdk"
|
||||
"github.com/aws/smithy-go/logging"
|
||||
"github.com/aws/smithy-go/middleware"
|
||||
smithymiddle "github.com/aws/smithy-go/middleware"
|
||||
"github.com/aws/smithy-go/transport/http"
|
||||
)
|
||||
|
||||
// RequestCloner is a function that can take an input request type and clone the request
|
||||
// for use in a subsequent retry attempt
|
||||
type RequestCloner func(interface{}) interface{}
|
||||
|
||||
type retryMetadata struct {
|
||||
AttemptNum int
|
||||
AttemptTime time.Time
|
||||
MaxAttempts int
|
||||
AttemptClockSkew time.Duration
|
||||
}
|
||||
|
||||
// Attempt is a Smithy FinalizeMiddleware that handles retry attempts using the provided
|
||||
// Retryer implementation
|
||||
type Attempt struct {
|
||||
// Enable the logging of retry attempts performed by the SDK.
|
||||
// This will include logging retry attempts, unretryable errors, and when max attempts are reached.
|
||||
LogAttempts bool
|
||||
|
||||
retryer aws.Retryer
|
||||
requestCloner RequestCloner
|
||||
}
|
||||
|
||||
// NewAttemptMiddleware returns a new Attempt retry middleware.
|
||||
func NewAttemptMiddleware(retryer aws.Retryer, requestCloner RequestCloner, optFns ...func(*Attempt)) *Attempt {
|
||||
m := &Attempt{retryer: retryer, requestCloner: requestCloner}
|
||||
for _, fn := range optFns {
|
||||
fn(m)
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
// ID returns the middleware identifier
|
||||
func (r *Attempt) ID() string {
|
||||
return "Retry"
|
||||
}
|
||||
|
||||
func (r Attempt) logf(logger logging.Logger, classification logging.Classification, format string, v ...interface{}) {
|
||||
if !r.LogAttempts {
|
||||
return
|
||||
}
|
||||
logger.Logf(classification, format, v...)
|
||||
}
|
||||
|
||||
// HandleFinalize utilizes the provider Retryer implementation to attempt retries over the next handler
|
||||
func (r Attempt) HandleFinalize(ctx context.Context, in smithymiddle.FinalizeInput, next smithymiddle.FinalizeHandler) (
|
||||
out smithymiddle.FinalizeOutput, metadata smithymiddle.Metadata, err error,
|
||||
) {
|
||||
var attemptNum int
|
||||
var attemptClockSkew time.Duration
|
||||
var attemptResults AttemptResults
|
||||
|
||||
maxAttempts := r.retryer.MaxAttempts()
|
||||
|
||||
for {
|
||||
attemptNum++
|
||||
attemptInput := in
|
||||
attemptInput.Request = r.requestCloner(attemptInput.Request)
|
||||
|
||||
attemptCtx := setRetryMetadata(ctx, retryMetadata{
|
||||
AttemptNum: attemptNum,
|
||||
AttemptTime: sdk.NowTime().UTC(),
|
||||
MaxAttempts: maxAttempts,
|
||||
AttemptClockSkew: attemptClockSkew,
|
||||
})
|
||||
|
||||
var attemptResult AttemptResult
|
||||
|
||||
out, attemptResult, err = r.handleAttempt(attemptCtx, attemptInput, next)
|
||||
|
||||
var ok bool
|
||||
attemptClockSkew, ok = awsmiddle.GetAttemptSkew(attemptResult.ResponseMetadata)
|
||||
if !ok {
|
||||
attemptClockSkew = 0
|
||||
}
|
||||
|
||||
shouldRetry := attemptResult.Retried
|
||||
|
||||
// add attempt metadata to list of all attempt metadata
|
||||
attemptResults.Results = append(attemptResults.Results, attemptResult)
|
||||
|
||||
if !shouldRetry {
|
||||
// Ensure the last response's metadata is used as the bases for result
|
||||
// metadata returned by the stack.
|
||||
metadata = attemptResult.ResponseMetadata.Clone()
|
||||
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
addAttemptResults(&metadata, attemptResults)
|
||||
return out, metadata, err
|
||||
}
|
||||
|
||||
// handleAttempt handles an individual request attempt.
|
||||
func (r Attempt) handleAttempt(ctx context.Context, in smithymiddle.FinalizeInput, next smithymiddle.FinalizeHandler) (
|
||||
out smithymiddle.FinalizeOutput, attemptResult AttemptResult, err error,
|
||||
) {
|
||||
defer func() {
|
||||
attemptResult.Err = err
|
||||
}()
|
||||
|
||||
relRetryToken := r.retryer.GetInitialToken()
|
||||
logger := smithymiddle.GetLogger(ctx)
|
||||
service, operation := awsmiddle.GetServiceID(ctx), awsmiddle.GetOperationName(ctx)
|
||||
|
||||
retryMetadata, _ := getRetryMetadata(ctx)
|
||||
attemptNum := retryMetadata.AttemptNum
|
||||
maxAttempts := retryMetadata.MaxAttempts
|
||||
|
||||
if attemptNum > 1 {
|
||||
if rewindable, ok := in.Request.(interface{ RewindStream() error }); ok {
|
||||
if rewindErr := rewindable.RewindStream(); rewindErr != nil {
|
||||
err = fmt.Errorf("failed to rewind transport stream for retry, %w", rewindErr)
|
||||
return out, attemptResult, err
|
||||
}
|
||||
}
|
||||
|
||||
r.logf(logger, logging.Debug, "retrying request %s/%s, attempt %d", service, operation, attemptNum)
|
||||
}
|
||||
|
||||
var metadata smithymiddle.Metadata
|
||||
out, metadata, err = next.HandleFinalize(ctx, in)
|
||||
attemptResult.ResponseMetadata = metadata
|
||||
|
||||
if releaseError := relRetryToken(err); releaseError != nil && err != nil {
|
||||
err = fmt.Errorf("failed to release token after request error, %w", err)
|
||||
return out, attemptResult, err
|
||||
}
|
||||
|
||||
if err == nil {
|
||||
return out, attemptResult, err
|
||||
}
|
||||
|
||||
retryable := r.retryer.IsErrorRetryable(err)
|
||||
if !retryable {
|
||||
r.logf(logger, logging.Debug, "request failed with unretryable error %v", err)
|
||||
return out, attemptResult, err
|
||||
}
|
||||
|
||||
// set retryable to true
|
||||
attemptResult.Retryable = true
|
||||
|
||||
if maxAttempts > 0 && attemptNum >= maxAttempts {
|
||||
r.logf(logger, logging.Debug, "max retry attempts exhausted, max %d", maxAttempts)
|
||||
err = &MaxAttemptsError{
|
||||
Attempt: attemptNum,
|
||||
Err: err,
|
||||
}
|
||||
return out, attemptResult, err
|
||||
}
|
||||
|
||||
relRetryToken, reqErr := r.retryer.GetRetryToken(ctx, err)
|
||||
if reqErr != nil {
|
||||
return out, attemptResult, reqErr
|
||||
}
|
||||
|
||||
retryDelay, reqErr := r.retryer.RetryDelay(attemptNum, err)
|
||||
if reqErr != nil {
|
||||
return out, attemptResult, reqErr
|
||||
}
|
||||
|
||||
if reqErr = sdk.SleepWithContext(ctx, retryDelay); reqErr != nil {
|
||||
err = &aws.RequestCanceledError{Err: reqErr}
|
||||
return out, attemptResult, err
|
||||
}
|
||||
|
||||
attemptResult.Retried = true
|
||||
|
||||
return out, attemptResult, err
|
||||
}
|
||||
|
||||
// MetricsHeader attaches SDK request metric header for retries to the transport
|
||||
type MetricsHeader struct{}
|
||||
|
||||
// ID returns the middleware identifier
|
||||
func (r *MetricsHeader) ID() string {
|
||||
return "RetryMetricsHeader"
|
||||
}
|
||||
|
||||
// HandleFinalize attaches the sdk request metric header to the transport layer
|
||||
func (r MetricsHeader) HandleFinalize(ctx context.Context, in smithymiddle.FinalizeInput, next smithymiddle.FinalizeHandler) (
|
||||
out smithymiddle.FinalizeOutput, metadata smithymiddle.Metadata, err error,
|
||||
) {
|
||||
retryMetadata, _ := getRetryMetadata(ctx)
|
||||
|
||||
const retryMetricHeader = "Amz-Sdk-Request"
|
||||
var parts []string
|
||||
|
||||
parts = append(parts, "attempt="+strconv.Itoa(retryMetadata.AttemptNum))
|
||||
if retryMetadata.MaxAttempts != 0 {
|
||||
parts = append(parts, "max="+strconv.Itoa(retryMetadata.MaxAttempts))
|
||||
}
|
||||
|
||||
var ttl time.Time
|
||||
if deadline, ok := ctx.Deadline(); ok {
|
||||
ttl = deadline
|
||||
}
|
||||
|
||||
// Only append the TTL if it can be determined.
|
||||
if !ttl.IsZero() && retryMetadata.AttemptClockSkew > 0 {
|
||||
const unixTimeFormat = "20060102T150405Z"
|
||||
ttl = ttl.Add(retryMetadata.AttemptClockSkew)
|
||||
parts = append(parts, "ttl="+ttl.Format(unixTimeFormat))
|
||||
}
|
||||
|
||||
switch req := in.Request.(type) {
|
||||
case *http.Request:
|
||||
req.Header[retryMetricHeader] = append(req.Header[retryMetricHeader][:0], strings.Join(parts, "; "))
|
||||
default:
|
||||
return out, metadata, fmt.Errorf("unknown transport type %T", req)
|
||||
}
|
||||
|
||||
return next.HandleFinalize(ctx, in)
|
||||
}
|
||||
|
||||
type retryMetadataKey struct{}
|
||||
|
||||
// getRetryMetadata retrieves retryMetadata from the context and a bool
|
||||
// indicating if it was set.
|
||||
//
|
||||
// Scoped to stack values. Use github.com/aws/smithy-go/middleware#ClearStackValues
|
||||
// to clear all stack values.
|
||||
func getRetryMetadata(ctx context.Context) (metadata retryMetadata, ok bool) {
|
||||
metadata, ok = middleware.GetStackValue(ctx, retryMetadataKey{}).(retryMetadata)
|
||||
return metadata, ok
|
||||
}
|
||||
|
||||
// setRetryMetadata sets the retryMetadata on the context.
|
||||
//
|
||||
// Scoped to stack values. Use github.com/aws/smithy-go/middleware#ClearStackValues
|
||||
// to clear all stack values.
|
||||
func setRetryMetadata(ctx context.Context, metadata retryMetadata) context.Context {
|
||||
return middleware.WithStackValue(ctx, retryMetadataKey{}, metadata)
|
||||
}
|
||||
|
||||
// AddRetryMiddlewaresOptions is the set of options that can be passed to AddRetryMiddlewares for configuring retry
|
||||
// associated middleware.
|
||||
type AddRetryMiddlewaresOptions struct {
|
||||
Retryer aws.Retryer
|
||||
|
||||
// Enable the logging of retry attempts performed by the SDK.
|
||||
// This will include logging retry attempts, unretryable errors, and when max attempts are reached.
|
||||
LogRetryAttempts bool
|
||||
}
|
||||
|
||||
// AddRetryMiddlewares adds retry middleware to operation middleware stack
|
||||
func AddRetryMiddlewares(stack *smithymiddle.Stack, options AddRetryMiddlewaresOptions) error {
|
||||
attempt := NewAttemptMiddleware(options.Retryer, http.RequestCloner, func(middleware *Attempt) {
|
||||
middleware.LogAttempts = options.LogRetryAttempts
|
||||
})
|
||||
|
||||
if err := stack.Finalize.Add(attempt, smithymiddle.After); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := stack.Finalize.Add(&MetricsHeader{}, smithymiddle.After); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
72
vendor/github.com/aws/aws-sdk-go-v2/aws/retry/retry.go
generated
vendored
Normal file
@ -0,0 +1,72 @@
|
||||
package retry
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/aws/aws-sdk-go-v2/aws"
|
||||
)
|
||||
|
||||
// AddWithErrorCodes returns a Retryer with additional error codes considered
|
||||
// for determining if the error should be retried.
|
||||
func AddWithErrorCodes(r aws.Retryer, codes ...string) aws.Retryer {
|
||||
retryable := &RetryableErrorCode{
|
||||
Codes: map[string]struct{}{},
|
||||
}
|
||||
for _, c := range codes {
|
||||
retryable.Codes[c] = struct{}{}
|
||||
}
|
||||
|
||||
return &withIsErrorRetryable{
|
||||
Retryer: r,
|
||||
Retryable: retryable,
|
||||
}
|
||||
}
|
||||
|
||||
type withIsErrorRetryable struct {
|
||||
aws.Retryer
|
||||
Retryable IsErrorRetryable
|
||||
}
|
||||
|
||||
func (r *withIsErrorRetryable) IsErrorRetryable(err error) bool {
|
||||
if v := r.Retryable.IsErrorRetryable(err); v != aws.UnknownTernary {
|
||||
return v.Bool()
|
||||
}
|
||||
return r.Retryer.IsErrorRetryable(err)
|
||||
}
|
||||
|
||||
// AddWithMaxAttempts returns a Retryer with MaxAttempts set to the value
|
||||
// specified.
|
||||
func AddWithMaxAttempts(r aws.Retryer, max int) aws.Retryer {
|
||||
return &withMaxAttempts{
|
||||
Retryer: r,
|
||||
Max: max,
|
||||
}
|
||||
}
|
||||
|
||||
type withMaxAttempts struct {
|
||||
aws.Retryer
|
||||
Max int
|
||||
}
|
||||
|
||||
func (w *withMaxAttempts) MaxAttempts() int {
|
||||
return w.Max
|
||||
}
|
||||
|
||||
// AddWithMaxBackoffDelay returns a retryer wrapping the passed in retryer
|
||||
// overriding the RetryDelay behavior for a alternate minimum initial backoff
|
||||
// delay.
|
||||
func AddWithMaxBackoffDelay(r aws.Retryer, delay time.Duration) aws.Retryer {
|
||||
return &withMaxBackoffDelay{
|
||||
Retryer: r,
|
||||
backoff: NewExponentialJitterBackoff(delay),
|
||||
}
|
||||
}
|
||||
|
||||
type withMaxBackoffDelay struct {
|
||||
aws.Retryer
|
||||
backoff *ExponentialJitterBackoff
|
||||
}
|
||||
|
||||
func (r *withMaxBackoffDelay) RetryDelay(attempt int, err error) (time.Duration, error) {
|
||||
return r.backoff.BackoffDelay(attempt, err)
|
||||
}
|
186
vendor/github.com/aws/aws-sdk-go-v2/aws/retry/retryable_error.go
generated
vendored
Normal file
@ -0,0 +1,186 @@
|
||||
package retry
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"github.com/aws/aws-sdk-go-v2/aws"
|
||||
)
|
||||
|
||||
// IsErrorRetryable provides the interface of an implementation to determine if
|
||||
// a error as the result of an operation is retryable.
|
||||
type IsErrorRetryable interface {
|
||||
IsErrorRetryable(error) aws.Ternary
|
||||
}
|
||||
|
||||
// IsErrorRetryables is a collection of checks to determine of the error is
|
||||
// retryable. Iterates through the checks and returns the state of retryable
|
||||
// if any check returns something other than unknown.
|
||||
type IsErrorRetryables []IsErrorRetryable
|
||||
|
||||
// IsErrorRetryable returns if the error is retryable if any of the checks in
|
||||
// the list return a value other than unknown.
|
||||
func (r IsErrorRetryables) IsErrorRetryable(err error) aws.Ternary {
|
||||
for _, re := range r {
|
||||
if v := re.IsErrorRetryable(err); v != aws.UnknownTernary {
|
||||
return v
|
||||
}
|
||||
}
|
||||
return aws.UnknownTernary
|
||||
}
|
||||
|
||||
// IsErrorRetryableFunc wraps a function with the IsErrorRetryable interface.
|
||||
type IsErrorRetryableFunc func(error) aws.Ternary
|
||||
|
||||
// IsErrorRetryable returns if the error is retryable.
|
||||
func (fn IsErrorRetryableFunc) IsErrorRetryable(err error) aws.Ternary {
|
||||
return fn(err)
|
||||
}
|
||||
|
||||
// RetryableError is an IsErrorRetryable implementation which uses the
|
||||
// optional interface Retryable on the error value to determine if the error is
|
||||
// retryable.
|
||||
type RetryableError struct{}
|
||||
|
||||
// IsErrorRetryable returns if the error is retryable if it satisfies the
|
||||
// Retryable interface, and returns if the attempt should be retried.
|
||||
func (RetryableError) IsErrorRetryable(err error) aws.Ternary {
|
||||
var v interface{ RetryableError() bool }
|
||||
|
||||
if !errors.As(err, &v) {
|
||||
return aws.UnknownTernary
|
||||
}
|
||||
|
||||
return aws.BoolTernary(v.RetryableError())
|
||||
}
|
||||
|
||||
// NoRetryCanceledError detects if the error was an request canceled error and
|
||||
// returns if so.
|
||||
type NoRetryCanceledError struct{}
|
||||
|
||||
// IsErrorRetryable returns the error is not retryable if the request was
|
||||
// canceled.
|
||||
func (NoRetryCanceledError) IsErrorRetryable(err error) aws.Ternary {
|
||||
var v interface{ CanceledError() bool }
|
||||
|
||||
if !errors.As(err, &v) {
|
||||
return aws.UnknownTernary
|
||||
}
|
||||
|
||||
if v.CanceledError() {
|
||||
return aws.FalseTernary
|
||||
}
|
||||
return aws.UnknownTernary
|
||||
}
|
||||
|
||||
// RetryableConnectionError determines if the underlying error is an HTTP
|
||||
// connection and returns if it should be retried.
|
||||
//
|
||||
// Includes errors such as connection reset, connection refused, net dial,
|
||||
// temporary, and timeout errors.
|
||||
type RetryableConnectionError struct{}
|
||||
|
||||
// IsErrorRetryable returns if the error is caused by and HTTP connection
|
||||
// error, and should be retried.
|
||||
func (r RetryableConnectionError) IsErrorRetryable(err error) aws.Ternary {
|
||||
if err == nil {
|
||||
return aws.UnknownTernary
|
||||
}
|
||||
var retryable bool
|
||||
|
||||
var conErr interface{ ConnectionError() bool }
|
||||
var tempErr interface{ Temporary() bool }
|
||||
var timeoutErr interface{ Timeout() bool }
|
||||
var urlErr *url.Error
|
||||
var netOpErr *net.OpError
|
||||
|
||||
switch {
|
||||
case errors.As(err, &conErr) && conErr.ConnectionError():
|
||||
retryable = true
|
||||
|
||||
case strings.Contains(err.Error(), "connection reset"):
|
||||
retryable = true
|
||||
|
||||
case errors.As(err, &urlErr):
|
||||
// Refused connections should be retried as the service may not yet be
|
||||
// running on the port. Go TCP dial considers refused connections as
|
||||
// not temporary.
|
||||
if strings.Contains(urlErr.Error(), "connection refused") {
|
||||
retryable = true
|
||||
} else {
|
||||
return r.IsErrorRetryable(errors.Unwrap(urlErr))
|
||||
}
|
||||
|
||||
case errors.As(err, &netOpErr):
|
||||
// Network dial, or temporary network errors are always retryable.
|
||||
if strings.EqualFold(netOpErr.Op, "dial") || netOpErr.Temporary() {
|
||||
retryable = true
|
||||
} else {
|
||||
return r.IsErrorRetryable(errors.Unwrap(netOpErr))
|
||||
}
|
||||
|
||||
case errors.As(err, &tempErr) && tempErr.Temporary():
|
||||
// Fallback to the generic temporary check, with temporary errors
|
||||
// retryable.
|
||||
retryable = true
|
||||
|
||||
case errors.As(err, &timeoutErr) && timeoutErr.Timeout():
|
||||
// Fallback to the generic timeout check, with timeout errors
|
||||
// retryable.
|
||||
retryable = true
|
||||
|
||||
default:
|
||||
return aws.UnknownTernary
|
||||
}
|
||||
|
||||
return aws.BoolTernary(retryable)
|
||||
|
||||
}
|
||||
|
||||
// RetryableHTTPStatusCode provides a IsErrorRetryable based on HTTP status
|
||||
// codes.
|
||||
type RetryableHTTPStatusCode struct {
|
||||
Codes map[int]struct{}
|
||||
}
|
||||
|
||||
// IsErrorRetryable return if the passed in error is retryable based on the
|
||||
// HTTP status code.
|
||||
func (r RetryableHTTPStatusCode) IsErrorRetryable(err error) aws.Ternary {
|
||||
var v interface{ HTTPStatusCode() int }
|
||||
|
||||
if !errors.As(err, &v) {
|
||||
return aws.UnknownTernary
|
||||
}
|
||||
|
||||
_, ok := r.Codes[v.HTTPStatusCode()]
|
||||
if !ok {
|
||||
return aws.UnknownTernary
|
||||
}
|
||||
|
||||
return aws.TrueTernary
|
||||
}
|
||||
|
||||
// RetryableErrorCode determines if an attempt should be retried based on the
|
||||
// API error code.
|
||||
type RetryableErrorCode struct {
|
||||
Codes map[string]struct{}
|
||||
}
|
||||
|
||||
// IsErrorRetryable return if the error is retryable based on the error codes.
|
||||
// Returns unknown if the error doesn't have a code or it is unknown.
|
||||
func (r RetryableErrorCode) IsErrorRetryable(err error) aws.Ternary {
|
||||
var v interface{ ErrorCode() string }
|
||||
|
||||
if !errors.As(err, &v) {
|
||||
return aws.UnknownTernary
|
||||
}
|
||||
|
||||
_, ok := r.Codes[v.ErrorCode()]
|
||||
if !ok {
|
||||
return aws.UnknownTernary
|
||||
}
|
||||
|
||||
return aws.TrueTernary
|
||||
}
|
208
vendor/github.com/aws/aws-sdk-go-v2/aws/retry/standard.go
generated
vendored
Normal file
@ -0,0 +1,208 @@
|
||||
package retry
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/aws/aws-sdk-go-v2/aws/ratelimit"
|
||||
)
|
||||
|
||||
// BackoffDelayer provides the interface for determining the delay to before
|
||||
// another request attempt, that previously failed.
|
||||
type BackoffDelayer interface {
|
||||
BackoffDelay(attempt int, err error) (time.Duration, error)
|
||||
}
|
||||
|
||||
// BackoffDelayerFunc provides a wrapper around a function to determine the
|
||||
// backoff delay of an attempt retry.
|
||||
type BackoffDelayerFunc func(int, error) (time.Duration, error)
|
||||
|
||||
// BackoffDelay returns the delay before attempt to retry a request.
|
||||
func (fn BackoffDelayerFunc) BackoffDelay(attempt int, err error) (time.Duration, error) {
|
||||
return fn(attempt, err)
|
||||
}
|
||||
|
||||
const (
|
||||
// DefaultMaxAttempts is the maximum of attempts for an API request
|
||||
DefaultMaxAttempts int = 3
|
||||
|
||||
// DefaultMaxBackoff is the maximum back off delay between attempts
|
||||
DefaultMaxBackoff time.Duration = 20 * time.Second
|
||||
)
|
||||
|
||||
// Default retry token quota values.
|
||||
const (
|
||||
DefaultRetryRateTokens uint = 500
|
||||
DefaultRetryCost uint = 5
|
||||
DefaultRetryTimeoutCost uint = 10
|
||||
DefaultNoRetryIncrement uint = 1
|
||||
)
|
||||
|
||||
// DefaultRetryableHTTPStatusCodes is the default set of HTTP status codes the SDK
|
||||
// should consider as retryable errors.
|
||||
var DefaultRetryableHTTPStatusCodes = map[int]struct{}{
|
||||
500: {},
|
||||
502: {},
|
||||
503: {},
|
||||
504: {},
|
||||
}
|
||||
|
||||
// DefaultRetryableErrorCodes provides the set of API error codes that should
|
||||
// be retried.
|
||||
var DefaultRetryableErrorCodes = map[string]struct{}{
|
||||
"RequestTimeout": {},
|
||||
"RequestTimeoutException": {},
|
||||
|
||||
// Throttled status codes
|
||||
"Throttling": {},
|
||||
"ThrottlingException": {},
|
||||
"ThrottledException": {},
|
||||
"RequestThrottledException": {},
|
||||
"TooManyRequestsException": {},
|
||||
"ProvisionedThroughputExceededException": {},
|
||||
"TransactionInProgressException": {},
|
||||
"RequestLimitExceeded": {},
|
||||
"BandwidthLimitExceeded": {},
|
||||
"LimitExceededException": {},
|
||||
"RequestThrottled": {},
|
||||
"SlowDown": {},
|
||||
"PriorRequestNotComplete": {},
|
||||
"EC2ThrottledException": {},
|
||||
}
|
||||
|
||||
// DefaultRetryables provides the set of retryable checks that are used by
|
||||
// default.
|
||||
var DefaultRetryables = []IsErrorRetryable{
|
||||
NoRetryCanceledError{},
|
||||
RetryableError{},
|
||||
RetryableConnectionError{},
|
||||
RetryableHTTPStatusCode{
|
||||
Codes: DefaultRetryableHTTPStatusCodes,
|
||||
},
|
||||
RetryableErrorCode{
|
||||
Codes: DefaultRetryableErrorCodes,
|
||||
},
|
||||
}
|
||||
|
||||
// StandardOptions provides the functional options for configuring the standard
|
||||
// retryable, and delay behavior.
|
||||
type StandardOptions struct {
|
||||
MaxAttempts int
|
||||
MaxBackoff time.Duration
|
||||
Backoff BackoffDelayer
|
||||
|
||||
Retryables []IsErrorRetryable
|
||||
Timeouts []IsErrorTimeout
|
||||
|
||||
RateLimiter RateLimiter
|
||||
RetryCost uint
|
||||
RetryTimeoutCost uint
|
||||
NoRetryIncrement uint
|
||||
}
|
||||
|
||||
// RateLimiter provides the interface for limiting the rate of request retries
|
||||
// allowed by the retrier.
|
||||
type RateLimiter interface {
|
||||
GetToken(ctx context.Context, cost uint) (releaseToken func() error, err error)
|
||||
AddTokens(uint) error
|
||||
}
|
||||
|
||||
// Standard is the standard retry pattern for the SDK. It uses a set of
|
||||
// retryable checks to determine of the failed request should be retried, and
|
||||
// what retry delay should be used.
|
||||
type Standard struct {
|
||||
options StandardOptions
|
||||
|
||||
timeout IsErrorTimeout
|
||||
retryable IsErrorRetryable
|
||||
backoff BackoffDelayer
|
||||
}
|
||||
|
||||
// NewStandard initializes a standard retry behavior with defaults that can be
|
||||
// overridden via functional options.
|
||||
func NewStandard(fnOpts ...func(*StandardOptions)) *Standard {
|
||||
o := StandardOptions{
|
||||
MaxAttempts: DefaultMaxAttempts,
|
||||
MaxBackoff: DefaultMaxBackoff,
|
||||
Retryables: DefaultRetryables,
|
||||
|
||||
RateLimiter: ratelimit.NewTokenRateLimit(DefaultRetryRateTokens),
|
||||
RetryCost: DefaultRetryCost,
|
||||
RetryTimeoutCost: DefaultRetryTimeoutCost,
|
||||
NoRetryIncrement: DefaultNoRetryIncrement,
|
||||
}
|
||||
for _, fn := range fnOpts {
|
||||
fn(&o)
|
||||
}
|
||||
|
||||
backoff := o.Backoff
|
||||
if backoff == nil {
|
||||
backoff = NewExponentialJitterBackoff(o.MaxBackoff)
|
||||
}
|
||||
|
||||
rs := make([]IsErrorRetryable, len(o.Retryables))
|
||||
copy(rs, o.Retryables)
|
||||
|
||||
ts := make([]IsErrorTimeout, len(o.Timeouts))
|
||||
copy(ts, o.Timeouts)
|
||||
|
||||
return &Standard{
|
||||
options: o,
|
||||
backoff: backoff,
|
||||
retryable: IsErrorRetryables(rs),
|
||||
timeout: IsErrorTimeouts(ts),
|
||||
}
|
||||
}
|
||||
|
||||
// MaxAttempts returns the maximum number of attempts that can be made for a
|
||||
// request before failing.
|
||||
func (s *Standard) MaxAttempts() int {
|
||||
return s.options.MaxAttempts
|
||||
}
|
||||
|
||||
// IsErrorRetryable returns if the error is can be retried or not. Should not
|
||||
// consider the number of attempts made.
|
||||
func (s *Standard) IsErrorRetryable(err error) bool {
|
||||
return s.retryable.IsErrorRetryable(err).Bool()
|
||||
}
|
||||
|
||||
// RetryDelay returns the delay to use before another request attempt is made.
|
||||
func (s *Standard) RetryDelay(attempt int, err error) (time.Duration, error) {
|
||||
return s.backoff.BackoffDelay(attempt, err)
|
||||
}
|
||||
|
||||
// GetInitialToken returns the initial request token that can increment the
|
||||
// retry token pool if the request is successful.
|
||||
func (s *Standard) GetInitialToken() func(error) error {
|
||||
return releaseToken(s.incrementTokens).release
|
||||
}
|
||||
|
||||
func (s *Standard) incrementTokens() error {
|
||||
return s.options.RateLimiter.AddTokens(s.options.NoRetryIncrement)
|
||||
}
|
||||
|
||||
// GetRetryToken attempts to deduct the retry cost from the retry token pool.
|
||||
// Returning the token release function, or error.
|
||||
func (s *Standard) GetRetryToken(ctx context.Context, err error) (func(error) error, error) {
|
||||
cost := s.options.RetryCost
|
||||
if s.timeout.IsErrorTimeout(err).Bool() {
|
||||
cost = s.options.RetryTimeoutCost
|
||||
}
|
||||
|
||||
fn, err := s.options.RateLimiter.GetToken(ctx, cost)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return releaseToken(fn).release, nil
|
||||
}
|
||||
|
||||
type releaseToken func() error
|
||||
|
||||
func (f releaseToken) release(err error) error {
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return f()
|
||||
}
|
52
vendor/github.com/aws/aws-sdk-go-v2/aws/retry/timeout_error.go
generated
vendored
Normal file
@ -0,0 +1,52 @@
|
||||
package retry
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/aws/aws-sdk-go-v2/aws"
|
||||
)
|
||||
|
||||
// IsErrorTimeout provides the interface of an implementation to determine if
|
||||
// a error matches.
|
||||
type IsErrorTimeout interface {
|
||||
IsErrorTimeout(err error) aws.Ternary
|
||||
}
|
||||
|
||||
// IsErrorTimeouts is a collection of checks to determine of the error is
|
||||
// retryable. Iterates through the checks and returns the state of retryable
|
||||
// if any check returns something other than unknown.
|
||||
type IsErrorTimeouts []IsErrorTimeout
|
||||
|
||||
// IsErrorTimeout returns if the error is retryable if any of the checks in
|
||||
// the list return a value other than unknown.
|
||||
func (ts IsErrorTimeouts) IsErrorTimeout(err error) aws.Ternary {
|
||||
for _, t := range ts {
|
||||
if v := t.IsErrorTimeout(err); v != aws.UnknownTernary {
|
||||
return v
|
||||
}
|
||||
}
|
||||
return aws.UnknownTernary
|
||||
}
|
||||
|
||||
// IsErrorTimeoutFunc wraps a function with the IsErrorTimeout interface.
|
||||
type IsErrorTimeoutFunc func(error) aws.Ternary
|
||||
|
||||
// IsErrorTimeout returns if the error is retryable.
|
||||
func (fn IsErrorTimeoutFunc) IsErrorTimeout(err error) aws.Ternary {
|
||||
return fn(err)
|
||||
}
|
||||
|
||||
// TimeouterError provides the IsErrorTimeout implementation for determining if
|
||||
// an error is a timeout based on type with the Timeout method.
|
||||
type TimeouterError struct{}
|
||||
|
||||
// IsErrorTimeout returns if the error is a timeout error.
|
||||
func (t TimeouterError) IsErrorTimeout(err error) aws.Ternary {
|
||||
var v interface{ Timeout() bool }
|
||||
|
||||
if !errors.As(err, &v) {
|
||||
return aws.UnknownTernary
|
||||
}
|
||||
|
||||
return aws.BoolTernary(v.Timeout())
|
||||
}
|
62
vendor/github.com/aws/aws-sdk-go-v2/aws/retryer.go
generated
vendored
Normal file
@ -0,0 +1,62 @@
|
||||
package aws
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Retryer is an interface to determine if a given error from a
|
||||
// request should be retried, and if so what backoff delay to apply. The
|
||||
// default implementation used by most services is the retry package's Standard
|
||||
// type. Which contains basic retry logic using exponential backoff.
|
||||
type Retryer interface {
|
||||
// IsErrorRetryable returns if the failed request is retryable. This check
|
||||
// should determine if the error can be retried, or if the error is
|
||||
// terminal.
|
||||
IsErrorRetryable(error) bool
|
||||
|
||||
// MaxAttempts returns the maximum number of attempts that can be made for
|
||||
// a request before failing. A value of 0 implies that the request should
|
||||
// be retried until it succeeds if the errors are retryable.
|
||||
MaxAttempts() int
|
||||
|
||||
// RetryDelay returns the delay that should be used before retrying the
|
||||
// request. Will return error if the if the delay could not be determined.
|
||||
RetryDelay(attempt int, opErr error) (time.Duration, error)
|
||||
|
||||
// GetRetryToken attempts to deduct the retry cost from the retry token pool.
|
||||
// Returning the token release function, or error.
|
||||
GetRetryToken(ctx context.Context, opErr error) (releaseToken func(error) error, err error)
|
||||
|
||||
// GetInitalToken returns the initial request token that can increment the
|
||||
// retry token pool if the request is successful.
|
||||
GetInitialToken() (releaseToken func(error) error)
|
||||
}
|
||||
|
||||
// NopRetryer provides a RequestRetryDecider implementation that will flag
|
||||
// all attempt errors as not retryable, with a max attempts of 1.
|
||||
type NopRetryer struct{}
|
||||
|
||||
// IsErrorRetryable returns false for all error values.
|
||||
func (NopRetryer) IsErrorRetryable(error) bool { return false }
|
||||
|
||||
// MaxAttempts always returns 1 for the original request attempt.
|
||||
func (NopRetryer) MaxAttempts() int { return 1 }
|
||||
|
||||
// RetryDelay is not valid for the NopRetryer. Will always return error.
|
||||
func (NopRetryer) RetryDelay(int, error) (time.Duration, error) {
|
||||
return 0, fmt.Errorf("not retrying any request errors")
|
||||
}
|
||||
|
||||
// GetRetryToken returns a stub function that does nothing.
|
||||
func (NopRetryer) GetRetryToken(context.Context, error) (func(error) error, error) {
|
||||
return nopReleaseToken, nil
|
||||
}
|
||||
|
||||
// GetInitialToken returns a stub function that does nothing.
|
||||
func (NopRetryer) GetInitialToken() func(error) error {
|
||||
return nopReleaseToken
|
||||
}
|
||||
|
||||
func nopReleaseToken(error) error { return nil }
|
115
vendor/github.com/aws/aws-sdk-go-v2/aws/signer/internal/v4/cache.go
generated
vendored
Normal file
@ -0,0 +1,115 @@
|
||||
package v4
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/aws/aws-sdk-go-v2/aws"
|
||||
)
|
||||
|
||||
func lookupKey(service, region string) string {
|
||||
var s strings.Builder
|
||||
s.Grow(len(region) + len(service) + 3)
|
||||
s.WriteString(region)
|
||||
s.WriteRune('/')
|
||||
s.WriteString(service)
|
||||
return s.String()
|
||||
}
|
||||
|
||||
type derivedKey struct {
|
||||
AccessKey string
|
||||
Date time.Time
|
||||
Credential []byte
|
||||
}
|
||||
|
||||
type derivedKeyCache struct {
|
||||
values map[string]derivedKey
|
||||
mutex sync.RWMutex
|
||||
}
|
||||
|
||||
func newDerivedKeyCache() derivedKeyCache {
|
||||
return derivedKeyCache{
|
||||
values: make(map[string]derivedKey),
|
||||
}
|
||||
}
|
||||
|
||||
func (s *derivedKeyCache) Get(credentials aws.Credentials, service, region string, signingTime SigningTime) []byte {
|
||||
key := lookupKey(service, region)
|
||||
s.mutex.RLock()
|
||||
if cred, ok := s.get(key, credentials, signingTime.Time); ok {
|
||||
s.mutex.RUnlock()
|
||||
return cred
|
||||
}
|
||||
s.mutex.RUnlock()
|
||||
|
||||
s.mutex.Lock()
|
||||
if cred, ok := s.get(key, credentials, signingTime.Time); ok {
|
||||
s.mutex.Unlock()
|
||||
return cred
|
||||
}
|
||||
cred := deriveKey(credentials.SecretAccessKey, service, region, signingTime)
|
||||
entry := derivedKey{
|
||||
AccessKey: credentials.AccessKeyID,
|
||||
Date: signingTime.Time,
|
||||
Credential: cred,
|
||||
}
|
||||
s.values[key] = entry
|
||||
s.mutex.Unlock()
|
||||
|
||||
return cred
|
||||
}
|
||||
|
||||
func (s *derivedKeyCache) get(key string, credentials aws.Credentials, signingTime time.Time) ([]byte, bool) {
|
||||
cacheEntry, ok := s.retrieveFromCache(key)
|
||||
if ok && cacheEntry.AccessKey == credentials.AccessKeyID && isSameDay(signingTime, cacheEntry.Date) {
|
||||
return cacheEntry.Credential, true
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
||||
func (s *derivedKeyCache) retrieveFromCache(key string) (derivedKey, bool) {
|
||||
if v, ok := s.values[key]; ok {
|
||||
return v, true
|
||||
}
|
||||
return derivedKey{}, false
|
||||
}
|
||||
|
||||
// SigningKeyDeriver derives a signing key from a set of credentials
|
||||
type SigningKeyDeriver struct {
|
||||
cache derivedKeyCache
|
||||
}
|
||||
|
||||
// NewSigningKeyDeriver returns a new SigningKeyDeriver
|
||||
func NewSigningKeyDeriver() *SigningKeyDeriver {
|
||||
return &SigningKeyDeriver{
|
||||
cache: newDerivedKeyCache(),
|
||||
}
|
||||
}
|
||||
|
||||
// DeriveKey returns a derived signing key from the given credentials to be used with SigV4 signing.
|
||||
func (k *SigningKeyDeriver) DeriveKey(credential aws.Credentials, service, region string, signingTime SigningTime) []byte {
|
||||
return k.cache.Get(credential, service, region, signingTime)
|
||||
}
|
||||
|
||||
func deriveKey(secret, service, region string, t SigningTime) []byte {
|
||||
hmacDate := HMACSHA256([]byte("AWS4"+secret), []byte(t.ShortTimeFormat()))
|
||||
hmacRegion := HMACSHA256(hmacDate, []byte(region))
|
||||
hmacService := HMACSHA256(hmacRegion, []byte(service))
|
||||
return HMACSHA256(hmacService, []byte("aws4_request"))
|
||||
}
|
||||
|
||||
func isSameDay(x, y time.Time) bool {
|
||||
xYear, xMonth, xDay := x.Date()
|
||||
yYear, yMonth, yDay := y.Date()
|
||||
|
||||
if xYear != yYear {
|
||||
return false
|
||||
}
|
||||
|
||||
if xMonth != yMonth {
|
||||
return false
|
||||
}
|
||||
|
||||
return xDay == yDay
|
||||
}
|
36
vendor/github.com/aws/aws-sdk-go-v2/aws/signer/internal/v4/const.go
generated
vendored
Normal file
@ -0,0 +1,36 @@
|
||||
package v4
|
||||
|
||||
const (
|
||||
// EmptyStringSHA256 is the hex encoded sha256 value of an empty string
|
||||
EmptyStringSHA256 = `e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855`
|
||||
|
||||
// UnsignedPayload indicates that the request payload body is unsigned
|
||||
UnsignedPayload = "UNSIGNED-PAYLOAD"
|
||||
|
||||
// AmzAlgorithmKey indicates the signing algorithm
|
||||
AmzAlgorithmKey = "X-Amz-Algorithm"
|
||||
|
||||
// AmzSecurityTokenKey indicates the security token to be used with temporary credentials
|
||||
AmzSecurityTokenKey = "X-Amz-Security-Token"
|
||||
|
||||
// AmzDateKey is the UTC timestamp for the request in the format YYYYMMDD'T'HHMMSS'Z'
|
||||
AmzDateKey = "X-Amz-Date"
|
||||
|
||||
// AmzCredentialKey is the access key ID and credential scope
|
||||
AmzCredentialKey = "X-Amz-Credential"
|
||||
|
||||
// AmzSignedHeadersKey is the set of headers signed for the request
|
||||
AmzSignedHeadersKey = "X-Amz-SignedHeaders"
|
||||
|
||||
// AmzSignatureKey is the query parameter to store the SigV4 signature
|
||||
AmzSignatureKey = "X-Amz-Signature"
|
||||
|
||||
// TimeFormat is the time format to be used in the X-Amz-Date header or query parameter
|
||||
TimeFormat = "20060102T150405Z"
|
||||
|
||||
// ShortTimeFormat is the shorten time format used in the credential scope
|
||||
ShortTimeFormat = "20060102"
|
||||
|
||||
// ContentSHAKey is the SHA256 of request body
|
||||
ContentSHAKey = "X-Amz-Content-Sha256"
|
||||
)
|
82
vendor/github.com/aws/aws-sdk-go-v2/aws/signer/internal/v4/header_rules.go
generated
vendored
Normal file
@ -0,0 +1,82 @@
|
||||
package v4
|
||||
|
||||
import (
|
||||
sdkstrings "github.com/aws/aws-sdk-go-v2/internal/strings"
|
||||
)
|
||||
|
||||
// Rules houses a set of Rule needed for validation of a
|
||||
// string value
|
||||
type Rules []Rule
|
||||
|
||||
// Rule interface allows for more flexible rules and just simply
|
||||
// checks whether or not a value adheres to that Rule
|
||||
type Rule interface {
|
||||
IsValid(value string) bool
|
||||
}
|
||||
|
||||
// IsValid will iterate through all rules and see if any rules
|
||||
// apply to the value and supports nested rules
|
||||
func (r Rules) IsValid(value string) bool {
|
||||
for _, rule := range r {
|
||||
if rule.IsValid(value) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// MapRule generic Rule for maps
|
||||
type MapRule map[string]struct{}
|
||||
|
||||
// IsValid for the map Rule satisfies whether it exists in the map
|
||||
func (m MapRule) IsValid(value string) bool {
|
||||
_, ok := m[value]
|
||||
return ok
|
||||
}
|
||||
|
||||
// AllowList is a generic Rule for include listing
|
||||
type AllowList struct {
|
||||
Rule
|
||||
}
|
||||
|
||||
// IsValid for AllowList checks if the value is within the AllowList
|
||||
func (w AllowList) IsValid(value string) bool {
|
||||
return w.Rule.IsValid(value)
|
||||
}
|
||||
|
||||
// ExcludeList is a generic Rule for exclude listing
|
||||
type ExcludeList struct {
|
||||
Rule
|
||||
}
|
||||
|
||||
// IsValid for AllowList checks if the value is within the AllowList
|
||||
func (b ExcludeList) IsValid(value string) bool {
|
||||
return !b.Rule.IsValid(value)
|
||||
}
|
||||
|
||||
// Patterns is a list of strings to match against
|
||||
type Patterns []string
|
||||
|
||||
// IsValid for Patterns checks each pattern and returns if a match has
|
||||
// been found
|
||||
func (p Patterns) IsValid(value string) bool {
|
||||
for _, pattern := range p {
|
||||
if sdkstrings.HasPrefixFold(value, pattern) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// InclusiveRules rules allow for rules to depend on one another
|
||||
type InclusiveRules []Rule
|
||||
|
||||
// IsValid will return true if all rules are true
|
||||
func (r InclusiveRules) IsValid(value string) bool {
|
||||
for _, rule := range r {
|
||||
if !rule.IsValid(value) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
68
vendor/github.com/aws/aws-sdk-go-v2/aws/signer/internal/v4/headers.go
generated
vendored
Normal file
@ -0,0 +1,68 @@
|
||||
package v4
|
||||
|
||||
// IgnoredHeaders is a list of headers that are ignored during signing
|
||||
var IgnoredHeaders = Rules{
|
||||
ExcludeList{
|
||||
MapRule{
|
||||
"Authorization": struct{}{},
|
||||
"User-Agent": struct{}{},
|
||||
"X-Amzn-Trace-Id": struct{}{},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
// RequiredSignedHeaders is a allow list for Build canonical headers.
|
||||
var RequiredSignedHeaders = Rules{
|
||||
AllowList{
|
||||
MapRule{
|
||||
"Cache-Control": struct{}{},
|
||||
"Content-Disposition": struct{}{},
|
||||
"Content-Encoding": struct{}{},
|
||||
"Content-Language": struct{}{},
|
||||
"Content-Md5": struct{}{},
|
||||
"Content-Type": struct{}{},
|
||||
"Expires": struct{}{},
|
||||
"If-Match": struct{}{},
|
||||
"If-Modified-Since": struct{}{},
|
||||
"If-None-Match": struct{}{},
|
||||
"If-Unmodified-Since": struct{}{},
|
||||
"Range": struct{}{},
|
||||
"X-Amz-Acl": struct{}{},
|
||||
"X-Amz-Copy-Source": struct{}{},
|
||||
"X-Amz-Copy-Source-If-Match": struct{}{},
|
||||
"X-Amz-Copy-Source-If-Modified-Since": struct{}{},
|
||||
"X-Amz-Copy-Source-If-None-Match": struct{}{},
|
||||
"X-Amz-Copy-Source-If-Unmodified-Since": struct{}{},
|
||||
"X-Amz-Copy-Source-Range": struct{}{},
|
||||
"X-Amz-Copy-Source-Server-Side-Encryption-Customer-Algorithm": struct{}{},
|
||||
"X-Amz-Copy-Source-Server-Side-Encryption-Customer-Key": struct{}{},
|
||||
"X-Amz-Copy-Source-Server-Side-Encryption-Customer-Key-Md5": struct{}{},
|
||||
"X-Amz-Grant-Full-control": struct{}{},
|
||||
"X-Amz-Grant-Read": struct{}{},
|
||||
"X-Amz-Grant-Read-Acp": struct{}{},
|
||||
"X-Amz-Grant-Write": struct{}{},
|
||||
"X-Amz-Grant-Write-Acp": struct{}{},
|
||||
"X-Amz-Metadata-Directive": struct{}{},
|
||||
"X-Amz-Mfa": struct{}{},
|
||||
"X-Amz-Request-Payer": struct{}{},
|
||||
"X-Amz-Server-Side-Encryption": struct{}{},
|
||||
"X-Amz-Server-Side-Encryption-Aws-Kms-Key-Id": struct{}{},
|
||||
"X-Amz-Server-Side-Encryption-Customer-Algorithm": struct{}{},
|
||||
"X-Amz-Server-Side-Encryption-Customer-Key": struct{}{},
|
||||
"X-Amz-Server-Side-Encryption-Customer-Key-Md5": struct{}{},
|
||||
"X-Amz-Storage-Class": struct{}{},
|
||||
"X-Amz-Website-Redirect-Location": struct{}{},
|
||||
"X-Amz-Content-Sha256": struct{}{},
|
||||
"X-Amz-Tagging": struct{}{},
|
||||
},
|
||||
},
|
||||
Patterns{"X-Amz-Object-Lock-"},
|
||||
Patterns{"X-Amz-Meta-"},
|
||||
}
|
||||
|
||||
// AllowedQueryHoisting is a allowed list for Build query headers. The boolean value
|
||||
// represents whether or not it is a pattern.
|
||||
var AllowedQueryHoisting = InclusiveRules{
|
||||
ExcludeList{RequiredSignedHeaders},
|
||||
Patterns{"X-Amz-"},
|
||||
}
|
13
vendor/github.com/aws/aws-sdk-go-v2/aws/signer/internal/v4/hmac.go
generated
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
package v4
|
||||
|
||||
import (
|
||||
"crypto/hmac"
|
||||
"crypto/sha256"
|
||||
)
|
||||
|
||||
// HMACSHA256 computes a HMAC-SHA256 of data given the provided key.
|
||||
func HMACSHA256(key []byte, data []byte) []byte {
|
||||
hash := hmac.New(sha256.New, key)
|
||||
hash.Write(data)
|
||||
return hash.Sum(nil)
|
||||
}
|
75
vendor/github.com/aws/aws-sdk-go-v2/aws/signer/internal/v4/host.go
generated
vendored
Normal file
@ -0,0 +1,75 @@
|
||||
package v4
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// SanitizeHostForHeader removes default port from host and updates request.Host
|
||||
func SanitizeHostForHeader(r *http.Request) {
|
||||
host := getHost(r)
|
||||
port := portOnly(host)
|
||||
if port != "" && isDefaultPort(r.URL.Scheme, port) {
|
||||
r.Host = stripPort(host)
|
||||
}
|
||||
}
|
||||
|
||||
// Returns host from request
|
||||
func getHost(r *http.Request) string {
|
||||
if r.Host != "" {
|
||||
return r.Host
|
||||
}
|
||||
|
||||
return r.URL.Host
|
||||
}
|
||||
|
||||
// Hostname returns u.Host, without any port number.
|
||||
//
|
||||
// If Host is an IPv6 literal with a port number, Hostname returns the
|
||||
// IPv6 literal without the square brackets. IPv6 literals may include
|
||||
// a zone identifier.
|
||||
//
|
||||
// Copied from the Go 1.8 standard library (net/url)
|
||||
func stripPort(hostport string) string {
|
||||
colon := strings.IndexByte(hostport, ':')
|
||||
if colon == -1 {
|
||||
return hostport
|
||||
}
|
||||
if i := strings.IndexByte(hostport, ']'); i != -1 {
|
||||
return strings.TrimPrefix(hostport[:i], "[")
|
||||
}
|
||||
return hostport[:colon]
|
||||
}
|
||||
|
||||
// Port returns the port part of u.Host, without the leading colon.
|
||||
// If u.Host doesn't contain a port, Port returns an empty string.
|
||||
//
|
||||
// Copied from the Go 1.8 standard library (net/url)
|
||||
func portOnly(hostport string) string {
|
||||
colon := strings.IndexByte(hostport, ':')
|
||||
if colon == -1 {
|
||||
return ""
|
||||
}
|
||||
if i := strings.Index(hostport, "]:"); i != -1 {
|
||||
return hostport[i+len("]:"):]
|
||||
}
|
||||
if strings.Contains(hostport, "]") {
|
||||
return ""
|
||||
}
|
||||
return hostport[colon+len(":"):]
|
||||
}
|
||||
|
||||
// Returns true if the specified URI is using the standard port
|
||||
// (i.e. port 80 for HTTP URIs or 443 for HTTPS URIs)
|
||||
func isDefaultPort(scheme, port string) bool {
|
||||
if port == "" {
|
||||
return true
|
||||
}
|
||||
|
||||
lowerCaseScheme := strings.ToLower(scheme)
|
||||
if (lowerCaseScheme == "http" && port == "80") || (lowerCaseScheme == "https" && port == "443") {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
36
vendor/github.com/aws/aws-sdk-go-v2/aws/signer/internal/v4/time.go
generated
vendored
Normal file
@ -0,0 +1,36 @@
|
||||
package v4
|
||||
|
||||
import "time"
|
||||
|
||||
// SigningTime provides a wrapper around a time.Time which provides cached values for SigV4 signing.
|
||||
type SigningTime struct {
|
||||
time.Time
|
||||
timeFormat string
|
||||
shortTimeFormat string
|
||||
}
|
||||
|
||||
// NewSigningTime creates a new SigningTime given a time.Time
|
||||
func NewSigningTime(t time.Time) SigningTime {
|
||||
return SigningTime{
|
||||
Time: t,
|
||||
}
|
||||
}
|
||||
|
||||
// TimeFormat provides a time formatted in the X-Amz-Date format.
|
||||
func (m *SigningTime) TimeFormat() string {
|
||||
return m.format(&m.timeFormat, TimeFormat)
|
||||
}
|
||||
|
||||
// ShortTimeFormat provides a time formatted of 20060102.
|
||||
func (m *SigningTime) ShortTimeFormat() string {
|
||||
return m.format(&m.shortTimeFormat, ShortTimeFormat)
|
||||
}
|
||||
|
||||
func (m *SigningTime) format(target *string, format string) string {
|
||||
if len(*target) > 0 {
|
||||
return *target
|
||||
}
|
||||
v := m.Time.Format(format)
|
||||
*target = v
|
||||
return v
|
||||
}
|
64
vendor/github.com/aws/aws-sdk-go-v2/aws/signer/internal/v4/util.go
generated
vendored
Normal file
@ -0,0 +1,64 @@
|
||||
package v4
|
||||
|
||||
import (
|
||||
"net/url"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const doubleSpace = " "
|
||||
|
||||
// StripExcessSpaces will rewrite the passed in slice's string values to not
|
||||
// contain muliple side-by-side spaces.
|
||||
func StripExcessSpaces(str string) string {
|
||||
var j, k, l, m, spaces int
|
||||
// Trim trailing spaces
|
||||
for j = len(str) - 1; j >= 0 && str[j] == ' '; j-- {
|
||||
}
|
||||
|
||||
// Trim leading spaces
|
||||
for k = 0; k < j && str[k] == ' '; k++ {
|
||||
}
|
||||
str = str[k : j+1]
|
||||
|
||||
// Strip multiple spaces.
|
||||
j = strings.Index(str, doubleSpace)
|
||||
if j < 0 {
|
||||
return str
|
||||
}
|
||||
|
||||
buf := []byte(str)
|
||||
for k, m, l = j, j, len(buf); k < l; k++ {
|
||||
if buf[k] == ' ' {
|
||||
if spaces == 0 {
|
||||
// First space.
|
||||
buf[m] = buf[k]
|
||||
m++
|
||||
}
|
||||
spaces++
|
||||
} else {
|
||||
// End of multiple spaces.
|
||||
spaces = 0
|
||||
buf[m] = buf[k]
|
||||
m++
|
||||
}
|
||||
}
|
||||
|
||||
return string(buf[:m])
|
||||
}
|
||||
|
||||
// GetURIPath returns the escaped URI component from the provided URL
|
||||
func GetURIPath(u *url.URL) string {
|
||||
var uri string
|
||||
|
||||
if len(u.Opaque) > 0 {
|
||||
uri = "/" + strings.Join(strings.Split(u.Opaque, "/")[3:], "/")
|
||||
} else {
|
||||
uri = u.EscapedPath()
|
||||
}
|
||||
|
||||
if len(uri) == 0 {
|
||||
uri = "/"
|
||||
}
|
||||
|
||||
return uri
|
||||
}
|