├── .gitignore ├── .goxc.json ├── Dockerfile ├── Godeps ├── Godeps.json ├── Readme └── _workspace │ ├── .gitignore │ └── src │ └── github.com │ ├── aws │ └── aws-sdk-go │ │ ├── aws │ │ ├── awserr │ │ │ ├── error.go │ │ │ └── types.go │ │ ├── awsutil │ │ │ ├── copy.go │ │ │ ├── copy_test.go │ │ │ ├── path_value.go │ │ │ ├── path_value_test.go │ │ │ └── prettify.go │ │ ├── config.go │ │ ├── config_test.go │ │ ├── convert_types.go │ │ ├── convert_types_test.go │ │ ├── corehandlers │ │ │ ├── handlers.go │ │ │ ├── handlers_test.go │ │ │ ├── param_validator.go │ │ │ └── param_validator_test.go │ │ ├── credentials │ │ │ ├── chain_provider.go │ │ │ ├── chain_provider_test.go │ │ │ ├── credentials.go │ │ │ ├── credentials_test.go │ │ │ ├── ec2rolecreds │ │ │ │ ├── ec2_role_provider.go │ │ │ │ └── ec2_role_provider_test.go │ │ │ ├── env_provider.go │ │ │ ├── env_provider_test.go │ │ │ ├── example.ini │ │ │ ├── shared_credentials_provider.go │ │ │ ├── shared_credentials_provider_test.go │ │ │ ├── static_provider.go │ │ │ ├── static_provider_test.go │ │ │ └── stscreds │ │ │ │ ├── assume_role_provider.go │ │ │ │ └── assume_role_provider_test.go │ │ ├── defaults │ │ │ └── defaults.go │ │ ├── ec2metadata │ │ │ ├── api.go │ │ │ ├── api_test.go │ │ │ └── service.go │ │ ├── errors.go │ │ ├── logger.go │ │ ├── request │ │ │ ├── handlers.go │ │ │ ├── handlers_test.go │ │ │ ├── request.go │ │ │ ├── request_pagination_test.go │ │ │ ├── request_test.go │ │ │ └── retryer.go │ │ ├── service │ │ │ ├── default_retryer.go │ │ │ ├── service.go │ │ │ └── serviceinfo │ │ │ │ └── service_info.go │ │ ├── types.go │ │ ├── types_test.go │ │ └── version.go │ │ ├── internal │ │ ├── endpoints │ │ │ ├── endpoints.go │ │ │ ├── endpoints.json │ │ │ ├── endpoints_map.go │ │ │ └── endpoints_test.go │ │ ├── protocol │ │ │ ├── ec2query │ │ │ │ ├── build.go │ │ │ │ ├── build_test.go │ │ │ │ ├── unmarshal.go │ │ │ │ └── unmarshal_test.go │ │ │ ├── query │ │ │ │ └── queryutil │ │ │ │ │ └── queryutil.go │ │ │ ├── rest │ │ │ │ ├── build.go │ │ │ │ ├── payload.go │ │ │ │ └── unmarshal.go │ │ │ └── xml │ │ │ │ └── xmlutil │ │ │ │ ├── build.go │ │ │ │ ├── unmarshal.go │ │ │ │ └── xml_to_struct.go │ │ └── signer │ │ │ └── v4 │ │ │ ├── functional_test.go │ │ │ ├── v4.go │ │ │ └── v4_test.go │ │ └── service │ │ └── ec2 │ │ ├── api.go │ │ ├── customizations.go │ │ ├── customizations_test.go │ │ ├── ec2iface │ │ ├── interface.go │ │ └── interface_test.go │ │ ├── examples_test.go │ │ └── service.go │ ├── jessevdk │ └── go-flags │ │ ├── .travis.yml │ │ ├── LICENSE │ │ ├── README.md │ │ ├── arg.go │ │ ├── arg_test.go │ │ ├── assert_test.go │ │ ├── check_crosscompile.sh │ │ ├── closest.go │ │ ├── command.go │ │ ├── command_test.go │ │ ├── completion.go │ │ ├── completion_test.go │ │ ├── convert.go │ │ ├── convert_test.go │ │ ├── error.go │ │ ├── example_test.go │ │ ├── examples │ │ ├── add.go │ │ ├── bash-completion │ │ ├── main.go │ │ └── rm.go │ │ ├── flags.go │ │ ├── group.go │ │ ├── group_test.go │ │ ├── help.go │ │ ├── help_test.go │ │ ├── ini.go │ │ ├── ini_test.go │ │ ├── long_test.go │ │ ├── man.go │ │ ├── marshal_test.go │ │ ├── multitag.go │ │ ├── option.go │ │ ├── options_test.go │ │ ├── optstyle_other.go │ │ ├── optstyle_windows.go │ │ ├── parser.go │ │ ├── parser_test.go │ │ ├── pointer_test.go │ │ ├── short_test.go │ │ ├── tag_test.go │ │ ├── termsize.go │ │ ├── termsize_linux.go │ │ ├── termsize_nosysioctl.go │ │ ├── termsize_other.go │ │ ├── termsize_unix.go │ │ └── unknown_test.go │ └── vaughan0 │ └── go-ini │ ├── LICENSE │ ├── README.md │ ├── ini.go │ ├── ini_linux_test.go │ ├── ini_test.go │ └── test.ini ├── LICENSE ├── README.md ├── certs └── ca-certificates.crt └── let-me-in.go /.gitignore: -------------------------------------------------------------------------------- 1 | .goxc.local.json 2 | -------------------------------------------------------------------------------- /.goxc.json: -------------------------------------------------------------------------------- 1 | { 2 | "Tasks": [ 3 | "default", 4 | "publish-github" 5 | ], 6 | "PackageVersion": "0.2.0", 7 | "TaskSettings": { 8 | "publish-github": { 9 | "owner": "rlister", 10 | "repository": "let-me-in" 11 | } 12 | }, 13 | "ConfigVersion": "0.9" 14 | } -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM scratch 2 | MAINTAINER Ric Lister 3 | 4 | ADD certs/ca-certificates.crt /etc/ssl/certs/ 5 | ADD let-me-in / 6 | 7 | ENTRYPOINT [ "/let-me-in" ] 8 | -------------------------------------------------------------------------------- /Godeps/Godeps.json: -------------------------------------------------------------------------------- 1 | { 2 | "ImportPath": "github.com/rlister/let-me-in", 3 | "GoVersion": "go1.5.1", 4 | "Deps": [ 5 | { 6 | "ImportPath": "github.com/aws/aws-sdk-go/aws", 7 | "Comment": "v0.9.6", 8 | "Rev": "69142c71761512d894b028dc5c8cc312758372dd" 9 | }, 10 | { 11 | "ImportPath": "github.com/aws/aws-sdk-go/internal/endpoints", 12 | "Comment": "v0.9.6", 13 | "Rev": "69142c71761512d894b028dc5c8cc312758372dd" 14 | }, 15 | { 16 | "ImportPath": "github.com/aws/aws-sdk-go/internal/protocol/ec2query", 17 | "Comment": "v0.9.6", 18 | "Rev": "69142c71761512d894b028dc5c8cc312758372dd" 19 | }, 20 | { 21 | "ImportPath": "github.com/aws/aws-sdk-go/internal/protocol/query/queryutil", 22 | "Comment": "v0.9.6", 23 | "Rev": "69142c71761512d894b028dc5c8cc312758372dd" 24 | }, 25 | { 26 | "ImportPath": "github.com/aws/aws-sdk-go/internal/protocol/rest", 27 | "Comment": "v0.9.6", 28 | "Rev": "69142c71761512d894b028dc5c8cc312758372dd" 29 | }, 30 | { 31 | "ImportPath": "github.com/aws/aws-sdk-go/internal/protocol/xml/xmlutil", 32 | "Comment": "v0.9.6", 33 | "Rev": "69142c71761512d894b028dc5c8cc312758372dd" 34 | }, 35 | { 36 | "ImportPath": "github.com/aws/aws-sdk-go/internal/signer/v4", 37 | "Comment": "v0.9.6", 38 | "Rev": "69142c71761512d894b028dc5c8cc312758372dd" 39 | }, 40 | { 41 | "ImportPath": "github.com/aws/aws-sdk-go/service/ec2", 42 | "Comment": "v0.9.6", 43 | "Rev": "69142c71761512d894b028dc5c8cc312758372dd" 44 | }, 45 | { 46 | "ImportPath": "github.com/jessevdk/go-flags", 47 | "Comment": "v1-322-gfc93116", 48 | "Rev": "fc93116606d0a71d7e9de0ad5734fdb4b8eae834" 49 | }, 50 | { 51 | "ImportPath": "github.com/vaughan0/go-ini", 52 | "Rev": "a98ad7ee00ec53921f08832bc06ecf7fd600e6a1" 53 | } 54 | ] 55 | } 56 | -------------------------------------------------------------------------------- /Godeps/Readme: -------------------------------------------------------------------------------- 1 | This directory tree is generated automatically by godep. 2 | 3 | Please do not edit. 4 | 5 | See https://github.com/tools/godep for more information. 6 | -------------------------------------------------------------------------------- /Godeps/_workspace/.gitignore: -------------------------------------------------------------------------------- 1 | /pkg 2 | /bin 3 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/awserr/error.go: -------------------------------------------------------------------------------- 1 | // Package awserr represents API error interface accessors for the SDK. 2 | package awserr 3 | 4 | // An Error wraps lower level errors with code, message and an original error. 5 | // The underlying concrete error type may also satisfy other interfaces which 6 | // can be to used to obtain more specific information about the error. 7 | // 8 | // Calling Error() or String() will always include the full information about 9 | // an error based on its underlying type. 10 | // 11 | // Example: 12 | // 13 | // output, err := s3manage.Upload(svc, input, opts) 14 | // if err != nil { 15 | // if awsErr, ok := err.(awserr.Error); ok { 16 | // // Get error details 17 | // log.Println("Error:", err.Code(), err.Message()) 18 | // 19 | // // Prints out full error message, including original error if there was one. 20 | // log.Println("Error:", err.Error()) 21 | // 22 | // // Get original error 23 | // if origErr := err.Err(); origErr != nil { 24 | // // operate on original error. 25 | // } 26 | // } else { 27 | // fmt.Println(err.Error()) 28 | // } 29 | // } 30 | // 31 | type Error interface { 32 | // Satisfy the generic error interface. 33 | error 34 | 35 | // Returns the short phrase depicting the classification of the error. 36 | Code() string 37 | 38 | // Returns the error details message. 39 | Message() string 40 | 41 | // Returns the original error if one was set. Nil is returned if not set. 42 | OrigErr() error 43 | } 44 | 45 | // New returns an Error object described by the code, message, and origErr. 46 | // 47 | // If origErr satisfies the Error interface it will not be wrapped within a new 48 | // Error object and will instead be returned. 49 | func New(code, message string, origErr error) Error { 50 | if e, ok := origErr.(Error); ok && e != nil { 51 | return e 52 | } 53 | return newBaseError(code, message, origErr) 54 | } 55 | 56 | // A RequestFailure is an interface to extract request failure information from 57 | // an Error such as the request ID of the failed request returned by a service. 58 | // RequestFailures may not always have a requestID value if the request failed 59 | // prior to reaching the service such as a connection error. 60 | // 61 | // Example: 62 | // 63 | // output, err := s3manage.Upload(svc, input, opts) 64 | // if err != nil { 65 | // if reqerr, ok := err.(RequestFailure); ok { 66 | // log.Printf("Request failed", reqerr.Code(), reqerr.Message(), reqerr.RequestID()) 67 | // } else { 68 | // log.Printf("Error:", err.Error() 69 | // } 70 | // } 71 | // 72 | // Combined with awserr.Error: 73 | // 74 | // output, err := s3manage.Upload(svc, input, opts) 75 | // if err != nil { 76 | // if awsErr, ok := err.(awserr.Error); ok { 77 | // // Generic AWS Error with Code, Message, and original error (if any) 78 | // fmt.Println(awsErr.Code(), awsErr.Message(), awsErr.OrigErr()) 79 | // 80 | // if reqErr, ok := err.(awserr.RequestFailure); ok { 81 | // // A service error occurred 82 | // fmt.Println(reqErr.StatusCode(), reqErr.RequestID()) 83 | // } 84 | // } else { 85 | // fmt.Println(err.Error()) 86 | // } 87 | // } 88 | // 89 | type RequestFailure interface { 90 | Error 91 | 92 | // The status code of the HTTP response. 93 | StatusCode() int 94 | 95 | // The request ID returned by the service for a request failure. This will 96 | // be empty if no request ID is available such as the request failed due 97 | // to a connection error. 98 | RequestID() string 99 | } 100 | 101 | // NewRequestFailure returns a new request error wrapper for the given Error 102 | // provided. 103 | func NewRequestFailure(err Error, statusCode int, reqID string) RequestFailure { 104 | return newRequestError(err, statusCode, reqID) 105 | } 106 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/awserr/types.go: -------------------------------------------------------------------------------- 1 | package awserr 2 | 3 | import "fmt" 4 | 5 | // SprintError returns a string of the formatted error code. 6 | // 7 | // Both extra and origErr are optional. If they are included their lines 8 | // will be added, but if they are not included their lines will be ignored. 9 | func SprintError(code, message, extra string, origErr error) string { 10 | msg := fmt.Sprintf("%s: %s", code, message) 11 | if extra != "" { 12 | msg = fmt.Sprintf("%s\n\t%s", msg, extra) 13 | } 14 | if origErr != nil { 15 | msg = fmt.Sprintf("%s\ncaused by: %s", msg, origErr.Error()) 16 | } 17 | return msg 18 | } 19 | 20 | // A baseError wraps the code and message which defines an error. It also 21 | // can be used to wrap an original error object. 22 | // 23 | // Should be used as the root for errors satisfying the awserr.Error. Also 24 | // for any error which does not fit into a specific error wrapper type. 25 | type baseError struct { 26 | // Classification of error 27 | code string 28 | 29 | // Detailed information about error 30 | message string 31 | 32 | // Optional original error this error is based off of. Allows building 33 | // chained errors. 34 | origErr error 35 | } 36 | 37 | // newBaseError returns an error object for the code, message, and err. 38 | // 39 | // code is a short no whitespace phrase depicting the classification of 40 | // the error that is being created. 41 | // 42 | // message is the free flow string containing detailed information about the error. 43 | // 44 | // origErr is the error object which will be nested under the new error to be returned. 45 | func newBaseError(code, message string, origErr error) *baseError { 46 | return &baseError{ 47 | code: code, 48 | message: message, 49 | origErr: origErr, 50 | } 51 | } 52 | 53 | // Error returns the string representation of the error. 54 | // 55 | // See ErrorWithExtra for formatting. 56 | // 57 | // Satisfies the error interface. 58 | func (b baseError) Error() string { 59 | return SprintError(b.code, b.message, "", b.origErr) 60 | } 61 | 62 | // String returns the string representation of the error. 63 | // Alias for Error to satisfy the stringer interface. 64 | func (b baseError) String() string { 65 | return b.Error() 66 | } 67 | 68 | // Code returns the short phrase depicting the classification of the error. 69 | func (b baseError) Code() string { 70 | return b.code 71 | } 72 | 73 | // Message returns the error details message. 74 | func (b baseError) Message() string { 75 | return b.message 76 | } 77 | 78 | // OrigErr returns the original error if one was set. Nil is returned if no error 79 | // was set. 80 | func (b baseError) OrigErr() error { 81 | return b.origErr 82 | } 83 | 84 | // So that the Error interface type can be included as an anonymous field 85 | // in the requestError struct and not conflict with the error.Error() method. 86 | type awsError Error 87 | 88 | // A requestError wraps a request or service error. 89 | // 90 | // Composed of baseError for code, message, and original error. 91 | type requestError struct { 92 | awsError 93 | statusCode int 94 | requestID string 95 | } 96 | 97 | // newRequestError returns a wrapped error with additional information for request 98 | // status code, and service requestID. 99 | // 100 | // Should be used to wrap all request which involve service requests. Even if 101 | // the request failed without a service response, but had an HTTP status code 102 | // that may be meaningful. 103 | // 104 | // Also wraps original errors via the baseError. 105 | func newRequestError(err Error, statusCode int, requestID string) *requestError { 106 | return &requestError{ 107 | awsError: err, 108 | statusCode: statusCode, 109 | requestID: requestID, 110 | } 111 | } 112 | 113 | // Error returns the string representation of the error. 114 | // Satisfies the error interface. 115 | func (r requestError) Error() string { 116 | extra := fmt.Sprintf("status code: %d, request id: %s", 117 | r.statusCode, r.requestID) 118 | return SprintError(r.Code(), r.Message(), extra, r.OrigErr()) 119 | } 120 | 121 | // String returns the string representation of the error. 122 | // Alias for Error to satisfy the stringer interface. 123 | func (r requestError) String() string { 124 | return r.Error() 125 | } 126 | 127 | // StatusCode returns the wrapped status code for the error 128 | func (r requestError) StatusCode() int { 129 | return r.statusCode 130 | } 131 | 132 | // RequestID returns the wrapped requestID 133 | func (r requestError) RequestID() string { 134 | return r.requestID 135 | } 136 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/awsutil/copy.go: -------------------------------------------------------------------------------- 1 | package awsutil 2 | 3 | import ( 4 | "io" 5 | "reflect" 6 | ) 7 | 8 | // Copy deeply copies a src structure to dst. Useful for copying request and 9 | // response structures. 10 | // 11 | // Can copy between structs of different type, but will only copy fields which 12 | // are assignable, and exist in both structs. Fields which are not assignable, 13 | // or do not exist in both structs are ignored. 14 | func Copy(dst, src interface{}) { 15 | dstval := reflect.ValueOf(dst) 16 | if !dstval.IsValid() { 17 | panic("Copy dst cannot be nil") 18 | } 19 | 20 | rcopy(dstval, reflect.ValueOf(src), true) 21 | } 22 | 23 | // CopyOf returns a copy of src while also allocating the memory for dst. 24 | // src must be a pointer type or this operation will fail. 25 | func CopyOf(src interface{}) (dst interface{}) { 26 | dsti := reflect.New(reflect.TypeOf(src).Elem()) 27 | dst = dsti.Interface() 28 | rcopy(dsti, reflect.ValueOf(src), true) 29 | return 30 | } 31 | 32 | // rcopy performs a recursive copy of values from the source to destination. 33 | // 34 | // root is used to skip certain aspects of the copy which are not valid 35 | // for the root node of a object. 36 | func rcopy(dst, src reflect.Value, root bool) { 37 | if !src.IsValid() { 38 | return 39 | } 40 | 41 | switch src.Kind() { 42 | case reflect.Ptr: 43 | if _, ok := src.Interface().(io.Reader); ok { 44 | if dst.Kind() == reflect.Ptr && dst.Elem().CanSet() { 45 | dst.Elem().Set(src) 46 | } else if dst.CanSet() { 47 | dst.Set(src) 48 | } 49 | } else { 50 | e := src.Type().Elem() 51 | if dst.CanSet() && !src.IsNil() { 52 | dst.Set(reflect.New(e)) 53 | } 54 | if src.Elem().IsValid() { 55 | // Keep the current root state since the depth hasn't changed 56 | rcopy(dst.Elem(), src.Elem(), root) 57 | } 58 | } 59 | case reflect.Struct: 60 | if !root { 61 | dst.Set(reflect.New(src.Type()).Elem()) 62 | } 63 | 64 | t := dst.Type() 65 | for i := 0; i < t.NumField(); i++ { 66 | name := t.Field(i).Name 67 | srcval := src.FieldByName(name) 68 | if srcval.IsValid() { 69 | rcopy(dst.FieldByName(name), srcval, false) 70 | } 71 | } 72 | case reflect.Slice: 73 | if src.IsNil() { 74 | break 75 | } 76 | 77 | s := reflect.MakeSlice(src.Type(), src.Len(), src.Cap()) 78 | dst.Set(s) 79 | for i := 0; i < src.Len(); i++ { 80 | rcopy(dst.Index(i), src.Index(i), false) 81 | } 82 | case reflect.Map: 83 | if src.IsNil() { 84 | break 85 | } 86 | 87 | s := reflect.MakeMap(src.Type()) 88 | dst.Set(s) 89 | for _, k := range src.MapKeys() { 90 | v := src.MapIndex(k) 91 | v2 := reflect.New(v.Type()).Elem() 92 | rcopy(v2, v, false) 93 | dst.SetMapIndex(k, v2) 94 | } 95 | default: 96 | // Assign the value if possible. If its not assignable, the value would 97 | // need to be converted and the impact of that may be unexpected, or is 98 | // not compatible with the dst type. 99 | if src.Type().AssignableTo(dst.Type()) { 100 | dst.Set(src) 101 | } 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/awsutil/copy_test.go: -------------------------------------------------------------------------------- 1 | package awsutil_test 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | "io" 7 | "io/ioutil" 8 | "testing" 9 | 10 | "github.com/rlister/let-me-in/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/awsutil" 11 | "github.com/stretchr/testify/assert" 12 | ) 13 | 14 | func ExampleCopy() { 15 | type Foo struct { 16 | A int 17 | B []*string 18 | } 19 | 20 | // Create the initial value 21 | str1 := "hello" 22 | str2 := "bye bye" 23 | f1 := &Foo{A: 1, B: []*string{&str1, &str2}} 24 | 25 | // Do the copy 26 | var f2 Foo 27 | awsutil.Copy(&f2, f1) 28 | 29 | // Print the result 30 | fmt.Println(awsutil.Prettify(f2)) 31 | 32 | // Output: 33 | // { 34 | // A: 1, 35 | // B: ["hello","bye bye"] 36 | // } 37 | } 38 | 39 | func TestCopy(t *testing.T) { 40 | type Foo struct { 41 | A int 42 | B []*string 43 | C map[string]*int 44 | } 45 | 46 | // Create the initial value 47 | str1 := "hello" 48 | str2 := "bye bye" 49 | int1 := 1 50 | int2 := 2 51 | f1 := &Foo{ 52 | A: 1, 53 | B: []*string{&str1, &str2}, 54 | C: map[string]*int{ 55 | "A": &int1, 56 | "B": &int2, 57 | }, 58 | } 59 | 60 | // Do the copy 61 | var f2 Foo 62 | awsutil.Copy(&f2, f1) 63 | 64 | // Values are equal 65 | assert.Equal(t, f2.A, f1.A) 66 | assert.Equal(t, f2.B, f1.B) 67 | assert.Equal(t, f2.C, f1.C) 68 | 69 | // But pointers are not! 70 | str3 := "nothello" 71 | int3 := 57 72 | f2.A = 100 73 | f2.B[0] = &str3 74 | f2.C["B"] = &int3 75 | assert.NotEqual(t, f2.A, f1.A) 76 | assert.NotEqual(t, f2.B, f1.B) 77 | assert.NotEqual(t, f2.C, f1.C) 78 | } 79 | 80 | func TestCopyIgnoreNilMembers(t *testing.T) { 81 | type Foo struct { 82 | A *string 83 | B []string 84 | C map[string]string 85 | } 86 | 87 | f := &Foo{} 88 | assert.Nil(t, f.A) 89 | assert.Nil(t, f.B) 90 | assert.Nil(t, f.C) 91 | 92 | var f2 Foo 93 | awsutil.Copy(&f2, f) 94 | assert.Nil(t, f2.A) 95 | assert.Nil(t, f2.B) 96 | assert.Nil(t, f2.C) 97 | 98 | fcopy := awsutil.CopyOf(f) 99 | f3 := fcopy.(*Foo) 100 | assert.Nil(t, f3.A) 101 | assert.Nil(t, f3.B) 102 | assert.Nil(t, f3.C) 103 | } 104 | 105 | func TestCopyPrimitive(t *testing.T) { 106 | str := "hello" 107 | var s string 108 | awsutil.Copy(&s, &str) 109 | assert.Equal(t, "hello", s) 110 | } 111 | 112 | func TestCopyNil(t *testing.T) { 113 | var s string 114 | awsutil.Copy(&s, nil) 115 | assert.Equal(t, "", s) 116 | } 117 | 118 | func TestCopyReader(t *testing.T) { 119 | var buf io.Reader = bytes.NewReader([]byte("hello world")) 120 | var r io.Reader 121 | awsutil.Copy(&r, buf) 122 | b, err := ioutil.ReadAll(r) 123 | assert.NoError(t, err) 124 | assert.Equal(t, []byte("hello world"), b) 125 | 126 | // empty bytes because this is not a deep copy 127 | b, err = ioutil.ReadAll(buf) 128 | assert.NoError(t, err) 129 | assert.Equal(t, []byte(""), b) 130 | } 131 | 132 | func TestCopyDifferentStructs(t *testing.T) { 133 | type SrcFoo struct { 134 | A int 135 | B []*string 136 | C map[string]*int 137 | SrcUnique string 138 | SameNameDiffType int 139 | } 140 | type DstFoo struct { 141 | A int 142 | B []*string 143 | C map[string]*int 144 | DstUnique int 145 | SameNameDiffType string 146 | } 147 | 148 | // Create the initial value 149 | str1 := "hello" 150 | str2 := "bye bye" 151 | int1 := 1 152 | int2 := 2 153 | f1 := &SrcFoo{ 154 | A: 1, 155 | B: []*string{&str1, &str2}, 156 | C: map[string]*int{ 157 | "A": &int1, 158 | "B": &int2, 159 | }, 160 | SrcUnique: "unique", 161 | SameNameDiffType: 1, 162 | } 163 | 164 | // Do the copy 165 | var f2 DstFoo 166 | awsutil.Copy(&f2, f1) 167 | 168 | // Values are equal 169 | assert.Equal(t, f2.A, f1.A) 170 | assert.Equal(t, f2.B, f1.B) 171 | assert.Equal(t, f2.C, f1.C) 172 | assert.Equal(t, "unique", f1.SrcUnique) 173 | assert.Equal(t, 1, f1.SameNameDiffType) 174 | assert.Equal(t, 0, f2.DstUnique) 175 | assert.Equal(t, "", f2.SameNameDiffType) 176 | } 177 | 178 | func ExampleCopyOf() { 179 | type Foo struct { 180 | A int 181 | B []*string 182 | } 183 | 184 | // Create the initial value 185 | str1 := "hello" 186 | str2 := "bye bye" 187 | f1 := &Foo{A: 1, B: []*string{&str1, &str2}} 188 | 189 | // Do the copy 190 | v := awsutil.CopyOf(f1) 191 | var f2 *Foo = v.(*Foo) 192 | 193 | // Print the result 194 | fmt.Println(awsutil.Prettify(f2)) 195 | 196 | // Output: 197 | // { 198 | // A: 1, 199 | // B: ["hello","bye bye"] 200 | // } 201 | } 202 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/awsutil/path_value.go: -------------------------------------------------------------------------------- 1 | package awsutil 2 | 3 | import ( 4 | "reflect" 5 | "regexp" 6 | "strconv" 7 | "strings" 8 | ) 9 | 10 | var indexRe = regexp.MustCompile(`(.+)\[(-?\d+)?\]$`) 11 | 12 | // rValuesAtPath returns a slice of values found in value v. The values 13 | // in v are explored recursively so all nested values are collected. 14 | func rValuesAtPath(v interface{}, path string, create bool, caseSensitive bool) []reflect.Value { 15 | pathparts := strings.Split(path, "||") 16 | if len(pathparts) > 1 { 17 | for _, pathpart := range pathparts { 18 | vals := rValuesAtPath(v, pathpart, create, caseSensitive) 19 | if vals != nil && len(vals) > 0 { 20 | return vals 21 | } 22 | } 23 | return nil 24 | } 25 | 26 | values := []reflect.Value{reflect.Indirect(reflect.ValueOf(v))} 27 | components := strings.Split(path, ".") 28 | for len(values) > 0 && len(components) > 0 { 29 | var index *int64 30 | var indexStar bool 31 | c := strings.TrimSpace(components[0]) 32 | if c == "" { // no actual component, illegal syntax 33 | return nil 34 | } else if caseSensitive && c != "*" && strings.ToLower(c[0:1]) == c[0:1] { 35 | // TODO normalize case for user 36 | return nil // don't support unexported fields 37 | } 38 | 39 | // parse this component 40 | if m := indexRe.FindStringSubmatch(c); m != nil { 41 | c = m[1] 42 | if m[2] == "" { 43 | index = nil 44 | indexStar = true 45 | } else { 46 | i, _ := strconv.ParseInt(m[2], 10, 32) 47 | index = &i 48 | indexStar = false 49 | } 50 | } 51 | 52 | nextvals := []reflect.Value{} 53 | for _, value := range values { 54 | // pull component name out of struct member 55 | if value.Kind() != reflect.Struct { 56 | continue 57 | } 58 | 59 | if c == "*" { // pull all members 60 | for i := 0; i < value.NumField(); i++ { 61 | if f := reflect.Indirect(value.Field(i)); f.IsValid() { 62 | nextvals = append(nextvals, f) 63 | } 64 | } 65 | continue 66 | } 67 | 68 | value = value.FieldByNameFunc(func(name string) bool { 69 | if c == name { 70 | return true 71 | } else if !caseSensitive && strings.ToLower(name) == strings.ToLower(c) { 72 | return true 73 | } 74 | return false 75 | }) 76 | 77 | if create && value.Kind() == reflect.Ptr && value.IsNil() { 78 | value.Set(reflect.New(value.Type().Elem())) 79 | value = value.Elem() 80 | } else { 81 | value = reflect.Indirect(value) 82 | } 83 | 84 | if value.Kind() == reflect.Slice || value.Kind() == reflect.Map { 85 | if !create && value.IsNil() { 86 | value = reflect.ValueOf(nil) 87 | } 88 | } 89 | 90 | if value.IsValid() { 91 | nextvals = append(nextvals, value) 92 | } 93 | } 94 | values = nextvals 95 | 96 | if indexStar || index != nil { 97 | nextvals = []reflect.Value{} 98 | for _, value := range values { 99 | value := reflect.Indirect(value) 100 | if value.Kind() != reflect.Slice { 101 | continue 102 | } 103 | 104 | if indexStar { // grab all indices 105 | for i := 0; i < value.Len(); i++ { 106 | idx := reflect.Indirect(value.Index(i)) 107 | if idx.IsValid() { 108 | nextvals = append(nextvals, idx) 109 | } 110 | } 111 | continue 112 | } 113 | 114 | // pull out index 115 | i := int(*index) 116 | if i >= value.Len() { // check out of bounds 117 | if create { 118 | // TODO resize slice 119 | } else { 120 | continue 121 | } 122 | } else if i < 0 { // support negative indexing 123 | i = value.Len() + i 124 | } 125 | value = reflect.Indirect(value.Index(i)) 126 | 127 | if value.Kind() == reflect.Slice || value.Kind() == reflect.Map { 128 | if !create && value.IsNil() { 129 | value = reflect.ValueOf(nil) 130 | } 131 | } 132 | 133 | if value.IsValid() { 134 | nextvals = append(nextvals, value) 135 | } 136 | } 137 | values = nextvals 138 | } 139 | 140 | components = components[1:] 141 | } 142 | return values 143 | } 144 | 145 | // ValuesAtPath returns a list of objects at the lexical path inside of a structure 146 | func ValuesAtPath(i interface{}, path string) []interface{} { 147 | if rvals := rValuesAtPath(i, path, false, true); rvals != nil { 148 | vals := make([]interface{}, len(rvals)) 149 | for i, rval := range rvals { 150 | vals[i] = rval.Interface() 151 | } 152 | return vals 153 | } 154 | return nil 155 | } 156 | 157 | // ValuesAtAnyPath returns a list of objects at the case-insensitive lexical 158 | // path inside of a structure 159 | func ValuesAtAnyPath(i interface{}, path string) []interface{} { 160 | if rvals := rValuesAtPath(i, path, false, false); rvals != nil { 161 | vals := make([]interface{}, len(rvals)) 162 | for i, rval := range rvals { 163 | vals[i] = rval.Interface() 164 | } 165 | return vals 166 | } 167 | return nil 168 | } 169 | 170 | // SetValueAtPath sets an object at the lexical path inside of a structure 171 | func SetValueAtPath(i interface{}, path string, v interface{}) { 172 | if rvals := rValuesAtPath(i, path, true, true); rvals != nil { 173 | for _, rval := range rvals { 174 | rval.Set(reflect.ValueOf(v)) 175 | } 176 | } 177 | } 178 | 179 | // SetValueAtAnyPath sets an object at the case insensitive lexical path inside 180 | // of a structure 181 | func SetValueAtAnyPath(i interface{}, path string, v interface{}) { 182 | if rvals := rValuesAtPath(i, path, true, false); rvals != nil { 183 | for _, rval := range rvals { 184 | rval.Set(reflect.ValueOf(v)) 185 | } 186 | } 187 | } 188 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/awsutil/path_value_test.go: -------------------------------------------------------------------------------- 1 | package awsutil_test 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/rlister/let-me-in/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/awsutil" 7 | "github.com/stretchr/testify/assert" 8 | ) 9 | 10 | type Struct struct { 11 | A []Struct 12 | z []Struct 13 | B *Struct 14 | D *Struct 15 | C string 16 | } 17 | 18 | var data = Struct{ 19 | A: []Struct{{C: "value1"}, {C: "value2"}, {C: "value3"}}, 20 | z: []Struct{{C: "value1"}, {C: "value2"}, {C: "value3"}}, 21 | B: &Struct{B: &Struct{C: "terminal"}, D: &Struct{C: "terminal2"}}, 22 | C: "initial", 23 | } 24 | 25 | func TestValueAtPathSuccess(t *testing.T) { 26 | assert.Equal(t, []interface{}{"initial"}, awsutil.ValuesAtPath(data, "C")) 27 | assert.Equal(t, []interface{}{"value1"}, awsutil.ValuesAtPath(data, "A[0].C")) 28 | assert.Equal(t, []interface{}{"value2"}, awsutil.ValuesAtPath(data, "A[1].C")) 29 | assert.Equal(t, []interface{}{"value3"}, awsutil.ValuesAtPath(data, "A[2].C")) 30 | assert.Equal(t, []interface{}{"value3"}, awsutil.ValuesAtAnyPath(data, "a[2].c")) 31 | assert.Equal(t, []interface{}{"value3"}, awsutil.ValuesAtPath(data, "A[-1].C")) 32 | assert.Equal(t, []interface{}{"value1", "value2", "value3"}, awsutil.ValuesAtPath(data, "A[].C")) 33 | assert.Equal(t, []interface{}{"terminal"}, awsutil.ValuesAtPath(data, "B . B . C")) 34 | assert.Equal(t, []interface{}{"terminal", "terminal2"}, awsutil.ValuesAtPath(data, "B.*.C")) 35 | assert.Equal(t, []interface{}{"initial"}, awsutil.ValuesAtPath(data, "A.D.X || C")) 36 | } 37 | 38 | func TestValueAtPathFailure(t *testing.T) { 39 | assert.Equal(t, []interface{}(nil), awsutil.ValuesAtPath(data, "C.x")) 40 | assert.Equal(t, []interface{}(nil), awsutil.ValuesAtPath(data, ".x")) 41 | assert.Equal(t, []interface{}{}, awsutil.ValuesAtPath(data, "X.Y.Z")) 42 | assert.Equal(t, []interface{}{}, awsutil.ValuesAtPath(data, "A[100].C")) 43 | assert.Equal(t, []interface{}{}, awsutil.ValuesAtPath(data, "A[3].C")) 44 | assert.Equal(t, []interface{}{}, awsutil.ValuesAtPath(data, "B.B.C.Z")) 45 | assert.Equal(t, []interface{}(nil), awsutil.ValuesAtPath(data, "z[-1].C")) 46 | assert.Equal(t, []interface{}{}, awsutil.ValuesAtPath(nil, "A.B.C")) 47 | assert.Equal(t, []interface{}{}, awsutil.ValuesAtPath(Struct{}, "A")) 48 | } 49 | 50 | func TestSetValueAtPathSuccess(t *testing.T) { 51 | var s Struct 52 | awsutil.SetValueAtPath(&s, "C", "test1") 53 | awsutil.SetValueAtPath(&s, "B.B.C", "test2") 54 | awsutil.SetValueAtPath(&s, "B.D.C", "test3") 55 | assert.Equal(t, "test1", s.C) 56 | assert.Equal(t, "test2", s.B.B.C) 57 | assert.Equal(t, "test3", s.B.D.C) 58 | 59 | awsutil.SetValueAtPath(&s, "B.*.C", "test0") 60 | assert.Equal(t, "test0", s.B.B.C) 61 | assert.Equal(t, "test0", s.B.D.C) 62 | 63 | var s2 Struct 64 | awsutil.SetValueAtAnyPath(&s2, "b.b.c", "test0") 65 | assert.Equal(t, "test0", s2.B.B.C) 66 | awsutil.SetValueAtAnyPath(&s2, "A", []Struct{{}}) 67 | assert.Equal(t, []Struct{{}}, s2.A) 68 | } 69 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/awsutil/prettify.go: -------------------------------------------------------------------------------- 1 | package awsutil 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | "io" 7 | "reflect" 8 | "strings" 9 | ) 10 | 11 | // Prettify returns the string representation of a value. 12 | func Prettify(i interface{}) string { 13 | var buf bytes.Buffer 14 | prettify(reflect.ValueOf(i), 0, &buf) 15 | return buf.String() 16 | } 17 | 18 | // prettify will recursively walk value v to build a textual 19 | // representation of the value. 20 | func prettify(v reflect.Value, indent int, buf *bytes.Buffer) { 21 | for v.Kind() == reflect.Ptr { 22 | v = v.Elem() 23 | } 24 | 25 | switch v.Kind() { 26 | case reflect.Struct: 27 | strtype := v.Type().String() 28 | if strtype == "time.Time" { 29 | fmt.Fprintf(buf, "%s", v.Interface()) 30 | break 31 | } else if strings.HasPrefix(strtype, "io.") { 32 | buf.WriteString("") 33 | break 34 | } 35 | 36 | buf.WriteString("{\n") 37 | 38 | names := []string{} 39 | for i := 0; i < v.Type().NumField(); i++ { 40 | name := v.Type().Field(i).Name 41 | f := v.Field(i) 42 | if name[0:1] == strings.ToLower(name[0:1]) { 43 | continue // ignore unexported fields 44 | } 45 | if (f.Kind() == reflect.Ptr || f.Kind() == reflect.Slice || f.Kind() == reflect.Map) && f.IsNil() { 46 | continue // ignore unset fields 47 | } 48 | names = append(names, name) 49 | } 50 | 51 | for i, n := range names { 52 | val := v.FieldByName(n) 53 | buf.WriteString(strings.Repeat(" ", indent+2)) 54 | buf.WriteString(n + ": ") 55 | prettify(val, indent+2, buf) 56 | 57 | if i < len(names)-1 { 58 | buf.WriteString(",\n") 59 | } 60 | } 61 | 62 | buf.WriteString("\n" + strings.Repeat(" ", indent) + "}") 63 | case reflect.Slice: 64 | nl, id, id2 := "", "", "" 65 | if v.Len() > 3 { 66 | nl, id, id2 = "\n", strings.Repeat(" ", indent), strings.Repeat(" ", indent+2) 67 | } 68 | buf.WriteString("[" + nl) 69 | for i := 0; i < v.Len(); i++ { 70 | buf.WriteString(id2) 71 | prettify(v.Index(i), indent+2, buf) 72 | 73 | if i < v.Len()-1 { 74 | buf.WriteString("," + nl) 75 | } 76 | } 77 | 78 | buf.WriteString(nl + id + "]") 79 | case reflect.Map: 80 | buf.WriteString("{\n") 81 | 82 | for i, k := range v.MapKeys() { 83 | buf.WriteString(strings.Repeat(" ", indent+2)) 84 | buf.WriteString(k.String() + ": ") 85 | prettify(v.MapIndex(k), indent+2, buf) 86 | 87 | if i < v.Len()-1 { 88 | buf.WriteString(",\n") 89 | } 90 | } 91 | 92 | buf.WriteString("\n" + strings.Repeat(" ", indent) + "}") 93 | default: 94 | format := "%v" 95 | switch v.Interface().(type) { 96 | case string: 97 | format = "%q" 98 | case io.ReadSeeker, io.Reader: 99 | format = "buffer(%p)" 100 | } 101 | fmt.Fprintf(buf, format, v.Interface()) 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/config_test.go: -------------------------------------------------------------------------------- 1 | package aws 2 | 3 | import ( 4 | "net/http" 5 | "reflect" 6 | "testing" 7 | 8 | "github.com/rlister/let-me-in/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/credentials" 9 | ) 10 | 11 | var testCredentials = credentials.NewStaticCredentials("AKID", "SECRET", "SESSION") 12 | 13 | var copyTestConfig = Config{ 14 | Credentials: testCredentials, 15 | Endpoint: String("CopyTestEndpoint"), 16 | Region: String("COPY_TEST_AWS_REGION"), 17 | DisableSSL: Bool(true), 18 | HTTPClient: http.DefaultClient, 19 | LogLevel: LogLevel(LogDebug), 20 | Logger: NewDefaultLogger(), 21 | MaxRetries: Int(DefaultRetries), 22 | DisableParamValidation: Bool(true), 23 | DisableComputeChecksums: Bool(true), 24 | S3ForcePathStyle: Bool(true), 25 | } 26 | 27 | func TestCopy(t *testing.T) { 28 | want := copyTestConfig 29 | got := copyTestConfig.Copy() 30 | if !reflect.DeepEqual(*got, want) { 31 | t.Errorf("Copy() = %+v", got) 32 | t.Errorf(" want %+v", want) 33 | } 34 | } 35 | 36 | func TestCopyReturnsNewInstance(t *testing.T) { 37 | want := copyTestConfig 38 | got := copyTestConfig.Copy() 39 | if got == &want { 40 | t.Errorf("Copy() = %p; want different instance as source %p", got, &want) 41 | } 42 | } 43 | 44 | var mergeTestZeroValueConfig = Config{} 45 | 46 | var mergeTestConfig = Config{ 47 | Credentials: testCredentials, 48 | Endpoint: String("MergeTestEndpoint"), 49 | Region: String("MERGE_TEST_AWS_REGION"), 50 | DisableSSL: Bool(true), 51 | HTTPClient: http.DefaultClient, 52 | LogLevel: LogLevel(LogDebug), 53 | Logger: NewDefaultLogger(), 54 | MaxRetries: Int(10), 55 | DisableParamValidation: Bool(true), 56 | DisableComputeChecksums: Bool(true), 57 | S3ForcePathStyle: Bool(true), 58 | } 59 | 60 | var mergeTests = []struct { 61 | cfg *Config 62 | in *Config 63 | want *Config 64 | }{ 65 | {&Config{}, nil, &Config{}}, 66 | {&Config{}, &mergeTestZeroValueConfig, &Config{}}, 67 | {&Config{}, &mergeTestConfig, &mergeTestConfig}, 68 | } 69 | 70 | func TestMerge(t *testing.T) { 71 | for i, tt := range mergeTests { 72 | got := tt.cfg.Merge(tt.in) 73 | if !reflect.DeepEqual(got, tt.want) { 74 | t.Errorf("Config %d %+v", i, tt.cfg) 75 | t.Errorf(" Merge(%+v)", tt.in) 76 | t.Errorf(" got %+v", got) 77 | t.Errorf(" want %+v", tt.want) 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/corehandlers/handlers.go: -------------------------------------------------------------------------------- 1 | package corehandlers 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | "io" 7 | "io/ioutil" 8 | "net/http" 9 | "net/url" 10 | "regexp" 11 | "strconv" 12 | 13 | "github.com/rlister/let-me-in/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws" 14 | "github.com/rlister/let-me-in/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/awserr" 15 | "github.com/rlister/let-me-in/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/request" 16 | ) 17 | 18 | // Interface for matching types which also have a Len method. 19 | type lener interface { 20 | Len() int 21 | } 22 | 23 | // BuildContentLength builds the content length of a request based on the body, 24 | // or will use the HTTPRequest.Header's "Content-Length" if defined. If unable 25 | // to determine request body length and no "Content-Length" was specified it will panic. 26 | var BuildContentLengthHandler = request.NamedHandler{"core.BuildContentLengthHandler", func(r *request.Request) { 27 | if slength := r.HTTPRequest.Header.Get("Content-Length"); slength != "" { 28 | length, _ := strconv.ParseInt(slength, 10, 64) 29 | r.HTTPRequest.ContentLength = length 30 | return 31 | } 32 | 33 | var length int64 34 | switch body := r.Body.(type) { 35 | case nil: 36 | length = 0 37 | case lener: 38 | length = int64(body.Len()) 39 | case io.Seeker: 40 | r.BodyStart, _ = body.Seek(0, 1) 41 | end, _ := body.Seek(0, 2) 42 | body.Seek(r.BodyStart, 0) // make sure to seek back to original location 43 | length = end - r.BodyStart 44 | default: 45 | panic("Cannot get length of body, must provide `ContentLength`") 46 | } 47 | 48 | r.HTTPRequest.ContentLength = length 49 | r.HTTPRequest.Header.Set("Content-Length", fmt.Sprintf("%d", length)) 50 | }} 51 | 52 | // UserAgentHandler is a request handler for injecting User agent into requests. 53 | var UserAgentHandler = request.NamedHandler{"core.UserAgentHandler", func(r *request.Request) { 54 | r.HTTPRequest.Header.Set("User-Agent", aws.SDKName+"/"+aws.SDKVersion) 55 | }} 56 | 57 | var reStatusCode = regexp.MustCompile(`^(\d{3})`) 58 | 59 | // SendHandler is a request handler to send service request using HTTP client. 60 | var SendHandler = request.NamedHandler{"core.SendHandler", func(r *request.Request) { 61 | var err error 62 | r.HTTPResponse, err = r.Service.Config.HTTPClient.Do(r.HTTPRequest) 63 | if err != nil { 64 | // Capture the case where url.Error is returned for error processing 65 | // response. e.g. 301 without location header comes back as string 66 | // error and r.HTTPResponse is nil. Other url redirect errors will 67 | // comeback in a similar method. 68 | if e, ok := err.(*url.Error); ok && e.Err != nil { 69 | if s := reStatusCode.FindStringSubmatch(e.Err.Error()); s != nil { 70 | code, _ := strconv.ParseInt(s[1], 10, 64) 71 | r.HTTPResponse = &http.Response{ 72 | StatusCode: int(code), 73 | Status: http.StatusText(int(code)), 74 | Body: ioutil.NopCloser(bytes.NewReader([]byte{})), 75 | } 76 | return 77 | } 78 | } 79 | if r.HTTPResponse == nil { 80 | // Add a dummy request response object to ensure the HTTPResponse 81 | // value is consistent. 82 | r.HTTPResponse = &http.Response{ 83 | StatusCode: int(0), 84 | Status: http.StatusText(int(0)), 85 | Body: ioutil.NopCloser(bytes.NewReader([]byte{})), 86 | } 87 | } 88 | // Catch all other request errors. 89 | r.Error = awserr.New("RequestError", "send request failed", err) 90 | r.Retryable = aws.Bool(true) // network errors are retryable 91 | } 92 | }} 93 | 94 | // ValidateResponseHandler is a request handler to validate service response. 95 | var ValidateResponseHandler = request.NamedHandler{"core.ValidateResponseHandler", func(r *request.Request) { 96 | if r.HTTPResponse.StatusCode == 0 || r.HTTPResponse.StatusCode >= 300 { 97 | // this may be replaced by an UnmarshalError handler 98 | r.Error = awserr.New("UnknownError", "unknown error", nil) 99 | } 100 | }} 101 | 102 | // AfterRetryHandler performs final checks to determine if the request should 103 | // be retried and how long to delay. 104 | var AfterRetryHandler = request.NamedHandler{"core.AfterRetryHandler", func(r *request.Request) { 105 | // If one of the other handlers already set the retry state 106 | // we don't want to override it based on the service's state 107 | if r.Retryable == nil { 108 | r.Retryable = aws.Bool(r.ShouldRetry(r)) 109 | } 110 | 111 | if r.WillRetry() { 112 | r.RetryDelay = r.RetryRules(r) 113 | r.Service.Config.SleepDelay(r.RetryDelay) 114 | 115 | // when the expired token exception occurs the credentials 116 | // need to be expired locally so that the next request to 117 | // get credentials will trigger a credentials refresh. 118 | if r.IsErrorExpired() { 119 | r.Service.Config.Credentials.Expire() 120 | } 121 | 122 | r.RetryCount++ 123 | r.Error = nil 124 | } 125 | }} 126 | 127 | // ValidateEndpointHandler is a request handler to validate a request had the 128 | // appropriate Region and Endpoint set. Will set r.Error if the endpoint or 129 | // region is not valid. 130 | var ValidateEndpointHandler = request.NamedHandler{"core.ValidateEndpointHandler", func(r *request.Request) { 131 | if r.Service.SigningRegion == "" && aws.StringValue(r.Service.Config.Region) == "" { 132 | r.Error = aws.ErrMissingRegion 133 | } else if r.Service.Endpoint == "" { 134 | r.Error = aws.ErrMissingEndpoint 135 | } 136 | }} 137 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/corehandlers/handlers_test.go: -------------------------------------------------------------------------------- 1 | package corehandlers_test 2 | 3 | import ( 4 | "fmt" 5 | "net/http" 6 | "os" 7 | "testing" 8 | 9 | "github.com/stretchr/testify/assert" 10 | 11 | "github.com/rlister/let-me-in/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws" 12 | "github.com/rlister/let-me-in/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/awserr" 13 | "github.com/rlister/let-me-in/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/corehandlers" 14 | "github.com/rlister/let-me-in/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/credentials" 15 | "github.com/rlister/let-me-in/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/request" 16 | "github.com/rlister/let-me-in/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/service" 17 | ) 18 | 19 | func TestValidateEndpointHandler(t *testing.T) { 20 | os.Clearenv() 21 | svc := service.New(aws.NewConfig().WithRegion("us-west-2")) 22 | svc.Handlers.Clear() 23 | svc.Handlers.Validate.PushBackNamed(corehandlers.ValidateEndpointHandler) 24 | 25 | req := svc.NewRequest(&request.Operation{Name: "Operation"}, nil, nil) 26 | err := req.Build() 27 | 28 | assert.NoError(t, err) 29 | } 30 | 31 | func TestValidateEndpointHandlerErrorRegion(t *testing.T) { 32 | os.Clearenv() 33 | svc := service.New(nil) 34 | svc.Handlers.Clear() 35 | svc.Handlers.Validate.PushBackNamed(corehandlers.ValidateEndpointHandler) 36 | 37 | req := svc.NewRequest(&request.Operation{Name: "Operation"}, nil, nil) 38 | err := req.Build() 39 | 40 | assert.Error(t, err) 41 | assert.Equal(t, aws.ErrMissingRegion, err) 42 | } 43 | 44 | type mockCredsProvider struct { 45 | expired bool 46 | retrieveCalled bool 47 | } 48 | 49 | func (m *mockCredsProvider) Retrieve() (credentials.Value, error) { 50 | m.retrieveCalled = true 51 | return credentials.Value{}, nil 52 | } 53 | 54 | func (m *mockCredsProvider) IsExpired() bool { 55 | return m.expired 56 | } 57 | 58 | func TestAfterRetryRefreshCreds(t *testing.T) { 59 | os.Clearenv() 60 | credProvider := &mockCredsProvider{} 61 | svc := service.New(&aws.Config{Credentials: credentials.NewCredentials(credProvider), MaxRetries: aws.Int(1)}) 62 | 63 | svc.Handlers.Clear() 64 | svc.Handlers.ValidateResponse.PushBack(func(r *request.Request) { 65 | r.Error = awserr.New("UnknownError", "", nil) 66 | r.HTTPResponse = &http.Response{StatusCode: 400} 67 | }) 68 | svc.Handlers.UnmarshalError.PushBack(func(r *request.Request) { 69 | r.Error = awserr.New("ExpiredTokenException", "", nil) 70 | }) 71 | svc.Handlers.AfterRetry.PushBackNamed(corehandlers.AfterRetryHandler) 72 | 73 | assert.True(t, svc.Config.Credentials.IsExpired(), "Expect to start out expired") 74 | assert.False(t, credProvider.retrieveCalled) 75 | 76 | req := svc.NewRequest(&request.Operation{Name: "Operation"}, nil, nil) 77 | req.Send() 78 | 79 | assert.True(t, svc.Config.Credentials.IsExpired()) 80 | assert.False(t, credProvider.retrieveCalled) 81 | 82 | _, err := svc.Config.Credentials.Get() 83 | assert.NoError(t, err) 84 | assert.True(t, credProvider.retrieveCalled) 85 | } 86 | 87 | type testSendHandlerTransport struct{} 88 | 89 | func (t *testSendHandlerTransport) RoundTrip(r *http.Request) (*http.Response, error) { 90 | return nil, fmt.Errorf("mock error") 91 | } 92 | 93 | func TestSendHandlerError(t *testing.T) { 94 | svc := service.New(&aws.Config{ 95 | HTTPClient: &http.Client{ 96 | Transport: &testSendHandlerTransport{}, 97 | }, 98 | }) 99 | svc.Handlers.Clear() 100 | svc.Handlers.Send.PushBackNamed(corehandlers.SendHandler) 101 | r := svc.NewRequest(&request.Operation{Name: "Operation"}, nil, nil) 102 | 103 | r.Send() 104 | 105 | assert.Error(t, r.Error) 106 | assert.NotNil(t, r.HTTPResponse) 107 | } 108 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/corehandlers/param_validator.go: -------------------------------------------------------------------------------- 1 | package corehandlers 2 | 3 | import ( 4 | "fmt" 5 | "reflect" 6 | "strings" 7 | 8 | "github.com/rlister/let-me-in/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/awserr" 9 | "github.com/rlister/let-me-in/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/request" 10 | ) 11 | 12 | // ValidateParameters is a request handler to validate the input parameters. 13 | // Validating parameters only has meaning if done prior to the request being sent. 14 | var ValidateParametersHandler = request.NamedHandler{"core.ValidateParametersHandler", func(r *request.Request) { 15 | if r.ParamsFilled() { 16 | v := validator{errors: []string{}} 17 | v.validateAny(reflect.ValueOf(r.Params), "") 18 | 19 | if count := len(v.errors); count > 0 { 20 | format := "%d validation errors:\n- %s" 21 | msg := fmt.Sprintf(format, count, strings.Join(v.errors, "\n- ")) 22 | r.Error = awserr.New("InvalidParameter", msg, nil) 23 | } 24 | } 25 | }} 26 | 27 | // A validator validates values. Collects validations errors which occurs. 28 | type validator struct { 29 | errors []string 30 | } 31 | 32 | // validateAny will validate any struct, slice or map type. All validations 33 | // are also performed recursively for nested types. 34 | func (v *validator) validateAny(value reflect.Value, path string) { 35 | value = reflect.Indirect(value) 36 | if !value.IsValid() { 37 | return 38 | } 39 | 40 | switch value.Kind() { 41 | case reflect.Struct: 42 | v.validateStruct(value, path) 43 | case reflect.Slice: 44 | for i := 0; i < value.Len(); i++ { 45 | v.validateAny(value.Index(i), path+fmt.Sprintf("[%d]", i)) 46 | } 47 | case reflect.Map: 48 | for _, n := range value.MapKeys() { 49 | v.validateAny(value.MapIndex(n), path+fmt.Sprintf("[%q]", n.String())) 50 | } 51 | } 52 | } 53 | 54 | // validateStruct will validate the struct value's fields. If the structure has 55 | // nested types those types will be validated also. 56 | func (v *validator) validateStruct(value reflect.Value, path string) { 57 | prefix := "." 58 | if path == "" { 59 | prefix = "" 60 | } 61 | 62 | for i := 0; i < value.Type().NumField(); i++ { 63 | f := value.Type().Field(i) 64 | if strings.ToLower(f.Name[0:1]) == f.Name[0:1] { 65 | continue 66 | } 67 | fvalue := value.FieldByName(f.Name) 68 | 69 | notset := false 70 | if f.Tag.Get("required") != "" { 71 | switch fvalue.Kind() { 72 | case reflect.Ptr, reflect.Slice, reflect.Map: 73 | if fvalue.IsNil() { 74 | notset = true 75 | } 76 | default: 77 | if !fvalue.IsValid() { 78 | notset = true 79 | } 80 | } 81 | } 82 | 83 | if notset { 84 | msg := "missing required parameter: " + path + prefix + f.Name 85 | v.errors = append(v.errors, msg) 86 | } else { 87 | v.validateAny(fvalue, path+prefix+f.Name) 88 | } 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/corehandlers/param_validator_test.go: -------------------------------------------------------------------------------- 1 | package corehandlers_test 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/assert" 7 | 8 | "github.com/rlister/let-me-in/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws" 9 | "github.com/rlister/let-me-in/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/awserr" 10 | "github.com/rlister/let-me-in/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/corehandlers" 11 | "github.com/rlister/let-me-in/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/request" 12 | "github.com/rlister/let-me-in/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/service" 13 | "github.com/rlister/let-me-in/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/service/serviceinfo" 14 | ) 15 | 16 | var testSvc = func() *service.Service { 17 | s := &service.Service{ 18 | ServiceInfo: serviceinfo.ServiceInfo{ 19 | Config: &aws.Config{}, 20 | ServiceName: "mock-service", 21 | APIVersion: "2015-01-01", 22 | }, 23 | } 24 | return s 25 | }() 26 | 27 | type StructShape struct { 28 | RequiredList []*ConditionalStructShape `required:"true"` 29 | RequiredMap map[string]*ConditionalStructShape `required:"true"` 30 | RequiredBool *bool `required:"true"` 31 | OptionalStruct *ConditionalStructShape 32 | 33 | hiddenParameter *string 34 | 35 | metadataStructureShape 36 | } 37 | 38 | type metadataStructureShape struct { 39 | SDKShapeTraits bool 40 | } 41 | 42 | type ConditionalStructShape struct { 43 | Name *string `required:"true"` 44 | SDKShapeTraits bool 45 | } 46 | 47 | func TestNoErrors(t *testing.T) { 48 | input := &StructShape{ 49 | RequiredList: []*ConditionalStructShape{}, 50 | RequiredMap: map[string]*ConditionalStructShape{ 51 | "key1": {Name: aws.String("Name")}, 52 | "key2": {Name: aws.String("Name")}, 53 | }, 54 | RequiredBool: aws.Bool(true), 55 | OptionalStruct: &ConditionalStructShape{Name: aws.String("Name")}, 56 | } 57 | 58 | req := testSvc.NewRequest(&request.Operation{}, input, nil) 59 | corehandlers.ValidateParametersHandler.Fn(req) 60 | assert.NoError(t, req.Error) 61 | } 62 | 63 | func TestMissingRequiredParameters(t *testing.T) { 64 | input := &StructShape{} 65 | req := testSvc.NewRequest(&request.Operation{}, input, nil) 66 | corehandlers.ValidateParametersHandler.Fn(req) 67 | 68 | assert.Error(t, req.Error) 69 | assert.Equal(t, "InvalidParameter", req.Error.(awserr.Error).Code()) 70 | assert.Equal(t, "3 validation errors:\n- missing required parameter: RequiredList\n- missing required parameter: RequiredMap\n- missing required parameter: RequiredBool", req.Error.(awserr.Error).Message()) 71 | } 72 | 73 | func TestNestedMissingRequiredParameters(t *testing.T) { 74 | input := &StructShape{ 75 | RequiredList: []*ConditionalStructShape{{}}, 76 | RequiredMap: map[string]*ConditionalStructShape{ 77 | "key1": {Name: aws.String("Name")}, 78 | "key2": {}, 79 | }, 80 | RequiredBool: aws.Bool(true), 81 | OptionalStruct: &ConditionalStructShape{}, 82 | } 83 | 84 | req := testSvc.NewRequest(&request.Operation{}, input, nil) 85 | corehandlers.ValidateParametersHandler.Fn(req) 86 | 87 | assert.Error(t, req.Error) 88 | assert.Equal(t, "InvalidParameter", req.Error.(awserr.Error).Code()) 89 | assert.Equal(t, "3 validation errors:\n- missing required parameter: RequiredList[0].Name\n- missing required parameter: RequiredMap[\"key2\"].Name\n- missing required parameter: OptionalStruct.Name", req.Error.(awserr.Error).Message()) 90 | 91 | } 92 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/credentials/chain_provider.go: -------------------------------------------------------------------------------- 1 | package credentials 2 | 3 | import ( 4 | "github.com/rlister/let-me-in/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/awserr" 5 | ) 6 | 7 | var ( 8 | // ErrNoValidProvidersFoundInChain Is returned when there are no valid 9 | // providers in the ChainProvider. 10 | // 11 | // @readonly 12 | ErrNoValidProvidersFoundInChain = awserr.New("NoCredentialProviders", "no valid providers in chain", nil) 13 | ) 14 | 15 | // A ChainProvider will search for a provider which returns credentials 16 | // and cache that provider until Retrieve is called again. 17 | // 18 | // The ChainProvider provides a way of chaining multiple providers together 19 | // which will pick the first available using priority order of the Providers 20 | // in the list. 21 | // 22 | // If none of the Providers retrieve valid credentials Value, ChainProvider's 23 | // Retrieve() will return the error ErrNoValidProvidersFoundInChain. 24 | // 25 | // If a Provider is found which returns valid credentials Value ChainProvider 26 | // will cache that Provider for all calls to IsExpired(), until Retrieve is 27 | // called again. 28 | // 29 | // Example of ChainProvider to be used with an EnvProvider and EC2RoleProvider. 30 | // In this example EnvProvider will first check if any credentials are available 31 | // vai the environment variables. If there are none ChainProvider will check 32 | // the next Provider in the list, EC2RoleProvider in this case. If EC2RoleProvider 33 | // does not return any credentials ChainProvider will return the error 34 | // ErrNoValidProvidersFoundInChain 35 | // 36 | // creds := NewChainCredentials( 37 | // []Provider{ 38 | // &EnvProvider{}, 39 | // &EC2RoleProvider{}, 40 | // }) 41 | // 42 | // // Usage of ChainCredentials with aws.Config 43 | // svc := ec2.New(&aws.Config{Credentials: creds}) 44 | // 45 | type ChainProvider struct { 46 | Providers []Provider 47 | curr Provider 48 | } 49 | 50 | // NewChainCredentials returns a pointer to a new Credentials object 51 | // wrapping a chain of providers. 52 | func NewChainCredentials(providers []Provider) *Credentials { 53 | return NewCredentials(&ChainProvider{ 54 | Providers: append([]Provider{}, providers...), 55 | }) 56 | } 57 | 58 | // Retrieve returns the credentials value or error if no provider returned 59 | // without error. 60 | // 61 | // If a provider is found it will be cached and any calls to IsExpired() 62 | // will return the expired state of the cached provider. 63 | func (c *ChainProvider) Retrieve() (Value, error) { 64 | for _, p := range c.Providers { 65 | if creds, err := p.Retrieve(); err == nil { 66 | c.curr = p 67 | return creds, nil 68 | } 69 | } 70 | c.curr = nil 71 | 72 | // TODO better error reporting. maybe report error for each failed retrieve? 73 | 74 | return Value{}, ErrNoValidProvidersFoundInChain 75 | } 76 | 77 | // IsExpired will returned the expired state of the currently cached provider 78 | // if there is one. If there is no current provider, true will be returned. 79 | func (c *ChainProvider) IsExpired() bool { 80 | if c.curr != nil { 81 | return c.curr.IsExpired() 82 | } 83 | 84 | return true 85 | } 86 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/credentials/chain_provider_test.go: -------------------------------------------------------------------------------- 1 | package credentials 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/rlister/let-me-in/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/awserr" 7 | "github.com/stretchr/testify/assert" 8 | ) 9 | 10 | func TestChainProviderGet(t *testing.T) { 11 | p := &ChainProvider{ 12 | Providers: []Provider{ 13 | &stubProvider{err: awserr.New("FirstError", "first provider error", nil)}, 14 | &stubProvider{err: awserr.New("SecondError", "second provider error", nil)}, 15 | &stubProvider{ 16 | creds: Value{ 17 | AccessKeyID: "AKID", 18 | SecretAccessKey: "SECRET", 19 | SessionToken: "", 20 | }, 21 | }, 22 | }, 23 | } 24 | 25 | creds, err := p.Retrieve() 26 | assert.Nil(t, err, "Expect no error") 27 | assert.Equal(t, "AKID", creds.AccessKeyID, "Expect access key ID to match") 28 | assert.Equal(t, "SECRET", creds.SecretAccessKey, "Expect secret access key to match") 29 | assert.Empty(t, creds.SessionToken, "Expect session token to be empty") 30 | } 31 | 32 | func TestChainProviderIsExpired(t *testing.T) { 33 | stubProvider := &stubProvider{expired: true} 34 | p := &ChainProvider{ 35 | Providers: []Provider{ 36 | stubProvider, 37 | }, 38 | } 39 | 40 | assert.True(t, p.IsExpired(), "Expect expired to be true before any Retrieve") 41 | _, err := p.Retrieve() 42 | assert.Nil(t, err, "Expect no error") 43 | assert.False(t, p.IsExpired(), "Expect not expired after retrieve") 44 | 45 | stubProvider.expired = true 46 | assert.True(t, p.IsExpired(), "Expect return of expired provider") 47 | 48 | _, err = p.Retrieve() 49 | assert.False(t, p.IsExpired(), "Expect not expired after retrieve") 50 | } 51 | 52 | func TestChainProviderWithNoProvider(t *testing.T) { 53 | p := &ChainProvider{ 54 | Providers: []Provider{}, 55 | } 56 | 57 | assert.True(t, p.IsExpired(), "Expect expired with no providers") 58 | _, err := p.Retrieve() 59 | assert.Equal(t, ErrNoValidProvidersFoundInChain, err, "Expect no providers error returned") 60 | } 61 | 62 | func TestChainProviderWithNoValidProvider(t *testing.T) { 63 | p := &ChainProvider{ 64 | Providers: []Provider{ 65 | &stubProvider{err: awserr.New("FirstError", "first provider error", nil)}, 66 | &stubProvider{err: awserr.New("SecondError", "second provider error", nil)}, 67 | }, 68 | } 69 | 70 | assert.True(t, p.IsExpired(), "Expect expired with no providers") 71 | _, err := p.Retrieve() 72 | assert.Equal(t, ErrNoValidProvidersFoundInChain, err, "Expect no providers error returned") 73 | } 74 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/credentials/credentials_test.go: -------------------------------------------------------------------------------- 1 | package credentials 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/rlister/let-me-in/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/awserr" 7 | "github.com/stretchr/testify/assert" 8 | ) 9 | 10 | type stubProvider struct { 11 | creds Value 12 | expired bool 13 | err error 14 | } 15 | 16 | func (s *stubProvider) Retrieve() (Value, error) { 17 | s.expired = false 18 | return s.creds, s.err 19 | } 20 | func (s *stubProvider) IsExpired() bool { 21 | return s.expired 22 | } 23 | 24 | func TestCredentialsGet(t *testing.T) { 25 | c := NewCredentials(&stubProvider{ 26 | creds: Value{ 27 | AccessKeyID: "AKID", 28 | SecretAccessKey: "SECRET", 29 | SessionToken: "", 30 | }, 31 | expired: true, 32 | }) 33 | 34 | creds, err := c.Get() 35 | assert.Nil(t, err, "Expected no error") 36 | assert.Equal(t, "AKID", creds.AccessKeyID, "Expect access key ID to match") 37 | assert.Equal(t, "SECRET", creds.SecretAccessKey, "Expect secret access key to match") 38 | assert.Empty(t, creds.SessionToken, "Expect session token to be empty") 39 | } 40 | 41 | func TestCredentialsGetWithError(t *testing.T) { 42 | c := NewCredentials(&stubProvider{err: awserr.New("provider error", "", nil), expired: true}) 43 | 44 | _, err := c.Get() 45 | assert.Equal(t, "provider error", err.(awserr.Error).Code(), "Expected provider error") 46 | } 47 | 48 | func TestCredentialsExpire(t *testing.T) { 49 | stub := &stubProvider{} 50 | c := NewCredentials(stub) 51 | 52 | stub.expired = false 53 | assert.True(t, c.IsExpired(), "Expected to start out expired") 54 | c.Expire() 55 | assert.True(t, c.IsExpired(), "Expected to be expired") 56 | 57 | c.forceRefresh = false 58 | assert.False(t, c.IsExpired(), "Expected not to be expired") 59 | 60 | stub.expired = true 61 | assert.True(t, c.IsExpired(), "Expected to be expired") 62 | } 63 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/credentials/ec2rolecreds/ec2_role_provider_test.go: -------------------------------------------------------------------------------- 1 | package ec2rolecreds_test 2 | 3 | import ( 4 | "fmt" 5 | "net/http" 6 | "net/http/httptest" 7 | "testing" 8 | "time" 9 | 10 | "github.com/stretchr/testify/assert" 11 | 12 | "github.com/rlister/let-me-in/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws" 13 | "github.com/rlister/let-me-in/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/awserr" 14 | "github.com/rlister/let-me-in/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/credentials/ec2rolecreds" 15 | "github.com/rlister/let-me-in/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/ec2metadata" 16 | ) 17 | 18 | const credsRespTmpl = `{ 19 | "Code": "Success", 20 | "Type": "AWS-HMAC", 21 | "AccessKeyId" : "accessKey", 22 | "SecretAccessKey" : "secret", 23 | "Token" : "token", 24 | "Expiration" : "%s", 25 | "LastUpdated" : "2009-11-23T0:00:00Z" 26 | }` 27 | 28 | const credsFailRespTmpl = `{ 29 | "Code": "ErrorCode", 30 | "Message": "ErrorMsg", 31 | "LastUpdated": "2009-11-23T0:00:00Z" 32 | }` 33 | 34 | func initTestServer(expireOn string, failAssume bool) *httptest.Server { 35 | server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 36 | if r.URL.Path == "/latest/meta-data/iam/security-credentials" { 37 | fmt.Fprintln(w, "RoleName") 38 | } else if r.URL.Path == "/latest/meta-data/iam/security-credentials/RoleName" { 39 | if failAssume { 40 | fmt.Fprintf(w, credsFailRespTmpl) 41 | } else { 42 | fmt.Fprintf(w, credsRespTmpl, expireOn) 43 | } 44 | } else { 45 | http.Error(w, "bad request", http.StatusBadRequest) 46 | } 47 | })) 48 | 49 | return server 50 | } 51 | 52 | func TestEC2RoleProvider(t *testing.T) { 53 | server := initTestServer("2014-12-16T01:51:37Z", false) 54 | defer server.Close() 55 | 56 | p := &ec2rolecreds.EC2RoleProvider{ 57 | Client: ec2metadata.New(&ec2metadata.Config{Endpoint: aws.String(server.URL + "/latest")}), 58 | } 59 | 60 | creds, err := p.Retrieve() 61 | assert.Nil(t, err, "Expect no error") 62 | 63 | assert.Equal(t, "accessKey", creds.AccessKeyID, "Expect access key ID to match") 64 | assert.Equal(t, "secret", creds.SecretAccessKey, "Expect secret access key to match") 65 | assert.Equal(t, "token", creds.SessionToken, "Expect session token to match") 66 | } 67 | 68 | func TestEC2RoleProviderFailAssume(t *testing.T) { 69 | server := initTestServer("2014-12-16T01:51:37Z", true) 70 | defer server.Close() 71 | 72 | p := &ec2rolecreds.EC2RoleProvider{ 73 | Client: ec2metadata.New(&ec2metadata.Config{Endpoint: aws.String(server.URL + "/latest")}), 74 | } 75 | 76 | creds, err := p.Retrieve() 77 | assert.Error(t, err, "Expect error") 78 | 79 | e := err.(awserr.Error) 80 | assert.Equal(t, "ErrorCode", e.Code()) 81 | assert.Equal(t, "ErrorMsg", e.Message()) 82 | assert.Nil(t, e.OrigErr()) 83 | 84 | assert.Equal(t, "", creds.AccessKeyID, "Expect access key ID to match") 85 | assert.Equal(t, "", creds.SecretAccessKey, "Expect secret access key to match") 86 | assert.Equal(t, "", creds.SessionToken, "Expect session token to match") 87 | } 88 | 89 | func TestEC2RoleProviderIsExpired(t *testing.T) { 90 | server := initTestServer("2014-12-16T01:51:37Z", false) 91 | defer server.Close() 92 | 93 | p := &ec2rolecreds.EC2RoleProvider{ 94 | Client: ec2metadata.New(&ec2metadata.Config{Endpoint: aws.String(server.URL + "/latest")}), 95 | } 96 | p.CurrentTime = func() time.Time { 97 | return time.Date(2014, 12, 15, 21, 26, 0, 0, time.UTC) 98 | } 99 | 100 | assert.True(t, p.IsExpired(), "Expect creds to be expired before retrieve.") 101 | 102 | _, err := p.Retrieve() 103 | assert.Nil(t, err, "Expect no error") 104 | 105 | assert.False(t, p.IsExpired(), "Expect creds to not be expired after retrieve.") 106 | 107 | p.CurrentTime = func() time.Time { 108 | return time.Date(3014, 12, 15, 21, 26, 0, 0, time.UTC) 109 | } 110 | 111 | assert.True(t, p.IsExpired(), "Expect creds to be expired.") 112 | } 113 | 114 | func TestEC2RoleProviderExpiryWindowIsExpired(t *testing.T) { 115 | server := initTestServer("2014-12-16T01:51:37Z", false) 116 | defer server.Close() 117 | 118 | p := &ec2rolecreds.EC2RoleProvider{ 119 | Client: ec2metadata.New(&ec2metadata.Config{Endpoint: aws.String(server.URL + "/latest")}), 120 | ExpiryWindow: time.Hour * 1, 121 | } 122 | p.CurrentTime = func() time.Time { 123 | return time.Date(2014, 12, 15, 0, 51, 37, 0, time.UTC) 124 | } 125 | 126 | assert.True(t, p.IsExpired(), "Expect creds to be expired before retrieve.") 127 | 128 | _, err := p.Retrieve() 129 | assert.Nil(t, err, "Expect no error") 130 | 131 | assert.False(t, p.IsExpired(), "Expect creds to not be expired after retrieve.") 132 | 133 | p.CurrentTime = func() time.Time { 134 | return time.Date(2014, 12, 16, 0, 55, 37, 0, time.UTC) 135 | } 136 | 137 | assert.True(t, p.IsExpired(), "Expect creds to be expired.") 138 | } 139 | 140 | func BenchmarkEC2RoleProvider(b *testing.B) { 141 | server := initTestServer("2014-12-16T01:51:37Z", false) 142 | defer server.Close() 143 | 144 | p := &ec2rolecreds.EC2RoleProvider{ 145 | Client: ec2metadata.New(&ec2metadata.Config{Endpoint: aws.String(server.URL + "/latest")}), 146 | } 147 | _, err := p.Retrieve() 148 | if err != nil { 149 | b.Fatal(err) 150 | } 151 | 152 | b.ResetTimer() 153 | b.RunParallel(func(pb *testing.PB) { 154 | for pb.Next() { 155 | _, err := p.Retrieve() 156 | if err != nil { 157 | b.Fatal(err) 158 | } 159 | } 160 | }) 161 | } 162 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/credentials/env_provider.go: -------------------------------------------------------------------------------- 1 | package credentials 2 | 3 | import ( 4 | "os" 5 | 6 | "github.com/rlister/let-me-in/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/awserr" 7 | ) 8 | 9 | var ( 10 | // ErrAccessKeyIDNotFound is returned when the AWS Access Key ID can't be 11 | // found in the process's environment. 12 | // 13 | // @readonly 14 | ErrAccessKeyIDNotFound = awserr.New("EnvAccessKeyNotFound", "AWS_ACCESS_KEY_ID or AWS_ACCESS_KEY not found in environment", nil) 15 | 16 | // ErrSecretAccessKeyNotFound is returned when the AWS Secret Access Key 17 | // can't be found in the process's environment. 18 | // 19 | // @readonly 20 | ErrSecretAccessKeyNotFound = awserr.New("EnvSecretNotFound", "AWS_SECRET_ACCESS_KEY or AWS_SECRET_KEY not found in environment", nil) 21 | ) 22 | 23 | // A EnvProvider retrieves credentials from the environment variables of the 24 | // running process. Environment credentials never expire. 25 | // 26 | // Environment variables used: 27 | // 28 | // * Access Key ID: AWS_ACCESS_KEY_ID or AWS_ACCESS_KEY 29 | // * Secret Access Key: AWS_SECRET_ACCESS_KEY or AWS_SECRET_KEY 30 | type EnvProvider struct { 31 | retrieved bool 32 | } 33 | 34 | // NewEnvCredentials returns a pointer to a new Credentials object 35 | // wrapping the environment variable provider. 36 | func NewEnvCredentials() *Credentials { 37 | return NewCredentials(&EnvProvider{}) 38 | } 39 | 40 | // Retrieve retrieves the keys from the environment. 41 | func (e *EnvProvider) Retrieve() (Value, error) { 42 | e.retrieved = false 43 | 44 | id := os.Getenv("AWS_ACCESS_KEY_ID") 45 | if id == "" { 46 | id = os.Getenv("AWS_ACCESS_KEY") 47 | } 48 | 49 | secret := os.Getenv("AWS_SECRET_ACCESS_KEY") 50 | if secret == "" { 51 | secret = os.Getenv("AWS_SECRET_KEY") 52 | } 53 | 54 | if id == "" { 55 | return Value{}, ErrAccessKeyIDNotFound 56 | } 57 | 58 | if secret == "" { 59 | return Value{}, ErrSecretAccessKeyNotFound 60 | } 61 | 62 | e.retrieved = true 63 | return Value{ 64 | AccessKeyID: id, 65 | SecretAccessKey: secret, 66 | SessionToken: os.Getenv("AWS_SESSION_TOKEN"), 67 | }, nil 68 | } 69 | 70 | // IsExpired returns if the credentials have been retrieved. 71 | func (e *EnvProvider) IsExpired() bool { 72 | return !e.retrieved 73 | } 74 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/credentials/env_provider_test.go: -------------------------------------------------------------------------------- 1 | package credentials 2 | 3 | import ( 4 | "github.com/stretchr/testify/assert" 5 | "os" 6 | "testing" 7 | ) 8 | 9 | func TestEnvProviderRetrieve(t *testing.T) { 10 | os.Clearenv() 11 | os.Setenv("AWS_ACCESS_KEY_ID", "access") 12 | os.Setenv("AWS_SECRET_ACCESS_KEY", "secret") 13 | os.Setenv("AWS_SESSION_TOKEN", "token") 14 | 15 | e := EnvProvider{} 16 | creds, err := e.Retrieve() 17 | assert.Nil(t, err, "Expect no error") 18 | 19 | assert.Equal(t, "access", creds.AccessKeyID, "Expect access key ID to match") 20 | assert.Equal(t, "secret", creds.SecretAccessKey, "Expect secret access key to match") 21 | assert.Equal(t, "token", creds.SessionToken, "Expect session token to match") 22 | } 23 | 24 | func TestEnvProviderIsExpired(t *testing.T) { 25 | os.Clearenv() 26 | os.Setenv("AWS_ACCESS_KEY_ID", "access") 27 | os.Setenv("AWS_SECRET_ACCESS_KEY", "secret") 28 | os.Setenv("AWS_SESSION_TOKEN", "token") 29 | 30 | e := EnvProvider{} 31 | 32 | assert.True(t, e.IsExpired(), "Expect creds to be expired before retrieve.") 33 | 34 | _, err := e.Retrieve() 35 | assert.Nil(t, err, "Expect no error") 36 | 37 | assert.False(t, e.IsExpired(), "Expect creds to not be expired after retrieve.") 38 | } 39 | 40 | func TestEnvProviderNoAccessKeyID(t *testing.T) { 41 | os.Clearenv() 42 | os.Setenv("AWS_SECRET_ACCESS_KEY", "secret") 43 | 44 | e := EnvProvider{} 45 | creds, err := e.Retrieve() 46 | assert.Equal(t, ErrAccessKeyIDNotFound, err, "ErrAccessKeyIDNotFound expected, but was %#v error: %#v", creds, err) 47 | } 48 | 49 | func TestEnvProviderNoSecretAccessKey(t *testing.T) { 50 | os.Clearenv() 51 | os.Setenv("AWS_ACCESS_KEY_ID", "access") 52 | 53 | e := EnvProvider{} 54 | creds, err := e.Retrieve() 55 | assert.Equal(t, ErrSecretAccessKeyNotFound, err, "ErrSecretAccessKeyNotFound expected, but was %#v error: %#v", creds, err) 56 | } 57 | 58 | func TestEnvProviderAlternateNames(t *testing.T) { 59 | os.Clearenv() 60 | os.Setenv("AWS_ACCESS_KEY", "access") 61 | os.Setenv("AWS_SECRET_KEY", "secret") 62 | 63 | e := EnvProvider{} 64 | creds, err := e.Retrieve() 65 | assert.Nil(t, err, "Expect no error") 66 | 67 | assert.Equal(t, "access", creds.AccessKeyID, "Expected access key ID") 68 | assert.Equal(t, "secret", creds.SecretAccessKey, "Expected secret access key") 69 | assert.Empty(t, creds.SessionToken, "Expected no token") 70 | } 71 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/credentials/example.ini: -------------------------------------------------------------------------------- 1 | [default] 2 | aws_access_key_id = accessKey 3 | aws_secret_access_key = secret 4 | aws_session_token = token 5 | 6 | [no_token] 7 | aws_access_key_id = accessKey 8 | aws_secret_access_key = secret 9 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/credentials/shared_credentials_provider.go: -------------------------------------------------------------------------------- 1 | package credentials 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | "path/filepath" 7 | 8 | "github.com/rlister/let-me-in/Godeps/_workspace/src/github.com/vaughan0/go-ini" 9 | 10 | "github.com/rlister/let-me-in/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/awserr" 11 | ) 12 | 13 | var ( 14 | // ErrSharedCredentialsHomeNotFound is emitted when the user directory cannot be found. 15 | // 16 | // @readonly 17 | ErrSharedCredentialsHomeNotFound = awserr.New("UserHomeNotFound", "user home directory not found.", nil) 18 | ) 19 | 20 | // A SharedCredentialsProvider retrieves credentials from the current user's home 21 | // directory, and keeps track if those credentials are expired. 22 | // 23 | // Profile ini file example: $HOME/.aws/credentials 24 | type SharedCredentialsProvider struct { 25 | // Path to the shared credentials file. 26 | // 27 | // If empty will look for "AWS_SHARED_CREDENTIALS_FILE" env variable. If the 28 | // env value is empty will default to current user's home directory. 29 | // Linux/OSX: "$HOME/.aws/credentials" 30 | // Windows: "%USERPROFILE%\.aws\credentials" 31 | Filename string 32 | 33 | // AWS Profile to extract credentials from the shared credentials file. If empty 34 | // will default to environment variable "AWS_PROFILE" or "default" if 35 | // environment variable is also not set. 36 | Profile string 37 | 38 | // retrieved states if the credentials have been successfully retrieved. 39 | retrieved bool 40 | } 41 | 42 | // NewSharedCredentials returns a pointer to a new Credentials object 43 | // wrapping the Profile file provider. 44 | func NewSharedCredentials(filename, profile string) *Credentials { 45 | return NewCredentials(&SharedCredentialsProvider{ 46 | Filename: filename, 47 | Profile: profile, 48 | }) 49 | } 50 | 51 | // Retrieve reads and extracts the shared credentials from the current 52 | // users home directory. 53 | func (p *SharedCredentialsProvider) Retrieve() (Value, error) { 54 | p.retrieved = false 55 | 56 | filename, err := p.filename() 57 | if err != nil { 58 | return Value{}, err 59 | } 60 | 61 | creds, err := loadProfile(filename, p.profile()) 62 | if err != nil { 63 | return Value{}, err 64 | } 65 | 66 | p.retrieved = true 67 | return creds, nil 68 | } 69 | 70 | // IsExpired returns if the shared credentials have expired. 71 | func (p *SharedCredentialsProvider) IsExpired() bool { 72 | return !p.retrieved 73 | } 74 | 75 | // loadProfiles loads from the file pointed to by shared credentials filename for profile. 76 | // The credentials retrieved from the profile will be returned or error. Error will be 77 | // returned if it fails to read from the file, or the data is invalid. 78 | func loadProfile(filename, profile string) (Value, error) { 79 | config, err := ini.LoadFile(filename) 80 | if err != nil { 81 | return Value{}, awserr.New("SharedCredsLoad", "failed to load shared credentials file", err) 82 | } 83 | iniProfile := config.Section(profile) 84 | 85 | id, ok := iniProfile["aws_access_key_id"] 86 | if !ok { 87 | return Value{}, awserr.New("SharedCredsAccessKey", 88 | fmt.Sprintf("shared credentials %s in %s did not contain aws_access_key_id", profile, filename), 89 | nil) 90 | } 91 | 92 | secret, ok := iniProfile["aws_secret_access_key"] 93 | if !ok { 94 | return Value{}, awserr.New("SharedCredsSecret", 95 | fmt.Sprintf("shared credentials %s in %s did not contain aws_secret_access_key", profile, filename), 96 | nil) 97 | } 98 | 99 | token := iniProfile["aws_session_token"] 100 | 101 | return Value{ 102 | AccessKeyID: id, 103 | SecretAccessKey: secret, 104 | SessionToken: token, 105 | }, nil 106 | } 107 | 108 | // filename returns the filename to use to read AWS shared credentials. 109 | // 110 | // Will return an error if the user's home directory path cannot be found. 111 | func (p *SharedCredentialsProvider) filename() (string, error) { 112 | if p.Filename == "" { 113 | if p.Filename = os.Getenv("AWS_SHARED_CREDENTIALS_FILE"); p.Filename != "" { 114 | return p.Filename, nil 115 | } 116 | 117 | homeDir := os.Getenv("HOME") // *nix 118 | if homeDir == "" { // Windows 119 | homeDir = os.Getenv("USERPROFILE") 120 | } 121 | if homeDir == "" { 122 | return "", ErrSharedCredentialsHomeNotFound 123 | } 124 | 125 | p.Filename = filepath.Join(homeDir, ".aws", "credentials") 126 | } 127 | 128 | return p.Filename, nil 129 | } 130 | 131 | // profile returns the AWS shared credentials profile. If empty will read 132 | // environment variable "AWS_PROFILE". If that is not set profile will 133 | // return "default". 134 | func (p *SharedCredentialsProvider) profile() string { 135 | if p.Profile == "" { 136 | p.Profile = os.Getenv("AWS_PROFILE") 137 | } 138 | if p.Profile == "" { 139 | p.Profile = "default" 140 | } 141 | 142 | return p.Profile 143 | } 144 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/credentials/shared_credentials_provider_test.go: -------------------------------------------------------------------------------- 1 | package credentials 2 | 3 | import ( 4 | "github.com/stretchr/testify/assert" 5 | "os" 6 | "testing" 7 | ) 8 | 9 | func TestSharedCredentialsProvider(t *testing.T) { 10 | os.Clearenv() 11 | 12 | p := SharedCredentialsProvider{Filename: "example.ini", Profile: ""} 13 | creds, err := p.Retrieve() 14 | assert.Nil(t, err, "Expect no error") 15 | 16 | assert.Equal(t, "accessKey", creds.AccessKeyID, "Expect access key ID to match") 17 | assert.Equal(t, "secret", creds.SecretAccessKey, "Expect secret access key to match") 18 | assert.Equal(t, "token", creds.SessionToken, "Expect session token to match") 19 | } 20 | 21 | func TestSharedCredentialsProviderIsExpired(t *testing.T) { 22 | os.Clearenv() 23 | 24 | p := SharedCredentialsProvider{Filename: "example.ini", Profile: ""} 25 | 26 | assert.True(t, p.IsExpired(), "Expect creds to be expired before retrieve") 27 | 28 | _, err := p.Retrieve() 29 | assert.Nil(t, err, "Expect no error") 30 | 31 | assert.False(t, p.IsExpired(), "Expect creds to not be expired after retrieve") 32 | } 33 | 34 | func TestSharedCredentialsProviderWithAWS_SHARED_CREDENTIALS_FILE(t *testing.T) { 35 | os.Clearenv() 36 | os.Setenv("AWS_SHARED_CREDENTIALS_FILE", "example.ini") 37 | p := SharedCredentialsProvider{} 38 | creds, err := p.Retrieve() 39 | 40 | assert.Nil(t, err, "Expect no error") 41 | 42 | assert.Equal(t, "accessKey", creds.AccessKeyID, "Expect access key ID to match") 43 | assert.Equal(t, "secret", creds.SecretAccessKey, "Expect secret access key to match") 44 | assert.Equal(t, "token", creds.SessionToken, "Expect session token to match") 45 | } 46 | 47 | func TestSharedCredentialsProviderWithAWS_PROFILE(t *testing.T) { 48 | os.Clearenv() 49 | os.Setenv("AWS_PROFILE", "no_token") 50 | 51 | p := SharedCredentialsProvider{Filename: "example.ini", Profile: ""} 52 | creds, err := p.Retrieve() 53 | assert.Nil(t, err, "Expect no error") 54 | 55 | assert.Equal(t, "accessKey", creds.AccessKeyID, "Expect access key ID to match") 56 | assert.Equal(t, "secret", creds.SecretAccessKey, "Expect secret access key to match") 57 | assert.Empty(t, creds.SessionToken, "Expect no token") 58 | } 59 | 60 | func TestSharedCredentialsProviderWithoutTokenFromProfile(t *testing.T) { 61 | os.Clearenv() 62 | 63 | p := SharedCredentialsProvider{Filename: "example.ini", Profile: "no_token"} 64 | creds, err := p.Retrieve() 65 | assert.Nil(t, err, "Expect no error") 66 | 67 | assert.Equal(t, "accessKey", creds.AccessKeyID, "Expect access key ID to match") 68 | assert.Equal(t, "secret", creds.SecretAccessKey, "Expect secret access key to match") 69 | assert.Empty(t, creds.SessionToken, "Expect no token") 70 | } 71 | 72 | func BenchmarkSharedCredentialsProvider(b *testing.B) { 73 | os.Clearenv() 74 | 75 | p := SharedCredentialsProvider{Filename: "example.ini", Profile: ""} 76 | _, err := p.Retrieve() 77 | if err != nil { 78 | b.Fatal(err) 79 | } 80 | 81 | b.ResetTimer() 82 | for i := 0; i < b.N; i++ { 83 | _, err := p.Retrieve() 84 | if err != nil { 85 | b.Fatal(err) 86 | } 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/credentials/static_provider.go: -------------------------------------------------------------------------------- 1 | package credentials 2 | 3 | import ( 4 | "github.com/rlister/let-me-in/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/awserr" 5 | ) 6 | 7 | var ( 8 | // ErrStaticCredentialsEmpty is emitted when static credentials are empty. 9 | // 10 | // @readonly 11 | ErrStaticCredentialsEmpty = awserr.New("EmptyStaticCreds", "static credentials are empty", nil) 12 | ) 13 | 14 | // A StaticProvider is a set of credentials which are set pragmatically, 15 | // and will never expire. 16 | type StaticProvider struct { 17 | Value 18 | } 19 | 20 | // NewStaticCredentials returns a pointer to a new Credentials object 21 | // wrapping a static credentials value provider. 22 | func NewStaticCredentials(id, secret, token string) *Credentials { 23 | return NewCredentials(&StaticProvider{Value: Value{ 24 | AccessKeyID: id, 25 | SecretAccessKey: secret, 26 | SessionToken: token, 27 | }}) 28 | } 29 | 30 | // Retrieve returns the credentials or error if the credentials are invalid. 31 | func (s *StaticProvider) Retrieve() (Value, error) { 32 | if s.AccessKeyID == "" || s.SecretAccessKey == "" { 33 | return Value{}, ErrStaticCredentialsEmpty 34 | } 35 | 36 | return s.Value, nil 37 | } 38 | 39 | // IsExpired returns if the credentials are expired. 40 | // 41 | // For StaticProvider, the credentials never expired. 42 | func (s *StaticProvider) IsExpired() bool { 43 | return false 44 | } 45 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/credentials/static_provider_test.go: -------------------------------------------------------------------------------- 1 | package credentials 2 | 3 | import ( 4 | "github.com/stretchr/testify/assert" 5 | "testing" 6 | ) 7 | 8 | func TestStaticProviderGet(t *testing.T) { 9 | s := StaticProvider{ 10 | Value: Value{ 11 | AccessKeyID: "AKID", 12 | SecretAccessKey: "SECRET", 13 | SessionToken: "", 14 | }, 15 | } 16 | 17 | creds, err := s.Retrieve() 18 | assert.Nil(t, err, "Expect no error") 19 | assert.Equal(t, "AKID", creds.AccessKeyID, "Expect access key ID to match") 20 | assert.Equal(t, "SECRET", creds.SecretAccessKey, "Expect secret access key to match") 21 | assert.Empty(t, creds.SessionToken, "Expect no session token") 22 | } 23 | 24 | func TestStaticProviderIsExpired(t *testing.T) { 25 | s := StaticProvider{ 26 | Value: Value{ 27 | AccessKeyID: "AKID", 28 | SecretAccessKey: "SECRET", 29 | SessionToken: "", 30 | }, 31 | } 32 | 33 | assert.False(t, s.IsExpired(), "Expect static credentials to never expire") 34 | } 35 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/credentials/stscreds/assume_role_provider.go: -------------------------------------------------------------------------------- 1 | // Package stscreds are credential Providers to retrieve STS AWS credentials. 2 | // 3 | // STS provides multiple ways to retrieve credentials which can be used when making 4 | // future AWS service API operation calls. 5 | package stscreds 6 | 7 | import ( 8 | "fmt" 9 | "time" 10 | 11 | "github.com/aws/aws-sdk-go/service/sts" 12 | "github.com/rlister/let-me-in/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws" 13 | "github.com/rlister/let-me-in/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/credentials" 14 | ) 15 | 16 | // AssumeRoler represents the minimal subset of the STS client API used by this provider. 17 | type AssumeRoler interface { 18 | AssumeRole(input *sts.AssumeRoleInput) (*sts.AssumeRoleOutput, error) 19 | } 20 | 21 | // AssumeRoleProvider retrieves temporary credentials from the STS service, and 22 | // keeps track of their expiration time. This provider must be used explicitly, 23 | // as it is not included in the credentials chain. 24 | // 25 | // Example how to configure a service to use this provider: 26 | // 27 | // config := &aws.Config{ 28 | // Credentials: stscreds.NewCredentials(nil, "arn-of-the-role-to-assume", 10*time.Second), 29 | // }) 30 | // // Use config for creating your AWS service. 31 | // 32 | // Example how to obtain customised credentials: 33 | // 34 | // provider := &stscreds.Provider{ 35 | // // Extend the duration to 1 hour. 36 | // Duration: time.Hour, 37 | // // Custom role name. 38 | // RoleSessionName: "custom-session-name", 39 | // } 40 | // creds := credentials.NewCredentials(provider) 41 | // 42 | type AssumeRoleProvider struct { 43 | credentials.Expiry 44 | 45 | // Custom STS client. If not set the default STS client will be used. 46 | Client AssumeRoler 47 | 48 | // Role to be assumed. 49 | RoleARN string 50 | 51 | // Session name, if you wish to reuse the credentials elsewhere. 52 | RoleSessionName string 53 | 54 | // Expiry duration of the STS credentials. Defaults to 15 minutes if not set. 55 | Duration time.Duration 56 | 57 | // Optional ExternalID to pass along, defaults to nil if not set. 58 | ExternalID *string 59 | 60 | // ExpiryWindow will allow the credentials to trigger refreshing prior to 61 | // the credentials actually expiring. This is beneficial so race conditions 62 | // with expiring credentials do not cause request to fail unexpectedly 63 | // due to ExpiredTokenException exceptions. 64 | // 65 | // So a ExpiryWindow of 10s would cause calls to IsExpired() to return true 66 | // 10 seconds before the credentials are actually expired. 67 | // 68 | // If ExpiryWindow is 0 or less it will be ignored. 69 | ExpiryWindow time.Duration 70 | } 71 | 72 | // NewCredentials returns a pointer to a new Credentials object wrapping the 73 | // AssumeRoleProvider. The credentials will expire every 15 minutes and the 74 | // role will be named after a nanosecond timestamp of this operation. 75 | // 76 | // The sts and roleARN parameters are used for building the "AssumeRole" call. 77 | // Pass nil as sts to use the default client. 78 | // 79 | // Window is the expiry window that will be subtracted from the expiry returned 80 | // by the role credential request. This is done so that the credentials will 81 | // expire sooner than their actual lifespan. 82 | func NewCredentials(client AssumeRoler, roleARN string, window time.Duration) *credentials.Credentials { 83 | return credentials.NewCredentials(&AssumeRoleProvider{ 84 | Client: client, 85 | RoleARN: roleARN, 86 | ExpiryWindow: window, 87 | }) 88 | } 89 | 90 | // Retrieve generates a new set of temporary credentials using STS. 91 | func (p *AssumeRoleProvider) Retrieve() (credentials.Value, error) { 92 | 93 | // Apply defaults where parameters are not set. 94 | if p.Client == nil { 95 | p.Client = sts.New(nil) 96 | } 97 | if p.RoleSessionName == "" { 98 | // Try to work out a role name that will hopefully end up unique. 99 | p.RoleSessionName = fmt.Sprintf("%d", time.Now().UTC().UnixNano()) 100 | } 101 | if p.Duration == 0 { 102 | // Expire as often as AWS permits. 103 | p.Duration = 15 * time.Minute 104 | } 105 | 106 | roleOutput, err := p.Client.AssumeRole(&sts.AssumeRoleInput{ 107 | DurationSeconds: aws.Int64(int64(p.Duration / time.Second)), 108 | RoleArn: aws.String(p.RoleARN), 109 | RoleSessionName: aws.String(p.RoleSessionName), 110 | ExternalId: p.ExternalID, 111 | }) 112 | 113 | if err != nil { 114 | return credentials.Value{}, err 115 | } 116 | 117 | // We will proactively generate new credentials before they expire. 118 | p.SetExpiration(*roleOutput.Credentials.Expiration, p.ExpiryWindow) 119 | 120 | return credentials.Value{ 121 | AccessKeyID: *roleOutput.Credentials.AccessKeyId, 122 | SecretAccessKey: *roleOutput.Credentials.SecretAccessKey, 123 | SessionToken: *roleOutput.Credentials.SessionToken, 124 | }, nil 125 | } 126 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/credentials/stscreds/assume_role_provider_test.go: -------------------------------------------------------------------------------- 1 | package stscreds 2 | 3 | import ( 4 | "testing" 5 | "time" 6 | 7 | "github.com/aws/aws-sdk-go/service/sts" 8 | "github.com/rlister/let-me-in/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws" 9 | "github.com/stretchr/testify/assert" 10 | ) 11 | 12 | type stubSTS struct { 13 | } 14 | 15 | func (s *stubSTS) AssumeRole(input *sts.AssumeRoleInput) (*sts.AssumeRoleOutput, error) { 16 | expiry := time.Now().Add(60 * time.Minute) 17 | return &sts.AssumeRoleOutput{ 18 | Credentials: &sts.Credentials{ 19 | // Just reflect the role arn to the provider. 20 | AccessKeyId: input.RoleArn, 21 | SecretAccessKey: aws.String("assumedSecretAccessKey"), 22 | SessionToken: aws.String("assumedSessionToken"), 23 | Expiration: &expiry, 24 | }, 25 | }, nil 26 | } 27 | 28 | func TestAssumeRoleProvider(t *testing.T) { 29 | stub := &stubSTS{} 30 | p := &AssumeRoleProvider{ 31 | Client: stub, 32 | RoleARN: "roleARN", 33 | } 34 | 35 | creds, err := p.Retrieve() 36 | assert.Nil(t, err, "Expect no error") 37 | 38 | assert.Equal(t, "roleARN", creds.AccessKeyID, "Expect access key ID to be reflected role ARN") 39 | assert.Equal(t, "assumedSecretAccessKey", creds.SecretAccessKey, "Expect secret access key to match") 40 | assert.Equal(t, "assumedSessionToken", creds.SessionToken, "Expect session token to match") 41 | } 42 | 43 | func BenchmarkAssumeRoleProvider(b *testing.B) { 44 | stub := &stubSTS{} 45 | p := &AssumeRoleProvider{ 46 | Client: stub, 47 | RoleARN: "roleARN", 48 | } 49 | 50 | b.ResetTimer() 51 | b.RunParallel(func(pb *testing.PB) { 52 | for pb.Next() { 53 | _, err := p.Retrieve() 54 | if err != nil { 55 | b.Fatal(err) 56 | } 57 | } 58 | }) 59 | } 60 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/defaults/defaults.go: -------------------------------------------------------------------------------- 1 | package defaults 2 | 3 | import ( 4 | "net/http" 5 | "os" 6 | "time" 7 | 8 | "github.com/rlister/let-me-in/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws" 9 | "github.com/rlister/let-me-in/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/credentials" 10 | "github.com/rlister/let-me-in/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/credentials/ec2rolecreds" 11 | ) 12 | 13 | // DefaultChainCredentials is a Credentials which will find the first available 14 | // credentials Value from the list of Providers. 15 | // 16 | // This should be used in the default case. Once the type of credentials are 17 | // known switching to the specific Credentials will be more efficient. 18 | var DefaultChainCredentials = credentials.NewChainCredentials( 19 | []credentials.Provider{ 20 | &credentials.EnvProvider{}, 21 | &credentials.SharedCredentialsProvider{Filename: "", Profile: ""}, 22 | &ec2rolecreds.EC2RoleProvider{ExpiryWindow: 5 * time.Minute}, 23 | }) 24 | 25 | // DefaultConfig is the default all service configuration will be based off of. 26 | // By default, all clients use this structure for initialization options unless 27 | // a custom configuration object is passed in. 28 | // 29 | // You may modify this global structure to change all default configuration 30 | // in the SDK. Note that configuration options are copied by value, so any 31 | // modifications must happen before constructing a client. 32 | var DefaultConfig = aws.NewConfig(). 33 | WithCredentials(DefaultChainCredentials). 34 | WithRegion(os.Getenv("AWS_REGION")). 35 | WithHTTPClient(http.DefaultClient). 36 | WithMaxRetries(aws.DefaultRetries). 37 | WithLogger(aws.NewDefaultLogger()). 38 | WithLogLevel(aws.LogOff). 39 | WithSleepDelay(time.Sleep) 40 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/ec2metadata/api.go: -------------------------------------------------------------------------------- 1 | package ec2metadata 2 | 3 | import ( 4 | "path" 5 | 6 | "github.com/rlister/let-me-in/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/request" 7 | ) 8 | 9 | // GetMetadata uses the path provided to request 10 | func (c *Client) GetMetadata(p string) (string, error) { 11 | op := &request.Operation{ 12 | Name: "GetMetadata", 13 | HTTPMethod: "GET", 14 | HTTPPath: path.Join("/", "meta-data", p), 15 | } 16 | 17 | output := &metadataOutput{} 18 | req := request.New(c.Service.ServiceInfo, c.Service.Handlers, c.Service.Retryer, op, nil, output) 19 | 20 | return output.Content, req.Send() 21 | } 22 | 23 | // Region returns the region the instance is running in. 24 | func (c *Client) Region() (string, error) { 25 | resp, err := c.GetMetadata("placement/availability-zone") 26 | if err != nil { 27 | return "", err 28 | } 29 | 30 | // returns region without the suffix. Eg: us-west-2a becomes us-west-2 31 | return resp[:len(resp)-1], nil 32 | } 33 | 34 | // Available returns if the application has access to the EC2 Metadata service. 35 | // Can be used to determine if application is running within an EC2 Instance and 36 | // the metadata service is available. 37 | func (c *Client) Available() bool { 38 | if _, err := c.GetMetadata("instance-id"); err != nil { 39 | return false 40 | } 41 | 42 | return true 43 | } 44 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/ec2metadata/api_test.go: -------------------------------------------------------------------------------- 1 | package ec2metadata_test 2 | 3 | import ( 4 | "bytes" 5 | "io/ioutil" 6 | "net/http" 7 | "net/http/httptest" 8 | "path" 9 | "testing" 10 | 11 | "github.com/stretchr/testify/assert" 12 | 13 | "github.com/rlister/let-me-in/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws" 14 | "github.com/rlister/let-me-in/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/awserr" 15 | "github.com/rlister/let-me-in/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/ec2metadata" 16 | "github.com/rlister/let-me-in/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/request" 17 | ) 18 | 19 | func initTestServer(path string, resp string) *httptest.Server { 20 | return httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 21 | if r.RequestURI != path { 22 | http.Error(w, "not found", http.StatusNotFound) 23 | return 24 | } 25 | 26 | w.Write([]byte(resp)) 27 | })) 28 | } 29 | 30 | func TestEndpoint(t *testing.T) { 31 | c := ec2metadata.New(&ec2metadata.Config{}) 32 | op := &request.Operation{ 33 | Name: "GetMetadata", 34 | HTTPMethod: "GET", 35 | HTTPPath: path.Join("/", "meta-data", "testpath"), 36 | } 37 | 38 | req := c.Service.NewRequest(op, nil, nil) 39 | assert.Equal(t, "http://169.254.169.254/latest", req.Service.Endpoint) 40 | assert.Equal(t, "http://169.254.169.254/latest/meta-data/testpath", req.HTTPRequest.URL.String()) 41 | } 42 | 43 | func TestGetMetadata(t *testing.T) { 44 | server := initTestServer( 45 | "/latest/meta-data/some/path", 46 | "success", // real response includes suffix 47 | ) 48 | defer server.Close() 49 | c := ec2metadata.New(&ec2metadata.Config{Endpoint: aws.String(server.URL + "/latest")}) 50 | 51 | resp, err := c.GetMetadata("some/path") 52 | 53 | assert.NoError(t, err) 54 | assert.Equal(t, "success", resp) 55 | } 56 | 57 | func TestGetRegion(t *testing.T) { 58 | server := initTestServer( 59 | "/latest/meta-data/placement/availability-zone", 60 | "us-west-2a", // real response includes suffix 61 | ) 62 | defer server.Close() 63 | c := ec2metadata.New(&ec2metadata.Config{Endpoint: aws.String(server.URL + "/latest")}) 64 | 65 | region, err := c.Region() 66 | 67 | assert.NoError(t, err) 68 | assert.Equal(t, "us-west-2", region) 69 | } 70 | 71 | func TestMetadataAvailable(t *testing.T) { 72 | server := initTestServer( 73 | "/latest/meta-data/instance-id", 74 | "instance-id", 75 | ) 76 | defer server.Close() 77 | c := ec2metadata.New(&ec2metadata.Config{Endpoint: aws.String(server.URL + "/latest")}) 78 | 79 | available := c.Available() 80 | 81 | assert.True(t, available) 82 | } 83 | 84 | func TestMetadataNotAvailable(t *testing.T) { 85 | c := ec2metadata.New(nil) 86 | c.Handlers.Send.Clear() 87 | c.Handlers.Send.PushBack(func(r *request.Request) { 88 | r.HTTPResponse = &http.Response{ 89 | StatusCode: int(0), 90 | Status: http.StatusText(int(0)), 91 | Body: ioutil.NopCloser(bytes.NewReader([]byte{})), 92 | } 93 | r.Error = awserr.New("RequestError", "send request failed", nil) 94 | r.Retryable = aws.Bool(true) // network errors are retryable 95 | }) 96 | 97 | available := c.Available() 98 | 99 | assert.False(t, available) 100 | } 101 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/ec2metadata/service.go: -------------------------------------------------------------------------------- 1 | package ec2metadata 2 | 3 | import ( 4 | "io/ioutil" 5 | "net/http" 6 | 7 | "github.com/rlister/let-me-in/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws" 8 | "github.com/rlister/let-me-in/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/awserr" 9 | "github.com/rlister/let-me-in/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/credentials" 10 | "github.com/rlister/let-me-in/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/request" 11 | "github.com/rlister/let-me-in/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/service" 12 | "github.com/rlister/let-me-in/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/service/serviceinfo" 13 | ) 14 | 15 | // DefaultRetries states the default number of times the service client will 16 | // attempt to retry a failed request before failing. 17 | const DefaultRetries = 3 18 | 19 | // A Config provides the configuration for the EC2 Metadata service. 20 | type Config struct { 21 | // An optional endpoint URL (hostname only or fully qualified URI) 22 | // that overrides the default service endpoint for a client. Set this 23 | // to nil, or `""` to use the default service endpoint. 24 | Endpoint *string 25 | 26 | // The HTTP client to use when sending requests. Defaults to 27 | // `http.DefaultClient`. 28 | HTTPClient *http.Client 29 | 30 | // An integer value representing the logging level. The default log level 31 | // is zero (LogOff), which represents no logging. To enable logging set 32 | // to a LogLevel Value. 33 | Logger aws.Logger 34 | 35 | // The logger writer interface to write logging messages to. Defaults to 36 | // standard out. 37 | LogLevel *aws.LogLevelType 38 | 39 | // The maximum number of times that a request will be retried for failures. 40 | // Defaults to DefaultRetries for the number of retries to be performed 41 | // per request. 42 | MaxRetries *int 43 | } 44 | 45 | // A Client is an EC2 Metadata service Client. 46 | type Client struct { 47 | *service.Service 48 | } 49 | 50 | // New creates a new instance of the EC2 Metadata service client. 51 | // 52 | // In the general use case the configuration for this service client should not 53 | // be needed and `nil` can be provided. Configuration is only needed if the 54 | // `ec2metadata.Config` defaults need to be overridden. Eg. Setting LogLevel. 55 | // 56 | // @note This configuration will NOT be merged with the default AWS service 57 | // client configuration `defaults.DefaultConfig`. Due to circular dependencies 58 | // with the defaults package and credentials EC2 Role Provider. 59 | func New(config *Config) *Client { 60 | service := &service.Service{ 61 | ServiceInfo: serviceinfo.ServiceInfo{ 62 | Config: copyConfig(config), 63 | ServiceName: "Client", 64 | Endpoint: "http://169.254.169.254/latest", 65 | APIVersion: "latest", 66 | }, 67 | } 68 | service.Initialize() 69 | service.Handlers.Unmarshal.PushBack(unmarshalHandler) 70 | service.Handlers.UnmarshalError.PushBack(unmarshalError) 71 | service.Handlers.Validate.Clear() 72 | service.Handlers.Validate.PushBack(validateEndpointHandler) 73 | 74 | return &Client{service} 75 | } 76 | 77 | func copyConfig(config *Config) *aws.Config { 78 | if config == nil { 79 | config = &Config{} 80 | } 81 | c := &aws.Config{ 82 | Credentials: credentials.AnonymousCredentials, 83 | Endpoint: config.Endpoint, 84 | HTTPClient: config.HTTPClient, 85 | Logger: config.Logger, 86 | LogLevel: config.LogLevel, 87 | MaxRetries: config.MaxRetries, 88 | } 89 | 90 | if c.HTTPClient == nil { 91 | c.HTTPClient = http.DefaultClient 92 | } 93 | if c.Logger == nil { 94 | c.Logger = aws.NewDefaultLogger() 95 | } 96 | if c.LogLevel == nil { 97 | c.LogLevel = aws.LogLevel(aws.LogOff) 98 | } 99 | if c.MaxRetries == nil { 100 | c.MaxRetries = aws.Int(DefaultRetries) 101 | } 102 | 103 | return c 104 | } 105 | 106 | type metadataOutput struct { 107 | Content string 108 | } 109 | 110 | func unmarshalHandler(r *request.Request) { 111 | defer r.HTTPResponse.Body.Close() 112 | b, err := ioutil.ReadAll(r.HTTPResponse.Body) 113 | if err != nil { 114 | r.Error = awserr.New("SerializationError", "unable to unmarshal EC2 metadata respose", err) 115 | } 116 | 117 | data := r.Data.(*metadataOutput) 118 | data.Content = string(b) 119 | } 120 | 121 | func unmarshalError(r *request.Request) { 122 | defer r.HTTPResponse.Body.Close() 123 | _, err := ioutil.ReadAll(r.HTTPResponse.Body) 124 | if err != nil { 125 | r.Error = awserr.New("SerializationError", "unable to unmarshal EC2 metadata error respose", err) 126 | } 127 | 128 | // TODO extract the error... 129 | } 130 | 131 | func validateEndpointHandler(r *request.Request) { 132 | if r.Service.Endpoint == "" { 133 | r.Error = aws.ErrMissingEndpoint 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/errors.go: -------------------------------------------------------------------------------- 1 | package aws 2 | 3 | import "github.com/rlister/let-me-in/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/awserr" 4 | 5 | var ( 6 | // ErrMissingRegion is an error that is returned if region configuration is 7 | // not found. 8 | // 9 | // @readonly 10 | ErrMissingRegion error = awserr.New("MissingRegion", "could not find region configuration", nil) 11 | 12 | // ErrMissingEndpoint is an error that is returned if an endpoint cannot be 13 | // resolved for a service. 14 | // 15 | // @readonly 16 | ErrMissingEndpoint error = awserr.New("MissingEndpoint", "'Endpoint' configuration is required for this service", nil) 17 | ) 18 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/logger.go: -------------------------------------------------------------------------------- 1 | package aws 2 | 3 | import ( 4 | "log" 5 | "os" 6 | ) 7 | 8 | // A LogLevelType defines the level logging should be performed at. Used to instruct 9 | // the SDK which statements should be logged. 10 | type LogLevelType uint 11 | 12 | // LogLevel returns the pointer to a LogLevel. Should be used to workaround 13 | // not being able to take the address of a non-composite literal. 14 | func LogLevel(l LogLevelType) *LogLevelType { 15 | return &l 16 | } 17 | 18 | // Value returns the LogLevel value or the default value LogOff if the LogLevel 19 | // is nil. Safe to use on nil value LogLevelTypes. 20 | func (l *LogLevelType) Value() LogLevelType { 21 | if l != nil { 22 | return *l 23 | } 24 | return LogOff 25 | } 26 | 27 | // Matches returns true if the v LogLevel is enabled by this LogLevel. Should be 28 | // used with logging sub levels. Is safe to use on nil value LogLevelTypes. If 29 | // LogLevel is nill, will default to LogOff comparison. 30 | func (l *LogLevelType) Matches(v LogLevelType) bool { 31 | c := l.Value() 32 | return c&v == v 33 | } 34 | 35 | // AtLeast returns true if this LogLevel is at least high enough to satisfies v. 36 | // Is safe to use on nil value LogLevelTypes. If LogLevel is nill, will default 37 | // to LogOff comparison. 38 | func (l *LogLevelType) AtLeast(v LogLevelType) bool { 39 | c := l.Value() 40 | return c >= v 41 | } 42 | 43 | const ( 44 | // LogOff states that no logging should be performed by the SDK. This is the 45 | // default state of the SDK, and should be use to disable all logging. 46 | LogOff LogLevelType = iota * 0x1000 47 | 48 | // LogDebug state that debug output should be logged by the SDK. This should 49 | // be used to inspect request made and responses received. 50 | LogDebug 51 | ) 52 | 53 | // Debug Logging Sub Levels 54 | const ( 55 | // LogDebugWithSigning states that the SDK should log request signing and 56 | // presigning events. This should be used to log the signing details of 57 | // requests for debugging. Will also enable LogDebug. 58 | LogDebugWithSigning LogLevelType = LogDebug | (1 << iota) 59 | 60 | // LogDebugWithHTTPBody states the SDK should log HTTP request and response 61 | // HTTP bodys in addition to the headers and path. This should be used to 62 | // see the body content of requests and responses made while using the SDK 63 | // Will also enable LogDebug. 64 | LogDebugWithHTTPBody 65 | 66 | // LogDebugWithRequestRetries states the SDK should log when service requests will 67 | // be retried. This should be used to log when you want to log when service 68 | // requests are being retried. Will also enable LogDebug. 69 | LogDebugWithRequestRetries 70 | 71 | // LogDebugWithRequestErrors states the SDK should log when service requests fail 72 | // to build, send, validate, or unmarshal. 73 | LogDebugWithRequestErrors 74 | ) 75 | 76 | // A Logger is a minimalistic interface for the SDK to log messages to. Should 77 | // be used to provide custom logging writers for the SDK to use. 78 | type Logger interface { 79 | Log(...interface{}) 80 | } 81 | 82 | // NewDefaultLogger returns a Logger which will write log messages to stdout, and 83 | // use same formatting runes as the stdlib log.Logger 84 | func NewDefaultLogger() Logger { 85 | return &defaultLogger{ 86 | logger: log.New(os.Stdout, "", log.LstdFlags), 87 | } 88 | } 89 | 90 | // A defaultLogger provides a minimalistic logger satisfying the Logger interface. 91 | type defaultLogger struct { 92 | logger *log.Logger 93 | } 94 | 95 | // Log logs the parameters to the stdlib logger. See log.Println. 96 | func (l defaultLogger) Log(args ...interface{}) { 97 | l.logger.Println(args...) 98 | } 99 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/request/handlers.go: -------------------------------------------------------------------------------- 1 | package request 2 | 3 | // A Handlers provides a collection of request handlers for various 4 | // stages of handling requests. 5 | type Handlers struct { 6 | Validate HandlerList 7 | Build HandlerList 8 | Sign HandlerList 9 | Send HandlerList 10 | ValidateResponse HandlerList 11 | Unmarshal HandlerList 12 | UnmarshalMeta HandlerList 13 | UnmarshalError HandlerList 14 | Retry HandlerList 15 | AfterRetry HandlerList 16 | } 17 | 18 | // Copy returns of this handler's lists. 19 | func (h *Handlers) Copy() Handlers { 20 | return Handlers{ 21 | Validate: h.Validate.copy(), 22 | Build: h.Build.copy(), 23 | Sign: h.Sign.copy(), 24 | Send: h.Send.copy(), 25 | ValidateResponse: h.ValidateResponse.copy(), 26 | Unmarshal: h.Unmarshal.copy(), 27 | UnmarshalError: h.UnmarshalError.copy(), 28 | UnmarshalMeta: h.UnmarshalMeta.copy(), 29 | Retry: h.Retry.copy(), 30 | AfterRetry: h.AfterRetry.copy(), 31 | } 32 | } 33 | 34 | // Clear removes callback functions for all handlers 35 | func (h *Handlers) Clear() { 36 | h.Validate.Clear() 37 | h.Build.Clear() 38 | h.Send.Clear() 39 | h.Sign.Clear() 40 | h.Unmarshal.Clear() 41 | h.UnmarshalMeta.Clear() 42 | h.UnmarshalError.Clear() 43 | h.ValidateResponse.Clear() 44 | h.Retry.Clear() 45 | h.AfterRetry.Clear() 46 | } 47 | 48 | // A HandlerList manages zero or more handlers in a list. 49 | type HandlerList struct { 50 | list []NamedHandler 51 | } 52 | 53 | // A NamedHandler is a struct that contains a name and function callback. 54 | type NamedHandler struct { 55 | Name string 56 | Fn func(*Request) 57 | } 58 | 59 | // copy creates a copy of the handler list. 60 | func (l *HandlerList) copy() HandlerList { 61 | var n HandlerList 62 | n.list = append([]NamedHandler{}, l.list...) 63 | return n 64 | } 65 | 66 | // Clear clears the handler list. 67 | func (l *HandlerList) Clear() { 68 | l.list = []NamedHandler{} 69 | } 70 | 71 | // Len returns the number of handlers in the list. 72 | func (l *HandlerList) Len() int { 73 | return len(l.list) 74 | } 75 | 76 | // PushBack pushes handler f to the back of the handler list. 77 | func (l *HandlerList) PushBack(f func(*Request)) { 78 | l.list = append(l.list, NamedHandler{"__anonymous", f}) 79 | } 80 | 81 | // PushFront pushes handler f to the front of the handler list. 82 | func (l *HandlerList) PushFront(f func(*Request)) { 83 | l.list = append([]NamedHandler{{"__anonymous", f}}, l.list...) 84 | } 85 | 86 | // PushBackNamed pushes named handler f to the back of the handler list. 87 | func (l *HandlerList) PushBackNamed(n NamedHandler) { 88 | l.list = append(l.list, n) 89 | } 90 | 91 | // PushFrontNamed pushes named handler f to the front of the handler list. 92 | func (l *HandlerList) PushFrontNamed(n NamedHandler) { 93 | l.list = append([]NamedHandler{n}, l.list...) 94 | } 95 | 96 | // Remove removes a NamedHandler n 97 | func (l *HandlerList) Remove(n NamedHandler) { 98 | newlist := []NamedHandler{} 99 | for _, m := range l.list { 100 | if m.Name != n.Name { 101 | newlist = append(newlist, m) 102 | } 103 | } 104 | l.list = newlist 105 | } 106 | 107 | // Run executes all handlers in the list with a given request object. 108 | func (l *HandlerList) Run(r *Request) { 109 | for _, f := range l.list { 110 | f.Fn(r) 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/request/handlers_test.go: -------------------------------------------------------------------------------- 1 | package request_test 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/assert" 7 | 8 | "github.com/rlister/let-me-in/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws" 9 | "github.com/rlister/let-me-in/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/request" 10 | ) 11 | 12 | func TestHandlerList(t *testing.T) { 13 | s := "" 14 | r := &request.Request{} 15 | l := request.HandlerList{} 16 | l.PushBack(func(r *request.Request) { 17 | s += "a" 18 | r.Data = s 19 | }) 20 | l.Run(r) 21 | assert.Equal(t, "a", s) 22 | assert.Equal(t, "a", r.Data) 23 | } 24 | 25 | func TestMultipleHandlers(t *testing.T) { 26 | r := &request.Request{} 27 | l := request.HandlerList{} 28 | l.PushBack(func(r *request.Request) { r.Data = nil }) 29 | l.PushFront(func(r *request.Request) { r.Data = aws.Bool(true) }) 30 | l.Run(r) 31 | if r.Data != nil { 32 | t.Error("Expected handler to execute") 33 | } 34 | } 35 | 36 | func TestNamedHandlers(t *testing.T) { 37 | l := request.HandlerList{} 38 | named := request.NamedHandler{"Name", func(r *request.Request) {}} 39 | named2 := request.NamedHandler{"NotName", func(r *request.Request) {}} 40 | l.PushBackNamed(named) 41 | l.PushBackNamed(named) 42 | l.PushBackNamed(named2) 43 | l.PushBack(func(r *request.Request) {}) 44 | assert.Equal(t, 4, l.Len()) 45 | l.Remove(named) 46 | assert.Equal(t, 2, l.Len()) 47 | } 48 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/request/retryer.go: -------------------------------------------------------------------------------- 1 | package request 2 | 3 | import ( 4 | "time" 5 | 6 | "github.com/rlister/let-me-in/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/awserr" 7 | ) 8 | 9 | // Retryer is an interface to control retry logic for a given service. 10 | // The default implementation used by most services is the service.DefaultRetryer 11 | // structure, which contains basic retry logic using exponential backoff. 12 | type Retryer interface { 13 | RetryRules(*Request) time.Duration 14 | ShouldRetry(*Request) bool 15 | MaxRetries() uint 16 | } 17 | 18 | // retryableCodes is a collection of service response codes which are retry-able 19 | // without any further action. 20 | var retryableCodes = map[string]struct{}{ 21 | "RequestError": {}, 22 | "ProvisionedThroughputExceededException": {}, 23 | "Throttling": {}, 24 | "ThrottlingException": {}, 25 | "RequestLimitExceeded": {}, 26 | "RequestThrottled": {}, 27 | } 28 | 29 | // credsExpiredCodes is a collection of error codes which signify the credentials 30 | // need to be refreshed. Expired tokens require refreshing of credentials, and 31 | // resigning before the request can be retried. 32 | var credsExpiredCodes = map[string]struct{}{ 33 | "ExpiredToken": {}, 34 | "ExpiredTokenException": {}, 35 | "RequestExpired": {}, // EC2 Only 36 | } 37 | 38 | func isCodeRetryable(code string) bool { 39 | if _, ok := retryableCodes[code]; ok { 40 | return true 41 | } 42 | 43 | return isCodeExpiredCreds(code) 44 | } 45 | 46 | func isCodeExpiredCreds(code string) bool { 47 | _, ok := credsExpiredCodes[code] 48 | return ok 49 | } 50 | 51 | // IsErrorRetryable returns whether the error is retryable, based on its Code. 52 | // Returns false if the request has no Error set. 53 | func (r *Request) IsErrorRetryable() bool { 54 | if r.Error != nil { 55 | if err, ok := r.Error.(awserr.Error); ok { 56 | return isCodeRetryable(err.Code()) 57 | } 58 | } 59 | return false 60 | } 61 | 62 | // IsErrorExpired returns whether the error code is a credential expiry error. 63 | // Returns false if the request has no Error set. 64 | func (r *Request) IsErrorExpired() bool { 65 | if r.Error != nil { 66 | if err, ok := r.Error.(awserr.Error); ok { 67 | return isCodeExpiredCreds(err.Code()) 68 | } 69 | } 70 | return false 71 | } 72 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/service/default_retryer.go: -------------------------------------------------------------------------------- 1 | package service 2 | 3 | import ( 4 | "math" 5 | "math/rand" 6 | "time" 7 | 8 | "github.com/rlister/let-me-in/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws" 9 | "github.com/rlister/let-me-in/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/request" 10 | ) 11 | 12 | // DefaultRetryer implements basic retry logic using exponential backoff for 13 | // most services. If you want to implement custom retry logic, implement the 14 | // request.Retryer interface or create a structure type that composes this 15 | // struct and override the specific methods. For example, to override only 16 | // the MaxRetries method: 17 | // 18 | // type retryer struct { 19 | // service.DefaultRetryer 20 | // } 21 | // 22 | // // This implementation always has 100 max retries 23 | // func (d retryer) MaxRetries() uint { return 100 } 24 | type DefaultRetryer struct { 25 | *Service 26 | } 27 | 28 | // MaxRetries returns the number of maximum returns the service will use to make 29 | // an individual API request. 30 | func (d DefaultRetryer) MaxRetries() uint { 31 | if aws.IntValue(d.Service.Config.MaxRetries) < 0 { 32 | return d.DefaultMaxRetries 33 | } 34 | return uint(aws.IntValue(d.Service.Config.MaxRetries)) 35 | } 36 | 37 | var seededRand = rand.New(rand.NewSource(time.Now().UnixNano())) 38 | 39 | // RetryRules returns the delay duration before retrying this request again 40 | func (d DefaultRetryer) RetryRules(r *request.Request) time.Duration { 41 | delay := int(math.Pow(2, float64(r.RetryCount))) * (seededRand.Intn(30) + 30) 42 | return time.Duration(delay) * time.Millisecond 43 | } 44 | 45 | // ShouldRetry returns if the request should be retried. 46 | func (d DefaultRetryer) ShouldRetry(r *request.Request) bool { 47 | if r.HTTPResponse.StatusCode >= 500 { 48 | return true 49 | } 50 | return r.IsErrorRetryable() 51 | } 52 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/service/service.go: -------------------------------------------------------------------------------- 1 | package service 2 | 3 | import ( 4 | "fmt" 5 | "io/ioutil" 6 | "net/http" 7 | "net/http/httputil" 8 | "regexp" 9 | "time" 10 | 11 | "github.com/rlister/let-me-in/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws" 12 | "github.com/rlister/let-me-in/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/corehandlers" 13 | "github.com/rlister/let-me-in/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/request" 14 | "github.com/rlister/let-me-in/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/service/serviceinfo" 15 | "github.com/rlister/let-me-in/Godeps/_workspace/src/github.com/aws/aws-sdk-go/internal/endpoints" 16 | ) 17 | 18 | // A Service implements the base service request and response handling 19 | // used by all services. 20 | type Service struct { 21 | serviceinfo.ServiceInfo 22 | request.Retryer 23 | DefaultMaxRetries uint 24 | Handlers request.Handlers 25 | } 26 | 27 | var schemeRE = regexp.MustCompile("^([^:]+)://") 28 | 29 | // New will return a pointer to a new Server object initialized. 30 | func New(config *aws.Config) *Service { 31 | svc := &Service{ServiceInfo: serviceinfo.ServiceInfo{Config: config}} 32 | svc.Initialize() 33 | return svc 34 | } 35 | 36 | // Initialize initializes the service. 37 | func (s *Service) Initialize() { 38 | if s.Config == nil { 39 | s.Config = &aws.Config{} 40 | } 41 | if s.Config.HTTPClient == nil { 42 | s.Config.HTTPClient = http.DefaultClient 43 | } 44 | if s.Config.SleepDelay == nil { 45 | s.Config.SleepDelay = time.Sleep 46 | } 47 | 48 | s.Retryer = DefaultRetryer{s} 49 | s.DefaultMaxRetries = 3 50 | s.Handlers.Validate.PushBackNamed(corehandlers.ValidateEndpointHandler) 51 | s.Handlers.Build.PushBackNamed(corehandlers.UserAgentHandler) 52 | s.Handlers.Sign.PushBackNamed(corehandlers.BuildContentLengthHandler) 53 | s.Handlers.Send.PushBackNamed(corehandlers.SendHandler) 54 | s.Handlers.AfterRetry.PushBackNamed(corehandlers.AfterRetryHandler) 55 | s.Handlers.ValidateResponse.PushBackNamed(corehandlers.ValidateResponseHandler) 56 | if !aws.BoolValue(s.Config.DisableParamValidation) { 57 | s.Handlers.Validate.PushBackNamed(corehandlers.ValidateParametersHandler) 58 | } 59 | s.AddDebugHandlers() 60 | s.buildEndpoint() 61 | } 62 | 63 | // NewRequest returns a new Request pointer for the service API 64 | // operation and parameters. 65 | func (s *Service) NewRequest(operation *request.Operation, params interface{}, data interface{}) *request.Request { 66 | return request.New(s.ServiceInfo, s.Handlers, s.Retryer, operation, params, data) 67 | } 68 | 69 | // buildEndpoint builds the endpoint values the service will use to make requests with. 70 | func (s *Service) buildEndpoint() { 71 | if aws.StringValue(s.Config.Endpoint) != "" { 72 | s.Endpoint = *s.Config.Endpoint 73 | } else if s.Endpoint == "" { 74 | s.Endpoint, s.SigningRegion = 75 | endpoints.EndpointForRegion(s.ServiceName, aws.StringValue(s.Config.Region)) 76 | } 77 | 78 | if s.Endpoint != "" && !schemeRE.MatchString(s.Endpoint) { 79 | scheme := "https" 80 | if aws.BoolValue(s.Config.DisableSSL) { 81 | scheme = "http" 82 | } 83 | s.Endpoint = scheme + "://" + s.Endpoint 84 | } 85 | } 86 | 87 | // AddDebugHandlers injects debug logging handlers into the service to log request 88 | // debug information. 89 | func (s *Service) AddDebugHandlers() { 90 | if !s.Config.LogLevel.AtLeast(aws.LogDebug) { 91 | return 92 | } 93 | 94 | s.Handlers.Send.PushFront(logRequest) 95 | s.Handlers.Send.PushBack(logResponse) 96 | } 97 | 98 | const logReqMsg = `DEBUG: Request %s/%s Details: 99 | ---[ REQUEST POST-SIGN ]----------------------------- 100 | %s 101 | -----------------------------------------------------` 102 | 103 | func logRequest(r *request.Request) { 104 | logBody := r.Service.Config.LogLevel.Matches(aws.LogDebugWithHTTPBody) 105 | dumpedBody, _ := httputil.DumpRequestOut(r.HTTPRequest, logBody) 106 | 107 | if logBody { 108 | // Reset the request body because dumpRequest will re-wrap the r.HTTPRequest's 109 | // Body as a NoOpCloser and will not be reset after read by the HTTP 110 | // client reader. 111 | r.Body.Seek(r.BodyStart, 0) 112 | r.HTTPRequest.Body = ioutil.NopCloser(r.Body) 113 | } 114 | 115 | r.Service.Config.Logger.Log(fmt.Sprintf(logReqMsg, r.Service.ServiceName, r.Operation.Name, string(dumpedBody))) 116 | } 117 | 118 | const logRespMsg = `DEBUG: Response %s/%s Details: 119 | ---[ RESPONSE ]-------------------------------------- 120 | %s 121 | -----------------------------------------------------` 122 | 123 | func logResponse(r *request.Request) { 124 | var msg = "no reponse data" 125 | if r.HTTPResponse != nil { 126 | logBody := r.Service.Config.LogLevel.Matches(aws.LogDebugWithHTTPBody) 127 | dumpedBody, _ := httputil.DumpResponse(r.HTTPResponse, logBody) 128 | msg = string(dumpedBody) 129 | } else if r.Error != nil { 130 | msg = r.Error.Error() 131 | } 132 | r.Service.Config.Logger.Log(fmt.Sprintf(logRespMsg, r.Service.ServiceName, r.Operation.Name, msg)) 133 | } 134 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/service/serviceinfo/service_info.go: -------------------------------------------------------------------------------- 1 | package serviceinfo 2 | 3 | import "github.com/rlister/let-me-in/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws" 4 | 5 | // ServiceInfo wraps immutable data from the service.Service structure. 6 | type ServiceInfo struct { 7 | Config *aws.Config 8 | ServiceName string 9 | APIVersion string 10 | Endpoint string 11 | SigningName string 12 | SigningRegion string 13 | JSONVersion string 14 | TargetPrefix string 15 | } 16 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/types.go: -------------------------------------------------------------------------------- 1 | package aws 2 | 3 | import ( 4 | "io" 5 | "sync" 6 | ) 7 | 8 | // ReadSeekCloser wraps a io.Reader returning a ReaderSeakerCloser 9 | func ReadSeekCloser(r io.Reader) ReaderSeekerCloser { 10 | return ReaderSeekerCloser{r} 11 | } 12 | 13 | // ReaderSeekerCloser represents a reader that can also delegate io.Seeker and 14 | // io.Closer interfaces to the underlying object if they are available. 15 | type ReaderSeekerCloser struct { 16 | r io.Reader 17 | } 18 | 19 | // Read reads from the reader up to size of p. The number of bytes read, and 20 | // error if it occurred will be returned. 21 | // 22 | // If the reader is not an io.Reader zero bytes read, and nil error will be returned. 23 | // 24 | // Performs the same functionality as io.Reader Read 25 | func (r ReaderSeekerCloser) Read(p []byte) (int, error) { 26 | switch t := r.r.(type) { 27 | case io.Reader: 28 | return t.Read(p) 29 | } 30 | return 0, nil 31 | } 32 | 33 | // Seek sets the offset for the next Read to offset, interpreted according to 34 | // whence: 0 means relative to the origin of the file, 1 means relative to the 35 | // current offset, and 2 means relative to the end. Seek returns the new offset 36 | // and an error, if any. 37 | // 38 | // If the ReaderSeekerCloser is not an io.Seeker nothing will be done. 39 | func (r ReaderSeekerCloser) Seek(offset int64, whence int) (int64, error) { 40 | switch t := r.r.(type) { 41 | case io.Seeker: 42 | return t.Seek(offset, whence) 43 | } 44 | return int64(0), nil 45 | } 46 | 47 | // Close closes the ReaderSeekerCloser. 48 | // 49 | // If the ReaderSeekerCloser is not an io.Closer nothing will be done. 50 | func (r ReaderSeekerCloser) Close() error { 51 | switch t := r.r.(type) { 52 | case io.Closer: 53 | return t.Close() 54 | } 55 | return nil 56 | } 57 | 58 | // A WriteAtBuffer provides a in memory buffer supporting the io.WriterAt interface 59 | // Can be used with the s3manager.Downloader to download content to a buffer 60 | // in memory. Safe to use concurrently. 61 | type WriteAtBuffer struct { 62 | buf []byte 63 | m sync.Mutex 64 | } 65 | 66 | // WriteAt writes a slice of bytes to a buffer starting at the position provided 67 | // The number of bytes written will be returned, or error. Can overwrite previous 68 | // written slices if the write ats overlap. 69 | func (b *WriteAtBuffer) WriteAt(p []byte, pos int64) (n int, err error) { 70 | b.m.Lock() 71 | defer b.m.Unlock() 72 | 73 | expLen := pos + int64(len(p)) 74 | if int64(len(b.buf)) < expLen { 75 | newBuf := make([]byte, expLen) 76 | copy(newBuf, b.buf) 77 | b.buf = newBuf 78 | } 79 | copy(b.buf[pos:], p) 80 | return len(p), nil 81 | } 82 | 83 | // Bytes returns a slice of bytes written to the buffer. 84 | func (b *WriteAtBuffer) Bytes() []byte { 85 | b.m.Lock() 86 | defer b.m.Unlock() 87 | return b.buf[:len(b.buf):len(b.buf)] 88 | } 89 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/types_test.go: -------------------------------------------------------------------------------- 1 | package aws 2 | 3 | import ( 4 | "math/rand" 5 | "testing" 6 | 7 | "github.com/stretchr/testify/assert" 8 | ) 9 | 10 | func TestWriteAtBuffer(t *testing.T) { 11 | b := &WriteAtBuffer{} 12 | 13 | n, err := b.WriteAt([]byte{1}, 0) 14 | assert.NoError(t, err) 15 | assert.Equal(t, 1, n) 16 | 17 | n, err = b.WriteAt([]byte{1, 1, 1}, 5) 18 | assert.NoError(t, err) 19 | assert.Equal(t, 3, n) 20 | 21 | n, err = b.WriteAt([]byte{2}, 1) 22 | assert.NoError(t, err) 23 | assert.Equal(t, 1, n) 24 | 25 | n, err = b.WriteAt([]byte{3}, 2) 26 | assert.NoError(t, err) 27 | assert.Equal(t, 1, n) 28 | 29 | assert.Equal(t, []byte{1, 2, 3, 0, 0, 1, 1, 1}, b.Bytes()) 30 | } 31 | 32 | func BenchmarkWriteAtBuffer(b *testing.B) { 33 | buf := &WriteAtBuffer{} 34 | r := rand.New(rand.NewSource(1)) 35 | 36 | b.ResetTimer() 37 | for i := 0; i < b.N; i++ { 38 | to := r.Intn(10) * 4096 39 | bs := make([]byte, to) 40 | buf.WriteAt(bs, r.Int63n(10)*4096) 41 | } 42 | } 43 | 44 | func BenchmarkWriteAtBufferParallel(b *testing.B) { 45 | buf := &WriteAtBuffer{} 46 | r := rand.New(rand.NewSource(1)) 47 | 48 | b.ResetTimer() 49 | b.RunParallel(func(pb *testing.PB) { 50 | for pb.Next() { 51 | to := r.Intn(10) * 4096 52 | bs := make([]byte, to) 53 | buf.WriteAt(bs, r.Int63n(10)*4096) 54 | } 55 | }) 56 | } 57 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/version.go: -------------------------------------------------------------------------------- 1 | // Package aws provides core functionality for making requests to AWS services. 2 | package aws 3 | 4 | // SDKName is the name of this AWS SDK 5 | const SDKName = "aws-sdk-go" 6 | 7 | // SDKVersion is the version of this SDK 8 | const SDKVersion = "0.9.6" 9 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/aws/aws-sdk-go/internal/endpoints/endpoints.go: -------------------------------------------------------------------------------- 1 | // Package endpoints validates regional endpoints for services. 2 | package endpoints 3 | 4 | //go:generate go run ../model/cli/gen-endpoints/main.go endpoints.json endpoints_map.go 5 | //go:generate gofmt -s -w endpoints_map.go 6 | 7 | import "strings" 8 | 9 | // EndpointForRegion returns an endpoint and its signing region for a service and region. 10 | // if the service and region pair are not found endpoint and signingRegion will be empty. 11 | func EndpointForRegion(svcName, region string) (endpoint, signingRegion string) { 12 | derivedKeys := []string{ 13 | region + "/" + svcName, 14 | region + "/*", 15 | "*/" + svcName, 16 | "*/*", 17 | } 18 | 19 | for _, key := range derivedKeys { 20 | if val, ok := endpointsMap.Endpoints[key]; ok { 21 | ep := val.Endpoint 22 | ep = strings.Replace(ep, "{region}", region, -1) 23 | ep = strings.Replace(ep, "{service}", svcName, -1) 24 | 25 | endpoint = ep 26 | signingRegion = val.SigningRegion 27 | return 28 | } 29 | } 30 | return 31 | } 32 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/aws/aws-sdk-go/internal/endpoints/endpoints.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 2, 3 | "endpoints": { 4 | "*/*": { 5 | "endpoint": "{service}.{region}.amazonaws.com" 6 | }, 7 | "cn-north-1/*": { 8 | "endpoint": "{service}.{region}.amazonaws.com.cn", 9 | "signatureVersion": "v4" 10 | }, 11 | "us-gov-west-1/iam": { 12 | "endpoint": "iam.us-gov.amazonaws.com" 13 | }, 14 | "us-gov-west-1/sts": { 15 | "endpoint": "sts.us-gov-west-1.amazonaws.com" 16 | }, 17 | "us-gov-west-1/s3": { 18 | "endpoint": "s3-{region}.amazonaws.com" 19 | }, 20 | "*/cloudfront": { 21 | "endpoint": "cloudfront.amazonaws.com", 22 | "signingRegion": "us-east-1" 23 | }, 24 | "*/cloudsearchdomain": { 25 | "endpoint": "", 26 | "signingRegion": "us-east-1" 27 | }, 28 | "*/iam": { 29 | "endpoint": "iam.amazonaws.com", 30 | "signingRegion": "us-east-1" 31 | }, 32 | "*/importexport": { 33 | "endpoint": "importexport.amazonaws.com", 34 | "signingRegion": "us-east-1" 35 | }, 36 | "*/route53": { 37 | "endpoint": "route53.amazonaws.com", 38 | "signingRegion": "us-east-1" 39 | }, 40 | "*/sts": { 41 | "endpoint": "sts.amazonaws.com", 42 | "signingRegion": "us-east-1" 43 | }, 44 | "us-east-1/sdb": { 45 | "endpoint": "sdb.amazonaws.com", 46 | "signingRegion": "us-east-1" 47 | }, 48 | "us-east-1/s3": { 49 | "endpoint": "s3.amazonaws.com" 50 | }, 51 | "us-west-1/s3": { 52 | "endpoint": "s3-{region}.amazonaws.com" 53 | }, 54 | "us-west-2/s3": { 55 | "endpoint": "s3-{region}.amazonaws.com" 56 | }, 57 | "eu-west-1/s3": { 58 | "endpoint": "s3-{region}.amazonaws.com" 59 | }, 60 | "ap-southeast-1/s3": { 61 | "endpoint": "s3-{region}.amazonaws.com" 62 | }, 63 | "ap-southeast-2/s3": { 64 | "endpoint": "s3-{region}.amazonaws.com" 65 | }, 66 | "ap-northeast-1/s3": { 67 | "endpoint": "s3-{region}.amazonaws.com" 68 | }, 69 | "sa-east-1/s3": { 70 | "endpoint": "s3-{region}.amazonaws.com" 71 | }, 72 | "eu-central-1/s3": { 73 | "endpoint": "{service}.{region}.amazonaws.com", 74 | "signatureVersion": "v4" 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/aws/aws-sdk-go/internal/endpoints/endpoints_map.go: -------------------------------------------------------------------------------- 1 | package endpoints 2 | 3 | // THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. 4 | 5 | type endpointStruct struct { 6 | Version int 7 | Endpoints map[string]endpointEntry 8 | } 9 | 10 | type endpointEntry struct { 11 | Endpoint string 12 | SigningRegion string 13 | } 14 | 15 | var endpointsMap = endpointStruct{ 16 | Version: 2, 17 | Endpoints: map[string]endpointEntry{ 18 | "*/*": { 19 | Endpoint: "{service}.{region}.amazonaws.com", 20 | }, 21 | "*/cloudfront": { 22 | Endpoint: "cloudfront.amazonaws.com", 23 | SigningRegion: "us-east-1", 24 | }, 25 | "*/cloudsearchdomain": { 26 | Endpoint: "", 27 | SigningRegion: "us-east-1", 28 | }, 29 | "*/iam": { 30 | Endpoint: "iam.amazonaws.com", 31 | SigningRegion: "us-east-1", 32 | }, 33 | "*/importexport": { 34 | Endpoint: "importexport.amazonaws.com", 35 | SigningRegion: "us-east-1", 36 | }, 37 | "*/route53": { 38 | Endpoint: "route53.amazonaws.com", 39 | SigningRegion: "us-east-1", 40 | }, 41 | "*/sts": { 42 | Endpoint: "sts.amazonaws.com", 43 | SigningRegion: "us-east-1", 44 | }, 45 | "ap-northeast-1/s3": { 46 | Endpoint: "s3-{region}.amazonaws.com", 47 | }, 48 | "ap-southeast-1/s3": { 49 | Endpoint: "s3-{region}.amazonaws.com", 50 | }, 51 | "ap-southeast-2/s3": { 52 | Endpoint: "s3-{region}.amazonaws.com", 53 | }, 54 | "cn-north-1/*": { 55 | Endpoint: "{service}.{region}.amazonaws.com.cn", 56 | }, 57 | "eu-central-1/s3": { 58 | Endpoint: "{service}.{region}.amazonaws.com", 59 | }, 60 | "eu-west-1/s3": { 61 | Endpoint: "s3-{region}.amazonaws.com", 62 | }, 63 | "sa-east-1/s3": { 64 | Endpoint: "s3-{region}.amazonaws.com", 65 | }, 66 | "us-east-1/s3": { 67 | Endpoint: "s3.amazonaws.com", 68 | }, 69 | "us-east-1/sdb": { 70 | Endpoint: "sdb.amazonaws.com", 71 | SigningRegion: "us-east-1", 72 | }, 73 | "us-gov-west-1/iam": { 74 | Endpoint: "iam.us-gov.amazonaws.com", 75 | }, 76 | "us-gov-west-1/s3": { 77 | Endpoint: "s3-{region}.amazonaws.com", 78 | }, 79 | "us-gov-west-1/sts": { 80 | Endpoint: "sts.us-gov-west-1.amazonaws.com", 81 | }, 82 | "us-west-1/s3": { 83 | Endpoint: "s3-{region}.amazonaws.com", 84 | }, 85 | "us-west-2/s3": { 86 | Endpoint: "s3-{region}.amazonaws.com", 87 | }, 88 | }, 89 | } 90 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/aws/aws-sdk-go/internal/endpoints/endpoints_test.go: -------------------------------------------------------------------------------- 1 | package endpoints 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/assert" 7 | ) 8 | 9 | func TestGlobalEndpoints(t *testing.T) { 10 | region := "mock-region-1" 11 | svcs := []string{"cloudfront", "iam", "importexport", "route53", "sts"} 12 | 13 | for _, name := range svcs { 14 | ep, sr := EndpointForRegion(name, region) 15 | assert.Equal(t, name+".amazonaws.com", ep) 16 | assert.Equal(t, "us-east-1", sr) 17 | } 18 | } 19 | 20 | func TestServicesInCN(t *testing.T) { 21 | region := "cn-north-1" 22 | svcs := []string{"cloudfront", "iam", "importexport", "route53", "sts", "s3"} 23 | 24 | for _, name := range svcs { 25 | ep, _ := EndpointForRegion(name, region) 26 | assert.Equal(t, name+"."+region+".amazonaws.com.cn", ep) 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/aws/aws-sdk-go/internal/protocol/ec2query/build.go: -------------------------------------------------------------------------------- 1 | // Package ec2query provides serialisation of AWS EC2 requests and responses. 2 | package ec2query 3 | 4 | //go:generate go run ../../fixtures/protocol/generate.go ../../fixtures/protocol/input/ec2.json build_test.go 5 | 6 | import ( 7 | "net/url" 8 | 9 | "github.com/rlister/let-me-in/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/awserr" 10 | "github.com/rlister/let-me-in/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/request" 11 | "github.com/rlister/let-me-in/Godeps/_workspace/src/github.com/aws/aws-sdk-go/internal/protocol/query/queryutil" 12 | ) 13 | 14 | // Build builds a request for the EC2 protocol. 15 | func Build(r *request.Request) { 16 | body := url.Values{ 17 | "Action": {r.Operation.Name}, 18 | "Version": {r.Service.APIVersion}, 19 | } 20 | if err := queryutil.Parse(body, r.Params, true); err != nil { 21 | r.Error = awserr.New("SerializationError", "failed encoding EC2 Query request", err) 22 | } 23 | 24 | if r.ExpireTime == 0 { 25 | r.HTTPRequest.Method = "POST" 26 | r.HTTPRequest.Header.Set("Content-Type", "application/x-www-form-urlencoded; charset=utf-8") 27 | r.SetBufferBody([]byte(body.Encode())) 28 | } else { // This is a pre-signed request 29 | r.HTTPRequest.Method = "GET" 30 | r.HTTPRequest.URL.RawQuery = body.Encode() 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/aws/aws-sdk-go/internal/protocol/ec2query/unmarshal.go: -------------------------------------------------------------------------------- 1 | package ec2query 2 | 3 | //go:generate go run ../../fixtures/protocol/generate.go ../../fixtures/protocol/output/ec2.json unmarshal_test.go 4 | 5 | import ( 6 | "encoding/xml" 7 | "io" 8 | 9 | "github.com/rlister/let-me-in/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/awserr" 10 | "github.com/rlister/let-me-in/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/request" 11 | "github.com/rlister/let-me-in/Godeps/_workspace/src/github.com/aws/aws-sdk-go/internal/protocol/xml/xmlutil" 12 | ) 13 | 14 | // Unmarshal unmarshals a response body for the EC2 protocol. 15 | func Unmarshal(r *request.Request) { 16 | defer r.HTTPResponse.Body.Close() 17 | if r.DataFilled() { 18 | decoder := xml.NewDecoder(r.HTTPResponse.Body) 19 | err := xmlutil.UnmarshalXML(r.Data, decoder, "") 20 | if err != nil { 21 | r.Error = awserr.New("SerializationError", "failed decoding EC2 Query response", err) 22 | return 23 | } 24 | } 25 | } 26 | 27 | // UnmarshalMeta unmarshals response headers for the EC2 protocol. 28 | func UnmarshalMeta(r *request.Request) { 29 | // TODO implement unmarshaling of request IDs 30 | } 31 | 32 | type xmlErrorResponse struct { 33 | XMLName xml.Name `xml:"Response"` 34 | Code string `xml:"Errors>Error>Code"` 35 | Message string `xml:"Errors>Error>Message"` 36 | RequestID string `xml:"RequestId"` 37 | } 38 | 39 | // UnmarshalError unmarshals a response error for the EC2 protocol. 40 | func UnmarshalError(r *request.Request) { 41 | defer r.HTTPResponse.Body.Close() 42 | 43 | resp := &xmlErrorResponse{} 44 | err := xml.NewDecoder(r.HTTPResponse.Body).Decode(resp) 45 | if err != nil && err != io.EOF { 46 | r.Error = awserr.New("SerializationError", "failed decoding EC2 Query error response", err) 47 | } else { 48 | r.Error = awserr.NewRequestFailure( 49 | awserr.New(resp.Code, resp.Message, nil), 50 | r.HTTPResponse.StatusCode, 51 | resp.RequestID, 52 | ) 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/aws/aws-sdk-go/internal/protocol/rest/payload.go: -------------------------------------------------------------------------------- 1 | package rest 2 | 3 | import "reflect" 4 | 5 | // PayloadMember returns the payload field member of i if there is one, or nil. 6 | func PayloadMember(i interface{}) interface{} { 7 | if i == nil { 8 | return nil 9 | } 10 | 11 | v := reflect.ValueOf(i).Elem() 12 | if !v.IsValid() { 13 | return nil 14 | } 15 | if field, ok := v.Type().FieldByName("SDKShapeTraits"); ok { 16 | if payloadName := field.Tag.Get("payload"); payloadName != "" { 17 | field, _ := v.Type().FieldByName(payloadName) 18 | if field.Tag.Get("type") != "structure" { 19 | return nil 20 | } 21 | 22 | payload := v.FieldByName(payloadName) 23 | if payload.IsValid() || (payload.Kind() == reflect.Ptr && !payload.IsNil()) { 24 | return payload.Interface() 25 | } 26 | } 27 | } 28 | return nil 29 | } 30 | 31 | // PayloadType returns the type of a payload field member of i if there is one, or "". 32 | func PayloadType(i interface{}) string { 33 | v := reflect.Indirect(reflect.ValueOf(i)) 34 | if !v.IsValid() { 35 | return "" 36 | } 37 | if field, ok := v.Type().FieldByName("SDKShapeTraits"); ok { 38 | if payloadName := field.Tag.Get("payload"); payloadName != "" { 39 | if member, ok := v.Type().FieldByName(payloadName); ok { 40 | return member.Tag.Get("type") 41 | } 42 | } 43 | } 44 | return "" 45 | } 46 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/aws/aws-sdk-go/internal/protocol/rest/unmarshal.go: -------------------------------------------------------------------------------- 1 | package rest 2 | 3 | import ( 4 | "encoding/base64" 5 | "fmt" 6 | "io/ioutil" 7 | "net/http" 8 | "reflect" 9 | "strconv" 10 | "strings" 11 | "time" 12 | 13 | "github.com/rlister/let-me-in/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws" 14 | "github.com/rlister/let-me-in/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/awserr" 15 | "github.com/rlister/let-me-in/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/request" 16 | ) 17 | 18 | // Unmarshal unmarshals the REST component of a response in a REST service. 19 | func Unmarshal(r *request.Request) { 20 | if r.DataFilled() { 21 | v := reflect.Indirect(reflect.ValueOf(r.Data)) 22 | unmarshalBody(r, v) 23 | } 24 | } 25 | 26 | // UnmarshalMeta unmarshals the REST metadata of a response in a REST service 27 | func UnmarshalMeta(r *request.Request) { 28 | r.RequestID = r.HTTPResponse.Header.Get("X-Amzn-Requestid") 29 | if r.DataFilled() { 30 | v := reflect.Indirect(reflect.ValueOf(r.Data)) 31 | unmarshalLocationElements(r, v) 32 | } 33 | } 34 | 35 | func unmarshalBody(r *request.Request, v reflect.Value) { 36 | if field, ok := v.Type().FieldByName("SDKShapeTraits"); ok { 37 | if payloadName := field.Tag.Get("payload"); payloadName != "" { 38 | pfield, _ := v.Type().FieldByName(payloadName) 39 | if ptag := pfield.Tag.Get("type"); ptag != "" && ptag != "structure" { 40 | payload := v.FieldByName(payloadName) 41 | if payload.IsValid() { 42 | switch payload.Interface().(type) { 43 | case []byte: 44 | b, err := ioutil.ReadAll(r.HTTPResponse.Body) 45 | if err != nil { 46 | r.Error = awserr.New("SerializationError", "failed to decode REST response", err) 47 | } else { 48 | payload.Set(reflect.ValueOf(b)) 49 | } 50 | case *string: 51 | b, err := ioutil.ReadAll(r.HTTPResponse.Body) 52 | if err != nil { 53 | r.Error = awserr.New("SerializationError", "failed to decode REST response", err) 54 | } else { 55 | str := string(b) 56 | payload.Set(reflect.ValueOf(&str)) 57 | } 58 | default: 59 | switch payload.Type().String() { 60 | case "io.ReadSeeker": 61 | payload.Set(reflect.ValueOf(aws.ReadSeekCloser(r.HTTPResponse.Body))) 62 | case "aws.ReadSeekCloser", "io.ReadCloser": 63 | payload.Set(reflect.ValueOf(r.HTTPResponse.Body)) 64 | default: 65 | r.Error = awserr.New("SerializationError", 66 | "failed to decode REST response", 67 | fmt.Errorf("unknown payload type %s", payload.Type())) 68 | } 69 | } 70 | } 71 | } 72 | } 73 | } 74 | } 75 | 76 | func unmarshalLocationElements(r *request.Request, v reflect.Value) { 77 | for i := 0; i < v.NumField(); i++ { 78 | m, field := v.Field(i), v.Type().Field(i) 79 | if n := field.Name; n[0:1] == strings.ToLower(n[0:1]) { 80 | continue 81 | } 82 | 83 | if m.IsValid() { 84 | name := field.Tag.Get("locationName") 85 | if name == "" { 86 | name = field.Name 87 | } 88 | 89 | switch field.Tag.Get("location") { 90 | case "statusCode": 91 | unmarshalStatusCode(m, r.HTTPResponse.StatusCode) 92 | case "header": 93 | err := unmarshalHeader(m, r.HTTPResponse.Header.Get(name)) 94 | if err != nil { 95 | r.Error = awserr.New("SerializationError", "failed to decode REST response", err) 96 | break 97 | } 98 | case "headers": 99 | prefix := field.Tag.Get("locationName") 100 | err := unmarshalHeaderMap(m, r.HTTPResponse.Header, prefix) 101 | if err != nil { 102 | r.Error = awserr.New("SerializationError", "failed to decode REST response", err) 103 | break 104 | } 105 | } 106 | } 107 | if r.Error != nil { 108 | return 109 | } 110 | } 111 | } 112 | 113 | func unmarshalStatusCode(v reflect.Value, statusCode int) { 114 | if !v.IsValid() { 115 | return 116 | } 117 | 118 | switch v.Interface().(type) { 119 | case *int64: 120 | s := int64(statusCode) 121 | v.Set(reflect.ValueOf(&s)) 122 | } 123 | } 124 | 125 | func unmarshalHeaderMap(r reflect.Value, headers http.Header, prefix string) error { 126 | switch r.Interface().(type) { 127 | case map[string]*string: // we only support string map value types 128 | out := map[string]*string{} 129 | for k, v := range headers { 130 | k = http.CanonicalHeaderKey(k) 131 | if strings.HasPrefix(strings.ToLower(k), strings.ToLower(prefix)) { 132 | out[k[len(prefix):]] = &v[0] 133 | } 134 | } 135 | r.Set(reflect.ValueOf(out)) 136 | } 137 | return nil 138 | } 139 | 140 | func unmarshalHeader(v reflect.Value, header string) error { 141 | if !v.IsValid() || (header == "" && v.Elem().Kind() != reflect.String) { 142 | return nil 143 | } 144 | 145 | switch v.Interface().(type) { 146 | case *string: 147 | v.Set(reflect.ValueOf(&header)) 148 | case []byte: 149 | b, err := base64.StdEncoding.DecodeString(header) 150 | if err != nil { 151 | return err 152 | } 153 | v.Set(reflect.ValueOf(&b)) 154 | case *bool: 155 | b, err := strconv.ParseBool(header) 156 | if err != nil { 157 | return err 158 | } 159 | v.Set(reflect.ValueOf(&b)) 160 | case *int64: 161 | i, err := strconv.ParseInt(header, 10, 64) 162 | if err != nil { 163 | return err 164 | } 165 | v.Set(reflect.ValueOf(&i)) 166 | case *float64: 167 | f, err := strconv.ParseFloat(header, 64) 168 | if err != nil { 169 | return err 170 | } 171 | v.Set(reflect.ValueOf(&f)) 172 | case *time.Time: 173 | t, err := time.Parse(RFC822, header) 174 | if err != nil { 175 | return err 176 | } 177 | v.Set(reflect.ValueOf(&t)) 178 | default: 179 | err := fmt.Errorf("Unsupported value for param %v (%s)", v.Interface(), v.Type()) 180 | return err 181 | } 182 | return nil 183 | } 184 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/aws/aws-sdk-go/internal/protocol/xml/xmlutil/xml_to_struct.go: -------------------------------------------------------------------------------- 1 | package xmlutil 2 | 3 | import ( 4 | "encoding/xml" 5 | "io" 6 | "sort" 7 | ) 8 | 9 | // A XMLNode contains the values to be encoded or decoded. 10 | type XMLNode struct { 11 | Name xml.Name `json:",omitempty"` 12 | Children map[string][]*XMLNode `json:",omitempty"` 13 | Text string `json:",omitempty"` 14 | Attr []xml.Attr `json:",omitempty"` 15 | } 16 | 17 | // NewXMLElement returns a pointer to a new XMLNode initialized to default values. 18 | func NewXMLElement(name xml.Name) *XMLNode { 19 | return &XMLNode{ 20 | Name: name, 21 | Children: map[string][]*XMLNode{}, 22 | Attr: []xml.Attr{}, 23 | } 24 | } 25 | 26 | // AddChild adds child to the XMLNode. 27 | func (n *XMLNode) AddChild(child *XMLNode) { 28 | if _, ok := n.Children[child.Name.Local]; !ok { 29 | n.Children[child.Name.Local] = []*XMLNode{} 30 | } 31 | n.Children[child.Name.Local] = append(n.Children[child.Name.Local], child) 32 | } 33 | 34 | // XMLToStruct converts a xml.Decoder stream to XMLNode with nested values. 35 | func XMLToStruct(d *xml.Decoder, s *xml.StartElement) (*XMLNode, error) { 36 | out := &XMLNode{} 37 | for { 38 | tok, err := d.Token() 39 | if tok == nil || err == io.EOF { 40 | break 41 | } 42 | if err != nil { 43 | return out, err 44 | } 45 | 46 | switch typed := tok.(type) { 47 | case xml.CharData: 48 | out.Text = string(typed.Copy()) 49 | case xml.StartElement: 50 | el := typed.Copy() 51 | out.Attr = el.Attr 52 | if out.Children == nil { 53 | out.Children = map[string][]*XMLNode{} 54 | } 55 | 56 | name := typed.Name.Local 57 | slice := out.Children[name] 58 | if slice == nil { 59 | slice = []*XMLNode{} 60 | } 61 | node, e := XMLToStruct(d, &el) 62 | if e != nil { 63 | return out, e 64 | } 65 | node.Name = typed.Name 66 | slice = append(slice, node) 67 | out.Children[name] = slice 68 | case xml.EndElement: 69 | if s != nil && s.Name.Local == typed.Name.Local { // matching end token 70 | return out, nil 71 | } 72 | } 73 | } 74 | return out, nil 75 | } 76 | 77 | // StructToXML writes an XMLNode to a xml.Encoder as tokens. 78 | func StructToXML(e *xml.Encoder, node *XMLNode, sorted bool) error { 79 | e.EncodeToken(xml.StartElement{Name: node.Name, Attr: node.Attr}) 80 | 81 | if node.Text != "" { 82 | e.EncodeToken(xml.CharData([]byte(node.Text))) 83 | } else if sorted { 84 | sortedNames := []string{} 85 | for k := range node.Children { 86 | sortedNames = append(sortedNames, k) 87 | } 88 | sort.Strings(sortedNames) 89 | 90 | for _, k := range sortedNames { 91 | for _, v := range node.Children[k] { 92 | StructToXML(e, v, sorted) 93 | } 94 | } 95 | } else { 96 | for _, c := range node.Children { 97 | for _, v := range c { 98 | StructToXML(e, v, sorted) 99 | } 100 | } 101 | } 102 | 103 | e.EncodeToken(xml.EndElement{Name: node.Name}) 104 | return e.Flush() 105 | } 106 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/aws/aws-sdk-go/internal/signer/v4/functional_test.go: -------------------------------------------------------------------------------- 1 | package v4_test 2 | 3 | import ( 4 | "net/url" 5 | "testing" 6 | "time" 7 | 8 | "github.com/aws/aws-sdk-go/internal/test/unit" 9 | "github.com/aws/aws-sdk-go/service/s3" 10 | "github.com/rlister/let-me-in/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws" 11 | "github.com/stretchr/testify/assert" 12 | ) 13 | 14 | var _ = unit.Imported 15 | 16 | func TestPresignHandler(t *testing.T) { 17 | svc := s3.New(nil) 18 | req, _ := svc.PutObjectRequest(&s3.PutObjectInput{ 19 | Bucket: aws.String("bucket"), 20 | Key: aws.String("key"), 21 | ContentDisposition: aws.String("a+b c$d"), 22 | ACL: aws.String("public-read"), 23 | }) 24 | req.Time = time.Unix(0, 0) 25 | urlstr, err := req.Presign(5 * time.Minute) 26 | 27 | assert.NoError(t, err) 28 | 29 | expectedDate := "19700101T000000Z" 30 | expectedHeaders := "host;x-amz-acl" 31 | expectedSig := "7edcb4e3a1bf12f4989018d75acbe3a7f03df24bd6f3112602d59fc551f0e4e2" 32 | expectedCred := "AKID/19700101/mock-region/s3/aws4_request" 33 | 34 | u, _ := url.Parse(urlstr) 35 | urlQ := u.Query() 36 | assert.Equal(t, expectedSig, urlQ.Get("X-Amz-Signature")) 37 | assert.Equal(t, expectedCred, urlQ.Get("X-Amz-Credential")) 38 | assert.Equal(t, expectedHeaders, urlQ.Get("X-Amz-SignedHeaders")) 39 | assert.Equal(t, expectedDate, urlQ.Get("X-Amz-Date")) 40 | assert.Equal(t, "300", urlQ.Get("X-Amz-Expires")) 41 | 42 | assert.NotContains(t, urlstr, "+") // + encoded as %20 43 | } 44 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/aws/aws-sdk-go/service/ec2/customizations.go: -------------------------------------------------------------------------------- 1 | package ec2 2 | 3 | import ( 4 | "time" 5 | 6 | "github.com/rlister/let-me-in/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/awsutil" 7 | "github.com/rlister/let-me-in/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/request" 8 | ) 9 | 10 | func init() { 11 | initRequest = func(r *request.Request) { 12 | if r.Operation.Name == opCopySnapshot { // fill the PresignedURL parameter 13 | r.Handlers.Build.PushFront(fillPresignedURL) 14 | } 15 | } 16 | } 17 | 18 | func fillPresignedURL(r *request.Request) { 19 | if !r.ParamsFilled() { 20 | return 21 | } 22 | 23 | params := r.Params.(*CopySnapshotInput) 24 | 25 | // Stop if PresignedURL/DestinationRegion is set 26 | if params.PresignedUrl != nil || params.DestinationRegion != nil { 27 | return 28 | } 29 | 30 | // First generate a copy of parameters 31 | r.Params = awsutil.CopyOf(r.Params) 32 | params = r.Params.(*CopySnapshotInput) 33 | 34 | // Set destination region. Avoids infinite handler loop. 35 | // Also needed to sign sub-request. 36 | params.DestinationRegion = r.Service.Config.Region 37 | 38 | // Create a new client pointing at source region. 39 | // We will use this to presign the CopySnapshot request against 40 | // the source region 41 | config := r.Service.Config.Copy(). 42 | WithEndpoint(""). 43 | WithRegion(*params.SourceRegion) 44 | 45 | client := New(config) 46 | 47 | // Presign a CopySnapshot request with modified params 48 | req, _ := client.CopySnapshotRequest(params) 49 | url, err := req.Presign(300 * time.Second) // 5 minutes should be enough. 50 | 51 | if err != nil { // bubble error back up to original request 52 | r.Error = err 53 | } 54 | 55 | // We have our URL, set it on params 56 | params.PresignedUrl = &url 57 | } 58 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/aws/aws-sdk-go/service/ec2/customizations_test.go: -------------------------------------------------------------------------------- 1 | package ec2_test 2 | 3 | import ( 4 | "io/ioutil" 5 | "net/url" 6 | "testing" 7 | 8 | "github.com/aws/aws-sdk-go/internal/test/unit" 9 | "github.com/rlister/let-me-in/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws" 10 | "github.com/rlister/let-me-in/Godeps/_workspace/src/github.com/aws/aws-sdk-go/service/ec2" 11 | "github.com/stretchr/testify/assert" 12 | ) 13 | 14 | var _ = unit.Imported 15 | 16 | func TestCopySnapshotPresignedURL(t *testing.T) { 17 | svc := ec2.New(&aws.Config{Region: aws.String("us-west-2")}) 18 | 19 | assert.NotPanics(t, func() { 20 | // Doesn't panic on nil input 21 | req, _ := svc.CopySnapshotRequest(nil) 22 | req.Sign() 23 | }) 24 | 25 | req, _ := svc.CopySnapshotRequest(&ec2.CopySnapshotInput{ 26 | SourceRegion: aws.String("us-west-1"), 27 | SourceSnapshotId: aws.String("snap-id"), 28 | }) 29 | req.Sign() 30 | 31 | b, _ := ioutil.ReadAll(req.HTTPRequest.Body) 32 | q, _ := url.ParseQuery(string(b)) 33 | url, _ := url.QueryUnescape(q.Get("PresignedUrl")) 34 | assert.Equal(t, "us-west-2", q.Get("DestinationRegion")) 35 | assert.Regexp(t, `^https://ec2\.us-west-1\.amazon.+&DestinationRegion=us-west-2`, url) 36 | } 37 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/aws/aws-sdk-go/service/ec2/ec2iface/interface_test.go: -------------------------------------------------------------------------------- 1 | // THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. 2 | 3 | package ec2iface_test 4 | 5 | import ( 6 | "testing" 7 | 8 | "github.com/rlister/let-me-in/Godeps/_workspace/src/github.com/aws/aws-sdk-go/service/ec2" 9 | "github.com/rlister/let-me-in/Godeps/_workspace/src/github.com/aws/aws-sdk-go/service/ec2/ec2iface" 10 | "github.com/stretchr/testify/assert" 11 | ) 12 | 13 | func TestInterface(t *testing.T) { 14 | assert.Implements(t, (*ec2iface.EC2API)(nil), ec2.New(nil)) 15 | } 16 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/aws/aws-sdk-go/service/ec2/service.go: -------------------------------------------------------------------------------- 1 | // THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. 2 | 3 | package ec2 4 | 5 | import ( 6 | "github.com/rlister/let-me-in/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws" 7 | "github.com/rlister/let-me-in/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/defaults" 8 | "github.com/rlister/let-me-in/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/request" 9 | "github.com/rlister/let-me-in/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/service" 10 | "github.com/rlister/let-me-in/Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/service/serviceinfo" 11 | "github.com/rlister/let-me-in/Godeps/_workspace/src/github.com/aws/aws-sdk-go/internal/protocol/ec2query" 12 | "github.com/rlister/let-me-in/Godeps/_workspace/src/github.com/aws/aws-sdk-go/internal/signer/v4" 13 | ) 14 | 15 | // Amazon Elastic Compute Cloud (Amazon EC2) provides resizable computing capacity 16 | // in the Amazon Web Services (AWS) cloud. Using Amazon EC2 eliminates your 17 | // need to invest in hardware up front, so you can develop and deploy applications 18 | // faster. 19 | type EC2 struct { 20 | *service.Service 21 | } 22 | 23 | // Used for custom service initialization logic 24 | var initService func(*service.Service) 25 | 26 | // Used for custom request initialization logic 27 | var initRequest func(*request.Request) 28 | 29 | // New returns a new EC2 client. 30 | func New(config *aws.Config) *EC2 { 31 | service := &service.Service{ 32 | ServiceInfo: serviceinfo.ServiceInfo{ 33 | Config: defaults.DefaultConfig.Merge(config), 34 | ServiceName: "ec2", 35 | APIVersion: "2015-04-15", 36 | }, 37 | } 38 | service.Initialize() 39 | 40 | // Handlers 41 | service.Handlers.Sign.PushBack(v4.Sign) 42 | service.Handlers.Build.PushBack(ec2query.Build) 43 | service.Handlers.Unmarshal.PushBack(ec2query.Unmarshal) 44 | service.Handlers.UnmarshalMeta.PushBack(ec2query.UnmarshalMeta) 45 | service.Handlers.UnmarshalError.PushBack(ec2query.UnmarshalError) 46 | 47 | // Run custom service initialization if present 48 | if initService != nil { 49 | initService(service) 50 | } 51 | 52 | return &EC2{service} 53 | } 54 | 55 | // newRequest creates a new request for a EC2 operation and runs any 56 | // custom request initialization. 57 | func (c *EC2) newRequest(op *request.Operation, params, data interface{}) *request.Request { 58 | req := c.NewRequest(op, params, data) 59 | 60 | // Run custom request initialization if present 61 | if initRequest != nil { 62 | initRequest(req) 63 | } 64 | 65 | return req 66 | } 67 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/jessevdk/go-flags/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | 3 | install: 4 | # go-flags 5 | - go get -d -v ./... 6 | - go build -v ./... 7 | 8 | # linting 9 | - go get golang.org/x/tools/cmd/vet 10 | - go get github.com/golang/lint 11 | - go install github.com/golang/lint/golint 12 | 13 | # code coverage 14 | - go get golang.org/x/tools/cmd/cover 15 | - go get github.com/onsi/ginkgo/ginkgo 16 | - go get github.com/modocache/gover 17 | - if [ "$TRAVIS_SECURE_ENV_VARS" = "true" ]; then go get github.com/mattn/goveralls; fi 18 | 19 | script: 20 | # go-flags 21 | - $(exit $(gofmt -l . | wc -l)) 22 | - go test -v ./... 23 | 24 | # linting 25 | - go tool vet -all=true -v=true . || true 26 | - $(go env GOPATH | awk 'BEGIN{FS=":"} {print $1}')/bin/golint ./... 27 | 28 | # code coverage 29 | - $(go env GOPATH | awk 'BEGIN{FS=":"} {print $1}')/bin/ginkgo -r -cover 30 | - $(go env GOPATH | awk 'BEGIN{FS=":"} {print $1}')/bin/gover 31 | - if [ "$TRAVIS_SECURE_ENV_VARS" = "true" ]; then $(go env GOPATH | awk 'BEGIN{FS=":"} {print $1}')/bin/goveralls -coverprofile=gover.coverprofile -service=travis-ci -repotoken $COVERALLS_TOKEN; fi 32 | 33 | env: 34 | # coveralls.io 35 | secure: "RCYbiB4P0RjQRIoUx/vG/AjP3mmYCbzOmr86DCww1Z88yNcy3hYr3Cq8rpPtYU5v0g7wTpu4adaKIcqRE9xknYGbqj3YWZiCoBP1/n4Z+9sHW3Dsd9D/GRGeHUus0laJUGARjWoCTvoEtOgTdGQDoX7mH+pUUY0FBltNYUdOiiU=" 36 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/jessevdk/go-flags/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012 Jesse van den Kieboom. All rights reserved. 2 | Redistribution and use in source and binary forms, with or without 3 | modification, are permitted provided that the following conditions are 4 | met: 5 | 6 | * Redistributions of source code must retain the above copyright 7 | notice, this list of conditions and the following disclaimer. 8 | * Redistributions in binary form must reproduce the above 9 | copyright notice, this list of conditions and the following disclaimer 10 | in the documentation and/or other materials provided with the 11 | distribution. 12 | * Neither the name of Google Inc. nor the names of its 13 | contributors may be used to endorse or promote products derived from 14 | this software without specific prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/jessevdk/go-flags/README.md: -------------------------------------------------------------------------------- 1 | go-flags: a go library for parsing command line arguments 2 | ========================================================= 3 | 4 | [![GoDoc](https://godoc.org/github.com/jessevdk/go-flags?status.png)](https://godoc.org/github.com/jessevdk/go-flags) [![Build Status](https://travis-ci.org/jessevdk/go-flags.svg?branch=master)](https://travis-ci.org/jessevdk/go-flags) [![Coverage Status](https://img.shields.io/coveralls/jessevdk/go-flags.svg)](https://coveralls.io/r/jessevdk/go-flags?branch=master) 5 | 6 | This library provides similar functionality to the builtin flag library of 7 | go, but provides much more functionality and nicer formatting. From the 8 | documentation: 9 | 10 | Package flags provides an extensive command line option parser. 11 | The flags package is similar in functionality to the go builtin flag package 12 | but provides more options and uses reflection to provide a convenient and 13 | succinct way of specifying command line options. 14 | 15 | Supported features: 16 | * Options with short names (-v) 17 | * Options with long names (--verbose) 18 | * Options with and without arguments (bool v.s. other type) 19 | * Options with optional arguments and default values 20 | * Multiple option groups each containing a set of options 21 | * Generate and print well-formatted help message 22 | * Passing remaining command line arguments after -- (optional) 23 | * Ignoring unknown command line options (optional) 24 | * Supports -I/usr/include -I=/usr/include -I /usr/include option argument specification 25 | * Supports multiple short options -aux 26 | * Supports all primitive go types (string, int{8..64}, uint{8..64}, float) 27 | * Supports same option multiple times (can store in slice or last option counts) 28 | * Supports maps 29 | * Supports function callbacks 30 | * Supports namespaces for (nested) option groups 31 | 32 | The flags package uses structs, reflection and struct field tags 33 | to allow users to specify command line options. This results in very simple 34 | and concise specification of your application options. For example: 35 | 36 | type Options struct { 37 | Verbose []bool `short:"v" long:"verbose" description:"Show verbose debug information"` 38 | } 39 | 40 | This specifies one option with a short name -v and a long name --verbose. 41 | When either -v or --verbose is found on the command line, a 'true' value 42 | will be appended to the Verbose field. e.g. when specifying -vvv, the 43 | resulting value of Verbose will be {[true, true, true]}. 44 | 45 | Example: 46 | -------- 47 | var opts struct { 48 | // Slice of bool will append 'true' each time the option 49 | // is encountered (can be set multiple times, like -vvv) 50 | Verbose []bool `short:"v" long:"verbose" description:"Show verbose debug information"` 51 | 52 | // Example of automatic marshalling to desired type (uint) 53 | Offset uint `long:"offset" description:"Offset"` 54 | 55 | // Example of a callback, called each time the option is found. 56 | Call func(string) `short:"c" description:"Call phone number"` 57 | 58 | // Example of a required flag 59 | Name string `short:"n" long:"name" description:"A name" required:"true"` 60 | 61 | // Example of a value name 62 | File string `short:"f" long:"file" description:"A file" value-name:"FILE"` 63 | 64 | // Example of a pointer 65 | Ptr *int `short:"p" description:"A pointer to an integer"` 66 | 67 | // Example of a slice of strings 68 | StringSlice []string `short:"s" description:"A slice of strings"` 69 | 70 | // Example of a slice of pointers 71 | PtrSlice []*string `long:"ptrslice" description:"A slice of pointers to string"` 72 | 73 | // Example of a map 74 | IntMap map[string]int `long:"intmap" description:"A map from string to int"` 75 | } 76 | 77 | // Callback which will invoke callto: to call a number. 78 | // Note that this works just on OS X (and probably only with 79 | // Skype) but it shows the idea. 80 | opts.Call = func(num string) { 81 | cmd := exec.Command("open", "callto:"+num) 82 | cmd.Start() 83 | cmd.Process.Release() 84 | } 85 | 86 | // Make some fake arguments to parse. 87 | args := []string{ 88 | "-vv", 89 | "--offset=5", 90 | "-n", "Me", 91 | "-p", "3", 92 | "-s", "hello", 93 | "-s", "world", 94 | "--ptrslice", "hello", 95 | "--ptrslice", "world", 96 | "--intmap", "a:1", 97 | "--intmap", "b:5", 98 | "arg1", 99 | "arg2", 100 | "arg3", 101 | } 102 | 103 | // Parse flags from `args'. Note that here we use flags.ParseArgs for 104 | // the sake of making a working example. Normally, you would simply use 105 | // flags.Parse(&opts) which uses os.Args 106 | args, err := flags.ParseArgs(&opts, args) 107 | 108 | if err != nil { 109 | panic(err) 110 | os.Exit(1) 111 | } 112 | 113 | fmt.Printf("Verbosity: %v\n", opts.Verbose) 114 | fmt.Printf("Offset: %d\n", opts.Offset) 115 | fmt.Printf("Name: %s\n", opts.Name) 116 | fmt.Printf("Ptr: %d\n", *opts.Ptr) 117 | fmt.Printf("StringSlice: %v\n", opts.StringSlice) 118 | fmt.Printf("PtrSlice: [%v %v]\n", *opts.PtrSlice[0], *opts.PtrSlice[1]) 119 | fmt.Printf("IntMap: [a:%v b:%v]\n", opts.IntMap["a"], opts.IntMap["b"]) 120 | fmt.Printf("Remaining args: %s\n", strings.Join(args, " ")) 121 | 122 | // Output: Verbosity: [true true] 123 | // Offset: 5 124 | // Name: Me 125 | // Ptr: 3 126 | // StringSlice: [hello world] 127 | // PtrSlice: [hello world] 128 | // IntMap: [a:1 b:5] 129 | // Remaining args: arg1 arg2 arg3 130 | 131 | More information can be found in the godocs: 132 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/jessevdk/go-flags/arg.go: -------------------------------------------------------------------------------- 1 | package flags 2 | 3 | import ( 4 | "reflect" 5 | ) 6 | 7 | // Arg represents a positional argument on the command line. 8 | type Arg struct { 9 | // The name of the positional argument (used in the help) 10 | Name string 11 | 12 | // A description of the positional argument (used in the help) 13 | Description string 14 | 15 | // Whether a positional argument is required 16 | Required int 17 | 18 | value reflect.Value 19 | tag multiTag 20 | } 21 | 22 | func (a *Arg) isRemaining() bool { 23 | return a.value.Type().Kind() == reflect.Slice 24 | } 25 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/jessevdk/go-flags/arg_test.go: -------------------------------------------------------------------------------- 1 | package flags 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestPositional(t *testing.T) { 8 | var opts = struct { 9 | Value bool `short:"v"` 10 | 11 | Positional struct { 12 | Command int 13 | Filename string 14 | Rest []string 15 | } `positional-args:"yes" required:"yes"` 16 | }{} 17 | 18 | p := NewParser(&opts, Default) 19 | ret, err := p.ParseArgs([]string{"10", "arg_test.go", "a", "b"}) 20 | 21 | if err != nil { 22 | t.Fatalf("Unexpected error: %v", err) 23 | return 24 | } 25 | 26 | if opts.Positional.Command != 10 { 27 | t.Fatalf("Expected opts.Positional.Command to be 10, but got %v", opts.Positional.Command) 28 | } 29 | 30 | if opts.Positional.Filename != "arg_test.go" { 31 | t.Fatalf("Expected opts.Positional.Filename to be \"arg_test.go\", but got %v", opts.Positional.Filename) 32 | } 33 | 34 | assertStringArray(t, opts.Positional.Rest, []string{"a", "b"}) 35 | assertStringArray(t, ret, []string{}) 36 | } 37 | 38 | func TestPositionalRequired(t *testing.T) { 39 | var opts = struct { 40 | Value bool `short:"v"` 41 | 42 | Positional struct { 43 | Command int 44 | Filename string 45 | Rest []string 46 | } `positional-args:"yes" required:"yes"` 47 | }{} 48 | 49 | p := NewParser(&opts, None) 50 | _, err := p.ParseArgs([]string{"10"}) 51 | 52 | assertError(t, err, ErrRequired, "the required argument `Filename` was not provided") 53 | } 54 | 55 | func TestPositionalRequiredRest1Fail(t *testing.T) { 56 | var opts = struct { 57 | Value bool `short:"v"` 58 | 59 | Positional struct { 60 | Rest []string `required:"yes"` 61 | } `positional-args:"yes"` 62 | }{} 63 | 64 | p := NewParser(&opts, None) 65 | _, err := p.ParseArgs([]string{}) 66 | 67 | assertError(t, err, ErrRequired, "the required argument `Rest (at least 1 argument)` was not provided") 68 | } 69 | 70 | func TestPositionalRequiredRest1Pass(t *testing.T) { 71 | var opts = struct { 72 | Value bool `short:"v"` 73 | 74 | Positional struct { 75 | Rest []string `required:"yes"` 76 | } `positional-args:"yes"` 77 | }{} 78 | 79 | p := NewParser(&opts, None) 80 | _, err := p.ParseArgs([]string{"rest1"}) 81 | 82 | if err != nil { 83 | t.Fatalf("Unexpected error: %v", err) 84 | return 85 | } 86 | 87 | if len(opts.Positional.Rest) != 1 { 88 | t.Fatalf("Expected 1 positional rest argument") 89 | } 90 | 91 | assertString(t, opts.Positional.Rest[0], "rest1") 92 | } 93 | 94 | func TestPositionalRequiredRest2Fail(t *testing.T) { 95 | var opts = struct { 96 | Value bool `short:"v"` 97 | 98 | Positional struct { 99 | Rest []string `required:"2"` 100 | } `positional-args:"yes"` 101 | }{} 102 | 103 | p := NewParser(&opts, None) 104 | _, err := p.ParseArgs([]string{"rest1"}) 105 | 106 | assertError(t, err, ErrRequired, "the required argument `Rest (at least 2 arguments, but got only 1)` was not provided") 107 | } 108 | 109 | func TestPositionalRequiredRest2Pass(t *testing.T) { 110 | var opts = struct { 111 | Value bool `short:"v"` 112 | 113 | Positional struct { 114 | Rest []string `required:"2"` 115 | } `positional-args:"yes"` 116 | }{} 117 | 118 | p := NewParser(&opts, None) 119 | _, err := p.ParseArgs([]string{"rest1", "rest2", "rest3"}) 120 | 121 | if err != nil { 122 | t.Fatalf("Unexpected error: %v", err) 123 | return 124 | } 125 | 126 | if len(opts.Positional.Rest) != 3 { 127 | t.Fatalf("Expected 3 positional rest argument") 128 | } 129 | 130 | assertString(t, opts.Positional.Rest[0], "rest1") 131 | assertString(t, opts.Positional.Rest[1], "rest2") 132 | assertString(t, opts.Positional.Rest[2], "rest3") 133 | } 134 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/jessevdk/go-flags/assert_test.go: -------------------------------------------------------------------------------- 1 | package flags 2 | 3 | import ( 4 | "fmt" 5 | "io" 6 | "io/ioutil" 7 | "os" 8 | "os/exec" 9 | "path" 10 | "runtime" 11 | "testing" 12 | ) 13 | 14 | func assertCallerInfo() (string, int) { 15 | ptr := make([]uintptr, 15) 16 | n := runtime.Callers(1, ptr) 17 | 18 | if n == 0 { 19 | return "", 0 20 | } 21 | 22 | mef := runtime.FuncForPC(ptr[0]) 23 | mefile, meline := mef.FileLine(ptr[0]) 24 | 25 | for i := 2; i < n; i++ { 26 | f := runtime.FuncForPC(ptr[i]) 27 | file, line := f.FileLine(ptr[i]) 28 | 29 | if file != mefile { 30 | return file, line 31 | } 32 | } 33 | 34 | return mefile, meline 35 | } 36 | 37 | func assertErrorf(t *testing.T, format string, args ...interface{}) { 38 | msg := fmt.Sprintf(format, args...) 39 | 40 | file, line := assertCallerInfo() 41 | 42 | t.Errorf("%s:%d: %s", path.Base(file), line, msg) 43 | } 44 | 45 | func assertFatalf(t *testing.T, format string, args ...interface{}) { 46 | msg := fmt.Sprintf(format, args...) 47 | 48 | file, line := assertCallerInfo() 49 | 50 | t.Fatalf("%s:%d: %s", path.Base(file), line, msg) 51 | } 52 | 53 | func assertString(t *testing.T, a string, b string) { 54 | if a != b { 55 | assertErrorf(t, "Expected %#v, but got %#v", b, a) 56 | } 57 | } 58 | 59 | func assertStringArray(t *testing.T, a []string, b []string) { 60 | if len(a) != len(b) { 61 | assertErrorf(t, "Expected %#v, but got %#v", b, a) 62 | return 63 | } 64 | 65 | for i, v := range a { 66 | if b[i] != v { 67 | assertErrorf(t, "Expected %#v, but got %#v", b, a) 68 | return 69 | } 70 | } 71 | } 72 | 73 | func assertBoolArray(t *testing.T, a []bool, b []bool) { 74 | if len(a) != len(b) { 75 | assertErrorf(t, "Expected %#v, but got %#v", b, a) 76 | return 77 | } 78 | 79 | for i, v := range a { 80 | if b[i] != v { 81 | assertErrorf(t, "Expected %#v, but got %#v", b, a) 82 | return 83 | } 84 | } 85 | } 86 | 87 | func assertParserSuccess(t *testing.T, data interface{}, args ...string) (*Parser, []string) { 88 | parser := NewParser(data, Default&^PrintErrors) 89 | ret, err := parser.ParseArgs(args) 90 | 91 | if err != nil { 92 | t.Fatalf("Unexpected parse error: %s", err) 93 | return nil, nil 94 | } 95 | 96 | return parser, ret 97 | } 98 | 99 | func assertParseSuccess(t *testing.T, data interface{}, args ...string) []string { 100 | _, ret := assertParserSuccess(t, data, args...) 101 | return ret 102 | } 103 | 104 | func assertError(t *testing.T, err error, typ ErrorType, msg string) { 105 | if err == nil { 106 | assertFatalf(t, "Expected error: %s", msg) 107 | return 108 | } 109 | 110 | if e, ok := err.(*Error); !ok { 111 | assertFatalf(t, "Expected Error type, but got %#v", err) 112 | } else { 113 | if e.Type != typ { 114 | assertErrorf(t, "Expected error type {%s}, but got {%s}", typ, e.Type) 115 | } 116 | 117 | if e.Message != msg { 118 | assertErrorf(t, "Expected error message %#v, but got %#v", msg, e.Message) 119 | } 120 | } 121 | } 122 | 123 | func assertParseFail(t *testing.T, typ ErrorType, msg string, data interface{}, args ...string) []string { 124 | parser := NewParser(data, Default&^PrintErrors) 125 | ret, err := parser.ParseArgs(args) 126 | 127 | assertError(t, err, typ, msg) 128 | return ret 129 | } 130 | 131 | func diff(a, b string) (string, error) { 132 | atmp, err := ioutil.TempFile("", "help-diff") 133 | 134 | if err != nil { 135 | return "", err 136 | } 137 | 138 | btmp, err := ioutil.TempFile("", "help-diff") 139 | 140 | if err != nil { 141 | return "", err 142 | } 143 | 144 | if _, err := io.WriteString(atmp, a); err != nil { 145 | return "", err 146 | } 147 | 148 | if _, err := io.WriteString(btmp, b); err != nil { 149 | return "", err 150 | } 151 | 152 | ret, err := exec.Command("diff", "-u", "-d", "--label", "got", atmp.Name(), "--label", "expected", btmp.Name()).Output() 153 | 154 | os.Remove(atmp.Name()) 155 | os.Remove(btmp.Name()) 156 | 157 | if err.Error() == "exit status 1" { 158 | return string(ret), nil 159 | } 160 | 161 | return string(ret), err 162 | } 163 | 164 | func assertDiff(t *testing.T, actual, expected, msg string) { 165 | if actual == expected { 166 | return 167 | } 168 | 169 | ret, err := diff(actual, expected) 170 | 171 | if err != nil { 172 | assertErrorf(t, "Unexpected diff error: %s", err) 173 | assertErrorf(t, "Unexpected %s, expected:\n\n%s\n\nbut got\n\n%s", msg, expected, actual) 174 | } else { 175 | assertErrorf(t, "Unexpected %s:\n\n%s", msg, ret) 176 | } 177 | } 178 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/jessevdk/go-flags/check_crosscompile.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | echo '# linux arm7' 6 | GOARM=7 GOARCH=arm GOOS=linux go build 7 | echo '# linux arm5' 8 | GOARM=5 GOARCH=arm GOOS=linux go build 9 | echo '# windows 386' 10 | GOARCH=386 GOOS=windows go build 11 | echo '# windows amd64' 12 | GOARCH=amd64 GOOS=windows go build 13 | echo '# darwin' 14 | GOARCH=amd64 GOOS=darwin go build 15 | echo '# freebsd' 16 | GOARCH=amd64 GOOS=freebsd go build 17 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/jessevdk/go-flags/closest.go: -------------------------------------------------------------------------------- 1 | package flags 2 | 3 | func levenshtein(s string, t string) int { 4 | if len(s) == 0 { 5 | return len(t) 6 | } 7 | 8 | if len(t) == 0 { 9 | return len(s) 10 | } 11 | 12 | dists := make([][]int, len(s)+1) 13 | for i := range dists { 14 | dists[i] = make([]int, len(t)+1) 15 | dists[i][0] = i 16 | } 17 | 18 | for j := range t { 19 | dists[0][j] = j 20 | } 21 | 22 | for i, sc := range s { 23 | for j, tc := range t { 24 | if sc == tc { 25 | dists[i+1][j+1] = dists[i][j] 26 | } else { 27 | dists[i+1][j+1] = dists[i][j] + 1 28 | if dists[i+1][j] < dists[i+1][j+1] { 29 | dists[i+1][j+1] = dists[i+1][j] + 1 30 | } 31 | if dists[i][j+1] < dists[i+1][j+1] { 32 | dists[i+1][j+1] = dists[i][j+1] + 1 33 | } 34 | } 35 | } 36 | } 37 | 38 | return dists[len(s)][len(t)] 39 | } 40 | 41 | func closestChoice(cmd string, choices []string) (string, int) { 42 | if len(choices) == 0 { 43 | return "", 0 44 | } 45 | 46 | mincmd := -1 47 | mindist := -1 48 | 49 | for i, c := range choices { 50 | l := levenshtein(cmd, c) 51 | 52 | if mincmd < 0 || l < mindist { 53 | mindist = l 54 | mincmd = i 55 | } 56 | } 57 | 58 | return choices[mincmd], mindist 59 | } 60 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/jessevdk/go-flags/convert_test.go: -------------------------------------------------------------------------------- 1 | package flags 2 | 3 | import ( 4 | "testing" 5 | "time" 6 | ) 7 | 8 | func expectConvert(t *testing.T, o *Option, expected string) { 9 | s, err := convertToString(o.value, o.tag) 10 | 11 | if err != nil { 12 | t.Errorf("Unexpected error: %v", err) 13 | return 14 | } 15 | 16 | assertString(t, s, expected) 17 | } 18 | 19 | func TestConvertToString(t *testing.T) { 20 | d, _ := time.ParseDuration("1h2m4s") 21 | 22 | var opts = struct { 23 | String string `long:"string"` 24 | 25 | Int int `long:"int"` 26 | Int8 int8 `long:"int8"` 27 | Int16 int16 `long:"int16"` 28 | Int32 int32 `long:"int32"` 29 | Int64 int64 `long:"int64"` 30 | 31 | Uint uint `long:"uint"` 32 | Uint8 uint8 `long:"uint8"` 33 | Uint16 uint16 `long:"uint16"` 34 | Uint32 uint32 `long:"uint32"` 35 | Uint64 uint64 `long:"uint64"` 36 | 37 | Float32 float32 `long:"float32"` 38 | Float64 float64 `long:"float64"` 39 | 40 | Duration time.Duration `long:"duration"` 41 | 42 | Bool bool `long:"bool"` 43 | 44 | IntSlice []int `long:"int-slice"` 45 | IntFloatMap map[int]float64 `long:"int-float-map"` 46 | 47 | PtrBool *bool `long:"ptr-bool"` 48 | Interface interface{} `long:"interface"` 49 | 50 | Int32Base int32 `long:"int32-base" base:"16"` 51 | Uint32Base uint32 `long:"uint32-base" base:"16"` 52 | }{ 53 | "string", 54 | 55 | -2, 56 | -1, 57 | 0, 58 | 1, 59 | 2, 60 | 61 | 1, 62 | 2, 63 | 3, 64 | 4, 65 | 5, 66 | 67 | 1.2, 68 | -3.4, 69 | 70 | d, 71 | true, 72 | 73 | []int{-3, 4, -2}, 74 | map[int]float64{-2: 4.5}, 75 | 76 | new(bool), 77 | float32(5.2), 78 | 79 | -5823, 80 | 4232, 81 | } 82 | 83 | p := NewNamedParser("test", Default) 84 | grp, _ := p.AddGroup("test group", "", &opts) 85 | 86 | expects := []string{ 87 | "string", 88 | "-2", 89 | "-1", 90 | "0", 91 | "1", 92 | "2", 93 | 94 | "1", 95 | "2", 96 | "3", 97 | "4", 98 | "5", 99 | 100 | "1.2", 101 | "-3.4", 102 | 103 | "1h2m4s", 104 | "true", 105 | 106 | "[-3, 4, -2]", 107 | "{-2:4.5}", 108 | 109 | "false", 110 | "5.2", 111 | 112 | "-16bf", 113 | "1088", 114 | } 115 | 116 | for i, v := range grp.Options() { 117 | expectConvert(t, v, expects[i]) 118 | } 119 | } 120 | 121 | func TestConvertToStringInvalidIntBase(t *testing.T) { 122 | var opts = struct { 123 | Int int `long:"int" base:"no"` 124 | }{ 125 | 2, 126 | } 127 | 128 | p := NewNamedParser("test", Default) 129 | grp, _ := p.AddGroup("test group", "", &opts) 130 | o := grp.Options()[0] 131 | 132 | _, err := convertToString(o.value, o.tag) 133 | 134 | if err != nil { 135 | err = newErrorf(ErrMarshal, "%v", err) 136 | } 137 | 138 | assertError(t, err, ErrMarshal, "strconv.ParseInt: parsing \"no\": invalid syntax") 139 | } 140 | 141 | func TestConvertToStringInvalidUintBase(t *testing.T) { 142 | var opts = struct { 143 | Uint uint `long:"uint" base:"no"` 144 | }{ 145 | 2, 146 | } 147 | 148 | p := NewNamedParser("test", Default) 149 | grp, _ := p.AddGroup("test group", "", &opts) 150 | o := grp.Options()[0] 151 | 152 | _, err := convertToString(o.value, o.tag) 153 | 154 | if err != nil { 155 | err = newErrorf(ErrMarshal, "%v", err) 156 | } 157 | 158 | assertError(t, err, ErrMarshal, "strconv.ParseInt: parsing \"no\": invalid syntax") 159 | } 160 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/jessevdk/go-flags/error.go: -------------------------------------------------------------------------------- 1 | package flags 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | // ErrorType represents the type of error. 8 | type ErrorType uint 9 | 10 | const ( 11 | // ErrUnknown indicates a generic error. 12 | ErrUnknown ErrorType = iota 13 | 14 | // ErrExpectedArgument indicates that an argument was expected. 15 | ErrExpectedArgument 16 | 17 | // ErrUnknownFlag indicates an unknown flag. 18 | ErrUnknownFlag 19 | 20 | // ErrUnknownGroup indicates an unknown group. 21 | ErrUnknownGroup 22 | 23 | // ErrMarshal indicates a marshalling error while converting values. 24 | ErrMarshal 25 | 26 | // ErrHelp indicates that the built-in help was shown (the error 27 | // contains the help message). 28 | ErrHelp 29 | 30 | // ErrNoArgumentForBool indicates that an argument was given for a 31 | // boolean flag (which don't not take any arguments). 32 | ErrNoArgumentForBool 33 | 34 | // ErrRequired indicates that a required flag was not provided. 35 | ErrRequired 36 | 37 | // ErrShortNameTooLong indicates that a short flag name was specified, 38 | // longer than one character. 39 | ErrShortNameTooLong 40 | 41 | // ErrDuplicatedFlag indicates that a short or long flag has been 42 | // defined more than once 43 | ErrDuplicatedFlag 44 | 45 | // ErrTag indicates an error while parsing flag tags. 46 | ErrTag 47 | 48 | // ErrCommandRequired indicates that a command was required but not 49 | // specified 50 | ErrCommandRequired 51 | 52 | // ErrUnknownCommand indicates that an unknown command was specified. 53 | ErrUnknownCommand 54 | 55 | // ErrInvalidChoice indicates an invalid option value which only allows 56 | // a certain number of choices. 57 | ErrInvalidChoice 58 | ) 59 | 60 | func (e ErrorType) String() string { 61 | switch e { 62 | case ErrUnknown: 63 | return "unknown" 64 | case ErrExpectedArgument: 65 | return "expected argument" 66 | case ErrUnknownFlag: 67 | return "unknown flag" 68 | case ErrUnknownGroup: 69 | return "unknown group" 70 | case ErrMarshal: 71 | return "marshal" 72 | case ErrHelp: 73 | return "help" 74 | case ErrNoArgumentForBool: 75 | return "no argument for bool" 76 | case ErrRequired: 77 | return "required" 78 | case ErrShortNameTooLong: 79 | return "short name too long" 80 | case ErrDuplicatedFlag: 81 | return "duplicated flag" 82 | case ErrTag: 83 | return "tag" 84 | case ErrCommandRequired: 85 | return "command required" 86 | case ErrUnknownCommand: 87 | return "unknown command" 88 | case ErrInvalidChoice: 89 | return "invalid choice" 90 | } 91 | 92 | return "unrecognized error type" 93 | } 94 | 95 | // Error represents a parser error. The error returned from Parse is of this 96 | // type. The error contains both a Type and Message. 97 | type Error struct { 98 | // The type of error 99 | Type ErrorType 100 | 101 | // The error message 102 | Message string 103 | } 104 | 105 | // Error returns the error's message 106 | func (e *Error) Error() string { 107 | return e.Message 108 | } 109 | 110 | func newError(tp ErrorType, message string) *Error { 111 | return &Error{ 112 | Type: tp, 113 | Message: message, 114 | } 115 | } 116 | 117 | func newErrorf(tp ErrorType, format string, args ...interface{}) *Error { 118 | return newError(tp, fmt.Sprintf(format, args...)) 119 | } 120 | 121 | func wrapError(err error) *Error { 122 | ret, ok := err.(*Error) 123 | 124 | if !ok { 125 | return newError(ErrUnknown, err.Error()) 126 | } 127 | 128 | return ret 129 | } 130 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/jessevdk/go-flags/example_test.go: -------------------------------------------------------------------------------- 1 | // Example of use of the flags package. 2 | package flags 3 | 4 | import ( 5 | "fmt" 6 | "os/exec" 7 | ) 8 | 9 | func Example() { 10 | var opts struct { 11 | // Slice of bool will append 'true' each time the option 12 | // is encountered (can be set multiple times, like -vvv) 13 | Verbose []bool `short:"v" long:"verbose" description:"Show verbose debug information"` 14 | 15 | // Example of automatic marshalling to desired type (uint) 16 | Offset uint `long:"offset" description:"Offset"` 17 | 18 | // Example of a callback, called each time the option is found. 19 | Call func(string) `short:"c" description:"Call phone number"` 20 | 21 | // Example of a required flag 22 | Name string `short:"n" long:"name" description:"A name" required:"true"` 23 | 24 | // Example of a value name 25 | File string `short:"f" long:"file" description:"A file" value-name:"FILE"` 26 | 27 | // Example of a pointer 28 | Ptr *int `short:"p" description:"A pointer to an integer"` 29 | 30 | // Example of a slice of strings 31 | StringSlice []string `short:"s" description:"A slice of strings"` 32 | 33 | // Example of a slice of pointers 34 | PtrSlice []*string `long:"ptrslice" description:"A slice of pointers to string"` 35 | 36 | // Example of a map 37 | IntMap map[string]int `long:"intmap" description:"A map from string to int"` 38 | 39 | // Example of a filename (useful for completion) 40 | Filename Filename `long:"filename" description:"A filename"` 41 | 42 | // Example of positional arguments 43 | Args struct { 44 | Id string 45 | Num int 46 | Rest []string 47 | } `positional-args:"yes" required:"yes"` 48 | } 49 | 50 | // Callback which will invoke callto: to call a number. 51 | // Note that this works just on OS X (and probably only with 52 | // Skype) but it shows the idea. 53 | opts.Call = func(num string) { 54 | cmd := exec.Command("open", "callto:"+num) 55 | cmd.Start() 56 | cmd.Process.Release() 57 | } 58 | 59 | // Make some fake arguments to parse. 60 | args := []string{ 61 | "-vv", 62 | "--offset=5", 63 | "-n", "Me", 64 | "-p", "3", 65 | "-s", "hello", 66 | "-s", "world", 67 | "--ptrslice", "hello", 68 | "--ptrslice", "world", 69 | "--intmap", "a:1", 70 | "--intmap", "b:5", 71 | "--filename", "hello.go", 72 | "id", 73 | "10", 74 | "remaining1", 75 | "remaining2", 76 | } 77 | 78 | // Parse flags from `args'. Note that here we use flags.ParseArgs for 79 | // the sake of making a working example. Normally, you would simply use 80 | // flags.Parse(&opts) which uses os.Args 81 | _, err := ParseArgs(&opts, args) 82 | 83 | if err != nil { 84 | panic(err) 85 | } 86 | 87 | fmt.Printf("Verbosity: %v\n", opts.Verbose) 88 | fmt.Printf("Offset: %d\n", opts.Offset) 89 | fmt.Printf("Name: %s\n", opts.Name) 90 | fmt.Printf("Ptr: %d\n", *opts.Ptr) 91 | fmt.Printf("StringSlice: %v\n", opts.StringSlice) 92 | fmt.Printf("PtrSlice: [%v %v]\n", *opts.PtrSlice[0], *opts.PtrSlice[1]) 93 | fmt.Printf("IntMap: [a:%v b:%v]\n", opts.IntMap["a"], opts.IntMap["b"]) 94 | fmt.Printf("Filename: %v\n", opts.Filename) 95 | fmt.Printf("Args.Id: %s\n", opts.Args.Id) 96 | fmt.Printf("Args.Num: %d\n", opts.Args.Num) 97 | fmt.Printf("Args.Rest: %v\n", opts.Args.Rest) 98 | 99 | // Output: Verbosity: [true true] 100 | // Offset: 5 101 | // Name: Me 102 | // Ptr: 3 103 | // StringSlice: [hello world] 104 | // PtrSlice: [hello world] 105 | // IntMap: [a:1 b:5] 106 | // Filename: hello.go 107 | // Args.Id: id 108 | // Args.Num: 10 109 | // Args.Rest: [remaining1 remaining2] 110 | } 111 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/jessevdk/go-flags/examples/add.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | type AddCommand struct { 8 | All bool `short:"a" long:"all" description:"Add all files"` 9 | } 10 | 11 | var addCommand AddCommand 12 | 13 | func (x *AddCommand) Execute(args []string) error { 14 | fmt.Printf("Adding (all=%v): %#v\n", x.All, args) 15 | return nil 16 | } 17 | 18 | func init() { 19 | parser.AddCommand("add", 20 | "Add a file", 21 | "The add command adds a file to the repository. Use -a to add all files.", 22 | &addCommand) 23 | } 24 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/jessevdk/go-flags/examples/bash-completion: -------------------------------------------------------------------------------- 1 | _examples() { 2 | args=("${COMP_WORDS[@]:1:$COMP_CWORD}") 3 | 4 | local IFS=$'\n' 5 | COMPREPLY=($(GO_FLAGS_COMPLETION=1 ${COMP_WORDS[0]} "${args[@]}")) 6 | return 1 7 | } 8 | 9 | complete -F _examples examples 10 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/jessevdk/go-flags/examples/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "github.com/rlister/let-me-in/Godeps/_workspace/src/github.com/jessevdk/go-flags" 7 | "os" 8 | "strconv" 9 | "strings" 10 | ) 11 | 12 | type EditorOptions struct { 13 | Input flags.Filename `short:"i" long:"input" description:"Input file" default:"-"` 14 | Output flags.Filename `short:"o" long:"output" description:"Output file" default:"-"` 15 | } 16 | 17 | type Point struct { 18 | X, Y int 19 | } 20 | 21 | func (p *Point) UnmarshalFlag(value string) error { 22 | parts := strings.Split(value, ",") 23 | 24 | if len(parts) != 2 { 25 | return errors.New("expected two numbers separated by a ,") 26 | } 27 | 28 | x, err := strconv.ParseInt(parts[0], 10, 32) 29 | 30 | if err != nil { 31 | return err 32 | } 33 | 34 | y, err := strconv.ParseInt(parts[1], 10, 32) 35 | 36 | if err != nil { 37 | return err 38 | } 39 | 40 | p.X = int(x) 41 | p.Y = int(y) 42 | 43 | return nil 44 | } 45 | 46 | func (p Point) MarshalFlag() (string, error) { 47 | return fmt.Sprintf("%d,%d", p.X, p.Y), nil 48 | } 49 | 50 | type Options struct { 51 | // Example of verbosity with level 52 | Verbose []bool `short:"v" long:"verbose" description:"Verbose output"` 53 | 54 | // Example of optional value 55 | User string `short:"u" long:"user" description:"User name" optional:"yes" optional-value:"pancake"` 56 | 57 | // Example of map with multiple default values 58 | Users map[string]string `long:"users" description:"User e-mail map" default:"system:system@example.org" default:"admin:admin@example.org"` 59 | 60 | // Example of option group 61 | Editor EditorOptions `group:"Editor Options"` 62 | 63 | // Example of custom type Marshal/Unmarshal 64 | Point Point `long:"point" description:"A x,y point" default:"1,2"` 65 | } 66 | 67 | var options Options 68 | 69 | var parser = flags.NewParser(&options, flags.Default) 70 | 71 | func main() { 72 | if _, err := parser.Parse(); err != nil { 73 | os.Exit(1) 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/jessevdk/go-flags/examples/rm.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | type RmCommand struct { 8 | Force bool `short:"f" long:"force" description:"Force removal of files"` 9 | } 10 | 11 | var rmCommand RmCommand 12 | 13 | func (x *RmCommand) Execute(args []string) error { 14 | fmt.Printf("Removing (force=%v): %#v\n", x.Force, args) 15 | return nil 16 | } 17 | 18 | func init() { 19 | parser.AddCommand("rm", 20 | "Remove a file", 21 | "The rm command removes a file to the repository. Use -f to force removal of files.", 22 | &rmCommand) 23 | } 24 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/jessevdk/go-flags/long_test.go: -------------------------------------------------------------------------------- 1 | package flags 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestLong(t *testing.T) { 8 | var opts = struct { 9 | Value bool `long:"value"` 10 | }{} 11 | 12 | ret := assertParseSuccess(t, &opts, "--value") 13 | 14 | assertStringArray(t, ret, []string{}) 15 | 16 | if !opts.Value { 17 | t.Errorf("Expected Value to be true") 18 | } 19 | } 20 | 21 | func TestLongArg(t *testing.T) { 22 | var opts = struct { 23 | Value string `long:"value"` 24 | }{} 25 | 26 | ret := assertParseSuccess(t, &opts, "--value", "value") 27 | 28 | assertStringArray(t, ret, []string{}) 29 | assertString(t, opts.Value, "value") 30 | } 31 | 32 | func TestLongArgEqual(t *testing.T) { 33 | var opts = struct { 34 | Value string `long:"value"` 35 | }{} 36 | 37 | ret := assertParseSuccess(t, &opts, "--value=value") 38 | 39 | assertStringArray(t, ret, []string{}) 40 | assertString(t, opts.Value, "value") 41 | } 42 | 43 | func TestLongDefault(t *testing.T) { 44 | var opts = struct { 45 | Value string `long:"value" default:"value"` 46 | }{} 47 | 48 | ret := assertParseSuccess(t, &opts) 49 | 50 | assertStringArray(t, ret, []string{}) 51 | assertString(t, opts.Value, "value") 52 | } 53 | 54 | func TestLongOptional(t *testing.T) { 55 | var opts = struct { 56 | Value string `long:"value" optional:"yes" optional-value:"value"` 57 | }{} 58 | 59 | ret := assertParseSuccess(t, &opts, "--value") 60 | 61 | assertStringArray(t, ret, []string{}) 62 | assertString(t, opts.Value, "value") 63 | } 64 | 65 | func TestLongOptionalArg(t *testing.T) { 66 | var opts = struct { 67 | Value string `long:"value" optional:"yes" optional-value:"value"` 68 | }{} 69 | 70 | ret := assertParseSuccess(t, &opts, "--value", "no") 71 | 72 | assertStringArray(t, ret, []string{"no"}) 73 | assertString(t, opts.Value, "value") 74 | } 75 | 76 | func TestLongOptionalArgEqual(t *testing.T) { 77 | var opts = struct { 78 | Value string `long:"value" optional:"yes" optional-value:"value"` 79 | }{} 80 | 81 | ret := assertParseSuccess(t, &opts, "--value=value", "no") 82 | 83 | assertStringArray(t, ret, []string{"no"}) 84 | assertString(t, opts.Value, "value") 85 | } 86 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/jessevdk/go-flags/man.go: -------------------------------------------------------------------------------- 1 | package flags 2 | 3 | import ( 4 | "fmt" 5 | "io" 6 | "runtime" 7 | "strings" 8 | "time" 9 | ) 10 | 11 | func manQuote(s string) string { 12 | return strings.Replace(s, "\\", "\\\\", -1) 13 | } 14 | 15 | func formatForMan(wr io.Writer, s string) { 16 | for { 17 | idx := strings.IndexRune(s, '`') 18 | 19 | if idx < 0 { 20 | fmt.Fprintf(wr, "%s", manQuote(s)) 21 | break 22 | } 23 | 24 | fmt.Fprintf(wr, "%s", manQuote(s[:idx])) 25 | 26 | s = s[idx+1:] 27 | idx = strings.IndexRune(s, '\'') 28 | 29 | if idx < 0 { 30 | fmt.Fprintf(wr, "%s", manQuote(s)) 31 | break 32 | } 33 | 34 | fmt.Fprintf(wr, "\\fB%s\\fP", manQuote(s[:idx])) 35 | s = s[idx+1:] 36 | } 37 | } 38 | 39 | func writeManPageOptions(wr io.Writer, grp *Group) { 40 | grp.eachGroup(func(group *Group) { 41 | if group.Hidden { 42 | return 43 | } 44 | 45 | for _, opt := range group.options { 46 | if !opt.canCli() || opt.Hidden { 47 | continue 48 | } 49 | 50 | fmt.Fprintln(wr, ".TP") 51 | fmt.Fprintf(wr, "\\fB") 52 | 53 | if opt.ShortName != 0 { 54 | fmt.Fprintf(wr, "\\fB\\-%c\\fR", opt.ShortName) 55 | } 56 | 57 | if len(opt.LongName) != 0 { 58 | if opt.ShortName != 0 { 59 | fmt.Fprintf(wr, ", ") 60 | } 61 | 62 | fmt.Fprintf(wr, "\\fB\\-\\-%s\\fR", manQuote(opt.LongNameWithNamespace())) 63 | } 64 | 65 | if len(opt.ValueName) != 0 || opt.OptionalArgument { 66 | if opt.OptionalArgument { 67 | fmt.Fprintf(wr, " [\\fI%s=%s\\fR]", manQuote(opt.ValueName), manQuote(strings.Join(quoteV(opt.OptionalValue), ", "))) 68 | } else { 69 | fmt.Fprintf(wr, " \\fI%s\\fR", manQuote(opt.ValueName)) 70 | } 71 | } 72 | 73 | if len(opt.Default) != 0 { 74 | fmt.Fprintf(wr, " ", manQuote(strings.Join(quoteV(opt.Default), ", "))) 75 | } else if len(opt.EnvDefaultKey) != 0 { 76 | if runtime.GOOS == "windows" { 77 | fmt.Fprintf(wr, " ", manQuote(opt.EnvDefaultKey)) 78 | } else { 79 | fmt.Fprintf(wr, " ", manQuote(opt.EnvDefaultKey)) 80 | } 81 | } 82 | 83 | if opt.Required { 84 | fmt.Fprintf(wr, " (\\fIrequired\\fR)") 85 | } 86 | 87 | fmt.Fprintln(wr, "\\fP") 88 | 89 | if len(opt.Description) != 0 { 90 | formatForMan(wr, opt.Description) 91 | fmt.Fprintln(wr, "") 92 | } 93 | } 94 | }) 95 | } 96 | 97 | func writeManPageSubcommands(wr io.Writer, name string, root *Command) { 98 | commands := root.sortedVisibleCommands() 99 | 100 | for _, c := range commands { 101 | var nn string 102 | 103 | if c.Hidden { 104 | continue 105 | } 106 | 107 | if len(name) != 0 { 108 | nn = name + " " + c.Name 109 | } else { 110 | nn = c.Name 111 | } 112 | 113 | writeManPageCommand(wr, nn, root, c) 114 | } 115 | } 116 | 117 | func writeManPageCommand(wr io.Writer, name string, root *Command, command *Command) { 118 | fmt.Fprintf(wr, ".SS %s\n", name) 119 | fmt.Fprintln(wr, command.ShortDescription) 120 | 121 | if len(command.LongDescription) > 0 { 122 | fmt.Fprintln(wr, "") 123 | 124 | cmdstart := fmt.Sprintf("The %s command", manQuote(command.Name)) 125 | 126 | if strings.HasPrefix(command.LongDescription, cmdstart) { 127 | fmt.Fprintf(wr, "The \\fI%s\\fP command", manQuote(command.Name)) 128 | 129 | formatForMan(wr, command.LongDescription[len(cmdstart):]) 130 | fmt.Fprintln(wr, "") 131 | } else { 132 | formatForMan(wr, command.LongDescription) 133 | fmt.Fprintln(wr, "") 134 | } 135 | } 136 | 137 | var usage string 138 | if us, ok := command.data.(Usage); ok { 139 | usage = us.Usage() 140 | } else if command.hasCliOptions() { 141 | usage = fmt.Sprintf("[%s-OPTIONS]", command.Name) 142 | } 143 | 144 | var pre string 145 | if root.hasCliOptions() { 146 | pre = fmt.Sprintf("%s [OPTIONS] %s", root.Name, command.Name) 147 | } else { 148 | pre = fmt.Sprintf("%s %s", root.Name, command.Name) 149 | } 150 | 151 | if len(usage) > 0 { 152 | fmt.Fprintf(wr, "\n\\fBUsage\\fP: %s %s\n.TP\n", manQuote(pre), manQuote(usage)) 153 | } 154 | 155 | if len(command.Aliases) > 0 { 156 | fmt.Fprintf(wr, "\n\\fBAliases\\fP: %s\n\n", manQuote(strings.Join(command.Aliases, ", "))) 157 | } 158 | 159 | writeManPageOptions(wr, command.Group) 160 | writeManPageSubcommands(wr, name, command) 161 | } 162 | 163 | // WriteManPage writes a basic man page in groff format to the specified 164 | // writer. 165 | func (p *Parser) WriteManPage(wr io.Writer) { 166 | t := time.Now() 167 | 168 | fmt.Fprintf(wr, ".TH %s 1 \"%s\"\n", manQuote(p.Name), t.Format("2 January 2006")) 169 | fmt.Fprintln(wr, ".SH NAME") 170 | fmt.Fprintf(wr, "%s \\- %s\n", manQuote(p.Name), manQuote(p.ShortDescription)) 171 | fmt.Fprintln(wr, ".SH SYNOPSIS") 172 | 173 | usage := p.Usage 174 | 175 | if len(usage) == 0 { 176 | usage = "[OPTIONS]" 177 | } 178 | 179 | fmt.Fprintf(wr, "\\fB%s\\fP %s\n", manQuote(p.Name), manQuote(usage)) 180 | fmt.Fprintln(wr, ".SH DESCRIPTION") 181 | 182 | formatForMan(wr, p.LongDescription) 183 | fmt.Fprintln(wr, "") 184 | 185 | fmt.Fprintln(wr, ".SH OPTIONS") 186 | 187 | writeManPageOptions(wr, p.Command.Group) 188 | 189 | if len(p.visibleCommands()) > 0 { 190 | fmt.Fprintln(wr, ".SH COMMANDS") 191 | 192 | writeManPageSubcommands(wr, "", p.Command) 193 | } 194 | } 195 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/jessevdk/go-flags/marshal_test.go: -------------------------------------------------------------------------------- 1 | package flags 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | ) 7 | 8 | type marshalled bool 9 | 10 | func (m *marshalled) UnmarshalFlag(value string) error { 11 | if value == "yes" { 12 | *m = true 13 | } else if value == "no" { 14 | *m = false 15 | } else { 16 | return fmt.Errorf("`%s' is not a valid value, please specify `yes' or `no'", value) 17 | } 18 | 19 | return nil 20 | } 21 | 22 | func (m marshalled) MarshalFlag() (string, error) { 23 | if m { 24 | return "yes", nil 25 | } 26 | 27 | return "no", nil 28 | } 29 | 30 | type marshalledError bool 31 | 32 | func (m marshalledError) MarshalFlag() (string, error) { 33 | return "", newErrorf(ErrMarshal, "Failed to marshal") 34 | } 35 | 36 | func TestUnmarshal(t *testing.T) { 37 | var opts = struct { 38 | Value marshalled `short:"v"` 39 | }{} 40 | 41 | ret := assertParseSuccess(t, &opts, "-v=yes") 42 | 43 | assertStringArray(t, ret, []string{}) 44 | 45 | if !opts.Value { 46 | t.Errorf("Expected Value to be true") 47 | } 48 | } 49 | 50 | func TestUnmarshalDefault(t *testing.T) { 51 | var opts = struct { 52 | Value marshalled `short:"v" default:"yes"` 53 | }{} 54 | 55 | ret := assertParseSuccess(t, &opts) 56 | 57 | assertStringArray(t, ret, []string{}) 58 | 59 | if !opts.Value { 60 | t.Errorf("Expected Value to be true") 61 | } 62 | } 63 | 64 | func TestUnmarshalOptional(t *testing.T) { 65 | var opts = struct { 66 | Value marshalled `short:"v" optional:"yes" optional-value:"yes"` 67 | }{} 68 | 69 | ret := assertParseSuccess(t, &opts, "-v") 70 | 71 | assertStringArray(t, ret, []string{}) 72 | 73 | if !opts.Value { 74 | t.Errorf("Expected Value to be true") 75 | } 76 | } 77 | 78 | func TestUnmarshalError(t *testing.T) { 79 | var opts = struct { 80 | Value marshalled `short:"v"` 81 | }{} 82 | 83 | assertParseFail(t, ErrMarshal, fmt.Sprintf("invalid argument for flag `%cv' (expected flags.marshalled): `invalid' is not a valid value, please specify `yes' or `no'", defaultShortOptDelimiter), &opts, "-vinvalid") 84 | } 85 | 86 | func TestMarshalError(t *testing.T) { 87 | var opts = struct { 88 | Value marshalledError `short:"v"` 89 | }{} 90 | 91 | p := NewParser(&opts, Default) 92 | o := p.Command.Groups()[0].Options()[0] 93 | 94 | _, err := convertToString(o.value, o.tag) 95 | 96 | assertError(t, err, ErrMarshal, "Failed to marshal") 97 | } 98 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/jessevdk/go-flags/multitag.go: -------------------------------------------------------------------------------- 1 | package flags 2 | 3 | import ( 4 | "strconv" 5 | ) 6 | 7 | type multiTag struct { 8 | value string 9 | cache map[string][]string 10 | } 11 | 12 | func newMultiTag(v string) multiTag { 13 | return multiTag{ 14 | value: v, 15 | } 16 | } 17 | 18 | func (x *multiTag) scan() (map[string][]string, error) { 19 | v := x.value 20 | 21 | ret := make(map[string][]string) 22 | 23 | // This is mostly copied from reflect.StructTag.Get 24 | for v != "" { 25 | i := 0 26 | 27 | // Skip whitespace 28 | for i < len(v) && v[i] == ' ' { 29 | i++ 30 | } 31 | 32 | v = v[i:] 33 | 34 | if v == "" { 35 | break 36 | } 37 | 38 | // Scan to colon to find key 39 | i = 0 40 | 41 | for i < len(v) && v[i] != ' ' && v[i] != ':' && v[i] != '"' { 42 | i++ 43 | } 44 | 45 | if i >= len(v) { 46 | return nil, newErrorf(ErrTag, "expected `:' after key name, but got end of tag (in `%v`)", x.value) 47 | } 48 | 49 | if v[i] != ':' { 50 | return nil, newErrorf(ErrTag, "expected `:' after key name, but got `%v' (in `%v`)", v[i], x.value) 51 | } 52 | 53 | if i+1 >= len(v) { 54 | return nil, newErrorf(ErrTag, "expected `\"' to start tag value at end of tag (in `%v`)", x.value) 55 | } 56 | 57 | if v[i+1] != '"' { 58 | return nil, newErrorf(ErrTag, "expected `\"' to start tag value, but got `%v' (in `%v`)", v[i+1], x.value) 59 | } 60 | 61 | name := v[:i] 62 | v = v[i+1:] 63 | 64 | // Scan quoted string to find value 65 | i = 1 66 | 67 | for i < len(v) && v[i] != '"' { 68 | if v[i] == '\n' { 69 | return nil, newErrorf(ErrTag, "unexpected newline in tag value `%v' (in `%v`)", name, x.value) 70 | } 71 | 72 | if v[i] == '\\' { 73 | i++ 74 | } 75 | i++ 76 | } 77 | 78 | if i >= len(v) { 79 | return nil, newErrorf(ErrTag, "expected end of tag value `\"' at end of tag (in `%v`)", x.value) 80 | } 81 | 82 | val, err := strconv.Unquote(v[:i+1]) 83 | 84 | if err != nil { 85 | return nil, newErrorf(ErrTag, "Malformed value of tag `%v:%v` => %v (in `%v`)", name, v[:i+1], err, x.value) 86 | } 87 | 88 | v = v[i+1:] 89 | 90 | ret[name] = append(ret[name], val) 91 | } 92 | 93 | return ret, nil 94 | } 95 | 96 | func (x *multiTag) Parse() error { 97 | vals, err := x.scan() 98 | x.cache = vals 99 | 100 | return err 101 | } 102 | 103 | func (x *multiTag) cached() map[string][]string { 104 | if x.cache == nil { 105 | cache, _ := x.scan() 106 | 107 | if cache == nil { 108 | cache = make(map[string][]string) 109 | } 110 | 111 | x.cache = cache 112 | } 113 | 114 | return x.cache 115 | } 116 | 117 | func (x *multiTag) Get(key string) string { 118 | c := x.cached() 119 | 120 | if v, ok := c[key]; ok { 121 | return v[len(v)-1] 122 | } 123 | 124 | return "" 125 | } 126 | 127 | func (x *multiTag) GetMany(key string) []string { 128 | c := x.cached() 129 | return c[key] 130 | } 131 | 132 | func (x *multiTag) Set(key string, value string) { 133 | c := x.cached() 134 | c[key] = []string{value} 135 | } 136 | 137 | func (x *multiTag) SetMany(key string, value []string) { 138 | c := x.cached() 139 | c[key] = value 140 | } 141 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/jessevdk/go-flags/options_test.go: -------------------------------------------------------------------------------- 1 | package flags 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestPassDoubleDash(t *testing.T) { 8 | var opts = struct { 9 | Value bool `short:"v"` 10 | }{} 11 | 12 | p := NewParser(&opts, PassDoubleDash) 13 | ret, err := p.ParseArgs([]string{"-v", "--", "-v", "-g"}) 14 | 15 | if err != nil { 16 | t.Fatalf("Unexpected error: %v", err) 17 | return 18 | } 19 | 20 | if !opts.Value { 21 | t.Errorf("Expected Value to be true") 22 | } 23 | 24 | assertStringArray(t, ret, []string{"-v", "-g"}) 25 | } 26 | 27 | func TestPassAfterNonOption(t *testing.T) { 28 | var opts = struct { 29 | Value bool `short:"v"` 30 | }{} 31 | 32 | p := NewParser(&opts, PassAfterNonOption) 33 | ret, err := p.ParseArgs([]string{"-v", "arg", "-v", "-g"}) 34 | 35 | if err != nil { 36 | t.Fatalf("Unexpected error: %v", err) 37 | return 38 | } 39 | 40 | if !opts.Value { 41 | t.Errorf("Expected Value to be true") 42 | } 43 | 44 | assertStringArray(t, ret, []string{"arg", "-v", "-g"}) 45 | } 46 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/jessevdk/go-flags/optstyle_other.go: -------------------------------------------------------------------------------- 1 | // +build !windows 2 | 3 | package flags 4 | 5 | import ( 6 | "strings" 7 | ) 8 | 9 | const ( 10 | defaultShortOptDelimiter = '-' 11 | defaultLongOptDelimiter = "--" 12 | defaultNameArgDelimiter = '=' 13 | ) 14 | 15 | func argumentStartsOption(arg string) bool { 16 | return len(arg) > 0 && arg[0] == '-' 17 | } 18 | 19 | func argumentIsOption(arg string) bool { 20 | if len(arg) > 1 && arg[0] == '-' && arg[1] != '-' { 21 | return true 22 | } 23 | 24 | if len(arg) > 2 && arg[0] == '-' && arg[1] == '-' && arg[2] != '-' { 25 | return true 26 | } 27 | 28 | return false 29 | } 30 | 31 | // stripOptionPrefix returns the option without the prefix and whether or 32 | // not the option is a long option or not. 33 | func stripOptionPrefix(optname string) (prefix string, name string, islong bool) { 34 | if strings.HasPrefix(optname, "--") { 35 | return "--", optname[2:], true 36 | } else if strings.HasPrefix(optname, "-") { 37 | return "-", optname[1:], false 38 | } 39 | 40 | return "", optname, false 41 | } 42 | 43 | // splitOption attempts to split the passed option into a name and an argument. 44 | // When there is no argument specified, nil will be returned for it. 45 | func splitOption(prefix string, option string, islong bool) (string, string, *string) { 46 | pos := strings.Index(option, "=") 47 | 48 | if (islong && pos >= 0) || (!islong && pos == 1) { 49 | rest := option[pos+1:] 50 | return option[:pos], "=", &rest 51 | } 52 | 53 | return option, "", nil 54 | } 55 | 56 | // addHelpGroup adds a new group that contains default help parameters. 57 | func (c *Command) addHelpGroup(showHelp func() error) *Group { 58 | var help struct { 59 | ShowHelp func() error `short:"h" long:"help" description:"Show this help message"` 60 | } 61 | 62 | help.ShowHelp = showHelp 63 | ret, _ := c.AddGroup("Help Options", "", &help) 64 | ret.isBuiltinHelp = true 65 | 66 | return ret 67 | } 68 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/jessevdk/go-flags/optstyle_windows.go: -------------------------------------------------------------------------------- 1 | package flags 2 | 3 | import ( 4 | "strings" 5 | ) 6 | 7 | // Windows uses a front slash for both short and long options. Also it uses 8 | // a colon for name/argument delimter. 9 | const ( 10 | defaultShortOptDelimiter = '/' 11 | defaultLongOptDelimiter = "/" 12 | defaultNameArgDelimiter = ':' 13 | ) 14 | 15 | func argumentStartsOption(arg string) bool { 16 | return len(arg) > 0 && (arg[0] == '-' || arg[0] == '/') 17 | } 18 | 19 | func argumentIsOption(arg string) bool { 20 | // Windows-style options allow front slash for the option 21 | // delimiter. 22 | if len(arg) > 1 && arg[0] == '/' { 23 | return true 24 | } 25 | 26 | if len(arg) > 1 && arg[0] == '-' && arg[1] != '-' { 27 | return true 28 | } 29 | 30 | if len(arg) > 2 && arg[0] == '-' && arg[1] == '-' && arg[2] != '-' { 31 | return true 32 | } 33 | 34 | return false 35 | } 36 | 37 | // stripOptionPrefix returns the option without the prefix and whether or 38 | // not the option is a long option or not. 39 | func stripOptionPrefix(optname string) (prefix string, name string, islong bool) { 40 | // Determine if the argument is a long option or not. Windows 41 | // typically supports both long and short options with a single 42 | // front slash as the option delimiter, so handle this situation 43 | // nicely. 44 | possplit := 0 45 | 46 | if strings.HasPrefix(optname, "--") { 47 | possplit = 2 48 | islong = true 49 | } else if strings.HasPrefix(optname, "-") { 50 | possplit = 1 51 | islong = false 52 | } else if strings.HasPrefix(optname, "/") { 53 | possplit = 1 54 | islong = len(optname) > 2 55 | } 56 | 57 | return optname[:possplit], optname[possplit:], islong 58 | } 59 | 60 | // splitOption attempts to split the passed option into a name and an argument. 61 | // When there is no argument specified, nil will be returned for it. 62 | func splitOption(prefix string, option string, islong bool) (string, string, *string) { 63 | if len(option) == 0 { 64 | return option, "", nil 65 | } 66 | 67 | // Windows typically uses a colon for the option name and argument 68 | // delimiter while POSIX typically uses an equals. Support both styles, 69 | // but don't allow the two to be mixed. That is to say /foo:bar and 70 | // --foo=bar are acceptable, but /foo=bar and --foo:bar are not. 71 | var pos int 72 | var sp string 73 | 74 | if prefix == "/" { 75 | sp = ":" 76 | pos = strings.Index(option, sp) 77 | } else if len(prefix) > 0 { 78 | sp = "=" 79 | pos = strings.Index(option, sp) 80 | } 81 | 82 | if (islong && pos >= 0) || (!islong && pos == 1) { 83 | rest := option[pos+1:] 84 | return option[:pos], sp, &rest 85 | } 86 | 87 | return option, "", nil 88 | } 89 | 90 | // addHelpGroup adds a new group that contains default help parameters. 91 | func (c *Command) addHelpGroup(showHelp func() error) *Group { 92 | // Windows CLI applications typically use /? for help, so make both 93 | // that available as well as the POSIX style h and help. 94 | var help struct { 95 | ShowHelpWindows func() error `short:"?" description:"Show this help message"` 96 | ShowHelpPosix func() error `short:"h" long:"help" description:"Show this help message"` 97 | } 98 | 99 | help.ShowHelpWindows = showHelp 100 | help.ShowHelpPosix = showHelp 101 | 102 | ret, _ := c.AddGroup("Help Options", "", &help) 103 | ret.isBuiltinHelp = true 104 | 105 | return ret 106 | } 107 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/jessevdk/go-flags/pointer_test.go: -------------------------------------------------------------------------------- 1 | package flags 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestPointerBool(t *testing.T) { 8 | var opts = struct { 9 | Value *bool `short:"v"` 10 | }{} 11 | 12 | ret := assertParseSuccess(t, &opts, "-v") 13 | 14 | assertStringArray(t, ret, []string{}) 15 | 16 | if !*opts.Value { 17 | t.Errorf("Expected Value to be true") 18 | } 19 | } 20 | 21 | func TestPointerString(t *testing.T) { 22 | var opts = struct { 23 | Value *string `short:"v"` 24 | }{} 25 | 26 | ret := assertParseSuccess(t, &opts, "-v", "value") 27 | 28 | assertStringArray(t, ret, []string{}) 29 | assertString(t, *opts.Value, "value") 30 | } 31 | 32 | func TestPointerSlice(t *testing.T) { 33 | var opts = struct { 34 | Value *[]string `short:"v"` 35 | }{} 36 | 37 | ret := assertParseSuccess(t, &opts, "-v", "value1", "-v", "value2") 38 | 39 | assertStringArray(t, ret, []string{}) 40 | assertStringArray(t, *opts.Value, []string{"value1", "value2"}) 41 | } 42 | 43 | func TestPointerMap(t *testing.T) { 44 | var opts = struct { 45 | Value *map[string]int `short:"v"` 46 | }{} 47 | 48 | ret := assertParseSuccess(t, &opts, "-v", "k1:2", "-v", "k2:-5") 49 | 50 | assertStringArray(t, ret, []string{}) 51 | 52 | if v, ok := (*opts.Value)["k1"]; !ok { 53 | t.Errorf("Expected key \"k1\" to exist") 54 | } else if v != 2 { 55 | t.Errorf("Expected \"k1\" to be 2, but got %#v", v) 56 | } 57 | 58 | if v, ok := (*opts.Value)["k2"]; !ok { 59 | t.Errorf("Expected key \"k2\" to exist") 60 | } else if v != -5 { 61 | t.Errorf("Expected \"k2\" to be -5, but got %#v", v) 62 | } 63 | } 64 | 65 | type PointerGroup struct { 66 | Value bool `short:"v"` 67 | } 68 | 69 | func TestPointerGroup(t *testing.T) { 70 | var opts = struct { 71 | Group *PointerGroup `group:"Group Options"` 72 | }{} 73 | 74 | ret := assertParseSuccess(t, &opts, "-v") 75 | 76 | assertStringArray(t, ret, []string{}) 77 | 78 | if !opts.Group.Value { 79 | t.Errorf("Expected Group.Value to be true") 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/jessevdk/go-flags/short_test.go: -------------------------------------------------------------------------------- 1 | package flags 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | ) 7 | 8 | func TestShort(t *testing.T) { 9 | var opts = struct { 10 | Value bool `short:"v"` 11 | }{} 12 | 13 | ret := assertParseSuccess(t, &opts, "-v") 14 | 15 | assertStringArray(t, ret, []string{}) 16 | 17 | if !opts.Value { 18 | t.Errorf("Expected Value to be true") 19 | } 20 | } 21 | 22 | func TestShortTooLong(t *testing.T) { 23 | var opts = struct { 24 | Value bool `short:"vv"` 25 | }{} 26 | 27 | assertParseFail(t, ErrShortNameTooLong, "short names can only be 1 character long, not `vv'", &opts) 28 | } 29 | 30 | func TestShortRequired(t *testing.T) { 31 | var opts = struct { 32 | Value bool `short:"v" required:"true"` 33 | }{} 34 | 35 | assertParseFail(t, ErrRequired, fmt.Sprintf("the required flag `%cv' was not specified", defaultShortOptDelimiter), &opts) 36 | } 37 | 38 | func TestShortMultiConcat(t *testing.T) { 39 | var opts = struct { 40 | V bool `short:"v"` 41 | O bool `short:"o"` 42 | F bool `short:"f"` 43 | }{} 44 | 45 | ret := assertParseSuccess(t, &opts, "-vo", "-f") 46 | 47 | assertStringArray(t, ret, []string{}) 48 | 49 | if !opts.V { 50 | t.Errorf("Expected V to be true") 51 | } 52 | 53 | if !opts.O { 54 | t.Errorf("Expected O to be true") 55 | } 56 | 57 | if !opts.F { 58 | t.Errorf("Expected F to be true") 59 | } 60 | } 61 | 62 | func TestShortMultiRequiredConcat(t *testing.T) { 63 | var opts = struct { 64 | V bool `short:"v" required:"true"` 65 | O bool `short:"o" required:"true"` 66 | F bool `short:"f" required:"true"` 67 | }{} 68 | 69 | ret := assertParseSuccess(t, &opts, "-vo", "-f") 70 | 71 | assertStringArray(t, ret, []string{}) 72 | 73 | if !opts.V { 74 | t.Errorf("Expected V to be true") 75 | } 76 | 77 | if !opts.O { 78 | t.Errorf("Expected O to be true") 79 | } 80 | 81 | if !opts.F { 82 | t.Errorf("Expected F to be true") 83 | } 84 | } 85 | 86 | func TestShortMultiSlice(t *testing.T) { 87 | var opts = struct { 88 | Values []bool `short:"v"` 89 | }{} 90 | 91 | ret := assertParseSuccess(t, &opts, "-v", "-v") 92 | 93 | assertStringArray(t, ret, []string{}) 94 | assertBoolArray(t, opts.Values, []bool{true, true}) 95 | } 96 | 97 | func TestShortMultiSliceConcat(t *testing.T) { 98 | var opts = struct { 99 | Values []bool `short:"v"` 100 | }{} 101 | 102 | ret := assertParseSuccess(t, &opts, "-vvv") 103 | 104 | assertStringArray(t, ret, []string{}) 105 | assertBoolArray(t, opts.Values, []bool{true, true, true}) 106 | } 107 | 108 | func TestShortWithEqualArg(t *testing.T) { 109 | var opts = struct { 110 | Value string `short:"v"` 111 | }{} 112 | 113 | ret := assertParseSuccess(t, &opts, "-v=value") 114 | 115 | assertStringArray(t, ret, []string{}) 116 | assertString(t, opts.Value, "value") 117 | } 118 | 119 | func TestShortWithArg(t *testing.T) { 120 | var opts = struct { 121 | Value string `short:"v"` 122 | }{} 123 | 124 | ret := assertParseSuccess(t, &opts, "-vvalue") 125 | 126 | assertStringArray(t, ret, []string{}) 127 | assertString(t, opts.Value, "value") 128 | } 129 | 130 | func TestShortArg(t *testing.T) { 131 | var opts = struct { 132 | Value string `short:"v"` 133 | }{} 134 | 135 | ret := assertParseSuccess(t, &opts, "-v", "value") 136 | 137 | assertStringArray(t, ret, []string{}) 138 | assertString(t, opts.Value, "value") 139 | } 140 | 141 | func TestShortMultiWithEqualArg(t *testing.T) { 142 | var opts = struct { 143 | F []bool `short:"f"` 144 | Value string `short:"v"` 145 | }{} 146 | 147 | assertParseFail(t, ErrExpectedArgument, fmt.Sprintf("expected argument for flag `%cv'", defaultShortOptDelimiter), &opts, "-ffv=value") 148 | } 149 | 150 | func TestShortMultiArg(t *testing.T) { 151 | var opts = struct { 152 | F []bool `short:"f"` 153 | Value string `short:"v"` 154 | }{} 155 | 156 | ret := assertParseSuccess(t, &opts, "-ffv", "value") 157 | 158 | assertStringArray(t, ret, []string{}) 159 | assertBoolArray(t, opts.F, []bool{true, true}) 160 | assertString(t, opts.Value, "value") 161 | } 162 | 163 | func TestShortMultiArgConcatFail(t *testing.T) { 164 | var opts = struct { 165 | F []bool `short:"f"` 166 | Value string `short:"v"` 167 | }{} 168 | 169 | assertParseFail(t, ErrExpectedArgument, fmt.Sprintf("expected argument for flag `%cv'", defaultShortOptDelimiter), &opts, "-ffvvalue") 170 | } 171 | 172 | func TestShortMultiArgConcat(t *testing.T) { 173 | var opts = struct { 174 | F []bool `short:"f"` 175 | Value string `short:"v"` 176 | }{} 177 | 178 | ret := assertParseSuccess(t, &opts, "-vff") 179 | 180 | assertStringArray(t, ret, []string{}) 181 | assertString(t, opts.Value, "ff") 182 | } 183 | 184 | func TestShortOptional(t *testing.T) { 185 | var opts = struct { 186 | F []bool `short:"f"` 187 | Value string `short:"v" optional:"yes" optional-value:"value"` 188 | }{} 189 | 190 | ret := assertParseSuccess(t, &opts, "-fv", "f") 191 | 192 | assertStringArray(t, ret, []string{"f"}) 193 | assertString(t, opts.Value, "value") 194 | } 195 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/jessevdk/go-flags/tag_test.go: -------------------------------------------------------------------------------- 1 | package flags 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestTagMissingColon(t *testing.T) { 8 | var opts = struct { 9 | Value bool `short` 10 | }{} 11 | 12 | assertParseFail(t, ErrTag, "expected `:' after key name, but got end of tag (in `short`)", &opts, "") 13 | } 14 | 15 | func TestTagMissingValue(t *testing.T) { 16 | var opts = struct { 17 | Value bool `short:` 18 | }{} 19 | 20 | assertParseFail(t, ErrTag, "expected `\"' to start tag value at end of tag (in `short:`)", &opts, "") 21 | } 22 | 23 | func TestTagMissingQuote(t *testing.T) { 24 | var opts = struct { 25 | Value bool `short:"v` 26 | }{} 27 | 28 | assertParseFail(t, ErrTag, "expected end of tag value `\"' at end of tag (in `short:\"v`)", &opts, "") 29 | } 30 | 31 | func TestTagNewline(t *testing.T) { 32 | var opts = struct { 33 | Value bool `long:"verbose" description:"verbose 34 | something"` 35 | }{} 36 | 37 | assertParseFail(t, ErrTag, "unexpected newline in tag value `description' (in `long:\"verbose\" description:\"verbose\nsomething\"`)", &opts, "") 38 | } 39 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/jessevdk/go-flags/termsize.go: -------------------------------------------------------------------------------- 1 | // +build !windows,!plan9,!solaris 2 | 3 | package flags 4 | 5 | import ( 6 | "syscall" 7 | "unsafe" 8 | ) 9 | 10 | type winsize struct { 11 | row, col uint16 12 | xpixel, ypixel uint16 13 | } 14 | 15 | func getTerminalColumns() int { 16 | ws := winsize{} 17 | 18 | if tIOCGWINSZ != 0 { 19 | syscall.Syscall(syscall.SYS_IOCTL, 20 | uintptr(0), 21 | uintptr(tIOCGWINSZ), 22 | uintptr(unsafe.Pointer(&ws))) 23 | 24 | return int(ws.col) 25 | } 26 | 27 | return 80 28 | } 29 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/jessevdk/go-flags/termsize_linux.go: -------------------------------------------------------------------------------- 1 | // +build linux 2 | 3 | package flags 4 | 5 | const ( 6 | tIOCGWINSZ = 0x5413 7 | ) 8 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/jessevdk/go-flags/termsize_nosysioctl.go: -------------------------------------------------------------------------------- 1 | // +build windows plan9 solaris 2 | 3 | package flags 4 | 5 | func getTerminalColumns() int { 6 | return 80 7 | } 8 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/jessevdk/go-flags/termsize_other.go: -------------------------------------------------------------------------------- 1 | // +build !darwin,!freebsd,!netbsd,!openbsd,!linux 2 | 3 | package flags 4 | 5 | const ( 6 | tIOCGWINSZ = 0 7 | ) 8 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/jessevdk/go-flags/termsize_unix.go: -------------------------------------------------------------------------------- 1 | // +build darwin freebsd netbsd openbsd 2 | 3 | package flags 4 | 5 | const ( 6 | tIOCGWINSZ = 0x40087468 7 | ) 8 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/jessevdk/go-flags/unknown_test.go: -------------------------------------------------------------------------------- 1 | package flags 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestUnknownFlags(t *testing.T) { 8 | var opts = struct { 9 | Verbose []bool `short:"v" long:"verbose" description:"Verbose output"` 10 | }{} 11 | 12 | args := []string{ 13 | "-f", 14 | } 15 | 16 | p := NewParser(&opts, 0) 17 | args, err := p.ParseArgs(args) 18 | 19 | if err == nil { 20 | t.Fatal("Expected error for unknown argument") 21 | } 22 | } 23 | 24 | func TestIgnoreUnknownFlags(t *testing.T) { 25 | var opts = struct { 26 | Verbose []bool `short:"v" long:"verbose" description:"Verbose output"` 27 | }{} 28 | 29 | args := []string{ 30 | "hello", 31 | "world", 32 | "-v", 33 | "--foo=bar", 34 | "--verbose", 35 | "-f", 36 | } 37 | 38 | p := NewParser(&opts, IgnoreUnknown) 39 | args, err := p.ParseArgs(args) 40 | 41 | if err != nil { 42 | t.Fatal(err) 43 | } 44 | 45 | exargs := []string{ 46 | "hello", 47 | "world", 48 | "--foo=bar", 49 | "-f", 50 | } 51 | 52 | issame := (len(args) == len(exargs)) 53 | 54 | if issame { 55 | for i := 0; i < len(args); i++ { 56 | if args[i] != exargs[i] { 57 | issame = false 58 | break 59 | } 60 | } 61 | } 62 | 63 | if !issame { 64 | t.Fatalf("Expected %v but got %v", exargs, args) 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/vaughan0/go-ini/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013 Vaughan Newton 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated 4 | documentation files (the "Software"), to deal in the Software without restriction, including without limitation the 5 | rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit 6 | persons to whom the Software is furnished to do so, subject to the following conditions: 7 | 8 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the 9 | Software. 10 | 11 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE 12 | WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 13 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 14 | OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 15 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/vaughan0/go-ini/README.md: -------------------------------------------------------------------------------- 1 | go-ini 2 | ====== 3 | 4 | INI parsing library for Go (golang). 5 | 6 | View the API documentation [here](http://godoc.org/github.com/vaughan0/go-ini). 7 | 8 | Usage 9 | ----- 10 | 11 | Parse an INI file: 12 | 13 | ```go 14 | import "github.com/vaughan0/go-ini" 15 | 16 | file, err := ini.LoadFile("myfile.ini") 17 | ``` 18 | 19 | Get data from the parsed file: 20 | 21 | ```go 22 | name, ok := file.Get("person", "name") 23 | if !ok { 24 | panic("'name' variable missing from 'person' section") 25 | } 26 | ``` 27 | 28 | Iterate through values in a section: 29 | 30 | ```go 31 | for key, value := range file["mysection"] { 32 | fmt.Printf("%s => %s\n", key, value) 33 | } 34 | ``` 35 | 36 | Iterate through sections in a file: 37 | 38 | ```go 39 | for name, section := range file { 40 | fmt.Printf("Section name: %s\n", name) 41 | } 42 | ``` 43 | 44 | File Format 45 | ----------- 46 | 47 | INI files are parsed by go-ini line-by-line. Each line may be one of the following: 48 | 49 | * A section definition: [section-name] 50 | * A property: key = value 51 | * A comment: #blahblah _or_ ;blahblah 52 | * Blank. The line will be ignored. 53 | 54 | Properties defined before any section headers are placed in the default section, which has 55 | the empty string as it's key. 56 | 57 | Example: 58 | 59 | ```ini 60 | # I am a comment 61 | ; So am I! 62 | 63 | [apples] 64 | colour = red or green 65 | shape = applish 66 | 67 | [oranges] 68 | shape = square 69 | colour = blue 70 | ``` 71 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/vaughan0/go-ini/ini.go: -------------------------------------------------------------------------------- 1 | // Package ini provides functions for parsing INI configuration files. 2 | package ini 3 | 4 | import ( 5 | "bufio" 6 | "fmt" 7 | "io" 8 | "os" 9 | "regexp" 10 | "strings" 11 | ) 12 | 13 | var ( 14 | sectionRegex = regexp.MustCompile(`^\[(.*)\]$`) 15 | assignRegex = regexp.MustCompile(`^([^=]+)=(.*)$`) 16 | ) 17 | 18 | // ErrSyntax is returned when there is a syntax error in an INI file. 19 | type ErrSyntax struct { 20 | Line int 21 | Source string // The contents of the erroneous line, without leading or trailing whitespace 22 | } 23 | 24 | func (e ErrSyntax) Error() string { 25 | return fmt.Sprintf("invalid INI syntax on line %d: %s", e.Line, e.Source) 26 | } 27 | 28 | // A File represents a parsed INI file. 29 | type File map[string]Section 30 | 31 | // A Section represents a single section of an INI file. 32 | type Section map[string]string 33 | 34 | // Returns a named Section. A Section will be created if one does not already exist for the given name. 35 | func (f File) Section(name string) Section { 36 | section := f[name] 37 | if section == nil { 38 | section = make(Section) 39 | f[name] = section 40 | } 41 | return section 42 | } 43 | 44 | // Looks up a value for a key in a section and returns that value, along with a boolean result similar to a map lookup. 45 | func (f File) Get(section, key string) (value string, ok bool) { 46 | if s := f[section]; s != nil { 47 | value, ok = s[key] 48 | } 49 | return 50 | } 51 | 52 | // Loads INI data from a reader and stores the data in the File. 53 | func (f File) Load(in io.Reader) (err error) { 54 | bufin, ok := in.(*bufio.Reader) 55 | if !ok { 56 | bufin = bufio.NewReader(in) 57 | } 58 | return parseFile(bufin, f) 59 | } 60 | 61 | // Loads INI data from a named file and stores the data in the File. 62 | func (f File) LoadFile(file string) (err error) { 63 | in, err := os.Open(file) 64 | if err != nil { 65 | return 66 | } 67 | defer in.Close() 68 | return f.Load(in) 69 | } 70 | 71 | func parseFile(in *bufio.Reader, file File) (err error) { 72 | section := "" 73 | lineNum := 0 74 | for done := false; !done; { 75 | var line string 76 | if line, err = in.ReadString('\n'); err != nil { 77 | if err == io.EOF { 78 | done = true 79 | } else { 80 | return 81 | } 82 | } 83 | lineNum++ 84 | line = strings.TrimSpace(line) 85 | if len(line) == 0 { 86 | // Skip blank lines 87 | continue 88 | } 89 | if line[0] == ';' || line[0] == '#' { 90 | // Skip comments 91 | continue 92 | } 93 | 94 | if groups := assignRegex.FindStringSubmatch(line); groups != nil { 95 | key, val := groups[1], groups[2] 96 | key, val = strings.TrimSpace(key), strings.TrimSpace(val) 97 | file.Section(section)[key] = val 98 | } else if groups := sectionRegex.FindStringSubmatch(line); groups != nil { 99 | name := strings.TrimSpace(groups[1]) 100 | section = name 101 | // Create the section if it does not exist 102 | file.Section(section) 103 | } else { 104 | return ErrSyntax{lineNum, line} 105 | } 106 | 107 | } 108 | return nil 109 | } 110 | 111 | // Loads and returns a File from a reader. 112 | func Load(in io.Reader) (File, error) { 113 | file := make(File) 114 | err := file.Load(in) 115 | return file, err 116 | } 117 | 118 | // Loads and returns an INI File from a file on disk. 119 | func LoadFile(filename string) (File, error) { 120 | file := make(File) 121 | err := file.LoadFile(filename) 122 | return file, err 123 | } 124 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/vaughan0/go-ini/ini_linux_test.go: -------------------------------------------------------------------------------- 1 | package ini 2 | 3 | import ( 4 | "reflect" 5 | "syscall" 6 | "testing" 7 | ) 8 | 9 | func TestLoadFile(t *testing.T) { 10 | originalOpenFiles := numFilesOpen(t) 11 | 12 | file, err := LoadFile("test.ini") 13 | if err != nil { 14 | t.Fatal(err) 15 | } 16 | 17 | if originalOpenFiles != numFilesOpen(t) { 18 | t.Error("test.ini not closed") 19 | } 20 | 21 | if !reflect.DeepEqual(file, File{"default": {"stuff": "things"}}) { 22 | t.Error("file not read correctly") 23 | } 24 | } 25 | 26 | func numFilesOpen(t *testing.T) (num uint64) { 27 | var rlimit syscall.Rlimit 28 | err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &rlimit) 29 | if err != nil { 30 | t.Fatal(err) 31 | } 32 | maxFds := int(rlimit.Cur) 33 | 34 | var stat syscall.Stat_t 35 | for i := 0; i < maxFds; i++ { 36 | if syscall.Fstat(i, &stat) == nil { 37 | num++ 38 | } else { 39 | return 40 | } 41 | } 42 | return 43 | } 44 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/vaughan0/go-ini/ini_test.go: -------------------------------------------------------------------------------- 1 | package ini 2 | 3 | import ( 4 | "reflect" 5 | "strings" 6 | "testing" 7 | ) 8 | 9 | func TestLoad(t *testing.T) { 10 | src := ` 11 | # Comments are ignored 12 | 13 | herp = derp 14 | 15 | [foo] 16 | hello=world 17 | whitespace should = not matter 18 | ; sneaky semicolon-style comment 19 | multiple = equals = signs 20 | 21 | [bar] 22 | this = that` 23 | 24 | file, err := Load(strings.NewReader(src)) 25 | if err != nil { 26 | t.Fatal(err) 27 | } 28 | check := func(section, key, expect string) { 29 | if value, _ := file.Get(section, key); value != expect { 30 | t.Errorf("Get(%q, %q): expected %q, got %q", section, key, expect, value) 31 | } 32 | } 33 | 34 | check("", "herp", "derp") 35 | check("foo", "hello", "world") 36 | check("foo", "whitespace should", "not matter") 37 | check("foo", "multiple", "equals = signs") 38 | check("bar", "this", "that") 39 | } 40 | 41 | func TestSyntaxError(t *testing.T) { 42 | src := ` 43 | # Line 2 44 | [foo] 45 | bar = baz 46 | # Here's an error on line 6: 47 | wut? 48 | herp = derp` 49 | _, err := Load(strings.NewReader(src)) 50 | t.Logf("%T: %v", err, err) 51 | if err == nil { 52 | t.Fatal("expected an error, got nil") 53 | } 54 | syntaxErr, ok := err.(ErrSyntax) 55 | if !ok { 56 | t.Fatal("expected an error of type ErrSyntax") 57 | } 58 | if syntaxErr.Line != 6 { 59 | t.Fatal("incorrect line number") 60 | } 61 | if syntaxErr.Source != "wut?" { 62 | t.Fatal("incorrect source") 63 | } 64 | } 65 | 66 | func TestDefinedSectionBehaviour(t *testing.T) { 67 | check := func(src string, expect File) { 68 | file, err := Load(strings.NewReader(src)) 69 | if err != nil { 70 | t.Fatal(err) 71 | } 72 | if !reflect.DeepEqual(file, expect) { 73 | t.Errorf("expected %v, got %v", expect, file) 74 | } 75 | } 76 | // No sections for an empty file 77 | check("", File{}) 78 | // Default section only if there are actually values for it 79 | check("foo=bar", File{"": {"foo": "bar"}}) 80 | // User-defined sections should always be present, even if empty 81 | check("[a]\n[b]\nfoo=bar", File{ 82 | "a": {}, 83 | "b": {"foo": "bar"}, 84 | }) 85 | check("foo=bar\n[a]\nthis=that", File{ 86 | "": {"foo": "bar"}, 87 | "a": {"this": "that"}, 88 | }) 89 | } 90 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/vaughan0/go-ini/test.ini: -------------------------------------------------------------------------------- 1 | [default] 2 | stuff = things 3 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Richard Lister 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. --------------------------------------------------------------------------------