Showing preview only (1,408K chars total). Download the full file or copy to clipboard to get everything.
Repository: EagerIO/Stout
Branch: master
Commit: e50d63a2f523
Files: 97
Total size: 1.3 MB
Directory structure:
gitextract_dxdit0ui/
├── .github/
│ └── workflows/
│ └── semgrep.yml
├── .gitignore
├── Godeps/
│ ├── Godeps.json
│ └── Readme
├── LICENSE
├── README.md
├── docs/
│ └── getting-started.md
├── src/
│ ├── admin.go
│ ├── cli.go
│ ├── deploy.go
│ ├── rollback.go
│ └── utils.go
├── utils/
│ ├── build.sh
│ ├── create_site.sh
│ ├── release.sh
│ └── xc.sh
└── vendor/
├── github.com/
│ ├── cenk/
│ │ └── backoff/
│ │ ├── .gitignore
│ │ ├── .travis.yml
│ │ ├── LICENSE
│ │ ├── README.md
│ │ ├── backoff.go
│ │ ├── exponential.go
│ │ ├── retry.go
│ │ └── ticker.go
│ ├── imdario/
│ │ └── mergo/
│ │ ├── .travis.yml
│ │ ├── LICENSE
│ │ ├── README.md
│ │ ├── doc.go
│ │ ├── map.go
│ │ ├── merge.go
│ │ └── mergo.go
│ ├── mitchellh/
│ │ └── go-homedir/
│ │ ├── LICENSE
│ │ ├── README.md
│ │ └── homedir.go
│ ├── wsxiaoys/
│ │ └── terminal/
│ │ ├── LICENSE
│ │ └── color/
│ │ └── color.go
│ └── zackbloom/
│ ├── go-ini/
│ │ ├── .gitignore
│ │ ├── README.md
│ │ ├── decode.go
│ │ └── stack.go
│ └── goamz/
│ ├── LICENSE
│ ├── aws/
│ │ ├── attempt.go
│ │ ├── aws.go
│ │ ├── client.go
│ │ ├── regions.go
│ │ ├── retry.go
│ │ └── sign.go
│ ├── cloudfront/
│ │ └── cloudfront.go
│ ├── iam/
│ │ ├── iam.go
│ │ └── sign.go
│ ├── route53/
│ │ └── route53.go
│ └── s3/
│ ├── lifecycle.go
│ ├── multi.go
│ ├── s3.go
│ └── sign.go
├── golang.org/
│ └── x/
│ ├── crypto/
│ │ ├── LICENSE
│ │ ├── PATENTS
│ │ └── ssh/
│ │ └── terminal/
│ │ ├── terminal.go
│ │ ├── util.go
│ │ ├── util_bsd.go
│ │ ├── util_linux.go
│ │ ├── util_plan9.go
│ │ └── util_windows.go
│ └── net/
│ ├── LICENSE
│ ├── PATENTS
│ ├── html/
│ │ ├── atom/
│ │ │ ├── atom.go
│ │ │ ├── gen.go
│ │ │ └── table.go
│ │ ├── const.go
│ │ ├── doc.go
│ │ ├── doctype.go
│ │ ├── entity.go
│ │ ├── escape.go
│ │ ├── foreign.go
│ │ ├── node.go
│ │ ├── parse.go
│ │ ├── render.go
│ │ └── token.go
│ └── publicsuffix/
│ ├── gen.go
│ ├── list.go
│ └── table.go
└── gopkg.in/
└── yaml.v1/
├── LICENSE
├── LICENSE.libyaml
├── README.md
├── apic.go
├── decode.go
├── emitterc.go
├── encode.go
├── parserc.go
├── readerc.go
├── resolve.go
├── scannerc.go
├── sorter.go
├── writerc.go
├── yaml.go
├── yamlh.go
└── yamlprivateh.go
================================================
FILE CONTENTS
================================================
================================================
FILE: .github/workflows/semgrep.yml
================================================
on:
pull_request: {}
workflow_dispatch: {}
push:
branches:
- main
- master
schedule:
- cron: '0 0 * * *'
name: Semgrep config
jobs:
semgrep:
name: semgrep/ci
runs-on: ubuntu-latest
env:
SEMGREP_APP_TOKEN: ${{ secrets.SEMGREP_APP_TOKEN }}
SEMGREP_URL: https://cloudflare.semgrep.dev
SEMGREP_APP_URL: https://cloudflare.semgrep.dev
SEMGREP_VERSION_CHECK_URL: https://cloudflare.semgrep.dev/api/check-version
container:
image: semgrep/semgrep
steps:
- uses: actions/checkout@v4
- run: semgrep ci
================================================
FILE: .gitignore
================================================
.DS_Store
builds/
debian/
================================================
FILE: Godeps/Godeps.json
================================================
{
"ImportPath": "github.com/eagerio/stout",
"GoVersion": "go1.6",
"GodepVersion": "v63",
"Packages": [
"./..."
],
"Deps": [
{
"ImportPath": "github.com/cenk/backoff",
"Comment": "v1.0.0-7-gcdf48bb",
"Rev": "cdf48bbc1eb78d1349cbda326a4a037f7ba565c6"
},
{
"ImportPath": "github.com/imdario/mergo",
"Comment": "0.2.2-6-g50d4dbd",
"Rev": "50d4dbd4eb0e84778abe37cefef140271d96fade"
},
{
"ImportPath": "github.com/mitchellh/go-homedir",
"Rev": "1111e456ffea841564ac0fa5f69c26ef44dafec9"
},
{
"ImportPath": "github.com/wsxiaoys/terminal/color",
"Rev": "0940f3fc43a0ed42d04916b1c04578462c650b09"
},
{
"ImportPath": "github.com/zackbloom/go-ini",
"Rev": "3db81f263990ac57212cfdc3ce9a65e8af8af966"
},
{
"ImportPath": "github.com/zackbloom/goamz/aws",
"Rev": "0f589c21f1937992b2952e1f4ce0d31f132b685d"
},
{
"ImportPath": "github.com/zackbloom/goamz/cloudfront",
"Rev": "0f589c21f1937992b2952e1f4ce0d31f132b685d"
},
{
"ImportPath": "github.com/zackbloom/goamz/iam",
"Rev": "0f589c21f1937992b2952e1f4ce0d31f132b685d"
},
{
"ImportPath": "github.com/zackbloom/goamz/route53",
"Rev": "0f589c21f1937992b2952e1f4ce0d31f132b685d"
},
{
"ImportPath": "github.com/zackbloom/goamz/s3",
"Rev": "0f589c21f1937992b2952e1f4ce0d31f132b685d"
},
{
"ImportPath": "golang.org/x/crypto/ssh/terminal",
"Rev": "5bcd134fee4dd1475da17714aac19c0aa0142e2f"
},
{
"ImportPath": "golang.org/x/net/html",
"Rev": "8a52c78636f6b7be1b1e5cb58b01a85f1e082659"
},
{
"ImportPath": "golang.org/x/net/html/atom",
"Rev": "8a52c78636f6b7be1b1e5cb58b01a85f1e082659"
},
{
"ImportPath": "golang.org/x/net/publicsuffix",
"Rev": "8a52c78636f6b7be1b1e5cb58b01a85f1e082659"
},
{
"ImportPath": "gopkg.in/yaml.v1",
"Rev": "9f9df34309c04878acc86042b16630b0f696e1de"
}
]
}
================================================
FILE: Godeps/Readme
================================================
This directory tree is generated automatically by godep.
Please do not edit.
See https://github.com/tools/godep for more information.
================================================
FILE: LICENSE
================================================
Copyright (c) 2014 Eager Platform Co.
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
================================================
FILE: README.md
================================================
# Stout
#### [View the site →](http://stout.is/)
Stout is a deploy tool for static websites. It takes a website and uploads it to S3 in a more reliable way than other tools. It can be an alternative
to paid services like Divshot, to dynamic web servers like Rails, or to manually uploading your site to S3 or an FTP server.
## Why You Need Stout
Traditionally uploading your files to S3 introduces a serious caching issue we ran into in practice at [Eager](https://eager.io).
The cache for the various files your site depends on can expire at different times, meaning your users get an inconsistent (broken) set of files for a
time after every single deploy. Further, traditional static site deployments don't offer any method of rolling back a previous deploy.
We built Stout to fix these issues.
### Features
- Versions script and style files to ensure your pages don't use an inconsistent set of files during or after a deploy
- Supports rollback to any previous version
- Does not depend on any specific build tool or workflow (it is a standalone executable written in Go)
- Does not require a datastore of any kind to maintain state or history
- Can be used by multiple developers simultaneously without locking or a danger of inconsistent state
- Properly handles caching headers
- Supports deploying multiple projects to various subdirectories of the same site without conflicts
- Compresses files for faster delivery
### Limitations
- Stout doesn't currently support rolling back files that aren't HTML, JS or CSS (images, videos, etc.). See the Versioning section for more information.
- All-or-nothing consistency is only guarenteed on a per-html-file basis, not for the entire deploy. See the Consistency section for more information.
## Getting Started
[Download](https://github.com/EagerIO/Stout/releases) the `stout` executable for your system from our latest release into a directory on your `$PATH`, like `/usr/local/bin`.
You can use the `create` command to create a new site. It automatically creates an S3 bucket, a CloudFront distribution, and a user account for deployment. It therefore requires
credentials for an Amazon AWS account which has permissions to those services along with Route 53.
```sh
stout create --bucket my.website.com --key MY_AWS_KEY --secret MY_AWS_SECRET
```
You can then deploy your project:
```sh
stout deploy --bucket my.website.com --key MY_AWS_KEY --secret MY_AWS_SECRET
```
If your built files are in another directory, add the `--root` option:
```sh
stout deploy --bucket my.website.com --key MY_AWS_KEY --secret MY_AWS_SECRET --root ./build
```
If your bucket located not in the default region, which is us-east-1, add the `--region` option:
```sh
stout deploy --bucket my.website.com --key MY_AWS_KEY --secret MY_AWS_SECRET --region us-west-1
```
If you don't want to deploy all the files in your folder, use the files argument.
```sh
stout deploy --bucket my.website.com --key MY_AWS_KEY --secret MY_AWS_SECRET --root ./build --files "*.html,images/*"
```
Javascript and CSS included in your HTML files will always be included automatically.
The deploy command will give you a deploy id you can use in the future to rollback if you have to:
```sh
stout rollback --bucket my.website.com --key MY_AWS_KEY --secret MY_AWS_SECRET a3b8ff290c33
```
Eventually you'll probably want to move your config to a deploy.yaml file, rather than specifying it in the command every time.
Using the info below you can learn about what the deploy/rollback tools actually do, deploying to subfolders, deploying from your build tool, and rolling back.
## Backstory
We wrote Stout because we couldn't find an open-source way to reliably and efficiently deploy our static sites (including our app and blog). We used a traditional upload-to-s3 tool, but caching meant a user could get the new html and styles, but the old scripts, for example, causing sporatic and random errors. It also didn't support reliably rolling back when necessary. We built Stout to be the reliable, production-ready choice for static deploys.
## Function
Stout is an executable file built from Go code. The `deploy` command deploys one or more html files and their dependencies to a specified location in S3. The `rollback` command takes a deploy id and rolls the project back to that version.
### Deploy
The deploy process works by parsing the script and style tags out of one or more html files. It then hashes those files, uploads them prefixed with their hashes, and updates the location of the original script and link tags with the hashed locations.
It generates a deploy id by hashing all of the files in the deploy, and uploads the html files to a location prefixed by the deploy id.
When the uploads are successful, the prefixed html files are atomically copied to their unprefixed paths, completing the deploy.
### Rollback
A rollback simply copies the html files prefixed with the specified deploy id to the unprefixed paths.
### Deploy Configuration
You can configure the deploy tool with any combination of command line flags or arguments provided in a configuration yaml file.
The options are:
##### `bucket`
The S3 bucket to deploy to. In most configurations this bucket should be the origin for the CDN which actually serves your site. It usually makes sense to make this the url you are going to host your site from (i.e. `"example.com"`)
##### `config` ("./deploy.yaml")
The location of a yaml file to read any otherwise unspecified configuration from.
##### `dest` ("./")
The destination directory to write files to in the S3 bucket. For example if you wanted your this project to end up hosted at `yoursite.com/blog`, you would specify `--dest blog`.
##### `root` ("./")
The local directory where the files to be uploaded lives. It's common to make this your "./build" directory or the like.
##### `files` ("*")
Comma-seperated glob patterns of the files to be deployed (within the `--root`). HTML files will be parsed, and the CSS/JS they point to will be included (versioned) automatically. If you also include those files in your glob pattern they will be uploaded twice, once with a versioning hash in the URL, again without.
Be sure to include any additional files you would like deployed like images, videos, font files, etc.
You can use relative paths which break out of the `root`. If you prefix the path with `-/`, it will be interpreted as relative to the project directory, not the `root`.
##### `env`
The config file can contain configurations for multiple environments (production, staging, etc.). This specifies which is used. See the "YAML Config" section for more information.
##### `key`
The AWS key to use. The create command will create an IAM user for each project with access only to the relevant bucket. See the Permissions section for more information.
##### `secret`
The AWS secret of the provided key.
##### `region` ("us-east-1")
The AWS region the S3 bucket is located in.
If you are getting a `The bucket you are attempting to access must be addressed using the specified endpoint. Please send all future requests to this endpoint.` error, specify your bucket `--region`.
### YAML Config
You can provide a yaml file which specifies configuration defaults for the project being deployed. We include this file in each project which will be deployed. This file can have multiple configurations for different environments, along with a default section.
For example, the `deploy.yaml` for one of our projects looks like:
```yaml
default:
root: 'build/'
production:
key: 'XXX'
secret: 'XXX'
bucket: 'eager.io'
development:
key: 'XXX'
secret: 'XXX'
bucket: 'next.eager.io'
```
Replacing the "XXX"s with our actual credentials.
To deploy to development we run (from the directory with the deploy.yaml file in it):
```bash
deploy --env development
```
A rollback of development would be:
```bash
rollback --env development $DEPLOY_ID
```
Where the deploy id is taken from the output of the deploy you wish to rollback to.
Our public projects use a similar config, but they specify the Amazon credentials as environment vars from the build system, passed in as flags:
```bash
deploy --env development --key $AMAZON_KEY_DEV --secret $AMAZON_SECRET_DEV
```
Never commit Amazon credentials to a file in a public repo. Keep them on your local machine, or in your build system's configuration.
### Clean URLS
It's not specific to Stout, but it's worth mentioning that we recommend you structure your built folder to use a folder with an index.html file for each page.
For example, if you want a root and a page at `/blog`, you would have:
```
index.html
blog/
index.html
```
That way, assuming S3 and CloudFront are configured properly, you'll be able to use the clean URLs `/` and `/blog/`.
### SSL
Cloudfront has the ability to serve your site using SSL. The general procedure for setting it up is:
1. Get an SSL certificate for your domain
2. Upload it to Amazon
3. Select that certificate in the configuration for the CloudFront distribution Stout creates for you
You will absolutely need more detailed instructions, which you can find [here](https://bryce.fisher-fleig.org/blog/setting-up-ssl-on-aws-cloudfront-and-s3/).
Selecting a certificate for you is one of the few things the `create` command does not do, as it's not always possible to decide which certificate is appropriate. If you need SSL support, you will have to remember to select the cert in the Amazon Console or CLI after running the `create` command.
### Permissions
The AWS user which is used for Stout should have the `GetObject`, `PutObject`, `DeleteObject`, and `ListBucket` permissions. The `create` command will set this up for you if you use it.
This is an example policy config which works:
```json
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:DeleteObject",
"s3:ListBucket",
"s3:PutObject",
"s3:PutObjectAcl",
"s3:GetObject"
],
"Resource": [
"arn:aws:s3:::BUCKET", "arn:aws:s3:::BUCKET/*"
]
}
]
}
```
Be sure to replace `BUCKET` with your bucket's actual name.
### Deploying with CircleCI
Deploying with CircleCI is simply a matter of installing the deploy tool and running it as you would locally. Here's an excerpt of a working circle.yml:
```yaml
dependencies:
post:
- go get github.com/tools/godep
- git clone git@github.com:EagerIO/Stout.git
- cd Stout; godep go build -o ../stout src/*.go
deployment:
development:
branch: dev
commands:
- ./stout deploy --env development --key $AMAZON_KEY_DEV --secret $AMAZON_SECRET_DEV
production:
branch: master
commands:
- ./stout deploy --env production --key $AMAZON_KEY_PROD --secret $AMAZON_SECRET_PROD
```
If you use environment vars for your credentials, make sure to add them to your Circle config.
If your repo is private, you can specify your Amazon key and secret in your deploy.yaml file, removing the need to specify them in the commands.
### Caching
All versioned files (include a hash of their contents in the path) are configured to cache for one year. All unversioned files are configured to cache for 60 seconds. This means it will take up to 60 seconds for users to see changes made to your site.
### Versioning
Only JS and CSS files which are pointed to in HTML files are hashed, as we need to be able to update the HTML to point to our new, versioned, files.
Any other file included in your `--files` argument will be uploaded, but not versioned, meaning a rollback will not effect these files. This is something we'd like to improve.
### Consistency
As the final step of the deploy is atomic, multiple actors can trigger deploys simultaneously without any danger of inconsistent state. Whichever process triggers the final 'copy' step for a given file will win, with it's specified dependencies guarenteed to be used in their entirity. Note that this consistency is only guarenteed on a per-html-file level, you may end up with some html files from one deployer, and others from another, but all files will point to their correct dependencies.
### Deploying Multiple Projects To One Site
You can deploy multiple projects to the same domain simply by specifying the appropriate `dest` for each one. For example your homepage might have the dest `./`, and your blog `./blog`. Your homepage will be hosted at `your-site.com`, your blog `your-site.com/blog`.
### Using Client-side Routers
It is possible to use a client-side router (where you have multiple request URLs point to the same HTML file) by configuring your CloudFront distribution to serve your index.html file in response to 403s and 404s.

### Installing
- Download the release for your system type from our [releases](https://github.com/EagerIO/Stout/releases)
- Copy or symlink the `stout` binary contained in the archive into your path (for example, into `/usr/local/bin`)
### Building
- Install go and godep
- Run `godep restore ./...`
- Run `go build -o ../stout src/*`
#### For a Release (Cross Compiling)
- Run `go get github.com/laher/goxc`
- Run `go get code.google.com/p/go.tools/cmd/vet`
- Run `./utils/xc.sh`
The first run will take significantly longer than future runs. The built files will be placed in the `./builds` directory.
### Running
To run the commands for development purposes, run: `go run src/*`, followed by any command line args you would normally give to the command.
### Contributing
Please do, we would love for this to become a project of the community. Feel free to open an issue, submit a PR or contribute to the wiki.
================================================
FILE: docs/getting-started.md
================================================
### Setting Up Your Site
If you don't already have an S3-hosted site, start here.
We're going to create a basic site config which uses CloudFront's CDN to deliver high performance at a minimal cost. Once you run the setup, you'll end up with a configuration which looks like this:
```
The Deploy Tool -> S3 <- CloudFront's Global CDN <- DNS <- Your Users
```
The simplest way to get started is to run the `create_site.sh` script in the utils folder. After installing the [aws command line tools](http://aws.amazon.com/cli/), run:
```bash
./utils/create_site.sh subdomain.my-site.com
```
Feel free to leave out the subdomain if you'd like to host it at the root of your domain.
This will:
- Create an S3 bucket for this site with the correct security policy and website hosting
- Create a CloudFront distribution pointed at that bucket
- Create a user with the appropriate permissions to upload to that bucket
- Create an access key for that user
Once that's done, copy the access key, secret key (from the JSON blob the access key request spits out) and bucket (the bucket's name is just the url you provided) it printed to your `deploy.yaml`, or save them to use with the `stout deploy` as arguments.
The final step is to point your DNS records to the new CloudFront distribution. If you use Route 53 you want to create an alias to the distribution (it will be named the same as the new domain). If you use another DNS service, you'll want to create a CNAME to the CloudFront distribution's hostname.
Please note that it will take up to twenty minutes for the CloudFront distribution to initialize. Additionally it may take some time for your DNS records to update.
If you'd like development or staging environments, just run the command again with the URL you'd like them to have, and add the new credentials as before. See the "YAML Config" section of the README for an example of how to configure multiple environments.
Be very careful to never commit a file to a public repo that contains your AWS credentials. If you are deploying a public repo, either keep the credentials on your local machine you deploy from, or in the build service (like CircleCI) you're using.
#### Step-by-step Instructions
1. Install Amazon's AWS Command-Line Tools (and create an AWS account if you don't have one)
1. Run the `create_site.sh` tool with the URL of the site you'd like to deploy
1. Take note of the AWS key and secret in the final JSON blob outputted by the script
1. Download the executable from this project
1. Run `stout deploy --bucket subdomain.your-site.com --key YOUR_NEW_AWS_KEY --secret YOUR_NEW_AWS_SECRET` to deploy
1. Add the `--root` argument if your built files are in a subdirectory.
1. Visit the cloudfront url of your new distribution to see how your site currently looks, include any new files you may have missed and deploy again
1. Optionally, Move any configuration options you don't mind being committed to your repository to a deploy.yaml file
1. Optionally, Run `create_site.sh` again to create staging or development sites, and add their configuration to your deploy.yaml as well
1. Optionally, Deploy more projects to this same site by running deploy with the `--dest` argument
1. Optionally, Add the deploy step to your build tool
================================================
FILE: src/admin.go
================================================
package main
import (
"fmt"
"os"
"os/exec"
"strings"
"github.com/zackbloom/goamz/cloudfront"
"github.com/zackbloom/goamz/iam"
"github.com/zackbloom/goamz/route53"
"github.com/zackbloom/goamz/s3"
"golang.org/x/crypto/ssh/terminal"
"golang.org/x/net/publicsuffix"
)
func CreateBucket(options Options) error {
bucket := s3Session.Bucket(options.Bucket)
err := bucket.PutBucket("public-read")
if err != nil {
return err
}
err = bucket.PutBucketWebsite(s3.WebsiteConfiguration{
IndexDocument: &s3.IndexDocument{"index.html"},
ErrorDocument: &s3.ErrorDocument{"error.html"},
})
if err != nil {
return err
}
err = bucket.PutPolicy([]byte(`{
"Version": "2008-10-17",
"Statement": [
{
"Sid": "PublicReadForGetBucketObjects",
"Effect": "Allow",
"Principal": {
"AWS": "*"
},
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::` + options.Bucket + `/*"
}
]
}`,
))
if err != nil {
return err
}
return nil
}
func GetDistribution(options Options) (dist cloudfront.DistributionSummary, err error) {
distP, err := cfSession.FindDistributionByAlias(options.Bucket)
if err != nil {
return
}
if distP != nil {
fmt.Println("CloudFront distribution found with the provided bucket name, assuming config matches.")
fmt.Println("If you run into issues, delete the distribution and rerun this command.")
dist = *distP
return
}
conf := cloudfront.DistributionConfig{
Origins: cloudfront.Origins{
cloudfront.Origin{
Id: "S3-" + options.Bucket,
DomainName: options.Bucket + ".s3-website-" + options.AWSRegion + ".amazonaws.com",
CustomOriginConfig: &cloudfront.CustomOriginConfig{
HTTPPort: 80,
HTTPSPort: 443,
OriginProtocolPolicy: "http-only",
},
},
},
DefaultRootObject: "index.html",
PriceClass: "PriceClass_All",
Enabled: true,
DefaultCacheBehavior: cloudfront.CacheBehavior{
TargetOriginId: "S3-" + options.Bucket,
ViewerProtocolPolicy: "allow-all",
AllowedMethods: cloudfront.AllowedMethods{
Allowed: []string{"GET", "HEAD"},
Cached: []string{"GET", "HEAD"},
},
},
ViewerCertificate: &cloudfront.ViewerCertificate{
CloudFrontDefaultCertificate: true,
MinimumProtocolVersion: "TLSv1",
SSLSupportMethod: "sni-only",
},
CustomErrorResponses: cloudfront.CustomErrorResponses{
// This adds support for single-page apps
cloudfront.CustomErrorResponse{
ErrorCode: 403,
ResponsePagePath: "/index.html",
ResponseCode: 200,
ErrorCachingMinTTL: 60,
},
cloudfront.CustomErrorResponse{
ErrorCode: 404,
ResponsePagePath: "/index.html",
ResponseCode: 200,
ErrorCachingMinTTL: 60,
},
},
Aliases: cloudfront.Aliases{
options.Bucket,
},
}
return cfSession.Create(conf)
}
func CreateUser(options Options) (key iam.AccessKey, err error) {
name := options.Bucket + "_deploy"
_, err = iamSession.CreateUser(name, "/")
if err != nil {
iamErr, ok := err.(*iam.Error)
if ok && iamErr.Code == "EntityAlreadyExists" {
err = nil
} else {
return
}
}
_, err = iamSession.PutUserPolicy(name, name, `{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:DeleteObject",
"s3:ListBucket",
"s3:PutObject",
"s3:PutObjectAcl",
"s3:GetObject"
],
"Resource": [
"arn:aws:s3:::`+options.Bucket+`", "arn:aws:s3:::`+options.Bucket+`/*"
]
}
]
}`,
)
if err != nil {
return
}
keyResp, err := iamSession.CreateAccessKey(name)
if err != nil {
return
}
return keyResp.AccessKey, nil
}
func UpdateRoute(options Options, dist cloudfront.DistributionSummary) error {
zoneName, err := publicsuffix.EffectiveTLDPlusOne(options.Bucket)
if err != nil {
return err
}
zoneName = zoneName + "."
resp, err := r53Session.ListHostedZonesByName(zoneName, "", 100)
if err != nil {
return err
}
if resp.IsTruncated {
panic("More than 100 zones in the account")
}
var zone *route53.HostedZone
for _, z := range resp.HostedZones {
if z.Name == zoneName {
zone = &z
break
}
}
if zone == nil {
fmt.Printf("A Route 53 hosted zone was not found for %s\n", zoneName)
if zoneName != options.Bucket {
fmt.Println("If you would like to use Route 53 to manage your DNS, create a zone for this domain, and update your registrar's configuration to point to the DNS servers Amazon provides and rerun this command. Note that you must copy any existing DNS configuration you have to Route 53 if you do not wish existing services hosted on this domain to stop working.")
fmt.Printf("If you would like to continue to use your existing DNS, create a CNAME record pointing %s to %s and the site setup will be finished.\n", options.Bucket, dist.DomainName)
} else {
fmt.Println("Since you are hosting the root of your domain, using an alternative DNS host is unfortunately not possible.")
fmt.Println("If you wish to host your site at the root of your domain, you must switch your sites DNS to Amazon's Route 53 and retry this command.")
}
return nil
}
fmt.Printf("Adding %s to %s Route 53 zone\n", options.Bucket, zone.Name)
parts := strings.Split(zone.Id, "/")
idValue := parts[2]
_, err = r53Session.ChangeResourceRecordSet(&route53.ChangeResourceRecordSetsRequest{
Changes: []route53.Change{
route53.Change{
Action: "CREATE",
Name: options.Bucket,
Type: "A",
AliasTarget: route53.AliasTarget{
HostedZoneId: "Z2FDTNDATAQYW2",
DNSName: dist.DomainName,
EvaluateTargetHealth: false,
},
},
},
}, idValue)
if err != nil {
if strings.Contains(err.Error(), "it already exists") {
fmt.Println("Existing route found, assuming it is correct")
fmt.Printf("If you run into trouble, you may need to delete the %s route in Route53 and try again\n", options.Bucket)
return nil
}
return err
}
return nil
}
func Create(options Options) {
if s3Session == nil {
s3Session = openS3(options.AWSKey, options.AWSSecret, options.AWSRegion, options.S3Host)
}
if iamSession == nil {
iamSession = openIAM(options.AWSKey, options.AWSSecret, options.AWSRegion)
}
if r53Session == nil {
r53Session = openRoute53(options.AWSKey, options.AWSSecret)
}
if cfSession == nil {
cfSession = openCloudFront(options.AWSKey, options.AWSSecret)
}
_, err := exec.LookPath("aws")
if err != nil {
fmt.Println("The aws CLI executable was not found in the PATH")
fmt.Println("Install it from http://aws.amazon.com/cli/ and try again")
}
fmt.Println("Creating Bucket")
err = CreateBucket(options)
if err != nil {
fmt.Println("Error creating S3 bucket")
fmt.Println(err)
return
}
fmt.Println("Loading/Creating CloudFront Distribution")
dist, err := GetDistribution(options)
if err != nil {
fmt.Println("Error loading/creating CloudFront distribution")
fmt.Println(err)
return
}
fmt.Println("Adding Route")
err = UpdateRoute(options, dist)
if err != nil {
fmt.Println("Error adding route to Route53 DNS config")
fmt.Println(err)
return
}
if !options.NoUser {
key, err := CreateUser(options)
if err != nil {
fmt.Println("Error creating user")
fmt.Println(err)
return
}
fmt.Println("An access key has been created with just the permissions required to deploy / rollback this site")
fmt.Println("It is strongly recommended you use this limited account to deploy this project in the future\n")
fmt.Printf("ACCESS_KEY_ID=%s\n", key.Id)
fmt.Printf("ACCESS_KEY_SECRET=%s\n\n", key.Secret)
if terminal.IsTerminal(int(os.Stdin.Fd())) {
fmt.Println(`You can either add these credentials to the deploy.yaml file,
or specify them as arguments to the stout deploy / stout rollback commands.
You MUST NOT add them to the deploy.yaml file if this project is public
(i.e. a public GitHub repo).
If you can't add them to the deploy.yaml file, you can specify them as
arguments on the command line. If you use a build system like CircleCI, you
can add them as environment variables and pass those variables to the deploy
commands (see the README).
Your first deploy command might be:
stout deploy --bucket ` + options.Bucket + ` --key ` + key.Id + ` --secret '` + key.Secret + `'
`)
}
}
fmt.Println("You can begin deploying now, but it can take up to ten minutes for your site to begin to work")
fmt.Println("Depending on the configuration of your site, you might need to set the 'root', 'dest' or 'files' options to get your deploys working as you wish. See the README for details.")
fmt.Println("It's also a good idea to look into the 'env' option, as in real-world situations it usually makes sense to have a development and/or staging site for each of your production sites.")
}
func createCmd() {
options, _ := parseOptions()
loadConfigFile(&options)
addAWSConfig(&options)
if options.Bucket == "" {
panic("You must specify a bucket")
}
if options.AWSKey == "" || options.AWSSecret == "" {
panic("You must specify your AWS credentials")
}
Create(options)
}
================================================
FILE: src/cli.go
================================================
package main
import (
"flag"
"fmt"
)
func printUsage() {
fmt.Println(`Stout Static Deploy Tool
Supports three commands, create, deploy and rollback.
Example Usage:
To create a site which will be hosted at my.awesome.website:
stout create --bucket my.awesome.website --key AWS_KEY --secret AWS_SECRET
To deploy the current folder to the root of the my.awesome.website site:
stout deploy --bucket my.awesome.website --key AWS_KEY --secret AWS_SECRET
To rollback to a specific deploy:
stout rollback --bucket my.awesome.website --key AWS_KEY --secret AWS_SECRET c4a22bf94de1
See the README for more configuration information.
`)
}
func main() {
flag.Parse()
command := flag.Arg(0)
switch command {
case "help":
printUsage()
case "deploy":
deployCmd()
case "rollback":
rollbackCmd()
case "create":
createCmd()
default:
fmt.Println("Command not understood")
fmt.Println("")
printUsage()
}
}
================================================
FILE: src/deploy.go
================================================
package main
import (
"bytes"
"compress/gzip"
"crypto/md5"
"encoding/base64"
"fmt"
"io"
"math/big"
"mime"
"net/url"
"os"
"os/exec"
"path/filepath"
"strings"
"sync"
"time"
"github.com/cenk/backoff"
"golang.org/x/net/html"
"log"
"github.com/wsxiaoys/terminal/color"
"github.com/zackbloom/goamz/s3"
)
const (
SCRIPT = iota
STYLE
)
const UPLOAD_WORKERS = 20
var NO_GZIP = []string{
"mp4",
"webm",
"ogg",
}
func hashFile(path string) []byte {
hash := md5.New()
io.WriteString(hash, path)
io.WriteString(hash, "\n")
// TODO: Encode type?
ref := must(os.Open(path)).(*os.File)
defer ref.Close()
must(io.Copy(hash, ref))
return hash.Sum(nil)
}
func hashBytes(data []byte) []byte {
hash := md5.New()
must(io.Copy(hash, bytes.NewReader(data)))
return hash.Sum(nil)
}
func hashFiles(files []string) string {
hash := new(big.Int)
for _, file := range files {
val := new(big.Int)
val.SetBytes(hashFile(file))
hash = hash.Xor(hash, val)
}
return fmt.Sprintf("%x", hash)
}
func getRef() string {
gitPath := mustString(exec.LookPath("git"))
cmd := exec.Command(gitPath, "rev-parse", "--verify", "HEAD")
out := bytes.Buffer{}
cmd.Stdout = &out
panicIf(cmd.Run())
return string(out.Bytes())
}
func guessContentType(file string) string {
return mime.TypeByExtension(filepath.Ext(file))
}
func shouldCompress(file string) bool {
ext := filepath.Ext(file)
for _, e := range NO_GZIP {
if "."+e == ext {
return false
}
}
return true
}
type UploadFileRequest struct {
Bucket *s3.Bucket
Reader io.Reader
Path string
Dest string
IncludeHash bool
CacheSeconds int
}
func uploadFile(req UploadFileRequest) (remotePath string) {
buffer := bytes.NewBuffer([]byte{})
compress := shouldCompress(req.Path)
if compress {
writer := gzip.NewWriter(buffer)
must(io.Copy(writer, req.Reader))
writer.Close()
} else {
must(io.Copy(buffer, req.Reader))
}
data := buffer.Bytes()
hash := hashBytes(data)
hashPrefix := fmt.Sprintf("%x", hash)[:12]
s3Opts := s3.Options{
ContentMD5: base64.StdEncoding.EncodeToString(hash),
CacheControl: fmt.Sprintf("public, max-age=%d", req.CacheSeconds),
}
if compress {
s3Opts.ContentEncoding = "gzip"
}
dest := req.Path
if req.IncludeHash {
dest = hashPrefix + "_" + dest
}
dest = filepath.Join(req.Dest, dest)
log.Printf("Uploading to %s in %s (%s) [%d]\n", dest, req.Bucket.Name, hashPrefix, req.CacheSeconds)
op := func() error {
// We need to create a new reader each time, as we might be doing this more than once (if it fails)
return req.Bucket.PutReader(dest, bytes.NewReader(data), int64(len(data)), guessContentType(dest)+"; charset=utf-8", s3.PublicRead, s3Opts)
}
back := backoff.NewExponentialBackOff()
back.MaxElapsedTime = 30 * time.Second
err := backoff.RetryNotify(op, back, func(err error, next time.Duration) {
log.Println("Error uploading", err, "retrying in", next)
})
panicIf(err)
return dest
}
type FileRef struct {
LocalPath string
RemotePath string
UploadedPath string
}
type FileInst struct {
File *FileRef
InstPath string
}
func writeFiles(options Options, includeHash bool, files chan *FileRef) {
bucket := s3Session.Bucket(options.Bucket)
for file := range files {
handle := must(os.Open(file.LocalPath)).(*os.File)
defer handle.Close()
var ttl int
ttl = FOREVER
if !includeHash {
ttl = LIMITED
}
remote := file.RemotePath
if strings.HasPrefix(remote, "/") {
remote = remote[1:]
}
partialPath, err := filepath.Rel(options.Dest, remote)
if err != nil {
panic(err)
}
(*file).UploadedPath = uploadFile(UploadFileRequest{
Bucket: bucket,
Reader: handle,
Path: partialPath,
Dest: options.Dest,
IncludeHash: includeHash,
CacheSeconds: ttl,
})
}
}
func deployFiles(options Options, includeHash bool, files []*FileRef) {
ch := make(chan *FileRef)
wg := new(sync.WaitGroup)
for i := 0; i < UPLOAD_WORKERS; i++ {
wg.Add(1)
go func() {
writeFiles(options, includeHash, ch)
wg.Done()
}()
}
for _, file := range files {
if !includeHash && strings.HasSuffix(file.RemotePath, ".html") {
panic(fmt.Sprintf("Cowardly refusing to deploy an html file (%s) without versioning.", file.RemotePath))
}
ch <- file
}
close(ch)
wg.Wait()
}
func addFiles(form uint8, parent *html.Node, files []string) {
for _, file := range files {
node := html.Node{
Type: html.ElementNode,
}
switch form {
case SCRIPT:
node.Data = "script"
node.Attr = []html.Attribute{
html.Attribute{
Key: "src",
Val: file,
},
}
case STYLE:
node.Data = "link"
node.Attr = []html.Attribute{
html.Attribute{
Key: "rel",
Val: "stylesheet",
},
html.Attribute{
Key: "href",
Val: file,
},
}
default:
panic("Type not understood")
}
parent.AppendChild(&node)
}
}
func isLocal(href string) bool {
parsed := must(url.Parse(href)).(*url.URL)
return parsed.Host == ""
}
func formatHref(path string) string {
if !strings.HasPrefix(path, "/") {
path = "/" + path
}
return path
}
func renderHTML(options Options, file HTMLFile) string {
handle := must(os.Open(file.File.LocalPath)).(*os.File)
defer handle.Close()
doc := must(html.Parse(handle)).(*html.Node)
var f func(*html.Node)
f = func(n *html.Node) {
for c := n.FirstChild; c != nil; c = c.NextSibling {
f(c)
}
if n.Type == html.ElementNode {
switch n.Data {
case "script":
for i, a := range n.Attr {
if a.Key == "src" {
for _, dep := range file.Deps {
if dep.InstPath == a.Val {
n.Attr[i].Val = formatHref(dep.File.UploadedPath)
break
}
}
}
}
case "link":
stylesheet := false
for _, a := range n.Attr {
if a.Key == "rel" {
stylesheet = a.Val == "stylesheet"
break
}
}
if !stylesheet {
return
}
for i, a := range n.Attr {
if a.Key == "href" {
for _, dep := range file.Deps {
if dep.InstPath == a.Val {
n.Attr[i].Val = formatHref(dep.File.UploadedPath)
break
}
}
}
}
}
}
}
f(doc)
buf := bytes.NewBuffer([]byte{})
panicIf(html.Render(buf, doc))
return buf.String()
}
func parseHTML(options Options, path string) (files []string, base string) {
files = make([]string, 0)
handle := must(os.Open(path)).(*os.File)
defer handle.Close()
doc := must(html.Parse(handle)).(*html.Node)
var f func(*html.Node)
f = func(n *html.Node) {
for c := n.FirstChild; c != nil; c = c.NextSibling {
f(c)
}
if n.Type == html.ElementNode {
switch n.Data {
case "base":
for _, a := range n.Attr {
if a.Key == "href" {
base = a.Val
}
}
case "script":
for _, a := range n.Attr {
if a.Key == "src" {
if isLocal(a.Val) {
files = append(files, a.Val)
}
}
}
case "link":
local := false
stylesheet := false
href := ""
for _, a := range n.Attr {
switch a.Key {
case "href":
local = isLocal(a.Val)
href = a.Val
case "rel":
stylesheet = a.Val == "stylesheet"
}
}
if local && stylesheet {
files = append(files, href)
}
}
}
}
f(doc)
return
}
func deployHTML(options Options, id string, file HTMLFile) {
data := renderHTML(options, file)
internalPath, err := filepath.Rel(options.Root, file.File.LocalPath)
if err != nil {
panic(err)
}
permPath := joinPath(options.Dest, id, internalPath)
curPath := joinPath(options.Dest, internalPath)
bucket := s3Session.Bucket(options.Bucket)
uploadFile(UploadFileRequest{
Bucket: bucket,
Reader: strings.NewReader(data),
Path: permPath,
IncludeHash: false,
CacheSeconds: FOREVER,
})
log.Println("Copying", permPath, "to", curPath)
copyFile(bucket, permPath, curPath, "text/html; charset=utf-8", LIMITED)
}
func expandFiles(root string, glob string) []string {
out := make([]string, 0)
cases := strings.Split(glob, ",")
for _, pattern := range cases {
if strings.HasPrefix(pattern, "-/") {
pattern = pattern[2:]
} else {
pattern = joinPath(root, pattern)
}
list := must(filepath.Glob(pattern)).([]string)
for _, file := range list {
info := must(os.Stat(file)).(os.FileInfo)
if info.IsDir() {
filepath.Walk(file, func(path string, info os.FileInfo, err error) error {
panicIf(err)
if !info.IsDir() {
out = append(out, path)
}
return nil
})
} else {
out = append(out, file)
}
}
}
return out
}
func listFiles(options Options) []*FileRef {
filePaths := expandFiles(options.Root, options.Files)
files := make([]*FileRef, len(filePaths))
for i, path := range filePaths {
remotePath := joinPath(options.Dest, mustString(filepath.Rel(options.Root, path)))
for strings.HasPrefix(remotePath, "../") {
remotePath = remotePath[3:]
}
files[i] = &FileRef{
LocalPath: path,
RemotePath: remotePath,
}
}
return files
}
func ignoreFiles(full []*FileRef, rem []*FileRef) []*FileRef {
out := make([]*FileRef, 0, len(full))
for _, file := range full {
ignore := false
path := filepath.Clean(file.LocalPath)
for _, remFile := range rem {
if filepath.Clean(remFile.LocalPath) == path {
ignore = true
break
}
}
if !ignore {
out = append(out, file)
}
}
return out
}
func extractFileList(options Options, pattern string) (files []string) {
files = make([]string, 0)
parts := strings.Split(pattern, ",")
for _, part := range parts {
matches, err := filepath.Glob(joinPath(options.Root, part))
if err != nil {
panic(err)
}
if matches == nil {
panic(fmt.Sprintf("Pattern %s did not match any files", part))
}
files = append(files, matches...)
}
return files
}
func filesWithExtension(files []*FileRef, ext string) (outFiles []*FileRef) {
outFiles = make([]*FileRef, 0)
for _, file := range files {
if filepath.Ext(file.LocalPath) == ext {
outFiles = append(outFiles, file)
}
}
return
}
type HTMLFile struct {
File FileRef
Deps []FileInst
Base string
}
func (f HTMLFile) GetLocalPath() string {
return f.File.LocalPath
}
func Deploy(options Options) {
if s3Session == nil {
s3Session = openS3(options.AWSKey, options.AWSSecret, options.AWSRegion, options.S3Host)
}
files := listFiles(options)
htmlFileRefs := filesWithExtension(files, ".html")
var htmlFiles []HTMLFile
var id string
if len(htmlFileRefs) == 0 {
log.Println("No HTML files found")
} else {
inclFiles := make(map[string]*FileRef)
htmlFiles = make([]HTMLFile, len(htmlFileRefs))
for i, file := range htmlFileRefs {
dir := filepath.Dir(file.LocalPath)
rel, err := filepath.Rel(options.Root, dir)
if err != nil {
panic(err)
}
paths, base := parseHTML(options, file.LocalPath)
if strings.HasPrefix(strings.ToLower(base), "http") || strings.HasPrefix(base, "//") {
panic("Absolute base tags are not supported")
}
if strings.HasSuffix(base, "/") {
base = base[:len(base)-1]
}
htmlFiles[i] = HTMLFile{
File: *file,
Deps: make([]FileInst, len(paths)),
Base: base,
}
var dest string
if strings.HasPrefix(base, "/") && strings.HasPrefix(base, "/"+options.Dest) {
dest = base
} else {
dest = joinPath(options.Dest, base)
}
var root string
if strings.HasPrefix(base, "/") && strings.HasSuffix(options.Root, base) {
root = options.Root
} else {
root = joinPath(options.Root, base)
}
for j, path := range paths {
var local, remote string
if strings.HasPrefix(path, "/") {
local = joinPath(options.Root, path)
remote = joinPath(options.Dest, path)
} else {
if strings.HasPrefix(base, "/") {
local = joinPath(root, path)
remote = joinPath(dest, path)
} else {
local = joinPath(options.Root, rel, base, path)
remote = joinPath(options.Dest, rel, base, path)
}
}
for strings.HasPrefix(remote, "../") {
remote = remote[3:]
}
ref, ok := inclFiles[local]
if !ok {
ref = &FileRef{
LocalPath: local,
RemotePath: remote,
// Filled in after the deploy:
UploadedPath: "",
}
inclFiles[local] = ref
}
use := FileInst{
File: ref,
InstPath: path,
}
htmlFiles[i].Deps[j] = use
}
}
inclFileList := make([]*FileRef, len(inclFiles))
i := 0
for _, ref := range inclFiles {
inclFileList[i] = ref
i++
}
hashPaths := make([]string, 0)
for _, item := range inclFileList {
hashPaths = append(hashPaths, item.LocalPath)
}
for _, item := range htmlFiles {
hashPaths = append(hashPaths, item.File.LocalPath)
}
hash := hashFiles(hashPaths)
id = hash[:12]
deployFiles(options, true, inclFileList)
}
deployFiles(options, false, ignoreFiles(files, htmlFileRefs))
if len(htmlFileRefs) != 0 {
// Ensure that the new files exist in s3
// Time based on "Eventual Consistency: How soon is eventual?"
time.Sleep(1500 * time.Millisecond)
wg := sync.WaitGroup{}
for _, file := range htmlFiles {
wg.Add(1)
go func(file HTMLFile) {
defer wg.Done()
deployHTML(options, id, file)
}(file)
}
wg.Wait()
}
visId := id
if id == "" {
visId = "0 HTML Files"
}
color.Printf(`
+------------------------------------+
| @{g}Deploy Successful!@{|} |
| |
| Deploy ID: @{?}%s@{|} |
+------------------------------------+
`, visId)
}
func deployCmd() {
options, _ := parseOptions()
loadConfigFile(&options)
addAWSConfig(&options)
if options.Bucket == "" {
panic("You must specify a bucket")
}
if options.AWSKey == "" || options.AWSSecret == "" {
panic("You must specify your AWS credentials")
}
Deploy(options)
}
================================================
FILE: src/rollback.go
================================================
package main
import (
"fmt"
"log"
"path/filepath"
"sync"
"github.com/zackbloom/goamz/s3"
)
func Rollback(options Options, version string) {
if s3Session == nil {
s3Session = openS3(options.AWSKey, options.AWSSecret, options.AWSRegion, options.S3Host)
}
bucket := s3Session.Bucket(options.Bucket)
// List files with the correct prefix in bucket
// Remove their prefix with a copy.
prefix := filepath.Join(options.Dest, version) + "/"
list, err := bucket.List(prefix, "", "", 1000)
panicIf(err)
if list.IsTruncated {
panic(fmt.Sprintf("More than %d HTML files in version, rollback is not supported. Consider filing a GitHub issue if you need support for this.", list.MaxKeys))
}
if len(list.Contents) == 0 {
log.Printf("A deploy with the provided id (%s) was not found in the specified bucket", version)
return
}
wg := sync.WaitGroup{}
count := 0
for _, file := range list.Contents {
wg.Add(1)
go func(file s3.Key) {
defer wg.Done()
path := file.Key
if filepath.Ext(path) != ".html" {
log.Printf("Skipping non-html file %s", path)
return
}
newPath := filepath.Join(options.Dest, path[len(prefix):])
log.Printf("Aliasing %s to %s", path, newPath)
copyFile(bucket, path, newPath, "text/html", LIMITED)
count++
}(file)
}
wg.Wait()
log.Printf("Reverted %d HTML files to version %s", count, version)
}
func rollbackCmd() {
options, set := parseOptions()
version := set.Arg(0)
loadConfigFile(&options)
addAWSConfig(&options)
if options.Bucket == "" {
panic("You must specify a bucket")
}
if options.AWSKey == "" || options.AWSSecret == "" {
panic("You must specify your AWS credentials")
}
if version == "" {
panic("You must specify a version to rollback to")
}
Rollback(options, version)
}
================================================
FILE: src/utils.go
================================================
package main
import (
"flag"
"fmt"
"io/ioutil"
"log"
"os"
"path/filepath"
"regexp"
"strings"
"github.com/imdario/mergo"
homedir "github.com/mitchellh/go-homedir"
ini "github.com/sspencer/go-ini"
"github.com/zackbloom/goamz/aws"
"github.com/zackbloom/goamz/cloudfront"
"github.com/zackbloom/goamz/iam"
"github.com/zackbloom/goamz/route53"
"github.com/zackbloom/goamz/s3"
"gopkg.in/yaml.v1"
)
const (
LIMITED = 60
FOREVER = 31556926
)
var s3Session *s3.S3
var iamSession *iam.IAM
var r53Session *route53.Route53
var cfSession *cloudfront.CloudFront
func getRegion(region string, s3Host string) aws.Region {
regionS, ok := aws.Regions[region]
if !ok {
panic("Region not found")
}
log.Println("HOST", s3Host)
if s3Host != "" {
regionS.S3Endpoint = "https://" + s3Host
regionS.S3BucketEndpoint = "https://${bucket}." + s3Host
}
return regionS
}
func openS3(key, secret, region, s3Host string) *s3.S3 {
regionS := getRegion(region, s3Host)
auth := aws.Auth{
AccessKey: key,
SecretKey: secret,
}
return s3.New(auth, regionS)
}
func openIAM(key, secret, region string) *iam.IAM {
regionS := getRegion(region, "")
auth := aws.Auth{
AccessKey: key,
SecretKey: secret,
}
return iam.New(auth, regionS)
}
func openCloudFront(key, secret string) *cloudfront.CloudFront {
auth := aws.Auth{
AccessKey: key,
SecretKey: secret,
}
return cloudfront.NewCloudFront(auth)
}
func openRoute53(key, secret string) *route53.Route53 {
auth := aws.Auth{
AccessKey: key,
SecretKey: secret,
}
r53, _ := route53.NewRoute53(auth)
return r53
}
func panicIf(err error) {
if err != nil {
panic(err)
}
}
func must(val interface{}, err error) interface{} {
if err != nil {
panic(err)
}
return val
}
func mustString(val string, err error) string {
panicIf(err)
return val
}
func mustInt(val int, err error) int {
panicIf(err)
return val
}
type Options struct {
Files string `yaml:"files"`
Root string `yaml:"root"`
Dest string `yaml:"dest"`
ConfigFile string `yaml:"-"`
Env string `yaml:"-"`
Bucket string `yaml:"bucket"`
AWSKey string `yaml:"key"`
AWSSecret string `yaml:"secret"`
AWSRegion string `yaml:"region"`
S3Host string `yaml:"s3Host"`
NoUser bool `yaml:"-"`
}
func parseOptions() (o Options, set *flag.FlagSet) {
set = flag.NewFlagSet(os.Args[1], flag.ExitOnError)
//TODO: Set set.Usage
set.StringVar(&o.Files, "files", "*", "Comma-seperated glob patterns of files to deploy (within root)")
set.StringVar(&o.Root, "root", "./", "The local directory to deploy")
set.StringVar(&o.Dest, "dest", "./", "The destination directory to write files to in the S3 bucket")
set.StringVar(&o.ConfigFile, "config", "", "A yaml file to read configuration from")
set.StringVar(&o.Env, "env", "", "The env to read from the config file")
set.StringVar(&o.Bucket, "bucket", "", "The bucket to deploy to")
set.StringVar(&o.AWSKey, "key", "", "The AWS key to use")
set.StringVar(&o.AWSSecret, "secret", "", "The AWS secret of the provided key")
set.StringVar(&o.AWSRegion, "region", "us-east-1", "The AWS region the S3 bucket is in")
set.StringVar(&o.S3Host, "s3-host", "s3.amazonaws.com", "The hostname of an S3 implementation, overrides region")
set.BoolVar(&o.NoUser, "no-user", false, "When creating, should we make a user account?")
set.Parse(os.Args[2:])
return
}
type ConfigFile map[string]Options
func loadConfigFile(o *Options) {
isDefault := false
configPath := o.ConfigFile
if o.ConfigFile == "" {
isDefault = true
configPath = "./deploy.yaml"
}
data, err := ioutil.ReadFile(configPath)
if err != nil {
if os.IsNotExist(err) && isDefault {
return
}
panic(err)
}
var file ConfigFile
err = yaml.Unmarshal(data, &file)
panicIf(err)
var envCfg Options
if o.Env != "" {
var ok bool
envCfg, ok = file[o.Env]
if !ok {
panic("Config for specified env not found")
}
}
defCfg, _ := file["default"]
panicIf(mergo.MergeWithOverwrite(o, defCfg))
panicIf(mergo.MergeWithOverwrite(o, envCfg))
}
func addAWSConfig(o *Options) {
if o.AWSKey == "" && o.AWSSecret == "" {
o.AWSKey, o.AWSSecret = loadAWSConfig()
}
}
type AWSConfig struct {
Default struct {
AccessKey string `ini:"aws_access_key_id"`
SecretKey string `ini:"aws_secret_access_key"`
} `ini:"[default]"`
}
func loadAWSConfig() (access string, secret string) {
cfg := AWSConfig{}
for _, file := range []string{"~/.aws/config", "~/.aws/credentials"} {
path, err := homedir.Expand(file)
if err != nil {
continue
}
content, err := ioutil.ReadFile(path)
if err != nil {
continue
}
ini.Unmarshal(content, &cfg)
if cfg.Default.AccessKey != "" {
break
}
}
return cfg.Default.AccessKey, cfg.Default.SecretKey
}
func copyFile(bucket *s3.Bucket, from string, to string, contentType string, maxAge int) {
copyOpts := s3.CopyOptions{
MetadataDirective: "REPLACE",
ContentType: contentType,
Options: s3.Options{
CacheControl: fmt.Sprintf("public, max-age=%d", maxAge),
ContentEncoding: "gzip",
},
}
_, err := bucket.PutCopy(to, s3.PublicRead, copyOpts, joinPath(bucket.Name, from))
if err != nil {
panic(err)
}
}
var pathRe = regexp.MustCompile("/{2,}")
func joinPath(parts ...string) string {
// Like filepath.Join, but always uses '/'
out := filepath.Join(parts...)
if os.PathSeparator != '/' {
out = strings.Replace(out, string(os.PathSeparator), "/", -1)
}
return out
}
================================================
FILE: utils/build.sh
================================================
GOOS=linux GOARCH=amd64 go build -o stout-linux src/*
GOOS=darwin GOARCH=amd64 go build -o stout-osx src/*
GOOS=windows GOARCH=amd64 go build -o stout-windows.exe src/*
================================================
FILE: utils/create_site.sh
================================================
#set -e
export HOST=$1
export DEPLOY_USER=${HOST}_deploy
aws s3 mb s3://$HOST --region us-east-1
aws s3 website s3://$HOST --index-document index.html --error-document error.html
aws s3api put-bucket-policy --bucket $HOST --policy "{
\"Version\": \"2008-10-17\",
\"Statement\": [
{
\"Sid\": \"PublicReadForGetBucketObjects\",
\"Effect\": \"Allow\",
\"Principal\": {
\"AWS\": \"*\"
},
\"Action\": \"s3:GetObject\",
\"Resource\": \"arn:aws:s3:::$HOST/*\"
}
]
}"
export CALLER=`date +"%T"`
aws cloudfront create-distribution --distribution-config "
{
\"CallerReference\": \"$CALLER\",
\"Comment\": null,
\"CacheBehaviors\": {
\"Quantity\": 0
},
\"Logging\": {
\"Bucket\": null,
\"Prefix\": null,
\"Enabled\": false,
\"IncludeCookies\": false
},
\"Origins\": {
\"Items\": [
{
\"S3OriginConfig\": {
\"OriginAccessIdentity\": null
},
\"Id\": \"S3-$HOST\",
\"DomainName\": \"$HOST.s3.amazonaws.com\"
}
],
\"Quantity\": 1
},
\"DefaultRootObject\": \"index.html\",
\"PriceClass\": \"PriceClass_All\",
\"Enabled\": true,
\"DefaultCacheBehavior\": {
\"TrustedSigners\": {
\"Enabled\": false,
\"Quantity\": 0
},
\"TargetOriginId\": \"S3-$HOST\",
\"ViewerProtocolPolicy\": \"allow-all\",
\"ForwardedValues\": {
\"Cookies\": {
\"Forward\": \"none\"
},
\"QueryString\": false
},
\"AllowedMethods\": {
\"Items\": [
\"GET\",
\"HEAD\"
],
\"Quantity\": 2
},
\"MinTTL\": 0
},
\"ViewerCertificate\": {
\"CloudFrontDefaultCertificate\": true
},
\"CustomErrorResponses\": {
\"Quantity\": 0
},
\"Restrictions\": {
\"GeoRestriction\": {
\"RestrictionType\": \"none\",
\"Quantity\": 0
}
},
\"Aliases\": {
\"Items\": [
\"$HOST\"
],
\"Quantity\": 1
}
}"
aws iam create-user --user-name $DEPLOY_USER
aws iam put-user-policy --user-name $DEPLOY_USER --policy-name $DEPLOY_USER --policy-document "{
\"Version\": \"2012-10-17\",
\"Statement\": [
{
\"Effect\": \"Allow\",
\"Action\": [
\"s3:DeleteObject\",
\"s3:ListBucket\",
\"s3:PutObject\",
\"s3:PutObjectAcl\",
\"s3:GetObject\"
],
\"Resource\": [
\"arn:aws:s3:::$HOST\", \"arn:aws:s3:::$HOST/*\"
]
}
]
}"
aws iam create-access-key --user-name $DEPLOY_USER | cat
echo "Select a SSL Cert in CloudFront if applicable"
echo "Site set up. You must now manually add the cloudfront distribution to your DNS configuration."
================================================
FILE: utils/release.sh
================================================
set -e
# Install jq with brew install jq
RELEASE=$1
git tag $RELEASE
git push origin master --tags
UPLOAD_URL=$(curl -X POST "https://api.github.com/repos/EagerIO/Stout/releases" \
-H "Accept: application/vnd.github.v3+json" \
-H "Authorization: token $GITHUB_AUTH" \
-H "Content-Type: application/json" \
-d "
{
\"tag_name\": \"$RELEASE\"
}" | jq -r '.upload_url' | cut -d { -f 1)
mkdir -p debian
echo "
Package: stout
Source: stout
Version: $RELEASE
Architecture: all
Maintainer: Zack Bloom <zack@eager.io>
Description: The reliable static website deploy tool
" > `dirname $0`/../control
`dirname $0`/xc.sh
upload () {
local archive=$1
local filename=$(basename "$archive")
local extension="${filename##*.}"
if [ "$extension" == "md" ]; then
return
fi
curl -X POST "$UPLOAD_URL?name=$filename" \
-H "Content-Type: application/octet-stream" \
-H "Authorization: token $GITHUB_AUTH" \
--data-binary @$archive
}
for f in builds/snapshot/*; do upload "$f" & done
wait
================================================
FILE: utils/xc.sh
================================================
goxc -tasks-=downloads-page -d=./builds
================================================
FILE: vendor/github.com/cenk/backoff/.gitignore
================================================
# Compiled Object files, Static and Dynamic libs (Shared Objects)
*.o
*.a
*.so
# Folders
_obj
_test
# Architecture specific extensions/prefixes
*.[568vq]
[568vq].out
*.cgo1.go
*.cgo2.c
_cgo_defun.c
_cgo_gotypes.go
_cgo_export.*
_testmain.go
*.exe
================================================
FILE: vendor/github.com/cenk/backoff/.travis.yml
================================================
language: go
go:
- 1.3.3
- tip
before_install:
- go get github.com/mattn/goveralls
- go get golang.org/x/tools/cmd/cover
script:
- $HOME/gopath/bin/goveralls -service=travis-ci
================================================
FILE: vendor/github.com/cenk/backoff/LICENSE
================================================
The MIT License (MIT)
Copyright (c) 2014 Cenk Altı
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
================================================
FILE: vendor/github.com/cenk/backoff/README.md
================================================
# Exponential Backoff [![GoDoc][godoc image]][godoc] [![Build Status][travis image]][travis] [![Coverage Status][coveralls image]][coveralls]
This is a Go port of the exponential backoff algorithm from [Google's HTTP Client Library for Java][google-http-java-client].
[Exponential backoff][exponential backoff wiki]
is an algorithm that uses feedback to multiplicatively decrease the rate of some process,
in order to gradually find an acceptable rate.
The retries exponentially increase and stop increasing when a certain threshold is met.
## How To
We define two functions, `Retry()` and `RetryNotify()`.
They receive an `Operation` to execute, a `BackOff` algorithm,
and an optional `Notify` error handler.
The operation will be executed, and will be retried on failure with delay
as given by the backoff algorithm. The backoff algorithm can also decide when to stop
retrying.
In addition, the notify error handler will be called after each failed attempt,
except for the last time, whose error should be handled by the caller.
```go
// An Operation is executing by Retry() or RetryNotify().
// The operation will be retried using a backoff policy if it returns an error.
type Operation func() error
// Notify is a notify-on-error function. It receives an operation error and
// backoff delay if the operation failed (with an error).
//
// NOTE that if the backoff policy stated to stop retrying,
// the notify function isn't called.
type Notify func(error, time.Duration)
func Retry(Operation, BackOff) error
func RetryNotify(Operation, BackOff, Notify)
```
## Examples
### Retry
Simple retry helper that uses the default exponential backoff algorithm:
```go
operation := func() error {
// An operation that might fail.
return nil // or return errors.New("some error")
}
err := Retry(operation, NewExponentialBackOff())
if err != nil {
// Handle error.
return err
}
// Operation is successful.
return nil
```
### Ticker
Ticker is for using backoff algorithms with channels.
```go
operation := func() error {
// An operation that might fail
return nil // or return errors.New("some error")
}
b := NewExponentialBackOff()
ticker := NewTicker(b)
var err error
// Ticks will continue to arrive when the previous operation is still running,
// so operations that take a while to fail could run in quick succession.
for range ticker.C {
if err = operation(); err != nil {
log.Println(err, "will retry...")
continue
}
ticker.Stop()
break
}
if err != nil {
// Operation has failed.
return err
}
// Operation is successful.
return nil
```
## Getting Started
```bash
# install
$ go get github.com/cenk/backoff
# test
$ cd $GOPATH/src/github.com/cenk/backoff
$ go get -t ./...
$ go test -v -cover
```
[godoc]: https://godoc.org/github.com/cenk/backoff
[godoc image]: https://godoc.org/github.com/cenk/backoff?status.png
[travis]: https://travis-ci.org/cenk/backoff
[travis image]: https://travis-ci.org/cenk/backoff.png?branch=master
[coveralls]: https://coveralls.io/github/cenk/backoff?branch=master
[coveralls image]: https://coveralls.io/repos/github/cenk/backoff/badge.svg?branch=master
[google-http-java-client]: https://github.com/google/google-http-java-client
[exponential backoff wiki]: http://en.wikipedia.org/wiki/Exponential_backoff
[advanced example]: https://godoc.org/github.com/cenk/backoff#example_
================================================
FILE: vendor/github.com/cenk/backoff/backoff.go
================================================
// Package backoff implements backoff algorithms for retrying operations.
//
// Also has a Retry() helper for retrying operations that may fail.
package backoff
import "time"
// BackOff is a backoff policy for retrying an operation.
type BackOff interface {
// NextBackOff returns the duration to wait before retrying the operation,
// or backoff.Stop to indicate that no more retries should be made.
//
// Example usage:
//
// duration := backoff.NextBackOff();
// if (duration == backoff.Stop) {
// // Do not retry operation.
// } else {
// // Sleep for duration and retry operation.
// }
//
NextBackOff() time.Duration
// Reset to initial state.
Reset()
}
// Indicates that no more retries should be made for use in NextBackOff().
const Stop time.Duration = -1
// ZeroBackOff is a fixed backoff policy whose backoff time is always zero,
// meaning that the operation is retried immediately without waiting, indefinitely.
type ZeroBackOff struct{}
func (b *ZeroBackOff) Reset() {}
func (b *ZeroBackOff) NextBackOff() time.Duration { return 0 }
// StopBackOff is a fixed backoff policy that always returns backoff.Stop for
// NextBackOff(), meaning that the operation should never be retried.
type StopBackOff struct{}
func (b *StopBackOff) Reset() {}
func (b *StopBackOff) NextBackOff() time.Duration { return Stop }
// ConstantBackOff is a backoff policy that always returns the same backoff delay.
// This is in contrast to an exponential backoff policy,
// which returns a delay that grows longer as you call NextBackOff() over and over again.
type ConstantBackOff struct {
Interval time.Duration
}
func (b *ConstantBackOff) Reset() {}
func (b *ConstantBackOff) NextBackOff() time.Duration { return b.Interval }
func NewConstantBackOff(d time.Duration) *ConstantBackOff {
return &ConstantBackOff{Interval: d}
}
================================================
FILE: vendor/github.com/cenk/backoff/exponential.go
================================================
package backoff
import (
"math/rand"
"time"
)
/*
ExponentialBackOff is a backoff implementation that increases the backoff
period for each retry attempt using a randomization function that grows exponentially.
NextBackOff() is calculated using the following formula:
randomized interval =
RetryInterval * (random value in range [1 - RandomizationFactor, 1 + RandomizationFactor])
In other words NextBackOff() will range between the randomization factor
percentage below and above the retry interval.
For example, given the following parameters:
RetryInterval = 2
RandomizationFactor = 0.5
Multiplier = 2
the actual backoff period used in the next retry attempt will range between 1 and 3 seconds,
multiplied by the exponential, that is, between 2 and 6 seconds.
Note: MaxInterval caps the RetryInterval and not the randomized interval.
If the time elapsed since an ExponentialBackOff instance is created goes past the
MaxElapsedTime, then the method NextBackOff() starts returning backoff.Stop.
The elapsed time can be reset by calling Reset().
Example: Given the following default arguments, for 10 tries the sequence will be,
and assuming we go over the MaxElapsedTime on the 10th try:
Request # RetryInterval (seconds) Randomized Interval (seconds)
1 0.5 [0.25, 0.75]
2 0.75 [0.375, 1.125]
3 1.125 [0.562, 1.687]
4 1.687 [0.8435, 2.53]
5 2.53 [1.265, 3.795]
6 3.795 [1.897, 5.692]
7 5.692 [2.846, 8.538]
8 8.538 [4.269, 12.807]
9 12.807 [6.403, 19.210]
10 19.210 backoff.Stop
Note: Implementation is not thread-safe.
*/
type ExponentialBackOff struct {
InitialInterval time.Duration
RandomizationFactor float64
Multiplier float64
MaxInterval time.Duration
// After MaxElapsedTime the ExponentialBackOff stops.
// It never stops if MaxElapsedTime == 0.
MaxElapsedTime time.Duration
Clock Clock
currentInterval time.Duration
startTime time.Time
}
// Clock is an interface that returns current time for BackOff.
type Clock interface {
Now() time.Time
}
// Default values for ExponentialBackOff.
const (
DefaultInitialInterval = 500 * time.Millisecond
DefaultRandomizationFactor = 0.5
DefaultMultiplier = 1.5
DefaultMaxInterval = 60 * time.Second
DefaultMaxElapsedTime = 15 * time.Minute
)
// NewExponentialBackOff creates an instance of ExponentialBackOff using default values.
func NewExponentialBackOff() *ExponentialBackOff {
b := &ExponentialBackOff{
InitialInterval: DefaultInitialInterval,
RandomizationFactor: DefaultRandomizationFactor,
Multiplier: DefaultMultiplier,
MaxInterval: DefaultMaxInterval,
MaxElapsedTime: DefaultMaxElapsedTime,
Clock: SystemClock,
}
if b.RandomizationFactor < 0 {
b.RandomizationFactor = 0
} else if b.RandomizationFactor > 1 {
b.RandomizationFactor = 1
}
b.Reset()
return b
}
type systemClock struct{}
func (t systemClock) Now() time.Time {
return time.Now()
}
// SystemClock implements Clock interface that uses time.Now().
var SystemClock = systemClock{}
// Reset the interval back to the initial retry interval and restarts the timer.
func (b *ExponentialBackOff) Reset() {
b.currentInterval = b.InitialInterval
b.startTime = b.Clock.Now()
}
// NextBackOff calculates the next backoff interval using the formula:
// Randomized interval = RetryInterval +/- (RandomizationFactor * RetryInterval)
func (b *ExponentialBackOff) NextBackOff() time.Duration {
// Make sure we have not gone over the maximum elapsed time.
if b.MaxElapsedTime != 0 && b.GetElapsedTime() > b.MaxElapsedTime {
return Stop
}
defer b.incrementCurrentInterval()
return getRandomValueFromInterval(b.RandomizationFactor, rand.Float64(), b.currentInterval)
}
// GetElapsedTime returns the elapsed time since an ExponentialBackOff instance
// is created and is reset when Reset() is called.
//
// The elapsed time is computed using time.Now().UnixNano().
func (b *ExponentialBackOff) GetElapsedTime() time.Duration {
return b.Clock.Now().Sub(b.startTime)
}
// Increments the current interval by multiplying it with the multiplier.
func (b *ExponentialBackOff) incrementCurrentInterval() {
// Check for overflow, if overflow is detected set the current interval to the max interval.
if float64(b.currentInterval) >= float64(b.MaxInterval)/b.Multiplier {
b.currentInterval = b.MaxInterval
} else {
b.currentInterval = time.Duration(float64(b.currentInterval) * b.Multiplier)
}
}
// Returns a random value from the following interval:
// [randomizationFactor * currentInterval, randomizationFactor * currentInterval].
func getRandomValueFromInterval(randomizationFactor, random float64, currentInterval time.Duration) time.Duration {
var delta = randomizationFactor * float64(currentInterval)
var minInterval = float64(currentInterval) - delta
var maxInterval = float64(currentInterval) + delta
// Get a random value from the range [minInterval, maxInterval].
// The formula used below has a +1 because if the minInterval is 1 and the maxInterval is 3 then
// we want a 33% chance for selecting either 1, 2 or 3.
return time.Duration(minInterval + (random * (maxInterval - minInterval + 1)))
}
================================================
FILE: vendor/github.com/cenk/backoff/retry.go
================================================
package backoff
import "time"
// An Operation is executing by Retry() or RetryNotify().
// The operation will be retried using a backoff policy if it returns an error.
type Operation func() error
// Notify is a notify-on-error function. It receives an operation error and
// backoff delay if the operation failed (with an error).
//
// NOTE that if the backoff policy stated to stop retrying,
// the notify function isn't called.
type Notify func(error, time.Duration)
// Retry the operation o until it does not return error or BackOff stops.
// o is guaranteed to be run at least once.
// It is the caller's responsibility to reset b after Retry returns.
//
// Retry sleeps the goroutine for the duration returned by BackOff after a
// failed operation returns.
func Retry(o Operation, b BackOff) error { return RetryNotify(o, b, nil) }
// RetryNotify calls notify function with the error and wait duration
// for each failed attempt before sleep.
func RetryNotify(operation Operation, b BackOff, notify Notify) error {
var err error
var next time.Duration
b.Reset()
for {
if err = operation(); err == nil {
return nil
}
if next = b.NextBackOff(); next == Stop {
return err
}
if notify != nil {
notify(err, next)
}
time.Sleep(next)
}
}
================================================
FILE: vendor/github.com/cenk/backoff/ticker.go
================================================
package backoff
import (
"runtime"
"sync"
"time"
)
// Ticker holds a channel that delivers `ticks' of a clock at times reported by a BackOff.
//
// Ticks will continue to arrive when the previous operation is still running,
// so operations that take a while to fail could run in quick succession.
type Ticker struct {
C <-chan time.Time
c chan time.Time
b BackOff
stop chan struct{}
stopOnce sync.Once
}
// NewTicker returns a new Ticker containing a channel that will send the time at times
// specified by the BackOff argument. Ticker is guaranteed to tick at least once.
// The channel is closed when Stop method is called or BackOff stops.
func NewTicker(b BackOff) *Ticker {
c := make(chan time.Time)
t := &Ticker{
C: c,
c: c,
b: b,
stop: make(chan struct{}),
}
go t.run()
runtime.SetFinalizer(t, (*Ticker).Stop)
return t
}
// Stop turns off a ticker. After Stop, no more ticks will be sent.
func (t *Ticker) Stop() {
t.stopOnce.Do(func() { close(t.stop) })
}
func (t *Ticker) run() {
c := t.c
defer close(c)
t.b.Reset()
// Ticker is guaranteed to tick at least once.
afterC := t.send(time.Now())
for {
if afterC == nil {
return
}
select {
case tick := <-afterC:
afterC = t.send(tick)
case <-t.stop:
t.c = nil // Prevent future ticks from being sent to the channel.
return
}
}
}
func (t *Ticker) send(tick time.Time) <-chan time.Time {
select {
case t.c <- tick:
case <-t.stop:
return nil
}
next := t.b.NextBackOff()
if next == Stop {
t.Stop()
return nil
}
return time.After(next)
}
================================================
FILE: vendor/github.com/imdario/mergo/.travis.yml
================================================
language: go
install: go get -t
================================================
FILE: vendor/github.com/imdario/mergo/LICENSE
================================================
Copyright (c) 2013 Dario Castañé. All rights reserved.
Copyright (c) 2012 The Go Authors. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
================================================
FILE: vendor/github.com/imdario/mergo/README.md
================================================
# Mergo
A helper to merge structs and maps in Golang. Useful for configuration default values, avoiding messy if-statements.
Also a lovely [comune](http://en.wikipedia.org/wiki/Mergo) (municipality) in the Province of Ancona in the Italian region Marche.

## Status
It is ready for production use. It works fine after extensive use in the wild.
[![Build Status][1]][2]
[![GoDoc][3]][4]
[![GoCard][5]][6]
[1]: https://travis-ci.org/imdario/mergo.png
[2]: https://travis-ci.org/imdario/mergo
[3]: https://godoc.org/github.com/imdario/mergo?status.svg
[4]: https://godoc.org/github.com/imdario/mergo
[5]: https://goreportcard.com/badge/imdario/mergo
[6]: https://goreportcard.com/report/github.com/imdario/mergo
### Important note
Mergo is intended to assign **only** zero value fields on destination with source value. Since April 6th it works like this. Before it didn't work properly, causing some random overwrites. After some issues and PRs I found it didn't merge as I designed it. Thanks to [imdario/mergo#8](https://github.com/imdario/mergo/pull/8) overwriting functions were added and the wrong behavior was clearly detected.
If you were using Mergo **before** April 6th 2015, please check your project works as intended after updating your local copy with ```go get -u github.com/imdario/mergo```. I apologize for any issue caused by its previous behavior and any future bug that Mergo could cause (I hope it won't!) in existing projects after the change (release 0.2.0).
### Mergo in the wild
- [docker/docker](https://github.com/docker/docker/)
- [kubernetes/kubernetes](https://github.com/kubernetes/kubernetes)
- [imdario/zas](https://github.com/imdario/zas)
- [soniah/dnsmadeeasy](https://github.com/soniah/dnsmadeeasy)
- [EagerIO/Stout](https://github.com/EagerIO/Stout)
- [lynndylanhurley/defsynth-api](https://github.com/lynndylanhurley/defsynth-api)
- [russross/canvasassignments](https://github.com/russross/canvasassignments)
- [rdegges/cryptly-api](https://github.com/rdegges/cryptly-api)
- [casualjim/exeggutor](https://github.com/casualjim/exeggutor)
- [divshot/gitling](https://github.com/divshot/gitling)
- [RWJMurphy/gorl](https://github.com/RWJMurphy/gorl)
- [andrerocker/deploy42](https://github.com/andrerocker/deploy42)
- [elwinar/rambler](https://github.com/elwinar/rambler)
- [tmaiaroto/gopartman](https://github.com/tmaiaroto/gopartman)
- [jfbus/impressionist](https://github.com/jfbus/impressionist)
- [Jmeyering/zealot](https://github.com/Jmeyering/zealot)
- [godep-migrator/rigger-host](https://github.com/godep-migrator/rigger-host)
- [Dronevery/MultiwaySwitch-Go](https://github.com/Dronevery/MultiwaySwitch-Go)
- [thoas/picfit](https://github.com/thoas/picfit)
- [mantasmatelis/whooplist-server](https://github.com/mantasmatelis/whooplist-server)
- [jnuthong/item_search](https://github.com/jnuthong/item_search)
- [Iris Web Framework](https://github.com/kataras/iris)
## Installation
go get github.com/imdario/mergo
// use in your .go code
import (
"github.com/imdario/mergo"
)
## Usage
You can only merge same-type structs with exported fields initialized as zero value of their type and same-types maps. Mergo won't merge unexported (private) fields but will do recursively any exported one. Also maps will be merged recursively except for structs inside maps (because they are not addressable using Go reflection).
if err := mergo.Merge(&dst, src); err != nil {
// ...
}
Additionally, you can map a map[string]interface{} to a struct (and otherwise, from struct to map), following the same restrictions as in Merge(). Keys are capitalized to find each corresponding exported field.
if err := mergo.Map(&dst, srcMap); err != nil {
// ...
}
Warning: if you map a struct to map, it won't do it recursively. Don't expect Mergo to map struct members of your struct as map[string]interface{}. They will be just assigned as values.
More information and examples in [godoc documentation](http://godoc.org/github.com/imdario/mergo).
### Nice example
```go
package main
import (
"fmt"
"github.com/imdario/mergo"
)
type Foo struct {
A string
B int64
}
func main() {
src := Foo{
A: "one",
}
dest := Foo{
A: "two",
B: 2,
}
mergo.Merge(&dest, src)
fmt.Println(dest)
// Will print
// {two 2}
}
```
Note: if test are failing due missing package, please execute:
go get gopkg.in/yaml.v1
## Contact me
If I can help you, you have an idea or you are using Mergo in your projects, don't hesitate to drop me a line (or a pull request): [@im_dario](https://twitter.com/im_dario)
## About
Written by [Dario Castañé](http://dario.im).
## License
[BSD 3-Clause](http://opensource.org/licenses/BSD-3-Clause) license, as [Go language](http://golang.org/LICENSE).
================================================
FILE: vendor/github.com/imdario/mergo/doc.go
================================================
// Copyright 2013 Dario Castañé. All rights reserved.
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
/*
Package mergo merges same-type structs and maps by setting default values in zero-value fields.
Mergo won't merge unexported (private) fields but will do recursively any exported one. It also won't merge structs inside maps (because they are not addressable using Go reflection).
Usage
From my own work-in-progress project:
type networkConfig struct {
Protocol string
Address string
ServerType string `json: "server_type"`
Port uint16
}
type FssnConfig struct {
Network networkConfig
}
var fssnDefault = FssnConfig {
networkConfig {
"tcp",
"127.0.0.1",
"http",
31560,
},
}
// Inside a function [...]
if err := mergo.Merge(&config, fssnDefault); err != nil {
log.Fatal(err)
}
// More code [...]
*/
package mergo
================================================
FILE: vendor/github.com/imdario/mergo/map.go
================================================
// Copyright 2014 Dario Castañé. All rights reserved.
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Based on src/pkg/reflect/deepequal.go from official
// golang's stdlib.
package mergo
import (
"fmt"
"reflect"
"unicode"
"unicode/utf8"
)
func changeInitialCase(s string, mapper func(rune) rune) string {
if s == "" {
return s
}
r, n := utf8.DecodeRuneInString(s)
return string(mapper(r)) + s[n:]
}
func isExported(field reflect.StructField) bool {
r, _ := utf8.DecodeRuneInString(field.Name)
return r >= 'A' && r <= 'Z'
}
// Traverses recursively both values, assigning src's fields values to dst.
// The map argument tracks comparisons that have already been seen, which allows
// short circuiting on recursive types.
func deepMap(dst, src reflect.Value, visited map[uintptr]*visit, depth int, overwrite bool) (err error) {
if dst.CanAddr() {
addr := dst.UnsafeAddr()
h := 17 * addr
seen := visited[h]
typ := dst.Type()
for p := seen; p != nil; p = p.next {
if p.ptr == addr && p.typ == typ {
return nil
}
}
// Remember, remember...
visited[h] = &visit{addr, typ, seen}
}
zeroValue := reflect.Value{}
switch dst.Kind() {
case reflect.Map:
dstMap := dst.Interface().(map[string]interface{})
for i, n := 0, src.NumField(); i < n; i++ {
srcType := src.Type()
field := srcType.Field(i)
if !isExported(field) {
continue
}
fieldName := field.Name
fieldName = changeInitialCase(fieldName, unicode.ToLower)
if v, ok := dstMap[fieldName]; !ok || (isEmptyValue(reflect.ValueOf(v)) || overwrite) {
dstMap[fieldName] = src.Field(i).Interface()
}
}
case reflect.Struct:
srcMap := src.Interface().(map[string]interface{})
for key := range srcMap {
srcValue := srcMap[key]
fieldName := changeInitialCase(key, unicode.ToUpper)
dstElement := dst.FieldByName(fieldName)
if dstElement == zeroValue {
// We discard it because the field doesn't exist.
continue
}
srcElement := reflect.ValueOf(srcValue)
dstKind := dstElement.Kind()
srcKind := srcElement.Kind()
if srcKind == reflect.Ptr && dstKind != reflect.Ptr {
srcElement = srcElement.Elem()
srcKind = reflect.TypeOf(srcElement.Interface()).Kind()
} else if dstKind == reflect.Ptr {
// Can this work? I guess it can't.
if srcKind != reflect.Ptr && srcElement.CanAddr() {
srcPtr := srcElement.Addr()
srcElement = reflect.ValueOf(srcPtr)
srcKind = reflect.Ptr
}
}
if !srcElement.IsValid() {
continue
}
if srcKind == dstKind {
if err = deepMerge(dstElement, srcElement, visited, depth+1, overwrite); err != nil {
return
}
} else {
if srcKind == reflect.Map {
if err = deepMap(dstElement, srcElement, visited, depth+1, overwrite); err != nil {
return
}
} else {
return fmt.Errorf("type mismatch on %s field: found %v, expected %v", fieldName, srcKind, dstKind)
}
}
}
}
return
}
// Map sets fields' values in dst from src.
// src can be a map with string keys or a struct. dst must be the opposite:
// if src is a map, dst must be a valid pointer to struct. If src is a struct,
// dst must be map[string]interface{}.
// It won't merge unexported (private) fields and will do recursively
// any exported field.
// If dst is a map, keys will be src fields' names in lower camel case.
// Missing key in src that doesn't match a field in dst will be skipped. This
// doesn't apply if dst is a map.
// This is separated method from Merge because it is cleaner and it keeps sane
// semantics: merging equal types, mapping different (restricted) types.
func Map(dst, src interface{}) error {
return _map(dst, src, false)
}
// MapWithOverwrite will do the same as Map except that non-empty dst attributes will be overriden by
// non-empty src attribute values.
func MapWithOverwrite(dst, src interface{}) error {
return _map(dst, src, true)
}
func _map(dst, src interface{}, overwrite bool) error {
var (
vDst, vSrc reflect.Value
err error
)
if vDst, vSrc, err = resolveValues(dst, src); err != nil {
return err
}
// To be friction-less, we redirect equal-type arguments
// to deepMerge. Only because arguments can be anything.
if vSrc.Kind() == vDst.Kind() {
return deepMerge(vDst, vSrc, make(map[uintptr]*visit), 0, overwrite)
}
switch vSrc.Kind() {
case reflect.Struct:
if vDst.Kind() != reflect.Map {
return ErrExpectedMapAsDestination
}
case reflect.Map:
if vDst.Kind() != reflect.Struct {
return ErrExpectedStructAsDestination
}
default:
return ErrNotSupported
}
return deepMap(vDst, vSrc, make(map[uintptr]*visit), 0, overwrite)
}
================================================
FILE: vendor/github.com/imdario/mergo/merge.go
================================================
// Copyright 2013 Dario Castañé. All rights reserved.
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Based on src/pkg/reflect/deepequal.go from official
// golang's stdlib.
package mergo
import (
"reflect"
)
// Traverses recursively both values, assigning src's fields values to dst.
// The map argument tracks comparisons that have already been seen, which allows
// short circuiting on recursive types.
func deepMerge(dst, src reflect.Value, visited map[uintptr]*visit, depth int, overwrite bool) (err error) {
if !src.IsValid() {
return
}
if dst.CanAddr() {
addr := dst.UnsafeAddr()
h := 17 * addr
seen := visited[h]
typ := dst.Type()
for p := seen; p != nil; p = p.next {
if p.ptr == addr && p.typ == typ {
return nil
}
}
// Remember, remember...
visited[h] = &visit{addr, typ, seen}
}
switch dst.Kind() {
case reflect.Struct:
for i, n := 0, dst.NumField(); i < n; i++ {
if err = deepMerge(dst.Field(i), src.Field(i), visited, depth+1, overwrite); err != nil {
return
}
}
case reflect.Map:
for _, key := range src.MapKeys() {
srcElement := src.MapIndex(key)
if !srcElement.IsValid() {
continue
}
dstElement := dst.MapIndex(key)
switch srcElement.Kind() {
case reflect.Chan, reflect.Func, reflect.Map, reflect.Ptr, reflect.Interface, reflect.Slice:
if srcElement.IsNil() {
continue
}
fallthrough
default:
if !srcElement.CanInterface() {
continue
}
switch reflect.TypeOf(srcElement.Interface()).Kind() {
case reflect.Struct:
fallthrough
case reflect.Ptr:
fallthrough
case reflect.Map:
if err = deepMerge(dstElement, srcElement, visited, depth+1, overwrite); err != nil {
return
}
}
}
if !isEmptyValue(srcElement) && (overwrite || (!dstElement.IsValid() || isEmptyValue(dst))) {
if dst.IsNil() {
dst.Set(reflect.MakeMap(dst.Type()))
}
dst.SetMapIndex(key, srcElement)
}
}
case reflect.Ptr:
fallthrough
case reflect.Interface:
if src.IsNil() {
break
} else if dst.IsNil() || overwrite {
if dst.CanSet() && (overwrite || isEmptyValue(dst)) {
dst.Set(src)
}
} else if err = deepMerge(dst.Elem(), src.Elem(), visited, depth+1, overwrite); err != nil {
return
}
default:
if dst.CanSet() && !isEmptyValue(src) && (overwrite || isEmptyValue(dst)) {
dst.Set(src)
}
}
return
}
// Merge will fill any empty for value type attributes on the dst struct using corresponding
// src attributes if they themselves are not empty. dst and src must be valid same-type structs
// and dst must be a pointer to struct.
// It won't merge unexported (private) fields and will do recursively any exported field.
func Merge(dst, src interface{}) error {
return merge(dst, src, false)
}
// MergeWithOverwrite will do the same as Merge except that non-empty dst attributes will be overriden by
// non-empty src attribute values.
func MergeWithOverwrite(dst, src interface{}) error {
return merge(dst, src, true)
}
func merge(dst, src interface{}, overwrite bool) error {
var (
vDst, vSrc reflect.Value
err error
)
if vDst, vSrc, err = resolveValues(dst, src); err != nil {
return err
}
if vDst.Type() != vSrc.Type() {
return ErrDifferentArgumentsTypes
}
return deepMerge(vDst, vSrc, make(map[uintptr]*visit), 0, overwrite)
}
================================================
FILE: vendor/github.com/imdario/mergo/mergo.go
================================================
// Copyright 2013 Dario Castañé. All rights reserved.
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Based on src/pkg/reflect/deepequal.go from official
// golang's stdlib.
package mergo
import (
"errors"
"reflect"
)
// Errors reported by Mergo when it finds invalid arguments.
var (
ErrNilArguments = errors.New("src and dst must not be nil")
ErrDifferentArgumentsTypes = errors.New("src and dst must be of same type")
ErrNotSupported = errors.New("only structs and maps are supported")
ErrExpectedMapAsDestination = errors.New("dst was expected to be a map")
ErrExpectedStructAsDestination = errors.New("dst was expected to be a struct")
)
// During deepMerge, must keep track of checks that are
// in progress. The comparison algorithm assumes that all
// checks in progress are true when it reencounters them.
// Visited are stored in a map indexed by 17 * a1 + a2;
type visit struct {
ptr uintptr
typ reflect.Type
next *visit
}
// From src/pkg/encoding/json.
func isEmptyValue(v reflect.Value) bool {
switch v.Kind() {
case reflect.Array, reflect.Map, reflect.Slice, reflect.String:
return v.Len() == 0
case reflect.Bool:
return !v.Bool()
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return v.Int() == 0
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
return v.Uint() == 0
case reflect.Float32, reflect.Float64:
return v.Float() == 0
case reflect.Interface, reflect.Ptr:
return v.IsNil()
}
return false
}
func resolveValues(dst, src interface{}) (vDst, vSrc reflect.Value, err error) {
if dst == nil || src == nil {
err = ErrNilArguments
return
}
vDst = reflect.ValueOf(dst).Elem()
if vDst.Kind() != reflect.Struct && vDst.Kind() != reflect.Map {
err = ErrNotSupported
return
}
vSrc = reflect.ValueOf(src)
// We check if vSrc is a pointer to dereference it.
if vSrc.Kind() == reflect.Ptr {
vSrc = vSrc.Elem()
}
return
}
// Traverses recursively both values, assigning src's fields values to dst.
// The map argument tracks comparisons that have already been seen, which allows
// short circuiting on recursive types.
func deeper(dst, src reflect.Value, visited map[uintptr]*visit, depth int) (err error) {
if dst.CanAddr() {
addr := dst.UnsafeAddr()
h := 17 * addr
seen := visited[h]
typ := dst.Type()
for p := seen; p != nil; p = p.next {
if p.ptr == addr && p.typ == typ {
return nil
}
}
// Remember, remember...
visited[h] = &visit{addr, typ, seen}
}
return // TODO refactor
}
================================================
FILE: vendor/github.com/mitchellh/go-homedir/LICENSE
================================================
The MIT License (MIT)
Copyright (c) 2013 Mitchell Hashimoto
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
================================================
FILE: vendor/github.com/mitchellh/go-homedir/README.md
================================================
# go-homedir
This is a Go library for detecting the user's home directory without
the use of cgo, so the library can be used in cross-compilation environments.
Usage is incredibly simple, just call `homedir.Dir()` to get the home directory
for a user, and `homedir.Expand()` to expand the `~` in a path to the home
directory.
**Why not just use `os/user`?** The built-in `os/user` package requires
cgo on Darwin systems. This means that any Go code that uses that package
cannot cross compile. But 99% of the time the use for `os/user` is just to
retrieve the home directory, which we can do for the current user without
cgo. This library does that, enabling cross-compilation.
================================================
FILE: vendor/github.com/mitchellh/go-homedir/homedir.go
================================================
package homedir
import (
"bytes"
"errors"
"os"
"os/exec"
"path/filepath"
"runtime"
"strconv"
"strings"
"sync"
)
// DisableCache will disable caching of the home directory. Caching is enabled
// by default.
var DisableCache bool
var homedirCache string
var cacheLock sync.RWMutex
// Dir returns the home directory for the executing user.
//
// This uses an OS-specific method for discovering the home directory.
// An error is returned if a home directory cannot be detected.
func Dir() (string, error) {
if !DisableCache {
cacheLock.RLock()
cached := homedirCache
cacheLock.RUnlock()
if cached != "" {
return cached, nil
}
}
cacheLock.Lock()
defer cacheLock.Unlock()
var result string
var err error
if runtime.GOOS == "windows" {
result, err = dirWindows()
} else {
// Unix-like system, so just assume Unix
result, err = dirUnix()
}
if err != nil {
return "", err
}
homedirCache = result
return result, nil
}
// Expand expands the path to include the home directory if the path
// is prefixed with `~`. If it isn't prefixed with `~`, the path is
// returned as-is.
func Expand(path string) (string, error) {
if len(path) == 0 {
return path, nil
}
if path[0] != '~' {
return path, nil
}
if len(path) > 1 && path[1] != '/' && path[1] != '\\' {
return "", errors.New("cannot expand user-specific home dir")
}
dir, err := Dir()
if err != nil {
return "", err
}
return filepath.Join(dir, path[1:]), nil
}
func dirUnix() (string, error) {
// First prefer the HOME environmental variable
if home := os.Getenv("HOME"); home != "" {
return home, nil
}
// If that fails, try getent
var stdout bytes.Buffer
cmd := exec.Command("getent", "passwd", strconv.Itoa(os.Getuid()))
cmd.Stdout = &stdout
if err := cmd.Run(); err != nil {
// If "getent" is missing, ignore it
if err == exec.ErrNotFound {
return "", err
}
} else {
if passwd := strings.TrimSpace(stdout.String()); passwd != "" {
// username:password:uid:gid:gecos:home:shell
passwdParts := strings.SplitN(passwd, ":", 7)
if len(passwdParts) > 5 {
return passwdParts[5], nil
}
}
}
// If all else fails, try the shell
stdout.Reset()
cmd = exec.Command("sh", "-c", "cd && pwd")
cmd.Stdout = &stdout
if err := cmd.Run(); err != nil {
return "", err
}
result := strings.TrimSpace(stdout.String())
if result == "" {
return "", errors.New("blank output when reading home directory")
}
return result, nil
}
func dirWindows() (string, error) {
// First prefer the HOME environmental variable
if home := os.Getenv("HOME"); home != "" {
return home, nil
}
drive := os.Getenv("HOMEDRIVE")
path := os.Getenv("HOMEPATH")
home := drive + path
if drive == "" || path == "" {
home = os.Getenv("USERPROFILE")
}
if home == "" {
return "", errors.New("HOMEDRIVE, HOMEPATH, and USERPROFILE are blank")
}
return home, nil
}
================================================
FILE: vendor/github.com/wsxiaoys/terminal/LICENSE
================================================
Copyright (c) 2013 Meng Zhang. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
================================================
FILE: vendor/github.com/wsxiaoys/terminal/color/color.go
================================================
// The colors package provide a simple way to bring colorful characters to terminal interface.
//
// This example will output the text with a Blue foreground and a Black background
// color.Println("@{bK}Example Text")
//
// This one will output the text with a red foreground
// color.Println("@rExample Text")
//
// This one will escape the @
// color.Println("@@")
//
// Full color syntax code
// @{rgbcmykwRGBCMYKW} foreground/background color
// r/R: Red
// g/G: Green
// b/B: Blue
// c/C: Cyan
// m/M: Magenta
// y/Y: Yellow
// k/K: Black
// w/W: White
// @{|} Reset format style
// @{!./_} Bold / Dim / Italic / Underline
// @{^&} Blink / Fast blink
// @{*} High intensity foreground color
// @{?} Reverse the foreground and background color
// @{-} Hide the text
// Note some of the functions are not widely supported, like "Fast blink" and "Italic".
package color
import (
"bytes"
"errors"
"fmt"
"io"
"log"
)
const (
EscapeChar = '@' // Escape character for color syntax
ResetCode = "\033[0m" // Short for reset to default style
)
// Mapping from character to concrete escape code.
var codeMap = map[int]int{
'|': 0,
'!': 1,
'.': 2,
'/': 3,
'_': 4,
'^': 5,
'&': 6,
'?': 7,
'-': 8,
'*': 60,
'k': 30,
'r': 31,
'g': 32,
'y': 33,
'b': 34,
'm': 35,
'c': 36,
'w': 37,
'd': 39,
'K': 40,
'R': 41,
'G': 42,
'Y': 43,
'B': 44,
'M': 45,
'C': 46,
'W': 47,
'D': 49,
}
// Compile color syntax string like "rG" to escape code.
func Colorize(x string) string {
attr := 0
fg := 39
bg := 49
for _, key := range x {
c, ok := codeMap[int(key)]
switch {
case !ok:
log.Printf("Wrong color syntax: %c", key)
case 0 <= c && c <= 8:
attr = c
case 30 <= c && c <= 37:
fg = c
case 40 <= c && c <= 47:
bg = c
case c == 60:
fg += c
}
}
return fmt.Sprintf("\033[%d;%d;%dm", attr, fg, bg)
}
// Handle state after meeting one '@'
func compileColorSyntax(input, output *bytes.Buffer) {
i, _, err := input.ReadRune()
if err != nil {
// EOF got
log.Print("Parse failed on color syntax")
return
}
switch i {
default:
output.WriteString(Colorize(string(i)))
case '{':
color := bytes.NewBufferString("")
for {
i, _, err := input.ReadRune()
if err != nil {
log.Print("Parse failed on color syntax")
break
}
if i == '}' {
break
}
color.WriteRune(i)
}
output.WriteString(Colorize(color.String()))
case EscapeChar:
output.WriteRune(EscapeChar)
}
}
// Compile the string and replace color syntax with concrete escape code.
func compile(x string) string {
if x == "" {
return ""
}
input := bytes.NewBufferString(x)
output := bytes.NewBufferString("")
for {
i, _, err := input.ReadRune()
if err != nil {
break
}
switch i {
default:
output.WriteRune(i)
case EscapeChar:
compileColorSyntax(input, output)
}
}
return output.String()
}
// Compile multiple values, only do compiling on string type.
func compileValues(a *[]interface{}) {
for i, x := range *a {
if str, ok := x.(string); ok {
(*a)[i] = compile(str)
}
}
}
// Similar to fmt.Print, will reset the color at the end.
func Print(a ...interface{}) (int, error) {
a = append(a, ResetCode)
compileValues(&a)
return fmt.Print(a...)
}
// Similar to fmt.Println, will reset the color at the end.
func Println(a ...interface{}) (int, error) {
a = append(a, ResetCode)
compileValues(&a)
return fmt.Println(a...)
}
// Similar to fmt.Printf, will reset the color at the end.
func Printf(format string, a ...interface{}) (int, error) {
format += ResetCode
format = compile(format)
return fmt.Printf(format, a...)
}
// Similar to fmt.Fprint, will reset the color at the end.
func Fprint(w io.Writer, a ...interface{}) (int, error) {
a = append(a, ResetCode)
compileValues(&a)
return fmt.Fprint(w, a...)
}
// Similar to fmt.Fprintln, will reset the color at the end.
func Fprintln(w io.Writer, a ...interface{}) (int, error) {
a = append(a, ResetCode)
compileValues(&a)
return fmt.Fprintln(w, a...)
}
// Similar to fmt.Fprintf, will reset the color at the end.
func Fprintf(w io.Writer, format string, a ...interface{}) (int, error) {
format += ResetCode
format = compile(format)
return fmt.Fprintf(w, format, a...)
}
// Similar to fmt.Sprint, will reset the color at the end.
func Sprint(a ...interface{}) string {
a = append(a, ResetCode)
compileValues(&a)
return fmt.Sprint(a...)
}
// Similar to fmt.Sprintf, will reset the color at the end.
func Sprintf(format string, a ...interface{}) string {
format += ResetCode
format = compile(format)
return fmt.Sprintf(format, a...)
}
// Similar to fmt.Errorf, will reset the color at the end.
func Errorf(format string, a ...interface{}) error {
return errors.New(Sprintf(format, a...))
}
================================================
FILE: vendor/github.com/zackbloom/go-ini/.gitignore
================================================
# Compiled Object files, Static and Dynamic libs (Shared Objects)
*.o
*.a
*.so
# Folders
_obj
_test
# Architecture specific extensions/prefixes
*.[568vq]
[568vq].out
*.cgo1.go
*.cgo2.c
_cgo_defun.c
_cgo_gotypes.go
_cgo_export.*
_testmain.go
*.exe
*.test
*.prof
*.nope
================================================
FILE: vendor/github.com/zackbloom/go-ini/README.md
================================================
go-ini
======
INI file decoder for Go lang. Idea is to have an unmarshaller similar to JSON - specify parts of the file you want coded with structs and tags.
For example, for an INI file like this:
[Pod_mysql]
cache_size = 2000
default_socket = /tmp/mysql.sock
[Mysql]
default_socket = /tmp/mysql.sock
Decode into a structure like this:
type MyIni struct {
PdoMysql struct {
CacheSize int `ini:"cache_size"`
DefaultSocket string `ini:"default_socket"`
} `ini:"[Pdo_myqsl]"`
Mysql struct {
DefaultSocket string `ini:"default_socket"`
} `ini:"[Myqsl]"`
}
With code like this:
var config MyIni
var b []byte // config file stored here
err := ini.Unmarshal(b, &config)
Advanced Types
==============
Over the years, INI files have grown from simple `name=value` lists of properties to files that support arrays and arrays of structures. For example, to support playlists a music config file may look like this:
[CREATE SONG]
SongId=21348
Title=Long Way to Go
Artist=The Coach
[CREATE SONG]
SongId=9855
Title=The Falcon Lead
Artist=It Wasn't Safe
[CREATE PLAYLIST]
PlaylistId=438432
Title=Acid Jazz
Song=21348
Song=482
Song=9855
[CREATE PLAYLIST]
PlaylistId=2585
Title=Lounge
Song=7558
Song=25828
With GO-INI, parsing is as simple as defining the structure and unmarshalling it.
package main
import (
"encoding/json"
"github.com/sspencer/go-ini"
"io/ioutil"
"log"
"os"
)
type TunePlayer struct {
Songs []struct {
SongId int
Title string
Artist string
} `ini:"[CREATE SONG]"`
Playlists []struct {
PlaylistId int
Title string
SongIds []int `ini:"Song"`
} `ini:[CREATE PLAYLIST]`
}
func main() {
var player TunePlayer
content, err := ioutil.ReadFile("./tunes.ini")
if err != nil {
log.Fatal(err)
}
err = ini.Unmarshal(content, &player)
if err != nil {
log.Fatal(err)
}
// Output same struct as JSON to verify parsing worked
enc := json.NewEncoder(os.Stdout)
if err := enc.Encode(&player); err != nil {
log.Println(err)
}
}
Todo
=====
Need to parse inner array of structs
struct {
Playlists []struct {
Id int
Title string
Programs []struct {
Id int
Mix string
Separation int
} `ini:"Play Program"`
} `ini:"[CREATE PLAYLIST]"`
}
[CREATE PLAYLIST]
ID=6524
Title=Pop
Start Schedule
Play Program
ID=391
Mix=RAND
Play Program
ID=3912
Separation=10
End Schedule
================================================
FILE: vendor/github.com/zackbloom/go-ini/decode.go
================================================
// Decode INI files with a syntax similar to JSON decoding
package ini
import (
"bufio"
"bytes"
"fmt"
"io"
"io/ioutil"
"reflect"
"strconv"
"strings"
)
type Unmatched struct {
lineNum int
line string
}
type IniError struct {
lineNum int
line string
error string
}
// decodeState represents the state while decoding a INI value.
type decodeState struct {
lineNum int
line string
scanner *bufio.Scanner
savedError error
unmatched []Unmatched
}
type property struct {
tag string
value reflect.Value
children propertyMap
isArray bool
//array []interface{}
isInitialized bool
}
type propertyMap map[string]property
//------------------------------------------------------------------
// NewStack returns a new stack.
func NewPropMapStack() *PropMapStack {
return &PropMapStack{}
}
// Stack is a basic LIFO stack that resizes as needed.
type PropMapStack struct {
items []propertyMap
count int
}
// Push adds an iterm to the top of the stack
func (s *PropMapStack) Push(item propertyMap) {
s.items = append(s.items[:s.count], item)
s.count++
}
// Pop removes the top item (LIFO) from the stack
func (s *PropMapStack) Pop() propertyMap {
if s.count == 0 {
return nil
}
s.count--
return s.items[s.count]
}
// Peek returns item at top of stack without removing it
func (s *PropMapStack) Peek() propertyMap {
if s.count == 0 {
return nil
}
return s.items[s.count-1]
}
// Empty returns true when stack is empty, false otherwise
func (s *PropMapStack) Empty() bool {
return s.count == 0
}
// Size returns the number of items in the stack
func (s *PropMapStack) Size() int {
return s.count
}
/*
* Unmarshal parses the INI-encoded data and stores the result
* in the value pointed to by v.
*/
func Unmarshal(data []byte, v interface{}) error {
var d decodeState
d.init(data)
return d.unmarshal(v)
}
/*
* String interfacer for Unmatched
*/
func (u Unmatched) String() string {
return fmt.Sprintf("%d %s", u.lineNum, u.line)
}
/*
* Conform to Error Interfacer
*/
func (e *IniError) Error() string {
if e.lineNum > 0 {
return fmt.Sprintf("%s on line %d: \"%s\"", e.error, e.lineNum, e.line)
} else {
return e.error
}
}
/*
* Stringer interface for property
*/
func (p property) String() string {
return fmt.Sprintf("<property %s, isArray:%t>", p.tag, p.isArray)
}
/*
* Convenience function to prep for decoding byte array.
*/
func (d *decodeState) init(data []byte) *decodeState {
d.lineNum = 0
d.line = ""
d.scanner = bufio.NewScanner(bytes.NewReader(data))
d.savedError = nil
return d
}
/*
* saveError saves the first err it is called with,
* for reporting at the end of the unmarshal.
*/
func (d *decodeState) saveError(err error) {
if d.savedError == nil {
d.savedError = err
}
}
/*
* Recursive function to map data types in the describing structs
* to string markers (tags) in the INI file.
*/
func (d *decodeState) generateMap(m propertyMap, v reflect.Value) {
if v.Type().Kind() == reflect.Ptr {
d.generateMap(m, v.Elem())
} else if v.Kind() == reflect.Struct {
typ := v.Type()
for i := 0; i < typ.NumField(); i++ {
sf := typ.Field(i)
f := v.Field(i)
kind := f.Type().Kind()
tag := sf.Tag.Get("ini")
if len(tag) == 0 {
tag = sf.Name
}
tag = strings.TrimSpace(strings.ToLower(tag))
st := property{tag, f, make(propertyMap), kind == reflect.Slice, true}
// some structures are just for organizing data
if tag != "-" {
m[tag] = st
}
if kind == reflect.Struct {
if tag == "-" {
d.generateMap(m, f)
} else {
// little namespacing here so property names can
// be the same under different sections
//fmt.Printf("Struct tag: %s, type: %s\n", tag, f.Type())
d.generateMap(st.children, f)
}
} else if kind == reflect.Slice {
d.generateMap(st.children, reflect.New(f.Type().Elem()))
}
}
}
}
/*
* Iterates line-by-line through INI file setting values into a struct.
*/
func (d *decodeState) unmarshal(x interface{}) error {
var topMap propertyMap
topMap = make(propertyMap)
d.generateMap(topMap, reflect.ValueOf(x))
propStack := NewPropMapStack()
propStack.Push(topMap)
// for every line in file
for d.scanner.Scan() {
if d.savedError != nil {
break // breaks on first error
}
d.line = d.scanner.Text()
d.lineNum++
line := strings.TrimSpace(d.line)
if len(line) < 1 || line[0] == ';' || line[0] == '#' {
continue // skip comments
}
// Two types of lines:
// 1. NAME=VALUE (at least one equal sign - breaks on first)
// 2. [HEADER] (no equals sign, square brackets NOT required)
matches := strings.SplitN(line, "=", 2)
matched := false
pn := ""
pv := ""
if len(matches) == 2 {
// NAME=VALUE
pn = strings.ToLower(strings.TrimSpace(matches[0]))
pv = strings.TrimSpace(matches[1])
prop := propStack.Peek()[pn]
if prop.isInitialized {
if prop.isArray {
value := reflect.New(prop.value.Type().Elem())
d.setValue(reflect.Indirect(value), pv)
appendValue(prop.value, value)
} else {
d.setValue(prop.value, pv)
}
matched = true
}
// What if property is umatched - keep popping the stack
// until a potential map is found or stay within current section?
// Think answer is pop.
// NOPE
// Section could have unmatched name=value if user doesn't
// care about certain values - only stack crawling happens
// during numMatches==1 time?
// This means if there is > 1 section, there needs to be
// section breaks for everything
} else {
// [Header] section
pn = strings.ToLower(strings.TrimSpace(matches[0]))
for propStack.Size() > 0 {
prop := propStack.Peek()[pn]
if prop.isInitialized {
propStack.Push(prop.children)
matched = true
break
} else if propStack.Size() > 1 {
_ = propStack.Pop()
} else {
break
}
}
}
if !matched {
d.unmatched = append(d.unmatched, Unmatched{d.lineNum, d.line})
}
}
return d.savedError
}
func (d *decodeState) unmarshal2(x interface{}) error {
var sectionMap propertyMap = make(propertyMap)
var tempMap propertyMap = make(propertyMap)
var section, nextSection property
var inSection, nextHasSection bool = false, false
var tempValue reflect.Value // "temp" is for filling in array of structs
var numTempValue int
d.generateMap(sectionMap, reflect.ValueOf(x))
for d.scanner.Scan() {
if d.savedError != nil {
break
}
d.line = d.scanner.Text()
d.lineNum++
//fmt.Printf("%03d: %s\n", d.lineNum, d.line)
line := strings.ToLower(strings.TrimSpace(d.line))
if len(line) < 1 || line[0] == ';' || line[0] == '#' {
continue // skip comments
}
// [Sections] could appear at any time (square brackets not required)
// When in a section, also look in children map
nextSection, nextHasSection = sectionMap[line]
if nextHasSection {
if numTempValue > 0 && section.isArray {
appendValue(section.value, tempValue)
}
section = nextSection
inSection = true
if section.isArray {
tempValue = reflect.New(section.value.Type().Elem())
d.generateMap(tempMap, tempValue)
}
numTempValue = 0
continue
}
// unrecognized section - exit out of current section
if line[0] == '[' && line[len(line)-1] == ']' {
inSection = false
continue
}
matches := strings.SplitN(d.line, "=", 2)
matched := false
// potential property=value
if len(matches) == 2 {
n := strings.ToLower(strings.TrimSpace(matches[0]))
s := strings.TrimSpace(matches[1])
if inSection {
// child property, within a section
childProperty, hasProp := section.children[n]
if hasProp {
if section.isArray {
tempProperty := tempMap[n]
numTempValue++
d.setValue(tempProperty.value, s)
} else {
d.setValue(childProperty.value, s)
}
matched = true
}
}
if !matched {
// top level property
topLevelProperty, hasProp := sectionMap[n]
if hasProp {
// just encountered a top level property - switch out of section mode
inSection = false
matched = true
d.setValue(topLevelProperty.value, s)
}
}
}
if !matched {
d.unmatched = append(d.unmatched, Unmatched{d.lineNum, d.line})
}
}
if numTempValue > 0 {
appendValue(section.value, tempValue)
}
return d.savedError
}
func appendValue(arr, val reflect.Value) {
arr.Set(reflect.Append(arr, reflect.Indirect(val)))
}
// Set Value with given string
func (d *decodeState) setValue(v reflect.Value, s string) {
//fmt.Printf("SET(kind:%s, %s)\n", v.Kind(), s)
switch v.Kind() {
case reflect.String:
v.SetString(s)
case reflect.Bool:
v.SetBool(boolValue(s))
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
n, err := strconv.ParseInt(s, 10, 64)
if err != nil || v.OverflowInt(n) {
d.saveError(&IniError{d.lineNum, d.line, "Invalid int"})
return
}
v.SetInt(n)
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
n, err := strconv.ParseUint(s, 10, 64)
if err != nil || v.OverflowUint(n) {
d.saveError(&IniError{d.lineNum, d.line, "Invalid uint"})
return
}
v.SetUint(n)
case reflect.Float32, reflect.Float64:
n, err := strconv.ParseFloat(s, v.Type().Bits())
if err != nil || v.OverflowFloat(n) {
d.saveError(&IniError{d.lineNum, d.line, "Invalid float"})
return
}
v.SetFloat(n)
case reflect.Slice:
d.sliceValue(v, s)
default:
d.saveError(&IniError{d.lineNum, d.line, fmt.Sprintf("Can't set value of type %s", v.Kind())})
}
}
func (d *decodeState) sliceValue(v reflect.Value, s string) {
//fmt.Printf(":SLICE(%s, %s)\n", v.Kind(), s)
switch v.Type().Elem().Kind() {
case reflect.String:
v.Set(reflect.Append(v, reflect.ValueOf(s)))
case reflect.Bool:
v.Set(reflect.Append(v, reflect.ValueOf(boolValue(s))))
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
// Hardcoding of []int temporarily
n, err := strconv.ParseInt(s, 10, 64)
if err != nil {
d.saveError(&IniError{d.lineNum, d.line, "Invalid int"})
return
}
n1 := reflect.ValueOf(n)
n2 := n1.Convert(v.Type().Elem())
v.Set(reflect.Append(v, n2))
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
n, err := strconv.ParseUint(s, 10, 64)
if err != nil {
d.saveError(&IniError{d.lineNum, d.line, "Invalid uint"})
return
}
n1 := reflect.ValueOf(n)
n2 := n1.Convert(v.Type().Elem())
v.Set(reflect.Append(v, n2))
case reflect.Float32, reflect.Float64:
n, err := strconv.ParseFloat(s, 64)
if err != nil {
d.saveError(&IniError{d.lineNum, d.line, "Invalid float"})
return
}
n1 := reflect.ValueOf(n)
n2 := n1.Convert(v.Type().Elem())
v.Set(reflect.Append(v, n2))
default:
d.saveError(&IniError{d.lineNum, d.line, fmt.Sprintf("Can't set value in array of type %s",
v.Type().Elem().Kind())})
}
}
// Returns true for truthy values like t/true/y/yes/1, false otherwise
func boolValue(s string) bool {
v := false
switch strings.ToLower(s) {
case "t", "true", "y", "yes", "1":
v = true
}
return v
}
// A Decoder reads and decodes INI object from an input stream.
type Decoder struct {
r io.Reader
d decodeState
}
// NewDecoder returns a new decoder that reads from r.
//
// The decoder introduces its own buffering and may
// read data from r beyond the JSON values requested.
func NewDecoder(r io.Reader) *Decoder {
return &Decoder{r: r}
}
// Decode reads the INI file and stores it in the value pointed to by v.
//
// See the documentation for Unmarshal for details about
// the conversion of an INI into a Go value.
func (dec *Decoder) Decode(v interface{}) error {
buf, readErr := ioutil.ReadAll(dec.r)
if readErr != nil {
return readErr
}
// Don't save err from unmarshal into dec.err:
// the connection is still usable since we read a complete JSON
// object from it before the error happened.
dec.d.init(buf)
err := dec.d.unmarshal(v)
return err
}
// UnparsedLines returns an array of strings where each string is an
// unparsed line from the file.
func (dec *Decoder) Unmatched() []Unmatched {
return dec.d.unmatched
}
================================================
FILE: vendor/github.com/zackbloom/go-ini/stack.go
================================================
package ini
// NewStack returns a new stack.
func NewStack() *Stack {
return &Stack{}
}
// Stack is a basic LIFO stack that resizes as needed.
type Stack struct {
items []interface{}
count int
}
// Push adds an iterm to the top of the stack
func (s *Stack) Push(item interface{}) {
s.items = append(s.items[:s.count], item)
s.count++
}
// Pop removes the top item (LIFO) from the stack
func (s *Stack) Pop() interface{} {
if s.count == 0 {
return nil
}
s.count--
return s.items[s.count]
}
// Peek returns item at top of stack without removing it
func (s *Stack) Peek() interface{} {
if s.count == 0 {
return nil
}
return s.items[s.count-1]
}
// Empty returns true when stack is empty, false otherwise
func (s *Stack) Empty() bool {
return s.count == 0
}
// Size returns the number of items in the stack
func (s *Stack) Size() int {
return s.count
}
================================================
FILE: vendor/github.com/zackbloom/goamz/LICENSE
================================================
This software is licensed under the LGPLv3, included below.
As a special exception to the GNU Lesser General Public License version 3
("LGPL3"), the copyright holders of this Library give you permission to
convey to a third party a Combined Work that links statically or dynamically
to this Library without providing any Minimal Corresponding Source or
Minimal Application Code as set out in 4d or providing the installation
information set out in section 4e, provided that you comply with the other
provisions of LGPL3 and provided that you meet, for the Application the
terms and conditions of the license(s) which apply to the Application.
Except as stated in this special exception, the provisions of LGPL3 will
continue to comply in full to this Library. If you modify this Library, you
may apply this exception to your version of this Library, but you are not
obliged to do so. If you do not wish to do so, delete this exception
statement from your version. This exception does not (and cannot) modify any
license terms which apply to the Application, with which you must still
comply.
GNU LESSER GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
This version of the GNU Lesser General Public License incorporates
the terms and conditions of version 3 of the GNU General Public
License, supplemented by the additional permissions listed below.
0. Additional Definitions.
As used herein, "this License" refers to version 3 of the GNU Lesser
General Public License, and the "GNU GPL" refers to version 3 of the GNU
General Public License.
"The Library" refers to a covered work governed by this License,
other than an Application or a Combined Work as defined below.
An "Application" is any work that makes use of an interface provided
by the Library, but which is not otherwise based on the Library.
Defining a subclass of a class defined by the Library is deemed a mode
of using an interface provided by the Library.
A "Combined Work" is a work produced by combining or linking an
Application with the Library. The particular version of the Library
with which the Combined Work was made is also called the "Linked
Version".
The "Minimal Corresponding Source" for a Combined Work means the
Corresponding Source for the Combined Work, excluding any source code
for portions of the Combined Work that, considered in isolation, are
based on the Application, and not on the Linked Version.
The "Corresponding Application Code" for a Combined Work means the
object code and/or source code for the Application, including any data
and utility programs needed for reproducing the Combined Work from the
Application, but excluding the System Libraries of the Combined Work.
1. Exception to Section 3 of the GNU GPL.
You may convey a covered work under sections 3 and 4 of this License
without being bound by section 3 of the GNU GPL.
2. Conveying Modified Versions.
If you modify a copy of the Library, and, in your modifications, a
facility refers to a function or data to be supplied by an Application
that uses the facility (other than as an argument passed when the
facility is invoked), then you may convey a copy of the modified
version:
a) under this License, provided that you make a good faith effort to
ensure that, in the event an Application does not supply the
function or data, the facility still operates, and performs
whatever part of its purpose remains meaningful, or
b) under the GNU GPL, with none of the additional permissions of
this License applicable to that copy.
3. Object Code Incorporating Material from Library Header Files.
The object code form of an Application may incorporate material from
a header file that is part of the Library. You may convey such object
code under terms of your choice, provided that, if the incorporated
material is not limited to numerical parameters, data structure
layouts and accessors, or small macros, inline functions and templates
(ten or fewer lines in length), you do both of the following:
a) Give prominent notice with each copy of the object code that the
Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the object code with a copy of the GNU GPL and this license
document.
4. Combined Works.
You may convey a Combined Work under terms of your choice that,
taken together, effectively do not restrict modification of the
portions of the Library contained in the Combined Work and reverse
engineering for debugging such modifications, if you also do each of
the following:
a) Give prominent notice with each copy of the Combined Work that
the Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the Combined Work with a copy of the GNU GPL and this license
document.
c) For a Combined Work that displays copyright notices during
execution, include the copyright notice for the Library among
these notices, as well as a reference directing the user to the
copies of the GNU GPL and this license document.
d) Do one of the following:
0) Convey the Minimal Corresponding Source under the terms of this
License, and the Corresponding Application Code in a form
suitable for, and under terms that permit, the user to
recombine or relink the Application with a modified version of
the Linked Version to produce a modified Combined Work, in the
manner specified by section 6 of the GNU GPL for conveying
Corresponding Source.
1) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (a) uses at run time
a copy of the Library already present on the user's computer
system, and (b) will operate properly with a modified version
of the Library that is interface-compatible with the Linked
Version.
e) Provide Installation Information, but only if you would otherwise
be required to provide such information under section 6 of the
GNU GPL, and only to the extent that such information is
necessary to install and execute a modified version of the
Combined Work produced by recombining or relinking the
Application with a modified version of the Linked Version. (If
you use option 4d0, the Installation Information must accompany
the Minimal Corresponding Source and Corresponding Application
Code. If you use option 4d1, you must provide the Installation
Information in the manner specified by section 6 of the GNU GPL
for conveying Corresponding Source.)
5. Combined Libraries.
You may place library facilities that are a work based on the
Library side by side in a single library together with other library
facilities that are not Applications and are not covered by this
License, and convey such a combined library under terms of your
choice, if you do both of the following:
a) Accompany the combined library with a copy of the same work based
on the Library, uncombined with any other library facilities,
conveyed under the terms of this License.
b) Give prominent notice with the combined library that part of it
is a work based on the Library, and explaining where to find the
accompanying uncombined form of the same work.
6. Revised Versions of the GNU Lesser General Public License.
The Free Software Foundation may publish revised and/or new versions
of the GNU Lesser General Public License from time to time. Such new
versions will be similar in spirit to the present version, but may
differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the
Library as you received it specifies that a certain numbered version
of the GNU Lesser General Public License "or any later version"
applies to it, you have the option of following the terms and
conditions either of that published version or of any later version
published by the Free Software Foundation. If the Library as you
received it does not specify a version number of the GNU Lesser
General Public License, you may choose any version of the GNU Lesser
General Public License ever published by the Free Software Foundation.
If the Library as you received it specifies that a proxy can decide
whether future versions of the GNU Lesser General Public License shall
apply, that proxy's public statement of acceptance of any version is
permanent authorization for you to choose that version for the
Library.
================================================
FILE: vendor/github.com/zackbloom/goamz/aws/attempt.go
================================================
package aws
import (
"time"
)
// AttemptStrategy represents a strategy for waiting for an action
// to complete successfully. This is an internal type used by the
// implementation of other goamz packages.
type AttemptStrategy struct {
Total time.Duration // total duration of attempt.
Delay time.Duration // interval between each try in the burst.
Min int // minimum number of retries; overrides Total
}
type Attempt struct {
strategy AttemptStrategy
last time.Time
end time.Time
force bool
count int
}
// Start begins a new sequence of attempts for the given strategy.
func (s AttemptStrategy) Start() *Attempt {
now := time.Now()
return &Attempt{
strategy: s,
last: now,
end: now.Add(s.Total),
force: true,
}
}
// Next waits until it is time to perform the next attempt or returns
// false if it is time to stop trying.
func (a *Attempt) Next() bool {
now := time.Now()
sleep := a.nextSleep(now)
if !a.force && !now.Add(sleep).Before(a.end) && a.strategy.Min <= a.count {
return false
}
a.force = false
if sleep > 0 && a.count > 0 {
time.Sleep(sleep)
now = time.Now()
}
a.count++
a.last = now
return true
}
func (a *Attempt) nextSleep(now time.Time) time.Duration {
sleep := a.strategy.Delay - now.Sub(a.last)
if sleep < 0 {
return 0
}
return sleep
}
// HasNext returns whether another attempt will be made if the current
// one fails. If it returns true, the following call to Next is
// guaranteed to return true.
func (a *Attempt) HasNext() bool {
if a.force || a.strategy.Min > a.count {
return true
}
now := time.Now()
if now.Add(a.nextSleep(now)).Before(a.end) {
a.force = true
return true
}
return false
}
================================================
FILE: vendor/github.com/zackbloom/goamz/aws/aws.go
================================================
//
// goamz - Go packages to interact with the Amazon Web Services.
//
// https://wiki.ubuntu.com/goamz
//
// Copyright (c) 2011 Canonical Ltd.
//
// Written by Gustavo Niemeyer <gustavo.niemeyer@canonical.com>
//
package aws
import (
"encoding/json"
"encoding/xml"
"errors"
"fmt"
"io/ioutil"
"net"
"net/http"
"net/url"
"os"
"os/user"
"path"
"regexp"
"strings"
"time"
)
// Regular expressions for INI files
var (
iniSectionRegexp = regexp.MustCompile(`^\s*\[([^\[\]]+)\]\s*$`)
iniSettingRegexp = regexp.MustCompile(`^\s*(.+?)\s*=\s*(.*\S)\s*$`)
)
// Defines the valid signers
const (
V2Signature = iota
V4Signature = iota
Route53Signature = iota
)
// Defines the service endpoint and correct Signer implementation to use
// to sign requests for this endpoint
type ServiceInfo struct {
Endpoint string
Signer uint
}
// Region defines the URLs where AWS services may be accessed.
//
// See http://goo.gl/d8BP1 for more details.
type Region struct {
Name string // the canonical name of this region.
EC2Endpoint string
S3Endpoint string
S3BucketEndpoint string // Not needed by AWS S3. Use ${bucket} for bucket name.
S3LocationConstraint bool // true if this region requires a LocationConstraint declaration.
S3LowercaseBucket bool // true if the region requires bucket names to be lower case.
SDBEndpoint string
SNSEndpoint string
SQSEndpoint string
SESEndpoint string
IAMEndpoint string
ELBEndpoint string
DynamoDBEndpoint string
CloudWatchServicepoint ServiceInfo
AutoScalingEndpoint string
RDSEndpoint ServiceInfo
KinesisEndpoint string
STSEndpoint string
CloudFormationEndpoint string
ElastiCacheEndpoint string
}
var Regions = map[string]Region{
APNortheast.Name: APNortheast,
APSoutheast.Name: APSoutheast,
APSoutheast2.Name: APSoutheast2,
EUCentral.Name: EUCentral,
EUWest.Name: EUWest,
USEast.Name: USEast,
USWest.Name: USWest,
USWest2.Name: USWest2,
USGovWest.Name: USGovWest,
SAEast.Name: SAEast,
}
// Designates a signer interface suitable for signing AWS requests, params
// should be appropriately encoded for the request before signing.
//
// A signer should be initialized with Auth and the appropriate endpoint.
type Signer interface {
Sign(method, path string, params map[string]string)
}
// An AWS Service interface with the API to query the AWS service
//
// Supplied as an easy way to mock out service calls during testing.
type AWSService interface {
// Queries the AWS service at a given method/path with the params and
// returns an http.Response and error
Query(method, path string, params map[string]string) (*http.Response, error)
// Builds an error given an XML payload in the http.Response, can be used
// to process an error if the status code is not 200 for example.
BuildError(r *http.Response) error
}
// Implements a Server Query/Post API to easily query AWS services and build
// errors when desired
type Service struct {
service ServiceInfo
signer Signer
}
// Create a base set of params for an action
func MakeParams(action string) map[string]string {
params := make(map[string]string)
params["Action"] = action
return params
}
// Create a new AWS server to handle making requests
func NewService(auth Auth, service ServiceInfo) (s *Service, err error) {
var signer Signer
switch service.Signer {
case V2Signature:
signer, err = NewV2Signer(auth, service)
// case V4Signature:
// signer, err = NewV4Signer(auth, service, Regions["eu-west-1"])
default:
err = fmt.Errorf("Unsupported signer for service")
}
if err != nil {
return
}
s = &Service{service: service, signer: signer}
return
}
func (s *Service) Query(method, path string, params map[string]string) (resp *http.Response, err error) {
params["Timestamp"] = time.Now().UTC().Format(time.RFC3339)
u, err := url.Parse(s.service.Endpoint)
if err != nil {
return nil, err
}
u.Path = path
s.signer.Sign(method, path, params)
if method == "GET" {
u.RawQuery = multimap(params).Encode()
resp, err = http.Get(u.String())
} else if method == "POST" {
resp, err = http.PostForm(u.String(), multimap(params))
}
return
}
func (s *Service) BuildError(r *http.Response) error {
errors := ErrorResponse{}
xml.NewDecoder(r.Body).Decode(&errors)
var err Error
err = errors.Errors
err.RequestId = errors.RequestId
err.StatusCode = r.StatusCode
if err.Message == "" {
err.Message = r.Status
}
return &err
}
type ServiceError interface {
error
ErrorCode() string
}
type ErrorResponse struct {
Errors Error `xml:"Error"`
RequestId string // A unique ID for tracking the request
}
type Error struct {
StatusCode int
Type string
Code string
Message string
RequestId string
}
func (err *Error) Error() string {
return fmt.Sprintf("Type: %s, Code: %s, Message: %s",
err.Type, err.Code, err.Message,
)
}
func (err *Error) ErrorCode() string {
return err.Code
}
type Auth struct {
AccessKey, SecretKey string
token string
expiration time.Time
}
func (a *Auth) Token() string {
if a.token == "" {
return ""
}
if time.Since(a.expiration) >= -30*time.Second { //in an ideal world this should be zero assuming the instance is synching it's clock
*a, _ = GetAuth("", "", "", time.Time{})
}
return a.token
}
func (a *Auth) Expiration() time.Time {
return a.expiration
}
// To be used with other APIs that return auth credentials such as STS
func NewAuth(accessKey, secretKey, token string, expiration time.Time) *Auth {
return &Auth{
AccessKey: accessKey,
SecretKey: secretKey,
token: token,
expiration: expiration,
}
}
// ResponseMetadata
type ResponseMetadata struct {
RequestId string // A unique ID for tracking the request
}
type BaseResponse struct {
ResponseMetadata ResponseMetadata
}
var unreserved = make([]bool, 128)
var hex = "0123456789ABCDEF"
func init() {
// RFC3986
u := "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01234567890-_.~"
for _, c := range u {
unreserved[c] = true
}
}
func multimap(p map[string]string) url.Values {
q := make(url.Values, len(p))
for k, v := range p {
q[k] = []string{v}
}
return q
}
type credentials struct {
Code string
LastUpdated string
Type string
AccessKeyId string
SecretAccessKey string
Token string
Expiration string
}
// GetMetaData retrieves instance metadata about the current machine.
//
// See http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/AESDG-chapter-instancedata.html for more details.
func GetMetaData(path string) (contents []byte, err error) {
c := http.Client{
Transport: &http.Transport{
Dial: func(netw, addr string) (net.Conn, error) {
deadline := time.Now().Add(5 * time.Second)
c, err := net.DialTimeout(netw, addr, time.Second*2)
if err != nil {
return nil, err
}
c.SetDeadline(deadline)
return c, nil
},
},
}
url := "http://169.254.169.254/latest/meta-data/" + path
resp, err := c.Get(url)
if err != nil {
return
}
defer resp.Body.Close()
if resp.StatusCode != 200 {
err = fmt.Errorf("Code %d returned for url %s", resp.StatusCode, url)
return
}
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return
}
return []byte(body), err
}
func GetRegion(regionName string) (region Region) {
region = Regions[regionName]
return
}
// GetInstanceCredentials creates an Auth based on the instance's role credentials.
// If the running instance is not in EC2 or does not have a valid IAM role, an error will be returned.
// For more info about setting up IAM roles, see http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/iam-roles-for-amazon-ec2.html
func GetInstanceCredentials() (cred credentials, err error) {
credentialPath := "iam/security-credentials/"
// Get the instance role
role, err := GetMetaData(credentialPath)
if err != nil {
return
}
// Get the instance role credentials
credentialJSON, err := GetMetaData(credentialPath + string(role))
if err != nil {
return
}
err = json.Unmarshal([]byte(credentialJSON), &cred)
return
}
// GetAuth creates an Auth based on either passed in credentials,
// environment information or instance based role credentials.
func GetAuth(accessKey string, secretKey, token string, expiration time.Time) (auth Auth, err error) {
// First try passed in credentials
if accessKey != "" && secretKey != "" {
return Auth{accessKey, secretKey, token, expiration}, nil
}
// Next try to get auth from the environment
auth, err = EnvAuth()
if err == nil {
// Found auth, return
return
}
// Next try getting auth from the instance role
cred, err := GetInstanceCredentials()
if err == nil {
// Found auth, return
auth.AccessKey = cred.AccessKeyId
auth.SecretKey = cred.SecretAccessKey
auth.token = cred.Token
exptdate, err := time.Parse("2006-01-02T15:04:05Z", cred.Expiration)
if err != nil {
err = fmt.Errorf("Error Parsing expiration date: cred.Expiration :%s , error: %s \n", cred.Expiration, err)
}
auth.expiration = exptdate
return auth, err
}
// Next try getting auth from the credentials file
auth, err = CredentialFileAuth("", "", time.Minute*5)
if err == nil {
return
}
//err = errors.New("No valid AWS authentication found")
err = fmt.Errorf("No valid AWS authentication found: %s", err)
return auth, err
}
// EnvAuth creates an Auth based on environment information.
// The AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY environment
// variables are used.
func EnvAuth() (auth Auth, err error) {
auth.AccessKey = os.Getenv("AWS_ACCESS_KEY_ID")
if auth.AccessKey == "" {
auth.AccessKey = os.Getenv("AWS_ACCESS_KEY")
}
auth.SecretKey = os.Getenv("AWS_SECRET_ACCESS_KEY")
if auth.SecretKey == "" {
auth.SecretKey = os.Getenv("AWS_SECRET_KEY")
}
if auth.AccessKey == "" {
err = errors.New("AWS_ACCESS_KEY_ID or AWS_ACCESS_KEY not found in environment")
}
if auth.SecretKey == "" {
err = errors.New("AWS_SECRET_ACCESS_KEY or AWS_SECRET_KEY not found in environment")
}
return
}
// CredentialFileAuth creates and Auth based on a credentials file. The file
// contains various authentication profiles for use with AWS.
//
// The credentials file, which is used by other AWS SDKs, is documented at
// http://blogs.aws.amazon.com/security/post/Tx3D6U6WSFGOK2H/A-New-and-Standardized-Way-to-Manage-Credentials-in-the-AWS-SDKs
func CredentialFileAuth(filePath string, profile string, expiration time.Duration) (auth Auth, err error) {
if profile == "" {
profile = "default"
}
if filePath == "" {
u, err := user.Current()
if err != nil {
return auth, err
}
filePath = path.Join(u.HomeDir, ".aws", "credentials")
}
// read the file, then parse the INI
contents, err := ioutil.ReadFile(filePath)
if err != nil {
return
}
profiles := parseINI(string(contents))
profileData, ok := profiles[profile]
if !ok {
err = errors.New("The credentials file did not contain the profile")
return
}
keyId, ok := profileData["aws_access_key_id"]
if !ok {
err = errors.New("The credentials file did not contain required attribute aws_access_key_id")
return
}
secretKey, ok := profileData["aws_secret_access_key"]
if !ok {
err = errors.New("The credentials file did not contain required attribute aws_secret_access_key")
return
}
auth.AccessKey = keyId
auth.SecretKey = secretKey
if token, ok := profileData["aws_session_token"]; ok {
auth.token = token
}
auth.expiration = time.Now().Add(expiration)
return
}
// parseINI takes the contents of a credentials file and returns a map, whose keys
// are the various profiles, and whose values are maps of the settings for the
// profiles
func parseINI(fileContents string) map[string]map[string]string {
profiles := make(map[string]map[string]string)
lines := strings.Split(fileContents, "\n")
var currentSection map[string]string
for _, line := range lines {
// remove comments, which start with a semi-colon
if split := strings.Split(line, ";"); len(split) > 1 {
line = split[0]
}
// check if the line is the start of a profile.
//
// for example:
// [default]
//
// otherwise, check for the proper setting
// property=value
if sectMatch := iniSectionRegexp.FindStringSubmatch(line); len(sectMatch) == 2 {
currentSection = make(map[string]string)
profiles[sectMatch[1]] = currentSection
} else if setMatch := iniSettingRegexp.FindStringSubmatch(line); len(setMatch) == 3 && currentSection != nil {
currentSection[setMatch[1]] = setMatch[2]
}
}
return profiles
}
// Encode takes a string and URI-encodes it in a way suitable
// to be used in AWS signatures.
func Encode(s string) string {
encode := false
for i := 0; i != len(s); i++ {
c := s[i]
if c > 127 || !unreserved[c] {
encode = true
break
}
}
if !encode {
return s
}
e := make([]byte, len(s)*3)
ei := 0
for i := 0; i != len(s); i++ {
c := s[i]
if c > 127 || !unreserved[c] {
e[ei] = '%'
e[ei+1] = hex[c>>4]
e[ei+2] = hex[c&0xF]
ei += 3
} else {
e[ei] = c
ei += 1
}
}
return string(e[:ei])
}
func dialTimeout(network, addr string) (net.Conn, error) {
return net.DialTimeout(network, addr, time.Duration(2*time.Second))
}
func AvailabilityZone() string {
transport := http.Transport{Dial: dialTimeout}
client := http.Client{
Transport: &transport,
}
resp, err := client.Get("http://169.254.169.254/latest/meta-data/placement/availability-zone")
if err != nil {
return "unknown"
} else {
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return "unknown"
} else {
return string(body)
}
}
}
func InstanceRegion() string {
az := AvailabilityZone()
if az == "unknown" {
return az
} else {
region := az[:len(az)-1]
return region
}
}
func InstanceId() string {
transport := http.Transport{Dial: dialTimeout}
client := http.Client{
Transport: &transport,
}
resp, err := client.Get("http://169.254.169.254/latest/meta-data/instance-id")
if err != nil {
return "unknown"
} else {
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return "unknown"
} else {
return string(body)
}
}
}
func InstanceType() string {
transport := http.Transport{Dial: dialTimeout}
client := http.Client{
Transport: &transport,
}
resp, err := client.Get("http://169.254.169.254/latest/meta-data/instance-type")
if err != nil {
return "unknown"
} else {
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return "unknown"
} else {
return string(body)
}
}
}
func ServerLocalIp() string {
transport := http.Transport{Dial: dialTimeout}
client := http.Client{
Transport: &transport,
}
resp, err := client.Get("http://169.254.169.254/latest/meta-data/local-ipv4")
if err != nil {
return "127.0.0.1"
} else {
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return "127.0.0.1"
} else {
return string(body)
}
}
}
func ServerPublicIp() string {
transport := http.Transport{Dial: dialTimeout}
client := http.Client{
Transport: &transport,
}
resp, err := client.Get("http://169.254.169.254/latest/meta-data/public-ipv4")
if err != nil {
return "127.0.0.1"
} else {
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return "127.0.0.1"
} else {
return string(body)
}
}
}
================================================
FILE: vendor/github.com/zackbloom/goamz/aws/client.go
================================================
package aws
import (
"math"
"net"
"net/http"
"time"
)
type RetryableFunc func(*http.Request, *http.Response, error) bool
type WaitFunc func(try int)
type DeadlineFunc func() time.Time
type ResilientTransport struct {
// Timeout is the maximum amount of time a dial will wait for
// a connect to complete.
//
// The default is no timeout.
//
// With or without a timeout, the operating system may impose
// its own earlier timeout. For instance, TCP timeouts are
// often around 3 minutes.
DialTimeout time.Duration
// MaxTries, if non-zero, specifies the number of times we will retry on
// failure. Retries are only attempted for temporary network errors or known
// safe failures.
MaxTries int
Deadline DeadlineFunc
ShouldRetry RetryableFunc
Wait WaitFunc
transport *http.Transport
}
// Convenience method for creating an http client
func NewClient(rt *ResilientTransport) *http.Client {
rt.transport = &http.Transport{
Dial: func(netw, addr string) (net.Conn, error) {
c, err := net.DialTimeout(netw, addr, rt.DialTimeout)
if err != nil {
return nil, err
}
c.SetDeadline(rt.Deadline())
return c, nil
},
Proxy: http.ProxyFromEnvironment,
}
// TODO: Would be nice is ResilientTransport allowed clients to initialize
// with http.Transport attributes.
return &http.Client{
Transport: rt,
}
}
var retryingTransport = &ResilientTransport{
Deadline: func() time.Time {
return time.Now().Add(5 * time.Second)
},
DialTimeout: 10 * time.Second,
MaxTries: 3,
ShouldRetry: awsRetry,
Wait: ExpBackoff,
}
// Exported default client
var RetryingClient = NewClient(retryingTransport)
func (t *ResilientTransport) RoundTrip(req *http.Request) (*http.Response, error) {
return t.tries(req)
}
// Retry a request a maximum of t.MaxTries times.
// We'll only retry if the proper criteria are met.
// If a wait function is specified, wait that amount of time
// In between requests.
func (t *ResilientTransport) tries(req *http.Request) (res *http.Response, err error) {
for try := 0; try < t.MaxTries; try += 1 {
res, err = t.transport.RoundTrip(req)
if !t.ShouldRetry(req, res, err) {
break
}
if res != nil {
res.Body.Close()
}
if t.Wait != nil {
t.Wait(try)
}
}
return
}
func ExpBackoff(try int) {
time.Sleep(100 * time.Millisecond *
time.Duration(math.Exp2(float64(try))))
}
func LinearBackoff(try int) {
time.Sleep(time.Duration(try*100) * time.Millisecond)
}
// Decide if we should retry a request.
// In general, the criteria for retrying a request is described here
// http://docs.aws.amazon.com/general/latest/gr/api-retries.html
func awsRetry(req *http.Request, res *http.Response, err error) bool {
retry := false
// Retry if there's a temporary network error.
if neterr, ok := err.(net.Error); ok {
if neterr.Temporary() {
retry = true
}
}
// Retry if we get a 5xx series error.
if res != nil {
if res.StatusCode >= 500 && res.StatusCode < 600 {
retry = true
}
}
return retry
}
================================================
FILE: vendor/github.com/zackbloom/goamz/aws/regions.go
================================================
package aws
var USGovWest = Region{
"us-gov-west-1",
"https://ec2.us-gov-west-1.amazonaws.com",
"https://s3-fips-us-gov-west-1.amazonaws.com",
"",
true,
true,
"",
"https://sns.us-gov-west-1.amazonaws.com",
"https://sqs.us-gov-west-1.amazonaws.com",
"",
"https://iam.us-gov.amazonaws.com",
"https://elasticloadbalancing.us-gov-west-1.amazonaws.com",
"https://dynamodb.us-gov-west-1.amazonaws.com",
ServiceInfo{"https://monitoring.us-gov-west-1.amazonaws.com", V2Signature},
"https://autoscaling.us-gov-west-1.amazonaws.com",
ServiceInfo{"https://rds.us-gov-west-1.amazonaws.com", V2Signature},
"",
"https://sts.amazonaws.com",
"https://cloudformation.us-gov-west-1.amazonaws.com",
"",
}
var USEast = Region{
"us-east-1",
"https://ec2.us-east-1.amazonaws.com",
"https://s3.amazonaws.com",
"",
false,
false,
"https://sdb.amazonaws.com",
"https://sns.us-east-1.amazonaws.com",
"https://sqs.us-east-1.amazonaws.com",
"https://email.us-east-1.amazonaws.com",
"https://iam.amazonaws.com",
"https://elasticloadbalancing.us-east-1.amazonaws.com",
"https://dynamodb.us-east-1.amazonaws.com",
ServiceInfo{"https://monitoring.us-east-1.amazonaws.com", V2Signature},
"https://autoscaling.us-east-1.amazonaws.com",
ServiceInfo{"https://rds.us-east-1.amazonaws.com", V2Signature},
"https://kinesis.us-east-1.amazonaws.com",
"https://sts.amazonaws.com",
"https://cloudformation.us-east-1.amazonaws.com",
"https://elasticache.us-east-1.amazonaws.com",
}
var USWest = Region{
"us-west-1",
"https://ec2.us-west-1.amazonaws.com",
"https://s3-us-west-1.amazonaws.com",
"",
true,
true,
"https://sdb.us-west-1.amazonaws.com",
"https://sns.us-west-1.amazonaws.com",
"https://sqs.us-west-1.amazonaws.com",
"",
"https://iam.amazonaws.com",
"https://elasticloadbalancing.us-west-1.amazonaws.com",
"https://dynamodb.us-west-1.amazonaws.com",
ServiceInfo{"https://monitoring.us-west-1.amazonaws.com", V2Signature},
"https://autoscaling.us-west-1.amazonaws.com",
ServiceInfo{"https://rds.us-west-1.amazonaws.com", V2Signature},
"https://kinesis.us-west-1.amazonaws.com",
"https://sts.amazonaws.com",
"https://cloudformation.us-west-1.amazonaws.com",
"https://elasticache.us-west-1.amazonaws.com",
}
var USWest2 = Region{
"us-west-2",
"https://ec2.us-west-2.amazonaws.com",
"https://s3-us-west-2.amazonaws.com",
"",
true,
true,
"https://sdb.us-west-2.amazonaws.com",
"https://sns.us-west-2.amazonaws.com",
"https://sqs.us-west-2.amazonaws.com",
"https://email.us-west-2.amazonaws.com",
"https://iam.amazonaws.com",
"https://elasticloadbalancing.us-west-2.amazonaws.com",
"https://dynamodb.us-west-2.amazonaws.com",
ServiceInfo{"https://monitoring.us-west-2.amazonaws.com", V2Signature},
"https://autoscaling.us-west-2.amazonaws.com",
ServiceInfo{"https://rds.us-west-2.amazonaws.com", V2Signature},
"https://kinesis.us-west-2.amazonaws.com",
"https://sts.amazonaws.com",
"https://cloudformation.us-west-2.amazonaws.com",
"https://elasticache.us-west-2.amazonaws.com",
}
var EUWest = Region{
"eu-west-1",
"https://ec2.eu-west-1.amazonaws.com",
"https://s3-eu-west-1.amazonaws.com",
"",
true,
true,
"https://sdb.eu-west-1.amazonaws.com",
"https://sns.eu-west-1.amazonaws.com",
"https://sqs.eu-west-1.amazonaws.com",
"https://email.eu-west-1.amazonaws.com",
"https://iam.amazonaws.com",
"https://elasticloadbalancing.eu-west-1.amazonaws.com",
"https://dynamodb.eu-west-1.amazonaws.com",
ServiceInfo{"https://monitoring.eu-west-1.amazonaws.com", V2Signature},
"https://autoscaling.eu-west-1.amazonaws.com",
ServiceInfo{"https://rds.eu-west-1.amazonaws.com", V2Signature},
"https://kinesis.eu-west-1.amazonaws.com",
"https://sts.amazonaws.com",
"https://cloudformation.eu-west-1.amazonaws.com",
"https://elasticache.eu-west-1.amazonaws.com",
}
var EUCentral = Region{
"eu-central-1",
"https://ec2.eu-central-1.amazonaws.com",
"https://s3-eu-central-1.amazonaws.com",
"",
true,
true,
"https://sdb.eu-central-1.amazonaws.com",
"https://sns.eu-central-1.amazonaws.com",
"https://sqs.eu-central-1.amazonaws.com",
"",
"https://iam.amazonaws.com",
"https://elasticloadbalancing.eu-central-1.amazonaws.com",
"https://dynamodb.eu-central-1.amazonaws.com",
ServiceInfo{"https://monitoring.eu-central-1.amazonaws.com", V2Signature},
"https://autoscaling.eu-central-1.amazonaws.com",
ServiceInfo{"https://rds.eu-central-1.amazonaws.com", V2Signature},
"https://kinesis.eu-central-1.amazonaws.com",
"https://sts.amazonaws.com",
"https://cloudformation.eu-central-1.amazonaws.com",
"",
}
var APSoutheast = Region{
"ap-southeast-1",
"https://ec2.ap-southeast-1.amazonaws.com",
"https://s3-ap-southeast-1.amazonaws.com",
"",
true,
true,
"https://sdb.ap-southeast-1.amazonaws.com",
"https://sns.ap-southeast-1.amazonaws.com",
"https://sqs.ap-southeast-1.amazonaws.com",
"",
"https://iam.amazonaws.com",
"https://elasticloadbalancing.ap-southeast-1.amazonaws.com",
"https://dynamodb.ap-southeast-1.amazonaws.com",
ServiceInfo{"https://monitoring.ap-southeast-1.amazonaws.com", V2Signature},
"https://autoscaling.ap-southeast-1.amazonaws.com",
ServiceInfo{"https://rds.ap-southeast-1.amazonaws.com", V2Signature},
"https://kinesis.ap-southeast-1.amazonaws.com",
"https://sts.amazonaws.com",
"https://cloudformation.ap-southeast-1.amazonaws.com",
"https://elasticache.ap-southeast-1.amazonaws.com",
}
var APSoutheast2 = Region{
"ap-southeast-2",
"https://ec2.ap-southeast-2.amazonaws.com",
"https://s3-ap-southeast-2.amazonaws.com",
"",
true,
true,
"https://sdb.ap-southeast-2.amazonaws.com",
"https://sns.ap-southeast-2.amazonaws.com",
"https://sqs.ap-southeast-2.amazonaws.com",
"",
"https://iam.amazonaws.com",
"https://elasticloadbalancing.ap-southeast-2.amazonaws.com",
"https://dynamodb.ap-southeast-2.amazonaws.com",
ServiceInfo{"https://monitoring.ap-southeast-2.amazonaws.com", V2Signature},
"https://autoscaling.ap-southeast-2.amazonaws.com",
ServiceInfo{"https://rds.ap-southeast-2.amazonaws.com", V2Signature},
"https://kinesis.ap-southeast-2.amazonaws.com",
"https://sts.amazonaws.com",
"https://cloudformation.ap-southeast-2.amazonaws.com",
"https://elasticache.ap-southeast-2.amazonaws.com",
}
var APNortheast = Region{
"ap-northeast-1",
"https://ec2.ap-northeast-1.amazonaws.com",
"https://s3-ap-northeast-1.amazonaws.com",
"",
true,
true,
"https://sdb.ap-northeast-1.amazonaws.com",
"https://sns.ap-northeast-1.amazonaws.com",
"https://sqs.ap-northeast-1.amazonaws.com",
"",
"https://iam.amazonaws.com",
"https://elasticloadbalancing.ap-northeast-1.amazonaws.com",
"https://dynamodb.ap-northeast-1.amazonaws.com",
ServiceInfo{"https://monitoring.ap-northeast-1.amazonaws.com", V2Signature},
"https://autoscaling.ap-northeast-1.amazonaws.com",
ServiceInfo{"https://rds.ap-northeast-1.amazonaws.com", V2Signature},
"https://kinesis.ap-northeast-1.amazonaws.com",
"https://sts.amazonaws.com",
"https://cloudformation.ap-northeast-1.amazonaws.com",
"https://elasticache.ap-northeast-1.amazonaws.com",
}
var SAEast = Region{
"sa-east-1",
"https://ec2.sa-east-1.amazonaws.com",
"https://s3-sa-east-1.amazonaws.com",
"",
true,
true,
"https://sdb.sa-east-1.amazonaws.com",
"https://sns.sa-east-1.amazonaws.com",
"https://sqs.sa-east-1.amazonaws.com",
"",
"https://iam.amazonaws.com",
"https://elasticloadbalancing.sa-east-1.amazonaws.com",
"https://dynamodb.sa-east-1.amazonaws.com",
ServiceInfo{"https://monitoring.sa-east-1.amazonaws.com", V2Signature},
"https://autoscaling.sa-east-1.amazonaws.com",
ServiceInfo{"https://rds.sa-east-1.amazonaws.com", V2Signature},
"",
"https://sts.amazonaws.com",
"https://cloudformation.sa-east-1.amazonaws.com",
"https://elasticache.sa-east-1.amazonaws.com",
}
================================================
FILE: vendor/github.com/zackbloom/goamz/aws/retry.go
================================================
package aws
import (
"math/rand"
"net"
"net/http"
"time"
)
const (
maxDelay = 20 * time.Second
defaultScale = 300 * time.Millisecond
throttlingScale = 500 * time.Millisecond
throttlingScaleRange = throttlingScale / 4
defaultMaxRetries = 3
dynamoDBScale = 25 * time.Millisecond
dynamoDBMaxRetries = 10
)
// A RetryPolicy encapsulates a strategy for implementing client retries.
//
// Default implementations are provided which match the AWS SDKs.
type RetryPolicy interface {
// ShouldRetry returns whether a client should retry a failed request.
ShouldRetry(target string, r *http.Response, err error, numRetries int) bool
// Delay returns the time a client should wait before issuing a retry.
Delay(target string, r *http.Response, err error, numRetries int) time.Duration
}
// DefaultRetryPolicy implements the AWS SDK default retry policy.
//
// It will retry up to 3 times, and uses an exponential backoff with a scale
// factor of 300ms (300ms, 600ms, 1200ms). If the retry is because of
// throttling, the delay will also include some randomness.
//
// See https://github.com/aws/aws-sdk-java/blob/master/aws-java-sdk-core/src/main/java/com/amazonaws/retry/PredefinedRetryPolicies.java#L90.
type DefaultRetryPolicy struct {
}
// ShouldRetry implements the RetryPolicy ShouldRetry method.
func (policy DefaultRetryPolicy) ShouldRetry(target string, r *http.Response, err error, numRetries int) bool {
return shouldRetry(r, err, numRetries, defaultMaxRetries)
}
// Delay implements the RetryPolicy Delay method.
func (policy DefaultRetryPolicy) Delay(target string, r *http.Response, err error, numRetries int) time.Duration {
scale := defaultScale
if err, ok := err.(*Error); ok && isThrottlingException(err) {
scale = throttlingScale + time.Duration(rand.Int63n(int64(throttlingScaleRange)))
}
return exponentialBackoff(numRetries, scale)
}
// DynamoDBRetryPolicy implements the AWS SDK DynamoDB retry policy.
//
// It will retry up to 10 times, and uses an exponential backoff with a scale
// factor of 25ms (25ms, 50ms, 100ms, ...).
//
// See https://github.com/aws/aws-sdk-java/blob/master/aws-java-sdk-core/src/main/java/com/amazonaws/retry/PredefinedRetryPolicies.java#L103.
type DynamoDBRetryPolicy struct {
}
// ShouldRetry implements the RetryPolicy ShouldRetry method.
func (policy DynamoDBRetryPolicy) ShouldRetry(target string, r *http.Response, err error, numRetries int) bool {
return shouldRetry(r, err, numRetries, dynamoDBMaxRetries)
}
// Delay implements the RetryPolicy Delay method.
func (policy DynamoDBRetryPolicy) Delay(target string, r *http.Response, err error, numRetries int) time.Duration {
return exponentialBackoff(numRetries, dynamoDBScale)
}
// NeverRetryPolicy never retries requests and returns immediately on failure.
type NeverRetryPolicy struct {
}
// ShouldRetry implements the RetryPolicy ShouldRetry method.
func (policy NeverRetryPolicy) ShouldRetry(target string, r *http.Response, err error, numRetries int) bool {
return false
}
// Delay implements the RetryPolicy Delay method.
func (policy NeverRetryPolicy) Delay(target string, r *http.Response, err error, numRetries int) time.Duration {
return time.Duration(0)
}
// shouldRetry determines if we should retry the request.
//
// See http://docs.aws.amazon.com/general/latest/gr/api-retries.html.
func shouldRetry(r *http.Response, err error, numRetries int, maxRetries int) bool {
// Once we've exceeded the max retry attempts, game over.
if numRetries >= maxRetries {
return false
}
// Always retry temporary network errors.
if err, ok := err.(net.Error); ok && err.Temporary() {
return true
}
// Always retry 5xx responses.
if r != nil && r.StatusCode >= 500 {
return true
}
// Always retry throttling exceptions.
if err, ok := err.(ServiceError); ok && isThrottlingException(err) {
return true
}
// Other classes of failures indicate a problem with the request. Retrying
// won't help.
return false
}
func exponentialBackoff(numRetries int, scale time.Duration) time.Duration {
if numRetries < 0 {
return time.Duration(0)
}
delay := (1 << uint(numRetries)) * scale
if delay > maxDelay {
return maxDelay
}
return delay
}
func isThrottlingException(err ServiceError) bool {
switch err.ErrorCode() {
case "Throttling", "ThrottlingException", "ProvisionedThroughputExceededException":
return true
default:
return false
}
}
================================================
FILE: vendor/github.com/zackbloom/goamz/aws/sign.go
================================================
package aws
import (
"bytes"
"crypto/hmac"
"crypto/sha256"
"encoding/base64"
"fmt"
"io/ioutil"
"net/http"
"net/url"
"path"
"sort"
"strings"
"time"
)
type V2Signer struct {
auth Auth
service ServiceInfo
host string
}
var b64 = base64.StdEncoding
func NewV2Signer(auth Auth, service ServiceInfo) (*V2Signer, error) {
u, err := url.Parse(service.Endpoint)
if err != nil {
return nil, err
}
return &V2Signer{auth: auth, service: service, host: u.Host}, nil
}
func (s *V2Signer) Sign(method, path string, params map[string]string) {
params["AWSAccessKeyId"] = s.auth.AccessKey
params["SignatureVersion"] = "2"
params["SignatureMethod"] = "HmacSHA256"
if s.auth.Token() != "" {
params["SecurityToken"] = s.auth.Token()
}
// AWS specifies that the parameters in a signed request must
// be provided in the natural order of the keys. This is distinct
// from the natural order of the encoded value of key=value.
// Percent and gocheck.Equals affect the sorting order.
var keys, sarray []string
for k, _ := range params {
keys = append(keys, k)
}
sort.Strings(keys)
for _, k := range keys {
sarray = append(sarray, Encode(k)+"="+Encode(params[k]))
}
joined := strings.Join(sarray, "&")
payload := method + "\n" + s.host + "\n" + path + "\n" + joined
hash := hmac.New(sha256.New, []byte(s.auth.SecretKey))
hash.Write([]byte(payload))
signature := make([]byte, b64.EncodedLen(hash.Size()))
b64.Encode(signature, hash.Sum(nil))
params["Signature"] = string(signature)
}
// Common date formats for signing requests
const (
ISO8601BasicFormat = "20060102T150405Z"
ISO8601BasicFormatShort = "20060102"
)
type Route53Signer struct {
auth Auth
}
func NewRoute53Signer(auth Auth) *Route53Signer {
return &Route53Signer{auth: auth}
}
// getCurrentDate fetches the date stamp from the aws servers to
// ensure the auth headers are within 5 minutes of the server time
func (s *Route53Signer) getCurrentDate() string {
response, err := http.Get("https://route53.amazonaws.com/date")
if err != nil {
fmt.Print("Unable to get date from amazon: ", err)
return ""
}
response.Body.Close()
return response.Header.Get("Date")
}
// Creates the authorize signature based on the date stamp and secret key
func (s *Route53Signer) getHeaderAuthorize(message string) string {
hmacSha256 := hmac.New(sha256.New, []byte(s.auth.SecretKey))
hmacSha256.Write([]byte(message))
cryptedString := hmacSha256.Sum(nil)
return base64.StdEncoding.EncodeToString(cryptedString)
}
// Adds all the required headers for AWS Route53 API to the request
// including the authorization
func (s *Route53Signer) Sign(req *http.Request) {
date := s.getCurrentDate()
authHeader := fmt.Sprintf("AWS3-HTTPS AWSAccessKeyId=%s,Algorithm=%s,Signature=%s",
s.auth.AccessKey, "HmacSHA256", s.getHeaderAuthorize(date))
req.Header.Set("Host", req.Host)
req.Header.Set("X-Amzn-Authorization", authHeader)
req.Header.Set("X-Amz-Date", date)
req.Header.Set("Content-Type", "application/xml")
if s.auth.Token() != "" {
req.Header.Set("X-Amzn-Security-Token", s.auth.Token())
}
}
/*
The V4Signer encapsulates all of the functionality to sign a request with the AWS
Signature Version 4 Signing Process. (http://goo.gl/u1OWZz)
*/
type V4Signer struct {
auth Auth
serviceName string
region Region
// Add the x-amz-content-sha256 header
IncludeXAmzContentSha256 bool
}
/*
Return a new instance of a V4Signer capable of signing AWS requests.
*/
func NewV4Signer(auth Auth, serviceName string, region Region) *V4Signer {
return &V4Signer{
auth: auth,
serviceName: serviceName,
region: region,
IncludeXAmzContentSha256: false,
}
}
/*
Sign a request according to the AWS Signature Version 4 Signing Process. (http://goo.gl/u1OWZz)
The signed request will include an "x-amz-date" header with a current timestamp if a valid "x-amz-date"
or "date" header was not available in the original request. In addition, AWS Signature Version 4 requires
the "host" header to be a signed header, therefor the Sign method will manually set a "host" header from
the request.Host.
The signed request will include a new "Authorization" header indicating that the request has been signed.
Any changes to the request after signing the request will invalidate the signature.
*/
func (s *V4Signer) Sign(req *http.Request) {
req.Header.Set("host", req.Host) // host header must be included as a signed header
t := s.requestTime(req) // Get request time
payloadHash := ""
if _, ok := req.Form["X-Amz-Expires"]; ok {
// We are authenticating the the request by using query params
// (also known as pre-signing a url, http://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-query-string-auth.html)
payloadHash = "UNSIGNED-PAYLOAD"
req.Header.Del("x-amz-date")
req.Form["X-Amz-SignedHeaders"] = []string{s.signedHeaders(req.Header)}
req.Form["X-Amz-Algorithm"] = []string{"AWS4-HMAC-SHA256"}
req.Form["X-Amz-Credential"] = []string{s.auth.AccessKey + "/" + s.credentialScope(t)}
req.Form["X-Amz-Date"] = []string{t.Format(ISO8601BasicFormat)}
req.URL.RawQuery = req.Form.Encode()
} else {
payloadHash = s.payloadHash(req)
if s.IncludeXAmzContentSha256 {
req.Header.Set("x-amz-content-sha256", payloadHash) // x-amz-content-sha256 contains the payload hash
}
}
creq := s.canonicalRequest(req, payloadHash) // Build canonical request
sts := s.stringToSign(t, creq) // Build string to sign
signature := s.signature(t, sts) // Calculate the AWS Signature Version 4
auth := s.authorization(req.Header, t, signature) // Create Authorization header value
if _, ok := req.Form["X-Amz-Expires"]; ok {
req.Form["X-Amz-Signature"] = []string{signature}
} else {
req.Header.Set("Authorization", auth) // Add Authorization header to request
}
return
}
/*
requestTime method will parse the time from the request "x-amz-date" or "date" headers.
If the "x-amz-date" header is present, that will take priority over the "date" header.
If neither header is defined or we are unable to parse either header as a valid date
then we will create a new "x-amz-date" header with the current time.
*/
func (s *V4Signer) requestTime(req *http.Request) time.Time {
// Get "x-amz-date" header
date := req.Header.Get("x-amz-date")
// Attempt to parse as ISO8601BasicFormat
t, err := time.Parse(ISO8601BasicFormat, date)
if err == nil {
return t
}
// Attempt to parse as http.TimeFormat
t, err = time.Parse(http.TimeFormat, date)
if err == nil {
req.Header.Set("x-amz-date", t.Format(ISO8601BasicFormat))
return t
}
// Get "date" header
date = req.Header.Get("date")
// Attempt to parse as http.TimeFormat
t, err = time.Parse(http.TimeFormat, date)
if err == nil {
return t
}
// Create a current time header to be used
t = time.Now().UTC()
req.Header.Set("x-amz-date", t.Format(ISO8601BasicFormat))
return t
}
/*
canonicalRequest method creates the canonical request according to Task 1 of the AWS Signature Version 4 Signing Process. (http://goo.gl/eUUZ3S)
CanonicalRequest =
HTTPRequestMethod + '\n' +
CanonicalURI + '\n' +
CanonicalQueryString + '\n' +
CanonicalHeaders + '\n' +
SignedHeaders + '\n' +
HexEncode(Hash(Payload))
payloadHash is optional; use the empty string and it will be calculated from the request
*/
func (s *V4Signer) canonicalRequest(req *http.Request, payloadHash string) string {
if payloadHash == "" {
payloadHash = s.payloadHash(req)
}
c := new(bytes.Buffer)
fmt.Fprintf(c, "%s\n", req.Method)
fmt.Fprintf(c, "%s\n", s.canonicalURI(req.URL))
fmt.Fprintf(c, "%s\n", s.canonicalQueryString(req.URL))
fmt.Fprintf(c, "%s\n\n", s.canonicalHeaders(req.Header))
fmt.Fprintf(c, "%s\n", s.signedHeaders(req.Header))
fmt.Fprintf(c, "%s", payloadHash)
return c.String()
}
func (s *V4Signer) canonicalURI(u *url.URL) string {
u = &url.URL{Path: u.Path}
canonicalPath := u.String()
slash := strings.HasSuffix(canonicalPath, "/")
canonicalPath = path.Clean(canonicalPath)
if canonicalPath == "" || canonicalPath == "." {
canonicalPath = "/"
}
if canonicalPath != "/" && slash {
canonicalPath += "/"
}
return canonicalPath
}
func (s *V4Signer) canonicalQueryString(u *url.URL) string {
var a []string
for k, vs := range u.Query() {
k = url.QueryEscape(k)
for _, v := range vs {
if v == "" {
a = append(a, k+"=")
} else {
v = url.QueryEscape(v)
a = append(a, k+"="+v)
}
}
}
sort.Strings(a)
return strings.Join(a, "&")
}
func (s *V4Signer) canonicalHeaders(h http.Header) string {
i, a, lowerCase := 0, make([]string, len(h)), make(map[string][]string)
for k, v := range h {
lowerCase[strings.ToLower(k)] = v
}
var keys []string
for k := range lowerCase {
keys = append(keys, k)
}
sort.Strings(keys)
for _, k := range keys {
v := lowerCase[k]
for j, w := range v {
v[j] = strings.Trim(w, " ")
}
sort.Strings(v)
a[i] = strings.ToLower(k) + ":" + strings.Join(v, ",")
i++
}
return strings.Join(a, "\n")
}
func (s *V4Signer) signedHeaders(h http.Header) string {
i, a := 0, make([]string, len(h))
for k, _ := range h {
a[i] = strings.ToLower(k)
i++
}
sort.Strings(a)
return strings.Join(a, ";")
}
func (s *V4Signer) payloadHash(req *http.Request) string {
var b []byte
if req.Body == nil {
b = []byte("")
} else {
var err error
b, err = ioutil.ReadAll(req.Body)
if err != nil {
// TODO: I REALLY DON'T LIKE THIS PANIC!!!!
panic(err)
}
}
req.Body = ioutil.NopCloser(bytes.NewBuffer(b))
return s.hash(string(b))
}
/*
stringToSign method creates the string to sign accorting to Task 2 of the AWS Signature Version 4 Signing Process. (http://goo.gl/es1PAu)
StringToSign =
Algorithm + '\n' +
RequestDate + '\n' +
CredentialScope + '\n' +
HexEncode(Hash(CanonicalRequest))
*/
func (s *V4Signer) stringToSign(t time.Time, creq string) string {
w := new(bytes.Buffer)
fmt.Fprint(w, "AWS4-HMAC-SHA256\n")
fmt.Fprintf(w, "%s\n", t.Format(ISO8601BasicFormat))
fmt.Fprintf(w, "%s\n", s.credentialScope(t))
fmt.Fprintf(w, "%s", s.hash(creq))
return w.String()
}
func (s *V4Signer) credentialScope(t time.Time) string {
return fmt.Sprintf("%s/%s/%s/aws4_request", t.Format(ISO8601BasicFormatShort), s.region.Name, s.serviceName)
}
/*
signature method calculates the AWS Signature Version 4 according to Task 3 of the AWS Signature Version 4 Signing Process. (http://goo.gl/j0Yqe1)
signature = HexEncode(HMAC(derived-signing-key, string-to-sign))
*/
func (s *V4Signer) signature(t time.Time, sts string) string {
h := s.hmac(s.derivedKey(t), []byte(sts))
return fmt.Sprintf("%x", h)
}
/*
derivedKey method derives a signing key to be used for signing a request.
kSecret = Your AWS Secret Access Key
kDate = HMAC("AWS4" + kSecret, Date)
kRegion = HMAC(kDate, Region)
kService = HMAC(kRegion, Service)
kSigning = HMAC(kService, "aws4_request")
*/
func (s *V4Signer) derivedKey(t time.Time) []byte {
h := s.hmac([]byte("AWS4"+s.auth.SecretKey), []byte(t.Format(ISO8601BasicFormatShort)))
h = s.hmac(h, []byte(s.region.Name))
h = s.hmac(h, []byte(s.serviceName))
h = s.hmac(h, []byte("aws4_request"))
return h
}
/*
authorization method generates the authorization header value.
*/
func (s *V4Signer) authorization(header http.Header, t time.Time, signature string) string {
w := new(bytes.Buffer)
fmt.Fprint(w, "AWS4-HMAC-SHA256 ")
fmt.Fprintf(w, "Credential=%s/%s, ", s.auth.AccessKey, s.credentialScope(t))
fmt.Fprintf(w, "SignedHeaders=%s, ", s.signedHeaders(header))
fmt.Fprintf(w, "Signature=%s", signature)
return w.String()
}
// hash method calculates the sha256 hash for a given string
func (s *V4Signer) hash(in string) string {
h := sha256.New()
fmt.Fprintf(h, "%s", in)
return fmt.Sprintf("%x", h.Sum(nil))
}
// hmac method calculates the sha256 hmac for a given slice of bytes
func (s *V4Signer) hmac(key, data []byte) []byte {
h := hmac.New(sha256.New, key)
h.Write(data)
return h.Sum(nil)
}
================================================
FILE: vendor/github.com/zackbloom/goamz/cloudfront/cloudfront.go
================================================
package cloudfront
import (
"bytes"
"crypto"
"crypto/rsa"
"crypto/sha1"
"encoding/base64"
"encoding/json"
"encoding/xml"
"fmt"
"net/http"
"net/url"
"strconv"
"strings"
"time"
"github.com/zackbloom/goamz/aws"
)
const (
ServiceName = "cloudfront"
ApiVersion = "2014-11-06"
)
// TODO Reconcile with 'New' fn below
func NewCloudFront(auth aws.Auth) *CloudFront {
signer := aws.NewV4Signer(auth, "cloudfront", aws.USEast)
return &CloudFront{
Signer: signer,
Auth: auth,
}
}
type CloudFront struct {
Signer *aws.V4Signer
Auth aws.Auth
BaseURL string
keyPairId string
key *rsa.PrivateKey
}
type DistributionConfig struct {
XMLName xml.Name `xml:"DistributionConfig"`
CallerReference string
Aliases Aliases
DefaultRootObject string
Origins Origins
DefaultCacheBehavior CacheBehavior
Comment string
CacheBehaviors CacheBehaviors
CustomErrorResponses CustomErrorResponses
Restrictions *GeoRestriction `xml:"Restrictions>GeoRestriction,omitempty"`
Logging Logging
ViewerCertificate *ViewerCertificate `xml:",omitempty"`
PriceClass string
Enabled bool
}
type DistributionSummary struct {
XMLName xml.Name `xml:"Distribution"`
DistributionConfig
DomainName string
Status string
Id string
LastModifiedTime time.Time
}
type Aliases []string
type EncodedAliases struct {
Quantity int
Items []string `xml:"Items>CNAME"`
}
func (a Aliases) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
enc := EncodedAliases{
Quantity: len(a),
Items: []string(a),
}
return e.EncodeElement(enc, start)
}
func (n *Aliases) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
enc := EncodedAliases{}
err := d.DecodeElement(&enc, &start)
if err != nil {
return err
}
*n = enc.Items
return nil
}
type CustomErrorResponses []CustomErrorResponse
type EncodedCustomErrorResponses struct {
Quantity int
Items []CustomErrorResponse `xml:"Items>CustomErrorResponse"`
}
func (a CustomErrorResponses) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
enc := EncodedCustomErrorResponses{
Quantity: len(a),
Items: []CustomErrorResponse(a),
}
return e.EncodeElement(enc, start)
}
func (n *CustomErrorResponses) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
enc := EncodedCustomErrorResponses{}
err := d.DecodeElement(&enc, &start)
if err != nil {
return err
}
*n = enc.Items
return nil
}
type CacheBehaviors []CacheBehavior
type EncodedCacheBehaviors struct {
Quantity int
Items []CacheBehavior `xml:"Items>CacheBehavior"`
}
func (a CacheBehaviors) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
enc := EncodedCacheBehaviors{
Quantity: len(a),
Items: []CacheBehavior(a),
}
return e.EncodeElement(enc, start)
}
func (n *CacheBehaviors) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
enc := EncodedCacheBehaviors{}
err := d.DecodeElement(&enc, &start)
if err != nil {
return err
}
*n = enc.Items
return nil
}
type Logging struct {
Enabled bool
IncludeCookies bool
Bucket string
Prefix string
}
type ViewerCertificate struct {
IAMCertificateId string `xml:",omitempty"`
CloudFrontDefaultCertificate bool `xml:",omitempty"`
SSLSupportMethod string
MinimumProtocolVersion string
}
type GeoRestriction struct {
RestrictionType string
Locations []string
}
type EncodedGeoRestriction struct {
RestrictionType string
Quantity int
Locations []string `xml:"Items>Location"`
}
func (a GeoRestriction) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
enc := EncodedGeoRestriction{
RestrictionType: a.RestrictionType,
Quantity: len(a.Locations),
Locations: []string(a.Locations),
}
return e.EncodeElement(enc, start)
}
func (n *GeoRestriction) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
enc := EncodedGeoRestriction{}
err := d.DecodeElement(&enc, &start)
if err != nil {
return err
}
n.Locations = enc.Locations
n.RestrictionType = enc.RestrictionType
return nil
}
type CustomErrorResponse struct {
XMLName xml.Name `xml:"CustomErrorResponse"`
ErrorCode int
ResponsePagePath string
ResponseCode int
ErrorCachingMinTTL int
}
type Origin struct {
XMLName xml.Name `xml:"Origin"`
Id string
DomainName string
OriginPath string `xml:"OriginPath,omitempty"`
S3OriginConfig *S3OriginConfig `xml:",omitempty"`
CustomOriginConfig *CustomOriginConfig `xml:",omitempty"`
}
type S3OriginConfig struct {
OriginAccessIdentity string
}
type CustomOriginConfig struct {
HTTPPort int
HTTPSPort int
OriginProtocolPolicy string
}
type Origins []Origin
type EncodedOrigins struct {
Quantity int
Items []Origin `xml:"Items>Origin"`
}
func (o Origins) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
enc := EncodedOrigins{
Quantity: len(o),
Items: []Origin(o),
}
return e.EncodeElement(enc, start)
}
func (o *Origins) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
enc := EncodedOrigins{}
err := d.DecodeElement(&enc, &start)
if err != nil {
return err
}
*o = Origins(enc.Items)
return nil
}
type CacheBehavior struct {
TargetOriginId string
PathPattern string `xml:",omitempty"`
ForwardedValues ForwardedValues
TrustedSigners TrustedSigners
ViewerProtocolPolicy string
MinTTL int
AllowedMethods AllowedMethods
SmoothStreaming bool
}
type ForwardedValues struct {
QueryString bool
Cookies *Cookies
Headers Names
}
type Cookies struct {
Forward string
WhitelistedNames Names
}
var CookiesDefault = Cookies{
Forward: "none",
WhitelistedNames: Names{},
}
func cacheBehaviorDefault(cache *CacheBehavior) {
if cache.ForwardedValues.Cookies == nil {
clone := CookiesDefault
cache.ForwardedValues.Cookies = &clone
}
}
type Names []string
type EncodedNames struct {
Quantity int
Items []string `xml:"Items>Name"`
}
func (w Names) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
enc := EncodedNames{
Quantity: len(w),
Items: []string(w),
}
return e.EncodeElement(enc, start)
}
func (n *Names) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
enc := EncodedNames{}
err := d.DecodeElement(&enc, &start)
if err != nil {
return err
}
*n = Names(enc.Items)
return nil
}
type ItemsList []string
type TrustedSigners struct {
Enabled bool
AWSAccountNumbers []string
}
type EncodedTrustedSigners struct {
Enabled bool
Quantity int
Items []string `xml:"Items>AWSAccountNumber"`
}
func (n TrustedSigners) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
enc := EncodedTrustedSigners{
Enabled: n.Enabled,
Quantity: len(n.AWSAccountNumbers),
Items: n.AWSAccountNumbers,
}
return e.EncodeElement(enc, start)
}
func (n *TrustedSigners) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
enc := EncodedTrustedSigners{}
err := d.DecodeElement(&enc, &start)
if err != nil {
return err
}
n.AWSAccountNumbers = enc.Items
n.Enabled = enc.Enabled
return nil
}
type AllowedMethods struct {
Allowed []string `xml:"Items"`
Cached []string `xml:"CachedMethods>Items,omitempty"`
}
type EncodedAllowedMethods struct {
AllowedQuantity int `xml:"Quantity"`
Allowed []string `xml:"Items>Method"`
CachedQuantity int `xml:"CachedMethods>Quantity"`
Cached []string `xml:"CachedMethods>Items>Method"`
}
func (n AllowedMethods) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
enc := EncodedAllowedMethods{
AllowedQuantity: len(n.Allowed),
Allowed: n.Allowed,
CachedQuantity: len(n.Cached),
Cached: n.Cached,
}
return e.EncodeElement(enc, start)
}
func (n *AllowedMethods) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
enc := EncodedAllowedMethods{}
err := d.DecodeElement(&enc, &start)
if err != nil {
return err
}
n.Allowed = enc.Allowed
n.Cached = enc.Cached
return nil
}
var base64Replacer = strings.NewReplacer("=", "_", "+", "-", "/", "~")
func NewKeyLess(auth aws.Auth, baseurl string) *CloudFront {
return &CloudFront{keyPairId: auth.AccessKey, BaseURL: baseurl}
}
func New(baseurl string, key *rsa.PrivateKey, keyPairId string) *CloudFront {
return &CloudFront{
BaseURL: baseurl,
keyPairId: keyPairId,
key: key,
}
}
type epochTime struct {
EpochTime int64 `json:"AWS:EpochTime"`
}
type condition struct {
DateLessThan epochTime
}
type statement struct {
Resource string
Condition condition
}
type policy struct {
Statement []statement
}
func buildPolicy(resource string, expireTime time.Time) ([]byte, error) {
p := &policy{
Statement: []statement{
statement{
Resource: resource,
Condition: condition{
DateLessThan: epochTime{
EpochTime: expireTime.Truncate(time.Millisecond).Unix(),
},
},
},
},
}
return json.Marshal(p)
}
func (cf *CloudFront) generateSignature(policy []byte) (string, error) {
hash := sha1.New()
_, err := hash.Write(policy)
if err != nil {
return "", err
}
hashed := hash.Sum(nil)
var signed []byte
if cf.key.Validate() == nil {
signed, err = rsa.SignPKCS1v15(nil, cf.key, crypto.SHA1, hashed)
if err != nil {
return "", err
}
} else {
signed = hashed
}
encoded := base64Replacer.Replace(base64.StdEncoding.EncodeToString(signed))
return encoded, nil
}
// Create a CloudFront distribution
//
// Usage:
// conf := cloudfront.DistributionConfig{
// Enabled: true,
//
// Origins: cloudfront.Origins{
// cloudfront.Origin{
// Id: "test",
// DomainName: "example.com",
// CustomOriginConfig: &cloudfront.CustomOriginConfig{
// HTTPPort: 80,
// HTTPSPort: 443,
// OriginProtocolPolicy: "http-only",
// },
// },
// },
//
// DefaultCacheBehavior: cloudfront.CacheBehavior{
// TargetOriginId: "test",
// PathPattern: "/test",
// ForwardedValues: cloudfront.ForwardedValues{
// QueryString: true,
// Cookies: cloudfront.Cookies{
// Forward: "whitelist",
// WhitelistedNames: cloudfront.Names{
// "cat",
// "dog",
// },
// },
// Headers: cloudfront.Names{
// "horse",
// "pig",
// },
// },
// ViewerProtocolPolicy: "allow-all",
// MinTTL: 300,
// AllowedMethods: cloudfront.AllowedMethods{
// Allowed: []string{"GET", "HEAD"},
// Cached: []string{"GET", "HEAD"},
// },
// },
//
// Restrictions: cloudfront.GeoRestriction{
// RestrictionType: "blacklist",
// Locations: []string{
// "CA",
// "DE",
// },
// },
//
// CustomErrorResponses: cloudfront.CustomErrorResponses{
// cloudfront.CustomErrorResponse{
// ErrorCode: 404,
// ResponseCode: 403,
// ResponsePagePath: "/index.html",
// },
// },
//
// PriceClass: "PriceClass_All",
// }
//
// cf := cloudfront.NewCloudFront(aws.Auth{
// AccessKey: // ...
// SecretKey: // ...
// })
// cf.CreateDistribution(conf)
func (cf *CloudFront) Create(config DistributionConfig) (summary DistributionSummary, err error) {
if config.CallerReference == "" {
config.CallerReference = strconv.FormatInt(time.Now().Unix(), 10)
}
cacheBehaviorDefault(&config.DefaultCacheBehavior)
for i, _ := range config.CacheBehaviors {
cacheBehaviorDefault(&(config.CacheBehaviors[i]))
}
body, err := xml.Marshal(config)
if err != nil {
return
}
client := http.Client{}
req, err := http.NewRequest("POST", "https://"+ServiceName+".amazonaws.com/"+ApiVersion+"/distribution", bytes.NewReader(body))
if err != nil {
return
}
cf.Signer.Sign(req)
resp, err := client.Do(req)
if err != nil {
return
}
defer resp.Body.Close()
if resp.StatusCode >= 400 {
errors := aws.ErrorResponse{}
xml.NewDecoder(resp.Body).Decode(&errors)
err := errors.Errors
err.RequestId = errors.RequestId
err.StatusCode = resp.StatusCode
if err.Message == "" {
err.Message = resp.Status
}
return summary, &err
} else {
err = xml.NewDecoder(resp.Body).Decode(&summary)
}
return
}
type DistributionItem struct {
XMLName xml.Name `xml:"DistributionSummary"`
DistributionSummary
}
type DistributionsResp struct {
Items []DistributionItem `xml:"Items>DistributionSummary"`
IsTruncated bool
Marker string
// Use this to get the next page of results if IsTruncated is true
NextMarker string
// Total number in account
Quantity int
MaxItems int
}
// Marker is an optional pointer to the NextMarker from the previous page of results
// Max is the maximum number of results to return, max 100
func (cf *CloudFront) List(marker string, max int) (items *DistributionsResp, err error) {
params := url.Values{
"MaxItems": []string{strconv.FormatInt(int64(max), 10)},
}
if marker != "" {
params["Marker"] = []string{marker}
}
uri, _ := url.Parse("https://" + ServiceName + ".amazonaws.com/" + ApiVersion + "/distribution")
uri.RawQuery = params.Encode()
client := http.Client{}
req, err := http.NewRequest("GET", uri.String(), nil)
if err != nil {
return
}
cf.Signer.Sign(req)
resp, err := client.Do(req)
if err != nil {
return
}
defer resp.Body.Close()
if resp.StatusCode >= 400 {
errors := aws.ErrorResponse{}
xml.NewDecoder(resp.Body).Decode(&errors)
errors.Errors.RequestId = errors.RequestId
errors.Errors.StatusCode = resp.StatusCode
if errors.Errors.Message == "" {
errors.Errors.Message = resp.Status
}
err = &errors.Errors
} else {
items = &DistributionsResp{}
err = xml.NewDecoder(resp.Body).Decode(items)
}
return
}
func (cf *CloudFront) FindDistributionByAlias(alias string) (dist *DistributionSummary, err error) {
marker := ""
for page := 0; page < 10; page++ {
var resp *DistributionsResp
resp, err = cf.List(marker, 100)
if err != nil {
return
}
if resp.Quantity > 1000 {
panic("More than 1000 CloudFront distributions in account, not all will be correctly searched")
}
var item DistributionItem
for _, item = range resp.Items {
for _, _alias := range item.Aliases {
if _alias == alias {
dist = &(item.DistributionSummary)
return
}
}
}
marker = resp.NextMarker
if !resp.IsTruncated {
break
}
}
return
}
// Creates a signed url using RSAwithSHA1 as specified by
// http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/private-content-creating-signed-url-canned-policy.html#private-content-canned-policy-creating-signature
func (cf *CloudFront) CannedSignedURL(path, queryString string, expires time.Time) (string, error) {
resource := cf.BaseURL + path
if queryString != "" {
resource = path + "?" + queryString
}
policy, err := buildPolicy(resource, expires)
if err != nil {
return "", err
}
signature, err := cf.generateSignature(policy)
if err != nil {
return "", err
}
// TOOD: Do this once
uri, err := url.Parse(cf.BaseURL)
if err != nil {
return "", err
}
uri.RawQuery = queryString
if queryString != "" {
uri.RawQuery += "&"
}
expireTime := expires.Truncate(time.Millisecond).Unix()
uri.Path = path
uri.RawQuery += fmt.Sprintf("Expires=%d&Signature=%s&Key-Pair-Id=%s", expireTime, signature, cf.keyPairId)
return uri.String(), nil
}
func (cloudfront *CloudFront) SignedURL(path, querystrings string, expires time.Time) string {
policy := `{"Statement":[{"Resource":"` + path + "?" + querystrings + `,"Condition":{"DateLessThan":{"AWS:EpochTime":` + strconv.FormatInt(expires.Truncate(time.Millisecond).Unix(), 10) + `}}}]}`
hash := sha1.New()
hash.Write([]byte(policy))
b := hash.Sum(nil)
he := base64.StdEncoding.EncodeToString(b)
policySha1 := he
url := cloudfront.BaseURL + path + "?" + querystrings + "&Expires=" + strconv.FormatInt(expires.Unix(), 10) + "&Signature=" + policySha1 + "&Key-Pair-Id=" + cloudfront.keyPairId
return url
}
================================================
FILE: vendor/github.com/zackbloom/goamz/iam/iam.go
================================================
// The iam package provides types and functions for interaction with the AWS
// Identity and Access Management (IAM) service.
package iam
import (
"encoding/xml"
"github.com/zackbloom/goamz/aws"
"net/http"
"net/url"
"strconv"
"strings"
"time"
)
// The IAM type encapsulates operations operations with the IAM endpoint.
type IAM struct {
aws.Auth
aws.Region
}
// New creates a new IAM instance.
func New(auth aws.Auth, region aws.Region) *IAM {
return &IAM{auth, region}
}
func (iam *IAM) query(params map[string]string, resp interface{}) error {
params["Version"] = "2010-05-08"
params["Timestamp"] = time.Now().In(time.UTC).Format(time.RFC3339)
endpoint, err := url.Parse(iam.IAMEndpoint)
if err != nil {
return err
}
sign(iam.Auth, "GET", "/", params, endpoint.Host)
endpoint.RawQuery = multimap(params).Encode()
r, err := http.Get(endpoint.String())
if err != nil {
return err
}
defer r.Body.Close()
if r.StatusCode > 200 {
return buildError(r)
}
return xml.NewDecoder(r.Body).Decode(resp)
}
func (iam *IAM) postQuery(params map[string]string, resp interface{}) error {
endpoint, err := url.Parse(iam.IAMEndpoint)
if err != nil {
return err
}
params["Version"] = "2010-05-08"
params["Timestamp"] = time.Now().In(time.UTC).Format(time.RFC3339)
sign(iam.Auth, "POST", "/", params, endpoint.Host)
encoded := multimap(params).Encode()
body := strings.NewReader(encoded)
req, err := http.NewRequest("POST", endpoint.String(), body)
if err != nil {
return err
}
req.Header.Set("Host", endpoint.Host)
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
req.Header.Set("Content-Length", strconv.Itoa(len(encoded)))
r, err := http.DefaultClient.Do(req)
if err != nil {
return err
}
defer r.Body.Close()
if r.StatusCode > 200 {
return buildError(r)
}
return xml.NewDecoder(r.Body).Decode(resp)
}
func buildError(r *http.Response) error {
var (
err Error
errors xmlErrors
)
xml.NewDecoder(r.Body).Decode(&errors)
if len(errors.Errors) > 0 {
err = errors.Errors[0]
}
err.StatusCode = r.StatusCode
if err.Message == "" {
err.Message = r.Status
}
return &err
}
func multimap(p map[string]string) url.Values {
q := make(url.Values, len(p))
for k, v := range p {
q[k] = []string{v}
}
return q
}
// Response to a CreateUser request.
//
// See http://goo.gl/JS9Gz for more details.
type CreateUserResp struct {
RequestId string `xml:"ResponseMetadata>RequestId"`
User User `xml:"CreateUserResult>User"`
}
// User encapsulates a user managed by IAM.
//
// See http://goo.gl/BwIQ3 for more details.
type User struct {
Arn string
Path string
Id string `xml:"UserId"`
Name string `xml:"UserName"`
}
// CreateUser creates a new user in IAM.
//
// See http://goo.gl/JS9Gz for more details.
func (iam *IAM) CreateUser(name, path string) (*CreateUserResp, error) {
params := map[string]string{
"Action": "CreateUser",
"Path": path,
"UserName": name,
}
resp := new(CreateUserResp)
if err := iam.query(params, resp); err != nil {
return nil, err
}
return resp, nil
}
// Response for GetUser requests.
//
// See http://goo.gl/ZnzRN for more details.
type GetUserResp struct {
RequestId string `xml:"ResponseMetadata>RequestId"`
User User `xml:"GetUserResult>User"`
}
// GetUser gets a user from IAM.
//
// See http://goo.gl/ZnzRN for more details.
func (iam *IAM) GetUser(name string) (*GetUserResp, error) {
params := map[string]string{
"Action": "GetUser",
}
if name != "" {
params["UserName"] = name
}
resp := new(GetUserResp)
if err := iam.query(params, resp); err != nil {
return nil, err
}
return resp, nil
}
// DeleteUser deletes a user from IAM.
//
// See http://goo.gl/jBuCG for more details.
func (iam *IAM) DeleteUser(name string) (*SimpleResp, error) {
params := map[string]string{
"Action": "DeleteUser",
"UserName": name,
}
resp := new(SimpleResp)
if err := iam.query(params, resp); err != nil {
return nil, err
}
return resp, nil
}
// Response to a CreateGroup request.
//
// See http://goo.gl/n7NNQ for more details.
type CreateGroupResp struct {
Group Group `xml:"CreateGroupResult>Group"`
RequestId string `xml:"ResponseMetadata>RequestId"`
}
// Group encapsulates a group managed by IAM.
//
// See http://goo.gl/ae7Vs for more details.
type Group struct {
Arn string
Id string `xml:"GroupId"`
Name string `xml:"GroupName"`
Path string
}
// CreateGroup creates a new group in IAM.
//
// The path parameter can be used to identify which division or part of the
// organization the user belongs to.
//
// If path is unset ("") it defaults to "/".
//
// See http://goo.gl/n7NNQ for more details.
func (iam *IAM) CreateGroup(name string, path string) (*CreateGroupResp, error) {
params := map[string]string{
"Action": "CreateGroup",
"GroupName": name,
}
if path != "" {
params["Path"] = path
}
resp := new(CreateGroupResp)
if err := iam.query(params, resp); err != nil {
return nil, err
}
return resp, nil
}
// Response to a ListGroups request.
//
// See http://goo.gl/W2TRj for more details.
type GroupsResp struct {
Groups []Group `xml:"ListGroupsResult>Groups>member"`
RequestId string `xml:"ResponseMetadata>RequestId"`
}
// Groups list the groups that have the specified path prefix.
//
// The parameter pathPrefix is optional. If pathPrefix is "", all groups are
// returned.
//
// See http://goo.gl/W2TRj for more details.
func (iam *IAM) Groups(pathPrefix string) (*GroupsResp, error) {
params := map[string]string{
"Action": "ListGroups",
}
if pathPrefix != "" {
params["PathPrefix"] = pathPrefix
}
resp := new(GroupsResp)
if err := iam.query(params, resp); err != nil {
return nil, err
}
return resp, nil
}
// DeleteGroup deletes a group from IAM.
//
// See http://goo.gl/d5i2i for more details.
func (iam *IAM) DeleteGroup(name string) (*SimpleResp, error) {
params := map[string]string{
"Action": "DeleteGroup",
"GroupName": name,
}
resp := new(SimpleResp)
if err := iam.query(params, resp); err != nil {
return nil, err
}
return resp, nil
}
// Response to a CreateAccessKey request.
//
// See http://goo.gl/L46Py for more details.
type CreateAccessKeyResp struct {
RequestId string `xml:"ResponseMetadata>RequestId"`
AccessKey AccessKey `xml:"Crea
gitextract_dxdit0ui/
├── .github/
│ └── workflows/
│ └── semgrep.yml
├── .gitignore
├── Godeps/
│ ├── Godeps.json
│ └── Readme
├── LICENSE
├── README.md
├── docs/
│ └── getting-started.md
├── src/
│ ├── admin.go
│ ├── cli.go
│ ├── deploy.go
│ ├── rollback.go
│ └── utils.go
├── utils/
│ ├── build.sh
│ ├── create_site.sh
│ ├── release.sh
│ └── xc.sh
└── vendor/
├── github.com/
│ ├── cenk/
│ │ └── backoff/
│ │ ├── .gitignore
│ │ ├── .travis.yml
│ │ ├── LICENSE
│ │ ├── README.md
│ │ ├── backoff.go
│ │ ├── exponential.go
│ │ ├── retry.go
│ │ └── ticker.go
│ ├── imdario/
│ │ └── mergo/
│ │ ├── .travis.yml
│ │ ├── LICENSE
│ │ ├── README.md
│ │ ├── doc.go
│ │ ├── map.go
│ │ ├── merge.go
│ │ └── mergo.go
│ ├── mitchellh/
│ │ └── go-homedir/
│ │ ├── LICENSE
│ │ ├── README.md
│ │ └── homedir.go
│ ├── wsxiaoys/
│ │ └── terminal/
│ │ ├── LICENSE
│ │ └── color/
│ │ └── color.go
│ └── zackbloom/
│ ├── go-ini/
│ │ ├── .gitignore
│ │ ├── README.md
│ │ ├── decode.go
│ │ └── stack.go
│ └── goamz/
│ ├── LICENSE
│ ├── aws/
│ │ ├── attempt.go
│ │ ├── aws.go
│ │ ├── client.go
│ │ ├── regions.go
│ │ ├── retry.go
│ │ └── sign.go
│ ├── cloudfront/
│ │ └── cloudfront.go
│ ├── iam/
│ │ ├── iam.go
│ │ └── sign.go
│ ├── route53/
│ │ └── route53.go
│ └── s3/
│ ├── lifecycle.go
│ ├── multi.go
│ ├── s3.go
│ └── sign.go
├── golang.org/
│ └── x/
│ ├── crypto/
│ │ ├── LICENSE
│ │ ├── PATENTS
│ │ └── ssh/
│ │ └── terminal/
│ │ ├── terminal.go
│ │ ├── util.go
│ │ ├── util_bsd.go
│ │ ├── util_linux.go
│ │ ├── util_plan9.go
│ │ └── util_windows.go
│ └── net/
│ ├── LICENSE
│ ├── PATENTS
│ ├── html/
│ │ ├── atom/
│ │ │ ├── atom.go
│ │ │ ├── gen.go
│ │ │ └── table.go
│ │ ├── const.go
│ │ ├── doc.go
│ │ ├── doctype.go
│ │ ├── entity.go
│ │ ├── escape.go
│ │ ├── foreign.go
│ │ ├── node.go
│ │ ├── parse.go
│ │ ├── render.go
│ │ └── token.go
│ └── publicsuffix/
│ ├── gen.go
│ ├── list.go
│ └── table.go
└── gopkg.in/
└── yaml.v1/
├── LICENSE
├── LICENSE.libyaml
├── README.md
├── apic.go
├── decode.go
├── emitterc.go
├── encode.go
├── parserc.go
├── readerc.go
├── resolve.go
├── scannerc.go
├── sorter.go
├── writerc.go
├── yaml.go
├── yamlh.go
└── yamlprivateh.go
SYMBOL INDEX (1617 symbols across 63 files)
FILE: src/admin.go
function CreateBucket (line 17) | func CreateBucket(options Options) error {
function GetDistribution (line 55) | func GetDistribution(options Options) (dist cloudfront.DistributionSumma...
function CreateUser (line 120) | func CreateUser(options Options) (key iam.AccessKey, err error) {
function UpdateRoute (line 164) | func UpdateRoute(options Options, dist cloudfront.DistributionSummary) e...
function Create (line 233) | func Create(options Options) {
function createCmd (line 318) | func createCmd() {
FILE: src/cli.go
function printUsage (line 8) | func printUsage() {
function main (line 30) | func main() {
FILE: src/deploy.go
constant SCRIPT (line 30) | SCRIPT = iota
constant STYLE (line 31) | STYLE
constant UPLOAD_WORKERS (line 34) | UPLOAD_WORKERS = 20
function hashFile (line 42) | func hashFile(path string) []byte {
function hashBytes (line 57) | func hashBytes(data []byte) []byte {
function hashFiles (line 63) | func hashFiles(files []string) string {
function getRef (line 75) | func getRef() string {
function guessContentType (line 87) | func guessContentType(file string) string {
function shouldCompress (line 91) | func shouldCompress(file string) bool {
type UploadFileRequest (line 102) | type UploadFileRequest struct
function uploadFile (line 111) | func uploadFile(req UploadFileRequest) (remotePath string) {
type FileRef (line 161) | type FileRef struct
type FileInst (line 167) | type FileInst struct
function writeFiles (line 172) | func writeFiles(options Options, includeHash bool, files chan *FileRef) {
function deployFiles (line 205) | func deployFiles(options Options, includeHash bool, files []*FileRef) {
function addFiles (line 230) | func addFiles(form uint8, parent *html.Node, files []string) {
function isLocal (line 265) | func isLocal(href string) bool {
function formatHref (line 270) | func formatHref(path string) string {
function renderHTML (line 277) | func renderHTML(options Options, file HTMLFile) string {
function parseHTML (line 335) | func parseHTML(options Options, path string) (files []string, base strin...
function deployHTML (line 389) | func deployHTML(options Options, id string, file HTMLFile) {
function expandFiles (line 413) | func expandFiles(root string, glob string) []string {
function listFiles (line 447) | func listFiles(options Options) []*FileRef {
function ignoreFiles (line 467) | func ignoreFiles(full []*FileRef, rem []*FileRef) []*FileRef {
function extractFileList (line 489) | func extractFileList(options Options, pattern string) (files []string) {
function filesWithExtension (line 509) | func filesWithExtension(files []*FileRef, ext string) (outFiles []*FileR...
type HTMLFile (line 520) | type HTMLFile struct
method GetLocalPath (line 526) | func (f HTMLFile) GetLocalPath() string {
function Deploy (line 530) | func Deploy(options Options) {
function deployCmd (line 681) | func deployCmd() {
FILE: src/rollback.go
function Rollback (line 12) | func Rollback(options Options, version string) {
function rollbackCmd (line 64) | func rollbackCmd() {
FILE: src/utils.go
constant LIMITED (line 25) | LIMITED = 60
constant FOREVER (line 26) | FOREVER = 31556926
function getRegion (line 34) | func getRegion(region string, s3Host string) aws.Region {
function openS3 (line 48) | func openS3(key, secret, region, s3Host string) *s3.S3 {
function openIAM (line 58) | func openIAM(key, secret, region string) *iam.IAM {
function openCloudFront (line 68) | func openCloudFront(key, secret string) *cloudfront.CloudFront {
function openRoute53 (line 76) | func openRoute53(key, secret string) *route53.Route53 {
function panicIf (line 86) | func panicIf(err error) {
function must (line 91) | func must(val interface{}, err error) interface{} {
function mustString (line 98) | func mustString(val string, err error) string {
function mustInt (line 102) | func mustInt(val int, err error) int {
type Options (line 107) | type Options struct
function parseOptions (line 121) | func parseOptions() (o Options, set *flag.FlagSet) {
type ConfigFile (line 142) | type ConfigFile
function loadConfigFile (line 144) | func loadConfigFile(o *Options) {
function addAWSConfig (line 180) | func addAWSConfig(o *Options) {
type AWSConfig (line 186) | type AWSConfig struct
function loadAWSConfig (line 193) | func loadAWSConfig() (access string, secret string) {
function copyFile (line 217) | func copyFile(bucket *s3.Bucket, from string, to string, contentType str...
function joinPath (line 235) | func joinPath(parts ...string) string {
FILE: vendor/github.com/cenk/backoff/backoff.go
type BackOff (line 9) | type BackOff interface
constant Stop (line 29) | Stop time.Duration = -1
type ZeroBackOff (line 33) | type ZeroBackOff struct
method Reset (line 35) | func (b *ZeroBackOff) Reset() {}
method NextBackOff (line 37) | func (b *ZeroBackOff) NextBackOff() time.Duration { return 0 }
type StopBackOff (line 41) | type StopBackOff struct
method Reset (line 43) | func (b *StopBackOff) Reset() {}
method NextBackOff (line 45) | func (b *StopBackOff) NextBackOff() time.Duration { return Stop }
type ConstantBackOff (line 50) | type ConstantBackOff struct
method Reset (line 54) | func (b *ConstantBackOff) Reset() {}
method NextBackOff (line 55) | func (b *ConstantBackOff) NextBackOff() time.Duration { return b.Inter...
function NewConstantBackOff (line 57) | func NewConstantBackOff(d time.Duration) *ConstantBackOff {
FILE: vendor/github.com/cenk/backoff/exponential.go
type ExponentialBackOff (line 54) | type ExponentialBackOff struct
method Reset (line 111) | func (b *ExponentialBackOff) Reset() {
method NextBackOff (line 118) | func (b *ExponentialBackOff) NextBackOff() time.Duration {
method GetElapsedTime (line 131) | func (b *ExponentialBackOff) GetElapsedTime() time.Duration {
method incrementCurrentInterval (line 136) | func (b *ExponentialBackOff) incrementCurrentInterval() {
type Clock (line 69) | type Clock interface
constant DefaultInitialInterval (line 75) | DefaultInitialInterval = 500 * time.Millisecond
constant DefaultRandomizationFactor (line 76) | DefaultRandomizationFactor = 0.5
constant DefaultMultiplier (line 77) | DefaultMultiplier = 1.5
constant DefaultMaxInterval (line 78) | DefaultMaxInterval = 60 * time.Second
constant DefaultMaxElapsedTime (line 79) | DefaultMaxElapsedTime = 15 * time.Minute
function NewExponentialBackOff (line 83) | func NewExponentialBackOff() *ExponentialBackOff {
type systemClock (line 101) | type systemClock struct
method Now (line 103) | func (t systemClock) Now() time.Time {
function getRandomValueFromInterval (line 147) | func getRandomValueFromInterval(randomizationFactor, random float64, cur...
FILE: vendor/github.com/cenk/backoff/retry.go
type Operation (line 7) | type Operation
type Notify (line 14) | type Notify
function Retry (line 22) | func Retry(o Operation, b BackOff) error { return RetryNotify(o, b, nil) }
function RetryNotify (line 26) | func RetryNotify(operation Operation, b BackOff, notify Notify) error {
FILE: vendor/github.com/cenk/backoff/ticker.go
type Ticker (line 13) | type Ticker struct
method Stop (line 38) | func (t *Ticker) Stop() {
method run (line 42) | func (t *Ticker) run() {
method send (line 65) | func (t *Ticker) send(tick time.Time) <-chan time.Time {
function NewTicker (line 24) | func NewTicker(b BackOff) *Ticker {
FILE: vendor/github.com/imdario/mergo/map.go
function changeInitialCase (line 18) | func changeInitialCase(s string, mapper func(rune) rune) string {
function isExported (line 26) | func isExported(field reflect.StructField) bool {
function deepMap (line 34) | func deepMap(dst, src reflect.Value, visited map[uintptr]*visit, depth i...
function Map (line 120) | func Map(dst, src interface{}) error {
function MapWithOverwrite (line 126) | func MapWithOverwrite(dst, src interface{}) error {
function _map (line 130) | func _map(dst, src interface{}, overwrite bool) error {
FILE: vendor/github.com/imdario/mergo/merge.go
function deepMerge (line 18) | func deepMerge(dst, src reflect.Value, visited map[uintptr]*visit, depth...
function Merge (line 101) | func Merge(dst, src interface{}) error {
function MergeWithOverwrite (line 107) | func MergeWithOverwrite(dst, src interface{}) error {
function merge (line 111) | func merge(dst, src interface{}, overwrite bool) error {
FILE: vendor/github.com/imdario/mergo/mergo.go
type visit (line 29) | type visit struct
function isEmptyValue (line 36) | func isEmptyValue(v reflect.Value) bool {
function resolveValues (line 54) | func resolveValues(dst, src interface{}) (vDst, vSrc reflect.Value, err ...
function deeper (line 75) | func deeper(dst, src reflect.Value, visited map[uintptr]*visit, depth in...
FILE: vendor/github.com/mitchellh/go-homedir/homedir.go
function Dir (line 26) | func Dir() (string, error) {
function Expand (line 58) | func Expand(path string) (string, error) {
function dirUnix (line 79) | func dirUnix() (string, error) {
function dirWindows (line 120) | func dirWindows() (string, error) {
FILE: vendor/github.com/wsxiaoys/terminal/color/color.go
constant EscapeChar (line 40) | EscapeChar = '@'
constant ResetCode (line 41) | ResetCode = "\033[0m"
function Colorize (line 79) | func Colorize(x string) string {
function compileColorSyntax (line 103) | func compileColorSyntax(input, output *bytes.Buffer) {
function compile (line 134) | func compile(x string) string {
function compileValues (line 158) | func compileValues(a *[]interface{}) {
function Print (line 167) | func Print(a ...interface{}) (int, error) {
function Println (line 174) | func Println(a ...interface{}) (int, error) {
function Printf (line 181) | func Printf(format string, a ...interface{}) (int, error) {
function Fprint (line 188) | func Fprint(w io.Writer, a ...interface{}) (int, error) {
function Fprintln (line 195) | func Fprintln(w io.Writer, a ...interface{}) (int, error) {
function Fprintf (line 202) | func Fprintf(w io.Writer, format string, a ...interface{}) (int, error) {
function Sprint (line 209) | func Sprint(a ...interface{}) string {
function Sprintf (line 216) | func Sprintf(format string, a ...interface{}) string {
function Errorf (line 223) | func Errorf(format string, a ...interface{}) error {
FILE: vendor/github.com/zackbloom/go-ini/decode.go
type Unmatched (line 15) | type Unmatched struct
method String (line 107) | func (u Unmatched) String() string {
type IniError (line 20) | type IniError struct
method Error (line 114) | func (e *IniError) Error() string {
type decodeState (line 27) | type decodeState struct
method init (line 132) | func (d *decodeState) init(data []byte) *decodeState {
method saveError (line 146) | func (d *decodeState) saveError(err error) {
method generateMap (line 156) | func (d *decodeState) generateMap(m propertyMap, v reflect.Value) {
method unmarshal (line 200) | func (d *decodeState) unmarshal(x interface{}) error {
method unmarshal2 (line 289) | func (d *decodeState) unmarshal2(x interface{}) error {
method setValue (line 397) | func (d *decodeState) setValue(v reflect.Value, s string) {
method sliceValue (line 441) | func (d *decodeState) sliceValue(v reflect.Value, s string) {
type property (line 35) | type property struct
method String (line 125) | func (p property) String() string {
type propertyMap (line 44) | type propertyMap
function NewPropMapStack (line 49) | func NewPropMapStack() *PropMapStack {
type PropMapStack (line 54) | type PropMapStack struct
method Push (line 60) | func (s *PropMapStack) Push(item propertyMap) {
method Pop (line 66) | func (s *PropMapStack) Pop() propertyMap {
method Peek (line 76) | func (s *PropMapStack) Peek() propertyMap {
method Empty (line 85) | func (s *PropMapStack) Empty() bool {
method Size (line 90) | func (s *PropMapStack) Size() int {
function Unmarshal (line 98) | func Unmarshal(data []byte, v interface{}) error {
function appendValue (line 392) | func appendValue(arr, val reflect.Value) {
function boolValue (line 497) | func boolValue(s string) bool {
type Decoder (line 508) | type Decoder struct
method Decode (line 525) | func (dec *Decoder) Decode(v interface{}) error {
method Unmatched (line 542) | func (dec *Decoder) Unmatched() []Unmatched {
function NewDecoder (line 517) | func NewDecoder(r io.Reader) *Decoder {
FILE: vendor/github.com/zackbloom/go-ini/stack.go
function NewStack (line 4) | func NewStack() *Stack {
type Stack (line 9) | type Stack struct
method Push (line 15) | func (s *Stack) Push(item interface{}) {
method Pop (line 21) | func (s *Stack) Pop() interface{} {
method Peek (line 31) | func (s *Stack) Peek() interface{} {
method Empty (line 40) | func (s *Stack) Empty() bool {
method Size (line 45) | func (s *Stack) Size() int {
FILE: vendor/github.com/zackbloom/goamz/aws/attempt.go
type AttemptStrategy (line 10) | type AttemptStrategy struct
method Start (line 25) | func (s AttemptStrategy) Start() *Attempt {
type Attempt (line 16) | type Attempt struct
method Next (line 37) | func (a *Attempt) Next() bool {
method nextSleep (line 53) | func (a *Attempt) nextSleep(now time.Time) time.Duration {
method HasNext (line 64) | func (a *Attempt) HasNext() bool {
FILE: vendor/github.com/zackbloom/goamz/aws/aws.go
constant V2Signature (line 37) | V2Signature = iota
constant V4Signature (line 38) | V4Signature = iota
constant Route53Signature (line 39) | Route53Signature = iota
type ServiceInfo (line 44) | type ServiceInfo struct
type Region (line 52) | type Region struct
type Signer (line 92) | type Signer interface
type AWSService (line 99) | type AWSService interface
type Service (line 110) | type Service struct
method Query (line 140) | func (s *Service) Query(method, path string, params map[string]string)...
method BuildError (line 159) | func (s *Service) BuildError(r *http.Response) error {
function MakeParams (line 116) | func MakeParams(action string) map[string]string {
function NewService (line 123) | func NewService(auth Auth, service ServiceInfo) (s *Service, err error) {
type ServiceError (line 172) | type ServiceError interface
type ErrorResponse (line 177) | type ErrorResponse struct
type Error (line 182) | type Error struct
method Error (line 190) | func (err *Error) Error() string {
method ErrorCode (line 196) | func (err *Error) ErrorCode() string {
type Auth (line 200) | type Auth struct
method Token (line 206) | func (a *Auth) Token() string {
method Expiration (line 216) | func (a *Auth) Expiration() time.Time {
function NewAuth (line 221) | func NewAuth(accessKey, secretKey, token string, expiration time.Time) *...
type ResponseMetadata (line 231) | type ResponseMetadata struct
type BaseResponse (line 235) | type BaseResponse struct
function init (line 242) | func init() {
function multimap (line 250) | func multimap(p map[string]string) url.Values {
type credentials (line 258) | type credentials struct
function GetMetaData (line 271) | func GetMetaData(path string) (contents []byte, err error) {
function GetRegion (line 306) | func GetRegion(regionName string) (region Region) {
function GetInstanceCredentials (line 314) | func GetInstanceCredentials() (cred credentials, err error) {
function GetAuth (line 335) | func GetAuth(accessKey string, secretKey, token string, expiration time....
function EnvAuth (line 377) | func EnvAuth() (auth Auth, err error) {
function CredentialFileAuth (line 401) | func CredentialFileAuth(filePath string, profile string, expiration time...
function parseINI (line 456) | func parseINI(fileContents string) map[string]map[string]string {
function Encode (line 488) | func Encode(s string) string {
function dialTimeout (line 517) | func dialTimeout(network, addr string) (net.Conn, error) {
function AvailabilityZone (line 521) | func AvailabilityZone() string {
function InstanceRegion (line 540) | func InstanceRegion() string {
function InstanceId (line 550) | func InstanceId() string {
function InstanceType (line 569) | func InstanceType() string {
function ServerLocalIp (line 588) | func ServerLocalIp() string {
function ServerPublicIp (line 607) | func ServerPublicIp() string {
FILE: vendor/github.com/zackbloom/goamz/aws/client.go
type RetryableFunc (line 10) | type RetryableFunc
type WaitFunc (line 11) | type WaitFunc
type DeadlineFunc (line 12) | type DeadlineFunc
type ResilientTransport (line 14) | type ResilientTransport struct
method RoundTrip (line 68) | func (t *ResilientTransport) RoundTrip(req *http.Request) (*http.Respo...
method tries (line 76) | func (t *ResilientTransport) tries(req *http.Request) (res *http.Respo...
function NewClient (line 36) | func NewClient(rt *ResilientTransport) *http.Client {
function ExpBackoff (line 94) | func ExpBackoff(try int) {
function LinearBackoff (line 99) | func LinearBackoff(try int) {
function awsRetry (line 106) | func awsRetry(req *http.Request, res *http.Response, err error) bool {
FILE: vendor/github.com/zackbloom/goamz/aws/retry.go
constant maxDelay (line 11) | maxDelay = 20 * time.Second
constant defaultScale (line 12) | defaultScale = 300 * time.Millisecond
constant throttlingScale (line 13) | throttlingScale = 500 * time.Millisecond
constant throttlingScaleRange (line 14) | throttlingScaleRange = throttlingScale / 4
constant defaultMaxRetries (line 15) | defaultMaxRetries = 3
constant dynamoDBScale (line 16) | dynamoDBScale = 25 * time.Millisecond
constant dynamoDBMaxRetries (line 17) | dynamoDBMaxRetries = 10
type RetryPolicy (line 23) | type RetryPolicy interface
type DefaultRetryPolicy (line 38) | type DefaultRetryPolicy struct
method ShouldRetry (line 42) | func (policy DefaultRetryPolicy) ShouldRetry(target string, r *http.Re...
method Delay (line 47) | func (policy DefaultRetryPolicy) Delay(target string, r *http.Response...
type DynamoDBRetryPolicy (line 61) | type DynamoDBRetryPolicy struct
method ShouldRetry (line 65) | func (policy DynamoDBRetryPolicy) ShouldRetry(target string, r *http.R...
method Delay (line 70) | func (policy DynamoDBRetryPolicy) Delay(target string, r *http.Respons...
type NeverRetryPolicy (line 75) | type NeverRetryPolicy struct
method ShouldRetry (line 79) | func (policy NeverRetryPolicy) ShouldRetry(target string, r *http.Resp...
method Delay (line 84) | func (policy NeverRetryPolicy) Delay(target string, r *http.Response, ...
function shouldRetry (line 91) | func shouldRetry(r *http.Response, err error, numRetries int, maxRetries...
function exponentialBackoff (line 117) | func exponentialBackoff(numRetries int, scale time.Duration) time.Durati...
function isThrottlingException (line 129) | func isThrottlingException(err ServiceError) bool {
FILE: vendor/github.com/zackbloom/goamz/aws/sign.go
type V2Signer (line 18) | type V2Signer struct
method Sign (line 34) | func (s *V2Signer) Sign(method, path string, params map[string]string) {
function NewV2Signer (line 26) | func NewV2Signer(auth Auth, service ServiceInfo) (*V2Signer, error) {
constant ISO8601BasicFormat (line 66) | ISO8601BasicFormat = "20060102T150405Z"
constant ISO8601BasicFormatShort (line 67) | ISO8601BasicFormatShort = "20060102"
type Route53Signer (line 70) | type Route53Signer struct
method getCurrentDate (line 80) | func (s *Route53Signer) getCurrentDate() string {
method getHeaderAuthorize (line 92) | func (s *Route53Signer) getHeaderAuthorize(message string) string {
method Sign (line 102) | func (s *Route53Signer) Sign(req *http.Request) {
function NewRoute53Signer (line 74) | func NewRoute53Signer(auth Auth) *Route53Signer {
type V4Signer (line 120) | type V4Signer struct
method Sign (line 152) | func (s *V4Signer) Sign(req *http.Request) {
method requestTime (line 194) | func (s *V4Signer) requestTime(req *http.Request) time.Time {
method canonicalRequest (line 240) | func (s *V4Signer) canonicalRequest(req *http.Request, payloadHash str...
method canonicalURI (line 254) | func (s *V4Signer) canonicalURI(u *url.URL) string {
method canonicalQueryString (line 272) | func (s *V4Signer) canonicalQueryString(u *url.URL) string {
method canonicalHeaders (line 289) | func (s *V4Signer) canonicalHeaders(h http.Header) string {
method signedHeaders (line 314) | func (s *V4Signer) signedHeaders(h http.Header) string {
method payloadHash (line 324) | func (s *V4Signer) payloadHash(req *http.Request) string {
method stringToSign (line 349) | func (s *V4Signer) stringToSign(t time.Time, creq string) string {
method credentialScope (line 358) | func (s *V4Signer) credentialScope(t time.Time) string {
method signature (line 367) | func (s *V4Signer) signature(t time.Time, sts string) string {
method derivedKey (line 381) | func (s *V4Signer) derivedKey(t time.Time) []byte {
method authorization (line 392) | func (s *V4Signer) authorization(header http.Header, t time.Time, sign...
method hash (line 402) | func (s *V4Signer) hash(in string) string {
method hmac (line 409) | func (s *V4Signer) hmac(key, data []byte) []byte {
function NewV4Signer (line 131) | func NewV4Signer(auth Auth, serviceName string, region Region) *V4Signer {
FILE: vendor/github.com/zackbloom/goamz/cloudfront/cloudfront.go
constant ServiceName (line 22) | ServiceName = "cloudfront"
constant ApiVersion (line 23) | ApiVersion = "2014-11-06"
function NewCloudFront (line 27) | func NewCloudFront(auth aws.Auth) *CloudFront {
type CloudFront (line 36) | type CloudFront struct
method generateSignature (line 431) | func (cf *CloudFront) generateSignature(policy []byte) (string, error) {
method Create (line 520) | func (cf *CloudFront) Create(config DistributionConfig) (summary Distr...
method List (line 587) | func (cf *CloudFront) List(marker string, max int) (items *Distributio...
method FindDistributionByAlias (line 631) | func (cf *CloudFront) FindDistributionByAlias(alias string) (dist *Dis...
method CannedSignedURL (line 665) | func (cf *CloudFront) CannedSignedURL(path, queryString string, expire...
method SignedURL (line 700) | func (cloudfront *CloudFront) SignedURL(path, querystrings string, exp...
type DistributionConfig (line 44) | type DistributionConfig struct
type DistributionSummary (line 61) | type DistributionSummary struct
type Aliases (line 70) | type Aliases
method MarshalXML (line 77) | func (a Aliases) MarshalXML(e *xml.Encoder, start xml.StartElement) er...
method UnmarshalXML (line 86) | func (n *Aliases) UnmarshalXML(d *xml.Decoder, start xml.StartElement)...
type EncodedAliases (line 72) | type EncodedAliases struct
type CustomErrorResponses (line 97) | type CustomErrorResponses
method MarshalXML (line 104) | func (a CustomErrorResponses) MarshalXML(e *xml.Encoder, start xml.Sta...
method UnmarshalXML (line 113) | func (n *CustomErrorResponses) UnmarshalXML(d *xml.Decoder, start xml....
type EncodedCustomErrorResponses (line 99) | type EncodedCustomErrorResponses struct
type CacheBehaviors (line 124) | type CacheBehaviors
method MarshalXML (line 131) | func (a CacheBehaviors) MarshalXML(e *xml.Encoder, start xml.StartElem...
method UnmarshalXML (line 140) | func (n *CacheBehaviors) UnmarshalXML(d *xml.Decoder, start xml.StartE...
type EncodedCacheBehaviors (line 126) | type EncodedCacheBehaviors struct
type Logging (line 151) | type Logging struct
type ViewerCertificate (line 158) | type ViewerCertificate struct
type GeoRestriction (line 165) | type GeoRestriction struct
method MarshalXML (line 176) | func (a GeoRestriction) MarshalXML(e *xml.Encoder, start xml.StartElem...
method UnmarshalXML (line 186) | func (n *GeoRestriction) UnmarshalXML(d *xml.Decoder, start xml.StartE...
type EncodedGeoRestriction (line 170) | type EncodedGeoRestriction struct
type CustomErrorResponse (line 198) | type CustomErrorResponse struct
type Origin (line 206) | type Origin struct
type S3OriginConfig (line 215) | type S3OriginConfig struct
type CustomOriginConfig (line 219) | type CustomOriginConfig struct
type Origins (line 225) | type Origins
method MarshalXML (line 232) | func (o Origins) MarshalXML(e *xml.Encoder, start xml.StartElement) er...
method UnmarshalXML (line 241) | func (o *Origins) UnmarshalXML(d *xml.Decoder, start xml.StartElement)...
type EncodedOrigins (line 227) | type EncodedOrigins struct
type CacheBehavior (line 252) | type CacheBehavior struct
type ForwardedValues (line 263) | type ForwardedValues struct
type Cookies (line 269) | type Cookies struct
function cacheBehaviorDefault (line 279) | func cacheBehaviorDefault(cache *CacheBehavior) {
type Names (line 286) | type Names
method MarshalXML (line 293) | func (w Names) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
method UnmarshalXML (line 302) | func (n *Names) UnmarshalXML(d *xml.Decoder, start xml.StartElement) e...
type EncodedNames (line 288) | type EncodedNames struct
type ItemsList (line 313) | type ItemsList
type TrustedSigners (line 315) | type TrustedSigners struct
method MarshalXML (line 326) | func (n TrustedSigners) MarshalXML(e *xml.Encoder, start xml.StartElem...
method UnmarshalXML (line 336) | func (n *TrustedSigners) UnmarshalXML(d *xml.Decoder, start xml.StartE...
type EncodedTrustedSigners (line 320) | type EncodedTrustedSigners struct
type AllowedMethods (line 348) | type AllowedMethods struct
method MarshalXML (line 360) | func (n AllowedMethods) MarshalXML(e *xml.Encoder, start xml.StartElem...
method UnmarshalXML (line 371) | func (n *AllowedMethods) UnmarshalXML(d *xml.Decoder, start xml.StartE...
type EncodedAllowedMethods (line 353) | type EncodedAllowedMethods struct
function NewKeyLess (line 385) | func NewKeyLess(auth aws.Auth, baseurl string) *CloudFront {
function New (line 389) | func New(baseurl string, key *rsa.PrivateKey, keyPairId string) *CloudFr...
type epochTime (line 397) | type epochTime struct
type condition (line 401) | type condition struct
type statement (line 405) | type statement struct
type policy (line 410) | type policy struct
function buildPolicy (line 414) | func buildPolicy(resource string, expireTime time.Time) ([]byte, error) {
type DistributionItem (line 567) | type DistributionItem struct
type DistributionsResp (line 572) | type DistributionsResp struct
FILE: vendor/github.com/zackbloom/goamz/iam/iam.go
type IAM (line 16) | type IAM struct
method query (line 26) | func (iam *IAM) query(params map[string]string, resp interface{}) error {
method postQuery (line 46) | func (iam *IAM) postQuery(params map[string]string, resp interface{}) ...
method CreateUser (line 119) | func (iam *IAM) CreateUser(name, path string) (*CreateUserResp, error) {
method GetUser (line 143) | func (iam *IAM) GetUser(name string) (*GetUserResp, error) {
method DeleteUser (line 160) | func (iam *IAM) DeleteUser(name string) (*SimpleResp, error) {
method CreateGroup (line 198) | func (iam *IAM) CreateGroup(name string, path string) (*CreateGroupRes...
method Groups (line 227) | func (iam *IAM) Groups(pathPrefix string) (*GroupsResp, error) {
method DeleteGroup (line 244) | func (iam *IAM) DeleteGroup(name string) (*SimpleResp, error) {
method CreateAccessKey (line 277) | func (iam *IAM) CreateAccessKey(userName string) (*CreateAccessKeyResp...
method AccessKeys (line 303) | func (iam *IAM) AccessKeys(userName string) (*AccessKeysResp, error) {
method DeleteAccessKey (line 323) | func (iam *IAM) DeleteAccessKey(id, userName string) (*SimpleResp, err...
method GetUserPolicy (line 358) | func (iam *IAM) GetUserPolicy(userName, policyName string) (*GetUserPo...
method PutUserPolicy (line 375) | func (iam *IAM) PutUserPolicy(userName, policyName, policyDocument str...
method DeleteUserPolicy (line 392) | func (iam *IAM) DeleteUserPolicy(userName, policyName string) (*Simple...
function New (line 22) | func New(auth aws.Auth, region aws.Region) *IAM {
function buildError (line 74) | func buildError(r *http.Response) error {
function multimap (line 90) | func multimap(p map[string]string) url.Values {
type CreateUserResp (line 101) | type CreateUserResp struct
type User (line 109) | type User struct
type GetUserResp (line 135) | type GetUserResp struct
type CreateGroupResp (line 175) | type CreateGroupResp struct
type Group (line 183) | type Group struct
type GroupsResp (line 216) | type GroupsResp struct
type CreateAccessKeyResp (line 259) | type CreateAccessKeyResp struct
type AccessKey (line 267) | type AccessKey struct
type AccessKeysResp (line 292) | type AccessKeysResp struct
type GetUserPolicyResp (line 341) | type GetUserPolicyResp struct
type UserPolicy (line 349) | type UserPolicy struct
type SimpleResp (line 405) | type SimpleResp struct
type xmlErrors (line 409) | type xmlErrors struct
type Error (line 414) | type Error struct
method Error (line 425) | func (e *Error) Error() string {
FILE: vendor/github.com/zackbloom/goamz/iam/sign.go
function sign (line 17) | func sign(auth aws.Auth, method, path string, params map[string]string, ...
FILE: vendor/github.com/zackbloom/goamz/route53/route53.go
type Route53 (line 15) | type Route53 struct
method query (line 231) | func (r *Route53) query(method string, path string, body io.Reader, re...
method CreateHostedZone (line 260) | func (r *Route53) CreateHostedZone(hostedZoneReq *CreateHostedZoneRequ...
method ListResourceRecordSets (line 273) | func (r *Route53) ListResourceRecordSets(hostedZone string, name strin...
method ChangeResourceRecordSet (line 306) | func (r *Route53) ChangeResourceRecordSet(req *ChangeResourceRecordSet...
method ListHostedZones (line 323) | func (r *Route53) ListHostedZones(marker string, maxItems int) (result...
method ListHostedZonesByName (line 339) | func (r *Route53) ListHostedZonesByName(DNSName string, nextHostedZone...
method GetHostedZone (line 359) | func (r *Route53) GetHostedZone(id string) (result *GetHostedZoneRespo...
method DeleteHostedZone (line 367) | func (r *Route53) DeleteHostedZone(id string) (result *DeleteHostedZon...
method AssociateVPCWithHostedZone (line 377) | func (r *Route53) AssociateVPCWithHostedZone(zoneid string, req *Assoc...
method DisassociateVPCWithHostedZone (line 392) | func (r *Route53) DisassociateVPCWithHostedZone(zoneid string, req *Di...
constant route53_host (line 22) | route53_host = "https://route53.amazonaws.com"
constant route53_ver (line 23) | route53_ver = "2013-04-01"
function NewRoute53 (line 26) | func NewRoute53(auth aws.Auth) (*Route53, error) {
type HostedZone (line 37) | type HostedZone struct
type Config (line 47) | type Config struct
type ListHostedZonesResponse (line 54) | type ListHostedZonesResponse struct
type ListHostedZonesByNameResponse (line 63) | type ListHostedZonesByNameResponse struct
type CreateHostedZoneRequest (line 75) | type CreateHostedZoneRequest struct
type ResourceRecordValue (line 84) | type ResourceRecordValue struct
type Change (line 88) | type Change struct
type ChangeResourceRecordSetsRequest (line 97) | type ChangeResourceRecordSetsRequest struct
type AssociateVPCWithHostedZoneRequest (line 103) | type AssociateVPCWithHostedZoneRequest struct
type DisassociateVPCWithHostedZoneRequest (line 110) | type DisassociateVPCWithHostedZoneRequest struct
type HostedZoneConfig (line 117) | type HostedZoneConfig struct
type HostedZoneVPC (line 122) | type HostedZoneVPC struct
type CreateHostedZoneResponse (line 128) | type CreateHostedZoneResponse struct
type AliasTarget (line 135) | type AliasTarget struct
type ResourceRecord (line 141) | type ResourceRecord struct
type ResourceRecords (line 146) | type ResourceRecords struct
type ResourceRecordSet (line 151) | type ResourceRecordSet struct
method GetValues (line 294) | func (recordset *ResourceRecordSet) GetValues() []string {
type ResourceRecordSets (line 163) | type ResourceRecordSets struct
type ListResourceRecordSetsResponse (line 168) | type ListResourceRecordSetsResponse struct
method GetResourceRecordSets (line 290) | func (response *ListResourceRecordSetsResponse) GetResourceRecordSets(...
type ChangeResourceRecordSetsResponse (line 178) | type ChangeResourceRecordSetsResponse struct
type ChangeInfo (line 185) | type ChangeInfo struct
type DelegationSet (line 192) | type DelegationSet struct
type NameServers (line 197) | type NameServers struct
type GetHostedZoneResponse (line 202) | type GetHostedZoneResponse struct
type DeleteHostedZoneResponse (line 209) | type DeleteHostedZoneResponse struct
type AssociateVPCWithHostedZoneResponse (line 215) | type AssociateVPCWithHostedZoneResponse struct
type DisassociateVPCWithHostedZoneResponse (line 221) | type DisassociateVPCWithHostedZoneResponse struct
function addParam (line 406) | func addParam(buffer *bytes.Buffer, name, value string) {
FILE: vendor/github.com/zackbloom/goamz/s3/lifecycle.go
constant LifecycleRuleStatusEnabled (line 16) | LifecycleRuleStatusEnabled = "Enabled"
constant LifecycleRuleStatusDisabled (line 17) | LifecycleRuleStatusDisabled = "Disabled"
constant LifecycleRuleDateFormat (line 18) | LifecycleRuleDateFormat = "2006-01-02"
constant StorageClassGlacier (line 19) | StorageClassGlacier = "GLACIER"
type Expiration (line 22) | type Expiration struct
method ParseDate (line 28) | func (r *Expiration) ParseDate() (time.Time, error) {
type Transition (line 32) | type Transition struct
method ParseDate (line 39) | func (r *Transition) ParseDate() (time.Time, error) {
type NoncurrentVersionExpiration (line 43) | type NoncurrentVersionExpiration struct
type NoncurrentVersionTransition (line 47) | type NoncurrentVersionTransition struct
type LifecycleRule (line 52) | type LifecycleRule struct
method SetTransitionDays (line 74) | func (r *LifecycleRule) SetTransitionDays(days uint) {
method SetTransitionDate (line 82) | func (r *LifecycleRule) SetTransitionDate(date time.Time) {
method SetExpirationDays (line 91) | func (r *LifecycleRule) SetExpirationDays(days uint) {
method SetExpirationDate (line 98) | func (r *LifecycleRule) SetExpirationDate(date time.Time) {
method SetNoncurrentVersionTransitionDays (line 106) | func (r *LifecycleRule) SetNoncurrentVersionTransitionDays(days uint) {
method SetNoncurrentVersionExpirationDays (line 115) | func (r *LifecycleRule) SetNoncurrentVersionExpirationDays(days uint) {
method Disable (line 122) | func (r *LifecycleRule) Disable() {
method Enable (line 127) | func (r *LifecycleRule) Enable() {
function NewLifecycleRule (line 64) | func NewLifecycleRule(id, prefix string) *LifecycleRule {
type LifecycleConfiguration (line 131) | type LifecycleConfiguration struct
method AddRule (line 137) | func (c *LifecycleConfiguration) AddRule(r *LifecycleRule) {
method PutLifecycleConfiguration (line 147) | func (b *Bucket) PutLifecycleConfiguration(c *LifecycleConfiguration) er...
method GetLifecycleConfiguration (line 179) | func (b *Bucket) GetLifecycleConfiguration() (*LifecycleConfiguration, e...
method DeleteLifecycleConfiguration (line 193) | func (b *Bucket) DeleteLifecycleConfiguration() error {
FILE: vendor/github.com/zackbloom/goamz/s3/multi.go
type Multi (line 24) | type Multi struct
method PutPartCopy (line 143) | func (m *Multi) PutPartCopy(n int, options CopyOptions, source string)...
method PutPart (line 187) | func (m *Multi) PutPart(n int, r io.ReadSeeker) (Part, error) {
method putPart (line 195) | func (m *Multi) putPart(n int, r io.ReadSeeker, partSize int64, md5b64...
method ListParts (line 275) | func (m *Multi) ListParts() ([]Part, error) {
method ListPartsFull (line 285) | func (m *Multi) ListPartsFull(partNumberMarker int, maxParts int) ([]P...
method PutAll (line 333) | func (m *Multi) PutAll(r ReaderAtSeeker, partSize int64) ([]Part, erro...
method Complete (line 401) | func (m *Multi) Complete(parts []Part) error {
method Abort (line 446) | func (m *Multi) Abort() error {
type listMultiResp (line 33) | type listMultiResp struct
method ListMulti (line 53) | func (b *Bucket) ListMulti(prefix, delim string) (multis []*Multi, prefi...
method Multi (line 93) | func (b *Bucket) Multi(key, contType string, perm ACL, options Options) ...
method InitMulti (line 110) | func (b *Bucket) InitMulti(key string, contType string, perm ACL, option...
function seekerInfo (line 237) | func seekerInfo(r io.ReadSeeker) (size int64, md5hex string, md5b64 stri...
type Part (line 253) | type Part struct
type partSlice (line 259) | type partSlice
method Len (line 261) | func (s partSlice) Len() int { return len(s) }
method Less (line 262) | func (s partSlice) Less(i, j int) bool { return s[i].N < s[j].N }
method Swap (line 263) | func (s partSlice) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
type listPartsResp (line 265) | type listPartsResp struct
type ReaderAtSeeker (line 322) | type ReaderAtSeeker interface
type completeUpload (line 381) | type completeUpload struct
type completePart (line 386) | type completePart struct
type completeParts (line 391) | type completeParts
method Len (line 393) | func (p completeParts) Len() int { return len(p) }
method Less (line 394) | func (p completeParts) Less(i, j int) bool { return p[i].PartNumber < ...
method Swap (line 395) | func (p completeParts) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
FILE: vendor/github.com/zackbloom/goamz/s3/s3.go
constant debug (line 35) | debug = false
type S3 (line 38) | type S3 struct
method Bucket (line 103) | func (s3 *S3) Bucket(name string) *Bucket {
method GetService (line 123) | func (s3 *S3) GetService() (*GetServiceResp, error) {
method locationConstraint (line 148) | func (s3 *S3) locationConstraint() io.Reader {
method query (line 963) | func (s3 *S3) query(req *request, resp interface{}) error {
method queryV4Sign (line 978) | func (s3 *S3) queryV4Sign(req *request, resp interface{}) error {
method setBaseURL (line 1005) | func (s3 *S3) setBaseURL(req *request) error {
method prepare (line 1053) | func (s3 *S3) prepare(req *request) error {
method setupHttpRequest (line 1121) | func (s3 *S3) setupHttpRequest(req *request) (*http.Request, error) {
method doHttpRequest (line 1159) | func (s3 *S3) doHttpRequest(hreq *http.Request, resp interface{}) (*ht...
method run (line 1207) | func (s3 *S3) run(req *request, resp interface{}) (*http.Response, err...
type Bucket (line 48) | type Bucket struct
method PutBucket (line 170) | func (b *Bucket) PutBucket(perm ACL) error {
method DelBucket (line 188) | func (b *Bucket) DelBucket() (err error) {
method Get (line 206) | func (b *Bucket) Get(path string) (data []byte, err error) {
method GetReader (line 220) | func (b *Bucket) GetReader(path string) (rc io.ReadCloser, err error) {
method GetResponse (line 232) | func (b *Bucket) GetResponse(path string) (resp *http.Response, err er...
method GetResponseWithHeaders (line 241) | func (b *Bucket) GetResponseWithHeaders(path string, headers map[strin...
method Exists (line 265) | func (b *Bucket) Exists(path string) (exists bool, err error) {
method Head (line 303) | func (b *Bucket) Head(path string, headers map[string][]string) (*http...
method Put (line 331) | func (b *Bucket) Put(path string, data []byte, contType string, perm A...
method PutCopy (line 337) | func (b *Bucket) PutCopy(path string, perm ACL, options CopyOptions, s...
method PutReader (line 359) | func (b *Bucket) PutReader(path string, r io.Reader, length int64, con...
method PutBucketWebsite (line 460) | func (b *Bucket) PutBucketWebsite(configuration WebsiteConfiguration) ...
method PutBucketSubresource (line 471) | func (b *Bucket) PutBucketSubresource(subresource string, r io.Reader,...
method Del (line 490) | func (b *Bucket) Del(path string) error {
method DelMulti (line 512) | func (b *Bucket) DelMulti(objects Delete) error {
method List (line 629) | func (b *Bucket) List(prefix, delim, marker string, max int) (result *...
method Versions (line 690) | func (b *Bucket) Versions(prefix, delim, keyMarker string, versionIdMa...
method Location (line 728) | func (b *Bucket) Location() (string, error) {
method GetPolicy (line 748) | func (b *Bucket) GetPolicy() ([]byte, error) {
method PutPolicy (line 774) | func (b *Bucket) PutPolicy(data []byte) error {
method URL (line 788) | func (b *Bucket) URL(path string) string {
method SignedURL (line 807) | func (b *Bucket) SignedURL(path string, expires time.Time) string {
method SignedURLWithArgs (line 813) | func (b *Bucket) SignedURLWithArgs(path string, expires time.Time, par...
method SignedURLWithMethod (line 819) | func (b *Bucket) SignedURLWithMethod(method, path string, expires time...
method UploadSignedURL (line 858) | func (b *Bucket) UploadSignedURL(path, method, content_type string, ex...
method PostFormArgsEx (line 901) | func (b *Bucket) PostFormArgsEx(path string, expires time.Time, redire...
method PostFormArgs (line 935) | func (b *Bucket) PostFormArgs(path string, expires time.Time, redirect...
type Owner (line 54) | type Owner struct
type Options (line 61) | type Options struct
method addHeaders (line 377) | func (o Options) addHeaders(headers map[string][]string) {
type CopyOptions (line 78) | type CopyOptions struct
method addHeaders (line 410) | func (o CopyOptions) addHeaders(headers map[string][]string) {
type CopyObjectResult (line 86) | type CopyObjectResult struct
function New (line 98) | func New(auth aws.Auth, region aws.Region) *S3 {
type BucketInfo (line 110) | type BucketInfo struct
type GetServiceResp (line 115) | type GetServiceResp struct
type ACL (line 156) | type ACL
constant Private (line 159) | Private = ACL("private")
constant PublicRead (line 160) | PublicRead = ACL("public-read")
constant PublicReadWrite (line 161) | PublicReadWrite = ACL("public-read-write")
constant AuthenticatedRead (line 162) | AuthenticatedRead = ACL("authenticated-read")
constant BucketOwnerRead (line 163) | BucketOwnerRead = ACL("bucket-owner-read")
constant BucketOwnerFull (line 164) | BucketOwnerFull = ACL("bucket-owner-full-control")
function makeXmlBuffer (line 423) | func makeXmlBuffer(doc []byte) *bytes.Buffer {
type IndexDocument (line 430) | type IndexDocument struct
type ErrorDocument (line 434) | type ErrorDocument struct
type RoutingRule (line 438) | type RoutingRule struct
type RedirectAllRequestsTo (line 444) | type RedirectAllRequestsTo struct
type WebsiteConfiguration (line 449) | type WebsiteConfiguration struct
type Delete (line 499) | type Delete struct
type Object (line 504) | type Object struct
type ListResp (line 543) | type ListResp struct
type Key (line 562) | type Key struct
type VersionsResp (line 664) | type VersionsResp struct
type Version (line 677) | type Version struct
type GetLocationResp (line 724) | type GetLocationResp struct
type request (line 939) | type request struct
method url (line 950) | func (req *request) url() (*url.URL, error) {
function partiallyEscapedPath (line 1039) | func partiallyEscapedPath(path string) string {
type Error (line 1221) | type Error struct
method Error (line 1230) | func (e *Error) Error() string {
function buildError (line 1234) | func buildError(r *http.Response) error {
function shouldRetry (line 1260) | func shouldRetry(err error) bool {
function hasCode (line 1298) | func hasCode(err error, code string) bool {
FILE: vendor/github.com/zackbloom/goamz/s3/sign.go
function sign (line 42) | func sign(auth aws.Auth, method, canonicalPath string, params, headers m...
FILE: vendor/golang.org/x/crypto/ssh/terminal/terminal.go
type EscapeCodes (line 16) | type EscapeCodes struct
type Terminal (line 39) | type Terminal struct
method queue (line 218) | func (t *Terminal) queue(data []rune) {
method moveCursorToPos (line 232) | func (t *Terminal) moveCursorToPos(pos int) {
method move (line 266) | func (t *Terminal) move(up, down, left, right int) {
method clearLineToRight (line 297) | func (t *Terminal) clearLineToRight() {
method setLine (line 304) | func (t *Terminal) setLine(newLine []rune, newPos int) {
method advanceCursor (line 317) | func (t *Terminal) advanceCursor(places int) {
method eraseNPreviousChars (line 340) | func (t *Terminal) eraseNPreviousChars(n int) {
method countToLeftWord (line 365) | func (t *Terminal) countToLeftWord() int {
method countToRightWord (line 390) | func (t *Terminal) countToRightWord() int {
method handleKey (line 430) | func (t *Terminal) handleKey(key rune) (line string, ok bool) {
method addKeyToLine (line 567) | func (t *Terminal) addKeyToLine(key rune) {
method writeLine (line 583) | func (t *Terminal) writeLine(line []rune) {
method Write (line 596) | func (t *Terminal) Write(buf []byte) (n int, err error) {
method ReadPassword (line 643) | func (t *Terminal) ReadPassword(prompt string) (line string, err error) {
method ReadLine (line 660) | func (t *Terminal) ReadLine() (line string, err error) {
method readLine (line 667) | func (t *Terminal) readLine() (line string, err error) {
method SetPrompt (line 748) | func (t *Terminal) SetPrompt(prompt string) {
method clearAndRepaintLinePlusNPrevious (line 755) | func (t *Terminal) clearAndRepaintLinePlusNPrevious(numPrevLines int) {
method SetSize (line 776) | func (t *Terminal) SetSize(width, height int) error {
method SetBracketedPasteMode (line 846) | func (t *Terminal) SetBracketedPasteMode(on bool) {
function NewTerminal (line 101) | func NewTerminal(c io.ReadWriter, prompt string) *Terminal {
constant keyCtrlD (line 114) | keyCtrlD = 4
constant keyCtrlU (line 115) | keyCtrlU = 21
constant keyEnter (line 116) | keyEnter = '\r'
constant keyEscape (line 117) | keyEscape = 27
constant keyBackspace (line 118) | keyBackspace = 127
constant keyUnknown (line 119) | keyUnknown = 0xd800 /* UTF-16 surrogate area */ + iota
constant keyUp (line 120) | keyUp
constant keyDown (line 121) | keyDown
constant keyLeft (line 122) | keyLeft
constant keyRight (line 123) | keyRight
constant keyAltLeft (line 124) | keyAltLeft
constant keyAltRight (line 125) | keyAltRight
constant keyHome (line 126) | keyHome
constant keyEnd (line 127) | keyEnd
constant keyDeleteWord (line 128) | keyDeleteWord
constant keyDeleteLine (line 129) | keyDeleteLine
constant keyClearScreen (line 130) | keyClearScreen
constant keyPasteStart (line 131) | keyPasteStart
constant keyPasteEnd (line 132) | keyPasteEnd
function bytesToKey (line 140) | func bytesToKey(b []byte, pasteActive bool) (rune, []byte) {
function isPrintable (line 225) | func isPrintable(key rune) bool {
constant maxLineLength (line 302) | maxLineLength = 4096
function visualLength (line 408) | func visualLength(runes []rune) int {
type pasteIndicatorError (line 829) | type pasteIndicatorError struct
method Error (line 831) | func (pasteIndicatorError) Error() string {
type stRingBuffer (line 855) | type stRingBuffer struct
method Add (line 865) | func (s *stRingBuffer) Add(a string) {
method NthPreviousEntry (line 883) | func (s *stRingBuffer) NthPreviousEntry(n int) (value string, ok bool) {
FILE: vendor/golang.org/x/crypto/ssh/terminal/util.go
type State (line 26) | type State struct
function IsTerminal (line 31) | func IsTerminal(fd int) bool {
function MakeRaw (line 40) | func MakeRaw(fd int) (*State, error) {
function GetState (line 58) | func GetState(fd int) (*State, error) {
function Restore (line 69) | func Restore(fd int, state *State) error {
function GetSize (line 75) | func GetSize(fd int) (width, height int, err error) {
function ReadPassword (line 87) | func ReadPassword(fd int) ([]byte, error) {
FILE: vendor/golang.org/x/crypto/ssh/terminal/util_bsd.go
constant ioctlReadTermios (line 11) | ioctlReadTermios = syscall.TIOCGETA
constant ioctlWriteTermios (line 12) | ioctlWriteTermios = syscall.TIOCSETA
FILE: vendor/golang.org/x/crypto/ssh/terminal/util_linux.go
constant ioctlReadTermios (line 10) | ioctlReadTermios = 0x5401
constant ioctlWriteTermios (line 11) | ioctlWriteTermios = 0x5402
FILE: vendor/golang.org/x/crypto/ssh/terminal/util_plan9.go
type State (line 22) | type State struct
function IsTerminal (line 25) | func IsTerminal(fd int) bool {
function MakeRaw (line 32) | func MakeRaw(fd int) (*State, error) {
function GetState (line 38) | func GetState(fd int) (*State, error) {
function Restore (line 44) | func Restore(fd int, state *State) error {
function GetSize (line 49) | func GetSize(fd int) (width, height int, err error) {
function ReadPassword (line 56) | func ReadPassword(fd int) ([]byte, error) {
FILE: vendor/golang.org/x/crypto/ssh/terminal/util_windows.go
constant enableLineInput (line 26) | enableLineInput = 2
constant enableEchoInput (line 27) | enableEchoInput = 4
constant enableProcessedInput (line 28) | enableProcessedInput = 1
constant enableWindowInput (line 29) | enableWindowInput = 8
constant enableMouseInput (line 30) | enableMouseInput = 16
constant enableInsertMode (line 31) | enableInsertMode = 32
constant enableQuickEditMode (line 32) | enableQuickEditMode = 64
constant enableExtendedFlags (line 33) | enableExtendedFlags = 128
constant enableAutoPosition (line 34) | enableAutoPosition = 256
constant enableProcessedOutput (line 35) | enableProcessedOutput = 1
constant enableWrapAtEolOutput (line 36) | enableWrapAtEolOutput = 2
type short (line 48) | type short
type word (line 49) | type word
type coord (line 51) | type coord struct
type smallRect (line 55) | type smallRect struct
type consoleScreenBufferInfo (line 61) | type consoleScreenBufferInfo struct
type State (line 70) | type State struct
function IsTerminal (line 75) | func IsTerminal(fd int) bool {
function MakeRaw (line 84) | func MakeRaw(fd int) (*State, error) {
function GetState (line 100) | func GetState(fd int) (*State, error) {
function Restore (line 111) | func Restore(fd int, state *State) error {
function GetSize (line 117) | func GetSize(fd int) (width, height int, err error) {
function ReadPassword (line 129) | func ReadPassword(fd int) ([]byte, error) {
FILE: vendor/golang.org/x/net/html/atom/atom.go
type Atom (line 21) | type Atom
method String (line 24) | func (a Atom) String() string {
method string (line 33) | func (a Atom) string() string {
function fnv (line 38) | func fnv(h uint32, s []byte) uint32 {
function match (line 46) | func match(s string, t []byte) bool {
function Lookup (line 57) | func Lookup(s []byte) Atom {
function String (line 73) | func String(s []byte) string {
FILE: vendor/golang.org/x/net/html/atom/gen.go
function identifier (line 26) | func identifier(s string) string {
function main (line 45) | func main() {
type byLen (line 198) | type byLen
method Less (line 200) | func (x byLen) Less(i, j int) bool { return len(x[i]) > len(x[j]) }
method Swap (line 201) | func (x byLen) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
method Len (line 202) | func (x byLen) Len() int { return len(x) }
function fnv (line 205) | func fnv(h uint32, s string) uint32 {
type table (line 216) | type table struct
method hash (line 224) | func (t *table) hash(s string) (h1, h2 uint32) {
method init (line 236) | func (t *table) init(h0 uint32, k uint, x []string) bool {
method insert (line 250) | func (t *table) insert(s string) bool {
method push (line 272) | func (t *table) push(i uint32, depth int) bool {
FILE: vendor/golang.org/x/net/html/atom/table.go
constant A (line 6) | A Atom = 0x1
constant Abbr (line 7) | Abbr Atom = 0x4
constant Accept (line 8) | Accept Atom = 0x2106
constant AcceptCharset (line 9) | AcceptCharset Atom = 0x210e
constant Accesskey (line 10) | Accesskey Atom = 0x3309
constant Action (line 11) | Action Atom = 0x1f606
constant Address (line 12) | Address Atom = 0x4f307
constant Align (line 13) | Align Atom = 0x1105
constant Alt (line 14) | Alt Atom = 0x4503
constant Annotation (line 15) | Annotation Atom = 0x1670a
constant AnnotationXml (line 16) | AnnotationXml Atom = 0x1670e
constant Applet (line 17) | Applet Atom = 0x2b306
constant Area (line 18) | Area Atom = 0x2fa04
constant Article (line 19) | Article Atom = 0x38807
constant Aside (line 20) | Aside Atom = 0x8305
constant Async (line 21) | Async Atom = 0x7b05
constant Audio (line 22) | Audio Atom = 0xa605
constant Autocomplete (line 23) | Autocomplete Atom = 0x1fc0c
constant Autofocus (line 24) | Autofocus Atom = 0xb309
constant Autoplay (line 25) | Autoplay Atom = 0xce08
constant B (line 26) | B Atom = 0x101
constant Base (line 27) | Base Atom = 0xd604
constant Basefont (line 28) | Basefont Atom = 0xd608
constant Bdi (line 29) | Bdi Atom = 0x1a03
constant Bdo (line 30) | Bdo Atom = 0xe703
constant Bgsound (line 31) | Bgsound Atom = 0x11807
constant Big (line 32) | Big Atom = 0x12403
constant Blink (line 33) | Blink Atom = 0x12705
constant Blockquote (line 34) | Blockquote Atom = 0x12c0a
constant Body (line 35) | Body Atom = 0x2f04
constant Br (line 36) | Br Atom = 0x202
constant Button (line 37) | Button Atom = 0x13606
constant Canvas (line 38) | Canvas Atom = 0x7f06
constant Caption (line 39) | Caption Atom = 0x1bb07
constant Center (line 40) | Center Atom = 0x5b506
constant Challenge (line 41) | Challenge Atom = 0x21f09
constant Charset (line 42) | Charset Atom = 0x2807
constant Checked (line 43) | Checked Atom = 0x32807
constant Cite (line 44) | Cite Atom = 0x3c804
constant Class (line 45) | Class Atom = 0x4de05
constant Code (line 46) | Code Atom = 0x14904
constant Col (line 47) | Col Atom = 0x15003
constant Colgroup (line 48) | Colgroup Atom = 0x15008
constant Color (line 49) | Color Atom = 0x15d05
constant Cols (line 50) | Cols Atom = 0x16204
constant Colspan (line 51) | Colspan Atom = 0x16207
constant Command (line 52) | Command Atom = 0x17507
constant Content (line 53) | Content Atom = 0x42307
constant Contenteditable (line 54) | Contenteditable Atom = 0x4230f
constant Contextmenu (line 55) | Contextmenu Atom = 0x3310b
constant Controls (line 56) | Controls Atom = 0x18808
constant Coords (line 57) | Coords Atom = 0x19406
constant Crossorigin (line 58) | Crossorigin Atom = 0x19f0b
constant Data (line 59) | Data Atom = 0x44a04
constant Datalist (line 60) | Datalist Atom = 0x44a08
constant Datetime (line 61) | Datetime Atom = 0x23c08
constant Dd (line 62) | Dd Atom = 0x26702
constant Default (line 63) | Default Atom = 0x8607
constant Defer (line 64) | Defer Atom = 0x14b05
constant Del (line 65) | Del Atom = 0x3ef03
constant Desc (line 66) | Desc Atom = 0x4db04
constant Details (line 67) | Details Atom = 0x4807
constant Dfn (line 68) | Dfn Atom = 0x6103
constant Dialog (line 69) | Dialog Atom = 0x1b06
constant Dir (line 70) | Dir Atom = 0x6903
constant Dirname (line 71) | Dirname Atom = 0x6907
constant Disabled (line 72) | Disabled Atom = 0x10c08
constant Div (line 73) | Div Atom = 0x11303
constant Dl (line 74) | Dl Atom = 0x11e02
constant Download (line 75) | Download Atom = 0x40008
constant Draggable (line 76) | Draggable Atom = 0x17b09
constant Dropzone (line 77) | Dropzone Atom = 0x39108
constant Dt (line 78) | Dt Atom = 0x50902
constant Em (line 79) | Em Atom = 0x6502
constant Embed (line 80) | Embed Atom = 0x6505
constant Enctype (line 81) | Enctype Atom = 0x21107
constant Face (line 82) | Face Atom = 0x5b304
constant Fieldset (line 83) | Fieldset Atom = 0x1b008
constant Figcaption (line 84) | Figcaption Atom = 0x1b80a
constant Figure (line 85) | Figure Atom = 0x1cc06
constant Font (line 86) | Font Atom = 0xda04
constant Footer (line 87) | Footer Atom = 0x8d06
constant For (line 88) | For Atom = 0x1d803
constant ForeignObject (line 89) | ForeignObject Atom = 0x1d80d
constant Foreignobject (line 90) | Foreignobject Atom = 0x1e50d
constant Form (line 91) | Form Atom = 0x1f204
constant Formaction (line 92) | Formaction Atom = 0x1f20a
constant Formenctype (line 93) | Formenctype Atom = 0x20d0b
constant Formmethod (line 94) | Formmethod Atom = 0x2280a
constant Formnovalidate (line 95) | Formnovalidate Atom = 0x2320e
constant Formtarget (line 96) | Formtarget Atom = 0x2470a
constant Frame (line 97) | Frame Atom = 0x9a05
constant Frameset (line 98) | Frameset Atom = 0x9a08
constant H1 (line 99) | H1 Atom = 0x26e02
constant H2 (line 100) | H2 Atom = 0x29402
constant H3 (line 101) | H3 Atom = 0x2a702
constant H4 (line 102) | H4 Atom = 0x2e902
constant H5 (line 103) | H5 Atom = 0x2f302
constant H6 (line 104) | H6 Atom = 0x50b02
constant Head (line 105) | Head Atom = 0x2d504
constant Header (line 106) | Header Atom = 0x2d506
constant Headers (line 107) | Headers Atom = 0x2d507
constant Height (line 108) | Height Atom = 0x25106
constant Hgroup (line 109) | Hgroup Atom = 0x25906
constant Hidden (line 110) | Hidden Atom = 0x26506
constant High (line 111) | High Atom = 0x26b04
constant Hr (line 112) | Hr Atom = 0x27002
constant Href (line 113) | Href Atom = 0x27004
constant Hreflang (line 114) | Hreflang Atom = 0x27008
constant Html (line 115) | Html Atom = 0x25504
constant HttpEquiv (line 116) | HttpEquiv Atom = 0x2780a
constant I (line 117) | I Atom = 0x601
constant Icon (line 118) | Icon Atom = 0x42204
constant Id (line 119) | Id Atom = 0x8502
constant Iframe (line 120) | Iframe Atom = 0x29606
constant Image (line 121) | Image Atom = 0x29c05
constant Img (line 122) | Img Atom = 0x2a103
constant Input (line 123) | Input Atom = 0x3e805
constant Inputmode (line 124) | Inputmode Atom = 0x3e809
constant Ins (line 125) | Ins Atom = 0x1a803
constant Isindex (line 126) | Isindex Atom = 0x2a907
constant Ismap (line 127) | Ismap Atom = 0x2b005
constant Itemid (line 128) | Itemid Atom = 0x33c06
constant Itemprop (line 129) | Itemprop Atom = 0x3c908
constant Itemref (line 130) | Itemref Atom = 0x5ad07
constant Itemscope (line 131) | Itemscope Atom = 0x2b909
constant Itemtype (line 132) | Itemtype Atom = 0x2c308
constant Kbd (line 133) | Kbd Atom = 0x1903
constant Keygen (line 134) | Keygen Atom = 0x3906
constant Keytype (line 135) | Keytype Atom = 0x53707
constant Kind (line 136) | Kind Atom = 0x10904
constant Label (line 137) | Label Atom = 0xf005
constant Lang (line 138) | Lang Atom = 0x27404
constant Legend (line 139) | Legend Atom = 0x18206
constant Li (line 140) | Li Atom = 0x1202
constant Link (line 141) | Link Atom = 0x12804
constant List (line 142) | List Atom = 0x44e04
constant Listing (line 143) | Listing Atom = 0x44e07
constant Loop (line 144) | Loop Atom = 0xf404
constant Low (line 145) | Low Atom = 0x11f03
constant Malignmark (line 146) | Malignmark Atom = 0x100a
constant Manifest (line 147) | Manifest Atom = 0x5f108
constant Map (line 148) | Map Atom = 0x2b203
constant Mark (line 149) | Mark Atom = 0x1604
constant Marquee (line 150) | Marquee Atom = 0x2cb07
constant Math (line 151) | Math Atom = 0x2d204
constant Max (line 152) | Max Atom = 0x2e103
constant Maxlength (line 153) | Maxlength Atom = 0x2e109
constant Media (line 154) | Media Atom = 0x6e05
constant Mediagroup (line 155) | Mediagroup Atom = 0x6e0a
constant Menu (line 156) | Menu Atom = 0x33804
constant Menuitem (line 157) | Menuitem Atom = 0x33808
constant Meta (line 158) | Meta Atom = 0x45d04
constant Meter (line 159) | Meter Atom = 0x24205
constant Method (line 160) | Method Atom = 0x22c06
constant Mglyph (line 161) | Mglyph Atom = 0x2a206
constant Mi (line 162) | Mi Atom = 0x2eb02
constant Min (line 163) | Min Atom = 0x2eb03
constant Minlength (line 164) | Minlength Atom = 0x2eb09
constant Mn (line 165) | Mn Atom = 0x23502
constant Mo (line 166) | Mo Atom = 0x3ed02
constant Ms (line 167) | Ms Atom = 0x2bc02
constant Mtext (line 168) | Mtext Atom = 0x2f505
constant Multiple (line 169) | Multiple Atom = 0x30308
constant Muted (line 170) | Muted Atom = 0x30b05
constant Name (line 171) | Name Atom = 0x6c04
constant Nav (line 172) | Nav Atom = 0x3e03
constant Nobr (line 173) | Nobr Atom = 0x5704
constant Noembed (line 174) | Noembed Atom = 0x6307
constant Noframes (line 175) | Noframes Atom = 0x9808
constant Noscript (line 176) | Noscript Atom = 0x3d208
constant Novalidate (line 177) | Novalidate Atom = 0x2360a
constant Object (line 178) | Object Atom = 0x1ec06
constant Ol (line 179) | Ol Atom = 0xc902
constant Onabort (line 180) | Onabort Atom = 0x13a07
constant Onafterprint (line 181) | Onafterprint Atom = 0x1c00c
constant Onautocomplete (line 182) | Onautocomplete Atom = 0x1fa0e
constant Onautocompleteerror (line 183) | Onautocompleteerror Atom = 0x1fa13
constant Onbeforeprint (line 184) | Onbeforeprint Atom = 0x6040d
constant Onbeforeunload (line 185) | Onbeforeunload Atom = 0x4e70e
constant Onblur (line 186) | Onblur Atom = 0xaa06
constant Oncancel (line 187) | Oncancel Atom = 0xe908
constant Oncanplay (line 188) | Oncanplay Atom = 0x28509
constant Oncanplaythrough (line 189) | Oncanplaythrough Atom = 0x28510
constant Onchange (line 190) | Onchange Atom = 0x3a708
constant Onclick (line 191) | Onclick Atom = 0x31007
constant Onclose (line 192) | Onclose Atom = 0x31707
constant Oncontextmenu (line 193) | Oncontextmenu Atom = 0x32f0d
constant Oncuechange (line 194) | Oncuechange Atom = 0x3420b
constant Ondblclick (line 195) | Ondblclick Atom = 0x34d0a
constant Ondrag (line 196) | Ondrag Atom = 0x35706
constant Ondragend (line 197) | Ondragend Atom = 0x35709
constant Ondragenter (line 198) | Ondragenter Atom = 0x3600b
constant Ondragleave (line 199) | Ondragleave Atom = 0x36b0b
constant Ondragover (line 200) | Ondragover Atom = 0x3760a
constant Ondragstart (line 201) | Ondragstart Atom = 0x3800b
constant Ondrop (line 202) | Ondrop Atom = 0x38f06
constant Ondurationchange (line 203) | Ondurationchange Atom = 0x39f10
constant Onemptied (line 204) | Onemptied Atom = 0x39609
constant Onended (line 205) | Onended Atom = 0x3af07
constant Onerror (line 206) | Onerror Atom = 0x3b607
constant Onfocus (line 207) | Onfocus Atom = 0x3bd07
constant Onhashchange (line 208) | Onhashchange Atom = 0x3da0c
constant Oninput (line 209) | Oninput Atom = 0x3e607
constant Oninvalid (line 210) | Oninvalid Atom = 0x3f209
constant Onkeydown (line 211) | Onkeydown Atom = 0x3fb09
constant Onkeypress (line 212) | Onkeypress Atom = 0x4080a
constant Onkeyup (line 213) | Onkeyup Atom = 0x41807
constant Onlanguagechange (line 214) | Onlanguagechange Atom = 0x43210
constant Onload (line 215) | Onload Atom = 0x44206
constant Onloadeddata (line 216) | Onloadeddata Atom = 0x4420c
constant Onloadedmetadata (line 217) | Onloadedmetadata Atom = 0x45510
constant Onloadstart (line 218) | Onloadstart Atom = 0x46b0b
constant Onmessage (line 219) | Onmessage Atom = 0x47609
constant Onmousedown (line 220) | Onmousedown Atom = 0x47f0b
constant Onmousemove (line 221) | Onmousemove Atom = 0x48a0b
constant Onmouseout (line 222) | Onmouseout Atom = 0x4950a
constant Onmouseover (line 223) | Onmouseover Atom = 0x4a20b
constant Onmouseup (line 224) | Onmouseup Atom = 0x4ad09
constant Onmousewheel (line 225) | Onmousewheel Atom = 0x4b60c
constant Onoffline (line 226) | Onoffline Atom = 0x4c209
constant Ononline (line 227) | Ononline Atom = 0x4cb08
constant Onpagehide (line 228) | Onpagehide Atom = 0x4d30a
constant Onpageshow (line 229) | Onpageshow Atom = 0x4fe0a
constant Onpause (line 230) | Onpause Atom = 0x50d07
constant Onplay (line 231) | Onplay Atom = 0x51706
constant Onplaying (line 232) | Onplaying Atom = 0x51709
constant Onpopstate (line 233) | Onpopstate Atom = 0x5200a
constant Onprogress (line 234) | Onprogress Atom = 0x52a0a
constant Onratechange (line 235) | Onratechange Atom = 0x53e0c
constant Onreset (line 236) | Onreset Atom = 0x54a07
constant Onresize (line 237) | Onresize Atom = 0x55108
constant Onscroll (line 238) | Onscroll Atom = 0x55f08
constant Onseeked (line 239) | Onseeked Atom = 0x56708
constant Onseeking (line 240) | Onseeking Atom = 0x56f09
constant Onselect (line 241) | Onselect Atom = 0x57808
constant Onshow (line 242) | Onshow Atom = 0x58206
constant Onsort (line 243) | Onsort Atom = 0x58b06
constant Onstalled (line 244) | Onstalled Atom = 0x59509
constant Onstorage (line 245) | Onstorage Atom = 0x59e09
constant Onsubmit (line 246) | Onsubmit Atom = 0x5a708
constant Onsuspend (line 247) | Onsuspend Atom = 0x5bb09
constant Ontimeupdate (line 248) | Ontimeupdate Atom = 0xdb0c
constant Ontoggle (line 249) | Ontoggle Atom = 0x5c408
constant Onunload (line 250) | Onunload Atom = 0x5cc08
constant Onvolumechange (line 251) | Onvolumechange Atom = 0x5d40e
constant Onwaiting (line 252) | Onwaiting Atom = 0x5e209
constant Open (line 253) | Open Atom = 0x3cf04
constant Optgroup (line 254) | Optgroup Atom = 0xf608
constant Optimum (line 255) | Optimum Atom = 0x5eb07
constant Option (line 256) | Option Atom = 0x60006
constant Output (line 257) | Output Atom = 0x49c06
constant P (line 258) | P Atom = 0xc01
constant Param (line 259) | Param Atom = 0xc05
constant Pattern (line 260) | Pattern Atom = 0x5107
constant Ping (line 261) | Ping Atom = 0x7704
constant Placeholder (line 262) | Placeholder Atom = 0xc30b
constant Plaintext (line 263) | Plaintext Atom = 0xfd09
constant Poster (line 264) | Poster Atom = 0x15706
constant Pre (line 265) | Pre Atom = 0x25e03
constant Preload (line 266) | Preload Atom = 0x25e07
constant Progress (line 267) | Progress Atom = 0x52c08
constant Prompt (line 268) | Prompt Atom = 0x5fa06
constant Public (line 269) | Public Atom = 0x41e06
constant Q (line 270) | Q Atom = 0x13101
constant Radiogroup (line 271) | Radiogroup Atom = 0x30a
constant Readonly (line 272) | Readonly Atom = 0x2fb08
constant Rel (line 273) | Rel Atom = 0x25f03
constant Required (line 274) | Required Atom = 0x1d008
constant Reversed (line 275) | Reversed Atom = 0x5a08
constant Rows (line 276) | Rows Atom = 0x9204
constant Rowspan (line 277) | Rowspan Atom = 0x9207
constant Rp (line 278) | Rp Atom = 0x1c602
constant Rt (line 279) | Rt Atom = 0x13f02
constant Ruby (line 280) | Ruby Atom = 0xaf04
constant S (line 281) | S Atom = 0x2c01
constant Samp (line 282) | Samp Atom = 0x4e04
constant Sandbox (line 283) | Sandbox Atom = 0xbb07
constant Scope (line 284) | Scope Atom = 0x2bd05
constant Scoped (line 285) | Scoped Atom = 0x2bd06
constant Script (line 286) | Script Atom = 0x3d406
constant Seamless (line 287) | Seamless Atom = 0x31c08
constant Section (line 288) | Section Atom = 0x4e207
constant Select (line 289) | Select Atom = 0x57a06
constant Selected (line 290) | Selected Atom = 0x57a08
constant Shape (line 291) | Shape Atom = 0x4f905
constant Size (line 292) | Size Atom = 0x55504
constant Sizes (line 293) | Sizes Atom = 0x55505
constant Small (line 294) | Small Atom = 0x18f05
constant Sortable (line 295) | Sortable Atom = 0x58d08
constant Sorted (line 296) | Sorted Atom = 0x19906
constant Source (line 297) | Source Atom = 0x1aa06
constant Spacer (line 298) | Spacer Atom = 0x2db06
constant Span (line 299) | Span Atom = 0x9504
constant Spellcheck (line 300) | Spellcheck Atom = 0x3230a
constant Src (line 301) | Src Atom = 0x3c303
constant Srcdoc (line 302) | Srcdoc Atom = 0x3c306
constant Srclang (line 303) | Srclang Atom = 0x41107
constant Start (line 304) | Start Atom = 0x38605
constant Step (line 305) | Step Atom = 0x5f704
constant Strike (line 306) | Strike Atom = 0x53306
constant Strong (line 307) | Strong Atom = 0x55906
constant Style (line 308) | Style Atom = 0x61105
constant Sub (line 309) | Sub Atom = 0x5a903
constant Summary (line 310) | Summary Atom = 0x61607
constant Sup (line 311) | Sup Atom = 0x61d03
constant Svg (line 312) | Svg Atom = 0x62003
constant System (line 313) | System Atom = 0x62306
constant Tabindex (line 314) | Tabindex Atom = 0x46308
constant Table (line 315) | Table Atom = 0x42d05
constant Target (line 316) | Target Atom = 0x24b06
constant Tbody (line 317) | Tbody Atom = 0x2e05
constant Td (line 318) | Td Atom = 0x4702
constant Template (line 319) | Template Atom = 0x62608
constant Textarea (line 320) | Textarea Atom = 0x2f608
constant Tfoot (line 321) | Tfoot Atom = 0x8c05
constant Th (line 322) | Th Atom = 0x22e02
constant Thead (line 323) | Thead Atom = 0x2d405
constant Time (line 324) | Time Atom = 0xdd04
constant Title (line 325) | Title Atom = 0xa105
constant Tr (line 326) | Tr Atom = 0x10502
constant Track (line 327) | Track Atom = 0x10505
constant Translate (line 328) | Translate Atom = 0x14009
constant Tt (line 329) | Tt Atom = 0x5302
constant Type (line 330) | Type Atom = 0x21404
constant Typemustmatch (line 331) | Typemustmatch Atom = 0x2140d
constant U (line 332) | U Atom = 0xb01
constant Ul (line 333) | Ul Atom = 0x8a02
constant Usemap (line 334) | Usemap Atom = 0x51106
constant Value (line 335) | Value Atom = 0x4005
constant Var (line 336) | Var Atom = 0x11503
constant Video (line 337) | Video Atom = 0x28105
constant Wbr (line 338) | Wbr Atom = 0x12103
constant Width (line 339) | Width Atom = 0x50705
constant Wrap (line 340) | Wrap Atom = 0x58704
constant Xmp (line 341) | Xmp Atom = 0xc103
constant hash0 (line 344) | hash0 = 0xc17da63e
constant maxAtomLen (line 346) | maxAtomLen = 19
constant atomText (line 687) | atomText = "abbradiogrouparamalignmarkbdialogaccept-charsetbodyaccesskey" +
FILE: vendor/golang.org/x/net/html/const.go
function isSpecialElement (line 94) | func isSpecialElement(element *Node) bool {
FILE: vendor/golang.org/x/net/html/doctype.go
function parseDoctype (line 16) | func parseDoctype(s string) (n *Node, quirks bool) {
FILE: vendor/golang.org/x/net/html/entity.go
constant longestEntityWithoutSemicolon (line 8) | longestEntityWithoutSemicolon = 6
FILE: vendor/golang.org/x/net/html/escape.go
function unescapeEntity (line 57) | func unescapeEntity(b []byte, dst, src int, attribute bool) (dst1, src1 ...
function unescape (line 167) | func unescape(b []byte, attribute bool) []byte {
function lower (line 187) | func lower(b []byte) []byte {
constant escapedChars (line 196) | escapedChars = "&'<>\"\r"
function escape (line 198) | func escape(w writer, s string) error {
function EscapeString (line 237) | func EscapeString(s string) string {
function UnescapeString (line 251) | func UnescapeString(s string) string {
FILE: vendor/golang.org/x/net/html/foreign.go
function adjustAttributeNames (line 11) | func adjustAttributeNames(aa []Attribute, nameMap map[string]string) {
function adjustForeignAttributes (line 19) | func adjustForeignAttributes(aa []Attribute) {
function htmlIntegrationPoint (line 34) | func htmlIntegrationPoint(n *Node) bool {
function mathMLTextIntegrationPoint (line 59) | func mathMLTextIntegrationPoint(n *Node) bool {
FILE: vendor/golang.org/x/net/html/node.go
type NodeType (line 12) | type NodeType
constant ErrorNode (line 15) | ErrorNode NodeType = iota
constant TextNode (line 16) | TextNode
constant DocumentNode (line 17) | DocumentNode
constant ElementNode (line 18) | ElementNode
constant CommentNode (line 19) | CommentNode
constant DoctypeNode (line 20) | DoctypeNode
constant scopeMarkerNode (line 21) | scopeMarkerNode
type Node (line 38) | type Node struct
method InsertBefore (line 53) | func (n *Node) InsertBefore(newChild, oldChild *Node) {
method AppendChild (line 81) | func (n *Node) AppendChild(c *Node) {
method RemoveChild (line 100) | func (n *Node) RemoveChild(c *Node) {
method clone (line 135) | func (n *Node) clone() *Node {
function reparentChildren (line 122) | func reparentChildren(dst, src *Node) {
type nodeStack (line 147) | type nodeStack
method pop (line 150) | func (s *nodeStack) pop() *Node {
method top (line 158) | func (s *nodeStack) top() *Node {
method index (line 167) | func (s *nodeStack) index(n *Node) int {
method insert (line 177) | func (s *nodeStack) insert(i int, n *Node) {
method remove (line 184) | func (s *nodeStack) remove(n *Node) {
FILE: vendor/golang.org/x/net/html/parse.go
type parser (line 18) | type parser struct
method top (line 52) | func (p *parser) top() *Node {
method popUntil (line 97) | func (p *parser) popUntil(s scope, matchTags ...a.Atom) bool {
method indexOfElementInScope (line 108) | func (p *parser) indexOfElementInScope(s scope, matchTags ...a.Atom) i...
method elementInScope (line 154) | func (p *parser) elementInScope(s scope, matchTags ...a.Atom) bool {
method clearStackToContext (line 160) | func (p *parser) clearStackToContext(s scope) {
method generateImpliedEndTags (line 188) | func (p *parser) generateImpliedEndTags(exceptions ...string) {
method addChild (line 212) | func (p *parser) addChild(n *Node) {
method shouldFosterParent (line 226) | func (p *parser) shouldFosterParent() bool {
method fosterParent (line 238) | func (p *parser) fosterParent(n *Node) {
method addText (line 273) | func (p *parser) addText(text string) {
method addElement (line 298) | func (p *parser) addElement() {
method addFormattingElement (line 308) | func (p *parser) addFormattingElement() {
method clearActiveFormattingElements (line 355) | func (p *parser) clearActiveFormattingElements() {
method reconstructActiveFormattingElements (line 365) | func (p *parser) reconstructActiveFormattingElements() {
method acknowledgeSelfClosingTag (line 394) | func (p *parser) acknowledgeSelfClosingTag() {
method setOriginalIM (line 407) | func (p *parser) setOriginalIM() {
method resetInsertionMode (line 415) | func (p *parser) resetInsertionMode() {
method inBodyEndTagFormatting (line 1038) | func (p *parser) inBodyEndTagFormatting(tagAtom a.Atom) {
method inBodyEndTagOther (line 1165) | func (p *parser) inBodyEndTagOther(tagAtom a.Atom) {
method inForeignContent (line 1928) | func (p *parser) inForeignContent() bool {
method parseImpliedToken (line 1958) | func (p *parser) parseImpliedToken(t TokenType, dataAtom a.Atom, data ...
method parseCurrentToken (line 1972) | func (p *parser) parseCurrentToken() {
method parse (line 1993) | func (p *parser) parse() error {
type scope (line 68) | type scope
constant defaultScope (line 71) | defaultScope scope = iota
constant listItemScope (line 72) | listItemScope
constant buttonScope (line 73) | buttonScope
constant tableScope (line 74) | tableScope
constant tableRowScope (line 75) | tableRowScope
constant tableBodyScope (line 76) | tableBodyScope
constant selectScope (line 77) | selectScope
type insertionMode (line 402) | type insertionMode
constant whitespace (line 453) | whitespace = " \t\r\n\f"
function initialIM (line 456) | func initialIM(p *parser) bool {
function beforeHTMLIM (line 483) | func beforeHTMLIM(p *parser) bool {
function beforeHeadIM (line 521) | func beforeHeadIM(p *parser) bool {
function inHeadIM (line 564) | func inHeadIM(p *parser) bool {
function afterHeadIM (line 626) | func afterHeadIM(p *parser) bool {
function copyAttributes (line 684) | func copyAttributes(dst *Node, src Token) {
function inBodyIM (line 701) | func inBodyIM(p *parser) bool {
function textIM (line 1178) | func textIM(p *parser) bool {
function inTableIM (line 1207) | func inTableIM(p *parser) bool {
function inCaptionIM (line 1313) | func inCaptionIM(p *parser) bool {
function inColumnGroupIM (line 1359) | func inColumnGroupIM(p *parser) bool {
function inTableBodyIM (line 1412) | func inTableBodyIM(p *parser) bool {
function inRowIM (line 1464) | func inRowIM(p *parser) bool {
function inCellIM (line 1515) | func inCellIM(p *parser) bool {
function inSelectIM (line 1564) | func inSelectIM(p *parser) bool {
function inSelectInTableIM (line 1636) | func inSelectInTableIM(p *parser) bool {
function afterBodyIM (line 1654) | func afterBodyIM(p *parser) bool {
function inFramesetIM (line 1692) | func inFramesetIM(p *parser) bool {
function afterFramesetIM (line 1742) | func afterFramesetIM(p *parser) bool {
function afterAfterBodyIM (line 1781) | func afterAfterBodyIM(p *parser) bool {
function afterAfterFramesetIM (line 1810) | func afterAfterFramesetIM(p *parser) bool {
constant whitespaceOrNUL (line 1845) | whitespaceOrNUL = whitespace + "\x00"
function parseForeignContent (line 1848) | func parseForeignContent(p *parser) bool {
function Parse (line 2016) | func Parse(r io.Reader) (*Node, error) {
function ParseFragment (line 2036) | func ParseFragment(r io.Reader, context *Node) ([]*Node, error) {
FILE: vendor/golang.org/x/net/html/render.go
type writer (line 15) | type writer interface
function Render (line 45) | func Render(w io.Writer, n *Node) error {
function render (line 60) | func render(w writer, n *Node) error {
function render1 (line 68) | func render1(w writer, n *Node) error {
function writeQuoted (line 235) | func writeQuoted(w writer, s string) error {
FILE: vendor/golang.org/x/net/html/token.go
type TokenType (line 18) | type TokenType
method String (line 41) | func (t TokenType) String() string {
constant ErrorToken (line 22) | ErrorToken TokenType = iota
constant TextToken (line 24) | TextToken
constant StartTagToken (line 26) | StartTagToken
constant EndTagToken (line 28) | EndTagToken
constant SelfClosingTagToken (line 30) | SelfClosingTagToken
constant CommentToken (line 32) | CommentToken
constant DoctypeToken (line 34) | DoctypeToken
type Attribute (line 67) | type Attribute struct
type Token (line 76) | type Token struct
method tagString (line 84) | func (t Token) tagString() string {
method String (line 100) | func (t Token) String() string {
type span (line 122) | type span struct
type Tokenizer (line 127) | type Tokenizer struct
method AllowCDATA (line 188) | func (z *Tokenizer) AllowCDATA(allowCDATA bool) {
method NextIsNotRawText (line 216) | func (z *Tokenizer) NextIsNotRawText() {
method Err (line 222) | func (z *Tokenizer) Err() error {
method readByte (line 234) | func (z *Tokenizer) readByte() byte {
method Buffered (line 290) | func (z *Tokenizer) Buffered() []byte {
method skipWhiteSpace (line 308) | func (z *Tokenizer) skipWhiteSpace() {
method readRawOrRCDATA (line 329) | func (z *Tokenizer) readRawOrRCDATA() {
method readRawEndTag (line 366) | func (z *Tokenizer) readRawEndTag() bool {
method readScript (line 393) | func (z *Tokenizer) readScript() {
method readComment (line 600) | func (z *Tokenizer) readComment() {
method readUntilCloseAngle (line 645) | func (z *Tokenizer) readUntilCloseAngle() {
method readMarkupDeclaration (line 663) | func (z *Tokenizer) readMarkupDeclaration() TokenType {
method readDoctype (line 692) | func (z *Tokenizer) readDoctype() bool {
method readCDATA (line 717) | func (z *Tokenizer) readCDATA() bool {
method startTagIn (line 756) | func (z *Tokenizer) startTagIn(ss ...string) bool {
method readStartTag (line 778) | func (z *Tokenizer) readStartTag() TokenType {
method readTag (line 816) | func (z *Tokenizer) readTag(saveAttr bool) {
method readTagName (line 845) | func (z *Tokenizer) readTagName() {
method readTagAttrKey (line 867) | func (z *Tokenizer) readTagAttrKey() {
method readTagAttrVal (line 888) | func (z *Tokenizer) readTagAttrVal() {
method Next (line 950) | func (z *Tokenizer) Next() TokenType {
method Raw (line 1070) | func (z *Tokenizer) Raw() []byte {
method Text (line 1113) | func (z *Tokenizer) Text() []byte {
method TagName (line 1134) | func (z *Tokenizer) TagName() (name []byte, hasAttr bool) {
method TagAttr (line 1150) | func (z *Tokenizer) TagAttr() (key, val []byte, moreAttr bool) {
method Token (line 1166) | func (z *Tokenizer) Token() Token {
method SetMaxBuf (line 1189) | func (z *Tokenizer) SetMaxBuf(n int) {
function readAtLeastOneByte (line 297) | func readAtLeastOneByte(r io.Reader, b []byte) (int, error) {
function convertNewlines (line 1076) | func convertNewlines(s []byte) []byte {
function NewTokenizer (line 1195) | func NewTokenizer(r io.Reader) *Tokenizer {
function NewTokenizerFragment (line 1207) | func NewTokenizerFragment(r io.Reader, contextTag string) *Tokenizer {
FILE: vendor/golang.org/x/net/publicsuffix/gen.go
constant nodesBitsChildren (line 41) | nodesBitsChildren = 9
constant nodesBitsICANN (line 42) | nodesBitsICANN = 1
constant nodesBitsTextOffset (line 43) | nodesBitsTextOffset = 15
constant nodesBitsTextLength (line 44) | nodesBitsTextLength = 6
constant childrenBitsWildcard (line 47) | childrenBitsWildcard = 1
constant childrenBitsNodeType (line 48) | childrenBitsNodeType = 2
constant childrenBitsHi (line 49) | childrenBitsHi = 14
constant childrenBitsLo (line 50) | childrenBitsLo = 14
function max (line 61) | func max(a, b int) int {
function u32max (line 68) | func u32max(a, b uint32) uint32 {
constant nodeTypeNormal (line 76) | nodeTypeNormal = 0
constant nodeTypeException (line 77) | nodeTypeException = 1
constant nodeTypeParentOnly (line 78) | nodeTypeParentOnly = 2
constant numNodeType (line 79) | numNodeType = 3
function nodeTypeStr (line 82) | func nodeTypeStr(n int) string {
function main (line 114) | func main() {
function main1 (line 121) | func main1() error {
function printTest (line 247) | func printTest(w io.Writer, n *node) error {
function printReal (line 261) | func printReal(w io.Writer, n *node) error {
type node (line 389) | type node struct
method walk (line 404) | func (n *node) walk(w io.Writer, f func(w1 io.Writer, n1 *node) error)...
method child (line 418) | func (n *node) child(label string) *node {
type byLabel (line 434) | type byLabel
method Len (line 436) | func (b byLabel) Len() int { return len(b) }
method Swap (line 437) | func (b byLabel) Swap(i, j int) { b[i], b[j] = b[j], b[i] }
method Less (line 438) | func (b byLabel) Less(i, j int) bool { return b[i].label < b[j].label }
function assignIndexes (line 455) | func assignIndexes(w io.Writer, n *node) error {
function printNode (line 500) | func printNode(w io.Writer, n *node) error {
function printNodeLabel (line 519) | func printNodeLabel(w io.Writer, n *node) error {
function icannStr (line 526) | func icannStr(icann bool) string {
function wildcardStr (line 533) | func wildcardStr(wildcard bool) string {
function combineText (line 543) | func combineText(labelsList []string) string {
type byLength (line 556) | type byLength
method Len (line 558) | func (s byLength) Len() int { return len(s) }
method Swap (line 559) | func (s byLength) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
method Less (line 560) | func (s byLength) Less(i, j int) bool { return len(s[i]) < len(s[j]) }
function removeSubstrings (line 564) | func removeSubstrings(input []string) []string {
function crush (line 590) | func crush(ss []string) string {
function mergeLabel (line 616) | func mergeLabel(ss []string, i, prefixLen int, prefixes prefixMap) {
type prefixMap (line 647) | type prefixMap
function makePrefixMap (line 650) | func makePrefixMap(ss []string, prefixLen int) prefixMap {
FILE: vendor/golang.org/x/net/publicsuffix/list.go
type list (line 23) | type list struct
method PublicSuffix (line 25) | func (list) PublicSuffix(domain string) string {
method String (line 30) | func (list) String() string {
function PublicSuffix (line 45) | func PublicSuffix(domain string) (publicSuffix string, icann bool) {
constant notFound (line 92) | notFound uint32 = 1<<32 - 1
function find (line 97) | func find(label string, lo, hi uint32) uint32 {
function nodeLabel (line 113) | func nodeLabel(i uint32) string {
function EffectiveTLDPlusOne (line 123) | func EffectiveTLDPlusOne(domain string) (string, error) {
FILE: vendor/golang.org/x/net/publicsuffix/table.go
constant version (line 5) | version = "publicsuffix.org's public_suffix_list.dat, git revision bade6...
constant nodesBitsChildren (line 8) | nodesBitsChildren = 9
constant nodesBitsICANN (line 9) | nodesBitsICANN = 1
constant nodesBitsTextOffset (line 10) | nodesBitsTextOffset = 15
constant nodesBitsTextLength (line 11) | nodesBitsTextLength = 6
constant childrenBitsWildcard (line 13) | childrenBitsWildcard = 1
constant childrenBitsNodeType (line 14) | childrenBitsNodeType = 2
constant childrenBitsHi (line 15) | childrenBitsHi = 14
constant childrenBitsLo (line 16) | childrenBitsLo = 14
constant nodeTypeNormal (line 20) | nodeTypeNormal = 0
constant nodeTypeException (line 21) | nodeTypeException = 1
constant nodeTypeParentOnly (line 22) | nodeTypeParentOnly = 2
constant numTLD (line 26) | numTLD = 1545
constant text (line 29) | text = "bievatmallorcadaquesanfranciscotlandupontarioceanographiquebifuk" +
FILE: vendor/gopkg.in/yaml.v1/apic.go
function yaml_insert_token (line 8) | func yaml_insert_token(parser *yaml_parser_t, pos int, token *yaml_token...
function yaml_parser_initialize (line 28) | func yaml_parser_initialize(parser *yaml_parser_t) bool {
function yaml_parser_delete (line 37) | func yaml_parser_delete(parser *yaml_parser_t) {
function yaml_string_read_handler (line 42) | func yaml_string_read_handler(parser *yaml_parser_t, buffer []byte) (n i...
function yaml_file_read_handler (line 52) | func yaml_file_read_handler(parser *yaml_parser_t, buffer []byte) (n int...
function yaml_parser_set_input_string (line 57) | func yaml_parser_set_input_string(parser *yaml_parser_t, input []byte) {
function yaml_parser_set_input_file (line 67) | func yaml_parser_set_input_file(parser *yaml_parser_t, file *os.File) {
function yaml_parser_set_encoding (line 76) | func yaml_parser_set_encoding(parser *yaml_parser_t, encoding yaml_encod...
function yaml_emitter_initialize (line 84) | func yaml_emitter_initialize(emitter *yaml_emitter_t) bool {
function yaml_emitter_delete (line 95) | func yaml_emitter_delete(emitter *yaml_emitter_t) {
function yaml_string_write_handler (line 100) | func yaml_string_write_handler(emitter *yaml_emitter_t, buffer []byte) e...
function yaml_file_write_handler (line 106) | func yaml_file_write_handler(emitter *yaml_emitter_t, buffer []byte) err...
function yaml_emitter_set_output_string (line 112) | func yaml_emitter_set_output_string(emitter *yaml_emitter_t, output_buff...
function yaml_emitter_set_output_file (line 121) | func yaml_emitter_set_output_file(emitter *yaml_emitter_t, file io.Write...
function yaml_emitter_set_encoding (line 130) | func yaml_emitter_set_encoding(emitter *yaml_emitter_t, encoding yaml_en...
function yaml_emitter_set_canonical (line 138) | func yaml_emitter_set_canonical(emitter *yaml_emitter_t, canonical bool) {
function yaml_emitter_set_indent (line 143) | func yaml_emitter_set_indent(emitter *yaml_emitter_t, indent int) {
function yaml_emitter_set_width (line 151) | func yaml_emitter_set_width(emitter *yaml_emitter_t, width int) {
function yaml_emitter_set_unicode (line 159) | func yaml_emitter_set_unicode(emitter *yaml_emitter_t, unicode bool) {
function yaml_emitter_set_break (line 164) | func yaml_emitter_set_break(emitter *yaml_emitter_t, line_break yaml_bre...
function yaml_stream_start_event_initialize (line 255) | func yaml_stream_start_event_initialize(event *yaml_event_t, encoding ya...
function yaml_stream_end_event_initialize (line 264) | func yaml_stream_end_event_initialize(event *yaml_event_t) bool {
function yaml_document_start_event_initialize (line 272) | func yaml_document_start_event_initialize(event *yaml_event_t, version_d...
function yaml_document_end_event_initialize (line 284) | func yaml_document_end_event_initialize(event *yaml_event_t, implicit bo...
function yaml_scalar_event_initialize (line 317) | func yaml_scalar_event_initialize(event *yaml_event_t, anchor, tag, valu...
function yaml_sequence_start_event_initialize (line 331) | func yaml_sequence_start_event_initialize(event *yaml_event_t, anchor, t...
function yaml_sequence_end_event_initialize (line 343) | func yaml_sequence_end_event_initialize(event *yaml_event_t) bool {
function yaml_mapping_start_event_initialize (line 351) | func yaml_mapping_start_event_initialize(event *yaml_event_t, anchor, ta...
function yaml_mapping_end_event_initialize (line 363) | func yaml_mapping_end_event_initialize(event *yaml_event_t) bool {
function yaml_event_delete (line 371) | func yaml_event_delete(event *yaml_event_t) {
FILE: vendor/gopkg.in/yaml.v1/decode.go
constant documentNode (line 12) | documentNode = 1 << iota
constant mappingNode (line 13) | mappingNode
constant sequenceNode (line 14) | sequenceNode
constant scalarNode (line 15) | scalarNode
constant aliasNode (line 16) | aliasNode
type node (line 19) | type node struct
type parser (line 32) | type parser struct
method destroy (line 58) | func (p *parser) destroy() {
method skip (line 65) | func (p *parser) skip() {
method fail (line 77) | func (p *parser) fail() {
method anchor (line 97) | func (p *parser) anchor(n *node, anchor []byte) {
method parse (line 103) | func (p *parser) parse() *node {
method node (line 124) | func (p *parser) node(kind int) *node {
method document (line 132) | func (p *parser) document() *node {
method alias (line 145) | func (p *parser) alias() *node {
method scalar (line 152) | func (p *parser) scalar() *node {
method sequence (line 162) | func (p *parser) sequence() *node {
method mapping (line 173) | func (p *parser) mapping() *node {
function newParser (line 38) | func newParser(b []byte) *parser {
type decoder (line 187) | type decoder struct
method setter (line 214) | func (d *decoder) setter(tag string, out *reflect.Value, good *bool) (...
method unmarshal (line 252) | func (d *decoder) unmarshal(n *node, out reflect.Value) (good bool) {
method document (line 270) | func (d *decoder) document(n *node, out reflect.Value) (good bool) {
method alias (line 279) | func (d *decoder) alias(n *node, out reflect.Value) (good bool) {
method scalar (line 303) | func (d *decoder) scalar(n *node, out reflect.Value) (good bool) {
method sequence (line 427) | func (d *decoder) sequence(n *node, out reflect.Value) (good bool) {
method mapping (line 456) | func (d *decoder) mapping(n *node, out reflect.Value) (good bool) {
method mappingStruct (line 505) | func (d *decoder) mappingStruct(n *node, out reflect.Value) (good bool) {
method merge (line 534) | func (d *decoder) merge(n *node, out reflect.Value) {
function newDecoder (line 192) | func newDecoder() *decoder {
function resetMap (line 295) | func resetMap(out reflect.Value) {
function settableValueOf (line 420) | func settableValueOf(i interface{}) reflect.Value {
function isMerge (line 564) | func isMerge(n *node) bool {
FILE: vendor/gopkg.in/yaml.v1/emitterc.go
function flush (line 8) | func flush(emitter *yaml_emitter_t) bool {
function put (line 16) | func put(emitter *yaml_emitter_t, value byte) bool {
function put_break (line 27) | func put_break(emitter *yaml_emitter_t) bool {
function write (line 51) | func write(emitter *yaml_emitter_t, s []byte, i *int) bool {
function write_all (line 79) | func write_all(emitter *yaml_emitter_t, s []byte) bool {
function write_break (line 89) | func write_break(emitter *yaml_emitter_t, s []byte, i *int) bool {
function yaml_emitter_set_emitter_error (line 106) | func yaml_emitter_set_emitter_error(emitter *yaml_emitter_t, problem str...
function yaml_emitter_emit (line 113) | func yaml_emitter_emit(emitter *yaml_emitter_t, event *yaml_event_t) bool {
function yaml_emitter_need_more_events (line 136) | func yaml_emitter_need_more_events(emitter *yaml_emitter_t) bool {
function yaml_emitter_append_tag_directive (line 173) | func yaml_emitter_append_tag_directive(emitter *yaml_emitter_t, value *y...
function yaml_emitter_increase_indent (line 196) | func yaml_emitter_increase_indent(emitter *yaml_emitter_t, flow, indentl...
function yaml_emitter_state_machine (line 211) | func yaml_emitter_state_machine(emitter *yaml_emitter_t, event *yaml_eve...
function yaml_emitter_emit_stream_start (line 272) | func yaml_emitter_emit_stream_start(emitter *yaml_emitter_t, event *yaml...
function yaml_emitter_emit_document_start (line 311) | func yaml_emitter_emit_document_start(emitter *yaml_emitter_t, event *ya...
function yaml_emitter_emit_document_content (line 425) | func yaml_emitter_emit_document_content(emitter *yaml_emitter_t, event *...
function yaml_emitter_emit_document_end (line 431) | func yaml_emitter_emit_document_end(emitter *yaml_emitter_t, event *yaml...
function yaml_emitter_emit_flow_sequence_item (line 456) | func yaml_emitter_emit_flow_sequence_item(emitter *yaml_emitter_t, event...
function yaml_emitter_emit_flow_mapping_key (line 504) | func yaml_emitter_emit_flow_mapping_key(emitter *yaml_emitter_t, event *...
function yaml_emitter_emit_flow_mapping_value (line 558) | func yaml_emitter_emit_flow_mapping_value(emitter *yaml_emitter_t, event...
function yaml_emitter_emit_block_sequence_item (line 578) | func yaml_emitter_emit_block_sequence_item(emitter *yaml_emitter_t, even...
function yaml_emitter_emit_block_mapping_key (line 602) | func yaml_emitter_emit_block_mapping_key(emitter *yaml_emitter_t, event ...
function yaml_emitter_emit_block_mapping_value (line 630) | func yaml_emitter_emit_block_mapping_value(emitter *yaml_emitter_t, even...
function yaml_emitter_emit_node (line 648) | func yaml_emitter_emit_node(emitter *yaml_emitter_t, event *yaml_event_t,
function yaml_emitter_emit_alias (line 673) | func yaml_emitter_emit_alias(emitter *yaml_emitter_t, event *yaml_event_...
function yaml_emitter_emit_scalar (line 683) | func yaml_emitter_emit_scalar(emitter *yaml_emitter_t, event *yaml_event...
function yaml_emitter_emit_sequence_start (line 707) | func yaml_emitter_emit_sequence_start(emitter *yaml_emitter_t, event *ya...
function yaml_emitter_emit_mapping_start (line 724) | func yaml_emitter_emit_mapping_start(emitter *yaml_emitter_t, event *yam...
function yaml_emitter_check_empty_document (line 741) | func yaml_emitter_check_empty_document(emitter *yaml_emitter_t) bool {
function yaml_emitter_check_empty_sequence (line 746) | func yaml_emitter_check_empty_sequence(emitter *yaml_emitter_t) bool {
function yaml_emitter_check_empty_mapping (line 755) | func yaml_emitter_check_empty_mapping(emitter *yaml_emitter_t) bool {
function yaml_emitter_check_simple_key (line 764) | func yaml_emitter_check_simple_key(emitter *yaml_emitter_t) bool {
function yaml_emitter_select_scalar_style (line 798) | func yaml_emitter_select_scalar_style(emitter *yaml_emitter_t, event *ya...
function yaml_emitter_process_anchor (line 847) | func yaml_emitter_process_anchor(emitter *yaml_emitter_t) bool {
function yaml_emitter_process_tag (line 862) | func yaml_emitter_process_tag(emitter *yaml_emitter_t) bool {
function yaml_emitter_process_scalar (line 891) | func yaml_emitter_process_scalar(emitter *yaml_emitter_t) bool {
function yaml_emitter_analyze_version_directive (line 912) | func yaml_emitter_analyze_version_directive(emitter *yaml_emitter_t, ver...
function yaml_emitter_analyze_tag_directive (line 920) | func yaml_emitter_analyze_tag_directive(emitter *yaml_emitter_t, tag_dir...
function yaml_emitter_analyze_anchor (line 944) | func yaml_emitter_analyze_anchor(emitter *yaml_emitter_t, anchor []byte,...
function yaml_emitter_analyze_tag (line 967) | func yaml_emitter_analyze_tag(emitter *yaml_emitter_t, tag []byte) bool {
function yaml_emitter_analyze_scalar (line 984) | func yaml_emitter_analyze_scalar(emitter *yaml_emitter_t, value []byte) ...
function yaml_emitter_analyze_event (line 1133) | func yaml_emitter_analyze_event(emitter *yaml_emitter_t, event *yaml_eve...
function yaml_emitter_write_bom (line 1189) | func yaml_emitter_write_bom(emitter *yaml_emitter_t) bool {
function yaml_emitter_write_indent (line 1201) | func yaml_emitter_write_indent(emitter *yaml_emitter_t) bool {
function yaml_emitter_write_indicator (line 1221) | func yaml_emitter_write_indicator(emitter *yaml_emitter_t, indicator []b...
function yaml_emitter_write_anchor (line 1236) | func yaml_emitter_write_anchor(emitter *yaml_emitter_t, value []byte) bo...
function yaml_emitter_write_tag_handle (line 1245) | func yaml_emitter_write_tag_handle(emitter *yaml_emitter_t, value []byte...
function yaml_emitter_write_tag_content (line 1259) | func yaml_emitter_write_tag_content(emitter *yaml_emitter_t, value []byt...
function yaml_emitter_write_plain_scalar (line 1313) | func yaml_emitter_write_plain_scalar(emitter *yaml_emitter_t, value []by...
function yaml_emitter_write_single_quoted_scalar (line 1370) | func yaml_emitter_write_single_quoted_scalar(emitter *yaml_emitter_t, va...
function yaml_emitter_write_double_quoted_scalar (line 1429) | func yaml_emitter_write_double_quoted_scalar(emitter *yaml_emitter_t, va...
function yaml_emitter_write_block_scalar_hints (line 1550) | func yaml_emitter_write_block_scalar_hints(emitter *yaml_emitter_t, valu...
function yaml_emitter_write_literal_scalar (line 1592) | func yaml_emitter_write_literal_scalar(emitter *yaml_emitter_t, value []...
function yaml_emitter_write_folded_scalar (line 1629) | func yaml_emitter_write_folded_scalar(emitter *yaml_emitter_t, value []b...
FILE: vendor/gopkg.in/yaml.v1/encode.go
type encoder (line 12) | type encoder struct
method finish (line 30) | func (e *encoder) finish() {
method destroy (line 38) | func (e *encoder) destroy() {
method emit (line 42) | func (e *encoder) emit() {
method must (line 49) | func (e *encoder) must(ok bool) {
method marshal (line 59) | func (e *encoder) marshal(tag string, in reflect.Value) {
method mapv (line 112) | func (e *encoder) mapv(tag string, in reflect.Value) {
method structv (line 123) | func (e *encoder) structv(tag string, in reflect.Value) {
method mappingv (line 146) | func (e *encoder) mappingv(tag string, f func()) {
method slicev (line 160) | func (e *encoder) slicev(tag string, in reflect.Value) {
method stringv (line 199) | func (e *encoder) stringv(tag string, in reflect.Value) {
method boolv (line 223) | func (e *encoder) boolv(tag string, in reflect.Value) {
method intv (line 233) | func (e *encoder) intv(tag string, in reflect.Value) {
method uintv (line 238) | func (e *encoder) uintv(tag string, in reflect.Value) {
method floatv (line 243) | func (e *encoder) floatv(tag string, in reflect.Value) {
method nilv (line 257) | func (e *encoder) nilv() {
method emitScalar (line 261) | func (e *encoder) emitScalar(value, anchor, tag string, style yaml_sca...
function newEncoder (line 19) | func newEncoder() (e *encoder) {
function isBase60Float (line 182) | func isBase60Float(s string) (result bool) {
FILE: vendor/gopkg.in/yaml.v1/parserc.go
function peek_token (line 46) | func peek_token(parser *yaml_parser_t) *yaml_token_t {
function skip_token (line 54) | func skip_token(parser *yaml_parser_t) {
function yaml_parser_parse (line 62) | func yaml_parser_parse(parser *yaml_parser_t, event *yaml_event_t) bool {
function yaml_parser_set_parser_error (line 76) | func yaml_parser_set_parser_error(parser *yaml_parser_t, problem string,...
function yaml_parser_set_parser_error_context (line 83) | func yaml_parser_set_parser_error_context(parser *yaml_parser_t, context...
function yaml_parser_state_machine (line 93) | func yaml_parser_state_machine(parser *yaml_parser_t, event *yaml_event_...
function yaml_parser_parse_stream_start (line 175) | func yaml_parser_parse_stream_start(parser *yaml_parser_t, event *yaml_e...
function yaml_parser_parse_document_start (line 199) | func yaml_parser_parse_document_start(parser *yaml_parser_t, event *yaml...
function yaml_parser_parse_document_content (line 283) | func yaml_parser_parse_document_content(parser *yaml_parser_t, event *ya...
function yaml_parser_parse_document_end (line 306) | func yaml_parser_parse_document_end(parser *yaml_parser_t, event *yaml_e...
function yaml_parser_parse_node (line 360) | func yaml_parser_parse_node(parser *yaml_parser_t, event *yaml_event_t, ...
function yaml_parser_parse_block_sequence_entry (line 580) | func yaml_parser_parse_block_sequence_entry(parser *yaml_parser_t, event...
function yaml_parser_parse_indentless_sequence_entry (line 632) | func yaml_parser_parse_indentless_sequence_entry(parser *yaml_parser_t, ...
function yaml_parser_parse_block_mapping_key (line 676) | func yaml_parser_parse_block_mapping_key(parser *yaml_parser_t, event *y...
function yaml_parser_parse_block_mapping_value (line 734) | func yaml_parser_parse_block_mapping_value(parser *yaml_parser_t, event ...
function yaml_parser_parse_flow_sequence_entry (line 771) | func yaml_parser_parse_flow_sequence_entry(parser *yaml_parser_t, event ...
function yaml_parser_parse_flow_sequence_entry_mapping_key (line 834) | func yaml_parser_parse_flow_sequence_entry_mapping_key(parser *yaml_pars...
function yaml_parser_parse_flow_sequence_entry_mapping_value (line 855) | func yaml_parser_parse_flow_sequence_entry_mapping_value(parser *yaml_pa...
function yaml_parser_parse_flow_sequence_entry_mapping_end (line 879) | func yaml_parser_parse_flow_sequence_entry_mapping_end(parser *yaml_pars...
function yaml_parser_parse_flow_mapping_key (line 905) | func yaml_parser_parse_flow_mapping_key(parser *yaml_parser_t, event *ya...
function yaml_parser_parse_flow_mapping_value (line 971) | func yaml_parser_parse_flow_mapping_value(parser *yaml_parser_t, event *...
function yaml_parser_process_empty_scalar (line 996) | func yaml_parser_process_empty_scalar(parser *yaml_parser_t, event *yaml...
function yaml_parser_process_directives (line 1014) | func yaml_parser_process_directives(parser *yaml_parser_t,
function yaml_parser_append_tag_directive (line 1076) | func yaml_parser_append_tag_directive(parser *yaml_parser_t, value yaml_...
FILE: vendor/gopkg.in/yaml.v1/readerc.go
function yaml_parser_set_reader_error (line 8) | func yaml_parser_set_reader_error(parser *yaml_parser_t, problem string,...
constant bom_UTF8 (line 18) | bom_UTF8 = "\xef\xbb\xbf"
constant bom_UTF16LE (line 19) | bom_UTF16LE = "\xff\xfe"
constant bom_UTF16BE (line 20) | bom_UTF16BE = "\xfe\xff"
function yaml_parser_determine_encoding (line 25) | func yaml_parser_determine_encoding(parser *yaml_parser_t) bool {
function yaml_parser_update_raw_buffer (line 56) | func yaml_parser_update_raw_buffer(parser *yaml_parser_t) bool {
function yaml_parser_update_buffer (line 91) | func yaml_parser_update_buffer(parser *yaml_parser_t, length int) bool {
FILE: vendor/gopkg.in/yaml.v1/resolve.go
type resolveMapItem (line 14) | type resolveMapItem struct
function init (line 22) | func init() {
constant longTagPrefix (line 61) | longTagPrefix = "tag:yaml.org,2002:"
function shortTag (line 63) | func shortTag(tag string) string {
function longTag (line 71) | func longTag(tag string) string {
function resolvableTag (line 78) | func resolvableTag(tag string) bool {
function resolve (line 86) | func resolve(tag string, in string) (rtag string, out interface{}) {
function encodeBase64 (line 169) | func encodeBase64(s string) string {
FILE: vendor/gopkg.in/yaml.v1/scannerc.go
function cache (line 485) | func cache(parser *yaml_parser_t, length int) bool {
function skip (line 491) | func skip(parser *yaml_parser_t) {
function skip_line (line 498) | func skip_line(parser *yaml_parser_t) {
function read (line 515) | func read(parser *yaml_parser_t, s []byte) []byte {
function read_line (line 538) | func read_line(parser *yaml_parser_t, s []byte) []byte {
function yaml_parser_scan (line 571) | func yaml_parser_scan(parser *yaml_parser_t, token *yaml_token_t) bool {
function yaml_parser_set_scanner_error (line 600) | func yaml_parser_set_scanner_error(parser *yaml_parser_t, context string...
function yaml_parser_set_scanner_tag_error (line 609) | func yaml_parser_set_scanner_tag_error(parser *yaml_parser_t, directive ...
function trace (line 617) | func trace(args ...interface{}) func() {
function yaml_parser_fetch_more_tokens (line 626) | func yaml_parser_fetch_more_tokens(parser *yaml_parser_t) bool {
function yaml_parser_fetch_next_token (line 665) | func yaml_parser_fetch_next_token(parser *yaml_parser_t) bool {
function yaml_parser_stale_simple_keys (line 842) | func yaml_parser_stale_simple_keys(parser *yaml_parser_t) bool {
function yaml_parser_save_simple_key (line 867) | func yaml_parser_save_simple_key(parser *yaml_parser_t) bool {
function yaml_parser_remove_simple_key (line 900) | func yaml_parser_remove_simple_key(parser *yaml_parser_t) bool {
function yaml_parser_increase_flow_level (line 916) | func yaml_parser_increase_flow_level(parser *yaml_parser_t) bool {
function yaml_parser_decrease_flow_level (line 926) | func yaml_parser_decrease_flow_level(parser *yaml_parser_t) bool {
function yaml_parser_roll_indent (line 937) | func yaml_parser_roll_indent(parser *yaml_parser_t, column, number int, ...
function yaml_parser_unroll_indent (line 966) | func yaml_parser_unroll_indent(parser *yaml_parser_t, column int) bool {
function yaml_parser_fetch_stream_start (line 990) | func yaml_parser_fetch_stream_start(parser *yaml_parser_t) bool {
function yaml_parser_fetch_stream_end (line 1016) | func yaml_parser_fetch_stream_end(parser *yaml_parser_t) bool {
function yaml_parser_fetch_directive (line 1047) | func yaml_parser_fetch_directive(parser *yaml_parser_t) bool {
function yaml_parser_fetch_document_indicator (line 1071) | func yaml_parser_fetch_document_indicator(parser *yaml_parser_t, typ yam...
function yaml_parser_fetch_flow_collection_start (line 1105) | func yaml_parser_fetch_flow_collection_start(parser *yaml_parser_t, typ ...
function yaml_parser_fetch_flow_collection_end (line 1136) | func yaml_parser_fetch_flow_collection_end(parser *yaml_parser_t, typ ya...
function yaml_parser_fetch_flow_entry (line 1168) | func yaml_parser_fetch_flow_entry(parser *yaml_parser_t) bool {
function yaml_parser_fetch_block_entry (line 1193) | func yaml_parser_fetch_block_entry(parser *yaml_parser_t) bool {
function yaml_parser_fetch_key (line 1235) | func yaml_parser_fetch_key(parser *yaml_parser_t) bool {
function yaml_parser_fetch_value (line 1274) | func yaml_parser_fetch_value(parser *yaml_parser_t) bool {
function yaml_parser_fetch_anchor (line 1339) | func yaml_parser_fetch_anchor(parser *yaml_parser_t, typ yaml_token_type...
function yaml_parser_fetch_tag (line 1358) | func yaml_parser_fetch_tag(parser *yaml_parser_t) bool {
function yaml_parser_fetch_block_scalar (line 1377) | func yaml_parser_fetch_block_scalar(parser *yaml_parser_t, literal bool)...
function yaml_parser_fetch_flow_scalar (line 1396) | func yaml_parser_fetch_flow_scalar(parser *yaml_parser_t, single bool) b...
function yaml_parser_fetch_plain_scalar (line 1415) | func yaml_parser_fetch_plain_scalar(parser *yaml_parser_t) bool {
function yaml_parser_scan_to_next_token (line 1434) | func yaml_parser_scan_to_next_token(parser *yaml_parser_t) bool {
function yaml_parser_scan_directive (line 1499) | func yaml_parser_scan_directive(parser *yaml_parser_t, token *yaml_token...
function yaml_parser_scan_directive_name (line 1600) | func yaml_parser_scan_directive_name(parser *yaml_parser_t, start_mark y...
function yaml_parser_scan_version_directive_value (line 1636) | func yaml_parser_scan_version_directive_value(parser *yaml_parser_t, sta...
constant max_number_length (line 1668) | max_number_length = 2
function yaml_parser_scan_version_directive_number (line 1677) | func yaml_parser_scan_version_directive_number(parser *yaml_parser_t, st...
function yaml_parser_scan_tag_directive_value (line 1713) | func yaml_parser_scan_tag_directive_value(parser *yaml_parser_t, start_m...
function yaml_parser_scan_anchor (line 1771) | func yaml_parser_scan_anchor(parser *yaml_parser_t, token *yaml_token_t,...
function yaml_parser_scan_tag (line 1829) | func yaml_parser_scan_tag(parser *yaml_parser_t, token *yaml_token_t) bo...
function yaml_parser_scan_tag_handle (line 1914) | func yaml_parser_scan_tag_handle(parser *yaml_parser_t, directive bool, ...
function yaml_parser_scan_tag_uri (line 1959) | func yaml_parser_scan_tag_uri(parser *yaml_parser_t, directive bool, hea...
function yaml_parser_scan_uri_escapes (line 2016) | func yaml_parser_scan_uri_escapes(parser *yaml_parser_t, directive bool,...
function yaml_parser_scan_block_scalar (line 2062) | func yaml_parser_scan_block_scalar(parser *yaml_parser_t, token *yaml_to...
function yaml_parser_scan_block_scalar_breaks (line 2250) | func yaml_parser_scan_block_scalar_breaks(parser *yaml_parser_t, indent ...
function yaml_parser_scan_flow_scalar (line 2304) | func yaml_parser_scan_flow_scalar(parser *yaml_parser_t, token *yaml_tok...
function yaml_parser_scan_plain_scalar (line 2560) | func yaml_parser_scan_plain_scalar(parser *yaml_parser_t, token *yaml_to...
FILE: vendor/gopkg.in/yaml.v1/sorter.go
type keyList (line 8) | type keyList
method Len (line 10) | func (l keyList) Len() int { return len(l) }
method Swap (line 11) | func (l keyList) Swap(i, j int) { l[i], l[j] = l[j], l[i] }
method Less (line 12) | func (l keyList) Less(i, j int) bool {
function keyFloat (line 73) | func keyFloat(v reflect.Value) (f float64, ok bool) {
function numLess (line 92) | func numLess(a, b reflect.Value) bool {
FILE: vendor/gopkg.in/yaml.v1/writerc.go
function yaml_emitter_set_writer_error (line 4) | func yaml_emitter_set_writer_error(emitter *yaml_emitter_t, problem stri...
function yaml_emitter_flush (line 11) | func yaml_emitter_flush(emitter *yaml_emitter_t) bool {
FILE: vendor/gopkg.in/yaml.v1/yaml.go
type yamlError (line 17) | type yamlError
function fail (line 19) | func fail(msg string) {
function handleErr (line 23) | func handleErr(err *error) {
type Setter (line 38) | type Setter interface
type Getter (line 44) | type Getter interface
function Unmarshal (line 84) | func Unmarshal(in []byte, out interface{}) (err error) {
function Marshal (line 139) | func Marshal(in interface{}) (out []byte, err error) {
type structInfo (line 156) | type structInfo struct
type fieldInfo (line 165) | type fieldInfo struct
function getStructInfo (line 178) | func getStructInfo(st reflect.Type) (*structInfo, error) {
function isZero (line 283) | func isZero(v reflect.Value) bool {
FILE: vendor/gopkg.in/yaml.v1/yamlh.go
type yaml_version_directive_t (line 8) | type yaml_version_directive_t struct
type yaml_tag_directive_t (line 14) | type yaml_tag_directive_t struct
type yaml_encoding_t (line 19) | type yaml_encoding_t
constant yaml_ANY_ENCODING (line 24) | yaml_ANY_ENCODING yaml_encoding_t = iota
constant yaml_UTF8_ENCODING (line 26) | yaml_UTF8_ENCODING
constant yaml_UTF16LE_ENCODING (line 27) | yaml_UTF16LE_ENCODING
constant yaml_UTF16BE_ENCODING (line 28) | yaml_UTF16BE_ENCODING
type yaml_break_t (line 31) | type yaml_break_t
constant yaml_ANY_BREAK (line 36) | yaml_ANY_BREAK yaml_break_t = iota
constant yaml_CR_BREAK (line 38) | yaml_CR_BREAK
constant yaml_LN_BREAK (line 39) | yaml_LN_BREAK
constant yaml_CRLN_BREAK (line 40) | yaml_CRLN_BREAK
type yaml_error_type_t (line 43) | type yaml_error_type_t
constant yaml_NO_ERROR (line 48) | yaml_NO_ERROR yaml_error_type_t = iota
constant yaml_MEMORY_ERROR (line 50) | yaml_MEMORY_ERROR
constant yaml_READER_ERROR (line 51) | yaml_READER_ERROR
constant yaml_SCANNER_ERROR (line 52) | yaml_SCANNER_ERROR
constant yaml_PARSER_ERROR (line 53) | yaml_PARSER_ERROR
constant yaml_COMPOSER_ERROR (line 54) | yaml_COMPOSER_ERROR
constant yaml_WRITER_ERROR (line 55) | yaml_WRITER_ERROR
constant yaml_EMITTER_ERROR (line 56) | yaml_EMITTER_ERROR
type yaml_mark_t (line 60) | type yaml_mark_t struct
type yaml_style_t (line 68) | type yaml_style_t
type yaml_scalar_style_t (line 70) | type yaml_scalar_style_t
constant yaml_ANY_SCALAR_STYLE (line 75) | yaml_ANY_SCALAR_STYLE yaml_scalar_style_t = iota
constant yaml_PLAIN_SCALAR_STYLE (line 77) | yaml_PLAIN_SCALAR_STYLE
constant yaml_SINGLE_QUOTED_SCALAR_STYLE (line 78) | yaml_SINGLE_QUOTED_SCALAR_STYLE
constant yaml_DOUBLE_QUOTED_SCALAR_STYLE (line 79) | yaml_DOUBLE_QUOTED_SCALAR_STYLE
constant yaml_LITERAL_SCALAR_STYLE (line 80) | yaml_LITERAL_SCALAR_STYLE
constant yaml_FOLDED_SCALAR_STYLE (line 81) | yaml_FOLDED_SCALAR_STYLE
type yaml_sequence_style_t (line 84) | type yaml_sequence_style_t
constant yaml_ANY_SEQUENCE_STYLE (line 89) | yaml_ANY_SEQUENCE_STYLE yaml_sequence_style_t = iota
constant yaml_BLOCK_SEQUENCE_STYLE (line 91) | yaml_BLOCK_SEQUENCE_STYLE
constant yaml_FLOW_SEQUENCE_STYLE (line 92) | yaml_FLOW_SEQUENCE_STYLE
type yaml_mapping_style_t (line 95) | type yaml_mapping_style_t
constant yaml_ANY_MAPPING_STYLE (line 100) | yaml_ANY_MAPPING_STYLE yaml_mapping_style_t = iota
constant yaml_BLOCK_MAPPING_STYLE (line 102) | yaml_BLOCK_MAPPING_STYLE
constant yaml_FLOW_MAPPING_STYLE (line 103) | yaml_FLOW_MAPPING_STYLE
type yaml_token_type_t (line 108) | type yaml_token_type_t
method String (line 143) | func (tt yaml_token_type_t) String() string {
constant yaml_NO_TOKEN (line 113) | yaml_NO_TOKEN yaml_token_type_t = iota
constant yaml_STREAM_START_TOKEN (line 115) | yaml_STREAM_START_TOKEN
constant yaml_STREAM_END_TOKEN (line 116) | yaml_STREAM_END_TOKEN
constant yaml_VERSION_DIRECTIVE_TOKEN (line 118) | yaml_VERSION_DIRECTIVE_TOKEN
constant yaml_TAG_DIRECTIVE_TOKEN (line 119) | yaml_TAG_DIRECTIVE_TOKEN
constant yaml_DOCUMENT_START_TOKEN (line 120) | yaml_DOCUMENT_START_TOKEN
constant yaml_DOCUMENT_END_TOKEN (line 121) | yaml_DOCUMENT_END_TOKEN
constant yaml_BLOCK_SEQUENCE_START_TOKEN (line 123) | yaml_BLOCK_SEQUENCE_START_TOKEN
constant yaml_BLOCK_MAPPING_START_TOKEN (line 124) | yaml_BLOCK_MAPPING_START_TOKEN
constant yaml_BLOCK_END_TOKEN (line 125) | yaml_BLOCK_END_TOKEN
constant yaml_FLOW_SEQUENCE_START_TOKEN (line 127) | yaml_FLOW_SEQUENCE_START_TOKEN
constant yaml_FLOW_SEQUENCE_END_TOKEN (line 128) | yaml_FLOW_SEQUENCE_END_TOKEN
constant yaml_FLOW_MAPPING_START_TOKEN (line 129) | yaml_FLOW_MAPPING_START_TOKEN
constant yaml_FLOW_MAPPING_END_TOKEN (line 130) | yaml_FLOW_MAPPING_END_TOKEN
constant yaml_BLOCK_ENTRY_TOKEN (line 132) | yaml_BLOCK_ENTRY_TOKEN
constant yaml_FLOW_ENTRY_TOKEN (line 133) | yaml_FLOW_ENTRY_TOKEN
constant yaml_KEY_TOKEN (line 134) | yaml_KEY_TOKEN
constant yaml_VALUE_TOKEN (line 135) | yaml_VALUE_TOKEN
constant yaml_ALIAS_TOKEN (line 137) | yaml_ALIAS_TOKEN
constant yaml_ANCHOR_TOKEN (line 138) | yaml_ANCHOR_TOKEN
constant yaml_TAG_TOKEN (line 139) | yaml_TAG_TOKEN
constant yaml_SCALAR_TOKEN (line 140) | yaml_SCALAR_TOKEN
type yaml_token_t (line 194) | type yaml_token_t struct
type yaml_event_type_t (line 223) | type yaml_event_type_t
constant yaml_NO_EVENT (line 228) | yaml_NO_EVENT yaml_event_type_t = iota
constant yaml_STREAM_START_EVENT (line 230) | yaml_STREAM_START_EVENT
constant yaml_STREAM_END_EVENT (line 231) | yaml_STREAM_END_EVENT
constant yaml_DOCUMENT_START_EVENT (line 232) | yaml_DOCUMENT_START_EVENT
constant yaml_DOCUMENT_END_EVENT (line 233) | yaml_DOCUMENT_END_EVENT
constant yaml_ALIAS_EVENT (line 234) | yaml_ALIAS_EVENT
constant yaml_SCALAR_EVENT (line 235) | yaml_SCALAR_EVENT
constant yaml_SEQUENCE_START_EVENT (line 236) | yaml_SEQUENCE_START_EVENT
constant yaml_SEQUENCE_END_EVENT (line 237) | yaml_SEQUENCE_END_EVENT
constant yaml_MAPPING_START_EVENT (line 238) | yaml_MAPPING_START_EVENT
constant yaml_MAPPING_END_EVENT (line 239) | yaml_MAPPING_END_EVENT
type yaml_event_t (line 243) | type yaml_event_t struct
method scalar_style (line 280) | func (e *yaml_event_t) scalar_style() yaml_scalar_style_t { return...
method sequence_style (line 281) | func (e *yaml_event_t) sequence_style() yaml_sequence_style_t { return...
method mapping_style (line 282) | func (e *yaml_event_t) mapping_style() yaml_mapping_style_t { return...
constant yaml_NULL_TAG (line 287) | yaml_NULL_TAG = "tag:yaml.org,2002:null"
constant yaml_BOOL_TAG (line 288) | yaml_BOOL_TAG = "tag:yaml.org,2002:bool"
constant yaml_STR_TAG (line 289) | yaml_STR_TAG = "tag:yaml.org,2002:str"
constant yaml_INT_TAG (line 290) | yaml_INT_TAG = "tag:yaml.org,2002:int"
constant yaml_FLOAT_TAG (line 291) | yaml_FLOAT_TAG = "tag:yaml.org,2002:float"
constant yaml_TIMESTAMP_TAG (line 292) | yaml_TIMESTAMP_TAG = "tag:yaml.org,2002:timestamp"
constant yaml_SEQ_TAG (line 294) | yaml_SEQ_TAG = "tag:yaml.org,2002:seq"
constant yaml_MAP_TAG (line 295) | yaml_MAP_TAG = "tag:yaml.org,2002:map"
constant yaml_BINARY_TAG (line 298) | yaml_BINARY_TAG = "tag:yaml.org,2002:binary"
constant yaml_MERGE_TAG (line 299) | yaml_MERGE_TAG = "tag:yaml.org,2002:merge"
constant yaml_DEFAULT_SCALAR_TAG (line 301) | yaml_DEFAULT_SCALAR_TAG = yaml_STR_TAG
constant yaml_DEFAULT_SEQUENCE_TAG (line 302) | yaml_DEFAULT_SEQUENCE_TAG = yaml_SEQ_TAG
constant yaml_DEFAULT_MAPPING_TAG (line 303) | yaml_DEFAULT_MAPPING_TAG = yaml_MAP_TAG
type yaml_node_type_t (line 306) | type yaml_node_type_t
constant yaml_NO_NODE (line 311) | yaml_NO_NODE yaml_node_type_t = iota
constant yaml_SCALAR_NODE (line 313) | yaml_SCALAR_NODE
constant yaml_SEQUENCE_NODE (line 314) | yaml_SEQUENCE_NODE
constant yaml_MAPPING_NODE (line 315) | yaml_MAPPING_NODE
type yaml_node_item_t (line 319) | type yaml_node_item_t
type yaml_node_pair_t (line 322) | type yaml_node_pair_t struct
type yaml_node_t (line 328) | type yaml_node_t struct
type yaml_document_t (line 362) | type yaml_document_t struct
type yaml_read_handler_t (line 397) | type yaml_read_handler_t
type yaml_simple_key_t (line 400) | type yaml_simple_key_t struct
type yaml_parser_state_t (line 408) | type yaml_parser_state_t
method String (line 438) | func (ps yaml_parser_state_t) String() string {
constant yaml_PARSE_STREAM_START_STATE (line 411) | yaml_PARSE_STREAM_START_STATE yaml_parser_state_t = iota
constant yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE (line 413) | yaml_PARSE_IMPLICIT_DOCUMENT_START_STATE
constant yaml_PARSE_DOCUMENT_START_STATE (line 414) | yaml_PARSE_DOCUMENT_START_STATE
constant yaml_PARSE_DOCUMENT_CONTENT_STATE (line 415) | yaml_PARSE_DOCUMENT_CONTENT_STATE
constant yaml_PARSE_DOCUMENT_END_STATE (line 416) | yaml_PARSE_DOCUMENT_END_STATE
constant yaml_PARSE_BLOCK_NODE_STATE (line 417) | yaml_PARSE_BLOCK_NODE_STATE
constant yaml_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE (line 418) | yaml_PARSE_BLOCK_NODE_OR_INDENTLESS_SEQUENCE_STATE
constant yaml_PARSE_FLOW_NODE_STATE (line 419) | yaml_PARSE_FLOW_NODE_STATE
constant yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE (line 420) | yaml_PARSE_BLOCK_SEQUENCE_FIRST_ENTRY_STATE
constant yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE (line 421) | yaml_PARSE_BLOCK_SEQUENCE_ENTRY_STATE
constant yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE (line 422) | yaml_PARSE_INDENTLESS_SEQUENCE_ENTRY_STATE
constant yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE (line 423) | yaml_PARSE_BLOCK_MAPPING_FIRST_KEY_STATE
constant yaml_PARSE_BLOCK_MAPPING_KEY_STATE (line 424) | yaml_PARSE_BLOCK_MAPPING_KEY_STATE
constant yaml_PARSE_BLOCK_MAPPING_VALUE_STATE (line 425) | yaml_PARSE_BLOCK_MAPPING_VALUE_STATE
constant yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE (line 426) | yaml_PARSE_FLOW_SEQUENCE_FIRST_ENTRY_STATE
constant yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE (line 427) | yaml_PARSE_FLOW_SEQUENCE_ENTRY_STATE
constant yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE (line 428) | yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_KEY_STATE
constant yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE (line 429) | yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_VALUE_STATE
constant yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE (line 430) | yaml_PARSE_FLOW_SEQUENCE_ENTRY_MAPPING_END_STATE
constant yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE (line 431) | yaml_PARSE_FLOW_MAPPING_FIRST_KEY_STATE
constant yaml_PARSE_FLOW_MAPPING_KEY_STATE (line 432) | yaml_PARSE_FLOW_MAPPING_KEY_STATE
constant yaml_PARSE_FLOW_MAPPING_VALUE_STATE (line 433) | yaml_PARSE_FLOW_MAPPING_VALUE_STATE
constant yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE (line 434) | yaml_PARSE_FLOW_MAPPING_EMPTY_VALUE_STATE
constant yaml_PARSE_END_STATE (line 435) | yaml_PARSE_END_STATE
type yaml_alias_data_t (line 493) | type yaml_alias_data_t struct
type yaml_parser_t (line 503) | type yaml_parser_t struct
type yaml_write_handler_t (line 591) | type yaml_write_handler_t
type yaml_emitter_state_t (line 593) | type yaml_emitter_state_t
constant yaml_EMIT_STREAM_START_STATE (line 598) | yaml_EMIT_STREAM_START_STATE yaml_emitter_state_t = iota
constant yaml_EMIT_FIRST_DOCUMENT_START_STATE (line 600) | yaml_EMIT_FIRST_DOCUMENT_START_STATE
constant yaml_EMIT_DOCUMENT_START_STATE (line 601) | yaml_EMIT_DOCUMENT_START_STATE
constant yaml_EMIT_DOCUMENT_CONTENT_STATE (line 602) | yaml_EMIT_DOCUMENT_CONTENT_STATE
constant yaml_EMIT_DOCUMENT_END_STATE (line 603) | yaml_EMIT_DOCUMENT_END_STATE
constant yaml_EMIT_FLOW_SEQUENCE_FIRST_ITEM_STATE (line 604) | yaml_EMIT_FLOW_SEQUENCE_FIRST_ITEM_STATE
constant yaml_EMIT_FLOW_SEQUENCE_ITEM_STATE (line 605) | yaml_EMIT_FLOW_SEQUENCE_ITEM_STATE
constant yaml_EMIT_FLOW_MAPPING_FIRST_KEY_STATE (line 606) | yaml_EMIT_FLOW_MAPPING_FIRST_KEY_STATE
constant yaml_EMIT_FLOW_MAPPING_KEY_STATE (line 607) | yaml_EMIT_FLOW_MAPPING_KEY_STATE
constant yaml_EMIT_FLOW_MAPPING_SIMPLE_VALUE_STATE (line 608) | yaml_EMIT_FLOW_MAPPING_SIMPLE_VALUE_STATE
constant yaml_EMIT_FLOW_MAPPING_VALUE_STATE (line 609) | yaml_EMIT_FLOW_MAPPING_VALUE_STATE
constant yaml_EMIT_BLOCK_SEQUENCE_FIRST_ITEM_STATE (line 610) | yaml_EMIT_BLOCK_SEQUENCE_FIRST_ITEM_STATE
constant yaml_EMIT_BLOCK_SEQUENCE_ITEM_STATE (line 611) | yaml_EMIT_BLOCK_SEQUENCE_ITEM_STATE
constant yaml_EMIT_BLOCK_MAPPING_FIRST_KEY_STATE (line 612) | yaml_EMIT_BLOCK_MAPPING_FIRST_KEY_STATE
constant yaml_EMIT_BLOCK_MAPPING_KEY_STATE (line 613) | yaml_EMIT_BLOCK_MAPPING_KEY_STATE
constant yaml_EMIT_BLOCK_MAPPING_SIMPLE_VALUE_STATE (line 614) | yaml_EMIT_BLOCK_MAPPING_SIMPLE_VALUE_STATE
constant yaml_EMIT_BLOCK_MAPPING_VALUE_STATE (line 615) | yaml_EMIT_BLOCK_MAPPING_VALUE_STATE
constant yaml_EMIT_END_STATE (line 616) | yaml_EMIT_END_STATE
type yaml_emitter_t (line 623) | type yaml_emitter_t struct
FILE: vendor/gopkg.in/yaml.v1/yamlprivateh.go
constant input_raw_buffer_size (line 5) | input_raw_buffer_size = 512
constant input_buffer_size (line 9) | input_buffer_size = input_raw_buffer_size * 3
constant output_buffer_size (line 12) | output_buffer_size = 128
constant output_raw_buffer_size (line 16) | output_raw_buffer_size = (output_buffer_size*2 + 2)
constant initial_stack_size (line 19) | initial_stack_size = 16
constant initial_queue_size (line 20) | initial_queue_size = 16
constant initial_string_size (line 21) | initial_string_size = 16
function is_alpha (line 26) | func is_alpha(b []byte, i int) bool {
function is_digit (line 31) | func is_digit(b []byte, i int) bool {
function as_digit (line 36) | func as_digit(b []byte, i int) int {
function is_hex (line 41) | func is_hex(b []byte, i int) bool {
function as_hex (line 46) | func as_hex(b []byte, i int) int {
function is_ascii (line 58) | func is_ascii(b []byte, i int) bool {
function is_printable (line 63) | func is_printable(b []byte, i int) bool {
function is_z (line 76) | func is_z(b []byte, i int) bool {
function is_bom (line 81) | func is_bom(b []byte, i int) bool {
function is_space (line 86) | func is_space(b []byte, i int) bool {
function is_tab (line 91) | func is_tab(b []byte, i int) bool {
function is_blank (line 96) | func is_blank(b []byte, i int) bool {
function is_break (line 102) | func is_break(b []byte, i int) bool {
function is_crlf (line 110) | func is_crlf(b []byte, i int) bool {
function is_breakz (line 115) | func is_breakz(b []byte, i int) bool {
function is_spacez (line 128) | func is_spacez(b []byte, i int) bool {
function is_blankz (line 142) | func is_blankz(b []byte, i int) bool {
function width (line 156) | func width(b byte) int {
Condensed preview — 97 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (1,494K chars).
[
{
"path": ".github/workflows/semgrep.yml",
"chars": 586,
"preview": "on:\n pull_request: {}\n workflow_dispatch: {}\n push: \n branches:\n - main\n - master\n schedule:\n - cron"
},
{
"path": ".gitignore",
"chars": 26,
"preview": ".DS_Store\nbuilds/\ndebian/\n"
},
{
"path": "Godeps/Godeps.json",
"chars": 1873,
"preview": "{\n\t\"ImportPath\": \"github.com/eagerio/stout\",\n\t\"GoVersion\": \"go1.6\",\n\t\"GodepVersion\": \"v63\",\n\t\"Packages\": [\n\t\t\"./...\"\n\t],"
},
{
"path": "Godeps/Readme",
"chars": 136,
"preview": "This directory tree is generated automatically by godep.\n\nPlease do not edit.\n\nSee https://github.com/tools/godep for mo"
},
{
"path": "LICENSE",
"chars": 1062,
"preview": "Copyright (c) 2014 Eager Platform Co.\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of t"
},
{
"path": "README.md",
"chars": 13892,
"preview": "# Stout\n\n#### [View the site →](http://stout.is/)\n\nStout is a deploy tool for static websites. It takes a website and u"
},
{
"path": "docs/getting-started.md",
"chars": 3277,
"preview": "### Setting Up Your Site\n\nIf you don't already have an S3-hosted site, start here.\n\nWe're going to create a basic site c"
},
{
"path": "src/admin.go",
"chars": 9179,
"preview": "package main\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"os/exec\"\n\t\"strings\"\n\n\t\"github.com/zackbloom/goamz/cloudfront\"\n\t\"github.com/zackblo"
},
{
"path": "src/cli.go",
"chars": 925,
"preview": "package main\n\nimport (\n\t\"flag\"\n\t\"fmt\"\n)\n\nfunc printUsage() {\n\tfmt.Println(`Stout Static Deploy Tool\nSupports three comma"
},
{
"path": "src/deploy.go",
"chars": 13901,
"preview": "package main\n\nimport (\n\t\"bytes\"\n\t\"compress/gzip\"\n\t\"crypto/md5\"\n\t\"encoding/base64\"\n\t\"fmt\"\n\t\"io\"\n\t\"math/big\"\n\t\"mime\"\n\t\"net"
},
{
"path": "src/rollback.go",
"chars": 1791,
"preview": "package main\n\nimport (\n\t\"fmt\"\n\t\"log\"\n\t\"path/filepath\"\n\t\"sync\"\n\n\t\"github.com/zackbloom/goamz/s3\"\n)\n\nfunc Rollback(options"
},
{
"path": "src/utils.go",
"chars": 5472,
"preview": "package main\n\nimport (\n\t\"flag\"\n\t\"fmt\"\n\t\"io/ioutil\"\n\t\"log\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"regexp\"\n\t\"strings\"\n\n\t\"github.com/imda"
},
{
"path": "utils/build.sh",
"chars": 172,
"preview": "GOOS=linux GOARCH=amd64 go build -o stout-linux src/* \nGOOS=darwin GOARCH=amd64 go build -o stout-osx src/* \nGOOS=window"
},
{
"path": "utils/create_site.sh",
"chars": 2961,
"preview": "#set -e\n\nexport HOST=$1\nexport DEPLOY_USER=${HOST}_deploy\n\naws s3 mb s3://$HOST --region us-east-1\n\naws s3 website s3://"
},
{
"path": "utils/release.sh",
"chars": 1016,
"preview": "set -e\n\n# Install jq with brew install jq\n\nRELEASE=$1\n\ngit tag $RELEASE\ngit push origin master --tags\n\nUPLOAD_URL=$(curl"
},
{
"path": "utils/xc.sh",
"chars": 40,
"preview": "goxc -tasks-=downloads-page -d=./builds\n"
},
{
"path": "vendor/github.com/cenk/backoff/.gitignore",
"chars": 252,
"preview": "# Compiled Object files, Static and Dynamic libs (Shared Objects)\n*.o\n*.a\n*.so\n\n# Folders\n_obj\n_test\n\n# Architecture spe"
},
{
"path": "vendor/github.com/cenk/backoff/.travis.yml",
"chars": 187,
"preview": "language: go\ngo:\n - 1.3.3\n - tip\nbefore_install:\n - go get github.com/mattn/goveralls\n - go get golang.org/x/tools/c"
},
{
"path": "vendor/github.com/cenk/backoff/LICENSE",
"chars": 1076,
"preview": "The MIT License (MIT)\n\nCopyright (c) 2014 Cenk Altı\n\nPermission is hereby granted, free of charge, to any person obtaini"
},
{
"path": "vendor/github.com/cenk/backoff/README.md",
"chars": 3403,
"preview": "# Exponential Backoff [![GoDoc][godoc image]][godoc] [![Build Status][travis image]][travis] [![Coverage Status][coveral"
},
{
"path": "vendor/github.com/cenk/backoff/backoff.go",
"chars": 1874,
"preview": "// Package backoff implements backoff algorithms for retrying operations.\n//\n// Also has a Retry() helper for retrying o"
},
{
"path": "vendor/github.com/cenk/backoff/exponential.go",
"chars": 5506,
"preview": "package backoff\n\nimport (\n\t\"math/rand\"\n\t\"time\"\n)\n\n/*\nExponentialBackOff is a backoff implementation that increases the b"
},
{
"path": "vendor/github.com/cenk/backoff/retry.go",
"chars": 1274,
"preview": "package backoff\n\nimport \"time\"\n\n// An Operation is executing by Retry() or RetryNotify().\n// The operation will be retri"
},
{
"path": "vendor/github.com/cenk/backoff/ticker.go",
"chars": 1602,
"preview": "package backoff\n\nimport (\n\t\"runtime\"\n\t\"sync\"\n\t\"time\"\n)\n\n// Ticker holds a channel that delivers `ticks' of a clock at ti"
},
{
"path": "vendor/github.com/imdario/mergo/.travis.yml",
"chars": 32,
"preview": "language: go\ninstall: go get -t\n"
},
{
"path": "vendor/github.com/imdario/mergo/LICENSE",
"chars": 1534,
"preview": "Copyright (c) 2013 Dario Castañé. All rights reserved.\nCopyright (c) 2012 The Go Authors. All rights reserved.\n\nRedistri"
},
{
"path": "vendor/github.com/imdario/mergo/README.md",
"chars": 4887,
"preview": "# Mergo\n\nA helper to merge structs and maps in Golang. Useful for configuration default values, avoiding messy if-statem"
},
{
"path": "vendor/github.com/imdario/mergo/doc.go",
"chars": 976,
"preview": "// Copyright 2013 Dario Castañé. All rights reserved.\n// Copyright 2009 The Go Authors. All rights reserved.\n// Use of t"
},
{
"path": "vendor/github.com/imdario/mergo/map.go",
"chars": 4762,
"preview": "// Copyright 2014 Dario Castañé. All rights reserved.\n// Copyright 2009 The Go Authors. All rights reserved.\n// Use of t"
},
{
"path": "vendor/github.com/imdario/mergo/merge.go",
"chars": 3463,
"preview": "// Copyright 2013 Dario Castañé. All rights reserved.\n// Copyright 2009 The Go Authors. All rights reserved.\n// Use of t"
},
{
"path": "vendor/github.com/imdario/mergo/mergo.go",
"chars": 2711,
"preview": "// Copyright 2013 Dario Castañé. All rights reserved.\n// Copyright 2009 The Go Authors. All rights reserved.\n// Use of t"
},
{
"path": "vendor/github.com/mitchellh/go-homedir/LICENSE",
"chars": 1085,
"preview": "The MIT License (MIT)\n\nCopyright (c) 2013 Mitchell Hashimoto\n\nPermission is hereby granted, free of charge, to any perso"
},
{
"path": "vendor/github.com/mitchellh/go-homedir/README.md",
"chars": 681,
"preview": "# go-homedir\n\nThis is a Go library for detecting the user's home directory without\nthe use of cgo, so the library can be"
},
{
"path": "vendor/github.com/mitchellh/go-homedir/homedir.go",
"chars": 2900,
"preview": "package homedir\n\nimport (\n\t\"bytes\"\n\t\"errors\"\n\t\"os\"\n\t\"os/exec\"\n\t\"path/filepath\"\n\t\"runtime\"\n\t\"strconv\"\n\t\"strings\"\n\t\"sync\"\n"
},
{
"path": "vendor/github.com/wsxiaoys/terminal/LICENSE",
"chars": 1475,
"preview": "Copyright (c) 2013 Meng Zhang. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\n"
},
{
"path": "vendor/github.com/wsxiaoys/terminal/color/color.go",
"chars": 4880,
"preview": "// The colors package provide a simple way to bring colorful characters to terminal interface.\n//\n// This example will o"
},
{
"path": "vendor/github.com/zackbloom/go-ini/.gitignore",
"chars": 273,
"preview": "# Compiled Object files, Static and Dynamic libs (Shared Objects)\n*.o\n*.a\n*.so\n\n# Folders\n_obj\n_test\n\n# Architecture spe"
},
{
"path": "vendor/github.com/zackbloom/go-ini/README.md",
"chars": 2936,
"preview": "go-ini\n======\n\nINI file decoder for Go lang. Idea is to have an unmarshaller similar to JSON - specify parts of the fil"
},
{
"path": "vendor/github.com/zackbloom/go-ini/decode.go",
"chars": 12276,
"preview": "// Decode INI files with a syntax similar to JSON decoding\npackage ini\n\nimport (\n\t\"bufio\"\n\t\"bytes\"\n\t\"fmt\"\n\t\"io\"\n\t\"io/iou"
},
{
"path": "vendor/github.com/zackbloom/go-ini/stack.go",
"chars": 876,
"preview": "package ini\n\n// NewStack returns a new stack.\nfunc NewStack() *Stack {\n\treturn &Stack{}\n}\n\n// Stack is a basic LIFO stac"
},
{
"path": "vendor/github.com/zackbloom/goamz/LICENSE",
"chars": 8747,
"preview": "This software is licensed under the LGPLv3, included below.\n\nAs a special exception to the GNU Lesser General Public Lic"
},
{
"path": "vendor/github.com/zackbloom/goamz/aws/attempt.go",
"chars": 1716,
"preview": "package aws\n\nimport (\n\t\"time\"\n)\n\n// AttemptStrategy represents a strategy for waiting for an action\n// to complete succe"
},
{
"path": "vendor/github.com/zackbloom/goamz/aws/aws.go",
"chars": 15616,
"preview": "//\n// goamz - Go packages to interact with the Amazon Web Services.\n//\n// https://wiki.ubuntu.com/goamz\n//\n// Copyrigh"
},
{
"path": "vendor/github.com/zackbloom/goamz/aws/client.go",
"chars": 3029,
"preview": "package aws\n\nimport (\n\t\"math\"\n\t\"net\"\n\t\"net/http\"\n\t\"time\"\n)\n\ntype RetryableFunc func(*http.Request, *http.Response, error"
},
{
"path": "vendor/github.com/zackbloom/goamz/aws/regions.go",
"chars": 7764,
"preview": "package aws\n\nvar USGovWest = Region{\n\t\"us-gov-west-1\",\n\t\"https://ec2.us-gov-west-1.amazonaws.com\",\n\t\"https://s3-fips-us-"
},
{
"path": "vendor/github.com/zackbloom/goamz/aws/retry.go",
"chars": 4449,
"preview": "package aws\n\nimport (\n\t\"math/rand\"\n\t\"net\"\n\t\"net/http\"\n\t\"time\"\n)\n\nconst (\n\tmaxDelay = 20 * time.Second\n\tdefau"
},
{
"path": "vendor/github.com/zackbloom/goamz/aws/sign.go",
"chars": 12089,
"preview": "package aws\n\nimport (\n\t\"bytes\"\n\t\"crypto/hmac\"\n\t\"crypto/sha256\"\n\t\"encoding/base64\"\n\t\"fmt\"\n\t\"io/ioutil\"\n\t\"net/http\"\n\t\"net/"
},
{
"path": "vendor/github.com/zackbloom/goamz/cloudfront/cloudfront.go",
"chars": 16134,
"preview": "package cloudfront\n\nimport (\n\t\"bytes\"\n\t\"crypto\"\n\t\"crypto/rsa\"\n\t\"crypto/sha1\"\n\t\"encoding/base64\"\n\t\"encoding/json\"\n\t\"encod"
},
{
"path": "vendor/github.com/zackbloom/goamz/iam/iam.go",
"chars": 10784,
"preview": "// The iam package provides types and functions for interaction with the AWS\n// Identity and Access Management (IAM) ser"
},
{
"path": "vendor/github.com/zackbloom/goamz/iam/sign.go",
"chars": 1024,
"preview": "package iam\n\nimport (\n\t\"crypto/hmac\"\n\t\"crypto/sha256\"\n\t\"encoding/base64\"\n\t\"github.com/zackbloom/goamz/aws\"\n\t\"sort\"\n\t\"str"
},
{
"path": "vendor/github.com/zackbloom/goamz/route53/route53.go",
"chars": 11808,
"preview": "package route53\n\nimport (\n\t\"bytes\"\n\t\"encoding/xml\"\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strconv\"\n\n\t\"github.com/zackbloo"
},
{
"path": "vendor/github.com/zackbloom/goamz/s3/lifecycle.go",
"chars": 5496,
"preview": "package s3\n\nimport (\n\t\"crypto/md5\"\n\t\"encoding/base64\"\n\t\"encoding/xml\"\n\t\"net/url\"\n\t\"strconv\"\n\t\"time\"\n)\n\n// Implements an "
},
{
"path": "vendor/github.com/zackbloom/goamz/s3/multi.go",
"chars": 12787,
"preview": "package s3\n\nimport (\n\t\"bytes\"\n\t\"crypto/md5\"\n\t\"encoding/base64\"\n\t\"encoding/hex\"\n\t\"encoding/xml\"\n\t\"errors\"\n\t\"io\"\n\t\"net/url"
},
{
"path": "vendor/github.com/zackbloom/goamz/s3/s3.go",
"chars": 34410,
"preview": "//\n// goamz - Go packages to interact with the Amazon Web Services.\n//\n// https://wiki.ubuntu.com/goamz\n//\n// Copyrigh"
},
{
"path": "vendor/github.com/zackbloom/goamz/s3/sign.go",
"chars": 3098,
"preview": "package s3\n\nimport (\n\t\"crypto/hmac\"\n\t\"crypto/sha1\"\n\t\"encoding/base64\"\n\t\"github.com/zackbloom/goamz/aws\"\n\t\"log\"\n\t\"sort\"\n\t"
},
{
"path": "vendor/golang.org/x/crypto/LICENSE",
"chars": 1479,
"preview": "Copyright (c) 2009 The Go Authors. All rights reserved.\n\nRedistribution and use in source and binary forms, with or with"
},
{
"path": "vendor/golang.org/x/crypto/PATENTS",
"chars": 1303,
"preview": "Additional IP Rights Grant (Patents)\n\n\"This implementation\" means the copyrightable works distributed by\nGoogle as part "
},
{
"path": "vendor/golang.org/x/crypto/ssh/terminal/terminal.go",
"chars": 20992,
"preview": "// Copyright 2011 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "vendor/golang.org/x/crypto/ssh/terminal/util.go",
"chars": 3980,
"preview": "// Copyright 2011 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "vendor/golang.org/x/crypto/ssh/terminal/util_bsd.go",
"chars": 332,
"preview": "// Copyright 2013 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "vendor/golang.org/x/crypto/ssh/terminal/util_linux.go",
"chars": 457,
"preview": "// Copyright 2013 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "vendor/golang.org/x/crypto/ssh/terminal/util_plan9.go",
"chars": 2028,
"preview": "// Copyright 2016 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "vendor/golang.org/x/crypto/ssh/terminal/util_windows.go",
"chars": 4430,
"preview": "// Copyright 2011 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "vendor/golang.org/x/net/LICENSE",
"chars": 1479,
"preview": "Copyright (c) 2009 The Go Authors. All rights reserved.\n\nRedistribution and use in source and binary forms, with or with"
},
{
"path": "vendor/golang.org/x/net/PATENTS",
"chars": 1303,
"preview": "Additional IP Rights Grant (Patents)\n\n\"This implementation\" means the copyrightable works distributed by\nGoogle as part "
},
{
"path": "vendor/golang.org/x/net/html/atom/atom.go",
"chars": 2282,
"preview": "// Copyright 2012 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "vendor/golang.org/x/net/html/atom/gen.go",
"chars": 10410,
"preview": "// Copyright 2012 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "vendor/golang.org/x/net/html/atom/table.go",
"chars": 23166,
"preview": "// generated by go run gen.go; DO NOT EDIT\n\npackage atom\n\nconst (\n\tA Atom = 0x1\n\tAbbr A"
},
{
"path": "vendor/golang.org/x/net/html/const.go",
"chars": 2334,
"preview": "// Copyright 2011 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "vendor/golang.org/x/net/html/doc.go",
"chars": 3356,
"preview": "// Copyright 2010 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "vendor/golang.org/x/net/html/doctype.go",
"chars": 4925,
"preview": "// Copyright 2011 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "vendor/golang.org/x/net/html/entity.go",
"chars": 100055,
"preview": "// Copyright 2010 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "vendor/golang.org/x/net/html/escape.go",
"chars": 6052,
"preview": "// Copyright 2010 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "vendor/golang.org/x/net/html/foreign.go",
"chars": 6913,
"preview": "// Copyright 2011 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "vendor/golang.org/x/net/html/node.go",
"chars": 4835,
"preview": "// Copyright 2011 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "vendor/golang.org/x/net/html/parse.go",
"chars": 49266,
"preview": "// Copyright 2010 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "vendor/golang.org/x/net/html/render.go",
"chars": 7062,
"preview": "// Copyright 2011 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "vendor/golang.org/x/net/html/token.go",
"chars": 30249,
"preview": "// Copyright 2010 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "vendor/golang.org/x/net/publicsuffix/gen.go",
"chars": 19203,
"preview": "// Copyright 2012 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "vendor/golang.org/x/net/publicsuffix/list.go",
"chars": 3827,
"preview": "// Copyright 2012 The Go Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style\n// license "
},
{
"path": "vendor/golang.org/x/net/publicsuffix/table.go",
"chars": 540322,
"preview": "// generated by go run gen.go; DO NOT EDIT\n\npackage publicsuffix\n\nconst version = \"publicsuffix.org's public_suffix_list"
},
{
"path": "vendor/gopkg.in/yaml.v1/LICENSE",
"chars": 8790,
"preview": "\nCopyright (c) 2011-2014 - Canonical Inc.\n\nThis software is licensed under the LGPLv3, included below.\n\nAs a special exc"
},
{
"path": "vendor/gopkg.in/yaml.v1/LICENSE.libyaml",
"chars": 1313,
"preview": "The following files were ported to Go from C files of libyaml, and thus\nare still covered by their original copyright an"
},
{
"path": "vendor/gopkg.in/yaml.v1/README.md",
"chars": 2566,
"preview": "# YAML support for the Go language\n\nIntroduction\n------------\n\nThe yaml package enables Go programs to comfortably encod"
},
{
"path": "vendor/gopkg.in/yaml.v1/apic.go",
"chars": 21246,
"preview": "package yaml\n\nimport (\n\t\"io\"\n\t\"os\"\n)\n\nfunc yaml_insert_token(parser *yaml_parser_t, pos int, token *yaml_token_t) {\n\t//f"
},
{
"path": "vendor/gopkg.in/yaml.v1/decode.go",
"chars": 12779,
"preview": "package yaml\n\nimport (\n\t\"encoding/base64\"\n\t\"fmt\"\n\t\"reflect\"\n\t\"strconv\"\n\t\"time\"\n)\n\nconst (\n\tdocumentNode = 1 << iota\n\tmap"
},
{
"path": "vendor/gopkg.in/yaml.v1/emitterc.go",
"chars": 45308,
"preview": "package yaml\n\nimport (\n\t\"bytes\"\n)\n\n// Flush the buffer if needed.\nfunc flush(emitter *yaml_emitter_t) bool {\n\tif emitter"
},
{
"path": "vendor/gopkg.in/yaml.v1/encode.go",
"chars": 6434,
"preview": "package yaml\n\nimport (\n\t\"reflect\"\n\t\"regexp\"\n\t\"sort\"\n\t\"strconv\"\n\t\"strings\"\n\t\"time\"\n)\n\ntype encoder struct {\n\temitter yaml"
},
{
"path": "vendor/gopkg.in/yaml.v1/parserc.go",
"chars": 34775,
"preview": "package yaml\n\nimport (\n\t\"bytes\"\n)\n\n// The parser implements the following grammar:\n//\n// stream ::= STREAM"
},
{
"path": "vendor/gopkg.in/yaml.v1/readerc.go",
"chars": 11893,
"preview": "package yaml\n\nimport (\n\t\"io\"\n)\n\n// Set the reader error and return 0.\nfunc yaml_parser_set_reader_error(parser *yaml_par"
},
{
"path": "vendor/gopkg.in/yaml.v1/resolve.go",
"chars": 4770,
"preview": "package yaml\n\nimport (\n\t\"encoding/base64\"\n\t\"fmt\"\n\t\"math\"\n\t\"strconv\"\n\t\"strings\"\n\t\"unicode/utf8\"\n)\n\n// TODO: merge, timest"
},
{
"path": "vendor/gopkg.in/yaml.v1/scannerc.go",
"chars": 77263,
"preview": "package yaml\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n)\n\n// Introduction\n// ************\n//\n// The following notes assume that you are "
},
{
"path": "vendor/gopkg.in/yaml.v1/sorter.go",
"chars": 2476,
"preview": "package yaml\n\nimport (\n\t\"reflect\"\n\t\"unicode\"\n)\n\ntype keyList []reflect.Value\n\nfunc (l keyList) Len() int { return l"
},
{
"path": "vendor/gopkg.in/yaml.v1/writerc.go",
"chars": 2435,
"preview": "package yaml\n\n// Set the writer error and return false.\nfunc yaml_emitter_set_writer_error(emitter *yaml_emitter_t, prob"
},
{
"path": "vendor/gopkg.in/yaml.v1/yaml.go",
"chars": 8662,
"preview": "// Package yaml implements YAML support for the Go language.\n//\n// Source code and other details for the project are ava"
},
{
"path": "vendor/gopkg.in/yaml.v1/yamlh.go",
"chars": 25408,
"preview": "package yaml\n\nimport (\n\t\"io\"\n)\n\n// The version directive data.\ntype yaml_version_directive_t struct {\n\tmajor int8 // The"
},
{
"path": "vendor/gopkg.in/yaml.v1/yamlprivateh.go",
"chars": 4961,
"preview": "package yaml\n\nconst (\n\t// The size of the input raw buffer.\n\tinput_raw_buffer_size = 512\n\n\t// The size of the input buff"
}
]
About this extraction
This page contains the full source code of the EagerIO/Stout GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 97 files (1.3 MB), approximately 498.2k tokens, and a symbol index with 1617 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.