github.com/smugmug/godynamo@v0.0.0-20151122084750-7913028f6623/README.md (about) 1 # GoDynamo: A User's Guide 2 3 ## Introduction 4 5 GoDynamo is a API for the DynamoDB database (http://aws.amazon.com/documentation/dynamodb/) written in Go. 6 7 GoDynamo supports all endpoints, uses AWSv4 request signing, and supports IAM authentication as well 8 as traditional AWS keys. 9 10 To install GoDynamo, run the following command: 11 12 ```bash 13 go get github.com/smugmug/godynamo 14 ``` 15 16 which installs a package that requires the rest of the packages in the library. 17 18 Also installed as dependencies are [goawsroles](https://github.com/smugmug/goawsroles) which manages support for IAM roles, namely: https://github.com/smugmug/goawsroles/tree/master/roles_files 19 20 GoDynamo is the foundation of *bbpd*, the http proxy daemon for DynamoDB. 21 You may find that package here: https://github.com/smugmug/bbpd 22 23 To understand how to use Go code in your environment, please see: http://golang.org/doc/install 24 25 and other documentation on the golang.org site. 26 27 ## Configuration 28 29 GoDynamo is configured with an external file. This allows you to write programs that do not contain 30 hardcoded authentication values. The `conf_file` package contains an exported method `Read` 31 that must be called to read these configuration variables into your program state, where they 32 will be visible as the exported global variable `Conf`. The `Read` method will first look for 33 `~/.aws-config.json`, and then `/etc/aws-config.json`. You may also set an environment variable 34 `GODYNAMO_CONF_FILE` that will permit you to specify a fully-qualified file path for your own 35 conf file. If none of those files are present, 36 the `Read` method will return false and it is advised that your program terminate. 37 38 A sample of a skeleton `aws-config.json` file is found in `conf/SAMPLE-aws-config.json`. 39 Please see the go docs for the `conf` package to see an explanation of the fields and their use. 40 It is recommended that you set file permissions on the configuration file to be as restrictive 41 as possible. 42 43 For convenience, here is the sample configuration file (comments nonstandard): 44 45 ``` 46 { 47 "extends":[], 48 "services": { 49 "default_settings":{ 50 "params":{ 51 // Traditional AWS access/secret authentication pair. 52 "access_key_id":"xxx", 53 "secret_access_key":"xxx", 54 // If you use syslogd (a linux or *bsd system), you may set this to "true". 55 // (currently unusued) 56 "use_sys_log":true 57 } 58 }, 59 "dynamo_db": { 60 "host":"dynamodb.us-east-1.amazonaws.com", 61 "zone":"us-east-1", 62 // You can alternately set the scheme/port to be https/443. 63 "scheme":"http", 64 "port":80, 65 // If set to true, programs that are written with godynamo may 66 // opt to launch the keepalive goroutine to keep conns open. 67 "keepalive":true, 68 "iam": { 69 // If you do not want to use IAM (i.e. just use access_key/secret), 70 // set this to false and use the settings above. 71 "use_iam":true, 72 // The role provider is described in the goawsroles package. 73 // See: https://github.com/smugmug/goawsroles/ 74 // Currently the only support is for the "file" provider, whereby 75 // roles data is written to local files. 76 "role_provider":"file", 77 // The identifier (filename, etc) for the IAM Access Key 78 "access_key":"role_access_key", 79 // The identifier (filename, etc) for the IAM Secret Key 80 "secret_key":"role_secret_key", 81 // The identifier (filename, etc) for the IAM Token 82 "token":"role_token", 83 // If using the "file" role provider, the base dir to read IAM files. 84 "base_dir":"/dir/where/you/update/role_files", 85 // Set to true if you would like the roles resource watched for changes 86 // and automatically (and atomically) updated. 87 "watch":true 88 } 89 } 90 } 91 } 92 ``` 93 94 In this configuration example, the recommended option of using IAM credentials has been selected, 95 with the source for these credentials being local text files. Creating the automation to 96 retrieve these credential files and store them on your host is specific to your installation 97 as IAM is capable of setting fine-grained permissions. See your sysadmin for assistance. If 98 you do not wish to use IAM or cannot create the automation to keep your local credential files 99 up to date, you may wish to set `use_iam` to false and just set the access and secret keypair. 100 101 ## Example Program 102 103 In any program you write using GoDynamo, you must first make sure that your configuration has 104 been initialized properly. You will optionally wish to use IAM support for authentication. 105 106 See the files in `tests` for full examples for various endpoints. Below is a small example 107 illustrating the way a program using GoDynamo is set up: 108 109 ```go 110 package main 111 112 import ( 113 "fmt" 114 "github.com/smugmug/godynamo/conf" 115 "github.com/smugmug/godynamo/conf_file" 116 conf_iam "github.com/smugmug/godynamo/conf_iam" 117 put "github.com/smugmug/godynamo/endpoints/put_item" 118 keepalive "github.com/smugmug/godynamo/keepalive" 119 "github.com/smugmug/godynamo/types/attributevalue" 120 "log" 121 "net/http" 122 ) 123 124 // This example will attempt to put an item to a imaginary test table. 125 func main() { 126 // Let's try to read a conf file located at `$HOME/.aws-config.json`. 127 home := os.Getenv("HOME") 128 home_conf_file := home + string(os.PathSeparator) + "." + conf.CONF_NAME 129 home_conf, home_conf_err := conf_file.ReadConfFile(home_conf_file) 130 if home_conf_err != nil { 131 panic("cannot read conf from " + home_conf_file) 132 } 133 home_conf.ConfLock.RLock() 134 if home_conf.Initialized == false { 135 panic("conf struct has not been initialized") 136 } 137 138 // A convenience to keep connections to AWS open, which is not needed if you 139 // are generating many requests through normal use. 140 if home_conf.Network.DynamoDB.KeepAlive { 141 log.Printf("launching background keepalive") 142 go keepalive.KeepAlive([]string{home_conf.Network.DynamoDB.URL}) 143 } 144 145 // Initialize a goroutine which will watch for changes in the local files 146 // we have chosen (in our conf file) to contain our IAM authentication values. 147 // It is assumed that another process refreshes these files. 148 // If you opt to use plain old AWS authentication pairs, you don't need this. 149 if home_conf.UseIAM { 150 iam_ready_chan := make(chan bool) 151 go conf_iam.GoIAM(iam_ready_chan) 152 iam_ready := <-iam_ready_chan 153 if iam_ready { 154 fmt.Printf("using iam\n") 155 } else { 156 fmt.Printf("not using iam\n") 157 } 158 } 159 160 home_conf.ConfLock.RUnlock() 161 162 put1 := put.NewPutItem() 163 put1.TableName = "test-godynamo-livetest" 164 165 hashKey := fmt.Sprintf("my-hash-key") 166 rangeKey := fmt.Sprintf("%v", 1) 167 put1.Item["TheHashKey"] = &attributevalue.AttributeValue{S: hashKey} 168 put1.Item["TheRangeKey"] = &attributevalue.AttributeValue{N: rangeKey} 169 170 // All endpoints now support a parameterized conf. 171 body, code, err := put1.EndpointReqWithConf(home_conf) 172 if err != nil || code != http.StatusOK { 173 fmt.Printf("put failed %d %v %s\n", code, err, body) 174 } 175 fmt.Printf("%v\n%v\n,%v\n", string(body), code, err) 176 177 } 178 ``` 179 180 For more examples that demonstrate how you might wish to use various endpoint libraries, please refer to the 181 `tests` directory which contains a series of files that are intended to run against AWS, so executing them 182 will require valid AWS credentials. 183 184 ## Special Features 185 186 One noteworthy feature of GoDynamo is some convenience functions to get around some static limitations of the 187 default DynamoDB service. In particular, in `endpoints/batch_get_item` you will find a function `DoBatchGet` 188 which allows an input structure with an arbitrary number of get requests, which are dispatched in segments 189 and re-assembled. Likewise, in `endpoints/batch_write_item` you will find a function `DoBatchWrite` which 190 allows an input structure with an arbitrary number of write requests. These functions are provided 191 as a convenience and do not alter your provisioning model, so be careful. 192 193 *Throttling* occurs in DynamoDB operations when AWS wishes to shape traffic to their service. 194 GoDynamo utilizes the standard *exponential decay* resubmission algorithm as described in 195 the AWS documentation. While you will see messages regarding the throttling, GoDynamo continues to 196 retry your request as per the resubmission algorithm. 197 198 ### JSON Documents 199 200 Amazon has been augmenting their SDKs with wrappers that allow the caller to coerce 201 their Items (both when writing and reading) to what I will refer to as "basic JSON". 202 203 Basic JSON is stripped of the type signifiers ('S','NS', etc) that AWS specifies in their 204 `AttributeValue` specification (http://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_AttributeValue.html). 205 206 For example, the `AttributeValue` 207 208 ```json 209 {"AString":{"S":"this is a string"}} 210 ``` 211 212 is translated to this basic JSON: 213 214 ```json 215 {"AString":"this is a string"} 216 ``` 217 218 Here are some other examples: 219 220 `AttributeValue`: 221 222 ```json 223 {"AStringSet":{"SS":["a","b","c"]}} 224 {"ANumber":{"N":"4"}} 225 {"AList":[{"N":"4"},{"SS":["a","b","c"]}]} 226 ``` 227 228 are translated to these basic JSON values: 229 230 ```json 231 {"AStringSet":["a","b","c"]} 232 {"ANumber":4} 233 {"AList":[4,["a","b","c"]]} 234 ``` 235 236 GoDynamo now includes support for passing in basic JSON documents in place of Items in the 237 following endpoints: 238 239 - GetItem 240 - PutItem 241 - BatchGetItem 242 - BatchWriteItem 243 244 In the case of `GetItem` and `BatchGetItem`, the method is to call the methods 245 `ToResponseItemJSON` and `ToResponseItemsJSON` respective methods on the `Response` 246 types for each package, unmarshaled from the response strings returned from AWS 247 after calling `EndpointReq` to complete requests. 248 249 In the case of `PutItem`, use `NewPutItemJSON()` to initialize a variable of type 250 `PutItemJSON`. The `Item` field of this struct is an `interface{}`, to which you 251 can assign data representing basic JSON. Once done, call the `ToPutItem()` method on the `PutItemJSON` 252 variable to translate the basic JSON into `AttributeValue` types and return a `PutItem` 253 type that you can now call `EndpointReq` on. 254 255 In the case of `PutItem`, use `NewBatchWriteItemJSON()` to initialize a variable of type 256 `BatchWriteItemJSON`. The `Item` field of this `PutRequest` subfield is an `interface {}` you 257 can assign data representing basic JSON. Once done, call the `ToBatchWriteItem()` method on the `BatchWriteItemJSON` 258 variable to translate the basic JSON into `AttributeValue` types and return a `BatchWriteItem` 259 type that you can now call `EndpointReq` on. 260 261 Note that AWS itself does not support basic JSON - the support is always delivered by a 262 coercion of basic JSON to and from `AttrbiuteValue`. This coercion is lossy! For example, 263 a `B` or `BS` will be coerced to a string type (`S`, `SS`) and `NULL` types will be 264 coerced to `BOOL`. Use with caution. 265 266 This feature is only enabled for `Item` types, not for `Key` or other `AttributeValue` 267 aliases. So for example, `BatchWriteItemJSON` requests of type `DeleteRequest` cannot use 268 basic JSON, only `PutRequest`. 269 270 ## Troubleshooting 271 272 GoDynamo provides verbose error messages when appropriate, as well as STDERR messaging. If error 273 reporting is not useful, it is possible that DynamoDB itself has a new or changed feature that is 274 not reflected in GoDynamo. 275 276 ## Recent Noteworthy Changes 277 278 Early versions of GoDynamo utilized a global configuration that was accessed inside relevant 279 functions once set. Many developers requested that these configurations become parameterized 280 so they could utilize different configurations simultaneously. GoDynamo now supports 281 parameterized configurations in every function. These new functions are called `EndpointReqWithConf`. 282 283 Parameterized configuration has been moved into the full api including the core authorization 284 functions. 285 286 ## Contact Us 287 288 Please contact opensource@smugmug.com for information related to this package. Pull requests also welcome!