diff options
author | 2019-01-03 13:55:15 -0800 | |
---|---|---|
committer | 2019-01-03 13:55:15 -0800 | |
commit | 2bf0f688f895aa19f976051e30b967a6187e27b4 (patch) | |
tree | 6e3425e59eafaf05546e348bd2182a08a7fbe0f0 | |
parent | a3b25c3f7761b0c8d4cd3871e335a32a929f8dda (diff) | |
download | sally-2bf0f688f895aa19f976051e30b967a6187e27b4.tar.gz sally-2bf0f688f895aa19f976051e30b967a6187e27b4.tar.zst sally-2bf0f688f895aa19f976051e30b967a6187e27b4.zip |
template: Bundle in binary with bindata (#36)
This uses go-bindata/go-bindata to bundle the template in the binary.
I also realized that the handler test was now broken because we were
checking the exact contents of the index page in the test. This change
fixes that too.
-rw-r--r-- | CHANGELOG.md | 7 | ||||
-rw-r--r-- | Dockerfile.scratch | 1 | ||||
-rw-r--r-- | Makefile | 7 | ||||
-rw-r--r-- | bindata.go | 258 | ||||
-rw-r--r-- | go.mod | 1 | ||||
-rw-r--r-- | go.sum | 3 | ||||
-rw-r--r-- | handler.go | 17 | ||||
-rw-r--r-- | handler_test.go | 22 | ||||
-rw-r--r-- | tools.go | 1 |
9 files changed, 293 insertions, 24 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index 4786b15..32aa730 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,13 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [Unreleased] +### Fixed +- Templates are now bundled with the binary rather than requiring a copy of the + sally source. + ## 1.0.0 - 2019-01-03 - Initial tagged release. + +[Unreleased]: https://github.com/uber-go/sally/compare/v1.0.0...HEAD diff --git a/Dockerfile.scratch b/Dockerfile.scratch index f6cf130..f78f304 100644 --- a/Dockerfile.scratch +++ b/Dockerfile.scratch @@ -3,5 +3,4 @@ FROM scratch EXPOSE 8080 ADD sally.yaml / ADD _tmp/sally / -ADD templates /templates ENTRYPOINT ["/sally"] @@ -1,5 +1,6 @@ GOLINT = go run github.com/golang/lint/golint STATICCHECK = go run honnef.co/go/tools/cmd/staticcheck +GOBINDATA = go run github.com/go-bindata/go-bindata/go-bindata .PHONY: all all: test @@ -8,6 +9,12 @@ all: test build: go build +.PHONY: generate +generate: bindata.go + +bindata.go: templates/* + $(GOBINDATA) templates + .PHONY: install install: go install . diff --git a/bindata.go b/bindata.go new file mode 100644 index 0000000..a2b1492 --- /dev/null +++ b/bindata.go @@ -0,0 +1,258 @@ +// Code generated by go-bindata. DO NOT EDIT. +// sources: +// templates/index.html +// templates/package.html +package main + +import ( + "bytes" + "compress/gzip" + "fmt" + "io" + "io/ioutil" + "os" + "path/filepath" + "strings" + "time" +) + +func bindataRead(data []byte, name string) ([]byte, error) { + gz, err := gzip.NewReader(bytes.NewBuffer(data)) + if err != nil { + return nil, fmt.Errorf("Read %q: %v", name, err) + } + + var buf bytes.Buffer + _, err = io.Copy(&buf, gz) + clErr := gz.Close() + + if err != nil { + return nil, fmt.Errorf("Read %q: %v", name, err) + } + if clErr != nil { + return nil, err + } + + return buf.Bytes(), nil +} + +type asset struct { + bytes []byte + info os.FileInfo +} + +type bindataFileInfo struct { + name string + size int64 + mode os.FileMode + modTime time.Time +} + +func (fi bindataFileInfo) Name() string { + return fi.name +} +func (fi bindataFileInfo) Size() int64 { + return fi.size +} +func (fi bindataFileInfo) Mode() os.FileMode { + return fi.mode +} +func (fi bindataFileInfo) ModTime() time.Time { + return fi.modTime +} +func (fi bindataFileInfo) IsDir() bool { + return false +} +func (fi bindataFileInfo) Sys() interface{} { + return nil +} + +var _templatesIndexHtml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xac\x54\x3f\x6f\xdb\x3e\x10\xdd\x7f\x9f\xe2\x7e\x84\xb3\x35\xbc\xa2\xe8\x14\xd0\xee\x50\x17\x5d\x0a\xd4\x48\xdb\xa1\x23\x4d\x9e\x25\xc6\x14\x69\x90\x27\xa5\x46\xa0\xef\x5e\x58\x72\xe2\x44\xae\xe4\x00\xad\x16\x89\xba\xf7\xde\xfd\xe5\xa9\xff\x97\x5f\x3f\x7e\xff\xb9\xfa\x04\x25\x57\x7e\xf1\x9f\xea\x5f\x00\x00\xaa\x24\x6d\xfb\xcf\xee\xe8\x5d\xd8\x42\x22\x3f\x17\x99\xf7\x9e\x72\x49\xc4\x02\xca\x44\x9b\xb9\x28\x99\x77\xf9\x06\xd1\xd8\x70\x97\xa5\xf1\xb1\xb6\x1b\xaf\x13\x49\x13\x2b\xd4\x77\xfa\x17\x7a\xb7\xce\x98\xb7\xe4\x89\x63\xc0\x77\xf2\xad\x7c\xff\x74\x94\x95\x0b\xd2\xe4\x2c\x00\x8f\xae\xf1\xe4\x5b\xad\xa3\xdd\x3f\x0b\xc3\xba\x06\x8c\xd7\x39\xcf\x85\x89\x81\xb5\x0b\x94\xc4\xc9\x3e\xc4\xa4\x78\x3f\xb0\x76\x08\xd6\x6b\x4f\x8f\x98\xfa\x7a\x53\x7b\x7f\x7d\xef\x2c\x97\x7f\x00\xf7\x84\x97\xd5\x38\xb7\xa7\x71\xe3\x51\x60\xb1\xd2\x66\xab\x0b\x52\xc8\xe5\x65\xf0\xb7\x58\x27\xf3\x4a\xec\x32\x9a\xba\xa2\xc0\x9a\x5d\x0c\xd3\x14\x85\x63\x91\x1e\x78\xa3\x39\x2a\x7e\xd9\x86\xe1\xf3\xf0\x00\x49\x87\x82\x60\xb6\xa5\xfd\x1b\x98\x35\xda\xd7\x04\x37\x73\x90\xc7\xa4\x33\xb4\xed\x14\x7b\xe6\xaa\x5d\x4c\xbc\xd2\x5c\x1e\x68\xbb\xe4\x02\x6f\x40\x5c\x35\x78\xd5\x08\x98\xc9\x1f\xb7\x5f\x3a\xed\x29\x99\x57\x34\xc1\x2e\x06\xbe\xda\x56\x21\x4f\x34\xf6\x91\x36\x09\xe8\x40\xfa\x78\x17\x10\x0f\x2e\xba\x02\xc8\x5b\xda\x45\x68\x5b\xb1\x38\xfb\xa5\x50\x5f\x70\xfa\xcf\xc3\x2a\xa2\x8d\x46\xc6\x54\xe0\x59\x0d\x46\xa6\xfe\x4c\xcc\x55\x05\xe4\x64\x2e\xa8\x7d\xc8\xac\xb9\xce\x32\x37\x85\x00\xed\x79\x2e\x3e\xc7\x65\x34\x4f\xd7\x7b\x3a\xed\xbf\xaa\xcb\xf8\x78\x43\x3f\x67\x14\xec\xd8\x08\x29\x1c\x19\x72\x85\xdd\xba\x18\x2c\x19\xb4\xae\x79\xb6\x97\x4e\x47\x85\xbd\x8c\xc2\x7e\x99\xfe\x0e\x00\x00\xff\xff\xb1\x54\x5d\xd8\x64\x05\x00\x00") + +func templatesIndexHtmlBytes() ([]byte, error) { + return bindataRead( + _templatesIndexHtml, + "templates/index.html", + ) +} + +func templatesIndexHtml() (*asset, error) { + bytes, err := templatesIndexHtmlBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "templates/index.html", size: 1380, mode: os.FileMode(420), modTime: time.Unix(1546544917, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +var _templatesPackageHtml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x8c\xd1\x3f\x4f\xf3\x30\x10\x06\xf0\xfd\xfd\x14\xf7\x86\xb9\x35\x33\x38\x5d\x0a\x62\xa9\xa0\xaa\x60\x60\x34\xc9\xd3\xd8\x92\xed\x0b\xf6\xa5\x12\x8a\xf2\xdd\x51\x70\xa5\x82\x28\x82\xc9\x7f\xf5\xbb\x47\x77\xfa\xff\xcd\xc3\xfa\xf1\x79\x7b\x4b\x56\x82\x5f\xfd\xd3\x65\x21\x22\xd2\x16\xa6\x2d\xdb\x8f\x63\x80\x18\x8a\x26\xa0\xae\x3a\x5e\xb8\xd0\x73\x92\x8a\x1a\x8e\x82\x28\x75\x35\x8e\xb4\x5c\x9b\xc8\xd1\x35\xc6\x3f\xed\x36\x34\x4d\xd4\x39\x21\x2b\xd2\xe7\x2b\xa5\xe6\xf7\x1d\x7a\xa6\x69\xaa\x7e\x54\x33\x0f\xa9\xc1\x2f\xea\x19\xf1\xdc\x9d\x92\x04\xa8\x60\xb2\x20\x8d\xaa\x75\xe9\x8f\xbf\xd4\xb8\x77\x1e\xd3\xc5\x66\xf4\x2e\xe2\x7b\xd8\x19\x59\xe0\x75\x70\x87\xba\x4a\xd8\x27\x64\xfb\x29\xf0\xe5\x35\x0d\xc9\xd7\x73\x85\x3b\x6e\xb9\x29\x99\x8f\x88\x56\xa7\x9e\xea\x17\x6e\xdf\x4e\xf6\x3d\x8b\x75\xb1\x23\x61\xca\x00\x59\x24\x2c\x69\xeb\x61\x32\x48\x1b\xb2\x09\xfb\xd2\x8d\x2f\x6a\xe0\x03\xc8\x78\x8e\x9d\x56\x66\xb5\x3c\x16\x29\xb2\x56\x65\x96\xef\x01\x00\x00\xff\xff\x69\xc7\x6b\xa3\xe3\x01\x00\x00") + +func templatesPackageHtmlBytes() ([]byte, error) { + return bindataRead( + _templatesPackageHtml, + "templates/package.html", + ) +} + +func templatesPackageHtml() (*asset, error) { + bytes, err := templatesPackageHtmlBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "templates/package.html", size: 483, mode: os.FileMode(420), modTime: time.Unix(1546544917, 0)} + a := &asset{bytes: bytes, info: info} + return a, nil +} + +// Asset loads and returns the asset for the given name. +// It returns an error if the asset could not be found or +// could not be loaded. +func Asset(name string) ([]byte, error) { + cannonicalName := strings.Replace(name, "\\", "/", -1) + if f, ok := _bindata[cannonicalName]; ok { + a, err := f() + if err != nil { + return nil, fmt.Errorf("Asset %s can't read by error: %v", name, err) + } + return a.bytes, nil + } + return nil, fmt.Errorf("Asset %s not found", name) +} + +// MustAsset is like Asset but panics when Asset would return an error. +// It simplifies safe initialization of global variables. +func MustAsset(name string) []byte { + a, err := Asset(name) + if err != nil { + panic("asset: Asset(" + name + "): " + err.Error()) + } + + return a +} + +// AssetInfo loads and returns the asset info for the given name. +// It returns an error if the asset could not be found or +// could not be loaded. +func AssetInfo(name string) (os.FileInfo, error) { + cannonicalName := strings.Replace(name, "\\", "/", -1) + if f, ok := _bindata[cannonicalName]; ok { + a, err := f() + if err != nil { + return nil, fmt.Errorf("AssetInfo %s can't read by error: %v", name, err) + } + return a.info, nil + } + return nil, fmt.Errorf("AssetInfo %s not found", name) +} + +// AssetNames returns the names of the assets. +func AssetNames() []string { + names := make([]string, 0, len(_bindata)) + for name := range _bindata { + names = append(names, name) + } + return names +} + +// _bindata is a table, holding each asset generator, mapped to its name. +var _bindata = map[string]func() (*asset, error){ + "templates/index.html": templatesIndexHtml, + "templates/package.html": templatesPackageHtml, +} + +// AssetDir returns the file names below a certain +// directory embedded in the file by go-bindata. +// For example if you run go-bindata on data/... and data contains the +// following hierarchy: +// data/ +// foo.txt +// img/ +// a.png +// b.png +// then AssetDir("data") would return []string{"foo.txt", "img"} +// AssetDir("data/img") would return []string{"a.png", "b.png"} +// AssetDir("foo.txt") and AssetDir("notexist") would return an error +// AssetDir("") will return []string{"data"}. +func AssetDir(name string) ([]string, error) { + node := _bintree + if len(name) != 0 { + cannonicalName := strings.Replace(name, "\\", "/", -1) + pathList := strings.Split(cannonicalName, "/") + for _, p := range pathList { + node = node.Children[p] + if node == nil { + return nil, fmt.Errorf("Asset %s not found", name) + } + } + } + if node.Func != nil { + return nil, fmt.Errorf("Asset %s not found", name) + } + rv := make([]string, 0, len(node.Children)) + for childName := range node.Children { + rv = append(rv, childName) + } + return rv, nil +} + +type bintree struct { + Func func() (*asset, error) + Children map[string]*bintree +} +var _bintree = &bintree{nil, map[string]*bintree{ + "templates": &bintree{nil, map[string]*bintree{ + "index.html": &bintree{templatesIndexHtml, map[string]*bintree{}}, + "package.html": &bintree{templatesPackageHtml, map[string]*bintree{}}, + }}, +}} + +// RestoreAsset restores an asset under the given directory +func RestoreAsset(dir, name string) error { + data, err := Asset(name) + if err != nil { + return err + } + info, err := AssetInfo(name) + if err != nil { + return err + } + err = os.MkdirAll(_filePath(dir, filepath.Dir(name)), os.FileMode(0755)) + if err != nil { + return err + } + err = ioutil.WriteFile(_filePath(dir, name), data, info.Mode()) + if err != nil { + return err + } + err = os.Chtimes(_filePath(dir, name), info.ModTime(), info.ModTime()) + if err != nil { + return err + } + return nil +} + +// RestoreAssets restores an asset under the given directory recursively +func RestoreAssets(dir, name string) error { + children, err := AssetDir(name) + // File + if err != nil { + return RestoreAsset(dir, name) + } + // Dir + for _, child := range children { + err = RestoreAssets(dir, filepath.Join(name, child)) + if err != nil { + return err + } + } + return nil +} + +func _filePath(dir, name string) string { + cannonicalName := strings.Replace(name, "\\", "/", -1) + return filepath.Join(append([]string{dir}, strings.Split(cannonicalName, "/")...)...) +} + @@ -2,6 +2,7 @@ module go.uber.org/sally require ( github.com/davecgh/go-spew v1.1.1 // indirect + github.com/go-bindata/go-bindata v1.0.0 github.com/golang/lint v0.0.0-20181217174547-8f45f776aaf1 github.com/julienschmidt/httprouter v1.2.0 github.com/kisielk/gotool v1.0.0 // indirect @@ -1,5 +1,7 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/go-bindata/go-bindata v1.0.0 h1:upAQEGKG3hFv00/4cU/VhzF+NpCHz+Jk3rO946wWr+A= +github.com/go-bindata/go-bindata v1.0.0/go.mod h1:xK8Dsgwmeed+BBsSy2XTopBn/8uK2HWuGSnA11C3Joo= github.com/golang/lint v0.0.0-20181217174547-8f45f776aaf1 h1:6DVPu65tee05kY0/rciBQ47ue+AnuY8KTayV6VHikIo= github.com/golang/lint v0.0.0-20181217174547-8f45f776aaf1/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E= github.com/julienschmidt/httprouter v1.2.0 h1:TDTW5Yz1mjftljbcKqRcrYhd4XeOoI98t+9HbQbYf7g= @@ -11,6 +13,7 @@ github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORN github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= @@ -8,17 +8,12 @@ import ( "github.com/julienschmidt/httprouter" ) -var indexTemplate, packageTemplate *template.Template - -func init() { - tmpls := template.Must(template.ParseGlob("templates/*.html")) - if indexTemplate = tmpls.Lookup("index.html"); indexTemplate == nil { - panic("Missing index.html template") - } - if packageTemplate = tmpls.Lookup("package.html"); packageTemplate == nil { - panic("Missing package.html template") - } -} +var ( + indexTemplate = template.Must( + template.New("index.html").Parse(string(MustAsset("templates/index.html")))) + packageTemplate = template.Must( + template.New("package.html").Parse(string(MustAsset("templates/package.html")))) +) // CreateHandler creates a Sally http.Handler func CreateHandler(config *Config) http.Handler { diff --git a/handler_test.go b/handler_test.go index ce5e290..ab8cd67 100644 --- a/handler_test.go +++ b/handler_test.go @@ -1,6 +1,10 @@ package main -import "testing" +import ( + "testing" + + "github.com/stretchr/testify/assert" +) var config = ` @@ -15,17 +19,11 @@ packages: func TestIndex(t *testing.T) { rr := CallAndRecord(t, config, "/") - AssertResponse(t, rr, 200, ` -<!DOCTYPE html> -<html> - <body> - <ul> - <li>thriftrw - github.com/thriftrw/thriftrw-go</li> - <li>yarpc - github.com/yarpc/yarpc-go</li> - </ul> - </body> -</html> -`) + assert.Equal(t, 200, rr.Code) + + body := rr.Body.String() + assert.Contains(t, body, "github.com/thriftrw/thriftrw-go") + assert.Contains(t, body, "github.com/yarpc/yarpc-go") } func TestPackageShouldExist(t *testing.T) { @@ -3,6 +3,7 @@ package main import ( + _ "github.com/go-bindata/go-bindata/go-bindata" _ "github.com/golang/lint/golint" _ "honnef.co/go/tools/cmd/staticcheck" ) |