1// +build go1.13,integration,perftest 2 3package main 4 5import ( 6 "flag" 7 "fmt" 8 "net/http" 9 "strings" 10 "time" 11 12 "github.com/aws/aws-sdk-go/service/s3/s3manager" 13) 14 15type Config struct { 16 Bucket string 17 Size int64 18 Key string 19 LogVerbose bool 20 UploadPartSize int64 21 22 SDK SDKConfig 23 Client ClientConfig 24 Profiler Profiler 25} 26 27func (c *Config) SetupFlags(prefix string, flagset *flag.FlagSet) { 28 flagset.StringVar(&c.Bucket, "bucket", "", 29 "The S3 bucket `name` to download the object from.") 30 flagset.Int64Var(&c.Size, "size", 0, 31 "The S3 object size in bytes to be first uploaded then downloaded") 32 flagset.StringVar(&c.Key, "key", "", "The S3 object key to download") 33 flagset.BoolVar(&c.LogVerbose, "verbose", false, 34 "The output log will include verbose request information") 35 flagset.Int64Var(&c.UploadPartSize, "upload-part-size", 0, "the upload part size when uploading a file to s3") 36 37 c.SDK.SetupFlags(prefix, flagset) 38 c.Client.SetupFlags(prefix, flagset) 39 c.Profiler.SetupFlags(prefix, flagset) 40} 41 42func (c *Config) Validate() error { 43 var errs Errors 44 45 if len(c.Bucket) == 0 || (c.Size <= 0 && len(c.Key) == 0) { 46 errs = append(errs, fmt.Errorf("bucket and filename/size are required")) 47 } 48 49 if err := c.SDK.Validate(); err != nil { 50 errs = append(errs, err) 51 } 52 if err := c.Client.Validate(); err != nil { 53 errs = append(errs, err) 54 } 55 56 if len(errs) != 0 { 57 return errs 58 } 59 60 return nil 61} 62 63type SDKConfig struct { 64 PartSize int64 65 Concurrency int 66 BufferProvider s3manager.WriterReadFromProvider 67} 68 69func (c *SDKConfig) SetupFlags(prefix string, flagset *flag.FlagSet) { 70 prefix += "sdk." 71 72 flagset.Int64Var(&c.PartSize, prefix+"part-size", s3manager.DefaultDownloadPartSize, 73 "Specifies the `size` of parts of the object to download.") 74 flagset.IntVar(&c.Concurrency, prefix+"concurrency", s3manager.DefaultDownloadConcurrency, 75 "Specifies the number of parts to download `at once`.") 76} 77 78func (c *SDKConfig) Validate() error { 79 return nil 80} 81 82type ClientConfig struct { 83 KeepAlive bool 84 Timeouts Timeouts 85 86 MaxIdleConns int 87 MaxIdleConnsPerHost int 88 89 // Go 1.13 90 ReadBufferSize int 91 WriteBufferSize int 92} 93 94func (c *ClientConfig) SetupFlags(prefix string, flagset *flag.FlagSet) { 95 prefix += "client." 96 97 flagset.BoolVar(&c.KeepAlive, prefix+"http-keep-alive", true, 98 "Specifies if HTTP keep alive is enabled.") 99 100 defTR := http.DefaultTransport.(*http.Transport) 101 102 flagset.IntVar(&c.MaxIdleConns, prefix+"idle-conns", defTR.MaxIdleConns, 103 "Specifies max idle connection pool size.") 104 105 flagset.IntVar(&c.MaxIdleConnsPerHost, prefix+"idle-conns-host", http.DefaultMaxIdleConnsPerHost, 106 "Specifies max idle connection pool per host, will be truncated by idle-conns.") 107 108 flagset.IntVar(&c.ReadBufferSize, prefix+"read-buffer", defTR.ReadBufferSize, "size of the transport read buffer used") 109 flagset.IntVar(&c.WriteBufferSize, prefix+"writer-buffer", defTR.WriteBufferSize, "size of the transport write buffer used") 110 111 c.Timeouts.SetupFlags(prefix, flagset) 112} 113 114func (c *ClientConfig) Validate() error { 115 var errs Errors 116 117 if err := c.Timeouts.Validate(); err != nil { 118 errs = append(errs, err) 119 } 120 121 if len(errs) != 0 { 122 return errs 123 } 124 return nil 125} 126 127type Timeouts struct { 128 Connect time.Duration 129 TLSHandshake time.Duration 130 ExpectContinue time.Duration 131 ResponseHeader time.Duration 132} 133 134func (c *Timeouts) SetupFlags(prefix string, flagset *flag.FlagSet) { 135 prefix += "timeout." 136 137 flagset.DurationVar(&c.Connect, prefix+"connect", 30*time.Second, 138 "The `timeout` connecting to the remote host.") 139 140 defTR := http.DefaultTransport.(*http.Transport) 141 142 flagset.DurationVar(&c.TLSHandshake, prefix+"tls", defTR.TLSHandshakeTimeout, 143 "The `timeout` waiting for the TLS handshake to complete.") 144 145 flagset.DurationVar(&c.ExpectContinue, prefix+"expect-continue", defTR.ExpectContinueTimeout, 146 "The `timeout` waiting for the TLS handshake to complete.") 147 148 flagset.DurationVar(&c.ResponseHeader, prefix+"response-header", defTR.ResponseHeaderTimeout, 149 "The `timeout` waiting for the TLS handshake to complete.") 150} 151 152func (c *Timeouts) Validate() error { 153 return nil 154} 155 156type Errors []error 157 158func (es Errors) Error() string { 159 var buf strings.Builder 160 for _, e := range es { 161 buf.WriteString(e.Error()) 162 } 163 164 return buf.String() 165} 166