├── .gitignore ├── run.sh ├── vendor └── go │ └── src │ ├── code.google.com │ └── p │ │ └── gcfg │ │ ├── testdata │ │ ├── gcfg_unicode_test.gcfg │ │ └── gcfg_test.gcfg │ │ ├── go1_0.go │ │ ├── types │ │ ├── doc.go │ │ ├── bool.go │ │ ├── scan.go │ │ ├── enum_test.go │ │ ├── scan_test.go │ │ ├── enum.go │ │ ├── int.go │ │ └── int_test.go │ │ ├── go1_2.go │ │ ├── README │ │ ├── scanner │ │ ├── example_test.go │ │ └── errors.go │ │ ├── token │ │ ├── serialize.go │ │ ├── token.go │ │ └── serialize_test.go │ │ ├── issues_test.go │ │ ├── example_test.go │ │ ├── LICENSE │ │ ├── read.go │ │ └── doc.go │ └── github.com │ ├── mitchellh │ └── goamz │ │ ├── exp │ │ ├── sns │ │ │ ├── README │ │ │ ├── Makefile │ │ │ └── sign.go │ │ ├── mturk │ │ │ ├── export_test.go │ │ │ ├── sign_test.go │ │ │ ├── sign.go │ │ │ ├── responses_test.go │ │ │ └── mturk_test.go │ │ └── sdb │ │ │ ├── export_test.go │ │ │ ├── sign_test.go │ │ │ ├── sign.go │ │ │ └── responses_test.go │ │ ├── CHANGES.md │ │ ├── README.md │ │ ├── ec2 │ │ ├── export_test.go │ │ ├── sign.go │ │ ├── sign_test.go │ │ └── ec2test │ │ │ └── filter.go │ │ ├── s3 │ │ ├── export_test.go │ │ ├── s3t_test.go │ │ ├── sign.go │ │ └── sign_test.go │ │ ├── testutil │ │ ├── suite.go │ │ └── http.go │ │ ├── iam │ │ ├── iamt_test.go │ │ ├── sign.go │ │ └── responses_test.go │ │ └── aws │ │ ├── attempt_test.go │ │ ├── attempt.go │ │ ├── aws_test.go │ │ ├── client_test.go │ │ └── client.go │ └── fsouza │ └── go-dockerclient │ ├── .travis.yml │ ├── DOCKER-LICENSE │ ├── utils │ ├── uname_darwin.go │ ├── uname_linux.go │ ├── random.go │ └── stdcopy.go │ ├── AUTHORS │ ├── engine │ ├── hack.go │ ├── helpers_test.go │ ├── http.go │ ├── job_test.go │ ├── engine_test.go │ ├── env_test.go │ ├── engine.go │ ├── streams.go │ └── job.go │ ├── change_test.go │ ├── change.go │ ├── misc.go │ ├── LICENSE │ ├── term │ ├── termios_linux.go │ ├── termios_darwin.go │ └── term.go │ ├── README.markdown │ ├── testing │ └── data │ │ └── container.tar │ ├── example_test.go │ ├── misc_test.go │ └── client_test.go ├── dogestry.eg.cfg ├── remote ├── id.go ├── s3_responses_test.go ├── local.go ├── s3_test.go └── remote.go ├── main.go ├── cli ├── remote.go ├── push.go ├── cli.go └── pull.go ├── Dockerfile ├── config └── config.go ├── utils ├── progress.go └── utils.go ├── client ├── container.go └── image.go ├── compressor └── compressor.go └── s3 ├── client.go └── sign.go /.gitignore: -------------------------------------------------------------------------------- 1 | /.bundle/config 2 | dogestry -------------------------------------------------------------------------------- /run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | GOPATH=$(pwd)/vendor/go:$GOPATH go run *.go $* 6 | -------------------------------------------------------------------------------- /vendor/go/src/code.google.com/p/gcfg/testdata/gcfg_unicode_test.gcfg: -------------------------------------------------------------------------------- 1 | ; Comment line 2 | [甲] 3 | 乙=丙 # comment 4 | -------------------------------------------------------------------------------- /vendor/go/src/github.com/mitchellh/goamz/exp/sns/README: -------------------------------------------------------------------------------- 1 | Amazon Simple Notification Service API for Golang. 2 | -------------------------------------------------------------------------------- /vendor/go/src/code.google.com/p/gcfg/testdata/gcfg_test.gcfg: -------------------------------------------------------------------------------- 1 | ; Comment line 2 | [section] 3 | name=value # comment 4 | -------------------------------------------------------------------------------- /vendor/go/src/code.google.com/p/gcfg/go1_0.go: -------------------------------------------------------------------------------- 1 | // +build !go1.2 2 | 3 | package gcfg 4 | 5 | type textUnmarshaler interface { 6 | UnmarshalText(text []byte) error 7 | } 8 | -------------------------------------------------------------------------------- /vendor/go/src/github.com/mitchellh/goamz/CHANGES.md: -------------------------------------------------------------------------------- 1 | # Changes in this fork 2 | 3 | * Added EC2.CreateImage() 4 | * Added EC2.CreateKeyPair() 5 | * Added EC2.DeleteKeyPair() 6 | -------------------------------------------------------------------------------- /vendor/go/src/code.google.com/p/gcfg/types/doc.go: -------------------------------------------------------------------------------- 1 | // Package types defines helpers for type conversions. 2 | // 3 | // The API for this package is not finalized yet. 4 | package types 5 | -------------------------------------------------------------------------------- /vendor/go/src/code.google.com/p/gcfg/go1_2.go: -------------------------------------------------------------------------------- 1 | // +build go1.2 2 | 3 | package gcfg 4 | 5 | import ( 6 | "encoding" 7 | ) 8 | 9 | type textUnmarshaler encoding.TextUnmarshaler 10 | -------------------------------------------------------------------------------- /dogestry.eg.cfg: -------------------------------------------------------------------------------- 1 | [remote "s3"] 2 | url=s3://bucket/key-prefix 3 | 4 | [s3] 5 | access-key-id=ididid 6 | secret-key=keykeykey 7 | 8 | [docker] 9 | connection=http://docker-host:4243 10 | -------------------------------------------------------------------------------- /vendor/go/src/github.com/mitchellh/goamz/README.md: -------------------------------------------------------------------------------- 1 | # goamz - An Amazon Library for Go 2 | 3 | This is a fork of [https://launchpad.net/goamz](https://launchpad.net/goamz) 4 | that adds some missing API calls to certain packages. 5 | -------------------------------------------------------------------------------- /vendor/go/src/github.com/fsouza/go-dockerclient/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | go: 3 | - 1.1.2 4 | - 1.2 5 | - tip 6 | env: 7 | - GOARCH=amd64 8 | - GOARCH=386 9 | install: 10 | - go get -d ./... 11 | script: 12 | - go test ./... 13 | -------------------------------------------------------------------------------- /remote/id.go: -------------------------------------------------------------------------------- 1 | package remote 2 | 3 | type ID string 4 | 5 | func (id ID) Short() ID { 6 | shortLen := 12 7 | if len(id) < shortLen { 8 | shortLen = len(id) 9 | } 10 | return id[:shortLen] 11 | } 12 | 13 | func (id ID) String() string { 14 | return string(id) 15 | } 16 | -------------------------------------------------------------------------------- /vendor/go/src/code.google.com/p/gcfg/README: -------------------------------------------------------------------------------- 1 | Gcfg reads INI-style configuration files into Go structs; 2 | supports user-defined types and subsections. 3 | 4 | Project page: https://code.google.com/p/gcfg 5 | Package docs: http://godoc.org/code.google.com/p/gcfg 6 | 7 | My other projects: https://speter.net 8 | -------------------------------------------------------------------------------- /vendor/go/src/github.com/mitchellh/goamz/exp/mturk/export_test.go: -------------------------------------------------------------------------------- 1 | package mturk 2 | 3 | import ( 4 | "github.com/mitchellh/goamz/aws" 5 | ) 6 | 7 | func Sign(auth aws.Auth, service, method, timestamp string, params map[string]string) { 8 | sign(auth, service, method, timestamp, params) 9 | } 10 | -------------------------------------------------------------------------------- /vendor/go/src/github.com/mitchellh/goamz/exp/sdb/export_test.go: -------------------------------------------------------------------------------- 1 | package sdb 2 | 3 | import ( 4 | "github.com/mitchellh/goamz/aws" 5 | ) 6 | 7 | func Sign(auth aws.Auth, method, path string, params map[string][]string, headers map[string][]string) { 8 | sign(auth, method, path, params, headers) 9 | } 10 | -------------------------------------------------------------------------------- /vendor/go/src/github.com/fsouza/go-dockerclient/DOCKER-LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | You can find the Docker license int the following link: 6 | https://raw2.github.com/dotcloud/docker/master/LICENSE 7 | -------------------------------------------------------------------------------- /vendor/go/src/github.com/fsouza/go-dockerclient/utils/uname_darwin.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 Docker authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the DOCKER-LICENSE file. 4 | 5 | package utils 6 | 7 | import ( 8 | "errors" 9 | ) 10 | 11 | type Utsname struct { 12 | Release [65]byte 13 | } 14 | 15 | func uname() (*Utsname, error) { 16 | return nil, errors.New("Kernel version detection is not available on darwin") 17 | } 18 | -------------------------------------------------------------------------------- /vendor/go/src/github.com/mitchellh/goamz/exp/sns/Makefile: -------------------------------------------------------------------------------- 1 | include $(GOROOT)/src/Make.inc 2 | 3 | TARG=launchpad.net/goamz/sns 4 | 5 | GOFILES=\ 6 | sns.go\ 7 | sign.go\ 8 | 9 | include $(GOROOT)/src/Make.pkg 10 | 11 | GOFMT=gofmt 12 | BADFMT=$(shell $(GOFMT) -l $(GOFILES) 2> /dev/null) 13 | 14 | gofmt: $(BADFMT) 15 | @for F in $(BADFMT); do $(GOFMT) -w $$F && echo $$F; done 16 | 17 | ifneq ($(BADFMT),) 18 | ifneq ($(MAKECMDGOALS), gofmt) 19 | #$(warning WARNING: make gofmt: $(BADFMT)) 20 | endif 21 | endif 22 | -------------------------------------------------------------------------------- /vendor/go/src/github.com/mitchellh/goamz/ec2/export_test.go: -------------------------------------------------------------------------------- 1 | package ec2 2 | 3 | import ( 4 | "github.com/mitchellh/goamz/aws" 5 | "time" 6 | ) 7 | 8 | func Sign(auth aws.Auth, method, path string, params map[string]string, host string) { 9 | sign(auth, method, path, params, host) 10 | } 11 | 12 | func fixedTime() time.Time { 13 | return time.Date(2012, 1, 1, 0, 0, 0, 0, time.UTC) 14 | } 15 | 16 | func FakeTime(fakeIt bool) { 17 | if fakeIt { 18 | timeNow = fixedTime 19 | } else { 20 | timeNow = time.Now 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /vendor/go/src/github.com/fsouza/go-dockerclient/utils/uname_linux.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 Docker authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the DOCKER-LICENSE file. 4 | 5 | package utils 6 | 7 | import ( 8 | "syscall" 9 | ) 10 | 11 | type Utsname syscall.Utsname 12 | 13 | func uname() (*syscall.Utsname, error) { 14 | uts := &syscall.Utsname{} 15 | 16 | if err := syscall.Uname(uts); err != nil { 17 | return nil, err 18 | } 19 | return uts, nil 20 | } 21 | -------------------------------------------------------------------------------- /vendor/go/src/github.com/fsouza/go-dockerclient/AUTHORS: -------------------------------------------------------------------------------- 1 | # This is the official list of go-dockerclient authors for copyright purposes. 2 | 3 | Andrews Medina 4 | Ben McCann 5 | Flavia Missi 6 | Francisco Souza 7 | Jean-Baptiste Dalido 8 | Philippe Lafoucrière 9 | Sridhar Ratnakumar 10 | Tim Schindler 11 | Wiliam Souza 12 | -------------------------------------------------------------------------------- /vendor/go/src/github.com/fsouza/go-dockerclient/utils/random.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 Docker authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the DOCKER-LICENSE file. 4 | 5 | package utils 6 | 7 | import ( 8 | "crypto/rand" 9 | "encoding/hex" 10 | "io" 11 | ) 12 | 13 | func RandomString() string { 14 | id := make([]byte, 32) 15 | _, err := io.ReadFull(rand.Reader, id) 16 | if err != nil { 17 | panic(err) // This shouldn't happen 18 | } 19 | return hex.EncodeToString(id) 20 | } 21 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | //"os" 6 | "log" 7 | 8 | "github.com/blake-education/dogestry/cli" 9 | ) 10 | 11 | func main() { 12 | flConfigFile := flag.String("config", "", "the dogestry config file (defaults to 'dogestry.cfg' in the current directory). Config is optional - if using s3 you can use env vars or signed URLs.") 13 | flTempDir := flag.String("tempdir", "", "an alternate tempdir to use") 14 | flag.Parse() 15 | 16 | err := cli.ParseCommands(*flConfigFile, *flTempDir, flag.Args()...) 17 | 18 | if err != nil { 19 | log.Println("err") 20 | log.Fatal(err) 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /vendor/go/src/github.com/mitchellh/goamz/s3/export_test.go: -------------------------------------------------------------------------------- 1 | package s3 2 | 3 | import ( 4 | "github.com/mitchellh/goamz/aws" 5 | ) 6 | 7 | var originalStrategy = attempts 8 | 9 | func SetAttemptStrategy(s *aws.AttemptStrategy) { 10 | if s == nil { 11 | attempts = originalStrategy 12 | } else { 13 | attempts = *s 14 | } 15 | } 16 | 17 | func Sign(auth aws.Auth, method, path string, params, headers map[string][]string) { 18 | sign(auth, method, path, params, headers) 19 | } 20 | 21 | func SetListPartsMax(n int) { 22 | listPartsMax = n 23 | } 24 | 25 | func SetListMultiMax(n int) { 26 | listMultiMax = n 27 | } 28 | -------------------------------------------------------------------------------- /cli/remote.go: -------------------------------------------------------------------------------- 1 | package cli 2 | 3 | import ( 4 | "github.com/blake-education/dogestry/remote" 5 | "fmt" 6 | ) 7 | 8 | func (cli *DogestryCli) CmdRemote(args ...string) error { 9 | cmd := cli.Subcmd("remote", "REMOTE", "describes a remote") 10 | if err := cmd.Parse(args); err != nil { 11 | return nil 12 | } 13 | 14 | if len(cmd.Args()) < 1 { 15 | return fmt.Errorf("Error: REMOTE not specified") 16 | } 17 | 18 | remoteDef := cmd.Arg(0) 19 | 20 | r, err := remote.NewRemote(remoteDef, cli.Config) 21 | if err != nil { 22 | return err 23 | } 24 | 25 | fmt.Println("remote: ", r.Desc()) 26 | 27 | return nil 28 | } 29 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:13.10 2 | MAINTAINER Lachie Cox 3 | 4 | RUN apt-get update && \ 5 | apt-get -y install \ 6 | curl \ 7 | git \ 8 | ca-certificates \ 9 | --no-install-recommends 10 | 11 | RUN curl -s https://go.googlecode.com/files/go1.2.linux-amd64.tar.gz | tar -v -C /usr/local -xz 12 | ENV PATH /usr/local/go/bin:$PATH 13 | ENV GOPATH /go:/go/src/github.com/blake-education/dogestry/vendor/go 14 | ADD . /go/src/github.com/blake-education/dogestry 15 | 16 | RUN cd /go/src/github.com/blake-education/dogestry && \ 17 | go get && \ 18 | go build && \ 19 | cp dogestry /dogestry 20 | -------------------------------------------------------------------------------- /vendor/go/src/github.com/mitchellh/goamz/exp/mturk/sign_test.go: -------------------------------------------------------------------------------- 1 | package mturk_test 2 | 3 | import ( 4 | "github.com/mitchellh/goamz/aws" 5 | "github.com/mitchellh/goamz/exp/mturk" 6 | . "github.com/motain/gocheck" 7 | ) 8 | 9 | // Mechanical Turk REST authentication docs: http://goo.gl/wrzfn 10 | 11 | var testAuth = aws.Auth{"user", "secret", ""} 12 | 13 | // == fIJy9wCApBNL2R4J2WjJGtIBFX4= 14 | func (s *S) TestBasicSignature(c *C) { 15 | params := map[string]string{} 16 | mturk.Sign(testAuth, "AWSMechanicalTurkRequester", "CreateHIT", "2012-02-16T20:30:47Z", params) 17 | expected := "b/TnvzrdeD/L/EyzdFrznPXhido=" 18 | c.Assert(params["Signature"], Equals, expected) 19 | } 20 | -------------------------------------------------------------------------------- /vendor/go/src/github.com/fsouza/go-dockerclient/engine/hack.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 Docker authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the DOCKER-LICENSE file. 4 | 5 | package engine 6 | 7 | type Hack map[string]interface{} 8 | 9 | func (eng *Engine) Hack_GetGlobalVar(key string) interface{} { 10 | if eng.hack == nil { 11 | return nil 12 | } 13 | val, exists := eng.hack[key] 14 | if !exists { 15 | return nil 16 | } 17 | return val 18 | } 19 | 20 | func (eng *Engine) Hack_SetGlobalVar(key string, val interface{}) { 21 | if eng.hack == nil { 22 | eng.hack = make(Hack) 23 | } 24 | eng.hack[key] = val 25 | } 26 | -------------------------------------------------------------------------------- /vendor/go/src/code.google.com/p/gcfg/types/bool.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | // BoolValues defines the name and value mappings for ParseBool. 4 | var BoolValues = map[string]interface{}{ 5 | "true": true, "yes": true, "on": true, "1": true, 6 | "false": false, "no": false, "off": false, "0": false, 7 | } 8 | 9 | var boolParser = func() *EnumParser { 10 | ep := &EnumParser{} 11 | ep.AddVals(BoolValues) 12 | return ep 13 | }() 14 | 15 | // ParseBool parses bool values according to the definitions in BoolValues. 16 | // Parsing is case-insensitive. 17 | func ParseBool(s string) (bool, error) { 18 | v, err := boolParser.Parse(s) 19 | if err != nil { 20 | return false, err 21 | } 22 | return v.(bool), nil 23 | } 24 | -------------------------------------------------------------------------------- /vendor/go/src/github.com/fsouza/go-dockerclient/engine/helpers_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 Docker authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the DOCKER-LICENSE file. 4 | 5 | package engine 6 | 7 | import ( 8 | "io/ioutil" 9 | "testing" 10 | ) 11 | 12 | var globalTestID string 13 | 14 | func newTestEngine(t *testing.T) *Engine { 15 | tmp, err := ioutil.TempDir("", "asd") 16 | if err != nil { 17 | t.Fatal(err) 18 | } 19 | eng, err := New(tmp) 20 | if err != nil { 21 | t.Fatal(err) 22 | } 23 | return eng 24 | } 25 | 26 | func mkJob(t *testing.T, name string, args ...string) *Job { 27 | return newTestEngine(t).Job(name, args...) 28 | } 29 | -------------------------------------------------------------------------------- /vendor/go/src/github.com/mitchellh/goamz/exp/mturk/sign.go: -------------------------------------------------------------------------------- 1 | package mturk 2 | 3 | import ( 4 | "crypto/hmac" 5 | "crypto/sha1" 6 | "encoding/base64" 7 | "github.com/mitchellh/goamz/aws" 8 | ) 9 | 10 | var b64 = base64.StdEncoding 11 | 12 | // ---------------------------------------------------------------------------- 13 | // Mechanical Turk signing (http://goo.gl/wrzfn) 14 | func sign(auth aws.Auth, service, method, timestamp string, params map[string]string) { 15 | payload := service + method + timestamp 16 | hash := hmac.New(sha1.New, []byte(auth.SecretKey)) 17 | hash.Write([]byte(payload)) 18 | signature := make([]byte, b64.EncodedLen(hash.Size())) 19 | b64.Encode(signature, hash.Sum(nil)) 20 | 21 | params["Signature"] = string(signature) 22 | } 23 | -------------------------------------------------------------------------------- /vendor/go/src/github.com/mitchellh/goamz/testutil/suite.go: -------------------------------------------------------------------------------- 1 | package testutil 2 | 3 | import ( 4 | "flag" 5 | "github.com/mitchellh/goamz/aws" 6 | . "github.com/motain/gocheck" 7 | ) 8 | 9 | // Amazon must be used by all tested packages to determine whether to 10 | // run functional tests against the real AWS servers. 11 | var Amazon bool 12 | 13 | func init() { 14 | flag.BoolVar(&Amazon, "amazon", false, "Enable tests against amazon server") 15 | } 16 | 17 | type LiveSuite struct { 18 | auth aws.Auth 19 | } 20 | 21 | func (s *LiveSuite) SetUpSuite(c *C) { 22 | if !Amazon { 23 | c.Skip("amazon tests not enabled (-amazon flag)") 24 | } 25 | auth, err := aws.EnvAuth() 26 | if err != nil { 27 | c.Fatal(err.Error()) 28 | } 29 | s.auth = auth 30 | } 31 | -------------------------------------------------------------------------------- /vendor/go/src/code.google.com/p/gcfg/types/scan.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "fmt" 5 | "io" 6 | "reflect" 7 | ) 8 | 9 | // ScanFully uses fmt.Sscanf with verb to fully scan val into ptr. 10 | func ScanFully(ptr interface{}, val string, verb byte) error { 11 | t := reflect.ValueOf(ptr).Elem().Type() 12 | // attempt to read extra bytes to make sure the value is consumed 13 | var b []byte 14 | n, err := fmt.Sscanf(val, "%"+string(verb)+"%s", ptr, &b) 15 | switch { 16 | case n < 1 || n == 1 && err != io.EOF: 17 | return fmt.Errorf("failed to parse %q as %v: %v", val, t, err) 18 | case n > 1: 19 | return fmt.Errorf("failed to parse %q as %v: extra characters %q", val, t, string(b)) 20 | } 21 | // n == 1 && err == io.EOF 22 | return nil 23 | } 24 | -------------------------------------------------------------------------------- /vendor/go/src/code.google.com/p/gcfg/types/enum_test.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestEnumParserBool(t *testing.T) { 8 | for _, tt := range []struct { 9 | val string 10 | res bool 11 | ok bool 12 | }{ 13 | {val: "tRuE", res: true, ok: true}, 14 | {val: "False", res: false, ok: true}, 15 | {val: "t", ok: false}, 16 | } { 17 | b, err := ParseBool(tt.val) 18 | switch { 19 | case tt.ok && err != nil: 20 | t.Errorf("%q: got error %v, want %v", tt.val, err, tt.res) 21 | case !tt.ok && err == nil: 22 | t.Errorf("%q: got %v, want error", tt.val, b) 23 | case tt.ok && b != tt.res: 24 | t.Errorf("%q: got %v, want %v", tt.val, b, tt.res) 25 | default: 26 | t.Logf("%q: got %v, %v", tt.val, b, err) 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /config/config.go: -------------------------------------------------------------------------------- 1 | package config 2 | 3 | import ( 4 | "code.google.com/p/gcfg" 5 | ) 6 | 7 | type RemoteConfig struct { 8 | Url string 9 | } 10 | 11 | type S3Config struct { 12 | Access_Key_Id string 13 | Secret_Key string 14 | } 15 | 16 | type CompressorConfig struct { 17 | Lz4 string 18 | } 19 | 20 | type DockerConfig struct { 21 | Connection string 22 | } 23 | 24 | type DogestryConfig struct { 25 | Temp_Dir string 26 | } 27 | 28 | type Config struct { 29 | Remote map[string]*RemoteConfig 30 | S3 S3Config 31 | Compressor CompressorConfig 32 | Docker DockerConfig 33 | Dogestry DogestryConfig 34 | } 35 | 36 | func ParseConfig(configFilePath string) (config Config, err error) { 37 | err = gcfg.ReadFileInto(&config, configFilePath) 38 | return 39 | } 40 | -------------------------------------------------------------------------------- /vendor/go/src/github.com/fsouza/go-dockerclient/change_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 go-dockerclient authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package docker 6 | 7 | import ( 8 | "testing" 9 | ) 10 | 11 | func TestChangeString(t *testing.T) { 12 | var tests = []struct { 13 | change Change 14 | expected string 15 | }{ 16 | {Change{"/etc/passwd", ChangeModify}, "C /etc/passwd"}, 17 | {Change{"/etc/passwd", ChangeAdd}, "A /etc/passwd"}, 18 | {Change{"/etc/passwd", ChangeDelete}, "D /etc/passwd"}, 19 | {Change{"/etc/passwd", 33}, " /etc/passwd"}, 20 | } 21 | for _, tt := range tests { 22 | if got := tt.change.String(); got != tt.expected { 23 | t.Errorf("Change.String(): want %q. Got %q.", tt.expected, got) 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /vendor/go/src/github.com/fsouza/go-dockerclient/change.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 go-dockerclient authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package docker 6 | 7 | import "fmt" 8 | 9 | type ChangeType int 10 | 11 | const ( 12 | ChangeModify ChangeType = iota 13 | ChangeAdd 14 | ChangeDelete 15 | ) 16 | 17 | // Change represents a change in a container. 18 | // 19 | // See http://goo.gl/DpGyzK for more details. 20 | type Change struct { 21 | Path string 22 | Kind ChangeType 23 | } 24 | 25 | func (change *Change) String() string { 26 | var kind string 27 | switch change.Kind { 28 | case ChangeModify: 29 | kind = "C" 30 | case ChangeAdd: 31 | kind = "A" 32 | case ChangeDelete: 33 | kind = "D" 34 | } 35 | return fmt.Sprintf("%s %s", kind, change.Path) 36 | } 37 | -------------------------------------------------------------------------------- /vendor/go/src/github.com/mitchellh/goamz/exp/sdb/sign_test.go: -------------------------------------------------------------------------------- 1 | package sdb_test 2 | 3 | import ( 4 | "github.com/mitchellh/goamz/aws" 5 | "github.com/mitchellh/goamz/exp/sdb" 6 | . "github.com/motain/gocheck" 7 | ) 8 | 9 | // SimpleDB ReST authentication docs: http://goo.gl/CaY81 10 | 11 | var testAuth = aws.Auth{"access-key-id-s8eBOWuU", "secret-access-key-UkQjTLd9", ""} 12 | 13 | func (s *S) TestSignExampleDomainCreate(c *C) { 14 | method := "GET" 15 | params := map[string][]string{ 16 | "Action": {"CreateDomain"}, 17 | "DomainName": {"MyDomain"}, 18 | "Timestamp": {"2011-08-20T07:23:57+12:00"}, 19 | "Version": {"2009-04-15"}, 20 | } 21 | headers := map[string][]string{ 22 | "Host": {"sdb.amazonaws.com"}, 23 | } 24 | sdb.Sign(testAuth, method, "", params, headers) 25 | expected := "ot2JaeeqMRJqgAqW67hkzUlffgxdOz4RykbrECB+tDU=" 26 | c.Assert(params["Signature"], DeepEquals, []string{expected}) 27 | } 28 | 29 | // Do a few test methods which takes combinations of params 30 | -------------------------------------------------------------------------------- /vendor/go/src/github.com/mitchellh/goamz/iam/iamt_test.go: -------------------------------------------------------------------------------- 1 | package iam_test 2 | 3 | import ( 4 | "github.com/mitchellh/goamz/aws" 5 | "github.com/mitchellh/goamz/iam" 6 | "github.com/mitchellh/goamz/iam/iamtest" 7 | . "github.com/motain/gocheck" 8 | ) 9 | 10 | // LocalServer represents a local ec2test fake server. 11 | type LocalServer struct { 12 | auth aws.Auth 13 | region aws.Region 14 | srv *iamtest.Server 15 | } 16 | 17 | func (s *LocalServer) SetUp(c *C) { 18 | srv, err := iamtest.NewServer() 19 | c.Assert(err, IsNil) 20 | c.Assert(srv, NotNil) 21 | 22 | s.srv = srv 23 | s.region = aws.Region{IAMEndpoint: srv.URL()} 24 | } 25 | 26 | // LocalServerSuite defines tests that will run 27 | // against the local iamtest server. It includes 28 | // tests from ClientTests. 29 | type LocalServerSuite struct { 30 | srv LocalServer 31 | ClientTests 32 | } 33 | 34 | var _ = Suite(&LocalServerSuite{}) 35 | 36 | func (s *LocalServerSuite) SetUpSuite(c *C) { 37 | s.srv.SetUp(c) 38 | s.ClientTests.iam = iam.New(s.srv.auth, s.srv.region) 39 | } 40 | -------------------------------------------------------------------------------- /vendor/go/src/code.google.com/p/gcfg/types/scan_test.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "reflect" 5 | "testing" 6 | ) 7 | 8 | func TestScanFully(t *testing.T) { 9 | for _, tt := range []struct { 10 | val string 11 | verb byte 12 | res interface{} 13 | ok bool 14 | }{ 15 | {"a", 'v', int(0), false}, 16 | {"0x", 'v', int(0), true}, 17 | {"0x", 'd', int(0), false}, 18 | } { 19 | d := reflect.New(reflect.TypeOf(tt.res)).Interface() 20 | err := ScanFully(d, tt.val, tt.verb) 21 | switch { 22 | case tt.ok && err != nil: 23 | t.Errorf("ScanFully(%T, %q, '%c'): want ok, got error %v", 24 | d, tt.val, tt.verb, err) 25 | case !tt.ok && err == nil: 26 | t.Errorf("ScanFully(%T, %q, '%c'): want error, got %v", 27 | d, tt.val, tt.verb, elem(d)) 28 | case tt.ok && err == nil && !reflect.DeepEqual(tt.res, elem(d)): 29 | t.Errorf("ScanFully(%T, %q, '%c'): want %v, got %v", 30 | d, tt.val, tt.verb, tt.res, elem(d)) 31 | default: 32 | t.Logf("ScanFully(%T, %q, '%c') = %v; *ptr==%v", 33 | d, tt.val, tt.verb, err, elem(d)) 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /utils/progress.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import ( 4 | "fmt" 5 | "io" 6 | ) 7 | 8 | type progressReader struct { 9 | r io.Reader 10 | TotalSize int64 11 | Output io.Writer 12 | Current int64 13 | LastUpdate int64 14 | UpdateInterval int64 15 | } 16 | 17 | func NewProgressReader(r io.Reader, size int64, w io.Writer) io.Reader { 18 | return &progressReader{r, size, w, 0, 0, 1024*512} 19 | } 20 | 21 | 22 | func printProgress(w io.Writer, progress, total int64) { 23 | fmt.Fprintf(w, "%s/%s \r", HumanSize(progress), HumanSize(total)) 24 | } 25 | 26 | func (p *progressReader) Read(in []byte) (n int, err error) { 27 | n,err = p.r.Read(in) 28 | p.Current += int64(n) 29 | 30 | if p.Current-p.LastUpdate > p.UpdateInterval { 31 | printProgress(p.Output, p.Current, p.TotalSize) 32 | p.LastUpdate = p.Current 33 | } 34 | 35 | 36 | if err != nil { 37 | printProgress(p.Output, p.Current, p.TotalSize) 38 | fmt.Fprintf(p.Output, "\n") 39 | if err == io.EOF { 40 | fmt.Fprintf(p.Output, "done\n") 41 | } else { 42 | fmt.Fprintf(p.Output, "error: %s\n", err) 43 | } 44 | } 45 | 46 | return 47 | } 48 | -------------------------------------------------------------------------------- /vendor/go/src/github.com/mitchellh/goamz/iam/sign.go: -------------------------------------------------------------------------------- 1 | package iam 2 | 3 | import ( 4 | "crypto/hmac" 5 | "crypto/sha256" 6 | "encoding/base64" 7 | "github.com/mitchellh/goamz/aws" 8 | "sort" 9 | "strings" 10 | ) 11 | 12 | // ---------------------------------------------------------------------------- 13 | // Version 2 signing (http://goo.gl/RSRp5) 14 | 15 | var b64 = base64.StdEncoding 16 | 17 | func sign(auth aws.Auth, method, path string, params map[string]string, host string) { 18 | params["AWSAccessKeyId"] = auth.AccessKey 19 | params["SignatureVersion"] = "2" 20 | params["SignatureMethod"] = "HmacSHA256" 21 | if auth.Token != "" { 22 | params["SecurityToken"] = auth.Token 23 | } 24 | 25 | var sarray []string 26 | for k, v := range params { 27 | sarray = append(sarray, aws.Encode(k)+"="+aws.Encode(v)) 28 | } 29 | sort.StringSlice(sarray).Sort() 30 | joined := strings.Join(sarray, "&") 31 | payload := method + "\n" + host + "\n" + path + "\n" + joined 32 | hash := hmac.New(sha256.New, []byte(auth.SecretKey)) 33 | hash.Write([]byte(payload)) 34 | signature := make([]byte, b64.EncodedLen(hash.Size())) 35 | b64.Encode(signature, hash.Sum(nil)) 36 | 37 | params["Signature"] = string(signature) 38 | } 39 | -------------------------------------------------------------------------------- /vendor/go/src/code.google.com/p/gcfg/types/enum.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "fmt" 5 | "reflect" 6 | "strings" 7 | ) 8 | 9 | // EnumParser parses "enum" values; i.e. a predefined set of strings to 10 | // predefined values. 11 | type EnumParser struct { 12 | Type string // type name; if not set, use type of first value added 13 | CaseMatch bool // if true, matching of strings is case-sensitive 14 | // PrefixMatch bool 15 | vals map[string]interface{} 16 | } 17 | 18 | // AddVals adds strings and values to an EnumParser. 19 | func (ep *EnumParser) AddVals(vals map[string]interface{}) { 20 | if ep.vals == nil { 21 | ep.vals = make(map[string]interface{}) 22 | } 23 | for k, v := range vals { 24 | if ep.Type == "" { 25 | ep.Type = reflect.TypeOf(v).Name() 26 | } 27 | if !ep.CaseMatch { 28 | k = strings.ToLower(k) 29 | } 30 | ep.vals[k] = v 31 | } 32 | } 33 | 34 | // Parse parses the string and returns the value or an error. 35 | func (ep EnumParser) Parse(s string) (interface{}, error) { 36 | if !ep.CaseMatch { 37 | s = strings.ToLower(s) 38 | } 39 | v, ok := ep.vals[s] 40 | if !ok { 41 | return false, fmt.Errorf("failed to parse %s %#q", ep.Type, s) 42 | } 43 | return v, nil 44 | } 45 | -------------------------------------------------------------------------------- /vendor/go/src/github.com/fsouza/go-dockerclient/misc.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 go-dockerclient authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package docker 6 | 7 | import ( 8 | "bytes" 9 | "github.com/fsouza/go-dockerclient/engine" 10 | "io" 11 | ) 12 | 13 | // Version returns version information about the docker server. 14 | // 15 | // See http://goo.gl/IqKNRE for more details. 16 | func (c *Client) Version() (*engine.Env, error) { 17 | body, _, err := c.do("GET", "/version", nil) 18 | if err != nil { 19 | return nil, err 20 | } 21 | out := engine.NewOutput() 22 | remoteVersion, err := out.AddEnv() 23 | if err != nil { 24 | return nil, err 25 | } 26 | if _, err := io.Copy(out, bytes.NewReader(body)); err != nil { 27 | return nil, err 28 | } 29 | return remoteVersion, nil 30 | } 31 | 32 | // Info returns system-wide information, like the number of running containers. 33 | // 34 | // See http://goo.gl/LOmySw for more details. 35 | func (c *Client) Info() (*engine.Env, error) { 36 | body, _, err := c.do("GET", "/info", nil) 37 | if err != nil { 38 | return nil, err 39 | } 40 | var info engine.Env 41 | err = info.Decode(bytes.NewReader(body)) 42 | if err != nil { 43 | return nil, err 44 | } 45 | return &info, nil 46 | } 47 | -------------------------------------------------------------------------------- /vendor/go/src/code.google.com/p/gcfg/scanner/example_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package scanner_test 6 | 7 | import ( 8 | "fmt" 9 | ) 10 | 11 | import ( 12 | "code.google.com/p/gcfg/scanner" 13 | "code.google.com/p/gcfg/token" 14 | ) 15 | 16 | func ExampleScanner_Scan() { 17 | // src is the input that we want to tokenize. 18 | src := []byte(`[profile "A"] 19 | color = blue ; Comment`) 20 | 21 | // Initialize the scanner. 22 | var s scanner.Scanner 23 | fset := token.NewFileSet() // positions are relative to fset 24 | file := fset.AddFile("", fset.Base(), len(src)) // register input "file" 25 | s.Init(file, src, nil /* no error handler */, scanner.ScanComments) 26 | 27 | // Repeated calls to Scan yield the token sequence found in the input. 28 | for { 29 | pos, tok, lit := s.Scan() 30 | if tok == token.EOF { 31 | break 32 | } 33 | fmt.Printf("%s\t%q\t%q\n", fset.Position(pos), tok, lit) 34 | } 35 | 36 | // output: 37 | // 1:1 "[" "" 38 | // 1:2 "IDENT" "profile" 39 | // 1:10 "STRING" "\"A\"" 40 | // 1:13 "]" "" 41 | // 1:14 "\n" "" 42 | // 2:1 "IDENT" "color" 43 | // 2:7 "=" "" 44 | // 2:9 "STRING" "blue" 45 | // 2:14 "COMMENT" "; Comment" 46 | } 47 | -------------------------------------------------------------------------------- /vendor/go/src/github.com/fsouza/go-dockerclient/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014, go-dockerclient authors 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, 8 | this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright notice, 10 | this list of conditions and the following disclaimer in the documentation 11 | and/or other materials provided with the distribution. 12 | 13 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 14 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 15 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 16 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 17 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 19 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 20 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 21 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 22 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 | -------------------------------------------------------------------------------- /remote/s3_responses_test.go: -------------------------------------------------------------------------------- 1 | package remote 2 | 3 | var GetListResultDump1 = ` 4 | 5 | 6 | quotes 7 | N 8 | false 9 | 10 | prefix/Nelson 11 | 2006-01-01T12:00:00.000Z 12 | "828ef3fdfa96f00ad9f27c383fc9ac7f" 13 | 5 14 | STANDARD 15 | 16 | bcaf161ca5fb16fd081034f 17 | webfile 18 | 19 | 20 | 21 | prefix/Nelson.sum 22 | 2006-01-01T12:00:00.000Z 23 | "828ef3fdfa96f00ad9f27c383fc9ac7f" 24 | 5 25 | STANDARD 26 | 27 | bcaf161ca5fb16fd081034f 28 | webfile 29 | 30 | 31 | 32 | prefix/Neo 33 | 2006-01-01T12:00:00.000Z 34 | "828ef3fdfa96f00ad9f27c383fc9ac7f" 35 | 4 36 | STANDARD 37 | 38 | bcaf1ffd86a5fb16fd081034f 39 | webfile 40 | 41 | 42 | 43 | ` 44 | 45 | 46 | -------------------------------------------------------------------------------- /vendor/go/src/github.com/mitchellh/goamz/ec2/sign.go: -------------------------------------------------------------------------------- 1 | package ec2 2 | 3 | import ( 4 | "crypto/hmac" 5 | "crypto/sha256" 6 | "encoding/base64" 7 | "github.com/mitchellh/goamz/aws" 8 | "sort" 9 | "strings" 10 | ) 11 | 12 | // ---------------------------------------------------------------------------- 13 | // EC2 signing (http://goo.gl/fQmAN) 14 | 15 | var b64 = base64.StdEncoding 16 | 17 | func sign(auth aws.Auth, method, path string, params map[string]string, host string) { 18 | params["AWSAccessKeyId"] = auth.AccessKey 19 | params["SignatureVersion"] = "2" 20 | params["SignatureMethod"] = "HmacSHA256" 21 | if auth.Token != "" { 22 | params["SecurityToken"] = auth.Token 23 | } 24 | 25 | // AWS specifies that the parameters in a signed request must 26 | // be provided in the natural order of the keys. This is distinct 27 | // from the natural order of the encoded value of key=value. 28 | // Percent and equals affect the sorting order. 29 | var keys, sarray []string 30 | for k, _ := range params { 31 | keys = append(keys, k) 32 | } 33 | sort.Strings(keys) 34 | for _, k := range keys { 35 | sarray = append(sarray, aws.Encode(k)+"="+aws.Encode(params[k])) 36 | } 37 | joined := strings.Join(sarray, "&") 38 | payload := method + "\n" + host + "\n" + path + "\n" + joined 39 | hash := hmac.New(sha256.New, []byte(auth.SecretKey)) 40 | hash.Write([]byte(payload)) 41 | signature := make([]byte, b64.EncodedLen(hash.Size())) 42 | b64.Encode(signature, hash.Sum(nil)) 43 | 44 | params["Signature"] = string(signature) 45 | } 46 | -------------------------------------------------------------------------------- /vendor/go/src/github.com/mitchellh/goamz/exp/mturk/responses_test.go: -------------------------------------------------------------------------------- 1 | package mturk_test 2 | 3 | var BasicHitResponse = ` 4 | 643b794b-66b6-4427-bb8a-4d3df5c9a20eTrue28J4IXKO2L927XKJTHO34OCDNASCDW2XZ7D1X3V0FKQVW7LU51S7PKKGFKDF 5 | ` 6 | 7 | var SearchHITResponse = ` 8 | 38862d9c-f015-4177-a2d3-924110a9d6f2True1112BU26DG67D1XTE823B3OQ2JF2XWF8322OWJ5OPB0YV6IGL5727KP9U38P5XR2011-12-28T19:56:20Ztest hitplease disregard, testing onlyReviewable10.01USD$0.0125920002011-12-28T19:56:50Z30010 9 | ` 10 | -------------------------------------------------------------------------------- /vendor/go/src/code.google.com/p/gcfg/token/serialize.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package token 6 | 7 | type serializedFile struct { 8 | // fields correspond 1:1 to fields with same (lower-case) name in File 9 | Name string 10 | Base int 11 | Size int 12 | Lines []int 13 | Infos []lineInfo 14 | } 15 | 16 | type serializedFileSet struct { 17 | Base int 18 | Files []serializedFile 19 | } 20 | 21 | // Read calls decode to deserialize a file set into s; s must not be nil. 22 | func (s *FileSet) Read(decode func(interface{}) error) error { 23 | var ss serializedFileSet 24 | if err := decode(&ss); err != nil { 25 | return err 26 | } 27 | 28 | s.mutex.Lock() 29 | s.base = ss.Base 30 | files := make([]*File, len(ss.Files)) 31 | for i := 0; i < len(ss.Files); i++ { 32 | f := &ss.Files[i] 33 | files[i] = &File{s, f.Name, f.Base, f.Size, f.Lines, f.Infos} 34 | } 35 | s.files = files 36 | s.last = nil 37 | s.mutex.Unlock() 38 | 39 | return nil 40 | } 41 | 42 | // Write calls encode to serialize the file set s. 43 | func (s *FileSet) Write(encode func(interface{}) error) error { 44 | var ss serializedFileSet 45 | 46 | s.mutex.Lock() 47 | ss.Base = s.base 48 | files := make([]serializedFile, len(s.files)) 49 | for i, f := range s.files { 50 | files[i] = serializedFile{f.name, f.base, f.size, f.lines, f.infos} 51 | } 52 | ss.Files = files 53 | s.mutex.Unlock() 54 | 55 | return encode(ss) 56 | } 57 | -------------------------------------------------------------------------------- /vendor/go/src/github.com/fsouza/go-dockerclient/term/termios_linux.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 Docker authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the DOCKER-LICENSE file. 4 | 5 | package term 6 | 7 | import ( 8 | "syscall" 9 | "unsafe" 10 | ) 11 | 12 | const ( 13 | getTermios = syscall.TCGETS 14 | setTermios = syscall.TCSETS 15 | ) 16 | 17 | type Termios struct { 18 | Iflag uint32 19 | Oflag uint32 20 | Cflag uint32 21 | Lflag uint32 22 | Cc [20]byte 23 | Ispeed uint32 24 | Ospeed uint32 25 | } 26 | 27 | // MakeRaw put the terminal connected to the given file descriptor into raw 28 | // mode and returns the previous state of the terminal so that it can be 29 | // restored. 30 | func MakeRaw(fd uintptr) (*State, error) { 31 | var oldState State 32 | if _, _, err := syscall.Syscall(syscall.SYS_IOCTL, fd, getTermios, uintptr(unsafe.Pointer(&oldState.termios))); err != 0 { 33 | return nil, err 34 | } 35 | 36 | newState := oldState.termios 37 | 38 | newState.Iflag &^= (syscall.IGNBRK | syscall.BRKINT | syscall.PARMRK | syscall.ISTRIP | syscall.INLCR | syscall.IGNCR | syscall.ICRNL | syscall.IXON) 39 | newState.Oflag &^= syscall.OPOST 40 | newState.Lflag &^= (syscall.ECHO | syscall.ECHONL | syscall.ICANON | syscall.ISIG | syscall.IEXTEN) 41 | newState.Cflag &^= (syscall.CSIZE | syscall.PARENB) 42 | newState.Cflag |= syscall.CS8 43 | 44 | if _, _, err := syscall.Syscall(syscall.SYS_IOCTL, fd, setTermios, uintptr(unsafe.Pointer(&newState))); err != 0 { 45 | return nil, err 46 | } 47 | return &oldState, nil 48 | } 49 | -------------------------------------------------------------------------------- /vendor/go/src/github.com/fsouza/go-dockerclient/term/termios_darwin.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 Docker authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the DOCKER-LICENSE file. 4 | 5 | package term 6 | 7 | import ( 8 | "syscall" 9 | "unsafe" 10 | ) 11 | 12 | const ( 13 | getTermios = syscall.TIOCGETA 14 | setTermios = syscall.TIOCSETA 15 | 16 | ECHO = 0x00000008 17 | ONLCR = 0x2 18 | ISTRIP = 0x20 19 | INLCR = 0x40 20 | ISIG = 0x80 21 | IGNCR = 0x80 22 | ICANON = 0x100 23 | ICRNL = 0x100 24 | IXOFF = 0x400 25 | IXON = 0x200 26 | ) 27 | 28 | type Termios struct { 29 | Iflag uint64 30 | Oflag uint64 31 | Cflag uint64 32 | Lflag uint64 33 | Cc [20]byte 34 | Ispeed uint64 35 | Ospeed uint64 36 | } 37 | 38 | // MakeRaw put the terminal connected to the given file descriptor into raw 39 | // mode and returns the previous state of the terminal so that it can be 40 | // restored. 41 | func MakeRaw(fd uintptr) (*State, error) { 42 | var oldState State 43 | if _, _, err := syscall.Syscall(syscall.SYS_IOCTL, fd, uintptr(getTermios), uintptr(unsafe.Pointer(&oldState.termios))); err != 0 { 44 | return nil, err 45 | } 46 | 47 | newState := oldState.termios 48 | newState.Iflag &^= (ISTRIP | INLCR | IGNCR | IXON | IXOFF) 49 | newState.Iflag |= ICRNL 50 | newState.Oflag |= ONLCR 51 | newState.Lflag &^= (ECHO | ICANON | ISIG) 52 | 53 | if _, _, err := syscall.Syscall(syscall.SYS_IOCTL, fd, uintptr(setTermios), uintptr(unsafe.Pointer(&newState))); err != 0 { 54 | return nil, err 55 | } 56 | 57 | return &oldState, nil 58 | } 59 | -------------------------------------------------------------------------------- /utils/utils.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | 7 | "crypto/md5" 8 | "crypto/sha1" 9 | "encoding/hex" 10 | "bufio" 11 | "io" 12 | ) 13 | 14 | // HumanSize returns a human-readable approximation of a size 15 | // using SI standard (eg. "44kB", "17MB") 16 | func HumanSize(size int64) string { 17 | i := 0 18 | var sizef float64 19 | sizef = float64(size) 20 | units := []string{"B", "kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"} 21 | for sizef >= 1000.0 { 22 | sizef = sizef / 1000.0 23 | i++ 24 | } 25 | return fmt.Sprintf("%.4g %s", sizef, units[i]) 26 | } 27 | 28 | 29 | func FileHumanSize(path string) string { 30 | var size int64 31 | info,err := os.Stat(path) 32 | if err != nil { 33 | size = 0 34 | } else { 35 | size = info.Size() 36 | } 37 | 38 | return HumanSize(size) 39 | } 40 | 41 | 42 | // md5 file at path 43 | func Md5File(path string) (string, error) { 44 | f, err := os.Open(path) 45 | if err != nil { 46 | return "", nil 47 | } 48 | defer f.Close() 49 | 50 | // files could be pretty big, lets buffer 51 | buff := bufio.NewReader(f) 52 | hash := md5.New() 53 | 54 | io.Copy(hash, buff) 55 | return hex.EncodeToString(hash.Sum(nil)), nil 56 | } 57 | 58 | 59 | // sha1 file at path 60 | func Sha1File(path string) (string, error) { 61 | f, err := os.Open(path) 62 | if err != nil { 63 | return "", nil 64 | } 65 | defer f.Close() 66 | 67 | // files could be pretty big, lets buffer 68 | buff := bufio.NewReader(f) 69 | hash := sha1.New() 70 | 71 | io.Copy(hash, buff) 72 | return hex.EncodeToString(hash.Sum(nil)), nil 73 | } 74 | -------------------------------------------------------------------------------- /vendor/go/src/github.com/fsouza/go-dockerclient/README.markdown: -------------------------------------------------------------------------------- 1 | #go-dockerclient 2 | 3 | [![Build Status](https://drone.io/github.com/fsouza/go-dockerclient/status.png)](https://drone.io/github.com/fsouza/go-dockerclient/latest) 4 | [![Build Status](https://travis-ci.org/fsouza/go-dockerclient.png)](https://travis-ci.org/fsouza/go-dockerclient) 5 | 6 | [![GoDoc](http://godoc.org/github.com/fsouza/go-dockerclient?status.png)](http://godoc.org/github.com/fsouza/go-dockerclient) 7 | 8 | This package presents a client for the Docker remote API. 9 | 10 | For more details, check the remote API documentation: 11 | http://docs.docker.io/en/latest/api/docker_remote_api. 12 | 13 | ##Versioning 14 | 15 | * Version 0.1 is compatible with Docker v0.7.1 16 | * The master is compatible with Docker's master 17 | 18 | 19 | ## Example 20 | 21 | package main 22 | 23 | import ( 24 | "fmt" 25 | "github.com/fsouza/go-dockerclient" 26 | ) 27 | 28 | func main() { 29 | endpoint := "unix:///var/run/docker.sock" 30 | client, _ := docker.NewClient(endpoint) 31 | imgs, _ := client.ListImages(true) 32 | for _, img := range imgs { 33 | fmt.Println("ID: ", img.ID) 34 | fmt.Println("RepoTags: ", img.RepoTags) 35 | fmt.Println("Created: ", img.Created) 36 | fmt.Println("Size: ", img.Size) 37 | fmt.Println("VirtualSize: ", img.VirtualSize) 38 | fmt.Println("ParentId: ", img.ParentId) 39 | fmt.Println("Repository: ", img.Repository) 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /vendor/go/src/github.com/mitchellh/goamz/exp/sdb/sign.go: -------------------------------------------------------------------------------- 1 | package sdb 2 | 3 | import ( 4 | "crypto/hmac" 5 | "crypto/sha256" 6 | "encoding/base64" 7 | "github.com/mitchellh/goamz/aws" 8 | "net/http" 9 | "net/url" 10 | "sort" 11 | "strings" 12 | ) 13 | 14 | var b64 = base64.StdEncoding 15 | 16 | // ---------------------------------------------------------------------------- 17 | // SimpleDB signing (http://goo.gl/CaY81) 18 | 19 | func sign(auth aws.Auth, method, path string, params url.Values, headers http.Header) { 20 | var host string 21 | for k, v := range headers { 22 | k = strings.ToLower(k) 23 | switch k { 24 | case "host": 25 | host = v[0] 26 | } 27 | } 28 | 29 | // set up some defaults used for signing the request 30 | params["AWSAccessKeyId"] = []string{auth.AccessKey} 31 | params["SignatureVersion"] = []string{"2"} 32 | params["SignatureMethod"] = []string{"HmacSHA256"} 33 | if auth.Token != "" { 34 | params["SecurityToken"] = auth.Token 35 | } 36 | 37 | // join up all the incoming params 38 | var sarray []string 39 | for k, v := range params { 40 | sarray = append(sarray, aws.Encode(k)+"="+aws.Encode(v[0])) 41 | } 42 | sort.StringSlice(sarray).Sort() 43 | joined := strings.Join(sarray, "&") 44 | 45 | // create the payload, sign it and create the signature 46 | payload := strings.Join([]string{method, host, "/", joined}, "\n") 47 | hash := hmac.New(sha256.New, []byte(auth.SecretKey)) 48 | hash.Write([]byte(payload)) 49 | signature := make([]byte, b64.EncodedLen(hash.Size())) 50 | b64.Encode(signature, hash.Sum(nil)) 51 | 52 | // add the signature to the outgoing params 53 | params["Signature"] = []string{string(signature)} 54 | } 55 | -------------------------------------------------------------------------------- /vendor/go/src/code.google.com/p/gcfg/issues_test.go: -------------------------------------------------------------------------------- 1 | package gcfg 2 | 3 | import ( 4 | "fmt" 5 | "math/big" 6 | "strings" 7 | "testing" 8 | ) 9 | 10 | type Config1 struct { 11 | Section struct { 12 | Int int 13 | BigInt big.Int 14 | } 15 | } 16 | 17 | var testsIssue1 = []struct { 18 | cfg string 19 | typename string 20 | }{ 21 | {"[section]\nint=X", "int"}, 22 | {"[section]\nint=", "int"}, 23 | {"[section]\nint=1A", "int"}, 24 | {"[section]\nbigint=X", "big.Int"}, 25 | {"[section]\nbigint=", "big.Int"}, 26 | {"[section]\nbigint=1A", "big.Int"}, 27 | } 28 | 29 | // Value parse error should: 30 | // - include plain type name 31 | // - not include reflect internals 32 | func TestIssue1(t *testing.T) { 33 | for i, tt := range testsIssue1 { 34 | var c Config1 35 | err := ReadStringInto(&c, tt.cfg) 36 | switch { 37 | case err == nil: 38 | t.Errorf("%d fail: got ok; wanted error", i) 39 | case !strings.Contains(err.Error(), tt.typename): 40 | t.Errorf("%d fail: error message doesn't contain type name %q: %v", 41 | i, tt.typename, err) 42 | case strings.Contains(err.Error(), "reflect"): 43 | t.Errorf("%d fail: error message includes reflect internals: %v", 44 | i, err) 45 | default: 46 | t.Logf("%d pass: %v", i, err) 47 | } 48 | } 49 | } 50 | 51 | type confIssue2 struct{ Main struct{ Foo string } } 52 | 53 | var testsIssue2 = []readtest{ 54 | {"[main]\n;\nfoo = bar\n", &confIssue2{struct{ Foo string }{"bar"}}, true}, 55 | {"[main]\r\n;\r\nfoo = bar\r\n", &confIssue2{struct{ Foo string }{"bar"}}, true}, 56 | } 57 | 58 | func TestIssue2(t *testing.T) { 59 | for i, tt := range testsIssue2 { 60 | id := fmt.Sprintf("issue2:%d", i) 61 | testRead(t, id, tt) 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /client/container.go: -------------------------------------------------------------------------------- 1 | package client 2 | 3 | import ( 4 | "encoding/json" 5 | "net/http" 6 | 7 | "fmt" 8 | ) 9 | 10 | 11 | type Container struct { 12 | ID string 13 | } 14 | 15 | type Containers struct { 16 | ID string `json:"Id"` 17 | Image string 18 | Command string 19 | Created int64 20 | Status string 21 | Ports []Port 22 | SizeRw int64 23 | SizeRootFs int64 24 | Names []string 25 | } 26 | 27 | 28 | type NoSuchContainer struct { 29 | ID string 30 | } 31 | 32 | func (err NoSuchContainer) Error() string { 33 | return "No such container: " + err.ID 34 | } 35 | 36 | 37 | type ListContainersOptions struct { 38 | All bool 39 | Size bool 40 | Limit int 41 | Since string 42 | Before string 43 | } 44 | 45 | 46 | func (c *Client) ListContainers(opts ListContainersOptions) ([]Containers, error) { 47 | path := "/containers/json?" + queryString(opts) 48 | body, _, err := c.do("GET", path, nil) 49 | if err != nil { 50 | return nil, err 51 | } 52 | 53 | fmt.Println("conts", string(body)) 54 | 55 | var containers []Containers 56 | err = json.Unmarshal(body, &containers) 57 | if err != nil { 58 | return nil, err 59 | } 60 | return containers, nil 61 | } 62 | 63 | 64 | func (c *Client) InspectContainer(id string) (*Container, error) { 65 | path := "/containers/" + id + "/json" 66 | body, status, err := c.do("GET", path, nil) 67 | if status == http.StatusNotFound { 68 | return nil, &NoSuchContainer{ID: id} 69 | } 70 | if err != nil { 71 | return nil, err 72 | } 73 | 74 | var container Container 75 | err = json.Unmarshal(body, &container) 76 | if err != nil { 77 | return nil, err 78 | } 79 | return &container, nil 80 | } 81 | -------------------------------------------------------------------------------- /vendor/go/src/github.com/mitchellh/goamz/aws/attempt_test.go: -------------------------------------------------------------------------------- 1 | package aws_test 2 | 3 | import ( 4 | "github.com/mitchellh/goamz/aws" 5 | . "github.com/motain/gocheck" 6 | "time" 7 | ) 8 | 9 | func (S) TestAttemptTiming(c *C) { 10 | testAttempt := aws.AttemptStrategy{ 11 | Total: 0.25e9, 12 | Delay: 0.1e9, 13 | } 14 | want := []time.Duration{0, 0.1e9, 0.2e9, 0.2e9} 15 | got := make([]time.Duration, 0, len(want)) // avoid allocation when testing timing 16 | t0 := time.Now() 17 | for a := testAttempt.Start(); a.Next(); { 18 | got = append(got, time.Now().Sub(t0)) 19 | } 20 | got = append(got, time.Now().Sub(t0)) 21 | c.Assert(got, HasLen, len(want)) 22 | const margin = 0.01e9 23 | for i, got := range want { 24 | lo := want[i] - margin 25 | hi := want[i] + margin 26 | if got < lo || got > hi { 27 | c.Errorf("attempt %d want %g got %g", i, want[i].Seconds(), got.Seconds()) 28 | } 29 | } 30 | } 31 | 32 | func (S) TestAttemptNextHasNext(c *C) { 33 | a := aws.AttemptStrategy{}.Start() 34 | c.Assert(a.Next(), Equals, true) 35 | c.Assert(a.Next(), Equals, false) 36 | 37 | a = aws.AttemptStrategy{}.Start() 38 | c.Assert(a.Next(), Equals, true) 39 | c.Assert(a.HasNext(), Equals, false) 40 | c.Assert(a.Next(), Equals, false) 41 | 42 | a = aws.AttemptStrategy{Total: 2e8}.Start() 43 | c.Assert(a.Next(), Equals, true) 44 | c.Assert(a.HasNext(), Equals, true) 45 | time.Sleep(2e8) 46 | c.Assert(a.HasNext(), Equals, true) 47 | c.Assert(a.Next(), Equals, true) 48 | c.Assert(a.Next(), Equals, false) 49 | 50 | a = aws.AttemptStrategy{Total: 1e8, Min: 2}.Start() 51 | time.Sleep(1e8) 52 | c.Assert(a.Next(), Equals, true) 53 | c.Assert(a.HasNext(), Equals, true) 54 | c.Assert(a.Next(), Equals, true) 55 | c.Assert(a.HasNext(), Equals, false) 56 | c.Assert(a.Next(), Equals, false) 57 | } 58 | -------------------------------------------------------------------------------- /vendor/go/src/github.com/fsouza/go-dockerclient/engine/http.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 Docker authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the DOCKER-LICENSE file. 4 | 5 | package engine 6 | 7 | import ( 8 | "net/http" 9 | "path" 10 | ) 11 | 12 | // ServeHTTP executes a job as specified by the http request `r`, and sends the 13 | // result as an http response. 14 | // This method allows an Engine instance to be passed as a standard http.Handler interface. 15 | // 16 | // Note that the protocol used in this methid is a convenience wrapper and is not the canonical 17 | // implementation of remote job execution. This is because HTTP/1 does not handle stream multiplexing, 18 | // and so cannot differentiate stdout from stderr. Additionally, headers cannot be added to a response 19 | // once data has been written to the body, which makes it inconvenient to return metadata such 20 | // as the exit status. 21 | // 22 | func (eng *Engine) ServeHTTP(w http.ResponseWriter, r *http.Request) { 23 | jobName := path.Base(r.URL.Path) 24 | jobArgs, exists := r.URL.Query()["a"] 25 | if !exists { 26 | jobArgs = []string{} 27 | } 28 | w.Header().Set("Job-Name", jobName) 29 | for _, arg := range jobArgs { 30 | w.Header().Add("Job-Args", arg) 31 | } 32 | job := eng.Job(jobName, jobArgs...) 33 | job.Stdout.Add(w) 34 | job.Stderr.Add(w) 35 | // FIXME: distinguish job status from engine error in Run() 36 | // The former should be passed as a special header, the former 37 | // should cause a 500 status 38 | w.WriteHeader(http.StatusOK) 39 | // The exit status cannot be sent reliably with HTTP1, because headers 40 | // can only be sent before the body. 41 | // (we could possibly use http footers via chunked encoding, but I couldn't find 42 | // how to use them in net/http) 43 | job.Run() 44 | } 45 | -------------------------------------------------------------------------------- /compressor/compressor.go: -------------------------------------------------------------------------------- 1 | package compressor 2 | 3 | import ( 4 | "github.com/blake-education/dogestry/config" 5 | 6 | "os" 7 | "os/exec" 8 | "strings" 9 | "fmt" 10 | 11 | "io" 12 | ) 13 | 14 | type Compressor struct { 15 | lz4Path string 16 | } 17 | 18 | 19 | func NewCompressor(config config.Config) (Compressor, error) { 20 | lz4 := config.Compressor.Lz4 21 | if lz4 == "" { 22 | lz4 = "lz4" 23 | } 24 | 25 | path,err := exec.LookPath(lz4) 26 | if err != nil { 27 | return Compressor{}, fmt.Errorf("can't find executable lz4 on the $PATH") 28 | } 29 | 30 | return Compressor{ 31 | lz4Path: path, 32 | }, nil 33 | } 34 | 35 | 36 | 37 | // compress using lz4 38 | // would use go version if we could (needs a streaming version) 39 | // lz4 is low compression, but extremely fast 40 | func (cmp Compressor) Compress(path string) error { 41 | compressedPath := path + ".lz4" 42 | 43 | err := exec.Command(cmp.lz4Path, path, compressedPath).Run() 44 | if err != nil { 45 | return err 46 | } 47 | 48 | return os.Remove(path) 49 | } 50 | 51 | 52 | func (cmp Compressor) CompressReader(r io.Reader) (out io.Reader, err error) { 53 | cmd := exec.Command(cmp.lz4Path, "-") 54 | 55 | cmd.Stdin = r 56 | out,err = cmd.StdoutPipe() 57 | if err != nil { 58 | return 59 | } 60 | 61 | err = cmd.Start() 62 | if err != nil { 63 | return 64 | } 65 | 66 | return 67 | } 68 | 69 | 70 | func (cmp Compressor) Decompress(path string) error { 71 | if !strings.HasSuffix(path, ".lz4") { 72 | return nil 73 | } 74 | 75 | uncompressedPath := strings.TrimSuffix(path, ".lz4") 76 | 77 | if _, err := os.Stat(path); !os.IsNotExist(err) { 78 | cmd := exec.Command(cmp.lz4Path, "-d", "-f", path, uncompressedPath) 79 | if err := cmd.Run(); err != nil { 80 | return err 81 | } 82 | 83 | return os.Remove(path) 84 | } 85 | 86 | return nil 87 | } 88 | -------------------------------------------------------------------------------- /vendor/go/src/github.com/fsouza/go-dockerclient/testing/data/container.tar: -------------------------------------------------------------------------------- 1 | fakecontainer000644 000766 000024 00000000065 12210121775 016021 0ustar00flavia.carlettestaff000000 000000 this is supposed to be a fake container in a tar. xD 2 | -------------------------------------------------------------------------------- /vendor/go/src/github.com/mitchellh/goamz/aws/attempt.go: -------------------------------------------------------------------------------- 1 | package aws 2 | 3 | import ( 4 | "time" 5 | ) 6 | 7 | // AttemptStrategy represents a strategy for waiting for an action 8 | // to complete successfully. This is an internal type used by the 9 | // implementation of other goamz packages. 10 | type AttemptStrategy struct { 11 | Total time.Duration // total duration of attempt. 12 | Delay time.Duration // interval between each try in the burst. 13 | Min int // minimum number of retries; overrides Total 14 | } 15 | 16 | type Attempt struct { 17 | strategy AttemptStrategy 18 | last time.Time 19 | end time.Time 20 | force bool 21 | count int 22 | } 23 | 24 | // Start begins a new sequence of attempts for the given strategy. 25 | func (s AttemptStrategy) Start() *Attempt { 26 | now := time.Now() 27 | return &Attempt{ 28 | strategy: s, 29 | last: now, 30 | end: now.Add(s.Total), 31 | force: true, 32 | } 33 | } 34 | 35 | // Next waits until it is time to perform the next attempt or returns 36 | // false if it is time to stop trying. 37 | func (a *Attempt) Next() bool { 38 | now := time.Now() 39 | sleep := a.nextSleep(now) 40 | if !a.force && !now.Add(sleep).Before(a.end) && a.strategy.Min <= a.count { 41 | return false 42 | } 43 | a.force = false 44 | if sleep > 0 && a.count > 0 { 45 | time.Sleep(sleep) 46 | now = time.Now() 47 | } 48 | a.count++ 49 | a.last = now 50 | return true 51 | } 52 | 53 | func (a *Attempt) nextSleep(now time.Time) time.Duration { 54 | sleep := a.strategy.Delay - now.Sub(a.last) 55 | if sleep < 0 { 56 | return 0 57 | } 58 | return sleep 59 | } 60 | 61 | // HasNext returns whether another attempt will be made if the current 62 | // one fails. If it returns true, the following call to Next is 63 | // guaranteed to return true. 64 | func (a *Attempt) HasNext() bool { 65 | if a.force || a.strategy.Min > a.count { 66 | return true 67 | } 68 | now := time.Now() 69 | if now.Add(a.nextSleep(now)).Before(a.end) { 70 | a.force = true 71 | return true 72 | } 73 | return false 74 | } 75 | -------------------------------------------------------------------------------- /vendor/go/src/github.com/fsouza/go-dockerclient/example_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 go-dockerclient authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package docker_test 6 | 7 | import ( 8 | "archive/tar" 9 | "bytes" 10 | "github.com/fsouza/go-dockerclient" 11 | "io" 12 | "log" 13 | ) 14 | 15 | func ExampleClient_AttachToContainer() { 16 | client, err := docker.NewClient("http://localhost:4243") 17 | if err != nil { 18 | log.Fatal(err) 19 | } 20 | // Reading logs from container a84849 and sending them to buf. 21 | var buf bytes.Buffer 22 | err = client.AttachToContainer(docker.AttachToContainerOptions{ 23 | Container: "a84849", 24 | OutputStream: &buf, 25 | Logs: true, 26 | Stdout: true, 27 | Stderr: true, 28 | }) 29 | if err != nil { 30 | log.Fatal(err) 31 | } 32 | log.Println(buf.String()) 33 | // Attaching to stdout and streaming. 34 | buf.Reset() 35 | err = client.AttachToContainer(docker.AttachToContainerOptions{ 36 | Container: "a84849", 37 | OutputStream: &buf, 38 | Stdout: true, 39 | Stream: true, 40 | }) 41 | if err != nil { 42 | log.Fatal(err) 43 | } 44 | log.Println(buf.String()) 45 | } 46 | 47 | func ExampleClient_CopyFromContainer() { 48 | client, err := docker.NewClient("http://localhost:4243") 49 | if err != nil { 50 | log.Fatal(err) 51 | } 52 | cid := "a84849" 53 | // Copy resulting file 54 | var buf bytes.Buffer 55 | filename := "/tmp/output.txt" 56 | err = client.CopyFromContainer(docker.CopyFromContainerOptions{ 57 | Container: cid, 58 | Resource: filename, 59 | OutputStream: &buf, 60 | }) 61 | if err != nil { 62 | log.Fatalf("Error while copying from %s: %s\n", cid, err) 63 | } 64 | content := new(bytes.Buffer) 65 | r := bytes.NewReader(buf.Bytes()) 66 | tr := tar.NewReader(r) 67 | tr.Next() 68 | if err != nil && err != io.EOF { 69 | log.Fatal(err) 70 | } 71 | if _, err := io.Copy(content, tr); err != nil { 72 | log.Fatal(err) 73 | } 74 | log.Println(buf.String()) 75 | } 76 | -------------------------------------------------------------------------------- /vendor/go/src/code.google.com/p/gcfg/types/int.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "fmt" 5 | "strings" 6 | ) 7 | 8 | // An IntMode is a mode for parsing integer values, representing a set of 9 | // accepted bases. 10 | type IntMode uint8 11 | 12 | // IntMode values for ParseInt; can be combined using binary or. 13 | const ( 14 | Dec IntMode = 1 << iota 15 | Hex 16 | Oct 17 | ) 18 | 19 | // String returns a string representation of IntMode; e.g. `IntMode(Dec|Hex)`. 20 | func (m IntMode) String() string { 21 | var modes []string 22 | if m&Dec != 0 { 23 | modes = append(modes, "Dec") 24 | } 25 | if m&Hex != 0 { 26 | modes = append(modes, "Hex") 27 | } 28 | if m&Oct != 0 { 29 | modes = append(modes, "Oct") 30 | } 31 | return "IntMode(" + strings.Join(modes, "|") + ")" 32 | } 33 | 34 | var errIntAmbig = fmt.Errorf("ambiguous integer value; must include '0' prefix") 35 | 36 | func prefix0(val string) bool { 37 | return strings.HasPrefix(val, "0") || strings.HasPrefix(val, "-0") 38 | } 39 | 40 | func prefix0x(val string) bool { 41 | return strings.HasPrefix(val, "0x") || strings.HasPrefix(val, "-0x") 42 | } 43 | 44 | // ParseInt parses val using mode into intptr, which must be a pointer to an 45 | // integer kind type. Non-decimal value require prefix `0` or `0x` in the cases 46 | // when mode permits ambiguity of base; otherwise the prefix can be omitted. 47 | func ParseInt(intptr interface{}, val string, mode IntMode) error { 48 | val = strings.TrimSpace(val) 49 | verb := byte(0) 50 | switch mode { 51 | case Dec: 52 | verb = 'd' 53 | case Dec + Hex: 54 | if prefix0x(val) { 55 | verb = 'v' 56 | } else { 57 | verb = 'd' 58 | } 59 | case Dec + Oct: 60 | if prefix0(val) && !prefix0x(val) { 61 | verb = 'v' 62 | } else { 63 | verb = 'd' 64 | } 65 | case Dec + Hex + Oct: 66 | verb = 'v' 67 | case Hex: 68 | if prefix0x(val) { 69 | verb = 'v' 70 | } else { 71 | verb = 'x' 72 | } 73 | case Oct: 74 | verb = 'o' 75 | case Hex + Oct: 76 | if prefix0(val) { 77 | verb = 'v' 78 | } else { 79 | return errIntAmbig 80 | } 81 | } 82 | if verb == 0 { 83 | panic("unsupported mode") 84 | } 85 | return ScanFully(intptr, val, verb) 86 | } 87 | -------------------------------------------------------------------------------- /vendor/go/src/github.com/mitchellh/goamz/s3/s3t_test.go: -------------------------------------------------------------------------------- 1 | package s3_test 2 | 3 | import ( 4 | "github.com/mitchellh/goamz/aws" 5 | "github.com/mitchellh/goamz/s3" 6 | "github.com/mitchellh/goamz/s3/s3test" 7 | . "github.com/motain/gocheck" 8 | ) 9 | 10 | type LocalServer struct { 11 | auth aws.Auth 12 | region aws.Region 13 | srv *s3test.Server 14 | config *s3test.Config 15 | } 16 | 17 | func (s *LocalServer) SetUp(c *C) { 18 | srv, err := s3test.NewServer(s.config) 19 | c.Assert(err, IsNil) 20 | c.Assert(srv, NotNil) 21 | 22 | s.srv = srv 23 | s.region = aws.Region{ 24 | Name: "faux-region-1", 25 | S3Endpoint: srv.URL(), 26 | S3LocationConstraint: true, // s3test server requires a LocationConstraint 27 | } 28 | } 29 | 30 | // LocalServerSuite defines tests that will run 31 | // against the local s3test server. It includes 32 | // selected tests from ClientTests; 33 | // when the s3test functionality is sufficient, it should 34 | // include all of them, and ClientTests can be simply embedded. 35 | type LocalServerSuite struct { 36 | srv LocalServer 37 | clientTests ClientTests 38 | } 39 | 40 | var ( 41 | // run tests twice, once in us-east-1 mode, once not. 42 | _ = Suite(&LocalServerSuite{}) 43 | _ = Suite(&LocalServerSuite{ 44 | srv: LocalServer{ 45 | config: &s3test.Config{ 46 | Send409Conflict: true, 47 | }, 48 | }, 49 | }) 50 | ) 51 | 52 | func (s *LocalServerSuite) SetUpSuite(c *C) { 53 | s.srv.SetUp(c) 54 | s.clientTests.s3 = s3.New(s.srv.auth, s.srv.region) 55 | 56 | // TODO Sadly the fake server ignores auth completely right now. :-( 57 | s.clientTests.authIsBroken = true 58 | s.clientTests.Cleanup() 59 | } 60 | 61 | func (s *LocalServerSuite) TearDownTest(c *C) { 62 | s.clientTests.Cleanup() 63 | } 64 | 65 | func (s *LocalServerSuite) TestBasicFunctionality(c *C) { 66 | s.clientTests.TestBasicFunctionality(c) 67 | } 68 | 69 | func (s *LocalServerSuite) TestGetNotFound(c *C) { 70 | s.clientTests.TestGetNotFound(c) 71 | } 72 | 73 | func (s *LocalServerSuite) TestBucketList(c *C) { 74 | s.clientTests.TestBucketList(c) 75 | } 76 | 77 | func (s *LocalServerSuite) TestDoublePutBucket(c *C) { 78 | s.clientTests.TestDoublePutBucket(c) 79 | } 80 | -------------------------------------------------------------------------------- /vendor/go/src/github.com/mitchellh/goamz/exp/sns/sign.go: -------------------------------------------------------------------------------- 1 | package sns 2 | 3 | import ( 4 | "crypto/hmac" 5 | "crypto/sha256" 6 | "encoding/base64" 7 | "github.com/mitchellh/goamz/aws" 8 | "sort" 9 | "strings" 10 | ) 11 | 12 | var b64 = base64.StdEncoding 13 | 14 | /* 15 | func sign(auth aws.Auth, method, path string, params url.Values, headers http.Header) { 16 | var host string 17 | for k, v := range headers { 18 | k = strings.ToLower(k) 19 | switch k { 20 | case "host": 21 | host = v[0] 22 | } 23 | } 24 | 25 | params["AWSAccessKeyId"] = []string{auth.AccessKey} 26 | params["SignatureVersion"] = []string{"2"} 27 | params["SignatureMethod"] = []string{"HmacSHA256"} 28 | if auth.Token != "" { 29 | params["SecurityToken"] = auth.Token 30 | } 31 | 32 | var sarry []string 33 | for k, v := range params { 34 | sarry = append(sarry, aws.Encode(k) + "=" + aws.Encode(v[0])) 35 | } 36 | 37 | sort.StringSlice(sarry).Sort() 38 | joined := strings.Join(sarry, "&") 39 | 40 | payload := strings.Join([]string{method, host, "/", joined}, "\n") 41 | hash := hmac.NewSHA256([]byte(auth.SecretKey)) 42 | hash.Write([]byte(payload)) 43 | signature := make([]byte, b64.EncodedLen(hash.Size())) 44 | b64.Encode(signature, hash.Sum()) 45 | 46 | params["Signature"] = []string{"AWS " + string(signature)} 47 | println("Payload:", payload) 48 | println("Signature:", strings.Join(params["Signature"], "|")) 49 | }*/ 50 | 51 | func sign(auth aws.Auth, method, path string, params map[string]string, host string) { 52 | params["AWSAccessKeyId"] = auth.AccessKey 53 | params["SignatureVersion"] = "2" 54 | params["SignatureMethod"] = "HmacSHA256" 55 | 56 | var sarray []string 57 | for k, v := range params { 58 | sarray = append(sarray, aws.Encode(k)+"="+aws.Encode(v)) 59 | } 60 | sort.StringSlice(sarray).Sort() 61 | joined := strings.Join(sarray, "&") 62 | payload := method + "\n" + host + "\n" + path + "\n" + joined 63 | hash := hmac.New(sha256.New, []byte(auth.SecretKey)) 64 | hash.Write([]byte(payload)) 65 | signature := make([]byte, b64.EncodedLen(hash.Size())) 66 | b64.Encode(signature, hash.Sum(nil)) 67 | 68 | params["Signature"] = string(signature) 69 | } 70 | -------------------------------------------------------------------------------- /vendor/go/src/github.com/mitchellh/goamz/ec2/sign_test.go: -------------------------------------------------------------------------------- 1 | package ec2_test 2 | 3 | import ( 4 | "github.com/mitchellh/goamz/aws" 5 | "github.com/mitchellh/goamz/ec2" 6 | . "github.com/motain/gocheck" 7 | ) 8 | 9 | // EC2 ReST authentication docs: http://goo.gl/fQmAN 10 | 11 | var testAuth = aws.Auth{"user", "secret", ""} 12 | 13 | func (s *S) TestBasicSignature(c *C) { 14 | params := map[string]string{} 15 | ec2.Sign(testAuth, "GET", "/path", params, "localhost") 16 | c.Assert(params["SignatureVersion"], Equals, "2") 17 | c.Assert(params["SignatureMethod"], Equals, "HmacSHA256") 18 | expected := "6lSe5QyXum0jMVc7cOUz32/52ZnL7N5RyKRk/09yiK4=" 19 | c.Assert(params["Signature"], Equals, expected) 20 | } 21 | 22 | func (s *S) TestParamSignature(c *C) { 23 | params := map[string]string{ 24 | "param1": "value1", 25 | "param2": "value2", 26 | "param3": "value3", 27 | } 28 | ec2.Sign(testAuth, "GET", "/path", params, "localhost") 29 | expected := "XWOR4+0lmK8bD8CGDGZ4kfuSPbb2JibLJiCl/OPu1oU=" 30 | c.Assert(params["Signature"], Equals, expected) 31 | } 32 | 33 | func (s *S) TestManyParams(c *C) { 34 | params := map[string]string{ 35 | "param1": "value10", 36 | "param2": "value2", 37 | "param3": "value3", 38 | "param4": "value4", 39 | "param5": "value5", 40 | "param6": "value6", 41 | "param7": "value7", 42 | "param8": "value8", 43 | "param9": "value9", 44 | "param10": "value1", 45 | } 46 | ec2.Sign(testAuth, "GET", "/path", params, "localhost") 47 | expected := "di0sjxIvezUgQ1SIL6i+C/H8lL+U0CQ9frLIak8jkVg=" 48 | c.Assert(params["Signature"], Equals, expected) 49 | } 50 | 51 | func (s *S) TestEscaping(c *C) { 52 | params := map[string]string{"Nonce": "+ +"} 53 | ec2.Sign(testAuth, "GET", "/path", params, "localhost") 54 | c.Assert(params["Nonce"], Equals, "+ +") 55 | expected := "bqffDELReIqwjg/W0DnsnVUmfLK4wXVLO4/LuG+1VFA=" 56 | c.Assert(params["Signature"], Equals, expected) 57 | } 58 | 59 | func (s *S) TestSignatureExample1(c *C) { 60 | params := map[string]string{ 61 | "Timestamp": "2009-02-01T12:53:20+00:00", 62 | "Version": "2007-11-07", 63 | "Action": "ListDomains", 64 | } 65 | ec2.Sign(aws.Auth{"access", "secret", ""}, "GET", "/", params, "sdb.amazonaws.com") 66 | expected := "okj96/5ucWBSc1uR2zXVfm6mDHtgfNv657rRtt/aunQ=" 67 | c.Assert(params["Signature"], Equals, expected) 68 | } 69 | -------------------------------------------------------------------------------- /vendor/go/src/code.google.com/p/gcfg/types/int_test.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | import ( 4 | "reflect" 5 | "testing" 6 | ) 7 | 8 | func elem(p interface{}) interface{} { 9 | return reflect.ValueOf(p).Elem().Interface() 10 | } 11 | 12 | func TestParseInt(t *testing.T) { 13 | for _, tt := range []struct { 14 | val string 15 | mode IntMode 16 | exp interface{} 17 | ok bool 18 | }{ 19 | {"0", Dec, int(0), true}, 20 | {"10", Dec, int(10), true}, 21 | {"-10", Dec, int(-10), true}, 22 | {"x", Dec, int(0), false}, 23 | {"0xa", Hex, int(0xa), true}, 24 | {"a", Hex, int(0xa), true}, 25 | {"10", Hex, int(0x10), true}, 26 | {"-0xa", Hex, int(-0xa), true}, 27 | {"0x", Hex, int(0x0), true}, // Scanf doesn't require digit behind 0x 28 | {"-0x", Hex, int(0x0), true}, // Scanf doesn't require digit behind 0x 29 | {"-a", Hex, int(-0xa), true}, 30 | {"-10", Hex, int(-0x10), true}, 31 | {"x", Hex, int(0), false}, 32 | {"10", Oct, int(010), true}, 33 | {"010", Oct, int(010), true}, 34 | {"-10", Oct, int(-010), true}, 35 | {"-010", Oct, int(-010), true}, 36 | {"10", Dec | Hex, int(10), true}, 37 | {"010", Dec | Hex, int(10), true}, 38 | {"0x10", Dec | Hex, int(0x10), true}, 39 | {"10", Dec | Oct, int(10), true}, 40 | {"010", Dec | Oct, int(010), true}, 41 | {"0x10", Dec | Oct, int(0), false}, 42 | {"10", Hex | Oct, int(0), false}, // need prefix to distinguish Hex/Oct 43 | {"010", Hex | Oct, int(010), true}, 44 | {"0x10", Hex | Oct, int(0x10), true}, 45 | {"10", Dec | Hex | Oct, int(10), true}, 46 | {"010", Dec | Hex | Oct, int(010), true}, 47 | {"0x10", Dec | Hex | Oct, int(0x10), true}, 48 | } { 49 | typ := reflect.TypeOf(tt.exp) 50 | res := reflect.New(typ).Interface() 51 | err := ParseInt(res, tt.val, tt.mode) 52 | switch { 53 | case tt.ok && err != nil: 54 | t.Errorf("ParseInt(%v, %#v, %v): fail; got error %v, want ok", 55 | typ, tt.val, tt.mode, err) 56 | case !tt.ok && err == nil: 57 | t.Errorf("ParseInt(%v, %#v, %v): fail; got %v, want error", 58 | typ, tt.val, tt.mode, elem(res)) 59 | case tt.ok && !reflect.DeepEqual(elem(res), tt.exp): 60 | t.Errorf("ParseInt(%v, %#v, %v): fail; got %v, want %v", 61 | typ, tt.val, tt.mode, elem(res), tt.exp) 62 | default: 63 | t.Logf("ParseInt(%v, %#v, %s): pass; got %v, error %v", 64 | typ, tt.val, tt.mode, elem(res), err) 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /vendor/go/src/github.com/mitchellh/goamz/aws/aws_test.go: -------------------------------------------------------------------------------- 1 | package aws_test 2 | 3 | import ( 4 | "github.com/mitchellh/goamz/aws" 5 | . "github.com/motain/gocheck" 6 | "os" 7 | "strings" 8 | "testing" 9 | ) 10 | 11 | func Test(t *testing.T) { 12 | TestingT(t) 13 | } 14 | 15 | var _ = Suite(&S{}) 16 | 17 | type S struct { 18 | environ []string 19 | } 20 | 21 | func (s *S) SetUpSuite(c *C) { 22 | s.environ = os.Environ() 23 | } 24 | 25 | func (s *S) TearDownTest(c *C) { 26 | os.Clearenv() 27 | for _, kv := range s.environ { 28 | l := strings.SplitN(kv, "=", 2) 29 | os.Setenv(l[0], l[1]) 30 | } 31 | } 32 | 33 | func (s *S) TestEnvAuthNoSecret(c *C) { 34 | os.Clearenv() 35 | _, err := aws.EnvAuth() 36 | c.Assert(err, ErrorMatches, "AWS_SECRET_ACCESS_KEY or AWS_SECRET_KEY not found in environment") 37 | } 38 | 39 | func (s *S) TestEnvAuthNoAccess(c *C) { 40 | os.Clearenv() 41 | os.Setenv("AWS_SECRET_ACCESS_KEY", "foo") 42 | _, err := aws.EnvAuth() 43 | c.Assert(err, ErrorMatches, "AWS_ACCESS_KEY_ID or AWS_ACCESS_KEY not found in environment") 44 | } 45 | 46 | func (s *S) TestEnvAuth(c *C) { 47 | os.Clearenv() 48 | os.Setenv("AWS_SECRET_ACCESS_KEY", "secret") 49 | os.Setenv("AWS_ACCESS_KEY_ID", "access") 50 | auth, err := aws.EnvAuth() 51 | c.Assert(err, IsNil) 52 | c.Assert(auth, Equals, aws.Auth{SecretKey: "secret", AccessKey: "access"}) 53 | } 54 | 55 | func (s *S) TestEnvAuthAlt(c *C) { 56 | os.Clearenv() 57 | os.Setenv("AWS_SECRET_KEY", "secret") 58 | os.Setenv("AWS_ACCESS_KEY", "access") 59 | auth, err := aws.EnvAuth() 60 | c.Assert(err, IsNil) 61 | c.Assert(auth, Equals, aws.Auth{SecretKey: "secret", AccessKey: "access"}) 62 | } 63 | 64 | func (s *S) TestGetAuthStatic(c *C) { 65 | auth, err := aws.GetAuth("access", "secret") 66 | c.Assert(err, IsNil) 67 | c.Assert(auth, Equals, aws.Auth{SecretKey: "secret", AccessKey: "access"}) 68 | } 69 | 70 | func (s *S) TestGetAuthEnv(c *C) { 71 | os.Clearenv() 72 | os.Setenv("AWS_SECRET_ACCESS_KEY", "secret") 73 | os.Setenv("AWS_ACCESS_KEY_ID", "access") 74 | auth, err := aws.GetAuth("", "") 75 | c.Assert(err, IsNil) 76 | c.Assert(auth, Equals, aws.Auth{SecretKey: "secret", AccessKey: "access"}) 77 | } 78 | 79 | func (s *S) TestEncode(c *C) { 80 | c.Assert(aws.Encode("foo"), Equals, "foo") 81 | c.Assert(aws.Encode("/"), Equals, "%2F") 82 | } 83 | 84 | func (s *S) TestRegionsAreNamed(c *C) { 85 | for n, r := range aws.Regions { 86 | c.Assert(n, Equals, r.Name) 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /vendor/go/src/code.google.com/p/gcfg/token/token.go: -------------------------------------------------------------------------------- 1 | // Copyright 2009 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // Package token defines constants representing the lexical tokens of the gcfg 6 | // configuration syntax and basic operations on tokens (printing, predicates). 7 | // 8 | // Note that the API for the token package may change to accommodate new 9 | // features or implementation changes in gcfg. 10 | // 11 | package token 12 | 13 | import "strconv" 14 | 15 | // Token is the set of lexical tokens of the gcfg configuration syntax. 16 | type Token int 17 | 18 | // The list of tokens. 19 | const ( 20 | // Special tokens 21 | ILLEGAL Token = iota 22 | EOF 23 | COMMENT 24 | 25 | literal_beg 26 | // Identifiers and basic type literals 27 | // (these tokens stand for classes of literals) 28 | IDENT // section-name, variable-name 29 | STRING // "subsection-name", variable value 30 | literal_end 31 | 32 | operator_beg 33 | // Operators and delimiters 34 | ASSIGN // = 35 | LBRACK // [ 36 | RBRACK // ] 37 | EOL // \n 38 | operator_end 39 | ) 40 | 41 | var tokens = [...]string{ 42 | ILLEGAL: "ILLEGAL", 43 | 44 | EOF: "EOF", 45 | COMMENT: "COMMENT", 46 | 47 | IDENT: "IDENT", 48 | STRING: "STRING", 49 | 50 | ASSIGN: "=", 51 | LBRACK: "[", 52 | RBRACK: "]", 53 | EOL: "\n", 54 | } 55 | 56 | // String returns the string corresponding to the token tok. 57 | // For operators and delimiters, the string is the actual token character 58 | // sequence (e.g., for the token ASSIGN, the string is "="). For all other 59 | // tokens the string corresponds to the token constant name (e.g. for the 60 | // token IDENT, the string is "IDENT"). 61 | // 62 | func (tok Token) String() string { 63 | s := "" 64 | if 0 <= tok && tok < Token(len(tokens)) { 65 | s = tokens[tok] 66 | } 67 | if s == "" { 68 | s = "token(" + strconv.Itoa(int(tok)) + ")" 69 | } 70 | return s 71 | } 72 | 73 | // Predicates 74 | 75 | // IsLiteral returns true for tokens corresponding to identifiers 76 | // and basic type literals; it returns false otherwise. 77 | // 78 | func (tok Token) IsLiteral() bool { return literal_beg < tok && tok < literal_end } 79 | 80 | // IsOperator returns true for tokens corresponding to operators and 81 | // delimiters; it returns false otherwise. 82 | // 83 | func (tok Token) IsOperator() bool { return operator_beg < tok && tok < operator_end } 84 | -------------------------------------------------------------------------------- /vendor/go/src/github.com/mitchellh/goamz/ec2/ec2test/filter.go: -------------------------------------------------------------------------------- 1 | package ec2test 2 | 3 | import ( 4 | "fmt" 5 | "net/url" 6 | "strings" 7 | ) 8 | 9 | // filter holds an ec2 filter. A filter maps an attribute to a set of 10 | // possible values for that attribute. For an item to pass through the 11 | // filter, every attribute of the item mentioned in the filter must match 12 | // at least one of its given values. 13 | type filter map[string][]string 14 | 15 | // newFilter creates a new filter from the Filter fields in the url form. 16 | // 17 | // The filtering is specified through a map of name=>values, where the 18 | // name is a well-defined key identifying the data to be matched, 19 | // and the list of values holds the possible values the filtered 20 | // item can take for the key to be included in the 21 | // result set. For example: 22 | // 23 | // Filter.1.Name=instance-type 24 | // Filter.1.Value.1=m1.small 25 | // Filter.1.Value.2=m1.large 26 | // 27 | func newFilter(form url.Values) filter { 28 | // TODO return an error if the fields are not well formed? 29 | names := make(map[int]string) 30 | values := make(map[int][]string) 31 | maxId := 0 32 | for name, fvalues := range form { 33 | var rest string 34 | var id int 35 | if x, _ := fmt.Sscanf(name, "Filter.%d.%s", &id, &rest); x != 2 { 36 | continue 37 | } 38 | if id > maxId { 39 | maxId = id 40 | } 41 | if rest == "Name" { 42 | names[id] = fvalues[0] 43 | continue 44 | } 45 | if !strings.HasPrefix(rest, "Value.") { 46 | continue 47 | } 48 | values[id] = append(values[id], fvalues[0]) 49 | } 50 | 51 | f := make(filter) 52 | for id, name := range names { 53 | f[name] = values[id] 54 | } 55 | return f 56 | } 57 | 58 | func notDigit(r rune) bool { 59 | return r < '0' || r > '9' 60 | } 61 | 62 | // filterable represents an object that can be passed through a filter. 63 | type filterable interface { 64 | // matchAttr returns true if given attribute of the 65 | // object matches value. It returns an error if the 66 | // attribute is not recognised or the value is malformed. 67 | matchAttr(attr, value string) (bool, error) 68 | } 69 | 70 | // ok returns true if x passes through the filter. 71 | func (f filter) ok(x filterable) (bool, error) { 72 | next: 73 | for a, vs := range f { 74 | for _, v := range vs { 75 | if ok, err := x.matchAttr(a, v); ok { 76 | continue next 77 | } else if err != nil { 78 | return false, fmt.Errorf("bad attribute or value %q=%q for type %T: %v", a, v, x, err) 79 | } 80 | } 81 | return false, nil 82 | } 83 | return true, nil 84 | } 85 | -------------------------------------------------------------------------------- /vendor/go/src/github.com/fsouza/go-dockerclient/engine/job_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 Docker authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the DOCKER-LICENSE file. 4 | 5 | package engine 6 | 7 | import ( 8 | "os" 9 | "testing" 10 | ) 11 | 12 | func TestJobStatusOK(t *testing.T) { 13 | eng := newTestEngine(t) 14 | defer os.RemoveAll(eng.Root()) 15 | eng.Register("return_ok", func(job *Job) Status { return StatusOK }) 16 | err := eng.Job("return_ok").Run() 17 | if err != nil { 18 | t.Fatalf("Expected: err=%v\nReceived: err=%v", nil, err) 19 | } 20 | } 21 | 22 | func TestJobStatusErr(t *testing.T) { 23 | eng := newTestEngine(t) 24 | defer os.RemoveAll(eng.Root()) 25 | eng.Register("return_err", func(job *Job) Status { return StatusErr }) 26 | err := eng.Job("return_err").Run() 27 | if err == nil { 28 | t.Fatalf("When a job returns StatusErr, Run() should return an error") 29 | } 30 | } 31 | 32 | func TestJobStatusNotFound(t *testing.T) { 33 | eng := newTestEngine(t) 34 | defer os.RemoveAll(eng.Root()) 35 | eng.Register("return_not_found", func(job *Job) Status { return StatusNotFound }) 36 | err := eng.Job("return_not_found").Run() 37 | if err == nil { 38 | t.Fatalf("When a job returns StatusNotFound, Run() should return an error") 39 | } 40 | } 41 | 42 | func TestJobStdoutString(t *testing.T) { 43 | eng := newTestEngine(t) 44 | defer os.RemoveAll(eng.Root()) 45 | // FIXME: test multiple combinations of output and status 46 | eng.Register("say_something_in_stdout", func(job *Job) Status { 47 | job.Printf("Hello world\n") 48 | return StatusOK 49 | }) 50 | 51 | job := eng.Job("say_something_in_stdout") 52 | var output string 53 | if err := job.Stdout.AddString(&output); err != nil { 54 | t.Fatal(err) 55 | } 56 | if err := job.Run(); err != nil { 57 | t.Fatal(err) 58 | } 59 | if expectedOutput := "Hello world"; output != expectedOutput { 60 | t.Fatalf("Stdout last line:\nExpected: %v\nReceived: %v", expectedOutput, output) 61 | } 62 | } 63 | 64 | func TestJobStderrString(t *testing.T) { 65 | eng := newTestEngine(t) 66 | defer os.RemoveAll(eng.Root()) 67 | // FIXME: test multiple combinations of output and status 68 | eng.Register("say_something_in_stderr", func(job *Job) Status { 69 | job.Errorf("Warning, something might happen\nHere it comes!\nOh no...\nSomething happened\n") 70 | return StatusOK 71 | }) 72 | 73 | job := eng.Job("say_something_in_stderr") 74 | var output string 75 | if err := job.Stderr.AddString(&output); err != nil { 76 | t.Fatal(err) 77 | } 78 | if err := job.Run(); err != nil { 79 | t.Fatal(err) 80 | } 81 | if expectedOutput := "Something happened"; output != expectedOutput { 82 | t.Fatalf("Stderr last line:\nExpected: %v\nReceived: %v", expectedOutput, output) 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /client/image.go: -------------------------------------------------------------------------------- 1 | package client 2 | 3 | import ( 4 | "encoding/json" 5 | "errors" 6 | "io" 7 | "net/http" 8 | "time" 9 | ) 10 | 11 | var ( 12 | ErrNoSuchImage = errors.New("No such image") 13 | ) 14 | 15 | type Port string 16 | 17 | // Note: the Config structure should hold only portable information about the container. 18 | // Here, "portable" means "independent from the host we are running on". 19 | // Non-portable information *should* appear in HostConfig. 20 | type Config struct { 21 | Hostname string 22 | Domainname string 23 | User string 24 | Memory int64 // Memory limit (in bytes) 25 | MemorySwap int64 // Total memory usage (memory + swap); set `-1' to disable swap 26 | CpuShares int64 // CPU shares (relative weight vs. other containers) 27 | AttachStdin bool 28 | AttachStdout bool 29 | AttachStderr bool 30 | PortSpecs []string // Deprecated - Can be in the format of 8080/tcp 31 | ExposedPorts map[Port]struct{} 32 | Tty bool // Attach standard streams to a tty, including stdin if it is not closed. 33 | OpenStdin bool // Open stdin 34 | StdinOnce bool // If true, close stdin after the 1 attached client disconnects. 35 | Env []string 36 | Cmd []string 37 | Dns []string 38 | Image string // Name of the image as it was passed by the operator (eg. could be symbolic) 39 | Volumes map[string]struct{} 40 | VolumesFrom string 41 | WorkingDir string 42 | Entrypoint []string 43 | NetworkDisabled bool 44 | } 45 | 46 | type Image struct { 47 | ID string `json:"id"` 48 | Parent string `json:"parent,omitempty"` 49 | Comment string `json:"comment,omitempty"` 50 | Created time.Time `json:"created"` 51 | Container string `json:"container,omitempty"` 52 | ContainerConfig Config `json:"container_config,omitempty"` 53 | DockerVersion string `json:"docker_version,omitempty"` 54 | Author string `json:"author,omitempty"` 55 | Config *Config `json:"config,omitempty"` 56 | Architecture string `json:"architecture,omitempty"` 57 | Size int64 58 | } 59 | 60 | func (c *Client) InspectImage(name string) (*Image, error) { 61 | body, status, err := c.do("GET", "/images/"+name+"/json", nil) 62 | if status == http.StatusNotFound { 63 | return nil, ErrNoSuchImage 64 | } 65 | if err != nil { 66 | return nil, err 67 | } 68 | var image Image 69 | err = json.Unmarshal(body, &image) 70 | if err != nil { 71 | return nil, err 72 | } 73 | return &image, nil 74 | } 75 | 76 | func (c *Client) GetImageTarball(imageName string, w io.Writer) error { 77 | return c.stream("GET", "/images/"+imageName+"/get", nil, w) 78 | } 79 | 80 | func (c *Client) PostImageTarball(r io.Reader) error { 81 | return c.stream("POST", "/images/load", r, nil) 82 | } 83 | -------------------------------------------------------------------------------- /s3/client.go: -------------------------------------------------------------------------------- 1 | package s3 2 | 3 | type Keys struct { 4 | AccessKey string 5 | SecretKey string 6 | } 7 | 8 | // Initializes and returns a Keys using the AWS_ACCESS_KEY and AWS_SECRET_KEY 9 | // environment variables. 10 | func keysFromEnvironment() (keys *Keys, err error) { 11 | keys = &Keys{ 12 | AccessKey: os.Getenv("AWS_ACCESS_KEY"), 13 | SecretKey: os.Getenv("AWS_SECRET_KEY"), 14 | } 15 | 16 | if keys.AccessKey == "" { 17 | err = errors.New("AWS_ACCESS_KEY not found in environment") 18 | return 19 | } 20 | 21 | if keys.SecretKey == "" { 22 | err = errors.New("AWS_SECRET_KEY not found in environment") 23 | return 24 | } 25 | return 26 | } 27 | 28 | func NewClient(accessKey, secretKey string) (c Client) { 29 | keys := &Keys{ 30 | AccessKey: accessKey, 31 | SecretKey: secretKey, 32 | } 33 | c = Client{Keys: keys} 34 | return 35 | } 36 | 37 | func NewClientFromEnv() (c Client, err error) { 38 | keys, err := keysFromEnvironment() 39 | if err != nil { 40 | return 41 | } 42 | 43 | c = Client{Keys: keys} 44 | return 45 | } 46 | 47 | // Client is like http.Client, but signs all requests using Keys. 48 | type Client struct { 49 | Keys *Keys 50 | 51 | // The http client to make requests with. If nil, http.DefaultClient is used. 52 | Client *http.Client 53 | } 54 | 55 | // Client is like http.Client, but signs all requests using Keys. 56 | type Client struct { 57 | Keys *Keys 58 | 59 | // The http client to make requests with. If nil, http.DefaultClient is used. 60 | Client *http.Client 61 | } 62 | 63 | func (c *Client) client() *http.Client { 64 | if c.Client == nil { 65 | return http.DefaultClient 66 | } 67 | return c.Client 68 | } 69 | 70 | func (c *Client) Do(req *http.Request) (resp *http.Response, err error) { 71 | err = Sign(c.Keys, req) 72 | if err != nil { 73 | return nil, err 74 | } 75 | return c.client().Do(req) 76 | } 77 | 78 | func (c *Client) Get(url string) (resp *http.Response, err error) { 79 | req, err := http.NewRequest("GET", url, nil) 80 | if err != nil { 81 | return nil, err 82 | } 83 | return c.Do(req) 84 | } 85 | 86 | func (c *Client) Head(url string) (resp *http.Response, err error) { 87 | req, err := http.NewRequest("HEAD", url, nil) 88 | if err != nil { 89 | return nil, err 90 | } 91 | return c.Do(req) 92 | } 93 | 94 | func (c *Client) Post(url string, bodyType string, body io.Reader) (resp *http.Response, err error) { 95 | req, err := http.NewRequest("POST", url, body) 96 | if err != nil { 97 | return nil, err 98 | } 99 | req.Header.Set("Content-Type", bodyType) 100 | return c.Do(req) 101 | } 102 | 103 | func (c *Client) PostForm(url string, data url.Values) (resp *http.Response, err error) { 104 | return c.Post(url, "application/x-www-form-urlencoded", strings.NewReader(data.Encode())) 105 | } 106 | -------------------------------------------------------------------------------- /vendor/go/src/github.com/mitchellh/goamz/exp/mturk/mturk_test.go: -------------------------------------------------------------------------------- 1 | package mturk_test 2 | 3 | import ( 4 | "github.com/mitchellh/goamz/aws" 5 | "github.com/mitchellh/goamz/exp/mturk" 6 | "github.com/mitchellh/goamz/testutil" 7 | . "github.com/motain/gocheck" 8 | "net/url" 9 | "testing" 10 | ) 11 | 12 | func Test(t *testing.T) { 13 | TestingT(t) 14 | } 15 | 16 | var _ = Suite(&S{}) 17 | 18 | type S struct { 19 | mturk *mturk.MTurk 20 | } 21 | 22 | var testServer = testutil.NewHTTPServer() 23 | 24 | func (s *S) SetUpSuite(c *C) { 25 | testServer.Start() 26 | auth := aws.Auth{"abc", "123", ""} 27 | u, err := url.Parse(testServer.URL) 28 | if err != nil { 29 | panic(err.Error()) 30 | } 31 | 32 | s.mturk = &mturk.MTurk{ 33 | Auth: auth, 34 | URL: u, 35 | } 36 | } 37 | 38 | func (s *S) TearDownTest(c *C) { 39 | testServer.Flush() 40 | } 41 | 42 | func (s *S) TestCreateHIT(c *C) { 43 | testServer.Response(200, nil, BasicHitResponse) 44 | 45 | question := mturk.ExternalQuestion{ 46 | ExternalURL: "http://www.amazon.com", 47 | FrameHeight: 200, 48 | } 49 | reward := mturk.Price{ 50 | Amount: "0.01", 51 | CurrencyCode: "USD", 52 | } 53 | hit, err := s.mturk.CreateHIT("title", "description", question, reward, 1, 2, "key1,key2", 3, nil, "annotation") 54 | 55 | testServer.WaitRequest() 56 | 57 | c.Assert(err, IsNil) 58 | c.Assert(hit, NotNil) 59 | 60 | c.Assert(hit.HITId, Equals, "28J4IXKO2L927XKJTHO34OCDNASCDW") 61 | c.Assert(hit.HITTypeId, Equals, "2XZ7D1X3V0FKQVW7LU51S7PKKGFKDF") 62 | } 63 | 64 | func (s *S) TestSearchHITs(c *C) { 65 | testServer.Response(200, nil, SearchHITResponse) 66 | 67 | hitResult, err := s.mturk.SearchHITs() 68 | 69 | c.Assert(err, IsNil) 70 | c.Assert(hitResult, NotNil) 71 | 72 | c.Assert(hitResult.NumResults, Equals, uint(1)) 73 | c.Assert(hitResult.PageNumber, Equals, uint(1)) 74 | c.Assert(hitResult.TotalNumResults, Equals, uint(1)) 75 | 76 | c.Assert(len(hitResult.HITs), Equals, 1) 77 | c.Assert(hitResult.HITs[0].HITId, Equals, "2BU26DG67D1XTE823B3OQ2JF2XWF83") 78 | c.Assert(hitResult.HITs[0].HITTypeId, Equals, "22OWJ5OPB0YV6IGL5727KP9U38P5XR") 79 | c.Assert(hitResult.HITs[0].CreationTime, Equals, "2011-12-28T19:56:20Z") 80 | c.Assert(hitResult.HITs[0].Title, Equals, "test hit") 81 | c.Assert(hitResult.HITs[0].Description, Equals, "please disregard, testing only") 82 | c.Assert(hitResult.HITs[0].HITStatus, Equals, "Reviewable") 83 | c.Assert(hitResult.HITs[0].MaxAssignments, Equals, uint(1)) 84 | c.Assert(hitResult.HITs[0].Reward.Amount, Equals, "0.01") 85 | c.Assert(hitResult.HITs[0].Reward.CurrencyCode, Equals, "USD") 86 | c.Assert(hitResult.HITs[0].AutoApprovalDelayInSeconds, Equals, uint(2592000)) 87 | c.Assert(hitResult.HITs[0].AssignmentDurationInSeconds, Equals, uint(30)) 88 | c.Assert(hitResult.HITs[0].NumberOfAssignmentsPending, Equals, uint(0)) 89 | c.Assert(hitResult.HITs[0].NumberOfAssignmentsAvailable, Equals, uint(1)) 90 | c.Assert(hitResult.HITs[0].NumberOfAssignmentsCompleted, Equals, uint(0)) 91 | } 92 | -------------------------------------------------------------------------------- /vendor/go/src/github.com/fsouza/go-dockerclient/term/term.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 Docker authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the DOCKER-LICENSE file. 4 | 5 | package term 6 | 7 | import ( 8 | "errors" 9 | "os" 10 | "os/signal" 11 | "syscall" 12 | "unsafe" 13 | ) 14 | 15 | var ( 16 | ErrInvalidState = errors.New("Invalid terminal state") 17 | ) 18 | 19 | type State struct { 20 | termios Termios 21 | } 22 | 23 | type Winsize struct { 24 | Height uint16 25 | Width uint16 26 | x uint16 27 | y uint16 28 | } 29 | 30 | func GetWinsize(fd uintptr) (*Winsize, error) { 31 | ws := &Winsize{} 32 | _, _, err := syscall.Syscall(syscall.SYS_IOCTL, fd, uintptr(syscall.TIOCGWINSZ), uintptr(unsafe.Pointer(ws))) 33 | // Skipp errno = 0 34 | if err == 0 { 35 | return ws, nil 36 | } 37 | return ws, err 38 | } 39 | 40 | func SetWinsize(fd uintptr, ws *Winsize) error { 41 | _, _, err := syscall.Syscall(syscall.SYS_IOCTL, fd, uintptr(syscall.TIOCSWINSZ), uintptr(unsafe.Pointer(ws))) 42 | // Skipp errno = 0 43 | if err == 0 { 44 | return nil 45 | } 46 | return err 47 | } 48 | 49 | // IsTerminal returns true if the given file descriptor is a terminal. 50 | func IsTerminal(fd uintptr) bool { 51 | var termios Termios 52 | _, _, err := syscall.Syscall(syscall.SYS_IOCTL, fd, uintptr(getTermios), uintptr(unsafe.Pointer(&termios))) 53 | return err == 0 54 | } 55 | 56 | // Restore restores the terminal connected to the given file descriptor to a 57 | // previous state. 58 | func RestoreTerminal(fd uintptr, state *State) error { 59 | if state == nil { 60 | return ErrInvalidState 61 | } 62 | _, _, err := syscall.Syscall(syscall.SYS_IOCTL, fd, uintptr(setTermios), uintptr(unsafe.Pointer(&state.termios))) 63 | if err != 0 { 64 | return err 65 | } 66 | return nil 67 | } 68 | 69 | func SaveState(fd uintptr) (*State, error) { 70 | var oldState State 71 | if _, _, err := syscall.Syscall(syscall.SYS_IOCTL, fd, getTermios, uintptr(unsafe.Pointer(&oldState.termios))); err != 0 { 72 | return nil, err 73 | } 74 | 75 | return &oldState, nil 76 | } 77 | 78 | func DisableEcho(fd uintptr, state *State) error { 79 | newState := state.termios 80 | newState.Lflag &^= syscall.ECHO 81 | 82 | if _, _, err := syscall.Syscall(syscall.SYS_IOCTL, fd, setTermios, uintptr(unsafe.Pointer(&newState))); err != 0 { 83 | return err 84 | } 85 | handleInterrupt(fd, state) 86 | return nil 87 | } 88 | 89 | func SetRawTerminal(fd uintptr) (*State, error) { 90 | oldState, err := MakeRaw(fd) 91 | if err != nil { 92 | return nil, err 93 | } 94 | handleInterrupt(fd, oldState) 95 | return oldState, err 96 | } 97 | 98 | func handleInterrupt(fd uintptr, state *State) { 99 | sigchan := make(chan os.Signal, 1) 100 | signal.Notify(sigchan, os.Interrupt) 101 | 102 | go func() { 103 | _ = <-sigchan 104 | RestoreTerminal(fd, state) 105 | os.Exit(0) 106 | }() 107 | } 108 | -------------------------------------------------------------------------------- /vendor/go/src/github.com/mitchellh/goamz/aws/client_test.go: -------------------------------------------------------------------------------- 1 | package aws_test 2 | 3 | import ( 4 | "fmt" 5 | "github.com/mitchellh/goamz/aws" 6 | "io/ioutil" 7 | "net/http" 8 | "net/http/httptest" 9 | "strings" 10 | "testing" 11 | "time" 12 | ) 13 | 14 | // Retrieve the response from handler using aws.RetryingClient 15 | func serveAndGet(handler http.HandlerFunc) (body string, err error) { 16 | ts := httptest.NewServer(handler) 17 | defer ts.Close() 18 | resp, err := aws.RetryingClient.Get(ts.URL) 19 | if err != nil { 20 | return 21 | } 22 | if resp.StatusCode != 200 { 23 | return "", fmt.Errorf("Bad status code: %d", resp.StatusCode) 24 | } 25 | greeting, err := ioutil.ReadAll(resp.Body) 26 | resp.Body.Close() 27 | if err != nil { 28 | return 29 | } 30 | return strings.TrimSpace(string(greeting)), nil 31 | } 32 | 33 | func TestClient_expected(t *testing.T) { 34 | body := "foo bar" 35 | 36 | resp, err := serveAndGet(func(w http.ResponseWriter, r *http.Request) { 37 | fmt.Fprintln(w, body) 38 | }) 39 | if err != nil { 40 | t.Fatal(err) 41 | } 42 | if resp != body { 43 | t.Fatal("Body not as expected.") 44 | } 45 | } 46 | 47 | func TestClient_delay(t *testing.T) { 48 | body := "baz" 49 | wait := 4 50 | resp, err := serveAndGet(func(w http.ResponseWriter, r *http.Request) { 51 | if wait < 0 { 52 | // If we dipped to zero delay and still failed. 53 | t.Fatal("Never succeeded.") 54 | } 55 | wait -= 1 56 | time.Sleep(time.Second * time.Duration(wait)) 57 | fmt.Fprintln(w, body) 58 | }) 59 | if err != nil { 60 | t.Fatal(err) 61 | } 62 | if resp != body { 63 | t.Fatal("Body not as expected.", resp) 64 | } 65 | } 66 | 67 | func TestClient_no4xxRetry(t *testing.T) { 68 | tries := 0 69 | 70 | // Fail once before succeeding. 71 | _, err := serveAndGet(func(w http.ResponseWriter, r *http.Request) { 72 | tries += 1 73 | http.Error(w, "error", 404) 74 | }) 75 | 76 | if err == nil { 77 | t.Fatal("should have error") 78 | } 79 | 80 | if tries != 1 { 81 | t.Fatalf("should only try once: %d", tries) 82 | } 83 | } 84 | 85 | func TestClient_retries(t *testing.T) { 86 | body := "biz" 87 | failed := false 88 | // Fail once before succeeding. 89 | resp, err := serveAndGet(func(w http.ResponseWriter, r *http.Request) { 90 | if !failed { 91 | http.Error(w, "error", 500) 92 | failed = true 93 | } else { 94 | fmt.Fprintln(w, body) 95 | } 96 | }) 97 | if failed != true { 98 | t.Error("We didn't retry!") 99 | } 100 | if err != nil { 101 | t.Fatal(err) 102 | } 103 | if resp != body { 104 | t.Fatal("Body not as expected.") 105 | } 106 | } 107 | 108 | func TestClient_fails(t *testing.T) { 109 | tries := 0 110 | // Fail 3 times and return the last error. 111 | _, err := serveAndGet(func(w http.ResponseWriter, r *http.Request) { 112 | tries += 1 113 | http.Error(w, "error", 500) 114 | }) 115 | if err == nil { 116 | t.Fatal(err) 117 | } 118 | if tries != 3 { 119 | t.Fatal("Didn't retry enough") 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /vendor/go/src/github.com/fsouza/go-dockerclient/engine/engine_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 Docker authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the DOCKER-LICENSE file. 4 | 5 | package engine 6 | 7 | import ( 8 | "io/ioutil" 9 | "os" 10 | "path" 11 | "path/filepath" 12 | "testing" 13 | ) 14 | 15 | func TestRegister(t *testing.T) { 16 | if err := Register("dummy1", nil); err != nil { 17 | t.Fatal(err) 18 | } 19 | 20 | if err := Register("dummy1", nil); err == nil { 21 | t.Fatalf("Expecting error, got none") 22 | } 23 | 24 | eng := newTestEngine(t) 25 | 26 | //Should fail because global handlers are copied 27 | //at the engine creation 28 | if err := eng.Register("dummy1", nil); err == nil { 29 | t.Fatalf("Expecting error, got none") 30 | } 31 | 32 | if err := eng.Register("dummy2", nil); err != nil { 33 | t.Fatal(err) 34 | } 35 | 36 | if err := eng.Register("dummy2", nil); err == nil { 37 | t.Fatalf("Expecting error, got none") 38 | } 39 | } 40 | 41 | func TestJob(t *testing.T) { 42 | eng := newTestEngine(t) 43 | job1 := eng.Job("dummy1", "--level=awesome") 44 | 45 | if job1.handler != nil { 46 | t.Fatalf("job1.handler should be empty") 47 | } 48 | 49 | h := func(j *Job) Status { 50 | j.Printf("%s\n", j.Name) 51 | return 42 52 | } 53 | 54 | eng.Register("dummy2", h) 55 | job2 := eng.Job("dummy2", "--level=awesome") 56 | 57 | if job2.handler == nil { 58 | t.Fatalf("job2.handler shouldn't be nil") 59 | } 60 | 61 | if job2.handler(job2) != 42 { 62 | t.Fatalf("handler dummy2 was not found in job2") 63 | } 64 | } 65 | 66 | func TestEngineRoot(t *testing.T) { 67 | tmp, err := ioutil.TempDir("", "docker-test-TestEngineCreateDir") 68 | if err != nil { 69 | t.Fatal(err) 70 | } 71 | defer os.RemoveAll(tmp) 72 | dir := path.Join(tmp, "dir") 73 | eng, err := New(dir) 74 | if err != nil { 75 | t.Fatal(err) 76 | } 77 | if st, err := os.Stat(dir); err != nil { 78 | t.Fatal(err) 79 | } else if !st.IsDir() { 80 | t.Fatalf("engine.New() created something other than a directory at %s", dir) 81 | } 82 | r := eng.Root() 83 | r, _ = filepath.EvalSymlinks(r) 84 | dir, _ = filepath.EvalSymlinks(dir) 85 | if r != dir { 86 | t.Fatalf("Expected: %v\nReceived: %v", dir, r) 87 | } 88 | } 89 | 90 | func TestEngineString(t *testing.T) { 91 | eng1 := newTestEngine(t) 92 | defer os.RemoveAll(eng1.Root()) 93 | eng2 := newTestEngine(t) 94 | defer os.RemoveAll(eng2.Root()) 95 | s1 := eng1.String() 96 | s2 := eng2.String() 97 | if eng1 == eng2 { 98 | t.Fatalf("Different engines should have different names (%v == %v)", s1, s2) 99 | } 100 | } 101 | 102 | func TestEngineLogf(t *testing.T) { 103 | eng := newTestEngine(t) 104 | defer os.RemoveAll(eng.Root()) 105 | input := "Test log line" 106 | if n, err := eng.Logf("%s\n", input); err != nil { 107 | t.Fatal(err) 108 | } else if n < len(input) { 109 | t.Fatalf("Test: Logf() should print at least as much as the input\ninput=%d\nprinted=%d", len(input), n) 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /vendor/go/src/code.google.com/p/gcfg/example_test.go: -------------------------------------------------------------------------------- 1 | package gcfg_test 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | ) 7 | 8 | import "code.google.com/p/gcfg" 9 | 10 | func ExampleReadStringInto() { 11 | cfgStr := `; Comment line 12 | [section] 13 | name=value # comment` 14 | cfg := struct { 15 | Section struct { 16 | Name string 17 | } 18 | }{} 19 | err := gcfg.ReadStringInto(&cfg, cfgStr) 20 | if err != nil { 21 | log.Fatalf("Failed to parse gcfg data: %s", err) 22 | } 23 | fmt.Println(cfg.Section.Name) 24 | // Output: value 25 | } 26 | 27 | func ExampleReadStringInto_bool() { 28 | cfgStr := `; Comment line 29 | [section] 30 | switch=on` 31 | cfg := struct { 32 | Section struct { 33 | Switch bool 34 | } 35 | }{} 36 | err := gcfg.ReadStringInto(&cfg, cfgStr) 37 | if err != nil { 38 | log.Fatalf("Failed to parse gcfg data: %s", err) 39 | } 40 | fmt.Println(cfg.Section.Switch) 41 | // Output: true 42 | } 43 | 44 | func ExampleReadStringInto_hyphens() { 45 | cfgStr := `; Comment line 46 | [section-name] 47 | variable-name=value # comment` 48 | cfg := struct { 49 | Section_Name struct { 50 | Variable_Name string 51 | } 52 | }{} 53 | err := gcfg.ReadStringInto(&cfg, cfgStr) 54 | if err != nil { 55 | log.Fatalf("Failed to parse gcfg data: %s", err) 56 | } 57 | fmt.Println(cfg.Section_Name.Variable_Name) 58 | // Output: value 59 | } 60 | 61 | func ExampleReadStringInto_tags() { 62 | cfgStr := `; Comment line 63 | [section] 64 | var-name=value # comment` 65 | cfg := struct { 66 | Section struct { 67 | FieldName string `gcfg:"var-name"` 68 | } 69 | }{} 70 | err := gcfg.ReadStringInto(&cfg, cfgStr) 71 | if err != nil { 72 | log.Fatalf("Failed to parse gcfg data: %s", err) 73 | } 74 | fmt.Println(cfg.Section.FieldName) 75 | // Output: value 76 | } 77 | 78 | func ExampleReadStringInto_subsections() { 79 | cfgStr := `; Comment line 80 | [profile "A"] 81 | color = white 82 | 83 | [profile "B"] 84 | color = black 85 | ` 86 | cfg := struct { 87 | Profile map[string]*struct { 88 | Color string 89 | } 90 | }{} 91 | err := gcfg.ReadStringInto(&cfg, cfgStr) 92 | if err != nil { 93 | log.Fatalf("Failed to parse gcfg data: %s", err) 94 | } 95 | fmt.Printf("%s %s\n", cfg.Profile["A"].Color, cfg.Profile["B"].Color) 96 | // Output: white black 97 | } 98 | 99 | func ExampleReadStringInto_multivalue() { 100 | cfgStr := `; Comment line 101 | [section] 102 | multi=value1 103 | multi=value2` 104 | cfg := struct { 105 | Section struct { 106 | Multi []string 107 | } 108 | }{} 109 | err := gcfg.ReadStringInto(&cfg, cfgStr) 110 | if err != nil { 111 | log.Fatalf("Failed to parse gcfg data: %s", err) 112 | } 113 | fmt.Println(cfg.Section.Multi) 114 | // Output: [value1 value2] 115 | } 116 | 117 | func ExampleReadStringInto_unicode() { 118 | cfgStr := `; Comment line 119 | [甲] 120 | 乙=丙 # comment` 121 | cfg := struct { 122 | X甲 struct { 123 | X乙 string 124 | } 125 | }{} 126 | err := gcfg.ReadStringInto(&cfg, cfgStr) 127 | if err != nil { 128 | log.Fatalf("Failed to parse gcfg data: %s", err) 129 | } 130 | fmt.Println(cfg.X甲.X乙) 131 | // Output: 丙 132 | } 133 | -------------------------------------------------------------------------------- /vendor/go/src/code.google.com/p/gcfg/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012 Péter Surányi. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are 5 | met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above 10 | copyright notice, this list of conditions and the following disclaimer 11 | in the documentation and/or other materials provided with the 12 | distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 15 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 16 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 17 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 18 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 19 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 20 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 24 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | 26 | ---------------------------------------------------------------------- 27 | Portions of gcfg's source code have been derived from Go, and are 28 | covered by the following license: 29 | ---------------------------------------------------------------------- 30 | 31 | Copyright (c) 2009 The Go Authors. All rights reserved. 32 | 33 | Redistribution and use in source and binary forms, with or without 34 | modification, are permitted provided that the following conditions are 35 | met: 36 | 37 | * Redistributions of source code must retain the above copyright 38 | notice, this list of conditions and the following disclaimer. 39 | * Redistributions in binary form must reproduce the above 40 | copyright notice, this list of conditions and the following disclaimer 41 | in the documentation and/or other materials provided with the 42 | distribution. 43 | * Neither the name of Google Inc. nor the names of its 44 | contributors may be used to endorse or promote products derived from 45 | this software without specific prior written permission. 46 | 47 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 48 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 49 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 50 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 51 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 52 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 53 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 54 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 55 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 56 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 57 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 58 | -------------------------------------------------------------------------------- /vendor/go/src/code.google.com/p/gcfg/token/serialize_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package token 6 | 7 | import ( 8 | "bytes" 9 | "encoding/gob" 10 | "fmt" 11 | "testing" 12 | ) 13 | 14 | // equal returns nil if p and q describe the same file set; 15 | // otherwise it returns an error describing the discrepancy. 16 | func equal(p, q *FileSet) error { 17 | if p == q { 18 | // avoid deadlock if p == q 19 | return nil 20 | } 21 | 22 | // not strictly needed for the test 23 | p.mutex.Lock() 24 | q.mutex.Lock() 25 | defer q.mutex.Unlock() 26 | defer p.mutex.Unlock() 27 | 28 | if p.base != q.base { 29 | return fmt.Errorf("different bases: %d != %d", p.base, q.base) 30 | } 31 | 32 | if len(p.files) != len(q.files) { 33 | return fmt.Errorf("different number of files: %d != %d", len(p.files), len(q.files)) 34 | } 35 | 36 | for i, f := range p.files { 37 | g := q.files[i] 38 | if f.set != p { 39 | return fmt.Errorf("wrong fileset for %q", f.name) 40 | } 41 | if g.set != q { 42 | return fmt.Errorf("wrong fileset for %q", g.name) 43 | } 44 | if f.name != g.name { 45 | return fmt.Errorf("different filenames: %q != %q", f.name, g.name) 46 | } 47 | if f.base != g.base { 48 | return fmt.Errorf("different base for %q: %d != %d", f.name, f.base, g.base) 49 | } 50 | if f.size != g.size { 51 | return fmt.Errorf("different size for %q: %d != %d", f.name, f.size, g.size) 52 | } 53 | for j, l := range f.lines { 54 | m := g.lines[j] 55 | if l != m { 56 | return fmt.Errorf("different offsets for %q", f.name) 57 | } 58 | } 59 | for j, l := range f.infos { 60 | m := g.infos[j] 61 | if l.Offset != m.Offset || l.Filename != m.Filename || l.Line != m.Line { 62 | return fmt.Errorf("different infos for %q", f.name) 63 | } 64 | } 65 | } 66 | 67 | // we don't care about .last - it's just a cache 68 | return nil 69 | } 70 | 71 | func checkSerialize(t *testing.T, p *FileSet) { 72 | var buf bytes.Buffer 73 | encode := func(x interface{}) error { 74 | return gob.NewEncoder(&buf).Encode(x) 75 | } 76 | if err := p.Write(encode); err != nil { 77 | t.Errorf("writing fileset failed: %s", err) 78 | return 79 | } 80 | q := NewFileSet() 81 | decode := func(x interface{}) error { 82 | return gob.NewDecoder(&buf).Decode(x) 83 | } 84 | if err := q.Read(decode); err != nil { 85 | t.Errorf("reading fileset failed: %s", err) 86 | return 87 | } 88 | if err := equal(p, q); err != nil { 89 | t.Errorf("filesets not identical: %s", err) 90 | } 91 | } 92 | 93 | func TestSerialization(t *testing.T) { 94 | p := NewFileSet() 95 | checkSerialize(t, p) 96 | // add some files 97 | for i := 0; i < 10; i++ { 98 | f := p.AddFile(fmt.Sprintf("file%d", i), p.Base()+i, i*100) 99 | checkSerialize(t, p) 100 | // add some lines and alternative file infos 101 | line := 1000 102 | for offs := 0; offs < f.Size(); offs += 40 + i { 103 | f.AddLine(offs) 104 | if offs%7 == 0 { 105 | f.AddLineInfo(offs, fmt.Sprintf("file%d", offs), line) 106 | line += 33 107 | } 108 | } 109 | checkSerialize(t, p) 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /vendor/go/src/code.google.com/p/gcfg/scanner/errors.go: -------------------------------------------------------------------------------- 1 | // Copyright 2009 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package scanner 6 | 7 | import ( 8 | "fmt" 9 | "io" 10 | "sort" 11 | ) 12 | 13 | import ( 14 | "code.google.com/p/gcfg/token" 15 | ) 16 | 17 | // In an ErrorList, an error is represented by an *Error. 18 | // The position Pos, if valid, points to the beginning of 19 | // the offending token, and the error condition is described 20 | // by Msg. 21 | // 22 | type Error struct { 23 | Pos token.Position 24 | Msg string 25 | } 26 | 27 | // Error implements the error interface. 28 | func (e Error) Error() string { 29 | if e.Pos.Filename != "" || e.Pos.IsValid() { 30 | // don't print "" 31 | // TODO(gri) reconsider the semantics of Position.IsValid 32 | return e.Pos.String() + ": " + e.Msg 33 | } 34 | return e.Msg 35 | } 36 | 37 | // ErrorList is a list of *Errors. 38 | // The zero value for an ErrorList is an empty ErrorList ready to use. 39 | // 40 | type ErrorList []*Error 41 | 42 | // Add adds an Error with given position and error message to an ErrorList. 43 | func (p *ErrorList) Add(pos token.Position, msg string) { 44 | *p = append(*p, &Error{pos, msg}) 45 | } 46 | 47 | // Reset resets an ErrorList to no errors. 48 | func (p *ErrorList) Reset() { *p = (*p)[0:0] } 49 | 50 | // ErrorList implements the sort Interface. 51 | func (p ErrorList) Len() int { return len(p) } 52 | func (p ErrorList) Swap(i, j int) { p[i], p[j] = p[j], p[i] } 53 | 54 | func (p ErrorList) Less(i, j int) bool { 55 | e := &p[i].Pos 56 | f := &p[j].Pos 57 | if e.Filename < f.Filename { 58 | return true 59 | } 60 | if e.Filename == f.Filename { 61 | return e.Offset < f.Offset 62 | } 63 | return false 64 | } 65 | 66 | // Sort sorts an ErrorList. *Error entries are sorted by position, 67 | // other errors are sorted by error message, and before any *Error 68 | // entry. 69 | // 70 | func (p ErrorList) Sort() { 71 | sort.Sort(p) 72 | } 73 | 74 | // RemoveMultiples sorts an ErrorList and removes all but the first error per line. 75 | func (p *ErrorList) RemoveMultiples() { 76 | sort.Sort(p) 77 | var last token.Position // initial last.Line is != any legal error line 78 | i := 0 79 | for _, e := range *p { 80 | if e.Pos.Filename != last.Filename || e.Pos.Line != last.Line { 81 | last = e.Pos 82 | (*p)[i] = e 83 | i++ 84 | } 85 | } 86 | (*p) = (*p)[0:i] 87 | } 88 | 89 | // An ErrorList implements the error interface. 90 | func (p ErrorList) Error() string { 91 | switch len(p) { 92 | case 0: 93 | return "no errors" 94 | case 1: 95 | return p[0].Error() 96 | } 97 | return fmt.Sprintf("%s (and %d more errors)", p[0], len(p)-1) 98 | } 99 | 100 | // Err returns an error equivalent to this error list. 101 | // If the list is empty, Err returns nil. 102 | func (p ErrorList) Err() error { 103 | if len(p) == 0 { 104 | return nil 105 | } 106 | return p 107 | } 108 | 109 | // PrintError is a utility function that prints a list of errors to w, 110 | // one error per line, if the err parameter is an ErrorList. Otherwise 111 | // it prints the err string. 112 | // 113 | func PrintError(w io.Writer, err error) { 114 | if list, ok := err.(ErrorList); ok { 115 | for _, e := range list { 116 | fmt.Fprintf(w, "%s\n", e) 117 | } 118 | } else if err != nil { 119 | fmt.Fprintf(w, "%s\n", err) 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /vendor/go/src/github.com/mitchellh/goamz/s3/sign.go: -------------------------------------------------------------------------------- 1 | package s3 2 | 3 | import ( 4 | "crypto/hmac" 5 | "crypto/sha1" 6 | "encoding/base64" 7 | "github.com/mitchellh/goamz/aws" 8 | "log" 9 | "sort" 10 | "strings" 11 | ) 12 | 13 | var b64 = base64.StdEncoding 14 | 15 | // ---------------------------------------------------------------------------- 16 | // S3 signing (http://goo.gl/G1LrK) 17 | 18 | var s3ParamsToSign = map[string]bool{ 19 | "acl": true, 20 | "location": true, 21 | "logging": true, 22 | "notification": true, 23 | "partNumber": true, 24 | "policy": true, 25 | "requestPayment": true, 26 | "torrent": true, 27 | "uploadId": true, 28 | "uploads": true, 29 | "versionId": true, 30 | "versioning": true, 31 | "versions": true, 32 | "response-content-type": true, 33 | "response-content-language": true, 34 | "response-expires": true, 35 | "response-cache-control": true, 36 | "response-content-disposition": true, 37 | "response-content-encoding": true, 38 | } 39 | 40 | func sign(auth aws.Auth, method, canonicalPath string, params, headers map[string][]string) { 41 | var md5, ctype, date, xamz string 42 | var xamzDate bool 43 | var sarray []string 44 | 45 | // add security token 46 | if auth.Token != "" { 47 | headers["x-amz-security-token"] = []string{auth.Token} 48 | } 49 | 50 | for k, v := range headers { 51 | k = strings.ToLower(k) 52 | switch k { 53 | case "content-md5": 54 | md5 = v[0] 55 | case "content-type": 56 | ctype = v[0] 57 | case "date": 58 | if !xamzDate { 59 | date = v[0] 60 | } 61 | default: 62 | if strings.HasPrefix(k, "x-amz-") { 63 | vall := strings.Join(v, ",") 64 | sarray = append(sarray, k+":"+vall) 65 | if k == "x-amz-date" { 66 | xamzDate = true 67 | date = "" 68 | } 69 | } 70 | } 71 | } 72 | if len(sarray) > 0 { 73 | sort.StringSlice(sarray).Sort() 74 | xamz = strings.Join(sarray, "\n") + "\n" 75 | } 76 | 77 | expires := false 78 | if v, ok := params["Expires"]; ok { 79 | // Query string request authentication alternative. 80 | expires = true 81 | date = v[0] 82 | params["AWSAccessKeyId"] = []string{auth.AccessKey} 83 | } 84 | 85 | sarray = sarray[0:0] 86 | for k, v := range params { 87 | if s3ParamsToSign[k] { 88 | for _, vi := range v { 89 | if vi == "" { 90 | sarray = append(sarray, k) 91 | } else { 92 | // "When signing you do not encode these values." 93 | sarray = append(sarray, k+"="+vi) 94 | } 95 | } 96 | } 97 | } 98 | if len(sarray) > 0 { 99 | sort.StringSlice(sarray).Sort() 100 | canonicalPath = canonicalPath + "?" + strings.Join(sarray, "&") 101 | } 102 | 103 | payload := method + "\n" + md5 + "\n" + ctype + "\n" + date + "\n" + xamz + canonicalPath 104 | hash := hmac.New(sha1.New, []byte(auth.SecretKey)) 105 | hash.Write([]byte(payload)) 106 | signature := make([]byte, b64.EncodedLen(hash.Size())) 107 | b64.Encode(signature, hash.Sum(nil)) 108 | 109 | if expires { 110 | params["Signature"] = []string{string(signature)} 111 | } else { 112 | headers["Authorization"] = []string{"AWS " + auth.AccessKey + ":" + string(signature)} 113 | } 114 | if debug { 115 | log.Printf("Signature payload: %q", payload) 116 | log.Printf("Signature: %q", signature) 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /vendor/go/src/github.com/mitchellh/goamz/aws/client.go: -------------------------------------------------------------------------------- 1 | package aws 2 | 3 | import ( 4 | "math" 5 | "net" 6 | "net/http" 7 | "time" 8 | ) 9 | 10 | type RetryableFunc func(*http.Request, *http.Response, error) bool 11 | type WaitFunc func(try int) 12 | type DeadlineFunc func() time.Time 13 | 14 | type ResilientTransport struct { 15 | // Timeout is the maximum amount of time a dial will wait for 16 | // a connect to complete. 17 | // 18 | // The default is no timeout. 19 | // 20 | // With or without a timeout, the operating system may impose 21 | // its own earlier timeout. For instance, TCP timeouts are 22 | // often around 3 minutes. 23 | DialTimeout time.Duration 24 | 25 | // MaxTries, if non-zero, specifies the number of times we will retry on 26 | // failure. Retries are only attempted for temporary network errors or known 27 | // safe failures. 28 | MaxTries int 29 | Deadline DeadlineFunc 30 | ShouldRetry RetryableFunc 31 | Wait WaitFunc 32 | transport *http.Transport 33 | } 34 | 35 | // Convenience method for creating an http client 36 | func NewClient(rt *ResilientTransport) *http.Client { 37 | rt.transport = &http.Transport{ 38 | Dial: func(netw, addr string) (net.Conn, error) { 39 | c, err := net.DialTimeout(netw, addr, rt.DialTimeout) 40 | if err != nil { 41 | return nil, err 42 | } 43 | c.SetDeadline(rt.Deadline()) 44 | return c, nil 45 | }, 46 | Proxy: http.ProxyFromEnvironment, 47 | } 48 | // TODO: Would be nice is ResilientTransport allowed clients to initialize 49 | // with http.Transport attributes. 50 | return &http.Client{ 51 | Transport: rt, 52 | } 53 | } 54 | 55 | var retryingTransport = &ResilientTransport{ 56 | Deadline: func() time.Time { 57 | return time.Now().Add(5 * time.Second) 58 | }, 59 | DialTimeout: 10 * time.Second, 60 | MaxTries: 3, 61 | ShouldRetry: awsRetry, 62 | Wait: ExpBackoff, 63 | } 64 | 65 | // Exported default client 66 | var RetryingClient = NewClient(retryingTransport) 67 | 68 | func (t *ResilientTransport) RoundTrip(req *http.Request) (*http.Response, error) { 69 | return t.tries(req) 70 | } 71 | 72 | // Retry a request a maximum of t.MaxTries times. 73 | // We'll only retry if the proper criteria are met. 74 | // If a wait function is specified, wait that amount of time 75 | // In between requests. 76 | func (t *ResilientTransport) tries(req *http.Request) (res *http.Response, err error) { 77 | for try := 0; try < t.MaxTries; try += 1 { 78 | res, err = t.transport.RoundTrip(req) 79 | 80 | if !t.ShouldRetry(req, res, err) { 81 | break 82 | } 83 | if res != nil { 84 | res.Body.Close() 85 | } 86 | if t.Wait != nil { 87 | t.Wait(try) 88 | } 89 | } 90 | 91 | return 92 | } 93 | 94 | func ExpBackoff(try int) { 95 | time.Sleep(100 * time.Millisecond * 96 | time.Duration(math.Exp2(float64(try)))) 97 | } 98 | 99 | func LinearBackoff(try int) { 100 | time.Sleep(time.Duration(try*100) * time.Millisecond) 101 | } 102 | 103 | // Decide if we should retry a request. 104 | // In general, the criteria for retrying a request is described here 105 | // http://docs.aws.amazon.com/general/latest/gr/api-retries.html 106 | func awsRetry(req *http.Request, res *http.Response, err error) bool { 107 | retry := false 108 | 109 | // Retry if there's a temporary network error. 110 | if neterr, ok := err.(net.Error); ok { 111 | if neterr.Temporary() { 112 | retry = true 113 | } 114 | } 115 | 116 | // Retry if we get a 5xx series error. 117 | if res != nil { 118 | if res.StatusCode >= 500 && res.StatusCode < 600 { 119 | retry = true 120 | } 121 | } 122 | 123 | return retry 124 | } 125 | -------------------------------------------------------------------------------- /remote/local.go: -------------------------------------------------------------------------------- 1 | package remote 2 | 3 | import ( 4 | docker "github.com/fsouza/go-dockerclient" 5 | 6 | "encoding/json" 7 | "fmt" 8 | "io/ioutil" 9 | "log" 10 | "net/url" 11 | "os" 12 | "os/exec" 13 | "path/filepath" 14 | "strings" 15 | ) 16 | 17 | type LocalRemote struct { 18 | config RemoteConfig 19 | Url url.URL 20 | Path string 21 | } 22 | 23 | func NewLocalRemote(config RemoteConfig) (*LocalRemote, error) { 24 | // TODO validate 25 | 26 | return &LocalRemote{ 27 | config: config, 28 | Url: config.Url, 29 | Path: config.Url.Path, 30 | }, nil 31 | } 32 | 33 | func (remote *LocalRemote) Validate() error { 34 | return nil 35 | } 36 | 37 | func (remote *LocalRemote) Desc() string { 38 | return fmt.Sprintf("local(%s)", remote.Path) 39 | } 40 | 41 | // push all of imageRoot to the remote 42 | func (remote *LocalRemote) Push(image, imageRoot string) error { 43 | log.Println("pushing local", remote.Url.Path) 44 | 45 | return remote.rsyncTo(imageRoot, "") 46 | } 47 | 48 | // pull image with id into dst 49 | func (remote *LocalRemote) PullImageId(id ID, dst string) error { 50 | log.Println("pulling local", "images/"+id, "->", dst) 51 | 52 | return remote.rsyncFrom("images/"+string(id), dst) 53 | } 54 | 55 | func (remote *LocalRemote) ImageFullId(id ID) (ID, error) { 56 | // look for an image 57 | imagesRoot := filepath.Join(filepath.Clean(remote.Url.Path), "images") 58 | file, err := os.Open(imagesRoot) 59 | if err != nil { 60 | return "", err 61 | } 62 | 63 | names, err := file.Readdirnames(-1) 64 | if err != nil { 65 | return "", err 66 | } 67 | 68 | for _, name := range names { 69 | if strings.HasPrefix(name, string(id)) { 70 | return ID(name), nil 71 | } 72 | } 73 | 74 | return "", ErrNoSuchImage 75 | } 76 | 77 | func (remote *LocalRemote) WalkImages(id ID, walker ImageWalkFn) error { 78 | return WalkImages(remote, id, walker) 79 | } 80 | 81 | func (remote *LocalRemote) ResolveImageNameToId(image string) (ID, error) { 82 | return ResolveImageNameToId(remote, image) 83 | } 84 | 85 | func (remote *LocalRemote) ParseTag(repo, tag string) (ID, error) { 86 | repoPath := filepath.Join(filepath.Clean(remote.Url.Path), "repositories", repo, tag) 87 | 88 | if id, err := ioutil.ReadFile(repoPath); err == nil { 89 | return ID(id), nil 90 | } else if os.IsNotExist(err) { 91 | return "", nil 92 | } else { 93 | return "", err 94 | } 95 | } 96 | 97 | func (remote *LocalRemote) ImageMetadata(id ID) (docker.Image, error) { 98 | image := docker.Image{} 99 | 100 | imageJson, err := ioutil.ReadFile(filepath.Join(remote.imagePath(id), "json")) 101 | if os.IsNotExist(err) { 102 | return image, ErrNoSuchImage 103 | } else if err != nil { 104 | return image, err 105 | } 106 | 107 | if err := json.Unmarshal(imageJson, &image); err != nil { 108 | return image, err 109 | } 110 | 111 | return image, nil 112 | } 113 | 114 | func (remote *LocalRemote) rsyncTo(src, dst string) error { 115 | return remote.rsync(src+"/", remote.RemotePath(dst)+"/") 116 | } 117 | 118 | func (remote *LocalRemote) rsyncFrom(src, dst string) error { 119 | return remote.rsync(remote.RemotePath(src)+"/", dst+"/") 120 | } 121 | 122 | func (remote *LocalRemote) rsync(src, dst string) error { 123 | out, err := exec.Command("rsync", "-av", src, dst).CombinedOutput() 124 | if err != nil { 125 | return fmt.Errorf("rsync failed: %s\noutput: %s", err, string(out)) 126 | } 127 | log.Println(string(out)) 128 | 129 | return nil 130 | } 131 | 132 | func (remote *LocalRemote) imagePath(id ID) string { 133 | return remote.RemotePath("images", string(id)) 134 | } 135 | 136 | func (remote *LocalRemote) RemotePath(part ...string) string { 137 | return filepath.Join(remote.Path, filepath.Join(part...)) 138 | } 139 | -------------------------------------------------------------------------------- /vendor/go/src/github.com/fsouza/go-dockerclient/engine/env_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 Docker authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the DOCKER-LICENSE file. 4 | 5 | package engine 6 | 7 | import ( 8 | "testing" 9 | ) 10 | 11 | func TestNewJob(t *testing.T) { 12 | job := mkJob(t, "dummy", "--level=awesome") 13 | if job.Name != "dummy" { 14 | t.Fatalf("Wrong job name: %s", job.Name) 15 | } 16 | if len(job.Args) != 1 { 17 | t.Fatalf("Wrong number of job arguments: %d", len(job.Args)) 18 | } 19 | if job.Args[0] != "--level=awesome" { 20 | t.Fatalf("Wrong job arguments: %s", job.Args[0]) 21 | } 22 | } 23 | 24 | func TestSetenv(t *testing.T) { 25 | job := mkJob(t, "dummy") 26 | job.Setenv("foo", "bar") 27 | if val := job.Getenv("foo"); val != "bar" { 28 | t.Fatalf("Getenv returns incorrect value: %s", val) 29 | } 30 | 31 | job.Setenv("bar", "") 32 | if val := job.Getenv("bar"); val != "" { 33 | t.Fatalf("Getenv returns incorrect value: %s", val) 34 | } 35 | if val := job.Getenv("nonexistent"); val != "" { 36 | t.Fatalf("Getenv returns incorrect value: %s", val) 37 | } 38 | } 39 | 40 | func TestSetenvBool(t *testing.T) { 41 | job := mkJob(t, "dummy") 42 | job.SetenvBool("foo", true) 43 | if val := job.GetenvBool("foo"); !val { 44 | t.Fatalf("GetenvBool returns incorrect value: %t", val) 45 | } 46 | 47 | job.SetenvBool("bar", false) 48 | if val := job.GetenvBool("bar"); val { 49 | t.Fatalf("GetenvBool returns incorrect value: %t", val) 50 | } 51 | 52 | if val := job.GetenvBool("nonexistent"); val { 53 | t.Fatalf("GetenvBool returns incorrect value: %t", val) 54 | } 55 | } 56 | 57 | func TestSetenvInt(t *testing.T) { 58 | job := mkJob(t, "dummy") 59 | 60 | job.SetenvInt("foo", -42) 61 | if val := job.GetenvInt("foo"); val != -42 { 62 | t.Fatalf("GetenvInt returns incorrect value: %d", val) 63 | } 64 | 65 | job.SetenvInt("bar", 42) 66 | if val := job.GetenvInt("bar"); val != 42 { 67 | t.Fatalf("GetenvInt returns incorrect value: %d", val) 68 | } 69 | if val := job.GetenvInt("nonexistent"); val != -1 { 70 | t.Fatalf("GetenvInt returns incorrect value: %d", val) 71 | } 72 | } 73 | 74 | func TestSetenvList(t *testing.T) { 75 | job := mkJob(t, "dummy") 76 | 77 | job.SetenvList("foo", []string{"bar"}) 78 | if val := job.GetenvList("foo"); len(val) != 1 || val[0] != "bar" { 79 | t.Fatalf("GetenvList returns incorrect value: %v", val) 80 | } 81 | 82 | job.SetenvList("bar", nil) 83 | if val := job.GetenvList("bar"); val != nil { 84 | t.Fatalf("GetenvList returns incorrect value: %v", val) 85 | } 86 | if val := job.GetenvList("nonexistent"); val != nil { 87 | t.Fatalf("GetenvList returns incorrect value: %v", val) 88 | } 89 | } 90 | 91 | func TestImportEnv(t *testing.T) { 92 | type dummy struct { 93 | DummyInt int 94 | DummyStringArray []string 95 | } 96 | 97 | job := mkJob(t, "dummy") 98 | if err := job.ImportEnv(&dummy{42, []string{"foo", "bar"}}); err != nil { 99 | t.Fatal(err) 100 | } 101 | 102 | dmy := dummy{} 103 | if err := job.ExportEnv(&dmy); err != nil { 104 | t.Fatal(err) 105 | } 106 | 107 | if dmy.DummyInt != 42 { 108 | t.Fatalf("Expected 42, got %d", dmy.DummyInt) 109 | } 110 | 111 | if len(dmy.DummyStringArray) != 2 || dmy.DummyStringArray[0] != "foo" || dmy.DummyStringArray[1] != "bar" { 112 | t.Fatalf("Expected {foo, bar}, got %v", dmy.DummyStringArray) 113 | } 114 | 115 | } 116 | 117 | func TestEnviron(t *testing.T) { 118 | job := mkJob(t, "dummy") 119 | job.Setenv("foo", "bar") 120 | val, exists := job.Environ()["foo"] 121 | if !exists { 122 | t.Fatalf("foo not found in the environ") 123 | } 124 | if val != "bar" { 125 | t.Fatalf("bar not found in the environ") 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /vendor/go/src/github.com/fsouza/go-dockerclient/misc_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 go-dockerclient authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package docker 6 | 7 | import ( 8 | "github.com/fsouza/go-dockerclient/engine" 9 | "net/http" 10 | "net/url" 11 | "reflect" 12 | "sort" 13 | "testing" 14 | ) 15 | 16 | type DockerVersion struct { 17 | Version string 18 | GitCommit string 19 | GoVersion string 20 | } 21 | 22 | func TestVersion(t *testing.T) { 23 | body := `{ 24 | "Version":"0.2.2", 25 | "GitCommit":"5a2a5cc+CHANGES", 26 | "GoVersion":"go1.0.3" 27 | }` 28 | fakeRT := FakeRoundTripper{message: body, status: http.StatusOK} 29 | client := newTestClient(&fakeRT) 30 | expected := DockerVersion{ 31 | Version: "0.2.2", 32 | GitCommit: "5a2a5cc+CHANGES", 33 | GoVersion: "go1.0.3", 34 | } 35 | version, err := client.Version() 36 | if err != nil { 37 | t.Fatal(err) 38 | } 39 | 40 | if result := version.Get("Version"); result != expected.Version { 41 | t.Errorf("Version(): Wrong result. Want %#v. Got %#v.", expected.Version, version.Get("Version")) 42 | } 43 | if result := version.Get("GitCommit"); result != expected.GitCommit { 44 | t.Errorf("GitCommit(): Wrong result. Want %#v. Got %#v.", expected.GitCommit, version.Get("GitCommit")) 45 | } 46 | if result := version.Get("GoVersion"); result != expected.GoVersion { 47 | t.Errorf("GoVersion(): Wrong result. Want %#v. Got %#v.", expected.GoVersion, version.Get("GoVersion")) 48 | } 49 | req := fakeRT.requests[0] 50 | if req.Method != "GET" { 51 | t.Errorf("Version(): wrong request method. Want GET. Got %s.", req.Method) 52 | } 53 | u, _ := url.Parse(client.getURL("/version")) 54 | if req.URL.Path != u.Path { 55 | t.Errorf("Version(): wrong request path. Want %q. Got %q.", u.Path, req.URL.Path) 56 | } 57 | } 58 | 59 | func TestVersionError(t *testing.T) { 60 | fakeRT := &FakeRoundTripper{message: "internal error", status: http.StatusInternalServerError} 61 | client := newTestClient(fakeRT) 62 | version, err := client.Version() 63 | if version != nil { 64 | t.Errorf("Version(): expected value, got %#v.", version) 65 | } 66 | if err == nil { 67 | t.Error("Version(): unexpected error") 68 | } 69 | } 70 | 71 | func TestInfo(t *testing.T) { 72 | body := `{ 73 | "Containers":11, 74 | "Images":16, 75 | "Debug":0, 76 | "NFd":11, 77 | "NGoroutines":21, 78 | "MemoryLimit":1, 79 | "SwapLimit":0 80 | }` 81 | fakeRT := FakeRoundTripper{message: body, status: http.StatusOK} 82 | client := newTestClient(&fakeRT) 83 | expected := engine.Env{} 84 | expected.SetInt("Containers", 11) 85 | expected.SetInt("Images", 16) 86 | expected.SetBool("Debug", false) 87 | expected.SetInt("NFd", 11) 88 | expected.SetInt("NGoroutines", 21) 89 | expected.SetBool("MemoryLimit", true) 90 | expected.SetBool("SwapLimit", false) 91 | info, err := client.Info() 92 | if err != nil { 93 | t.Fatal(err) 94 | } 95 | infoSlice := []string(*info) 96 | expectedSlice := []string(expected) 97 | sort.Strings(infoSlice) 98 | sort.Strings(expectedSlice) 99 | if !reflect.DeepEqual(expectedSlice, infoSlice) { 100 | t.Errorf("Info(): Wrong result.\nWant %#v.\nGot %#v.", expected, *info) 101 | } 102 | req := fakeRT.requests[0] 103 | if req.Method != "GET" { 104 | t.Errorf("Info(): Wrong HTTP method. Want GET. Got %s.", req.Method) 105 | } 106 | u, _ := url.Parse(client.getURL("/info")) 107 | if req.URL.Path != u.Path { 108 | t.Errorf("Info(): Wrong request path. Want %q. Got %q.", u.Path, req.URL.Path) 109 | } 110 | } 111 | 112 | func TestInfoError(t *testing.T) { 113 | fakeRT := &FakeRoundTripper{message: "internal error", status: http.StatusInternalServerError} 114 | client := newTestClient(fakeRT) 115 | version, err := client.Info() 116 | if version != nil { 117 | t.Errorf("Info(): expected value, got %#v.", version) 118 | } 119 | if err == nil { 120 | t.Error("Info(): unexpected error") 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /remote/s3_test.go: -------------------------------------------------------------------------------- 1 | package remote 2 | 3 | import ( 4 | //"bytes" 5 | //"io/ioutil" 6 | //"net/http" 7 | //"strings" 8 | 9 | "testing" 10 | "time" 11 | 12 | "os" 13 | "io/ioutil" 14 | "path/filepath" 15 | 16 | "github.com/lachie/goamz/aws" 17 | "github.com/lachie/goamz/s3" 18 | "github.com/lachie/goamz/testutil" 19 | . "launchpad.net/gocheck" 20 | 21 | "github.com/blake-education/dogestry/config" 22 | ) 23 | 24 | func Test(t *testing.T) { 25 | TestingT(t) 26 | } 27 | 28 | type S struct { 29 | remote *S3Remote 30 | tempDir string 31 | } 32 | 33 | var _ = Suite(&S{}) 34 | 35 | var testServer = testutil.NewHTTPServer() 36 | 37 | var baseConfig = RemoteConfig{ 38 | Config: config.Config{ 39 | S3: config.S3Config{ 40 | Access_Key_Id: "abc", 41 | Secret_Key: "123", 42 | }, 43 | }, 44 | } 45 | 46 | func (s *S) SetUpSuite(c *C) { 47 | testServer.Start() 48 | 49 | auth := aws.Auth{"abc", "123", ""} 50 | client := s3.New(auth, aws.Region{Name: "faux-region-1", S3Endpoint: testServer.URL}) 51 | 52 | 53 | tempDir, err := ioutil.TempDir("", "dogestry-test") 54 | if err != nil { 55 | c.Fatalf("couldn't get tempdir: %s", err) 56 | } 57 | 58 | s.tempDir = tempDir 59 | 60 | s.remote = &S3Remote{ 61 | config: baseConfig, 62 | BucketName: "bucket", 63 | KeyPrefix: "prefix", 64 | client: client, 65 | } 66 | } 67 | 68 | func (s *S) TearDownSuite(c *C) { 69 | s3.SetAttemptStrategy(nil) 70 | 71 | defer os.RemoveAll(s.tempDir) 72 | } 73 | 74 | func (s *S) SetUpTest(c *C) { 75 | attempts := aws.AttemptStrategy{ 76 | Total: 300 * time.Millisecond, 77 | Delay: 100 * time.Millisecond, 78 | } 79 | s3.SetAttemptStrategy(&attempts) 80 | } 81 | 82 | 83 | func (s *S) TestBucket(c *C) { 84 | testServer.Response(200, nil, "content") 85 | 86 | b := s.remote.getBucket() 87 | c.Assert(b.Name, Equals, "bucket") 88 | } 89 | 90 | func (s *S) TestRepoKeys(c *C) { 91 | nelsonSha := "123" 92 | 93 | //testServer.Response(200, nil, "content") 94 | testServer.Response(200, nil, GetListResultDump1) 95 | testServer.Response(200, nil, nelsonSha) 96 | 97 | keys,err := s.remote.repoKeys("") 98 | c.Assert(err, IsNil) 99 | 100 | testServer.WaitRequests(2) 101 | 102 | c.Log(keys["Nelson"]) 103 | 104 | c.Assert(keys["Nelson"].key, Equals, "Nelson") 105 | c.Assert(keys["Nelson"].Sum(), Equals, nelsonSha) 106 | 107 | c.Assert(keys["Neo"].key, Equals, "Neo") 108 | c.Assert(keys["Neo"].Sum(), Equals, "") 109 | } 110 | 111 | 112 | func (s *S) TestLocalKeys(c *C) { 113 | dumpFile(s.tempDir, "file1", "hello world") 114 | dumpFile(s.tempDir, "dir/file2", "hello mars") 115 | 116 | keys,err := s.remote.localKeys(s.tempDir) 117 | c.Assert(err, IsNil) 118 | 119 | c.Assert(keys["file1"].key, Equals, "file1") 120 | c.Assert(keys["file1"].fullPath, Equals, filepath.Join(s.tempDir,"file1")) 121 | c.Assert(keys["file1"].sum, Equals, "2aae6c35c94fcfb415dbe95f408b9ce91ee846ed") 122 | 123 | c.Assert(keys["dir/file2"].key, Equals, "dir/file2") 124 | c.Assert(keys["dir/file2"].fullPath, Equals, filepath.Join(s.tempDir,"dir/file2")) 125 | c.Assert(keys["dir/file2"].sum, Equals, "dd6944c43fabd03cf643fe0daf625759dbdea808") 126 | } 127 | 128 | 129 | func (s *S) TestResolveImageNameToId(c *C) { 130 | rubyId := "123" 131 | 132 | testServer.Response(200, nil, "123") 133 | 134 | id,err := s.remote.ResolveImageNameToId("ruby") 135 | c.Assert(err, IsNil) 136 | 137 | c.Assert(string(id), Equals, rubyId) 138 | 139 | 140 | testServer.Flush() 141 | testServer.Response(404, nil, "") 142 | 143 | id,err = s.remote.ResolveImageNameToId("rubyx") 144 | c.Assert(err, Not(IsNil)) 145 | } 146 | 147 | 148 | //func (s *S) TestGetFiles(c *C) { 149 | //s.remote.getFiles(s.tempDir, ) 150 | //} 151 | 152 | 153 | func dumpFile(temp, filename, content string) error { 154 | out := filepath.Join(temp, filename) 155 | if err := os.MkdirAll(filepath.Dir(out), 0700); err != nil { 156 | return err 157 | } 158 | return ioutil.WriteFile(out, []byte(content), 0600) 159 | } 160 | -------------------------------------------------------------------------------- /vendor/go/src/github.com/mitchellh/goamz/exp/sdb/responses_test.go: -------------------------------------------------------------------------------- 1 | package sdb_test 2 | 3 | var TestCreateDomainXmlOK = ` 4 | 5 | 6 | 7 | 63264005-7a5f-e01a-a224-395c63b89f6d 8 | 0.0055590279 9 | 10 | 11 | ` 12 | 13 | var TestListDomainsXmlOK = ` 14 | 15 | 16 | 17 | Account 18 | Domain 19 | Record 20 | 21 | 22 | 15fcaf55-9914-63c2-21f3-951e31193790 23 | 0.0000071759 24 | 25 | 26 | ` 27 | 28 | var TestListDomainsWithNextTokenXmlOK = ` 29 | 30 | 31 | 32 | Domain1-200706011651 33 | Domain2-200706011652 34 | TWV0ZXJpbmdUZXN0RG9tYWluMS0yMDA3MDYwMTE2NTY= 35 | 36 | 37 | eb13162f-1b95-4511-8b12-489b86acfd28 38 | 0.0000219907 39 | 40 | 41 | ` 42 | 43 | var TestDeleteDomainXmlOK = ` 44 | 45 | 46 | 47 | 039e1e25-9a64-2a74-93da-2fda36122a97 48 | 0.0055590278 49 | 50 | 51 | ` 52 | 53 | var TestDomainMetadataXmlNoSuchDomain = ` 54 | 55 | 56 | 57 | 58 | NoSuchDomain 59 | The specified domain does not exist. 60 | 0.0000071759 61 | 62 | 63 | e050cea2-a772-f90e-2cb0-98ebd42c2898 64 | 65 | ` 66 | 67 | var TestPutAttrsXmlOK = ` 68 | 69 | 70 | 71 | 490206ce-8292-456c-a00f-61b335eb202b 72 | 0.0000219907 73 | 74 | 75 | ` 76 | 77 | var TestAttrsXmlOK = ` 78 | 79 | 80 | 81 | ColorBlue 82 | SizeMed 83 | 84 | 85 | b1e8f1f7-42e9-494c-ad09-2674e557526d 86 | 0.0000219942 87 | 88 | 89 | ` 90 | 91 | var TestSelectXmlOK = ` 92 | 93 | 94 | 95 | 96 | Item_03 97 | CategoryClothes 98 | SubcategoryPants 99 | NameSweatpants 100 | ColorBlue 101 | ColorYellow 102 | ColorPink 103 | SizeLarge 104 | 105 | 106 | Item_06 107 | CategoryMotorcycle Parts 108 | SubcategoryBodywork 109 | NameFender Eliminator 110 | ColorBlue 111 | MakeYamaha 112 | ModelR1 113 | 114 | 115 | 116 | b1e8f1f7-42e9-494c-ad09-2674e557526d 117 | 0.0000219907 118 | 119 | 120 | ` 121 | -------------------------------------------------------------------------------- /cli/push.go: -------------------------------------------------------------------------------- 1 | package cli 2 | 3 | import ( 4 | "github.com/blake-education/dogestry/remote" 5 | "github.com/blake-education/dogestry/utils" 6 | "encoding/json" 7 | 8 | "archive/tar" 9 | "fmt" 10 | "io" 11 | "io/ioutil" 12 | "os" 13 | "path/filepath" 14 | "strings" 15 | ) 16 | 17 | func (cli *DogestryCli) CmdPush(args ...string) error { 18 | cmd := cli.Subcmd("push", "REMOTE IMAGE[:TAG]", "push IMAGE to the REMOTE. TAG defaults to 'latest'") 19 | if err := cmd.Parse(args); err != nil { 20 | return nil 21 | } 22 | 23 | if len(cmd.Args()) < 2 { 24 | return fmt.Errorf("Error: IMAGE and REMOTE not specified") 25 | } 26 | 27 | remoteDef := cmd.Arg(0) 28 | image := cmd.Arg(1) 29 | 30 | imageRoot, err := cli.WorkDir(image) 31 | if err != nil { 32 | return err 33 | } 34 | 35 | remote, err := remote.NewRemote(remoteDef, cli.Config) 36 | if err != nil { 37 | return err 38 | } 39 | 40 | fmt.Println("remote", remote.Desc()) 41 | 42 | fmt.Println("preparing image") 43 | if err := cli.prepareImage(image, imageRoot); err != nil { 44 | return err 45 | } 46 | 47 | fmt.Println("pushing image to remote") 48 | if err := remote.Push(image, imageRoot); err != nil { 49 | return err 50 | } 51 | 52 | return nil 53 | } 54 | 55 | // Stream the tarball from docker and translate it into the portable repo format 56 | // Note that its easier to handle as a stream on the way out. 57 | func (cli *DogestryCli) prepareImage(image, root string) error { 58 | reader, writer := io.Pipe() 59 | defer writer.Close() 60 | defer reader.Close() 61 | 62 | tarball := tar.NewReader(reader) 63 | 64 | errch := make(chan error) 65 | 66 | go func() { 67 | // consume the tar 68 | for { 69 | header, err := tarball.Next() 70 | if err == io.EOF { 71 | // end of tar archive 72 | break 73 | } 74 | if err != nil { 75 | errch <- err 76 | return 77 | } 78 | 79 | if err := cli.processTarEntry(root, header, tarball); err != nil { 80 | errch <- err 81 | return 82 | } 83 | } 84 | 85 | // donno... read a bit more? 86 | if _, err := ioutil.ReadAll(reader); err != nil { 87 | errch <- err 88 | return 89 | } 90 | 91 | errch <- nil 92 | }() 93 | 94 | if err := cli.client.GetImageTarball(image, writer); err != nil { 95 | // this should stop the tar reader 96 | writer.Close() 97 | <-errch 98 | return err 99 | } 100 | 101 | writer.Close() 102 | 103 | // wait for the tar reader 104 | if err := <-errch; err != nil { 105 | return err 106 | } 107 | 108 | return nil 109 | } 110 | 111 | func (cli *DogestryCli) processTarEntry(root string, header *tar.Header, tarball io.Reader) error { 112 | // only handle files (directories are implicit) 113 | if header.Typeflag == tar.TypeReg { 114 | fmt.Printf(" tar: processing %s\n", header.Name) 115 | 116 | // special case - repositories file 117 | if filepath.Base(header.Name) == "repositories" { 118 | if err := writeRepositories(root, tarball); err != nil { 119 | return err 120 | } 121 | 122 | } else { 123 | barename := strings.TrimPrefix(header.Name, "./") 124 | 125 | dest := filepath.Join(root, "images", barename) 126 | if err := os.MkdirAll(filepath.Dir(dest), os.ModeDir|0700); err != nil { 127 | return err 128 | } 129 | 130 | destFile, err := os.Create(dest) 131 | if err != nil { 132 | return err 133 | } 134 | defer destFile.Close() 135 | 136 | if wrote, err := io.Copy(destFile, tarball); err != nil { 137 | return err 138 | } else { 139 | fmt.Printf(" tar: wrote %s\n", utils.HumanSize(wrote)) 140 | } 141 | destFile.Close() 142 | } 143 | } 144 | 145 | return nil 146 | } 147 | 148 | type Repository map[string]string 149 | 150 | func writeRepositories(root string, tarball io.Reader) error { 151 | destRoot := filepath.Join(root, "repositories") 152 | 153 | repositories := map[string]Repository{} 154 | if err := json.NewDecoder(tarball).Decode(&repositories); err != nil { 155 | return err 156 | } 157 | 158 | for repoName, repo := range repositories { 159 | for tag, id := range repo { 160 | dest := filepath.Join(destRoot, repoName, tag) 161 | 162 | if err := os.MkdirAll(filepath.Dir(dest), os.ModeDir|0700); err != nil { 163 | return err 164 | } 165 | 166 | if err := ioutil.WriteFile(dest, []byte(id), 0600); err != nil { 167 | return err 168 | } 169 | } 170 | } 171 | 172 | return nil 173 | } 174 | 175 | 176 | -------------------------------------------------------------------------------- /vendor/go/src/github.com/fsouza/go-dockerclient/utils/stdcopy.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 Docker authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the DOCKER-LICENSE file. 4 | 5 | package utils 6 | 7 | import ( 8 | "encoding/binary" 9 | "errors" 10 | "io" 11 | ) 12 | 13 | const ( 14 | StdWriterPrefixLen = 8 15 | StdWriterFdIndex = 0 16 | StdWriterSizeIndex = 4 17 | ) 18 | 19 | type StdType [StdWriterPrefixLen]byte 20 | 21 | var ( 22 | Stdin StdType = StdType{0: 0} 23 | Stdout StdType = StdType{0: 1} 24 | Stderr StdType = StdType{0: 2} 25 | ) 26 | 27 | type StdWriter struct { 28 | io.Writer 29 | prefix StdType 30 | sizeBuf []byte 31 | } 32 | 33 | func (w *StdWriter) Write(buf []byte) (n int, err error) { 34 | if w == nil || w.Writer == nil { 35 | return 0, errors.New("Writer not instanciated") 36 | } 37 | binary.BigEndian.PutUint32(w.prefix[4:], uint32(len(buf))) 38 | buf = append(w.prefix[:], buf...) 39 | 40 | n, err = w.Writer.Write(buf) 41 | return n - StdWriterPrefixLen, err 42 | } 43 | 44 | // NewStdWriter instanciates a new Writer. 45 | // Everything written to it will be encapsulated using a custom format, 46 | // and written to the underlying `w` stream. 47 | // This allows multiple write streams (e.g. stdout and stderr) to be muxed into a single connection. 48 | // `t` indicates the id of the stream to encapsulate. 49 | // It can be utils.Stdin, utils.Stdout, utils.Stderr. 50 | func NewStdWriter(w io.Writer, t StdType) *StdWriter { 51 | if len(t) != StdWriterPrefixLen { 52 | return nil 53 | } 54 | 55 | return &StdWriter{ 56 | Writer: w, 57 | prefix: t, 58 | sizeBuf: make([]byte, 4), 59 | } 60 | } 61 | 62 | var ErrInvalidStdHeader = errors.New("Unrecognized input header") 63 | 64 | // StdCopy is a modified version of io.Copy. 65 | // 66 | // StdCopy will demultiplex `src`, assuming that it contains two streams, 67 | // previously multiplexed together using a StdWriter instance. 68 | // As it reads from `src`, StdCopy will write to `dstout` and `dsterr`. 69 | // 70 | // StdCopy will read until it hits EOF on `src`. It will then return a nil error. 71 | // In other words: if `err` is non nil, it indicates a real underlying error. 72 | // 73 | // `written` will hold the total number of bytes written to `dstout` and `dsterr`. 74 | func StdCopy(dstout, dsterr io.Writer, src io.Reader) (written int64, err error) { 75 | var ( 76 | buf = make([]byte, 32*1024+StdWriterPrefixLen+1) 77 | bufLen = len(buf) 78 | nr, nw int 79 | er, ew error 80 | out io.Writer 81 | frameSize int 82 | ) 83 | 84 | for { 85 | // Make sure we have at least a full header 86 | for nr < StdWriterPrefixLen { 87 | var nr2 int 88 | nr2, er = src.Read(buf[nr:]) 89 | if er == io.EOF { 90 | return written, nil 91 | } 92 | if er != nil { 93 | return 0, er 94 | } 95 | nr += nr2 96 | } 97 | 98 | // Check the first byte to know where to write 99 | switch buf[StdWriterFdIndex] { 100 | case 0: 101 | fallthrough 102 | case 1: 103 | // Write on stdout 104 | out = dstout 105 | case 2: 106 | // Write on stderr 107 | out = dsterr 108 | default: 109 | Debugf("Error selecting output fd: (%d)", buf[StdWriterFdIndex]) 110 | return 0, ErrInvalidStdHeader 111 | } 112 | 113 | // Retrieve the size of the frame 114 | frameSize = int(binary.BigEndian.Uint32(buf[StdWriterSizeIndex : StdWriterSizeIndex+4])) 115 | 116 | // Check if the buffer is big enough to read the frame. 117 | // Extend it if necessary. 118 | if frameSize+StdWriterPrefixLen > bufLen { 119 | Debugf("Extending buffer cap.") 120 | buf = append(buf, make([]byte, frameSize-len(buf)+1)...) 121 | bufLen = len(buf) 122 | } 123 | 124 | // While the amount of bytes read is less than the size of the frame + header, we keep reading 125 | for nr < frameSize+StdWriterPrefixLen { 126 | var nr2 int 127 | nr2, er = src.Read(buf[nr:]) 128 | if er == io.EOF { 129 | return written, nil 130 | } 131 | if er != nil { 132 | Debugf("Error reading frame: %s", er) 133 | return 0, er 134 | } 135 | nr += nr2 136 | } 137 | 138 | // Write the retrieved frame (without header) 139 | nw, ew = out.Write(buf[StdWriterPrefixLen : frameSize+StdWriterPrefixLen]) 140 | if nw > 0 { 141 | written += int64(nw) 142 | } 143 | if ew != nil { 144 | Debugf("Error writing frame: %s", ew) 145 | return 0, ew 146 | } 147 | // If the frame has not been fully written: error 148 | if nw != frameSize { 149 | Debugf("Error Short Write: (%d on %d)", nw, frameSize) 150 | return 0, io.ErrShortWrite 151 | } 152 | 153 | // Move the rest of the buffer to the beginning 154 | copy(buf, buf[frameSize+StdWriterPrefixLen:]) 155 | // Move the index 156 | nr -= frameSize + StdWriterPrefixLen 157 | } 158 | } 159 | -------------------------------------------------------------------------------- /vendor/go/src/github.com/fsouza/go-dockerclient/engine/engine.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 Docker authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the DOCKER-LICENSE file. 4 | 5 | package engine 6 | 7 | import ( 8 | "fmt" 9 | "github.com/fsouza/go-dockerclient/utils" 10 | "io" 11 | "log" 12 | "os" 13 | "path/filepath" 14 | "runtime" 15 | "strings" 16 | ) 17 | 18 | type Handler func(*Job) Status 19 | 20 | var globalHandlers map[string]Handler 21 | 22 | func init() { 23 | globalHandlers = make(map[string]Handler) 24 | } 25 | 26 | func Register(name string, handler Handler) error { 27 | _, exists := globalHandlers[name] 28 | if exists { 29 | return fmt.Errorf("Can't overwrite global handler for command %s", name) 30 | } 31 | globalHandlers[name] = handler 32 | return nil 33 | } 34 | 35 | // The Engine is the core of Docker. 36 | // It acts as a store for *containers*, and allows manipulation of these 37 | // containers by executing *jobs*. 38 | type Engine struct { 39 | root string 40 | handlers map[string]Handler 41 | hack Hack // data for temporary hackery (see hack.go) 42 | id string 43 | Stdout io.Writer 44 | Stderr io.Writer 45 | Stdin io.Reader 46 | } 47 | 48 | func (eng *Engine) Root() string { 49 | return eng.root 50 | } 51 | 52 | func (eng *Engine) Register(name string, handler Handler) error { 53 | eng.Logf("Register(%s) (handlers=%v)", name, eng.handlers) 54 | _, exists := eng.handlers[name] 55 | if exists { 56 | return fmt.Errorf("Can't overwrite handler for command %s", name) 57 | } 58 | eng.handlers[name] = handler 59 | return nil 60 | } 61 | 62 | // New initializes a new engine managing the directory specified at `root`. 63 | // `root` is used to store containers and any other state private to the engine. 64 | // Changing the contents of the root without executing a job will cause unspecified 65 | // behavior. 66 | func New(root string) (*Engine, error) { 67 | // Check for unsupported architectures 68 | if runtime.GOARCH != "amd64" { 69 | return nil, fmt.Errorf("The docker runtime currently only supports amd64 (not %s). This will change in the future. Aborting.", runtime.GOARCH) 70 | } 71 | // Check for unsupported kernel versions 72 | // FIXME: it would be cleaner to not test for specific versions, but rather 73 | // test for specific functionalities. 74 | // Unfortunately we can't test for the feature "does not cause a kernel panic" 75 | // without actually causing a kernel panic, so we need this workaround until 76 | // the circumstances of pre-3.8 crashes are clearer. 77 | // For details see http://github.com/dotcloud/docker/issues/407 78 | if k, err := utils.GetKernelVersion(); err != nil { 79 | log.Printf("WARNING: %s\n", err) 80 | } else { 81 | if utils.CompareKernelVersion(k, &utils.KernelVersionInfo{Kernel: 3, Major: 8, Minor: 0}) < 0 { 82 | if os.Getenv("DOCKER_NOWARN_KERNEL_VERSION") == "" { 83 | log.Printf("WARNING: You are running linux kernel version %s, which might be unstable running docker. Please upgrade your kernel to 3.8.0.", k.String()) 84 | } 85 | } 86 | } 87 | 88 | if err := os.MkdirAll(root, 0700); err != nil && !os.IsExist(err) { 89 | return nil, err 90 | } 91 | 92 | // Docker makes some assumptions about the "absoluteness" of root 93 | // ... so let's make sure it has no symlinks 94 | if p, err := filepath.Abs(root); err != nil { 95 | log.Fatalf("Unable to get absolute root (%s): %s", root, err) 96 | } else { 97 | root = p 98 | } 99 | if p, err := filepath.EvalSymlinks(root); err != nil { 100 | log.Fatalf("Unable to canonicalize root (%s): %s", root, err) 101 | } else { 102 | root = p 103 | } 104 | 105 | eng := &Engine{ 106 | root: root, 107 | handlers: make(map[string]Handler), 108 | id: utils.RandomString(), 109 | Stdout: os.Stdout, 110 | Stderr: os.Stderr, 111 | Stdin: os.Stdin, 112 | } 113 | // Copy existing global handlers 114 | for k, v := range globalHandlers { 115 | eng.handlers[k] = v 116 | } 117 | return eng, nil 118 | } 119 | 120 | func (eng *Engine) String() string { 121 | return fmt.Sprintf("%s|%s", eng.Root(), eng.id[:8]) 122 | } 123 | 124 | // Job creates a new job which can later be executed. 125 | // This function mimics `Command` from the standard os/exec package. 126 | func (eng *Engine) Job(name string, args ...string) *Job { 127 | job := &Job{ 128 | Eng: eng, 129 | Name: name, 130 | Args: args, 131 | Stdin: NewInput(), 132 | Stdout: NewOutput(), 133 | Stderr: NewOutput(), 134 | env: &Env{}, 135 | } 136 | job.Stderr.Add(utils.NopWriteCloser(eng.Stderr)) 137 | handler, exists := eng.handlers[name] 138 | if exists { 139 | job.handler = handler 140 | } 141 | return job 142 | } 143 | 144 | func (eng *Engine) Logf(format string, args ...interface{}) (n int, err error) { 145 | prefixedFormat := fmt.Sprintf("[%s] %s\n", eng, strings.TrimRight(format, "\n")) 146 | return fmt.Fprintf(eng.Stderr, prefixedFormat, args...) 147 | } 148 | -------------------------------------------------------------------------------- /remote/remote.go: -------------------------------------------------------------------------------- 1 | package remote 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "net/url" 7 | "strings" 8 | 9 | "github.com/blake-education/dogestry/config" 10 | docker "github.com/fsouza/go-dockerclient" 11 | ) 12 | 13 | var ( 14 | // ErrInvalidRemote is returned when the remote is not a valid. 15 | ErrInvalidRemote = errors.New("Invalid remote") 16 | 17 | ErrNoSuchImage = errors.New("No such image") 18 | ErrNoSuchTag = errors.New("No such tag") 19 | BreakWalk = errors.New("break walk") 20 | ) 21 | 22 | type RemoteConfig struct { 23 | config.RemoteConfig 24 | Kind string 25 | Config config.Config 26 | Url url.URL 27 | } 28 | 29 | type ImageWalkFn func(id ID, image docker.Image, err error) error 30 | 31 | type Remote interface { 32 | // push image and parent images to remote 33 | Push(image, imageRoot string) error 34 | 35 | // pull a single image from the remote 36 | PullImageId(id ID, imageRoot string) error 37 | 38 | // map repo:tag to id (like git rev-parse) 39 | ParseTag(repo, tag string) (ID, error) 40 | 41 | // map a ref-like to id. "ref-like" could be a ref or an id. 42 | ResolveImageNameToId(image string) (ID, error) 43 | 44 | ImageFullId(id ID) (ID, error) 45 | 46 | ImageMetadata(id ID) (docker.Image, error) 47 | 48 | // walk the image history on the remote, starting at id 49 | WalkImages(id ID, walker ImageWalkFn) error 50 | 51 | // checks the config and connectivity of the remote 52 | Validate() error 53 | 54 | // describe the remote 55 | Desc() string 56 | } 57 | 58 | func NewRemote(remoteName string, config config.Config) (remote Remote, err error) { 59 | remoteConfig, err := resolveConfig(remoteName, config) 60 | if err != nil { 61 | return 62 | } 63 | 64 | switch remoteConfig.Kind { 65 | case "local": 66 | remote, err = NewLocalRemote(remoteConfig) 67 | case "s3": 68 | remote, err = NewS3Remote(remoteConfig) 69 | default: 70 | err = fmt.Errorf("unknown remote type '%s'", remoteConfig.Kind) 71 | return 72 | } 73 | 74 | if err != nil { 75 | return 76 | } 77 | 78 | err = remote.Validate() 79 | return 80 | } 81 | 82 | func resolveConfig(remoteUrl string, config config.Config) (remoteConfig RemoteConfig, err error) { 83 | // its a bareword, use it as a lookup key 84 | if !strings.Contains(remoteUrl, "/") { 85 | return lookupUrlInConfig(remoteUrl, config) 86 | } 87 | 88 | // its a url 89 | return makeRemoteFromUrl(remoteUrl, config) 90 | } 91 | 92 | func lookupUrlInConfig(remoteName string, config config.Config) (remoteConfig RemoteConfig, err error) { 93 | remote, ok := config.Remote[remoteName] 94 | if !ok { 95 | err = fmt.Errorf("no remote '%s' found", remoteName) 96 | return 97 | } 98 | 99 | return makeRemoteFromUrl(remote.Url, config) 100 | // XXX Extra setup can come from here 101 | } 102 | 103 | func makeRemoteFromUrl(remoteUrl string, config config.Config) (remoteConfig RemoteConfig, err error) { 104 | remoteConfig = RemoteConfig{ 105 | Config: config, 106 | } 107 | 108 | u, err := url.Parse(remoteUrl) 109 | if err != nil { 110 | err = ErrInvalidRemote 111 | return 112 | } 113 | 114 | if u.Scheme == "" { 115 | u.Scheme = "local" 116 | } 117 | remoteConfig.Url = *u 118 | remoteConfig.Kind = u.Scheme 119 | remoteConfig.Config = config 120 | 121 | return 122 | } 123 | 124 | func NormaliseImageName(image string) (string, string) { 125 | repoParts := strings.Split(image, ":") 126 | if len(repoParts) == 1 { 127 | return repoParts[0], "latest" 128 | } else { 129 | return repoParts[0], repoParts[1] 130 | } 131 | } 132 | 133 | func ResolveImageNameToId(remote Remote, image string) (ID, error) { 134 | // first, try the repos 135 | repoName, repoTag := NormaliseImageName(image) 136 | if id, err := remote.ParseTag(repoName, repoTag); err != nil { 137 | return "", err 138 | } else if id != "" { 139 | return id, nil 140 | } 141 | 142 | // ok, no repo, search the images: 143 | fullId, err := remote.ImageFullId(ID(image)) 144 | if err != nil { 145 | return "", err 146 | } else if fullId != "" { 147 | return fullId, nil 148 | } 149 | 150 | return "", ErrNoSuchImage 151 | } 152 | 153 | // Common implementation of walking a remote's images 154 | // 155 | // Starting at id, follow the ancestry tree, calling walker for each image found. 156 | // Walker can abort the walk by returning an error. 157 | // - BreakWalk - the walk stops and WalkImages returns nil (no error) 158 | // - other error - the walk stop and WalkImages returns the error. 159 | // - nil - the walk continues 160 | func WalkImages(remote Remote, id ID, walker ImageWalkFn) error { 161 | if id == "" { 162 | return nil 163 | } 164 | 165 | img, err := remote.ImageMetadata(id) 166 | // image wasn't found 167 | if err != nil { 168 | return walker(id, docker.Image{}, err) 169 | } 170 | 171 | err = walker(id, img, nil) 172 | if err != nil { 173 | // abort the walk 174 | if err == BreakWalk { 175 | return nil 176 | } 177 | return err 178 | } 179 | 180 | return remote.WalkImages(ID(img.Parent), walker) 181 | } 182 | -------------------------------------------------------------------------------- /vendor/go/src/github.com/mitchellh/goamz/testutil/http.go: -------------------------------------------------------------------------------- 1 | package testutil 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | "io/ioutil" 7 | "net" 8 | "net/http" 9 | "net/url" 10 | "os" 11 | "time" 12 | ) 13 | 14 | type HTTPServer struct { 15 | URL string 16 | Timeout time.Duration 17 | started bool 18 | request chan *http.Request 19 | response chan ResponseFunc 20 | } 21 | 22 | type Response struct { 23 | Status int 24 | Headers map[string]string 25 | Body string 26 | } 27 | 28 | var DefaultClient = &http.Client{ 29 | Transport: &http.Transport{ 30 | Proxy: http.ProxyFromEnvironment, 31 | }, 32 | } 33 | 34 | func NewHTTPServer() *HTTPServer { 35 | return &HTTPServer{URL: "http://localhost:4444", Timeout: 5 * time.Second} 36 | } 37 | 38 | type ResponseFunc func(path string) Response 39 | 40 | func (s *HTTPServer) Start() { 41 | if s.started { 42 | return 43 | } 44 | s.started = true 45 | s.request = make(chan *http.Request, 1024) 46 | s.response = make(chan ResponseFunc, 1024) 47 | u, err := url.Parse(s.URL) 48 | if err != nil { 49 | panic(err) 50 | } 51 | l, err := net.Listen("tcp", u.Host) 52 | if err != nil { 53 | panic(err) 54 | } 55 | go http.Serve(l, s) 56 | 57 | s.Response(203, nil, "") 58 | for { 59 | // Wait for it to be up. 60 | resp, err := http.Get(s.URL) 61 | if err == nil && resp.StatusCode == 203 { 62 | break 63 | } 64 | time.Sleep(1e8) 65 | } 66 | s.WaitRequest() // Consume dummy request. 67 | } 68 | 69 | // Flush discards all pending requests and responses. 70 | func (s *HTTPServer) Flush() { 71 | for { 72 | select { 73 | case <-s.request: 74 | case <-s.response: 75 | default: 76 | return 77 | } 78 | } 79 | } 80 | 81 | func body(req *http.Request) string { 82 | data, err := ioutil.ReadAll(req.Body) 83 | if err != nil { 84 | panic(err) 85 | } 86 | return string(data) 87 | } 88 | 89 | func (s *HTTPServer) ServeHTTP(w http.ResponseWriter, req *http.Request) { 90 | req.ParseMultipartForm(1e6) 91 | data, err := ioutil.ReadAll(req.Body) 92 | if err != nil { 93 | panic(err) 94 | } 95 | req.Body = ioutil.NopCloser(bytes.NewBuffer(data)) 96 | s.request <- req 97 | var resp Response 98 | select { 99 | case respFunc := <-s.response: 100 | resp = respFunc(req.URL.Path) 101 | case <-time.After(s.Timeout): 102 | const msg = "ERROR: Timeout waiting for test to prepare a response\n" 103 | fmt.Fprintf(os.Stderr, msg) 104 | resp = Response{500, nil, msg} 105 | } 106 | if resp.Headers != nil { 107 | h := w.Header() 108 | for k, v := range resp.Headers { 109 | h.Set(k, v) 110 | } 111 | } 112 | if resp.Status != 0 { 113 | w.WriteHeader(resp.Status) 114 | } 115 | w.Write([]byte(resp.Body)) 116 | } 117 | 118 | // WaitRequests returns the next n requests made to the http server from 119 | // the queue. If not enough requests were previously made, it waits until 120 | // the timeout value for them to be made. 121 | func (s *HTTPServer) WaitRequests(n int) []*http.Request { 122 | reqs := make([]*http.Request, 0, n) 123 | for i := 0; i < n; i++ { 124 | select { 125 | case req := <-s.request: 126 | reqs = append(reqs, req) 127 | case <-time.After(s.Timeout): 128 | panic("Timeout waiting for request") 129 | } 130 | } 131 | return reqs 132 | } 133 | 134 | // WaitRequest returns the next request made to the http server from 135 | // the queue. If no requests were previously made, it waits until the 136 | // timeout value for one to be made. 137 | func (s *HTTPServer) WaitRequest() *http.Request { 138 | return s.WaitRequests(1)[0] 139 | } 140 | 141 | // ResponseFunc prepares the test server to respond the following n 142 | // requests using f to build each response. 143 | func (s *HTTPServer) ResponseFunc(n int, f ResponseFunc) { 144 | for i := 0; i < n; i++ { 145 | s.response <- f 146 | } 147 | } 148 | 149 | // ResponseMap maps request paths to responses. 150 | type ResponseMap map[string]Response 151 | 152 | // ResponseMap prepares the test server to respond the following n 153 | // requests using the m to obtain the responses. 154 | func (s *HTTPServer) ResponseMap(n int, m ResponseMap) { 155 | f := func(path string) Response { 156 | for rpath, resp := range m { 157 | if rpath == path { 158 | return resp 159 | } 160 | } 161 | body := "Path not found in response map: " + path 162 | return Response{Status: 500, Body: body} 163 | } 164 | s.ResponseFunc(n, f) 165 | } 166 | 167 | // Responses prepares the test server to respond the following n requests 168 | // using the provided response parameters. 169 | func (s *HTTPServer) Responses(n int, status int, headers map[string]string, body string) { 170 | f := func(path string) Response { 171 | return Response{status, headers, body} 172 | } 173 | s.ResponseFunc(n, f) 174 | } 175 | 176 | // Response prepares the test server to respond the following request 177 | // using the provided response parameters. 178 | func (s *HTTPServer) Response(status int, headers map[string]string, body string) { 179 | s.Responses(1, status, headers, body) 180 | } 181 | -------------------------------------------------------------------------------- /cli/cli.go: -------------------------------------------------------------------------------- 1 | package cli 2 | 3 | import ( 4 | "github.com/blake-education/dogestry/config" 5 | docker "github.com/fsouza/go-dockerclient" 6 | 7 | "flag" 8 | "fmt" 9 | "io" 10 | "io/ioutil" 11 | "log" 12 | "os" 13 | "path/filepath" 14 | "reflect" 15 | "strings" 16 | ) 17 | 18 | var ( 19 | DefaultConfigFilePath = "./dogestry.cfg" 20 | DefaultConfig = config.Config{ 21 | Remote: make(map[string]*config.RemoteConfig), 22 | Compressor: config.CompressorConfig{ 23 | Lz4: "lz4", 24 | }, 25 | } 26 | ) 27 | 28 | type DogestryCli struct { 29 | client docker.Client 30 | err io.Writer 31 | tempDir string 32 | tempDirRoot string 33 | Config config.Config 34 | } 35 | 36 | func NewDogestryCli(config config.Config) (*DogestryCli, error) { 37 | dockerConnection := config.Docker.Connection 38 | if dockerConnection == "" { 39 | dockerConnection = "unix:///var/run/docker.sock" 40 | } 41 | 42 | newClient, err := docker.NewClient(dockerConnection) 43 | if err != nil { 44 | log.Fatal(err) 45 | } 46 | 47 | return &DogestryCli{ 48 | Config: config, 49 | client: *newClient, 50 | err: os.Stderr, 51 | }, nil 52 | } 53 | 54 | // Note: snatched from docker 55 | 56 | func (cli *DogestryCli) getMethod(name string) (func(...string) error, bool) { 57 | methodName := "Cmd" + strings.ToUpper(name[:1]) + strings.ToLower(name[1:]) 58 | method := reflect.ValueOf(cli).MethodByName(methodName) 59 | if !method.IsValid() { 60 | return nil, false 61 | } 62 | return method.Interface().(func(...string) error), true 63 | } 64 | 65 | func ParseCommands(configFilePath string, tempDirRoot string, args ...string) error { 66 | config, err := parseConfig(configFilePath) 67 | if err != nil { 68 | return err 69 | } 70 | 71 | cli, err := NewDogestryCli(config) 72 | if err != nil { 73 | return err 74 | } 75 | defer cli.Cleanup() 76 | 77 | cli.tempDirRoot = tempDirRoot 78 | if cli.tempDirRoot == "" { 79 | cli.tempDirRoot = config.Dogestry.Temp_Dir 80 | } 81 | 82 | if len(args) > 0 { 83 | method, exists := cli.getMethod(args[0]) 84 | if !exists { 85 | fmt.Println("Error: Command not found:", args[0]) 86 | return cli.CmdHelp(args[1:]...) 87 | } 88 | return method(args[1:]...) 89 | } 90 | return cli.CmdHelp(args...) 91 | } 92 | 93 | func parseConfig(configFilePath string) (cfg config.Config, err error) { 94 | // no config file was specified 95 | if configFilePath == "" { 96 | // if default config exists use it 97 | if _, err := os.Stat(DefaultConfigFilePath); !os.IsNotExist(err) { 98 | configFilePath = DefaultConfigFilePath 99 | } else { 100 | fmt.Fprintln(os.Stdout, "Note: no config file found, using default config.") 101 | return DefaultConfig, nil 102 | } 103 | } 104 | 105 | return config.ParseConfig(configFilePath) 106 | } 107 | 108 | func (cli *DogestryCli) CmdHelp(args ...string) error { 109 | if len(args) > 0 { 110 | method, exists := cli.getMethod(args[0]) 111 | if !exists { 112 | fmt.Fprintf(cli.err, "Error: Command not found: %s\n", args[0]) 113 | } else { 114 | method("--help") 115 | return nil 116 | } 117 | } 118 | 119 | help := fmt.Sprintf( 120 | `Usage: dogestry [OPTIONS] COMMAND [arg...] 121 | Alternate registry and simple image storage for docker. 122 | Typical S3 Usage: 123 | export AWS_ACCESS_KEY=ABC 124 | export AWS_SECRET_KEY=DEF 125 | dogestry pull s3:////?region=us-east-1 126 | Commands: 127 | pull - Pull an image from a remote 128 | push - Push an image to a remote 129 | remote - Check a remote 130 | `) 131 | fmt.Println(help) 132 | return nil 133 | } 134 | 135 | func (cli *DogestryCli) Subcmd(name, signature, description string) *flag.FlagSet { 136 | flags := flag.NewFlagSet(name, flag.ContinueOnError) 137 | flags.Usage = func() { 138 | fmt.Fprintf(cli.err, "\nUsage: dogestry %s %s\n\n%s\n\n", name, signature, description) 139 | flags.PrintDefaults() 140 | os.Exit(2) 141 | } 142 | return flags 143 | } 144 | 145 | // Creates and returns temporary work dir 146 | // This dir is cleaned up on exit 147 | func (cli *DogestryCli) TempDir() string { 148 | if cli.tempDir == "" { 149 | if cli.tempDirRoot != "" { 150 | if err := os.MkdirAll(cli.tempDirRoot, 0755); err != nil { 151 | log.Fatal(err) 152 | } 153 | } 154 | 155 | if tempDir, err := ioutil.TempDir(cli.tempDirRoot, "dogestry"); err != nil { 156 | log.Fatal(err) 157 | } else { 158 | cli.tempDir = tempDir 159 | } 160 | } 161 | 162 | return cli.tempDir 163 | } 164 | 165 | // Creates and returns a workdir under TempDir 166 | func (cli *DogestryCli) WorkDir(suffix string) (string, error) { 167 | path := filepath.Join(cli.TempDir(), suffix) 168 | 169 | if err := os.MkdirAll(path, os.ModeDir|0700); err != nil { 170 | return "", err 171 | } 172 | 173 | return path, nil 174 | } 175 | 176 | // clean up the tempDir 177 | func (cli *DogestryCli) Cleanup() { 178 | if cli.tempDir != "" { 179 | if err := os.RemoveAll(cli.tempDir); err != nil { 180 | log.Println(err) 181 | } 182 | } 183 | } 184 | -------------------------------------------------------------------------------- /vendor/go/src/code.google.com/p/gcfg/read.go: -------------------------------------------------------------------------------- 1 | package gcfg 2 | 3 | import ( 4 | "fmt" 5 | "io" 6 | "io/ioutil" 7 | "os" 8 | "strings" 9 | ) 10 | 11 | import ( 12 | "code.google.com/p/gcfg/scanner" 13 | "code.google.com/p/gcfg/token" 14 | ) 15 | 16 | var unescape = map[rune]rune{'\\': '\\', '"': '"', 'n': '\n', 't': '\t'} 17 | 18 | // no error: invalid literals should be caught by scanner 19 | func unquote(s string) string { 20 | u, q, esc := make([]rune, 0, len(s)), false, false 21 | for _, c := range s { 22 | if esc { 23 | uc, ok := unescape[c] 24 | switch { 25 | case ok: 26 | u = append(u, uc) 27 | fallthrough 28 | case !q && c == '\n': 29 | esc = false 30 | continue 31 | } 32 | panic("invalid escape sequence") 33 | } 34 | switch c { 35 | case '"': 36 | q = !q 37 | case '\\': 38 | esc = true 39 | default: 40 | u = append(u, c) 41 | } 42 | } 43 | if q { 44 | panic("missing end quote") 45 | } 46 | if esc { 47 | panic("invalid escape sequence") 48 | } 49 | return string(u) 50 | } 51 | 52 | func readInto(config interface{}, fset *token.FileSet, file *token.File, src []byte) error { 53 | var s scanner.Scanner 54 | var errs scanner.ErrorList 55 | s.Init(file, src, func(p token.Position, m string) { errs.Add(p, m) }, 0) 56 | sect, sectsub := "", "" 57 | pos, tok, lit := s.Scan() 58 | errfn := func(msg string) error { 59 | return fmt.Errorf("%s: %s", fset.Position(pos), msg) 60 | } 61 | for { 62 | if errs.Len() > 0 { 63 | return errs.Err() 64 | } 65 | switch tok { 66 | case token.EOF: 67 | return nil 68 | case token.EOL, token.COMMENT: 69 | pos, tok, lit = s.Scan() 70 | case token.LBRACK: 71 | pos, tok, lit = s.Scan() 72 | if errs.Len() > 0 { 73 | return errs.Err() 74 | } 75 | if tok != token.IDENT { 76 | return errfn("expected section name") 77 | } 78 | sect, sectsub = lit, "" 79 | pos, tok, lit = s.Scan() 80 | if errs.Len() > 0 { 81 | return errs.Err() 82 | } 83 | if tok == token.STRING { 84 | sectsub = unquote(lit) 85 | if sectsub == "" { 86 | return errfn("empty subsection name") 87 | } 88 | pos, tok, lit = s.Scan() 89 | if errs.Len() > 0 { 90 | return errs.Err() 91 | } 92 | } 93 | if tok != token.RBRACK { 94 | if sectsub == "" { 95 | return errfn("expected subsection name or right bracket") 96 | } 97 | return errfn("expected right bracket") 98 | } 99 | pos, tok, lit = s.Scan() 100 | if tok != token.EOL && tok != token.EOF && tok != token.COMMENT { 101 | return errfn("expected EOL, EOF, or comment") 102 | } 103 | case token.IDENT: 104 | if sect == "" { 105 | return errfn("expected section header") 106 | } 107 | n := lit 108 | pos, tok, lit = s.Scan() 109 | if errs.Len() > 0 { 110 | return errs.Err() 111 | } 112 | blank, v := tok == token.EOF || tok == token.EOL || tok == token.COMMENT, "" 113 | if !blank { 114 | if tok != token.ASSIGN { 115 | return errfn("expected '='") 116 | } 117 | pos, tok, lit = s.Scan() 118 | if errs.Len() > 0 { 119 | return errs.Err() 120 | } 121 | if tok != token.STRING { 122 | return errfn("expected value") 123 | } 124 | v = unquote(lit) 125 | pos, tok, lit = s.Scan() 126 | if errs.Len() > 0 { 127 | return errs.Err() 128 | } 129 | if tok != token.EOL && tok != token.EOF && tok != token.COMMENT { 130 | return errfn("expected EOL, EOF, or comment") 131 | } 132 | } 133 | err := set(config, sect, sectsub, n, blank, v) 134 | if err != nil { 135 | return err 136 | } 137 | default: 138 | if sect == "" { 139 | return errfn("expected section header") 140 | } 141 | return errfn("expected section header or variable declaration") 142 | } 143 | } 144 | panic("never reached") 145 | } 146 | 147 | // ReadInto reads gcfg formatted data from reader and sets the values into the 148 | // corresponding fields in config. 149 | func ReadInto(config interface{}, reader io.Reader) error { 150 | src, err := ioutil.ReadAll(reader) 151 | if err != nil { 152 | return err 153 | } 154 | fset := token.NewFileSet() 155 | file := fset.AddFile("", fset.Base(), len(src)) 156 | return readInto(config, fset, file, src) 157 | } 158 | 159 | // ReadStringInto reads gcfg formatted data from str and sets the values into 160 | // the corresponding fields in config. 161 | func ReadStringInto(config interface{}, str string) error { 162 | r := strings.NewReader(str) 163 | return ReadInto(config, r) 164 | } 165 | 166 | // ReadFileInto reads gcfg formatted data from the file filename and sets the 167 | // values into the corresponding fields in config. 168 | func ReadFileInto(config interface{}, filename string) error { 169 | f, err := os.Open(filename) 170 | if err != nil { 171 | return err 172 | } 173 | defer f.Close() 174 | src, err := ioutil.ReadAll(f) 175 | if err != nil { 176 | return err 177 | } 178 | fset := token.NewFileSet() 179 | file := fset.AddFile(filename, fset.Base(), len(src)) 180 | return readInto(config, fset, file, src) 181 | } 182 | -------------------------------------------------------------------------------- /vendor/go/src/github.com/fsouza/go-dockerclient/client_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 go-dockerclient authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package docker 6 | 7 | import ( 8 | "fmt" 9 | "io/ioutil" 10 | "net/http" 11 | "net/url" 12 | "reflect" 13 | "strconv" 14 | "strings" 15 | "testing" 16 | ) 17 | 18 | func TestNewAPIClient(t *testing.T) { 19 | endpoint := "http://localhost:4243" 20 | client, err := NewClient(endpoint) 21 | if err != nil { 22 | t.Fatal(err) 23 | } 24 | if client.endpoint != endpoint { 25 | t.Errorf("Expected endpoint %s. Got %s.", endpoint, client.endpoint) 26 | } 27 | if client.client != http.DefaultClient { 28 | t.Errorf("Expected http.Client %#v. Got %#v.", http.DefaultClient, client.client) 29 | } 30 | 31 | // test unix socket endpoints 32 | endpoint = "unix:///var/run/docker.sock" 33 | client, err = NewClient(endpoint) 34 | if err != nil { 35 | t.Fatal(err) 36 | } 37 | if client.endpoint != endpoint { 38 | t.Errorf("Expected endpoint %s. Got %s.", endpoint, client.endpoint) 39 | } 40 | 41 | } 42 | 43 | func TestNewClientInvalidEndpoint(t *testing.T) { 44 | cases := []string{ 45 | "htp://localhost:3243", "http://localhost:a", "localhost:8080", 46 | "", "localhost", "http://localhost:8080:8383", "http://localhost:65536", 47 | "https://localhost:-20", 48 | } 49 | for _, c := range cases { 50 | client, err := NewClient(c) 51 | if client != nil { 52 | t.Errorf("Want client for invalid endpoint, got %#v.", client) 53 | } 54 | if !reflect.DeepEqual(err, ErrInvalidEndpoint) { 55 | t.Errorf("NewClient(%q): Got invalid error for invalid endpoint. Want %#v. Got %#v.", c, ErrInvalidEndpoint, err) 56 | } 57 | } 58 | } 59 | 60 | func TestGetURL(t *testing.T) { 61 | var tests = []struct { 62 | endpoint string 63 | path string 64 | expected string 65 | }{ 66 | {"http://localhost:4243/", "/", "http://localhost:4243/"}, 67 | {"http://localhost:4243", "/", "http://localhost:4243/"}, 68 | {"http://localhost:4243", "/containers/ps", "http://localhost:4243/containers/ps"}, 69 | {"http://localhost:4243/////", "/", "http://localhost:4243/"}, 70 | {"unix:///var/run/docker.socket", "/containers", "/containers"}, 71 | } 72 | for _, tt := range tests { 73 | client, _ := NewClient(tt.endpoint) 74 | client.endpoint = tt.endpoint 75 | got := client.getURL(tt.path) 76 | if got != tt.expected { 77 | t.Errorf("getURL(%q): Got %s. Want %s.", tt.path, got, tt.expected) 78 | } 79 | } 80 | } 81 | 82 | func TestError(t *testing.T) { 83 | err := newError(400, []byte("bad parameter")) 84 | expected := Error{Status: 400, Message: "bad parameter"} 85 | if !reflect.DeepEqual(expected, *err) { 86 | t.Errorf("Wrong error type. Want %#v. Got %#v.", expected, *err) 87 | } 88 | message := "API error (400): bad parameter" 89 | if err.Error() != message { 90 | t.Errorf("Wrong error message. Want %q. Got %q.", message, err.Error()) 91 | } 92 | } 93 | 94 | func TestQueryString(t *testing.T) { 95 | v := float32(2.4) 96 | f32QueryString := fmt.Sprintf("w=%s&x=10&y=10.35", strconv.FormatFloat(float64(v), 'f', -1, 64)) 97 | jsonPerson := url.QueryEscape(`{"Name":"gopher","age":4}`) 98 | var tests = []struct { 99 | input interface{} 100 | want string 101 | }{ 102 | {&ListContainersOptions{All: true}, "all=1"}, 103 | {ListContainersOptions{All: true}, "all=1"}, 104 | {ListContainersOptions{Before: "something"}, "before=something"}, 105 | {ListContainersOptions{Before: "something", Since: "other"}, "before=something&since=other"}, 106 | {dumb{X: 10, Y: 10.35000}, "x=10&y=10.35"}, 107 | {dumb{W: v, X: 10, Y: 10.35000}, f32QueryString}, 108 | {dumb{X: 10, Y: 10.35000, Z: 10}, "x=10&y=10.35&zee=10"}, 109 | {dumb{v: 4, X: 10, Y: 10.35000}, "x=10&y=10.35"}, 110 | {dumb{T: 10, Y: 10.35000}, "y=10.35"}, 111 | {dumb{Person: &person{Name: "gopher", Age: 4}}, "p=" + jsonPerson}, 112 | {nil, ""}, 113 | {10, ""}, 114 | {"not_a_struct", ""}, 115 | } 116 | for _, tt := range tests { 117 | got := queryString(tt.input) 118 | if got != tt.want { 119 | t.Errorf("queryString(%v). Want %q. Got %q.", tt.input, tt.want, got) 120 | } 121 | } 122 | } 123 | 124 | type FakeRoundTripper struct { 125 | message string 126 | status int 127 | requests []*http.Request 128 | } 129 | 130 | func (rt *FakeRoundTripper) RoundTrip(r *http.Request) (*http.Response, error) { 131 | body := strings.NewReader(rt.message) 132 | rt.requests = append(rt.requests, r) 133 | return &http.Response{ 134 | StatusCode: rt.status, 135 | Body: ioutil.NopCloser(body), 136 | }, nil 137 | } 138 | 139 | func (rt *FakeRoundTripper) Reset() { 140 | rt.requests = nil 141 | } 142 | 143 | type person struct { 144 | Name string 145 | Age int `json:"age"` 146 | } 147 | 148 | type dumb struct { 149 | T int `qs:"-"` 150 | v int 151 | W float32 152 | X int 153 | Y float64 154 | Z int `qs:"zee"` 155 | Person *person `qs:"p"` 156 | } 157 | 158 | type fakeEndpointURL struct { 159 | Scheme string 160 | } 161 | -------------------------------------------------------------------------------- /s3/sign.go: -------------------------------------------------------------------------------- 1 | package s3 2 | 3 | import ( 4 | "crypto/hmac" 5 | "crypto/sha1" 6 | "encoding/base64" 7 | "log" 8 | "sort" 9 | "strings" 10 | ) 11 | 12 | var b64 = base64.StdEncoding 13 | 14 | // ---------------------------------------------------------------------------- 15 | // S3 signing (http://goo.gl/G1LrK) 16 | 17 | var s3ParamsToSign = map[string]bool{ 18 | "acl": true, 19 | "location": true, 20 | "logging": true, 21 | "notification": true, 22 | "partNumber": true, 23 | "policy": true, 24 | "requestPayment": true, 25 | "torrent": true, 26 | "uploadId": true, 27 | "uploads": true, 28 | "versionId": true, 29 | "versioning": true, 30 | "versions": true, 31 | "response-content-type": true, 32 | "response-content-language": true, 33 | "response-expires": true, 34 | "response-cache-control": true, 35 | "response-content-disposition": true, 36 | "response-content-encoding": true, 37 | } 38 | 39 | var lf = []byte{'\n'} 40 | 41 | 42 | func Sign(keys *Keys, req *http.Request) { 43 | 44 | auth := bytes.NewBufferString("AWS ") 45 | auth.Write([]byte(keys.AccessKey)) 46 | 47 | normaliseRequest(req) 48 | 49 | writeSignature(auth, req) 50 | 51 | req.Header.Set("Authorization", auth.String() 52 | } 53 | 54 | 55 | func writeSignature(keys *Keys, w io.Writer, r *http.Request) { 56 | hash := hmac.New(sha1.New, []byte(keys.SecretKey)) 57 | writeStringToSign(hash, r) 58 | } 59 | 60 | func writeStringToSign(w io.Writer, r *http.Request) { 61 | w.Write([]byte(r.Method)) 62 | w.Write(lf) 63 | writeHeader("content-md5", w, r) 64 | w.Write(lf) 65 | writeHeader("content-type", w, r) 66 | w.Write(lf) 67 | writeDate(w, r) 68 | w.Write(lf) 69 | writeCanonicalAmzHeaders(w, r) 70 | writeCanonicalResource(w, r) 71 | } 72 | 73 | 74 | func writeHeader(key string, w io.Writer, r *http.Request) { 75 | w.Write([]byte(r.Headers.Get(key))) 76 | } 77 | 78 | 79 | func writeDate(w io.Writer, r *http.Request) { 80 | // TODO handle x-amz-date ? 81 | w.Write([]byte(r.Header.Get('date'))) 82 | } 83 | 84 | 85 | func writeCanonicalAmzHeaders(w io.Writer, r *http.Request) { 86 | headers := make([]string) 87 | for header := range r.Header { 88 | header = strings.ToLower(header) 89 | if strings.HasPrefix(header, "x-amz-") { 90 | headers = append(headers, header) 91 | } 92 | } 93 | 94 | sort.Strings(headers) 95 | 96 | for i,header := range headers { 97 | //vall := strings.Join(value, ",") 98 | w.Write([]byte(header+":"r.Header.Get(header))) 99 | } 100 | } 101 | 102 | 103 | func writeCanonicalResource(w io.Writer, r *http.Request) { 104 | hostParts := strings.Split(r.Host, ".") 105 | 106 | if len(hostParts) > 3 { 107 | writeVhostStyleCanonicalResource(w, r) 108 | } else { 109 | writePathStyleCanonicalResource(w, r) 110 | } 111 | } 112 | 113 | 114 | func writeVhostStyleCanonicalResource(w io.Writer, r *http.Request) { 115 | } 116 | 117 | func writePathStyleCanonicalResource io.Writer, r *http.Request) { 118 | } 119 | 120 | keys := make([]string) 121 | for k, v := range params { 122 | if s3ParamsToSign[k] { 123 | for _, vi := range v { 124 | if vi == "" { 125 | sarray = append(sarray, k) 126 | } else { 127 | // "When signing you do not encode these values." 128 | sarray = append(sarray, k+"="+vi) 129 | } 130 | } 131 | } 132 | } 133 | if len(sarray) > 0 { 134 | sort.StringSlice(sarray).Sort() 135 | canonicalPath = canonicalPath + "?" + strings.Join(sarray, "&") 136 | } 137 | } 138 | 139 | 140 | var md5, ctype, date, xamz string 141 | var xamzDate bool 142 | var sarray []string 143 | for k, v := range headers { 144 | k = strings.ToLower(k) 145 | switch k { 146 | case "content-md5": 147 | md5 = v[0] 148 | case "content-type": 149 | ctype = v[0] 150 | case "date": 151 | if !xamzDate { 152 | date = v[0] 153 | } 154 | default: 155 | if strings.HasPrefix(k, "x-amz-") { 156 | vall := strings.Join(v, ",") 157 | sarray = append(sarray, k+":"+vall) 158 | if k == "x-amz-date" { 159 | xamzDate = true 160 | date = "" 161 | } 162 | } 163 | } 164 | } 165 | if len(sarray) > 0 { 166 | sort.StringSlice(sarray).Sort() 167 | xamz = strings.Join(sarray, "\n") + "\n" 168 | } 169 | 170 | expires := false 171 | if v, ok := params["Expires"]; ok { 172 | // Query string request authentication alternative. 173 | expires = true 174 | date = v[0] 175 | params["AWSAccessKeyId"] = []string{auth.AccessKey} 176 | } 177 | 178 | 179 | 180 | payload := req.Method + "\n" + md5 + "\n" + ctype + "\n" + date + "\n" + xamz + canonicalPath 181 | hash := hmac.New(sha1.New, []byte(auth.SecretKey)) 182 | hash.Write([]byte(payload)) 183 | signature := make([]byte, b64.EncodedLen(hash.Size())) 184 | b64.Encode(signature, hash.Sum(nil)) 185 | 186 | if expires { 187 | params["Signature"] = []string{string(signature)} 188 | } else { 189 | headers["Authorization"] = []string{"AWS " + auth.AccessKey + ":" + string(signature)} 190 | } 191 | if debug { 192 | log.Printf("Signature payload: %q", payload) 193 | log.Printf("Signature: %q", signature) 194 | } 195 | } 196 | -------------------------------------------------------------------------------- /cli/pull.go: -------------------------------------------------------------------------------- 1 | package cli 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "io/ioutil" 7 | "os" 8 | "os/exec" 9 | "path/filepath" 10 | 11 | "github.com/blake-education/dogestry/remote" 12 | docker "github.com/fsouza/go-dockerclient" 13 | ) 14 | 15 | func (cli *DogestryCli) CmdPull(args ...string) error { 16 | cmd := cli.Subcmd("pull", "REMOTE IMAGE[:TAG]", "pull IMAGE from the REMOTE and load it into docker. TAG defaults to 'latest'") 17 | if err := cmd.Parse(args); err != nil { 18 | return nil 19 | } 20 | 21 | if len(cmd.Args()) < 2 { 22 | return fmt.Errorf("Error: REMOTE and IMAGE not specified") 23 | } 24 | 25 | remoteDef := cmd.Arg(0) 26 | image := cmd.Arg(1) 27 | 28 | imageRoot, err := cli.WorkDir(image) 29 | if err != nil { 30 | return err 31 | } 32 | r, err := remote.NewRemote(remoteDef, cli.Config) 33 | if err != nil { 34 | return err 35 | } 36 | 37 | fmt.Println("remote", r.Desc()) 38 | 39 | fmt.Println("resolving image id") 40 | id, err := r.ResolveImageNameToId(image) 41 | if err != nil { 42 | return err 43 | } 44 | 45 | fmt.Printf("image '%s' resolved on remote id '%s'\n", image, id.Short()) 46 | 47 | fmt.Println("preparing images") 48 | if err := cli.preparePullImage(id, imageRoot, r); err != nil { 49 | return err 50 | } 51 | 52 | fmt.Println("preparing repositories file") 53 | if err := prepareRepositories(image, imageRoot, r); err != nil { 54 | return err 55 | } 56 | 57 | fmt.Println("sending tar to docker") 58 | if err := cli.sendTar(imageRoot); err != nil { 59 | return err 60 | } 61 | 62 | // in the case where we already have the image, but its not tagged: 63 | fmt.Println("ensuring tag") 64 | if err := cli.retag(image, id); err != nil { 65 | return err 66 | } 67 | 68 | return nil 69 | } 70 | 71 | func (cli *DogestryCli) preparePullImage(fromId remote.ID, imageRoot string, r remote.Remote) error { 72 | toDownload := make([]remote.ID, 0) 73 | 74 | // TODO flatten this list, then iterate and pull each required file 75 | // TODO parallelize 76 | err := r.WalkImages(fromId, func(id remote.ID, image docker.Image, err error) error { 77 | fmt.Printf("examining id '%s' on remote\n", id.Short()) 78 | if err != nil { 79 | fmt.Println("err", err) 80 | return err 81 | } 82 | 83 | _, err = cli.client.InspectImage(string(id)) 84 | if err == docker.ErrNoSuchImage { 85 | toDownload = append(toDownload, id) 86 | return nil 87 | } else if err != nil { 88 | return err 89 | } else { 90 | fmt.Printf("docker already has id '%s', stopping\n", id.Short()) 91 | return remote.BreakWalk 92 | } 93 | }) 94 | 95 | if err != nil { 96 | return err 97 | } 98 | 99 | for _, id := range toDownload { 100 | if err := cli.pullImage(id, filepath.Join(imageRoot, string(id)), r); err != nil { 101 | return err 102 | } 103 | } 104 | 105 | return nil 106 | } 107 | 108 | func (cli *DogestryCli) pullImage(id remote.ID, dst string, r remote.Remote) error { 109 | fmt.Printf("pulling image id '%s'\n", id.Short()) 110 | 111 | // XXX fix image name rewrite 112 | err := r.PullImageId(id, dst) 113 | if err != nil { 114 | return err 115 | } 116 | return cli.processPulled(id, dst) 117 | } 118 | 119 | // no-op for now 120 | func (cli *DogestryCli) processPulled(id remote.ID, dst string) error { 121 | return nil 122 | } 123 | 124 | func prepareRepositories(image, imageRoot string, r remote.Remote) error { 125 | repoName, repoTag := remote.NormaliseImageName(image) 126 | 127 | id, err := r.ParseTag(repoName, repoTag) 128 | if err != nil { 129 | return err 130 | } else if id == "" { 131 | return nil 132 | } 133 | 134 | reposPath := filepath.Join(imageRoot, "repositories") 135 | reposFile, err := os.Create(reposPath) 136 | if err != nil { 137 | return err 138 | } 139 | defer reposFile.Close() 140 | 141 | repositories := map[string]Repository{} 142 | repositories[repoName] = Repository{} 143 | repositories[repoName][repoTag] = string(id) 144 | 145 | return json.NewEncoder(reposFile).Encode(&repositories) 146 | } 147 | 148 | // stream the tarball into docker 149 | // its easier here to use tar command, but it'd be neater to mirror Push's approach 150 | func (cli *DogestryCli) sendTar(imageRoot string) error { 151 | notExist, err := dirNotExistOrEmpty(imageRoot) 152 | 153 | if err != nil { 154 | return err 155 | } 156 | if notExist { 157 | fmt.Println("no images to send to docker") 158 | return nil 159 | } 160 | 161 | // DEBUG - write out a tar to see what's there! 162 | // exec.Command("/bin/tar", "cvf", "/tmp/d.tar", "-C", imageRoot, ".").Run() 163 | 164 | cmd := exec.Command("/bin/tar", "cvf", "-", "-C", imageRoot, ".") 165 | cmd.Dir = imageRoot 166 | defer cmd.Wait() 167 | 168 | stdout, err := cmd.StdoutPipe() 169 | if err != nil { 170 | return err 171 | } 172 | 173 | if err := cmd.Start(); err != nil { 174 | return err 175 | } 176 | 177 | fmt.Println("kicking off post") 178 | return cli.client.PostImageTarball(stdout) 179 | } 180 | 181 | func (cli *DogestryCli) retag(tag string, id remote.ID) error { 182 | return cli.client.SetImageTag(id.String(), tag, false) 183 | } 184 | 185 | func dirNotExistOrEmpty(path string) (bool, error) { 186 | imagesDir, err := os.Open(path) 187 | if err != nil { 188 | // no images 189 | if os.IsNotExist(err) { 190 | return true, nil 191 | } else { 192 | return false, err 193 | } 194 | } 195 | defer imagesDir.Close() 196 | 197 | names, err := ioutil.ReadDir(path) 198 | if err != nil { 199 | return false, err 200 | } 201 | 202 | if len(names) <= 1 { 203 | return true, nil 204 | } 205 | 206 | return false, nil 207 | } 208 | -------------------------------------------------------------------------------- /vendor/go/src/github.com/fsouza/go-dockerclient/engine/streams.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 Docker authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the DOCKER-LICENSE file. 4 | 5 | package engine 6 | 7 | import ( 8 | "bufio" 9 | "container/ring" 10 | "fmt" 11 | "io" 12 | "sync" 13 | ) 14 | 15 | type Output struct { 16 | sync.Mutex 17 | dests []io.Writer 18 | tasks sync.WaitGroup 19 | } 20 | 21 | // NewOutput returns a new Output object with no destinations attached. 22 | // Writing to an empty Output will cause the written data to be discarded. 23 | func NewOutput() *Output { 24 | return &Output{} 25 | } 26 | 27 | // Add attaches a new destination to the Output. Any data subsequently written 28 | // to the output will be written to the new destination in addition to all the others. 29 | // This method is thread-safe. 30 | // FIXME: Add cannot fail 31 | func (o *Output) Add(dst io.Writer) error { 32 | o.Mutex.Lock() 33 | defer o.Mutex.Unlock() 34 | o.dests = append(o.dests, dst) 35 | return nil 36 | } 37 | 38 | // AddPipe creates an in-memory pipe with io.Pipe(), adds its writing end as a destination, 39 | // and returns its reading end for consumption by the caller. 40 | // This is a rough equivalent similar to Cmd.StdoutPipe() in the standard os/exec package. 41 | // This method is thread-safe. 42 | func (o *Output) AddPipe() (io.Reader, error) { 43 | r, w := io.Pipe() 44 | o.Add(w) 45 | return r, nil 46 | } 47 | 48 | // AddTail starts a new goroutine which will read all subsequent data written to the output, 49 | // line by line, and append the last `n` lines to `dst`. 50 | func (o *Output) AddTail(dst *[]string, n int) error { 51 | src, err := o.AddPipe() 52 | if err != nil { 53 | return err 54 | } 55 | o.tasks.Add(1) 56 | go func() { 57 | defer o.tasks.Done() 58 | Tail(src, n, dst) 59 | }() 60 | return nil 61 | } 62 | 63 | // AddString starts a new goroutine which will read all subsequent data written to the output, 64 | // line by line, and store the last line into `dst`. 65 | func (o *Output) AddString(dst *string) error { 66 | src, err := o.AddPipe() 67 | if err != nil { 68 | return err 69 | } 70 | o.tasks.Add(1) 71 | go func() { 72 | defer o.tasks.Done() 73 | lines := make([]string, 0, 1) 74 | Tail(src, 1, &lines) 75 | if len(lines) == 0 { 76 | *dst = "" 77 | } else { 78 | *dst = lines[0] 79 | } 80 | }() 81 | return nil 82 | } 83 | 84 | // Write writes the same data to all registered destinations. 85 | // This method is thread-safe. 86 | func (o *Output) Write(p []byte) (n int, err error) { 87 | o.Mutex.Lock() 88 | defer o.Mutex.Unlock() 89 | var firstErr error 90 | for _, dst := range o.dests { 91 | _, err := dst.Write(p) 92 | if err != nil && firstErr == nil { 93 | firstErr = err 94 | } 95 | } 96 | return len(p), firstErr 97 | } 98 | 99 | // Close unregisters all destinations and waits for all background 100 | // AddTail and AddString tasks to complete. 101 | // The Close method of each destination is called if it exists. 102 | func (o *Output) Close() error { 103 | o.Mutex.Lock() 104 | defer o.Mutex.Unlock() 105 | var firstErr error 106 | for _, dst := range o.dests { 107 | if closer, ok := dst.(io.WriteCloser); ok { 108 | err := closer.Close() 109 | if err != nil && firstErr == nil { 110 | firstErr = err 111 | } 112 | } 113 | } 114 | o.tasks.Wait() 115 | return firstErr 116 | } 117 | 118 | type Input struct { 119 | src io.Reader 120 | sync.Mutex 121 | } 122 | 123 | // NewInput returns a new Input object with no source attached. 124 | // Reading to an empty Input will return io.EOF. 125 | func NewInput() *Input { 126 | return &Input{} 127 | } 128 | 129 | // Read reads from the input in a thread-safe way. 130 | func (i *Input) Read(p []byte) (n int, err error) { 131 | i.Mutex.Lock() 132 | defer i.Mutex.Unlock() 133 | if i.src == nil { 134 | return 0, io.EOF 135 | } 136 | return i.src.Read(p) 137 | } 138 | 139 | // Add attaches a new source to the input. 140 | // Add can only be called once per input. Subsequent calls will 141 | // return an error. 142 | func (i *Input) Add(src io.Reader) error { 143 | i.Mutex.Lock() 144 | defer i.Mutex.Unlock() 145 | if i.src != nil { 146 | return fmt.Errorf("Maximum number of sources reached: 1") 147 | } 148 | i.src = src 149 | return nil 150 | } 151 | 152 | // Tail reads from `src` line per line, and returns the last `n` lines as an array. 153 | // A ring buffer is used to only store `n` lines at any time. 154 | func Tail(src io.Reader, n int, dst *[]string) { 155 | scanner := bufio.NewScanner(src) 156 | r := ring.New(n) 157 | for scanner.Scan() { 158 | if n == 0 { 159 | continue 160 | } 161 | r.Value = scanner.Text() 162 | r = r.Next() 163 | } 164 | r.Do(func(v interface{}) { 165 | if v == nil { 166 | return 167 | } 168 | *dst = append(*dst, v.(string)) 169 | }) 170 | } 171 | 172 | // AddEnv starts a new goroutine which will decode all subsequent data 173 | // as a stream of json-encoded objects, and point `dst` to the last 174 | // decoded object. 175 | // The result `env` can be queried using the type-neutral Env interface. 176 | // It is not safe to query `env` until the Output is closed. 177 | func (o *Output) AddEnv() (dst *Env, err error) { 178 | src, err := o.AddPipe() 179 | if err != nil { 180 | return nil, err 181 | } 182 | dst = &Env{} 183 | o.tasks.Add(1) 184 | go func() { 185 | defer o.tasks.Done() 186 | decoder := NewDecoder(src) 187 | for { 188 | env, err := decoder.Decode() 189 | if err != nil { 190 | return 191 | } 192 | *dst = *env 193 | } 194 | }() 195 | return dst, nil 196 | } 197 | -------------------------------------------------------------------------------- /vendor/go/src/github.com/mitchellh/goamz/iam/responses_test.go: -------------------------------------------------------------------------------- 1 | package iam_test 2 | 3 | // http://goo.gl/EUIvl 4 | var CreateUserExample = ` 5 | 6 | 7 | 8 | /division_abc/subdivision_xyz/ 9 | Bob 10 | AIDACKCEVSQ6C2EXAMPLE 11 | arn:aws:iam::123456789012:user/division_abc/subdivision_xyz/Bob 12 | 13 | 14 | 15 | 7a62c49f-347e-4fc4-9331-6e8eEXAMPLE 16 | 17 | 18 | ` 19 | 20 | var DuplicateUserExample = ` 21 | 22 | 23 | Sender 24 | EntityAlreadyExists 25 | User with name Bob already exists. 26 | 27 | 1d5f5000-1316-11e2-a60f-91a8e6fb6d21 28 | 29 | ` 30 | 31 | var GetUserExample = ` 32 | 33 | 34 | 35 | /division_abc/subdivision_xyz/ 36 | Bob 37 | AIDACKCEVSQ6C2EXAMPLE 38 | arn:aws:iam::123456789012:user/division_abc/subdivision_xyz/Bob 39 | 40 | 41 | 42 | 7a62c49f-347e-4fc4-9331-6e8eEXAMPLE 43 | 44 | 45 | ` 46 | 47 | var CreateGroupExample = ` 48 | 49 | 50 | 51 | /admins/ 52 | Admins 53 | AGPACKCEVSQ6C2EXAMPLE 54 | arn:aws:iam::123456789012:group/Admins 55 | 56 | 57 | 58 | 7a62c49f-347e-4fc4-9331-6e8eEXAMPLE 59 | 60 | 61 | ` 62 | 63 | var ListGroupsExample = ` 64 | 65 | 66 | 67 | 68 | /division_abc/subdivision_xyz/ 69 | Admins 70 | AGPACKCEVSQ6C2EXAMPLE 71 | arn:aws:iam::123456789012:group/Admins 72 | 73 | 74 | /division_abc/subdivision_xyz/product_1234/engineering/ 75 | Test 76 | AGP2MAB8DPLSRHEXAMPLE 77 | arn:aws:iam::123456789012:group/division_abc/subdivision_xyz/product_1234/engineering/Test 78 | 79 | 80 | /division_abc/subdivision_xyz/product_1234/ 81 | Managers 82 | AGPIODR4TAW7CSEXAMPLE 83 | arn:aws:iam::123456789012:group/division_abc/subdivision_xyz/product_1234/Managers 84 | 85 | 86 | false 87 | 88 | 89 | 7a62c49f-347e-4fc4-9331-6e8eEXAMPLE 90 | 91 | 92 | ` 93 | 94 | var RequestIdExample = ` 95 | 96 | 97 | 7a62c49f-347e-4fc4-9331-6e8eEXAMPLE 98 | 99 | 100 | ` 101 | 102 | var CreateAccessKeyExample = ` 103 | 104 | 105 | 106 | Bob 107 | AKIAIOSFODNN7EXAMPLE 108 | Active 109 | wJalrXUtnFEMI/K7MDENG/bPxRfiCYzEXAMPLEKEY 110 | 111 | 112 | 113 | 7a62c49f-347e-4fc4-9331-6e8eEXAMPLE 114 | 115 | 116 | ` 117 | 118 | var ListAccessKeyExample = ` 119 | 120 | 121 | Bob 122 | 123 | 124 | Bob 125 | AKIAIOSFODNN7EXAMPLE 126 | Active 127 | 128 | 129 | Bob 130 | AKIAI44QH8DHBEXAMPLE 131 | Inactive 132 | 133 | 134 | false 135 | 136 | 137 | 7a62c49f-347e-4fc4-9331-6e8eEXAMPLE 138 | 139 | 140 | ` 141 | 142 | var GetUserPolicyExample = ` 143 | 144 | 145 | Bob 146 | AllAccessPolicy 147 | 148 | {"Statement":[{"Effect":"Allow","Action":"*","Resource":"*"}]} 149 | 150 | 151 | 152 | 7a62c49f-347e-4fc4-9331-6e8eEXAMPLE 153 | 154 | 155 | ` 156 | 157 | var AddUserToGroupExample = ` 158 | 159 | 160 | 7a62c49f-347e-4fc4-9331-6e8eEXAMPLE 161 | 162 | 163 | ` 164 | -------------------------------------------------------------------------------- /vendor/go/src/github.com/mitchellh/goamz/s3/sign_test.go: -------------------------------------------------------------------------------- 1 | package s3_test 2 | 3 | import ( 4 | "github.com/mitchellh/goamz/aws" 5 | "github.com/mitchellh/goamz/s3" 6 | . "github.com/motain/gocheck" 7 | ) 8 | 9 | // S3 ReST authentication docs: http://goo.gl/G1LrK 10 | 11 | var testAuth = aws.Auth{"0PN5J17HBGZHT7JJ3X82", "uV3F3YluFJax1cknvbcGwgjvx4QpvB+leU8dUj2o", ""} 12 | 13 | func (s *S) TestSignExampleObjectGet(c *C) { 14 | method := "GET" 15 | path := "/johnsmith/photos/puppy.jpg" 16 | headers := map[string][]string{ 17 | "Host": {"johnsmith.s3.amazonaws.com"}, 18 | "Date": {"Tue, 27 Mar 2007 19:36:42 +0000"}, 19 | } 20 | s3.Sign(testAuth, method, path, nil, headers) 21 | expected := "AWS 0PN5J17HBGZHT7JJ3X82:xXjDGYUmKxnwqr5KXNPGldn5LbA=" 22 | c.Assert(headers["Authorization"], DeepEquals, []string{expected}) 23 | } 24 | 25 | func (s *S) TestSignExampleObjectPut(c *C) { 26 | method := "PUT" 27 | path := "/johnsmith/photos/puppy.jpg" 28 | headers := map[string][]string{ 29 | "Host": {"johnsmith.s3.amazonaws.com"}, 30 | "Date": {"Tue, 27 Mar 2007 21:15:45 +0000"}, 31 | "Content-Type": {"image/jpeg"}, 32 | "Content-Length": {"94328"}, 33 | } 34 | s3.Sign(testAuth, method, path, nil, headers) 35 | expected := "AWS 0PN5J17HBGZHT7JJ3X82:hcicpDDvL9SsO6AkvxqmIWkmOuQ=" 36 | c.Assert(headers["Authorization"], DeepEquals, []string{expected}) 37 | } 38 | 39 | func (s *S) TestSignExampleList(c *C) { 40 | method := "GET" 41 | path := "/johnsmith/" 42 | params := map[string][]string{ 43 | "prefix": {"photos"}, 44 | "max-keys": {"50"}, 45 | "marker": {"puppy"}, 46 | } 47 | headers := map[string][]string{ 48 | "Host": {"johnsmith.s3.amazonaws.com"}, 49 | "Date": {"Tue, 27 Mar 2007 19:42:41 +0000"}, 50 | "User-Agent": {"Mozilla/5.0"}, 51 | } 52 | s3.Sign(testAuth, method, path, params, headers) 53 | expected := "AWS 0PN5J17HBGZHT7JJ3X82:jsRt/rhG+Vtp88HrYL706QhE4w4=" 54 | c.Assert(headers["Authorization"], DeepEquals, []string{expected}) 55 | } 56 | 57 | func (s *S) TestSignExampleFetch(c *C) { 58 | method := "GET" 59 | path := "/johnsmith/" 60 | params := map[string][]string{ 61 | "acl": {""}, 62 | } 63 | headers := map[string][]string{ 64 | "Host": {"johnsmith.s3.amazonaws.com"}, 65 | "Date": {"Tue, 27 Mar 2007 19:44:46 +0000"}, 66 | } 67 | s3.Sign(testAuth, method, path, params, headers) 68 | expected := "AWS 0PN5J17HBGZHT7JJ3X82:thdUi9VAkzhkniLj96JIrOPGi0g=" 69 | c.Assert(headers["Authorization"], DeepEquals, []string{expected}) 70 | } 71 | 72 | func (s *S) TestSignExampleDelete(c *C) { 73 | method := "DELETE" 74 | path := "/johnsmith/photos/puppy.jpg" 75 | params := map[string][]string{} 76 | headers := map[string][]string{ 77 | "Host": {"s3.amazonaws.com"}, 78 | "Date": {"Tue, 27 Mar 2007 21:20:27 +0000"}, 79 | "User-Agent": {"dotnet"}, 80 | "x-amz-date": {"Tue, 27 Mar 2007 21:20:26 +0000"}, 81 | } 82 | s3.Sign(testAuth, method, path, params, headers) 83 | expected := "AWS 0PN5J17HBGZHT7JJ3X82:k3nL7gH3+PadhTEVn5Ip83xlYzk=" 84 | c.Assert(headers["Authorization"], DeepEquals, []string{expected}) 85 | } 86 | 87 | func (s *S) TestSignExampleUpload(c *C) { 88 | method := "PUT" 89 | path := "/static.johnsmith.net/db-backup.dat.gz" 90 | params := map[string][]string{} 91 | headers := map[string][]string{ 92 | "Host": {"static.johnsmith.net:8080"}, 93 | "Date": {"Tue, 27 Mar 2007 21:06:08 +0000"}, 94 | "User-Agent": {"curl/7.15.5"}, 95 | "x-amz-acl": {"public-read"}, 96 | "content-type": {"application/x-download"}, 97 | "Content-MD5": {"4gJE4saaMU4BqNR0kLY+lw=="}, 98 | "X-Amz-Meta-ReviewedBy": {"joe@johnsmith.net,jane@johnsmith.net"}, 99 | "X-Amz-Meta-FileChecksum": {"0x02661779"}, 100 | "X-Amz-Meta-ChecksumAlgorithm": {"crc32"}, 101 | "Content-Disposition": {"attachment; filename=database.dat"}, 102 | "Content-Encoding": {"gzip"}, 103 | "Content-Length": {"5913339"}, 104 | } 105 | s3.Sign(testAuth, method, path, params, headers) 106 | expected := "AWS 0PN5J17HBGZHT7JJ3X82:C0FlOtU8Ylb9KDTpZqYkZPX91iI=" 107 | c.Assert(headers["Authorization"], DeepEquals, []string{expected}) 108 | } 109 | 110 | func (s *S) TestSignExampleListAllMyBuckets(c *C) { 111 | method := "GET" 112 | path := "/" 113 | headers := map[string][]string{ 114 | "Host": {"s3.amazonaws.com"}, 115 | "Date": {"Wed, 28 Mar 2007 01:29:59 +0000"}, 116 | } 117 | s3.Sign(testAuth, method, path, nil, headers) 118 | expected := "AWS 0PN5J17HBGZHT7JJ3X82:Db+gepJSUbZKwpx1FR0DLtEYoZA=" 119 | c.Assert(headers["Authorization"], DeepEquals, []string{expected}) 120 | } 121 | 122 | func (s *S) TestSignExampleUnicodeKeys(c *C) { 123 | method := "GET" 124 | path := "/dictionary/fran%C3%A7ais/pr%c3%a9f%c3%a8re" 125 | headers := map[string][]string{ 126 | "Host": {"s3.amazonaws.com"}, 127 | "Date": {"Wed, 28 Mar 2007 01:49:49 +0000"}, 128 | } 129 | s3.Sign(testAuth, method, path, nil, headers) 130 | expected := "AWS 0PN5J17HBGZHT7JJ3X82:dxhSBHoI6eVSPcXJqEghlUzZMnY=" 131 | c.Assert(headers["Authorization"], DeepEquals, []string{expected}) 132 | } 133 | 134 | // Not included in AWS documentation 135 | 136 | func (s *S) TestSignWithIAMToken(c *C) { 137 | method := "GET" 138 | path := "/" 139 | headers := map[string][]string{ 140 | "Host": {"s3.amazonaws.com"}, 141 | "Date": {"Wed, 28 Mar 2007 01:29:59 +0000"}, 142 | } 143 | 144 | authWithToken := testAuth 145 | authWithToken.Token = "totallysecret" 146 | 147 | s3.Sign(authWithToken, method, path, nil, headers) 148 | expected := "AWS 0PN5J17HBGZHT7JJ3X82:SJ0yQO7NpHyXJ7zkxY+/fGQ6aUw=" 149 | c.Assert(headers["Authorization"], DeepEquals, []string{expected}) 150 | c.Assert(headers["x-amz-security-token"], DeepEquals, []string{authWithToken.Token}) 151 | } 152 | -------------------------------------------------------------------------------- /vendor/go/src/github.com/fsouza/go-dockerclient/engine/job.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 Docker authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the DOCKER-LICENSE file. 4 | 5 | package engine 6 | 7 | import ( 8 | "fmt" 9 | "io" 10 | "strings" 11 | "time" 12 | ) 13 | 14 | // A job is the fundamental unit of work in the docker engine. 15 | // Everything docker can do should eventually be exposed as a job. 16 | // For example: execute a process in a container, create a new container, 17 | // download an archive from the internet, serve the http api, etc. 18 | // 19 | // The job API is designed after unix processes: a job has a name, arguments, 20 | // environment variables, standard streams for input, output and error, and 21 | // an exit status which can indicate success (0) or error (anything else). 22 | // 23 | // One slight variation is that jobs report their status as a string. The 24 | // string "0" indicates success, and any other strings indicates an error. 25 | // This allows for richer error reporting. 26 | // 27 | type Job struct { 28 | Eng *Engine 29 | Name string 30 | Args []string 31 | env *Env 32 | Stdout *Output 33 | Stderr *Output 34 | Stdin *Input 35 | handler Handler 36 | status Status 37 | end time.Time 38 | onExit []func() 39 | } 40 | 41 | type Status int 42 | 43 | const ( 44 | StatusOK Status = 0 45 | StatusErr Status = 1 46 | StatusNotFound Status = 127 47 | ) 48 | 49 | // Run executes the job and blocks until the job completes. 50 | // If the job returns a failure status, an error is returned 51 | // which includes the status. 52 | func (job *Job) Run() error { 53 | // FIXME: make this thread-safe 54 | // FIXME: implement wait 55 | if !job.end.IsZero() { 56 | return fmt.Errorf("%s: job has already completed", job.Name) 57 | } 58 | // Log beginning and end of the job 59 | job.Eng.Logf("+job %s", job.CallString()) 60 | defer func() { 61 | job.Eng.Logf("-job %s%s", job.CallString(), job.StatusString()) 62 | }() 63 | var errorMessage string 64 | job.Stderr.AddString(&errorMessage) 65 | if job.handler == nil { 66 | job.Errorf("%s: command not found", job.Name) 67 | job.status = 127 68 | } else { 69 | job.status = job.handler(job) 70 | job.end = time.Now() 71 | } 72 | // Wait for all background tasks to complete 73 | if err := job.Stdout.Close(); err != nil { 74 | return err 75 | } 76 | if err := job.Stderr.Close(); err != nil { 77 | return err 78 | } 79 | if job.status != 0 { 80 | return fmt.Errorf("%s: %s", job.Name, errorMessage) 81 | } 82 | return nil 83 | } 84 | 85 | func (job *Job) CallString() string { 86 | return fmt.Sprintf("%s(%s)", job.Name, strings.Join(job.Args, ", ")) 87 | } 88 | 89 | func (job *Job) StatusString() string { 90 | // If the job hasn't completed, status string is empty 91 | if job.end.IsZero() { 92 | return "" 93 | } 94 | var okerr string 95 | if job.status == StatusOK { 96 | okerr = "OK" 97 | } else { 98 | okerr = "ERR" 99 | } 100 | return fmt.Sprintf(" = %s (%d)", okerr, job.status) 101 | } 102 | 103 | // String returns a human-readable description of `job` 104 | func (job *Job) String() string { 105 | return fmt.Sprintf("%s.%s%s", job.Eng, job.CallString(), job.StatusString()) 106 | } 107 | 108 | func (job *Job) Getenv(key string) (value string) { 109 | return job.env.Get(key) 110 | } 111 | 112 | func (job *Job) GetenvBool(key string) (value bool) { 113 | return job.env.GetBool(key) 114 | } 115 | 116 | func (job *Job) SetenvBool(key string, value bool) { 117 | job.env.SetBool(key, value) 118 | } 119 | 120 | func (job *Job) GetenvInt64(key string) int64 { 121 | return job.env.GetInt64(key) 122 | } 123 | 124 | func (job *Job) GetenvInt(key string) int { 125 | return job.env.GetInt(key) 126 | } 127 | 128 | func (job *Job) SetenvInt64(key string, value int64) { 129 | job.env.SetInt64(key, value) 130 | } 131 | 132 | func (job *Job) SetenvInt(key string, value int) { 133 | job.env.SetInt(key, value) 134 | } 135 | 136 | // Returns nil if key not found 137 | func (job *Job) GetenvList(key string) []string { 138 | return job.env.GetList(key) 139 | } 140 | 141 | func (job *Job) GetenvJson(key string, iface interface{}) error { 142 | return job.env.GetJson(key, iface) 143 | } 144 | 145 | func (job *Job) SetenvJson(key string, value interface{}) error { 146 | return job.env.SetJson(key, value) 147 | } 148 | 149 | func (job *Job) SetenvList(key string, value []string) error { 150 | return job.env.SetJson(key, value) 151 | } 152 | 153 | func (job *Job) Setenv(key, value string) { 154 | job.env.Set(key, value) 155 | } 156 | 157 | // DecodeEnv decodes `src` as a json dictionary, and adds 158 | // each decoded key-value pair to the environment. 159 | // 160 | // If `src` cannot be decoded as a json dictionary, an error 161 | // is returned. 162 | func (job *Job) DecodeEnv(src io.Reader) error { 163 | return job.env.Decode(src) 164 | } 165 | 166 | func (job *Job) EncodeEnv(dst io.Writer) error { 167 | return job.env.Encode(dst) 168 | } 169 | 170 | func (job *Job) ExportEnv(dst interface{}) (err error) { 171 | return job.env.Export(dst) 172 | } 173 | 174 | func (job *Job) ImportEnv(src interface{}) (err error) { 175 | return job.env.Import(src) 176 | } 177 | 178 | func (job *Job) Environ() map[string]string { 179 | return job.env.Map() 180 | } 181 | 182 | func (job *Job) Logf(format string, args ...interface{}) (n int, err error) { 183 | prefixedFormat := fmt.Sprintf("[%s] %s\n", job, strings.TrimRight(format, "\n")) 184 | return fmt.Fprintf(job.Stderr, prefixedFormat, args...) 185 | } 186 | 187 | func (job *Job) Printf(format string, args ...interface{}) (n int, err error) { 188 | return fmt.Fprintf(job.Stdout, format, args...) 189 | } 190 | 191 | func (job *Job) Errorf(format string, args ...interface{}) (n int, err error) { 192 | return fmt.Fprintf(job.Stderr, format, args...) 193 | } 194 | 195 | func (job *Job) Error(err error) (int, error) { 196 | return fmt.Fprintf(job.Stderr, "%s", err) 197 | } 198 | -------------------------------------------------------------------------------- /vendor/go/src/code.google.com/p/gcfg/doc.go: -------------------------------------------------------------------------------- 1 | // Package gcfg reads "INI-style" text-based configuration files with 2 | // "name=value" pairs grouped into sections (gcfg files). 3 | // 4 | // This package is still a work in progress; see the sections below for planned 5 | // changes. 6 | // 7 | // Syntax 8 | // 9 | // The syntax is based on that used by git config: 10 | // http://git-scm.com/docs/git-config#_syntax . 11 | // There are some (planned) differences compared to the git config format: 12 | // - improve data portability: 13 | // - must be encoded in UTF-8 (for now) and must not contain the 0 byte 14 | // - include and "path" type is not supported 15 | // (path type may be implementable as a user-defined type) 16 | // - internationalization 17 | // - section and variable names can contain unicode letters, unicode digits 18 | // (as defined in http://golang.org/ref/spec#Characters ) and hyphens 19 | // (U+002D), starting with a unicode letter 20 | // - disallow potentially ambiguous or misleading definitions: 21 | // - `[sec.sub]` format is not allowed (deprecated in gitconfig) 22 | // - `[sec ""]` is not allowed 23 | // - use `[sec]` for section name "sec" and empty subsection name 24 | // - (planned) within a single file, definitions must be contiguous for each: 25 | // - section: '[secA]' -> '[secB]' -> '[secA]' is an error 26 | // - subsection: '[sec "A"]' -> '[sec "B"]' -> '[sec "A"]' is an error 27 | // - multivalued variable: 'multi=a' -> 'other=x' -> 'multi=b' is an error 28 | // 29 | // Data structure 30 | // 31 | // The functions in this package read values into a user-defined struct. 32 | // Each section corresponds to a struct field in the config struct, and each 33 | // variable in a section corresponds to a data field in the section struct. 34 | // The mapping of each section or variable name to fields is done either based 35 | // on the "gcfg" struct tag or by matching the name of the section or variable, 36 | // ignoring case. In the latter case, hyphens '-' in section and variable names 37 | // correspond to underscores '_' in field names. 38 | // Fields must be exported; to use a section or variable name starting with a 39 | // letter that is neither upper- or lower-case, prefix the field name with 'X'. 40 | // (See https://code.google.com/p/go/issues/detail?id=5763#c4 .) 41 | // 42 | // For sections with subsections, the corresponding field in config must be a 43 | // map, rather than a struct, with string keys and pointer-to-struct values. 44 | // Values for subsection variables are stored in the map with the subsection 45 | // name used as the map key. 46 | // (Note that unlike section and variable names, subsection names are case 47 | // sensitive.) 48 | // When using a map, and there is a section with the same section name but 49 | // without a subsection name, its values are stored with the empty string used 50 | // as the key. 51 | // 52 | // The functions in this package panic if config is not a pointer to a struct, 53 | // or when a field is not of a suitable type (either a struct or a map with 54 | // string keys and pointer-to-struct values). 55 | // 56 | // Parsing of values 57 | // 58 | // The section structs in the config struct may contain single-valued or 59 | // multi-valued variables. Variables of unnamed slice type (that is, a type 60 | // starting with `[]`) are treated as multi-value; all others (including named 61 | // slice types) are treated as single-valued variables. 62 | // 63 | // Single-valued variables are handled based on the type as follows. 64 | // Unnamed pointer types (that is, types starting with `*`) are dereferenced, 65 | // and if necessary, a new instance is allocated. 66 | // 67 | // For types implementing the encoding.TextUnmarshaler interface, the 68 | // UnmarshalText method is used to set the value. Implementing this method is 69 | // the recommended way for parsing user-defined types. 70 | // 71 | // For fields of string kind, the value string is assigned to the field, after 72 | // unquoting and unescaping as needed. 73 | // For fields of bool kind, the field is set to true if the value is "true", 74 | // "yes", "on" or "1", and set to false if the value is "false", "no", "off" or 75 | // "0", ignoring case. In addition, single-valued bool fields can be specified 76 | // with a "blank" value (variable name without equals sign and value); in such 77 | // case the value is set to true. 78 | // 79 | // Predefined integer types [u]int(|8|16|32|64) and big.Int are parsed as 80 | // decimal or hexadecimal (if having '0x' prefix). (This is to prevent 81 | // unintuitively handling zero-padded numbers as octal.) Other types having 82 | // [u]int* as the underlying type, such as os.FileMode and uintptr allow 83 | // decimal, hexadecimal, or octal values. 84 | // Parsing mode for integer types can be overridden using the struct tag option 85 | // ",int=mode" where mode is a combination of the 'd', 'h', and 'o' characters 86 | // (each standing for decimal, hexadecimal, and octal, respectively.) 87 | // 88 | // All other types are parsed using fmt.Sscanf with the "%v" verb. 89 | // 90 | // For multi-valued variables, each individual value is parsed as above and 91 | // appended to the slice. If the first value is specified as a "blank" value 92 | // (variable name without equals sign and value), a new slice is allocated; 93 | // that is any values previously set in the slice will be ignored. 94 | // 95 | // The types subpackage for provides helpers for parsing "enum-like" and integer 96 | // types. 97 | // 98 | // TODO 99 | // 100 | // The following is a list of changes under consideration: 101 | // - documentation 102 | // - self-contained syntax documentation 103 | // - more practical examples 104 | // - move TODOs to issue tracker (eventually) 105 | // - syntax 106 | // - reconsider valid escape sequences 107 | // (gitconfig doesn't support \r in value, \t in subsection name, etc.) 108 | // - reading / parsing gcfg files 109 | // - define internal representation structure 110 | // - support multiple inputs (readers, strings, files) 111 | // - support declaring encoding (?) 112 | // - support varying fields sets for subsections (?) 113 | // - writing gcfg files 114 | // - error handling 115 | // - make error context accessible programmatically? 116 | // - limit input size? 117 | // 118 | package gcfg 119 | --------------------------------------------------------------------------------