Update readme and docstrings, minor refactors.

This commit is contained in:
Rohan Verma
2018-12-24 17:31:36 +05:30
parent d218b23f05
commit e4c7d93da1
4 changed files with 150 additions and 30 deletions
+66 -1
View File
@@ -7,6 +7,8 @@ import (
"bytes"
"crypto/hmac"
"crypto/sha256"
"encoding/json"
"errors"
"fmt"
"io"
"io/ioutil"
@@ -16,6 +18,10 @@ import (
"time"
)
const (
securityCredentialsURL = "http://169.254.169.254/latest/meta-data/iam/security-credentials/"
)
// S3 provides a wrapper around your S3 credentials.
type S3 struct {
AccessKey string
@@ -40,6 +46,18 @@ type DeleteInput struct {
ObjectKey string
}
// IAMResponse is used by NewUsingIAM to auto
// detect the credentials
type IAMResponse struct {
Code string `json:"Code"`
LastUpdated string `json:"LastUpdated"`
Type string `json:"Type"`
AccessKeyID string `json:"AccessKeyId"`
SecretAccessKey string `json:"SecretAccessKey"`
Token string `json:"Token"`
Expiration string `json:"Expiration"`
}
// New returns an instance of S3.
func New(region, accessKey, secretKey string) *S3 {
return &S3{
@@ -51,6 +69,53 @@ func New(region, accessKey, secretKey string) *S3 {
}
}
// NewUsingIAM automatically generates an Instance of S3
// using instance metatdata.
func NewUsingIAM(region string) (*S3, error) {
// Get the IAM role
resp, err := http.Get(securityCredentialsURL)
if err != nil {
return nil, err
}
defer resp.Body.Close()
if resp.StatusCode != 200 {
return nil, errors.New(http.StatusText(resp.StatusCode))
}
role, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, err
}
resp, err = http.Get(securityCredentialsURL + "/" + string(role))
if err != nil {
return nil, err
}
defer resp.Body.Close()
if resp.StatusCode != 200 {
return nil, errors.New(http.StatusText(resp.StatusCode))
}
var jsonResp IAMResponse
jsonString, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, err
}
if err := json.Unmarshal(jsonString, &jsonResp); err != nil {
return nil, err
}
return &S3{
Region: region,
AccessKey: jsonResp.AccessKeyID,
SecretKey: jsonResp.SecretAccessKey,
URIFormat: "https://s3.%s.amazonaws.com/%s",
}, nil
}
func detectFileSize(body multipart.File) int64 {
switch r := body.(type) {
case io.Seeker:
@@ -133,7 +198,7 @@ func (s3 *S3) FileUpload(u UploadInput) error {
return nil
}
// FileDelete makes a POST call with the file written as multipart
// FileDelete makes a DELETE call with the file written as multipart
// and on successful upload, checks for 204 No Content.
func (s3 *S3) FileDelete(u DeleteInput) error {
url := fmt.Sprintf(