mirror of
https://github.com/FlipsideCrypto/convox.git
synced 2026-02-06 10:56:56 +00:00
init
This commit is contained in:
commit
473a4937f3
2
.dockerignore
Normal file
2
.dockerignore
Normal file
@ -0,0 +1,2 @@
|
||||
terraform
|
||||
terraform.tfvars
|
||||
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
.terraform
|
||||
51
Dockerfile
Normal file
51
Dockerfile
Normal file
@ -0,0 +1,51 @@
|
||||
## development #################################################################
|
||||
|
||||
FROM golang:1.12 AS development
|
||||
|
||||
RUN curl -Ls https://storage.googleapis.com/kubernetes-release/release/v1.13.0/bin/linux/amd64/kubectl -o /usr/bin/kubectl && \
|
||||
chmod +x /usr/bin/kubectl
|
||||
|
||||
RUN curl -Ls https://github.com/mattgreen/watchexec/releases/download/1.8.6/watchexec-1.8.6-x86_64-unknown-linux-gnu.tar.gz | \
|
||||
tar -C /usr/bin --strip-components 1 -xz
|
||||
|
||||
ENV DEVELOPMENT=true
|
||||
|
||||
WORKDIR /usr/src/convox
|
||||
|
||||
COPY go.mod go.sum ./
|
||||
COPY vendor vendor
|
||||
|
||||
RUN go build -mod=vendor --ldflags="-s -w" $(go list -mod=vendor ./vendor/...)
|
||||
|
||||
COPY . .
|
||||
|
||||
RUN make build
|
||||
|
||||
# ## package #####################################################################
|
||||
|
||||
# FROM golang:1.12 AS package
|
||||
|
||||
# RUN apt-get update && apt-get -y install upx-ucl
|
||||
|
||||
# RUN go get -u github.com/gobuffalo/packr/packr
|
||||
|
||||
# WORKDIR /usr/src/convox
|
||||
|
||||
# COPY --from=development /usr/src/convox .
|
||||
|
||||
# RUN make package build compress
|
||||
|
||||
# ## production ##################################################################
|
||||
|
||||
# FROM ubuntu:18.04
|
||||
|
||||
# RUN apt-get -qq update && apt-get -qq -y install curl
|
||||
|
||||
# RUN curl -Ls https://storage.googleapis.com/kubernetes-release/release/v1.13.0/bin/linux/amd64/kubectl -o /usr/bin/kubectl && \
|
||||
# chmod +x /usr/bin/kubectl
|
||||
|
||||
# ENV DEVELOPMENT=false
|
||||
|
||||
# WORKDIR /rack
|
||||
|
||||
# COPY --from=package /go/bin/router /usr/bin/
|
||||
36
Makefile
Normal file
36
Makefile
Normal file
@ -0,0 +1,36 @@
|
||||
.PHONY: all build clean clean-package compress dev-aws package release test
|
||||
|
||||
commands = atom router
|
||||
|
||||
binaries = $(addprefix $(GOPATH)/bin/, $(commands))
|
||||
sources = $(shell find . -name '*.go')
|
||||
version := dev-$(shell date +%Y%m%d%H%M%S)
|
||||
|
||||
all: build
|
||||
|
||||
build: $(binaries)
|
||||
|
||||
clean: clean-package
|
||||
|
||||
clean-package:
|
||||
find . -name '*-packr.go' -delete
|
||||
|
||||
compress: $(binaries)
|
||||
upx-ucl -1 $^
|
||||
|
||||
dev-aws: release
|
||||
echo "release = \"$(version)\"" > terraform/rack/aws/terraform.tfvars
|
||||
cd terraform/rack/aws && terraform apply
|
||||
|
||||
package:
|
||||
$(GOPATH)/bin/packr
|
||||
|
||||
release:
|
||||
docker build -t convox/convox:$(version) .
|
||||
docker push convox/convox:$(version)
|
||||
|
||||
test:
|
||||
env PROVIDER=test go test -covermode atomic -coverprofile coverage.txt ./...
|
||||
|
||||
$(binaries): $(GOPATH)/bin/%: $(sources)
|
||||
go install -mod=vendor --ldflags="-s -w" ./cmd/$*
|
||||
31
cmd/atom/main.go
Normal file
31
cmd/atom/main.go
Normal file
@ -0,0 +1,31 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/convox/convox/pkg/atom"
|
||||
"k8s.io/client-go/rest"
|
||||
)
|
||||
|
||||
func main() {
|
||||
if err := run(); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "ERROR: %s\n", err)
|
||||
}
|
||||
}
|
||||
|
||||
func run() error {
|
||||
cfg, err := rest.InClusterConfig()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ac, err := atom.NewController(cfg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ac.Run()
|
||||
|
||||
return nil
|
||||
}
|
||||
17
cmd/cx/main.go
Normal file
17
cmd/cx/main.go
Normal file
@ -0,0 +1,17 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/convox/convox/pkg/cli"
|
||||
)
|
||||
|
||||
var (
|
||||
version = "dev"
|
||||
)
|
||||
|
||||
func main() {
|
||||
c := cli.New("cx", version)
|
||||
|
||||
os.Exit(c.Execute(os.Args[1:]))
|
||||
}
|
||||
50
cmd/router/main.go
Normal file
50
cmd/router/main.go
Normal file
@ -0,0 +1,50 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/convox/convox/pkg/router"
|
||||
"k8s.io/apimachinery/pkg/util/runtime"
|
||||
)
|
||||
|
||||
func main() {
|
||||
if err := run(); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "ERROR: %s\n", err)
|
||||
}
|
||||
}
|
||||
|
||||
func run() error {
|
||||
// hack to make glog stop complaining about flag parsing
|
||||
fs := flag.NewFlagSet("", flag.ContinueOnError)
|
||||
_ = fs.Parse([]string{})
|
||||
flag.CommandLine = fs
|
||||
runtime.ErrorHandlers = []func(error){}
|
||||
|
||||
r, err := router.New()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ch := make(chan os.Signal, 1)
|
||||
signal.Notify(ch, syscall.SIGINT, syscall.SIGTERM)
|
||||
go handleSignals(r, ch)
|
||||
|
||||
return r.Serve()
|
||||
}
|
||||
|
||||
func handleSignals(r *router.Router, ch <-chan os.Signal) {
|
||||
sig := <-ch
|
||||
|
||||
fmt.Printf("ns=rack at=signal signal=%v terminate=true\n", sig)
|
||||
|
||||
ctx, _ := context.WithTimeout(context.Background(), 10*time.Second)
|
||||
r.Shutdown(ctx)
|
||||
|
||||
os.Exit(0)
|
||||
}
|
||||
43
go.mod
Normal file
43
go.mod
Normal file
@ -0,0 +1,43 @@
|
||||
module github.com/convox/convox
|
||||
|
||||
go 1.12
|
||||
|
||||
require (
|
||||
github.com/Microsoft/hcsshim v0.8.7-0.20190801035247-8694eade7dd3 // indirect
|
||||
github.com/aws/aws-sdk-go v1.21.10
|
||||
github.com/convox/logger v0.0.0-20180522214415-e39179955b52
|
||||
github.com/convox/stdcli v0.0.0-20190326115454-b78bee159e98
|
||||
github.com/docker/docker v1.4.2-0.20190710153559-aa8249ae1b8b
|
||||
github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96 // indirect
|
||||
github.com/dustin/go-humanize v1.0.0
|
||||
github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e // indirect
|
||||
github.com/fsouza/go-dockerclient v1.4.2
|
||||
github.com/gobuffalo/packr v1.30.1
|
||||
github.com/gobwas/glob v0.2.3
|
||||
github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d // indirect
|
||||
github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903 // indirect
|
||||
github.com/google/btree v0.0.0-20160524151835-7d79101e329e // indirect
|
||||
github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d // indirect
|
||||
github.com/gorilla/websocket v1.4.0
|
||||
github.com/gregjones/httpcache v0.0.0-20170728041850-787624de3eb7 // indirect
|
||||
github.com/imdario/mergo v0.3.7 // indirect
|
||||
github.com/json-iterator/go v1.1.7 // indirect
|
||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51
|
||||
github.com/miekg/dns v1.1.15
|
||||
github.com/modern-go/reflect2 v1.0.1 // indirect
|
||||
github.com/onsi/ginkgo v1.8.0 // indirect
|
||||
github.com/onsi/gomega v1.5.0 // indirect
|
||||
github.com/peterbourgon/diskv v2.0.1+incompatible // indirect
|
||||
github.com/pkg/errors v0.8.1
|
||||
github.com/stretchr/testify v1.3.0
|
||||
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4
|
||||
golang.org/x/net v0.0.0-20190812203447-cdfb69ac37fc // indirect
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 // indirect
|
||||
gopkg.in/inf.v0 v0.9.0 // indirect
|
||||
gopkg.in/yaml.v2 v2.2.2
|
||||
k8s.io/api v0.0.0-20190118113203-912cbe2bfef3
|
||||
k8s.io/apimachinery v0.0.0-20190223001710-c182ff3b9841
|
||||
k8s.io/client-go v0.0.0-20190117233410-4022682532b3
|
||||
k8s.io/kube-openapi v0.0.0-20190709113604-33be087ad058 // indirect
|
||||
k8s.io/metrics v0.0.0-20181204004050-3d8dd1c3a53c
|
||||
)
|
||||
306
go.sum
Normal file
306
go.sum
Normal file
@ -0,0 +1,306 @@
|
||||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 h1:w+iIsaOQNcT7OZ575w+acHgRric5iCyQh+xv+KJ4HB8=
|
||||
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8=
|
||||
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/Microsoft/go-winio v0.4.13-0.20190625174015-d2ef9cfdac5d/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA=
|
||||
github.com/Microsoft/go-winio v0.4.13 h1:Hmi80lzZuI/CaYmlJp/b+FjZdRZhKu9c2mDVqKlLWVs=
|
||||
github.com/Microsoft/go-winio v0.4.13/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA=
|
||||
github.com/Microsoft/hcsshim v0.8.6/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg=
|
||||
github.com/Microsoft/hcsshim v0.8.7-0.20190801035247-8694eade7dd3 h1:agmzOP0aQ42FpfjsjcI4cMDbT1GFCHFVYlv7zprTBh4=
|
||||
github.com/Microsoft/hcsshim v0.8.7-0.20190801035247-8694eade7dd3/go.mod h1:8OYooOlLyAIH/z8IDfdQH0L58ksBjNzsisBpmW2vg0Y=
|
||||
github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ=
|
||||
github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
|
||||
github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
|
||||
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
|
||||
github.com/aws/aws-sdk-go v1.21.10 h1:lTRdgyxraKbnNhx7kWeoW/Uow1TKnSNDpQGTtEXJQgk=
|
||||
github.com/aws/aws-sdk-go v1.21.10/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
|
||||
github.com/blang/semver v3.1.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/containerd/console v0.0.0-20180822173158-c12b1e7919c1/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw=
|
||||
github.com/containerd/containerd v0.0.0-20190214164719-faec567304bb/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
|
||||
github.com/containerd/continuity v0.0.0-20181203112020-004b46473808/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y=
|
||||
github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc h1:TP+534wVlf61smEIq1nwLLAjQVEK2EADoW3CX9AuT+8=
|
||||
github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y=
|
||||
github.com/containerd/fifo v0.0.0-20190226154929-a9fb20d87448/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI=
|
||||
github.com/containerd/go-runc v0.0.0-20180907222934-5a6d9f37cfa3/go.mod h1:IV7qH3hrUgRmyYrtgEeGWJfWbgcHL9CSRruz2Vqcph0=
|
||||
github.com/containerd/ttrpc v0.0.0-20180920185216-2a805f718635/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o=
|
||||
github.com/containerd/typeurl v0.0.0-20180627222232-a93fcdb778cd/go.mod h1:Cm3kwCdlkCfMSHURc+r6fwoGH6/F1hH3S4sg0rLFWPc=
|
||||
github.com/convox/logger v0.0.0-20180522214415-e39179955b52 h1:HTaloo6by+4NE1A1mRYprWzsOy1PGH2tPGfgZ60dyHU=
|
||||
github.com/convox/logger v0.0.0-20180522214415-e39179955b52/go.mod h1:IcbSD+Pq+bQV2z/otiMCHLAYBrDR/jPFopFatrWjlMM=
|
||||
github.com/convox/stdcli v0.0.0-20190326115454-b78bee159e98 h1:jSUPA5xGpERhDUevVwj8YPXhIbKq+YJPXpF8U9M4p1o=
|
||||
github.com/convox/stdcli v0.0.0-20190326115454-b78bee159e98/go.mod h1:D+mhXWLSLHQ+I2zZzYfrSzONMlE6FnPFw9hM4oDcN8Y=
|
||||
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
|
||||
github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk=
|
||||
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
||||
github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
|
||||
github.com/davecgh/go-spew v0.0.0-20151105211317-5215b55f46b2/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
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/docker/distribution v2.7.1+incompatible h1:a5mlkVzth6W5A4fOsS3D2EO5BUmsJpcB+cRlLU7cSug=
|
||||
github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
||||
github.com/docker/docker v1.4.2-0.20190710153559-aa8249ae1b8b h1:+Ga+YpCDpcY1fln6GI0fiiirpqHGcob5/Vk3oKNuGdU=
|
||||
github.com/docker/docker v1.4.2-0.20190710153559-aa8249ae1b8b/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||
github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ=
|
||||
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
|
||||
github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw=
|
||||
github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
|
||||
github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96 h1:cenwrSVm+Z7QLSV/BsnenAOcDXdX4cMv4wP0B/5QbPg=
|
||||
github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM=
|
||||
github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo=
|
||||
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||
github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e h1:p1yVGRW3nmb85p1Sh1ZJSDm4A4iKLS5QNbvUHMgGu/M=
|
||||
github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=
|
||||
github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
|
||||
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/fsouza/go-dockerclient v1.4.2 h1:dl6GfIWS5Qn4C6OfSnnoe6YuOV8lvKAE8W/YD1Q7udo=
|
||||
github.com/fsouza/go-dockerclient v1.4.2/go.mod h1:COunfLZrsdwX/j3YVDAG8gIw3KutrI0x1+vGEJ5zxdI=
|
||||
github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680 h1:ZktWZesgun21uEDrwW7iEV1zPCGQldM2atlJZ3TdvVM=
|
||||
github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
github.com/go-openapi/jsonpointer v0.0.0-20160704185906-46af16f9f7b1/go.mod h1:+35s3my2LFTysnkMfxsJBAMHj/DoqoB9knIWoYG/Vk0=
|
||||
github.com/go-openapi/jsonreference v0.0.0-20160704190145-13c6e3589ad9/go.mod h1:W3Z9FmVs9qj+KR4zFKmDPGiLdk1D9Rlm7cyMvf57TTg=
|
||||
github.com/go-openapi/spec v0.0.0-20160808142527-6aced65f8501/go.mod h1:J8+jY1nAiCcj+friV/PDoE1/3eeccG9LYBs0tYvLOWc=
|
||||
github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I=
|
||||
github.com/gobuffalo/envy v1.7.0 h1:GlXgaiBkmrYMHco6t4j7SacKO4XUjvh5pwXh0f4uxXU=
|
||||
github.com/gobuffalo/envy v1.7.0/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI=
|
||||
github.com/gobuffalo/logger v1.0.0/go.mod h1:2zbswyIUa45I+c+FLXuWl9zSWEiVuthsk8ze5s8JvPs=
|
||||
github.com/gobuffalo/packd v0.3.0 h1:eMwymTkA1uXsqxS0Tpoop3Lc0u3kTfiMBE6nKtQU4g4=
|
||||
github.com/gobuffalo/packd v0.3.0/go.mod h1:zC7QkmNkYVGKPw4tHpBQ+ml7W/3tIebgeo1b36chA3Q=
|
||||
github.com/gobuffalo/packr v1.30.1 h1:hu1fuVR3fXEZR7rXNW3h8rqSML8EVAf6KNm0NKO/wKg=
|
||||
github.com/gobuffalo/packr v1.30.1/go.mod h1:ljMyFO2EcrnzsHsN99cvbq055Y9OhRrIaviy289eRuk=
|
||||
github.com/gobuffalo/packr/v2 v2.5.1/go.mod h1:8f9c96ITobJlPzI44jj+4tHnEKNt0xXWSVlXRN9X1Iw=
|
||||
github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y=
|
||||
github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8=
|
||||
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
|
||||
github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d h1:3PaI8p3seN09VjbTYC/QWlUZdZ1qS1zGjy7LH2Wt07I=
|
||||
github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903 h1:LbsanbbD6LieFkXbj9YNNBupiGHJgFeLpO0j0Fza1h8=
|
||||
github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/protobuf v0.0.0-20161109072736-4bd1920723d7/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.0/go.mod h1:Qd/q+1AKNOZr9uGQzbzCmRO6sUih6GTPZv6a1/R87v0=
|
||||
github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg=
|
||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/google/btree v0.0.0-20160524151835-7d79101e329e h1:JHB7F/4TJCrYBW8+GZO8VkWDj1jxcWuCl6uxKODiyi4=
|
||||
github.com/google/btree v0.0.0-20160524151835-7d79101e329e/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||
github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY=
|
||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/gofuzz v0.0.0-20161122191042-44d81051d367/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI=
|
||||
github.com/google/gofuzz v1.0.0 h1:A8PeW59pxE9IoFRqBp37U+mSNaQoZ46F1f0f863XSXw=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/googleapis/gnostic v0.0.0-20170426233943-68f4ded48ba9/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
|
||||
github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d h1:7XGaL1e6bYS1yIonGp9761ExpPPV1ui0SAC59Yube9k=
|
||||
github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
|
||||
github.com/gorilla/mux v1.7.3 h1:gnP5JzjVOuiZD07fKKToCAOjS0yOpj/qPETTXCCS6hw=
|
||||
github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
||||
github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q=
|
||||
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
||||
github.com/gregjones/httpcache v0.0.0-20170728041850-787624de3eb7 h1:6TSoaYExHper8PYsJu23GWVNOyYRCSnIFyxKgLSZ54w=
|
||||
github.com/gregjones/httpcache v0.0.0-20170728041850-787624de3eb7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
|
||||
github.com/hashicorp/errwrap v0.0.0-20141028054710-7554cd9344ce/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
github.com/hashicorp/go-multierror v0.0.0-20161216184304-ed905158d874/go.mod h1:JMRHfdO9jKNzS/+BTlxCjKNQHg/jZAft8U7LloJvN7I=
|
||||
github.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU=
|
||||
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
||||
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/ijc/Gotty v0.0.0-20170406111628-a8b993ba6abd h1:anPrsicrIi2ColgWTVPk+TrN42hJIWlfPHSBP9S0ZkM=
|
||||
github.com/ijc/Gotty v0.0.0-20170406111628-a8b993ba6abd/go.mod h1:3LVOLeyx9XVvwPgrt2be44XgSqndprz1G18rSk8KD84=
|
||||
github.com/imdario/mergo v0.3.7 h1:Y+UAYTZ7gDEuOfhxKWy+dvb5dRQ6rJjFSdX2HZY1/gI=
|
||||
github.com/imdario/mergo v0.3.7/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
|
||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af h1:pmfjZENx5imkbgOkpRUYLnmbU7UEFbjtDA2hxJ1ichM=
|
||||
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
|
||||
github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc=
|
||||
github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg=
|
||||
github.com/json-iterator/go v0.0.0-20180612202835-f2b4162afba3/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||
github.com/json-iterator/go v1.1.7 h1:KfgG9LzI+pYjr4xvmz/5H4FXjokeP+rlHLhv3iH62Fo=
|
||||
github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/karrick/godirwalk v1.10.12/go.mod h1:RoGL9dQei4vP9ilrpETWE8CLOZ1kiN0LhBygSwrAsHA=
|
||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs=
|
||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
|
||||
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
|
||||
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.2 h1:DB17ag19krx9CFsz4o3enTrPXyIXCl+2iCXH/aMAp9s=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
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/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||
github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||
github.com/miekg/dns v1.1.15 h1:CSSIDtllwGLMoA6zjdKnaE6Tx6eVUxQ29LUgGetiDCI=
|
||||
github.com/miekg/dns v1.1.15/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
|
||||
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
|
||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v0.0.0-20180320133207-05fbef0ca5da/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI=
|
||||
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
|
||||
github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.8.0 h1:VkHVNpR4iVnU8XQR6DBm8BqYjN7CRzw+xKUbVVbbW9w=
|
||||
github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
|
||||
github.com/onsi/gomega v1.5.0 h1:izbySO9zDPmjJ8rDjLvkA2zJHIo+HkYXHnf7eN7SSyo=
|
||||
github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||
github.com/opencontainers/go-digest v0.0.0-20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
|
||||
github.com/opencontainers/go-digest v1.0.0-rc1 h1:WzifXhOVOEOuFYOJAW6aQqW0TooG2iki3E3Ii+WN7gQ=
|
||||
github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
|
||||
github.com/opencontainers/image-spec v1.0.1 h1:JMemWkRwHx4Zj+fVxWoMCFm/8sYGGrUVojFA6h/TRcI=
|
||||
github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
|
||||
github.com/opencontainers/runc v0.0.0-20190115041553-12f6a991201f/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
|
||||
github.com/opencontainers/runc v0.1.1 h1:GlxAyO6x8rfZYN9Tt0Kti5a/cP41iuiO2yYT0IJGY8Y=
|
||||
github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
|
||||
github.com/opencontainers/runtime-spec v0.0.0-20190207185410-29686dbc5559/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
||||
github.com/opencontainers/runtime-tools v0.0.0-20181011054405-1d69bd0f9c39/go.mod h1:r3f7wjNzSs2extwzU3Y+6pKfobzPh+kKFJ3ofN+3nfs=
|
||||
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
||||
github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI=
|
||||
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
|
||||
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
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/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/rogpeppe/go-internal v1.3.0 h1:RR9dF3JtopPvtkroDZuVD7qquD0bnHlKSqaQhgwt8yk=
|
||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
|
||||
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
|
||||
github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=
|
||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
|
||||
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
||||
github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
|
||||
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
|
||||
github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||
github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg=
|
||||
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||
github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
|
||||
github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A=
|
||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v0.0.0-20151208002404-e3a8ff8ce365/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/syndtr/gocapability v0.0.0-20170704070218-db04d3cc01c8/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
|
||||
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
|
||||
github.com/urfave/cli v0.0.0-20171014202726-7bc6a0acffa5/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
|
||||
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
|
||||
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ=
|
||||
github.com/xeipuuv/gojsonschema v0.0.0-20180618132009-1d523034197f/go.mod h1:5yf86TLmAcydyeJq5YvxkGPE2fm/u4myDekKRoLuqhs=
|
||||
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
|
||||
go.opencensus.io v0.22.0 h1:C9hSCOW830chIVkdja34wa6Ky+IzWllkUinR+BtRZd4=
|
||||
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
|
||||
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190621222207-cc06ce4a13d4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4 h1:HuIa8hRrWRSrqYzx1qI49NNxhdi2PrY7gxVSq1JjLDc=
|
||||
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190812203447-cdfb69ac37fc h1:gkKoSkUmnU6bpS/VhkuO27bzQeSA51uaEfbOW5dNb68=
|
||||
golang.org/x/net v0.0.0-20190812203447-cdfb69ac37fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20170830134202-bb24a47a89ea/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190515120540-06a5c4944438/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190710143415-6ec70d6a5542 h1:6ZQFf1D2YYDDI7eSwW8adlkkavTB9sw5I24FVtEvNUQ=
|
||||
golang.org/x/sys v0.0.0-20190710143415-6ec70d6a5542/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 h1:SvFZT6jyqRaOeXpc5h/JSfZenJ2O330aBsf7JfSUXmQ=
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20181011042414-1f849cf54d09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20190624180213-70d37148ca0c/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb h1:i1Ppqkc3WQXikh8bXiwHqAN5Rv3/qDCcRk0/Otx73BY=
|
||||
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
|
||||
google.golang.org/grpc v1.22.0 h1:J0UbZOIrCAl+fpTOf8YLs4dJo8L/owV4LYVtAXQoPkw=
|
||||
google.golang.org/grpc v1.22.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||
gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
|
||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||
gopkg.in/inf.v0 v0.9.0 h1:3zYtXIO92bvsdS3ggAdA8Gb4Azj0YU+TVY1uGYNFA8o=
|
||||
gopkg.in/inf.v0 v0.9.0/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo=
|
||||
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
k8s.io/api v0.0.0-20190118113203-912cbe2bfef3 h1:lV0+KGoNkvZOt4zGT4H83hQrzWMt/US/LSz4z4+BQS4=
|
||||
k8s.io/api v0.0.0-20190118113203-912cbe2bfef3/go.mod h1:iuAfoD4hCxJ8Onx9kaTIt30j7jUFS00AXQi6QMi99vA=
|
||||
k8s.io/apimachinery v0.0.0-20190223001710-c182ff3b9841 h1:Q4RZrHNtlC/mSdC1sTrcZ5RchC/9vxLVj57pWiCBKv4=
|
||||
k8s.io/apimachinery v0.0.0-20190223001710-c182ff3b9841/go.mod h1:ccL7Eh7zubPUSh9A3USN90/OzHNSVN6zxzde07TDCL0=
|
||||
k8s.io/client-go v0.0.0-20190117233410-4022682532b3 h1:7VVBo3+/iX6dzB8dshNuo6Duds/6AoNP5R59IUnwoxg=
|
||||
k8s.io/client-go v0.0.0-20190117233410-4022682532b3/go.mod h1:7vJpHMYJwNQCWgzmNV+VYUl1zCObLyodBc8nIyt8L5s=
|
||||
k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
|
||||
k8s.io/klog v0.0.0-20181102134211-b9b56d5dfc92/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk=
|
||||
k8s.io/kube-openapi v0.0.0-20190709113604-33be087ad058 h1:di3XCwddOR9cWBNpfgXaskhh6cgJuwcK54rvtwUaC10=
|
||||
k8s.io/kube-openapi v0.0.0-20190709113604-33be087ad058/go.mod h1:nfDlWeOsu3pUf4yWGL+ERqohP4YsZcBJXWMK+gkzOA4=
|
||||
k8s.io/kubernetes v1.13.0/go.mod h1:ocZa8+6APFNC2tX1DZASIbocyYT5jHzqFVsY5aoB7Jk=
|
||||
k8s.io/metrics v0.0.0-20181204004050-3d8dd1c3a53c h1:C5pPzP70ZI2ZxBm/5YHVwcIFZzxJ7lhW/5qOXgQIc+E=
|
||||
k8s.io/metrics v0.0.0-20181204004050-3d8dd1c3a53c/go.mod h1:a25VAbm3QT3xiVl1jtoF1ueAKQM149UdZ+L93ePfV3M=
|
||||
sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e/go.mod h1:wWxsB5ozmmv/SG7nM11ayaAW51xMvak/t1r0CSlcokI=
|
||||
8
pkg/atom/Makefile
Normal file
8
pkg/atom/Makefile
Normal file
@ -0,0 +1,8 @@
|
||||
all: generate
|
||||
|
||||
generate:
|
||||
# go get -u k8s.io/code-generator/...
|
||||
../../vendor/k8s.io/code-generator/generate-groups.sh all \
|
||||
github.com/convox/convox/pkg/atom/pkg/client \
|
||||
github.com/convox/convox/pkg/atom/pkg/apis \
|
||||
convox:v1,v2
|
||||
591
pkg/atom/atom.go
Normal file
591
pkg/atom/atom.go
Normal file
@ -0,0 +1,591 @@
|
||||
package atom
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"html/template"
|
||||
"os/exec"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
ca "github.com/convox/convox/pkg/atom/pkg/apis/convox/v2"
|
||||
cv "github.com/convox/convox/pkg/atom/pkg/client/clientset/versioned"
|
||||
"github.com/convox/convox/pkg/templater"
|
||||
"github.com/gobuffalo/packr"
|
||||
"github.com/pkg/errors"
|
||||
yaml "gopkg.in/yaml.v2"
|
||||
ac "k8s.io/api/core/v1"
|
||||
ae "k8s.io/apimachinery/pkg/api/errors"
|
||||
am "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apimachinery/pkg/runtime/serializer"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/kubernetes/scheme"
|
||||
"k8s.io/client-go/rest"
|
||||
)
|
||||
|
||||
var (
|
||||
templates = templater.New(packr.NewBox("../atom/templates"), templateHelpers())
|
||||
)
|
||||
|
||||
type Client struct {
|
||||
config *rest.Config
|
||||
convox cv.Interface
|
||||
k8s kubernetes.Interface
|
||||
}
|
||||
|
||||
func New(cfg *rest.Config) (*Client, error) {
|
||||
cc, err := cv.NewForConfig(cfg)
|
||||
if err != nil {
|
||||
return nil, errors.WithStack(err)
|
||||
}
|
||||
|
||||
kc, err := kubernetes.NewForConfig(cfg)
|
||||
if err != nil {
|
||||
return nil, errors.WithStack(err)
|
||||
}
|
||||
|
||||
c := &Client{
|
||||
config: cfg,
|
||||
convox: cc,
|
||||
k8s: kc,
|
||||
}
|
||||
|
||||
return c, nil
|
||||
}
|
||||
|
||||
func Apply(namespace, name, release string, template []byte, timeout int32) error {
|
||||
params := map[string]interface{}{
|
||||
"Name": name,
|
||||
"Namespace": namespace,
|
||||
"Release": release,
|
||||
"Template": base64.StdEncoding.EncodeToString(template),
|
||||
"Timeout": timeout,
|
||||
"Version": time.Now().UTC().UnixNano(),
|
||||
}
|
||||
|
||||
if err := exec.Command("kubectl", "get", fmt.Sprintf("ns/%s", namespace)).Run(); err != nil {
|
||||
if err := kubectlApplyTemplate("namespace.yml.tmpl", params); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for {
|
||||
if err := exec.Command("kubectl", "get", fmt.Sprintf("ns/%s", namespace)).Run(); err == nil {
|
||||
break
|
||||
}
|
||||
|
||||
time.Sleep(1 * time.Second)
|
||||
}
|
||||
}
|
||||
|
||||
data, err := templates.Render("version.yml.tmpl", params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if data, err := kubectlCreate(data); err != nil {
|
||||
return fmt.Errorf("could not create atom version for %s/%s: %s", name, release, strings.TrimSpace(string(data)))
|
||||
}
|
||||
|
||||
if err := kubectlApplyTemplate("atom.yml.tmpl", params); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func Wait(namespace, name string) error {
|
||||
for {
|
||||
data, err := exec.Command("kubectl", "get", fmt.Sprintf("atom/%s", name), "-n", namespace, "-o", "jsonpath={.status}").CombinedOutput()
|
||||
if err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
switch string(data) {
|
||||
case "Success":
|
||||
return nil
|
||||
case "Failure":
|
||||
return errors.WithStack(fmt.Errorf("atom failed"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Client) Apply(ns, name string, release string, template []byte, timeout int32) error {
|
||||
if _, err := c.k8s.CoreV1().Namespaces().Get(ns, am.GetOptions{}); ae.IsNotFound(err) {
|
||||
_, err := c.k8s.CoreV1().Namespaces().Create(&ac.Namespace{
|
||||
ObjectMeta: am.ObjectMeta{
|
||||
Name: ns,
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
for {
|
||||
if ns, err := c.k8s.CoreV1().Namespaces().Get(ns, am.GetOptions{}); err == nil && ns != nil {
|
||||
break
|
||||
}
|
||||
|
||||
time.Sleep(1 * time.Second)
|
||||
}
|
||||
}
|
||||
|
||||
v, err := c.convox.ConvoxV2().AtomVersions(ns).Create(&ca.AtomVersion{
|
||||
ObjectMeta: am.ObjectMeta{
|
||||
Name: fmt.Sprintf("%s-%d", name, time.Now().UTC().UnixNano()),
|
||||
},
|
||||
Spec: ca.AtomVersionSpec{
|
||||
Release: release,
|
||||
Template: template,
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
a, err := c.convox.ConvoxV2().Atoms(ns).Get(name, am.GetOptions{})
|
||||
switch {
|
||||
case ae.IsNotFound(err):
|
||||
a, err = c.convox.ConvoxV2().Atoms(ns).Create(&ca.Atom{
|
||||
ObjectMeta: am.ObjectMeta{
|
||||
Name: name,
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
case err != nil:
|
||||
return errors.WithStack(err)
|
||||
default:
|
||||
a.Spec.PreviousVersion = a.Spec.CurrentVersion
|
||||
}
|
||||
|
||||
a.Spec.CurrentVersion = v.Name
|
||||
a.Spec.ProgressDeadlineSeconds = timeout
|
||||
a.Status = "Pending"
|
||||
|
||||
if _, err := c.convox.ConvoxV2().Atoms(ns).Update(a); err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Client) Status(ns, name string) (string, string, error) {
|
||||
a, err := c.convox.ConvoxV2().Atoms(ns).Get(name, am.GetOptions{})
|
||||
if ae.IsNotFound(err) {
|
||||
return "", "", nil
|
||||
}
|
||||
if err != nil {
|
||||
return "", "", errors.WithStack(err)
|
||||
}
|
||||
|
||||
release := ""
|
||||
|
||||
if a.Spec.CurrentVersion != "" {
|
||||
v, err := c.convox.ConvoxV2().AtomVersions(ns).Get(a.Spec.CurrentVersion, am.GetOptions{})
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
|
||||
release = v.Spec.Release
|
||||
}
|
||||
|
||||
return string(a.Status), release, nil
|
||||
}
|
||||
|
||||
func (c *Client) Wait(ns, name string) error {
|
||||
for {
|
||||
a, err := c.convox.ConvoxV2().Atoms(ns).Get(name, am.GetOptions{})
|
||||
if err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
switch a.Status {
|
||||
case "Success":
|
||||
return nil
|
||||
case "Failure":
|
||||
return errors.WithStack(fmt.Errorf("atom failed"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Client) apply(a *ca.Atom) error {
|
||||
var err error
|
||||
|
||||
a.Status = "Building"
|
||||
|
||||
a, err = c.convox.ConvoxV2().Atoms(a.Namespace).Update(a)
|
||||
if err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
v, err := c.convox.ConvoxV2().AtomVersions(a.Namespace).Get(a.Spec.CurrentVersion, am.GetOptions{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
cs, err := extractConditions(v.Spec.Template)
|
||||
if err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
a.Spec.Conditions = cs
|
||||
|
||||
fmt.Printf("string(v.Spec.Template) = %+v\n", string(v.Spec.Template))
|
||||
|
||||
out, err := applyTemplate(v.Spec.Template, fmt.Sprintf("atom=%s.%s", a.Namespace, a.Name))
|
||||
fmt.Printf("string(out) = %+v\n", string(out))
|
||||
fmt.Printf("err = %+v\n", err)
|
||||
if err != nil {
|
||||
return errors.WithStack(errors.New(strings.TrimSpace(string(out))))
|
||||
}
|
||||
|
||||
time.Sleep(1 * time.Second)
|
||||
|
||||
a.Started = am.Now()
|
||||
a.Status = "Running"
|
||||
|
||||
a, err = c.convox.ConvoxV2().Atoms(a.Namespace).Update(a)
|
||||
if err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Client) check(a *ca.Atom) (bool, error) {
|
||||
cfg := *c.config
|
||||
|
||||
cfg.APIPath = "/apis"
|
||||
cfg.NegotiatedSerializer = serializer.DirectCodecFactory{CodecFactory: scheme.Codecs}
|
||||
|
||||
for _, c := range a.Spec.Conditions {
|
||||
gv, err := schema.ParseGroupVersion(c.ApiVersion)
|
||||
if err != nil {
|
||||
return false, errors.WithStack(err)
|
||||
}
|
||||
|
||||
cfg.GroupVersion = &gv
|
||||
|
||||
rc, err := rest.RESTClientFor(&cfg)
|
||||
if err != nil {
|
||||
return false, errors.WithStack(err)
|
||||
}
|
||||
|
||||
data, err := rc.Get().Namespace(c.Namespace).Name(c.Name).VersionedParams(&am.GetOptions{}, scheme.ParameterCodec).Resource(fmt.Sprintf("%ss", strings.ToLower(c.Kind))).Do().Raw()
|
||||
if err != nil {
|
||||
return false, errors.WithStack(err)
|
||||
}
|
||||
|
||||
var o struct {
|
||||
Status struct {
|
||||
Conditions []struct {
|
||||
Type string
|
||||
Status string
|
||||
Reason string
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if err := json.Unmarshal(data, &o); err != nil {
|
||||
return false, errors.WithStack(err)
|
||||
}
|
||||
|
||||
css := map[string]string{}
|
||||
crs := map[string]string{}
|
||||
|
||||
for _, c := range o.Status.Conditions {
|
||||
css[c.Type] = c.Status
|
||||
crs[c.Type] = c.Reason
|
||||
}
|
||||
|
||||
for k, c := range c.Conditions {
|
||||
if c.Status != css[k] {
|
||||
return false, nil
|
||||
}
|
||||
if c.Reason != "" && c.Reason != crs[k] {
|
||||
return false, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (c *Client) rollback(a *ca.Atom) error {
|
||||
v, err := c.convox.ConvoxV2().AtomVersions(a.Namespace).Get(a.Spec.PreviousVersion, am.GetOptions{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
out, err := applyTemplate(v.Spec.Template, fmt.Sprintf("atom=%s.%s", a.Namespace, a.Name))
|
||||
if err != nil {
|
||||
return errors.WithStack(errors.New(strings.TrimSpace(string(out))))
|
||||
}
|
||||
|
||||
time.Sleep(1 * time.Second)
|
||||
|
||||
a.Spec.CurrentVersion = v.Name
|
||||
a.Spec.PreviousVersion = ""
|
||||
a.Started = am.Now()
|
||||
a.Status = "Rollback"
|
||||
|
||||
a, err = c.convox.ConvoxV2().Atoms(a.Namespace).Update(a)
|
||||
if err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Client) status(a *ca.Atom, status string) error {
|
||||
var err error
|
||||
|
||||
a.Status = ca.AtomStatus(status)
|
||||
|
||||
a, err = c.convox.ConvoxV2().Atoms(a.Namespace).Update(a)
|
||||
if err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func applyLabels(data []byte, labels map[string]string) ([]byte, error) {
|
||||
var v map[string]interface{}
|
||||
|
||||
if err := yaml.Unmarshal(data, &v); err != nil {
|
||||
return nil, errors.WithStack(err)
|
||||
}
|
||||
|
||||
if len(v) == 0 {
|
||||
return data, nil
|
||||
}
|
||||
|
||||
switch t := v["metadata"].(type) {
|
||||
case nil:
|
||||
v["metadata"] = map[string]interface{}{"labels": labels}
|
||||
case map[interface{}]interface{}:
|
||||
switch u := t["labels"].(type) {
|
||||
case nil:
|
||||
t["labels"] = labels
|
||||
v["metadata"] = t
|
||||
case map[interface{}]interface{}:
|
||||
for k, v := range labels {
|
||||
u[k] = v
|
||||
}
|
||||
t["labels"] = u
|
||||
v["metadata"] = t
|
||||
default:
|
||||
return nil, errors.WithStack(fmt.Errorf("unknown labels type: %T", u))
|
||||
}
|
||||
default:
|
||||
return nil, errors.WithStack(fmt.Errorf("unknown metadata type: %T", t))
|
||||
}
|
||||
|
||||
pd, err := yaml.Marshal(v)
|
||||
if err != nil {
|
||||
return nil, errors.WithStack(err)
|
||||
}
|
||||
|
||||
return pd, nil
|
||||
}
|
||||
|
||||
func applyTemplate(data []byte, filter string) ([]byte, error) {
|
||||
rs, err := templateResources(filter)
|
||||
if err != nil {
|
||||
return nil, errors.WithStack(err)
|
||||
}
|
||||
|
||||
labels := parseLabels(filter)
|
||||
|
||||
parts := bytes.Split(data, []byte("---\n"))
|
||||
|
||||
for i := range parts {
|
||||
dp, err := applyLabels(parts[i], labels)
|
||||
if err != nil {
|
||||
return nil, errors.WithStack(err)
|
||||
}
|
||||
|
||||
parts[i] = dp
|
||||
}
|
||||
|
||||
data = bytes.Join(parts, []byte("---\n"))
|
||||
|
||||
args := []string{"--prune", "-l", filter}
|
||||
|
||||
for _, r := range rs {
|
||||
args = append(args, "--prune-whitelist", r)
|
||||
}
|
||||
|
||||
out, err := kubectlApply(data, args...)
|
||||
if err != nil {
|
||||
if !strings.Contains(string(out), "is immutable") {
|
||||
return out, errors.WithStack(err)
|
||||
}
|
||||
|
||||
out, err := kubectlApply(data, "--force")
|
||||
if err != nil {
|
||||
return out, errors.WithStack(err)
|
||||
}
|
||||
}
|
||||
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func extractConditions(data []byte) ([]ca.AtomCondition, error) {
|
||||
cs := []ca.AtomCondition{}
|
||||
|
||||
parts := bytes.Split(data, []byte("---\n"))
|
||||
|
||||
for _, p := range parts {
|
||||
var o struct {
|
||||
ApiVersion string `yaml:"apiVersion"`
|
||||
Kind string
|
||||
Metadata struct {
|
||||
Annotations map[string]string
|
||||
Name string
|
||||
Namespace string
|
||||
}
|
||||
}
|
||||
|
||||
if err := yaml.Unmarshal(p, &o); err != nil {
|
||||
return nil, errors.WithStack(err)
|
||||
}
|
||||
|
||||
if ac, ok := o.Metadata.Annotations["atom.conditions"]; ok {
|
||||
acps := strings.Split(ac, ",")
|
||||
|
||||
acs := map[string]ca.AtomConditionMatch{}
|
||||
|
||||
for _, acp := range acps {
|
||||
if acpps := strings.SplitN(acp, "=", 2); len(acpps) == 2 {
|
||||
if vps := strings.SplitN(acpps[1], "/", 2); len(vps) == 2 {
|
||||
acs[acpps[0]] = ca.AtomConditionMatch{Status: vps[0], Reason: vps[1]}
|
||||
} else {
|
||||
acs[acpps[0]] = ca.AtomConditionMatch{Status: vps[0]}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cs = append(cs, ca.AtomCondition{
|
||||
ApiVersion: o.ApiVersion,
|
||||
Conditions: acs,
|
||||
Kind: o.Kind,
|
||||
Name: o.Metadata.Name,
|
||||
Namespace: o.Metadata.Namespace,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return cs, nil
|
||||
}
|
||||
|
||||
func kubectlApply(data []byte, args ...string) ([]byte, error) {
|
||||
ka := append([]string{"apply", "-f", "-"}, args...)
|
||||
|
||||
cmd := exec.Command("kubectl", ka...)
|
||||
|
||||
cmd.Stdin = bytes.NewReader(data)
|
||||
|
||||
return cmd.CombinedOutput()
|
||||
}
|
||||
|
||||
func kubectlCreate(data []byte, args ...string) ([]byte, error) {
|
||||
ka := append([]string{"create", "-f", "-"}, args...)
|
||||
|
||||
cmd := exec.Command("kubectl", ka...)
|
||||
|
||||
cmd.Stdin = bytes.NewReader(data)
|
||||
|
||||
return cmd.CombinedOutput()
|
||||
}
|
||||
|
||||
func kubectlApplyTemplate(template string, params map[string]interface{}) error {
|
||||
data, err := templates.Render(template, params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if out, err := kubectlApply(data); err != nil {
|
||||
return errors.New(strings.TrimSpace(string(out)))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func parseLabels(labels string) map[string]string {
|
||||
ls := map[string]string{}
|
||||
|
||||
for _, part := range strings.Split(labels, ",") {
|
||||
ps := strings.SplitN(strings.TrimSpace(part), "=", 2)
|
||||
if len(ps) == 2 {
|
||||
ls[ps[0]] = ps[1]
|
||||
}
|
||||
}
|
||||
|
||||
return ls
|
||||
}
|
||||
|
||||
func templateResources(filter string) ([]string, error) {
|
||||
data, err := exec.Command("kubectl", "api-resources", "--verbs=list", "--namespaced", "-o", "name").CombinedOutput()
|
||||
if err != nil {
|
||||
return []string{}, nil
|
||||
}
|
||||
|
||||
ars := strings.Split(strings.TrimSpace(string(data)), "\n")
|
||||
|
||||
rsh := map[string]bool{}
|
||||
|
||||
data, err = exec.Command("kubectl", "get", "-l", filter, "--all-namespaces", "-o", "json", strings.Join(ars, ",")).CombinedOutput()
|
||||
if err != nil {
|
||||
return []string{}, nil
|
||||
}
|
||||
|
||||
if strings.TrimSpace(string(data)) == "" {
|
||||
return []string{}, nil
|
||||
}
|
||||
|
||||
var res struct {
|
||||
Items []struct {
|
||||
ApiVersion string `json:"apiVersion"`
|
||||
Kind string `json:"kind"`
|
||||
}
|
||||
}
|
||||
|
||||
if err := json.Unmarshal(data, &res); err != nil {
|
||||
return nil, errors.WithStack(err)
|
||||
}
|
||||
|
||||
for _, i := range res.Items {
|
||||
av := i.ApiVersion
|
||||
|
||||
if !strings.Contains(av, "/") {
|
||||
av = fmt.Sprintf("core/%s", av)
|
||||
}
|
||||
|
||||
rsh[fmt.Sprintf("%s/%s", av, i.Kind)] = true
|
||||
}
|
||||
|
||||
rs := []string{}
|
||||
|
||||
for r := range rsh {
|
||||
rs = append(rs, r)
|
||||
}
|
||||
|
||||
sort.Strings(rs)
|
||||
|
||||
return rs, nil
|
||||
}
|
||||
|
||||
func templateHelpers() map[string]interface{} {
|
||||
return map[string]interface{}{
|
||||
"safe": func(s string) template.HTML {
|
||||
return template.HTML(fmt.Sprintf("%q", s))
|
||||
},
|
||||
}
|
||||
}
|
||||
175
pkg/atom/controller.go
Normal file
175
pkg/atom/controller.go
Normal file
@ -0,0 +1,175 @@
|
||||
package atom
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
ct "github.com/convox/convox/pkg/atom/pkg/apis/convox/v2"
|
||||
cv "github.com/convox/convox/pkg/atom/pkg/client/clientset/versioned"
|
||||
ic "github.com/convox/convox/pkg/atom/pkg/client/informers/externalversions/convox/v2"
|
||||
"github.com/convox/convox/pkg/kctl"
|
||||
"github.com/pkg/errors"
|
||||
ac "k8s.io/api/core/v1"
|
||||
am "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/rest"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
)
|
||||
|
||||
type AtomController struct {
|
||||
atom *Client
|
||||
controller *kctl.Controller
|
||||
convox cv.Interface
|
||||
kubernetes kubernetes.Interface
|
||||
}
|
||||
|
||||
func NewController(cfg *rest.Config) (*AtomController, error) {
|
||||
ac, err := New(cfg)
|
||||
if err != nil {
|
||||
return nil, errors.WithStack(err)
|
||||
}
|
||||
|
||||
cc, err := cv.NewForConfig(cfg)
|
||||
if err != nil {
|
||||
return nil, errors.WithStack(err)
|
||||
}
|
||||
|
||||
kc, err := kubernetes.NewForConfig(cfg)
|
||||
if err != nil {
|
||||
return nil, errors.WithStack(err)
|
||||
}
|
||||
|
||||
acc := &AtomController{
|
||||
atom: ac,
|
||||
convox: cc,
|
||||
kubernetes: kc,
|
||||
}
|
||||
|
||||
c, err := kctl.NewController("kube-system", "convox-atom", acc)
|
||||
if err != nil {
|
||||
return nil, errors.WithStack(err)
|
||||
}
|
||||
|
||||
acc.controller = c
|
||||
|
||||
return acc, nil
|
||||
}
|
||||
|
||||
func (c *AtomController) Client() kubernetes.Interface {
|
||||
return c.kubernetes
|
||||
}
|
||||
|
||||
func (c *AtomController) ListOptions(opts *am.ListOptions) {
|
||||
}
|
||||
|
||||
func (c *AtomController) Run() {
|
||||
i := ic.NewFilteredAtomInformer(c.convox, ac.NamespaceAll, 5*time.Second, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, c.ListOptions)
|
||||
|
||||
ch := make(chan error)
|
||||
|
||||
go c.controller.Run(i, ch)
|
||||
|
||||
for err := range ch {
|
||||
fmt.Printf("err = %+v\n", err)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *AtomController) Start() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *AtomController) Stop() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *AtomController) Add(obj interface{}) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *AtomController) Delete(obj interface{}) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *AtomController) Update(prev, cur interface{}) error {
|
||||
pa, err := assertAtom(prev)
|
||||
if err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
ca, err := assertAtom(cur)
|
||||
if err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
switch ca.Status {
|
||||
case "Failed", "Reverted", "Success":
|
||||
if pa.ResourceVersion == ca.ResourceVersion {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Printf("atom: %s/%s (%s)\n", ca.Namespace, ca.Name, ca.Status)
|
||||
|
||||
// if ca.Spec.Current != pa.Spec.Current {
|
||||
// fmt.Printf("atom changed: %s/%s\n", ca.Namespace, ca.Name)
|
||||
|
||||
// return nil
|
||||
// }
|
||||
|
||||
switch ca.Status {
|
||||
case "Cancelled", "Deadline", "Error":
|
||||
if err := c.atom.rollback(ca); err != nil {
|
||||
c.atom.status(ca, "Failed")
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
case "Cleanup":
|
||||
ca.Spec.PreviousVersion = ""
|
||||
c.atom.status(ca, "Success")
|
||||
case "Pending":
|
||||
if err := c.atom.apply(ca); err != nil {
|
||||
c.atom.status(ca, "Rollback")
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
case "Rollback":
|
||||
if deadline := am.NewTime(time.Now().UTC().Add(-1 * time.Duration(ca.Spec.ProgressDeadlineSeconds) * time.Second)); ca.Started.Before(&deadline) {
|
||||
c.atom.status(ca, "Failed")
|
||||
return nil
|
||||
}
|
||||
|
||||
success, err := c.atom.check(ca)
|
||||
if err != nil {
|
||||
c.atom.status(ca, "Failed")
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
if success {
|
||||
c.atom.status(ca, "Reverted")
|
||||
}
|
||||
case "Running":
|
||||
if deadline := am.NewTime(time.Now().UTC().Add(-1 * time.Duration(ca.Spec.ProgressDeadlineSeconds) * time.Second)); ca.Started.Before(&deadline) {
|
||||
c.atom.status(ca, "Deadline")
|
||||
return nil
|
||||
}
|
||||
|
||||
success, err := c.atom.check(ca)
|
||||
if err != nil {
|
||||
c.atom.status(ca, "Error")
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
if success {
|
||||
c.atom.status(ca, "Cleanup")
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func assertAtom(v interface{}) (*ct.Atom, error) {
|
||||
a, ok := v.(*ct.Atom)
|
||||
if !ok {
|
||||
return nil, errors.WithStack(fmt.Errorf("could not assert atom for type: %T", v))
|
||||
}
|
||||
|
||||
return a, nil
|
||||
}
|
||||
5
pkg/atom/pkg/apis/convox/register.go
Normal file
5
pkg/atom/pkg/apis/convox/register.go
Normal file
@ -0,0 +1,5 @@
|
||||
package convox
|
||||
|
||||
const (
|
||||
GroupName = "convox.com"
|
||||
)
|
||||
4
pkg/atom/pkg/apis/convox/v1/doc.go
Normal file
4
pkg/atom/pkg/apis/convox/v1/doc.go
Normal file
@ -0,0 +1,4 @@
|
||||
// +k8s:deepcopy-gen=package
|
||||
|
||||
// +groupName=convox.com
|
||||
package v1
|
||||
37
pkg/atom/pkg/apis/convox/v1/register.go
Normal file
37
pkg/atom/pkg/apis/convox/v1/register.go
Normal file
@ -0,0 +1,37 @@
|
||||
package v1
|
||||
|
||||
import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
|
||||
convox "github.com/convox/convox/provider/k8s/pkg/apis/convox"
|
||||
)
|
||||
|
||||
// SchemeGroupVersion is group version used to register these objects
|
||||
var SchemeGroupVersion = schema.GroupVersion{Group: convox.GroupName, Version: "v1"}
|
||||
|
||||
// Kind takes an unqualified kind and returns back a Group qualified GroupKind
|
||||
func Kind(kind string) schema.GroupKind {
|
||||
return SchemeGroupVersion.WithKind(kind).GroupKind()
|
||||
}
|
||||
|
||||
// Resource takes an unqualified resource and returns a Group qualified GroupResource
|
||||
func Resource(resource string) schema.GroupResource {
|
||||
return SchemeGroupVersion.WithResource(resource).GroupResource()
|
||||
}
|
||||
|
||||
var (
|
||||
SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes)
|
||||
AddToScheme = SchemeBuilder.AddToScheme
|
||||
)
|
||||
|
||||
// Adds the list of known types to Scheme.
|
||||
func addKnownTypes(scheme *runtime.Scheme) error {
|
||||
scheme.AddKnownTypes(SchemeGroupVersion,
|
||||
&Atom{},
|
||||
&AtomList{},
|
||||
)
|
||||
metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
|
||||
return nil
|
||||
}
|
||||
53
pkg/atom/pkg/apis/convox/v1/types.go
Normal file
53
pkg/atom/pkg/apis/convox/v1/types.go
Normal file
@ -0,0 +1,53 @@
|
||||
package v1
|
||||
|
||||
import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
// +genclient
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
|
||||
type Atom struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
metav1.ObjectMeta `json:"metadata,omitempty"`
|
||||
|
||||
Started metav1.Time `json:"started"`
|
||||
Status AtomStatus `json:"status"`
|
||||
Spec AtomSpec `json:"spec"`
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
|
||||
type AtomList struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
metav1.ListMeta `json:"metadata"`
|
||||
|
||||
Items []Atom `json:"items"`
|
||||
}
|
||||
|
||||
type AtomCondition struct {
|
||||
ApiVersion string `json:"apiVersion"`
|
||||
Conditions map[string]AtomConditionMatch `json:"conditions"`
|
||||
Kind string `json:"kind"`
|
||||
Name string `json:"name"`
|
||||
Namespace string `json:"namespace"`
|
||||
}
|
||||
|
||||
type AtomConditionMatch struct {
|
||||
Reason string `json:"reason"`
|
||||
Status string `json:"status"`
|
||||
}
|
||||
|
||||
type AtomSpec struct {
|
||||
Conditions []AtomCondition `json:"conditions"`
|
||||
Current AtomState `json:"current"`
|
||||
Previous AtomState `json:"previous"`
|
||||
ProgressDeadlineSeconds int32 `json:"progressDeadlineSeconds"`
|
||||
}
|
||||
|
||||
type AtomStatus string
|
||||
|
||||
type AtomState struct {
|
||||
Template []byte `json:"template"`
|
||||
Version string `json:"version"`
|
||||
}
|
||||
171
pkg/atom/pkg/apis/convox/v1/zz_generated.deepcopy.go
Normal file
171
pkg/atom/pkg/apis/convox/v1/zz_generated.deepcopy.go
Normal file
@ -0,0 +1,171 @@
|
||||
// +build !ignore_autogenerated
|
||||
|
||||
/*
|
||||
Copyright The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Code generated by deepcopy-gen. DO NOT EDIT.
|
||||
|
||||
package v1
|
||||
|
||||
import (
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
)
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *Atom) DeepCopyInto(out *Atom) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
|
||||
in.Started.DeepCopyInto(&out.Started)
|
||||
in.Spec.DeepCopyInto(&out.Spec)
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Atom.
|
||||
func (in *Atom) DeepCopy() *Atom {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(Atom)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *Atom) DeepCopyObject() runtime.Object {
|
||||
if c := in.DeepCopy(); c != nil {
|
||||
return c
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *AtomCondition) DeepCopyInto(out *AtomCondition) {
|
||||
*out = *in
|
||||
if in.Conditions != nil {
|
||||
in, out := &in.Conditions, &out.Conditions
|
||||
*out = make(map[string]AtomConditionMatch, len(*in))
|
||||
for key, val := range *in {
|
||||
(*out)[key] = val
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AtomCondition.
|
||||
func (in *AtomCondition) DeepCopy() *AtomCondition {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(AtomCondition)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *AtomConditionMatch) DeepCopyInto(out *AtomConditionMatch) {
|
||||
*out = *in
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AtomConditionMatch.
|
||||
func (in *AtomConditionMatch) DeepCopy() *AtomConditionMatch {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(AtomConditionMatch)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *AtomList) DeepCopyInto(out *AtomList) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
out.ListMeta = in.ListMeta
|
||||
if in.Items != nil {
|
||||
in, out := &in.Items, &out.Items
|
||||
*out = make([]Atom, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AtomList.
|
||||
func (in *AtomList) DeepCopy() *AtomList {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(AtomList)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *AtomList) DeepCopyObject() runtime.Object {
|
||||
if c := in.DeepCopy(); c != nil {
|
||||
return c
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *AtomSpec) DeepCopyInto(out *AtomSpec) {
|
||||
*out = *in
|
||||
if in.Conditions != nil {
|
||||
in, out := &in.Conditions, &out.Conditions
|
||||
*out = make([]AtomCondition, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
in.Current.DeepCopyInto(&out.Current)
|
||||
in.Previous.DeepCopyInto(&out.Previous)
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AtomSpec.
|
||||
func (in *AtomSpec) DeepCopy() *AtomSpec {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(AtomSpec)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *AtomState) DeepCopyInto(out *AtomState) {
|
||||
*out = *in
|
||||
if in.Template != nil {
|
||||
in, out := &in.Template, &out.Template
|
||||
*out = make([]byte, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AtomState.
|
||||
func (in *AtomState) DeepCopy() *AtomState {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(AtomState)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
4
pkg/atom/pkg/apis/convox/v2/doc.go
Normal file
4
pkg/atom/pkg/apis/convox/v2/doc.go
Normal file
@ -0,0 +1,4 @@
|
||||
// +k8s:deepcopy-gen=package
|
||||
|
||||
// +groupName=convox.com
|
||||
package v2
|
||||
39
pkg/atom/pkg/apis/convox/v2/register.go
Normal file
39
pkg/atom/pkg/apis/convox/v2/register.go
Normal file
@ -0,0 +1,39 @@
|
||||
package v2
|
||||
|
||||
import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
|
||||
convox "github.com/convox/convox/provider/k8s/pkg/apis/convox"
|
||||
)
|
||||
|
||||
// SchemeGroupVersion is group version used to register these objects
|
||||
var SchemeGroupVersion = schema.GroupVersion{Group: convox.GroupName, Version: "v2"}
|
||||
|
||||
// Kind takes an unqualified kind and returns back a Group qualified GroupKind
|
||||
func Kind(kind string) schema.GroupKind {
|
||||
return SchemeGroupVersion.WithKind(kind).GroupKind()
|
||||
}
|
||||
|
||||
// Resource takes an unqualified resource and returns a Group qualified GroupResource
|
||||
func Resource(resource string) schema.GroupResource {
|
||||
return SchemeGroupVersion.WithResource(resource).GroupResource()
|
||||
}
|
||||
|
||||
var (
|
||||
SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes)
|
||||
AddToScheme = SchemeBuilder.AddToScheme
|
||||
)
|
||||
|
||||
// Adds the list of known types to Scheme.
|
||||
func addKnownTypes(scheme *runtime.Scheme) error {
|
||||
scheme.AddKnownTypes(SchemeGroupVersion,
|
||||
&Atom{},
|
||||
&AtomList{},
|
||||
&AtomVersion{},
|
||||
&AtomVersionList{},
|
||||
)
|
||||
metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
|
||||
return nil
|
||||
}
|
||||
75
pkg/atom/pkg/apis/convox/v2/types.go
Normal file
75
pkg/atom/pkg/apis/convox/v2/types.go
Normal file
@ -0,0 +1,75 @@
|
||||
package v2
|
||||
|
||||
import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
// +genclient
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
|
||||
type Atom struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
metav1.ObjectMeta `json:"metadata,omitempty"`
|
||||
|
||||
Started metav1.Time `json:"started"`
|
||||
Status AtomStatus `json:"status"`
|
||||
Spec AtomSpec `json:"spec"`
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
|
||||
type AtomList struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
metav1.ListMeta `json:"metadata"`
|
||||
|
||||
Items []Atom `json:"items"`
|
||||
}
|
||||
|
||||
type AtomCondition struct {
|
||||
ApiVersion string `json:"apiVersion"`
|
||||
Conditions map[string]AtomConditionMatch `json:"conditions"`
|
||||
Kind string `json:"kind"`
|
||||
Name string `json:"name"`
|
||||
Namespace string `json:"namespace"`
|
||||
}
|
||||
|
||||
type AtomConditionMatch struct {
|
||||
Reason string `json:"reason"`
|
||||
Status string `json:"status"`
|
||||
}
|
||||
|
||||
type AtomSpec struct {
|
||||
Conditions []AtomCondition `json:"conditions"`
|
||||
CurrentVersion string `json:"currentVersion"`
|
||||
PreviousVersion string `json:"previousVersion"`
|
||||
ProgressDeadlineSeconds int32 `json:"progressDeadlineSeconds"`
|
||||
}
|
||||
|
||||
type AtomStatus string
|
||||
|
||||
// +genclient
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
|
||||
type AtomVersion struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
metav1.ObjectMeta `json:"metadata,omitempty"`
|
||||
|
||||
Status AtomVersionStatus `json:"status"`
|
||||
Spec AtomVersionSpec `json:"spec"`
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
|
||||
type AtomVersionList struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
metav1.ListMeta `json:"metadata"`
|
||||
|
||||
Items []AtomVersion `json:"items"`
|
||||
}
|
||||
|
||||
type AtomVersionSpec struct {
|
||||
Release string `json:"release"`
|
||||
Template []byte `json:"template"`
|
||||
}
|
||||
|
||||
type AtomVersionStatus string
|
||||
229
pkg/atom/pkg/apis/convox/v2/zz_generated.deepcopy.go
Normal file
229
pkg/atom/pkg/apis/convox/v2/zz_generated.deepcopy.go
Normal file
@ -0,0 +1,229 @@
|
||||
// +build !ignore_autogenerated
|
||||
|
||||
/*
|
||||
Copyright The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Code generated by deepcopy-gen. DO NOT EDIT.
|
||||
|
||||
package v2
|
||||
|
||||
import (
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
)
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *Atom) DeepCopyInto(out *Atom) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
|
||||
in.Started.DeepCopyInto(&out.Started)
|
||||
in.Spec.DeepCopyInto(&out.Spec)
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Atom.
|
||||
func (in *Atom) DeepCopy() *Atom {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(Atom)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *Atom) DeepCopyObject() runtime.Object {
|
||||
if c := in.DeepCopy(); c != nil {
|
||||
return c
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *AtomCondition) DeepCopyInto(out *AtomCondition) {
|
||||
*out = *in
|
||||
if in.Conditions != nil {
|
||||
in, out := &in.Conditions, &out.Conditions
|
||||
*out = make(map[string]AtomConditionMatch, len(*in))
|
||||
for key, val := range *in {
|
||||
(*out)[key] = val
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AtomCondition.
|
||||
func (in *AtomCondition) DeepCopy() *AtomCondition {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(AtomCondition)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *AtomConditionMatch) DeepCopyInto(out *AtomConditionMatch) {
|
||||
*out = *in
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AtomConditionMatch.
|
||||
func (in *AtomConditionMatch) DeepCopy() *AtomConditionMatch {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(AtomConditionMatch)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *AtomList) DeepCopyInto(out *AtomList) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
out.ListMeta = in.ListMeta
|
||||
if in.Items != nil {
|
||||
in, out := &in.Items, &out.Items
|
||||
*out = make([]Atom, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AtomList.
|
||||
func (in *AtomList) DeepCopy() *AtomList {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(AtomList)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *AtomList) DeepCopyObject() runtime.Object {
|
||||
if c := in.DeepCopy(); c != nil {
|
||||
return c
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *AtomSpec) DeepCopyInto(out *AtomSpec) {
|
||||
*out = *in
|
||||
if in.Conditions != nil {
|
||||
in, out := &in.Conditions, &out.Conditions
|
||||
*out = make([]AtomCondition, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AtomSpec.
|
||||
func (in *AtomSpec) DeepCopy() *AtomSpec {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(AtomSpec)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *AtomVersion) DeepCopyInto(out *AtomVersion) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
|
||||
in.Spec.DeepCopyInto(&out.Spec)
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AtomVersion.
|
||||
func (in *AtomVersion) DeepCopy() *AtomVersion {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(AtomVersion)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *AtomVersion) DeepCopyObject() runtime.Object {
|
||||
if c := in.DeepCopy(); c != nil {
|
||||
return c
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *AtomVersionList) DeepCopyInto(out *AtomVersionList) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
out.ListMeta = in.ListMeta
|
||||
if in.Items != nil {
|
||||
in, out := &in.Items, &out.Items
|
||||
*out = make([]AtomVersion, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AtomVersionList.
|
||||
func (in *AtomVersionList) DeepCopy() *AtomVersionList {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(AtomVersionList)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *AtomVersionList) DeepCopyObject() runtime.Object {
|
||||
if c := in.DeepCopy(); c != nil {
|
||||
return c
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *AtomVersionSpec) DeepCopyInto(out *AtomVersionSpec) {
|
||||
*out = *in
|
||||
if in.Template != nil {
|
||||
in, out := &in.Template, &out.Template
|
||||
*out = make([]byte, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AtomVersionSpec.
|
||||
func (in *AtomVersionSpec) DeepCopy() *AtomVersionSpec {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(AtomVersionSpec)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
112
pkg/atom/pkg/client/clientset/versioned/clientset.go
Normal file
112
pkg/atom/pkg/client/clientset/versioned/clientset.go
Normal file
@ -0,0 +1,112 @@
|
||||
/*
|
||||
Copyright The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package versioned
|
||||
|
||||
import (
|
||||
convoxv1 "github.com/convox/convox/pkg/atom/pkg/client/clientset/versioned/typed/convox/v1"
|
||||
convoxv2 "github.com/convox/convox/pkg/atom/pkg/client/clientset/versioned/typed/convox/v2"
|
||||
discovery "k8s.io/client-go/discovery"
|
||||
rest "k8s.io/client-go/rest"
|
||||
flowcontrol "k8s.io/client-go/util/flowcontrol"
|
||||
)
|
||||
|
||||
type Interface interface {
|
||||
Discovery() discovery.DiscoveryInterface
|
||||
ConvoxV1() convoxv1.ConvoxV1Interface
|
||||
ConvoxV2() convoxv2.ConvoxV2Interface
|
||||
// Deprecated: please explicitly pick a version if possible.
|
||||
Convox() convoxv2.ConvoxV2Interface
|
||||
}
|
||||
|
||||
// Clientset contains the clients for groups. Each group has exactly one
|
||||
// version included in a Clientset.
|
||||
type Clientset struct {
|
||||
*discovery.DiscoveryClient
|
||||
convoxV1 *convoxv1.ConvoxV1Client
|
||||
convoxV2 *convoxv2.ConvoxV2Client
|
||||
}
|
||||
|
||||
// ConvoxV1 retrieves the ConvoxV1Client
|
||||
func (c *Clientset) ConvoxV1() convoxv1.ConvoxV1Interface {
|
||||
return c.convoxV1
|
||||
}
|
||||
|
||||
// ConvoxV2 retrieves the ConvoxV2Client
|
||||
func (c *Clientset) ConvoxV2() convoxv2.ConvoxV2Interface {
|
||||
return c.convoxV2
|
||||
}
|
||||
|
||||
// Deprecated: Convox retrieves the default version of ConvoxClient.
|
||||
// Please explicitly pick a version.
|
||||
func (c *Clientset) Convox() convoxv2.ConvoxV2Interface {
|
||||
return c.convoxV2
|
||||
}
|
||||
|
||||
// Discovery retrieves the DiscoveryClient
|
||||
func (c *Clientset) Discovery() discovery.DiscoveryInterface {
|
||||
if c == nil {
|
||||
return nil
|
||||
}
|
||||
return c.DiscoveryClient
|
||||
}
|
||||
|
||||
// NewForConfig creates a new Clientset for the given config.
|
||||
func NewForConfig(c *rest.Config) (*Clientset, error) {
|
||||
configShallowCopy := *c
|
||||
if configShallowCopy.RateLimiter == nil && configShallowCopy.QPS > 0 {
|
||||
configShallowCopy.RateLimiter = flowcontrol.NewTokenBucketRateLimiter(configShallowCopy.QPS, configShallowCopy.Burst)
|
||||
}
|
||||
var cs Clientset
|
||||
var err error
|
||||
cs.convoxV1, err = convoxv1.NewForConfig(&configShallowCopy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cs.convoxV2, err = convoxv2.NewForConfig(&configShallowCopy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cs.DiscoveryClient, err = discovery.NewDiscoveryClientForConfig(&configShallowCopy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &cs, nil
|
||||
}
|
||||
|
||||
// NewForConfigOrDie creates a new Clientset for the given config and
|
||||
// panics if there is an error in the config.
|
||||
func NewForConfigOrDie(c *rest.Config) *Clientset {
|
||||
var cs Clientset
|
||||
cs.convoxV1 = convoxv1.NewForConfigOrDie(c)
|
||||
cs.convoxV2 = convoxv2.NewForConfigOrDie(c)
|
||||
|
||||
cs.DiscoveryClient = discovery.NewDiscoveryClientForConfigOrDie(c)
|
||||
return &cs
|
||||
}
|
||||
|
||||
// New creates a new Clientset for the given RESTClient.
|
||||
func New(c rest.Interface) *Clientset {
|
||||
var cs Clientset
|
||||
cs.convoxV1 = convoxv1.New(c)
|
||||
cs.convoxV2 = convoxv2.New(c)
|
||||
|
||||
cs.DiscoveryClient = discovery.NewDiscoveryClient(c)
|
||||
return &cs
|
||||
}
|
||||
20
pkg/atom/pkg/client/clientset/versioned/doc.go
Normal file
20
pkg/atom/pkg/client/clientset/versioned/doc.go
Normal file
@ -0,0 +1,20 @@
|
||||
/*
|
||||
Copyright The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
// This package has the automatically generated clientset.
|
||||
package versioned
|
||||
@ -0,0 +1,89 @@
|
||||
/*
|
||||
Copyright The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package fake
|
||||
|
||||
import (
|
||||
clientset "github.com/convox/convox/pkg/atom/pkg/client/clientset/versioned"
|
||||
convoxv1 "github.com/convox/convox/pkg/atom/pkg/client/clientset/versioned/typed/convox/v1"
|
||||
fakeconvoxv1 "github.com/convox/convox/pkg/atom/pkg/client/clientset/versioned/typed/convox/v1/fake"
|
||||
convoxv2 "github.com/convox/convox/pkg/atom/pkg/client/clientset/versioned/typed/convox/v2"
|
||||
fakeconvoxv2 "github.com/convox/convox/pkg/atom/pkg/client/clientset/versioned/typed/convox/v2/fake"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/watch"
|
||||
"k8s.io/client-go/discovery"
|
||||
fakediscovery "k8s.io/client-go/discovery/fake"
|
||||
"k8s.io/client-go/testing"
|
||||
)
|
||||
|
||||
// NewSimpleClientset returns a clientset that will respond with the provided objects.
|
||||
// It's backed by a very simple object tracker that processes creates, updates and deletions as-is,
|
||||
// without applying any validations and/or defaults. It shouldn't be considered a replacement
|
||||
// for a real clientset and is mostly useful in simple unit tests.
|
||||
func NewSimpleClientset(objects ...runtime.Object) *Clientset {
|
||||
o := testing.NewObjectTracker(scheme, codecs.UniversalDecoder())
|
||||
for _, obj := range objects {
|
||||
if err := o.Add(obj); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
cs := &Clientset{}
|
||||
cs.discovery = &fakediscovery.FakeDiscovery{Fake: &cs.Fake}
|
||||
cs.AddReactor("*", "*", testing.ObjectReaction(o))
|
||||
cs.AddWatchReactor("*", func(action testing.Action) (handled bool, ret watch.Interface, err error) {
|
||||
gvr := action.GetResource()
|
||||
ns := action.GetNamespace()
|
||||
watch, err := o.Watch(gvr, ns)
|
||||
if err != nil {
|
||||
return false, nil, err
|
||||
}
|
||||
return true, watch, nil
|
||||
})
|
||||
|
||||
return cs
|
||||
}
|
||||
|
||||
// Clientset implements clientset.Interface. Meant to be embedded into a
|
||||
// struct to get a default implementation. This makes faking out just the method
|
||||
// you want to test easier.
|
||||
type Clientset struct {
|
||||
testing.Fake
|
||||
discovery *fakediscovery.FakeDiscovery
|
||||
}
|
||||
|
||||
func (c *Clientset) Discovery() discovery.DiscoveryInterface {
|
||||
return c.discovery
|
||||
}
|
||||
|
||||
var _ clientset.Interface = &Clientset{}
|
||||
|
||||
// ConvoxV1 retrieves the ConvoxV1Client
|
||||
func (c *Clientset) ConvoxV1() convoxv1.ConvoxV1Interface {
|
||||
return &fakeconvoxv1.FakeConvoxV1{Fake: &c.Fake}
|
||||
}
|
||||
|
||||
// ConvoxV2 retrieves the ConvoxV2Client
|
||||
func (c *Clientset) ConvoxV2() convoxv2.ConvoxV2Interface {
|
||||
return &fakeconvoxv2.FakeConvoxV2{Fake: &c.Fake}
|
||||
}
|
||||
|
||||
// Convox retrieves the ConvoxV2Client
|
||||
func (c *Clientset) Convox() convoxv2.ConvoxV2Interface {
|
||||
return &fakeconvoxv2.FakeConvoxV2{Fake: &c.Fake}
|
||||
}
|
||||
20
pkg/atom/pkg/client/clientset/versioned/fake/doc.go
Normal file
20
pkg/atom/pkg/client/clientset/versioned/fake/doc.go
Normal file
@ -0,0 +1,20 @@
|
||||
/*
|
||||
Copyright The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
// This package has the automatically generated fake clientset.
|
||||
package fake
|
||||
56
pkg/atom/pkg/client/clientset/versioned/fake/register.go
Normal file
56
pkg/atom/pkg/client/clientset/versioned/fake/register.go
Normal file
@ -0,0 +1,56 @@
|
||||
/*
|
||||
Copyright The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package fake
|
||||
|
||||
import (
|
||||
convoxv1 "github.com/convox/convox/pkg/atom/pkg/apis/convox/v1"
|
||||
convoxv2 "github.com/convox/convox/pkg/atom/pkg/apis/convox/v2"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
schema "k8s.io/apimachinery/pkg/runtime/schema"
|
||||
serializer "k8s.io/apimachinery/pkg/runtime/serializer"
|
||||
)
|
||||
|
||||
var scheme = runtime.NewScheme()
|
||||
var codecs = serializer.NewCodecFactory(scheme)
|
||||
var parameterCodec = runtime.NewParameterCodec(scheme)
|
||||
|
||||
func init() {
|
||||
v1.AddToGroupVersion(scheme, schema.GroupVersion{Version: "v1"})
|
||||
AddToScheme(scheme)
|
||||
}
|
||||
|
||||
// AddToScheme adds all types of this clientset into the given scheme. This allows composition
|
||||
// of clientsets, like in:
|
||||
//
|
||||
// import (
|
||||
// "k8s.io/client-go/kubernetes"
|
||||
// clientsetscheme "k8s.io/client-go/kubernetes/scheme"
|
||||
// aggregatorclientsetscheme "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme"
|
||||
// )
|
||||
//
|
||||
// kclientset, _ := kubernetes.NewForConfig(c)
|
||||
// aggregatorclientsetscheme.AddToScheme(clientsetscheme.Scheme)
|
||||
//
|
||||
// After this, RawExtensions in Kubernetes types will serialize kube-aggregator types
|
||||
// correctly.
|
||||
func AddToScheme(scheme *runtime.Scheme) {
|
||||
convoxv1.AddToScheme(scheme)
|
||||
convoxv2.AddToScheme(scheme)
|
||||
}
|
||||
20
pkg/atom/pkg/client/clientset/versioned/scheme/doc.go
Normal file
20
pkg/atom/pkg/client/clientset/versioned/scheme/doc.go
Normal file
@ -0,0 +1,20 @@
|
||||
/*
|
||||
Copyright The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
// This package contains the scheme of the automatically generated clientset.
|
||||
package scheme
|
||||
56
pkg/atom/pkg/client/clientset/versioned/scheme/register.go
Normal file
56
pkg/atom/pkg/client/clientset/versioned/scheme/register.go
Normal file
@ -0,0 +1,56 @@
|
||||
/*
|
||||
Copyright The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package scheme
|
||||
|
||||
import (
|
||||
convoxv1 "github.com/convox/convox/pkg/atom/pkg/apis/convox/v1"
|
||||
convoxv2 "github.com/convox/convox/pkg/atom/pkg/apis/convox/v2"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
schema "k8s.io/apimachinery/pkg/runtime/schema"
|
||||
serializer "k8s.io/apimachinery/pkg/runtime/serializer"
|
||||
)
|
||||
|
||||
var Scheme = runtime.NewScheme()
|
||||
var Codecs = serializer.NewCodecFactory(Scheme)
|
||||
var ParameterCodec = runtime.NewParameterCodec(Scheme)
|
||||
|
||||
func init() {
|
||||
v1.AddToGroupVersion(Scheme, schema.GroupVersion{Version: "v1"})
|
||||
AddToScheme(Scheme)
|
||||
}
|
||||
|
||||
// AddToScheme adds all types of this clientset into the given scheme. This allows composition
|
||||
// of clientsets, like in:
|
||||
//
|
||||
// import (
|
||||
// "k8s.io/client-go/kubernetes"
|
||||
// clientsetscheme "k8s.io/client-go/kubernetes/scheme"
|
||||
// aggregatorclientsetscheme "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme"
|
||||
// )
|
||||
//
|
||||
// kclientset, _ := kubernetes.NewForConfig(c)
|
||||
// aggregatorclientsetscheme.AddToScheme(clientsetscheme.Scheme)
|
||||
//
|
||||
// After this, RawExtensions in Kubernetes types will serialize kube-aggregator types
|
||||
// correctly.
|
||||
func AddToScheme(scheme *runtime.Scheme) {
|
||||
convoxv1.AddToScheme(scheme)
|
||||
convoxv2.AddToScheme(scheme)
|
||||
}
|
||||
174
pkg/atom/pkg/client/clientset/versioned/typed/convox/v1/atom.go
Normal file
174
pkg/atom/pkg/client/clientset/versioned/typed/convox/v1/atom.go
Normal file
@ -0,0 +1,174 @@
|
||||
/*
|
||||
Copyright The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package v1
|
||||
|
||||
import (
|
||||
v1 "github.com/convox/convox/pkg/atom/pkg/apis/convox/v1"
|
||||
scheme "github.com/convox/convox/pkg/atom/pkg/client/clientset/versioned/scheme"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
types "k8s.io/apimachinery/pkg/types"
|
||||
watch "k8s.io/apimachinery/pkg/watch"
|
||||
rest "k8s.io/client-go/rest"
|
||||
)
|
||||
|
||||
// AtomsGetter has a method to return a AtomInterface.
|
||||
// A group's client should implement this interface.
|
||||
type AtomsGetter interface {
|
||||
Atoms(namespace string) AtomInterface
|
||||
}
|
||||
|
||||
// AtomInterface has methods to work with Atom resources.
|
||||
type AtomInterface interface {
|
||||
Create(*v1.Atom) (*v1.Atom, error)
|
||||
Update(*v1.Atom) (*v1.Atom, error)
|
||||
UpdateStatus(*v1.Atom) (*v1.Atom, error)
|
||||
Delete(name string, options *metav1.DeleteOptions) error
|
||||
DeleteCollection(options *metav1.DeleteOptions, listOptions metav1.ListOptions) error
|
||||
Get(name string, options metav1.GetOptions) (*v1.Atom, error)
|
||||
List(opts metav1.ListOptions) (*v1.AtomList, error)
|
||||
Watch(opts metav1.ListOptions) (watch.Interface, error)
|
||||
Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1.Atom, err error)
|
||||
AtomExpansion
|
||||
}
|
||||
|
||||
// atoms implements AtomInterface
|
||||
type atoms struct {
|
||||
client rest.Interface
|
||||
ns string
|
||||
}
|
||||
|
||||
// newAtoms returns a Atoms
|
||||
func newAtoms(c *ConvoxV1Client, namespace string) *atoms {
|
||||
return &atoms{
|
||||
client: c.RESTClient(),
|
||||
ns: namespace,
|
||||
}
|
||||
}
|
||||
|
||||
// Get takes name of the atom, and returns the corresponding atom object, and an error if there is any.
|
||||
func (c *atoms) Get(name string, options metav1.GetOptions) (result *v1.Atom, err error) {
|
||||
result = &v1.Atom{}
|
||||
err = c.client.Get().
|
||||
Namespace(c.ns).
|
||||
Resource("atoms").
|
||||
Name(name).
|
||||
VersionedParams(&options, scheme.ParameterCodec).
|
||||
Do().
|
||||
Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
// List takes label and field selectors, and returns the list of Atoms that match those selectors.
|
||||
func (c *atoms) List(opts metav1.ListOptions) (result *v1.AtomList, err error) {
|
||||
result = &v1.AtomList{}
|
||||
err = c.client.Get().
|
||||
Namespace(c.ns).
|
||||
Resource("atoms").
|
||||
VersionedParams(&opts, scheme.ParameterCodec).
|
||||
Do().
|
||||
Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
// Watch returns a watch.Interface that watches the requested atoms.
|
||||
func (c *atoms) Watch(opts metav1.ListOptions) (watch.Interface, error) {
|
||||
opts.Watch = true
|
||||
return c.client.Get().
|
||||
Namespace(c.ns).
|
||||
Resource("atoms").
|
||||
VersionedParams(&opts, scheme.ParameterCodec).
|
||||
Watch()
|
||||
}
|
||||
|
||||
// Create takes the representation of a atom and creates it. Returns the server's representation of the atom, and an error, if there is any.
|
||||
func (c *atoms) Create(atom *v1.Atom) (result *v1.Atom, err error) {
|
||||
result = &v1.Atom{}
|
||||
err = c.client.Post().
|
||||
Namespace(c.ns).
|
||||
Resource("atoms").
|
||||
Body(atom).
|
||||
Do().
|
||||
Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
// Update takes the representation of a atom and updates it. Returns the server's representation of the atom, and an error, if there is any.
|
||||
func (c *atoms) Update(atom *v1.Atom) (result *v1.Atom, err error) {
|
||||
result = &v1.Atom{}
|
||||
err = c.client.Put().
|
||||
Namespace(c.ns).
|
||||
Resource("atoms").
|
||||
Name(atom.Name).
|
||||
Body(atom).
|
||||
Do().
|
||||
Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
// UpdateStatus was generated because the type contains a Status member.
|
||||
// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
|
||||
|
||||
func (c *atoms) UpdateStatus(atom *v1.Atom) (result *v1.Atom, err error) {
|
||||
result = &v1.Atom{}
|
||||
err = c.client.Put().
|
||||
Namespace(c.ns).
|
||||
Resource("atoms").
|
||||
Name(atom.Name).
|
||||
SubResource("status").
|
||||
Body(atom).
|
||||
Do().
|
||||
Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
// Delete takes name of the atom and deletes it. Returns an error if one occurs.
|
||||
func (c *atoms) Delete(name string, options *metav1.DeleteOptions) error {
|
||||
return c.client.Delete().
|
||||
Namespace(c.ns).
|
||||
Resource("atoms").
|
||||
Name(name).
|
||||
Body(options).
|
||||
Do().
|
||||
Error()
|
||||
}
|
||||
|
||||
// DeleteCollection deletes a collection of objects.
|
||||
func (c *atoms) DeleteCollection(options *metav1.DeleteOptions, listOptions metav1.ListOptions) error {
|
||||
return c.client.Delete().
|
||||
Namespace(c.ns).
|
||||
Resource("atoms").
|
||||
VersionedParams(&listOptions, scheme.ParameterCodec).
|
||||
Body(options).
|
||||
Do().
|
||||
Error()
|
||||
}
|
||||
|
||||
// Patch applies the patch and returns the patched atom.
|
||||
func (c *atoms) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1.Atom, err error) {
|
||||
result = &v1.Atom{}
|
||||
err = c.client.Patch(pt).
|
||||
Namespace(c.ns).
|
||||
Resource("atoms").
|
||||
SubResource(subresources...).
|
||||
Name(name).
|
||||
Body(data).
|
||||
Do().
|
||||
Into(result)
|
||||
return
|
||||
}
|
||||
@ -0,0 +1,90 @@
|
||||
/*
|
||||
Copyright The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package v1
|
||||
|
||||
import (
|
||||
v1 "github.com/convox/convox/pkg/atom/pkg/apis/convox/v1"
|
||||
"github.com/convox/convox/pkg/atom/pkg/client/clientset/versioned/scheme"
|
||||
serializer "k8s.io/apimachinery/pkg/runtime/serializer"
|
||||
rest "k8s.io/client-go/rest"
|
||||
)
|
||||
|
||||
type ConvoxV1Interface interface {
|
||||
RESTClient() rest.Interface
|
||||
AtomsGetter
|
||||
}
|
||||
|
||||
// ConvoxV1Client is used to interact with features provided by the convox.com group.
|
||||
type ConvoxV1Client struct {
|
||||
restClient rest.Interface
|
||||
}
|
||||
|
||||
func (c *ConvoxV1Client) Atoms(namespace string) AtomInterface {
|
||||
return newAtoms(c, namespace)
|
||||
}
|
||||
|
||||
// NewForConfig creates a new ConvoxV1Client for the given config.
|
||||
func NewForConfig(c *rest.Config) (*ConvoxV1Client, error) {
|
||||
config := *c
|
||||
if err := setConfigDefaults(&config); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
client, err := rest.RESTClientFor(&config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &ConvoxV1Client{client}, nil
|
||||
}
|
||||
|
||||
// NewForConfigOrDie creates a new ConvoxV1Client for the given config and
|
||||
// panics if there is an error in the config.
|
||||
func NewForConfigOrDie(c *rest.Config) *ConvoxV1Client {
|
||||
client, err := NewForConfig(c)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return client
|
||||
}
|
||||
|
||||
// New creates a new ConvoxV1Client for the given RESTClient.
|
||||
func New(c rest.Interface) *ConvoxV1Client {
|
||||
return &ConvoxV1Client{c}
|
||||
}
|
||||
|
||||
func setConfigDefaults(config *rest.Config) error {
|
||||
gv := v1.SchemeGroupVersion
|
||||
config.GroupVersion = &gv
|
||||
config.APIPath = "/apis"
|
||||
config.NegotiatedSerializer = serializer.DirectCodecFactory{CodecFactory: scheme.Codecs}
|
||||
|
||||
if config.UserAgent == "" {
|
||||
config.UserAgent = rest.DefaultKubernetesUserAgent()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// RESTClient returns a RESTClient that is used to communicate
|
||||
// with API server by this client implementation.
|
||||
func (c *ConvoxV1Client) RESTClient() rest.Interface {
|
||||
if c == nil {
|
||||
return nil
|
||||
}
|
||||
return c.restClient
|
||||
}
|
||||
@ -0,0 +1,20 @@
|
||||
/*
|
||||
Copyright The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
// This package has the automatically generated typed clients.
|
||||
package v1
|
||||
@ -0,0 +1,20 @@
|
||||
/*
|
||||
Copyright The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
// Package fake has the automatically generated clients.
|
||||
package fake
|
||||
@ -0,0 +1,140 @@
|
||||
/*
|
||||
Copyright The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package fake
|
||||
|
||||
import (
|
||||
convoxv1 "github.com/convox/convox/pkg/atom/pkg/apis/convox/v1"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
labels "k8s.io/apimachinery/pkg/labels"
|
||||
schema "k8s.io/apimachinery/pkg/runtime/schema"
|
||||
types "k8s.io/apimachinery/pkg/types"
|
||||
watch "k8s.io/apimachinery/pkg/watch"
|
||||
testing "k8s.io/client-go/testing"
|
||||
)
|
||||
|
||||
// FakeAtoms implements AtomInterface
|
||||
type FakeAtoms struct {
|
||||
Fake *FakeConvoxV1
|
||||
ns string
|
||||
}
|
||||
|
||||
var atomsResource = schema.GroupVersionResource{Group: "convox.com", Version: "v1", Resource: "atoms"}
|
||||
|
||||
var atomsKind = schema.GroupVersionKind{Group: "convox.com", Version: "v1", Kind: "Atom"}
|
||||
|
||||
// Get takes name of the atom, and returns the corresponding atom object, and an error if there is any.
|
||||
func (c *FakeAtoms) Get(name string, options v1.GetOptions) (result *convoxv1.Atom, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewGetAction(atomsResource, c.ns, name), &convoxv1.Atom{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*convoxv1.Atom), err
|
||||
}
|
||||
|
||||
// List takes label and field selectors, and returns the list of Atoms that match those selectors.
|
||||
func (c *FakeAtoms) List(opts v1.ListOptions) (result *convoxv1.AtomList, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewListAction(atomsResource, atomsKind, c.ns, opts), &convoxv1.AtomList{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
label, _, _ := testing.ExtractFromListOptions(opts)
|
||||
if label == nil {
|
||||
label = labels.Everything()
|
||||
}
|
||||
list := &convoxv1.AtomList{ListMeta: obj.(*convoxv1.AtomList).ListMeta}
|
||||
for _, item := range obj.(*convoxv1.AtomList).Items {
|
||||
if label.Matches(labels.Set(item.Labels)) {
|
||||
list.Items = append(list.Items, item)
|
||||
}
|
||||
}
|
||||
return list, err
|
||||
}
|
||||
|
||||
// Watch returns a watch.Interface that watches the requested atoms.
|
||||
func (c *FakeAtoms) Watch(opts v1.ListOptions) (watch.Interface, error) {
|
||||
return c.Fake.
|
||||
InvokesWatch(testing.NewWatchAction(atomsResource, c.ns, opts))
|
||||
|
||||
}
|
||||
|
||||
// Create takes the representation of a atom and creates it. Returns the server's representation of the atom, and an error, if there is any.
|
||||
func (c *FakeAtoms) Create(atom *convoxv1.Atom) (result *convoxv1.Atom, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewCreateAction(atomsResource, c.ns, atom), &convoxv1.Atom{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*convoxv1.Atom), err
|
||||
}
|
||||
|
||||
// Update takes the representation of a atom and updates it. Returns the server's representation of the atom, and an error, if there is any.
|
||||
func (c *FakeAtoms) Update(atom *convoxv1.Atom) (result *convoxv1.Atom, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewUpdateAction(atomsResource, c.ns, atom), &convoxv1.Atom{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*convoxv1.Atom), err
|
||||
}
|
||||
|
||||
// UpdateStatus was generated because the type contains a Status member.
|
||||
// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
|
||||
func (c *FakeAtoms) UpdateStatus(atom *convoxv1.Atom) (*convoxv1.Atom, error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewUpdateSubresourceAction(atomsResource, "status", c.ns, atom), &convoxv1.Atom{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*convoxv1.Atom), err
|
||||
}
|
||||
|
||||
// Delete takes name of the atom and deletes it. Returns an error if one occurs.
|
||||
func (c *FakeAtoms) Delete(name string, options *v1.DeleteOptions) error {
|
||||
_, err := c.Fake.
|
||||
Invokes(testing.NewDeleteAction(atomsResource, c.ns, name), &convoxv1.Atom{})
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// DeleteCollection deletes a collection of objects.
|
||||
func (c *FakeAtoms) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
|
||||
action := testing.NewDeleteCollectionAction(atomsResource, c.ns, listOptions)
|
||||
|
||||
_, err := c.Fake.Invokes(action, &convoxv1.AtomList{})
|
||||
return err
|
||||
}
|
||||
|
||||
// Patch applies the patch and returns the patched atom.
|
||||
func (c *FakeAtoms) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *convoxv1.Atom, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewPatchSubresourceAction(atomsResource, c.ns, name, data, subresources...), &convoxv1.Atom{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*convoxv1.Atom), err
|
||||
}
|
||||
@ -0,0 +1,40 @@
|
||||
/*
|
||||
Copyright The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package fake
|
||||
|
||||
import (
|
||||
v1 "github.com/convox/convox/pkg/atom/pkg/client/clientset/versioned/typed/convox/v1"
|
||||
rest "k8s.io/client-go/rest"
|
||||
testing "k8s.io/client-go/testing"
|
||||
)
|
||||
|
||||
type FakeConvoxV1 struct {
|
||||
*testing.Fake
|
||||
}
|
||||
|
||||
func (c *FakeConvoxV1) Atoms(namespace string) v1.AtomInterface {
|
||||
return &FakeAtoms{c, namespace}
|
||||
}
|
||||
|
||||
// RESTClient returns a RESTClient that is used to communicate
|
||||
// with API server by this client implementation.
|
||||
func (c *FakeConvoxV1) RESTClient() rest.Interface {
|
||||
var ret *rest.RESTClient
|
||||
return ret
|
||||
}
|
||||
@ -0,0 +1,21 @@
|
||||
/*
|
||||
Copyright The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package v1
|
||||
|
||||
type AtomExpansion interface{}
|
||||
174
pkg/atom/pkg/client/clientset/versioned/typed/convox/v2/atom.go
Normal file
174
pkg/atom/pkg/client/clientset/versioned/typed/convox/v2/atom.go
Normal file
@ -0,0 +1,174 @@
|
||||
/*
|
||||
Copyright The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package v2
|
||||
|
||||
import (
|
||||
v2 "github.com/convox/convox/pkg/atom/pkg/apis/convox/v2"
|
||||
scheme "github.com/convox/convox/pkg/atom/pkg/client/clientset/versioned/scheme"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
types "k8s.io/apimachinery/pkg/types"
|
||||
watch "k8s.io/apimachinery/pkg/watch"
|
||||
rest "k8s.io/client-go/rest"
|
||||
)
|
||||
|
||||
// AtomsGetter has a method to return a AtomInterface.
|
||||
// A group's client should implement this interface.
|
||||
type AtomsGetter interface {
|
||||
Atoms(namespace string) AtomInterface
|
||||
}
|
||||
|
||||
// AtomInterface has methods to work with Atom resources.
|
||||
type AtomInterface interface {
|
||||
Create(*v2.Atom) (*v2.Atom, error)
|
||||
Update(*v2.Atom) (*v2.Atom, error)
|
||||
UpdateStatus(*v2.Atom) (*v2.Atom, error)
|
||||
Delete(name string, options *v1.DeleteOptions) error
|
||||
DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error
|
||||
Get(name string, options v1.GetOptions) (*v2.Atom, error)
|
||||
List(opts v1.ListOptions) (*v2.AtomList, error)
|
||||
Watch(opts v1.ListOptions) (watch.Interface, error)
|
||||
Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v2.Atom, err error)
|
||||
AtomExpansion
|
||||
}
|
||||
|
||||
// atoms implements AtomInterface
|
||||
type atoms struct {
|
||||
client rest.Interface
|
||||
ns string
|
||||
}
|
||||
|
||||
// newAtoms returns a Atoms
|
||||
func newAtoms(c *ConvoxV2Client, namespace string) *atoms {
|
||||
return &atoms{
|
||||
client: c.RESTClient(),
|
||||
ns: namespace,
|
||||
}
|
||||
}
|
||||
|
||||
// Get takes name of the atom, and returns the corresponding atom object, and an error if there is any.
|
||||
func (c *atoms) Get(name string, options v1.GetOptions) (result *v2.Atom, err error) {
|
||||
result = &v2.Atom{}
|
||||
err = c.client.Get().
|
||||
Namespace(c.ns).
|
||||
Resource("atoms").
|
||||
Name(name).
|
||||
VersionedParams(&options, scheme.ParameterCodec).
|
||||
Do().
|
||||
Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
// List takes label and field selectors, and returns the list of Atoms that match those selectors.
|
||||
func (c *atoms) List(opts v1.ListOptions) (result *v2.AtomList, err error) {
|
||||
result = &v2.AtomList{}
|
||||
err = c.client.Get().
|
||||
Namespace(c.ns).
|
||||
Resource("atoms").
|
||||
VersionedParams(&opts, scheme.ParameterCodec).
|
||||
Do().
|
||||
Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
// Watch returns a watch.Interface that watches the requested atoms.
|
||||
func (c *atoms) Watch(opts v1.ListOptions) (watch.Interface, error) {
|
||||
opts.Watch = true
|
||||
return c.client.Get().
|
||||
Namespace(c.ns).
|
||||
Resource("atoms").
|
||||
VersionedParams(&opts, scheme.ParameterCodec).
|
||||
Watch()
|
||||
}
|
||||
|
||||
// Create takes the representation of a atom and creates it. Returns the server's representation of the atom, and an error, if there is any.
|
||||
func (c *atoms) Create(atom *v2.Atom) (result *v2.Atom, err error) {
|
||||
result = &v2.Atom{}
|
||||
err = c.client.Post().
|
||||
Namespace(c.ns).
|
||||
Resource("atoms").
|
||||
Body(atom).
|
||||
Do().
|
||||
Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
// Update takes the representation of a atom and updates it. Returns the server's representation of the atom, and an error, if there is any.
|
||||
func (c *atoms) Update(atom *v2.Atom) (result *v2.Atom, err error) {
|
||||
result = &v2.Atom{}
|
||||
err = c.client.Put().
|
||||
Namespace(c.ns).
|
||||
Resource("atoms").
|
||||
Name(atom.Name).
|
||||
Body(atom).
|
||||
Do().
|
||||
Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
// UpdateStatus was generated because the type contains a Status member.
|
||||
// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
|
||||
|
||||
func (c *atoms) UpdateStatus(atom *v2.Atom) (result *v2.Atom, err error) {
|
||||
result = &v2.Atom{}
|
||||
err = c.client.Put().
|
||||
Namespace(c.ns).
|
||||
Resource("atoms").
|
||||
Name(atom.Name).
|
||||
SubResource("status").
|
||||
Body(atom).
|
||||
Do().
|
||||
Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
// Delete takes name of the atom and deletes it. Returns an error if one occurs.
|
||||
func (c *atoms) Delete(name string, options *v1.DeleteOptions) error {
|
||||
return c.client.Delete().
|
||||
Namespace(c.ns).
|
||||
Resource("atoms").
|
||||
Name(name).
|
||||
Body(options).
|
||||
Do().
|
||||
Error()
|
||||
}
|
||||
|
||||
// DeleteCollection deletes a collection of objects.
|
||||
func (c *atoms) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
|
||||
return c.client.Delete().
|
||||
Namespace(c.ns).
|
||||
Resource("atoms").
|
||||
VersionedParams(&listOptions, scheme.ParameterCodec).
|
||||
Body(options).
|
||||
Do().
|
||||
Error()
|
||||
}
|
||||
|
||||
// Patch applies the patch and returns the patched atom.
|
||||
func (c *atoms) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v2.Atom, err error) {
|
||||
result = &v2.Atom{}
|
||||
err = c.client.Patch(pt).
|
||||
Namespace(c.ns).
|
||||
Resource("atoms").
|
||||
SubResource(subresources...).
|
||||
Name(name).
|
||||
Body(data).
|
||||
Do().
|
||||
Into(result)
|
||||
return
|
||||
}
|
||||
@ -0,0 +1,174 @@
|
||||
/*
|
||||
Copyright The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package v2
|
||||
|
||||
import (
|
||||
v2 "github.com/convox/convox/pkg/atom/pkg/apis/convox/v2"
|
||||
scheme "github.com/convox/convox/pkg/atom/pkg/client/clientset/versioned/scheme"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
types "k8s.io/apimachinery/pkg/types"
|
||||
watch "k8s.io/apimachinery/pkg/watch"
|
||||
rest "k8s.io/client-go/rest"
|
||||
)
|
||||
|
||||
// AtomVersionsGetter has a method to return a AtomVersionInterface.
|
||||
// A group's client should implement this interface.
|
||||
type AtomVersionsGetter interface {
|
||||
AtomVersions(namespace string) AtomVersionInterface
|
||||
}
|
||||
|
||||
// AtomVersionInterface has methods to work with AtomVersion resources.
|
||||
type AtomVersionInterface interface {
|
||||
Create(*v2.AtomVersion) (*v2.AtomVersion, error)
|
||||
Update(*v2.AtomVersion) (*v2.AtomVersion, error)
|
||||
UpdateStatus(*v2.AtomVersion) (*v2.AtomVersion, error)
|
||||
Delete(name string, options *v1.DeleteOptions) error
|
||||
DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error
|
||||
Get(name string, options v1.GetOptions) (*v2.AtomVersion, error)
|
||||
List(opts v1.ListOptions) (*v2.AtomVersionList, error)
|
||||
Watch(opts v1.ListOptions) (watch.Interface, error)
|
||||
Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v2.AtomVersion, err error)
|
||||
AtomVersionExpansion
|
||||
}
|
||||
|
||||
// atomVersions implements AtomVersionInterface
|
||||
type atomVersions struct {
|
||||
client rest.Interface
|
||||
ns string
|
||||
}
|
||||
|
||||
// newAtomVersions returns a AtomVersions
|
||||
func newAtomVersions(c *ConvoxV2Client, namespace string) *atomVersions {
|
||||
return &atomVersions{
|
||||
client: c.RESTClient(),
|
||||
ns: namespace,
|
||||
}
|
||||
}
|
||||
|
||||
// Get takes name of the atomVersion, and returns the corresponding atomVersion object, and an error if there is any.
|
||||
func (c *atomVersions) Get(name string, options v1.GetOptions) (result *v2.AtomVersion, err error) {
|
||||
result = &v2.AtomVersion{}
|
||||
err = c.client.Get().
|
||||
Namespace(c.ns).
|
||||
Resource("atomversions").
|
||||
Name(name).
|
||||
VersionedParams(&options, scheme.ParameterCodec).
|
||||
Do().
|
||||
Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
// List takes label and field selectors, and returns the list of AtomVersions that match those selectors.
|
||||
func (c *atomVersions) List(opts v1.ListOptions) (result *v2.AtomVersionList, err error) {
|
||||
result = &v2.AtomVersionList{}
|
||||
err = c.client.Get().
|
||||
Namespace(c.ns).
|
||||
Resource("atomversions").
|
||||
VersionedParams(&opts, scheme.ParameterCodec).
|
||||
Do().
|
||||
Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
// Watch returns a watch.Interface that watches the requested atomVersions.
|
||||
func (c *atomVersions) Watch(opts v1.ListOptions) (watch.Interface, error) {
|
||||
opts.Watch = true
|
||||
return c.client.Get().
|
||||
Namespace(c.ns).
|
||||
Resource("atomversions").
|
||||
VersionedParams(&opts, scheme.ParameterCodec).
|
||||
Watch()
|
||||
}
|
||||
|
||||
// Create takes the representation of a atomVersion and creates it. Returns the server's representation of the atomVersion, and an error, if there is any.
|
||||
func (c *atomVersions) Create(atomVersion *v2.AtomVersion) (result *v2.AtomVersion, err error) {
|
||||
result = &v2.AtomVersion{}
|
||||
err = c.client.Post().
|
||||
Namespace(c.ns).
|
||||
Resource("atomversions").
|
||||
Body(atomVersion).
|
||||
Do().
|
||||
Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
// Update takes the representation of a atomVersion and updates it. Returns the server's representation of the atomVersion, and an error, if there is any.
|
||||
func (c *atomVersions) Update(atomVersion *v2.AtomVersion) (result *v2.AtomVersion, err error) {
|
||||
result = &v2.AtomVersion{}
|
||||
err = c.client.Put().
|
||||
Namespace(c.ns).
|
||||
Resource("atomversions").
|
||||
Name(atomVersion.Name).
|
||||
Body(atomVersion).
|
||||
Do().
|
||||
Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
// UpdateStatus was generated because the type contains a Status member.
|
||||
// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
|
||||
|
||||
func (c *atomVersions) UpdateStatus(atomVersion *v2.AtomVersion) (result *v2.AtomVersion, err error) {
|
||||
result = &v2.AtomVersion{}
|
||||
err = c.client.Put().
|
||||
Namespace(c.ns).
|
||||
Resource("atomversions").
|
||||
Name(atomVersion.Name).
|
||||
SubResource("status").
|
||||
Body(atomVersion).
|
||||
Do().
|
||||
Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
// Delete takes name of the atomVersion and deletes it. Returns an error if one occurs.
|
||||
func (c *atomVersions) Delete(name string, options *v1.DeleteOptions) error {
|
||||
return c.client.Delete().
|
||||
Namespace(c.ns).
|
||||
Resource("atomversions").
|
||||
Name(name).
|
||||
Body(options).
|
||||
Do().
|
||||
Error()
|
||||
}
|
||||
|
||||
// DeleteCollection deletes a collection of objects.
|
||||
func (c *atomVersions) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
|
||||
return c.client.Delete().
|
||||
Namespace(c.ns).
|
||||
Resource("atomversions").
|
||||
VersionedParams(&listOptions, scheme.ParameterCodec).
|
||||
Body(options).
|
||||
Do().
|
||||
Error()
|
||||
}
|
||||
|
||||
// Patch applies the patch and returns the patched atomVersion.
|
||||
func (c *atomVersions) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v2.AtomVersion, err error) {
|
||||
result = &v2.AtomVersion{}
|
||||
err = c.client.Patch(pt).
|
||||
Namespace(c.ns).
|
||||
Resource("atomversions").
|
||||
SubResource(subresources...).
|
||||
Name(name).
|
||||
Body(data).
|
||||
Do().
|
||||
Into(result)
|
||||
return
|
||||
}
|
||||
@ -0,0 +1,95 @@
|
||||
/*
|
||||
Copyright The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package v2
|
||||
|
||||
import (
|
||||
v2 "github.com/convox/convox/pkg/atom/pkg/apis/convox/v2"
|
||||
"github.com/convox/convox/pkg/atom/pkg/client/clientset/versioned/scheme"
|
||||
serializer "k8s.io/apimachinery/pkg/runtime/serializer"
|
||||
rest "k8s.io/client-go/rest"
|
||||
)
|
||||
|
||||
type ConvoxV2Interface interface {
|
||||
RESTClient() rest.Interface
|
||||
AtomsGetter
|
||||
AtomVersionsGetter
|
||||
}
|
||||
|
||||
// ConvoxV2Client is used to interact with features provided by the convox.com group.
|
||||
type ConvoxV2Client struct {
|
||||
restClient rest.Interface
|
||||
}
|
||||
|
||||
func (c *ConvoxV2Client) Atoms(namespace string) AtomInterface {
|
||||
return newAtoms(c, namespace)
|
||||
}
|
||||
|
||||
func (c *ConvoxV2Client) AtomVersions(namespace string) AtomVersionInterface {
|
||||
return newAtomVersions(c, namespace)
|
||||
}
|
||||
|
||||
// NewForConfig creates a new ConvoxV2Client for the given config.
|
||||
func NewForConfig(c *rest.Config) (*ConvoxV2Client, error) {
|
||||
config := *c
|
||||
if err := setConfigDefaults(&config); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
client, err := rest.RESTClientFor(&config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &ConvoxV2Client{client}, nil
|
||||
}
|
||||
|
||||
// NewForConfigOrDie creates a new ConvoxV2Client for the given config and
|
||||
// panics if there is an error in the config.
|
||||
func NewForConfigOrDie(c *rest.Config) *ConvoxV2Client {
|
||||
client, err := NewForConfig(c)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return client
|
||||
}
|
||||
|
||||
// New creates a new ConvoxV2Client for the given RESTClient.
|
||||
func New(c rest.Interface) *ConvoxV2Client {
|
||||
return &ConvoxV2Client{c}
|
||||
}
|
||||
|
||||
func setConfigDefaults(config *rest.Config) error {
|
||||
gv := v2.SchemeGroupVersion
|
||||
config.GroupVersion = &gv
|
||||
config.APIPath = "/apis"
|
||||
config.NegotiatedSerializer = serializer.DirectCodecFactory{CodecFactory: scheme.Codecs}
|
||||
|
||||
if config.UserAgent == "" {
|
||||
config.UserAgent = rest.DefaultKubernetesUserAgent()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// RESTClient returns a RESTClient that is used to communicate
|
||||
// with API server by this client implementation.
|
||||
func (c *ConvoxV2Client) RESTClient() rest.Interface {
|
||||
if c == nil {
|
||||
return nil
|
||||
}
|
||||
return c.restClient
|
||||
}
|
||||
@ -0,0 +1,20 @@
|
||||
/*
|
||||
Copyright The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
// This package has the automatically generated typed clients.
|
||||
package v2
|
||||
@ -0,0 +1,20 @@
|
||||
/*
|
||||
Copyright The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
// Package fake has the automatically generated clients.
|
||||
package fake
|
||||
@ -0,0 +1,140 @@
|
||||
/*
|
||||
Copyright The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package fake
|
||||
|
||||
import (
|
||||
v2 "github.com/convox/convox/pkg/atom/pkg/apis/convox/v2"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
labels "k8s.io/apimachinery/pkg/labels"
|
||||
schema "k8s.io/apimachinery/pkg/runtime/schema"
|
||||
types "k8s.io/apimachinery/pkg/types"
|
||||
watch "k8s.io/apimachinery/pkg/watch"
|
||||
testing "k8s.io/client-go/testing"
|
||||
)
|
||||
|
||||
// FakeAtoms implements AtomInterface
|
||||
type FakeAtoms struct {
|
||||
Fake *FakeConvoxV2
|
||||
ns string
|
||||
}
|
||||
|
||||
var atomsResource = schema.GroupVersionResource{Group: "convox.com", Version: "v2", Resource: "atoms"}
|
||||
|
||||
var atomsKind = schema.GroupVersionKind{Group: "convox.com", Version: "v2", Kind: "Atom"}
|
||||
|
||||
// Get takes name of the atom, and returns the corresponding atom object, and an error if there is any.
|
||||
func (c *FakeAtoms) Get(name string, options v1.GetOptions) (result *v2.Atom, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewGetAction(atomsResource, c.ns, name), &v2.Atom{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v2.Atom), err
|
||||
}
|
||||
|
||||
// List takes label and field selectors, and returns the list of Atoms that match those selectors.
|
||||
func (c *FakeAtoms) List(opts v1.ListOptions) (result *v2.AtomList, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewListAction(atomsResource, atomsKind, c.ns, opts), &v2.AtomList{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
label, _, _ := testing.ExtractFromListOptions(opts)
|
||||
if label == nil {
|
||||
label = labels.Everything()
|
||||
}
|
||||
list := &v2.AtomList{ListMeta: obj.(*v2.AtomList).ListMeta}
|
||||
for _, item := range obj.(*v2.AtomList).Items {
|
||||
if label.Matches(labels.Set(item.Labels)) {
|
||||
list.Items = append(list.Items, item)
|
||||
}
|
||||
}
|
||||
return list, err
|
||||
}
|
||||
|
||||
// Watch returns a watch.Interface that watches the requested atoms.
|
||||
func (c *FakeAtoms) Watch(opts v1.ListOptions) (watch.Interface, error) {
|
||||
return c.Fake.
|
||||
InvokesWatch(testing.NewWatchAction(atomsResource, c.ns, opts))
|
||||
|
||||
}
|
||||
|
||||
// Create takes the representation of a atom and creates it. Returns the server's representation of the atom, and an error, if there is any.
|
||||
func (c *FakeAtoms) Create(atom *v2.Atom) (result *v2.Atom, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewCreateAction(atomsResource, c.ns, atom), &v2.Atom{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v2.Atom), err
|
||||
}
|
||||
|
||||
// Update takes the representation of a atom and updates it. Returns the server's representation of the atom, and an error, if there is any.
|
||||
func (c *FakeAtoms) Update(atom *v2.Atom) (result *v2.Atom, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewUpdateAction(atomsResource, c.ns, atom), &v2.Atom{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v2.Atom), err
|
||||
}
|
||||
|
||||
// UpdateStatus was generated because the type contains a Status member.
|
||||
// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
|
||||
func (c *FakeAtoms) UpdateStatus(atom *v2.Atom) (*v2.Atom, error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewUpdateSubresourceAction(atomsResource, "status", c.ns, atom), &v2.Atom{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v2.Atom), err
|
||||
}
|
||||
|
||||
// Delete takes name of the atom and deletes it. Returns an error if one occurs.
|
||||
func (c *FakeAtoms) Delete(name string, options *v1.DeleteOptions) error {
|
||||
_, err := c.Fake.
|
||||
Invokes(testing.NewDeleteAction(atomsResource, c.ns, name), &v2.Atom{})
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// DeleteCollection deletes a collection of objects.
|
||||
func (c *FakeAtoms) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
|
||||
action := testing.NewDeleteCollectionAction(atomsResource, c.ns, listOptions)
|
||||
|
||||
_, err := c.Fake.Invokes(action, &v2.AtomList{})
|
||||
return err
|
||||
}
|
||||
|
||||
// Patch applies the patch and returns the patched atom.
|
||||
func (c *FakeAtoms) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v2.Atom, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewPatchSubresourceAction(atomsResource, c.ns, name, data, subresources...), &v2.Atom{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v2.Atom), err
|
||||
}
|
||||
@ -0,0 +1,140 @@
|
||||
/*
|
||||
Copyright The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package fake
|
||||
|
||||
import (
|
||||
v2 "github.com/convox/convox/pkg/atom/pkg/apis/convox/v2"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
labels "k8s.io/apimachinery/pkg/labels"
|
||||
schema "k8s.io/apimachinery/pkg/runtime/schema"
|
||||
types "k8s.io/apimachinery/pkg/types"
|
||||
watch "k8s.io/apimachinery/pkg/watch"
|
||||
testing "k8s.io/client-go/testing"
|
||||
)
|
||||
|
||||
// FakeAtomVersions implements AtomVersionInterface
|
||||
type FakeAtomVersions struct {
|
||||
Fake *FakeConvoxV2
|
||||
ns string
|
||||
}
|
||||
|
||||
var atomversionsResource = schema.GroupVersionResource{Group: "convox.com", Version: "v2", Resource: "atomversions"}
|
||||
|
||||
var atomversionsKind = schema.GroupVersionKind{Group: "convox.com", Version: "v2", Kind: "AtomVersion"}
|
||||
|
||||
// Get takes name of the atomVersion, and returns the corresponding atomVersion object, and an error if there is any.
|
||||
func (c *FakeAtomVersions) Get(name string, options v1.GetOptions) (result *v2.AtomVersion, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewGetAction(atomversionsResource, c.ns, name), &v2.AtomVersion{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v2.AtomVersion), err
|
||||
}
|
||||
|
||||
// List takes label and field selectors, and returns the list of AtomVersions that match those selectors.
|
||||
func (c *FakeAtomVersions) List(opts v1.ListOptions) (result *v2.AtomVersionList, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewListAction(atomversionsResource, atomversionsKind, c.ns, opts), &v2.AtomVersionList{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
label, _, _ := testing.ExtractFromListOptions(opts)
|
||||
if label == nil {
|
||||
label = labels.Everything()
|
||||
}
|
||||
list := &v2.AtomVersionList{ListMeta: obj.(*v2.AtomVersionList).ListMeta}
|
||||
for _, item := range obj.(*v2.AtomVersionList).Items {
|
||||
if label.Matches(labels.Set(item.Labels)) {
|
||||
list.Items = append(list.Items, item)
|
||||
}
|
||||
}
|
||||
return list, err
|
||||
}
|
||||
|
||||
// Watch returns a watch.Interface that watches the requested atomVersions.
|
||||
func (c *FakeAtomVersions) Watch(opts v1.ListOptions) (watch.Interface, error) {
|
||||
return c.Fake.
|
||||
InvokesWatch(testing.NewWatchAction(atomversionsResource, c.ns, opts))
|
||||
|
||||
}
|
||||
|
||||
// Create takes the representation of a atomVersion and creates it. Returns the server's representation of the atomVersion, and an error, if there is any.
|
||||
func (c *FakeAtomVersions) Create(atomVersion *v2.AtomVersion) (result *v2.AtomVersion, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewCreateAction(atomversionsResource, c.ns, atomVersion), &v2.AtomVersion{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v2.AtomVersion), err
|
||||
}
|
||||
|
||||
// Update takes the representation of a atomVersion and updates it. Returns the server's representation of the atomVersion, and an error, if there is any.
|
||||
func (c *FakeAtomVersions) Update(atomVersion *v2.AtomVersion) (result *v2.AtomVersion, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewUpdateAction(atomversionsResource, c.ns, atomVersion), &v2.AtomVersion{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v2.AtomVersion), err
|
||||
}
|
||||
|
||||
// UpdateStatus was generated because the type contains a Status member.
|
||||
// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
|
||||
func (c *FakeAtomVersions) UpdateStatus(atomVersion *v2.AtomVersion) (*v2.AtomVersion, error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewUpdateSubresourceAction(atomversionsResource, "status", c.ns, atomVersion), &v2.AtomVersion{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v2.AtomVersion), err
|
||||
}
|
||||
|
||||
// Delete takes name of the atomVersion and deletes it. Returns an error if one occurs.
|
||||
func (c *FakeAtomVersions) Delete(name string, options *v1.DeleteOptions) error {
|
||||
_, err := c.Fake.
|
||||
Invokes(testing.NewDeleteAction(atomversionsResource, c.ns, name), &v2.AtomVersion{})
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// DeleteCollection deletes a collection of objects.
|
||||
func (c *FakeAtomVersions) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
|
||||
action := testing.NewDeleteCollectionAction(atomversionsResource, c.ns, listOptions)
|
||||
|
||||
_, err := c.Fake.Invokes(action, &v2.AtomVersionList{})
|
||||
return err
|
||||
}
|
||||
|
||||
// Patch applies the patch and returns the patched atomVersion.
|
||||
func (c *FakeAtomVersions) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v2.AtomVersion, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewPatchSubresourceAction(atomversionsResource, c.ns, name, data, subresources...), &v2.AtomVersion{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v2.AtomVersion), err
|
||||
}
|
||||
@ -0,0 +1,44 @@
|
||||
/*
|
||||
Copyright The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package fake
|
||||
|
||||
import (
|
||||
v2 "github.com/convox/convox/pkg/atom/pkg/client/clientset/versioned/typed/convox/v2"
|
||||
rest "k8s.io/client-go/rest"
|
||||
testing "k8s.io/client-go/testing"
|
||||
)
|
||||
|
||||
type FakeConvoxV2 struct {
|
||||
*testing.Fake
|
||||
}
|
||||
|
||||
func (c *FakeConvoxV2) Atoms(namespace string) v2.AtomInterface {
|
||||
return &FakeAtoms{c, namespace}
|
||||
}
|
||||
|
||||
func (c *FakeConvoxV2) AtomVersions(namespace string) v2.AtomVersionInterface {
|
||||
return &FakeAtomVersions{c, namespace}
|
||||
}
|
||||
|
||||
// RESTClient returns a RESTClient that is used to communicate
|
||||
// with API server by this client implementation.
|
||||
func (c *FakeConvoxV2) RESTClient() rest.Interface {
|
||||
var ret *rest.RESTClient
|
||||
return ret
|
||||
}
|
||||
@ -0,0 +1,23 @@
|
||||
/*
|
||||
Copyright The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package v2
|
||||
|
||||
type AtomExpansion interface{}
|
||||
|
||||
type AtomVersionExpansion interface{}
|
||||
@ -0,0 +1,54 @@
|
||||
/*
|
||||
Copyright The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Code generated by informer-gen. DO NOT EDIT.
|
||||
|
||||
package convox
|
||||
|
||||
import (
|
||||
v1 "github.com/convox/convox/pkg/atom/pkg/client/informers/externalversions/convox/v1"
|
||||
v2 "github.com/convox/convox/pkg/atom/pkg/client/informers/externalversions/convox/v2"
|
||||
internalinterfaces "github.com/convox/convox/pkg/atom/pkg/client/informers/externalversions/internalinterfaces"
|
||||
)
|
||||
|
||||
// Interface provides access to each of this group's versions.
|
||||
type Interface interface {
|
||||
// V1 provides access to shared informers for resources in V1.
|
||||
V1() v1.Interface
|
||||
// V2 provides access to shared informers for resources in V2.
|
||||
V2() v2.Interface
|
||||
}
|
||||
|
||||
type group struct {
|
||||
factory internalinterfaces.SharedInformerFactory
|
||||
namespace string
|
||||
tweakListOptions internalinterfaces.TweakListOptionsFunc
|
||||
}
|
||||
|
||||
// New returns a new Interface.
|
||||
func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface {
|
||||
return &group{factory: f, namespace: namespace, tweakListOptions: tweakListOptions}
|
||||
}
|
||||
|
||||
// V1 returns a new v1.Interface.
|
||||
func (g *group) V1() v1.Interface {
|
||||
return v1.New(g.factory, g.namespace, g.tweakListOptions)
|
||||
}
|
||||
|
||||
// V2 returns a new v2.Interface.
|
||||
func (g *group) V2() v2.Interface {
|
||||
return v2.New(g.factory, g.namespace, g.tweakListOptions)
|
||||
}
|
||||
@ -0,0 +1,89 @@
|
||||
/*
|
||||
Copyright The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Code generated by informer-gen. DO NOT EDIT.
|
||||
|
||||
package v1
|
||||
|
||||
import (
|
||||
time "time"
|
||||
|
||||
convoxv1 "github.com/convox/convox/pkg/atom/pkg/apis/convox/v1"
|
||||
versioned "github.com/convox/convox/pkg/atom/pkg/client/clientset/versioned"
|
||||
internalinterfaces "github.com/convox/convox/pkg/atom/pkg/client/informers/externalversions/internalinterfaces"
|
||||
v1 "github.com/convox/convox/pkg/atom/pkg/client/listers/convox/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
watch "k8s.io/apimachinery/pkg/watch"
|
||||
cache "k8s.io/client-go/tools/cache"
|
||||
)
|
||||
|
||||
// AtomInformer provides access to a shared informer and lister for
|
||||
// Atoms.
|
||||
type AtomInformer interface {
|
||||
Informer() cache.SharedIndexInformer
|
||||
Lister() v1.AtomLister
|
||||
}
|
||||
|
||||
type atomInformer struct {
|
||||
factory internalinterfaces.SharedInformerFactory
|
||||
tweakListOptions internalinterfaces.TweakListOptionsFunc
|
||||
namespace string
|
||||
}
|
||||
|
||||
// NewAtomInformer constructs a new informer for Atom type.
|
||||
// Always prefer using an informer factory to get a shared informer instead of getting an independent
|
||||
// one. This reduces memory footprint and number of connections to the server.
|
||||
func NewAtomInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer {
|
||||
return NewFilteredAtomInformer(client, namespace, resyncPeriod, indexers, nil)
|
||||
}
|
||||
|
||||
// NewFilteredAtomInformer constructs a new informer for Atom type.
|
||||
// Always prefer using an informer factory to get a shared informer instead of getting an independent
|
||||
// one. This reduces memory footprint and number of connections to the server.
|
||||
func NewFilteredAtomInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer {
|
||||
return cache.NewSharedIndexInformer(
|
||||
&cache.ListWatch{
|
||||
ListFunc: func(options metav1.ListOptions) (runtime.Object, error) {
|
||||
if tweakListOptions != nil {
|
||||
tweakListOptions(&options)
|
||||
}
|
||||
return client.ConvoxV1().Atoms(namespace).List(options)
|
||||
},
|
||||
WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) {
|
||||
if tweakListOptions != nil {
|
||||
tweakListOptions(&options)
|
||||
}
|
||||
return client.ConvoxV1().Atoms(namespace).Watch(options)
|
||||
},
|
||||
},
|
||||
&convoxv1.Atom{},
|
||||
resyncPeriod,
|
||||
indexers,
|
||||
)
|
||||
}
|
||||
|
||||
func (f *atomInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer {
|
||||
return NewFilteredAtomInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions)
|
||||
}
|
||||
|
||||
func (f *atomInformer) Informer() cache.SharedIndexInformer {
|
||||
return f.factory.InformerFor(&convoxv1.Atom{}, f.defaultInformer)
|
||||
}
|
||||
|
||||
func (f *atomInformer) Lister() v1.AtomLister {
|
||||
return v1.NewAtomLister(f.Informer().GetIndexer())
|
||||
}
|
||||
@ -0,0 +1,45 @@
|
||||
/*
|
||||
Copyright The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Code generated by informer-gen. DO NOT EDIT.
|
||||
|
||||
package v1
|
||||
|
||||
import (
|
||||
internalinterfaces "github.com/convox/convox/pkg/atom/pkg/client/informers/externalversions/internalinterfaces"
|
||||
)
|
||||
|
||||
// Interface provides access to all the informers in this group version.
|
||||
type Interface interface {
|
||||
// Atoms returns a AtomInformer.
|
||||
Atoms() AtomInformer
|
||||
}
|
||||
|
||||
type version struct {
|
||||
factory internalinterfaces.SharedInformerFactory
|
||||
namespace string
|
||||
tweakListOptions internalinterfaces.TweakListOptionsFunc
|
||||
}
|
||||
|
||||
// New returns a new Interface.
|
||||
func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface {
|
||||
return &version{factory: f, namespace: namespace, tweakListOptions: tweakListOptions}
|
||||
}
|
||||
|
||||
// Atoms returns a AtomInformer.
|
||||
func (v *version) Atoms() AtomInformer {
|
||||
return &atomInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions}
|
||||
}
|
||||
@ -0,0 +1,89 @@
|
||||
/*
|
||||
Copyright The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Code generated by informer-gen. DO NOT EDIT.
|
||||
|
||||
package v2
|
||||
|
||||
import (
|
||||
time "time"
|
||||
|
||||
convoxv2 "github.com/convox/convox/pkg/atom/pkg/apis/convox/v2"
|
||||
versioned "github.com/convox/convox/pkg/atom/pkg/client/clientset/versioned"
|
||||
internalinterfaces "github.com/convox/convox/pkg/atom/pkg/client/informers/externalversions/internalinterfaces"
|
||||
v2 "github.com/convox/convox/pkg/atom/pkg/client/listers/convox/v2"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
watch "k8s.io/apimachinery/pkg/watch"
|
||||
cache "k8s.io/client-go/tools/cache"
|
||||
)
|
||||
|
||||
// AtomInformer provides access to a shared informer and lister for
|
||||
// Atoms.
|
||||
type AtomInformer interface {
|
||||
Informer() cache.SharedIndexInformer
|
||||
Lister() v2.AtomLister
|
||||
}
|
||||
|
||||
type atomInformer struct {
|
||||
factory internalinterfaces.SharedInformerFactory
|
||||
tweakListOptions internalinterfaces.TweakListOptionsFunc
|
||||
namespace string
|
||||
}
|
||||
|
||||
// NewAtomInformer constructs a new informer for Atom type.
|
||||
// Always prefer using an informer factory to get a shared informer instead of getting an independent
|
||||
// one. This reduces memory footprint and number of connections to the server.
|
||||
func NewAtomInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer {
|
||||
return NewFilteredAtomInformer(client, namespace, resyncPeriod, indexers, nil)
|
||||
}
|
||||
|
||||
// NewFilteredAtomInformer constructs a new informer for Atom type.
|
||||
// Always prefer using an informer factory to get a shared informer instead of getting an independent
|
||||
// one. This reduces memory footprint and number of connections to the server.
|
||||
func NewFilteredAtomInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer {
|
||||
return cache.NewSharedIndexInformer(
|
||||
&cache.ListWatch{
|
||||
ListFunc: func(options v1.ListOptions) (runtime.Object, error) {
|
||||
if tweakListOptions != nil {
|
||||
tweakListOptions(&options)
|
||||
}
|
||||
return client.ConvoxV2().Atoms(namespace).List(options)
|
||||
},
|
||||
WatchFunc: func(options v1.ListOptions) (watch.Interface, error) {
|
||||
if tweakListOptions != nil {
|
||||
tweakListOptions(&options)
|
||||
}
|
||||
return client.ConvoxV2().Atoms(namespace).Watch(options)
|
||||
},
|
||||
},
|
||||
&convoxv2.Atom{},
|
||||
resyncPeriod,
|
||||
indexers,
|
||||
)
|
||||
}
|
||||
|
||||
func (f *atomInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer {
|
||||
return NewFilteredAtomInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions)
|
||||
}
|
||||
|
||||
func (f *atomInformer) Informer() cache.SharedIndexInformer {
|
||||
return f.factory.InformerFor(&convoxv2.Atom{}, f.defaultInformer)
|
||||
}
|
||||
|
||||
func (f *atomInformer) Lister() v2.AtomLister {
|
||||
return v2.NewAtomLister(f.Informer().GetIndexer())
|
||||
}
|
||||
@ -0,0 +1,89 @@
|
||||
/*
|
||||
Copyright The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Code generated by informer-gen. DO NOT EDIT.
|
||||
|
||||
package v2
|
||||
|
||||
import (
|
||||
time "time"
|
||||
|
||||
convoxv2 "github.com/convox/convox/pkg/atom/pkg/apis/convox/v2"
|
||||
versioned "github.com/convox/convox/pkg/atom/pkg/client/clientset/versioned"
|
||||
internalinterfaces "github.com/convox/convox/pkg/atom/pkg/client/informers/externalversions/internalinterfaces"
|
||||
v2 "github.com/convox/convox/pkg/atom/pkg/client/listers/convox/v2"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
watch "k8s.io/apimachinery/pkg/watch"
|
||||
cache "k8s.io/client-go/tools/cache"
|
||||
)
|
||||
|
||||
// AtomVersionInformer provides access to a shared informer and lister for
|
||||
// AtomVersions.
|
||||
type AtomVersionInformer interface {
|
||||
Informer() cache.SharedIndexInformer
|
||||
Lister() v2.AtomVersionLister
|
||||
}
|
||||
|
||||
type atomVersionInformer struct {
|
||||
factory internalinterfaces.SharedInformerFactory
|
||||
tweakListOptions internalinterfaces.TweakListOptionsFunc
|
||||
namespace string
|
||||
}
|
||||
|
||||
// NewAtomVersionInformer constructs a new informer for AtomVersion type.
|
||||
// Always prefer using an informer factory to get a shared informer instead of getting an independent
|
||||
// one. This reduces memory footprint and number of connections to the server.
|
||||
func NewAtomVersionInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer {
|
||||
return NewFilteredAtomVersionInformer(client, namespace, resyncPeriod, indexers, nil)
|
||||
}
|
||||
|
||||
// NewFilteredAtomVersionInformer constructs a new informer for AtomVersion type.
|
||||
// Always prefer using an informer factory to get a shared informer instead of getting an independent
|
||||
// one. This reduces memory footprint and number of connections to the server.
|
||||
func NewFilteredAtomVersionInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer {
|
||||
return cache.NewSharedIndexInformer(
|
||||
&cache.ListWatch{
|
||||
ListFunc: func(options v1.ListOptions) (runtime.Object, error) {
|
||||
if tweakListOptions != nil {
|
||||
tweakListOptions(&options)
|
||||
}
|
||||
return client.ConvoxV2().AtomVersions(namespace).List(options)
|
||||
},
|
||||
WatchFunc: func(options v1.ListOptions) (watch.Interface, error) {
|
||||
if tweakListOptions != nil {
|
||||
tweakListOptions(&options)
|
||||
}
|
||||
return client.ConvoxV2().AtomVersions(namespace).Watch(options)
|
||||
},
|
||||
},
|
||||
&convoxv2.AtomVersion{},
|
||||
resyncPeriod,
|
||||
indexers,
|
||||
)
|
||||
}
|
||||
|
||||
func (f *atomVersionInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer {
|
||||
return NewFilteredAtomVersionInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions)
|
||||
}
|
||||
|
||||
func (f *atomVersionInformer) Informer() cache.SharedIndexInformer {
|
||||
return f.factory.InformerFor(&convoxv2.AtomVersion{}, f.defaultInformer)
|
||||
}
|
||||
|
||||
func (f *atomVersionInformer) Lister() v2.AtomVersionLister {
|
||||
return v2.NewAtomVersionLister(f.Informer().GetIndexer())
|
||||
}
|
||||
@ -0,0 +1,52 @@
|
||||
/*
|
||||
Copyright The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Code generated by informer-gen. DO NOT EDIT.
|
||||
|
||||
package v2
|
||||
|
||||
import (
|
||||
internalinterfaces "github.com/convox/convox/pkg/atom/pkg/client/informers/externalversions/internalinterfaces"
|
||||
)
|
||||
|
||||
// Interface provides access to all the informers in this group version.
|
||||
type Interface interface {
|
||||
// Atoms returns a AtomInformer.
|
||||
Atoms() AtomInformer
|
||||
// AtomVersions returns a AtomVersionInformer.
|
||||
AtomVersions() AtomVersionInformer
|
||||
}
|
||||
|
||||
type version struct {
|
||||
factory internalinterfaces.SharedInformerFactory
|
||||
namespace string
|
||||
tweakListOptions internalinterfaces.TweakListOptionsFunc
|
||||
}
|
||||
|
||||
// New returns a new Interface.
|
||||
func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface {
|
||||
return &version{factory: f, namespace: namespace, tweakListOptions: tweakListOptions}
|
||||
}
|
||||
|
||||
// Atoms returns a AtomInformer.
|
||||
func (v *version) Atoms() AtomInformer {
|
||||
return &atomInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions}
|
||||
}
|
||||
|
||||
// AtomVersions returns a AtomVersionInformer.
|
||||
func (v *version) AtomVersions() AtomVersionInformer {
|
||||
return &atomVersionInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions}
|
||||
}
|
||||
180
pkg/atom/pkg/client/informers/externalversions/factory.go
Normal file
180
pkg/atom/pkg/client/informers/externalversions/factory.go
Normal file
@ -0,0 +1,180 @@
|
||||
/*
|
||||
Copyright The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Code generated by informer-gen. DO NOT EDIT.
|
||||
|
||||
package externalversions
|
||||
|
||||
import (
|
||||
reflect "reflect"
|
||||
sync "sync"
|
||||
time "time"
|
||||
|
||||
versioned "github.com/convox/convox/pkg/atom/pkg/client/clientset/versioned"
|
||||
convox "github.com/convox/convox/pkg/atom/pkg/client/informers/externalversions/convox"
|
||||
internalinterfaces "github.com/convox/convox/pkg/atom/pkg/client/informers/externalversions/internalinterfaces"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
schema "k8s.io/apimachinery/pkg/runtime/schema"
|
||||
cache "k8s.io/client-go/tools/cache"
|
||||
)
|
||||
|
||||
// SharedInformerOption defines the functional option type for SharedInformerFactory.
|
||||
type SharedInformerOption func(*sharedInformerFactory) *sharedInformerFactory
|
||||
|
||||
type sharedInformerFactory struct {
|
||||
client versioned.Interface
|
||||
namespace string
|
||||
tweakListOptions internalinterfaces.TweakListOptionsFunc
|
||||
lock sync.Mutex
|
||||
defaultResync time.Duration
|
||||
customResync map[reflect.Type]time.Duration
|
||||
|
||||
informers map[reflect.Type]cache.SharedIndexInformer
|
||||
// startedInformers is used for tracking which informers have been started.
|
||||
// This allows Start() to be called multiple times safely.
|
||||
startedInformers map[reflect.Type]bool
|
||||
}
|
||||
|
||||
// WithCustomResyncConfig sets a custom resync period for the specified informer types.
|
||||
func WithCustomResyncConfig(resyncConfig map[v1.Object]time.Duration) SharedInformerOption {
|
||||
return func(factory *sharedInformerFactory) *sharedInformerFactory {
|
||||
for k, v := range resyncConfig {
|
||||
factory.customResync[reflect.TypeOf(k)] = v
|
||||
}
|
||||
return factory
|
||||
}
|
||||
}
|
||||
|
||||
// WithTweakListOptions sets a custom filter on all listers of the configured SharedInformerFactory.
|
||||
func WithTweakListOptions(tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerOption {
|
||||
return func(factory *sharedInformerFactory) *sharedInformerFactory {
|
||||
factory.tweakListOptions = tweakListOptions
|
||||
return factory
|
||||
}
|
||||
}
|
||||
|
||||
// WithNamespace limits the SharedInformerFactory to the specified namespace.
|
||||
func WithNamespace(namespace string) SharedInformerOption {
|
||||
return func(factory *sharedInformerFactory) *sharedInformerFactory {
|
||||
factory.namespace = namespace
|
||||
return factory
|
||||
}
|
||||
}
|
||||
|
||||
// NewSharedInformerFactory constructs a new instance of sharedInformerFactory for all namespaces.
|
||||
func NewSharedInformerFactory(client versioned.Interface, defaultResync time.Duration) SharedInformerFactory {
|
||||
return NewSharedInformerFactoryWithOptions(client, defaultResync)
|
||||
}
|
||||
|
||||
// NewFilteredSharedInformerFactory constructs a new instance of sharedInformerFactory.
|
||||
// Listers obtained via this SharedInformerFactory will be subject to the same filters
|
||||
// as specified here.
|
||||
// Deprecated: Please use NewSharedInformerFactoryWithOptions instead
|
||||
func NewFilteredSharedInformerFactory(client versioned.Interface, defaultResync time.Duration, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerFactory {
|
||||
return NewSharedInformerFactoryWithOptions(client, defaultResync, WithNamespace(namespace), WithTweakListOptions(tweakListOptions))
|
||||
}
|
||||
|
||||
// NewSharedInformerFactoryWithOptions constructs a new instance of a SharedInformerFactory with additional options.
|
||||
func NewSharedInformerFactoryWithOptions(client versioned.Interface, defaultResync time.Duration, options ...SharedInformerOption) SharedInformerFactory {
|
||||
factory := &sharedInformerFactory{
|
||||
client: client,
|
||||
namespace: v1.NamespaceAll,
|
||||
defaultResync: defaultResync,
|
||||
informers: make(map[reflect.Type]cache.SharedIndexInformer),
|
||||
startedInformers: make(map[reflect.Type]bool),
|
||||
customResync: make(map[reflect.Type]time.Duration),
|
||||
}
|
||||
|
||||
// Apply all options
|
||||
for _, opt := range options {
|
||||
factory = opt(factory)
|
||||
}
|
||||
|
||||
return factory
|
||||
}
|
||||
|
||||
// Start initializes all requested informers.
|
||||
func (f *sharedInformerFactory) Start(stopCh <-chan struct{}) {
|
||||
f.lock.Lock()
|
||||
defer f.lock.Unlock()
|
||||
|
||||
for informerType, informer := range f.informers {
|
||||
if !f.startedInformers[informerType] {
|
||||
go informer.Run(stopCh)
|
||||
f.startedInformers[informerType] = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// WaitForCacheSync waits for all started informers' cache were synced.
|
||||
func (f *sharedInformerFactory) WaitForCacheSync(stopCh <-chan struct{}) map[reflect.Type]bool {
|
||||
informers := func() map[reflect.Type]cache.SharedIndexInformer {
|
||||
f.lock.Lock()
|
||||
defer f.lock.Unlock()
|
||||
|
||||
informers := map[reflect.Type]cache.SharedIndexInformer{}
|
||||
for informerType, informer := range f.informers {
|
||||
if f.startedInformers[informerType] {
|
||||
informers[informerType] = informer
|
||||
}
|
||||
}
|
||||
return informers
|
||||
}()
|
||||
|
||||
res := map[reflect.Type]bool{}
|
||||
for informType, informer := range informers {
|
||||
res[informType] = cache.WaitForCacheSync(stopCh, informer.HasSynced)
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// InternalInformerFor returns the SharedIndexInformer for obj using an internal
|
||||
// client.
|
||||
func (f *sharedInformerFactory) InformerFor(obj runtime.Object, newFunc internalinterfaces.NewInformerFunc) cache.SharedIndexInformer {
|
||||
f.lock.Lock()
|
||||
defer f.lock.Unlock()
|
||||
|
||||
informerType := reflect.TypeOf(obj)
|
||||
informer, exists := f.informers[informerType]
|
||||
if exists {
|
||||
return informer
|
||||
}
|
||||
|
||||
resyncPeriod, exists := f.customResync[informerType]
|
||||
if !exists {
|
||||
resyncPeriod = f.defaultResync
|
||||
}
|
||||
|
||||
informer = newFunc(f.client, resyncPeriod)
|
||||
f.informers[informerType] = informer
|
||||
|
||||
return informer
|
||||
}
|
||||
|
||||
// SharedInformerFactory provides shared informers for resources in all known
|
||||
// API group versions.
|
||||
type SharedInformerFactory interface {
|
||||
internalinterfaces.SharedInformerFactory
|
||||
ForResource(resource schema.GroupVersionResource) (GenericInformer, error)
|
||||
WaitForCacheSync(stopCh <-chan struct{}) map[reflect.Type]bool
|
||||
|
||||
Convox() convox.Interface
|
||||
}
|
||||
|
||||
func (f *sharedInformerFactory) Convox() convox.Interface {
|
||||
return convox.New(f, f.namespace, f.tweakListOptions)
|
||||
}
|
||||
69
pkg/atom/pkg/client/informers/externalversions/generic.go
Normal file
69
pkg/atom/pkg/client/informers/externalversions/generic.go
Normal file
@ -0,0 +1,69 @@
|
||||
/*
|
||||
Copyright The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Code generated by informer-gen. DO NOT EDIT.
|
||||
|
||||
package externalversions
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
v1 "github.com/convox/convox/pkg/atom/pkg/apis/convox/v1"
|
||||
v2 "github.com/convox/convox/pkg/atom/pkg/apis/convox/v2"
|
||||
schema "k8s.io/apimachinery/pkg/runtime/schema"
|
||||
cache "k8s.io/client-go/tools/cache"
|
||||
)
|
||||
|
||||
// GenericInformer is type of SharedIndexInformer which will locate and delegate to other
|
||||
// sharedInformers based on type
|
||||
type GenericInformer interface {
|
||||
Informer() cache.SharedIndexInformer
|
||||
Lister() cache.GenericLister
|
||||
}
|
||||
|
||||
type genericInformer struct {
|
||||
informer cache.SharedIndexInformer
|
||||
resource schema.GroupResource
|
||||
}
|
||||
|
||||
// Informer returns the SharedIndexInformer.
|
||||
func (f *genericInformer) Informer() cache.SharedIndexInformer {
|
||||
return f.informer
|
||||
}
|
||||
|
||||
// Lister returns the GenericLister.
|
||||
func (f *genericInformer) Lister() cache.GenericLister {
|
||||
return cache.NewGenericLister(f.Informer().GetIndexer(), f.resource)
|
||||
}
|
||||
|
||||
// ForResource gives generic access to a shared informer of the matching type
|
||||
// TODO extend this to unknown resources with a client pool
|
||||
func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource) (GenericInformer, error) {
|
||||
switch resource {
|
||||
// Group=convox.com, Version=v1
|
||||
case v1.SchemeGroupVersion.WithResource("atoms"):
|
||||
return &genericInformer{resource: resource.GroupResource(), informer: f.Convox().V1().Atoms().Informer()}, nil
|
||||
|
||||
// Group=convox.com, Version=v2
|
||||
case v2.SchemeGroupVersion.WithResource("atoms"):
|
||||
return &genericInformer{resource: resource.GroupResource(), informer: f.Convox().V2().Atoms().Informer()}, nil
|
||||
case v2.SchemeGroupVersion.WithResource("atomversions"):
|
||||
return &genericInformer{resource: resource.GroupResource(), informer: f.Convox().V2().AtomVersions().Informer()}, nil
|
||||
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("no informer found for %v", resource)
|
||||
}
|
||||
@ -0,0 +1,38 @@
|
||||
/*
|
||||
Copyright The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Code generated by informer-gen. DO NOT EDIT.
|
||||
|
||||
package internalinterfaces
|
||||
|
||||
import (
|
||||
time "time"
|
||||
|
||||
versioned "github.com/convox/convox/pkg/atom/pkg/client/clientset/versioned"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
cache "k8s.io/client-go/tools/cache"
|
||||
)
|
||||
|
||||
type NewInformerFunc func(versioned.Interface, time.Duration) cache.SharedIndexInformer
|
||||
|
||||
// SharedInformerFactory a small interface to allow for adding an informer without an import cycle
|
||||
type SharedInformerFactory interface {
|
||||
Start(stopCh <-chan struct{})
|
||||
InformerFor(obj runtime.Object, newFunc NewInformerFunc) cache.SharedIndexInformer
|
||||
}
|
||||
|
||||
type TweakListOptionsFunc func(*v1.ListOptions)
|
||||
94
pkg/atom/pkg/client/listers/convox/v1/atom.go
Normal file
94
pkg/atom/pkg/client/listers/convox/v1/atom.go
Normal file
@ -0,0 +1,94 @@
|
||||
/*
|
||||
Copyright The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Code generated by lister-gen. DO NOT EDIT.
|
||||
|
||||
package v1
|
||||
|
||||
import (
|
||||
v1 "github.com/convox/convox/pkg/atom/pkg/apis/convox/v1"
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
)
|
||||
|
||||
// AtomLister helps list Atoms.
|
||||
type AtomLister interface {
|
||||
// List lists all Atoms in the indexer.
|
||||
List(selector labels.Selector) (ret []*v1.Atom, err error)
|
||||
// Atoms returns an object that can list and get Atoms.
|
||||
Atoms(namespace string) AtomNamespaceLister
|
||||
AtomListerExpansion
|
||||
}
|
||||
|
||||
// atomLister implements the AtomLister interface.
|
||||
type atomLister struct {
|
||||
indexer cache.Indexer
|
||||
}
|
||||
|
||||
// NewAtomLister returns a new AtomLister.
|
||||
func NewAtomLister(indexer cache.Indexer) AtomLister {
|
||||
return &atomLister{indexer: indexer}
|
||||
}
|
||||
|
||||
// List lists all Atoms in the indexer.
|
||||
func (s *atomLister) List(selector labels.Selector) (ret []*v1.Atom, err error) {
|
||||
err = cache.ListAll(s.indexer, selector, func(m interface{}) {
|
||||
ret = append(ret, m.(*v1.Atom))
|
||||
})
|
||||
return ret, err
|
||||
}
|
||||
|
||||
// Atoms returns an object that can list and get Atoms.
|
||||
func (s *atomLister) Atoms(namespace string) AtomNamespaceLister {
|
||||
return atomNamespaceLister{indexer: s.indexer, namespace: namespace}
|
||||
}
|
||||
|
||||
// AtomNamespaceLister helps list and get Atoms.
|
||||
type AtomNamespaceLister interface {
|
||||
// List lists all Atoms in the indexer for a given namespace.
|
||||
List(selector labels.Selector) (ret []*v1.Atom, err error)
|
||||
// Get retrieves the Atom from the indexer for a given namespace and name.
|
||||
Get(name string) (*v1.Atom, error)
|
||||
AtomNamespaceListerExpansion
|
||||
}
|
||||
|
||||
// atomNamespaceLister implements the AtomNamespaceLister
|
||||
// interface.
|
||||
type atomNamespaceLister struct {
|
||||
indexer cache.Indexer
|
||||
namespace string
|
||||
}
|
||||
|
||||
// List lists all Atoms in the indexer for a given namespace.
|
||||
func (s atomNamespaceLister) List(selector labels.Selector) (ret []*v1.Atom, err error) {
|
||||
err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) {
|
||||
ret = append(ret, m.(*v1.Atom))
|
||||
})
|
||||
return ret, err
|
||||
}
|
||||
|
||||
// Get retrieves the Atom from the indexer for a given namespace and name.
|
||||
func (s atomNamespaceLister) Get(name string) (*v1.Atom, error) {
|
||||
obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !exists {
|
||||
return nil, errors.NewNotFound(v1.Resource("atom"), name)
|
||||
}
|
||||
return obj.(*v1.Atom), nil
|
||||
}
|
||||
27
pkg/atom/pkg/client/listers/convox/v1/expansion_generated.go
Normal file
27
pkg/atom/pkg/client/listers/convox/v1/expansion_generated.go
Normal file
@ -0,0 +1,27 @@
|
||||
/*
|
||||
Copyright The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Code generated by lister-gen. DO NOT EDIT.
|
||||
|
||||
package v1
|
||||
|
||||
// AtomListerExpansion allows custom methods to be added to
|
||||
// AtomLister.
|
||||
type AtomListerExpansion interface{}
|
||||
|
||||
// AtomNamespaceListerExpansion allows custom methods to be added to
|
||||
// AtomNamespaceLister.
|
||||
type AtomNamespaceListerExpansion interface{}
|
||||
94
pkg/atom/pkg/client/listers/convox/v2/atom.go
Normal file
94
pkg/atom/pkg/client/listers/convox/v2/atom.go
Normal file
@ -0,0 +1,94 @@
|
||||
/*
|
||||
Copyright The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Code generated by lister-gen. DO NOT EDIT.
|
||||
|
||||
package v2
|
||||
|
||||
import (
|
||||
v2 "github.com/convox/convox/pkg/atom/pkg/apis/convox/v2"
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
)
|
||||
|
||||
// AtomLister helps list Atoms.
|
||||
type AtomLister interface {
|
||||
// List lists all Atoms in the indexer.
|
||||
List(selector labels.Selector) (ret []*v2.Atom, err error)
|
||||
// Atoms returns an object that can list and get Atoms.
|
||||
Atoms(namespace string) AtomNamespaceLister
|
||||
AtomListerExpansion
|
||||
}
|
||||
|
||||
// atomLister implements the AtomLister interface.
|
||||
type atomLister struct {
|
||||
indexer cache.Indexer
|
||||
}
|
||||
|
||||
// NewAtomLister returns a new AtomLister.
|
||||
func NewAtomLister(indexer cache.Indexer) AtomLister {
|
||||
return &atomLister{indexer: indexer}
|
||||
}
|
||||
|
||||
// List lists all Atoms in the indexer.
|
||||
func (s *atomLister) List(selector labels.Selector) (ret []*v2.Atom, err error) {
|
||||
err = cache.ListAll(s.indexer, selector, func(m interface{}) {
|
||||
ret = append(ret, m.(*v2.Atom))
|
||||
})
|
||||
return ret, err
|
||||
}
|
||||
|
||||
// Atoms returns an object that can list and get Atoms.
|
||||
func (s *atomLister) Atoms(namespace string) AtomNamespaceLister {
|
||||
return atomNamespaceLister{indexer: s.indexer, namespace: namespace}
|
||||
}
|
||||
|
||||
// AtomNamespaceLister helps list and get Atoms.
|
||||
type AtomNamespaceLister interface {
|
||||
// List lists all Atoms in the indexer for a given namespace.
|
||||
List(selector labels.Selector) (ret []*v2.Atom, err error)
|
||||
// Get retrieves the Atom from the indexer for a given namespace and name.
|
||||
Get(name string) (*v2.Atom, error)
|
||||
AtomNamespaceListerExpansion
|
||||
}
|
||||
|
||||
// atomNamespaceLister implements the AtomNamespaceLister
|
||||
// interface.
|
||||
type atomNamespaceLister struct {
|
||||
indexer cache.Indexer
|
||||
namespace string
|
||||
}
|
||||
|
||||
// List lists all Atoms in the indexer for a given namespace.
|
||||
func (s atomNamespaceLister) List(selector labels.Selector) (ret []*v2.Atom, err error) {
|
||||
err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) {
|
||||
ret = append(ret, m.(*v2.Atom))
|
||||
})
|
||||
return ret, err
|
||||
}
|
||||
|
||||
// Get retrieves the Atom from the indexer for a given namespace and name.
|
||||
func (s atomNamespaceLister) Get(name string) (*v2.Atom, error) {
|
||||
obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !exists {
|
||||
return nil, errors.NewNotFound(v2.Resource("atom"), name)
|
||||
}
|
||||
return obj.(*v2.Atom), nil
|
||||
}
|
||||
94
pkg/atom/pkg/client/listers/convox/v2/atomversion.go
Normal file
94
pkg/atom/pkg/client/listers/convox/v2/atomversion.go
Normal file
@ -0,0 +1,94 @@
|
||||
/*
|
||||
Copyright The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Code generated by lister-gen. DO NOT EDIT.
|
||||
|
||||
package v2
|
||||
|
||||
import (
|
||||
v2 "github.com/convox/convox/pkg/atom/pkg/apis/convox/v2"
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
)
|
||||
|
||||
// AtomVersionLister helps list AtomVersions.
|
||||
type AtomVersionLister interface {
|
||||
// List lists all AtomVersions in the indexer.
|
||||
List(selector labels.Selector) (ret []*v2.AtomVersion, err error)
|
||||
// AtomVersions returns an object that can list and get AtomVersions.
|
||||
AtomVersions(namespace string) AtomVersionNamespaceLister
|
||||
AtomVersionListerExpansion
|
||||
}
|
||||
|
||||
// atomVersionLister implements the AtomVersionLister interface.
|
||||
type atomVersionLister struct {
|
||||
indexer cache.Indexer
|
||||
}
|
||||
|
||||
// NewAtomVersionLister returns a new AtomVersionLister.
|
||||
func NewAtomVersionLister(indexer cache.Indexer) AtomVersionLister {
|
||||
return &atomVersionLister{indexer: indexer}
|
||||
}
|
||||
|
||||
// List lists all AtomVersions in the indexer.
|
||||
func (s *atomVersionLister) List(selector labels.Selector) (ret []*v2.AtomVersion, err error) {
|
||||
err = cache.ListAll(s.indexer, selector, func(m interface{}) {
|
||||
ret = append(ret, m.(*v2.AtomVersion))
|
||||
})
|
||||
return ret, err
|
||||
}
|
||||
|
||||
// AtomVersions returns an object that can list and get AtomVersions.
|
||||
func (s *atomVersionLister) AtomVersions(namespace string) AtomVersionNamespaceLister {
|
||||
return atomVersionNamespaceLister{indexer: s.indexer, namespace: namespace}
|
||||
}
|
||||
|
||||
// AtomVersionNamespaceLister helps list and get AtomVersions.
|
||||
type AtomVersionNamespaceLister interface {
|
||||
// List lists all AtomVersions in the indexer for a given namespace.
|
||||
List(selector labels.Selector) (ret []*v2.AtomVersion, err error)
|
||||
// Get retrieves the AtomVersion from the indexer for a given namespace and name.
|
||||
Get(name string) (*v2.AtomVersion, error)
|
||||
AtomVersionNamespaceListerExpansion
|
||||
}
|
||||
|
||||
// atomVersionNamespaceLister implements the AtomVersionNamespaceLister
|
||||
// interface.
|
||||
type atomVersionNamespaceLister struct {
|
||||
indexer cache.Indexer
|
||||
namespace string
|
||||
}
|
||||
|
||||
// List lists all AtomVersions in the indexer for a given namespace.
|
||||
func (s atomVersionNamespaceLister) List(selector labels.Selector) (ret []*v2.AtomVersion, err error) {
|
||||
err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) {
|
||||
ret = append(ret, m.(*v2.AtomVersion))
|
||||
})
|
||||
return ret, err
|
||||
}
|
||||
|
||||
// Get retrieves the AtomVersion from the indexer for a given namespace and name.
|
||||
func (s atomVersionNamespaceLister) Get(name string) (*v2.AtomVersion, error) {
|
||||
obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !exists {
|
||||
return nil, errors.NewNotFound(v2.Resource("atomversion"), name)
|
||||
}
|
||||
return obj.(*v2.AtomVersion), nil
|
||||
}
|
||||
35
pkg/atom/pkg/client/listers/convox/v2/expansion_generated.go
Normal file
35
pkg/atom/pkg/client/listers/convox/v2/expansion_generated.go
Normal file
@ -0,0 +1,35 @@
|
||||
/*
|
||||
Copyright The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Code generated by lister-gen. DO NOT EDIT.
|
||||
|
||||
package v2
|
||||
|
||||
// AtomListerExpansion allows custom methods to be added to
|
||||
// AtomLister.
|
||||
type AtomListerExpansion interface{}
|
||||
|
||||
// AtomNamespaceListerExpansion allows custom methods to be added to
|
||||
// AtomNamespaceLister.
|
||||
type AtomNamespaceListerExpansion interface{}
|
||||
|
||||
// AtomVersionListerExpansion allows custom methods to be added to
|
||||
// AtomVersionLister.
|
||||
type AtomVersionListerExpansion interface{}
|
||||
|
||||
// AtomVersionNamespaceListerExpansion allows custom methods to be added to
|
||||
// AtomVersionNamespaceLister.
|
||||
type AtomVersionNamespaceListerExpansion interface{}
|
||||
9
pkg/atom/templates/atom.yml.tmpl
Normal file
9
pkg/atom/templates/atom.yml.tmpl
Normal file
@ -0,0 +1,9 @@
|
||||
apiVersion: convox.com/v2
|
||||
kind: Atom
|
||||
metadata:
|
||||
namespace: {{.Namespace}}
|
||||
name: {{.Name}}
|
||||
spec:
|
||||
currentVersion: {{.Name}}-{{.Version}}
|
||||
progressDeadlineSeconds: {{.Timeout}}
|
||||
status: Pending
|
||||
4
pkg/atom/templates/namespace.yml.tmpl
Normal file
4
pkg/atom/templates/namespace.yml.tmpl
Normal file
@ -0,0 +1,4 @@
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: {{.Namespace}}
|
||||
8
pkg/atom/templates/version.yml.tmpl
Executable file
8
pkg/atom/templates/version.yml.tmpl
Executable file
@ -0,0 +1,8 @@
|
||||
apiVersion: convox.com/v2
|
||||
kind: AtomVersion
|
||||
metadata:
|
||||
namespace: {{.Namespace}}
|
||||
name: {{.Name}}-{{.Version}}
|
||||
spec:
|
||||
release: {{ safe .Release }}
|
||||
template: {{ safe .Template }}
|
||||
90
pkg/cli/apps.go
Normal file
90
pkg/cli/apps.go
Normal file
@ -0,0 +1,90 @@
|
||||
package cli
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/convox/convox/pkg/common"
|
||||
"github.com/convox/convox/pkg/structs"
|
||||
"github.com/convox/stdcli"
|
||||
)
|
||||
|
||||
func init() {
|
||||
register("apps", "list apps", Apps, stdcli.CommandOptions{
|
||||
Flags: []stdcli.Flag{flagRack},
|
||||
Validate: stdcli.Args(0),
|
||||
})
|
||||
|
||||
register("apps create", "create an app", AppsCreate, stdcli.CommandOptions{
|
||||
Flags: append(stdcli.OptionFlags(structs.AppCreateOptions{}), flagRack, flagWait),
|
||||
Usage: "[name]",
|
||||
Validate: stdcli.ArgsMax(1),
|
||||
})
|
||||
|
||||
register("apps delete", "delete an app", AppsDelete, stdcli.CommandOptions{
|
||||
Flags: []stdcli.Flag{flagRack, flagWait},
|
||||
Usage: "<app>",
|
||||
Validate: stdcli.Args(1),
|
||||
})
|
||||
}
|
||||
|
||||
func Apps(p structs.Provider, c *stdcli.Context) error {
|
||||
as, err := p.AppList()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
t := c.Table("APP", "STATUS", "RELEASE")
|
||||
|
||||
for _, a := range as {
|
||||
t.AddRow(a.Name, a.Status, a.Release)
|
||||
}
|
||||
|
||||
return t.Print()
|
||||
}
|
||||
|
||||
func AppsCreate(p structs.Provider, c *stdcli.Context) error {
|
||||
app := common.CoalesceString(c.Arg(0), app(c))
|
||||
|
||||
if strings.TrimSpace(app) == "" {
|
||||
return fmt.Errorf("must specify an app name")
|
||||
}
|
||||
|
||||
var opts structs.AppCreateOptions
|
||||
|
||||
if err := c.Options(&opts); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
c.Startf("Creating <app>%s</app>", app)
|
||||
|
||||
if _, err := p.AppCreate(app, opts); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if c.Bool("wait") {
|
||||
if err := common.WaitForAppRunning(p, app); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return c.OK()
|
||||
}
|
||||
|
||||
func AppsDelete(p structs.Provider, c *stdcli.Context) error {
|
||||
app := c.Args[0]
|
||||
|
||||
c.Startf("Deleting <app>%s</app>", app)
|
||||
|
||||
if err := p.AppDelete(app); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if c.Bool("wait") {
|
||||
if err := common.WaitForAppDeleted(p, c, app); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return c.OK()
|
||||
}
|
||||
46
pkg/cli/cli.go
Normal file
46
pkg/cli/cli.go
Normal file
@ -0,0 +1,46 @@
|
||||
package cli
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/convox/stdcli"
|
||||
)
|
||||
|
||||
var (
|
||||
flagApp = stdcli.StringFlag("app", "a", "app name")
|
||||
flagId = stdcli.BoolFlag("id", "", "put logs on stderr, release id on stdout")
|
||||
flagNoFollow = stdcli.BoolFlag("no-follow", "", "do not follow logs")
|
||||
flagRack = stdcli.StringFlag("rack", "r", "rack name")
|
||||
flagWait = stdcli.BoolFlag("wait", "w", "wait for completion")
|
||||
)
|
||||
|
||||
func New(name, version string) *Engine {
|
||||
e := &Engine{
|
||||
Engine: stdcli.New(name, version),
|
||||
}
|
||||
|
||||
e.Writer.Tags["app"] = stdcli.RenderColors(39)
|
||||
e.Writer.Tags["command"] = stdcli.RenderColors(244)
|
||||
e.Writer.Tags["dir"] = stdcli.RenderColors(246)
|
||||
e.Writer.Tags["build"] = stdcli.RenderColors(23)
|
||||
e.Writer.Tags["fail"] = stdcli.RenderColors(160)
|
||||
e.Writer.Tags["rack"] = stdcli.RenderColors(26)
|
||||
e.Writer.Tags["process"] = stdcli.RenderColors(27)
|
||||
e.Writer.Tags["release"] = stdcli.RenderColors(24)
|
||||
e.Writer.Tags["service"] = stdcli.RenderColors(33)
|
||||
e.Writer.Tags["setting"] = stdcli.RenderColors(246)
|
||||
e.Writer.Tags["system"] = stdcli.RenderColors(15)
|
||||
|
||||
for i := 0; i < 18; i++ {
|
||||
e.Writer.Tags[fmt.Sprintf("color%d", i)] = stdcli.RenderColors(237 + i)
|
||||
}
|
||||
|
||||
if dir := os.Getenv("CONVOX_CONFIG"); dir != "" {
|
||||
e.Settings = dir
|
||||
}
|
||||
|
||||
e.RegisterCommands()
|
||||
|
||||
return e
|
||||
}
|
||||
88
pkg/cli/engine.go
Normal file
88
pkg/cli/engine.go
Normal file
@ -0,0 +1,88 @@
|
||||
package cli
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/convox/convox/pkg/structs"
|
||||
"github.com/convox/convox/provider/k8s"
|
||||
"github.com/convox/stdcli"
|
||||
)
|
||||
|
||||
type Engine struct {
|
||||
*stdcli.Engine
|
||||
Provider structs.Provider
|
||||
}
|
||||
|
||||
type HandlerFunc func(structs.Provider, *stdcli.Context) error
|
||||
|
||||
func (e *Engine) Command(command, description string, fn HandlerFunc, opts stdcli.CommandOptions) {
|
||||
wfn := func(c *stdcli.Context) error {
|
||||
p, err := e.currentProvider(c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return fn(p, c)
|
||||
}
|
||||
|
||||
e.Engine.Command(command, description, wfn, opts)
|
||||
}
|
||||
|
||||
func (e *Engine) CommandWithoutProvider(command, description string, fn HandlerFunc, opts stdcli.CommandOptions) {
|
||||
wfn := func(c *stdcli.Context) error {
|
||||
return fn(nil, c)
|
||||
}
|
||||
|
||||
e.Engine.Command(command, description, wfn, opts)
|
||||
}
|
||||
|
||||
func (e *Engine) RegisterCommands() {
|
||||
for _, c := range commands {
|
||||
if c.Rack {
|
||||
e.Command(c.Command, c.Description, c.Handler, c.Opts)
|
||||
} else {
|
||||
e.CommandWithoutProvider(c.Command, c.Description, c.Handler, c.Opts)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (e *Engine) currentProvider(c *stdcli.Context) (structs.Provider, error) {
|
||||
name := rack(c)
|
||||
|
||||
if strings.TrimSpace(name) == "" {
|
||||
return nil, fmt.Errorf("must specify a rack name")
|
||||
}
|
||||
|
||||
return k8s.New(name)
|
||||
}
|
||||
|
||||
var commands = []command{}
|
||||
|
||||
type command struct {
|
||||
Command string
|
||||
Description string
|
||||
Handler HandlerFunc
|
||||
Opts stdcli.CommandOptions
|
||||
Rack bool
|
||||
}
|
||||
|
||||
func register(cmd, description string, fn HandlerFunc, opts stdcli.CommandOptions) {
|
||||
commands = append(commands, command{
|
||||
Command: cmd,
|
||||
Description: description,
|
||||
Handler: fn,
|
||||
Opts: opts,
|
||||
Rack: true,
|
||||
})
|
||||
}
|
||||
|
||||
func registerWithoutProvider(cmd, description string, fn HandlerFunc, opts stdcli.CommandOptions) {
|
||||
commands = append(commands, command{
|
||||
Command: cmd,
|
||||
Description: description,
|
||||
Handler: fn,
|
||||
Opts: opts,
|
||||
Rack: false,
|
||||
})
|
||||
}
|
||||
22
pkg/cli/helpers.go
Normal file
22
pkg/cli/helpers.go
Normal file
@ -0,0 +1,22 @@
|
||||
package cli
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/convox/convox/pkg/common"
|
||||
"github.com/convox/stdcli"
|
||||
)
|
||||
|
||||
func app(c *stdcli.Context) string {
|
||||
wd, err := os.Getwd()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return common.CoalesceString(c.String("app"), filepath.Base(wd))
|
||||
}
|
||||
|
||||
func rack(c *stdcli.Context) string {
|
||||
return common.CoalesceString(c.String("rack"), os.Getenv("CONVOX_RACK"))
|
||||
}
|
||||
14
pkg/common/atom.go
Normal file
14
pkg/common/atom.go
Normal file
@ -0,0 +1,14 @@
|
||||
package common
|
||||
|
||||
func AtomStatus(status string) string {
|
||||
switch status {
|
||||
case "Failed":
|
||||
return "failed"
|
||||
case "Rollback":
|
||||
return "rollback"
|
||||
case "Deadline", "Error", "Pending", "Running":
|
||||
return "updating"
|
||||
default:
|
||||
return "running"
|
||||
}
|
||||
}
|
||||
104
pkg/common/certificate.go
Normal file
104
pkg/common/certificate.go
Normal file
@ -0,0 +1,104 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"crypto/rsa"
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"crypto/x509/pkix"
|
||||
"encoding/pem"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"time"
|
||||
)
|
||||
|
||||
func CertificateCA(host string, ca *tls.Certificate) (*tls.Certificate, error) {
|
||||
rkey, err := rsa.GenerateKey(rand.Reader, 2048)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
serial, err := rand.Int(rand.Reader, new(big.Int).Lsh(big.NewInt(1), 128))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cpub, err := x509.ParseCertificate(ca.Certificate[0])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
template := x509.Certificate{
|
||||
SerialNumber: serial,
|
||||
Subject: pkix.Name{
|
||||
CommonName: host,
|
||||
Organization: []string{"convox"},
|
||||
},
|
||||
Issuer: cpub.Subject,
|
||||
NotBefore: time.Now(),
|
||||
NotAfter: time.Now().Add(365 * 24 * time.Hour),
|
||||
KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
|
||||
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
|
||||
BasicConstraintsValid: true,
|
||||
DNSNames: []string{host, fmt.Sprintf("*.%s", host)},
|
||||
}
|
||||
|
||||
data, err := x509.CreateCertificate(rand.Reader, &template, cpub, &rkey.PublicKey, ca.PrivateKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
pub := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: data})
|
||||
key := pem.EncodeToMemory(&pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(rkey)})
|
||||
|
||||
cert, err := tls.X509KeyPair(pub, key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &cert, nil
|
||||
}
|
||||
|
||||
func CertificateSelfSigned(host string) (*tls.Certificate, error) {
|
||||
rkey, err := rsa.GenerateKey(rand.Reader, 2048)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
serial, err := rand.Int(rand.Reader, new(big.Int).Lsh(big.NewInt(1), 128))
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
template := x509.Certificate{
|
||||
SerialNumber: serial,
|
||||
Subject: pkix.Name{
|
||||
CommonName: host,
|
||||
Organization: []string{"convox"},
|
||||
},
|
||||
NotBefore: time.Now(),
|
||||
NotAfter: time.Now().Add(365 * 24 * time.Hour),
|
||||
KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
|
||||
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
|
||||
BasicConstraintsValid: true,
|
||||
DNSNames: []string{host},
|
||||
}
|
||||
|
||||
data, err := x509.CreateCertificate(rand.Reader, &template, &template, &rkey.PublicKey, rkey)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
pub := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: data})
|
||||
key := pem.EncodeToMemory(&pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(rkey)})
|
||||
|
||||
cert, err := tls.X509KeyPair(pub, key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &cert, nil
|
||||
}
|
||||
20
pkg/common/coalesce.go
Normal file
20
pkg/common/coalesce.go
Normal file
@ -0,0 +1,20 @@
|
||||
package common
|
||||
|
||||
func CoalesceInt(ii ...int) int {
|
||||
for _, i := range ii {
|
||||
if i != 0 {
|
||||
return i
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func CoalesceString(ss ...string) string {
|
||||
for _, s := range ss {
|
||||
if s != "" {
|
||||
return s
|
||||
}
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
43
pkg/common/default.go
Normal file
43
pkg/common/default.go
Normal file
@ -0,0 +1,43 @@
|
||||
package common
|
||||
|
||||
import "time"
|
||||
|
||||
func DefaultBool(v *bool, def bool) bool {
|
||||
if v == nil {
|
||||
return def
|
||||
}
|
||||
|
||||
return *v
|
||||
}
|
||||
|
||||
func DefaultDuration(v *time.Duration, def time.Duration) time.Duration {
|
||||
if v == nil {
|
||||
return def
|
||||
}
|
||||
|
||||
return *v
|
||||
}
|
||||
|
||||
func DefaultInt(v *int, def int) int {
|
||||
if v == nil {
|
||||
return def
|
||||
}
|
||||
|
||||
return *v
|
||||
}
|
||||
|
||||
func DefaultInt32(v *int32, def int32) int32 {
|
||||
if v == nil {
|
||||
return def
|
||||
}
|
||||
|
||||
return *v
|
||||
}
|
||||
|
||||
func DefaultString(v *string, def string) string {
|
||||
if v == nil {
|
||||
return def
|
||||
}
|
||||
|
||||
return *v
|
||||
}
|
||||
39
pkg/common/endpoint.go
Normal file
39
pkg/common/endpoint.go
Normal file
@ -0,0 +1,39 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"time"
|
||||
)
|
||||
|
||||
func EndpointCheck(url string) error {
|
||||
ht := NewDefaultTransport()
|
||||
ht.TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
|
||||
hc := &http.Client{Timeout: 2 * time.Second, Transport: ht}
|
||||
|
||||
res, err := hc.Get(fmt.Sprintf("%s/apps", url))
|
||||
if err == nil && res.StatusCode == 200 {
|
||||
return nil
|
||||
}
|
||||
|
||||
return fmt.Errorf("check failed")
|
||||
}
|
||||
|
||||
func EndpointWait(url string) error {
|
||||
tick := time.NewTicker(2 * time.Second)
|
||||
defer tick.Stop()
|
||||
|
||||
timeout := time.After(5 * time.Minute)
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-tick.C:
|
||||
if err := EndpointCheck(url); err == nil {
|
||||
return nil
|
||||
}
|
||||
case <-timeout:
|
||||
return fmt.Errorf("timeout")
|
||||
}
|
||||
}
|
||||
}
|
||||
27
pkg/common/file.go
Normal file
27
pkg/common/file.go
Normal file
@ -0,0 +1,27 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
func FileExists(filename string) bool {
|
||||
if _, err := os.Stat(filename); os.IsNotExist(err) {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func WriteFile(filename string, data []byte, mode os.FileMode) error {
|
||||
if err := os.MkdirAll(filepath.Dir(filename), 0755); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := ioutil.WriteFile(filename, data, mode); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
34
pkg/common/format.go
Normal file
34
pkg/common/format.go
Normal file
@ -0,0 +1,34 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"regexp"
|
||||
|
||||
yaml "gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
var (
|
||||
yamlSplitter = regexp.MustCompile(`(?m)^\s*---\s*$`)
|
||||
)
|
||||
|
||||
func FormatYAML(data []byte) ([]byte, error) {
|
||||
ps := yamlSplitter.Split(string(data), -1)
|
||||
bs := make([][]byte, len(ps))
|
||||
|
||||
for i, p := range ps {
|
||||
var v interface{}
|
||||
|
||||
if err := yaml.Unmarshal([]byte(p), &v); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
data, err := yaml.Marshal(v)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
bs[i] = data
|
||||
}
|
||||
|
||||
return bytes.Join(bs, []byte("---\n")), nil
|
||||
}
|
||||
1
pkg/common/helpers.go
Normal file
1
pkg/common/helpers.go
Normal file
@ -0,0 +1 @@
|
||||
package common
|
||||
38
pkg/common/http.go
Normal file
38
pkg/common/http.go
Normal file
@ -0,0 +1,38 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"net/http"
|
||||
"time"
|
||||
)
|
||||
|
||||
func Get(url string) ([]byte, error) {
|
||||
res, err := http.Get(url)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer res.Body.Close()
|
||||
|
||||
data, err := ioutil.ReadAll(res.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return data, nil
|
||||
}
|
||||
|
||||
func NewDefaultTransport() *http.Transport {
|
||||
return &http.Transport{
|
||||
Proxy: http.ProxyFromEnvironment,
|
||||
DialContext: (&net.Dialer{
|
||||
Timeout: 30 * time.Second,
|
||||
KeepAlive: 30 * time.Second,
|
||||
DualStack: true,
|
||||
}).DialContext,
|
||||
MaxIdleConns: 100,
|
||||
IdleConnTimeout: 90 * time.Second,
|
||||
TLSHandshakeTimeout: 10 * time.Second,
|
||||
ExpectContinueTimeout: 1 * time.Second,
|
||||
}
|
||||
}
|
||||
39
pkg/common/linux.go
Normal file
39
pkg/common/linux.go
Normal file
@ -0,0 +1,39 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"regexp"
|
||||
)
|
||||
|
||||
var reLinuxAttributes = regexp.MustCompile(`\s*(\w+)\s*=\s*"?([^"]*)`)
|
||||
|
||||
func LinuxRelease() (string, error) {
|
||||
attrs, err := linuxReleaseAttributes()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return fmt.Sprintf("%s-%s", attrs["ID"], attrs["VERSION_ID"]), nil
|
||||
}
|
||||
|
||||
func linuxReleaseAttributes() (map[string]string, error) {
|
||||
attrs := map[string]string{}
|
||||
|
||||
data, err := ioutil.ReadFile("/etc/os-release")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
s := bufio.NewScanner(bytes.NewReader(data))
|
||||
|
||||
for s.Scan() {
|
||||
if p := reLinuxAttributes.FindStringSubmatch(s.Text()); len(p) == 3 {
|
||||
attrs[p[1]] = p[2]
|
||||
}
|
||||
}
|
||||
|
||||
return attrs, nil
|
||||
}
|
||||
7
pkg/common/number.go
Normal file
7
pkg/common/number.go
Normal file
@ -0,0 +1,7 @@
|
||||
package common
|
||||
|
||||
import "fmt"
|
||||
|
||||
func Percent(num float64) string {
|
||||
return fmt.Sprintf("%0.2f%%", num*100)
|
||||
}
|
||||
238
pkg/common/provider.go
Normal file
238
pkg/common/provider.go
Normal file
@ -0,0 +1,238 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/convox/convox/pkg/manifest"
|
||||
"github.com/convox/convox/pkg/options"
|
||||
"github.com/convox/convox/pkg/structs"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
var (
|
||||
ProviderWaitDuration = 5 * time.Second
|
||||
)
|
||||
|
||||
func AppEnvironment(p structs.Provider, app string) (structs.Environment, error) {
|
||||
rs, err := ReleaseLatest(p, app)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if rs == nil {
|
||||
return structs.Environment{}, nil
|
||||
}
|
||||
|
||||
env := structs.Environment{}
|
||||
|
||||
if err := env.Load([]byte(rs.Env)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return env, nil
|
||||
}
|
||||
|
||||
func AppManifest(p structs.Provider, app string) (*manifest.Manifest, *structs.Release, error) {
|
||||
a, err := p.AppGet(app)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
if a.Release == "" {
|
||||
return nil, nil, errors.WithStack(fmt.Errorf("no release for app: %s", app))
|
||||
}
|
||||
|
||||
return ReleaseManifest(p, app, a.Release)
|
||||
}
|
||||
|
||||
func ReleaseLatest(p structs.Provider, app string) (*structs.Release, error) {
|
||||
rs, err := p.ReleaseList(app, structs.ReleaseListOptions{Limit: options.Int(1)})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(rs) < 1 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
return p.ReleaseGet(app, rs[0].Id)
|
||||
}
|
||||
|
||||
func ReleaseManifest(p structs.Provider, app, release string) (*manifest.Manifest, *structs.Release, error) {
|
||||
r, err := p.ReleaseGet(app, release)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
env := structs.Environment{}
|
||||
|
||||
if err := env.Load([]byte(r.Env)); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
m, err := manifest.Load([]byte(r.Manifest), env)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
return m, r, nil
|
||||
}
|
||||
|
||||
func StreamAppLogs(ctx context.Context, p structs.Provider, w io.Writer, app string) {
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return
|
||||
default:
|
||||
}
|
||||
|
||||
r, err := p.AppLogs(app, structs.LogsOptions{Prefix: options.Bool(true), Since: options.Duration(5 * time.Second)})
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
copySystemLogs(ctx, w, r)
|
||||
|
||||
time.Sleep(1 * time.Second)
|
||||
}
|
||||
}
|
||||
|
||||
func StreamSystemLogs(ctx context.Context, p structs.Provider, w io.Writer) {
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return
|
||||
default:
|
||||
}
|
||||
|
||||
r, err := p.SystemLogs(structs.LogsOptions{Prefix: options.Bool(true), Since: options.Duration(5 * time.Second)})
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
copySystemLogs(ctx, w, r)
|
||||
|
||||
time.Sleep(1 * time.Second)
|
||||
}
|
||||
}
|
||||
|
||||
func WaitForAppDeleted(p structs.Provider, w io.Writer, app string) error {
|
||||
time.Sleep(ProviderWaitDuration) // give the stack time to start updating
|
||||
|
||||
return Wait(ProviderWaitDuration, 35*time.Minute, 2, func() (bool, error) {
|
||||
_, err := p.AppGet(app)
|
||||
if err == nil {
|
||||
return false, nil
|
||||
}
|
||||
if strings.Contains(err.Error(), "no such app") {
|
||||
return true, nil
|
||||
}
|
||||
if strings.Contains(err.Error(), "app not found") {
|
||||
return true, nil
|
||||
}
|
||||
return false, err
|
||||
})
|
||||
}
|
||||
|
||||
func WaitForAppRunning(p structs.Provider, app string) error {
|
||||
return WaitForAppRunningContext(context.Background(), p, app)
|
||||
}
|
||||
|
||||
func WaitForAppRunningContext(ctx context.Context, p structs.Provider, app string) error {
|
||||
time.Sleep(ProviderWaitDuration) // give the stack time to start updating
|
||||
|
||||
var waitError error
|
||||
|
||||
return WaitContext(ctx, ProviderWaitDuration, 35*time.Minute, 2, func() (bool, error) {
|
||||
a, err := p.AppGet(app)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
if a.Status == "rollback" {
|
||||
waitError = fmt.Errorf("rollback")
|
||||
}
|
||||
|
||||
return a.Status == "running", waitError
|
||||
})
|
||||
}
|
||||
|
||||
func WaitForAppWithLogs(p structs.Provider, w io.Writer, app string) error {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
return WaitForAppWithLogsContext(ctx, p, w, app)
|
||||
}
|
||||
|
||||
func WaitForAppWithLogsContext(ctx context.Context, p structs.Provider, w io.Writer, app string) error {
|
||||
go StreamAppLogs(ctx, p, w, app)
|
||||
|
||||
if err := WaitForAppRunningContext(ctx, p, app); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func WaitForProcessRunning(p structs.Provider, w io.Writer, app, pid string) error {
|
||||
return Wait(1*time.Second, 5*time.Minute, 2, func() (bool, error) {
|
||||
ps, err := p.ProcessGet(app, pid)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return ps.Status == "running", nil
|
||||
})
|
||||
}
|
||||
|
||||
func WaitForRackRunning(p structs.Provider, w io.Writer) error {
|
||||
time.Sleep(ProviderWaitDuration) // give the stack time to start updating
|
||||
|
||||
return Wait(ProviderWaitDuration, 35*time.Minute, 2, func() (bool, error) {
|
||||
s, err := p.SystemGet()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return s.Status == "running", nil
|
||||
})
|
||||
}
|
||||
|
||||
func WaitForRackWithLogs(p structs.Provider, w io.Writer) error {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
go StreamSystemLogs(ctx, p, w)
|
||||
|
||||
if err := WaitForRackRunning(p, w); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func copySystemLogs(ctx context.Context, w io.Writer, r io.Reader) {
|
||||
s := bufio.NewScanner(r)
|
||||
|
||||
for s.Scan() {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return
|
||||
default:
|
||||
}
|
||||
|
||||
parts := strings.SplitN(s.Text(), " ", 3)
|
||||
|
||||
if len(parts) < 3 {
|
||||
continue
|
||||
}
|
||||
|
||||
if strings.HasPrefix(parts[1], "system/") {
|
||||
w.Write([]byte(fmt.Sprintf("%s\n", s.Text())))
|
||||
}
|
||||
}
|
||||
}
|
||||
42
pkg/common/random.go
Normal file
42
pkg/common/random.go
Normal file
@ -0,0 +1,42 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
alphabet = []byte("ABCDEFGHIJKLMNOPQRSTUVWXYZ")
|
||||
)
|
||||
|
||||
func init() {
|
||||
rand.Seed(time.Now().UnixNano())
|
||||
}
|
||||
|
||||
func Id(prefix string, length int) string {
|
||||
id := prefix
|
||||
|
||||
for i := 0; i < length-len(prefix); i++ {
|
||||
id += string(alphabet[rand.Intn(len(alphabet))])
|
||||
}
|
||||
|
||||
return id
|
||||
}
|
||||
|
||||
func RandomString(length int) (string, error) {
|
||||
data := make([]byte, 1024)
|
||||
|
||||
if _, err := rand.Read(data); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
key := fmt.Sprintf("%x", sha256.Sum256(data))
|
||||
|
||||
if len(key) < length {
|
||||
return "", fmt.Errorf("key too long")
|
||||
}
|
||||
|
||||
return key[0:length], nil
|
||||
}
|
||||
26
pkg/common/retry.go
Normal file
26
pkg/common/retry.go
Normal file
@ -0,0 +1,26 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
"time"
|
||||
)
|
||||
|
||||
func Retry(times int, interval time.Duration, fn func() error) error {
|
||||
i := 0
|
||||
|
||||
for {
|
||||
err := fn()
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
// add 20% jitter
|
||||
time.Sleep(interval + time.Duration(rand.Intn(int(interval/20))))
|
||||
|
||||
i++
|
||||
|
||||
if i > times {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
61
pkg/common/stream.go
Normal file
61
pkg/common/stream.go
Normal file
@ -0,0 +1,61 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"io"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
type ReadWriter struct {
|
||||
io.Reader
|
||||
io.Writer
|
||||
}
|
||||
|
||||
func Pipe(a, b io.ReadWriter) error {
|
||||
ch := make(chan error)
|
||||
|
||||
go halfPipe(a, b, ch)
|
||||
go halfPipe(b, a, ch)
|
||||
|
||||
if err := <-ch; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := <-ch; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func halfPipe(w io.Writer, r io.Reader, ch chan error) {
|
||||
ch <- Stream(w, r)
|
||||
|
||||
if c, ok := w.(io.Closer); ok {
|
||||
c.Close()
|
||||
}
|
||||
}
|
||||
|
||||
func Stream(w io.Writer, r io.Reader) error {
|
||||
buf := make([]byte, 1024)
|
||||
|
||||
for {
|
||||
n, err := r.Read(buf)
|
||||
if n > 0 {
|
||||
if _, err := w.Write(buf[0:n]); err != nil {
|
||||
if err == io.ErrClosedPipe {
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
if f, ok := w.(http.Flusher); ok {
|
||||
f.Flush()
|
||||
}
|
||||
}
|
||||
if err == io.EOF {
|
||||
return nil
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
148
pkg/common/tar.go
Normal file
148
pkg/common/tar.go
Normal file
@ -0,0 +1,148 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"archive/tar"
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/docker/docker/builder/dockerignore"
|
||||
"github.com/docker/docker/pkg/archive"
|
||||
)
|
||||
|
||||
func Archive(file string) (io.Reader, error) {
|
||||
opts := &archive.TarOptions{
|
||||
IncludeFiles: []string{file},
|
||||
}
|
||||
|
||||
r, err := archive.TarWithOptions("/", opts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return r, nil
|
||||
}
|
||||
|
||||
func RebaseArchive(r io.Reader, src, dst string) (io.Reader, error) {
|
||||
tr := tar.NewReader(r)
|
||||
|
||||
var buf bytes.Buffer
|
||||
|
||||
tw := tar.NewWriter(&buf)
|
||||
|
||||
for {
|
||||
h, err := tr.Next()
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if !strings.HasPrefix(h.Name, "/") {
|
||||
h.Name = fmt.Sprintf("/%s", h.Name)
|
||||
}
|
||||
|
||||
if !strings.HasPrefix(h.Name, src) {
|
||||
continue
|
||||
}
|
||||
|
||||
h.Name = filepath.Join(dst, strings.TrimPrefix(h.Name, src))
|
||||
|
||||
tw.WriteHeader(h)
|
||||
|
||||
if _, err := io.Copy(tw, tr); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
tw.Close()
|
||||
|
||||
return &buf, nil
|
||||
}
|
||||
|
||||
func Tarball(dir string) ([]byte, error) {
|
||||
abs, err := filepath.Abs(dir)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
sym, err := filepath.EvalSymlinks(abs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
data, err := ioutil.ReadFile(filepath.Join(sym, ".dockerignore"))
|
||||
if err != nil && !os.IsNotExist(err) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
excludes, err := dockerignore.ReadAll(bytes.NewReader(data))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cwd, err := os.Getwd()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defer os.Chdir(cwd)
|
||||
|
||||
if err := os.Chdir(sym); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
opts := &archive.TarOptions{
|
||||
Compression: archive.Gzip,
|
||||
ExcludePatterns: excludes,
|
||||
IncludeFiles: []string{"."},
|
||||
}
|
||||
|
||||
r, err := archive.TarWithOptions(sym, opts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return ioutil.ReadAll(r)
|
||||
}
|
||||
|
||||
func Unarchive(r io.Reader, target string) error {
|
||||
tr := tar.NewReader(r)
|
||||
|
||||
for {
|
||||
h, err := tr.Next()
|
||||
if err == io.EOF {
|
||||
return nil
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
file := filepath.Join(target, h.Name)
|
||||
|
||||
switch h.Typeflag {
|
||||
case tar.TypeDir:
|
||||
if err := os.MkdirAll(file, os.FileMode(h.Mode)); err != nil {
|
||||
return err
|
||||
}
|
||||
case tar.TypeReg:
|
||||
if err := os.MkdirAll(filepath.Dir(file), 0755); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fd, err := os.OpenFile(file, os.O_CREATE|os.O_WRONLY, os.FileMode(h.Mode))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err := io.Copy(fd, tr); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
10
pkg/common/test.go
Normal file
10
pkg/common/test.go
Normal file
@ -0,0 +1,10 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
)
|
||||
|
||||
func Testdata(name string) ([]byte, error) {
|
||||
return ioutil.ReadFile(fmt.Sprintf("testdata/%s.yml", name))
|
||||
}
|
||||
13
pkg/common/tick.go
Normal file
13
pkg/common/tick.go
Normal file
@ -0,0 +1,13 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
func Tick(d time.Duration, fn func()) {
|
||||
fn()
|
||||
|
||||
for range time.Tick(d) {
|
||||
fn()
|
||||
}
|
||||
}
|
||||
41
pkg/common/time.go
Normal file
41
pkg/common/time.go
Normal file
@ -0,0 +1,41 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
humanize "github.com/dustin/go-humanize"
|
||||
)
|
||||
|
||||
var (
|
||||
CompactSortableTime = "20060102150405000000000"
|
||||
PrintableTime = "2006-01-02 15:04:05"
|
||||
SortableTime = "20060102.150405.000000000"
|
||||
)
|
||||
|
||||
func Ago(t time.Time) string {
|
||||
if t.IsZero() {
|
||||
return ""
|
||||
}
|
||||
return humanize.Time(t)
|
||||
}
|
||||
|
||||
func Duration(start, end time.Time) string {
|
||||
d := end.Sub(start)
|
||||
|
||||
if end.IsZero() {
|
||||
return ""
|
||||
}
|
||||
|
||||
total := int64(d.Seconds())
|
||||
sec := total % 60
|
||||
min := total / 60
|
||||
|
||||
dur := fmt.Sprintf("%ds", sec)
|
||||
|
||||
if min >= 1 {
|
||||
dur = fmt.Sprintf("%dm", min) + dur
|
||||
}
|
||||
|
||||
return dur
|
||||
}
|
||||
52
pkg/common/wait.go
Normal file
52
pkg/common/wait.go
Normal file
@ -0,0 +1,52 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
)
|
||||
|
||||
func Wait(interval time.Duration, timeout time.Duration, times int, fn func() (bool, error)) error {
|
||||
return WaitContext(context.Background(), interval, timeout, times, fn)
|
||||
}
|
||||
|
||||
func WaitContext(ctx context.Context, interval time.Duration, timeout time.Duration, times int, fn func() (bool, error)) error {
|
||||
successes := 0
|
||||
errors := 0
|
||||
start := time.Now().UTC()
|
||||
|
||||
tick := time.NewTicker(interval)
|
||||
defer tick.Stop()
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return nil
|
||||
case <-tick.C:
|
||||
if start.Add(timeout).Before(time.Now().UTC()) {
|
||||
return fmt.Errorf("timeout")
|
||||
}
|
||||
|
||||
success, err := fn()
|
||||
if err != nil {
|
||||
errors += 1
|
||||
} else {
|
||||
errors = 0
|
||||
}
|
||||
|
||||
if errors >= times {
|
||||
return err
|
||||
}
|
||||
|
||||
if success {
|
||||
successes += 1
|
||||
} else {
|
||||
successes = 0
|
||||
}
|
||||
|
||||
if successes >= times {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
137
pkg/kctl/kctl.go
Normal file
137
pkg/kctl/kctl.go
Normal file
@ -0,0 +1,137 @@
|
||||
package kctl
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
ac "k8s.io/api/core/v1"
|
||||
am "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/kubernetes/scheme"
|
||||
tc "k8s.io/client-go/kubernetes/typed/core/v1"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
"k8s.io/client-go/tools/leaderelection"
|
||||
"k8s.io/client-go/tools/leaderelection/resourcelock"
|
||||
"k8s.io/client-go/tools/record"
|
||||
)
|
||||
|
||||
type Controller struct {
|
||||
Handler ControllerHandler
|
||||
Identifier string
|
||||
Name string
|
||||
Namespace string
|
||||
|
||||
errch chan error
|
||||
recorder record.EventRecorder
|
||||
}
|
||||
|
||||
type ControllerHandler interface {
|
||||
Add(interface{}) error
|
||||
Client() kubernetes.Interface
|
||||
Delete(interface{}) error
|
||||
Start() error
|
||||
Stop() error
|
||||
Update(interface{}, interface{}) error
|
||||
}
|
||||
|
||||
func NewController(namespace, name string, handler ControllerHandler) (*Controller, error) {
|
||||
hostname, err := os.Hostname()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
c := &Controller{
|
||||
Handler: handler,
|
||||
Identifier: hostname,
|
||||
Name: name,
|
||||
Namespace: namespace,
|
||||
}
|
||||
|
||||
return c, nil
|
||||
}
|
||||
|
||||
func (c *Controller) Event(object runtime.Object, eventtype, reason, message string) {
|
||||
c.recorder.Event(object, eventtype, reason, message)
|
||||
}
|
||||
|
||||
func (c *Controller) Run(informer cache.SharedInformer, ch chan error) {
|
||||
c.errch = ch
|
||||
|
||||
eb := record.NewBroadcaster()
|
||||
eb.StartRecordingToSink(&tc.EventSinkImpl{Interface: c.Handler.Client().CoreV1().Events("")})
|
||||
|
||||
c.recorder = eb.NewRecorder(scheme.Scheme, ac.EventSource{Component: c.Name})
|
||||
|
||||
rl := &resourcelock.ConfigMapLock{
|
||||
ConfigMapMeta: am.ObjectMeta{Namespace: c.Namespace, Name: c.Name},
|
||||
Client: c.Handler.Client().CoreV1(),
|
||||
LockConfig: resourcelock.ResourceLockConfig{
|
||||
Identity: c.Identifier,
|
||||
EventRecorder: c.recorder,
|
||||
},
|
||||
}
|
||||
|
||||
el, err := leaderelection.NewLeaderElector(leaderelection.LeaderElectionConfig{
|
||||
Lock: rl,
|
||||
LeaseDuration: 15 * time.Second,
|
||||
RenewDeadline: 10 * time.Second,
|
||||
RetryPeriod: 2 * time.Second,
|
||||
Callbacks: leaderelection.LeaderCallbacks{
|
||||
OnStartedLeading: c.leaderStart(informer),
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
ch <- err
|
||||
return
|
||||
}
|
||||
|
||||
go el.Run()
|
||||
}
|
||||
|
||||
func (c *Controller) leaderStart(informer cache.SharedInformer) func(<-chan struct{}) {
|
||||
return func(stop <-chan struct{}) {
|
||||
fmt.Printf("started leading: %s/%s (%s)\n", c.Namespace, c.Name, c.Identifier)
|
||||
|
||||
informer.AddEventHandler(cache.ResourceEventHandlerFuncs{
|
||||
AddFunc: c.addHandler,
|
||||
DeleteFunc: c.deleteHandler,
|
||||
UpdateFunc: c.updateHandler,
|
||||
})
|
||||
|
||||
if err := c.Handler.Start(); err != nil {
|
||||
c.errch <- err
|
||||
}
|
||||
|
||||
go informer.Run(stop)
|
||||
|
||||
fmt.Printf("stopped leading: %s/%s (%s)\n", c.Namespace, c.Name, c.Identifier)
|
||||
|
||||
if err := c.Handler.Stop(); err != nil {
|
||||
c.errch <- err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Controller) addHandler(obj interface{}) {
|
||||
if err := c.Handler.Add(obj); err != nil {
|
||||
c.errch <- err
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Controller) deleteHandler(obj interface{}) {
|
||||
if err := c.Handler.Delete(obj); err != nil {
|
||||
c.errch <- err
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Controller) updateHandler(prev, cur interface{}) {
|
||||
// if reflect.DeepEqual(prev, cur) {
|
||||
// return
|
||||
// }
|
||||
|
||||
if err := c.Handler.Update(prev, cur); err != nil {
|
||||
c.errch <- err
|
||||
}
|
||||
}
|
||||
3
pkg/manifest/environment.go
Normal file
3
pkg/manifest/environment.go
Normal file
@ -0,0 +1,3 @@
|
||||
package manifest
|
||||
|
||||
type Environment []string
|
||||
36
pkg/manifest/helpers.go
Normal file
36
pkg/manifest/helpers.go
Normal file
@ -0,0 +1,36 @@
|
||||
package manifest
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
"regexp"
|
||||
)
|
||||
|
||||
func coalesce(ss ...string) string {
|
||||
for _, s := range ss {
|
||||
if s != "" {
|
||||
return s
|
||||
}
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
var regexpInterpolation = regexp.MustCompile(`\$\{([^}]*?)\}`)
|
||||
|
||||
func interpolate(data []byte, env map[string]string) ([]byte, error) {
|
||||
p := regexpInterpolation.ReplaceAllFunc(data, func(m []byte) []byte {
|
||||
return []byte(env[string(m)[2:len(m)-1]])
|
||||
})
|
||||
|
||||
return p, nil
|
||||
}
|
||||
|
||||
var randomAlphabet = []rune("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz")
|
||||
|
||||
func randomString(size int) string {
|
||||
b := make([]rune, size)
|
||||
for i := range b {
|
||||
b[i] = randomAlphabet[rand.Intn(len(randomAlphabet))]
|
||||
}
|
||||
return string(b)
|
||||
}
|
||||
288
pkg/manifest/manifest.go
Normal file
288
pkg/manifest/manifest.go
Normal file
@ -0,0 +1,288 @@
|
||||
package manifest
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"math/rand"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
yaml "gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
var (
|
||||
DefaultCpu = 256
|
||||
DefaultMem = 512
|
||||
)
|
||||
|
||||
type Manifest struct {
|
||||
Environment Environment `yaml:"environment,omitempty"`
|
||||
Params Params `yaml:"params,omitempty"`
|
||||
Resources Resources `yaml:"resources,omitempty"`
|
||||
Services Services `yaml:"services,omitempty"`
|
||||
Timers Timers `yaml:"timers,omitempty"`
|
||||
|
||||
attributes map[string]bool
|
||||
env map[string]string
|
||||
}
|
||||
|
||||
func init() {
|
||||
rand.Seed(time.Now().UnixNano())
|
||||
}
|
||||
|
||||
func Load(data []byte, env map[string]string) (*Manifest, error) {
|
||||
var m Manifest
|
||||
|
||||
p, err := interpolate(data, env)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := yaml.Unmarshal(p, &m); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
m.attributes, err = yamlAttributes(p)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
m.env = map[string]string{}
|
||||
|
||||
for k, v := range env {
|
||||
m.env[k] = v
|
||||
}
|
||||
|
||||
if err := m.ApplyDefaults(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := m.CombineEnv(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := m.ValidateEnv(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &m, nil
|
||||
}
|
||||
|
||||
func (m *Manifest) Agents() []string {
|
||||
a := []string{}
|
||||
|
||||
for _, s := range m.Services {
|
||||
if s.Agent.Enabled {
|
||||
a = append(a, s.Name)
|
||||
}
|
||||
}
|
||||
|
||||
return a
|
||||
}
|
||||
|
||||
func (m *Manifest) Attributes() []string {
|
||||
attrs := []string{}
|
||||
|
||||
for k := range m.attributes {
|
||||
attrs = append(attrs, k)
|
||||
}
|
||||
|
||||
sort.Strings(attrs)
|
||||
|
||||
return attrs
|
||||
}
|
||||
|
||||
func (m *Manifest) AttributesByPrefix(prefix string) []string {
|
||||
attrs := []string{}
|
||||
|
||||
for _, a := range m.Attributes() {
|
||||
if strings.HasPrefix(a, prefix) {
|
||||
attrs = append(attrs, a)
|
||||
}
|
||||
}
|
||||
|
||||
return attrs
|
||||
}
|
||||
|
||||
func (m *Manifest) AttributeSet(name string) bool {
|
||||
return m.attributes[name]
|
||||
}
|
||||
|
||||
func (m *Manifest) Env() map[string]string {
|
||||
return m.env
|
||||
}
|
||||
|
||||
// used only for tests
|
||||
func (m *Manifest) SetAttributes(attrs []string) {
|
||||
m.attributes = map[string]bool{}
|
||||
|
||||
for _, a := range attrs {
|
||||
m.attributes[a] = true
|
||||
}
|
||||
}
|
||||
|
||||
// used only for tests
|
||||
func (m *Manifest) SetEnv(env map[string]string) {
|
||||
m.env = env
|
||||
}
|
||||
|
||||
func (m *Manifest) CombineEnv() error {
|
||||
for i, s := range m.Services {
|
||||
me := make([]string, len(m.Environment))
|
||||
copy(me, m.Environment)
|
||||
m.Services[i].Environment = append(me, s.Environment...)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Manifest) Service(name string) (*Service, error) {
|
||||
for _, s := range m.Services {
|
||||
if s.Name == name {
|
||||
return &s, nil
|
||||
}
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("no such service: %s", name)
|
||||
}
|
||||
|
||||
func (m *Manifest) ServiceEnvironment(service string) (map[string]string, error) {
|
||||
s, err := m.Service(service)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
env := map[string]string{}
|
||||
|
||||
missing := []string{}
|
||||
|
||||
for _, e := range s.Environment {
|
||||
parts := strings.SplitN(e, "=", 2)
|
||||
|
||||
switch len(parts) {
|
||||
case 1:
|
||||
if parts[0] == "*" {
|
||||
for k, v := range m.env {
|
||||
env[k] = v
|
||||
}
|
||||
} else {
|
||||
v, ok := m.env[parts[0]]
|
||||
if !ok {
|
||||
missing = append(missing, parts[0])
|
||||
}
|
||||
env[parts[0]] = v
|
||||
}
|
||||
case 2:
|
||||
v, ok := m.env[parts[0]]
|
||||
if ok {
|
||||
env[parts[0]] = v
|
||||
} else {
|
||||
env[parts[0]] = parts[1]
|
||||
}
|
||||
default:
|
||||
return nil, fmt.Errorf("invalid environment declaration: %s", e)
|
||||
}
|
||||
}
|
||||
|
||||
if len(missing) > 0 {
|
||||
sort.Strings(missing)
|
||||
|
||||
return nil, fmt.Errorf("required env: %s", strings.Join(missing, ", "))
|
||||
}
|
||||
|
||||
return env, nil
|
||||
}
|
||||
|
||||
// ValidateEnv returns an error if required env vars for a service are not available
|
||||
// It also filters m.env to the union of all service env vars defined in the manifest
|
||||
func (m *Manifest) ValidateEnv() error {
|
||||
keys := map[string]bool{}
|
||||
|
||||
for _, s := range m.Services {
|
||||
env, err := m.ServiceEnvironment(s.Name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for k := range env {
|
||||
keys[k] = true
|
||||
}
|
||||
}
|
||||
|
||||
for k := range m.env {
|
||||
if !keys[k] {
|
||||
delete(m.env, k)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Manifest) ApplyDefaults() error {
|
||||
for i, s := range m.Services {
|
||||
if s.Build.Path == "" && s.Image == "" {
|
||||
m.Services[i].Build.Path = "."
|
||||
}
|
||||
|
||||
if m.Services[i].Build.Path != "" && s.Build.Manifest == "" {
|
||||
m.Services[i].Build.Manifest = "Dockerfile"
|
||||
}
|
||||
|
||||
if s.Drain == 0 {
|
||||
m.Services[i].Drain = 30
|
||||
}
|
||||
|
||||
if s.Health.Path == "" {
|
||||
m.Services[i].Health.Path = "/"
|
||||
}
|
||||
|
||||
if s.Health.Interval == 0 {
|
||||
m.Services[i].Health.Interval = 5
|
||||
}
|
||||
|
||||
if s.Health.Grace == 0 {
|
||||
m.Services[i].Health.Grace = m.Services[i].Health.Interval
|
||||
}
|
||||
|
||||
if s.Health.Timeout == 0 {
|
||||
m.Services[i].Health.Timeout = m.Services[i].Health.Interval - 1
|
||||
}
|
||||
|
||||
if s.Port.Port > 0 && s.Port.Scheme == "" {
|
||||
m.Services[i].Port.Scheme = "http"
|
||||
}
|
||||
|
||||
sp := fmt.Sprintf("services.%s.scale", s.Name)
|
||||
|
||||
// if no scale attributes set
|
||||
if len(m.AttributesByPrefix(sp)) == 0 {
|
||||
m.Services[i].Scale.Count = ServiceScaleCount{Min: 1, Max: 1}
|
||||
}
|
||||
|
||||
// if no explicit count attribute set yet has multiple scale attributes other than count
|
||||
if !m.AttributeSet(fmt.Sprintf("%s.count", sp)) && len(m.AttributesByPrefix(sp)) > 1 {
|
||||
m.Services[i].Scale.Count = ServiceScaleCount{Min: 1, Max: 1}
|
||||
}
|
||||
|
||||
if m.Services[i].Scale.Cpu == 0 {
|
||||
m.Services[i].Scale.Cpu = DefaultCpu
|
||||
}
|
||||
|
||||
if m.Services[i].Scale.Memory == 0 {
|
||||
m.Services[i].Scale.Memory = DefaultMem
|
||||
}
|
||||
|
||||
if !m.AttributeSet(fmt.Sprintf("services.%s.sticky", s.Name)) {
|
||||
m.Services[i].Sticky = true
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func message(w io.Writer, format string, args ...interface{}) {
|
||||
if w != nil {
|
||||
w.Write([]byte(fmt.Sprintf(format, args...) + "\n"))
|
||||
}
|
||||
}
|
||||
404
pkg/manifest/manifest_test.go
Normal file
404
pkg/manifest/manifest_test.go
Normal file
@ -0,0 +1,404 @@
|
||||
package manifest_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/convox/convox/pkg/common"
|
||||
"github.com/convox/convox/pkg/manifest"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestManifestLoad(t *testing.T) {
|
||||
n := &manifest.Manifest{
|
||||
Environment: manifest.Environment{
|
||||
"DEVELOPMENT=true",
|
||||
"GLOBAL=true",
|
||||
"OTHERGLOBAL",
|
||||
},
|
||||
Params: manifest.Params{
|
||||
"Foo": "bar",
|
||||
},
|
||||
Resources: manifest.Resources{
|
||||
manifest.Resource{
|
||||
Name: "database",
|
||||
Type: "postgres",
|
||||
Options: map[string]string{
|
||||
"size": "db.t2.large",
|
||||
},
|
||||
},
|
||||
},
|
||||
Services: manifest.Services{
|
||||
manifest.Service{
|
||||
Name: "api",
|
||||
Build: manifest.ServiceBuild{
|
||||
Manifest: "Dockerfile2",
|
||||
Path: "api",
|
||||
},
|
||||
Command: "",
|
||||
Domains: []string{"foo.example.org"},
|
||||
Drain: 30,
|
||||
Environment: []string{
|
||||
"DEFAULT=test",
|
||||
"DEVELOPMENT=false",
|
||||
"SECRET",
|
||||
},
|
||||
Health: manifest.ServiceHealth{
|
||||
Grace: 10,
|
||||
Path: "/",
|
||||
Interval: 10,
|
||||
Timeout: 9,
|
||||
},
|
||||
Init: true,
|
||||
Port: manifest.ServicePort{Port: 1000, Scheme: "http"},
|
||||
Resources: []string{"database"},
|
||||
Scale: manifest.ServiceScale{
|
||||
Count: manifest.ServiceScaleCount{Min: 3, Max: 10},
|
||||
Cpu: 256,
|
||||
Memory: 512,
|
||||
},
|
||||
Sticky: true,
|
||||
Test: "make test",
|
||||
},
|
||||
manifest.Service{
|
||||
Name: "proxy",
|
||||
Command: "bash",
|
||||
Domains: []string{"bar.example.org", "*.example.org"},
|
||||
Drain: 30,
|
||||
Health: manifest.ServiceHealth{
|
||||
Grace: 5,
|
||||
Path: "/auth",
|
||||
Interval: 5,
|
||||
Timeout: 4,
|
||||
},
|
||||
Image: "ubuntu:16.04",
|
||||
Environment: []string{
|
||||
"SECRET",
|
||||
},
|
||||
Port: manifest.ServicePort{Port: 2000, Scheme: "https"},
|
||||
Scale: manifest.ServiceScale{
|
||||
Count: manifest.ServiceScaleCount{Min: 1, Max: 1},
|
||||
Cpu: 512,
|
||||
Memory: 1024,
|
||||
},
|
||||
Sticky: true,
|
||||
},
|
||||
manifest.Service{
|
||||
Name: "foo",
|
||||
Build: manifest.ServiceBuild{
|
||||
Manifest: "Dockerfile",
|
||||
Path: ".",
|
||||
},
|
||||
Command: "foo",
|
||||
Domains: []string{"baz.example.org", "qux.example.org"},
|
||||
Drain: 60,
|
||||
Health: manifest.ServiceHealth{
|
||||
Grace: 2,
|
||||
Interval: 5,
|
||||
Path: "/",
|
||||
Timeout: 3,
|
||||
},
|
||||
Port: manifest.ServicePort{Port: 3000, Scheme: "https"},
|
||||
Scale: manifest.ServiceScale{
|
||||
Count: manifest.ServiceScaleCount{Min: 0, Max: 0},
|
||||
Cpu: 256,
|
||||
Memory: 512,
|
||||
},
|
||||
Singleton: true,
|
||||
Sticky: false,
|
||||
},
|
||||
manifest.Service{
|
||||
Name: "bar",
|
||||
Build: manifest.ServiceBuild{
|
||||
Manifest: "Dockerfile",
|
||||
Path: ".",
|
||||
},
|
||||
Command: "",
|
||||
Drain: 30,
|
||||
Health: manifest.ServiceHealth{
|
||||
Grace: 5,
|
||||
Interval: 5,
|
||||
Path: "/",
|
||||
Timeout: 4,
|
||||
},
|
||||
Scale: manifest.ServiceScale{
|
||||
Count: manifest.ServiceScaleCount{Min: 1, Max: 1},
|
||||
Cpu: 256,
|
||||
Memory: 512,
|
||||
},
|
||||
Sticky: true,
|
||||
},
|
||||
manifest.Service{
|
||||
Name: "scaler",
|
||||
Build: manifest.ServiceBuild{
|
||||
Manifest: "Dockerfile",
|
||||
Path: ".",
|
||||
},
|
||||
Command: "",
|
||||
Drain: 30,
|
||||
Health: manifest.ServiceHealth{
|
||||
Grace: 5,
|
||||
Interval: 5,
|
||||
Path: "/",
|
||||
Timeout: 4,
|
||||
},
|
||||
Scale: manifest.ServiceScale{
|
||||
Count: manifest.ServiceScaleCount{Min: 1, Max: 5},
|
||||
Cpu: 256,
|
||||
Memory: 512,
|
||||
Targets: manifest.ServiceScaleTargets{
|
||||
Cpu: 50,
|
||||
Memory: 75,
|
||||
Requests: 200,
|
||||
Custom: manifest.ServiceScaleMetrics{
|
||||
{
|
||||
Aggregate: "max",
|
||||
Dimensions: map[string]string{"QueueName": "testqueue"},
|
||||
Namespace: "AWS/SQS",
|
||||
Name: "ApproximateNumberOfMessagesVisible",
|
||||
Value: float64(200),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Sticky: true,
|
||||
},
|
||||
manifest.Service{
|
||||
Name: "inherit",
|
||||
Command: "inherit",
|
||||
Domains: []string{"bar.example.org", "*.example.org"},
|
||||
Drain: 30,
|
||||
Health: manifest.ServiceHealth{
|
||||
Grace: 5,
|
||||
Path: "/auth",
|
||||
Interval: 5,
|
||||
Timeout: 4,
|
||||
},
|
||||
Image: "ubuntu:16.04",
|
||||
Environment: []string{
|
||||
"SECRET",
|
||||
},
|
||||
Port: manifest.ServicePort{Port: 2000, Scheme: "https"},
|
||||
Scale: manifest.ServiceScale{
|
||||
Count: manifest.ServiceScaleCount{Min: 1, Max: 1},
|
||||
Cpu: 512,
|
||||
Memory: 1024,
|
||||
},
|
||||
Sticky: true,
|
||||
},
|
||||
manifest.Service{
|
||||
Name: "agent",
|
||||
Agent: manifest.ServiceAgent{
|
||||
Enabled: true,
|
||||
Ports: []manifest.ServiceAgentPort{
|
||||
{Port: 5000, Protocol: "udp"},
|
||||
{Port: 5001, Protocol: "tcp"},
|
||||
{Port: 5002, Protocol: "tcp"},
|
||||
},
|
||||
},
|
||||
Build: manifest.ServiceBuild{
|
||||
Manifest: "Dockerfile",
|
||||
Path: ".",
|
||||
},
|
||||
Drain: 30,
|
||||
Health: manifest.ServiceHealth{
|
||||
Grace: 5,
|
||||
Path: "/",
|
||||
Interval: 5,
|
||||
Timeout: 4,
|
||||
},
|
||||
Scale: manifest.ServiceScale{
|
||||
Count: manifest.ServiceScaleCount{Min: 1, Max: 1},
|
||||
Cpu: 256,
|
||||
Memory: 512,
|
||||
},
|
||||
Sticky: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
attrs := []string{"services.proxy.environment",
|
||||
"environment",
|
||||
"params",
|
||||
"params.Foo",
|
||||
"resources",
|
||||
"resources.database",
|
||||
"resources.database.options",
|
||||
"resources.database.options.size",
|
||||
"resources.database.type",
|
||||
"services",
|
||||
"services.agent",
|
||||
"services.agent.agent",
|
||||
"services.agent.agent.ports",
|
||||
"services.api",
|
||||
"services.api.build",
|
||||
"services.api.build.manifest",
|
||||
"services.api.build.path",
|
||||
"services.api.domain",
|
||||
"services.api.environment",
|
||||
"services.api.health",
|
||||
"services.api.health.interval",
|
||||
"services.api.init",
|
||||
"services.api.port",
|
||||
"services.api.resources",
|
||||
"services.api.scale",
|
||||
"services.api.test",
|
||||
"services.bar",
|
||||
"services.foo",
|
||||
"services.foo.command",
|
||||
"services.foo.domain",
|
||||
"services.foo.drain",
|
||||
"services.foo.health",
|
||||
"services.foo.health.grace",
|
||||
"services.foo.health.timeout",
|
||||
"services.foo.port",
|
||||
"services.foo.port.port",
|
||||
"services.foo.port.scheme",
|
||||
"services.foo.scale",
|
||||
"services.foo.singleton",
|
||||
"services.foo.sticky",
|
||||
"services.inherit",
|
||||
"services.inherit.command",
|
||||
"services.inherit.domain",
|
||||
"services.inherit.environment",
|
||||
"services.inherit.health",
|
||||
"services.inherit.image",
|
||||
"services.inherit.port",
|
||||
"services.inherit.scale",
|
||||
"services.inherit.scale.cpu",
|
||||
"services.inherit.scale.memory",
|
||||
"services.proxy",
|
||||
"services.proxy.command",
|
||||
"services.proxy.domain",
|
||||
"services.proxy.health",
|
||||
"services.proxy.image",
|
||||
"services.proxy.port",
|
||||
"services.proxy.scale",
|
||||
"services.proxy.scale.cpu",
|
||||
"services.proxy.scale.memory",
|
||||
"services.scaler",
|
||||
"services.scaler.scale",
|
||||
"services.scaler.scale.count",
|
||||
"services.scaler.scale.targets",
|
||||
"services.scaler.scale.targets.cpu",
|
||||
"services.scaler.scale.targets.custom",
|
||||
"services.scaler.scale.targets.custom.AWS/SQS/ApproximateNumberOfMessagesVisible",
|
||||
"services.scaler.scale.targets.custom.AWS/SQS/ApproximateNumberOfMessagesVisible.aggregate",
|
||||
"services.scaler.scale.targets.custom.AWS/SQS/ApproximateNumberOfMessagesVisible.dimensions",
|
||||
"services.scaler.scale.targets.custom.AWS/SQS/ApproximateNumberOfMessagesVisible.dimensions.QueueName",
|
||||
"services.scaler.scale.targets.custom.AWS/SQS/ApproximateNumberOfMessagesVisible.value",
|
||||
"services.scaler.scale.targets.memory",
|
||||
"services.scaler.scale.targets.requests",
|
||||
}
|
||||
|
||||
env := map[string]string{"FOO": "bar", "SECRET": "shh", "OTHERGLOBAL": "test"}
|
||||
|
||||
n.SetAttributes(attrs)
|
||||
n.SetEnv(env)
|
||||
|
||||
// env processing that normally happens as part of load
|
||||
require.NoError(t, n.CombineEnv())
|
||||
require.NoError(t, n.ValidateEnv())
|
||||
|
||||
m, err := testdataManifest("full", env)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, n, m)
|
||||
|
||||
senv, err := m.ServiceEnvironment("api")
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, map[string]string{"DEFAULT": "test", "DEVELOPMENT": "false", "GLOBAL": "true", "OTHERGLOBAL": "test", "SECRET": "shh"}, senv)
|
||||
|
||||
s1, err := m.Service("api")
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, map[string]string{"DEFAULT": "test", "DEVELOPMENT": "false", "GLOBAL": "true"}, s1.EnvironmentDefaults())
|
||||
require.Equal(t, "DEFAULT,DEVELOPMENT,GLOBAL,OTHERGLOBAL,SECRET", s1.EnvironmentKeys())
|
||||
|
||||
s2, err := m.Service("proxy")
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, map[string]string{"DEVELOPMENT": "true", "GLOBAL": "true"}, s2.EnvironmentDefaults())
|
||||
require.Equal(t, "DEVELOPMENT,GLOBAL,OTHERGLOBAL,SECRET", s2.EnvironmentKeys())
|
||||
}
|
||||
|
||||
func TestManifestLoadSimple(t *testing.T) {
|
||||
_, err := testdataManifest("simple", map[string]string{})
|
||||
require.EqualError(t, err, "required env: REQUIRED")
|
||||
|
||||
n := &manifest.Manifest{
|
||||
Services: manifest.Services{
|
||||
manifest.Service{
|
||||
Name: "web",
|
||||
Build: manifest.ServiceBuild{
|
||||
Manifest: "Dockerfile",
|
||||
Path: ".",
|
||||
},
|
||||
Drain: 30,
|
||||
Environment: manifest.Environment{
|
||||
"REQUIRED",
|
||||
"DEFAULT=true",
|
||||
},
|
||||
Health: manifest.ServiceHealth{
|
||||
Grace: 5,
|
||||
Interval: 5,
|
||||
Path: "/",
|
||||
Timeout: 4,
|
||||
},
|
||||
Scale: manifest.ServiceScale{
|
||||
Count: manifest.ServiceScaleCount{Min: 1, Max: 1},
|
||||
Cpu: 256,
|
||||
Memory: 512,
|
||||
},
|
||||
Sticky: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
n.SetAttributes([]string{"services", "services.web", "services.web.build", "services.web.environment"})
|
||||
n.SetEnv(map[string]string{"REQUIRED": "test"})
|
||||
|
||||
// env processing that normally happens as part of load
|
||||
require.NoError(t, n.CombineEnv())
|
||||
require.NoError(t, n.ValidateEnv())
|
||||
|
||||
m, err := testdataManifest("simple", map[string]string{"REQUIRED": "test"})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, n, m)
|
||||
}
|
||||
|
||||
func TestManifestLoadClobberEnv(t *testing.T) {
|
||||
env := map[string]string{"FOO": "bar", "REQUIRED": "false"}
|
||||
|
||||
_, err := testdataManifest("simple", env)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, map[string]string{"FOO": "bar", "REQUIRED": "false"}, env)
|
||||
}
|
||||
|
||||
func TestManifestLoadInvalid(t *testing.T) {
|
||||
m, err := testdataManifest("full", map[string]string{})
|
||||
require.Nil(t, m)
|
||||
require.Error(t, err, "required env: OTHERGLOBAL, SECRET")
|
||||
|
||||
m, err = testdataManifest("invalid.1", map[string]string{})
|
||||
require.Nil(t, m)
|
||||
require.Error(t, err, "yaml: line 2: did not find expected comment or line break")
|
||||
|
||||
m, err = testdataManifest("invalid.2", map[string]string{})
|
||||
require.NotNil(t, m)
|
||||
require.Len(t, m.Services, 0)
|
||||
}
|
||||
|
||||
func TestManifestEnvManipulation(t *testing.T) {
|
||||
m, err := testdataManifest("env", map[string]string{})
|
||||
require.NotNil(t, m)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, "train-intent", m.Services[0].EnvironmentDefaults()["QUEUE_NAME"])
|
||||
require.Equal(t, "delete-intent", m.Services[1].EnvironmentDefaults()["QUEUE_NAME"])
|
||||
}
|
||||
|
||||
func testdataManifest(name string, env map[string]string) (*manifest.Manifest, error) {
|
||||
data, err := common.Testdata(name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return manifest.Load(data, env)
|
||||
}
|
||||
3
pkg/manifest/params.go
Normal file
3
pkg/manifest/params.go
Normal file
@ -0,0 +1,3 @@
|
||||
package manifest
|
||||
|
||||
type Params map[string]string
|
||||
13
pkg/manifest/resource.go
Normal file
13
pkg/manifest/resource.go
Normal file
@ -0,0 +1,13 @@
|
||||
package manifest
|
||||
|
||||
type Resource struct {
|
||||
Name string `yaml:"-"`
|
||||
Type string `yaml:"type"`
|
||||
Options map[string]string `yaml:"options"`
|
||||
}
|
||||
|
||||
type Resources []Resource
|
||||
|
||||
func (r Resource) GetName() string {
|
||||
return r.Name
|
||||
}
|
||||
161
pkg/manifest/service.go
Normal file
161
pkg/manifest/service.go
Normal file
@ -0,0 +1,161 @@
|
||||
package manifest
|
||||
|
||||
import (
|
||||
"crypto/sha1"
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type Service struct {
|
||||
Name string `yaml:"-"`
|
||||
|
||||
Agent ServiceAgent `yaml:"agent,omitempty"`
|
||||
Build ServiceBuild `yaml:"build,omitempty"`
|
||||
Command string `yaml:"command,omitempty"`
|
||||
Domains ServiceDomains `yaml:"domain,omitempty"`
|
||||
Drain int `yaml:"drain,omitempty"`
|
||||
Environment Environment `yaml:"environment,omitempty"`
|
||||
Health ServiceHealth `yaml:"health,omitempty"`
|
||||
Image string `yaml:"image,omitempty"`
|
||||
Init bool `yaml:"init,omitempty"`
|
||||
Internal bool `yaml:"internal,omitempty"`
|
||||
Links []string `yaml:"links,omitempty"`
|
||||
Port ServicePort `yaml:"port,omitempty"`
|
||||
Privileged bool `yaml:"privileged,omitempty"`
|
||||
Resources []string `yaml:"resources,omitempty"`
|
||||
Scale ServiceScale `yaml:"scale,omitempty"`
|
||||
Singleton bool `yaml:"singleton,omitempty"`
|
||||
Sticky bool `yaml:"sticky,omitempty"`
|
||||
Test string `yaml:"test,omitempty"`
|
||||
Volumes []string `yaml:"volumes,omitempty"`
|
||||
}
|
||||
|
||||
type Services []Service
|
||||
|
||||
type ServiceAgent struct {
|
||||
Enabled bool `yaml:"enabled,omitempty"`
|
||||
Ports []ServiceAgentPort `yaml:"ports,omitempty"`
|
||||
}
|
||||
|
||||
type ServiceAgentPort struct {
|
||||
Port int `yaml:"port,omitempty"`
|
||||
Protocol string `yaml:"protocol,omitempty"`
|
||||
}
|
||||
|
||||
type ServiceBuild struct {
|
||||
Args []string `yaml:"args,omitempty"`
|
||||
Manifest string `yaml:"manifest,omitempty"`
|
||||
Path string `yaml:"path,omitempty"`
|
||||
}
|
||||
|
||||
type ServiceDomains []string
|
||||
|
||||
type ServiceHealth struct {
|
||||
Grace int
|
||||
Interval int
|
||||
Path string
|
||||
Timeout int
|
||||
}
|
||||
|
||||
type ServicePort struct {
|
||||
Port int `yaml:"port,omitempty"`
|
||||
Scheme string `yaml:"scheme,omitempty"`
|
||||
}
|
||||
|
||||
type ServiceScale struct {
|
||||
Count ServiceScaleCount
|
||||
Cpu int
|
||||
Memory int
|
||||
Targets ServiceScaleTargets `yaml:"targets,omitempty"`
|
||||
}
|
||||
|
||||
type ServiceScaleCount struct {
|
||||
Min int
|
||||
Max int
|
||||
}
|
||||
|
||||
type ServiceScaleMetric struct {
|
||||
Aggregate string
|
||||
Dimensions map[string]string
|
||||
Namespace string
|
||||
Name string
|
||||
Value float64
|
||||
}
|
||||
|
||||
type ServiceScaleMetrics []ServiceScaleMetric
|
||||
|
||||
type ServiceScaleTargets struct {
|
||||
Cpu int
|
||||
Custom ServiceScaleMetrics
|
||||
Memory int
|
||||
Requests int
|
||||
}
|
||||
|
||||
func (s Service) BuildHash(key string) string {
|
||||
return fmt.Sprintf("%x", sha1.Sum([]byte(fmt.Sprintf("key=%q build[path=%q, manifest=%q, args=%v] image=%q", key, s.Build.Path, s.Build.Manifest, s.Build.Args, s.Image))))
|
||||
}
|
||||
|
||||
func (s Service) Domain() string {
|
||||
if len(s.Domains) < 1 {
|
||||
return ""
|
||||
}
|
||||
|
||||
return s.Domains[0]
|
||||
}
|
||||
|
||||
func (s Service) EnvironmentDefaults() map[string]string {
|
||||
defaults := map[string]string{}
|
||||
|
||||
for _, e := range s.Environment {
|
||||
switch parts := strings.Split(e, "="); len(parts) {
|
||||
case 2:
|
||||
defaults[parts[0]] = parts[1]
|
||||
}
|
||||
}
|
||||
|
||||
return defaults
|
||||
}
|
||||
|
||||
func (s Service) EnvironmentKeys() string {
|
||||
kh := map[string]bool{}
|
||||
|
||||
for _, e := range s.Environment {
|
||||
kh[strings.Split(e, "=")[0]] = true
|
||||
}
|
||||
|
||||
keys := []string{}
|
||||
|
||||
for k := range kh {
|
||||
keys = append(keys, k)
|
||||
}
|
||||
|
||||
sort.Strings(keys)
|
||||
|
||||
return strings.Join(keys, ",")
|
||||
}
|
||||
|
||||
func (s Service) GetName() string {
|
||||
return s.Name
|
||||
}
|
||||
|
||||
func (s Service) Autoscale() bool {
|
||||
if s.Agent.Enabled {
|
||||
return false
|
||||
}
|
||||
|
||||
switch {
|
||||
case s.Scale.Count.Min == s.Scale.Count.Max:
|
||||
return false
|
||||
case s.Scale.Targets.Cpu > 0:
|
||||
return true
|
||||
case len(s.Scale.Targets.Custom) > 0:
|
||||
return true
|
||||
case s.Scale.Targets.Memory > 0:
|
||||
return true
|
||||
case s.Scale.Targets.Requests > 0:
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
3
pkg/manifest/testdata/api/Dockerfile
vendored
Normal file
3
pkg/manifest/testdata/api/Dockerfile
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
FROM ubuntu:16.04
|
||||
|
||||
CMD bash
|
||||
13
pkg/manifest/testdata/env.yml
vendored
Normal file
13
pkg/manifest/testdata/env.yml
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
environment:
|
||||
- NODE_ENV=${STAGE}
|
||||
- SQS_AWS_ACCOUNT_ID=${AWS_ACCOUNT_ID}
|
||||
- SQS_REGION=${AWS_REGION}
|
||||
- SQS_ENDPOINT=https://sqs.${AWS_REGION}.amazonaws.com
|
||||
- FOO=bar
|
||||
services:
|
||||
q-train-intent:
|
||||
environment:
|
||||
- QUEUE_NAME=train-intent
|
||||
q-delete-intent:
|
||||
environment:
|
||||
- QUEUE_NAME=delete-intent
|
||||
78
pkg/manifest/testdata/full.yml
vendored
Normal file
78
pkg/manifest/testdata/full.yml
vendored
Normal file
@ -0,0 +1,78 @@
|
||||
environment:
|
||||
- DEVELOPMENT=true
|
||||
- GLOBAL=true
|
||||
- OTHERGLOBAL
|
||||
params:
|
||||
Foo: bar
|
||||
resources:
|
||||
database:
|
||||
type: postgres
|
||||
options:
|
||||
size: db.t2.large
|
||||
services:
|
||||
api:
|
||||
build:
|
||||
manifest: Dockerfile2
|
||||
path: api
|
||||
domain: foo.example.org
|
||||
environment:
|
||||
- DEFAULT=test
|
||||
- DEVELOPMENT=false
|
||||
- SECRET
|
||||
health:
|
||||
interval: 10
|
||||
init: true
|
||||
resources:
|
||||
- database
|
||||
port: 1000
|
||||
scale: 3-10
|
||||
test: make ${BAR} test
|
||||
proxy: &proxy
|
||||
command: bash
|
||||
domain:
|
||||
- bar.example.org
|
||||
- "*.example.org"
|
||||
image: ubuntu:16.04
|
||||
environment:
|
||||
- SECRET
|
||||
health: /auth
|
||||
port: https:2000
|
||||
scale:
|
||||
cpu: 512
|
||||
memory: 1024
|
||||
foo:
|
||||
command: foo
|
||||
domain: baz.example.org, qux.example.org
|
||||
drain: 60
|
||||
health:
|
||||
grace: 2
|
||||
timeout: 3
|
||||
port:
|
||||
scheme: https
|
||||
port: 3000
|
||||
scale: 0
|
||||
singleton: true
|
||||
sticky: false
|
||||
bar:
|
||||
scaler:
|
||||
scale:
|
||||
count: 1-5
|
||||
targets:
|
||||
cpu: 50
|
||||
memory: 75
|
||||
requests: 200
|
||||
custom:
|
||||
AWS/SQS/ApproximateNumberOfMessagesVisible:
|
||||
aggregate: max
|
||||
value: 200
|
||||
dimensions:
|
||||
QueueName: testqueue
|
||||
inherit:
|
||||
"<<": *proxy
|
||||
command: inherit
|
||||
agent:
|
||||
agent:
|
||||
ports:
|
||||
- 5000/udp
|
||||
- 5001
|
||||
- 5002/tcp
|
||||
1
pkg/manifest/testdata/invalid.1.yml
vendored
Normal file
1
pkg/manifest/testdata/invalid.1.yml
vendored
Normal file
@ -0,0 +1 @@
|
||||
foo
|
||||
3
pkg/manifest/testdata/invalid.2.yml
vendored
Normal file
3
pkg/manifest/testdata/invalid.2.yml
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
servicess:
|
||||
web:
|
||||
build: .
|
||||
6
pkg/manifest/testdata/simple.yml
vendored
Normal file
6
pkg/manifest/testdata/simple.yml
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
services:
|
||||
web:
|
||||
build: .
|
||||
environment:
|
||||
- REQUIRED
|
||||
- DEFAULT=true
|
||||
36
pkg/manifest/timer.go
Normal file
36
pkg/manifest/timer.go
Normal file
@ -0,0 +1,36 @@
|
||||
package manifest
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type Timer struct {
|
||||
Name string `yaml:"-"`
|
||||
|
||||
Command string `yaml:"command"`
|
||||
Schedule string `yaml:"schedule"`
|
||||
Service string `yaml:"service"`
|
||||
}
|
||||
|
||||
type Timers []Timer
|
||||
|
||||
func (t Timer) Cron() (string, error) {
|
||||
switch len(strings.Split(t.Schedule, " ")) {
|
||||
case 5:
|
||||
return fmt.Sprintf("%s *", t.Schedule), nil
|
||||
case 6:
|
||||
return t.Schedule, nil
|
||||
default:
|
||||
return "", fmt.Errorf("invalid schedule expression: %s", t.Schedule)
|
||||
}
|
||||
}
|
||||
|
||||
func (t Timer) GetName() string {
|
||||
return t.Name
|
||||
}
|
||||
|
||||
func (t *Timer) SetName(name string) error {
|
||||
t.Name = name
|
||||
return nil
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user