aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristine Dodrill <me@christine.website>2017-01-27 01:52:24 -0800
committerChristine Dodrill <me@christine.website>2017-01-27 01:52:59 -0800
commit599d2cfde3054fe0a08fdc35e5a0df934cecda52 (patch)
treed322c57a35f2ffa74f5c9a7a0950bb0fa0c94134
parent74df32d62e399a0880195c9003b13de916d8ef6b (diff)
downloadx-599d2cfde3054fe0a08fdc35e5a0df934cecda52.tar.xz
x-599d2cfde3054fe0a08fdc35e5a0df934cecda52.zip
do more work on svc
-rw-r--r--svc/cmd/svc/main.go214
-rw-r--r--svc/cmd/svcd/dockerswarm-svcd/.gitignore3
-rw-r--r--svc/cmd/svcd/dockerswarm-svcd/main.go253
-rw-r--r--svc/credentials/jwt/jwt.go24
-rwxr-xr-xsvc/proto/regen.sh19
-rw-r--r--svc/proto/svc.pb.go598
-rw-r--r--svc/proto/svc.pb.gw.go348
-rw-r--r--svc/proto/svc.proto92
-rw-r--r--svc/proto/svc.swagger.json309
9 files changed, 1860 insertions, 0 deletions
diff --git a/svc/cmd/svc/main.go b/svc/cmd/svc/main.go
new file mode 100644
index 0000000..3a7b30d
--- /dev/null
+++ b/svc/cmd/svc/main.go
@@ -0,0 +1,214 @@
+package main
+
+import (
+ "context"
+ "encoding/json"
+ "fmt"
+ "log"
+ "os"
+ "path/filepath"
+ "time"
+
+ "github.com/Bowery/prompt"
+ jwtcreds "github.com/Xe/tools/svc/credentials/jwt"
+ svc "github.com/Xe/tools/svc/proto"
+ "github.com/Xe/uuid"
+ jwt "github.com/dgrijalva/jwt-go"
+ "github.com/olekukonko/tablewriter"
+ "google.golang.org/grpc"
+ kingpin "gopkg.in/alecthomas/kingpin.v1"
+)
+
+var (
+ app = kingpin.New("svc", "A simple service manager")
+ debug = app.Flag("debug", "print debugging logs?").Bool()
+ host = app.Flag("host", "host to do these changes to").String()
+ dataDir = app.Flag("data-dir", "place for svc to store data").Default("/home/xena/.local/within/svc").String()
+
+ createToken = app.Command("create-token", "Creates the initial server control token")
+ createTokenJwtSecret = createToken.Flag("jwt-secret", "jwt secret used on the server").Required().String()
+ createTokenUsername = createToken.Arg("username", "username to create token for").Required().String()
+
+ list = app.Command("list", "List apps running with this backend")
+ listLabelKey = list.Flag("labelKey", "label key to match for").String()
+ listLabelValue = list.Flag("labelValue", "label value to match for (with labelKey)").String()
+
+ create = app.Command("create", "Create a new application")
+ createName = create.Flag("name", "name of the application").Required().String()
+ createEnvFile = create.Flag("env-file", "file with key->value envvars").String()
+ createEnvironment = create.Flag("env", "environment variables for the program").StringMap()
+ createLabels = create.Flag("label", "additional labels to attach to the service").StringMap()
+ createAuthorizedUsers = create.Flag("authorized-user", "additional user to allow modification access to").Strings()
+ createExclusive = create.Flag("exclusive", "can this only ever have one copy running at once?").Bool()
+ createInstances = create.Flag("instances", "number of instances of the backend service").Default("1").Int()
+ createDockerImage = create.Arg("docker image", "docker image to execute for this service").Required().String()
+
+ update = app.Command("update", "Update an application")
+ updateImage = update.Flag("image", "new docker image to use for this service").String()
+ updateEnvAdd = update.Flag("env-add", "new environment variables to set").StringMap()
+ updateEnvRm = update.Flag("env-rm", "environment variables to remove").StringMap()
+ updateLabelAdd = update.Flag("label-add", "container labels to addB").StringMap()
+ updateLabelRm = update.Flag("label-rm", "container labels to remove").StringMap()
+ updateGrantUsers = update.Flag("grant-user", "grant a user permission to this service").Strings()
+ updateRevokeUsers = update.Flag("revoke-user", "revoke a user's permission to this service").Strings()
+ updateInstanceCount = update.Flag("instances", "updates the instance count of the service").Int()
+
+ inspect = app.Command("inspect", "Inspect an application")
+ inspectName = inspect.Arg("name", "name of the service").String()
+
+ deleteCmd = app.Command("delete", "Deletes an application by name")
+ deleteName = deleteCmd.Arg("name", "name of the service").String()
+
+ hostCmd = app.Command("host", "Host management")
+ hostAdd = hostCmd.Command("add", "Add a host to the state file")
+ hostAddTor = hostAdd.Flag("tor", "connect to this over tor?").Bool()
+ hostAddName = hostAdd.Arg("name", "name of host to add").Required().String()
+ hostAddAddr = hostAdd.Arg("addr", "address of taget server (host:port)").Required().String()
+ hostRemove = hostCmd.Command("remove", "Remove a host from the state file")
+ hostRemoveName = hostRemove.Arg("name", "name of host to remove").Required().String()
+)
+
+func main() {
+ cmdline := kingpin.MustParse(app.Parse(os.Args[1:]))
+
+ state, err := readState()
+ if err != nil {
+ if os.IsNotExist(err) {
+ log.Println("Host file does not exist, please add a host with `svc host add`.")
+ }
+
+ log.Fatal(err)
+ }
+ writeState(state)
+
+ switch cmdline {
+ case "host add":
+ token, err := prompt.Basic("token: ", true)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ h := &Host{
+ Name: *hostAddName,
+ Addr: *hostAddAddr,
+ Token: token,
+ Tor: *hostAddTor,
+ }
+
+ state.Hosts[h.Name] = h
+ writeState(state)
+
+ log.Println("Host added to hosts file.")
+ return
+ case "host remove":
+ log.Println("removing host not yet implemented")
+ os.Exit(1)
+ case "create-token":
+ now := time.Now()
+ nva := now.AddDate(0, 1, 0) // Expiry time of this token
+ nb4 := now.AddDate(0, 0, -1) // Not before then is this token valid
+
+ hostname, _ := os.Hostname()
+ tid := uuid.New()
+
+ token := jwt.NewWithClaims(jwt.SigningMethodHS512, &jwt.StandardClaims{
+ IssuedAt: now.Unix(),
+ NotBefore: nb4.Unix(),
+ ExpiresAt: nva.Unix(),
+ Issuer: hostname,
+ Subject: *createTokenUsername,
+ Id: tid,
+ })
+
+ tokenString, err := token.SignedString([]byte(*createTokenJwtSecret))
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ fmt.Println(tokenString)
+
+ os.Exit(0)
+ }
+
+ if *host == "" {
+ log.Fatal("--host must be supplied")
+ }
+
+ hostInfo, ok := state.Hosts[*host]
+ if !ok {
+ log.Fatalf("Requested host %q that doesn't exist in state", *host)
+ }
+
+ creds := jwtcreds.NewFromToken(hostInfo.Token)
+ conn, err := grpc.Dial(hostInfo.Addr, grpc.WithInsecure(),
+ grpc.WithPerRPCCredentials(creds))
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ c := svc.NewAppsClient(conn)
+
+ // RPC commands
+ switch cmdline {
+ case list.FullCommand():
+ apps, err := c.List(context.Background(), &svc.AppsListParams{})
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ table := tablewriter.NewWriter(os.Stdout)
+
+ table.SetHeader([]string{"ID", "Name", "Image", "Users"})
+
+ for _, app := range apps.Apps {
+ table.Append([]string{app.Id, app.Name, app.DockerImage, fmt.Sprintf("%v", app.AuthorizedUsers)})
+ }
+ table.Render()
+
+ case create.FullCommand():
+ log.Println("create not implemented")
+ case update.FullCommand():
+ log.Println("update not implemented")
+ case inspect.FullCommand():
+ log.Println("inspect not implemented")
+ case deleteCmd.FullCommand():
+ log.Println("delete not implemented")
+ }
+}
+
+type state struct {
+ Hosts map[string]*Host
+}
+
+type Host struct {
+ Name string
+ Addr string
+ Token string
+ Tor bool
+}
+
+func readState() (*state, error) {
+ s := &state{}
+
+ fname := filepath.Join(*dataDir, "state.json")
+ fin, err := os.Open(fname)
+ if err != nil {
+ return nil, err
+ }
+ defer fin.Close()
+
+ err = json.NewDecoder(fin).Decode(s)
+
+ return s, err
+}
+
+func writeState(s *state) error {
+ fname := filepath.Join(*dataDir, "state.json")
+ fout, err := os.Create(fname)
+ if err != nil {
+ return err
+ }
+ defer fout.Close()
+
+ return json.NewEncoder(fout).Encode(s)
+}
diff --git a/svc/cmd/svcd/dockerswarm-svcd/.gitignore b/svc/cmd/svcd/dockerswarm-svcd/.gitignore
new file mode 100644
index 0000000..39305f0
--- /dev/null
+++ b/svc/cmd/svcd/dockerswarm-svcd/.gitignore
@@ -0,0 +1,3 @@
+state.json
+dockerswarm-svcd
+*.pem
diff --git a/svc/cmd/svcd/dockerswarm-svcd/main.go b/svc/cmd/svcd/dockerswarm-svcd/main.go
new file mode 100644
index 0000000..724e7c9
--- /dev/null
+++ b/svc/cmd/svcd/dockerswarm-svcd/main.go
@@ -0,0 +1,253 @@
+package main
+
+import (
+ "encoding/json"
+ "errors"
+ "flag"
+ "fmt"
+ "log"
+ "net"
+ "os"
+ "strings"
+ "sync"
+
+ svc "github.com/Xe/tools/svc/proto"
+ jwt "github.com/dgrijalva/jwt-go"
+ "github.com/docker/docker/api/types"
+ "github.com/docker/docker/api/types/swarm"
+ "github.com/docker/docker/client"
+ "github.com/facebookgo/flagenv"
+ _ "github.com/joho/godotenv/autoload"
+ "golang.org/x/net/context"
+ "google.golang.org/grpc"
+ "google.golang.org/grpc/codes"
+ "google.golang.org/grpc/metadata"
+)
+
+var (
+ listenAddress = flag.String("listen", "127.0.0.1:23142", "tcp host:port to listen on")
+ sslCert = flag.String("tls-cert", "cert.pem", "tls certificate to read from")
+ sslKey = flag.String("tls-key", "key.pem", "tls private key")
+ jwtSecret = flag.String("jwt-secret", "hunter2", "secret used to sign jwt's")
+)
+
+const admin = "xena"
+
+type server struct {
+ docker *client.Client
+
+ sync.Mutex
+ state map[string][]string
+}
+
+func (s *server) LoadState(fname string) error {
+ s.Lock()
+ defer s.Unlock()
+
+ fin, err := os.Open(fname)
+ if err != nil {
+ return err
+ }
+ defer fin.Close()
+
+ return json.NewDecoder(fin).Decode(&s.state)
+}
+
+func (s *server) SaveState(fname string) error {
+ s.Lock()
+ defer s.Unlock()
+
+ fout, err := os.Create(fname)
+ if err != nil {
+ return err
+ }
+ defer fout.Close()
+
+ return json.NewEncoder(fout).Encode(&s.state)
+}
+
+func (s *server) List(ctx context.Context, params *svc.AppsListParams) (*svc.AppsList, error) {
+ user, err := s.checkAuth(ctx)
+ if err != nil {
+ return nil, err
+ }
+
+ svcs, err := s.docker.ServiceList(ctx, types.ServiceListOptions{})
+ if err != nil {
+ return nil, err
+ }
+
+ result := &svc.AppsList{}
+
+ for _, ssvc := range svcs {
+ env := func(kv []string) map[string]string {
+ result := map[string]string{}
+
+ for _, pair := range kv {
+ split := strings.SplitN(pair, "=", 2)
+ result[split[0]] = split[1]
+ }
+
+ return result
+ }(ssvc.Spec.TaskTemplate.ContainerSpec.Env)
+
+ au := s.state[ssvc.Spec.Name]
+ if au == nil {
+ s.state[ssvc.Spec.Name] = []string{admin}
+ s.SaveState("state.json")
+ }
+
+ allowed := false
+
+ if user == admin {
+ allowed = true
+ }
+
+ for _, allowedUser := range au {
+ if user == allowedUser {
+ allowed = true
+ }
+ }
+
+ if !allowed {
+ continue
+ }
+
+ result.Apps = append(result.Apps, &svc.App{
+ Id: ssvc.ID,
+ Name: ssvc.Spec.Name,
+ DockerImage: ssvc.Spec.TaskTemplate.ContainerSpec.Image,
+ Environment: env,
+ Labels: ssvc.Spec.Labels,
+ AuthorizedUsers: au,
+ })
+ }
+
+ return result, nil
+}
+
+func (s *server) Create(ctx context.Context, manifest *svc.Manifest) (*svc.App, error) {
+ user, err := s.checkAuth(ctx)
+ if err != nil {
+ return nil, err
+ }
+
+ env := []string{}
+
+ for key, val := range manifest.Environment {
+ env = append(env, fmt.Sprintf("%s=%s", key, val))
+ }
+
+ spec := swarm.ServiceSpec{
+ Annotations: swarm.Annotations{
+ Name: manifest.Name,
+ Labels: manifest.Labels,
+ },
+
+ TaskTemplate: swarm.TaskSpec{
+ ContainerSpec: swarm.ContainerSpec{
+ Image: manifest.DockerImage,
+ Env: env,
+ },
+ },
+
+ Mode: swarm.ServiceMode{
+ Replicated: &swarm.ReplicatedService{},
+ },
+ }
+
+ resp, err := s.docker.ServiceCreate(ctx, spec, types.ServiceCreateOptions{})
+ if err != nil {
+ return nil, err
+ }
+
+ ssvc, _, err := s.docker.ServiceInspectWithRaw(ctx, resp.ID)
+ if err != nil {
+ return nil, err
+ }
+
+ app := &svc.App{
+ Id: ssvc.ID,
+ Name: ssvc.Spec.Name,
+ DockerImage: ssvc.Spec.TaskTemplate.ContainerSpec.Image,
+ Environment: manifest.Environment,
+ Labels: ssvc.Spec.Labels,
+ AuthorizedUsers: []string{user},
+ }
+
+ return app, nil
+}
+
+func (s *server) Update(ctx context.Context, params *svc.AppUpdate) (*svc.App, error) {
+ return nil, errors.New("not implemented")
+}
+
+func (s *server) Inspect(ctx context.Context, params *svc.AppInspect) (*svc.App, error) {
+ return nil, errors.New("not implemented")
+}
+
+func (s *server) Delete(ctx context.Context, params *svc.AppDelete) (*svc.Ok, error) {
+ return nil, errors.New("not implemented")
+}
+
+func main() {
+ flag.Parse()
+ flagenv.Parse()
+
+ gs := grpc.NewServer()
+
+ defaultHeaders := map[string]string{"User-Agent": "dockerswarm-svcd"}
+ cli, err := client.NewClient(client.DefaultDockerHost, client.DefaultVersion, nil, defaultHeaders)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ s := &server{
+ docker: cli,
+ state: map[string][]string{},
+ }
+
+ err = s.LoadState("state.json")
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ svc.RegisterAppsServer(gs, s)
+
+ l, err := net.Listen("tcp", *listenAddress)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ err = gs.Serve(l)
+ if err != nil {
+ log.Fatal(err)
+ }
+}
+
+func (s *server) checkAuth(ctx context.Context) (string, error) {
+ var err error
+
+ md, ok := metadata.FromContext(ctx)
+ if !ok {
+ return "", grpc.Errorf(codes.Unauthenticated, "valid token required.")
+ }
+
+ jwtToken, ok := md["authorization"]
+ if !ok {
+ return "", grpc.Errorf(codes.Unauthenticated, "valid token required.")
+ }
+
+ clms := &jwt.StandardClaims{}
+
+ p := &jwt.Parser{}
+ _, err = p.ParseWithClaims(jwtToken[0], clms, jwt.Keyfunc(func(t *jwt.Token) (interface{}, error) {
+ return []byte(*jwtSecret), nil
+ }))
+ if err != nil {
+ log.Printf("rpc error: %v", err)
+ return "", grpc.Errorf(codes.Unauthenticated, "valid token requried.")
+ }
+
+ return clms.Subject, nil
+}
diff --git a/svc/credentials/jwt/jwt.go b/svc/credentials/jwt/jwt.go
new file mode 100644
index 0000000..978c880
--- /dev/null
+++ b/svc/credentials/jwt/jwt.go
@@ -0,0 +1,24 @@
+package jwt
+
+import (
+ "golang.org/x/net/context"
+ "google.golang.org/grpc/credentials"
+)
+
+type jwt struct {
+ token string
+}
+
+func NewFromToken(token string) credentials.PerRPCCredentials {
+ return jwt{token: token}
+}
+
+func (j jwt) GetRequestMetadata(ctx context.Context, uri ...string) (map[string]string, error) {
+ return map[string]string{
+ "authorization": j.token,
+ }, nil
+}
+
+func (j jwt) RequireTransportSecurity() bool {
+ return false
+}
diff --git a/svc/proto/regen.sh b/svc/proto/regen.sh
new file mode 100755
index 0000000..cb20e86
--- /dev/null
+++ b/svc/proto/regen.sh
@@ -0,0 +1,19 @@
+#!/bin/bash
+
+protoc -I/usr/local/include -I. \
+ -I$GOPATH/src \
+ -I$GOPATH/src/github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis \
+ --go_out=Mgoogle/api/annotations.proto=github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis/google/api,plugins=grpc:. \
+ svc.proto
+
+protoc -I/usr/local/include -I. \
+ -I$GOPATH/src \
+ -I$GOPATH/src/github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis \
+ --grpc-gateway_out=logtostderr=true:. \
+ svc.proto
+
+protoc -I/usr/local/include -I. \
+ -I$GOPATH/src \
+ -I$GOPATH/src/github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis \
+ --swagger_out=logtostderr=true:. \
+ svc.proto
diff --git a/svc/proto/svc.pb.go b/svc/proto/svc.pb.go
new file mode 100644
index 0000000..445c1ba
--- /dev/null
+++ b/svc/proto/svc.pb.go
@@ -0,0 +1,598 @@
+// Code generated by protoc-gen-go.
+// source: svc.proto
+// DO NOT EDIT!
+
+/*
+Package svc is a generated protocol buffer package.
+
+It is generated from these files:
+ svc.proto
+
+It has these top-level messages:
+ AppsListParams
+ AppsList
+ Manifest
+ App
+ AppUpdate
+ AppInspect
+ AppDelete
+ Ok
+*/
+package svc
+
+import proto "github.com/golang/protobuf/proto"
+import fmt "fmt"
+import math "math"
+import _ "github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis/google/api"
+
+import (
+ context "golang.org/x/net/context"
+ grpc "google.golang.org/grpc"
+)
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
+
+type AppsListParams struct {
+ LabelKey string `protobuf:"bytes,1,opt,name=labelKey" json:"labelKey,omitempty"`
+ LabelVal string `protobuf:"bytes,2,opt,name=labelVal" json:"labelVal,omitempty"`
+ // will be matched to app names
+ Name string `protobuf:"bytes,3,opt,name=name" json:"name,omitempty"`
+}
+
+func (m *AppsListParams) Reset() { *m = AppsListParams{} }
+func (m *AppsListParams) String() string { return proto.CompactTextString(m) }
+func (*AppsListParams) ProtoMessage() {}
+func (*AppsListParams) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
+
+func (m *AppsListParams) GetLabelKey() string {
+ if m != nil {
+ return m.LabelKey
+ }
+ return ""
+}
+
+func (m *AppsListParams) GetLabelVal() string {
+ if m != nil {
+ return m.LabelVal
+ }
+ return ""
+}
+
+func (m *AppsListParams) GetName() string {
+ if m != nil {
+ return m.Name
+ }
+ return ""
+}
+
+type AppsList struct {
+ Message string `protobuf:"bytes,1,opt,name=message" json:"message,omitempty"`
+ Apps []*App `protobuf:"bytes,2,rep,name=apps" json:"apps,omitempty"`
+}
+
+func (m *AppsList) Reset() { *m = AppsList{} }
+func (m *AppsList) String() string { return proto.CompactTextString(m) }
+func (*AppsList) ProtoMessage() {}
+func (*AppsList) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} }
+
+func (m *AppsList) GetMessage() string {
+ if m != nil {
+ return m.Message
+ }
+ return ""
+}
+
+func (m *AppsList) GetApps() []*App {
+ if m != nil {
+ return m.Apps
+ }
+ return nil
+}
+
+type Manifest struct {
+ Environment map[string]string `protobuf:"bytes,1,rep,name=environment" json:"environment,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"`
+ Labels map[string]string `protobuf:"bytes,2,rep,name=labels" json:"labels,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"`
+ DockerImage string `protobuf:"bytes,3,opt,name=dockerImage" json:"dockerImage,omitempty"`
+ Name string `protobuf:"bytes,4,opt,name=name" json:"name,omitempty"`
+}
+
+func (m *Manifest) Reset() { *m = Manifest{} }
+func (m *Manifest) String() string { return proto.CompactTextString(m) }
+func (*Manifest) ProtoMessage() {}
+func (*Manifest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} }
+
+func (m *Manifest) GetEnvironment() map[string]string {
+ if m != nil {
+ return m.Environment
+ }
+ return nil
+}
+
+func (m *Manifest) GetLabels() map[string]string {
+ if m != nil {
+ return m.Labels
+ }
+ return nil
+}
+
+func (m *Manifest) GetDockerImage() string {
+ if m != nil {
+ return m.DockerImage
+ }
+ return ""
+}
+
+func (m *Manifest) GetName() string {
+ if m != nil {
+ return m.Name
+ }
+ return ""
+}
+
+type App struct {
+ Id string `protobuf:"bytes,1,opt,name=id" json:"id,omitempty"`
+ Name string `protobuf:"bytes,2,opt,name=name" json:"name,omitempty"`
+ DockerImage string `protobuf:"bytes,3,opt,name=dockerImage" json:"dockerImage,omitempty"`
+ Environment map[string]string `protobuf:"bytes,4,rep,name=environment" json:"environment,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"`
+ Labels map[string]string `protobuf:"bytes,5,rep,name=labels" json:"labels,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"`
+ AuthorizedUsers []string `protobuf:"bytes,6,rep,name=authorizedUsers" json:"authorizedUsers,omitempty"`
+ Instances int32 `protobuf:"varint,7,opt,name=instances" json:"instances,omitempty"`
+}
+
+func (m *App) Reset() { *m = App{} }
+func (m *App) String() string { return proto.CompactTextString(m) }
+func (*App) ProtoMessage() {}
+func (*App) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} }
+
+func (m *App) GetId() string {
+ if m != nil {
+ return m.Id
+ }
+ return ""
+}
+
+func (m *App) GetName() string {
+ if m != nil {
+ return m.Name
+ }
+ return ""
+}
+
+func (m *App) GetDockerImage() string {
+ if m != nil {
+ return m.DockerImage
+ }
+ return ""
+}
+
+func (m *App) GetEnvironment() map[string]string {
+ if m != nil {
+ return m.Environment
+ }
+ return nil
+}
+
+func (m *App) GetLabels() map[string]string {
+ if m != nil {
+ return m.Labels
+ }
+ return nil
+}
+
+func (m *App) GetAuthorizedUsers() []string {
+ if m != nil {
+ return m.AuthorizedUsers
+ }
+ return nil
+}
+
+func (m *App) GetInstances() int32 {
+ if m != nil {
+ return m.Instances
+ }
+ return 0
+}
+
+type AppUpdate struct {
+ Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
+ NewImage string `protobuf:"bytes,2,opt,name=newImage" json:"newImage,omitempty"`
+ EnvAdd map[string]string `protobuf:"bytes,3,rep,name=envAdd" json:"envAdd,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"`
+ EnvRm map[string]string `protobuf:"bytes,4,rep,name=envRm" json:"envRm,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"`
+ LabelAdd map[string]string `protobuf:"bytes,5,rep,name=labelAdd" json:"labelAdd,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"`
+ LabelRm map[string]string `protobuf:"bytes,6,rep,name=labelRm" json:"labelRm,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"`
+ GrantUsers []string `protobuf:"bytes,7,rep,name=grantUsers" json:"grantUsers,omitempty"`
+ RevokeUsers []string `protobuf:"bytes,8,rep,name=revokeUsers" json:"revokeUsers,omitempty"`
+ NewInstanceCount int32 `protobuf:"varint,9,opt,name=newInstanceCount" json:"newInstanceCount,omitempty"`
+}
+
+func (m *AppUpdate) Reset() { *m = AppUpdate{} }
+func (m *AppUpdate) String() string { return proto.CompactTextString(m) }
+func (*AppUpdate) ProtoMessage() {}
+func (*AppUpdate) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{4} }
+
+func (m *AppUpdate) GetName() string {
+ if m != nil {
+ return m.Name
+ }
+ return ""
+}
+
+func (m *AppUpdate) GetNewImage() string {
+ if m != nil {
+ return m.NewImage
+ }
+ return ""
+}
+
+func (m *AppUpdate) GetEnvAdd() map[string]string {
+ if m != nil {
+ return m.EnvAdd
+ }
+ return nil
+}
+
+func (m *AppUpdate) GetEnvRm() map[string]string {
+ if m != nil {
+ return m.EnvRm
+ }
+ return nil
+}
+
+func (m *AppUpdate) GetLabelAdd() map[string]string {
+ if m != nil {
+ return m.LabelAdd
+ }
+ return nil
+}
+
+func (m *AppUpdate) GetLabelRm() map[string]string {
+ if m != nil {
+ return m.LabelRm
+ }
+ return nil
+}
+
+func (m *AppUpdate) GetGrantUsers() []string {
+ if m != nil {
+ return m.GrantUsers
+ }
+ return nil
+}
+
+func (m *AppUpdate) GetRevokeUsers() []string {
+ if m != nil {
+ return m.RevokeUsers
+ }
+ return nil
+}
+
+func (m *AppUpdate) GetNewInstanceCount() int32 {
+ if m != nil {
+ return m.NewInstanceCount
+ }
+ return 0
+}
+
+type AppInspect struct {
+ Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
+}
+
+func (m *AppInspect) Reset() { *m = AppInspect{} }
+func (m *AppInspect) String() string { return proto.CompactTextString(m) }
+func (*AppInspect) ProtoMessage() {}
+func (*AppInspect) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{5} }
+
+func (m *AppInspect) GetName() string {
+ if m != nil {
+ return m.Name
+ }
+ return ""
+}
+
+type AppDelete struct {
+ Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
+}
+
+func (m *AppDelete) Reset() { *m = AppDelete{} }
+func (m *AppDelete) String() string { return proto.CompactTextString(m) }
+func (*AppDelete) ProtoMessage() {}
+func (*AppDelete) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{6} }
+
+func (m *AppDelete) GetName() string {
+ if m != nil {
+ return m.Name
+ }
+ return ""
+}
+
+type Ok struct {
+ Message string `protobuf:"bytes,1,opt,name=message" json:"message,omitempty"`
+}
+
+func (m *Ok) Reset() { *m = Ok{} }
+func (m *Ok) String() string { return proto.CompactTextString(m) }
+func (*Ok) ProtoMessage() {}
+func (*Ok) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{7} }
+
+func (m *Ok) GetMessage() string {
+ if m != nil {
+ return m.Message
+ }
+ return ""
+}
+
+func init() {
+ proto.RegisterType((*AppsListParams)(nil), "AppsListParams")
+ proto.RegisterType((*AppsList)(nil), "AppsList")
+ proto.RegisterType((*Manifest)(nil), "Manifest")
+ proto.RegisterType((*App)(nil), "App")
+ proto.RegisterType((*AppUpdate)(nil), "AppUpdate")
+ proto.RegisterType((*AppInspect)(nil), "AppInspect")
+ proto.RegisterType((*AppDelete)(nil), "AppDelete")
+ proto.RegisterType((*Ok)(nil), "Ok")
+}
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ context.Context
+var _ grpc.ClientConn
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the grpc package it is being compiled against.
+const _ = grpc.SupportPackageIsVersion4
+
+// Client API for Apps service
+
+type AppsClient interface {
+ List(ctx context.Context, in *AppsListParams, opts ...grpc.CallOption) (*AppsList, error)
+ Create(ctx context.Context, in *Manifest, opts ...grpc.CallOption) (*App, error)
+ Update(ctx context.Context, in *AppUpdate, opts ...grpc.CallOption) (*App, error)
+ Inspect(ctx context.Context, in *AppInspect, opts ...grpc.CallOption) (*App, error)
+ Delete(ctx context.Context, in *AppDelete, opts ...grpc.CallOption) (*Ok, error)
+}
+
+type appsClient struct {
+ cc *grpc.ClientConn
+}
+
+func NewAppsClient(cc *grpc.ClientConn) AppsClient {
+ return &appsClient{cc}
+}
+
+func (c *appsClient) List(ctx context.Context, in *AppsListParams, opts ...grpc.CallOption) (*AppsList, error) {
+ out := new(AppsList)
+ err := grpc.Invoke(ctx, "/Apps/List", in, out, c.cc, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *appsClient) Create(ctx context.Context, in *Manifest, opts ...grpc.CallOption) (*App, error) {
+ out := new(App)
+ err := grpc.Invoke(ctx, "/Apps/Create", in, out, c.cc, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *appsClient) Update(ctx context.Context, in *AppUpdate, opts ...grpc.CallOption) (*App, error) {
+ out := new(App)
+ err := grpc.Invoke(ctx, "/Apps/Update", in, out, c.cc, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *appsClient) Inspect(ctx context.Context, in *AppInspect, opts ...grpc.CallOption) (*App, error) {
+ out := new(App)
+ err := grpc.Invoke(ctx, "/Apps/Inspect", in, out, c.cc, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *appsClient) Delete(ctx context.Context, in *AppDelete, opts ...grpc.CallOption) (*Ok, error) {
+ out := new(Ok)
+ err := grpc.Invoke(ctx, "/Apps/Delete", in, out, c.cc, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+// Server API for Apps service
+
+type AppsServer interface {
+ List(context.Context, *AppsListParams) (*AppsList, error)
+ Create(context.Context, *Manifest) (*App, error)
+ Update(context.Context, *AppUpdate) (*App, error)
+ Inspect(context.Context, *AppInspect) (*App, error)
+ Delete(context.Context, *AppDelete) (*Ok, error)
+}
+
+func RegisterAppsServer(s *grpc.Server, srv AppsServer) {
+ s.RegisterService(&_Apps_serviceDesc, srv)
+}
+
+func _Apps_List_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(AppsListParams)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(AppsServer).List(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: "/Apps/List",
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(AppsServer).List(ctx, req.(*AppsListParams))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _Apps_Create_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(Manifest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(AppsServer).Create(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: "/Apps/Create",
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(AppsServer).Create(ctx, req.(*Manifest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _Apps_Update_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(AppUpdate)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(AppsServer).Update(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: "/Apps/Update",
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(AppsServer).Update(ctx, req.(*AppUpdate))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _Apps_Inspect_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(AppInspect)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(AppsServer).Inspect(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: "/Apps/Inspect",
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(AppsServer).Inspect(ctx, req.(*AppInspect))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _Apps_Delete_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(AppDelete)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(AppsServer).Delete(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: "/Apps/Delete",
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(AppsServer).Delete(ctx, req.(*AppDelete))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+var _Apps_serviceDesc = grpc.ServiceDesc{
+ ServiceName: "Apps",
+ HandlerType: (*AppsServer)(nil),
+ Methods: []grpc.MethodDesc{
+ {
+ MethodName: "List",
+ Handler: _Apps_List_Handler,
+ },
+ {
+ MethodName: "Create",
+ Handler: _Apps_Create_Handler,
+ },
+ {
+ MethodName: "Update",
+ Handler: _Apps_Update_Handler,
+ },
+ {
+ MethodName: "Inspect",
+ Handler: _Apps_Inspect_Handler,
+ },
+ {
+ MethodName: "Delete",
+ Handler: _Apps_Delete_Handler,
+ },
+ },
+ Streams: []grpc.StreamDesc{},
+ Metadata: "svc.proto",
+}
+
+func init() { proto.RegisterFile("svc.proto", fileDescriptor0) }
+
+var fileDescriptor0 = []byte{
+ // 728 bytes of a gzipped FileDescriptorProto
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xc4, 0x55, 0xcd, 0x6e, 0xd3, 0x40,
+ 0x10, 0x56, 0x1c, 0xe7, 0xc7, 0x13, 0x68, 0xc3, 0x96, 0x82, 0x71, 0x4b, 0x89, 0xcc, 0x25, 0x2a,
+ 0xc2, 0x51, 0x0b, 0x82, 0x52, 0x68, 0x25, 0xab, 0xf4, 0x50, 0x51, 0x54,