diff --git a/.dockerignore b/.dockerignore index e217e1960e..5be06200f3 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,3 +1,4 @@ * !image +!intercept !entrypoint.sh diff --git a/Makefile b/Makefile index a11a9d2102..79a81fa5b0 100644 --- a/Makefile +++ b/Makefile @@ -1,13 +1,14 @@ NAME=ambassador-ratelimit PROFILE ?= dev +include config.mk include build-aux/common.mk include build-aux/go-mod.mk +include build-aux/go-version.mk include build-aux/help.mk include build-aux/teleproxy.mk include build-aux/kubernaut-ui.mk include build-aux/kubeapply.mk - include build-aux/k8s.mk export PATH:=$(CURDIR)/bin_$(GOOS)_$(GOARCH):$(PATH) @@ -40,10 +41,10 @@ build-image: $(addprefix image/,$(notdir $(go.bins))) image/%: bin_linux_amd64/% @mkdir -p $(@D) cp $< $@ -docker: env build-image +docker: build-image docker build . -t $(RATELIMIT_IMAGE) - docker build intercept --target telepresence-proxy -t $(PROXY_IMAGE) - docker build intercept --target telepresence-sidecar -t $(SIDECAR_IMAGE) + docker build . -f intercept/Dockerfile --target telepresence-proxy -t $(PROXY_IMAGE) + docker build . -f intercept/Dockerfile --target telepresence-sidecar -t $(SIDECAR_IMAGE) .PHONY: docker # Utility targets @@ -51,5 +52,5 @@ docker-run: docker docker run -it $(IMAGE) .PHONY: docker-run -clean: $(CLUSTER).clean +clean: rm -rf image diff --git a/build-aux/env.go b/build-aux/env.go deleted file mode 100644 index 849d633c7e..0000000000 --- a/build-aux/env.go +++ /dev/null @@ -1,165 +0,0 @@ -// +build ignore - -package main - -import ( - "crypto/md5" - "encoding/json" - "flag" - "fmt" - "io" - "io/ioutil" - "os" - "os/exec" - "path/filepath" - "strconv" - "strings" -) - -var Verbose bool - -type Environ map[string]string -type Config struct { - Unversioned []string - Profiles map[string]Environ -} - -func die(err error, args ...interface{}) { - if err != nil { - if args != nil { - panic(fmt.Errorf("%v: %v", err, args)) - } else { - panic(err) - } - } -} - -func main() { - verb := os.Getenv("VERBOSE") - if verb != "" { - var err error - Verbose, err = strconv.ParseBool(verb) - if err != nil { - fmt.Printf("warning: unable to parse VERBOSE=%s as bool\n", verb) - } - } - - var profile = flag.String("profile", "dev", "profile") - var output = flag.String("output", "", "output file") - var input = flag.String("input", "", "input file") - var newline = flag.String("newline", "\n", "string to use for newline") - flag.Parse() - - var err error - var in *os.File - if *input != "" { - in, err = os.Open(*input) - defer in.Close() - } else { - in = os.Stdin - } - - var out *os.File - if *output != "" { - out, err := os.Create(*output) - die(err) - defer out.Close() - } else { - out = os.Stdout - } - - bytes, err := ioutil.ReadAll(in) - die(err) - - var config Config - err = json.Unmarshal(bytes, &config) - die(err) - - current, ok := config.Profiles[*profile] - if !ok { - panic("no such profile: " + *profile) - } - - out.WriteString(fmt.Sprintf("PROFILE=%s%s", *profile, *newline)) - - combined := make(map[string]string) - - for k, v := range config.Profiles["default"] { - combined[k] = v - } - for k, v := range current { - combined[k] = v - } - - for k, v := range combined { - out.WriteString(fmt.Sprintf("%s=%s%s", k, v, *newline)) - } - - out.WriteString(fmt.Sprintf("HASH=%x%s", hash(config.Unversioned), *newline)) -} - -func versioned(path string, excludes []string) bool { - for _, ex := range excludes { - m, err := filepath.Match(ex, path) - die(err) - if m { - return false - } - } - return true -} - -func hash(unversioned []string) []byte { - standard, err := shell("git ls-files --exclude-standard") - die(err) - others, err := shell("git ls-files --exclude-standard --others") - die(err) - - files := append(standard, others...) - - h := md5.New() - for _, file := range files { - if strings.TrimSpace(file) == "" { - continue - } - if !versioned(file, unversioned) { - if Verbose { - fmt.Printf("skipping %s\n", file) - } - continue - } - if Verbose { - fmt.Printf("hashing %s\n", file) - } - h.Write([]byte(file)) - info, err := os.Lstat(file) - if err != nil { - h.Write([]byte("error")) - h.Write([]byte(err.Error())) - } else { - if info.Mode()&os.ModeSymlink != 0 { - target, err := os.Readlink(file) - die(err) - h.Write([]byte("link")) - h.Write([]byte(target)) - } else if !info.IsDir() { - h.Write([]byte("file")) - f, err := os.Open(file) - die(err, file) - _, err = io.Copy(h, f) - f.Close() - die(err) - } - } - } - - return h.Sum(nil) -} - -func shell(command string) ([]string, error) { - cmd := exec.Command("sh", "-c", command) - out, err := cmd.CombinedOutput() - str := string(out) - lines := strings.Split(str, "\n") - return lines, err -} diff --git a/build-aux/go-version.mk b/build-aux/go-version.mk index 42d739d43c..19ab565909 100644 --- a/build-aux/go-version.mk +++ b/build-aux/go-version.mk @@ -8,9 +8,8 @@ ## Outputs ## # - Variable: go.LDFLAGS += … ifeq ($(words $(filter $(abspath $(lastword $(MAKEFILE_LIST))),$(abspath $(MAKEFILE_LIST)))),1) -include $(dir $(lastword $(MAKEFILE_LIST)))common.mk +include $(dir $(lastword $(MAKEFILE_LIST)))version.mk -VERSION ?= $(patsubst v%,%,$(shell git describe --tags --always --dirty)) go.LDFLAGS += -X main.Version=$(VERSION) endif diff --git a/build-aux/k8s.mk b/build-aux/k8s.mk index c64d8d0999..b2b2258a3d 100644 --- a/build-aux/k8s.mk +++ b/build-aux/k8s.mk @@ -2,24 +2,13 @@ ifeq ($(words $(filter $(abspath $(lastword $(MAKEFILE_LIST))),$(abspath $(MAKEF include $(dir $(lastword $(MAKEFILE_LIST)))kubernaut-ui.mk include $(dir $(lastword $(MAKEFILE_LIST)))kubeapply.mk -PROFILE?=dev - IMAGE_VARS=$(filter %_IMAGE,$(.VARIABLES)) IMAGES=$(foreach var,$(IMAGE_VARS),$($(var))) IMAGE_DEFS=$(foreach var,$(IMAGE_VARS),$(var)=$($(var))$(NL)) IMAGE_DEFS_SH="$(subst $(SPACE),\n,$(foreach var,$(IMAGE_VARS),$(var)=$($(var))))\n" MANIFESTS?=$(wildcard k8s/*.yaml) -env: - $(eval $(subst @NL,$(NL), $(shell go run build-aux/env.go -profile $(PROFILE) -newline "@NL" -input config.json))) -.PHONY: env - -hash: ## Show the computed version hash. The hash is based on non gitignored files. -hash: env - @echo HASH=$(HASH) -.PHONY: hash - -push_ok: env +push_ok: @if [ "$(PROFILE)" == "prod" ]; then echo "CANNOT PUSH TO PROD"; exit 1; fi .PHONY: push_ok diff --git a/build-aux/kubernaut.mk b/build-aux/kubernaut.mk index 7e2cd6e9ad..659eb4e2b6 100644 --- a/build-aux/kubernaut.mk +++ b/build-aux/kubernaut.mk @@ -46,9 +46,10 @@ # clean: test-cluster.knaut.clean # ifeq ($(words $(filter $(abspath $(lastword $(MAKEFILE_LIST))),$(abspath $(MAKEFILE_LIST)))),1) +_kubernaut.mk := $(lastword $(MAKEFILE_LIST)) include $(dir $(lastword $(MAKEFILE_LIST)))common.mk -GUBERNAUT = GO111MODULE=off go run build-aux/gubernaut.go +GUBERNAUT = GO111MODULE=off go run $(dir $(_kubernaut.mk))gubernaut.go %.knaut.claim: echo $(subst /,_,$*)-$${USER}-$$(uuidgen) > $@ diff --git a/build-aux/version.go b/build-aux/version.go new file mode 100644 index 0000000000..98216b5075 --- /dev/null +++ b/build-aux/version.go @@ -0,0 +1,77 @@ +// +build ignore + +package main + +import ( + "crypto/md5" + "fmt" + "io" + "os" + "os/exec" + "strings" +) + +var Verbose bool + +func die(err error, args ...interface{}) { + if err != nil { + if args != nil { + panic(fmt.Errorf("%v: %v", err, args)) + } else { + panic(err) + } + } +} + +func main() { + fmt.Printf("%x\n", hash()) +} + +func hash() []byte { + standard, err := shell("git ls-files --exclude-standard") + die(err) + others, err := shell("git ls-files --exclude-standard --others") + die(err) + + files := append(standard, others...) + + h := md5.New() + for _, file := range files { + if strings.TrimSpace(file) == "" { + continue + } + if Verbose { + fmt.Printf("hashing %s\n", file) + } + h.Write([]byte(file)) + info, err := os.Lstat(file) + if err != nil { + h.Write([]byte("error")) + h.Write([]byte(err.Error())) + } else { + if info.Mode()&os.ModeSymlink != 0 { + target, err := os.Readlink(file) + die(err) + h.Write([]byte("link")) + h.Write([]byte(target)) + } else if !info.IsDir() { + h.Write([]byte("file")) + f, err := os.Open(file) + die(err, file) + _, err = io.Copy(h, f) + f.Close() + die(err) + } + } + } + + return h.Sum(nil) +} + +func shell(command string) ([]string, error) { + cmd := exec.Command("sh", "-c", command) + out, err := cmd.CombinedOutput() + str := string(out) + lines := strings.Split(str, "\n") + return lines, err +} diff --git a/build-aux/version.mk b/build-aux/version.mk new file mode 100644 index 0000000000..3887316b2e --- /dev/null +++ b/build-aux/version.mk @@ -0,0 +1,16 @@ +# Copyright 2018 Datawire. All rights reserved. +# +# Makefile snippet for automatically setting VERSION. +# +## Inputs ## +# (none) +## Outputs ## +# - Variable: VERSION +ifeq ($(words $(filter $(abspath $(lastword $(MAKEFILE_LIST))),$(abspath $(MAKEFILE_LIST)))),1) +_version.mk := $(lastword $(MAKEFILE_LIST)) + +VERSION ?= $(patsubst v%,%,$(shell git describe --tags --always))$(if $(shell git status -s),-dirty$(_version.dirty_hash)) + +_version.dirty_hash = $(shell GO111MODULE=off go run $(dir $(_version.mk))version.go) + +endif diff --git a/cmd/apictl-key/main.go b/cmd/apictl-key/main.go index 121d278574..3abbbe180c 100644 --- a/cmd/apictl-key/main.go +++ b/cmd/apictl-key/main.go @@ -8,6 +8,9 @@ var apictl_key = &cobra.Command{ Use: "apictl-key [command]", } +// Version is inserted at build using --ldflags -X +var Version = "(unknown version)" + func main() { apictl_key.Execute() } diff --git a/cmd/apictl-key/version.go b/cmd/apictl-key/version.go new file mode 100644 index 0000000000..7166e0ab3a --- /dev/null +++ b/cmd/apictl-key/version.go @@ -0,0 +1,21 @@ +package main + +import ( + "fmt" + + "github.com/spf13/cobra" +) + +var version = &cobra.Command{ + Use: "version", + Short: "Show the program's version number", + Run: showVersion, +} + +func init() { + apictl_key.AddCommand(version) +} + +func showVersion(cmd *cobra.Command, args []string) { + fmt.Println(Version) +} diff --git a/cmd/apictl/main.go b/cmd/apictl/main.go index 2c3b41a8dd..3cbdc71e61 100644 --- a/cmd/apictl/main.go +++ b/cmd/apictl/main.go @@ -22,9 +22,8 @@ var apictl = &cobra.Command{ PersistentPreRun: keyCheck, } -const ( - VERSION = "0.0.8" -) +// Version is inserted at build using --ldflags -X +var Version = "(unknown version)" var ( LICENSE_KEY string @@ -86,7 +85,7 @@ func keyCheck(cmd *cobra.Command, args []string) { data := make(map[string]interface{}) data["application"] = "apictl" data["install_id"] = install_id.String() - data["version"] = VERSION + data["version"] = Version data["metadata"] = map[string]string{"id": id} body, err := json.MarshalIndent(data, "", " ") if err != nil { diff --git a/cmd/apictl/version.go b/cmd/apictl/version.go index 496bb756f5..af2673a466 100644 --- a/cmd/apictl/version.go +++ b/cmd/apictl/version.go @@ -17,5 +17,5 @@ func init() { } func showVersion(cmd *cobra.Command, args []string) { - fmt.Println(VERSION) + fmt.Println(Version) } diff --git a/config.json b/config.json deleted file mode 100644 index 37b3e4fd9a..0000000000 --- a/config.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "unversioned": ["Makefile", "k8s.mk", "k8s/*"], - "profiles": { - "dev": {}, - "prod": { - "REPO": "$(NAMESPACE)/$(NAME)" - }, - "default": { - "REGISTRY": "quay.io", - "NAMESPACE": "datawire", - "REPO": "$(NAMESPACE)/$(NAME)-$(PROFILE)", - "VERSION": "$(HASH)", - "RATELIMIT_IMAGE": "$(REGISTRY)/$(REPO):ratelimit-$(VERSION)", - "PROXY_IMAGE": "$(REGISTRY)/$(REPO):proxy-$(VERSION)", - "SIDECAR_IMAGE": "$(REGISTRY)/$(REPO):sidecar-$(VERSION)" - } - } -} diff --git a/config.mk b/config.mk new file mode 100644 index 0000000000..995be767d5 --- /dev/null +++ b/config.mk @@ -0,0 +1,17 @@ +PROFILE ?= dev + +# Default profile +REGISTRY = quay.io +NAMESPACE = datawire +REPO = $(NAMESPACE)/$(NAME)-$(PROFILE) +RATELIMIT_IMAGE = $(REGISTRY)/$(REPO):ratelimit-$(VERSION) +PROXY_IMAGE = $(REGISTRY)/$(REPO):proxy-$(VERSION) +SIDECAR_IMAGE = $(REGISTRY)/$(REPO):sidecar-$(VERSION) + +ifeq ($(PROFILE),prod) + REPO = $(NAMESPACE)/$(NAME) +endif + +ifeq ($(PROFILE),dev) + # no overrides +endif diff --git a/intercept/Dockerfile b/intercept/Dockerfile index 01deaf6fe0..5250203256 100644 --- a/intercept/Dockerfile +++ b/intercept/Dockerfile @@ -1,13 +1,3 @@ -FROM golang:1-alpine as builder -RUN apk update && apk add git -WORKDIR /go/src/app -COPY cmd ./cmd -RUN go get -d -v ./... -RUN wget -q https://s3.amazonaws.com/datawire-static-files/ambex/0.1.0/ambex -RUN chmod 755 ambex -RUN CGO_ENABLED=0 GOOS=linux go build cmd/proxy/proxy.go -RUN CGO_ENABLED=0 GOOS=linux go build cmd/sidecar/sidecar.go - FROM alpine:3.6 as telepresence-proxy RUN apk add --no-cache openssh && \ ssh-keygen -A && \ @@ -17,12 +7,14 @@ RUN apk add --no-cache openssh && \ chmod g+w /etc/passwd USER 1000:0 WORKDIR /app -COPY proxy_image/run.sh . -COPY --from=builder /go/src/app/proxy . +COPY intercept/proxy_image/run.sh . +COPY image/proxy . CMD ["/app/run.sh"] FROM envoyproxy/envoy:28d5f4118d60f828b1453cd8ad25033f2c8e38ab as telepresence-sidecar WORKDIR /application -COPY sidecar_image /application/ -COPY --from=builder /go/src/app/sidecar /go/src/app/ambex /application/ +COPY intercept/sidecar_image /application/ +RUN wget -q https://s3.amazonaws.com/datawire-static-files/ambex/0.1.0/ambex +RUN chmod 755 ambex +COPY image/sidecar /application/ CMD ["/application/entrypoint.sh"] diff --git a/intercept/cmd/proxy/proxy.go b/intercept/cmd/proxy/proxy.go index 094a8c848d..6cdb985f08 100644 --- a/intercept/cmd/proxy/proxy.go +++ b/intercept/cmd/proxy/proxy.go @@ -305,7 +305,11 @@ func (state *ProxyState) cleanup() { log.Printf("cleanup: finished") } +// Version is inserted at build using --ldflags -X +var Version = "(unknown version)" + func main() { + log.Printf("Proxy version %s", Version) manager, err := golongpoll.StartLongpoll(golongpoll.Options{ LoggingEnabled: true, MaxLongpollTimeoutSeconds: 120, diff --git a/intercept/cmd/sidecar/sidecar.go b/intercept/cmd/sidecar/sidecar.go index a920385285..6ca9b05037 100644 --- a/intercept/cmd/sidecar/sidecar.go +++ b/intercept/cmd/sidecar/sidecar.go @@ -8,6 +8,7 @@ import ( "fmt" "io/ioutil" "log" + "math" "net/http" "net/url" "os" @@ -225,8 +226,12 @@ func processIntercepts(intercepts []InterceptInfo) { err = os.Rename("temp/route.json", "data/route.json") } +// Version is inserted at build using --ldflags -X +var Version = "(unknown version)" + func main() { log.SetPrefix("SIDECAR: ") + log.Printf("Sidecar version %s", Version) os.Mkdir("temp", 0775) @@ -238,8 +243,8 @@ func main() { log.Print("ERROR: APPNAME env var not configured.") log.Print("Running without intercept capabilities.") processIntercepts(intercepts) - select {} // Block forever - // not reached + <-time.After(time.Duration(math.MaxInt64)) // Block forever-ish + // not reached for a long time } log.SetPrefix(fmt.Sprintf("%s(%s) ", log.Prefix(), appName))