From 974d61f6b398c9530d14f88d3d0cb7489f8075ac Mon Sep 17 00:00:00 2001 From: dinesh Date: Wed, 28 Mar 2018 18:52:46 +0530 Subject: [PATCH 01/13] Adding async version of logs streaming --- CHANGELOG.md | 5 +++++ api/helper.go | 2 +- api/logs.go | 7 ++++--- api/models/extra.go | 7 ++++--- api/server.go | 6 +++++- client/apps.go | 3 ++- cloud/kube/common.go | 38 +++++++++++++++++++++++++++++++++----- cloud/kube/deployment.go | 10 ++++++++-- cmd/logs.go | 9 ++++++--- 9 files changed, 68 insertions(+), 19 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 664b9b01..caa381c9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,11 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). ## [UNRELEASED] - 0000-00-00 +### Fixes +- AWS nginx ingress controller to respect `Path: /` +- Async support for streaming logs from mutiple processes. +### Added +- [CLI] Number of logs lines for process logs (`--lines 10`) ## [1.0.0-alpha.12] - 2018-03-27 ### Added diff --git a/api/helper.go b/api/helper.go index 510d40b9..7173aafa 100644 --- a/api/helper.go +++ b/api/helper.go @@ -128,7 +128,7 @@ func ws(at string, handler websocketFunc) websocket.Handler { err := handler(ws) if err != nil { - log.Error(err) + log.Errorf("ws %s: %v", at, err) ws.Write([]byte(fmt.Sprintf("ERROR: %v\n", err))) return } diff --git a/api/logs.go b/api/logs.go index 42980934..cb460513 100644 --- a/api/logs.go +++ b/api/logs.go @@ -40,9 +40,10 @@ func (s *Server) LogStreamWs(ws *websocket.Conn) error { } return s.Provider.LogStream(app, ws, pb.LogStreamOptions{ - Since: since, - Follow: follow, - Proctype: headers.Get("process"), + Since: since, + Follow: follow, + Proctype: headers.Get("process"), + TailLines: headers.Get("lines"), }) } diff --git a/api/models/extra.go b/api/models/extra.go index 55469be2..0c1da54e 100644 --- a/api/models/extra.go +++ b/api/models/extra.go @@ -46,9 +46,10 @@ type ReleaseOptions struct { } type LogStreamOptions struct { - Follow bool - Proctype string - Since time.Duration + Follow bool + Proctype string + Since time.Duration + TailLines string // number of recent lines to show for streaming (string format) } type AppCreateOptions struct { diff --git a/api/server.go b/api/server.go index 1b9930d9..b800d75a 100644 --- a/api/server.go +++ b/api/server.go @@ -297,7 +297,11 @@ func (s *Server) BuildLogStreamReq(ws *websocket.Conn) error { return err } - _, err = io.Copy(ws, r) + //FIXME: r can be nil for minikube-based environment. Should return io.Reader from docker daemon + if r != nil { + _, err = io.Copy(ws, r) + } + return err } diff --git a/client/apps.go b/client/apps.go index 5eb67254..299cb7b4 100644 --- a/client/apps.go +++ b/client/apps.go @@ -42,13 +42,14 @@ func (c *Client) RestartApp(name string) error { return err } -func (c *Client) StreamAppLogs(name string, follow bool, since time.Duration, process string, out io.Writer) error { +func (c *Client) StreamAppLogs(name string, follow bool, since time.Duration, process string, lines int, out io.Writer) error { in, out := os.Stdin, os.Stdout return c.Stream("/ws/v1/logs", map[string]string{ "app": name, "since": since.String(), "follow": strconv.FormatBool(follow), "Process": process, + "lines": strconv.Itoa(lines), }, in, out) } diff --git a/cloud/kube/common.go b/cloud/kube/common.go index f5a81ffe..7ee64d6c 100644 --- a/cloud/kube/common.go +++ b/cloud/kube/common.go @@ -6,6 +6,7 @@ import ( "math" "strconv" "strings" + "sync" "time" log "github.com/Sirupsen/logrus" @@ -17,6 +18,7 @@ import ( meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1" klabels "k8s.io/apimachinery/pkg/labels" "k8s.io/client-go/kubernetes" + "k8s.io/client-go/rest" ) func DeleteApp(c *kubernetes.Clientset, ns, app string, provider cloud.CloudProvider) error { @@ -208,6 +210,7 @@ func GetServiceEndpoint(c *kubernetes.Clientset, ns, name string) (string, error } func LogStreamReq(c *kubernetes.Clientset, w io.Writer, ns, app string, opts pb.LogStreamOptions) error { + pods, err := GetAllPods(c, ns, app) if err != nil { return err @@ -217,6 +220,12 @@ func LogStreamReq(c *kubernetes.Clientset, w io.Writer, ns, app string, opts pb. //TODO: consider using https://github.com/djherbis/stream for reading multiple streams var sources []multiplexio.Source + type reqQueue struct { + name string + request *rest.Request + } + + var requests []reqQueue for _, pod := range pods { if opts.Proctype != "" && opts.Proctype != pod.ObjectMeta.Labels[typeLabel] { @@ -229,7 +238,8 @@ func LogStreamReq(c *kubernetes.Clientset, w io.Writer, ns, app string, opts pb. Name(name). Resource("pods"). SubResource("log"). - Param("follow", strconv.FormatBool(opts.Follow)) + Param("follow", strconv.FormatBool(opts.Follow)). + Param("tailLines", opts.TailLines) var cntName string if len(pod.Spec.Containers) > 0 { @@ -237,24 +247,42 @@ func LogStreamReq(c *kubernetes.Clientset, w io.Writer, ns, app string, opts pb. } req = req.Param("container", cntName) - log.Debugf("streaming logs from pod:%v container:%s", name, cntName) + log.Debugf("will stream logs from %v/%s", name, cntName) if opts.Since > 0 { sec := int64(math.Ceil(float64(opts.Since) / float64(time.Second))) req = req.Param("sinceSeconds", strconv.FormatInt(sec, 10)) } - if r, err := req.Stream(); err == nil { - prefix := fmt.Sprintf("[%s] ", strings.TrimPrefix(name, app+"-")) + requests = append(requests, reqQueue{name: name, request: req}) + } + + var wg sync.WaitGroup + + for _, rq := range requests { + wg.Add(1) + + go func(rq reqQueue) { + defer wg.Done() + r, err := rq.request.Stream() + if err != nil { + log.Errorf("creating log stream: %v", err) + } + + prefix := fmt.Sprintf("[%s] ", strings.TrimPrefix(rq.name, app+"-")) sources = append(sources, multiplexio.Source{ Reader: r, Write: func(dest io.Writer, token []byte) (int, error) { return multiplexio.WriteNewLine(dest, append([]byte(prefix), token...)) }, }) - } + }(rq) } + log.Infof("waiting for stream handlers ...") + wg.Wait() + log.Debugf("Done. Got %d streams", len(sources)) + _, err = io.Copy(w, multiplexio.NewReader(multiplexio.Options{}, sources...)) return err } diff --git a/cloud/kube/deployment.go b/cloud/kube/deployment.go index 816f93e1..00ddf53b 100644 --- a/cloud/kube/deployment.go +++ b/cloud/kube/deployment.go @@ -137,12 +137,18 @@ func newIngress(payload *DeployResponse, domains []string) *v1beta1.Ingress { rules := make([]v1beta1.IngressRule, len(domains)) for i, domain := range domains { + ingressPath := "/" + + if payload.Request.Provider == cloud.GCPProvider { + // It's important to have * after / since GCP GLBC load balancer doesn't support subresources automatically. + ingressPath = "/*" + } + rules[i] = v1beta1.IngressRule{ Host: domain, IngressRuleValue: v1beta1.IngressRuleValue{HTTP: &v1beta1.HTTPIngressRuleValue{ Paths: []v1beta1.HTTPIngressPath{{ - // It's important to have * after / since GCP GLBC load balancer doesn't support subresources automatically. - Path: "/*", + Path: ingressPath, Backend: v1beta1.IngressBackend{ ServiceName: r.ServiceID, ServicePort: r.ContainerPort, diff --git a/cmd/logs.go b/cmd/logs.go index b8cc1002..6fd4c832 100644 --- a/cmd/logs.go +++ b/cmd/logs.go @@ -2,7 +2,6 @@ package cmd import ( "os" - "time" "github.com/datacol-io/datacol/cmd/stdcli" "github.com/urfave/cli" @@ -22,7 +21,11 @@ func init() { &cli.DurationFlag{ Name: "since", Usage: "show logs since a duration (e.g. 10m or 1h2m10s)", - Value: 2 * time.Minute, + }, + &cli.IntFlag{ + Name: "lines, l", + Usage: "Number of lines of recent log file to display", + Value: 10, }, &cli.StringFlag{ Name: "process, p", @@ -46,7 +49,7 @@ func cmdAppLogStream(c *cli.Context) error { name = c.Args().Get(0) } - err = client.StreamAppLogs(name, c.Bool("follow"), c.Duration("since"), c.String("process"), os.Stdout) + err = client.StreamAppLogs(name, c.Bool("follow"), c.Duration("since"), c.String("process"), c.Int("lines"), os.Stdout) stdcli.ExitOnError(err) return err From 5fc0bfe20873b5d789304aca6b17017ae6f6cf0c Mon Sep 17 00:00:00 2001 From: dinesh Date: Fri, 30 Mar 2018 12:54:14 +0530 Subject: [PATCH 02/13] Making `datacol run` independent of shell --- CHANGELOG.md | 3 ++- api/process.go | 7 +++++-- client/process.go | 2 +- cloud/aws/process.go | 4 ++-- cloud/google/process.go | 4 ++-- cloud/kube/process.go | 21 +++++++++------------ cloud/local/deploy.go | 4 ++-- cloud/provider.go | 2 +- 8 files changed, 24 insertions(+), 23 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index caa381c9..544cd010 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ This project adheres to [Semantic Versioning](http://semver.org/). ### Fixes - AWS nginx ingress controller to respect `Path: /` - Async support for streaming logs from mutiple processes. +- Making `datacol run` independent of shell ### Added - [CLI] Number of logs lines for process logs (`--lines 10`) @@ -19,7 +20,7 @@ This project adheres to [Semantic Versioning](http://semver.org/). - AWS elasticsearch support - Websocket connection for streaming logs and Running one-off commands - Added `--ref` flag into deploy cmd -- Proxy support through bastion Host +- Proxy support through bastion Host ### Fixed - CLI improvements - [CLI] Bump default version of GCP cluster to `1.7.14-gke.1` diff --git a/api/process.go b/api/process.go index c2af92c6..0a8f9b90 100644 --- a/api/process.go +++ b/api/process.go @@ -4,6 +4,7 @@ import ( "errors" "fmt" "net" + "strings" "sync" "time" @@ -57,7 +58,8 @@ func (s *Server) ProcessRunWs(ws *websocket.Conn) error { return fmt.Errorf("Missing require param: app") } - return s.Provider.ProcessRun(app, ws, headers.Get("command")) + command := strings.Split(headers.Get("command"), "#") + return s.Provider.ProcessRun(app, ws, command) } func (s *Server) ProcessRun(srv pbs.ProviderService_ProcessRunServer) error { @@ -65,7 +67,8 @@ func (s *Server) ProcessRun(srv pbs.ProviderService_ProcessRunServer) error { app, command := md["app"][0], md["command"][0] stream := &runStreamRW{srv} - if err := s.Provider.ProcessRun(app, stream, command); err != nil { + commandParts := strings.Split(command, "#") + if err := s.Provider.ProcessRun(app, stream, commandParts); err != nil { log.Errorf("failed to run the process: %v", err) return err } diff --git a/client/process.go b/client/process.go index 442727b4..99f507c8 100644 --- a/client/process.go +++ b/client/process.go @@ -44,6 +44,6 @@ func (c *Client) SaveProcess(name string, options map[string]string) error { func (c *Client) RunProcess(name string, args []string) error { return c.Stream("/ws/v1/exec", map[string]string{ "app": name, - "command": strings.Join(args, " "), + "command": strings.Join(args, "#"), }, os.Stdin, os.Stdout) } diff --git a/cloud/aws/process.go b/cloud/aws/process.go index bcd9abfa..8d4fd141 100644 --- a/cloud/aws/process.go +++ b/cloud/aws/process.go @@ -15,14 +15,14 @@ func (p *AwsCloud) ProcessList(app string) ([]*pb.Process, error) { return kube.ProcessList(p.kubeClient(), p.DeploymentName, app) } -func (p *AwsCloud) ProcessRun(name string, r io.ReadWriter, command string) error { +func (p *AwsCloud) ProcessRun(name string, r io.ReadWriter, command []string) error { ns := p.DeploymentName cfg, _ := getKubeClientConfig(ns) envVars, _ := p.EnvironmentGet(name) app, _ := p.AppGet(name) - return kube.ProcessExec(p.kubeClient(), cfg, ns, name, p.latestImage(app), command, envVars, false, r, cloud.AwsProvider) + return kube.ProcessRun(p.kubeClient(), cfg, ns, name, p.latestImage(app), command, envVars, false, r, cloud.AwsProvider) } func (p *AwsCloud) ProcessSave(name string, structure map[string]int32) error { diff --git a/cloud/google/process.go b/cloud/google/process.go index 768a092e..545c1767 100644 --- a/cloud/google/process.go +++ b/cloud/google/process.go @@ -10,7 +10,7 @@ import ( "github.com/datacol-io/datacol/cloud/kube" ) -func (g *GCPCloud) ProcessRun(name string, stream io.ReadWriter, command string) error { +func (g *GCPCloud) ProcessRun(name string, stream io.ReadWriter, command []string) error { ns := g.DeploymentName cfg, err := getKubeClientConfig(ns) if err != nil { @@ -21,7 +21,7 @@ func (g *GCPCloud) ProcessRun(name string, stream io.ReadWriter, command string) envVars, _ := g.EnvironmentGet(name) sqlproxy := g.appLinkedDB(app) - return kube.ProcessExec(g.kubeClient(), cfg, ns, name, g.latestImage(app), command, envVars, sqlproxy, stream, cloud.GCPProvider) + return kube.ProcessRun(g.kubeClient(), cfg, ns, name, g.latestImage(app), command, envVars, sqlproxy, stream, cloud.GCPProvider) } func (g *GCPCloud) ProcessList(app string) ([]*pb.Process, error) { diff --git a/cloud/kube/process.go b/cloud/kube/process.go index 8382d8c2..06ee9095 100644 --- a/cloud/kube/process.go +++ b/cloud/kube/process.go @@ -89,10 +89,7 @@ func (p *ExecOptions) Run() error { Name(pod.Name). Namespace(pod.Namespace). SubResource("exec"). - Param("container", containerName). - Param("command", "/bin/sh"). - Param("command", "-c"). - Param("tty", "true") + Param("container", containerName) req.VersionedParams(&corev1.PodExecOptions{ Container: containerName, @@ -142,10 +139,11 @@ func ProcessList(c *kubernetes.Clientset, ns, app string) ([]*pb.Process, error) return items, nil } -func ProcessExec( +func ProcessRun( c *kubernetes.Clientset, cfg *rest.Config, - ns, name, image, command string, + ns, name, image string, + command []string, envVars map[string]string, sqlproxy bool, stream io.ReadWriter, @@ -153,11 +151,11 @@ func ProcessExec( ) error { proctype := rand.Characters(6) podName := fmt.Sprintf("%s-%s", name, proctype) + req := &DeployRequest{ ServiceID: podName, Image: image, - Entrypoint: []string{"/bin/bash", "-c"}, - Args: []string{"trap : TERM INT; sleep infinity & wait"}, //FIXME: To let the pod stay around until being told to exit + Args: []string{"sleep", "infinity"}, //FIXME: To let the pod stay around until being told to exit EnvVars: envVars, App: name, Proctype: proctype, @@ -168,19 +166,18 @@ func ProcessExec( // Delete the pod sunce it's ephemeral defer deletePodByName(c, ns, podName) - return processExec(c, cfg, ns, command, req, stream) + return processRun(c, cfg, ns, command, req, stream) } func deletePodByName(c *kubernetes.Clientset, ns, name string) error { return c.Core().Pods(ns).Delete(name, &metav1.DeleteOptions{}) } -func processExec(c *kubernetes.Clientset, cfg *rest.Config, ns, command string, req *DeployRequest, stream io.ReadWriter) error { +func processRun(c *kubernetes.Clientset, cfg *rest.Config, ns string, command []string, req *DeployRequest, stream io.ReadWriter) error { spec := newPodSpec(req) spec.Spec.RestartPolicy = corev1.RestartPolicyNever log.Debugf("creating pod with spec %s", toJson(spec)) - pod, err := c.Core().Pods(ns).Create(spec) if err != nil { return err @@ -195,7 +192,7 @@ func processExec(c *kubernetes.Clientset, cfg *rest.Config, ns, command string, executer := &ExecOptions{ Namespace: ns, PodName: req.ServiceID, - Command: []string{command}, + Command: command, Stdin: true, In: stream, Out: stream, diff --git a/cloud/local/deploy.go b/cloud/local/deploy.go index 195e5243..1434eee5 100644 --- a/cloud/local/deploy.go +++ b/cloud/local/deploy.go @@ -19,7 +19,7 @@ func (g *LocalCloud) LogStream(app string, w io.Writer, opts pb.LogStreamOptions return sched.LogStreamReq(g.kubeClient(), w, g.Name, app, opts) } -func (g *LocalCloud) ProcessRun(name string, stream io.ReadWriter, command string) error { +func (g *LocalCloud) ProcessRun(name string, stream io.ReadWriter, command []string) error { ns := g.Name cfg, err := getKubeClientConfig(ns) if err != nil { @@ -29,7 +29,7 @@ func (g *LocalCloud) ProcessRun(name string, stream io.ReadWriter, command strin app, _ := g.AppGet(name) envVars, _ := g.EnvironmentGet(name) - return sched.ProcessExec(g.kubeClient(), cfg, ns, name, g.latestImage(app), command, envVars, false, stream, cloud.LocalProvider) + return sched.ProcessRun(g.kubeClient(), cfg, ns, name, g.latestImage(app), command, envVars, false, stream, cloud.LocalProvider) } func (g *LocalCloud) ProcessList(app string) ([]*pb.Process, error) { diff --git a/cloud/provider.go b/cloud/provider.go index 6fcd469f..54be35c6 100644 --- a/cloud/provider.go +++ b/cloud/provider.go @@ -31,7 +31,7 @@ type Provider interface { LogStream(app string, w io.Writer, opts pb.LogStreamOptions) error ProcessList(app string) ([]*pb.Process, error) - ProcessRun(app string, r io.ReadWriter, command string) error + ProcessRun(app string, r io.ReadWriter, command []string) error ProcessSave(app string, formation map[string]int32) error ResourceList() (pb.Resources, error) From b5f70e4d9a65890c8640876ea671967bf4008f98 Mon Sep 17 00:00:00 2001 From: dinesh Date: Wed, 4 Apr 2018 18:31:07 +0530 Subject: [PATCH 03/13] Sorting environment variable in API --- CHANGELOG.md | 2 ++ cloud/common/util.go | 21 ++++++++++++++++++- cloud/local/apps.go | 2 +- cmd/env.go | 2 +- cmd/infra.go | 1 + cmd/stdcli/apprc.go | 49 +++++++++++++++++++++++++------------------- 6 files changed, 53 insertions(+), 24 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 544cd010..2650d4a1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,10 +4,12 @@ This project adheres to [Semantic Versioning](http://semver.org/). ## [UNRELEASED] - 0000-00-00 ### Fixes +- Sort environment variables in API response - AWS nginx ingress controller to respect `Path: /` - Async support for streaming logs from mutiple processes. - Making `datacol run` independent of shell ### Added +- [CLI] `STACK` env var for `datacol env`, `datacol infra` - [CLI] Number of logs lines for process logs (`--lines 10`) ## [1.0.0-alpha.12] - 2018-03-27 diff --git a/cloud/common/util.go b/cloud/common/util.go index 16cbae82..a3f8f66f 100644 --- a/cloud/common/util.go +++ b/cloud/common/util.go @@ -5,6 +5,7 @@ import ( "bytes" "errors" "fmt" + "sort" "strings" log "github.com/Sirupsen/logrus" @@ -29,7 +30,7 @@ func LoadEnvironment(data []byte) pb.Environment { } } - return e + return SortEnvironment(e) } func GenerateId(prefix string, size int) string { @@ -119,3 +120,21 @@ func GetProcessCommand(proctype string, b *pb.Build) (command []string, err erro return } + +func SortEnvironment(current pb.Environment) pb.Environment { + sorted := make(pb.Environment) + keys := make([]string, 0, len(current)) + for key := range current { + keys = append(keys, key) + } + + sort.Slice(keys, func(i, j int) bool { + return keys[i] < keys[j] + }) + + for _, k := range keys { + sorted[k] = current[k] + } + + return sorted +} diff --git a/cloud/local/apps.go b/cloud/local/apps.go index 42047ab8..68e8a545 100644 --- a/cloud/local/apps.go +++ b/cloud/local/apps.go @@ -79,7 +79,7 @@ func (g *LocalCloud) AppDelete(name string) error { } func (g *LocalCloud) EnvironmentGet(name string) (pb.Environment, error) { - return g.EnvMap[name], nil + return common.SortEnvironment(g.EnvMap[name]), nil } func (g *LocalCloud) EnvironmentSet(name string, body io.Reader) error { diff --git a/cmd/env.go b/cmd/env.go index 8487e56f..1a1429be 100644 --- a/cmd/env.go +++ b/cmd/env.go @@ -13,7 +13,7 @@ func init() { Name: "env", Usage: "manage environment variables for an app", Action: cmdConfigList, - Flags: []cli.Flag{&appFlag}, + Flags: []cli.Flag{&appFlag, &stackFlag}, Subcommands: []cli.Command{ { Name: "set", diff --git a/cmd/infra.go b/cmd/infra.go index f7446f67..044b9f0f 100644 --- a/cmd/infra.go +++ b/cmd/infra.go @@ -47,6 +47,7 @@ func init() { Name: "infra", Usage: "Managed GCP stack resources and infrastructure", Action: cmdResourceList, + Flags: []cli.Flag{&stackFlag}, Subcommands: []cli.Command{ { Name: "create", diff --git a/cmd/stdcli/apprc.go b/cmd/stdcli/apprc.go index bc9b3b0c..1f207936 100644 --- a/cmd/stdcli/apprc.go +++ b/cmd/stdcli/apprc.go @@ -1,6 +1,7 @@ package stdcli import ( + "fmt" "os" "github.com/appscode/go/io" @@ -94,36 +95,17 @@ func LoadApprc() (*Apprc, error) { /* Exits if there is any error.*/ func GetAuthContextOrDie(stack string) (*Auth, *Apprc) { - rc, err := LoadApprc() - if err != nil { - term.Fatalln("Command requires authentication, please run `datacol login`") - } - - a := rc.GetAuth(stack) - - if a == nil { - term.Fatalln("Command requires authentication, please run `datacol login`") - } - return a, rc + return loadAuthForStack(stack) } /* Exits if there is any error.*/ func GetAuthOrDie(c *cli.Context) (*Auth, *Apprc) { - rc, err := LoadApprc() - if err != nil { - term.Fatalln("Command requires authentication, please run `datacol login`") - } - stack := c.String("stack") if stack == "" { stack = GetAppSetting("stack") } - a := rc.GetAuth(stack) - if a == nil { - term.Fatalln("Command requires authentication, please run `datacol login`") - } - return a, rc + return loadAuthForStack(stack) } /* Exits if there is any error.*/ @@ -153,3 +135,28 @@ func NewAnonAUth() *Auth { a := &Auth{ApiServer: "localhost"} return a } + +func loadAuthForStack(stack string) (*Auth, *Apprc) { + rc, err := LoadApprc() + if err != nil { + exitWithLoginError("failed to load config file.") + } + + if stack == "" { + term.Fatalln("No stack found. Please provide `STACK` environment variable or --stack flag") + } + + a := rc.GetAuth(stack) + + if a == nil { + exitWithLoginError(fmt.Sprintf("No stack found for `%s`.", stack)) + } + return a, rc +} + +func exitWithLoginError(msg ...string) { + for _, m := range msg { + term.Println(m) + } + term.Fatalln("Since the command requires authentication, please run `datacol login` if you haven't logged in.") +} From c15627119677bbcaee056fdc48b5042be2acae2f Mon Sep 17 00:00:00 2001 From: dinesh Date: Thu, 5 Apr 2018 18:12:51 +0530 Subject: [PATCH 04/13] Adding tabular data for apps and builds --- Gopkg.lock | 20 +- Gopkg.toml | 3 + cloud/aws/builder.go | 2 +- cmd/apps.go | 13 +- cmd/build.go | 11 +- vendor/github.com/ararog/timeago/.gitignore | 24 + vendor/github.com/ararog/timeago/.travis.yml | 5 + vendor/github.com/ararog/timeago/LICENSE | 21 + vendor/github.com/ararog/timeago/README.md | 6 + vendor/github.com/ararog/timeago/timeago.go | 139 ++ .../github.com/ararog/timeago/timeago_test.go | 79 ++ .../github.com/mattn/go-runewidth/.travis.yml | 8 + vendor/github.com/mattn/go-runewidth/LICENSE | 21 + .../github.com/mattn/go-runewidth/README.mkd | 27 + .../mattn/go-runewidth/runewidth.go | 1223 +++++++++++++++++ .../mattn/go-runewidth/runewidth_js.go | 8 + .../mattn/go-runewidth/runewidth_posix.go | 77 ++ .../mattn/go-runewidth/runewidth_test.go | 275 ++++ .../mattn/go-runewidth/runewidth_windows.go | 25 + .../olekukonko/tablewriter/.travis.yml | 12 + .../olekukonko/tablewriter/LICENCE.md | 19 + .../olekukonko/tablewriter/README.md | 277 ++++ .../github.com/olekukonko/tablewriter/csv.go | 52 + .../tablewriter/csv2table/README.md | 43 + .../tablewriter/csv2table/csv2table.go | 85 ++ .../olekukonko/tablewriter/table.go | 839 +++++++++++ .../olekukonko/tablewriter/table_test.go | 1120 +++++++++++++++ .../tablewriter/table_with_color.go | 134 ++ .../olekukonko/tablewriter/test.csv | 4 + .../olekukonko/tablewriter/test_info.csv | 4 + .../github.com/olekukonko/tablewriter/util.go | 78 ++ .../github.com/olekukonko/tablewriter/wrap.go | 99 ++ .../olekukonko/tablewriter/wrap_test.go | 66 + 33 files changed, 4815 insertions(+), 4 deletions(-) create mode 100644 vendor/github.com/ararog/timeago/.gitignore create mode 100644 vendor/github.com/ararog/timeago/.travis.yml create mode 100644 vendor/github.com/ararog/timeago/LICENSE create mode 100644 vendor/github.com/ararog/timeago/README.md create mode 100644 vendor/github.com/ararog/timeago/timeago.go create mode 100644 vendor/github.com/ararog/timeago/timeago_test.go create mode 100644 vendor/github.com/mattn/go-runewidth/.travis.yml create mode 100644 vendor/github.com/mattn/go-runewidth/LICENSE create mode 100644 vendor/github.com/mattn/go-runewidth/README.mkd create mode 100644 vendor/github.com/mattn/go-runewidth/runewidth.go create mode 100644 vendor/github.com/mattn/go-runewidth/runewidth_js.go create mode 100644 vendor/github.com/mattn/go-runewidth/runewidth_posix.go create mode 100644 vendor/github.com/mattn/go-runewidth/runewidth_test.go create mode 100644 vendor/github.com/mattn/go-runewidth/runewidth_windows.go create mode 100644 vendor/github.com/olekukonko/tablewriter/.travis.yml create mode 100644 vendor/github.com/olekukonko/tablewriter/LICENCE.md create mode 100644 vendor/github.com/olekukonko/tablewriter/README.md create mode 100644 vendor/github.com/olekukonko/tablewriter/csv.go create mode 100644 vendor/github.com/olekukonko/tablewriter/csv2table/README.md create mode 100644 vendor/github.com/olekukonko/tablewriter/csv2table/csv2table.go create mode 100644 vendor/github.com/olekukonko/tablewriter/table.go create mode 100644 vendor/github.com/olekukonko/tablewriter/table_test.go create mode 100644 vendor/github.com/olekukonko/tablewriter/table_with_color.go create mode 100644 vendor/github.com/olekukonko/tablewriter/test.csv create mode 100644 vendor/github.com/olekukonko/tablewriter/test_info.csv create mode 100644 vendor/github.com/olekukonko/tablewriter/util.go create mode 100644 vendor/github.com/olekukonko/tablewriter/wrap.go create mode 100644 vendor/github.com/olekukonko/tablewriter/wrap_test.go diff --git a/Gopkg.lock b/Gopkg.lock index 9199d007..c4566e39 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -30,6 +30,12 @@ packages = ["context","crypto/rand","env","errors","io","log","term"] revision = "0042f7fe164fd03992cfa5ea70a98615516be99b" +[[projects]] + name = "github.com/ararog/timeago" + packages = ["."] + revision = "518814407569bf983ea81e1bf8b550dd4e7b34f3" + version = "0.0.1" + [[projects]] name = "github.com/asaskevich/govalidator" packages = ["."] @@ -343,6 +349,12 @@ packages = ["."] revision = "57fdcb988a5c543893cc61bce354a6e24ab70022" +[[projects]] + name = "github.com/mattn/go-runewidth" + packages = ["."] + revision = "9e777a8366cce605130a531d2cd6363d07ad7317" + version = "v0.0.2" + [[projects]] name = "github.com/mholt/archiver" packages = ["."] @@ -367,6 +379,12 @@ packages = ["."] revision = "f22b7ef81a0afac9ce1447d37e5ab8e99fbd2f73" +[[projects]] + branch = "master" + name = "github.com/olekukonko/tablewriter" + packages = ["."] + revision = "b8a9be070da40449e501c3c4730a889e42d87a9e" + [[projects]] name = "github.com/pelletier/go-toml" packages = ["."] @@ -562,6 +580,6 @@ [solve-meta] analyzer-name = "dep" analyzer-version = 1 - inputs-digest = "46839c89b027427ff758080f2a6d231f96ae66876d4d84c45f630b36ef9275f2" + inputs-digest = "c97831aeb0d594a9f4347792339fcc7afdc24bd921d53359837e6895825b6232" solver-name = "gps-cdcl" solver-version = 1 diff --git a/Gopkg.toml b/Gopkg.toml index 87921ff4..83145aa6 100644 --- a/Gopkg.toml +++ b/Gopkg.toml @@ -75,3 +75,6 @@ required = [ [[constraint]] name = "github.com/mholt/archiver" + +[[constraint]] + name = "github.com/ararog/timeago" diff --git a/cloud/aws/builder.go b/cloud/aws/builder.go index e553ca67..b02c583f 100644 --- a/cloud/aws/builder.go +++ b/cloud/aws/builder.go @@ -96,7 +96,7 @@ func (a *AwsCloud) BuildList(app string, limit int) (pb.Builds, error) { } sort.Slice(builds, func(i, j int) bool { - return builds[i].CreatedAt < builds[j].CreatedAt + return builds[i].CreatedAt > builds[j].CreatedAt }) return builds, nil diff --git a/cmd/apps.go b/cmd/apps.go index b9d3155d..6d2201c0 100644 --- a/cmd/apps.go +++ b/cmd/apps.go @@ -3,6 +3,9 @@ package cmd import ( "fmt" "os" + "strings" + + "github.com/olekukonko/tablewriter" log "github.com/Sirupsen/logrus" term "github.com/appscode/go/term" @@ -75,7 +78,15 @@ func cmdAppsList(c *cli.Context) error { if len(apps) == 0 { fmt.Println("No apps found.") } else { - fmt.Println(toJson(apps)) + table := tablewriter.NewWriter(os.Stdout) + table.SetHeader([]string{"NAME", "BUILD", "RELEASE", "DOMAINS", "LOAD BALANCER"}) + for _, a := range apps { + table.Append([]string{a.Name, a.BuildId, a.ReleaseId, + strings.Join(a.Domains, "\n"), + a.Endpoint, + }) + } + table.Render() } return nil } diff --git a/cmd/build.go b/cmd/build.go index a56079d6..7207c9a0 100644 --- a/cmd/build.go +++ b/cmd/build.go @@ -15,9 +15,11 @@ import ( "github.com/datacol-io/datacol/client" "github.com/datacol-io/datacol/cmd/stdcli" + timeago "github.com/ararog/timeago" "github.com/docker/docker/builder/dockerignore" "github.com/docker/docker/pkg/archive" "github.com/docker/docker/pkg/fileutils" + "github.com/olekukonko/tablewriter" "github.com/urfave/cli" "golang.org/x/net/context" "golang.org/x/net/websocket" @@ -60,7 +62,14 @@ func cmdBuildList(c *cli.Context) error { builds, err := api.GetBuilds(name) stdcli.ExitOnError(err) - fmt.Println(toJson(builds)) + start, table := time.Now(), tablewriter.NewWriter(os.Stdout) + table.SetHeader([]string{"ID", "COMMIT", "STATUS", "CREATED"}) + for _, b := range builds { + delta, _ := timeago.TimeAgoWithTime(start, time.Unix(int64(b.CreatedAt), 0)) + table.Append([]string{b.Id, b.Version, b.Status, delta}) + } + + table.Render() return nil } diff --git a/vendor/github.com/ararog/timeago/.gitignore b/vendor/github.com/ararog/timeago/.gitignore new file mode 100644 index 00000000..daf913b1 --- /dev/null +++ b/vendor/github.com/ararog/timeago/.gitignore @@ -0,0 +1,24 @@ +# Compiled Object files, Static and Dynamic libs (Shared Objects) +*.o +*.a +*.so + +# Folders +_obj +_test + +# Architecture specific extensions/prefixes +*.[568vq] +[568vq].out + +*.cgo1.go +*.cgo2.c +_cgo_defun.c +_cgo_gotypes.go +_cgo_export.* + +_testmain.go + +*.exe +*.test +*.prof diff --git a/vendor/github.com/ararog/timeago/.travis.yml b/vendor/github.com/ararog/timeago/.travis.yml new file mode 100644 index 00000000..98b43464 --- /dev/null +++ b/vendor/github.com/ararog/timeago/.travis.yml @@ -0,0 +1,5 @@ +language: go + +go: + - 1.3 + - tip diff --git a/vendor/github.com/ararog/timeago/LICENSE b/vendor/github.com/ararog/timeago/LICENSE new file mode 100644 index 00000000..d5de9ae4 --- /dev/null +++ b/vendor/github.com/ararog/timeago/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2016 Rogério Pereira Araújo + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/ararog/timeago/README.md b/vendor/github.com/ararog/timeago/README.md new file mode 100644 index 00000000..38c5c916 --- /dev/null +++ b/vendor/github.com/ararog/timeago/README.md @@ -0,0 +1,6 @@ +# timeago + +[![Build Status](https://travis-ci.org/ararog/timeago.svg?branch=master)](https://travis-ci.org/ararog/timeago) + +TimeAgo is a library used to calculate how much time has been passed between +two dates, this library is mainly based on time type of go. diff --git a/vendor/github.com/ararog/timeago/timeago.go b/vendor/github.com/ararog/timeago/timeago.go new file mode 100644 index 00000000..3499fb0e --- /dev/null +++ b/vendor/github.com/ararog/timeago/timeago.go @@ -0,0 +1,139 @@ +package timeago + +import ( + "time" + "fmt" + "math" + "errors" +) + +type DateAgoValues int + +const ( + SecondsAgo DateAgoValues = iota + MinutesAgo + HoursAgo + DaysAgo + WeeksAgo + MonthsAgo + YearsAgo +) + +func TimeAgoFromNowWithTime(end time.Time) (string, error) { + + return TimeAgoWithTime(time.Now(), end) +} + +func TimeAgoFromNowWithString( + layout, end string) (string, error) { + + t, e := time.Parse(layout, end) + if e == nil { + return TimeAgoWithTime(time.Now(), t) + } else { + err := errors.New("Invalid format") + return "", err + } +} + +func TimeAgoWithTime(start, end time.Time) (string, error) { + duration := start.Sub(end) + return stringForDuration(duration), nil +} + +func TimeAgoWithString(layout, start, end string) (string, error) { + + timeStart, e := time.Parse(layout, start) + if e != nil { + err := errors.New("Invalid start time format") + return "", err + } + + timeEnd, e := time.Parse(layout, end) + if e != nil { + err := errors.New("Invalid end time format") + return "", err + } + + duration := timeStart.Sub(timeEnd) + return stringForDuration(duration), nil +} + +func stringForDuration(duration time.Duration) string { + if duration.Hours() < 24 { + if duration.Hours() >= 1 { + return localizedStringFor(HoursAgo, int(round(duration.Hours()))); + } else if duration.Minutes() >= 1 { + return localizedStringFor(MinutesAgo, int(round(duration.Minutes()))); + } else { + return localizedStringFor(SecondsAgo, int(round(duration.Seconds()))); + } + } else { + if duration.Hours() >= 8760 { + years := duration.Hours() / 8760 + return localizedStringFor(YearsAgo, int(years)); + } else if duration.Hours() >= 730 { + months := duration.Hours() / 730 + return localizedStringFor(MonthsAgo, int(months)); + } else if duration.Hours() >= 168 { + weeks := duration.Hours() / 168 + return localizedStringFor(WeeksAgo, int(weeks)); + } else { + days := duration.Hours() / 24 + return localizedStringFor(DaysAgo, int(days)); + } + } +} + +func round(f float64) float64 { + return math.Floor(f + .5) +} + +func localizedStringFor(valueType DateAgoValues, value int) string { + + switch valueType { + case YearsAgo: + if value >= 2 { + return fmt.Sprintf("%d years ago", value); + } else { + return "Last year"; + } + case MonthsAgo: + if value >= 2 { + return fmt.Sprintf("%d months ago", value); + } else { + return "Last month"; + } + case WeeksAgo: + if value >= 2 { + return fmt.Sprintf("%d weeks ago", value); + } else { + return "Last week"; + } + case DaysAgo: + if value >= 2 { + return fmt.Sprintf("%d days ago", value); + } else { + return "Yesterday"; + } + case HoursAgo: + if value >= 2 { + return fmt.Sprintf("%d hours ago", value); + } else { + return "An hour ago"; + } + case MinutesAgo: + if value >= 2 { + return fmt.Sprintf("%d minutes ago", value); + } else { + return "A minute ago"; + } + case SecondsAgo: + if value >= 2 { + return fmt.Sprintf("%d seconds ago", value); + } else { + return "Just now"; + } + } + return ""; +} diff --git a/vendor/github.com/ararog/timeago/timeago_test.go b/vendor/github.com/ararog/timeago/timeago_test.go new file mode 100644 index 00000000..6042f23a --- /dev/null +++ b/vendor/github.com/ararog/timeago/timeago_test.go @@ -0,0 +1,79 @@ +package timeago + +import ( + "time" +) + +import "testing" + +func check(t *testing.T, d time.Duration, result string) { + start := time.Now() + end := time.Now().Add(d) + got, error := TimeAgoWithTime(start, end) + if error == nil { + if got != result { + t.Errorf("Wrong result: %s", got) + } + } +} + +func TestThreeHoursAgo(t *testing.T) { + d, error := time.ParseDuration("-3h") + if error == nil { + check(t, d, "3 hours ago") + } +} + +func TestAnHourAgo(t *testing.T) { + d, error := time.ParseDuration("-1.5h") + if error == nil { + check(t, d, "An hour ago") + } +} + +func TestThreeMinutesAgo(t *testing.T) { + d, error := time.ParseDuration("-3m") + if error == nil { + check(t, d, "3 minutes ago") + } +} + +func TestAMinuteAgo(t *testing.T) { + d, error := time.ParseDuration("-1.2m") + if error == nil { + check(t, d, "A minute ago") + } +} + +func TestJustNow(t *testing.T) { + d, error := time.ParseDuration("-1.2s") + if error == nil { + check(t, d, "Just now") + } +} + +func TestFromNow(t *testing.T) { + d, error := time.ParseDuration("-1.2m") + if error == nil { + end := time.Now().Add(d) + got, err := TimeAgoFromNowWithTime(end) + if err == nil { + if got != "A minute ago" { + t.Errorf("Wrong result: %s", got) + } + } + } +} + +func TestFromNowWithString(t *testing.T) { + d, error := time.ParseDuration("-1.2m") + if error == nil { + end := time.Now().Add(d) + got, err := TimeAgoFromNowWithString(time.RFC3339, end.Format(time.RFC3339)) + if err == nil { + if got != "A minute ago" { + t.Errorf("Wrong result: %s", got) + } + } + } +} diff --git a/vendor/github.com/mattn/go-runewidth/.travis.yml b/vendor/github.com/mattn/go-runewidth/.travis.yml new file mode 100644 index 00000000..5c9c2a30 --- /dev/null +++ b/vendor/github.com/mattn/go-runewidth/.travis.yml @@ -0,0 +1,8 @@ +language: go +go: + - tip +before_install: + - go get github.com/mattn/goveralls + - go get golang.org/x/tools/cmd/cover +script: + - $HOME/gopath/bin/goveralls -repotoken lAKAWPzcGsD3A8yBX3BGGtRUdJ6CaGERL diff --git a/vendor/github.com/mattn/go-runewidth/LICENSE b/vendor/github.com/mattn/go-runewidth/LICENSE new file mode 100644 index 00000000..91b5cef3 --- /dev/null +++ b/vendor/github.com/mattn/go-runewidth/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2016 Yasuhiro Matsumoto + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/mattn/go-runewidth/README.mkd b/vendor/github.com/mattn/go-runewidth/README.mkd new file mode 100644 index 00000000..66663a94 --- /dev/null +++ b/vendor/github.com/mattn/go-runewidth/README.mkd @@ -0,0 +1,27 @@ +go-runewidth +============ + +[![Build Status](https://travis-ci.org/mattn/go-runewidth.png?branch=master)](https://travis-ci.org/mattn/go-runewidth) +[![Coverage Status](https://coveralls.io/repos/mattn/go-runewidth/badge.png?branch=HEAD)](https://coveralls.io/r/mattn/go-runewidth?branch=HEAD) +[![GoDoc](https://godoc.org/github.com/mattn/go-runewidth?status.svg)](http://godoc.org/github.com/mattn/go-runewidth) +[![Go Report Card](https://goreportcard.com/badge/github.com/mattn/go-runewidth)](https://goreportcard.com/report/github.com/mattn/go-runewidth) + +Provides functions to get fixed width of the character or string. + +Usage +----- + +```go +runewidth.StringWidth("つのだ☆HIRO") == 12 +``` + + +Author +------ + +Yasuhiro Matsumoto + +License +------- + +under the MIT License: http://mattn.mit-license.org/2013 diff --git a/vendor/github.com/mattn/go-runewidth/runewidth.go b/vendor/github.com/mattn/go-runewidth/runewidth.go new file mode 100644 index 00000000..2164497a --- /dev/null +++ b/vendor/github.com/mattn/go-runewidth/runewidth.go @@ -0,0 +1,1223 @@ +package runewidth + +var ( + // EastAsianWidth will be set true if the current locale is CJK + EastAsianWidth = IsEastAsian() + + // DefaultCondition is a condition in current locale + DefaultCondition = &Condition{EastAsianWidth} +) + +type interval struct { + first rune + last rune +} + +type table []interval + +func inTables(r rune, ts ...table) bool { + for _, t := range ts { + if inTable(r, t) { + return true + } + } + return false +} + +func inTable(r rune, t table) bool { + // func (t table) IncludesRune(r rune) bool { + if r < t[0].first { + return false + } + + bot := 0 + top := len(t) - 1 + for top >= bot { + mid := (bot + top) / 2 + + switch { + case t[mid].last < r: + bot = mid + 1 + case t[mid].first > r: + top = mid - 1 + default: + return true + } + } + + return false +} + +var private = table{ + {0x00E000, 0x00F8FF}, {0x0F0000, 0x0FFFFD}, {0x100000, 0x10FFFD}, +} + +var nonprint = table{ + {0x0000, 0x001F}, {0x007F, 0x009F}, {0x00AD, 0x00AD}, + {0x070F, 0x070F}, {0x180B, 0x180E}, {0x200B, 0x200F}, + {0x202A, 0x202E}, {0x206A, 0x206F}, {0xD800, 0xDFFF}, + {0xFEFF, 0xFEFF}, {0xFFF9, 0xFFFB}, {0xFFFE, 0xFFFF}, +} + +var combining = table{ + {0x0300, 0x036F}, {0x0483, 0x0489}, {0x0591, 0x05BD}, + {0x05BF, 0x05BF}, {0x05C1, 0x05C2}, {0x05C4, 0x05C5}, + {0x05C7, 0x05C7}, {0x0610, 0x061A}, {0x064B, 0x065F}, + {0x0670, 0x0670}, {0x06D6, 0x06DC}, {0x06DF, 0x06E4}, + {0x06E7, 0x06E8}, {0x06EA, 0x06ED}, {0x0711, 0x0711}, + {0x0730, 0x074A}, {0x07A6, 0x07B0}, {0x07EB, 0x07F3}, + {0x0816, 0x0819}, {0x081B, 0x0823}, {0x0825, 0x0827}, + {0x0829, 0x082D}, {0x0859, 0x085B}, {0x08D4, 0x08E1}, + {0x08E3, 0x0903}, {0x093A, 0x093C}, {0x093E, 0x094F}, + {0x0951, 0x0957}, {0x0962, 0x0963}, {0x0981, 0x0983}, + {0x09BC, 0x09BC}, {0x09BE, 0x09C4}, {0x09C7, 0x09C8}, + {0x09CB, 0x09CD}, {0x09D7, 0x09D7}, {0x09E2, 0x09E3}, + {0x0A01, 0x0A03}, {0x0A3C, 0x0A3C}, {0x0A3E, 0x0A42}, + {0x0A47, 0x0A48}, {0x0A4B, 0x0A4D}, {0x0A51, 0x0A51}, + {0x0A70, 0x0A71}, {0x0A75, 0x0A75}, {0x0A81, 0x0A83}, + {0x0ABC, 0x0ABC}, {0x0ABE, 0x0AC5}, {0x0AC7, 0x0AC9}, + {0x0ACB, 0x0ACD}, {0x0AE2, 0x0AE3}, {0x0B01, 0x0B03}, + {0x0B3C, 0x0B3C}, {0x0B3E, 0x0B44}, {0x0B47, 0x0B48}, + {0x0B4B, 0x0B4D}, {0x0B56, 0x0B57}, {0x0B62, 0x0B63}, + {0x0B82, 0x0B82}, {0x0BBE, 0x0BC2}, {0x0BC6, 0x0BC8}, + {0x0BCA, 0x0BCD}, {0x0BD7, 0x0BD7}, {0x0C00, 0x0C03}, + {0x0C3E, 0x0C44}, {0x0C46, 0x0C48}, {0x0C4A, 0x0C4D}, + {0x0C55, 0x0C56}, {0x0C62, 0x0C63}, {0x0C81, 0x0C83}, + {0x0CBC, 0x0CBC}, {0x0CBE, 0x0CC4}, {0x0CC6, 0x0CC8}, + {0x0CCA, 0x0CCD}, {0x0CD5, 0x0CD6}, {0x0CE2, 0x0CE3}, + {0x0D01, 0x0D03}, {0x0D3E, 0x0D44}, {0x0D46, 0x0D48}, + {0x0D4A, 0x0D4D}, {0x0D57, 0x0D57}, {0x0D62, 0x0D63}, + {0x0D82, 0x0D83}, {0x0DCA, 0x0DCA}, {0x0DCF, 0x0DD4}, + {0x0DD6, 0x0DD6}, {0x0DD8, 0x0DDF}, {0x0DF2, 0x0DF3}, + {0x0E31, 0x0E31}, {0x0E34, 0x0E3A}, {0x0E47, 0x0E4E}, + {0x0EB1, 0x0EB1}, {0x0EB4, 0x0EB9}, {0x0EBB, 0x0EBC}, + {0x0EC8, 0x0ECD}, {0x0F18, 0x0F19}, {0x0F35, 0x0F35}, + {0x0F37, 0x0F37}, {0x0F39, 0x0F39}, {0x0F3E, 0x0F3F}, + {0x0F71, 0x0F84}, {0x0F86, 0x0F87}, {0x0F8D, 0x0F97}, + {0x0F99, 0x0FBC}, {0x0FC6, 0x0FC6}, {0x102B, 0x103E}, + {0x1056, 0x1059}, {0x105E, 0x1060}, {0x1062, 0x1064}, + {0x1067, 0x106D}, {0x1071, 0x1074}, {0x1082, 0x108D}, + {0x108F, 0x108F}, {0x109A, 0x109D}, {0x135D, 0x135F}, + {0x1712, 0x1714}, {0x1732, 0x1734}, {0x1752, 0x1753}, + {0x1772, 0x1773}, {0x17B4, 0x17D3}, {0x17DD, 0x17DD}, + {0x180B, 0x180D}, {0x1885, 0x1886}, {0x18A9, 0x18A9}, + {0x1920, 0x192B}, {0x1930, 0x193B}, {0x1A17, 0x1A1B}, + {0x1A55, 0x1A5E}, {0x1A60, 0x1A7C}, {0x1A7F, 0x1A7F}, + {0x1AB0, 0x1ABE}, {0x1B00, 0x1B04}, {0x1B34, 0x1B44}, + {0x1B6B, 0x1B73}, {0x1B80, 0x1B82}, {0x1BA1, 0x1BAD}, + {0x1BE6, 0x1BF3}, {0x1C24, 0x1C37}, {0x1CD0, 0x1CD2}, + {0x1CD4, 0x1CE8}, {0x1CED, 0x1CED}, {0x1CF2, 0x1CF4}, + {0x1CF8, 0x1CF9}, {0x1DC0, 0x1DF5}, {0x1DFB, 0x1DFF}, + {0x20D0, 0x20F0}, {0x2CEF, 0x2CF1}, {0x2D7F, 0x2D7F}, + {0x2DE0, 0x2DFF}, {0x302A, 0x302F}, {0x3099, 0x309A}, + {0xA66F, 0xA672}, {0xA674, 0xA67D}, {0xA69E, 0xA69F}, + {0xA6F0, 0xA6F1}, {0xA802, 0xA802}, {0xA806, 0xA806}, + {0xA80B, 0xA80B}, {0xA823, 0xA827}, {0xA880, 0xA881}, + {0xA8B4, 0xA8C5}, {0xA8E0, 0xA8F1}, {0xA926, 0xA92D}, + {0xA947, 0xA953}, {0xA980, 0xA983}, {0xA9B3, 0xA9C0}, + {0xA9E5, 0xA9E5}, {0xAA29, 0xAA36}, {0xAA43, 0xAA43}, + {0xAA4C, 0xAA4D}, {0xAA7B, 0xAA7D}, {0xAAB0, 0xAAB0}, + {0xAAB2, 0xAAB4}, {0xAAB7, 0xAAB8}, {0xAABE, 0xAABF}, + {0xAAC1, 0xAAC1}, {0xAAEB, 0xAAEF}, {0xAAF5, 0xAAF6}, + {0xABE3, 0xABEA}, {0xABEC, 0xABED}, {0xFB1E, 0xFB1E}, + {0xFE00, 0xFE0F}, {0xFE20, 0xFE2F}, {0x101FD, 0x101FD}, + {0x102E0, 0x102E0}, {0x10376, 0x1037A}, {0x10A01, 0x10A03}, + {0x10A05, 0x10A06}, {0x10A0C, 0x10A0F}, {0x10A38, 0x10A3A}, + {0x10A3F, 0x10A3F}, {0x10AE5, 0x10AE6}, {0x11000, 0x11002}, + {0x11038, 0x11046}, {0x1107F, 0x11082}, {0x110B0, 0x110BA}, + {0x11100, 0x11102}, {0x11127, 0x11134}, {0x11173, 0x11173}, + {0x11180, 0x11182}, {0x111B3, 0x111C0}, {0x111CA, 0x111CC}, + {0x1122C, 0x11237}, {0x1123E, 0x1123E}, {0x112DF, 0x112EA}, + {0x11300, 0x11303}, {0x1133C, 0x1133C}, {0x1133E, 0x11344}, + {0x11347, 0x11348}, {0x1134B, 0x1134D}, {0x11357, 0x11357}, + {0x11362, 0x11363}, {0x11366, 0x1136C}, {0x11370, 0x11374}, + {0x11435, 0x11446}, {0x114B0, 0x114C3}, {0x115AF, 0x115B5}, + {0x115B8, 0x115C0}, {0x115DC, 0x115DD}, {0x11630, 0x11640}, + {0x116AB, 0x116B7}, {0x1171D, 0x1172B}, {0x11C2F, 0x11C36}, + {0x11C38, 0x11C3F}, {0x11C92, 0x11CA7}, {0x11CA9, 0x11CB6}, + {0x16AF0, 0x16AF4}, {0x16B30, 0x16B36}, {0x16F51, 0x16F7E}, + {0x16F8F, 0x16F92}, {0x1BC9D, 0x1BC9E}, {0x1D165, 0x1D169}, + {0x1D16D, 0x1D172}, {0x1D17B, 0x1D182}, {0x1D185, 0x1D18B}, + {0x1D1AA, 0x1D1AD}, {0x1D242, 0x1D244}, {0x1DA00, 0x1DA36}, + {0x1DA3B, 0x1DA6C}, {0x1DA75, 0x1DA75}, {0x1DA84, 0x1DA84}, + {0x1DA9B, 0x1DA9F}, {0x1DAA1, 0x1DAAF}, {0x1E000, 0x1E006}, + {0x1E008, 0x1E018}, {0x1E01B, 0x1E021}, {0x1E023, 0x1E024}, + {0x1E026, 0x1E02A}, {0x1E8D0, 0x1E8D6}, {0x1E944, 0x1E94A}, + {0xE0100, 0xE01EF}, +} + +var doublewidth = table{ + {0x1100, 0x115F}, {0x231A, 0x231B}, {0x2329, 0x232A}, + {0x23E9, 0x23EC}, {0x23F0, 0x23F0}, {0x23F3, 0x23F3}, + {0x25FD, 0x25FE}, {0x2614, 0x2615}, {0x2648, 0x2653}, + {0x267F, 0x267F}, {0x2693, 0x2693}, {0x26A1, 0x26A1}, + {0x26AA, 0x26AB}, {0x26BD, 0x26BE}, {0x26C4, 0x26C5}, + {0x26CE, 0x26CE}, {0x26D4, 0x26D4}, {0x26EA, 0x26EA}, + {0x26F2, 0x26F3}, {0x26F5, 0x26F5}, {0x26FA, 0x26FA}, + {0x26FD, 0x26FD}, {0x2705, 0x2705}, {0x270A, 0x270B}, + {0x2728, 0x2728}, {0x274C, 0x274C}, {0x274E, 0x274E}, + {0x2753, 0x2755}, {0x2757, 0x2757}, {0x2795, 0x2797}, + {0x27B0, 0x27B0}, {0x27BF, 0x27BF}, {0x2B1B, 0x2B1C}, + {0x2B50, 0x2B50}, {0x2B55, 0x2B55}, {0x2E80, 0x2E99}, + {0x2E9B, 0x2EF3}, {0x2F00, 0x2FD5}, {0x2FF0, 0x2FFB}, + {0x3000, 0x303E}, {0x3041, 0x3096}, {0x3099, 0x30FF}, + {0x3105, 0x312D}, {0x3131, 0x318E}, {0x3190, 0x31BA}, + {0x31C0, 0x31E3}, {0x31F0, 0x321E}, {0x3220, 0x3247}, + {0x3250, 0x32FE}, {0x3300, 0x4DBF}, {0x4E00, 0xA48C}, + {0xA490, 0xA4C6}, {0xA960, 0xA97C}, {0xAC00, 0xD7A3}, + {0xF900, 0xFAFF}, {0xFE10, 0xFE19}, {0xFE30, 0xFE52}, + {0xFE54, 0xFE66}, {0xFE68, 0xFE6B}, {0xFF01, 0xFF60}, + {0xFFE0, 0xFFE6}, {0x16FE0, 0x16FE0}, {0x17000, 0x187EC}, + {0x18800, 0x18AF2}, {0x1B000, 0x1B001}, {0x1F004, 0x1F004}, + {0x1F0CF, 0x1F0CF}, {0x1F18E, 0x1F18E}, {0x1F191, 0x1F19A}, + {0x1F200, 0x1F202}, {0x1F210, 0x1F23B}, {0x1F240, 0x1F248}, + {0x1F250, 0x1F251}, {0x1F300, 0x1F320}, {0x1F32D, 0x1F335}, + {0x1F337, 0x1F37C}, {0x1F37E, 0x1F393}, {0x1F3A0, 0x1F3CA}, + {0x1F3CF, 0x1F3D3}, {0x1F3E0, 0x1F3F0}, {0x1F3F4, 0x1F3F4}, + {0x1F3F8, 0x1F43E}, {0x1F440, 0x1F440}, {0x1F442, 0x1F4FC}, + {0x1F4FF, 0x1F53D}, {0x1F54B, 0x1F54E}, {0x1F550, 0x1F567}, + {0x1F57A, 0x1F57A}, {0x1F595, 0x1F596}, {0x1F5A4, 0x1F5A4}, + {0x1F5FB, 0x1F64F}, {0x1F680, 0x1F6C5}, {0x1F6CC, 0x1F6CC}, + {0x1F6D0, 0x1F6D2}, {0x1F6EB, 0x1F6EC}, {0x1F6F4, 0x1F6F6}, + {0x1F910, 0x1F91E}, {0x1F920, 0x1F927}, {0x1F930, 0x1F930}, + {0x1F933, 0x1F93E}, {0x1F940, 0x1F94B}, {0x1F950, 0x1F95E}, + {0x1F980, 0x1F991}, {0x1F9C0, 0x1F9C0}, {0x20000, 0x2FFFD}, + {0x30000, 0x3FFFD}, +} + +var ambiguous = table{ + {0x00A1, 0x00A1}, {0x00A4, 0x00A4}, {0x00A7, 0x00A8}, + {0x00AA, 0x00AA}, {0x00AD, 0x00AE}, {0x00B0, 0x00B4}, + {0x00B6, 0x00BA}, {0x00BC, 0x00BF}, {0x00C6, 0x00C6}, + {0x00D0, 0x00D0}, {0x00D7, 0x00D8}, {0x00DE, 0x00E1}, + {0x00E6, 0x00E6}, {0x00E8, 0x00EA}, {0x00EC, 0x00ED}, + {0x00F0, 0x00F0}, {0x00F2, 0x00F3}, {0x00F7, 0x00FA}, + {0x00FC, 0x00FC}, {0x00FE, 0x00FE}, {0x0101, 0x0101}, + {0x0111, 0x0111}, {0x0113, 0x0113}, {0x011B, 0x011B}, + {0x0126, 0x0127}, {0x012B, 0x012B}, {0x0131, 0x0133}, + {0x0138, 0x0138}, {0x013F, 0x0142}, {0x0144, 0x0144}, + {0x0148, 0x014B}, {0x014D, 0x014D}, {0x0152, 0x0153}, + {0x0166, 0x0167}, {0x016B, 0x016B}, {0x01CE, 0x01CE}, + {0x01D0, 0x01D0}, {0x01D2, 0x01D2}, {0x01D4, 0x01D4}, + {0x01D6, 0x01D6}, {0x01D8, 0x01D8}, {0x01DA, 0x01DA}, + {0x01DC, 0x01DC}, {0x0251, 0x0251}, {0x0261, 0x0261}, + {0x02C4, 0x02C4}, {0x02C7, 0x02C7}, {0x02C9, 0x02CB}, + {0x02CD, 0x02CD}, {0x02D0, 0x02D0}, {0x02D8, 0x02DB}, + {0x02DD, 0x02DD}, {0x02DF, 0x02DF}, {0x0300, 0x036F}, + {0x0391, 0x03A1}, {0x03A3, 0x03A9}, {0x03B1, 0x03C1}, + {0x03C3, 0x03C9}, {0x0401, 0x0401}, {0x0410, 0x044F}, + {0x0451, 0x0451}, {0x2010, 0x2010}, {0x2013, 0x2016}, + {0x2018, 0x2019}, {0x201C, 0x201D}, {0x2020, 0x2022}, + {0x2024, 0x2027}, {0x2030, 0x2030}, {0x2032, 0x2033}, + {0x2035, 0x2035}, {0x203B, 0x203B}, {0x203E, 0x203E}, + {0x2074, 0x2074}, {0x207F, 0x207F}, {0x2081, 0x2084}, + {0x20AC, 0x20AC}, {0x2103, 0x2103}, {0x2105, 0x2105}, + {0x2109, 0x2109}, {0x2113, 0x2113}, {0x2116, 0x2116}, + {0x2121, 0x2122}, {0x2126, 0x2126}, {0x212B, 0x212B}, + {0x2153, 0x2154}, {0x215B, 0x215E}, {0x2160, 0x216B}, + {0x2170, 0x2179}, {0x2189, 0x2189}, {0x2190, 0x2199}, + {0x21B8, 0x21B9}, {0x21D2, 0x21D2}, {0x21D4, 0x21D4}, + {0x21E7, 0x21E7}, {0x2200, 0x2200}, {0x2202, 0x2203}, + {0x2207, 0x2208}, {0x220B, 0x220B}, {0x220F, 0x220F}, + {0x2211, 0x2211}, {0x2215, 0x2215}, {0x221A, 0x221A}, + {0x221D, 0x2220}, {0x2223, 0x2223}, {0x2225, 0x2225}, + {0x2227, 0x222C}, {0x222E, 0x222E}, {0x2234, 0x2237}, + {0x223C, 0x223D}, {0x2248, 0x2248}, {0x224C, 0x224C}, + {0x2252, 0x2252}, {0x2260, 0x2261}, {0x2264, 0x2267}, + {0x226A, 0x226B}, {0x226E, 0x226F}, {0x2282, 0x2283}, + {0x2286, 0x2287}, {0x2295, 0x2295}, {0x2299, 0x2299}, + {0x22A5, 0x22A5}, {0x22BF, 0x22BF}, {0x2312, 0x2312}, + {0x2460, 0x24E9}, {0x24EB, 0x254B}, {0x2550, 0x2573}, + {0x2580, 0x258F}, {0x2592, 0x2595}, {0x25A0, 0x25A1}, + {0x25A3, 0x25A9}, {0x25B2, 0x25B3}, {0x25B6, 0x25B7}, + {0x25BC, 0x25BD}, {0x25C0, 0x25C1}, {0x25C6, 0x25C8}, + {0x25CB, 0x25CB}, {0x25CE, 0x25D1}, {0x25E2, 0x25E5}, + {0x25EF, 0x25EF}, {0x2605, 0x2606}, {0x2609, 0x2609}, + {0x260E, 0x260F}, {0x261C, 0x261C}, {0x261E, 0x261E}, + {0x2640, 0x2640}, {0x2642, 0x2642}, {0x2660, 0x2661}, + {0x2663, 0x2665}, {0x2667, 0x266A}, {0x266C, 0x266D}, + {0x266F, 0x266F}, {0x269E, 0x269F}, {0x26BF, 0x26BF}, + {0x26C6, 0x26CD}, {0x26CF, 0x26D3}, {0x26D5, 0x26E1}, + {0x26E3, 0x26E3}, {0x26E8, 0x26E9}, {0x26EB, 0x26F1}, + {0x26F4, 0x26F4}, {0x26F6, 0x26F9}, {0x26FB, 0x26FC}, + {0x26FE, 0x26FF}, {0x273D, 0x273D}, {0x2776, 0x277F}, + {0x2B56, 0x2B59}, {0x3248, 0x324F}, {0xE000, 0xF8FF}, + {0xFE00, 0xFE0F}, {0xFFFD, 0xFFFD}, {0x1F100, 0x1F10A}, + {0x1F110, 0x1F12D}, {0x1F130, 0x1F169}, {0x1F170, 0x1F18D}, + {0x1F18F, 0x1F190}, {0x1F19B, 0x1F1AC}, {0xE0100, 0xE01EF}, + {0xF0000, 0xFFFFD}, {0x100000, 0x10FFFD}, +} + +var emoji = table{ + {0x1F1E6, 0x1F1FF}, {0x1F321, 0x1F321}, {0x1F324, 0x1F32C}, + {0x1F336, 0x1F336}, {0x1F37D, 0x1F37D}, {0x1F396, 0x1F397}, + {0x1F399, 0x1F39B}, {0x1F39E, 0x1F39F}, {0x1F3CB, 0x1F3CE}, + {0x1F3D4, 0x1F3DF}, {0x1F3F3, 0x1F3F5}, {0x1F3F7, 0x1F3F7}, + {0x1F43F, 0x1F43F}, {0x1F441, 0x1F441}, {0x1F4FD, 0x1F4FD}, + {0x1F549, 0x1F54A}, {0x1F56F, 0x1F570}, {0x1F573, 0x1F579}, + {0x1F587, 0x1F587}, {0x1F58A, 0x1F58D}, {0x1F590, 0x1F590}, + {0x1F5A5, 0x1F5A5}, {0x1F5A8, 0x1F5A8}, {0x1F5B1, 0x1F5B2}, + {0x1F5BC, 0x1F5BC}, {0x1F5C2, 0x1F5C4}, {0x1F5D1, 0x1F5D3}, + {0x1F5DC, 0x1F5DE}, {0x1F5E1, 0x1F5E1}, {0x1F5E3, 0x1F5E3}, + {0x1F5E8, 0x1F5E8}, {0x1F5EF, 0x1F5EF}, {0x1F5F3, 0x1F5F3}, + {0x1F5FA, 0x1F5FA}, {0x1F6CB, 0x1F6CF}, {0x1F6E0, 0x1F6E5}, + {0x1F6E9, 0x1F6E9}, {0x1F6F0, 0x1F6F0}, {0x1F6F3, 0x1F6F3}, +} + +var notassigned = table{ + {0x0378, 0x0379}, {0x0380, 0x0383}, {0x038B, 0x038B}, + {0x038D, 0x038D}, {0x03A2, 0x03A2}, {0x0530, 0x0530}, + {0x0557, 0x0558}, {0x0560, 0x0560}, {0x0588, 0x0588}, + {0x058B, 0x058C}, {0x0590, 0x0590}, {0x05C8, 0x05CF}, + {0x05EB, 0x05EF}, {0x05F5, 0x05FF}, {0x061D, 0x061D}, + {0x070E, 0x070E}, {0x074B, 0x074C}, {0x07B2, 0x07BF}, + {0x07FB, 0x07FF}, {0x082E, 0x082F}, {0x083F, 0x083F}, + {0x085C, 0x085D}, {0x085F, 0x089F}, {0x08B5, 0x08B5}, + {0x08BE, 0x08D3}, {0x0984, 0x0984}, {0x098D, 0x098E}, + {0x0991, 0x0992}, {0x09A9, 0x09A9}, {0x09B1, 0x09B1}, + {0x09B3, 0x09B5}, {0x09BA, 0x09BB}, {0x09C5, 0x09C6}, + {0x09C9, 0x09CA}, {0x09CF, 0x09D6}, {0x09D8, 0x09DB}, + {0x09DE, 0x09DE}, {0x09E4, 0x09E5}, {0x09FC, 0x0A00}, + {0x0A04, 0x0A04}, {0x0A0B, 0x0A0E}, {0x0A11, 0x0A12}, + {0x0A29, 0x0A29}, {0x0A31, 0x0A31}, {0x0A34, 0x0A34}, + {0x0A37, 0x0A37}, {0x0A3A, 0x0A3B}, {0x0A3D, 0x0A3D}, + {0x0A43, 0x0A46}, {0x0A49, 0x0A4A}, {0x0A4E, 0x0A50}, + {0x0A52, 0x0A58}, {0x0A5D, 0x0A5D}, {0x0A5F, 0x0A65}, + {0x0A76, 0x0A80}, {0x0A84, 0x0A84}, {0x0A8E, 0x0A8E}, + {0x0A92, 0x0A92}, {0x0AA9, 0x0AA9}, {0x0AB1, 0x0AB1}, + {0x0AB4, 0x0AB4}, {0x0ABA, 0x0ABB}, {0x0AC6, 0x0AC6}, + {0x0ACA, 0x0ACA}, {0x0ACE, 0x0ACF}, {0x0AD1, 0x0ADF}, + {0x0AE4, 0x0AE5}, {0x0AF2, 0x0AF8}, {0x0AFA, 0x0B00}, + {0x0B04, 0x0B04}, {0x0B0D, 0x0B0E}, {0x0B11, 0x0B12}, + {0x0B29, 0x0B29}, {0x0B31, 0x0B31}, {0x0B34, 0x0B34}, + {0x0B3A, 0x0B3B}, {0x0B45, 0x0B46}, {0x0B49, 0x0B4A}, + {0x0B4E, 0x0B55}, {0x0B58, 0x0B5B}, {0x0B5E, 0x0B5E}, + {0x0B64, 0x0B65}, {0x0B78, 0x0B81}, {0x0B84, 0x0B84}, + {0x0B8B, 0x0B8D}, {0x0B91, 0x0B91}, {0x0B96, 0x0B98}, + {0x0B9B, 0x0B9B}, {0x0B9D, 0x0B9D}, {0x0BA0, 0x0BA2}, + {0x0BA5, 0x0BA7}, {0x0BAB, 0x0BAD}, {0x0BBA, 0x0BBD}, + {0x0BC3, 0x0BC5}, {0x0BC9, 0x0BC9}, {0x0BCE, 0x0BCF}, + {0x0BD1, 0x0BD6}, {0x0BD8, 0x0BE5}, {0x0BFB, 0x0BFF}, + {0x0C04, 0x0C04}, {0x0C0D, 0x0C0D}, {0x0C11, 0x0C11}, + {0x0C29, 0x0C29}, {0x0C3A, 0x0C3C}, {0x0C45, 0x0C45}, + {0x0C49, 0x0C49}, {0x0C4E, 0x0C54}, {0x0C57, 0x0C57}, + {0x0C5B, 0x0C5F}, {0x0C64, 0x0C65}, {0x0C70, 0x0C77}, + {0x0C84, 0x0C84}, {0x0C8D, 0x0C8D}, {0x0C91, 0x0C91}, + {0x0CA9, 0x0CA9}, {0x0CB4, 0x0CB4}, {0x0CBA, 0x0CBB}, + {0x0CC5, 0x0CC5}, {0x0CC9, 0x0CC9}, {0x0CCE, 0x0CD4}, + {0x0CD7, 0x0CDD}, {0x0CDF, 0x0CDF}, {0x0CE4, 0x0CE5}, + {0x0CF0, 0x0CF0}, {0x0CF3, 0x0D00}, {0x0D04, 0x0D04}, + {0x0D0D, 0x0D0D}, {0x0D11, 0x0D11}, {0x0D3B, 0x0D3C}, + {0x0D45, 0x0D45}, {0x0D49, 0x0D49}, {0x0D50, 0x0D53}, + {0x0D64, 0x0D65}, {0x0D80, 0x0D81}, {0x0D84, 0x0D84}, + {0x0D97, 0x0D99}, {0x0DB2, 0x0DB2}, {0x0DBC, 0x0DBC}, + {0x0DBE, 0x0DBF}, {0x0DC7, 0x0DC9}, {0x0DCB, 0x0DCE}, + {0x0DD5, 0x0DD5}, {0x0DD7, 0x0DD7}, {0x0DE0, 0x0DE5}, + {0x0DF0, 0x0DF1}, {0x0DF5, 0x0E00}, {0x0E3B, 0x0E3E}, + {0x0E5C, 0x0E80}, {0x0E83, 0x0E83}, {0x0E85, 0x0E86}, + {0x0E89, 0x0E89}, {0x0E8B, 0x0E8C}, {0x0E8E, 0x0E93}, + {0x0E98, 0x0E98}, {0x0EA0, 0x0EA0}, {0x0EA4, 0x0EA4}, + {0x0EA6, 0x0EA6}, {0x0EA8, 0x0EA9}, {0x0EAC, 0x0EAC}, + {0x0EBA, 0x0EBA}, {0x0EBE, 0x0EBF}, {0x0EC5, 0x0EC5}, + {0x0EC7, 0x0EC7}, {0x0ECE, 0x0ECF}, {0x0EDA, 0x0EDB}, + {0x0EE0, 0x0EFF}, {0x0F48, 0x0F48}, {0x0F6D, 0x0F70}, + {0x0F98, 0x0F98}, {0x0FBD, 0x0FBD}, {0x0FCD, 0x0FCD}, + {0x0FDB, 0x0FFF}, {0x10C6, 0x10C6}, {0x10C8, 0x10CC}, + {0x10CE, 0x10CF}, {0x1249, 0x1249}, {0x124E, 0x124F}, + {0x1257, 0x1257}, {0x1259, 0x1259}, {0x125E, 0x125F}, + {0x1289, 0x1289}, {0x128E, 0x128F}, {0x12B1, 0x12B1}, + {0x12B6, 0x12B7}, {0x12BF, 0x12BF}, {0x12C1, 0x12C1}, + {0x12C6, 0x12C7}, {0x12D7, 0x12D7}, {0x1311, 0x1311}, + {0x1316, 0x1317}, {0x135B, 0x135C}, {0x137D, 0x137F}, + {0x139A, 0x139F}, {0x13F6, 0x13F7}, {0x13FE, 0x13FF}, + {0x169D, 0x169F}, {0x16F9, 0x16FF}, {0x170D, 0x170D}, + {0x1715, 0x171F}, {0x1737, 0x173F}, {0x1754, 0x175F}, + {0x176D, 0x176D}, {0x1771, 0x1771}, {0x1774, 0x177F}, + {0x17DE, 0x17DF}, {0x17EA, 0x17EF}, {0x17FA, 0x17FF}, + {0x180F, 0x180F}, {0x181A, 0x181F}, {0x1878, 0x187F}, + {0x18AB, 0x18AF}, {0x18F6, 0x18FF}, {0x191F, 0x191F}, + {0x192C, 0x192F}, {0x193C, 0x193F}, {0x1941, 0x1943}, + {0x196E, 0x196F}, {0x1975, 0x197F}, {0x19AC, 0x19AF}, + {0x19CA, 0x19CF}, {0x19DB, 0x19DD}, {0x1A1C, 0x1A1D}, + {0x1A5F, 0x1A5F}, {0x1A7D, 0x1A7E}, {0x1A8A, 0x1A8F}, + {0x1A9A, 0x1A9F}, {0x1AAE, 0x1AAF}, {0x1ABF, 0x1AFF}, + {0x1B4C, 0x1B4F}, {0x1B7D, 0x1B7F}, {0x1BF4, 0x1BFB}, + {0x1C38, 0x1C3A}, {0x1C4A, 0x1C4C}, {0x1C89, 0x1CBF}, + {0x1CC8, 0x1CCF}, {0x1CF7, 0x1CF7}, {0x1CFA, 0x1CFF}, + {0x1DF6, 0x1DFA}, {0x1F16, 0x1F17}, {0x1F1E, 0x1F1F}, + {0x1F46, 0x1F47}, {0x1F4E, 0x1F4F}, {0x1F58, 0x1F58}, + {0x1F5A, 0x1F5A}, {0x1F5C, 0x1F5C}, {0x1F5E, 0x1F5E}, + {0x1F7E, 0x1F7F}, {0x1FB5, 0x1FB5}, {0x1FC5, 0x1FC5}, + {0x1FD4, 0x1FD5}, {0x1FDC, 0x1FDC}, {0x1FF0, 0x1FF1}, + {0x1FF5, 0x1FF5}, {0x1FFF, 0x1FFF}, {0x2065, 0x2065}, + {0x2072, 0x2073}, {0x208F, 0x208F}, {0x209D, 0x209F}, + {0x20BF, 0x20CF}, {0x20F1, 0x20FF}, {0x218C, 0x218F}, + {0x23FF, 0x23FF}, {0x2427, 0x243F}, {0x244B, 0x245F}, + {0x2B74, 0x2B75}, {0x2B96, 0x2B97}, {0x2BBA, 0x2BBC}, + {0x2BC9, 0x2BC9}, {0x2BD2, 0x2BEB}, {0x2BF0, 0x2BFF}, + {0x2C2F, 0x2C2F}, {0x2C5F, 0x2C5F}, {0x2CF4, 0x2CF8}, + {0x2D26, 0x2D26}, {0x2D28, 0x2D2C}, {0x2D2E, 0x2D2F}, + {0x2D68, 0x2D6E}, {0x2D71, 0x2D7E}, {0x2D97, 0x2D9F}, + {0x2DA7, 0x2DA7}, {0x2DAF, 0x2DAF}, {0x2DB7, 0x2DB7}, + {0x2DBF, 0x2DBF}, {0x2DC7, 0x2DC7}, {0x2DCF, 0x2DCF}, + {0x2DD7, 0x2DD7}, {0x2DDF, 0x2DDF}, {0x2E45, 0x2E7F}, + {0x2E9A, 0x2E9A}, {0x2EF4, 0x2EFF}, {0x2FD6, 0x2FEF}, + {0x2FFC, 0x2FFF}, {0x3040, 0x3040}, {0x3097, 0x3098}, + {0x3100, 0x3104}, {0x312E, 0x3130}, {0x318F, 0x318F}, + {0x31BB, 0x31BF}, {0x31E4, 0x31EF}, {0x321F, 0x321F}, + {0x32FF, 0x32FF}, {0x4DB6, 0x4DBF}, {0x9FD6, 0x9FFF}, + {0xA48D, 0xA48F}, {0xA4C7, 0xA4CF}, {0xA62C, 0xA63F}, + {0xA6F8, 0xA6FF}, {0xA7AF, 0xA7AF}, {0xA7B8, 0xA7F6}, + {0xA82C, 0xA82F}, {0xA83A, 0xA83F}, {0xA878, 0xA87F}, + {0xA8C6, 0xA8CD}, {0xA8DA, 0xA8DF}, {0xA8FE, 0xA8FF}, + {0xA954, 0xA95E}, {0xA97D, 0xA97F}, {0xA9CE, 0xA9CE}, + {0xA9DA, 0xA9DD}, {0xA9FF, 0xA9FF}, {0xAA37, 0xAA3F}, + {0xAA4E, 0xAA4F}, {0xAA5A, 0xAA5B}, {0xAAC3, 0xAADA}, + {0xAAF7, 0xAB00}, {0xAB07, 0xAB08}, {0xAB0F, 0xAB10}, + {0xAB17, 0xAB1F}, {0xAB27, 0xAB27}, {0xAB2F, 0xAB2F}, + {0xAB66, 0xAB6F}, {0xABEE, 0xABEF}, {0xABFA, 0xABFF}, + {0xD7A4, 0xD7AF}, {0xD7C7, 0xD7CA}, {0xD7FC, 0xD7FF}, + {0xFA6E, 0xFA6F}, {0xFADA, 0xFAFF}, {0xFB07, 0xFB12}, + {0xFB18, 0xFB1C}, {0xFB37, 0xFB37}, {0xFB3D, 0xFB3D}, + {0xFB3F, 0xFB3F}, {0xFB42, 0xFB42}, {0xFB45, 0xFB45}, + {0xFBC2, 0xFBD2}, {0xFD40, 0xFD4F}, {0xFD90, 0xFD91}, + {0xFDC8, 0xFDEF}, {0xFDFE, 0xFDFF}, {0xFE1A, 0xFE1F}, + {0xFE53, 0xFE53}, {0xFE67, 0xFE67}, {0xFE6C, 0xFE6F}, + {0xFE75, 0xFE75}, {0xFEFD, 0xFEFE}, {0xFF00, 0xFF00}, + {0xFFBF, 0xFFC1}, {0xFFC8, 0xFFC9}, {0xFFD0, 0xFFD1}, + {0xFFD8, 0xFFD9}, {0xFFDD, 0xFFDF}, {0xFFE7, 0xFFE7}, + {0xFFEF, 0xFFF8}, {0xFFFE, 0xFFFF}, {0x1000C, 0x1000C}, + {0x10027, 0x10027}, {0x1003B, 0x1003B}, {0x1003E, 0x1003E}, + {0x1004E, 0x1004F}, {0x1005E, 0x1007F}, {0x100FB, 0x100FF}, + {0x10103, 0x10106}, {0x10134, 0x10136}, {0x1018F, 0x1018F}, + {0x1019C, 0x1019F}, {0x101A1, 0x101CF}, {0x101FE, 0x1027F}, + {0x1029D, 0x1029F}, {0x102D1, 0x102DF}, {0x102FC, 0x102FF}, + {0x10324, 0x1032F}, {0x1034B, 0x1034F}, {0x1037B, 0x1037F}, + {0x1039E, 0x1039E}, {0x103C4, 0x103C7}, {0x103D6, 0x103FF}, + {0x1049E, 0x1049F}, {0x104AA, 0x104AF}, {0x104D4, 0x104D7}, + {0x104FC, 0x104FF}, {0x10528, 0x1052F}, {0x10564, 0x1056E}, + {0x10570, 0x105FF}, {0x10737, 0x1073F}, {0x10756, 0x1075F}, + {0x10768, 0x107FF}, {0x10806, 0x10807}, {0x10809, 0x10809}, + {0x10836, 0x10836}, {0x10839, 0x1083B}, {0x1083D, 0x1083E}, + {0x10856, 0x10856}, {0x1089F, 0x108A6}, {0x108B0, 0x108DF}, + {0x108F3, 0x108F3}, {0x108F6, 0x108FA}, {0x1091C, 0x1091E}, + {0x1093A, 0x1093E}, {0x10940, 0x1097F}, {0x109B8, 0x109BB}, + {0x109D0, 0x109D1}, {0x10A04, 0x10A04}, {0x10A07, 0x10A0B}, + {0x10A14, 0x10A14}, {0x10A18, 0x10A18}, {0x10A34, 0x10A37}, + {0x10A3B, 0x10A3E}, {0x10A48, 0x10A4F}, {0x10A59, 0x10A5F}, + {0x10AA0, 0x10ABF}, {0x10AE7, 0x10AEA}, {0x10AF7, 0x10AFF}, + {0x10B36, 0x10B38}, {0x10B56, 0x10B57}, {0x10B73, 0x10B77}, + {0x10B92, 0x10B98}, {0x10B9D, 0x10BA8}, {0x10BB0, 0x10BFF}, + {0x10C49, 0x10C7F}, {0x10CB3, 0x10CBF}, {0x10CF3, 0x10CF9}, + {0x10D00, 0x10E5F}, {0x10E7F, 0x10FFF}, {0x1104E, 0x11051}, + {0x11070, 0x1107E}, {0x110C2, 0x110CF}, {0x110E9, 0x110EF}, + {0x110FA, 0x110FF}, {0x11135, 0x11135}, {0x11144, 0x1114F}, + {0x11177, 0x1117F}, {0x111CE, 0x111CF}, {0x111E0, 0x111E0}, + {0x111F5, 0x111FF}, {0x11212, 0x11212}, {0x1123F, 0x1127F}, + {0x11287, 0x11287}, {0x11289, 0x11289}, {0x1128E, 0x1128E}, + {0x1129E, 0x1129E}, {0x112AA, 0x112AF}, {0x112EB, 0x112EF}, + {0x112FA, 0x112FF}, {0x11304, 0x11304}, {0x1130D, 0x1130E}, + {0x11311, 0x11312}, {0x11329, 0x11329}, {0x11331, 0x11331}, + {0x11334, 0x11334}, {0x1133A, 0x1133B}, {0x11345, 0x11346}, + {0x11349, 0x1134A}, {0x1134E, 0x1134F}, {0x11351, 0x11356}, + {0x11358, 0x1135C}, {0x11364, 0x11365}, {0x1136D, 0x1136F}, + {0x11375, 0x113FF}, {0x1145A, 0x1145A}, {0x1145C, 0x1145C}, + {0x1145E, 0x1147F}, {0x114C8, 0x114CF}, {0x114DA, 0x1157F}, + {0x115B6, 0x115B7}, {0x115DE, 0x115FF}, {0x11645, 0x1164F}, + {0x1165A, 0x1165F}, {0x1166D, 0x1167F}, {0x116B8, 0x116BF}, + {0x116CA, 0x116FF}, {0x1171A, 0x1171C}, {0x1172C, 0x1172F}, + {0x11740, 0x1189F}, {0x118F3, 0x118FE}, {0x11900, 0x11ABF}, + {0x11AF9, 0x11BFF}, {0x11C09, 0x11C09}, {0x11C37, 0x11C37}, + {0x11C46, 0x11C4F}, {0x11C6D, 0x11C6F}, {0x11C90, 0x11C91}, + {0x11CA8, 0x11CA8}, {0x11CB7, 0x11FFF}, {0x1239A, 0x123FF}, + {0x1246F, 0x1246F}, {0x12475, 0x1247F}, {0x12544, 0x12FFF}, + {0x1342F, 0x143FF}, {0x14647, 0x167FF}, {0x16A39, 0x16A3F}, + {0x16A5F, 0x16A5F}, {0x16A6A, 0x16A6D}, {0x16A70, 0x16ACF}, + {0x16AEE, 0x16AEF}, {0x16AF6, 0x16AFF}, {0x16B46, 0x16B4F}, + {0x16B5A, 0x16B5A}, {0x16B62, 0x16B62}, {0x16B78, 0x16B7C}, + {0x16B90, 0x16EFF}, {0x16F45, 0x16F4F}, {0x16F7F, 0x16F8E}, + {0x16FA0, 0x16FDF}, {0x16FE1, 0x16FFF}, {0x187ED, 0x187FF}, + {0x18AF3, 0x1AFFF}, {0x1B002, 0x1BBFF}, {0x1BC6B, 0x1BC6F}, + {0x1BC7D, 0x1BC7F}, {0x1BC89, 0x1BC8F}, {0x1BC9A, 0x1BC9B}, + {0x1BCA4, 0x1CFFF}, {0x1D0F6, 0x1D0FF}, {0x1D127, 0x1D128}, + {0x1D1E9, 0x1D1FF}, {0x1D246, 0x1D2FF}, {0x1D357, 0x1D35F}, + {0x1D372, 0x1D3FF}, {0x1D455, 0x1D455}, {0x1D49D, 0x1D49D}, + {0x1D4A0, 0x1D4A1}, {0x1D4A3, 0x1D4A4}, {0x1D4A7, 0x1D4A8}, + {0x1D4AD, 0x1D4AD}, {0x1D4BA, 0x1D4BA}, {0x1D4BC, 0x1D4BC}, + {0x1D4C4, 0x1D4C4}, {0x1D506, 0x1D506}, {0x1D50B, 0x1D50C}, + {0x1D515, 0x1D515}, {0x1D51D, 0x1D51D}, {0x1D53A, 0x1D53A}, + {0x1D53F, 0x1D53F}, {0x1D545, 0x1D545}, {0x1D547, 0x1D549}, + {0x1D551, 0x1D551}, {0x1D6A6, 0x1D6A7}, {0x1D7CC, 0x1D7CD}, + {0x1DA8C, 0x1DA9A}, {0x1DAA0, 0x1DAA0}, {0x1DAB0, 0x1DFFF}, + {0x1E007, 0x1E007}, {0x1E019, 0x1E01A}, {0x1E022, 0x1E022}, + {0x1E025, 0x1E025}, {0x1E02B, 0x1E7FF}, {0x1E8C5, 0x1E8C6}, + {0x1E8D7, 0x1E8FF}, {0x1E94B, 0x1E94F}, {0x1E95A, 0x1E95D}, + {0x1E960, 0x1EDFF}, {0x1EE04, 0x1EE04}, {0x1EE20, 0x1EE20}, + {0x1EE23, 0x1EE23}, {0x1EE25, 0x1EE26}, {0x1EE28, 0x1EE28}, + {0x1EE33, 0x1EE33}, {0x1EE38, 0x1EE38}, {0x1EE3A, 0x1EE3A}, + {0x1EE3C, 0x1EE41}, {0x1EE43, 0x1EE46}, {0x1EE48, 0x1EE48}, + {0x1EE4A, 0x1EE4A}, {0x1EE4C, 0x1EE4C}, {0x1EE50, 0x1EE50}, + {0x1EE53, 0x1EE53}, {0x1EE55, 0x1EE56}, {0x1EE58, 0x1EE58}, + {0x1EE5A, 0x1EE5A}, {0x1EE5C, 0x1EE5C}, {0x1EE5E, 0x1EE5E}, + {0x1EE60, 0x1EE60}, {0x1EE63, 0x1EE63}, {0x1EE65, 0x1EE66}, + {0x1EE6B, 0x1EE6B}, {0x1EE73, 0x1EE73}, {0x1EE78, 0x1EE78}, + {0x1EE7D, 0x1EE7D}, {0x1EE7F, 0x1EE7F}, {0x1EE8A, 0x1EE8A}, + {0x1EE9C, 0x1EEA0}, {0x1EEA4, 0x1EEA4}, {0x1EEAA, 0x1EEAA}, + {0x1EEBC, 0x1EEEF}, {0x1EEF2, 0x1EFFF}, {0x1F02C, 0x1F02F}, + {0x1F094, 0x1F09F}, {0x1F0AF, 0x1F0B0}, {0x1F0C0, 0x1F0C0}, + {0x1F0D0, 0x1F0D0}, {0x1F0F6, 0x1F0FF}, {0x1F10D, 0x1F10F}, + {0x1F12F, 0x1F12F}, {0x1F16C, 0x1F16F}, {0x1F1AD, 0x1F1E5}, + {0x1F203, 0x1F20F}, {0x1F23C, 0x1F23F}, {0x1F249, 0x1F24F}, + {0x1F252, 0x1F2FF}, {0x1F6D3, 0x1F6DF}, {0x1F6ED, 0x1F6EF}, + {0x1F6F7, 0x1F6FF}, {0x1F774, 0x1F77F}, {0x1F7D5, 0x1F7FF}, + {0x1F80C, 0x1F80F}, {0x1F848, 0x1F84F}, {0x1F85A, 0x1F85F}, + {0x1F888, 0x1F88F}, {0x1F8AE, 0x1F90F}, {0x1F91F, 0x1F91F}, + {0x1F928, 0x1F92F}, {0x1F931, 0x1F932}, {0x1F93F, 0x1F93F}, + {0x1F94C, 0x1F94F}, {0x1F95F, 0x1F97F}, {0x1F992, 0x1F9BF}, + {0x1F9C1, 0x1FFFF}, {0x2A6D7, 0x2A6FF}, {0x2B735, 0x2B73F}, + {0x2B81E, 0x2B81F}, {0x2CEA2, 0x2F7FF}, {0x2FA1E, 0xE0000}, + {0xE0002, 0xE001F}, {0xE0080, 0xE00FF}, {0xE01F0, 0xEFFFF}, + {0xFFFFE, 0xFFFFF}, +} + +var neutral = table{ + {0x0000, 0x001F}, {0x007F, 0x007F}, {0x0080, 0x009F}, + {0x00A0, 0x00A0}, {0x00A9, 0x00A9}, {0x00AB, 0x00AB}, + {0x00B5, 0x00B5}, {0x00BB, 0x00BB}, {0x00C0, 0x00C5}, + {0x00C7, 0x00CF}, {0x00D1, 0x00D6}, {0x00D9, 0x00DD}, + {0x00E2, 0x00E5}, {0x00E7, 0x00E7}, {0x00EB, 0x00EB}, + {0x00EE, 0x00EF}, {0x00F1, 0x00F1}, {0x00F4, 0x00F6}, + {0x00FB, 0x00FB}, {0x00FD, 0x00FD}, {0x00FF, 0x00FF}, + {0x0100, 0x0100}, {0x0102, 0x0110}, {0x0112, 0x0112}, + {0x0114, 0x011A}, {0x011C, 0x0125}, {0x0128, 0x012A}, + {0x012C, 0x0130}, {0x0134, 0x0137}, {0x0139, 0x013E}, + {0x0143, 0x0143}, {0x0145, 0x0147}, {0x014C, 0x014C}, + {0x014E, 0x0151}, {0x0154, 0x0165}, {0x0168, 0x016A}, + {0x016C, 0x017F}, {0x0180, 0x01BA}, {0x01BB, 0x01BB}, + {0x01BC, 0x01BF}, {0x01C0, 0x01C3}, {0x01C4, 0x01CD}, + {0x01CF, 0x01CF}, {0x01D1, 0x01D1}, {0x01D3, 0x01D3}, + {0x01D5, 0x01D5}, {0x01D7, 0x01D7}, {0x01D9, 0x01D9}, + {0x01DB, 0x01DB}, {0x01DD, 0x024F}, {0x0250, 0x0250}, + {0x0252, 0x0260}, {0x0262, 0x0293}, {0x0294, 0x0294}, + {0x0295, 0x02AF}, {0x02B0, 0x02C1}, {0x02C2, 0x02C3}, + {0x02C5, 0x02C5}, {0x02C6, 0x02C6}, {0x02C8, 0x02C8}, + {0x02CC, 0x02CC}, {0x02CE, 0x02CF}, {0x02D1, 0x02D1}, + {0x02D2, 0x02D7}, {0x02DC, 0x02DC}, {0x02DE, 0x02DE}, + {0x02E0, 0x02E4}, {0x02E5, 0x02EB}, {0x02EC, 0x02EC}, + {0x02ED, 0x02ED}, {0x02EE, 0x02EE}, {0x02EF, 0x02FF}, + {0x0370, 0x0373}, {0x0374, 0x0374}, {0x0375, 0x0375}, + {0x0376, 0x0377}, {0x037A, 0x037A}, {0x037B, 0x037D}, + {0x037E, 0x037E}, {0x037F, 0x037F}, {0x0384, 0x0385}, + {0x0386, 0x0386}, {0x0387, 0x0387}, {0x0388, 0x038A}, + {0x038C, 0x038C}, {0x038E, 0x0390}, {0x03AA, 0x03B0}, + {0x03C2, 0x03C2}, {0x03CA, 0x03F5}, {0x03F6, 0x03F6}, + {0x03F7, 0x03FF}, {0x0400, 0x0400}, {0x0402, 0x040F}, + {0x0450, 0x0450}, {0x0452, 0x0481}, {0x0482, 0x0482}, + {0x0483, 0x0487}, {0x0488, 0x0489}, {0x048A, 0x04FF}, + {0x0500, 0x052F}, {0x0531, 0x0556}, {0x0559, 0x0559}, + {0x055A, 0x055F}, {0x0561, 0x0587}, {0x0589, 0x0589}, + {0x058A, 0x058A}, {0x058D, 0x058E}, {0x058F, 0x058F}, + {0x0591, 0x05BD}, {0x05BE, 0x05BE}, {0x05BF, 0x05BF}, + {0x05C0, 0x05C0}, {0x05C1, 0x05C2}, {0x05C3, 0x05C3}, + {0x05C4, 0x05C5}, {0x05C6, 0x05C6}, {0x05C7, 0x05C7}, + {0x05D0, 0x05EA}, {0x05F0, 0x05F2}, {0x05F3, 0x05F4}, + {0x0600, 0x0605}, {0x0606, 0x0608}, {0x0609, 0x060A}, + {0x060B, 0x060B}, {0x060C, 0x060D}, {0x060E, 0x060F}, + {0x0610, 0x061A}, {0x061B, 0x061B}, {0x061C, 0x061C}, + {0x061E, 0x061F}, {0x0620, 0x063F}, {0x0640, 0x0640}, + {0x0641, 0x064A}, {0x064B, 0x065F}, {0x0660, 0x0669}, + {0x066A, 0x066D}, {0x066E, 0x066F}, {0x0670, 0x0670}, + {0x0671, 0x06D3}, {0x06D4, 0x06D4}, {0x06D5, 0x06D5}, + {0x06D6, 0x06DC}, {0x06DD, 0x06DD}, {0x06DE, 0x06DE}, + {0x06DF, 0x06E4}, {0x06E5, 0x06E6}, {0x06E7, 0x06E8}, + {0x06E9, 0x06E9}, {0x06EA, 0x06ED}, {0x06EE, 0x06EF}, + {0x06F0, 0x06F9}, {0x06FA, 0x06FC}, {0x06FD, 0x06FE}, + {0x06FF, 0x06FF}, {0x0700, 0x070D}, {0x070F, 0x070F}, + {0x0710, 0x0710}, {0x0711, 0x0711}, {0x0712, 0x072F}, + {0x0730, 0x074A}, {0x074D, 0x074F}, {0x0750, 0x077F}, + {0x0780, 0x07A5}, {0x07A6, 0x07B0}, {0x07B1, 0x07B1}, + {0x07C0, 0x07C9}, {0x07CA, 0x07EA}, {0x07EB, 0x07F3}, + {0x07F4, 0x07F5}, {0x07F6, 0x07F6}, {0x07F7, 0x07F9}, + {0x07FA, 0x07FA}, {0x0800, 0x0815}, {0x0816, 0x0819}, + {0x081A, 0x081A}, {0x081B, 0x0823}, {0x0824, 0x0824}, + {0x0825, 0x0827}, {0x0828, 0x0828}, {0x0829, 0x082D}, + {0x0830, 0x083E}, {0x0840, 0x0858}, {0x0859, 0x085B}, + {0x085E, 0x085E}, {0x08A0, 0x08B4}, {0x08B6, 0x08BD}, + {0x08D4, 0x08E1}, {0x08E2, 0x08E2}, {0x08E3, 0x08FF}, + {0x0900, 0x0902}, {0x0903, 0x0903}, {0x0904, 0x0939}, + {0x093A, 0x093A}, {0x093B, 0x093B}, {0x093C, 0x093C}, + {0x093D, 0x093D}, {0x093E, 0x0940}, {0x0941, 0x0948}, + {0x0949, 0x094C}, {0x094D, 0x094D}, {0x094E, 0x094F}, + {0x0950, 0x0950}, {0x0951, 0x0957}, {0x0958, 0x0961}, + {0x0962, 0x0963}, {0x0964, 0x0965}, {0x0966, 0x096F}, + {0x0970, 0x0970}, {0x0971, 0x0971}, {0x0972, 0x097F}, + {0x0980, 0x0980}, {0x0981, 0x0981}, {0x0982, 0x0983}, + {0x0985, 0x098C}, {0x098F, 0x0990}, {0x0993, 0x09A8}, + {0x09AA, 0x09B0}, {0x09B2, 0x09B2}, {0x09B6, 0x09B9}, + {0x09BC, 0x09BC}, {0x09BD, 0x09BD}, {0x09BE, 0x09C0}, + {0x09C1, 0x09C4}, {0x09C7, 0x09C8}, {0x09CB, 0x09CC}, + {0x09CD, 0x09CD}, {0x09CE, 0x09CE}, {0x09D7, 0x09D7}, + {0x09DC, 0x09DD}, {0x09DF, 0x09E1}, {0x09E2, 0x09E3}, + {0x09E6, 0x09EF}, {0x09F0, 0x09F1}, {0x09F2, 0x09F3}, + {0x09F4, 0x09F9}, {0x09FA, 0x09FA}, {0x09FB, 0x09FB}, + {0x0A01, 0x0A02}, {0x0A03, 0x0A03}, {0x0A05, 0x0A0A}, + {0x0A0F, 0x0A10}, {0x0A13, 0x0A28}, {0x0A2A, 0x0A30}, + {0x0A32, 0x0A33}, {0x0A35, 0x0A36}, {0x0A38, 0x0A39}, + {0x0A3C, 0x0A3C}, {0x0A3E, 0x0A40}, {0x0A41, 0x0A42}, + {0x0A47, 0x0A48}, {0x0A4B, 0x0A4D}, {0x0A51, 0x0A51}, + {0x0A59, 0x0A5C}, {0x0A5E, 0x0A5E}, {0x0A66, 0x0A6F}, + {0x0A70, 0x0A71}, {0x0A72, 0x0A74}, {0x0A75, 0x0A75}, + {0x0A81, 0x0A82}, {0x0A83, 0x0A83}, {0x0A85, 0x0A8D}, + {0x0A8F, 0x0A91}, {0x0A93, 0x0AA8}, {0x0AAA, 0x0AB0}, + {0x0AB2, 0x0AB3}, {0x0AB5, 0x0AB9}, {0x0ABC, 0x0ABC}, + {0x0ABD, 0x0ABD}, {0x0ABE, 0x0AC0}, {0x0AC1, 0x0AC5}, + {0x0AC7, 0x0AC8}, {0x0AC9, 0x0AC9}, {0x0ACB, 0x0ACC}, + {0x0ACD, 0x0ACD}, {0x0AD0, 0x0AD0}, {0x0AE0, 0x0AE1}, + {0x0AE2, 0x0AE3}, {0x0AE6, 0x0AEF}, {0x0AF0, 0x0AF0}, + {0x0AF1, 0x0AF1}, {0x0AF9, 0x0AF9}, {0x0B01, 0x0B01}, + {0x0B02, 0x0B03}, {0x0B05, 0x0B0C}, {0x0B0F, 0x0B10}, + {0x0B13, 0x0B28}, {0x0B2A, 0x0B30}, {0x0B32, 0x0B33}, + {0x0B35, 0x0B39}, {0x0B3C, 0x0B3C}, {0x0B3D, 0x0B3D}, + {0x0B3E, 0x0B3E}, {0x0B3F, 0x0B3F}, {0x0B40, 0x0B40}, + {0x0B41, 0x0B44}, {0x0B47, 0x0B48}, {0x0B4B, 0x0B4C}, + {0x0B4D, 0x0B4D}, {0x0B56, 0x0B56}, {0x0B57, 0x0B57}, + {0x0B5C, 0x0B5D}, {0x0B5F, 0x0B61}, {0x0B62, 0x0B63}, + {0x0B66, 0x0B6F}, {0x0B70, 0x0B70}, {0x0B71, 0x0B71}, + {0x0B72, 0x0B77}, {0x0B82, 0x0B82}, {0x0B83, 0x0B83}, + {0x0B85, 0x0B8A}, {0x0B8E, 0x0B90}, {0x0B92, 0x0B95}, + {0x0B99, 0x0B9A}, {0x0B9C, 0x0B9C}, {0x0B9E, 0x0B9F}, + {0x0BA3, 0x0BA4}, {0x0BA8, 0x0BAA}, {0x0BAE, 0x0BB9}, + {0x0BBE, 0x0BBF}, {0x0BC0, 0x0BC0}, {0x0BC1, 0x0BC2}, + {0x0BC6, 0x0BC8}, {0x0BCA, 0x0BCC}, {0x0BCD, 0x0BCD}, + {0x0BD0, 0x0BD0}, {0x0BD7, 0x0BD7}, {0x0BE6, 0x0BEF}, + {0x0BF0, 0x0BF2}, {0x0BF3, 0x0BF8}, {0x0BF9, 0x0BF9}, + {0x0BFA, 0x0BFA}, {0x0C00, 0x0C00}, {0x0C01, 0x0C03}, + {0x0C05, 0x0C0C}, {0x0C0E, 0x0C10}, {0x0C12, 0x0C28}, + {0x0C2A, 0x0C39}, {0x0C3D, 0x0C3D}, {0x0C3E, 0x0C40}, + {0x0C41, 0x0C44}, {0x0C46, 0x0C48}, {0x0C4A, 0x0C4D}, + {0x0C55, 0x0C56}, {0x0C58, 0x0C5A}, {0x0C60, 0x0C61}, + {0x0C62, 0x0C63}, {0x0C66, 0x0C6F}, {0x0C78, 0x0C7E}, + {0x0C7F, 0x0C7F}, {0x0C80, 0x0C80}, {0x0C81, 0x0C81}, + {0x0C82, 0x0C83}, {0x0C85, 0x0C8C}, {0x0C8E, 0x0C90}, + {0x0C92, 0x0CA8}, {0x0CAA, 0x0CB3}, {0x0CB5, 0x0CB9}, + {0x0CBC, 0x0CBC}, {0x0CBD, 0x0CBD}, {0x0CBE, 0x0CBE}, + {0x0CBF, 0x0CBF}, {0x0CC0, 0x0CC4}, {0x0CC6, 0x0CC6}, + {0x0CC7, 0x0CC8}, {0x0CCA, 0x0CCB}, {0x0CCC, 0x0CCD}, + {0x0CD5, 0x0CD6}, {0x0CDE, 0x0CDE}, {0x0CE0, 0x0CE1}, + {0x0CE2, 0x0CE3}, {0x0CE6, 0x0CEF}, {0x0CF1, 0x0CF2}, + {0x0D01, 0x0D01}, {0x0D02, 0x0D03}, {0x0D05, 0x0D0C}, + {0x0D0E, 0x0D10}, {0x0D12, 0x0D3A}, {0x0D3D, 0x0D3D}, + {0x0D3E, 0x0D40}, {0x0D41, 0x0D44}, {0x0D46, 0x0D48}, + {0x0D4A, 0x0D4C}, {0x0D4D, 0x0D4D}, {0x0D4E, 0x0D4E}, + {0x0D4F, 0x0D4F}, {0x0D54, 0x0D56}, {0x0D57, 0x0D57}, + {0x0D58, 0x0D5E}, {0x0D5F, 0x0D61}, {0x0D62, 0x0D63}, + {0x0D66, 0x0D6F}, {0x0D70, 0x0D78}, {0x0D79, 0x0D79}, + {0x0D7A, 0x0D7F}, {0x0D82, 0x0D83}, {0x0D85, 0x0D96}, + {0x0D9A, 0x0DB1}, {0x0DB3, 0x0DBB}, {0x0DBD, 0x0DBD}, + {0x0DC0, 0x0DC6}, {0x0DCA, 0x0DCA}, {0x0DCF, 0x0DD1}, + {0x0DD2, 0x0DD4}, {0x0DD6, 0x0DD6}, {0x0DD8, 0x0DDF}, + {0x0DE6, 0x0DEF}, {0x0DF2, 0x0DF3}, {0x0DF4, 0x0DF4}, + {0x0E01, 0x0E30}, {0x0E31, 0x0E31}, {0x0E32, 0x0E33}, + {0x0E34, 0x0E3A}, {0x0E3F, 0x0E3F}, {0x0E40, 0x0E45}, + {0x0E46, 0x0E46}, {0x0E47, 0x0E4E}, {0x0E4F, 0x0E4F}, + {0x0E50, 0x0E59}, {0x0E5A, 0x0E5B}, {0x0E81, 0x0E82}, + {0x0E84, 0x0E84}, {0x0E87, 0x0E88}, {0x0E8A, 0x0E8A}, + {0x0E8D, 0x0E8D}, {0x0E94, 0x0E97}, {0x0E99, 0x0E9F}, + {0x0EA1, 0x0EA3}, {0x0EA5, 0x0EA5}, {0x0EA7, 0x0EA7}, + {0x0EAA, 0x0EAB}, {0x0EAD, 0x0EB0}, {0x0EB1, 0x0EB1}, + {0x0EB2, 0x0EB3}, {0x0EB4, 0x0EB9}, {0x0EBB, 0x0EBC}, + {0x0EBD, 0x0EBD}, {0x0EC0, 0x0EC4}, {0x0EC6, 0x0EC6}, + {0x0EC8, 0x0ECD}, {0x0ED0, 0x0ED9}, {0x0EDC, 0x0EDF}, + {0x0F00, 0x0F00}, {0x0F01, 0x0F03}, {0x0F04, 0x0F12}, + {0x0F13, 0x0F13}, {0x0F14, 0x0F14}, {0x0F15, 0x0F17}, + {0x0F18, 0x0F19}, {0x0F1A, 0x0F1F}, {0x0F20, 0x0F29}, + {0x0F2A, 0x0F33}, {0x0F34, 0x0F34}, {0x0F35, 0x0F35}, + {0x0F36, 0x0F36}, {0x0F37, 0x0F37}, {0x0F38, 0x0F38}, + {0x0F39, 0x0F39}, {0x0F3A, 0x0F3A}, {0x0F3B, 0x0F3B}, + {0x0F3C, 0x0F3C}, {0x0F3D, 0x0F3D}, {0x0F3E, 0x0F3F}, + {0x0F40, 0x0F47}, {0x0F49, 0x0F6C}, {0x0F71, 0x0F7E}, + {0x0F7F, 0x0F7F}, {0x0F80, 0x0F84}, {0x0F85, 0x0F85}, + {0x0F86, 0x0F87}, {0x0F88, 0x0F8C}, {0x0F8D, 0x0F97}, + {0x0F99, 0x0FBC}, {0x0FBE, 0x0FC5}, {0x0FC6, 0x0FC6}, + {0x0FC7, 0x0FCC}, {0x0FCE, 0x0FCF}, {0x0FD0, 0x0FD4}, + {0x0FD5, 0x0FD8}, {0x0FD9, 0x0FDA}, {0x1000, 0x102A}, + {0x102B, 0x102C}, {0x102D, 0x1030}, {0x1031, 0x1031}, + {0x1032, 0x1037}, {0x1038, 0x1038}, {0x1039, 0x103A}, + {0x103B, 0x103C}, {0x103D, 0x103E}, {0x103F, 0x103F}, + {0x1040, 0x1049}, {0x104A, 0x104F}, {0x1050, 0x1055}, + {0x1056, 0x1057}, {0x1058, 0x1059}, {0x105A, 0x105D}, + {0x105E, 0x1060}, {0x1061, 0x1061}, {0x1062, 0x1064}, + {0x1065, 0x1066}, {0x1067, 0x106D}, {0x106E, 0x1070}, + {0x1071, 0x1074}, {0x1075, 0x1081}, {0x1082, 0x1082}, + {0x1083, 0x1084}, {0x1085, 0x1086}, {0x1087, 0x108C}, + {0x108D, 0x108D}, {0x108E, 0x108E}, {0x108F, 0x108F}, + {0x1090, 0x1099}, {0x109A, 0x109C}, {0x109D, 0x109D}, + {0x109E, 0x109F}, {0x10A0, 0x10C5}, {0x10C7, 0x10C7}, + {0x10CD, 0x10CD}, {0x10D0, 0x10FA}, {0x10FB, 0x10FB}, + {0x10FC, 0x10FC}, {0x10FD, 0x10FF}, {0x1160, 0x11FF}, + {0x1200, 0x1248}, {0x124A, 0x124D}, {0x1250, 0x1256}, + {0x1258, 0x1258}, {0x125A, 0x125D}, {0x1260, 0x1288}, + {0x128A, 0x128D}, {0x1290, 0x12B0}, {0x12B2, 0x12B5}, + {0x12B8, 0x12BE}, {0x12C0, 0x12C0}, {0x12C2, 0x12C5}, + {0x12C8, 0x12D6}, {0x12D8, 0x1310}, {0x1312, 0x1315}, + {0x1318, 0x135A}, {0x135D, 0x135F}, {0x1360, 0x1368}, + {0x1369, 0x137C}, {0x1380, 0x138F}, {0x1390, 0x1399}, + {0x13A0, 0x13F5}, {0x13F8, 0x13FD}, {0x1400, 0x1400}, + {0x1401, 0x166C}, {0x166D, 0x166E}, {0x166F, 0x167F}, + {0x1680, 0x1680}, {0x1681, 0x169A}, {0x169B, 0x169B}, + {0x169C, 0x169C}, {0x16A0, 0x16EA}, {0x16EB, 0x16ED}, + {0x16EE, 0x16F0}, {0x16F1, 0x16F8}, {0x1700, 0x170C}, + {0x170E, 0x1711}, {0x1712, 0x1714}, {0x1720, 0x1731}, + {0x1732, 0x1734}, {0x1735, 0x1736}, {0x1740, 0x1751}, + {0x1752, 0x1753}, {0x1760, 0x176C}, {0x176E, 0x1770}, + {0x1772, 0x1773}, {0x1780, 0x17B3}, {0x17B4, 0x17B5}, + {0x17B6, 0x17B6}, {0x17B7, 0x17BD}, {0x17BE, 0x17C5}, + {0x17C6, 0x17C6}, {0x17C7, 0x17C8}, {0x17C9, 0x17D3}, + {0x17D4, 0x17D6}, {0x17D7, 0x17D7}, {0x17D8, 0x17DA}, + {0x17DB, 0x17DB}, {0x17DC, 0x17DC}, {0x17DD, 0x17DD}, + {0x17E0, 0x17E9}, {0x17F0, 0x17F9}, {0x1800, 0x1805}, + {0x1806, 0x1806}, {0x1807, 0x180A}, {0x180B, 0x180D}, + {0x180E, 0x180E}, {0x1810, 0x1819}, {0x1820, 0x1842}, + {0x1843, 0x1843}, {0x1844, 0x1877}, {0x1880, 0x1884}, + {0x1885, 0x1886}, {0x1887, 0x18A8}, {0x18A9, 0x18A9}, + {0x18AA, 0x18AA}, {0x18B0, 0x18F5}, {0x1900, 0x191E}, + {0x1920, 0x1922}, {0x1923, 0x1926}, {0x1927, 0x1928}, + {0x1929, 0x192B}, {0x1930, 0x1931}, {0x1932, 0x1932}, + {0x1933, 0x1938}, {0x1939, 0x193B}, {0x1940, 0x1940}, + {0x1944, 0x1945}, {0x1946, 0x194F}, {0x1950, 0x196D}, + {0x1970, 0x1974}, {0x1980, 0x19AB}, {0x19B0, 0x19C9}, + {0x19D0, 0x19D9}, {0x19DA, 0x19DA}, {0x19DE, 0x19DF}, + {0x19E0, 0x19FF}, {0x1A00, 0x1A16}, {0x1A17, 0x1A18}, + {0x1A19, 0x1A1A}, {0x1A1B, 0x1A1B}, {0x1A1E, 0x1A1F}, + {0x1A20, 0x1A54}, {0x1A55, 0x1A55}, {0x1A56, 0x1A56}, + {0x1A57, 0x1A57}, {0x1A58, 0x1A5E}, {0x1A60, 0x1A60}, + {0x1A61, 0x1A61}, {0x1A62, 0x1A62}, {0x1A63, 0x1A64}, + {0x1A65, 0x1A6C}, {0x1A6D, 0x1A72}, {0x1A73, 0x1A7C}, + {0x1A7F, 0x1A7F}, {0x1A80, 0x1A89}, {0x1A90, 0x1A99}, + {0x1AA0, 0x1AA6}, {0x1AA7, 0x1AA7}, {0x1AA8, 0x1AAD}, + {0x1AB0, 0x1ABD}, {0x1ABE, 0x1ABE}, {0x1B00, 0x1B03}, + {0x1B04, 0x1B04}, {0x1B05, 0x1B33}, {0x1B34, 0x1B34}, + {0x1B35, 0x1B35}, {0x1B36, 0x1B3A}, {0x1B3B, 0x1B3B}, + {0x1B3C, 0x1B3C}, {0x1B3D, 0x1B41}, {0x1B42, 0x1B42}, + {0x1B43, 0x1B44}, {0x1B45, 0x1B4B}, {0x1B50, 0x1B59}, + {0x1B5A, 0x1B60}, {0x1B61, 0x1B6A}, {0x1B6B, 0x1B73}, + {0x1B74, 0x1B7C}, {0x1B80, 0x1B81}, {0x1B82, 0x1B82}, + {0x1B83, 0x1BA0}, {0x1BA1, 0x1BA1}, {0x1BA2, 0x1BA5}, + {0x1BA6, 0x1BA7}, {0x1BA8, 0x1BA9}, {0x1BAA, 0x1BAA}, + {0x1BAB, 0x1BAD}, {0x1BAE, 0x1BAF}, {0x1BB0, 0x1BB9}, + {0x1BBA, 0x1BBF}, {0x1BC0, 0x1BE5}, {0x1BE6, 0x1BE6}, + {0x1BE7, 0x1BE7}, {0x1BE8, 0x1BE9}, {0x1BEA, 0x1BEC}, + {0x1BED, 0x1BED}, {0x1BEE, 0x1BEE}, {0x1BEF, 0x1BF1}, + {0x1BF2, 0x1BF3}, {0x1BFC, 0x1BFF}, {0x1C00, 0x1C23}, + {0x1C24, 0x1C2B}, {0x1C2C, 0x1C33}, {0x1C34, 0x1C35}, + {0x1C36, 0x1C37}, {0x1C3B, 0x1C3F}, {0x1C40, 0x1C49}, + {0x1C4D, 0x1C4F}, {0x1C50, 0x1C59}, {0x1C5A, 0x1C77}, + {0x1C78, 0x1C7D}, {0x1C7E, 0x1C7F}, {0x1C80, 0x1C88}, + {0x1CC0, 0x1CC7}, {0x1CD0, 0x1CD2}, {0x1CD3, 0x1CD3}, + {0x1CD4, 0x1CE0}, {0x1CE1, 0x1CE1}, {0x1CE2, 0x1CE8}, + {0x1CE9, 0x1CEC}, {0x1CED, 0x1CED}, {0x1CEE, 0x1CF1}, + {0x1CF2, 0x1CF3}, {0x1CF4, 0x1CF4}, {0x1CF5, 0x1CF6}, + {0x1CF8, 0x1CF9}, {0x1D00, 0x1D2B}, {0x1D2C, 0x1D6A}, + {0x1D6B, 0x1D77}, {0x1D78, 0x1D78}, {0x1D79, 0x1D7F}, + {0x1D80, 0x1D9A}, {0x1D9B, 0x1DBF}, {0x1DC0, 0x1DF5}, + {0x1DFB, 0x1DFF}, {0x1E00, 0x1EFF}, {0x1F00, 0x1F15}, + {0x1F18, 0x1F1D}, {0x1F20, 0x1F45}, {0x1F48, 0x1F4D}, + {0x1F50, 0x1F57}, {0x1F59, 0x1F59}, {0x1F5B, 0x1F5B}, + {0x1F5D, 0x1F5D}, {0x1F5F, 0x1F7D}, {0x1F80, 0x1FB4}, + {0x1FB6, 0x1FBC}, {0x1FBD, 0x1FBD}, {0x1FBE, 0x1FBE}, + {0x1FBF, 0x1FC1}, {0x1FC2, 0x1FC4}, {0x1FC6, 0x1FCC}, + {0x1FCD, 0x1FCF}, {0x1FD0, 0x1FD3}, {0x1FD6, 0x1FDB}, + {0x1FDD, 0x1FDF}, {0x1FE0, 0x1FEC}, {0x1FED, 0x1FEF}, + {0x1FF2, 0x1FF4}, {0x1FF6, 0x1FFC}, {0x1FFD, 0x1FFE}, + {0x2000, 0x200A}, {0x200B, 0x200F}, {0x2011, 0x2012}, + {0x2017, 0x2017}, {0x201A, 0x201A}, {0x201B, 0x201B}, + {0x201E, 0x201E}, {0x201F, 0x201F}, {0x2023, 0x2023}, + {0x2028, 0x2028}, {0x2029, 0x2029}, {0x202A, 0x202E}, + {0x202F, 0x202F}, {0x2031, 0x2031}, {0x2034, 0x2034}, + {0x2036, 0x2038}, {0x2039, 0x2039}, {0x203A, 0x203A}, + {0x203C, 0x203D}, {0x203F, 0x2040}, {0x2041, 0x2043}, + {0x2044, 0x2044}, {0x2045, 0x2045}, {0x2046, 0x2046}, + {0x2047, 0x2051}, {0x2052, 0x2052}, {0x2053, 0x2053}, + {0x2054, 0x2054}, {0x2055, 0x205E}, {0x205F, 0x205F}, + {0x2060, 0x2064}, {0x2066, 0x206F}, {0x2070, 0x2070}, + {0x2071, 0x2071}, {0x2075, 0x2079}, {0x207A, 0x207C}, + {0x207D, 0x207D}, {0x207E, 0x207E}, {0x2080, 0x2080}, + {0x2085, 0x2089}, {0x208A, 0x208C}, {0x208D, 0x208D}, + {0x208E, 0x208E}, {0x2090, 0x209C}, {0x20A0, 0x20A8}, + {0x20AA, 0x20AB}, {0x20AD, 0x20BE}, {0x20D0, 0x20DC}, + {0x20DD, 0x20E0}, {0x20E1, 0x20E1}, {0x20E2, 0x20E4}, + {0x20E5, 0x20F0}, {0x2100, 0x2101}, {0x2102, 0x2102}, + {0x2104, 0x2104}, {0x2106, 0x2106}, {0x2107, 0x2107}, + {0x2108, 0x2108}, {0x210A, 0x2112}, {0x2114, 0x2114}, + {0x2115, 0x2115}, {0x2117, 0x2117}, {0x2118, 0x2118}, + {0x2119, 0x211D}, {0x211E, 0x2120}, {0x2123, 0x2123}, + {0x2124, 0x2124}, {0x2125, 0x2125}, {0x2127, 0x2127}, + {0x2128, 0x2128}, {0x2129, 0x2129}, {0x212A, 0x212A}, + {0x212C, 0x212D}, {0x212E, 0x212E}, {0x212F, 0x2134}, + {0x2135, 0x2138}, {0x2139, 0x2139}, {0x213A, 0x213B}, + {0x213C, 0x213F}, {0x2140, 0x2144}, {0x2145, 0x2149}, + {0x214A, 0x214A}, {0x214B, 0x214B}, {0x214C, 0x214D}, + {0x214E, 0x214E}, {0x214F, 0x214F}, {0x2150, 0x2152}, + {0x2155, 0x215A}, {0x215F, 0x215F}, {0x216C, 0x216F}, + {0x217A, 0x2182}, {0x2183, 0x2184}, {0x2185, 0x2188}, + {0x218A, 0x218B}, {0x219A, 0x219B}, {0x219C, 0x219F}, + {0x21A0, 0x21A0}, {0x21A1, 0x21A2}, {0x21A3, 0x21A3}, + {0x21A4, 0x21A5}, {0x21A6, 0x21A6}, {0x21A7, 0x21AD}, + {0x21AE, 0x21AE}, {0x21AF, 0x21B7}, {0x21BA, 0x21CD}, + {0x21CE, 0x21CF}, {0x21D0, 0x21D1}, {0x21D3, 0x21D3}, + {0x21D5, 0x21E6}, {0x21E8, 0x21F3}, {0x21F4, 0x21FF}, + {0x2201, 0x2201}, {0x2204, 0x2206}, {0x2209, 0x220A}, + {0x220C, 0x220E}, {0x2210, 0x2210}, {0x2212, 0x2214}, + {0x2216, 0x2219}, {0x221B, 0x221C}, {0x2221, 0x2222}, + {0x2224, 0x2224}, {0x2226, 0x2226}, {0x222D, 0x222D}, + {0x222F, 0x2233}, {0x2238, 0x223B}, {0x223E, 0x2247}, + {0x2249, 0x224B}, {0x224D, 0x2251}, {0x2253, 0x225F}, + {0x2262, 0x2263}, {0x2268, 0x2269}, {0x226C, 0x226D}, + {0x2270, 0x2281}, {0x2284, 0x2285}, {0x2288, 0x2294}, + {0x2296, 0x2298}, {0x229A, 0x22A4}, {0x22A6, 0x22BE}, + {0x22C0, 0x22FF}, {0x2300, 0x2307}, {0x2308, 0x2308}, + {0x2309, 0x2309}, {0x230A, 0x230A}, {0x230B, 0x230B}, + {0x230C, 0x2311}, {0x2313, 0x2319}, {0x231C, 0x231F}, + {0x2320, 0x2321}, {0x2322, 0x2328}, {0x232B, 0x237B}, + {0x237C, 0x237C}, {0x237D, 0x239A}, {0x239B, 0x23B3}, + {0x23B4, 0x23DB}, {0x23DC, 0x23E1}, {0x23E2, 0x23E8}, + {0x23ED, 0x23EF}, {0x23F1, 0x23F2}, {0x23F4, 0x23FE}, + {0x2400, 0x2426}, {0x2440, 0x244A}, {0x24EA, 0x24EA}, + {0x254C, 0x254F}, {0x2574, 0x257F}, {0x2590, 0x2591}, + {0x2596, 0x259F}, {0x25A2, 0x25A2}, {0x25AA, 0x25B1}, + {0x25B4, 0x25B5}, {0x25B8, 0x25BB}, {0x25BE, 0x25BF}, + {0x25C2, 0x25C5}, {0x25C9, 0x25CA}, {0x25CC, 0x25CD}, + {0x25D2, 0x25E1}, {0x25E6, 0x25EE}, {0x25F0, 0x25F7}, + {0x25F8, 0x25FC}, {0x25FF, 0x25FF}, {0x2600, 0x2604}, + {0x2607, 0x2608}, {0x260A, 0x260D}, {0x2610, 0x2613}, + {0x2616, 0x261B}, {0x261D, 0x261D}, {0x261F, 0x263F}, + {0x2641, 0x2641}, {0x2643, 0x2647}, {0x2654, 0x265F}, + {0x2662, 0x2662}, {0x2666, 0x2666}, {0x266B, 0x266B}, + {0x266E, 0x266E}, {0x2670, 0x267E}, {0x2680, 0x2692}, + {0x2694, 0x269D}, {0x26A0, 0x26A0}, {0x26A2, 0x26A9}, + {0x26AC, 0x26BC}, {0x26C0, 0x26C3}, {0x26E2, 0x26E2}, + {0x26E4, 0x26E7}, {0x2700, 0x2704}, {0x2706, 0x2709}, + {0x270C, 0x2727}, {0x2729, 0x273C}, {0x273E, 0x274B}, + {0x274D, 0x274D}, {0x274F, 0x2752}, {0x2756, 0x2756}, + {0x2758, 0x2767}, {0x2768, 0x2768}, {0x2769, 0x2769}, + {0x276A, 0x276A}, {0x276B, 0x276B}, {0x276C, 0x276C}, + {0x276D, 0x276D}, {0x276E, 0x276E}, {0x276F, 0x276F}, + {0x2770, 0x2770}, {0x2771, 0x2771}, {0x2772, 0x2772}, + {0x2773, 0x2773}, {0x2774, 0x2774}, {0x2775, 0x2775}, + {0x2780, 0x2793}, {0x2794, 0x2794}, {0x2798, 0x27AF}, + {0x27B1, 0x27BE}, {0x27C0, 0x27C4}, {0x27C5, 0x27C5}, + {0x27C6, 0x27C6}, {0x27C7, 0x27E5}, {0x27EE, 0x27EE}, + {0x27EF, 0x27EF}, {0x27F0, 0x27FF}, {0x2800, 0x28FF}, + {0x2900, 0x297F}, {0x2980, 0x2982}, {0x2983, 0x2983}, + {0x2984, 0x2984}, {0x2987, 0x2987}, {0x2988, 0x2988}, + {0x2989, 0x2989}, {0x298A, 0x298A}, {0x298B, 0x298B}, + {0x298C, 0x298C}, {0x298D, 0x298D}, {0x298E, 0x298E}, + {0x298F, 0x298F}, {0x2990, 0x2990}, {0x2991, 0x2991}, + {0x2992, 0x2992}, {0x2993, 0x2993}, {0x2994, 0x2994}, + {0x2995, 0x2995}, {0x2996, 0x2996}, {0x2997, 0x2997}, + {0x2998, 0x2998}, {0x2999, 0x29D7}, {0x29D8, 0x29D8}, + {0x29D9, 0x29D9}, {0x29DA, 0x29DA}, {0x29DB, 0x29DB}, + {0x29DC, 0x29FB}, {0x29FC, 0x29FC}, {0x29FD, 0x29FD}, + {0x29FE, 0x29FF}, {0x2A00, 0x2AFF}, {0x2B00, 0x2B1A}, + {0x2B1D, 0x2B2F}, {0x2B30, 0x2B44}, {0x2B45, 0x2B46}, + {0x2B47, 0x2B4C}, {0x2B4D, 0x2B4F}, {0x2B51, 0x2B54}, + {0x2B5A, 0x2B73}, {0x2B76, 0x2B95}, {0x2B98, 0x2BB9}, + {0x2BBD, 0x2BC8}, {0x2BCA, 0x2BD1}, {0x2BEC, 0x2BEF}, + {0x2C00, 0x2C2E}, {0x2C30, 0x2C5E}, {0x2C60, 0x2C7B}, + {0x2C7C, 0x2C7D}, {0x2C7E, 0x2C7F}, {0x2C80, 0x2CE4}, + {0x2CE5, 0x2CEA}, {0x2CEB, 0x2CEE}, {0x2CEF, 0x2CF1}, + {0x2CF2, 0x2CF3}, {0x2CF9, 0x2CFC}, {0x2CFD, 0x2CFD}, + {0x2CFE, 0x2CFF}, {0x2D00, 0x2D25}, {0x2D27, 0x2D27}, + {0x2D2D, 0x2D2D}, {0x2D30, 0x2D67}, {0x2D6F, 0x2D6F}, + {0x2D70, 0x2D70}, {0x2D7F, 0x2D7F}, {0x2D80, 0x2D96}, + {0x2DA0, 0x2DA6}, {0x2DA8, 0x2DAE}, {0x2DB0, 0x2DB6}, + {0x2DB8, 0x2DBE}, {0x2DC0, 0x2DC6}, {0x2DC8, 0x2DCE}, + {0x2DD0, 0x2DD6}, {0x2DD8, 0x2DDE}, {0x2DE0, 0x2DFF}, + {0x2E00, 0x2E01}, {0x2E02, 0x2E02}, {0x2E03, 0x2E03}, + {0x2E04, 0x2E04}, {0x2E05, 0x2E05}, {0x2E06, 0x2E08}, + {0x2E09, 0x2E09}, {0x2E0A, 0x2E0A}, {0x2E0B, 0x2E0B}, + {0x2E0C, 0x2E0C}, {0x2E0D, 0x2E0D}, {0x2E0E, 0x2E16}, + {0x2E17, 0x2E17}, {0x2E18, 0x2E19}, {0x2E1A, 0x2E1A}, + {0x2E1B, 0x2E1B}, {0x2E1C, 0x2E1C}, {0x2E1D, 0x2E1D}, + {0x2E1E, 0x2E1F}, {0x2E20, 0x2E20}, {0x2E21, 0x2E21}, + {0x2E22, 0x2E22}, {0x2E23, 0x2E23}, {0x2E24, 0x2E24}, + {0x2E25, 0x2E25}, {0x2E26, 0x2E26}, {0x2E27, 0x2E27}, + {0x2E28, 0x2E28}, {0x2E29, 0x2E29}, {0x2E2A, 0x2E2E}, + {0x2E2F, 0x2E2F}, {0x2E30, 0x2E39}, {0x2E3A, 0x2E3B}, + {0x2E3C, 0x2E3F}, {0x2E40, 0x2E40}, {0x2E41, 0x2E41}, + {0x2E42, 0x2E42}, {0x2E43, 0x2E44}, {0x303F, 0x303F}, + {0x4DC0, 0x4DFF}, {0xA4D0, 0xA4F7}, {0xA4F8, 0xA4FD}, + {0xA4FE, 0xA4FF}, {0xA500, 0xA60B}, {0xA60C, 0xA60C}, + {0xA60D, 0xA60F}, {0xA610, 0xA61F}, {0xA620, 0xA629}, + {0xA62A, 0xA62B}, {0xA640, 0xA66D}, {0xA66E, 0xA66E}, + {0xA66F, 0xA66F}, {0xA670, 0xA672}, {0xA673, 0xA673}, + {0xA674, 0xA67D}, {0xA67E, 0xA67E}, {0xA67F, 0xA67F}, + {0xA680, 0xA69B}, {0xA69C, 0xA69D}, {0xA69E, 0xA69F}, + {0xA6A0, 0xA6E5}, {0xA6E6, 0xA6EF}, {0xA6F0, 0xA6F1}, + {0xA6F2, 0xA6F7}, {0xA700, 0xA716}, {0xA717, 0xA71F}, + {0xA720, 0xA721}, {0xA722, 0xA76F}, {0xA770, 0xA770}, + {0xA771, 0xA787}, {0xA788, 0xA788}, {0xA789, 0xA78A}, + {0xA78B, 0xA78E}, {0xA78F, 0xA78F}, {0xA790, 0xA7AE}, + {0xA7B0, 0xA7B7}, {0xA7F7, 0xA7F7}, {0xA7F8, 0xA7F9}, + {0xA7FA, 0xA7FA}, {0xA7FB, 0xA7FF}, {0xA800, 0xA801}, + {0xA802, 0xA802}, {0xA803, 0xA805}, {0xA806, 0xA806}, + {0xA807, 0xA80A}, {0xA80B, 0xA80B}, {0xA80C, 0xA822}, + {0xA823, 0xA824}, {0xA825, 0xA826}, {0xA827, 0xA827}, + {0xA828, 0xA82B}, {0xA830, 0xA835}, {0xA836, 0xA837}, + {0xA838, 0xA838}, {0xA839, 0xA839}, {0xA840, 0xA873}, + {0xA874, 0xA877}, {0xA880, 0xA881}, {0xA882, 0xA8B3}, + {0xA8B4, 0xA8C3}, {0xA8C4, 0xA8C5}, {0xA8CE, 0xA8CF}, + {0xA8D0, 0xA8D9}, {0xA8E0, 0xA8F1}, {0xA8F2, 0xA8F7}, + {0xA8F8, 0xA8FA}, {0xA8FB, 0xA8FB}, {0xA8FC, 0xA8FC}, + {0xA8FD, 0xA8FD}, {0xA900, 0xA909}, {0xA90A, 0xA925}, + {0xA926, 0xA92D}, {0xA92E, 0xA92F}, {0xA930, 0xA946}, + {0xA947, 0xA951}, {0xA952, 0xA953}, {0xA95F, 0xA95F}, + {0xA980, 0xA982}, {0xA983, 0xA983}, {0xA984, 0xA9B2}, + {0xA9B3, 0xA9B3}, {0xA9B4, 0xA9B5}, {0xA9B6, 0xA9B9}, + {0xA9BA, 0xA9BB}, {0xA9BC, 0xA9BC}, {0xA9BD, 0xA9C0}, + {0xA9C1, 0xA9CD}, {0xA9CF, 0xA9CF}, {0xA9D0, 0xA9D9}, + {0xA9DE, 0xA9DF}, {0xA9E0, 0xA9E4}, {0xA9E5, 0xA9E5}, + {0xA9E6, 0xA9E6}, {0xA9E7, 0xA9EF}, {0xA9F0, 0xA9F9}, + {0xA9FA, 0xA9FE}, {0xAA00, 0xAA28}, {0xAA29, 0xAA2E}, + {0xAA2F, 0xAA30}, {0xAA31, 0xAA32}, {0xAA33, 0xAA34}, + {0xAA35, 0xAA36}, {0xAA40, 0xAA42}, {0xAA43, 0xAA43}, + {0xAA44, 0xAA4B}, {0xAA4C, 0xAA4C}, {0xAA4D, 0xAA4D}, + {0xAA50, 0xAA59}, {0xAA5C, 0xAA5F}, {0xAA60, 0xAA6F}, + {0xAA70, 0xAA70}, {0xAA71, 0xAA76}, {0xAA77, 0xAA79}, + {0xAA7A, 0xAA7A}, {0xAA7B, 0xAA7B}, {0xAA7C, 0xAA7C}, + {0xAA7D, 0xAA7D}, {0xAA7E, 0xAA7F}, {0xAA80, 0xAAAF}, + {0xAAB0, 0xAAB0}, {0xAAB1, 0xAAB1}, {0xAAB2, 0xAAB4}, + {0xAAB5, 0xAAB6}, {0xAAB7, 0xAAB8}, {0xAAB9, 0xAABD}, + {0xAABE, 0xAABF}, {0xAAC0, 0xAAC0}, {0xAAC1, 0xAAC1}, + {0xAAC2, 0xAAC2}, {0xAADB, 0xAADC}, {0xAADD, 0xAADD}, + {0xAADE, 0xAADF}, {0xAAE0, 0xAAEA}, {0xAAEB, 0xAAEB}, + {0xAAEC, 0xAAED}, {0xAAEE, 0xAAEF}, {0xAAF0, 0xAAF1}, + {0xAAF2, 0xAAF2}, {0xAAF3, 0xAAF4}, {0xAAF5, 0xAAF5}, + {0xAAF6, 0xAAF6}, {0xAB01, 0xAB06}, {0xAB09, 0xAB0E}, + {0xAB11, 0xAB16}, {0xAB20, 0xAB26}, {0xAB28, 0xAB2E}, + {0xAB30, 0xAB5A}, {0xAB5B, 0xAB5B}, {0xAB5C, 0xAB5F}, + {0xAB60, 0xAB65}, {0xAB70, 0xABBF}, {0xABC0, 0xABE2}, + {0xABE3, 0xABE4}, {0xABE5, 0xABE5}, {0xABE6, 0xABE7}, + {0xABE8, 0xABE8}, {0xABE9, 0xABEA}, {0xABEB, 0xABEB}, + {0xABEC, 0xABEC}, {0xABED, 0xABED}, {0xABF0, 0xABF9}, + {0xD7B0, 0xD7C6}, {0xD7CB, 0xD7FB}, {0xD800, 0xDB7F}, + {0xDB80, 0xDBFF}, {0xDC00, 0xDFFF}, {0xFB00, 0xFB06}, + {0xFB13, 0xFB17}, {0xFB1D, 0xFB1D}, {0xFB1E, 0xFB1E}, + {0xFB1F, 0xFB28}, {0xFB29, 0xFB29}, {0xFB2A, 0xFB36}, + {0xFB38, 0xFB3C}, {0xFB3E, 0xFB3E}, {0xFB40, 0xFB41}, + {0xFB43, 0xFB44}, {0xFB46, 0xFB4F}, {0xFB50, 0xFBB1}, + {0xFBB2, 0xFBC1}, {0xFBD3, 0xFD3D}, {0xFD3E, 0xFD3E}, + {0xFD3F, 0xFD3F}, {0xFD50, 0xFD8F}, {0xFD92, 0xFDC7}, + {0xFDF0, 0xFDFB}, {0xFDFC, 0xFDFC}, {0xFDFD, 0xFDFD}, + {0xFE20, 0xFE2F}, {0xFE70, 0xFE74}, {0xFE76, 0xFEFC}, + {0xFEFF, 0xFEFF}, {0xFFF9, 0xFFFB}, {0xFFFC, 0xFFFC}, + {0x10000, 0x1000B}, {0x1000D, 0x10026}, {0x10028, 0x1003A}, + {0x1003C, 0x1003D}, {0x1003F, 0x1004D}, {0x10050, 0x1005D}, + {0x10080, 0x100FA}, {0x10100, 0x10102}, {0x10107, 0x10133}, + {0x10137, 0x1013F}, {0x10140, 0x10174}, {0x10175, 0x10178}, + {0x10179, 0x10189}, {0x1018A, 0x1018B}, {0x1018C, 0x1018E}, + {0x10190, 0x1019B}, {0x101A0, 0x101A0}, {0x101D0, 0x101FC}, + {0x101FD, 0x101FD}, {0x10280, 0x1029C}, {0x102A0, 0x102D0}, + {0x102E0, 0x102E0}, {0x102E1, 0x102FB}, {0x10300, 0x1031F}, + {0x10320, 0x10323}, {0x10330, 0x10340}, {0x10341, 0x10341}, + {0x10342, 0x10349}, {0x1034A, 0x1034A}, {0x10350, 0x10375}, + {0x10376, 0x1037A}, {0x10380, 0x1039D}, {0x1039F, 0x1039F}, + {0x103A0, 0x103C3}, {0x103C8, 0x103CF}, {0x103D0, 0x103D0}, + {0x103D1, 0x103D5}, {0x10400, 0x1044F}, {0x10450, 0x1047F}, + {0x10480, 0x1049D}, {0x104A0, 0x104A9}, {0x104B0, 0x104D3}, + {0x104D8, 0x104FB}, {0x10500, 0x10527}, {0x10530, 0x10563}, + {0x1056F, 0x1056F}, {0x10600, 0x10736}, {0x10740, 0x10755}, + {0x10760, 0x10767}, {0x10800, 0x10805}, {0x10808, 0x10808}, + {0x1080A, 0x10835}, {0x10837, 0x10838}, {0x1083C, 0x1083C}, + {0x1083F, 0x1083F}, {0x10840, 0x10855}, {0x10857, 0x10857}, + {0x10858, 0x1085F}, {0x10860, 0x10876}, {0x10877, 0x10878}, + {0x10879, 0x1087F}, {0x10880, 0x1089E}, {0x108A7, 0x108AF}, + {0x108E0, 0x108F2}, {0x108F4, 0x108F5}, {0x108FB, 0x108FF}, + {0x10900, 0x10915}, {0x10916, 0x1091B}, {0x1091F, 0x1091F}, + {0x10920, 0x10939}, {0x1093F, 0x1093F}, {0x10980, 0x1099F}, + {0x109A0, 0x109B7}, {0x109BC, 0x109BD}, {0x109BE, 0x109BF}, + {0x109C0, 0x109CF}, {0x109D2, 0x109FF}, {0x10A00, 0x10A00}, + {0x10A01, 0x10A03}, {0x10A05, 0x10A06}, {0x10A0C, 0x10A0F}, + {0x10A10, 0x10A13}, {0x10A15, 0x10A17}, {0x10A19, 0x10A33}, + {0x10A38, 0x10A3A}, {0x10A3F, 0x10A3F}, {0x10A40, 0x10A47}, + {0x10A50, 0x10A58}, {0x10A60, 0x10A7C}, {0x10A7D, 0x10A7E}, + {0x10A7F, 0x10A7F}, {0x10A80, 0x10A9C}, {0x10A9D, 0x10A9F}, + {0x10AC0, 0x10AC7}, {0x10AC8, 0x10AC8}, {0x10AC9, 0x10AE4}, + {0x10AE5, 0x10AE6}, {0x10AEB, 0x10AEF}, {0x10AF0, 0x10AF6}, + {0x10B00, 0x10B35}, {0x10B39, 0x10B3F}, {0x10B40, 0x10B55}, + {0x10B58, 0x10B5F}, {0x10B60, 0x10B72}, {0x10B78, 0x10B7F}, + {0x10B80, 0x10B91}, {0x10B99, 0x10B9C}, {0x10BA9, 0x10BAF}, + {0x10C00, 0x10C48}, {0x10C80, 0x10CB2}, {0x10CC0, 0x10CF2}, + {0x10CFA, 0x10CFF}, {0x10E60, 0x10E7E}, {0x11000, 0x11000}, + {0x11001, 0x11001}, {0x11002, 0x11002}, {0x11003, 0x11037}, + {0x11038, 0x11046}, {0x11047, 0x1104D}, {0x11052, 0x11065}, + {0x11066, 0x1106F}, {0x1107F, 0x1107F}, {0x11080, 0x11081}, + {0x11082, 0x11082}, {0x11083, 0x110AF}, {0x110B0, 0x110B2}, + {0x110B3, 0x110B6}, {0x110B7, 0x110B8}, {0x110B9, 0x110BA}, + {0x110BB, 0x110BC}, {0x110BD, 0x110BD}, {0x110BE, 0x110C1}, + {0x110D0, 0x110E8}, {0x110F0, 0x110F9}, {0x11100, 0x11102}, + {0x11103, 0x11126}, {0x11127, 0x1112B}, {0x1112C, 0x1112C}, + {0x1112D, 0x11134}, {0x11136, 0x1113F}, {0x11140, 0x11143}, + {0x11150, 0x11172}, {0x11173, 0x11173}, {0x11174, 0x11175}, + {0x11176, 0x11176}, {0x11180, 0x11181}, {0x11182, 0x11182}, + {0x11183, 0x111B2}, {0x111B3, 0x111B5}, {0x111B6, 0x111BE}, + {0x111BF, 0x111C0}, {0x111C1, 0x111C4}, {0x111C5, 0x111C9}, + {0x111CA, 0x111CC}, {0x111CD, 0x111CD}, {0x111D0, 0x111D9}, + {0x111DA, 0x111DA}, {0x111DB, 0x111DB}, {0x111DC, 0x111DC}, + {0x111DD, 0x111DF}, {0x111E1, 0x111F4}, {0x11200, 0x11211}, + {0x11213, 0x1122B}, {0x1122C, 0x1122E}, {0x1122F, 0x11231}, + {0x11232, 0x11233}, {0x11234, 0x11234}, {0x11235, 0x11235}, + {0x11236, 0x11237}, {0x11238, 0x1123D}, {0x1123E, 0x1123E}, + {0x11280, 0x11286}, {0x11288, 0x11288}, {0x1128A, 0x1128D}, + {0x1128F, 0x1129D}, {0x1129F, 0x112A8}, {0x112A9, 0x112A9}, + {0x112B0, 0x112DE}, {0x112DF, 0x112DF}, {0x112E0, 0x112E2}, + {0x112E3, 0x112EA}, {0x112F0, 0x112F9}, {0x11300, 0x11301}, + {0x11302, 0x11303}, {0x11305, 0x1130C}, {0x1130F, 0x11310}, + {0x11313, 0x11328}, {0x1132A, 0x11330}, {0x11332, 0x11333}, + {0x11335, 0x11339}, {0x1133C, 0x1133C}, {0x1133D, 0x1133D}, + {0x1133E, 0x1133F}, {0x11340, 0x11340}, {0x11341, 0x11344}, + {0x11347, 0x11348}, {0x1134B, 0x1134D}, {0x11350, 0x11350}, + {0x11357, 0x11357}, {0x1135D, 0x11361}, {0x11362, 0x11363}, + {0x11366, 0x1136C}, {0x11370, 0x11374}, {0x11400, 0x11434}, + {0x11435, 0x11437}, {0x11438, 0x1143F}, {0x11440, 0x11441}, + {0x11442, 0x11444}, {0x11445, 0x11445}, {0x11446, 0x11446}, + {0x11447, 0x1144A}, {0x1144B, 0x1144F}, {0x11450, 0x11459}, + {0x1145B, 0x1145B}, {0x1145D, 0x1145D}, {0x11480, 0x114AF}, + {0x114B0, 0x114B2}, {0x114B3, 0x114B8}, {0x114B9, 0x114B9}, + {0x114BA, 0x114BA}, {0x114BB, 0x114BE}, {0x114BF, 0x114C0}, + {0x114C1, 0x114C1}, {0x114C2, 0x114C3}, {0x114C4, 0x114C5}, + {0x114C6, 0x114C6}, {0x114C7, 0x114C7}, {0x114D0, 0x114D9}, + {0x11580, 0x115AE}, {0x115AF, 0x115B1}, {0x115B2, 0x115B5}, + {0x115B8, 0x115BB}, {0x115BC, 0x115BD}, {0x115BE, 0x115BE}, + {0x115BF, 0x115C0}, {0x115C1, 0x115D7}, {0x115D8, 0x115DB}, + {0x115DC, 0x115DD}, {0x11600, 0x1162F}, {0x11630, 0x11632}, + {0x11633, 0x1163A}, {0x1163B, 0x1163C}, {0x1163D, 0x1163D}, + {0x1163E, 0x1163E}, {0x1163F, 0x11640}, {0x11641, 0x11643}, + {0x11644, 0x11644}, {0x11650, 0x11659}, {0x11660, 0x1166C}, + {0x11680, 0x116AA}, {0x116AB, 0x116AB}, {0x116AC, 0x116AC}, + {0x116AD, 0x116AD}, {0x116AE, 0x116AF}, {0x116B0, 0x116B5}, + {0x116B6, 0x116B6}, {0x116B7, 0x116B7}, {0x116C0, 0x116C9}, + {0x11700, 0x11719}, {0x1171D, 0x1171F}, {0x11720, 0x11721}, + {0x11722, 0x11725}, {0x11726, 0x11726}, {0x11727, 0x1172B}, + {0x11730, 0x11739}, {0x1173A, 0x1173B}, {0x1173C, 0x1173E}, + {0x1173F, 0x1173F}, {0x118A0, 0x118DF}, {0x118E0, 0x118E9}, + {0x118EA, 0x118F2}, {0x118FF, 0x118FF}, {0x11AC0, 0x11AF8}, + {0x11C00, 0x11C08}, {0x11C0A, 0x11C2E}, {0x11C2F, 0x11C2F}, + {0x11C30, 0x11C36}, {0x11C38, 0x11C3D}, {0x11C3E, 0x11C3E}, + {0x11C3F, 0x11C3F}, {0x11C40, 0x11C40}, {0x11C41, 0x11C45}, + {0x11C50, 0x11C59}, {0x11C5A, 0x11C6C}, {0x11C70, 0x11C71}, + {0x11C72, 0x11C8F}, {0x11C92, 0x11CA7}, {0x11CA9, 0x11CA9}, + {0x11CAA, 0x11CB0}, {0x11CB1, 0x11CB1}, {0x11CB2, 0x11CB3}, + {0x11CB4, 0x11CB4}, {0x11CB5, 0x11CB6}, {0x12000, 0x12399}, + {0x12400, 0x1246E}, {0x12470, 0x12474}, {0x12480, 0x12543}, + {0x13000, 0x1342E}, {0x14400, 0x14646}, {0x16800, 0x16A38}, + {0x16A40, 0x16A5E}, {0x16A60, 0x16A69}, {0x16A6E, 0x16A6F}, + {0x16AD0, 0x16AED}, {0x16AF0, 0x16AF4}, {0x16AF5, 0x16AF5}, + {0x16B00, 0x16B2F}, {0x16B30, 0x16B36}, {0x16B37, 0x16B3B}, + {0x16B3C, 0x16B3F}, {0x16B40, 0x16B43}, {0x16B44, 0x16B44}, + {0x16B45, 0x16B45}, {0x16B50, 0x16B59}, {0x16B5B, 0x16B61}, + {0x16B63, 0x16B77}, {0x16B7D, 0x16B8F}, {0x16F00, 0x16F44}, + {0x16F50, 0x16F50}, {0x16F51, 0x16F7E}, {0x16F8F, 0x16F92}, + {0x16F93, 0x16F9F}, {0x1BC00, 0x1BC6A}, {0x1BC70, 0x1BC7C}, + {0x1BC80, 0x1BC88}, {0x1BC90, 0x1BC99}, {0x1BC9C, 0x1BC9C}, + {0x1BC9D, 0x1BC9E}, {0x1BC9F, 0x1BC9F}, {0x1BCA0, 0x1BCA3}, + {0x1D000, 0x1D0F5}, {0x1D100, 0x1D126}, {0x1D129, 0x1D164}, + {0x1D165, 0x1D166}, {0x1D167, 0x1D169}, {0x1D16A, 0x1D16C}, + {0x1D16D, 0x1D172}, {0x1D173, 0x1D17A}, {0x1D17B, 0x1D182}, + {0x1D183, 0x1D184}, {0x1D185, 0x1D18B}, {0x1D18C, 0x1D1A9}, + {0x1D1AA, 0x1D1AD}, {0x1D1AE, 0x1D1E8}, {0x1D200, 0x1D241}, + {0x1D242, 0x1D244}, {0x1D245, 0x1D245}, {0x1D300, 0x1D356}, + {0x1D360, 0x1D371}, {0x1D400, 0x1D454}, {0x1D456, 0x1D49C}, + {0x1D49E, 0x1D49F}, {0x1D4A2, 0x1D4A2}, {0x1D4A5, 0x1D4A6}, + {0x1D4A9, 0x1D4AC}, {0x1D4AE, 0x1D4B9}, {0x1D4BB, 0x1D4BB}, + {0x1D4BD, 0x1D4C3}, {0x1D4C5, 0x1D505}, {0x1D507, 0x1D50A}, + {0x1D50D, 0x1D514}, {0x1D516, 0x1D51C}, {0x1D51E, 0x1D539}, + {0x1D53B, 0x1D53E}, {0x1D540, 0x1D544}, {0x1D546, 0x1D546}, + {0x1D54A, 0x1D550}, {0x1D552, 0x1D6A5}, {0x1D6A8, 0x1D6C0}, + {0x1D6C1, 0x1D6C1}, {0x1D6C2, 0x1D6DA}, {0x1D6DB, 0x1D6DB}, + {0x1D6DC, 0x1D6FA}, {0x1D6FB, 0x1D6FB}, {0x1D6FC, 0x1D714}, + {0x1D715, 0x1D715}, {0x1D716, 0x1D734}, {0x1D735, 0x1D735}, + {0x1D736, 0x1D74E}, {0x1D74F, 0x1D74F}, {0x1D750, 0x1D76E}, + {0x1D76F, 0x1D76F}, {0x1D770, 0x1D788}, {0x1D789, 0x1D789}, + {0x1D78A, 0x1D7A8}, {0x1D7A9, 0x1D7A9}, {0x1D7AA, 0x1D7C2}, + {0x1D7C3, 0x1D7C3}, {0x1D7C4, 0x1D7CB}, {0x1D7CE, 0x1D7FF}, + {0x1D800, 0x1D9FF}, {0x1DA00, 0x1DA36}, {0x1DA37, 0x1DA3A}, + {0x1DA3B, 0x1DA6C}, {0x1DA6D, 0x1DA74}, {0x1DA75, 0x1DA75}, + {0x1DA76, 0x1DA83}, {0x1DA84, 0x1DA84}, {0x1DA85, 0x1DA86}, + {0x1DA87, 0x1DA8B}, {0x1DA9B, 0x1DA9F}, {0x1DAA1, 0x1DAAF}, + {0x1E000, 0x1E006}, {0x1E008, 0x1E018}, {0x1E01B, 0x1E021}, + {0x1E023, 0x1E024}, {0x1E026, 0x1E02A}, {0x1E800, 0x1E8C4}, + {0x1E8C7, 0x1E8CF}, {0x1E8D0, 0x1E8D6}, {0x1E900, 0x1E943}, + {0x1E944, 0x1E94A}, {0x1E950, 0x1E959}, {0x1E95E, 0x1E95F}, + {0x1EE00, 0x1EE03}, {0x1EE05, 0x1EE1F}, {0x1EE21, 0x1EE22}, + {0x1EE24, 0x1EE24}, {0x1EE27, 0x1EE27}, {0x1EE29, 0x1EE32}, + {0x1EE34, 0x1EE37}, {0x1EE39, 0x1EE39}, {0x1EE3B, 0x1EE3B}, + {0x1EE42, 0x1EE42}, {0x1EE47, 0x1EE47}, {0x1EE49, 0x1EE49}, + {0x1EE4B, 0x1EE4B}, {0x1EE4D, 0x1EE4F}, {0x1EE51, 0x1EE52}, + {0x1EE54, 0x1EE54}, {0x1EE57, 0x1EE57}, {0x1EE59, 0x1EE59}, + {0x1EE5B, 0x1EE5B}, {0x1EE5D, 0x1EE5D}, {0x1EE5F, 0x1EE5F}, + {0x1EE61, 0x1EE62}, {0x1EE64, 0x1EE64}, {0x1EE67, 0x1EE6A}, + {0x1EE6C, 0x1EE72}, {0x1EE74, 0x1EE77}, {0x1EE79, 0x1EE7C}, + {0x1EE7E, 0x1EE7E}, {0x1EE80, 0x1EE89}, {0x1EE8B, 0x1EE9B}, + {0x1EEA1, 0x1EEA3}, {0x1EEA5, 0x1EEA9}, {0x1EEAB, 0x1EEBB}, + {0x1EEF0, 0x1EEF1}, {0x1F000, 0x1F003}, {0x1F005, 0x1F02B}, + {0x1F030, 0x1F093}, {0x1F0A0, 0x1F0AE}, {0x1F0B1, 0x1F0BF}, + {0x1F0C1, 0x1F0CE}, {0x1F0D1, 0x1F0F5}, {0x1F10B, 0x1F10C}, + {0x1F12E, 0x1F12E}, {0x1F16A, 0x1F16B}, {0x1F1E6, 0x1F1FF}, + {0x1F321, 0x1F32C}, {0x1F336, 0x1F336}, {0x1F37D, 0x1F37D}, + {0x1F394, 0x1F39F}, {0x1F3CB, 0x1F3CE}, {0x1F3D4, 0x1F3DF}, + {0x1F3F1, 0x1F3F3}, {0x1F3F5, 0x1F3F7}, {0x1F43F, 0x1F43F}, + {0x1F441, 0x1F441}, {0x1F4FD, 0x1F4FE}, {0x1F53E, 0x1F54A}, + {0x1F54F, 0x1F54F}, {0x1F568, 0x1F579}, {0x1F57B, 0x1F594}, + {0x1F597, 0x1F5A3}, {0x1F5A5, 0x1F5FA}, {0x1F650, 0x1F67F}, + {0x1F6C6, 0x1F6CB}, {0x1F6CD, 0x1F6CF}, {0x1F6E0, 0x1F6EA}, + {0x1F6F0, 0x1F6F3}, {0x1F700, 0x1F773}, {0x1F780, 0x1F7D4}, + {0x1F800, 0x1F80B}, {0x1F810, 0x1F847}, {0x1F850, 0x1F859}, + {0x1F860, 0x1F887}, {0x1F890, 0x1F8AD}, {0xE0001, 0xE0001}, + {0xE0020, 0xE007F}, +} + +// Condition have flag EastAsianWidth whether the current locale is CJK or not. +type Condition struct { + EastAsianWidth bool +} + +// NewCondition return new instance of Condition which is current locale. +func NewCondition() *Condition { + return &Condition{EastAsianWidth} +} + +// RuneWidth returns the number of cells in r. +// See http://www.unicode.org/reports/tr11/ +func (c *Condition) RuneWidth(r rune) int { + switch { + case r < 0 || r > 0x10FFFF || + inTables(r, nonprint, combining, notassigned): + return 0 + case (c.EastAsianWidth && IsAmbiguousWidth(r)) || + inTables(r, doublewidth, emoji): + return 2 + default: + return 1 + } +} + +// StringWidth return width as you can see +func (c *Condition) StringWidth(s string) (width int) { + for _, r := range []rune(s) { + width += c.RuneWidth(r) + } + return width +} + +// Truncate return string truncated with w cells +func (c *Condition) Truncate(s string, w int, tail string) string { + if c.StringWidth(s) <= w { + return s + } + r := []rune(s) + tw := c.StringWidth(tail) + w -= tw + width := 0 + i := 0 + for ; i < len(r); i++ { + cw := c.RuneWidth(r[i]) + if width+cw > w { + break + } + width += cw + } + return string(r[0:i]) + tail +} + +// Wrap return string wrapped with w cells +func (c *Condition) Wrap(s string, w int) string { + width := 0 + out := "" + for _, r := range []rune(s) { + cw := RuneWidth(r) + if r == '\n' { + out += string(r) + width = 0 + continue + } else if width+cw > w { + out += "\n" + width = 0 + out += string(r) + width += cw + continue + } + out += string(r) + width += cw + } + return out +} + +// FillLeft return string filled in left by spaces in w cells +func (c *Condition) FillLeft(s string, w int) string { + width := c.StringWidth(s) + count := w - width + if count > 0 { + b := make([]byte, count) + for i := range b { + b[i] = ' ' + } + return string(b) + s + } + return s +} + +// FillRight return string filled in left by spaces in w cells +func (c *Condition) FillRight(s string, w int) string { + width := c.StringWidth(s) + count := w - width + if count > 0 { + b := make([]byte, count) + for i := range b { + b[i] = ' ' + } + return s + string(b) + } + return s +} + +// RuneWidth returns the number of cells in r. +// See http://www.unicode.org/reports/tr11/ +func RuneWidth(r rune) int { + return DefaultCondition.RuneWidth(r) +} + +// IsAmbiguousWidth returns whether is ambiguous width or not. +func IsAmbiguousWidth(r rune) bool { + return inTables(r, private, ambiguous) +} + +// IsNeutralWidth returns whether is neutral width or not. +func IsNeutralWidth(r rune) bool { + return inTable(r, neutral) +} + +// StringWidth return width as you can see +func StringWidth(s string) (width int) { + return DefaultCondition.StringWidth(s) +} + +// Truncate return string truncated with w cells +func Truncate(s string, w int, tail string) string { + return DefaultCondition.Truncate(s, w, tail) +} + +// Wrap return string wrapped with w cells +func Wrap(s string, w int) string { + return DefaultCondition.Wrap(s, w) +} + +// FillLeft return string filled in left by spaces in w cells +func FillLeft(s string, w int) string { + return DefaultCondition.FillLeft(s, w) +} + +// FillRight return string filled in left by spaces in w cells +func FillRight(s string, w int) string { + return DefaultCondition.FillRight(s, w) +} diff --git a/vendor/github.com/mattn/go-runewidth/runewidth_js.go b/vendor/github.com/mattn/go-runewidth/runewidth_js.go new file mode 100644 index 00000000..0ce32c5e --- /dev/null +++ b/vendor/github.com/mattn/go-runewidth/runewidth_js.go @@ -0,0 +1,8 @@ +// +build js + +package runewidth + +func IsEastAsian() bool { + // TODO: Implement this for the web. Detect east asian in a compatible way, and return true. + return false +} diff --git a/vendor/github.com/mattn/go-runewidth/runewidth_posix.go b/vendor/github.com/mattn/go-runewidth/runewidth_posix.go new file mode 100644 index 00000000..c579e9a3 --- /dev/null +++ b/vendor/github.com/mattn/go-runewidth/runewidth_posix.go @@ -0,0 +1,77 @@ +// +build !windows,!js + +package runewidth + +import ( + "os" + "regexp" + "strings" +) + +var reLoc = regexp.MustCompile(`^[a-z][a-z][a-z]?(?:_[A-Z][A-Z])?\.(.+)`) + +var mblenTable = map[string]int{ + "utf-8": 6, + "utf8": 6, + "jis": 8, + "eucjp": 3, + "euckr": 2, + "euccn": 2, + "sjis": 2, + "cp932": 2, + "cp51932": 2, + "cp936": 2, + "cp949": 2, + "cp950": 2, + "big5": 2, + "gbk": 2, + "gb2312": 2, +} + +func isEastAsian(locale string) bool { + charset := strings.ToLower(locale) + r := reLoc.FindStringSubmatch(locale) + if len(r) == 2 { + charset = strings.ToLower(r[1]) + } + + if strings.HasSuffix(charset, "@cjk_narrow") { + return false + } + + for pos, b := range []byte(charset) { + if b == '@' { + charset = charset[:pos] + break + } + } + max := 1 + if m, ok := mblenTable[charset]; ok { + max = m + } + if max > 1 && (charset[0] != 'u' || + strings.HasPrefix(locale, "ja") || + strings.HasPrefix(locale, "ko") || + strings.HasPrefix(locale, "zh")) { + return true + } + return false +} + +// IsEastAsian return true if the current locale is CJK +func IsEastAsian() bool { + locale := os.Getenv("LC_CTYPE") + if locale == "" { + locale = os.Getenv("LANG") + } + + // ignore C locale + if locale == "POSIX" || locale == "C" { + return false + } + if len(locale) > 1 && locale[0] == 'C' && (locale[1] == '.' || locale[1] == '-') { + return false + } + + return isEastAsian(locale) +} diff --git a/vendor/github.com/mattn/go-runewidth/runewidth_test.go b/vendor/github.com/mattn/go-runewidth/runewidth_test.go new file mode 100644 index 00000000..b0378a19 --- /dev/null +++ b/vendor/github.com/mattn/go-runewidth/runewidth_test.go @@ -0,0 +1,275 @@ +package runewidth + +import ( + "sort" + "testing" +) + +var _ sort.Interface = (*table)(nil) + +func (t table) Len() int { + return len(t) +} + +func (t table) Less(i, j int) bool { + return t[i].first < t[j].first +} + +func (t *table) Swap(i, j int) { + (*t)[i], (*t)[j] = (*t)[j], (*t)[i] +} + +var tables = []table{ + private, + nonprint, + combining, + doublewidth, + ambiguous, + emoji, + notassigned, + neutral, +} + +func TestSorted(t *testing.T) { + for _, tbl := range tables { + if !sort.IsSorted(&tbl) { + t.Errorf("not sorted") + } + } +} + +var runewidthtests = []struct { + in rune + out int + eaout int +}{ + {'世', 2, 2}, + {'界', 2, 2}, + {'セ', 1, 1}, + {'カ', 1, 1}, + {'イ', 1, 1}, + {'☆', 1, 2}, // double width in ambiguous + {'\x00', 0, 0}, + {'\x01', 0, 0}, + {'\u0300', 0, 0}, +} + +func TestRuneWidth(t *testing.T) { + c := NewCondition() + for _, tt := range runewidthtests { + if out := c.RuneWidth(tt.in); out != tt.out { + t.Errorf("RuneWidth(%q) = %d, want %d", tt.in, out, tt.out) + } + } + c.EastAsianWidth = true + for _, tt := range runewidthtests { + if out := c.RuneWidth(tt.in); out != tt.eaout { + t.Errorf("RuneWidth(%q) = %d, want %d", tt.in, out, tt.eaout) + } + } +} + +var isambiguouswidthtests = []struct { + in rune + out bool +}{ + {'世', false}, + {'■', true}, + {'界', false}, + {'○', true}, + {'㈱', false}, + {'①', true}, + {'②', true}, + {'③', true}, + {'④', true}, + {'⑤', true}, + {'⑥', true}, + {'⑦', true}, + {'⑧', true}, + {'⑨', true}, + {'⑩', true}, + {'⑪', true}, + {'⑫', true}, + {'⑬', true}, + {'⑭', true}, + {'⑮', true}, + {'⑯', true}, + {'⑰', true}, + {'⑱', true}, + {'⑲', true}, + {'⑳', true}, + {'☆', true}, +} + +func TestIsAmbiguousWidth(t *testing.T) { + for _, tt := range isambiguouswidthtests { + if out := IsAmbiguousWidth(tt.in); out != tt.out { + t.Errorf("IsAmbiguousWidth(%q) = %v, want %v", tt.in, out, tt.out) + } + } +} + +var stringwidthtests = []struct { + in string + out int + eaout int +}{ + {"■㈱の世界①", 10, 12}, + {"スター☆", 7, 8}, + {"つのだ☆HIRO", 11, 12}, +} + +func TestStringWidth(t *testing.T) { + c := NewCondition() + for _, tt := range stringwidthtests { + if out := c.StringWidth(tt.in); out != tt.out { + t.Errorf("StringWidth(%q) = %q, want %q", tt.in, out, tt.out) + } + } + c.EastAsianWidth = true + for _, tt := range stringwidthtests { + if out := c.StringWidth(tt.in); out != tt.eaout { + t.Errorf("StringWidth(%q) = %q, want %q", tt.in, out, tt.eaout) + } + } +} + +func TestStringWidthInvalid(t *testing.T) { + s := "こんにちわ\x00世界" + if out := StringWidth(s); out != 14 { + t.Errorf("StringWidth(%q) = %q, want %q", s, out, 14) + } +} + +func TestTruncateSmaller(t *testing.T) { + s := "あいうえお" + expected := "あいうえお" + + if out := Truncate(s, 10, "..."); out != expected { + t.Errorf("Truncate(%q) = %q, want %q", s, out, expected) + } +} + +func TestTruncate(t *testing.T) { + s := "あいうえおあいうえおえおおおおおおおおおおおおおおおおおおおおおおおおおおおおおお" + expected := "あいうえおあいうえおえおおおおおおおおおおおおおおおおおおおおおおおおおおお..." + out := Truncate(s, 80, "...") + if out != expected { + t.Errorf("Truncate(%q) = %q, want %q", s, out, expected) + } + width := StringWidth(out) + if width != 79 { + t.Errorf("width of Truncate(%q) should be %d, but %d", s, 79, width) + } +} + +func TestTruncateFit(t *testing.T) { + s := "aあいうえおあいうえおえおおおおおおおおおおおおおおおおおおおおおおおおおおおおおお" + expected := "aあいうえおあいうえおえおおおおおおおおおおおおおおおおおおおおおおおおおおお..." + + out := Truncate(s, 80, "...") + if out != expected { + t.Errorf("Truncate(%q) = %q, want %q", s, out, expected) + } + width := StringWidth(out) + if width != 80 { + t.Errorf("width of Truncate(%q) should be %d, but %d", s, 80, width) + } +} + +func TestTruncateJustFit(t *testing.T) { + s := "あいうえおあいうえおえおおおおおおおおおおおおおおおおおおおおおおおおおおおおお" + expected := "あいうえおあいうえおえおおおおおおおおおおおおおおおおおおおおおおおおおおおおお" + + out := Truncate(s, 80, "...") + if out != expected { + t.Errorf("Truncate(%q) = %q, want %q", s, out, expected) + } + width := StringWidth(out) + if width != 80 { + t.Errorf("width of Truncate(%q) should be %d, but %d", s, 80, width) + } +} + +func TestWrap(t *testing.T) { + s := `東京特許許可局局長はよく柿喰う客だ/東京特許許可局局長はよく柿喰う客だ +123456789012345678901234567890 + +END` + expected := `東京特許許可局局長はよく柿喰う +客だ/東京特許許可局局長はよく +柿喰う客だ +123456789012345678901234567890 + +END` + + if out := Wrap(s, 30); out != expected { + t.Errorf("Wrap(%q) = %q, want %q", s, out, expected) + } +} + +func TestTruncateNoNeeded(t *testing.T) { + s := "あいうえおあい" + expected := "あいうえおあい" + + if out := Truncate(s, 80, "..."); out != expected { + t.Errorf("Truncate(%q) = %q, want %q", s, out, expected) + } +} + +var isneutralwidthtests = []struct { + in rune + out bool +}{ + {'→', false}, + {'┊', false}, + {'┈', false}, + {'~', false}, + {'└', false}, + {'⣀', true}, + {'⣀', true}, +} + +func TestIsNeutralWidth(t *testing.T) { + for _, tt := range isneutralwidthtests { + if out := IsNeutralWidth(tt.in); out != tt.out { + t.Errorf("IsNeutralWidth(%q) = %v, want %v", tt.in, out, tt.out) + } + } +} + +func TestFillLeft(t *testing.T) { + s := "あxいうえお" + expected := " あxいうえお" + + if out := FillLeft(s, 15); out != expected { + t.Errorf("FillLeft(%q) = %q, want %q", s, out, expected) + } +} + +func TestFillLeftFit(t *testing.T) { + s := "あいうえお" + expected := "あいうえお" + + if out := FillLeft(s, 10); out != expected { + t.Errorf("FillLeft(%q) = %q, want %q", s, out, expected) + } +} + +func TestFillRight(t *testing.T) { + s := "あxいうえお" + expected := "あxいうえお " + + if out := FillRight(s, 15); out != expected { + t.Errorf("FillRight(%q) = %q, want %q", s, out, expected) + } +} + +func TestFillRightFit(t *testing.T) { + s := "あいうえお" + expected := "あいうえお" + + if out := FillRight(s, 10); out != expected { + t.Errorf("FillRight(%q) = %q, want %q", s, out, expected) + } +} diff --git a/vendor/github.com/mattn/go-runewidth/runewidth_windows.go b/vendor/github.com/mattn/go-runewidth/runewidth_windows.go new file mode 100644 index 00000000..0258876b --- /dev/null +++ b/vendor/github.com/mattn/go-runewidth/runewidth_windows.go @@ -0,0 +1,25 @@ +package runewidth + +import ( + "syscall" +) + +var ( + kernel32 = syscall.NewLazyDLL("kernel32") + procGetConsoleOutputCP = kernel32.NewProc("GetConsoleOutputCP") +) + +// IsEastAsian return true if the current locale is CJK +func IsEastAsian() bool { + r1, _, _ := procGetConsoleOutputCP.Call() + if r1 == 0 { + return false + } + + switch int(r1) { + case 932, 51932, 936, 949, 950: + return true + } + + return false +} diff --git a/vendor/github.com/olekukonko/tablewriter/.travis.yml b/vendor/github.com/olekukonko/tablewriter/.travis.yml new file mode 100644 index 00000000..f156b3b8 --- /dev/null +++ b/vendor/github.com/olekukonko/tablewriter/.travis.yml @@ -0,0 +1,12 @@ +language: go + +go: + - 1.1 + - 1.2 + - 1.3 + - 1.4 + - 1.5 + - 1.6 + - 1.7 + - 1.8 + - tip diff --git a/vendor/github.com/olekukonko/tablewriter/LICENCE.md b/vendor/github.com/olekukonko/tablewriter/LICENCE.md new file mode 100644 index 00000000..1fd84842 --- /dev/null +++ b/vendor/github.com/olekukonko/tablewriter/LICENCE.md @@ -0,0 +1,19 @@ +Copyright (C) 2014 by Oleku Konko + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. \ No newline at end of file diff --git a/vendor/github.com/olekukonko/tablewriter/README.md b/vendor/github.com/olekukonko/tablewriter/README.md new file mode 100644 index 00000000..d7c36481 --- /dev/null +++ b/vendor/github.com/olekukonko/tablewriter/README.md @@ -0,0 +1,277 @@ +ASCII Table Writer +========= + +[![Build Status](https://travis-ci.org/olekukonko/tablewriter.png?branch=master)](https://travis-ci.org/olekukonko/tablewriter) +[![Total views](https://img.shields.io/sourcegraph/rrc/github.com/olekukonko/tablewriter.svg)](https://sourcegraph.com/github.com/olekukonko/tablewriter) +[![Godoc](https://godoc.org/github.com/olekukonko/tablewriter?status.svg)](https://godoc.org/github.com/olekukonko/tablewriter) + +Generate ASCII table on the fly ... Installation is simple as + + go get github.com/olekukonko/tablewriter + + +#### Features +- Automatic Padding +- Support Multiple Lines +- Supports Alignment +- Support Custom Separators +- Automatic Alignment of numbers & percentage +- Write directly to http , file etc via `io.Writer` +- Read directly from CSV file +- Optional row line via `SetRowLine` +- Normalise table header +- Make CSV Headers optional +- Enable or disable table border +- Set custom footer support +- Optional identical cells merging +- Set custom caption +- Optional reflowing of paragrpahs in multi-line cells. + +#### Example 1 - Basic +```go +data := [][]string{ + []string{"A", "The Good", "500"}, + []string{"B", "The Very very Bad Man", "288"}, + []string{"C", "The Ugly", "120"}, + []string{"D", "The Gopher", "800"}, +} + +table := tablewriter.NewWriter(os.Stdout) +table.SetHeader([]string{"Name", "Sign", "Rating"}) + +for _, v := range data { + table.Append(v) +} +table.Render() // Send output +``` + +##### Output 1 +``` ++------+-----------------------+--------+ +| NAME | SIGN | RATING | ++------+-----------------------+--------+ +| A | The Good | 500 | +| B | The Very very Bad Man | 288 | +| C | The Ugly | 120 | +| D | The Gopher | 800 | ++------+-----------------------+--------+ +``` + +#### Example 2 - Without Border / Footer / Bulk Append +```go +data := [][]string{ + []string{"1/1/2014", "Domain name", "2233", "$10.98"}, + []string{"1/1/2014", "January Hosting", "2233", "$54.95"}, + []string{"1/4/2014", "February Hosting", "2233", "$51.00"}, + []string{"1/4/2014", "February Extra Bandwidth", "2233", "$30.00"}, +} + +table := tablewriter.NewWriter(os.Stdout) +table.SetHeader([]string{"Date", "Description", "CV2", "Amount"}) +table.SetFooter([]string{"", "", "Total", "$146.93"}) // Add Footer +table.SetBorder(false) // Set Border to false +table.AppendBulk(data) // Add Bulk Data +table.Render() +``` + +##### Output 2 +``` + + DATE | DESCRIPTION | CV2 | AMOUNT ++----------+--------------------------+-------+---------+ + 1/1/2014 | Domain name | 2233 | $10.98 + 1/1/2014 | January Hosting | 2233 | $54.95 + 1/4/2014 | February Hosting | 2233 | $51.00 + 1/4/2014 | February Extra Bandwidth | 2233 | $30.00 ++----------+--------------------------+-------+---------+ + TOTAL | $146 93 + +-------+---------+ + +``` + + +#### Example 3 - CSV +```go +table, _ := tablewriter.NewCSV(os.Stdout, "test_info.csv", true) +table.SetAlignment(tablewriter.ALIGN_LEFT) // Set Alignment +table.Render() +``` + +##### Output 3 +``` ++----------+--------------+------+-----+---------+----------------+ +| FIELD | TYPE | NULL | KEY | DEFAULT | EXTRA | ++----------+--------------+------+-----+---------+----------------+ +| user_id | smallint(5) | NO | PRI | NULL | auto_increment | +| username | varchar(10) | NO | | NULL | | +| password | varchar(100) | NO | | NULL | | ++----------+--------------+------+-----+---------+----------------+ +``` + +#### Example 4 - Custom Separator +```go +table, _ := tablewriter.NewCSV(os.Stdout, "test.csv", true) +table.SetRowLine(true) // Enable row line + +// Change table lines +table.SetCenterSeparator("*") +table.SetColumnSeparator("‡") +table.SetRowSeparator("-") + +table.SetAlignment(tablewriter.ALIGN_LEFT) +table.Render() +``` + +##### Output 4 +``` +*------------*-----------*---------* +╪ FIRST NAME ╪ LAST NAME ╪ SSN ╪ +*------------*-----------*---------* +╪ John ╪ Barry ╪ 123456 ╪ +*------------*-----------*---------* +╪ Kathy ╪ Smith ╪ 687987 ╪ +*------------*-----------*---------* +╪ Bob ╪ McCornick ╪ 3979870 ╪ +*------------*-----------*---------* +``` + +#### Example 5 - Markdown Format +```go +data := [][]string{ + []string{"1/1/2014", "Domain name", "2233", "$10.98"}, + []string{"1/1/2014", "January Hosting", "2233", "$54.95"}, + []string{"1/4/2014", "February Hosting", "2233", "$51.00"}, + []string{"1/4/2014", "February Extra Bandwidth", "2233", "$30.00"}, +} + +table := tablewriter.NewWriter(os.Stdout) +table.SetHeader([]string{"Date", "Description", "CV2", "Amount"}) +table.SetBorders(tablewriter.Border{Left: true, Top: false, Right: true, Bottom: false}) +table.SetCenterSeparator("|") +table.AppendBulk(data) // Add Bulk Data +table.Render() +``` + +##### Output 5 +``` +| DATE | DESCRIPTION | CV2 | AMOUNT | +|----------|--------------------------|------|--------| +| 1/1/2014 | Domain name | 2233 | $10.98 | +| 1/1/2014 | January Hosting | 2233 | $54.95 | +| 1/4/2014 | February Hosting | 2233 | $51.00 | +| 1/4/2014 | February Extra Bandwidth | 2233 | $30.00 | +``` + +#### Example 6 - Identical cells merging +```go +data := [][]string{ + []string{"1/1/2014", "Domain name", "1234", "$10.98"}, + []string{"1/1/2014", "January Hosting", "2345", "$54.95"}, + []string{"1/4/2014", "February Hosting", "3456", "$51.00"}, + []string{"1/4/2014", "February Extra Bandwidth", "4567", "$30.00"}, +} + +table := tablewriter.NewWriter(os.Stdout) +table.SetHeader([]string{"Date", "Description", "CV2", "Amount"}) +table.SetFooter([]string{"", "", "Total", "$146.93"}) +table.SetAutoMergeCells(true) +table.SetRowLine(true) +table.AppendBulk(data) +table.Render() +``` + +##### Output 6 +``` ++----------+--------------------------+-------+---------+ +| DATE | DESCRIPTION | CV2 | AMOUNT | ++----------+--------------------------+-------+---------+ +| 1/1/2014 | Domain name | 1234 | $10.98 | ++ +--------------------------+-------+---------+ +| | January Hosting | 2345 | $54.95 | ++----------+--------------------------+-------+---------+ +| 1/4/2014 | February Hosting | 3456 | $51.00 | ++ +--------------------------+-------+---------+ +| | February Extra Bandwidth | 4567 | $30.00 | ++----------+--------------------------+-------+---------+ +| TOTAL | $146 93 | ++----------+--------------------------+-------+---------+ +``` + + +#### Table with color +```go +data := [][]string{ + []string{"1/1/2014", "Domain name", "2233", "$10.98"}, + []string{"1/1/2014", "January Hosting", "2233", "$54.95"}, + []string{"1/4/2014", "February Hosting", "2233", "$51.00"}, + []string{"1/4/2014", "February Extra Bandwidth", "2233", "$30.00"}, +} + +table := tablewriter.NewWriter(os.Stdout) +table.SetHeader([]string{"Date", "Description", "CV2", "Amount"}) +table.SetFooter([]string{"", "", "Total", "$146.93"}) // Add Footer +table.SetBorder(false) // Set Border to false + +table.SetHeaderColor(tablewriter.Colors{tablewriter.Bold, tablewriter.BgGreenColor}, + tablewriter.Colors{tablewriter.FgHiRedColor, tablewriter.Bold, tablewriter.BgBlackColor}, + tablewriter.Colors{tablewriter.BgRedColor, tablewriter.FgWhiteColor}, + tablewriter.Colors{tablewriter.BgCyanColor, tablewriter.FgWhiteColor}) + +table.SetColumnColor(tablewriter.Colors{tablewriter.Bold, tablewriter.FgHiBlackColor}, + tablewriter.Colors{tablewriter.Bold, tablewriter.FgHiRedColor}, + tablewriter.Colors{tablewriter.Bold, tablewriter.FgHiBlackColor}, + tablewriter.Colors{tablewriter.Bold, tablewriter.FgBlackColor}) + +table.SetFooterColor(tablewriter.Colors{}, tablewriter.Colors{}, + tablewriter.Colors{tablewriter.Bold}, + tablewriter.Colors{tablewriter.FgHiRedColor}) + +table.AppendBulk(data) +table.Render() +``` + +#### Table with color Output +![Table with Color](https://cloud.githubusercontent.com/assets/6460392/21101956/bbc7b356-c0a1-11e6-9f36-dba694746efc.png) + +#### Example 6 - Set table caption +```go +data := [][]string{ + []string{"A", "The Good", "500"}, + []string{"B", "The Very very Bad Man", "288"}, + []string{"C", "The Ugly", "120"}, + []string{"D", "The Gopher", "800"}, +} + +table := tablewriter.NewWriter(os.Stdout) +table.SetHeader([]string{"Name", "Sign", "Rating"}) +table.SetCaption(true, "Movie ratings.") + +for _, v := range data { + table.Append(v) +} +table.Render() // Send output +``` + +Note: Caption text will wrap with total width of rendered table. + +##### Output 6 +``` ++------+-----------------------+--------+ +| NAME | SIGN | RATING | ++------+-----------------------+--------+ +| A | The Good | 500 | +| B | The Very very Bad Man | 288 | +| C | The Ugly | 120 | +| D | The Gopher | 800 | ++------+-----------------------+--------+ +Movie ratings. +``` + +#### TODO +- ~~Import Directly from CSV~~ - `done` +- ~~Support for `SetFooter`~~ - `done` +- ~~Support for `SetBorder`~~ - `done` +- ~~Support table with uneven rows~~ - `done` +- ~~Support custom alignment~~ +- General Improvement & Optimisation +- `NewHTML` Parse table from HTML diff --git a/vendor/github.com/olekukonko/tablewriter/csv.go b/vendor/github.com/olekukonko/tablewriter/csv.go new file mode 100644 index 00000000..98878303 --- /dev/null +++ b/vendor/github.com/olekukonko/tablewriter/csv.go @@ -0,0 +1,52 @@ +// Copyright 2014 Oleku Konko All rights reserved. +// Use of this source code is governed by a MIT +// license that can be found in the LICENSE file. + +// This module is a Table Writer API for the Go Programming Language. +// The protocols were written in pure Go and works on windows and unix systems + +package tablewriter + +import ( + "encoding/csv" + "io" + "os" +) + +// Start A new table by importing from a CSV file +// Takes io.Writer and csv File name +func NewCSV(writer io.Writer, fileName string, hasHeader bool) (*Table, error) { + file, err := os.Open(fileName) + if err != nil { + return &Table{}, err + } + defer file.Close() + csvReader := csv.NewReader(file) + t, err := NewCSVReader(writer, csvReader, hasHeader) + return t, err +} + +// Start a New Table Writer with csv.Reader +// This enables customisation such as reader.Comma = ';' +// See http://golang.org/src/pkg/encoding/csv/reader.go?s=3213:3671#L94 +func NewCSVReader(writer io.Writer, csvReader *csv.Reader, hasHeader bool) (*Table, error) { + t := NewWriter(writer) + if hasHeader { + // Read the first row + headers, err := csvReader.Read() + if err != nil { + return &Table{}, err + } + t.SetHeader(headers) + } + for { + record, err := csvReader.Read() + if err == io.EOF { + break + } else if err != nil { + return &Table{}, err + } + t.Append(record) + } + return t, nil +} diff --git a/vendor/github.com/olekukonko/tablewriter/csv2table/README.md b/vendor/github.com/olekukonko/tablewriter/csv2table/README.md new file mode 100644 index 00000000..6cf5628a --- /dev/null +++ b/vendor/github.com/olekukonko/tablewriter/csv2table/README.md @@ -0,0 +1,43 @@ +ASCII Table Writer Tool +========= + +Generate ASCII table on the fly via command line ... Installation is simple as + +#### Get Tool + + go get github.com/olekukonko/tablewriter/csv2table + +#### Install Tool + + go install github.com/olekukonko/tablewriter/csv2table + + +#### Usage + + csv2table -f test.csv + +#### Support for Piping + + cat test.csv | csv2table -p=true + +#### Output + +``` ++------------+-----------+---------+ +| FIRST NAME | LAST NAME | SSN | ++------------+-----------+---------+ +| John | Barry | 123456 | +| Kathy | Smith | 687987 | +| Bob | McCornick | 3979870 | ++------------+-----------+---------+ +``` + +#### Another Piping with Header set to `false` + + echo dance,with,me | csv2table -p=true -h=false + +#### Output + + +-------+------+-----+ + | dance | with | me | + +-------+------+-----+ diff --git a/vendor/github.com/olekukonko/tablewriter/csv2table/csv2table.go b/vendor/github.com/olekukonko/tablewriter/csv2table/csv2table.go new file mode 100644 index 00000000..5e1d7f24 --- /dev/null +++ b/vendor/github.com/olekukonko/tablewriter/csv2table/csv2table.go @@ -0,0 +1,85 @@ +package main + +import ( + "encoding/csv" + "flag" + "fmt" + "io" + "os" + "unicode/utf8" + + "github.com/olekukonko/tablewriter" +) + +var ( + fileName = flag.String("f", "", "Set file with eg. sample.csv") + delimiter = flag.String("d", ",", "Set CSV File delimiter eg. ,|;|\t ") + header = flag.Bool("h", true, "Set header options eg. true|false ") + align = flag.String("a", "none", "Set aligmement with eg. none|left|right|center") + pipe = flag.Bool("p", false, "Suport for Piping from STDIN") + border = flag.Bool("b", true, "Enable / disable table border") +) + +func main() { + flag.Parse() + fmt.Println() + if *pipe || hasArg("-p") { + process(os.Stdin) + } else { + if *fileName == "" { + fmt.Fprintf(os.Stderr, "Usage of %s:\n", os.Args[0]) + flag.PrintDefaults() + fmt.Println() + os.Exit(1) + } + processFile() + } + fmt.Println() +} + +func hasArg(name string) bool { + for _, v := range os.Args { + if name == v { + return true + } + } + return false +} +func processFile() { + r, err := os.Open(*fileName) + if err != nil { + exit(err) + } + defer r.Close() + process(r) +} +func process(r io.Reader) { + csvReader := csv.NewReader(r) + rune, size := utf8.DecodeRuneInString(*delimiter) + if size == 0 { + rune = ',' + } + csvReader.Comma = rune + + table, err := tablewriter.NewCSVReader(os.Stdout, csvReader, *header) + + if err != nil { + exit(err) + } + + switch *align { + case "left": + table.SetAlignment(tablewriter.ALIGN_LEFT) + case "right": + table.SetAlignment(tablewriter.ALIGN_RIGHT) + case "center": + table.SetAlignment(tablewriter.ALIGN_CENTER) + } + table.SetBorder(*border) + table.Render() +} + +func exit(err error) { + fmt.Fprintf(os.Stderr, "#Error : %s", err) + os.Exit(1) +} diff --git a/vendor/github.com/olekukonko/tablewriter/table.go b/vendor/github.com/olekukonko/tablewriter/table.go new file mode 100644 index 00000000..6bbef96a --- /dev/null +++ b/vendor/github.com/olekukonko/tablewriter/table.go @@ -0,0 +1,839 @@ +// Copyright 2014 Oleku Konko All rights reserved. +// Use of this source code is governed by a MIT +// license that can be found in the LICENSE file. + +// This module is a Table Writer API for the Go Programming Language. +// The protocols were written in pure Go and works on windows and unix systems + +// Create & Generate text based table +package tablewriter + +import ( + "bytes" + "fmt" + "io" + "regexp" + "strings" +) + +const ( + MAX_ROW_WIDTH = 30 +) + +const ( + CENTER = "+" + ROW = "-" + COLUMN = "|" + SPACE = " " + NEWLINE = "\n" +) + +const ( + ALIGN_DEFAULT = iota + ALIGN_CENTER + ALIGN_RIGHT + ALIGN_LEFT +) + +var ( + decimal = regexp.MustCompile(`^-*\d*\.?\d*$`) + percent = regexp.MustCompile(`^-*\d*\.?\d*$%$`) +) + +type Border struct { + Left bool + Right bool + Top bool + Bottom bool +} + +type Table struct { + out io.Writer + rows [][]string + lines [][][]string + cs map[int]int + rs map[int]int + headers [][]string + footers [][]string + caption bool + captionText string + autoFmt bool + autoWrap bool + reflowText bool + mW int + pCenter string + pRow string + pColumn string + tColumn int + tRow int + hAlign int + fAlign int + align int + newLine string + rowLine bool + autoMergeCells bool + hdrLine bool + borders Border + colSize int + headerParams []string + columnsParams []string + footerParams []string + columnsAlign []int +} + +// Start New Table +// Take io.Writer Directly +func NewWriter(writer io.Writer) *Table { + t := &Table{ + out: writer, + rows: [][]string{}, + lines: [][][]string{}, + cs: make(map[int]int), + rs: make(map[int]int), + headers: [][]string{}, + footers: [][]string{}, + caption: false, + captionText: "Table caption.", + autoFmt: true, + autoWrap: true, + reflowText: true, + mW: MAX_ROW_WIDTH, + pCenter: CENTER, + pRow: ROW, + pColumn: COLUMN, + tColumn: -1, + tRow: -1, + hAlign: ALIGN_DEFAULT, + fAlign: ALIGN_DEFAULT, + align: ALIGN_DEFAULT, + newLine: NEWLINE, + rowLine: false, + hdrLine: true, + borders: Border{Left: true, Right: true, Bottom: true, Top: true}, + colSize: -1, + headerParams: []string{}, + columnsParams: []string{}, + footerParams: []string{}, + columnsAlign: []int{}} + return t +} + +// Render table output +func (t *Table) Render() { + if t.borders.Top { + t.printLine(true) + } + t.printHeading() + if t.autoMergeCells { + t.printRowsMergeCells() + } else { + t.printRows() + } + if !t.rowLine && t.borders.Bottom { + t.printLine(true) + } + t.printFooter() + + if t.caption { + t.printCaption() + } +} + +const ( + headerRowIdx = -1 + footerRowIdx = -2 +) + +// Set table header +func (t *Table) SetHeader(keys []string) { + t.colSize = len(keys) + for i, v := range keys { + lines := t.parseDimension(v, i, headerRowIdx) + t.headers = append(t.headers, lines) + } +} + +// Set table Footer +func (t *Table) SetFooter(keys []string) { + //t.colSize = len(keys) + for i, v := range keys { + lines := t.parseDimension(v, i, footerRowIdx) + t.footers = append(t.footers, lines) + } +} + +// Set table Caption +func (t *Table) SetCaption(caption bool, captionText ...string) { + t.caption = caption + if len(captionText) == 1 { + t.captionText = captionText[0] + } +} + +// Turn header autoformatting on/off. Default is on (true). +func (t *Table) SetAutoFormatHeaders(auto bool) { + t.autoFmt = auto +} + +// Turn automatic multiline text adjustment on/off. Default is on (true). +func (t *Table) SetAutoWrapText(auto bool) { + t.autoWrap = auto +} + +// Turn automatic reflowing of multiline text when rewrapping. Default is on (true). +func (t *Table) SetReflowDuringAutoWrap(auto bool) { + t.reflowText = auto +} + +// Set the Default column width +func (t *Table) SetColWidth(width int) { + t.mW = width +} + +// Set the minimal width for a column +func (t *Table) SetColMinWidth(column int, width int) { + t.cs[column] = width +} + +// Set the Column Separator +func (t *Table) SetColumnSeparator(sep string) { + t.pColumn = sep +} + +// Set the Row Separator +func (t *Table) SetRowSeparator(sep string) { + t.pRow = sep +} + +// Set the center Separator +func (t *Table) SetCenterSeparator(sep string) { + t.pCenter = sep +} + +// Set Header Alignment +func (t *Table) SetHeaderAlignment(hAlign int) { + t.hAlign = hAlign +} + +// Set Footer Alignment +func (t *Table) SetFooterAlignment(fAlign int) { + t.fAlign = fAlign +} + +// Set Table Alignment +func (t *Table) SetAlignment(align int) { + t.align = align +} + +func (t *Table) SetColumnAlignment(keys []int) { + for _, v := range keys { + switch v { + case ALIGN_CENTER: + break + case ALIGN_LEFT: + break + case ALIGN_RIGHT: + break + default: + v = ALIGN_DEFAULT + } + t.columnsAlign = append(t.columnsAlign, v) + } +} + +// Set New Line +func (t *Table) SetNewLine(nl string) { + t.newLine = nl +} + +// Set Header Line +// This would enable / disable a line after the header +func (t *Table) SetHeaderLine(line bool) { + t.hdrLine = line +} + +// Set Row Line +// This would enable / disable a line on each row of the table +func (t *Table) SetRowLine(line bool) { + t.rowLine = line +} + +// Set Auto Merge Cells +// This would enable / disable the merge of cells with identical values +func (t *Table) SetAutoMergeCells(auto bool) { + t.autoMergeCells = auto +} + +// Set Table Border +// This would enable / disable line around the table +func (t *Table) SetBorder(border bool) { + t.SetBorders(Border{border, border, border, border}) +} + +func (t *Table) SetBorders(border Border) { + t.borders = border +} + +// Append row to table +func (t *Table) Append(row []string) { + rowSize := len(t.headers) + if rowSize > t.colSize { + t.colSize = rowSize + } + + n := len(t.lines) + line := [][]string{} + for i, v := range row { + + // Detect string width + // Detect String height + // Break strings into words + out := t.parseDimension(v, i, n) + + // Append broken words + line = append(line, out) + } + t.lines = append(t.lines, line) +} + +// Allow Support for Bulk Append +// Eliminates repeated for loops +func (t *Table) AppendBulk(rows [][]string) { + for _, row := range rows { + t.Append(row) + } +} + +// NumLines to get the number of lines +func (t *Table) NumLines() int { + return len(t.lines) +} + +// Clear rows +func (t *Table) ClearRows() { + t.lines = [][][]string{} +} + +// Clear footer +func (t *Table) ClearFooter() { + t.footers = [][]string{} +} + +// Print line based on row width +func (t *Table) printLine(nl bool) { + fmt.Fprint(t.out, t.pCenter) + for i := 0; i < len(t.cs); i++ { + v := t.cs[i] + fmt.Fprintf(t.out, "%s%s%s%s", + t.pRow, + strings.Repeat(string(t.pRow), v), + t.pRow, + t.pCenter) + } + if nl { + fmt.Fprint(t.out, t.newLine) + } +} + +// Print line based on row width with our without cell separator +func (t *Table) printLineOptionalCellSeparators(nl bool, displayCellSeparator []bool) { + fmt.Fprint(t.out, t.pCenter) + for i := 0; i < len(t.cs); i++ { + v := t.cs[i] + if i > len(displayCellSeparator) || displayCellSeparator[i] { + // Display the cell separator + fmt.Fprintf(t.out, "%s%s%s%s", + t.pRow, + strings.Repeat(string(t.pRow), v), + t.pRow, + t.pCenter) + } else { + // Don't display the cell separator for this cell + fmt.Fprintf(t.out, "%s%s", + strings.Repeat(" ", v+2), + t.pCenter) + } + } + if nl { + fmt.Fprint(t.out, t.newLine) + } +} + +// Return the PadRight function if align is left, PadLeft if align is right, +// and Pad by default +func pad(align int) func(string, string, int) string { + padFunc := Pad + switch align { + case ALIGN_LEFT: + padFunc = PadRight + case ALIGN_RIGHT: + padFunc = PadLeft + } + return padFunc +} + +// Print heading information +func (t *Table) printHeading() { + // Check if headers is available + if len(t.headers) < 1 { + return + } + + // Identify last column + end := len(t.cs) - 1 + + // Get pad function + padFunc := pad(t.hAlign) + + // Checking for ANSI escape sequences for header + is_esc_seq := false + if len(t.headerParams) > 0 { + is_esc_seq = true + } + + // Maximum height. + max := t.rs[headerRowIdx] + + // Print Heading + for x := 0; x < max; x++ { + // Check if border is set + // Replace with space if not set + fmt.Fprint(t.out, ConditionString(t.borders.Left, t.pColumn, SPACE)) + + for y := 0; y <= end; y++ { + v := t.cs[y] + h := "" + if y < len(t.headers) && x < len(t.headers[y]) { + h = t.headers[y][x] + } + if t.autoFmt { + h = Title(h) + } + pad := ConditionString((y == end && !t.borders.Left), SPACE, t.pColumn) + + if is_esc_seq { + fmt.Fprintf(t.out, " %s %s", + format(padFunc(h, SPACE, v), + t.headerParams[y]), pad) + } else { + fmt.Fprintf(t.out, " %s %s", + padFunc(h, SPACE, v), + pad) + } + } + // Next line + fmt.Fprint(t.out, t.newLine) + } + if t.hdrLine { + t.printLine(true) + } +} + +// Print heading information +func (t *Table) printFooter() { + // Check if headers is available + if len(t.footers) < 1 { + return + } + + // Only print line if border is not set + if !t.borders.Bottom { + t.printLine(true) + } + + // Identify last column + end := len(t.cs) - 1 + + // Get pad function + padFunc := pad(t.fAlign) + + // Checking for ANSI escape sequences for header + is_esc_seq := false + if len(t.footerParams) > 0 { + is_esc_seq = true + } + + // Maximum height. + max := t.rs[footerRowIdx] + + // Print Footer + erasePad := make([]bool, len(t.footers)) + for x := 0; x < max; x++ { + // Check if border is set + // Replace with space if not set + fmt.Fprint(t.out, ConditionString(t.borders.Bottom, t.pColumn, SPACE)) + + for y := 0; y <= end; y++ { + v := t.cs[y] + f := "" + if y < len(t.footers) && x < len(t.footers[y]) { + f = t.footers[y][x] + } + if t.autoFmt { + f = Title(f) + } + pad := ConditionString((y == end && !t.borders.Top), SPACE, t.pColumn) + + if erasePad[y] || (x == 0 && len(f) == 0) { + pad = SPACE + erasePad[y] = true + } + + if is_esc_seq { + fmt.Fprintf(t.out, " %s %s", + format(padFunc(f, SPACE, v), + t.footerParams[y]), pad) + } else { + fmt.Fprintf(t.out, " %s %s", + padFunc(f, SPACE, v), + pad) + } + + //fmt.Fprintf(t.out, " %s %s", + // padFunc(f, SPACE, v), + // pad) + } + // Next line + fmt.Fprint(t.out, t.newLine) + //t.printLine(true) + } + + hasPrinted := false + + for i := 0; i <= end; i++ { + v := t.cs[i] + pad := t.pRow + center := t.pCenter + length := len(t.footers[i][0]) + + if length > 0 { + hasPrinted = true + } + + // Set center to be space if length is 0 + if length == 0 && !t.borders.Right { + center = SPACE + } + + // Print first junction + if i == 0 { + fmt.Fprint(t.out, center) + } + + // Pad With space of length is 0 + if length == 0 { + pad = SPACE + } + // Ignore left space of it has printed before + if hasPrinted || t.borders.Left { + pad = t.pRow + center = t.pCenter + } + + // Change Center start position + if center == SPACE { + if i < end && len(t.footers[i+1][0]) != 0 { + center = t.pCenter + } + } + + // Print the footer + fmt.Fprintf(t.out, "%s%s%s%s", + pad, + strings.Repeat(string(pad), v), + pad, + center) + + } + + fmt.Fprint(t.out, t.newLine) +} + +// Print caption text +func (t Table) printCaption() { + width := t.getTableWidth() + paragraph, _ := WrapString(t.captionText, width) + for linecount := 0; linecount < len(paragraph); linecount++ { + fmt.Fprintln(t.out, paragraph[linecount]) + } +} + +// Calculate the total number of characters in a row +func (t Table) getTableWidth() int { + var chars int + for _, v := range t.cs { + chars += v + } + + // Add chars, spaces, seperators to calculate the total width of the table. + // ncols := t.colSize + // spaces := ncols * 2 + // seps := ncols + 1 + + return (chars + (3 * t.colSize) + 2) +} + +func (t Table) printRows() { + for i, lines := range t.lines { + t.printRow(lines, i) + } +} + +func (t *Table) fillAlignment(num int) { + if len(t.columnsAlign) < num { + t.columnsAlign = make([]int, num) + for i := range t.columnsAlign { + t.columnsAlign[i] = t.align + } + } +} + +// Print Row Information +// Adjust column alignment based on type + +func (t *Table) printRow(columns [][]string, rowIdx int) { + // Get Maximum Height + max := t.rs[rowIdx] + total := len(columns) + + // TODO Fix uneven col size + // if total < t.colSize { + // for n := t.colSize - total; n < t.colSize ; n++ { + // columns = append(columns, []string{SPACE}) + // t.cs[n] = t.mW + // } + //} + + // Pad Each Height + pads := []int{} + + // Checking for ANSI escape sequences for columns + is_esc_seq := false + if len(t.columnsParams) > 0 { + is_esc_seq = true + } + t.fillAlignment(total) + + for i, line := range columns { + length := len(line) + pad := max - length + pads = append(pads, pad) + for n := 0; n < pad; n++ { + columns[i] = append(columns[i], " ") + } + } + //fmt.Println(max, "\n") + for x := 0; x < max; x++ { + for y := 0; y < total; y++ { + + // Check if border is set + fmt.Fprint(t.out, ConditionString((!t.borders.Left && y == 0), SPACE, t.pColumn)) + + fmt.Fprintf(t.out, SPACE) + str := columns[y][x] + + // Embedding escape sequence with column value + if is_esc_seq { + str = format(str, t.columnsParams[y]) + } + + // This would print alignment + // Default alignment would use multiple configuration + switch t.columnsAlign[y] { + case ALIGN_CENTER: // + fmt.Fprintf(t.out, "%s", Pad(str, SPACE, t.cs[y])) + case ALIGN_RIGHT: + fmt.Fprintf(t.out, "%s", PadLeft(str, SPACE, t.cs[y])) + case ALIGN_LEFT: + fmt.Fprintf(t.out, "%s", PadRight(str, SPACE, t.cs[y])) + default: + if decimal.MatchString(strings.TrimSpace(str)) || percent.MatchString(strings.TrimSpace(str)) { + fmt.Fprintf(t.out, "%s", PadLeft(str, SPACE, t.cs[y])) + } else { + fmt.Fprintf(t.out, "%s", PadRight(str, SPACE, t.cs[y])) + + // TODO Custom alignment per column + //if max == 1 || pads[y] > 0 { + // fmt.Fprintf(t.out, "%s", Pad(str, SPACE, t.cs[y])) + //} else { + // fmt.Fprintf(t.out, "%s", PadRight(str, SPACE, t.cs[y])) + //} + + } + } + fmt.Fprintf(t.out, SPACE) + } + // Check if border is set + // Replace with space if not set + fmt.Fprint(t.out, ConditionString(t.borders.Left, t.pColumn, SPACE)) + fmt.Fprint(t.out, t.newLine) + } + + if t.rowLine { + t.printLine(true) + } +} + +// Print the rows of the table and merge the cells that are identical +func (t *Table) printRowsMergeCells() { + var previousLine []string + var displayCellBorder []bool + var tmpWriter bytes.Buffer + for i, lines := range t.lines { + // We store the display of the current line in a tmp writer, as we need to know which border needs to be print above + previousLine, displayCellBorder = t.printRowMergeCells(&tmpWriter, lines, i, previousLine) + if i > 0 { //We don't need to print borders above first line + if t.rowLine { + t.printLineOptionalCellSeparators(true, displayCellBorder) + } + } + tmpWriter.WriteTo(t.out) + } + //Print the end of the table + if t.rowLine { + t.printLine(true) + } +} + +// Print Row Information to a writer and merge identical cells. +// Adjust column alignment based on type + +func (t *Table) printRowMergeCells(writer io.Writer, columns [][]string, rowIdx int, previousLine []string) ([]string, []bool) { + // Get Maximum Height + max := t.rs[rowIdx] + total := len(columns) + + // Pad Each Height + pads := []int{} + + for i, line := range columns { + length := len(line) + pad := max - length + pads = append(pads, pad) + for n := 0; n < pad; n++ { + columns[i] = append(columns[i], " ") + } + } + + var displayCellBorder []bool + t.fillAlignment(total) + for x := 0; x < max; x++ { + for y := 0; y < total; y++ { + + // Check if border is set + fmt.Fprint(writer, ConditionString((!t.borders.Left && y == 0), SPACE, t.pColumn)) + + fmt.Fprintf(writer, SPACE) + + str := columns[y][x] + + if t.autoMergeCells { + //Store the full line to merge mutli-lines cells + fullLine := strings.Join(columns[y], " ") + if len(previousLine) > y && fullLine == previousLine[y] && fullLine != "" { + // If this cell is identical to the one above but not empty, we don't display the border and keep the cell empty. + displayCellBorder = append(displayCellBorder, false) + str = "" + } else { + // First line or different content, keep the content and print the cell border + displayCellBorder = append(displayCellBorder, true) + } + } + + // This would print alignment + // Default alignment would use multiple configuration + switch t.columnsAlign[y] { + case ALIGN_CENTER: // + fmt.Fprintf(writer, "%s", Pad(str, SPACE, t.cs[y])) + case ALIGN_RIGHT: + fmt.Fprintf(writer, "%s", PadLeft(str, SPACE, t.cs[y])) + case ALIGN_LEFT: + fmt.Fprintf(writer, "%s", PadRight(str, SPACE, t.cs[y])) + default: + if decimal.MatchString(strings.TrimSpace(str)) || percent.MatchString(strings.TrimSpace(str)) { + fmt.Fprintf(writer, "%s", PadLeft(str, SPACE, t.cs[y])) + } else { + fmt.Fprintf(writer, "%s", PadRight(str, SPACE, t.cs[y])) + } + } + fmt.Fprintf(writer, SPACE) + } + // Check if border is set + // Replace with space if not set + fmt.Fprint(writer, ConditionString(t.borders.Left, t.pColumn, SPACE)) + fmt.Fprint(writer, t.newLine) + } + + //The new previous line is the current one + previousLine = make([]string, total) + for y := 0; y < total; y++ { + previousLine[y] = strings.Join(columns[y], " ") //Store the full line for multi-lines cells + } + //Returns the newly added line and wether or not a border should be displayed above. + return previousLine, displayCellBorder +} + +func (t *Table) parseDimension(str string, colKey, rowKey int) []string { + var ( + raw []string + maxWidth int + ) + + raw = getLines(str) + maxWidth = 0 + for _, line := range raw { + if w := DisplayWidth(line); w > maxWidth { + maxWidth = w + } + } + + // If wrapping, ensure that all paragraphs in the cell fit in the + // specified width. + if t.autoWrap { + // If there's a maximum allowed width for wrapping, use that. + if maxWidth > t.mW { + maxWidth = t.mW + } + + // In the process of doing so, we need to recompute maxWidth. This + // is because perhaps a word in the cell is longer than the + // allowed maximum width in t.mW. + newMaxWidth := maxWidth + newRaw := make([]string, 0, len(raw)) + + if t.reflowText { + // Make a single paragraph of everything. + raw = []string{strings.Join(raw, " ")} + } + for i, para := range raw { + paraLines, _ := WrapString(para, maxWidth) + for _, line := range paraLines { + if w := DisplayWidth(line); w > newMaxWidth { + newMaxWidth = w + } + } + if i > 0 { + newRaw = append(newRaw, " ") + } + newRaw = append(newRaw, paraLines...) + } + raw = newRaw + maxWidth = newMaxWidth + } + + // Store the new known maximum width. + v, ok := t.cs[colKey] + if !ok || v < maxWidth || v == 0 { + t.cs[colKey] = maxWidth + } + + // Remember the number of lines for the row printer. + h := len(raw) + v, ok = t.rs[rowKey] + + if !ok || v < h || v == 0 { + t.rs[rowKey] = h + } + //fmt.Printf("Raw %+v %d\n", raw, len(raw)) + return raw +} diff --git a/vendor/github.com/olekukonko/tablewriter/table_test.go b/vendor/github.com/olekukonko/tablewriter/table_test.go new file mode 100644 index 00000000..fb174d9a --- /dev/null +++ b/vendor/github.com/olekukonko/tablewriter/table_test.go @@ -0,0 +1,1120 @@ +// Copyright 2014 Oleku Konko All rights reserved. +// Use of this source code is governed by a MIT +// license that can be found in the LICENSE file. + +// This module is a Table Writer API for the Go Programming Language. +// The protocols were written in pure Go and works on windows and unix systems + +package tablewriter + +import ( + "bytes" + "fmt" + "io" + "os" + "reflect" + "strings" + "testing" +) + +func ExampleShort() { + data := [][]string{ + []string{"A", "The Good", "500"}, + []string{"B", "The Very very Bad Man", "288"}, + []string{"C", "The Ugly", "120"}, + []string{"D", "The Gopher", "800"}, + } + + table := NewWriter(os.Stdout) + table.SetHeader([]string{"Name", "Sign", "Rating"}) + + for _, v := range data { + table.Append(v) + } + table.Render() + + // Output: +------+-----------------------+--------+ + // | NAME | SIGN | RATING | + // +------+-----------------------+--------+ + // | A | The Good | 500 | + // | B | The Very very Bad Man | 288 | + // | C | The Ugly | 120 | + // | D | The Gopher | 800 | + // +------+-----------------------+--------+ +} + +func ExampleLong() { + data := [][]string{ + []string{"Learn East has computers with adapted keyboards with enlarged print etc", " Some Data ", " Another Data"}, + []string{"Instead of lining up the letters all ", "the way across, he splits the keyboard in two", "Like most ergonomic keyboards", "See Data"}, + } + + table := NewWriter(os.Stdout) + table.SetHeader([]string{"Name", "Sign", "Rating"}) + table.SetCenterSeparator("*") + table.SetRowSeparator("=") + + for _, v := range data { + table.Append(v) + } + table.Render() +} + +func ExampleCSV() { + table, _ := NewCSV(os.Stdout, "test.csv", true) + table.SetCenterSeparator("*") + table.SetRowSeparator("=") + + table.Render() + + // Output: *============*===========*=========* + // | FIRST NAME | LAST NAME | SSN | + // *============*===========*=========* + // | John | Barry | 123456 | + // | Kathy | Smith | 687987 | + // | Bob | McCornick | 3979870 | + // *============*===========*=========* +} + +// TestNumLines to test the numbers of lines +func TestNumLines(t *testing.T) { + data := [][]string{ + []string{"A", "The Good", "500"}, + []string{"B", "The Very very Bad Man", "288"}, + []string{"C", "The Ugly", "120"}, + []string{"D", "The Gopher", "800"}, + } + + buf := &bytes.Buffer{} + table := NewWriter(buf) + table.SetHeader([]string{"Name", "Sign", "Rating"}) + + for i, v := range data { + table.Append(v) + if i+1 != table.NumLines() { + t.Errorf("Number of lines failed\ngot:\n[%d]\nwant:\n[%d]\n", table.NumLines(), i+1) + } + } + + if len(data) != table.NumLines() { + t.Errorf("Number of lines failed\ngot:\n[%d]\nwant:\n[%d]\n", table.NumLines(), len(data)) + } +} + +func TestCSVInfo(t *testing.T) { + buf := &bytes.Buffer{} + table, err := NewCSV(buf, "test_info.csv", true) + if err != nil { + t.Error(err) + return + } + table.SetAlignment(ALIGN_LEFT) + table.SetBorder(false) + table.Render() + + got := buf.String() + want := ` FIELD | TYPE | NULL | KEY | DEFAULT | EXTRA ++----------+--------------+------+-----+---------+----------------+ + user_id | smallint(5) | NO | PRI | NULL | auto_increment + username | varchar(10) | NO | | NULL | + password | varchar(100) | NO | | NULL | +` + + if got != want { + t.Errorf("CSV info failed\ngot:\n[%s]\nwant:\n[%s]\n", got, want) + } +} + +func TestCSVSeparator(t *testing.T) { + buf := &bytes.Buffer{} + table, err := NewCSV(buf, "test.csv", true) + if err != nil { + t.Error(err) + return + } + table.SetRowLine(true) + table.SetCenterSeparator("+") + table.SetColumnSeparator("|") + table.SetRowSeparator("-") + table.SetAlignment(ALIGN_LEFT) + table.Render() + + want := `+------------+-----------+---------+ +| FIRST NAME | LAST NAME | SSN | ++------------+-----------+---------+ +| John | Barry | 123456 | ++------------+-----------+---------+ +| Kathy | Smith | 687987 | ++------------+-----------+---------+ +| Bob | McCornick | 3979870 | ++------------+-----------+---------+ +` + + got := buf.String() + if got != want { + t.Errorf("CSV info failed\ngot:\n[%s]\nwant:\n[%s]\n", got, want) + } +} + +func TestNoBorder(t *testing.T) { + data := [][]string{ + []string{"1/1/2014", "Domain name", "2233", "$10.98"}, + []string{"1/1/2014", "January Hosting", "2233", "$54.95"}, + []string{"", " (empty)\n (empty)", "", ""}, + []string{"1/4/2014", "February Hosting", "2233", "$51.00"}, + []string{"1/4/2014", "February Extra Bandwidth", "2233", "$30.00"}, + []string{"1/4/2014", " (Discount)", "2233", "-$1.00"}, + } + + var buf bytes.Buffer + table := NewWriter(&buf) + table.SetAutoWrapText(false) + table.SetHeader([]string{"Date", "Description", "CV2", "Amount"}) + table.SetFooter([]string{"", "", "Total", "$145.93"}) // Add Footer + table.SetBorder(false) // Set Border to false + table.AppendBulk(data) // Add Bulk Data + table.Render() + + want := ` DATE | DESCRIPTION | CV2 | AMOUNT ++----------+--------------------------+-------+---------+ + 1/1/2014 | Domain name | 2233 | $10.98 + 1/1/2014 | January Hosting | 2233 | $54.95 + | (empty) | | + | (empty) | | + 1/4/2014 | February Hosting | 2233 | $51.00 + 1/4/2014 | February Extra Bandwidth | 2233 | $30.00 + 1/4/2014 | (Discount) | 2233 | -$1.00 ++----------+--------------------------+-------+---------+ + TOTAL | $145 93 + +-------+---------+ +` + got := buf.String() + if got != want { + t.Errorf("border table rendering failed\ngot:\n%s\nwant:\n%s\n", got, want) + } +} + +func TestWithBorder(t *testing.T) { + data := [][]string{ + []string{"1/1/2014", "Domain name", "2233", "$10.98"}, + []string{"1/1/2014", "January Hosting", "2233", "$54.95"}, + []string{"", " (empty)\n (empty)", "", ""}, + []string{"1/4/2014", "February Hosting", "2233", "$51.00"}, + []string{"1/4/2014", "February Extra Bandwidth", "2233", "$30.00"}, + []string{"1/4/2014", " (Discount)", "2233", "-$1.00"}, + } + + var buf bytes.Buffer + table := NewWriter(&buf) + table.SetAutoWrapText(false) + table.SetHeader([]string{"Date", "Description", "CV2", "Amount"}) + table.SetFooter([]string{"", "", "Total", "$145.93"}) // Add Footer + table.AppendBulk(data) // Add Bulk Data + table.Render() + + want := `+----------+--------------------------+-------+---------+ +| DATE | DESCRIPTION | CV2 | AMOUNT | ++----------+--------------------------+-------+---------+ +| 1/1/2014 | Domain name | 2233 | $10.98 | +| 1/1/2014 | January Hosting | 2233 | $54.95 | +| | (empty) | | | +| | (empty) | | | +| 1/4/2014 | February Hosting | 2233 | $51.00 | +| 1/4/2014 | February Extra Bandwidth | 2233 | $30.00 | +| 1/4/2014 | (Discount) | 2233 | -$1.00 | ++----------+--------------------------+-------+---------+ +| TOTAL | $145 93 | ++----------+--------------------------+-------+---------+ +` + got := buf.String() + if got != want { + t.Errorf("border table rendering failed\ngot:\n%s\nwant:\n%s\n", got, want) + } +} + +func TestPrintingInMarkdown(t *testing.T) { + data := [][]string{ + []string{"1/1/2014", "Domain name", "2233", "$10.98"}, + []string{"1/1/2014", "January Hosting", "2233", "$54.95"}, + []string{"1/4/2014", "February Hosting", "2233", "$51.00"}, + []string{"1/4/2014", "February Extra Bandwidth", "2233", "$30.00"}, + } + + var buf bytes.Buffer + table := NewWriter(&buf) + table.SetHeader([]string{"Date", "Description", "CV2", "Amount"}) + table.AppendBulk(data) // Add Bulk Data + table.SetBorders(Border{Left: true, Top: false, Right: true, Bottom: false}) + table.SetCenterSeparator("|") + table.Render() + + want := `| DATE | DESCRIPTION | CV2 | AMOUNT | +|----------|--------------------------|------|--------| +| 1/1/2014 | Domain name | 2233 | $10.98 | +| 1/1/2014 | January Hosting | 2233 | $54.95 | +| 1/4/2014 | February Hosting | 2233 | $51.00 | +| 1/4/2014 | February Extra Bandwidth | 2233 | $30.00 | +` + got := buf.String() + if got != want { + t.Errorf("border table rendering failed\ngot:\n%s\nwant:\n%s\n", got, want) + } +} + +func TestPrintHeading(t *testing.T) { + var buf bytes.Buffer + table := NewWriter(&buf) + table.SetHeader([]string{"1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c"}) + table.printHeading() + want := `| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | ++---+---+---+---+---+---+---+---+---+---+---+---+ +` + got := buf.String() + if got != want { + t.Errorf("header rendering failed\ngot:\n%s\nwant:\n%s\n", got, want) + } +} + +func TestPrintHeadingWithoutAutoFormat(t *testing.T) { + var buf bytes.Buffer + table := NewWriter(&buf) + table.SetHeader([]string{"1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c"}) + table.SetAutoFormatHeaders(false) + table.printHeading() + want := `| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | a | b | c | ++---+---+---+---+---+---+---+---+---+---+---+---+ +` + got := buf.String() + if got != want { + t.Errorf("header rendering failed\ngot:\n%s\nwant:\n%s\n", got, want) + } +} + +func TestPrintFooter(t *testing.T) { + var buf bytes.Buffer + table := NewWriter(&buf) + table.SetHeader([]string{"1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c"}) + table.SetFooter([]string{"1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c"}) + table.printFooter() + want := `| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | ++---+---+---+---+---+---+---+---+---+---+---+---+ +` + got := buf.String() + if got != want { + t.Errorf("footer rendering failed\ngot:\n%s\nwant:\n%s\n", got, want) + } +} + +func TestPrintFooterWithoutAutoFormat(t *testing.T) { + var buf bytes.Buffer + table := NewWriter(&buf) + table.SetAutoFormatHeaders(false) + table.SetHeader([]string{"1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c"}) + table.SetFooter([]string{"1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c"}) + table.printFooter() + want := `| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | a | b | c | ++---+---+---+---+---+---+---+---+---+---+---+---+ +` + got := buf.String() + if got != want { + t.Errorf("footer rendering failed\ngot:\n%s\nwant:\n%s\n", got, want) + } +} + +func TestPrintShortCaption(t *testing.T) { + var buf bytes.Buffer + data := [][]string{ + []string{"A", "The Good", "500"}, + []string{"B", "The Very very Bad Man", "288"}, + []string{"C", "The Ugly", "120"}, + []string{"D", "The Gopher", "800"}, + } + + table := NewWriter(&buf) + table.SetHeader([]string{"Name", "Sign", "Rating"}) + table.SetCaption(true, "Short caption.") + + for _, v := range data { + table.Append(v) + } + table.Render() + + want := `+------+-----------------------+--------+ +| NAME | SIGN | RATING | ++------+-----------------------+--------+ +| A | The Good | 500 | +| B | The Very very Bad Man | 288 | +| C | The Ugly | 120 | +| D | The Gopher | 800 | ++------+-----------------------+--------+ +Short caption. +` + got := buf.String() + if got != want { + t.Errorf("long caption for short example rendering failed\ngot:\n%s\nwant:\n%s\n", got, want) + } +} + +func TestPrintLongCaptionWithShortExample(t *testing.T) { + var buf bytes.Buffer + data := [][]string{ + []string{"A", "The Good", "500"}, + []string{"B", "The Very very Bad Man", "288"}, + []string{"C", "The Ugly", "120"}, + []string{"D", "The Gopher", "800"}, + } + + table := NewWriter(&buf) + table.SetHeader([]string{"Name", "Sign", "Rating"}) + table.SetCaption(true, "This is a very long caption. The text should wrap. If not, we have a problem that needs to be solved.") + + for _, v := range data { + table.Append(v) + } + table.Render() + + want := `+------+-----------------------+--------+ +| NAME | SIGN | RATING | ++------+-----------------------+--------+ +| A | The Good | 500 | +| B | The Very very Bad Man | 288 | +| C | The Ugly | 120 | +| D | The Gopher | 800 | ++------+-----------------------+--------+ +This is a very long caption. The text +should wrap. If not, we have a problem +that needs to be solved. +` + got := buf.String() + if got != want { + t.Errorf("long caption for short example rendering failed\ngot:\n%s\nwant:\n%s\n", got, want) + } +} + +func TestPrintCaptionWithFooter(t *testing.T) { + data := [][]string{ + []string{"1/1/2014", "Domain name", "2233", "$10.98"}, + []string{"1/1/2014", "January Hosting", "2233", "$54.95"}, + []string{"1/4/2014", "February Hosting", "2233", "$51.00"}, + []string{"1/4/2014", "February Extra Bandwidth", "2233", "$30.00"}, + } + + var buf bytes.Buffer + table := NewWriter(&buf) + table.SetHeader([]string{"Date", "Description", "CV2", "Amount"}) + table.SetFooter([]string{"", "", "Total", "$146.93"}) // Add Footer + table.SetCaption(true, "This is a very long caption. The text should wrap to the width of the table.") // Add caption + table.SetBorder(false) // Set Border to false + table.AppendBulk(data) // Add Bulk Data + table.Render() + + want := ` DATE | DESCRIPTION | CV2 | AMOUNT ++----------+--------------------------+-------+---------+ + 1/1/2014 | Domain name | 2233 | $10.98 + 1/1/2014 | January Hosting | 2233 | $54.95 + 1/4/2014 | February Hosting | 2233 | $51.00 + 1/4/2014 | February Extra Bandwidth | 2233 | $30.00 ++----------+--------------------------+-------+---------+ + TOTAL | $146 93 + +-------+---------+ +This is a very long caption. The text should wrap to the +width of the table. +` + got := buf.String() + if got != want { + t.Errorf("border table rendering failed\ngot:\n%s\nwant:\n%s\n", got, want) + } +} + +func TestPrintLongCaptionWithLongExample(t *testing.T) { + var buf bytes.Buffer + data := [][]string{ + []string{"Learn East has computers with adapted keyboards with enlarged print etc", "Some Data", "Another Data"}, + []string{"Instead of lining up the letters all", "the way across, he splits the keyboard in two", "Like most ergonomic keyboards"}, + } + + table := NewWriter(&buf) + table.SetCaption(true, "This is a very long caption. The text should wrap. If not, we have a problem that needs to be solved.") + table.SetHeader([]string{"Name", "Sign", "Rating"}) + + for _, v := range data { + table.Append(v) + } + table.Render() + + want := `+--------------------------------+--------------------------------+-------------------------------+ +| NAME | SIGN | RATING | ++--------------------------------+--------------------------------+-------------------------------+ +| Learn East has computers | Some Data | Another Data | +| with adapted keyboards with | | | +| enlarged print etc | | | +| Instead of lining up the | the way across, he splits the | Like most ergonomic keyboards | +| letters all | keyboard in two | | ++--------------------------------+--------------------------------+-------------------------------+ +This is a very long caption. The text should wrap. If not, we have a problem that needs to be +solved. +` + got := buf.String() + if got != want { + t.Errorf("long caption for long example rendering failed\ngot:\n%s\nwant:\n%s\n", got, want) + } +} + +func Example_autowrap() { + var multiline = `A multiline +string with some lines being really long.` + + const ( + testRow = iota + testHeader + testFooter + testFooter2 + ) + for mode := testRow; mode <= testFooter2; mode++ { + for _, autoFmt := range []bool{false, true} { + if mode == testRow && autoFmt { + // Nothing special to test, skip + continue + } + for _, autoWrap := range []bool{false, true} { + for _, reflow := range []bool{false, true} { + if !autoWrap && reflow { + // Invalid configuration, skip + continue + } + fmt.Println("mode", mode, "autoFmt", autoFmt, "autoWrap", autoWrap, "reflow", reflow) + t := NewWriter(os.Stdout) + t.SetAutoFormatHeaders(autoFmt) + t.SetAutoWrapText(autoWrap) + t.SetReflowDuringAutoWrap(reflow) + if mode == testHeader { + t.SetHeader([]string{"woo", multiline}) + } else { + t.SetHeader([]string{"woo", "waa"}) + } + if mode == testRow { + t.Append([]string{"woo", multiline}) + } else { + t.Append([]string{"woo", "waa"}) + } + if mode == testFooter { + t.SetFooter([]string{"woo", multiline}) + } else if mode == testFooter2 { + t.SetFooter([]string{"", multiline}) + } else { + t.SetFooter([]string{"woo", "waa"}) + } + t.Render() + } + } + } + fmt.Println() + } + + // Output: + // mode 0 autoFmt false autoWrap false reflow false + // +-----+-------------------------------------------+ + // | woo | waa | + // +-----+-------------------------------------------+ + // | woo | A multiline | + // | | string with some lines being really long. | + // +-----+-------------------------------------------+ + // | woo | waa | + // +-----+-------------------------------------------+ + // mode 0 autoFmt false autoWrap true reflow false + // +-----+--------------------------------+ + // | woo | waa | + // +-----+--------------------------------+ + // | woo | A multiline | + // | | | + // | | string with some lines being | + // | | really long. | + // +-----+--------------------------------+ + // | woo | waa | + // +-----+--------------------------------+ + // mode 0 autoFmt false autoWrap true reflow true + // +-----+--------------------------------+ + // | woo | waa | + // +-----+--------------------------------+ + // | woo | A multiline string with some | + // | | lines being really long. | + // +-----+--------------------------------+ + // | woo | waa | + // +-----+--------------------------------+ + // + // mode 1 autoFmt false autoWrap false reflow false + // +-----+-------------------------------------------+ + // | woo | A multiline | + // | | string with some lines being really long. | + // +-----+-------------------------------------------+ + // | woo | waa | + // +-----+-------------------------------------------+ + // | woo | waa | + // +-----+-------------------------------------------+ + // mode 1 autoFmt false autoWrap true reflow false + // +-----+--------------------------------+ + // | woo | A multiline | + // | | | + // | | string with some lines being | + // | | really long. | + // +-----+--------------------------------+ + // | woo | waa | + // +-----+--------------------------------+ + // | woo | waa | + // +-----+--------------------------------+ + // mode 1 autoFmt false autoWrap true reflow true + // +-----+--------------------------------+ + // | woo | A multiline string with some | + // | | lines being really long. | + // +-----+--------------------------------+ + // | woo | waa | + // +-----+--------------------------------+ + // | woo | waa | + // +-----+--------------------------------+ + // mode 1 autoFmt true autoWrap false reflow false + // +-----+-------------------------------------------+ + // | WOO | A MULTILINE | + // | | STRING WITH SOME LINES BEING REALLY LONG | + // +-----+-------------------------------------------+ + // | woo | waa | + // +-----+-------------------------------------------+ + // | WOO | WAA | + // +-----+-------------------------------------------+ + // mode 1 autoFmt true autoWrap true reflow false + // +-----+--------------------------------+ + // | WOO | A MULTILINE | + // | | | + // | | STRING WITH SOME LINES BEING | + // | | REALLY LONG | + // +-----+--------------------------------+ + // | woo | waa | + // +-----+--------------------------------+ + // | WOO | WAA | + // +-----+--------------------------------+ + // mode 1 autoFmt true autoWrap true reflow true + // +-----+--------------------------------+ + // | WOO | A MULTILINE STRING WITH SOME | + // | | LINES BEING REALLY LONG | + // +-----+--------------------------------+ + // | woo | waa | + // +-----+--------------------------------+ + // | WOO | WAA | + // +-----+--------------------------------+ + // + // mode 2 autoFmt false autoWrap false reflow false + // +-----+-------------------------------------------+ + // | woo | waa | + // +-----+-------------------------------------------+ + // | woo | waa | + // +-----+-------------------------------------------+ + // | woo | A multiline | + // | | string with some lines being really long. | + // +-----+-------------------------------------------+ + // mode 2 autoFmt false autoWrap true reflow false + // +-----+--------------------------------+ + // | woo | waa | + // +-----+--------------------------------+ + // | woo | waa | + // +-----+--------------------------------+ + // | woo | A multiline | + // | | | + // | | string with some lines being | + // | | really long. | + // +-----+--------------------------------+ + // mode 2 autoFmt false autoWrap true reflow true + // +-----+--------------------------------+ + // | woo | waa | + // +-----+--------------------------------+ + // | woo | waa | + // +-----+--------------------------------+ + // | woo | A multiline string with some | + // | | lines being really long. | + // +-----+--------------------------------+ + // mode 2 autoFmt true autoWrap false reflow false + // +-----+-------------------------------------------+ + // | WOO | WAA | + // +-----+-------------------------------------------+ + // | woo | waa | + // +-----+-------------------------------------------+ + // | WOO | A MULTILINE | + // | | STRING WITH SOME LINES BEING REALLY LONG | + // +-----+-------------------------------------------+ + // mode 2 autoFmt true autoWrap true reflow false + // +-----+--------------------------------+ + // | WOO | WAA | + // +-----+--------------------------------+ + // | woo | waa | + // +-----+--------------------------------+ + // | WOO | A MULTILINE | + // | | | + // | | STRING WITH SOME LINES BEING | + // | | REALLY LONG | + // +-----+--------------------------------+ + // mode 2 autoFmt true autoWrap true reflow true + // +-----+--------------------------------+ + // | WOO | WAA | + // +-----+--------------------------------+ + // | woo | waa | + // +-----+--------------------------------+ + // | WOO | A MULTILINE STRING WITH SOME | + // | | LINES BEING REALLY LONG | + // +-----+--------------------------------+ + // + // mode 3 autoFmt false autoWrap false reflow false + // +-----+-------------------------------------------+ + // | woo | waa | + // +-----+-------------------------------------------+ + // | woo | waa | + // +-----+-------------------------------------------+ + // | A multiline | + // | string with some lines being really long. | + // +-----+-------------------------------------------+ + // mode 3 autoFmt false autoWrap true reflow false + // +-----+--------------------------------+ + // | woo | waa | + // +-----+--------------------------------+ + // | woo | waa | + // +-----+--------------------------------+ + // | A multiline | + // | | + // | string with some lines being | + // | really long. | + // +-----+--------------------------------+ + // mode 3 autoFmt false autoWrap true reflow true + // +-----+--------------------------------+ + // | woo | waa | + // +-----+--------------------------------+ + // | woo | waa | + // +-----+--------------------------------+ + // | A multiline string with some | + // | lines being really long. | + // +-----+--------------------------------+ + // mode 3 autoFmt true autoWrap false reflow false + // +-----+-------------------------------------------+ + // | WOO | WAA | + // +-----+-------------------------------------------+ + // | woo | waa | + // +-----+-------------------------------------------+ + // | A MULTILINE | + // | STRING WITH SOME LINES BEING REALLY LONG | + // +-----+-------------------------------------------+ + // mode 3 autoFmt true autoWrap true reflow false + // +-----+--------------------------------+ + // | WOO | WAA | + // +-----+--------------------------------+ + // | woo | waa | + // +-----+--------------------------------+ + // | A MULTILINE | + // | | + // | STRING WITH SOME LINES BEING | + // | REALLY LONG | + // +-----+--------------------------------+ + // mode 3 autoFmt true autoWrap true reflow true + // +-----+--------------------------------+ + // | WOO | WAA | + // +-----+--------------------------------+ + // | woo | waa | + // +-----+--------------------------------+ + // | A MULTILINE STRING WITH SOME | + // | LINES BEING REALLY LONG | + // +-----+--------------------------------+ +} + +func TestPrintLine(t *testing.T) { + header := make([]string, 12) + val := " " + want := "" + for i := range header { + header[i] = val + want = fmt.Sprintf("%s+-%s-", want, strings.Replace(val, " ", "-", -1)) + val = val + " " + } + want = want + "+" + var buf bytes.Buffer + table := NewWriter(&buf) + table.SetHeader(header) + table.printLine(false) + got := buf.String() + if got != want { + t.Errorf("line rendering failed\ngot:\n%s\nwant:\n%s\n", got, want) + } +} + +func TestAnsiStrip(t *testing.T) { + header := make([]string, 12) + val := " " + want := "" + for i := range header { + header[i] = "\033[43;30m" + val + "\033[00m" + want = fmt.Sprintf("%s+-%s-", want, strings.Replace(val, " ", "-", -1)) + val = val + " " + } + want = want + "+" + var buf bytes.Buffer + table := NewWriter(&buf) + table.SetHeader(header) + table.printLine(false) + got := buf.String() + if got != want { + t.Errorf("line rendering failed\ngot:\n%s\nwant:\n%s\n", got, want) + } +} + +func NewCustomizedTable(out io.Writer) *Table { + table := NewWriter(out) + table.SetCenterSeparator("") + table.SetColumnSeparator("") + table.SetRowSeparator("") + table.SetBorder(false) + table.SetAlignment(ALIGN_LEFT) + table.SetHeader([]string{}) + return table +} + +func TestSubclass(t *testing.T) { + buf := new(bytes.Buffer) + table := NewCustomizedTable(buf) + + data := [][]string{ + []string{"A", "The Good", "500"}, + []string{"B", "The Very very Bad Man", "288"}, + []string{"C", "The Ugly", "120"}, + []string{"D", "The Gopher", "800"}, + } + + for _, v := range data { + table.Append(v) + } + table.Render() + + output := string(buf.Bytes()) + want := ` A The Good 500 + B The Very very Bad Man 288 + C The Ugly 120 + D The Gopher 800 +` + if output != want { + t.Error(fmt.Sprintf("Unexpected output '%v' != '%v'", output, want)) + } +} + +func TestAutoMergeRows(t *testing.T) { + data := [][]string{ + []string{"A", "The Good", "500"}, + []string{"A", "The Very very Bad Man", "288"}, + []string{"B", "The Very very Bad Man", "120"}, + []string{"B", "The Very very Bad Man", "200"}, + } + var buf bytes.Buffer + table := NewWriter(&buf) + table.SetHeader([]string{"Name", "Sign", "Rating"}) + + for _, v := range data { + table.Append(v) + } + table.SetAutoMergeCells(true) + table.Render() + want := `+------+-----------------------+--------+ +| NAME | SIGN | RATING | ++------+-----------------------+--------+ +| A | The Good | 500 | +| | The Very very Bad Man | 288 | +| B | | 120 | +| | | 200 | ++------+-----------------------+--------+ +` + got := buf.String() + if got != want { + t.Errorf("\ngot:\n%s\nwant:\n%s\n", got, want) + } + + buf.Reset() + table = NewWriter(&buf) + table.SetHeader([]string{"Name", "Sign", "Rating"}) + + for _, v := range data { + table.Append(v) + } + table.SetAutoMergeCells(true) + table.SetRowLine(true) + table.Render() + want = `+------+-----------------------+--------+ +| NAME | SIGN | RATING | ++------+-----------------------+--------+ +| A | The Good | 500 | ++ +-----------------------+--------+ +| | The Very very Bad Man | 288 | ++------+ +--------+ +| B | | 120 | ++ + +--------+ +| | | 200 | ++------+-----------------------+--------+ +` + got = buf.String() + if got != want { + t.Errorf("\ngot:\n%s\nwant:\n%s\n", got, want) + } + + buf.Reset() + table = NewWriter(&buf) + table.SetHeader([]string{"Name", "Sign", "Rating"}) + + dataWithlongText := [][]string{ + []string{"A", "The Good", "500"}, + []string{"A", "The Very very very very very Bad Man", "288"}, + []string{"B", "The Very very very very very Bad Man", "120"}, + []string{"C", "The Very very Bad Man", "200"}, + } + table.AppendBulk(dataWithlongText) + table.SetAutoMergeCells(true) + table.SetRowLine(true) + table.Render() + want = `+------+--------------------------------+--------+ +| NAME | SIGN | RATING | ++------+--------------------------------+--------+ +| A | The Good | 500 | ++------+--------------------------------+--------+ +| A | The Very very very very very | 288 | +| | Bad Man | | ++------+ +--------+ +| B | | 120 | +| | | | ++------+--------------------------------+--------+ +| C | The Very very Bad Man | 200 | ++------+--------------------------------+--------+ +` + got = buf.String() + if got != want { + t.Errorf("\ngot:\n%s\nwant:\n%s\n", got, want) + } +} + +func TestClearRows(t *testing.T) { + data := [][]string{ + []string{"1/1/2014", "Domain name", "2233", "$10.98"}, + } + + var buf bytes.Buffer + table := NewWriter(&buf) + table.SetAutoWrapText(false) + table.SetHeader([]string{"Date", "Description", "CV2", "Amount"}) + table.SetFooter([]string{"", "", "Total", "$145.93"}) // Add Footer + table.AppendBulk(data) // Add Bulk Data + table.Render() + + originalWant := `+----------+-------------+-------+---------+ +| DATE | DESCRIPTION | CV2 | AMOUNT | ++----------+-------------+-------+---------+ +| 1/1/2014 | Domain name | 2233 | $10.98 | ++----------+-------------+-------+---------+ +| TOTAL | $145 93 | ++----------+-------------+-------+---------+ +` + want := originalWant + + got := buf.String() + if got != want { + t.Errorf("table clear rows failed\ngot:\n%s\nwant:\n%s\n", got, want) + } + + buf.Reset() + table.ClearRows() + table.Render() + + want = `+----------+-------------+-------+---------+ +| DATE | DESCRIPTION | CV2 | AMOUNT | ++----------+-------------+-------+---------+ ++----------+-------------+-------+---------+ +| TOTAL | $145 93 | ++----------+-------------+-------+---------+ +` + + got = buf.String() + if got != want { + t.Errorf("table clear failed\ngot:\n%s\nwant:\n%s\n", got, want) + } + + buf.Reset() + table.AppendBulk(data) // Add Bulk Data + table.Render() + + want = `+----------+-------------+-------+---------+ +| DATE | DESCRIPTION | CV2 | AMOUNT | ++----------+-------------+-------+---------+ +| 1/1/2014 | Domain name | 2233 | $10.98 | ++----------+-------------+-------+---------+ +| TOTAL | $145 93 | ++----------+-------------+-------+---------+ +` + + got = buf.String() + if got != want { + t.Errorf("table clear rows failed\ngot:\n%s\nwant:\n%s\n", got, want) + } +} + +func TestClearFooters(t *testing.T) { + data := [][]string{ + []string{"1/1/2014", "Domain name", "2233", "$10.98"}, + } + + var buf bytes.Buffer + table := NewWriter(&buf) + table.SetAutoWrapText(false) + table.SetHeader([]string{"Date", "Description", "CV2", "Amount"}) + table.SetFooter([]string{"", "", "Total", "$145.93"}) // Add Footer + table.AppendBulk(data) // Add Bulk Data + table.Render() + + buf.Reset() + table.ClearFooter() + table.Render() + + want := `+----------+-------------+-------+---------+ +| DATE | DESCRIPTION | CV2 | AMOUNT | ++----------+-------------+-------+---------+ +| 1/1/2014 | Domain name | 2233 | $10.98 | ++----------+-------------+-------+---------+ +` + + got := buf.String() + if got != want { + t.Errorf("table clear rows failed\ngot:\n%s\nwant:\n%s\n", got, want) + } +} + +func TestMoreDataColumnsThanHeaders(t *testing.T) { + var ( + buf = &bytes.Buffer{} + table = NewWriter(buf) + header = []string{"A", "B", "C"} + data = [][]string{ + []string{"a", "b", "c", "d"}, + []string{"1", "2", "3", "4"}, + } + want = `+---+---+---+---+ +| A | B | C | | ++---+---+---+---+ +| a | b | c | d | +| 1 | 2 | 3 | 4 | ++---+---+---+---+ +` + ) + table.SetHeader(header) + // table.SetFooter(ctx.tableCtx.footer) + table.AppendBulk(data) + table.Render() + + got := buf.String() + + if got != want { + t.Errorf("\ngot:\n%s\nwant:\n%s\n", got, want) + } +} + +func TestMoreFooterColumnsThanHeaders(t *testing.T) { + var ( + buf = &bytes.Buffer{} + table = NewWriter(buf) + header = []string{"A", "B", "C"} + data = [][]string{ + []string{"a", "b", "c", "d"}, + []string{"1", "2", "3", "4"}, + } + footer = []string{"a", "b", "c", "d", "e"} + want = `+---+---+---+---+---+ +| A | B | C | | | ++---+---+---+---+---+ +| a | b | c | d | +| 1 | 2 | 3 | 4 | ++---+---+---+---+---+ +| A | B | C | D | E | ++---+---+---+---+---+ +` + ) + table.SetHeader(header) + table.SetFooter(footer) + table.AppendBulk(data) + table.Render() + + got := buf.String() + + if got != want { + t.Errorf("\ngot:\n%s\nwant:\n%s\n", got, want) + } +} + +func TestSetColMinWidth(t *testing.T) { + var ( + buf = &bytes.Buffer{} + table = NewWriter(buf) + header = []string{"AAA", "BBB", "CCC"} + data = [][]string{ + []string{"a", "b", "c"}, + []string{"1", "2", "3"}, + } + footer = []string{"a", "b", "cccc"} + want = `+-----+-----+-------+ +| AAA | BBB | CCC | ++-----+-----+-------+ +| a | b | c | +| 1 | 2 | 3 | ++-----+-----+-------+ +| A | B | CCCC | ++-----+-----+-------+ +` + ) + table.SetHeader(header) + table.SetFooter(footer) + table.AppendBulk(data) + table.SetColMinWidth(2, 5) + table.Render() + + got := buf.String() + + if got != want { + t.Errorf("\ngot:\n%s\nwant:\n%s\n", got, want) + } +} + +func TestWrapString(t *testing.T) { + want := []string{"ああああああああああああああああああああああああ", "あああああああ"} + got, _ := WrapString("ああああああああああああああああああああああああ あああああああ", 55) + if !reflect.DeepEqual(got, want) { + t.Errorf("\ngot:\n%v\nwant:\n%v\n", got, want) + } +} + +func TestCustomAlign(t *testing.T) { + var ( + buf = &bytes.Buffer{} + table = NewWriter(buf) + header = []string{"AAA", "BBB", "CCC"} + data = [][]string{ + []string{"a", "b", "c"}, + []string{"1", "2", "3"}, + } + footer = []string{"a", "b", "cccc"} + want = `+-----+-----+-------+ +| AAA | BBB | CCC | ++-----+-----+-------+ +| a | b | c | +| 1 | 2 | 3 | ++-----+-----+-------+ +| A | B | CCCC | ++-----+-----+-------+ +` + ) + table.SetHeader(header) + table.SetFooter(footer) + table.AppendBulk(data) + table.SetColMinWidth(2, 5) + table.SetColumnAlignment([]int{ALIGN_LEFT, ALIGN_CENTER, ALIGN_RIGHT}) + table.Render() + + got := buf.String() + + if got != want { + t.Errorf("\ngot:\n%s\nwant:\n%s\n", got, want) + } +} diff --git a/vendor/github.com/olekukonko/tablewriter/table_with_color.go b/vendor/github.com/olekukonko/tablewriter/table_with_color.go new file mode 100644 index 00000000..5a4a53ec --- /dev/null +++ b/vendor/github.com/olekukonko/tablewriter/table_with_color.go @@ -0,0 +1,134 @@ +package tablewriter + +import ( + "fmt" + "strconv" + "strings" +) + +const ESC = "\033" +const SEP = ";" + +const ( + BgBlackColor int = iota + 40 + BgRedColor + BgGreenColor + BgYellowColor + BgBlueColor + BgMagentaColor + BgCyanColor + BgWhiteColor +) + +const ( + FgBlackColor int = iota + 30 + FgRedColor + FgGreenColor + FgYellowColor + FgBlueColor + FgMagentaColor + FgCyanColor + FgWhiteColor +) + +const ( + BgHiBlackColor int = iota + 100 + BgHiRedColor + BgHiGreenColor + BgHiYellowColor + BgHiBlueColor + BgHiMagentaColor + BgHiCyanColor + BgHiWhiteColor +) + +const ( + FgHiBlackColor int = iota + 90 + FgHiRedColor + FgHiGreenColor + FgHiYellowColor + FgHiBlueColor + FgHiMagentaColor + FgHiCyanColor + FgHiWhiteColor +) + +const ( + Normal = 0 + Bold = 1 + UnderlineSingle = 4 + Italic +) + +type Colors []int + +func startFormat(seq string) string { + return fmt.Sprintf("%s[%sm", ESC, seq) +} + +func stopFormat() string { + return fmt.Sprintf("%s[%dm", ESC, Normal) +} + +// Making the SGR (Select Graphic Rendition) sequence. +func makeSequence(codes []int) string { + codesInString := []string{} + for _, code := range codes { + codesInString = append(codesInString, strconv.Itoa(code)) + } + return strings.Join(codesInString, SEP) +} + +// Adding ANSI escape sequences before and after string +func format(s string, codes interface{}) string { + var seq string + + switch v := codes.(type) { + + case string: + seq = v + case []int: + seq = makeSequence(v) + default: + return s + } + + if len(seq) == 0 { + return s + } + return startFormat(seq) + s + stopFormat() +} + +// Adding header colors (ANSI codes) +func (t *Table) SetHeaderColor(colors ...Colors) { + if t.colSize != len(colors) { + panic("Number of header colors must be equal to number of headers.") + } + for i := 0; i < len(colors); i++ { + t.headerParams = append(t.headerParams, makeSequence(colors[i])) + } +} + +// Adding column colors (ANSI codes) +func (t *Table) SetColumnColor(colors ...Colors) { + if t.colSize != len(colors) { + panic("Number of column colors must be equal to number of headers.") + } + for i := 0; i < len(colors); i++ { + t.columnsParams = append(t.columnsParams, makeSequence(colors[i])) + } +} + +// Adding column colors (ANSI codes) +func (t *Table) SetFooterColor(colors ...Colors) { + if len(t.footers) != len(colors) { + panic("Number of footer colors must be equal to number of footer.") + } + for i := 0; i < len(colors); i++ { + t.footerParams = append(t.footerParams, makeSequence(colors[i])) + } +} + +func Color(colors ...int) []int { + return colors +} diff --git a/vendor/github.com/olekukonko/tablewriter/test.csv b/vendor/github.com/olekukonko/tablewriter/test.csv new file mode 100644 index 00000000..1609327e --- /dev/null +++ b/vendor/github.com/olekukonko/tablewriter/test.csv @@ -0,0 +1,4 @@ +first_name,last_name,ssn +John,Barry,123456 +Kathy,Smith,687987 +Bob,McCornick,3979870 \ No newline at end of file diff --git a/vendor/github.com/olekukonko/tablewriter/test_info.csv b/vendor/github.com/olekukonko/tablewriter/test_info.csv new file mode 100644 index 00000000..e4c40e98 --- /dev/null +++ b/vendor/github.com/olekukonko/tablewriter/test_info.csv @@ -0,0 +1,4 @@ +Field,Type,Null,Key,Default,Extra +user_id,smallint(5),NO,PRI,NULL,auto_increment +username,varchar(10),NO,,NULL, +password,varchar(100),NO,,NULL, \ No newline at end of file diff --git a/vendor/github.com/olekukonko/tablewriter/util.go b/vendor/github.com/olekukonko/tablewriter/util.go new file mode 100644 index 00000000..dea3c7aa --- /dev/null +++ b/vendor/github.com/olekukonko/tablewriter/util.go @@ -0,0 +1,78 @@ +// Copyright 2014 Oleku Konko All rights reserved. +// Use of this source code is governed by a MIT +// license that can be found in the LICENSE file. + +// This module is a Table Writer API for the Go Programming Language. +// The protocols were written in pure Go and works on windows and unix systems + +package tablewriter + +import ( + "math" + "regexp" + "strings" + + "github.com/mattn/go-runewidth" +) + +var ansi = regexp.MustCompile("\033\\[(?:[0-9]{1,3}(?:;[0-9]{1,3})*)?[m|K]") + +func DisplayWidth(str string) int { + return runewidth.StringWidth(ansi.ReplaceAllLiteralString(str, "")) +} + +// Simple Condition for string +// Returns value based on condition +func ConditionString(cond bool, valid, inValid string) string { + if cond { + return valid + } + return inValid +} + +// Format Table Header +// Replace _ , . and spaces +func Title(name string) string { + origLen := len(name) + name = strings.Replace(name, "_", " ", -1) + name = strings.Replace(name, ".", " ", -1) + name = strings.TrimSpace(name) + if len(name) == 0 && origLen > 0 { + // Keep at least one character. This is important to preserve + // empty lines in multi-line headers/footers. + name = " " + } + return strings.ToUpper(name) +} + +// Pad String +// Attempts to play string in the center +func Pad(s, pad string, width int) string { + gap := width - DisplayWidth(s) + if gap > 0 { + gapLeft := int(math.Ceil(float64(gap / 2))) + gapRight := gap - gapLeft + return strings.Repeat(string(pad), gapLeft) + s + strings.Repeat(string(pad), gapRight) + } + return s +} + +// Pad String Right position +// This would pace string at the left side fo the screen +func PadRight(s, pad string, width int) string { + gap := width - DisplayWidth(s) + if gap > 0 { + return s + strings.Repeat(string(pad), gap) + } + return s +} + +// Pad String Left position +// This would pace string at the right side fo the screen +func PadLeft(s, pad string, width int) string { + gap := width - DisplayWidth(s) + if gap > 0 { + return strings.Repeat(string(pad), gap) + s + } + return s +} diff --git a/vendor/github.com/olekukonko/tablewriter/wrap.go b/vendor/github.com/olekukonko/tablewriter/wrap.go new file mode 100644 index 00000000..a092ee1f --- /dev/null +++ b/vendor/github.com/olekukonko/tablewriter/wrap.go @@ -0,0 +1,99 @@ +// Copyright 2014 Oleku Konko All rights reserved. +// Use of this source code is governed by a MIT +// license that can be found in the LICENSE file. + +// This module is a Table Writer API for the Go Programming Language. +// The protocols were written in pure Go and works on windows and unix systems + +package tablewriter + +import ( + "math" + "strings" + + "github.com/mattn/go-runewidth" +) + +var ( + nl = "\n" + sp = " " +) + +const defaultPenalty = 1e5 + +// Wrap wraps s into a paragraph of lines of length lim, with minimal +// raggedness. +func WrapString(s string, lim int) ([]string, int) { + words := strings.Split(strings.Replace(s, nl, sp, -1), sp) + var lines []string + max := 0 + for _, v := range words { + max = runewidth.StringWidth(v) + if max > lim { + lim = max + } + } + for _, line := range WrapWords(words, 1, lim, defaultPenalty) { + lines = append(lines, strings.Join(line, sp)) + } + return lines, lim +} + +// WrapWords is the low-level line-breaking algorithm, useful if you need more +// control over the details of the text wrapping process. For most uses, +// WrapString will be sufficient and more convenient. +// +// WrapWords splits a list of words into lines with minimal "raggedness", +// treating each rune as one unit, accounting for spc units between adjacent +// words on each line, and attempting to limit lines to lim units. Raggedness +// is the total error over all lines, where error is the square of the +// difference of the length of the line and lim. Too-long lines (which only +// happen when a single word is longer than lim units) have pen penalty units +// added to the error. +func WrapWords(words []string, spc, lim, pen int) [][]string { + n := len(words) + + length := make([][]int, n) + for i := 0; i < n; i++ { + length[i] = make([]int, n) + length[i][i] = runewidth.StringWidth(words[i]) + for j := i + 1; j < n; j++ { + length[i][j] = length[i][j-1] + spc + runewidth.StringWidth(words[j]) + } + } + nbrk := make([]int, n) + cost := make([]int, n) + for i := range cost { + cost[i] = math.MaxInt32 + } + for i := n - 1; i >= 0; i-- { + if length[i][n-1] <= lim { + cost[i] = 0 + nbrk[i] = n + } else { + for j := i + 1; j < n; j++ { + d := lim - length[i][j-1] + c := d*d + cost[j] + if length[i][j-1] > lim { + c += pen // too-long lines get a worse penalty + } + if c < cost[i] { + cost[i] = c + nbrk[i] = j + } + } + } + } + var lines [][]string + i := 0 + for i < n { + lines = append(lines, words[i:nbrk[i]]) + i = nbrk[i] + } + return lines +} + +// getLines decomposes a multiline string into a slice of strings. +func getLines(s string) []string { + return strings.Split(s, nl) +} diff --git a/vendor/github.com/olekukonko/tablewriter/wrap_test.go b/vendor/github.com/olekukonko/tablewriter/wrap_test.go new file mode 100644 index 00000000..bec56b68 --- /dev/null +++ b/vendor/github.com/olekukonko/tablewriter/wrap_test.go @@ -0,0 +1,66 @@ +// Copyright 2014 Oleku Konko All rights reserved. +// Use of this source code is governed by a MIT +// license that can be found in the LICENSE file. + +// This module is a Table Writer API for the Go Programming Language. +// The protocols were written in pure Go and works on windows and unix systems + +package tablewriter + +import ( + "strings" + "testing" + + "github.com/mattn/go-runewidth" +) + +var text = "The quick brown fox jumps over the lazy dog." + +func TestWrap(t *testing.T) { + exp := []string{ + "The", "quick", "brown", "fox", + "jumps", "over", "the", "lazy", "dog."} + + got, _ := WrapString(text, 6) + if len(exp) != len(got) { + t.Fail() + } +} + +func TestWrapOneLine(t *testing.T) { + exp := "The quick brown fox jumps over the lazy dog." + words, _ := WrapString(text, 500) + got := strings.Join(words, string(sp)) + if exp != got { + t.Errorf("expected: %q, got: %q", exp, got) + } +} + +func TestUnicode(t *testing.T) { + input := "Česká řeřicha" + var wordsUnicode []string + if runewidth.IsEastAsian() { + wordsUnicode, _ = WrapString(input, 14) + } else { + wordsUnicode, _ = WrapString(input, 13) + } + // input contains 13 (or 14 for CJK) runes, so it fits on one line. + if len(wordsUnicode) != 1 { + t.Fail() + } +} + +func TestDisplayWidth(t *testing.T) { + input := "Česká řeřicha" + want := 13 + if runewidth.IsEastAsian() { + want = 14 + } + if n := DisplayWidth(input); n != want { + t.Errorf("Wants: %d Got: %d", want, n) + } + input = "\033[43;30m" + input + "\033[00m" + if n := DisplayWidth(input); n != want { + t.Errorf("Wants: %d Got: %d", want, n) + } +} From 812c506779760f02a94fd8718df3c873b16755a2 Mon Sep 17 00:00:00 2001 From: dinesh Date: Sat, 7 Apr 2018 18:20:07 +0530 Subject: [PATCH 05/13] Humanizing the time in CLI --- CHANGELOG.md | 2 + Gopkg.lock | 8 +- Gopkg.toml | 5 +- api/controller/services.pb.go | 259 +++--- api/controller/services.pb.gw.go | 2 +- api/controller/services.proto | 8 +- api/controller/services.swagger.json | 5 +- api/models/types.pb.go | 813 +++++++++--------- api/server.go | 4 +- client/build.go | 8 +- cloud/aws/builder.go | 2 +- cloud/aws/kubeconfig.go | 56 +- cloud/aws/templates.go | 10 +- cloud/google/builder.go | 5 +- cloud/google/kubeconfig.go | 1 - cloud/google/templates.go | 4 +- cmd/apps.go | 4 +- cmd/build.go | 14 +- cmd/helper.go | 105 +-- cmd/provider/aws/templates.go | 2 +- vendor/github.com/ararog/timeago/.gitignore | 24 - vendor/github.com/ararog/timeago/.travis.yml | 5 - vendor/github.com/ararog/timeago/LICENSE | 21 - vendor/github.com/ararog/timeago/README.md | 6 - vendor/github.com/ararog/timeago/timeago.go | 139 --- .../github.com/ararog/timeago/timeago_test.go | 79 -- 26 files changed, 681 insertions(+), 910 deletions(-) delete mode 100644 vendor/github.com/ararog/timeago/.gitignore delete mode 100644 vendor/github.com/ararog/timeago/.travis.yml delete mode 100644 vendor/github.com/ararog/timeago/LICENSE delete mode 100644 vendor/github.com/ararog/timeago/README.md delete mode 100644 vendor/github.com/ararog/timeago/timeago.go delete mode 100644 vendor/github.com/ararog/timeago/timeago_test.go diff --git a/CHANGELOG.md b/CHANGELOG.md index 2650d4a1..0b62c477 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,8 @@ This project adheres to [Semantic Versioning](http://semver.org/). - Async support for streaming logs from mutiple processes. - Making `datacol run` independent of shell ### Added +- Paging for `GET /v1/builds` API +- [CLI] Tabular output for listing apps and builds - [CLI] `STACK` env var for `datacol env`, `datacol infra` - [CLI] Number of logs lines for process logs (`--lines 10`) diff --git a/Gopkg.lock b/Gopkg.lock index c4566e39..2b75b733 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -30,12 +30,6 @@ packages = ["context","crypto/rand","env","errors","io","log","term"] revision = "0042f7fe164fd03992cfa5ea70a98615516be99b" -[[projects]] - name = "github.com/ararog/timeago" - packages = ["."] - revision = "518814407569bf983ea81e1bf8b550dd4e7b34f3" - version = "0.0.1" - [[projects]] name = "github.com/asaskevich/govalidator" packages = ["."] @@ -580,6 +574,6 @@ [solve-meta] analyzer-name = "dep" analyzer-version = 1 - inputs-digest = "c97831aeb0d594a9f4347792339fcc7afdc24bd921d53359837e6895825b6232" + inputs-digest = "d19ecfd1dcb05bb021b32d5e90162154643244b212751b86e9657be4c803a0e6" solver-name = "gps-cdcl" solver-version = 1 diff --git a/Gopkg.toml b/Gopkg.toml index 83145aa6..1f7ccc45 100644 --- a/Gopkg.toml +++ b/Gopkg.toml @@ -74,7 +74,4 @@ required = [ version = "~1.13.0" [[constraint]] - name = "github.com/mholt/archiver" - -[[constraint]] - name = "github.com/ararog/timeago" + name = "github.com/mholt/archiver" \ No newline at end of file diff --git a/api/controller/services.pb.go b/api/controller/services.pb.go index b0b53ee2..ae9158cb 100644 --- a/api/controller/services.pb.go +++ b/api/controller/services.pb.go @@ -20,6 +20,7 @@ It has these top-level messages: BuildLogResponse EnvSetRequest ResourceListResponse + BuildListRequest BuildListResponse ProcessListResponse CreateResourceRequest @@ -355,6 +356,30 @@ func (m *ResourceListResponse) GetResources() []*models.Resource { return nil } +type BuildListRequest struct { + Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` + Limit int32 `protobuf:"varint,2,opt,name=limit" json:"limit,omitempty"` +} + +func (m *BuildListRequest) Reset() { *m = BuildListRequest{} } +func (m *BuildListRequest) String() string { return proto.CompactTextString(m) } +func (*BuildListRequest) ProtoMessage() {} +func (*BuildListRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{11} } + +func (m *BuildListRequest) GetName() string { + if m != nil { + return m.Name + } + return "" +} + +func (m *BuildListRequest) GetLimit() int32 { + if m != nil { + return m.Limit + } + return 0 +} + type BuildListResponse struct { Builds []*models.Build `protobuf:"bytes,1,rep,name=builds" json:"builds,omitempty"` } @@ -362,7 +387,7 @@ type BuildListResponse struct { func (m *BuildListResponse) Reset() { *m = BuildListResponse{} } func (m *BuildListResponse) String() string { return proto.CompactTextString(m) } func (*BuildListResponse) ProtoMessage() {} -func (*BuildListResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{11} } +func (*BuildListResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{12} } func (m *BuildListResponse) GetBuilds() []*models.Build { if m != nil { @@ -378,7 +403,7 @@ type ProcessListResponse struct { func (m *ProcessListResponse) Reset() { *m = ProcessListResponse{} } func (m *ProcessListResponse) String() string { return proto.CompactTextString(m) } func (*ProcessListResponse) ProtoMessage() {} -func (*ProcessListResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{12} } +func (*ProcessListResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{13} } func (m *ProcessListResponse) GetItems() []*models.Process { if m != nil { @@ -396,7 +421,7 @@ type CreateResourceRequest struct { func (m *CreateResourceRequest) Reset() { *m = CreateResourceRequest{} } func (m *CreateResourceRequest) String() string { return proto.CompactTextString(m) } func (*CreateResourceRequest) ProtoMessage() {} -func (*CreateResourceRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{13} } +func (*CreateResourceRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{14} } func (m *CreateResourceRequest) GetName() string { if m != nil { @@ -427,7 +452,7 @@ type AppResourceReq struct { func (m *AppResourceReq) Reset() { *m = AppResourceReq{} } func (m *AppResourceReq) String() string { return proto.CompactTextString(m) } func (*AppResourceReq) ProtoMessage() {} -func (*AppResourceReq) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{14} } +func (*AppResourceReq) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{15} } func (m *AppResourceReq) GetApp() string { if m != nil { @@ -450,7 +475,7 @@ type KubectlReq struct { func (m *KubectlReq) Reset() { *m = KubectlReq{} } func (m *KubectlReq) String() string { return proto.CompactTextString(m) } func (*KubectlReq) ProtoMessage() {} -func (*KubectlReq) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{15} } +func (*KubectlReq) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{16} } func (m *KubectlReq) GetArgs() []string { if m != nil { @@ -469,7 +494,7 @@ type CmdResponse struct { func (m *CmdResponse) Reset() { *m = CmdResponse{} } func (m *CmdResponse) String() string { return proto.CompactTextString(m) } func (*CmdResponse) ProtoMessage() {} -func (*CmdResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{16} } +func (*CmdResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{17} } func (m *CmdResponse) GetExitCode() int32 { if m != nil { @@ -509,7 +534,7 @@ type LogStreamReq struct { func (m *LogStreamReq) Reset() { *m = LogStreamReq{} } func (m *LogStreamReq) String() string { return proto.CompactTextString(m) } func (*LogStreamReq) ProtoMessage() {} -func (*LogStreamReq) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{17} } +func (*LogStreamReq) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{18} } func (m *LogStreamReq) GetName() string { if m != nil { @@ -547,7 +572,7 @@ type ProcessRunReq struct { func (m *ProcessRunReq) Reset() { *m = ProcessRunReq{} } func (m *ProcessRunReq) String() string { return proto.CompactTextString(m) } func (*ProcessRunReq) ProtoMessage() {} -func (*ProcessRunReq) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{18} } +func (*ProcessRunReq) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{19} } func (m *ProcessRunReq) GetName() string { if m != nil { @@ -570,7 +595,7 @@ type StreamMsg struct { func (m *StreamMsg) Reset() { *m = StreamMsg{} } func (m *StreamMsg) String() string { return proto.CompactTextString(m) } func (*StreamMsg) ProtoMessage() {} -func (*StreamMsg) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{19} } +func (*StreamMsg) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{20} } func (m *StreamMsg) GetData() []byte { if m != nil { @@ -586,7 +611,7 @@ type ReleaseListResponse struct { func (m *ReleaseListResponse) Reset() { *m = ReleaseListResponse{} } func (m *ReleaseListResponse) String() string { return proto.CompactTextString(m) } func (*ReleaseListResponse) ProtoMessage() {} -func (*ReleaseListResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{20} } +func (*ReleaseListResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{21} } func (m *ReleaseListResponse) GetReleases() []*models.Release { if m != nil { @@ -603,7 +628,7 @@ type CreateReleaseRequest struct { func (m *CreateReleaseRequest) Reset() { *m = CreateReleaseRequest{} } func (m *CreateReleaseRequest) String() string { return proto.CompactTextString(m) } func (*CreateReleaseRequest) ProtoMessage() {} -func (*CreateReleaseRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{21} } +func (*CreateReleaseRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{22} } func (m *CreateReleaseRequest) GetBuild() *models.Build { if m != nil { @@ -631,6 +656,7 @@ func init() { proto.RegisterType((*BuildLogResponse)(nil), "controller.BuildLogResponse") proto.RegisterType((*EnvSetRequest)(nil), "controller.EnvSetRequest") proto.RegisterType((*ResourceListResponse)(nil), "controller.ResourceListResponse") + proto.RegisterType((*BuildListRequest)(nil), "controller.BuildListRequest") proto.RegisterType((*BuildListResponse)(nil), "controller.BuildListResponse") proto.RegisterType((*ProcessListResponse)(nil), "controller.ProcessListResponse") proto.RegisterType((*CreateResourceRequest)(nil), "controller.CreateResourceRequest") @@ -668,7 +694,7 @@ type ProviderServiceClient interface { BuildRelease(ctx context.Context, in *CreateReleaseRequest, opts ...grpc.CallOption) (*models.Release, error) BuildGet(ctx context.Context, in *AppIdRequest, opts ...grpc.CallOption) (*models.Build, error) BuildDelete(ctx context.Context, in *AppIdRequest, opts ...grpc.CallOption) (*google_protobuf1.Empty, error) - BuildList(ctx context.Context, in *AppRequest, opts ...grpc.CallOption) (*BuildListResponse, error) + BuildList(ctx context.Context, in *BuildListRequest, opts ...grpc.CallOption) (*BuildListResponse, error) BuildLogs(ctx context.Context, in *BuildLogRequest, opts ...grpc.CallOption) (*BuildLogResponse, error) EnvironmentGet(ctx context.Context, in *AppRequest, opts ...grpc.CallOption) (*models.EnvConfig, error) EnvironmentSet(ctx context.Context, in *EnvSetRequest, opts ...grpc.CallOption) (*google_protobuf1.Empty, error) @@ -824,7 +850,7 @@ func (c *providerServiceClient) BuildDelete(ctx context.Context, in *AppIdReques return out, nil } -func (c *providerServiceClient) BuildList(ctx context.Context, in *AppRequest, opts ...grpc.CallOption) (*BuildListResponse, error) { +func (c *providerServiceClient) BuildList(ctx context.Context, in *BuildListRequest, opts ...grpc.CallOption) (*BuildListResponse, error) { out := new(BuildListResponse) err := grpc.Invoke(ctx, "/controller.ProviderService/BuildList", in, out, c.cc, opts...) if err != nil { @@ -1038,7 +1064,7 @@ type ProviderServiceServer interface { BuildRelease(context.Context, *CreateReleaseRequest) (*models.Release, error) BuildGet(context.Context, *AppIdRequest) (*models.Build, error) BuildDelete(context.Context, *AppIdRequest) (*google_protobuf1.Empty, error) - BuildList(context.Context, *AppRequest) (*BuildListResponse, error) + BuildList(context.Context, *BuildListRequest) (*BuildListResponse, error) BuildLogs(context.Context, *BuildLogRequest) (*BuildLogResponse, error) EnvironmentGet(context.Context, *AppRequest) (*models.EnvConfig, error) EnvironmentSet(context.Context, *EnvSetRequest) (*google_protobuf1.Empty, error) @@ -1273,7 +1299,7 @@ func _ProviderService_BuildDelete_Handler(srv interface{}, ctx context.Context, } func _ProviderService_BuildList_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(AppRequest) + in := new(BuildListRequest) if err := dec(in); err != nil { return nil, err } @@ -1285,7 +1311,7 @@ func _ProviderService_BuildList_Handler(srv interface{}, ctx context.Context, de FullMethod: "/controller.ProviderService/BuildList", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(ProviderServiceServer).BuildList(ctx, req.(*AppRequest)) + return srv.(ProviderServiceServer).BuildList(ctx, req.(*BuildListRequest)) } return interceptor(ctx, in, info, handler) } @@ -1718,104 +1744,105 @@ var _ProviderService_serviceDesc = grpc.ServiceDesc{ func init() { proto.RegisterFile("services.proto", fileDescriptor0) } var fileDescriptor0 = []byte{ - // 1571 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x58, 0x5b, 0x6f, 0xdb, 0x46, - 0x16, 0x5e, 0xda, 0xf2, 0x45, 0x47, 0xf2, 0x6d, 0x7c, 0x93, 0xe5, 0xc4, 0x76, 0x26, 0x58, 0xac, - 0xe3, 0x45, 0xc4, 0x6c, 0x76, 0xb1, 0x17, 0x67, 0xf7, 0xc1, 0x76, 0x94, 0x85, 0x51, 0xb7, 0x71, - 0xe9, 0x06, 0xee, 0x25, 0x69, 0x42, 0x8b, 0x23, 0x99, 0x35, 0xc9, 0x99, 0x0e, 0x49, 0xa5, 0x46, - 0x90, 0x97, 0xa2, 0x40, 0x7f, 0x40, 0x7f, 0x51, 0xdf, 0xf2, 0x58, 0xa0, 0xef, 0x45, 0x11, 0xf4, - 0xb5, 0xff, 0xa1, 0x98, 0x1b, 0x45, 0xea, 0xe2, 0xba, 0x79, 0x31, 0xe6, 0xcc, 0xe5, 0x3b, 0x1f, - 0xcf, 0x7c, 0xe7, 0xcc, 0x91, 0x61, 0x36, 0x26, 0xbc, 0xeb, 0xb7, 0x48, 0xdc, 0x60, 0x9c, 0x26, - 0x14, 0x41, 0x8b, 0x46, 0x09, 0xa7, 0x41, 0x40, 0x78, 0xfd, 0x46, 0x87, 0xd2, 0x4e, 0x40, 0x6c, - 0x97, 0xf9, 0xb6, 0x1b, 0x45, 0x34, 0x71, 0x13, 0x9f, 0x46, 0x7a, 0x67, 0xbd, 0xc6, 0x92, 0x4b, - 0x46, 0x62, 0x9b, 0x84, 0x2c, 0xb9, 0x54, 0x7f, 0xf5, 0xca, 0x86, 0x5e, 0xf1, 0x52, 0x2e, 0x4f, - 0x64, 0x03, 0xbd, 0x7e, 0xb7, 0xe3, 0x27, 0xe7, 0xe9, 0x59, 0xa3, 0x45, 0x43, 0xbb, 0x43, 0x3b, - 0xd4, 0x96, 0xd3, 0x67, 0x69, 0x5b, 0x5a, 0xd2, 0x90, 0x23, 0xbd, 0xfd, 0x1f, 0xb9, 0xed, 0x9e, - 0x9b, 0xb8, 0x2d, 0x1a, 0xdc, 0xf5, 0xa9, 0x19, 0x4a, 0x76, 0x21, 0xf5, 0x48, 0x10, 0xdb, 0xd2, - 0xad, 0x3a, 0x85, 0x1f, 0x40, 0xe5, 0xc8, 0x8f, 0x13, 0x87, 0x7c, 0x99, 0x92, 0x38, 0x41, 0x2b, - 0x30, 0x49, 0xdb, 0xed, 0x98, 0x24, 0x35, 0x6b, 0xcb, 0xda, 0x9e, 0x70, 0xb4, 0x85, 0x96, 0x60, - 0x22, 0xf0, 0x43, 0x3f, 0xa9, 0x8d, 0xc9, 0x69, 0x65, 0xe0, 0x07, 0x00, 0x7b, 0x8c, 0x99, 0xb3, - 0x08, 0x4a, 0x91, 0x1b, 0x12, 0x79, 0xb2, 0xec, 0xc8, 0x31, 0x5a, 0x83, 0x69, 0x4e, 0x18, 0x7d, - 0x9e, 0xf2, 0x40, 0x1e, 0x2d, 0x3b, 0x53, 0xc2, 0x7e, 0xc2, 0x03, 0xdc, 0x86, 0xb9, 0x3d, 0xc6, - 0x94, 0xf3, 0x98, 0xd1, 0x28, 0x26, 0xe8, 0xcf, 0x50, 0x72, 0x19, 0x8b, 0x6b, 0xd6, 0xd6, 0xf8, - 0x76, 0xe5, 0x7e, 0xa5, 0xa1, 0xf8, 0x36, 0xf6, 0x18, 0xdb, 0x2f, 0xbd, 0xf9, 0x69, 0xf3, 0x4f, - 0x8e, 0x5c, 0x1e, 0x4e, 0x26, 0x47, 0x7d, 0x3c, 0x4f, 0x1d, 0xdf, 0x81, 0xca, 0x5e, 0x9a, 0x9c, - 0x1b, 0x96, 0x75, 0x98, 0x66, 0x6e, 0x1c, 0xbf, 0xa4, 0xdc, 0xd3, 0x4c, 0x33, 0x1b, 0x7f, 0x63, - 0x41, 0x55, 0xed, 0xd5, 0x84, 0x10, 0x94, 0xce, 0x69, 0x9c, 0x98, 0x4f, 0x12, 0xe3, 0xec, 0x33, - 0xc7, 0x72, 0x9f, 0x59, 0x83, 0x29, 0xc6, 0xe9, 0x17, 0xa4, 0xa5, 0x9c, 0x97, 0x1d, 0x63, 0x0a, - 0x56, 0x9c, 0x74, 0x7c, 0x1a, 0xd5, 0x4a, 0x72, 0x41, 0x5b, 0x92, 0x06, 0xa7, 0x5d, 0xdf, 0x23, - 0xbc, 0x36, 0xa1, 0x69, 0x68, 0x1b, 0x3f, 0x05, 0x74, 0xc0, 0x89, 0x9b, 0x90, 0xfd, 0xd4, 0x0f, - 0x3c, 0x43, 0x7c, 0x1e, 0xc6, 0x5d, 0xc6, 0x34, 0x15, 0x31, 0x14, 0x5e, 0xbb, 0x84, 0xc7, 0x02, - 0x5c, 0xc7, 0x56, 0x9b, 0x1a, 0xbd, 0xd5, 0xf6, 0x03, 0x22, 0x09, 0x55, 0x9d, 0xcc, 0xc6, 0xf7, - 0xa0, 0xba, 0xc7, 0xd8, 0xe1, 0x15, 0xb8, 0xb3, 0x30, 0xe6, 0x7b, 0x1a, 0x72, 0xcc, 0xf7, 0x70, - 0x13, 0xe6, 0x24, 0x93, 0x23, 0xda, 0xb9, 0xf6, 0x21, 0xb1, 0x83, 0xd1, 0x58, 0xdf, 0x85, 0x18, - 0xe2, 0x5d, 0x98, 0xef, 0xc1, 0xe8, 0x00, 0xeb, 0x5d, 0x56, 0xb6, 0x4b, 0x5d, 0x6e, 0x44, 0xe2, - 0xda, 0xd8, 0xd6, 0xf8, 0x76, 0xd9, 0x51, 0x06, 0xfe, 0x17, 0xcc, 0x34, 0xa3, 0xee, 0x09, 0x49, - 0xae, 0x12, 0x1b, 0x82, 0x92, 0x50, 0xbb, 0xb9, 0x19, 0x31, 0xc6, 0x8f, 0x60, 0xc9, 0x21, 0x31, - 0x4d, 0x79, 0x8b, 0x14, 0xa4, 0xd6, 0x80, 0x32, 0xd7, 0xf3, 0x46, 0x6f, 0xf3, 0x46, 0x6f, 0xe6, - 0x80, 0xd3, 0xdb, 0x82, 0x77, 0x61, 0x41, 0x91, 0x2f, 0xea, 0x75, 0xf2, 0x4c, 0x4c, 0x1a, 0x84, - 0x19, 0x83, 0xa0, 0x2e, 0x4e, 0x2f, 0xe2, 0xff, 0xc2, 0xe2, 0x31, 0xa7, 0x2d, 0x12, 0xc7, 0x7d, - 0xa7, 0x27, 0x0e, 0x13, 0x12, 0x9a, 0xc3, 0x73, 0xe6, 0xb0, 0xde, 0xeb, 0xa8, 0x55, 0xfc, 0xbd, - 0x05, 0xcb, 0x4a, 0x0e, 0x19, 0xaf, 0xab, 0x63, 0x70, 0xe1, 0x47, 0xe6, 0x22, 0xe4, 0x18, 0x35, - 0x61, 0x92, 0xb9, 0xdc, 0x0d, 0xc5, 0x6d, 0x08, 0x4f, 0x77, 0x1b, 0xbd, 0xea, 0xd5, 0x18, 0x0a, - 0xdd, 0x38, 0x96, 0xfb, 0x9b, 0x51, 0xc2, 0x2f, 0x1d, 0x7d, 0xb8, 0xfe, 0x1f, 0xa8, 0xe4, 0xa6, - 0xc5, 0xd5, 0x5d, 0x90, 0x4b, 0x23, 0x81, 0x0b, 0x72, 0x29, 0xae, 0xae, 0xeb, 0x06, 0xa9, 0x49, - 0x0d, 0x65, 0xec, 0x8e, 0xfd, 0xdb, 0xc2, 0xff, 0x84, 0x59, 0x59, 0x28, 0x32, 0x27, 0x43, 0x04, - 0x34, 0x24, 0xaf, 0xf0, 0x16, 0xc0, 0x7b, 0xe9, 0x19, 0x69, 0x25, 0x81, 0x38, 0x83, 0xa0, 0xe4, - 0xf2, 0x8e, 0x8a, 0x57, 0xd9, 0x91, 0x63, 0x1c, 0x40, 0xe5, 0x20, 0xf4, 0xb2, 0x98, 0xae, 0x43, - 0x99, 0x7c, 0xe5, 0x27, 0xcf, 0x5b, 0xd4, 0x23, 0x5a, 0x55, 0xd3, 0x62, 0xe2, 0x80, 0x7a, 0x52, - 0x6c, 0x84, 0x73, 0xed, 0x40, 0x0c, 0x45, 0x76, 0xc6, 0x89, 0xf7, 0x38, 0x35, 0x69, 0xab, 0x2d, - 0x3d, 0xdf, 0xe4, 0xdc, 0x64, 0xad, 0xb2, 0xf0, 0xb7, 0x16, 0x54, 0x8f, 0x68, 0xe7, 0x24, 0xe1, - 0xc4, 0x0d, 0x35, 0xa5, 0x81, 0x2b, 0x58, 0x81, 0xc9, 0x36, 0x0d, 0x02, 0xfa, 0x52, 0x7a, 0x9a, - 0x76, 0xb4, 0x85, 0x6c, 0x98, 0x88, 0xfd, 0xa8, 0xa5, 0x32, 0xb2, 0x72, 0x7f, 0xad, 0xa1, 0xde, - 0x8d, 0x86, 0x29, 0xeb, 0x8d, 0x87, 0xba, 0xfe, 0x3b, 0x6a, 0x9f, 0xc9, 0x62, 0x51, 0xae, 0x35, - 0x8f, 0xcc, 0xc6, 0xff, 0x83, 0x19, 0xa3, 0x93, 0x34, 0x1a, 0xc5, 0xa4, 0x06, 0x53, 0x2d, 0x1a, - 0x86, 0xae, 0xd4, 0x83, 0x88, 0x99, 0x31, 0xf1, 0x26, 0x94, 0xd5, 0x47, 0xbc, 0x1f, 0x77, 0xb2, - 0xbc, 0xb1, 0x64, 0xa5, 0x50, 0x79, 0xb3, 0x0f, 0x8b, 0x0e, 0x09, 0x88, 0x1b, 0x17, 0xd3, 0xe6, - 0xaf, 0xa2, 0x9e, 0xcb, 0xe9, 0x01, 0xd9, 0xea, 0xed, 0x4e, 0xb6, 0x01, 0x9f, 0xc0, 0x92, 0x51, - 0x97, 0x5a, 0xd2, 0xba, 0xbd, 0x0d, 0x13, 0x32, 0x33, 0xa4, 0xc3, 0x81, 0xac, 0x51, 0x6b, 0x22, - 0x8a, 0x1e, 0x0d, 0x5d, 0xdf, 0xd4, 0x36, 0x6d, 0xdd, 0xff, 0x75, 0x11, 0xe6, 0x8e, 0x75, 0xa5, - 0x3c, 0x51, 0x8f, 0x32, 0xfa, 0x00, 0x4a, 0xa2, 0x6c, 0xa3, 0xd5, 0xbc, 0xb0, 0x73, 0x45, 0xbf, - 0x5e, 0x1b, 0x5c, 0x50, 0x1f, 0x84, 0x17, 0xbf, 0xfe, 0xf1, 0x97, 0xef, 0xc6, 0x66, 0xf0, 0xb4, - 0xdd, 0xfd, 0x9b, 0xed, 0xa6, 0xc9, 0xf9, 0xae, 0xb5, 0x83, 0x3e, 0x84, 0x29, 0xfd, 0x34, 0x15, - 0x21, 0x73, 0x2f, 0x65, 0x7d, 0xbd, 0x00, 0x59, 0x7c, 0xc8, 0xf0, 0xbc, 0x44, 0x05, 0xa4, 0x50, - 0xc5, 0x9b, 0xd5, 0x84, 0xf2, 0x1e, 0x63, 0x2a, 0x1c, 0x68, 0xa5, 0xef, 0xac, 0xc1, 0xcc, 0xbf, - 0x78, 0x7d, 0xcc, 0x18, 0x8b, 0x05, 0xb3, 0x47, 0x30, 0xb9, 0xc7, 0xd8, 0xff, 0x49, 0x72, 0x3d, - 0x8c, 0x55, 0x89, 0xb1, 0x80, 0xe6, 0x0c, 0x86, 0xfd, 0x4a, 0x08, 0xe3, 0x35, 0x7a, 0xa6, 0x5f, - 0xee, 0x38, 0x71, 0xf9, 0x68, 0xac, 0x95, 0x01, 0x89, 0x36, 0x45, 0xff, 0x82, 0x37, 0x25, 0xec, - 0x1a, 0x5a, 0xed, 0x83, 0xb5, 0xb9, 0x06, 0xfc, 0x48, 0x7e, 0xed, 0x43, 0x12, 0x90, 0x2b, 0xbe, - 0x76, 0x14, 0xba, 0x26, 0xbd, 0x33, 0x40, 0xfa, 0x18, 0x2a, 0x52, 0x22, 0x3a, 0x8a, 0x1b, 0x83, - 0x65, 0x2c, 0xff, 0x60, 0xd6, 0x8b, 0xba, 0xc2, 0x48, 0xc2, 0x56, 0x31, 0x08, 0x58, 0x55, 0x99, - 0xd1, 0x27, 0x1a, 0xf1, 0x30, 0x64, 0x94, 0x27, 0x68, 0x39, 0x8f, 0x98, 0xe5, 0xc7, 0x48, 0xa2, - 0x6b, 0x12, 0x71, 0x11, 0x2f, 0xf4, 0x10, 0x6d, 0x5f, 0x22, 0x6d, 0x5b, 0xe8, 0x14, 0xaa, 0x9a, - 0x8d, 0xd4, 0x3e, 0xda, 0x1a, 0x56, 0x74, 0xf3, 0x69, 0x51, 0xef, 0xcf, 0x24, 0xbc, 0x24, 0xf1, - 0x67, 0x71, 0x55, 0xe0, 0x9b, 0xac, 0x42, 0x47, 0x30, 0x2d, 0x81, 0x85, 0x08, 0x6a, 0x7d, 0xa1, - 0x3d, 0x1c, 0xf5, 0xf1, 0x05, 0x21, 0x68, 0xaa, 0xaf, 0x7c, 0xef, 0x35, 0xfa, 0x58, 0x47, 0x40, - 0xdf, 0xd5, 0x68, 0xc0, 0x6b, 0xdd, 0x56, 0x1e, 0xf9, 0x19, 0x94, 0xb3, 0x17, 0x73, 0xa4, 0x06, - 0x6e, 0xe6, 0xe7, 0x07, 0x1e, 0x58, 0x13, 0x61, 0x94, 0x8f, 0xb0, 0x16, 0x83, 0x67, 0xe0, 0x69, - 0x27, 0x46, 0xeb, 0x83, 0x30, 0x59, 0xaf, 0x52, 0xbf, 0x31, 0x7c, 0x51, 0xbb, 0xb8, 0x21, 0x5d, - 0xac, 0xa0, 0xa5, 0x3e, 0xfe, 0x76, 0x20, 0x80, 0x4f, 0x60, 0xb6, 0x19, 0x75, 0x7d, 0x4e, 0xa3, - 0x90, 0x44, 0xc9, 0x55, 0x79, 0xb7, 0x60, 0x02, 0xde, 0x8c, 0xba, 0x07, 0x34, 0x6a, 0xfb, 0x1d, - 0xbc, 0x22, 0xa1, 0xe7, 0xd1, 0xac, 0x80, 0x26, 0x51, 0xd7, 0x50, 0xff, 0xac, 0x00, 0x7a, 0x42, - 0x12, 0xb4, 0x96, 0x07, 0x2d, 0x34, 0x3a, 0x23, 0xe3, 0xae, 0xc1, 0x71, 0x3f, 0x78, 0x0b, 0x2a, - 0xb9, 0xc2, 0x3d, 0x92, 0xee, 0x66, 0x7e, 0x7e, 0x48, 0xa5, 0xc7, 0xeb, 0x12, 0x7f, 0x19, 0x2d, - 0xe6, 0xc5, 0x67, 0x9c, 0x9c, 0xc1, 0x8c, 0x3e, 0xf3, 0xce, 0xba, 0xd1, 0x35, 0x64, 0x67, 0xb5, - 0x88, 0xef, 0x32, 0xf6, 0x5a, 0xe9, 0xe7, 0x05, 0x54, 0xf3, 0x9d, 0xdb, 0xe8, 0x4a, 0xbc, 0x55, - 0xfc, 0x94, 0xc1, 0x66, 0x0f, 0x2f, 0x4b, 0x5f, 0x73, 0x68, 0x46, 0xf9, 0xd2, 0x3d, 0x1d, 0x7a, - 0x22, 0x42, 0xa5, 0x8c, 0xab, 0x6e, 0x76, 0xa0, 0x2f, 0x2c, 0x6a, 0x26, 0xc3, 0x33, 0xc1, 0x79, - 0x0a, 0xb3, 0x66, 0xa7, 0xae, 0x54, 0xb7, 0x7e, 0xb7, 0xe1, 0x1a, 0xe2, 0x44, 0x93, 0xc6, 0x7d, - 0xa4, 0x3f, 0xef, 0xa1, 0xbf, 0x63, 0x7d, 0xd5, 0xec, 0x77, 0x86, 0xb3, 0x27, 0xf9, 0xb0, 0x47, - 0x17, 0xa8, 0x3e, 0x80, 0x9e, 0x11, 0x1f, 0x42, 0xfa, 0x2f, 0x12, 0xfb, 0x56, 0x7d, 0x73, 0x18, - 0xb6, 0x1d, 0xf8, 0xd1, 0x85, 0xba, 0x62, 0xe4, 0xf7, 0x3e, 0xe3, 0x49, 0x14, 0xfc, 0x71, 0x47, - 0x77, 0xa4, 0xa3, 0xdb, 0xf5, 0x5b, 0x43, 0x1d, 0xa5, 0x51, 0xce, 0xd5, 0x63, 0x98, 0xd2, 0x4d, - 0x64, 0x31, 0x54, 0xbd, 0xce, 0xb2, 0x5e, 0xd0, 0x56, 0xae, 0x9f, 0x34, 0x8f, 0x30, 0xaa, 0x08, - 0x37, 0x17, 0x1a, 0xe5, 0x14, 0xa0, 0xd7, 0x7b, 0x8d, 0x7a, 0x34, 0x86, 0x4f, 0x17, 0x0b, 0x31, - 0x53, 0x28, 0x36, 0x4f, 0xa3, 0x6d, 0xeb, 0x9e, 0x85, 0x5e, 0x40, 0x25, 0xf7, 0x43, 0xe1, 0x7a, - 0xb9, 0x3b, 0xe4, 0x97, 0x05, 0xae, 0x49, 0x27, 0x08, 0xcd, 0xe7, 0x9d, 0x04, 0x02, 0xf2, 0x34, - 0xf3, 0x70, 0xe2, 0x76, 0x09, 0xca, 0x8a, 0xd6, 0x23, 0xca, 0x43, 0xd9, 0x7b, 0x8e, 0x54, 0xcd, - 0x4d, 0x89, 0xb9, 0x8a, 0x96, 0xf3, 0x98, 0x6d, 0x73, 0x0c, 0x9d, 0x42, 0x39, 0x6b, 0x8c, 0x8b, - 0xd5, 0x20, 0xdf, 0x2f, 0x5f, 0x2b, 0x2a, 0xa2, 0xf0, 0xea, 0x8b, 0xbc, 0x67, 0xed, 0xd7, 0xde, - 0xbc, 0xdd, 0xb0, 0x7e, 0x78, 0xbb, 0x61, 0xfd, 0xfc, 0x76, 0xc3, 0xfa, 0x34, 0xf7, 0x7f, 0x97, - 0xb3, 0x49, 0xc9, 0xf0, 0xef, 0xbf, 0x05, 0x00, 0x00, 0xff, 0xff, 0x67, 0xc1, 0x55, 0x4a, 0x9c, - 0x11, 0x00, 0x00, + // 1585 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x58, 0x5b, 0x6f, 0x1b, 0xc5, + 0x17, 0xff, 0x6f, 0xe2, 0x5c, 0x7c, 0xec, 0xdc, 0x26, 0x37, 0xc7, 0x49, 0x93, 0x74, 0xaa, 0xbf, + 0x48, 0x83, 0x6a, 0x97, 0x82, 0xb8, 0xa4, 0xe5, 0x21, 0x49, 0x5d, 0x14, 0x11, 0x68, 0xd8, 0x50, + 0x85, 0x4b, 0xa1, 0xdd, 0xd8, 0x63, 0x67, 0xc9, 0x7a, 0x67, 0x98, 0x5d, 0xbb, 0x44, 0x55, 0x5f, + 0x10, 0x12, 0x1f, 0x80, 0x4f, 0xc4, 0x5b, 0x1f, 0x91, 0x78, 0x47, 0xa8, 0xe2, 0x1b, 0xf0, 0x05, + 0xd0, 0xdc, 0xd6, 0xb3, 0xf6, 0x3a, 0x84, 0xbe, 0x44, 0x73, 0x76, 0x66, 0x7e, 0xe7, 0x37, 0x67, + 0x7e, 0xe7, 0x9c, 0x71, 0x60, 0x3a, 0x22, 0xbc, 0xeb, 0xd7, 0x49, 0x54, 0x61, 0x9c, 0xc6, 0x14, + 0x41, 0x9d, 0x86, 0x31, 0xa7, 0x41, 0x40, 0x78, 0x79, 0xad, 0x45, 0x69, 0x2b, 0x20, 0x55, 0x8f, + 0xf9, 0x55, 0x2f, 0x0c, 0x69, 0xec, 0xc5, 0x3e, 0x0d, 0xf5, 0xca, 0x72, 0x89, 0xc5, 0x17, 0x8c, + 0x44, 0x55, 0xd2, 0x66, 0xf1, 0x85, 0xfa, 0xab, 0x67, 0xd6, 0xf5, 0x4c, 0xa3, 0xc3, 0xe5, 0x8e, + 0x64, 0xa0, 0xe7, 0x6f, 0xb5, 0xfc, 0xf8, 0xac, 0x73, 0x5a, 0xa9, 0xd3, 0x76, 0xb5, 0x45, 0x5b, + 0xb4, 0x2a, 0x3f, 0x9f, 0x76, 0x9a, 0xd2, 0x92, 0x86, 0x1c, 0xe9, 0xe5, 0xef, 0x58, 0xcb, 0x1b, + 0x5e, 0xec, 0xd5, 0x69, 0x70, 0xcb, 0xa7, 0x66, 0x28, 0xd9, 0xb5, 0x69, 0x83, 0x04, 0x51, 0x55, + 0xba, 0x55, 0xbb, 0xf0, 0x5d, 0x28, 0x1c, 0xfa, 0x51, 0xec, 0x92, 0xef, 0x3b, 0x24, 0x8a, 0xd1, + 0x12, 0x8c, 0xd3, 0x66, 0x33, 0x22, 0x71, 0xc9, 0xd9, 0x74, 0xb6, 0xc6, 0x5c, 0x6d, 0xa1, 0x05, + 0x18, 0x0b, 0xfc, 0xb6, 0x1f, 0x97, 0x46, 0xe4, 0x67, 0x65, 0xe0, 0xbb, 0x00, 0xbb, 0x8c, 0x99, + 0xbd, 0x08, 0x72, 0xa1, 0xd7, 0x26, 0x72, 0x67, 0xde, 0x95, 0x63, 0xb4, 0x02, 0x93, 0x9c, 0x30, + 0xfa, 0xa4, 0xc3, 0x03, 0xb9, 0x35, 0xef, 0x4e, 0x08, 0xfb, 0x11, 0x0f, 0x70, 0x13, 0x66, 0x76, + 0x19, 0x53, 0xce, 0x23, 0x46, 0xc3, 0x88, 0xa0, 0xff, 0x43, 0xce, 0x63, 0x2c, 0x2a, 0x39, 0x9b, + 0xa3, 0x5b, 0x85, 0x3b, 0x85, 0x8a, 0xe2, 0x5b, 0xd9, 0x65, 0x6c, 0x2f, 0xf7, 0xf2, 0x8f, 0x8d, + 0xff, 0xb9, 0x72, 0x3a, 0x9b, 0x8c, 0x45, 0x7d, 0xd4, 0xa6, 0x8e, 0x6f, 0x42, 0x61, 0xb7, 0x13, + 0x9f, 0x19, 0x96, 0x65, 0x98, 0x64, 0x5e, 0x14, 0x3d, 0xa3, 0xbc, 0xa1, 0x99, 0x26, 0x36, 0xfe, + 0xc9, 0x81, 0xa2, 0x5a, 0xab, 0x09, 0x21, 0xc8, 0x9d, 0xd1, 0x28, 0x36, 0x47, 0x12, 0xe3, 0xe4, + 0x98, 0x23, 0xd6, 0x31, 0x4b, 0x30, 0xc1, 0x38, 0xfd, 0x8e, 0xd4, 0x95, 0xf3, 0xbc, 0x6b, 0x4c, + 0xc1, 0x8a, 0x93, 0x96, 0x4f, 0xc3, 0x52, 0x4e, 0x4e, 0x68, 0x4b, 0xd2, 0xe0, 0xb4, 0xeb, 0x37, + 0x08, 0x2f, 0x8d, 0x69, 0x1a, 0xda, 0xc6, 0x8f, 0x01, 0xed, 0x73, 0xe2, 0xc5, 0x64, 0xaf, 0xe3, + 0x07, 0x0d, 0x43, 0x7c, 0x16, 0x46, 0x3d, 0xc6, 0x34, 0x15, 0x31, 0x14, 0x5e, 0xbb, 0x84, 0x47, + 0x02, 0x5c, 0xc7, 0x56, 0x9b, 0x1a, 0xbd, 0xde, 0xf4, 0x03, 0x22, 0x09, 0x15, 0xdd, 0xc4, 0xc6, + 0xb7, 0xa1, 0xb8, 0xcb, 0xd8, 0xc1, 0x25, 0xb8, 0xd3, 0x30, 0xe2, 0x37, 0x34, 0xe4, 0x88, 0xdf, + 0xc0, 0x35, 0x98, 0x91, 0x4c, 0x0e, 0x69, 0xeb, 0xca, 0x9b, 0xc4, 0x0a, 0x46, 0x23, 0x7d, 0x17, + 0x62, 0x88, 0x77, 0x60, 0xb6, 0x07, 0xa3, 0x03, 0xac, 0x57, 0x39, 0xc9, 0x2a, 0x75, 0xb9, 0x21, + 0x89, 0x4a, 0x23, 0x9b, 0xa3, 0x5b, 0x79, 0x57, 0x19, 0xf8, 0x3d, 0x98, 0xaa, 0x85, 0xdd, 0x63, + 0x12, 0x5f, 0x26, 0x36, 0x04, 0x39, 0xa1, 0x76, 0x73, 0x33, 0x62, 0x8c, 0x1f, 0xc0, 0x82, 0x4b, + 0x22, 0xda, 0xe1, 0x75, 0x92, 0x92, 0x5a, 0x05, 0xf2, 0x5c, 0x7f, 0x37, 0x7a, 0x9b, 0x35, 0x7a, + 0x33, 0x1b, 0xdc, 0xde, 0x12, 0x7c, 0xcf, 0x90, 0xb7, 0x92, 0x25, 0x8b, 0x43, 0x76, 0xa2, 0xec, + 0xc0, 0x9c, 0xb5, 0x3b, 0x51, 0xfb, 0xf8, 0xa9, 0xf8, 0x68, 0xfc, 0x4f, 0x19, 0xff, 0xea, 0xda, + 0xf5, 0x24, 0xbe, 0x07, 0xf3, 0x47, 0x9c, 0xd6, 0x49, 0x14, 0xf5, 0xed, 0x1e, 0x3b, 0x88, 0x49, + 0xdb, 0x6c, 0x9e, 0x31, 0x9b, 0xf5, 0x5a, 0x57, 0xcd, 0xe2, 0x5f, 0x1d, 0x58, 0x54, 0x62, 0x4a, + 0x4e, 0x75, 0x79, 0x04, 0xcf, 0xfd, 0xd0, 0x5c, 0xa3, 0x1c, 0xa3, 0x1a, 0x8c, 0x33, 0x8f, 0x7b, + 0x6d, 0x71, 0x97, 0xc2, 0xd3, 0xad, 0x4a, 0xaf, 0xf6, 0x55, 0x32, 0xa1, 0x2b, 0x47, 0x72, 0x7d, + 0x2d, 0x8c, 0xf9, 0x85, 0xab, 0x37, 0x97, 0x3f, 0x80, 0x82, 0xf5, 0x59, 0x5c, 0xfc, 0x39, 0xb9, + 0x30, 0x02, 0x3a, 0x27, 0x17, 0x22, 0x72, 0x5d, 0x2f, 0xe8, 0x98, 0xc4, 0x52, 0xc6, 0xce, 0xc8, + 0xfb, 0x0e, 0x7e, 0x17, 0xa6, 0x65, 0x99, 0x49, 0x9c, 0x64, 0xc8, 0x2f, 0x23, 0x2b, 0xf1, 0x26, + 0xc0, 0xc7, 0x9d, 0x53, 0x52, 0x8f, 0x03, 0xb1, 0x07, 0x41, 0xce, 0xe3, 0x2d, 0x15, 0xaf, 0xbc, + 0x2b, 0xc7, 0x38, 0x80, 0xc2, 0x7e, 0xbb, 0x91, 0xc4, 0x74, 0x15, 0xf2, 0xe4, 0x07, 0x3f, 0x7e, + 0x52, 0xa7, 0x0d, 0xa2, 0x35, 0x39, 0x29, 0x3e, 0xec, 0xd3, 0x86, 0x94, 0x2a, 0xe1, 0x5c, 0x3b, + 0x10, 0x43, 0x91, 0xdb, 0x51, 0xdc, 0x78, 0xd8, 0x31, 0x49, 0xaf, 0x2d, 0xfd, 0xbd, 0xc6, 0xb9, + 0xc9, 0x79, 0x65, 0xe1, 0x9f, 0x1d, 0x28, 0x1e, 0xd2, 0xd6, 0x71, 0xcc, 0x89, 0xd7, 0xd6, 0x94, + 0x06, 0xae, 0x60, 0x09, 0xc6, 0x9b, 0x34, 0x08, 0xe8, 0x33, 0xe9, 0x69, 0xd2, 0xd5, 0x16, 0xaa, + 0xc2, 0x58, 0xe4, 0x87, 0x75, 0x95, 0xcf, 0x85, 0x3b, 0x2b, 0x15, 0xd5, 0x75, 0x2a, 0xa6, 0x29, + 0x54, 0xee, 0xeb, 0xee, 0xe1, 0xaa, 0x75, 0xa6, 0x06, 0x88, 0x62, 0xaf, 0x79, 0x24, 0x36, 0xfe, + 0x10, 0xa6, 0x8c, 0x4e, 0x3a, 0xe1, 0x30, 0x26, 0x25, 0x98, 0xa8, 0xd3, 0x76, 0xdb, 0x93, 0x7a, + 0x10, 0x31, 0x33, 0x26, 0xde, 0x80, 0xbc, 0x3a, 0xc4, 0x27, 0x51, 0x2b, 0xc9, 0x3a, 0x47, 0xd6, + 0x19, 0x95, 0x75, 0x7b, 0x30, 0xef, 0x92, 0x80, 0x78, 0x51, 0x3a, 0xe9, 0xde, 0x14, 0xdd, 0x40, + 0x7e, 0x1e, 0x90, 0xad, 0x5e, 0xee, 0x26, 0x0b, 0xf0, 0x31, 0x2c, 0x18, 0x75, 0xa9, 0x29, 0xad, + 0xdb, 0x1b, 0x30, 0x26, 0x33, 0x43, 0x3a, 0x1c, 0xc8, 0x1a, 0x35, 0x27, 0xa2, 0xd8, 0xa0, 0x6d, + 0xcf, 0x37, 0x95, 0x51, 0x5b, 0x77, 0xfe, 0x9e, 0x87, 0x99, 0x23, 0x5d, 0x67, 0x8f, 0x55, 0x4b, + 0x47, 0x9f, 0x42, 0x4e, 0x14, 0x7d, 0xb4, 0x6c, 0x0b, 0xdb, 0x6a, 0x19, 0xe5, 0xd2, 0xe0, 0x84, + 0x3a, 0x10, 0x9e, 0xff, 0xf1, 0xf7, 0xbf, 0x7e, 0x19, 0x99, 0xc2, 0x93, 0xd5, 0xee, 0x5b, 0x55, + 0xaf, 0x13, 0x9f, 0xed, 0x38, 0xdb, 0xe8, 0x33, 0x98, 0xd0, 0x8d, 0x2d, 0x0d, 0x69, 0x95, 0x8e, + 0xf2, 0x6a, 0x0a, 0x32, 0xdd, 0x06, 0xf1, 0xac, 0x44, 0x05, 0xa4, 0x50, 0x45, 0xc7, 0xab, 0x41, + 0x7e, 0x97, 0x31, 0x15, 0x0e, 0xb4, 0xd4, 0xb7, 0xd7, 0x60, 0xda, 0xfd, 0xb2, 0x8f, 0x19, 0x63, + 0x91, 0x60, 0xf6, 0x00, 0xc6, 0x77, 0x19, 0xfb, 0x88, 0xc4, 0x57, 0xc3, 0x58, 0x96, 0x18, 0x73, + 0x68, 0xc6, 0x60, 0x54, 0x9f, 0x0b, 0x61, 0xbc, 0x40, 0xdf, 0xe8, 0xbe, 0x1f, 0xc5, 0x1e, 0x1f, + 0x8e, 0xb5, 0x34, 0x20, 0xd1, 0x9a, 0x78, 0xfd, 0xe0, 0x0d, 0x09, 0xbb, 0x82, 0x96, 0xfb, 0x60, + 0xab, 0x5c, 0x03, 0x7e, 0x2e, 0x4f, 0x7b, 0x9f, 0x04, 0xe4, 0x92, 0xd3, 0x0e, 0x43, 0xd7, 0xa4, + 0xb7, 0x07, 0x48, 0x1f, 0x41, 0x41, 0x4a, 0x44, 0x47, 0x71, 0x7d, 0xb0, 0x8c, 0xd9, 0xed, 0xb6, + 0x9c, 0xd6, 0x15, 0x46, 0x12, 0xb6, 0x88, 0x41, 0xc0, 0xaa, 0xca, 0x8c, 0xbe, 0xd4, 0x88, 0x07, + 0x6d, 0x46, 0x79, 0x8c, 0x16, 0x6d, 0xc4, 0x24, 0x3f, 0x86, 0x12, 0x5d, 0x91, 0x88, 0xf3, 0x78, + 0xae, 0x87, 0x58, 0xf5, 0x25, 0xd2, 0x96, 0x83, 0x4e, 0xa0, 0xa8, 0xd9, 0x48, 0xed, 0xa3, 0xcd, + 0xac, 0xa2, 0x6b, 0xa7, 0x45, 0xb9, 0x3f, 0x93, 0xf0, 0x82, 0xc4, 0x9f, 0xc6, 0x45, 0x81, 0x6f, + 0xb2, 0x0a, 0x1d, 0xc2, 0xa4, 0x04, 0x16, 0x22, 0x28, 0xf5, 0x85, 0xf6, 0x60, 0xd8, 0xe1, 0x53, + 0x42, 0xd0, 0x54, 0x9f, 0xfb, 0x8d, 0x17, 0xe8, 0x0b, 0x1d, 0x01, 0x7d, 0x57, 0xc3, 0x01, 0xaf, + 0x74, 0x5b, 0x36, 0x72, 0x1d, 0xf2, 0x49, 0xc7, 0x44, 0x6b, 0x36, 0x6e, 0x7f, 0x1b, 0x2e, 0x5f, + 0x1b, 0x32, 0xab, 0xb3, 0x49, 0xc7, 0x19, 0xd9, 0x71, 0xd6, 0x92, 0x68, 0x18, 0x27, 0xb4, 0x15, + 0xa1, 0xd5, 0x41, 0x98, 0xe4, 0xbd, 0x53, 0x5e, 0xcb, 0x9e, 0xd4, 0x2e, 0xd6, 0xa4, 0x8b, 0x25, + 0xb4, 0xd0, 0x77, 0x8a, 0x6a, 0x20, 0x80, 0x8f, 0x61, 0xba, 0x16, 0x76, 0x7d, 0x4e, 0xc3, 0x36, + 0x09, 0xe3, 0xcb, 0xb2, 0x6f, 0xce, 0x84, 0xbd, 0x16, 0x76, 0xf7, 0x69, 0xd8, 0xf4, 0x5b, 0x78, + 0x49, 0x42, 0xcf, 0xa2, 0x69, 0x01, 0x4d, 0xc2, 0xae, 0xa1, 0xfe, 0x75, 0x0a, 0xf4, 0x98, 0xc4, + 0x68, 0xc5, 0x06, 0x4d, 0x3d, 0x96, 0x86, 0x46, 0x5f, 0x83, 0xe3, 0x7e, 0xf0, 0x3a, 0x14, 0xac, + 0xf2, 0x3d, 0x94, 0xee, 0x86, 0xfd, 0x3d, 0xa3, 0xde, 0xe3, 0x55, 0x89, 0xbf, 0x88, 0xe6, 0x6d, + 0x09, 0x1a, 0x27, 0xa7, 0x30, 0xa5, 0xf7, 0xbc, 0xb6, 0x7a, 0x74, 0x25, 0xd9, 0x5e, 0x4e, 0xe3, + 0x7b, 0x8c, 0xbd, 0x50, 0x2a, 0x7a, 0x0a, 0x45, 0xfb, 0xf5, 0x37, 0xbc, 0x1e, 0x6f, 0xa6, 0x8f, + 0x32, 0xf8, 0x60, 0xc4, 0x8b, 0xd2, 0xd7, 0x0c, 0x9a, 0x52, 0xbe, 0xf4, 0xbb, 0x10, 0x3d, 0x12, + 0xa1, 0x52, 0xc6, 0x65, 0x37, 0x3b, 0xf0, 0xb6, 0x4c, 0x6b, 0x26, 0xc1, 0x33, 0xc1, 0x79, 0x0c, + 0xd3, 0x66, 0xa5, 0xae, 0x57, 0xd7, 0xff, 0xf5, 0xd9, 0x95, 0xe1, 0x44, 0x93, 0xc6, 0x7d, 0xa4, + 0xbf, 0xed, 0xa1, 0xbf, 0x66, 0x95, 0xd5, 0xec, 0xb7, 0xb3, 0xd9, 0x13, 0x3b, 0xec, 0xe1, 0x39, + 0x2a, 0x0f, 0xa0, 0x27, 0xc4, 0x33, 0x48, 0xbf, 0x21, 0xb1, 0xaf, 0x97, 0x37, 0xb2, 0xb0, 0xab, + 0x81, 0x1f, 0x9e, 0xab, 0x2b, 0x46, 0x7e, 0xef, 0x18, 0x8f, 0xc2, 0xe0, 0xbf, 0x3b, 0xba, 0x29, + 0x1d, 0xdd, 0x28, 0x5f, 0xcf, 0x74, 0xd4, 0x09, 0x2d, 0x57, 0x0f, 0x61, 0x42, 0x3f, 0x25, 0xd3, + 0xa1, 0xea, 0xbd, 0x2f, 0xcb, 0x29, 0x6d, 0x59, 0xaf, 0x4a, 0xd3, 0x8a, 0x51, 0x41, 0xb8, 0x39, + 0xd7, 0x28, 0x27, 0x00, 0xbd, 0x17, 0xd8, 0xb0, 0xd6, 0x91, 0xfd, 0x39, 0x5d, 0x8e, 0x99, 0x42, + 0xa9, 0xf2, 0x4e, 0xb8, 0xe5, 0xdc, 0x76, 0xd0, 0x53, 0x28, 0x58, 0x3f, 0x17, 0xae, 0x96, 0xbb, + 0x19, 0xbf, 0x2f, 0x70, 0x49, 0x3a, 0x41, 0x68, 0xd6, 0x76, 0x12, 0x08, 0xc8, 0x93, 0xc4, 0xc3, + 0xb1, 0xd7, 0x25, 0x28, 0x29, 0x5a, 0x0f, 0x28, 0x6f, 0xcb, 0x17, 0xe8, 0x50, 0xd5, 0x5c, 0x93, + 0x98, 0xcb, 0x68, 0xd1, 0xc6, 0x6c, 0x9a, 0x6d, 0xe8, 0x04, 0xf2, 0xc9, 0xf3, 0x38, 0x5d, 0x0d, + 0xec, 0x57, 0xf3, 0x95, 0xa2, 0x22, 0x0a, 0xaf, 0xbe, 0xc8, 0xdb, 0xce, 0x5e, 0xe9, 0xe5, 0xab, + 0x75, 0xe7, 0xb7, 0x57, 0xeb, 0xce, 0x9f, 0xaf, 0xd6, 0x9d, 0xaf, 0xac, 0xff, 0xdd, 0x9c, 0x8e, + 0x4b, 0x86, 0x6f, 0xff, 0x13, 0x00, 0x00, 0xff, 0xff, 0x05, 0xf4, 0xfb, 0xef, 0xe0, 0x11, 0x00, + 0x00, } diff --git a/api/controller/services.pb.gw.go b/api/controller/services.pb.gw.go index fd17f66c..bc193e4b 100644 --- a/api/controller/services.pb.gw.go +++ b/api/controller/services.pb.gw.go @@ -327,7 +327,7 @@ var ( ) func request_ProviderService_BuildList_0(ctx context.Context, marshaler runtime.Marshaler, client ProviderServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq AppRequest + var protoReq BuildListRequest var metadata runtime.ServerMetadata var ( diff --git a/api/controller/services.proto b/api/controller/services.proto index 95ae5dce..03579473 100644 --- a/api/controller/services.proto +++ b/api/controller/services.proto @@ -71,6 +71,12 @@ message ResourceListResponse { repeated models.Resource resources = 1; } + +message BuildListRequest { + string name = 1; + int32 limit = 2; +} + message BuildListResponse { repeated models.Build builds = 1; } @@ -197,7 +203,7 @@ service ProviderService { }; } - rpc BuildList(AppRequest) returns (BuildListResponse) { + rpc BuildList(BuildListRequest) returns (BuildListResponse) { option (google.api.http) = { get: "/v1/builds/{name}" }; diff --git a/api/controller/services.swagger.json b/api/controller/services.swagger.json index bae34437..7a7c16d1 100644 --- a/api/controller/services.swagger.json +++ b/api/controller/services.swagger.json @@ -321,10 +321,11 @@ "type": "string" }, { - "name": "repo_url", + "name": "limit", "in": "query", "required": false, - "type": "string" + "type": "integer", + "format": "int32" } ], "tags": [ diff --git a/api/models/types.pb.go b/api/models/types.pb.go index 9c67a5e5..e443ca50 100644 --- a/api/models/types.pb.go +++ b/api/models/types.pb.go @@ -891,6 +891,24 @@ func (m *Formation) MarshalTo(dAtA []byte) (int, error) { return i, nil } +func encodeFixed64Types(dAtA []byte, offset int, v uint64) int { + dAtA[offset] = uint8(v) + dAtA[offset+1] = uint8(v >> 8) + dAtA[offset+2] = uint8(v >> 16) + dAtA[offset+3] = uint8(v >> 24) + dAtA[offset+4] = uint8(v >> 32) + dAtA[offset+5] = uint8(v >> 40) + dAtA[offset+6] = uint8(v >> 48) + dAtA[offset+7] = uint8(v >> 56) + return offset + 8 +} +func encodeFixed32Types(dAtA []byte, offset int, v uint32) int { + dAtA[offset] = uint8(v) + dAtA[offset+1] = uint8(v >> 8) + dAtA[offset+2] = uint8(v >> 16) + dAtA[offset+3] = uint8(v >> 24) + return offset + 4 +} func encodeVarintTypes(dAtA []byte, offset int, v uint64) int { for v >= 1<<7 { dAtA[offset] = uint8(v&0x7f | 0x80) @@ -2085,14 +2103,51 @@ func (m *Resource) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } + var keykey uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + keykey |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + var stringLenmapkey uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLenmapkey |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLenmapkey := int(stringLenmapkey) + if intStringLenmapkey < 0 { + return ErrInvalidLengthTypes + } + postStringIndexmapkey := iNdEx + intStringLenmapkey + if postStringIndexmapkey > l { + return io.ErrUnexpectedEOF + } + mapkey := string(dAtA[iNdEx:postStringIndexmapkey]) + iNdEx = postStringIndexmapkey if m.Exports == nil { m.Exports = make(map[string]string) } - var mapkey string - var mapvalue string - for iNdEx < postIndex { - entryPreIndex := iNdEx - var wire uint64 + if iNdEx < postIndex { + var valuekey uint64 for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowTypes @@ -2102,80 +2157,41 @@ func (m *Resource) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - wire |= (uint64(b) & 0x7F) << shift + valuekey |= (uint64(b) & 0x7F) << shift if b < 0x80 { break } } - fieldNum := int32(wire >> 3) - if fieldNum == 1 { - var stringLenmapkey uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTypes - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLenmapkey |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - intStringLenmapkey := int(stringLenmapkey) - if intStringLenmapkey < 0 { - return ErrInvalidLengthTypes - } - postStringIndexmapkey := iNdEx + intStringLenmapkey - if postStringIndexmapkey > l { - return io.ErrUnexpectedEOF - } - mapkey = string(dAtA[iNdEx:postStringIndexmapkey]) - iNdEx = postStringIndexmapkey - } else if fieldNum == 2 { - var stringLenmapvalue uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTypes - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLenmapvalue |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - intStringLenmapvalue := int(stringLenmapvalue) - if intStringLenmapvalue < 0 { - return ErrInvalidLengthTypes + var stringLenmapvalue uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes } - postStringIndexmapvalue := iNdEx + intStringLenmapvalue - if postStringIndexmapvalue > l { + if iNdEx >= l { return io.ErrUnexpectedEOF } - mapvalue = string(dAtA[iNdEx:postStringIndexmapvalue]) - iNdEx = postStringIndexmapvalue - } else { - iNdEx = entryPreIndex - skippy, err := skipTypes(dAtA[iNdEx:]) - if err != nil { - return err - } - if skippy < 0 { - return ErrInvalidLengthTypes - } - if (iNdEx + skippy) > postIndex { - return io.ErrUnexpectedEOF + b := dAtA[iNdEx] + iNdEx++ + stringLenmapvalue |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break } - iNdEx += skippy } + intStringLenmapvalue := int(stringLenmapvalue) + if intStringLenmapvalue < 0 { + return ErrInvalidLengthTypes + } + postStringIndexmapvalue := iNdEx + intStringLenmapvalue + if postStringIndexmapvalue > l { + return io.ErrUnexpectedEOF + } + mapvalue := string(dAtA[iNdEx:postStringIndexmapvalue]) + iNdEx = postStringIndexmapvalue + m.Exports[mapkey] = mapvalue + } else { + var mapvalue string + m.Exports[mapkey] = mapvalue } - m.Exports[mapkey] = mapvalue iNdEx = postIndex case 9: if wireType != 2 { @@ -2203,14 +2219,51 @@ func (m *Resource) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } + var keykey uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + keykey |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + var stringLenmapkey uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLenmapkey |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLenmapkey := int(stringLenmapkey) + if intStringLenmapkey < 0 { + return ErrInvalidLengthTypes + } + postStringIndexmapkey := iNdEx + intStringLenmapkey + if postStringIndexmapkey > l { + return io.ErrUnexpectedEOF + } + mapkey := string(dAtA[iNdEx:postStringIndexmapkey]) + iNdEx = postStringIndexmapkey if m.Parameters == nil { m.Parameters = make(map[string]string) } - var mapkey string - var mapvalue string - for iNdEx < postIndex { - entryPreIndex := iNdEx - var wire uint64 + if iNdEx < postIndex { + var valuekey uint64 for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowTypes @@ -2220,80 +2273,41 @@ func (m *Resource) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - wire |= (uint64(b) & 0x7F) << shift + valuekey |= (uint64(b) & 0x7F) << shift if b < 0x80 { break } } - fieldNum := int32(wire >> 3) - if fieldNum == 1 { - var stringLenmapkey uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTypes - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLenmapkey |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - intStringLenmapkey := int(stringLenmapkey) - if intStringLenmapkey < 0 { - return ErrInvalidLengthTypes - } - postStringIndexmapkey := iNdEx + intStringLenmapkey - if postStringIndexmapkey > l { - return io.ErrUnexpectedEOF - } - mapkey = string(dAtA[iNdEx:postStringIndexmapkey]) - iNdEx = postStringIndexmapkey - } else if fieldNum == 2 { - var stringLenmapvalue uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTypes - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLenmapvalue |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - intStringLenmapvalue := int(stringLenmapvalue) - if intStringLenmapvalue < 0 { - return ErrInvalidLengthTypes + var stringLenmapvalue uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes } - postStringIndexmapvalue := iNdEx + intStringLenmapvalue - if postStringIndexmapvalue > l { + if iNdEx >= l { return io.ErrUnexpectedEOF } - mapvalue = string(dAtA[iNdEx:postStringIndexmapvalue]) - iNdEx = postStringIndexmapvalue - } else { - iNdEx = entryPreIndex - skippy, err := skipTypes(dAtA[iNdEx:]) - if err != nil { - return err - } - if skippy < 0 { - return ErrInvalidLengthTypes - } - if (iNdEx + skippy) > postIndex { - return io.ErrUnexpectedEOF + b := dAtA[iNdEx] + iNdEx++ + stringLenmapvalue |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break } - iNdEx += skippy } + intStringLenmapvalue := int(stringLenmapvalue) + if intStringLenmapvalue < 0 { + return ErrInvalidLengthTypes + } + postStringIndexmapvalue := iNdEx + intStringLenmapvalue + if postStringIndexmapvalue > l { + return io.ErrUnexpectedEOF + } + mapvalue := string(dAtA[iNdEx:postStringIndexmapvalue]) + iNdEx = postStringIndexmapvalue + m.Parameters[mapkey] = mapvalue + } else { + var mapvalue string + m.Parameters[mapkey] = mapvalue } - m.Parameters[mapkey] = mapvalue iNdEx = postIndex case 10: if wireType != 2 { @@ -2321,14 +2335,51 @@ func (m *Resource) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } + var keykey uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + keykey |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + var stringLenmapkey uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLenmapkey |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLenmapkey := int(stringLenmapkey) + if intStringLenmapkey < 0 { + return ErrInvalidLengthTypes + } + postStringIndexmapkey := iNdEx + intStringLenmapkey + if postStringIndexmapkey > l { + return io.ErrUnexpectedEOF + } + mapkey := string(dAtA[iNdEx:postStringIndexmapkey]) + iNdEx = postStringIndexmapkey if m.Outputs == nil { m.Outputs = make(map[string]string) } - var mapkey string - var mapvalue string - for iNdEx < postIndex { - entryPreIndex := iNdEx - var wire uint64 + if iNdEx < postIndex { + var valuekey uint64 for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowTypes @@ -2338,80 +2389,41 @@ func (m *Resource) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - wire |= (uint64(b) & 0x7F) << shift + valuekey |= (uint64(b) & 0x7F) << shift if b < 0x80 { break } } - fieldNum := int32(wire >> 3) - if fieldNum == 1 { - var stringLenmapkey uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTypes - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLenmapkey |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - intStringLenmapkey := int(stringLenmapkey) - if intStringLenmapkey < 0 { - return ErrInvalidLengthTypes - } - postStringIndexmapkey := iNdEx + intStringLenmapkey - if postStringIndexmapkey > l { - return io.ErrUnexpectedEOF - } - mapkey = string(dAtA[iNdEx:postStringIndexmapkey]) - iNdEx = postStringIndexmapkey - } else if fieldNum == 2 { - var stringLenmapvalue uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTypes - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLenmapvalue |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - intStringLenmapvalue := int(stringLenmapvalue) - if intStringLenmapvalue < 0 { - return ErrInvalidLengthTypes + var stringLenmapvalue uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes } - postStringIndexmapvalue := iNdEx + intStringLenmapvalue - if postStringIndexmapvalue > l { + if iNdEx >= l { return io.ErrUnexpectedEOF } - mapvalue = string(dAtA[iNdEx:postStringIndexmapvalue]) - iNdEx = postStringIndexmapvalue - } else { - iNdEx = entryPreIndex - skippy, err := skipTypes(dAtA[iNdEx:]) - if err != nil { - return err - } - if skippy < 0 { - return ErrInvalidLengthTypes - } - if (iNdEx + skippy) > postIndex { - return io.ErrUnexpectedEOF + b := dAtA[iNdEx] + iNdEx++ + stringLenmapvalue |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break } - iNdEx += skippy } + intStringLenmapvalue := int(stringLenmapvalue) + if intStringLenmapvalue < 0 { + return ErrInvalidLengthTypes + } + postStringIndexmapvalue := iNdEx + intStringLenmapvalue + if postStringIndexmapvalue > l { + return io.ErrUnexpectedEOF + } + mapvalue := string(dAtA[iNdEx:postStringIndexmapvalue]) + iNdEx = postStringIndexmapvalue + m.Outputs[mapkey] = mapvalue + } else { + var mapvalue string + m.Outputs[mapkey] = mapvalue } - m.Outputs[mapkey] = mapvalue iNdEx = postIndex case 11: if wireType != 2 { @@ -2439,14 +2451,51 @@ func (m *Resource) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } + var keykey uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + keykey |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + var stringLenmapkey uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLenmapkey |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLenmapkey := int(stringLenmapkey) + if intStringLenmapkey < 0 { + return ErrInvalidLengthTypes + } + postStringIndexmapkey := iNdEx + intStringLenmapkey + if postStringIndexmapkey > l { + return io.ErrUnexpectedEOF + } + mapkey := string(dAtA[iNdEx:postStringIndexmapkey]) + iNdEx = postStringIndexmapkey if m.Tags == nil { m.Tags = make(map[string]string) } - var mapkey string - var mapvalue string - for iNdEx < postIndex { - entryPreIndex := iNdEx - var wire uint64 + if iNdEx < postIndex { + var valuekey uint64 for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowTypes @@ -2456,80 +2505,41 @@ func (m *Resource) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - wire |= (uint64(b) & 0x7F) << shift + valuekey |= (uint64(b) & 0x7F) << shift if b < 0x80 { break } } - fieldNum := int32(wire >> 3) - if fieldNum == 1 { - var stringLenmapkey uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTypes - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLenmapkey |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - intStringLenmapkey := int(stringLenmapkey) - if intStringLenmapkey < 0 { - return ErrInvalidLengthTypes - } - postStringIndexmapkey := iNdEx + intStringLenmapkey - if postStringIndexmapkey > l { - return io.ErrUnexpectedEOF - } - mapkey = string(dAtA[iNdEx:postStringIndexmapkey]) - iNdEx = postStringIndexmapkey - } else if fieldNum == 2 { - var stringLenmapvalue uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTypes - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLenmapvalue |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - intStringLenmapvalue := int(stringLenmapvalue) - if intStringLenmapvalue < 0 { - return ErrInvalidLengthTypes + var stringLenmapvalue uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes } - postStringIndexmapvalue := iNdEx + intStringLenmapvalue - if postStringIndexmapvalue > l { + if iNdEx >= l { return io.ErrUnexpectedEOF } - mapvalue = string(dAtA[iNdEx:postStringIndexmapvalue]) - iNdEx = postStringIndexmapvalue - } else { - iNdEx = entryPreIndex - skippy, err := skipTypes(dAtA[iNdEx:]) - if err != nil { - return err - } - if skippy < 0 { - return ErrInvalidLengthTypes - } - if (iNdEx + skippy) > postIndex { - return io.ErrUnexpectedEOF + b := dAtA[iNdEx] + iNdEx++ + stringLenmapvalue |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break } - iNdEx += skippy } + intStringLenmapvalue := int(stringLenmapvalue) + if intStringLenmapvalue < 0 { + return ErrInvalidLengthTypes + } + postStringIndexmapvalue := iNdEx + intStringLenmapvalue + if postStringIndexmapvalue > l { + return io.ErrUnexpectedEOF + } + mapvalue := string(dAtA[iNdEx:postStringIndexmapvalue]) + iNdEx = postStringIndexmapvalue + m.Tags[mapkey] = mapvalue + } else { + var mapvalue string + m.Tags[mapkey] = mapvalue } - m.Tags[mapkey] = mapvalue iNdEx = postIndex default: iNdEx = preIndex @@ -2715,14 +2725,51 @@ func (m *EnvConfig) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } + var keykey uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + keykey |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + var stringLenmapkey uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLenmapkey |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLenmapkey := int(stringLenmapkey) + if intStringLenmapkey < 0 { + return ErrInvalidLengthTypes + } + postStringIndexmapkey := iNdEx + intStringLenmapkey + if postStringIndexmapkey > l { + return io.ErrUnexpectedEOF + } + mapkey := string(dAtA[iNdEx:postStringIndexmapkey]) + iNdEx = postStringIndexmapkey if m.Data == nil { m.Data = make(map[string]string) } - var mapkey string - var mapvalue string - for iNdEx < postIndex { - entryPreIndex := iNdEx - var wire uint64 + if iNdEx < postIndex { + var valuekey uint64 for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowTypes @@ -2732,80 +2779,41 @@ func (m *EnvConfig) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - wire |= (uint64(b) & 0x7F) << shift + valuekey |= (uint64(b) & 0x7F) << shift if b < 0x80 { break } } - fieldNum := int32(wire >> 3) - if fieldNum == 1 { - var stringLenmapkey uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTypes - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLenmapkey |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - intStringLenmapkey := int(stringLenmapkey) - if intStringLenmapkey < 0 { - return ErrInvalidLengthTypes - } - postStringIndexmapkey := iNdEx + intStringLenmapkey - if postStringIndexmapkey > l { - return io.ErrUnexpectedEOF - } - mapkey = string(dAtA[iNdEx:postStringIndexmapkey]) - iNdEx = postStringIndexmapkey - } else if fieldNum == 2 { - var stringLenmapvalue uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTypes - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLenmapvalue |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - intStringLenmapvalue := int(stringLenmapvalue) - if intStringLenmapvalue < 0 { - return ErrInvalidLengthTypes + var stringLenmapvalue uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes } - postStringIndexmapvalue := iNdEx + intStringLenmapvalue - if postStringIndexmapvalue > l { + if iNdEx >= l { return io.ErrUnexpectedEOF } - mapvalue = string(dAtA[iNdEx:postStringIndexmapvalue]) - iNdEx = postStringIndexmapvalue - } else { - iNdEx = entryPreIndex - skippy, err := skipTypes(dAtA[iNdEx:]) - if err != nil { - return err - } - if skippy < 0 { - return ErrInvalidLengthTypes - } - if (iNdEx + skippy) > postIndex { - return io.ErrUnexpectedEOF + b := dAtA[iNdEx] + iNdEx++ + stringLenmapvalue |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break } - iNdEx += skippy } + intStringLenmapvalue := int(stringLenmapvalue) + if intStringLenmapvalue < 0 { + return ErrInvalidLengthTypes + } + postStringIndexmapvalue := iNdEx + intStringLenmapvalue + if postStringIndexmapvalue > l { + return io.ErrUnexpectedEOF + } + mapvalue := string(dAtA[iNdEx:postStringIndexmapvalue]) + iNdEx = postStringIndexmapvalue + m.Data[mapkey] = mapvalue + } else { + var mapvalue string + m.Data[mapkey] = mapvalue } - m.Data[mapkey] = mapvalue iNdEx = postIndex default: iNdEx = preIndex @@ -3068,14 +3076,51 @@ func (m *Formation) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } + var keykey uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + keykey |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + var stringLenmapkey uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLenmapkey |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLenmapkey := int(stringLenmapkey) + if intStringLenmapkey < 0 { + return ErrInvalidLengthTypes + } + postStringIndexmapkey := iNdEx + intStringLenmapkey + if postStringIndexmapkey > l { + return io.ErrUnexpectedEOF + } + mapkey := string(dAtA[iNdEx:postStringIndexmapkey]) + iNdEx = postStringIndexmapkey if m.Structure == nil { m.Structure = make(map[string]int32) } - var mapkey string - var mapvalue int32 - for iNdEx < postIndex { - entryPreIndex := iNdEx - var wire uint64 + if iNdEx < postIndex { + var valuekey uint64 for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowTypes @@ -3085,69 +3130,31 @@ func (m *Formation) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - wire |= (uint64(b) & 0x7F) << shift + valuekey |= (uint64(b) & 0x7F) << shift if b < 0x80 { break } } - fieldNum := int32(wire >> 3) - if fieldNum == 1 { - var stringLenmapkey uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTypes - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLenmapkey |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - intStringLenmapkey := int(stringLenmapkey) - if intStringLenmapkey < 0 { - return ErrInvalidLengthTypes + var mapvalue int32 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes } - postStringIndexmapkey := iNdEx + intStringLenmapkey - if postStringIndexmapkey > l { + if iNdEx >= l { return io.ErrUnexpectedEOF } - mapkey = string(dAtA[iNdEx:postStringIndexmapkey]) - iNdEx = postStringIndexmapkey - } else if fieldNum == 2 { - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTypes - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - mapvalue |= (int32(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - } else { - iNdEx = entryPreIndex - skippy, err := skipTypes(dAtA[iNdEx:]) - if err != nil { - return err - } - if skippy < 0 { - return ErrInvalidLengthTypes - } - if (iNdEx + skippy) > postIndex { - return io.ErrUnexpectedEOF + b := dAtA[iNdEx] + iNdEx++ + mapvalue |= (int32(b) & 0x7F) << shift + if b < 0x80 { + break } - iNdEx += skippy } + m.Structure[mapkey] = mapvalue + } else { + var mapvalue int32 + m.Structure[mapkey] = mapvalue } - m.Structure[mapkey] = mapvalue iNdEx = postIndex default: iNdEx = preIndex diff --git a/api/server.go b/api/server.go index b800d75a..5b7399a3 100644 --- a/api/server.go +++ b/api/server.go @@ -242,8 +242,8 @@ func (s *Server) BuildImport(stream pbs.ProviderService_BuildImportServer) error return stream.SendAndClose(emptyMsg) } -func (s *Server) BuildList(ctx context.Context, req *pbs.AppRequest) (*pbs.BuildListResponse, error) { - items, err := s.Provider.BuildList(req.Name, 100) +func (s *Server) BuildList(ctx context.Context, req *pbs.BuildListRequest) (*pbs.BuildListResponse, error) { + items, err := s.Provider.BuildList(req.Name, int(req.Limit)) if err != nil { return nil, err } diff --git a/client/build.go b/client/build.go index e7cca526..bd7b155d 100644 --- a/client/build.go +++ b/client/build.go @@ -70,8 +70,12 @@ func (c *Client) CreateBuildGit(app *pb.App, version string, procfile []byte) (* }) } -func (c *Client) GetBuilds(app string) (pb.Builds, error) { - ret, err := c.ProviderServiceClient.BuildList(ctx, &pbs.AppRequest{Name: app}) +func (c *Client) GetBuilds(app string, limit int) (pb.Builds, error) { + ret, err := c.ProviderServiceClient.BuildList(ctx, &pbs.BuildListRequest{ + Name: app, + Limit: int32(limit), + }) + if err != nil { return nil, err } diff --git a/cloud/aws/builder.go b/cloud/aws/builder.go index b02c583f..ddd37320 100644 --- a/cloud/aws/builder.go +++ b/cloud/aws/builder.go @@ -99,7 +99,7 @@ func (a *AwsCloud) BuildList(app string, limit int) (pb.Builds, error) { return builds[i].CreatedAt > builds[j].CreatedAt }) - return builds, nil + return builds[0:limit], nil } func (a *AwsCloud) BuildImport(id, gzipPath string) error { diff --git a/cloud/aws/kubeconfig.go b/cloud/aws/kubeconfig.go index d77cf712..519f19e6 100644 --- a/cloud/aws/kubeconfig.go +++ b/cloud/aws/kubeconfig.go @@ -2,12 +2,18 @@ package aws import ( "fmt" + "io/ioutil" "os" "os/exec" "path/filepath" + "regexp" "sync" log "github.com/Sirupsen/logrus" + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/session" + "github.com/aws/aws-sdk-go/service/s3" + "github.com/aws/aws-sdk-go/service/s3/s3manager" "k8s.io/client-go/kubernetes" "k8s.io/client-go/rest" "k8s.io/client-go/tools/clientcmd" @@ -18,12 +24,13 @@ var cacheClientsetOnce sync.Once var cacheConfigPathOnce sync.Once var ( - rootPath = "/opt/datacol" - kcpath = filepath.Join(rootPath, "kubeconfig") - pemPathRE = filepath.Join(rootPath, "%s.pem") - privateIpAttr = "MasterPrivateIp" - bastionIpAttr = "BastionHostPublicIp" - scpCmd = "scp -i %s -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null ubuntu@%s:~/kubeconfig %s" + rootPath = "/opt/datacol" + kcpath = filepath.Join(rootPath, "kubeconfig") + pemPathRE = filepath.Join(rootPath, "%s.pem") + privateIpAttr = "MasterPrivateIp" + bastionIpAttr = "BastionHostPublicIp" + scpCmd = "scp -i %s -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null ubuntu@%s:~/kubeconfig %s" + s3StateStoreMatcher = regexp.MustCompile(`s3://(\S+)/cluster-info.yaml`) ) func (p *AwsCloud) kubeClient() *kubernetes.Clientset { @@ -43,9 +50,46 @@ func (p *AwsCloud) kubeClient() *kubernetes.Clientset { return kubeClient } +// fetchClusterInfoFromS3 tries to fetch cluster state from s3. Currently not being used +// since the cluster-info.yaml doesn't contain user credentials +func (p *AwsCloud) fetchClusterInfoFromS3(path string) (cached bool, err error) { + value, err := p.stackOutputValue("JoinNodes") + log.Warn(err) + + if value != "" { + log.Debugf("Found JoinNodes Output: %s", value) + + if match := s3StateStoreMatcher.FindStringSubmatch(value); len(match) == 2 { + s3bucket := match[1] + buff := &aws.WriteAtBuffer{} + s3dl := s3manager.NewDownloader(session.New()) + + if _, err = s3dl.Download(buff, &s3.GetObjectInput{ + Bucket: aws.String(s3bucket), + Key: aws.String("cluster-info.yaml"), + }); err != nil { + return + } + + err = ioutil.WriteFile(path, buff.Bytes(), 0644) + if err == nil { + cached = true + } + } + } + + return +} + func (p *AwsCloud) K8sConfigPath() (string, error) { if _, err := os.Stat(kcpath); err != nil { if os.IsNotExist(err) { + + // if fetched, err := p.fetchClusterInfoFromS3(kcpath); fetched { + // log.Infof("cached the %s from s3 state store. err:%v", kcpath, err) + // return kcpath, nil + // } + ipAddr, err := p.masterPrivateIp() if err != nil { return ipAddr, err diff --git a/cloud/aws/templates.go b/cloud/aws/templates.go index 6ca0bd3b..12afbb3c 100644 --- a/cloud/aws/templates.go +++ b/cloud/aws/templates.go @@ -87,7 +87,7 @@ func cloudAwsTemplatesAppTmpl() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "cloud/aws/templates/app.tmpl", size: 6660, mode: os.FileMode(436), modTime: time.Unix(1520015640, 0)} + info := bindataFileInfo{name: "cloud/aws/templates/app.tmpl", size: 6660, mode: os.FileMode(420), modTime: time.Unix(1519994908, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -107,7 +107,7 @@ func cloudAwsTemplatesElasticsearchTmpl() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "cloud/aws/templates/elasticsearch.tmpl", size: 4023, mode: os.FileMode(436), modTime: time.Unix(1520679773, 0)} + info := bindataFileInfo{name: "cloud/aws/templates/elasticsearch.tmpl", size: 4023, mode: os.FileMode(420), modTime: time.Unix(1520701517, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -127,7 +127,7 @@ func cloudAwsTemplatesMysqlTmpl() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "cloud/aws/templates/mysql.tmpl", size: 3587, mode: os.FileMode(436), modTime: time.Unix(1520015640, 0)} + info := bindataFileInfo{name: "cloud/aws/templates/mysql.tmpl", size: 3587, mode: os.FileMode(420), modTime: time.Unix(1500616848, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -147,7 +147,7 @@ func cloudAwsTemplatesPostgresTmpl() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "cloud/aws/templates/postgres.tmpl", size: 4389, mode: os.FileMode(436), modTime: time.Unix(1520679773, 0)} + info := bindataFileInfo{name: "cloud/aws/templates/postgres.tmpl", size: 4389, mode: os.FileMode(420), modTime: time.Unix(1520701517, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -167,7 +167,7 @@ func cloudAwsTemplatesRedisTmpl() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "cloud/aws/templates/redis.tmpl", size: 3164, mode: os.FileMode(436), modTime: time.Unix(1520271844, 0)} + info := bindataFileInfo{name: "cloud/aws/templates/redis.tmpl", size: 3164, mode: os.FileMode(420), modTime: time.Unix(1500616848, 0)} a := &asset{bytes: bytes, info: info} return a, nil } diff --git a/cloud/google/builder.go b/cloud/google/builder.go index aaf692d6..6e16f2a0 100644 --- a/cloud/google/builder.go +++ b/cloud/google/builder.go @@ -58,7 +58,10 @@ func (g *GCPCloud) BuildDelete(app, id string) error { } func (g *GCPCloud) BuildList(app string, limit int) (pb.Builds, error) { - q := datastore.NewQuery(buildKind).Namespace(g.DeploymentName).Filter("app = ", app).Limit(limit) + q := datastore.NewQuery(buildKind).Namespace(g.DeploymentName). + Filter("app = ", app). + Limit(limit). + Order("-" + "created_at") // descending order var builds pb.Builds _, err := g.datastore().GetAll(context.Background(), q, &builds) diff --git a/cloud/google/kubeconfig.go b/cloud/google/kubeconfig.go index dc332b0f..38370ec9 100644 --- a/cloud/google/kubeconfig.go +++ b/cloud/google/kubeconfig.go @@ -111,7 +111,6 @@ func generateClusterConfig(rackName, baseDir string, c *container.Cluster) error User: rackName, Context: rackName, Cluster: rackName, - // TokenFile: getTokenFile(rackName), } var kubeconfig bytes.Buffer diff --git a/cloud/google/templates.go b/cloud/google/templates.go index f8745714..b743a2fa 100644 --- a/cloud/google/templates.go +++ b/cloud/google/templates.go @@ -84,7 +84,7 @@ func cloudGoogleTemplatesMysqlTmpl() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "cloud/google/templates/mysql.tmpl", size: 1392, mode: os.FileMode(436), modTime: time.Unix(1520015640, 0)} + info := bindataFileInfo{name: "cloud/google/templates/mysql.tmpl", size: 1392, mode: os.FileMode(420), modTime: time.Unix(1506691380, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -104,7 +104,7 @@ func cloudGoogleTemplatesPostgresTmpl() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "cloud/google/templates/postgres.tmpl", size: 1134, mode: os.FileMode(436), modTime: time.Unix(1520015640, 0)} + info := bindataFileInfo{name: "cloud/google/templates/postgres.tmpl", size: 1134, mode: os.FileMode(420), modTime: time.Unix(1502614896, 0)} a := &asset{bytes: bytes, info: info} return a, nil } diff --git a/cmd/apps.go b/cmd/apps.go index 6d2201c0..40c0c69c 100644 --- a/cmd/apps.go +++ b/cmd/apps.go @@ -19,6 +19,7 @@ func init() { Name: "apps", Usage: "Manage your apps in a stack", Action: cmdAppsList, + Flags: []cli.Flag{&stackFlag}, Subcommands: []cli.Command{ cli.Command{ Name: "create", @@ -79,11 +80,10 @@ func cmdAppsList(c *cli.Context) error { fmt.Println("No apps found.") } else { table := tablewriter.NewWriter(os.Stdout) - table.SetHeader([]string{"NAME", "BUILD", "RELEASE", "DOMAINS", "LOAD BALANCER"}) + table.SetHeader([]string{"NAME", "BUILD", "RELEASE", "DOMAINS"}) for _, a := range apps { table.Append([]string{a.Name, a.BuildId, a.ReleaseId, strings.Join(a.Domains, "\n"), - a.Endpoint, }) } table.Render() diff --git a/cmd/build.go b/cmd/build.go index 7207c9a0..5747f3dd 100644 --- a/cmd/build.go +++ b/cmd/build.go @@ -15,7 +15,6 @@ import ( "github.com/datacol-io/datacol/client" "github.com/datacol-io/datacol/cmd/stdcli" - timeago "github.com/ararog/timeago" "github.com/docker/docker/builder/dockerignore" "github.com/docker/docker/pkg/archive" "github.com/docker/docker/pkg/fileutils" @@ -41,6 +40,13 @@ func init() { Name: "list", Usage: "get builds for an app", Action: cmdBuildList, + Flags: []cli.Flag{ + &cli.IntFlag{ + Name: "limit, n", + Usage: "Limit the number of recent builds to fetch", + Value: 5, + }, + }, }, { Name: "delete", @@ -59,13 +65,13 @@ func cmdBuildList(c *cli.Context) error { api, close := getApiClient(c) defer close() - builds, err := api.GetBuilds(name) + builds, err := api.GetBuilds(name, c.Int("limit")) stdcli.ExitOnError(err) - start, table := time.Now(), tablewriter.NewWriter(os.Stdout) + table := tablewriter.NewWriter(os.Stdout) table.SetHeader([]string{"ID", "COMMIT", "STATUS", "CREATED"}) for _, b := range builds { - delta, _ := timeago.TimeAgoWithTime(start, time.Unix(int64(b.CreatedAt), 0)) + delta := elaspedDuration(time.Unix(int64(b.CreatedAt), 0)) table.Append([]string{b.Id, b.Version, b.Status, delta}) } diff --git a/cmd/helper.go b/cmd/helper.go index 5435090b..5b28a9f5 100644 --- a/cmd/helper.go +++ b/cmd/helper.go @@ -6,6 +6,7 @@ import ( "errors" "fmt" "io/ioutil" + "math" "math/rand" "os" "regexp" @@ -109,81 +110,6 @@ type appYAMLConfig struct { RuntimeSteps []string } -func parseAppYAML() (*appYAMLConfig, error) { - data, err := ioutil.ReadFile("app.yaml") - if err != nil { - return nil, err - } - - var appyaml appYAMLConfig - if err := yaml.Unmarshal(data, &appyaml); err != nil { - return nil, err - } - - if !(appyaml.Env == "flex" || appyaml.Env == "custom") { - fmt.Printf("\nignoring %s env", appyaml.Env) - return &appyaml, nil - } - - return nil, fmt.Errorf("invalid app.yaml file.") -} - -func gnDockerFromGAE(filename string) error { - appyaml, err := parseAppYAML() - if err != nil { - return err - } - - if len(appyaml.Entrypoint) > 0 { - appyaml.Entrypoint = entrypoint(appyaml.Entrypoint) - } else { - appyaml.Entrypoint = "/bin/sh -c" - } - - appyaml.RuntimeSteps = getruntimeSteps(appyaml) - - log.Debugf(toJson(appyaml)) - tmpl, err := template.New("ct").Parse(dkrYAML) - if err != nil { - return err - } - - var doc bytes.Buffer - if err := tmpl.Execute(&doc, appyaml); err != nil { - return err - } - - err = ioutil.WriteFile(filename, doc.Bytes(), 0700) - if err != nil { - return err - } - - return nil -} - -func entrypoint(cmd string) string { - parts := strings.Split(cmd, " ") - return `["` + strings.Join(parts, `", "`) + `"]` -} - -func getruntimeSteps(spec *appYAMLConfig) []string { - steps := []string{} - switch spec.Runtime { - case "python": - steps = append(steps, []string{ - "RUN virtualenv /env", - "ENV VIRTUAL_ENV /env", - "ENV PATH /env/bin:$PATH", - "ADD requirements.txt /app/requirements.txt", - "RUN pip install -r /app/requirements.txt", - }...) - default: - log.Fatal(fmt.Errorf("unsupported runtime %s", spec.Runtime)) - } - - return steps -} - func toJson(object interface{}) string { dump, err := json.MarshalIndent(object, " ", " ") if err != nil { @@ -215,3 +141,32 @@ func unmarshalProcfile(procfile []byte) (map[string]string, error) { procfileMap := make(map[string]string) return procfileMap, yaml.Unmarshal(procfile, &procfileMap) } + +func elaspedDuration(t time.Time) string { + duration := time.Since(t) + days := int64(duration.Hours() / 24) + hours := int64(math.Mod(duration.Hours(), 24)) + minutes := int64(math.Mod(duration.Minutes(), 60)) + + chunks := []struct { + singularName string + amount int64 + }{ + {"d", days}, + {"h", hours}, + {"m", minutes}, + } + + parts := []string{} + + for _, chunk := range chunks { + switch chunk.amount { + case 0: + continue + default: + parts = append(parts, fmt.Sprintf("%d%s", chunk.amount, chunk.singularName)) + } + } + + return strings.Join(parts, " ") +} diff --git a/cmd/provider/aws/templates.go b/cmd/provider/aws/templates.go index fc036238..557a07d2 100644 --- a/cmd/provider/aws/templates.go +++ b/cmd/provider/aws/templates.go @@ -83,7 +83,7 @@ func cmdProviderAwsTemplatesFormationYaml() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "cmd/provider/aws/templates/formation.yaml", size: 22170, mode: os.FileMode(436), modTime: time.Unix(1521183917, 0)} + info := bindataFileInfo{name: "cmd/provider/aws/templates/formation.yaml", size: 22170, mode: os.FileMode(420), modTime: time.Unix(1521208860, 0)} a := &asset{bytes: bytes, info: info} return a, nil } diff --git a/vendor/github.com/ararog/timeago/.gitignore b/vendor/github.com/ararog/timeago/.gitignore deleted file mode 100644 index daf913b1..00000000 --- a/vendor/github.com/ararog/timeago/.gitignore +++ /dev/null @@ -1,24 +0,0 @@ -# Compiled Object files, Static and Dynamic libs (Shared Objects) -*.o -*.a -*.so - -# Folders -_obj -_test - -# Architecture specific extensions/prefixes -*.[568vq] -[568vq].out - -*.cgo1.go -*.cgo2.c -_cgo_defun.c -_cgo_gotypes.go -_cgo_export.* - -_testmain.go - -*.exe -*.test -*.prof diff --git a/vendor/github.com/ararog/timeago/.travis.yml b/vendor/github.com/ararog/timeago/.travis.yml deleted file mode 100644 index 98b43464..00000000 --- a/vendor/github.com/ararog/timeago/.travis.yml +++ /dev/null @@ -1,5 +0,0 @@ -language: go - -go: - - 1.3 - - tip diff --git a/vendor/github.com/ararog/timeago/LICENSE b/vendor/github.com/ararog/timeago/LICENSE deleted file mode 100644 index d5de9ae4..00000000 --- a/vendor/github.com/ararog/timeago/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2016 Rogério Pereira Araújo - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/vendor/github.com/ararog/timeago/README.md b/vendor/github.com/ararog/timeago/README.md deleted file mode 100644 index 38c5c916..00000000 --- a/vendor/github.com/ararog/timeago/README.md +++ /dev/null @@ -1,6 +0,0 @@ -# timeago - -[![Build Status](https://travis-ci.org/ararog/timeago.svg?branch=master)](https://travis-ci.org/ararog/timeago) - -TimeAgo is a library used to calculate how much time has been passed between -two dates, this library is mainly based on time type of go. diff --git a/vendor/github.com/ararog/timeago/timeago.go b/vendor/github.com/ararog/timeago/timeago.go deleted file mode 100644 index 3499fb0e..00000000 --- a/vendor/github.com/ararog/timeago/timeago.go +++ /dev/null @@ -1,139 +0,0 @@ -package timeago - -import ( - "time" - "fmt" - "math" - "errors" -) - -type DateAgoValues int - -const ( - SecondsAgo DateAgoValues = iota - MinutesAgo - HoursAgo - DaysAgo - WeeksAgo - MonthsAgo - YearsAgo -) - -func TimeAgoFromNowWithTime(end time.Time) (string, error) { - - return TimeAgoWithTime(time.Now(), end) -} - -func TimeAgoFromNowWithString( - layout, end string) (string, error) { - - t, e := time.Parse(layout, end) - if e == nil { - return TimeAgoWithTime(time.Now(), t) - } else { - err := errors.New("Invalid format") - return "", err - } -} - -func TimeAgoWithTime(start, end time.Time) (string, error) { - duration := start.Sub(end) - return stringForDuration(duration), nil -} - -func TimeAgoWithString(layout, start, end string) (string, error) { - - timeStart, e := time.Parse(layout, start) - if e != nil { - err := errors.New("Invalid start time format") - return "", err - } - - timeEnd, e := time.Parse(layout, end) - if e != nil { - err := errors.New("Invalid end time format") - return "", err - } - - duration := timeStart.Sub(timeEnd) - return stringForDuration(duration), nil -} - -func stringForDuration(duration time.Duration) string { - if duration.Hours() < 24 { - if duration.Hours() >= 1 { - return localizedStringFor(HoursAgo, int(round(duration.Hours()))); - } else if duration.Minutes() >= 1 { - return localizedStringFor(MinutesAgo, int(round(duration.Minutes()))); - } else { - return localizedStringFor(SecondsAgo, int(round(duration.Seconds()))); - } - } else { - if duration.Hours() >= 8760 { - years := duration.Hours() / 8760 - return localizedStringFor(YearsAgo, int(years)); - } else if duration.Hours() >= 730 { - months := duration.Hours() / 730 - return localizedStringFor(MonthsAgo, int(months)); - } else if duration.Hours() >= 168 { - weeks := duration.Hours() / 168 - return localizedStringFor(WeeksAgo, int(weeks)); - } else { - days := duration.Hours() / 24 - return localizedStringFor(DaysAgo, int(days)); - } - } -} - -func round(f float64) float64 { - return math.Floor(f + .5) -} - -func localizedStringFor(valueType DateAgoValues, value int) string { - - switch valueType { - case YearsAgo: - if value >= 2 { - return fmt.Sprintf("%d years ago", value); - } else { - return "Last year"; - } - case MonthsAgo: - if value >= 2 { - return fmt.Sprintf("%d months ago", value); - } else { - return "Last month"; - } - case WeeksAgo: - if value >= 2 { - return fmt.Sprintf("%d weeks ago", value); - } else { - return "Last week"; - } - case DaysAgo: - if value >= 2 { - return fmt.Sprintf("%d days ago", value); - } else { - return "Yesterday"; - } - case HoursAgo: - if value >= 2 { - return fmt.Sprintf("%d hours ago", value); - } else { - return "An hour ago"; - } - case MinutesAgo: - if value >= 2 { - return fmt.Sprintf("%d minutes ago", value); - } else { - return "A minute ago"; - } - case SecondsAgo: - if value >= 2 { - return fmt.Sprintf("%d seconds ago", value); - } else { - return "Just now"; - } - } - return ""; -} diff --git a/vendor/github.com/ararog/timeago/timeago_test.go b/vendor/github.com/ararog/timeago/timeago_test.go deleted file mode 100644 index 6042f23a..00000000 --- a/vendor/github.com/ararog/timeago/timeago_test.go +++ /dev/null @@ -1,79 +0,0 @@ -package timeago - -import ( - "time" -) - -import "testing" - -func check(t *testing.T, d time.Duration, result string) { - start := time.Now() - end := time.Now().Add(d) - got, error := TimeAgoWithTime(start, end) - if error == nil { - if got != result { - t.Errorf("Wrong result: %s", got) - } - } -} - -func TestThreeHoursAgo(t *testing.T) { - d, error := time.ParseDuration("-3h") - if error == nil { - check(t, d, "3 hours ago") - } -} - -func TestAnHourAgo(t *testing.T) { - d, error := time.ParseDuration("-1.5h") - if error == nil { - check(t, d, "An hour ago") - } -} - -func TestThreeMinutesAgo(t *testing.T) { - d, error := time.ParseDuration("-3m") - if error == nil { - check(t, d, "3 minutes ago") - } -} - -func TestAMinuteAgo(t *testing.T) { - d, error := time.ParseDuration("-1.2m") - if error == nil { - check(t, d, "A minute ago") - } -} - -func TestJustNow(t *testing.T) { - d, error := time.ParseDuration("-1.2s") - if error == nil { - check(t, d, "Just now") - } -} - -func TestFromNow(t *testing.T) { - d, error := time.ParseDuration("-1.2m") - if error == nil { - end := time.Now().Add(d) - got, err := TimeAgoFromNowWithTime(end) - if err == nil { - if got != "A minute ago" { - t.Errorf("Wrong result: %s", got) - } - } - } -} - -func TestFromNowWithString(t *testing.T) { - d, error := time.ParseDuration("-1.2m") - if error == nil { - end := time.Now().Add(d) - got, err := TimeAgoFromNowWithString(time.RFC3339, end.Format(time.RFC3339)) - if err == nil { - if got != "A minute ago" { - t.Errorf("Wrong result: %s", got) - } - } - } -} From fbc4e87fa561f53d1621ea38a2d2b54541ec02cb Mon Sep 17 00:00:00 2001 From: dinesh Date: Mon, 16 Apr 2018 18:44:39 +0530 Subject: [PATCH 06/13] fetching right pods --- cloud/kube/pod.go | 13 +++++++++++++ cloud/kube/process.go | 2 +- cmd/stdcli/apprc.go | 6 ++++++ 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/cloud/kube/pod.go b/cloud/kube/pod.go index 0acab836..60afad1a 100644 --- a/cloud/kube/pod.go +++ b/cloud/kube/pod.go @@ -85,6 +85,19 @@ func getPodsForDeployment(c *kubernetes.Clientset, dp *v1beta1.Deployment) ([]v1 return res.Items, nil } +func getLatestPodsForDeployment(c *kubernetes.Clientset, dp *v1beta1.Deployment) ([]v1.Pod, error) { + selector := klabels.Set(dp.Spec.Selector.MatchLabels).AsSelector() + res, err := c.Core().Pods(dp.Namespace).List(metav1.ListOptions{ + LabelSelector: selector.String(), + ResourceVersion: dp.ResourceVersion, + }) + if err != nil { + return nil, err + } + + return res.Items, nil +} + func getPodByName(c *kubernetes.Clientset, ns, app string) (*v1.Pod, error) { pods, err := GetAllPods(c, ns, app) if err != nil { diff --git a/cloud/kube/process.go b/cloud/kube/process.go index 06ee9095..398c58d7 100644 --- a/cloud/kube/process.go +++ b/cloud/kube/process.go @@ -117,7 +117,7 @@ func ProcessList(c *kubernetes.Clientset, ns, app string) ([]*pb.Process, error) var items []*pb.Process for _, dp := range deployments { - pods, err := getPodsForDeployment(c, &dp) + pods, err := getLatestPodsForDeployment(c, &dp) if err != nil { return nil, err } diff --git a/cmd/stdcli/apprc.go b/cmd/stdcli/apprc.go index 1f207936..7eead5d9 100644 --- a/cmd/stdcli/apprc.go +++ b/cmd/stdcli/apprc.go @@ -101,6 +101,12 @@ func GetAuthContextOrDie(stack string) (*Auth, *Apprc) { /* Exits if there is any error.*/ func GetAuthOrDie(c *cli.Context) (*Auth, *Apprc) { stack := c.String("stack") + + if stack == "" { + // Some commands might not parse arguments + stack = os.Getenv("STACK") + } + if stack == "" { stack = GetAppSetting("stack") } From f66092074255fd5ba01149806e132a6c362e7c8d Mon Sep 17 00:00:00 2001 From: dinesh Date: Tue, 17 Apr 2018 18:32:47 +0530 Subject: [PATCH 07/13] Fetching correct pods for logs and listing processes --- CHANGELOG.md | 3 + api/controller/services.swagger.json | 17 +- api/models/types.pb.go | 1121 ++++++++++++++------------ api/models/types.proto | 10 +- cloud/aws/templates.go | 10 +- cloud/common/apps.go | 4 +- cloud/common/procfile.go | 1 + cloud/google/templates.go | 4 +- cloud/kube/common.go | 86 -- cloud/kube/deployer.go | 1 + cloud/kube/deployment.go | 4 +- cloud/kube/logs.go | 99 +++ cloud/kube/pod.go | 33 + cloud/kube/process.go | 18 +- cmd/provider/aws/templates.go | 2 +- cmd/ps.go | 11 +- 16 files changed, 798 insertions(+), 626 deletions(-) create mode 100644 cloud/kube/logs.go diff --git a/CHANGELOG.md b/CHANGELOG.md index 0b62c477..ee8e3c1c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,9 @@ This project adheres to [Semantic Versioning](http://semver.org/). ## [UNRELEASED] - 0000-00-00 ### Fixes +- [API] Skipping ephemeral pods while log streaming +- [CLI] `ps` should list recent pods with tabular format (Added cpu, memory fields) +- [API] Don't stream logs from crashed/failed pods - Sort environment variables in API response - AWS nginx ingress controller to respect `Path: /` - Async support for streaming logs from mutiple processes. diff --git a/api/controller/services.swagger.json b/api/controller/services.swagger.json index 7a7c16d1..10b49b6b 100644 --- a/api/controller/services.swagger.json +++ b/api/controller/services.swagger.json @@ -1003,18 +1003,27 @@ "modelsProcess": { "type": "object", "properties": { - "name": { - "type": "string" - }, "proctype": { "type": "string" }, - "workers": { + "count": { "type": "integer", "format": "int32" }, "status": { "type": "string" + }, + "cpu": { + "type": "string" + }, + "memory": { + "type": "string" + }, + "command": { + "type": "array", + "items": { + "type": "string" + } } } }, diff --git a/api/models/types.pb.go b/api/models/types.pb.go index e443ca50..4a98b8ac 100644 --- a/api/models/types.pb.go +++ b/api/models/types.pb.go @@ -351,10 +351,12 @@ func (m *EnvConfig) GetData() map[string]string { } type Process struct { - Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` - Proctype string `protobuf:"bytes,2,opt,name=proctype,proto3" json:"proctype,omitempty"` - Workers int32 `protobuf:"varint,3,opt,name=workers,proto3" json:"workers,omitempty"` - Status string `protobuf:"bytes,4,opt,name=status,proto3" json:"status,omitempty"` + Proctype string `protobuf:"bytes,1,opt,name=proctype,proto3" json:"proctype,omitempty"` + Count int32 `protobuf:"varint,2,opt,name=count,proto3" json:"count,omitempty"` + Status string `protobuf:"bytes,3,opt,name=status,proto3" json:"status,omitempty"` + Cpu string `protobuf:"bytes,4,opt,name=cpu,proto3" json:"cpu,omitempty"` + Memory string `protobuf:"bytes,5,opt,name=memory,proto3" json:"memory,omitempty"` + Command []string `protobuf:"bytes,6,rep,name=command" json:"command,omitempty"` } func (m *Process) Reset() { *m = Process{} } @@ -362,13 +364,6 @@ func (m *Process) String() string { return proto.CompactTextString(m) func (*Process) ProtoMessage() {} func (*Process) Descriptor() ([]byte, []int) { return fileDescriptorTypes, []int{6} } -func (m *Process) GetName() string { - if m != nil { - return m.Name - } - return "" -} - func (m *Process) GetProctype() string { if m != nil { return m.Proctype @@ -376,9 +371,9 @@ func (m *Process) GetProctype() string { return "" } -func (m *Process) GetWorkers() int32 { +func (m *Process) GetCount() int32 { if m != nil { - return m.Workers + return m.Count } return 0 } @@ -390,6 +385,27 @@ func (m *Process) GetStatus() string { return "" } +func (m *Process) GetCpu() string { + if m != nil { + return m.Cpu + } + return "" +} + +func (m *Process) GetMemory() string { + if m != nil { + return m.Memory + } + return "" +} + +func (m *Process) GetCommand() []string { + if m != nil { + return m.Command + } + return nil +} + type Formation struct { App string `protobuf:"bytes,1,opt,name=app,proto3" json:"app,omitempty"` Structure map[string]int32 `protobuf:"bytes,2,rep,name=structure" json:"structure,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"varint,2,opt,name=value,proto3"` @@ -825,29 +841,50 @@ func (m *Process) MarshalTo(dAtA []byte) (int, error) { _ = i var l int _ = l - if len(m.Name) > 0 { - dAtA[i] = 0xa - i++ - i = encodeVarintTypes(dAtA, i, uint64(len(m.Name))) - i += copy(dAtA[i:], m.Name) - } if len(m.Proctype) > 0 { - dAtA[i] = 0x12 + dAtA[i] = 0xa i++ i = encodeVarintTypes(dAtA, i, uint64(len(m.Proctype))) i += copy(dAtA[i:], m.Proctype) } - if m.Workers != 0 { - dAtA[i] = 0x18 + if m.Count != 0 { + dAtA[i] = 0x10 i++ - i = encodeVarintTypes(dAtA, i, uint64(m.Workers)) + i = encodeVarintTypes(dAtA, i, uint64(m.Count)) } if len(m.Status) > 0 { - dAtA[i] = 0x22 + dAtA[i] = 0x1a i++ i = encodeVarintTypes(dAtA, i, uint64(len(m.Status))) i += copy(dAtA[i:], m.Status) } + if len(m.Cpu) > 0 { + dAtA[i] = 0x22 + i++ + i = encodeVarintTypes(dAtA, i, uint64(len(m.Cpu))) + i += copy(dAtA[i:], m.Cpu) + } + if len(m.Memory) > 0 { + dAtA[i] = 0x2a + i++ + i = encodeVarintTypes(dAtA, i, uint64(len(m.Memory))) + i += copy(dAtA[i:], m.Memory) + } + if len(m.Command) > 0 { + for _, s := range m.Command { + dAtA[i] = 0x32 + i++ + l = len(s) + for l >= 1<<7 { + dAtA[i] = uint8(uint64(l)&0x7f | 0x80) + l >>= 7 + i++ + } + dAtA[i] = uint8(l) + i++ + i += copy(dAtA[i:], s) + } + } return i, nil } @@ -891,24 +928,6 @@ func (m *Formation) MarshalTo(dAtA []byte) (int, error) { return i, nil } -func encodeFixed64Types(dAtA []byte, offset int, v uint64) int { - dAtA[offset] = uint8(v) - dAtA[offset+1] = uint8(v >> 8) - dAtA[offset+2] = uint8(v >> 16) - dAtA[offset+3] = uint8(v >> 24) - dAtA[offset+4] = uint8(v >> 32) - dAtA[offset+5] = uint8(v >> 40) - dAtA[offset+6] = uint8(v >> 48) - dAtA[offset+7] = uint8(v >> 56) - return offset + 8 -} -func encodeFixed32Types(dAtA []byte, offset int, v uint32) int { - dAtA[offset] = uint8(v) - dAtA[offset+1] = uint8(v >> 8) - dAtA[offset+2] = uint8(v >> 16) - dAtA[offset+3] = uint8(v >> 24) - return offset + 4 -} func encodeVarintTypes(dAtA []byte, offset int, v uint64) int { for v >= 1<<7 { dAtA[offset] = uint8(v&0x7f | 0x80) @@ -1113,21 +1132,31 @@ func (m *EnvConfig) Size() (n int) { func (m *Process) Size() (n int) { var l int _ = l - l = len(m.Name) + l = len(m.Proctype) if l > 0 { n += 1 + l + sovTypes(uint64(l)) } - l = len(m.Proctype) + if m.Count != 0 { + n += 1 + sovTypes(uint64(m.Count)) + } + l = len(m.Status) if l > 0 { n += 1 + l + sovTypes(uint64(l)) } - if m.Workers != 0 { - n += 1 + sovTypes(uint64(m.Workers)) + l = len(m.Cpu) + if l > 0 { + n += 1 + l + sovTypes(uint64(l)) } - l = len(m.Status) + l = len(m.Memory) if l > 0 { n += 1 + l + sovTypes(uint64(l)) } + if len(m.Command) > 0 { + for _, s := range m.Command { + l = len(s) + n += 1 + l + sovTypes(uint64(l)) + } + } return n } @@ -2103,51 +2132,14 @@ func (m *Resource) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - var keykey uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTypes - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - keykey |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - var stringLenmapkey uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTypes - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLenmapkey |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - intStringLenmapkey := int(stringLenmapkey) - if intStringLenmapkey < 0 { - return ErrInvalidLengthTypes - } - postStringIndexmapkey := iNdEx + intStringLenmapkey - if postStringIndexmapkey > l { - return io.ErrUnexpectedEOF - } - mapkey := string(dAtA[iNdEx:postStringIndexmapkey]) - iNdEx = postStringIndexmapkey if m.Exports == nil { m.Exports = make(map[string]string) } - if iNdEx < postIndex { - var valuekey uint64 + var mapkey string + var mapvalue string + for iNdEx < postIndex { + entryPreIndex := iNdEx + var wire uint64 for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowTypes @@ -2157,41 +2149,80 @@ func (m *Resource) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - valuekey |= (uint64(b) & 0x7F) << shift + wire |= (uint64(b) & 0x7F) << shift if b < 0x80 { break } } - var stringLenmapvalue uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTypes + fieldNum := int32(wire >> 3) + if fieldNum == 1 { + var stringLenmapkey uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLenmapkey |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } } - if iNdEx >= l { + intStringLenmapkey := int(stringLenmapkey) + if intStringLenmapkey < 0 { + return ErrInvalidLengthTypes + } + postStringIndexmapkey := iNdEx + intStringLenmapkey + if postStringIndexmapkey > l { return io.ErrUnexpectedEOF } - b := dAtA[iNdEx] - iNdEx++ - stringLenmapvalue |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break + mapkey = string(dAtA[iNdEx:postStringIndexmapkey]) + iNdEx = postStringIndexmapkey + } else if fieldNum == 2 { + var stringLenmapvalue uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLenmapvalue |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } } + intStringLenmapvalue := int(stringLenmapvalue) + if intStringLenmapvalue < 0 { + return ErrInvalidLengthTypes + } + postStringIndexmapvalue := iNdEx + intStringLenmapvalue + if postStringIndexmapvalue > l { + return io.ErrUnexpectedEOF + } + mapvalue = string(dAtA[iNdEx:postStringIndexmapvalue]) + iNdEx = postStringIndexmapvalue + } else { + iNdEx = entryPreIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > postIndex { + return io.ErrUnexpectedEOF + } + iNdEx += skippy } - intStringLenmapvalue := int(stringLenmapvalue) - if intStringLenmapvalue < 0 { - return ErrInvalidLengthTypes - } - postStringIndexmapvalue := iNdEx + intStringLenmapvalue - if postStringIndexmapvalue > l { - return io.ErrUnexpectedEOF - } - mapvalue := string(dAtA[iNdEx:postStringIndexmapvalue]) - iNdEx = postStringIndexmapvalue - m.Exports[mapkey] = mapvalue - } else { - var mapvalue string - m.Exports[mapkey] = mapvalue } + m.Exports[mapkey] = mapvalue iNdEx = postIndex case 9: if wireType != 2 { @@ -2219,51 +2250,14 @@ func (m *Resource) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - var keykey uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTypes - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - keykey |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - var stringLenmapkey uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTypes - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLenmapkey |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - intStringLenmapkey := int(stringLenmapkey) - if intStringLenmapkey < 0 { - return ErrInvalidLengthTypes - } - postStringIndexmapkey := iNdEx + intStringLenmapkey - if postStringIndexmapkey > l { - return io.ErrUnexpectedEOF - } - mapkey := string(dAtA[iNdEx:postStringIndexmapkey]) - iNdEx = postStringIndexmapkey if m.Parameters == nil { m.Parameters = make(map[string]string) } - if iNdEx < postIndex { - var valuekey uint64 + var mapkey string + var mapvalue string + for iNdEx < postIndex { + entryPreIndex := iNdEx + var wire uint64 for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowTypes @@ -2273,41 +2267,80 @@ func (m *Resource) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - valuekey |= (uint64(b) & 0x7F) << shift + wire |= (uint64(b) & 0x7F) << shift if b < 0x80 { break } } - var stringLenmapvalue uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTypes + fieldNum := int32(wire >> 3) + if fieldNum == 1 { + var stringLenmapkey uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLenmapkey |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } } - if iNdEx >= l { + intStringLenmapkey := int(stringLenmapkey) + if intStringLenmapkey < 0 { + return ErrInvalidLengthTypes + } + postStringIndexmapkey := iNdEx + intStringLenmapkey + if postStringIndexmapkey > l { return io.ErrUnexpectedEOF } - b := dAtA[iNdEx] - iNdEx++ - stringLenmapvalue |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break + mapkey = string(dAtA[iNdEx:postStringIndexmapkey]) + iNdEx = postStringIndexmapkey + } else if fieldNum == 2 { + var stringLenmapvalue uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLenmapvalue |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } } + intStringLenmapvalue := int(stringLenmapvalue) + if intStringLenmapvalue < 0 { + return ErrInvalidLengthTypes + } + postStringIndexmapvalue := iNdEx + intStringLenmapvalue + if postStringIndexmapvalue > l { + return io.ErrUnexpectedEOF + } + mapvalue = string(dAtA[iNdEx:postStringIndexmapvalue]) + iNdEx = postStringIndexmapvalue + } else { + iNdEx = entryPreIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > postIndex { + return io.ErrUnexpectedEOF + } + iNdEx += skippy } - intStringLenmapvalue := int(stringLenmapvalue) - if intStringLenmapvalue < 0 { - return ErrInvalidLengthTypes - } - postStringIndexmapvalue := iNdEx + intStringLenmapvalue - if postStringIndexmapvalue > l { - return io.ErrUnexpectedEOF - } - mapvalue := string(dAtA[iNdEx:postStringIndexmapvalue]) - iNdEx = postStringIndexmapvalue - m.Parameters[mapkey] = mapvalue - } else { - var mapvalue string - m.Parameters[mapkey] = mapvalue } + m.Parameters[mapkey] = mapvalue iNdEx = postIndex case 10: if wireType != 2 { @@ -2335,51 +2368,14 @@ func (m *Resource) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - var keykey uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTypes - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - keykey |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - var stringLenmapkey uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTypes - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLenmapkey |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - intStringLenmapkey := int(stringLenmapkey) - if intStringLenmapkey < 0 { - return ErrInvalidLengthTypes - } - postStringIndexmapkey := iNdEx + intStringLenmapkey - if postStringIndexmapkey > l { - return io.ErrUnexpectedEOF - } - mapkey := string(dAtA[iNdEx:postStringIndexmapkey]) - iNdEx = postStringIndexmapkey if m.Outputs == nil { m.Outputs = make(map[string]string) } - if iNdEx < postIndex { - var valuekey uint64 + var mapkey string + var mapvalue string + for iNdEx < postIndex { + entryPreIndex := iNdEx + var wire uint64 for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowTypes @@ -2389,41 +2385,80 @@ func (m *Resource) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - valuekey |= (uint64(b) & 0x7F) << shift + wire |= (uint64(b) & 0x7F) << shift if b < 0x80 { break } } - var stringLenmapvalue uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTypes + fieldNum := int32(wire >> 3) + if fieldNum == 1 { + var stringLenmapkey uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLenmapkey |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } } - if iNdEx >= l { + intStringLenmapkey := int(stringLenmapkey) + if intStringLenmapkey < 0 { + return ErrInvalidLengthTypes + } + postStringIndexmapkey := iNdEx + intStringLenmapkey + if postStringIndexmapkey > l { return io.ErrUnexpectedEOF } - b := dAtA[iNdEx] - iNdEx++ - stringLenmapvalue |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break + mapkey = string(dAtA[iNdEx:postStringIndexmapkey]) + iNdEx = postStringIndexmapkey + } else if fieldNum == 2 { + var stringLenmapvalue uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLenmapvalue |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } } + intStringLenmapvalue := int(stringLenmapvalue) + if intStringLenmapvalue < 0 { + return ErrInvalidLengthTypes + } + postStringIndexmapvalue := iNdEx + intStringLenmapvalue + if postStringIndexmapvalue > l { + return io.ErrUnexpectedEOF + } + mapvalue = string(dAtA[iNdEx:postStringIndexmapvalue]) + iNdEx = postStringIndexmapvalue + } else { + iNdEx = entryPreIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > postIndex { + return io.ErrUnexpectedEOF + } + iNdEx += skippy } - intStringLenmapvalue := int(stringLenmapvalue) - if intStringLenmapvalue < 0 { - return ErrInvalidLengthTypes - } - postStringIndexmapvalue := iNdEx + intStringLenmapvalue - if postStringIndexmapvalue > l { - return io.ErrUnexpectedEOF - } - mapvalue := string(dAtA[iNdEx:postStringIndexmapvalue]) - iNdEx = postStringIndexmapvalue - m.Outputs[mapkey] = mapvalue - } else { - var mapvalue string - m.Outputs[mapkey] = mapvalue } + m.Outputs[mapkey] = mapvalue iNdEx = postIndex case 11: if wireType != 2 { @@ -2451,51 +2486,14 @@ func (m *Resource) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - var keykey uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTypes - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - keykey |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - var stringLenmapkey uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTypes - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLenmapkey |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - intStringLenmapkey := int(stringLenmapkey) - if intStringLenmapkey < 0 { - return ErrInvalidLengthTypes - } - postStringIndexmapkey := iNdEx + intStringLenmapkey - if postStringIndexmapkey > l { - return io.ErrUnexpectedEOF - } - mapkey := string(dAtA[iNdEx:postStringIndexmapkey]) - iNdEx = postStringIndexmapkey if m.Tags == nil { m.Tags = make(map[string]string) } - if iNdEx < postIndex { - var valuekey uint64 + var mapkey string + var mapvalue string + for iNdEx < postIndex { + entryPreIndex := iNdEx + var wire uint64 for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowTypes @@ -2505,41 +2503,80 @@ func (m *Resource) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - valuekey |= (uint64(b) & 0x7F) << shift + wire |= (uint64(b) & 0x7F) << shift if b < 0x80 { break } } - var stringLenmapvalue uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTypes + fieldNum := int32(wire >> 3) + if fieldNum == 1 { + var stringLenmapkey uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLenmapkey |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } } - if iNdEx >= l { + intStringLenmapkey := int(stringLenmapkey) + if intStringLenmapkey < 0 { + return ErrInvalidLengthTypes + } + postStringIndexmapkey := iNdEx + intStringLenmapkey + if postStringIndexmapkey > l { return io.ErrUnexpectedEOF } - b := dAtA[iNdEx] - iNdEx++ - stringLenmapvalue |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break + mapkey = string(dAtA[iNdEx:postStringIndexmapkey]) + iNdEx = postStringIndexmapkey + } else if fieldNum == 2 { + var stringLenmapvalue uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLenmapvalue |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } } + intStringLenmapvalue := int(stringLenmapvalue) + if intStringLenmapvalue < 0 { + return ErrInvalidLengthTypes + } + postStringIndexmapvalue := iNdEx + intStringLenmapvalue + if postStringIndexmapvalue > l { + return io.ErrUnexpectedEOF + } + mapvalue = string(dAtA[iNdEx:postStringIndexmapvalue]) + iNdEx = postStringIndexmapvalue + } else { + iNdEx = entryPreIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > postIndex { + return io.ErrUnexpectedEOF + } + iNdEx += skippy } - intStringLenmapvalue := int(stringLenmapvalue) - if intStringLenmapvalue < 0 { - return ErrInvalidLengthTypes - } - postStringIndexmapvalue := iNdEx + intStringLenmapvalue - if postStringIndexmapvalue > l { - return io.ErrUnexpectedEOF - } - mapvalue := string(dAtA[iNdEx:postStringIndexmapvalue]) - iNdEx = postStringIndexmapvalue - m.Tags[mapkey] = mapvalue - } else { - var mapvalue string - m.Tags[mapkey] = mapvalue } + m.Tags[mapkey] = mapvalue iNdEx = postIndex default: iNdEx = preIndex @@ -2725,51 +2762,14 @@ func (m *EnvConfig) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - var keykey uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTypes - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - keykey |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - var stringLenmapkey uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTypes - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLenmapkey |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - intStringLenmapkey := int(stringLenmapkey) - if intStringLenmapkey < 0 { - return ErrInvalidLengthTypes - } - postStringIndexmapkey := iNdEx + intStringLenmapkey - if postStringIndexmapkey > l { - return io.ErrUnexpectedEOF - } - mapkey := string(dAtA[iNdEx:postStringIndexmapkey]) - iNdEx = postStringIndexmapkey if m.Data == nil { m.Data = make(map[string]string) } - if iNdEx < postIndex { - var valuekey uint64 + var mapkey string + var mapvalue string + for iNdEx < postIndex { + entryPreIndex := iNdEx + var wire uint64 for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowTypes @@ -2779,41 +2779,80 @@ func (m *EnvConfig) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - valuekey |= (uint64(b) & 0x7F) << shift + wire |= (uint64(b) & 0x7F) << shift if b < 0x80 { break } } - var stringLenmapvalue uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTypes + fieldNum := int32(wire >> 3) + if fieldNum == 1 { + var stringLenmapkey uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLenmapkey |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } } - if iNdEx >= l { + intStringLenmapkey := int(stringLenmapkey) + if intStringLenmapkey < 0 { + return ErrInvalidLengthTypes + } + postStringIndexmapkey := iNdEx + intStringLenmapkey + if postStringIndexmapkey > l { return io.ErrUnexpectedEOF } - b := dAtA[iNdEx] - iNdEx++ - stringLenmapvalue |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break + mapkey = string(dAtA[iNdEx:postStringIndexmapkey]) + iNdEx = postStringIndexmapkey + } else if fieldNum == 2 { + var stringLenmapvalue uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLenmapvalue |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } } + intStringLenmapvalue := int(stringLenmapvalue) + if intStringLenmapvalue < 0 { + return ErrInvalidLengthTypes + } + postStringIndexmapvalue := iNdEx + intStringLenmapvalue + if postStringIndexmapvalue > l { + return io.ErrUnexpectedEOF + } + mapvalue = string(dAtA[iNdEx:postStringIndexmapvalue]) + iNdEx = postStringIndexmapvalue + } else { + iNdEx = entryPreIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > postIndex { + return io.ErrUnexpectedEOF + } + iNdEx += skippy } - intStringLenmapvalue := int(stringLenmapvalue) - if intStringLenmapvalue < 0 { - return ErrInvalidLengthTypes - } - postStringIndexmapvalue := iNdEx + intStringLenmapvalue - if postStringIndexmapvalue > l { - return io.ErrUnexpectedEOF - } - mapvalue := string(dAtA[iNdEx:postStringIndexmapvalue]) - iNdEx = postStringIndexmapvalue - m.Data[mapkey] = mapvalue - } else { - var mapvalue string - m.Data[mapkey] = mapvalue } + m.Data[mapkey] = mapvalue iNdEx = postIndex default: iNdEx = preIndex @@ -2867,7 +2906,7 @@ func (m *Process) Unmarshal(dAtA []byte) error { switch fieldNum { case 1: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Name", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Proctype", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -2892,11 +2931,30 @@ func (m *Process) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.Name = string(dAtA[iNdEx:postIndex]) + m.Proctype = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Count", wireType) + } + m.Count = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Count |= (int32(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + case 3: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Proctype", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Status", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -2921,13 +2979,13 @@ func (m *Process) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.Proctype = string(dAtA[iNdEx:postIndex]) + m.Status = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex - case 3: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field Workers", wireType) + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Cpu", wireType) } - m.Workers = 0 + var stringLen uint64 for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowTypes @@ -2937,14 +2995,24 @@ func (m *Process) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - m.Workers |= (int32(b) & 0x7F) << shift + stringLen |= (uint64(b) & 0x7F) << shift if b < 0x80 { break } } - case 4: + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Cpu = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 5: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Status", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Memory", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -2969,7 +3037,36 @@ func (m *Process) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.Status = string(dAtA[iNdEx:postIndex]) + m.Memory = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Command", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTypes + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Command = append(m.Command, string(dAtA[iNdEx:postIndex])) iNdEx = postIndex default: iNdEx = preIndex @@ -3076,51 +3173,14 @@ func (m *Formation) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - var keykey uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTypes - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - keykey |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - var stringLenmapkey uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTypes - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLenmapkey |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - intStringLenmapkey := int(stringLenmapkey) - if intStringLenmapkey < 0 { - return ErrInvalidLengthTypes - } - postStringIndexmapkey := iNdEx + intStringLenmapkey - if postStringIndexmapkey > l { - return io.ErrUnexpectedEOF - } - mapkey := string(dAtA[iNdEx:postStringIndexmapkey]) - iNdEx = postStringIndexmapkey if m.Structure == nil { m.Structure = make(map[string]int32) } - if iNdEx < postIndex { - var valuekey uint64 + var mapkey string + var mapvalue int32 + for iNdEx < postIndex { + entryPreIndex := iNdEx + var wire uint64 for shift := uint(0); ; shift += 7 { if shift >= 64 { return ErrIntOverflowTypes @@ -3130,31 +3190,69 @@ func (m *Formation) Unmarshal(dAtA []byte) error { } b := dAtA[iNdEx] iNdEx++ - valuekey |= (uint64(b) & 0x7F) << shift + wire |= (uint64(b) & 0x7F) << shift if b < 0x80 { break } } - var mapvalue int32 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTypes + fieldNum := int32(wire >> 3) + if fieldNum == 1 { + var stringLenmapkey uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLenmapkey |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } } - if iNdEx >= l { + intStringLenmapkey := int(stringLenmapkey) + if intStringLenmapkey < 0 { + return ErrInvalidLengthTypes + } + postStringIndexmapkey := iNdEx + intStringLenmapkey + if postStringIndexmapkey > l { return io.ErrUnexpectedEOF } - b := dAtA[iNdEx] - iNdEx++ - mapvalue |= (int32(b) & 0x7F) << shift - if b < 0x80 { - break + mapkey = string(dAtA[iNdEx:postStringIndexmapkey]) + iNdEx = postStringIndexmapkey + } else if fieldNum == 2 { + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + mapvalue |= (int32(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + } else { + iNdEx = entryPreIndex + skippy, err := skipTypes(dAtA[iNdEx:]) + if err != nil { + return err + } + if skippy < 0 { + return ErrInvalidLengthTypes + } + if (iNdEx + skippy) > postIndex { + return io.ErrUnexpectedEOF } + iNdEx += skippy } - m.Structure[mapkey] = mapvalue - } else { - var mapvalue int32 - m.Structure[mapkey] = mapvalue } + m.Structure[mapkey] = mapvalue iNdEx = postIndex default: iNdEx = preIndex @@ -3285,64 +3383,65 @@ var ( func init() { proto.RegisterFile("types.proto", fileDescriptorTypes) } var fileDescriptorTypes = []byte{ - // 938 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xc4, 0x56, 0xdf, 0x6e, 0xe3, 0xc4, - 0x17, 0x96, 0xe3, 0x24, 0xae, 0x4f, 0xbb, 0x7f, 0x7e, 0xf3, 0xab, 0x16, 0x2b, 0xed, 0xc6, 0x59, - 0x4b, 0x2b, 0x72, 0x41, 0x13, 0x04, 0xe2, 0x5f, 0x59, 0x40, 0x0d, 0x14, 0xa9, 0xab, 0x95, 0x58, - 0x19, 0x16, 0x21, 0x6e, 0xaa, 0x69, 0x3c, 0x0d, 0x56, 0x12, 0x8f, 0x35, 0x33, 0x2e, 0xdb, 0x17, - 0xe0, 0x8a, 0x17, 0x40, 0x3c, 0x02, 0x2f, 0xc2, 0x25, 0x4f, 0x60, 0xa1, 0x3e, 0x82, 0x9f, 0x00, - 0xcd, 0x1f, 0xc7, 0x93, 0x66, 0x57, 0x10, 0x09, 0x89, 0xbb, 0xcc, 0x39, 0xdf, 0xf7, 0xf9, 0xcc, - 0x39, 0x5f, 0x8e, 0x0d, 0xbb, 0xe2, 0x3a, 0x27, 0x7c, 0x94, 0x33, 0x2a, 0x28, 0xea, 0x2e, 0x69, - 0x42, 0x16, 0xbc, 0x77, 0x38, 0xa3, 0x74, 0xb6, 0x20, 0x63, 0x9c, 0xa7, 0x63, 0x9c, 0x65, 0x54, - 0x60, 0x91, 0xd2, 0xcc, 0xa0, 0x7a, 0x47, 0xb3, 0x54, 0xfc, 0x50, 0x5c, 0x8c, 0xa6, 0x74, 0x39, - 0x9e, 0xd1, 0x19, 0x1d, 0xab, 0xf0, 0x45, 0x71, 0xa9, 0x4e, 0xea, 0xa0, 0x7e, 0x69, 0x78, 0xf4, - 0x8b, 0x0b, 0xee, 0x49, 0x9e, 0xa3, 0x21, 0xb4, 0x33, 0xbc, 0x24, 0x81, 0x33, 0x70, 0x86, 0xfe, - 0x64, 0xbf, 0x2a, 0xc3, 0xfb, 0x09, 0x16, 0x98, 0x0b, 0xca, 0xc8, 0x71, 0x24, 0x53, 0x51, 0xac, - 0x10, 0x68, 0x04, 0x5d, 0x2e, 0xb0, 0x28, 0x78, 0xd0, 0x52, 0xd8, 0x07, 0x55, 0x19, 0x22, 0x0b, - 0xab, 0x93, 0x51, 0x6c, 0x50, 0xe8, 0x04, 0x80, 0x91, 0x05, 0xc1, 0x9c, 0x9c, 0xa7, 0x49, 0xe0, - 0x2a, 0x4e, 0x54, 0x95, 0x61, 0xdf, 0xe2, 0x34, 0x80, 0xb7, 0x32, 0x9a, 0x66, 0x09, 0x79, 0x19, - 0xc5, 0xbe, 0x09, 0x9e, 0x25, 0xe8, 0x09, 0xec, 0x90, 0x2c, 0xc9, 0x69, 0x9a, 0x89, 0xa0, 0xad, - 0x04, 0x06, 0x55, 0x19, 0x1e, 0x5a, 0x02, 0x75, 0xba, 0xa1, 0xaf, 0x18, 0xe8, 0x63, 0xd8, 0xb9, - 0x28, 0xd2, 0x45, 0x22, 0x1f, 0xdf, 0x79, 0x25, 0xbb, 0x4e, 0x37, 0x6c, 0x4f, 0x85, 0xce, 0x12, - 0xf4, 0x11, 0x78, 0x09, 0x5d, 0xe2, 0x34, 0xe3, 0x41, 0x77, 0xe0, 0x0e, 0xfd, 0x49, 0x58, 0x95, - 0xe1, 0x81, 0xc5, 0x35, 0x59, 0x8b, 0x6a, 0x22, 0xe8, 0x33, 0xf0, 0x19, 0xe1, 0xb4, 0x60, 0x53, - 0xc2, 0x03, 0x4f, 0x91, 0x1f, 0x55, 0x65, 0xf8, 0x70, 0xed, 0xde, 0x26, 0xbf, 0x76, 0x6d, 0x13, - 0x8b, 0x7e, 0x72, 0xa1, 0x33, 0x91, 0x75, 0xa0, 0x08, 0x5a, 0x69, 0x62, 0x66, 0x83, 0xaa, 0x32, - 0xbc, 0x6b, 0x69, 0xa4, 0x49, 0x14, 0xb7, 0xd2, 0x04, 0x3d, 0x06, 0x17, 0xe7, 0xb9, 0x19, 0xca, - 0xff, 0xab, 0x32, 0xbc, 0x67, 0x81, 0x70, 0x9e, 0x47, 0xb1, 0xcc, 0xa3, 0x4f, 0x65, 0x55, 0x4b, - 0x2a, 0xac, 0x69, 0x6c, 0x56, 0x65, 0xf2, 0x56, 0x37, 0x75, 0xec, 0x2c, 0x41, 0xef, 0xaf, 0xc6, - 0xaf, 0x27, 0xd1, 0xaf, 0xca, 0xb0, 0xb7, 0x31, 0xfe, 0x86, 0x69, 0xd9, 0x60, 0xca, 0x08, 0x16, - 0x24, 0x39, 0xc7, 0x42, 0xcd, 0xa1, 0xb3, 0x61, 0x83, 0x06, 0x60, 0xf5, 0xc3, 0x04, 0x4f, 0x84, - 0xb4, 0x41, 0xce, 0xe8, 0xf4, 0x32, 0x5d, 0x90, 0xa0, 0x3b, 0x70, 0x86, 0x7b, 0x1b, 0x83, 0xac, - 0xd3, 0x56, 0xe1, 0x75, 0x48, 0x4e, 0xf2, 0x8a, 0x30, 0x9e, 0xd2, 0x2c, 0xf0, 0x54, 0xe5, 0xb7, - 0x27, 0x69, 0xb2, 0xd6, 0x24, 0x4d, 0x24, 0xfa, 0xb9, 0x05, 0x5e, 0xac, 0xdd, 0xf8, 0x6f, 0x8e, - 0xc2, 0x36, 0xa6, 0xbb, 0xad, 0x31, 0xff, 0xbb, 0x39, 0x44, 0xbf, 0x79, 0xb0, 0x13, 0x1b, 0x97, - 0x6e, 0xb1, 0x38, 0x86, 0xd0, 0x9e, 0xa7, 0x59, 0x62, 0xda, 0x72, 0x1b, 0x29, 0x53, 0x51, 0xac, - 0x10, 0xd6, 0xdd, 0xdc, 0xad, 0xee, 0xf6, 0x14, 0xee, 0xe8, 0x5f, 0xe7, 0x8c, 0x60, 0x4e, 0x33, - 0xd3, 0x9a, 0xc7, 0x55, 0x19, 0x3e, 0xda, 0xa0, 0x1b, 0x4c, 0xa3, 0xb2, 0xa7, 0xe3, 0xb1, 0x0a, - 0xa3, 0x23, 0x70, 0x5f, 0xc4, 0xcf, 0xcc, 0xc2, 0x38, 0xa8, 0xca, 0xf0, 0x0d, 0x4b, 0xe1, 0x45, - 0xfc, 0xac, 0xe1, 0x49, 0x1c, 0x7a, 0x13, 0x3a, 0x5c, 0xe0, 0xe9, 0x5c, 0x19, 0xd3, 0x9f, 0xfc, - 0xaf, 0x2a, 0xc3, 0x3b, 0x16, 0xe1, 0x28, 0x8a, 0x75, 0x1e, 0xbd, 0x0d, 0x6d, 0x9c, 0xe7, 0xf5, - 0x42, 0x38, 0xac, 0xca, 0x30, 0x58, 0x37, 0x87, 0x75, 0x2f, 0x85, 0x44, 0xdf, 0x81, 0x47, 0x5e, - 0xe6, 0x94, 0x09, 0x1e, 0xec, 0x0c, 0xdc, 0xe1, 0xee, 0x3b, 0x0f, 0x47, 0xfa, 0x4d, 0x30, 0xaa, - 0x87, 0x30, 0x3a, 0xd5, 0xf9, 0xd3, 0x4c, 0xb0, 0xeb, 0x0d, 0x5f, 0x1b, 0xb2, 0xe5, 0x21, 0x13, - 0x41, 0x09, 0x40, 0x8e, 0x19, 0x5e, 0x12, 0x41, 0x18, 0x0f, 0x7c, 0x25, 0x3e, 0xd8, 0x10, 0x7f, - 0xbe, 0x82, 0x68, 0xfd, 0xdb, 0x6e, 0x69, 0x24, 0x9a, 0x47, 0x58, 0xba, 0xe8, 0x29, 0x78, 0xb4, - 0x10, 0x79, 0x21, 0x78, 0x00, 0xaf, 0xa9, 0xff, 0x2b, 0x9d, 0xd7, 0xfa, 0xaf, 0xe8, 0x5d, 0x2d, - 0x80, 0x4e, 0xa0, 0x2d, 0xf0, 0x8c, 0x07, 0xbb, 0x4a, 0xa8, 0xb7, 0x21, 0xf4, 0x0d, 0x9e, 0xbd, - 0x5e, 0x45, 0x51, 0x7b, 0xc7, 0xb0, 0x67, 0xb7, 0x0b, 0xdd, 0x07, 0x77, 0x4e, 0xae, 0xb5, 0x7f, - 0x63, 0xf9, 0x13, 0xed, 0x43, 0xe7, 0x0a, 0x2f, 0x0a, 0xa2, 0x9d, 0x1a, 0xeb, 0xc3, 0x71, 0xeb, - 0x43, 0xa7, 0xf7, 0x09, 0xdc, 0xbb, 0xd5, 0x8d, 0xad, 0xe8, 0xc7, 0xb0, 0x67, 0xdf, 0x74, 0x2b, - 0xee, 0x07, 0xe0, 0xaf, 0x2e, 0xb7, 0x0d, 0x31, 0x7a, 0x0f, 0x76, 0xeb, 0xf6, 0x7c, 0x8b, 0xd9, - 0x3f, 0xa5, 0x46, 0x05, 0xf8, 0xa7, 0xd9, 0xd5, 0xe7, 0x34, 0xbb, 0x4c, 0x67, 0x68, 0x0c, 0x6d, - 0xd9, 0xca, 0xc0, 0x51, 0x6d, 0x3f, 0xa8, 0xdb, 0xbe, 0x02, 0x8c, 0xbe, 0xc0, 0x02, 0xab, 0xd2, - 0x62, 0x05, 0x94, 0xd5, 0xae, 0x42, 0x5b, 0x55, 0x3b, 0x07, 0xef, 0x39, 0xa3, 0x53, 0xc2, 0x39, - 0x42, 0xf6, 0x66, 0x31, 0x3b, 0xa4, 0xa7, 0x5f, 0x01, 0xf2, 0xb3, 0xc8, 0x70, 0x57, 0x67, 0x14, - 0x80, 0xf7, 0x23, 0x65, 0x73, 0x69, 0x65, 0xb9, 0x36, 0x3a, 0x71, 0x7d, 0x44, 0x0f, 0xd6, 0x77, - 0x65, 0xbd, 0x2f, 0xa2, 0x5f, 0x1d, 0xf0, 0xbf, 0xa4, 0x6c, 0xa9, 0x3e, 0xa0, 0x64, 0x99, 0x72, - 0x6b, 0x9b, 0x32, 0xcd, 0xbb, 0x92, 0x0b, 0x56, 0x4c, 0x45, 0xc1, 0xe4, 0xe3, 0xd6, 0xfe, 0x1e, - 0x2b, 0xde, 0xe8, 0xeb, 0x1a, 0xa2, 0x1b, 0xd0, 0x50, 0x7a, 0x4f, 0xe0, 0xee, 0x7a, 0xf2, 0xef, - 0x5a, 0xd1, 0xb1, 0x5a, 0x31, 0xd9, 0xff, 0xfd, 0xa6, 0xef, 0xfc, 0x71, 0xd3, 0x77, 0xfe, 0xbc, - 0xe9, 0x3b, 0xdf, 0x9b, 0xaf, 0xbf, 0x8b, 0xae, 0xfa, 0x6e, 0x7b, 0xf7, 0xaf, 0x00, 0x00, 0x00, - 0xff, 0xff, 0x83, 0x0d, 0x5c, 0x58, 0x1b, 0x0a, 0x00, 0x00, + // 960 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xc4, 0x56, 0xdd, 0x6e, 0xe3, 0x44, + 0x14, 0x96, 0xeb, 0xa4, 0x6e, 0x4e, 0xbb, 0xbb, 0x65, 0xa8, 0x16, 0x2b, 0xed, 0xc6, 0x59, 0x4b, + 0x2b, 0x72, 0x41, 0x13, 0x04, 0xe2, 0xaf, 0x2c, 0xa0, 0x06, 0x8a, 0xd4, 0xd5, 0x4a, 0xac, 0x0c, + 0x8b, 0x10, 0x37, 0xd5, 0xd4, 0x9e, 0x06, 0xab, 0xb1, 0xc7, 0x9a, 0x19, 0x57, 0xdb, 0x17, 0xe0, + 0x8a, 0x7b, 0x84, 0x78, 0x04, 0x5e, 0x84, 0x4b, 0x9e, 0xc0, 0x42, 0x7d, 0x04, 0x3f, 0x01, 0x9a, + 0x1f, 0xc7, 0x93, 0x66, 0x57, 0x10, 0x09, 0x69, 0xef, 0x66, 0xce, 0xf9, 0xbe, 0x2f, 0xe7, 0x2f, + 0xc7, 0x03, 0xdb, 0xe2, 0xba, 0x20, 0x7c, 0x5c, 0x30, 0x2a, 0x28, 0xda, 0xcc, 0x68, 0x42, 0xe6, + 0xbc, 0x7f, 0x30, 0xa3, 0x74, 0x36, 0x27, 0x13, 0x5c, 0xa4, 0x13, 0x9c, 0xe7, 0x54, 0x60, 0x91, + 0xd2, 0xdc, 0xa0, 0xfa, 0x87, 0xb3, 0x54, 0xfc, 0x54, 0x9e, 0x8f, 0x63, 0x9a, 0x4d, 0x66, 0x74, + 0x46, 0x27, 0xca, 0x7c, 0x5e, 0x5e, 0xa8, 0x9b, 0xba, 0xa8, 0x93, 0x86, 0x87, 0xbf, 0xb9, 0xe0, + 0x1e, 0x17, 0x05, 0x1a, 0x41, 0x27, 0xc7, 0x19, 0xf1, 0x9d, 0xa1, 0x33, 0xea, 0x4d, 0xf7, 0xea, + 0x2a, 0xd8, 0x4d, 0xb0, 0xc0, 0x5c, 0x50, 0x46, 0x8e, 0x42, 0xe9, 0x0a, 0x23, 0x85, 0x40, 0x63, + 0xd8, 0xe4, 0x02, 0x8b, 0x92, 0xfb, 0x1b, 0x0a, 0x7b, 0xbf, 0xae, 0x02, 0x64, 0x61, 0xb5, 0x33, + 0x8c, 0x0c, 0x0a, 0x1d, 0x03, 0x30, 0x32, 0x27, 0x98, 0x93, 0xb3, 0x34, 0xf1, 0x5d, 0xc5, 0x09, + 0xeb, 0x2a, 0x18, 0x58, 0x9c, 0x16, 0xf0, 0x4e, 0x4e, 0xd3, 0x3c, 0x21, 0x2f, 0xc2, 0xa8, 0x67, + 0x8c, 0xa7, 0x09, 0x7a, 0x0c, 0x5b, 0x24, 0x4f, 0x0a, 0x9a, 0xe6, 0xc2, 0xef, 0x28, 0x81, 0x61, + 0x5d, 0x05, 0x07, 0x96, 0x40, 0xe3, 0x6e, 0xe9, 0x0b, 0x06, 0xfa, 0x14, 0xb6, 0xce, 0xcb, 0x74, + 0x9e, 0xc8, 0x9f, 0xef, 0xbe, 0x94, 0xdd, 0xb8, 0x5b, 0xb6, 0xa7, 0x4c, 0xa7, 0x09, 0xfa, 0x04, + 0xbc, 0x84, 0x66, 0x38, 0xcd, 0xb9, 0xbf, 0x39, 0x74, 0x47, 0xbd, 0x69, 0x50, 0x57, 0xc1, 0xbe, + 0xc5, 0x35, 0x5e, 0x8b, 0x6a, 0x2c, 0xe8, 0x0b, 0xe8, 0x31, 0xc2, 0x69, 0xc9, 0x62, 0xc2, 0x7d, + 0x4f, 0x91, 0x1f, 0xd6, 0x55, 0xf0, 0x60, 0x29, 0x6f, 0xe3, 0x5f, 0x4a, 0xdb, 0xd8, 0xc2, 0x9f, + 0x5d, 0xe8, 0x4e, 0x65, 0x1c, 0x28, 0x84, 0x8d, 0x34, 0x31, 0xbd, 0x41, 0x75, 0x15, 0xdc, 0xb5, + 0x34, 0xd2, 0x24, 0x8c, 0x36, 0xd2, 0x04, 0x3d, 0x02, 0x17, 0x17, 0x85, 0x69, 0xca, 0x9b, 0x75, + 0x15, 0xdc, 0xb3, 0x40, 0xb8, 0x28, 0xc2, 0x48, 0xfa, 0xd1, 0xe7, 0x32, 0xaa, 0x8c, 0x0a, 0xab, + 0x1b, 0xab, 0x51, 0x19, 0xbf, 0x55, 0x4d, 0x6d, 0x3b, 0x4d, 0xd0, 0x87, 0x8b, 0xf6, 0xeb, 0x4e, + 0x0c, 0xea, 0x2a, 0xe8, 0xaf, 0xb4, 0xbf, 0x65, 0x5a, 0x63, 0x10, 0x33, 0x82, 0x05, 0x49, 0xce, + 0xb0, 0x50, 0x7d, 0xe8, 0xae, 0x8c, 0x41, 0x0b, 0xb0, 0xea, 0x61, 0x8c, 0xc7, 0x42, 0x8e, 0x41, + 0xc1, 0x68, 0x7c, 0x91, 0xce, 0x89, 0xbf, 0x39, 0x74, 0x46, 0x3b, 0x2b, 0x8d, 0x6c, 0xdc, 0x56, + 0xe0, 0x8d, 0x49, 0x76, 0xf2, 0x8a, 0x30, 0x9e, 0xd2, 0xdc, 0xf7, 0x54, 0xe4, 0xb7, 0x3b, 0x69, + 0xbc, 0x56, 0x27, 0x8d, 0x25, 0xfc, 0x65, 0x03, 0xbc, 0x48, 0x4f, 0xe3, 0xff, 0xd9, 0x0a, 0x7b, + 0x30, 0xdd, 0x75, 0x07, 0xf3, 0xf5, 0xf5, 0x21, 0xfc, 0xc3, 0x83, 0xad, 0xc8, 0x4c, 0xe9, 0x1a, + 0x8b, 0x63, 0x04, 0x9d, 0xcb, 0x34, 0x4f, 0x4c, 0x59, 0x6e, 0x23, 0xa5, 0x2b, 0x8c, 0x14, 0xc2, + 0xca, 0xcd, 0x5d, 0x2b, 0xb7, 0x27, 0x70, 0x47, 0x9f, 0xce, 0x18, 0xc1, 0x9c, 0xe6, 0xa6, 0x34, + 0x8f, 0xea, 0x2a, 0x78, 0xb8, 0x42, 0x37, 0x98, 0x56, 0x65, 0x47, 0xdb, 0x23, 0x65, 0x46, 0x87, + 0xe0, 0x3e, 0x8f, 0x9e, 0x9a, 0x85, 0xb1, 0x5f, 0x57, 0xc1, 0x5b, 0x96, 0xc2, 0xf3, 0xe8, 0x69, + 0xcb, 0x93, 0x38, 0xf4, 0x36, 0x74, 0xb9, 0xc0, 0xf1, 0xa5, 0x1a, 0xcc, 0xde, 0xf4, 0x8d, 0xba, + 0x0a, 0xee, 0x58, 0x84, 0xc3, 0x30, 0xd2, 0x7e, 0xf4, 0x2e, 0x74, 0x70, 0x51, 0x34, 0x0b, 0xe1, + 0xa0, 0xae, 0x02, 0x7f, 0x79, 0x38, 0xac, 0xbc, 0x14, 0x12, 0xfd, 0x00, 0x1e, 0x79, 0x51, 0x50, + 0x26, 0xb8, 0xbf, 0x35, 0x74, 0x47, 0xdb, 0xef, 0x3d, 0x18, 0xeb, 0x2f, 0xc1, 0xb8, 0x69, 0xc2, + 0xf8, 0x44, 0xfb, 0x4f, 0x72, 0xc1, 0xae, 0x57, 0xe6, 0xda, 0x90, 0xad, 0x19, 0x32, 0x16, 0x94, + 0x00, 0x14, 0x98, 0xe1, 0x8c, 0x08, 0xc2, 0xb8, 0xdf, 0x53, 0xe2, 0xc3, 0x15, 0xf1, 0x67, 0x0b, + 0x88, 0xd6, 0xbf, 0x3d, 0x2d, 0xad, 0x44, 0xfb, 0x13, 0x96, 0x2e, 0x7a, 0x02, 0x1e, 0x2d, 0x45, + 0x51, 0x0a, 0xee, 0xc3, 0x2b, 0xe2, 0xff, 0x46, 0xfb, 0xb5, 0xfe, 0x4b, 0x6a, 0xd7, 0x08, 0xa0, + 0x63, 0xe8, 0x08, 0x3c, 0xe3, 0xfe, 0xb6, 0x12, 0xea, 0xaf, 0x08, 0x7d, 0x87, 0x67, 0xaf, 0x56, + 0x51, 0xd4, 0xfe, 0x11, 0xec, 0xd8, 0xe5, 0x42, 0xbb, 0xe0, 0x5e, 0x92, 0x6b, 0x3d, 0xbf, 0x91, + 0x3c, 0xa2, 0x3d, 0xe8, 0x5e, 0xe1, 0x79, 0x49, 0xf4, 0xa4, 0x46, 0xfa, 0x72, 0xb4, 0xf1, 0xb1, + 0xd3, 0xff, 0x0c, 0xee, 0xdd, 0xaa, 0xc6, 0x5a, 0xf4, 0x23, 0xd8, 0xb1, 0x33, 0x5d, 0x8b, 0xfb, + 0x11, 0xf4, 0x16, 0xc9, 0xad, 0x43, 0x0c, 0x3f, 0x80, 0xed, 0xa6, 0x3c, 0xdf, 0x63, 0xf6, 0x5f, + 0xa9, 0x61, 0x09, 0xbd, 0x93, 0xfc, 0xea, 0x4b, 0x9a, 0x5f, 0xa4, 0x33, 0x34, 0x81, 0x8e, 0x2c, + 0xa5, 0xef, 0xa8, 0xb2, 0xef, 0x37, 0x65, 0x5f, 0x00, 0xc6, 0x5f, 0x61, 0x81, 0x55, 0x68, 0x91, + 0x02, 0xca, 0x68, 0x17, 0xa6, 0xb5, 0xa2, 0xfd, 0xd5, 0x01, 0xef, 0x19, 0xa3, 0x31, 0xe1, 0x1c, + 0xf5, 0xf5, 0xbe, 0x97, 0x6f, 0x20, 0x43, 0x5e, 0xdc, 0xa5, 0x42, 0x4c, 0xcb, 0x5c, 0x28, 0x85, + 0x6e, 0xa4, 0x2f, 0xe8, 0xfe, 0xf2, 0xe2, 0x58, 0x2c, 0x86, 0x5d, 0x70, 0xe3, 0xa2, 0xd4, 0xeb, + 0x20, 0x92, 0x47, 0x89, 0xcc, 0x48, 0x46, 0xd9, 0xb5, 0xfe, 0x87, 0x47, 0xe6, 0x86, 0x7c, 0xf0, + 0x62, 0x9a, 0x65, 0x38, 0x4f, 0xf4, 0xf7, 0x3e, 0x6a, 0xae, 0xe1, 0xef, 0x0e, 0xf4, 0xbe, 0xa6, + 0x2c, 0x53, 0xaf, 0x2d, 0xa9, 0x28, 0x57, 0xbc, 0xc9, 0xc9, 0x7c, 0x58, 0xb9, 0x60, 0x65, 0x2c, + 0x4a, 0x26, 0xf3, 0x5a, 0xfa, 0x2f, 0x2d, 0x78, 0xe3, 0x6f, 0x1b, 0x88, 0xae, 0x56, 0x4b, 0xe9, + 0x3f, 0x86, 0xbb, 0xcb, 0xce, 0x7f, 0xab, 0x5b, 0xd7, 0xaa, 0xdb, 0x74, 0xef, 0xcf, 0x9b, 0x81, + 0xf3, 0xd7, 0xcd, 0xc0, 0xf9, 0xfb, 0x66, 0xe0, 0xfc, 0x68, 0x9e, 0x8a, 0xe7, 0x9b, 0xea, 0x91, + 0xf7, 0xfe, 0x3f, 0x01, 0x00, 0x00, 0xff, 0xff, 0xac, 0x54, 0xdb, 0xee, 0x48, 0x0a, 0x00, 0x00, } diff --git a/api/models/types.proto b/api/models/types.proto index 81b7a4bc..fe0c685d 100644 --- a/api/models/types.proto +++ b/api/models/types.proto @@ -61,10 +61,12 @@ message EnvConfig { } message Process { - string name = 1; - string proctype = 2; - int32 workers = 3; - string status = 4; + string proctype = 1; + int32 count = 2; + string status = 3; + string cpu = 4; + string memory = 5; + repeated string command = 6; } message Formation { diff --git a/cloud/aws/templates.go b/cloud/aws/templates.go index 12afbb3c..6ca0bd3b 100644 --- a/cloud/aws/templates.go +++ b/cloud/aws/templates.go @@ -87,7 +87,7 @@ func cloudAwsTemplatesAppTmpl() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "cloud/aws/templates/app.tmpl", size: 6660, mode: os.FileMode(420), modTime: time.Unix(1519994908, 0)} + info := bindataFileInfo{name: "cloud/aws/templates/app.tmpl", size: 6660, mode: os.FileMode(436), modTime: time.Unix(1520015640, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -107,7 +107,7 @@ func cloudAwsTemplatesElasticsearchTmpl() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "cloud/aws/templates/elasticsearch.tmpl", size: 4023, mode: os.FileMode(420), modTime: time.Unix(1520701517, 0)} + info := bindataFileInfo{name: "cloud/aws/templates/elasticsearch.tmpl", size: 4023, mode: os.FileMode(436), modTime: time.Unix(1520679773, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -127,7 +127,7 @@ func cloudAwsTemplatesMysqlTmpl() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "cloud/aws/templates/mysql.tmpl", size: 3587, mode: os.FileMode(420), modTime: time.Unix(1500616848, 0)} + info := bindataFileInfo{name: "cloud/aws/templates/mysql.tmpl", size: 3587, mode: os.FileMode(436), modTime: time.Unix(1520015640, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -147,7 +147,7 @@ func cloudAwsTemplatesPostgresTmpl() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "cloud/aws/templates/postgres.tmpl", size: 4389, mode: os.FileMode(420), modTime: time.Unix(1520701517, 0)} + info := bindataFileInfo{name: "cloud/aws/templates/postgres.tmpl", size: 4389, mode: os.FileMode(436), modTime: time.Unix(1520679773, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -167,7 +167,7 @@ func cloudAwsTemplatesRedisTmpl() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "cloud/aws/templates/redis.tmpl", size: 3164, mode: os.FileMode(420), modTime: time.Unix(1500616848, 0)} + info := bindataFileInfo{name: "cloud/aws/templates/redis.tmpl", size: 3164, mode: os.FileMode(436), modTime: time.Unix(1520271844, 0)} a := &asset{bytes: bytes, info: info} return a, nil } diff --git a/cloud/common/apps.go b/cloud/common/apps.go index bfd65689..49ad643f 100644 --- a/cloud/common/apps.go +++ b/cloud/common/apps.go @@ -34,7 +34,7 @@ func UpdateApp(c *kubernetes.Clientset, build *pb.Build, defaultProctype := GetDefaultProctype(build) procesess = append(procesess, &pb.Process{ Proctype: defaultProctype, - Workers: 1, + Count: 1, }) runningProcesses, err := kube.ProcessList(c, ns, build.App) @@ -44,7 +44,7 @@ func UpdateApp(c *kubernetes.Clientset, build *pb.Build, for _, rp := range runningProcesses { if rp.Proctype == defaultProctype { - procesess[0].Workers = rp.Workers // set the current worker similar to whatever running currently + procesess[0].Count = rp.Count // set the current worker similar to whatever running currently } // Only append non-default proceses diff --git a/cloud/common/procfile.go b/cloud/common/procfile.go index ea253eea..5650cddf 100644 --- a/cloud/common/procfile.go +++ b/cloud/common/procfile.go @@ -12,6 +12,7 @@ const ( WebProcessKind = "web" CmdProcessKind = "cmd" + RunProcessKind = "run" defaultShell = "sh" ) diff --git a/cloud/google/templates.go b/cloud/google/templates.go index b743a2fa..1161baea 100644 --- a/cloud/google/templates.go +++ b/cloud/google/templates.go @@ -84,7 +84,7 @@ func cloudGoogleTemplatesMysqlTmpl() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "cloud/google/templates/mysql.tmpl", size: 1392, mode: os.FileMode(420), modTime: time.Unix(1506691380, 0)} + info := bindataFileInfo{name: "cloud/google/templates/mysql.tmpl", size: 1392, mode: os.FileMode(436), modTime: time.Unix(1521875529, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -104,7 +104,7 @@ func cloudGoogleTemplatesPostgresTmpl() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "cloud/google/templates/postgres.tmpl", size: 1134, mode: os.FileMode(420), modTime: time.Unix(1502614896, 0)} + info := bindataFileInfo{name: "cloud/google/templates/postgres.tmpl", size: 1134, mode: os.FileMode(436), modTime: time.Unix(1520015640, 0)} a := &asset{bytes: bytes, info: info} return a, nil } diff --git a/cloud/kube/common.go b/cloud/kube/common.go index 7ee64d6c..f85f54cf 100644 --- a/cloud/kube/common.go +++ b/cloud/kube/common.go @@ -2,23 +2,15 @@ package kube import ( "fmt" - "io" - "math" - "strconv" "strings" - "sync" - "time" log "github.com/Sirupsen/logrus" - "github.com/bjaglin/multiplexio" - pb "github.com/datacol-io/datacol/api/models" "github.com/datacol-io/datacol/cloud" core_v1 "k8s.io/api/core/v1" kerrors "k8s.io/apimachinery/pkg/api/errors" meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1" klabels "k8s.io/apimachinery/pkg/labels" "k8s.io/client-go/kubernetes" - "k8s.io/client-go/rest" ) func DeleteApp(c *kubernetes.Clientset, ns, app string, provider cloud.CloudProvider) error { @@ -209,84 +201,6 @@ func GetServiceEndpoint(c *kubernetes.Clientset, ns, name string) (string, error return endpoint, nil } -func LogStreamReq(c *kubernetes.Clientset, w io.Writer, ns, app string, opts pb.LogStreamOptions) error { - - pods, err := GetAllPods(c, ns, app) - if err != nil { - return err - } - - log.Debugf("Got %d pods for app=%s", len(pods), app) - - //TODO: consider using https://github.com/djherbis/stream for reading multiple streams - var sources []multiplexio.Source - type reqQueue struct { - name string - request *rest.Request - } - - var requests []reqQueue - - for _, pod := range pods { - if opts.Proctype != "" && opts.Proctype != pod.ObjectMeta.Labels[typeLabel] { - continue - } - - name := pod.Name - req := c.Core().RESTClient().Get(). - Namespace(ns). - Name(name). - Resource("pods"). - SubResource("log"). - Param("follow", strconv.FormatBool(opts.Follow)). - Param("tailLines", opts.TailLines) - - var cntName string - if len(pod.Spec.Containers) > 0 { - cntName = pod.Spec.Containers[0].Name - } - - req = req.Param("container", cntName) - log.Debugf("will stream logs from %v/%s", name, cntName) - - if opts.Since > 0 { - sec := int64(math.Ceil(float64(opts.Since) / float64(time.Second))) - req = req.Param("sinceSeconds", strconv.FormatInt(sec, 10)) - } - - requests = append(requests, reqQueue{name: name, request: req}) - } - - var wg sync.WaitGroup - - for _, rq := range requests { - wg.Add(1) - - go func(rq reqQueue) { - defer wg.Done() - r, err := rq.request.Stream() - if err != nil { - log.Errorf("creating log stream: %v", err) - } - - prefix := fmt.Sprintf("[%s] ", strings.TrimPrefix(rq.name, app+"-")) - sources = append(sources, multiplexio.Source{ - Reader: r, - Write: func(dest io.Writer, token []byte) (int, error) { - return multiplexio.WriteNewLine(dest, append([]byte(prefix), token...)) - }, - }) - }(rq) - } - - log.Infof("waiting for stream handlers ...") - wg.Wait() - log.Debugf("Done. Got %d streams", len(sources)) - - _, err = io.Copy(w, multiplexio.NewReader(multiplexio.Options{}, sources...)) - return err -} - func PruneCloudSQLManifest(spec *core_v1.PodSpec) { containers := spec.Containers diff --git a/cloud/kube/deployer.go b/cloud/kube/deployer.go index 4e5a661b..dd4c76d5 100644 --- a/cloud/kube/deployer.go +++ b/cloud/kube/deployer.go @@ -21,6 +21,7 @@ const ( heritage string = "datacol" appLabel string = "app" typeLabel string = "type" + runProcessKind string = "run" ) type Deployer struct { diff --git a/cloud/kube/deployment.go b/cloud/kube/deployment.go index 00ddf53b..e8f11b6e 100644 --- a/cloud/kube/deployment.go +++ b/cloud/kube/deployment.go @@ -16,8 +16,8 @@ import ( ) func newDeployment(payload *DeployRequest) *v1beta1.Deployment { - maxunavailable := intstr.FromString("25%") - maxsurge := intstr.FromString("25%") + maxunavailable := intstr.FromInt(0) + maxsurge := intstr.FromInt(1) labels := map[string]string{ appLabel: payload.App, diff --git a/cloud/kube/logs.go b/cloud/kube/logs.go new file mode 100644 index 00000000..18b1ada0 --- /dev/null +++ b/cloud/kube/logs.go @@ -0,0 +1,99 @@ +package kube + +import ( + "fmt" + "io" + "math" + "strconv" + "strings" + "sync" + "time" + + log "github.com/Sirupsen/logrus" + "github.com/bjaglin/multiplexio" + pb "github.com/datacol-io/datacol/api/models" + "k8s.io/client-go/kubernetes" + "k8s.io/client-go/rest" +) + +func LogStreamReq(c *kubernetes.Clientset, w io.Writer, ns, app string, opts pb.LogStreamOptions) error { + pods, err := GetAllRunningPods(c, ns, app) + if err != nil { + return err + } + + log.Debugf("Got %d pods for app=%s", len(pods), app) + + //TODO: consider using https://github.com/djherbis/stream for reading multiple streams + var sources []multiplexio.Source + type reqQueue struct { + name string + request *rest.Request + } + + var requests []reqQueue + + for _, pod := range pods { + if opts.Proctype != "" && opts.Proctype != pod.ObjectMeta.Labels[typeLabel] { + continue + } + + // Don't collect logs from ephemeral pods + if proctype := pod.ObjectMeta.Labels[typeLabel]; proctype == runProcessKind { + continue + } + + name := pod.Name + req := c.Core().RESTClient().Get(). + Namespace(ns). + Name(name). + Resource("pods"). + SubResource("log"). + Param("follow", strconv.FormatBool(opts.Follow)). + Param("tailLines", opts.TailLines) + + var cntName string + if len(pod.Spec.Containers) > 0 { + cntName = pod.Spec.Containers[0].Name + } + + req = req.Param("container", cntName) + log.Debugf("will stream logs from %v/%s", name, cntName) + + if opts.Since > 0 { + sec := int64(math.Ceil(float64(opts.Since) / float64(time.Second))) + req = req.Param("sinceSeconds", strconv.FormatInt(sec, 10)) + } + + requests = append(requests, reqQueue{name: name, request: req}) + } + + var wg sync.WaitGroup + + for _, rq := range requests { + wg.Add(1) + + go func(rq reqQueue) { + defer wg.Done() + r, err := rq.request.Stream() + if err != nil { + log.Errorf("creating log stream: %v", err) + } + + prefix := fmt.Sprintf("[%s] ", strings.TrimPrefix(rq.name, app+"-")) + sources = append(sources, multiplexio.Source{ + Reader: r, + Write: func(dest io.Writer, token []byte) (int, error) { + return multiplexio.WriteNewLine(dest, append([]byte(prefix), token...)) + }, + }) + }(rq) + } + + log.Infof("waiting for stream handlers ...") + wg.Wait() + log.Debugf("Done. Got %d streams", len(sources)) + + _, err = io.Copy(w, multiplexio.NewReader(multiplexio.Options{}, sources...)) + return err +} diff --git a/cloud/kube/pod.go b/cloud/kube/pod.go index 60afad1a..7e38161d 100644 --- a/cloud/kube/pod.go +++ b/cloud/kube/pod.go @@ -47,9 +47,35 @@ func GetAllPods(c *kubernetes.Clientset, ns, app string) ([]v1.Pod, error) { return nil, err } + sort.Slice(res.Items, func(i, j int) bool { + return res.Items[i].Status.StartTime.Before(res.Items[j].Status.StartTime) + }) + return res.Items, nil } +// Return the pods which seems to be up and running. +func GetAllRunningPods(c *kubernetes.Clientset, ns, app string) ([]v1.Pod, error) { + labels := map[string]string{appLabel: app, managedBy: heritage} + selector := klabels.Set(labels).AsSelector() + res, err := c.Core().Pods(ns).List(metav1.ListOptions{LabelSelector: selector.String()}) + if err != nil { + return nil, err + } + + items := make([]v1.Pod, 0, len(res.Items)) + + for _, item := range res.Items { + status := getPodStatus(c, &item) + if status == podDown || status == podCrashed { + continue + } + items = append(items, item) + } + + return items, nil +} + func GetAllPodNames(c *kubernetes.Clientset, ns, app string) ([]string, error) { pods, err := GetAllPods(c, ns, app) if err != nil { @@ -85,16 +111,23 @@ func getPodsForDeployment(c *kubernetes.Clientset, dp *v1beta1.Deployment) ([]v1 return res.Items, nil } +// Will return the pods in ordered by status.StartTime, Ideally we should filter the pods by the app's +// release version func getLatestPodsForDeployment(c *kubernetes.Clientset, dp *v1beta1.Deployment) ([]v1.Pod, error) { selector := klabels.Set(dp.Spec.Selector.MatchLabels).AsSelector() res, err := c.Core().Pods(dp.Namespace).List(metav1.ListOptions{ LabelSelector: selector.String(), ResourceVersion: dp.ResourceVersion, }) + if err != nil { return nil, err } + sort.Slice(res.Items, func(i, j int) bool { + return res.Items[i].Status.StartTime.Before(res.Items[j].Status.StartTime) + }) + return res.Items, nil } diff --git a/cloud/kube/process.go b/cloud/kube/process.go index 398c58d7..2431872f 100644 --- a/cloud/kube/process.go +++ b/cloud/kube/process.go @@ -122,17 +122,19 @@ func ProcessList(c *kubernetes.Clientset, ns, app string) ([]*pb.Process, error) return nil, err } - var status string - if len(pods) > 0 { - //FIXME: ideally should report status of all pods - status = getPodStatusStr(c, &pods[len(pods)-1]) + if len(pods) == 0 { + continue } + //FIXME: ideally should report status of all pods for latest release/version + targetPod := pods[len(pods)-1] + status := getPodStatusStr(c, &targetPod) + items = append(items, &pb.Process{ Proctype: dp.ObjectMeta.Labels[typeLabel], - Workers: *dp.Spec.Replicas, - Name: dp.Name, + Count: *dp.Spec.Replicas, Status: status, + Command: targetPod.Spec.Containers[0].Args, }) } @@ -149,8 +151,8 @@ func ProcessRun( stream io.ReadWriter, provider cloud.CloudProvider, ) error { - proctype := rand.Characters(6) - podName := fmt.Sprintf("%s-%s", name, proctype) + proctype := runProcessKind + podName := fmt.Sprintf("%s-%s-%s", name, proctype, rand.Characters(6)) req := &DeployRequest{ ServiceID: podName, diff --git a/cmd/provider/aws/templates.go b/cmd/provider/aws/templates.go index 557a07d2..c353406f 100644 --- a/cmd/provider/aws/templates.go +++ b/cmd/provider/aws/templates.go @@ -83,7 +83,7 @@ func cmdProviderAwsTemplatesFormationYaml() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "cmd/provider/aws/templates/formation.yaml", size: 22170, mode: os.FileMode(420), modTime: time.Unix(1521208860, 0)} + info := bindataFileInfo{name: "cmd/provider/aws/templates/formation.yaml", size: 22170, mode: os.FileMode(436), modTime: time.Unix(1522155621, 0)} a := &asset{bytes: bytes, info: info} return a, nil } diff --git a/cmd/ps.go b/cmd/ps.go index 9a431f4f..33540f43 100644 --- a/cmd/ps.go +++ b/cmd/ps.go @@ -3,9 +3,12 @@ package cmd import ( "errors" "fmt" + "os" + "strings" "github.com/appscode/go/term" "github.com/datacol-io/datacol/cmd/stdcli" + "github.com/olekukonko/tablewriter" "github.com/urfave/cli" ) @@ -49,7 +52,13 @@ func cmdAppPS(c *cli.Context) error { stdcli.ExitOnError(err) if len(items) > 0 { - term.Println(toJson(items)) + table := tablewriter.NewWriter(os.Stdout) + table.SetColWidth(100) + table.SetHeader([]string{"PROCESS", "REPLICAS", "STATUS", "COMMAND"}) + for _, item := range items { + table.Append([]string{item.Proctype, fmt.Sprintf("%d", item.Count), item.Status, strings.Join(item.Command, " ")}) + } + table.Render() } else { term.Println("No process running") } From 3adc1fb259a1119a7548b126bbf2ea727ce4c34b Mon Sep 17 00:00:00 2001 From: dinesh Date: Thu, 19 Apr 2018 08:37:24 +0530 Subject: [PATCH 08/13] Adding version label into k8s deployment --- CHANGELOG.md | 3 + api/controller/services.swagger.json | 4 + api/models/types.pb.go | 150 +++++++++++++++++---------- api/models/types.proto | 1 + cloud/aws/provider.go | 3 + cloud/aws/releases.go | 28 ++++- cloud/common/apps.go | 6 +- cloud/google/builder.go | 69 ------------ cloud/google/releases.go | 99 ++++++++++++++++++ cloud/kube/deployer.go | 4 +- cloud/kube/deployment.go | 5 +- cloud/kube/pod.go | 4 +- cloud/local/build.go | 10 +- cmd/build.go | 42 ++++---- cmd/ps.go | 13 ++- 15 files changed, 276 insertions(+), 165 deletions(-) create mode 100644 cloud/google/releases.go diff --git a/CHANGELOG.md b/CHANGELOG.md index ee8e3c1c..63c2625d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,9 @@ This project adheres to [Semantic Versioning](http://semver.org/). - Async support for streaming logs from mutiple processes. - Making `datacol run` independent of shell ### Added +- [CLI] Renaming command `ps scale` to `scale` +- [CLI] Renaming command `build list` to `builds` +- [API] version label into k8s deployments - Paging for `GET /v1/builds` API - [CLI] Tabular output for listing apps and builds - [CLI] `STACK` env var for `datacol env`, `datacol infra` diff --git a/api/controller/services.swagger.json b/api/controller/services.swagger.json index 10b49b6b..915f6feb 100644 --- a/api/controller/services.swagger.json +++ b/api/controller/services.swagger.json @@ -1045,6 +1045,10 @@ "created_at": { "type": "integer", "format": "int32" + }, + "version": { + "type": "string", + "format": "int64" } } }, diff --git a/api/models/types.pb.go b/api/models/types.pb.go index 4a98b8ac..544e1ed4 100644 --- a/api/models/types.pb.go +++ b/api/models/types.pb.go @@ -172,6 +172,7 @@ type Release struct { BuildId string `protobuf:"bytes,3,opt,name=build_id,json=buildId,proto3" json:"build_id,omitempty" datastore:"build_id,noindex"` Status string `protobuf:"bytes,4,opt,name=status,proto3" json:"status,omitempty" datastore:"status,noindex"` CreatedAt int32 `protobuf:"varint,5,opt,name=created_at,json=createdAt,proto3" json:"created_at,omitempty" datastore:"created_at,noindex"` + Version int64 `protobuf:"varint,6,opt,name=version,proto3" json:"version,omitempty" datastore:"version,noindex"` } func (m *Release) Reset() { *m = Release{} } @@ -214,6 +215,13 @@ func (m *Release) GetCreatedAt() int32 { return 0 } +func (m *Release) GetVersion() int64 { + if m != nil { + return m.Version + } + return 0 +} + type Resource struct { Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty" datastore:"name"` Kind string `protobuf:"bytes,2,opt,name=kind,proto3" json:"kind,omitempty" datastore:"kind"` @@ -621,6 +629,11 @@ func (m *Release) MarshalTo(dAtA []byte) (int, error) { i++ i = encodeVarintTypes(dAtA, i, uint64(m.CreatedAt)) } + if m.Version != 0 { + dAtA[i] = 0x30 + i++ + i = encodeVarintTypes(dAtA, i, uint64(m.Version)) + } return i, nil } @@ -1030,6 +1043,9 @@ func (m *Release) Size() (n int) { if m.CreatedAt != 0 { n += 1 + sovTypes(uint64(m.CreatedAt)) } + if m.Version != 0 { + n += 1 + sovTypes(uint64(m.Version)) + } return n } @@ -1853,6 +1869,25 @@ func (m *Release) Unmarshal(dAtA []byte) error { break } } + case 6: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Version", wireType) + } + m.Version = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTypes + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Version |= (int64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } default: iNdEx = preIndex skippy, err := skipTypes(dAtA[iNdEx:]) @@ -3383,65 +3418,66 @@ var ( func init() { proto.RegisterFile("types.proto", fileDescriptorTypes) } var fileDescriptorTypes = []byte{ - // 960 bytes of a gzipped FileDescriptorProto + // 967 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xc4, 0x56, 0xdd, 0x6e, 0xe3, 0x44, 0x14, 0x96, 0xeb, 0xa4, 0x6e, 0x4e, 0xbb, 0xbb, 0x65, 0xa8, 0x16, 0x2b, 0xed, 0xc6, 0x59, 0x4b, 0x2b, 0x72, 0x41, 0x13, 0x04, 0xe2, 0xaf, 0x2c, 0xa0, 0x06, 0x8a, 0xd4, 0xd5, 0x4a, 0xac, 0x0c, 0x8b, 0x10, 0x37, 0xd5, 0xd4, 0x9e, 0x06, 0xab, 0xb1, 0xc7, 0x9a, 0x19, 0x57, 0xdb, 0x17, 0xe0, - 0x8a, 0x7b, 0x84, 0x78, 0x04, 0x5e, 0x84, 0x4b, 0x9e, 0xc0, 0x42, 0x7d, 0x04, 0x3f, 0x01, 0x9a, - 0x1f, 0xc7, 0x93, 0x66, 0x57, 0x10, 0x09, 0x69, 0xef, 0x66, 0xce, 0xf9, 0xbe, 0x2f, 0xe7, 0x2f, - 0xc7, 0x03, 0xdb, 0xe2, 0xba, 0x20, 0x7c, 0x5c, 0x30, 0x2a, 0x28, 0xda, 0xcc, 0x68, 0x42, 0xe6, - 0xbc, 0x7f, 0x30, 0xa3, 0x74, 0x36, 0x27, 0x13, 0x5c, 0xa4, 0x13, 0x9c, 0xe7, 0x54, 0x60, 0x91, - 0xd2, 0xdc, 0xa0, 0xfa, 0x87, 0xb3, 0x54, 0xfc, 0x54, 0x9e, 0x8f, 0x63, 0x9a, 0x4d, 0x66, 0x74, - 0x46, 0x27, 0xca, 0x7c, 0x5e, 0x5e, 0xa8, 0x9b, 0xba, 0xa8, 0x93, 0x86, 0x87, 0xbf, 0xb9, 0xe0, - 0x1e, 0x17, 0x05, 0x1a, 0x41, 0x27, 0xc7, 0x19, 0xf1, 0x9d, 0xa1, 0x33, 0xea, 0x4d, 0xf7, 0xea, - 0x2a, 0xd8, 0x4d, 0xb0, 0xc0, 0x5c, 0x50, 0x46, 0x8e, 0x42, 0xe9, 0x0a, 0x23, 0x85, 0x40, 0x63, - 0xd8, 0xe4, 0x02, 0x8b, 0x92, 0xfb, 0x1b, 0x0a, 0x7b, 0xbf, 0xae, 0x02, 0x64, 0x61, 0xb5, 0x33, - 0x8c, 0x0c, 0x0a, 0x1d, 0x03, 0x30, 0x32, 0x27, 0x98, 0x93, 0xb3, 0x34, 0xf1, 0x5d, 0xc5, 0x09, - 0xeb, 0x2a, 0x18, 0x58, 0x9c, 0x16, 0xf0, 0x4e, 0x4e, 0xd3, 0x3c, 0x21, 0x2f, 0xc2, 0xa8, 0x67, - 0x8c, 0xa7, 0x09, 0x7a, 0x0c, 0x5b, 0x24, 0x4f, 0x0a, 0x9a, 0xe6, 0xc2, 0xef, 0x28, 0x81, 0x61, - 0x5d, 0x05, 0x07, 0x96, 0x40, 0xe3, 0x6e, 0xe9, 0x0b, 0x06, 0xfa, 0x14, 0xb6, 0xce, 0xcb, 0x74, - 0x9e, 0xc8, 0x9f, 0xef, 0xbe, 0x94, 0xdd, 0xb8, 0x5b, 0xb6, 0xa7, 0x4c, 0xa7, 0x09, 0xfa, 0x04, - 0xbc, 0x84, 0x66, 0x38, 0xcd, 0xb9, 0xbf, 0x39, 0x74, 0x47, 0xbd, 0x69, 0x50, 0x57, 0xc1, 0xbe, - 0xc5, 0x35, 0x5e, 0x8b, 0x6a, 0x2c, 0xe8, 0x0b, 0xe8, 0x31, 0xc2, 0x69, 0xc9, 0x62, 0xc2, 0x7d, - 0x4f, 0x91, 0x1f, 0xd6, 0x55, 0xf0, 0x60, 0x29, 0x6f, 0xe3, 0x5f, 0x4a, 0xdb, 0xd8, 0xc2, 0x9f, - 0x5d, 0xe8, 0x4e, 0x65, 0x1c, 0x28, 0x84, 0x8d, 0x34, 0x31, 0xbd, 0x41, 0x75, 0x15, 0xdc, 0xb5, - 0x34, 0xd2, 0x24, 0x8c, 0x36, 0xd2, 0x04, 0x3d, 0x02, 0x17, 0x17, 0x85, 0x69, 0xca, 0x9b, 0x75, - 0x15, 0xdc, 0xb3, 0x40, 0xb8, 0x28, 0xc2, 0x48, 0xfa, 0xd1, 0xe7, 0x32, 0xaa, 0x8c, 0x0a, 0xab, - 0x1b, 0xab, 0x51, 0x19, 0xbf, 0x55, 0x4d, 0x6d, 0x3b, 0x4d, 0xd0, 0x87, 0x8b, 0xf6, 0xeb, 0x4e, - 0x0c, 0xea, 0x2a, 0xe8, 0xaf, 0xb4, 0xbf, 0x65, 0x5a, 0x63, 0x10, 0x33, 0x82, 0x05, 0x49, 0xce, - 0xb0, 0x50, 0x7d, 0xe8, 0xae, 0x8c, 0x41, 0x0b, 0xb0, 0xea, 0x61, 0x8c, 0xc7, 0x42, 0x8e, 0x41, - 0xc1, 0x68, 0x7c, 0x91, 0xce, 0x89, 0xbf, 0x39, 0x74, 0x46, 0x3b, 0x2b, 0x8d, 0x6c, 0xdc, 0x56, - 0xe0, 0x8d, 0x49, 0x76, 0xf2, 0x8a, 0x30, 0x9e, 0xd2, 0xdc, 0xf7, 0x54, 0xe4, 0xb7, 0x3b, 0x69, - 0xbc, 0x56, 0x27, 0x8d, 0x25, 0xfc, 0x65, 0x03, 0xbc, 0x48, 0x4f, 0xe3, 0xff, 0xd9, 0x0a, 0x7b, - 0x30, 0xdd, 0x75, 0x07, 0xf3, 0xf5, 0xf5, 0x21, 0xfc, 0xc3, 0x83, 0xad, 0xc8, 0x4c, 0xe9, 0x1a, - 0x8b, 0x63, 0x04, 0x9d, 0xcb, 0x34, 0x4f, 0x4c, 0x59, 0x6e, 0x23, 0xa5, 0x2b, 0x8c, 0x14, 0xc2, - 0xca, 0xcd, 0x5d, 0x2b, 0xb7, 0x27, 0x70, 0x47, 0x9f, 0xce, 0x18, 0xc1, 0x9c, 0xe6, 0xa6, 0x34, - 0x8f, 0xea, 0x2a, 0x78, 0xb8, 0x42, 0x37, 0x98, 0x56, 0x65, 0x47, 0xdb, 0x23, 0x65, 0x46, 0x87, - 0xe0, 0x3e, 0x8f, 0x9e, 0x9a, 0x85, 0xb1, 0x5f, 0x57, 0xc1, 0x5b, 0x96, 0xc2, 0xf3, 0xe8, 0x69, - 0xcb, 0x93, 0x38, 0xf4, 0x36, 0x74, 0xb9, 0xc0, 0xf1, 0xa5, 0x1a, 0xcc, 0xde, 0xf4, 0x8d, 0xba, - 0x0a, 0xee, 0x58, 0x84, 0xc3, 0x30, 0xd2, 0x7e, 0xf4, 0x2e, 0x74, 0x70, 0x51, 0x34, 0x0b, 0xe1, - 0xa0, 0xae, 0x02, 0x7f, 0x79, 0x38, 0xac, 0xbc, 0x14, 0x12, 0xfd, 0x00, 0x1e, 0x79, 0x51, 0x50, - 0x26, 0xb8, 0xbf, 0x35, 0x74, 0x47, 0xdb, 0xef, 0x3d, 0x18, 0xeb, 0x2f, 0xc1, 0xb8, 0x69, 0xc2, - 0xf8, 0x44, 0xfb, 0x4f, 0x72, 0xc1, 0xae, 0x57, 0xe6, 0xda, 0x90, 0xad, 0x19, 0x32, 0x16, 0x94, - 0x00, 0x14, 0x98, 0xe1, 0x8c, 0x08, 0xc2, 0xb8, 0xdf, 0x53, 0xe2, 0xc3, 0x15, 0xf1, 0x67, 0x0b, - 0x88, 0xd6, 0xbf, 0x3d, 0x2d, 0xad, 0x44, 0xfb, 0x13, 0x96, 0x2e, 0x7a, 0x02, 0x1e, 0x2d, 0x45, - 0x51, 0x0a, 0xee, 0xc3, 0x2b, 0xe2, 0xff, 0x46, 0xfb, 0xb5, 0xfe, 0x4b, 0x6a, 0xd7, 0x08, 0xa0, - 0x63, 0xe8, 0x08, 0x3c, 0xe3, 0xfe, 0xb6, 0x12, 0xea, 0xaf, 0x08, 0x7d, 0x87, 0x67, 0xaf, 0x56, - 0x51, 0xd4, 0xfe, 0x11, 0xec, 0xd8, 0xe5, 0x42, 0xbb, 0xe0, 0x5e, 0x92, 0x6b, 0x3d, 0xbf, 0x91, - 0x3c, 0xa2, 0x3d, 0xe8, 0x5e, 0xe1, 0x79, 0x49, 0xf4, 0xa4, 0x46, 0xfa, 0x72, 0xb4, 0xf1, 0xb1, - 0xd3, 0xff, 0x0c, 0xee, 0xdd, 0xaa, 0xc6, 0x5a, 0xf4, 0x23, 0xd8, 0xb1, 0x33, 0x5d, 0x8b, 0xfb, - 0x11, 0xf4, 0x16, 0xc9, 0xad, 0x43, 0x0c, 0x3f, 0x80, 0xed, 0xa6, 0x3c, 0xdf, 0x63, 0xf6, 0x5f, - 0xa9, 0x61, 0x09, 0xbd, 0x93, 0xfc, 0xea, 0x4b, 0x9a, 0x5f, 0xa4, 0x33, 0x34, 0x81, 0x8e, 0x2c, - 0xa5, 0xef, 0xa8, 0xb2, 0xef, 0x37, 0x65, 0x5f, 0x00, 0xc6, 0x5f, 0x61, 0x81, 0x55, 0x68, 0x91, - 0x02, 0xca, 0x68, 0x17, 0xa6, 0xb5, 0xa2, 0xfd, 0xd5, 0x01, 0xef, 0x19, 0xa3, 0x31, 0xe1, 0x1c, - 0xf5, 0xf5, 0xbe, 0x97, 0x6f, 0x20, 0x43, 0x5e, 0xdc, 0xa5, 0x42, 0x4c, 0xcb, 0x5c, 0x28, 0x85, - 0x6e, 0xa4, 0x2f, 0xe8, 0xfe, 0xf2, 0xe2, 0x58, 0x2c, 0x86, 0x5d, 0x70, 0xe3, 0xa2, 0xd4, 0xeb, - 0x20, 0x92, 0x47, 0x89, 0xcc, 0x48, 0x46, 0xd9, 0xb5, 0xfe, 0x87, 0x47, 0xe6, 0x86, 0x7c, 0xf0, - 0x62, 0x9a, 0x65, 0x38, 0x4f, 0xf4, 0xf7, 0x3e, 0x6a, 0xae, 0xe1, 0xef, 0x0e, 0xf4, 0xbe, 0xa6, - 0x2c, 0x53, 0xaf, 0x2d, 0xa9, 0x28, 0x57, 0xbc, 0xc9, 0xc9, 0x7c, 0x58, 0xb9, 0x60, 0x65, 0x2c, - 0x4a, 0x26, 0xf3, 0x5a, 0xfa, 0x2f, 0x2d, 0x78, 0xe3, 0x6f, 0x1b, 0x88, 0xae, 0x56, 0x4b, 0xe9, - 0x3f, 0x86, 0xbb, 0xcb, 0xce, 0x7f, 0xab, 0x5b, 0xd7, 0xaa, 0xdb, 0x74, 0xef, 0xcf, 0x9b, 0x81, - 0xf3, 0xd7, 0xcd, 0xc0, 0xf9, 0xfb, 0x66, 0xe0, 0xfc, 0x68, 0x9e, 0x8a, 0xe7, 0x9b, 0xea, 0x91, - 0xf7, 0xfe, 0x3f, 0x01, 0x00, 0x00, 0xff, 0xff, 0xac, 0x54, 0xdb, 0xee, 0x48, 0x0a, 0x00, 0x00, + 0x15, 0x10, 0xe2, 0x11, 0x78, 0x10, 0xb8, 0xe4, 0x09, 0x2c, 0xd4, 0x47, 0xf0, 0x13, 0xa0, 0xf9, + 0x71, 0x3c, 0x69, 0x76, 0x05, 0x91, 0x90, 0xf6, 0xce, 0x73, 0xce, 0xf7, 0x7d, 0x39, 0xf3, 0x9d, + 0x93, 0x99, 0x81, 0x6d, 0x71, 0x5d, 0x10, 0x3e, 0x2e, 0x18, 0x15, 0x14, 0x6d, 0x66, 0x34, 0x21, + 0x73, 0xde, 0x3f, 0x98, 0x51, 0x3a, 0x9b, 0x93, 0x09, 0x2e, 0xd2, 0x09, 0xce, 0x73, 0x2a, 0xb0, + 0x48, 0x69, 0x6e, 0x50, 0xfd, 0xc3, 0x59, 0x2a, 0x7e, 0x2a, 0xcf, 0xc7, 0x31, 0xcd, 0x26, 0x33, + 0x3a, 0xa3, 0x13, 0x15, 0x3e, 0x2f, 0x2f, 0xd4, 0x4a, 0x2d, 0xd4, 0x97, 0x86, 0x87, 0xbf, 0xba, + 0xe0, 0x1e, 0x17, 0x05, 0x1a, 0x41, 0x27, 0xc7, 0x19, 0xf1, 0x9d, 0xa1, 0x33, 0xea, 0x4d, 0xf7, + 0xea, 0x2a, 0xd8, 0x4d, 0xb0, 0xc0, 0x5c, 0x50, 0x46, 0x8e, 0x42, 0x99, 0x0a, 0x23, 0x85, 0x40, + 0x63, 0xd8, 0xe4, 0x02, 0x8b, 0x92, 0xfb, 0x1b, 0x0a, 0x7b, 0xbf, 0xae, 0x02, 0x64, 0x61, 0x75, + 0x32, 0x8c, 0x0c, 0x0a, 0x1d, 0x03, 0x30, 0x32, 0x27, 0x98, 0x93, 0xb3, 0x34, 0xf1, 0x5d, 0xc5, + 0x09, 0xeb, 0x2a, 0x18, 0x58, 0x9c, 0x16, 0xf0, 0x4e, 0x4e, 0xd3, 0x3c, 0x21, 0x2f, 0xc2, 0xa8, + 0x67, 0x82, 0xa7, 0x09, 0x7a, 0x0c, 0x5b, 0x24, 0x4f, 0x0a, 0x9a, 0xe6, 0xc2, 0xef, 0x28, 0x81, + 0x61, 0x5d, 0x05, 0x07, 0x96, 0x40, 0x93, 0x6e, 0xe9, 0x0b, 0x06, 0xfa, 0x14, 0xb6, 0xce, 0xcb, + 0x74, 0x9e, 0xc8, 0x9f, 0xef, 0xbe, 0x94, 0xdd, 0xa4, 0x5b, 0xb6, 0xa7, 0x42, 0xa7, 0x09, 0xfa, + 0x04, 0xbc, 0x84, 0x66, 0x38, 0xcd, 0xb9, 0xbf, 0x39, 0x74, 0x47, 0xbd, 0x69, 0x50, 0x57, 0xc1, + 0xbe, 0xc5, 0x35, 0x59, 0x8b, 0x6a, 0x22, 0xe8, 0x0b, 0xe8, 0x31, 0xc2, 0x69, 0xc9, 0x62, 0xc2, + 0x7d, 0x4f, 0x91, 0x1f, 0xd6, 0x55, 0xf0, 0x60, 0x69, 0xdf, 0x26, 0xbf, 0xb4, 0x6d, 0x13, 0x0b, + 0x7f, 0x76, 0xa1, 0x3b, 0x95, 0x75, 0xa0, 0x10, 0x36, 0xd2, 0xc4, 0xf4, 0x06, 0xd5, 0x55, 0x70, + 0xd7, 0xd2, 0x48, 0x93, 0x30, 0xda, 0x48, 0x13, 0xf4, 0x08, 0x5c, 0x5c, 0x14, 0xa6, 0x29, 0x6f, + 0xd6, 0x55, 0x70, 0xcf, 0x02, 0xe1, 0xa2, 0x08, 0x23, 0x99, 0x47, 0x9f, 0xcb, 0xaa, 0x32, 0x2a, + 0xac, 0x6e, 0xac, 0x56, 0x65, 0xf2, 0x96, 0x9b, 0x3a, 0x76, 0x9a, 0xa0, 0x0f, 0x17, 0xed, 0xd7, + 0x9d, 0x18, 0xd4, 0x55, 0xd0, 0x5f, 0x69, 0x7f, 0xcb, 0xb4, 0xc6, 0x20, 0x66, 0x04, 0x0b, 0x92, + 0x9c, 0x61, 0xa1, 0xfa, 0xd0, 0x5d, 0x19, 0x83, 0x16, 0x60, 0xf9, 0x61, 0x82, 0xc7, 0x42, 0x8e, + 0x41, 0xc1, 0x68, 0x7c, 0x91, 0xce, 0x89, 0xbf, 0x39, 0x74, 0x46, 0x3b, 0x2b, 0x8d, 0x6c, 0xd2, + 0x56, 0xe1, 0x4d, 0x48, 0x76, 0xf2, 0x8a, 0x30, 0x9e, 0xd2, 0xdc, 0xf7, 0x54, 0xe5, 0xb7, 0x3b, + 0x69, 0xb2, 0x56, 0x27, 0x4d, 0x24, 0xfc, 0x63, 0x03, 0xbc, 0x48, 0x4f, 0xe3, 0xff, 0xd9, 0x0a, + 0x7b, 0x30, 0xdd, 0x75, 0x07, 0xf3, 0x35, 0xf6, 0xc1, 0x72, 0x52, 0xb6, 0xc1, 0x5d, 0xc3, 0xc9, + 0xdf, 0x3d, 0xd8, 0x8a, 0xcc, 0x80, 0xaf, 0x71, 0xe6, 0x8c, 0xa0, 0x73, 0x99, 0xe6, 0x89, 0x71, + 0xf4, 0x36, 0x52, 0xa6, 0xc2, 0x48, 0x21, 0x2c, 0x5b, 0xdc, 0xb5, 0x6c, 0x79, 0x02, 0x77, 0xf4, + 0xd7, 0x19, 0x23, 0x98, 0xd3, 0xdc, 0xb8, 0xfa, 0xa8, 0xae, 0x82, 0x87, 0x2b, 0x74, 0x83, 0x69, + 0x55, 0x76, 0x74, 0x3c, 0x52, 0x61, 0x74, 0x08, 0xee, 0xf3, 0xe8, 0xa9, 0x39, 0x6b, 0xf6, 0xeb, + 0x2a, 0x78, 0xcb, 0x52, 0x78, 0x1e, 0x3d, 0x6d, 0x79, 0x12, 0x87, 0xde, 0x86, 0x2e, 0x17, 0x38, + 0xbe, 0x54, 0x66, 0xf6, 0xa6, 0x6f, 0xd4, 0x55, 0x70, 0xc7, 0x22, 0x1c, 0x86, 0x91, 0xce, 0xa3, + 0x77, 0xa1, 0x83, 0x8b, 0xa2, 0x39, 0x4b, 0x0e, 0xea, 0x2a, 0xf0, 0x97, 0xe7, 0xca, 0xda, 0x97, + 0x42, 0xa2, 0x1f, 0xc0, 0x23, 0x2f, 0x0a, 0xca, 0x04, 0xf7, 0xb7, 0x86, 0xee, 0x68, 0xfb, 0xbd, + 0x07, 0x63, 0x7d, 0x89, 0x8c, 0x9b, 0x26, 0x8c, 0x4f, 0x74, 0xfe, 0x24, 0x17, 0xec, 0x7a, 0xa5, + 0x91, 0x86, 0x6c, 0x35, 0xd2, 0x44, 0x50, 0x02, 0x50, 0x60, 0x86, 0x33, 0x22, 0x08, 0xe3, 0x7e, + 0x4f, 0x89, 0x0f, 0x57, 0xc4, 0x9f, 0x2d, 0x20, 0x5a, 0xff, 0xf6, 0xa0, 0xb5, 0x12, 0xed, 0x4f, + 0x58, 0xba, 0xe8, 0x09, 0x78, 0xb4, 0x14, 0x45, 0x29, 0xb8, 0x0f, 0xaf, 0xa8, 0xff, 0x1b, 0x9d, + 0xd7, 0xfa, 0x2f, 0xf1, 0xae, 0x11, 0x40, 0xc7, 0xd0, 0x11, 0x78, 0xc6, 0xfd, 0x6d, 0x25, 0xd4, + 0x5f, 0x11, 0xfa, 0x0e, 0xcf, 0x5e, 0xad, 0xa2, 0xa8, 0xfd, 0x23, 0xd8, 0xb1, 0xed, 0x42, 0xbb, + 0xe0, 0x5e, 0x92, 0x6b, 0x3d, 0xbf, 0x91, 0xfc, 0x44, 0x7b, 0xd0, 0xbd, 0xc2, 0xf3, 0x92, 0xe8, + 0x49, 0x8d, 0xf4, 0xe2, 0x68, 0xe3, 0x63, 0xa7, 0xff, 0x19, 0xdc, 0xbb, 0xe5, 0xc6, 0x5a, 0xf4, + 0x23, 0xd8, 0xb1, 0x77, 0xba, 0x16, 0xf7, 0x23, 0xe8, 0x2d, 0x36, 0xb7, 0x0e, 0x31, 0xfc, 0x00, + 0xb6, 0x1b, 0x7b, 0xbe, 0xc7, 0xec, 0xbf, 0x52, 0xc3, 0x12, 0x7a, 0x27, 0xf9, 0xd5, 0x97, 0x34, + 0xbf, 0x48, 0x67, 0x68, 0x02, 0x1d, 0x69, 0xa5, 0xef, 0x28, 0xdb, 0xf7, 0x1b, 0xdb, 0x17, 0x80, + 0xf1, 0x57, 0x58, 0x60, 0x55, 0x5a, 0xa4, 0x80, 0xb2, 0xda, 0x45, 0x68, 0xad, 0x6a, 0x7f, 0x71, + 0xc0, 0x7b, 0xc6, 0x68, 0x4c, 0x38, 0x47, 0x7d, 0x7d, 0x55, 0xc8, 0xe7, 0x93, 0x21, 0x2f, 0xd6, + 0x52, 0x21, 0xa6, 0x65, 0x2e, 0x94, 0x42, 0x37, 0xd2, 0x0b, 0x74, 0x7f, 0xf9, 0xe0, 0x58, 0x1c, + 0x0c, 0xbb, 0xe0, 0xc6, 0x45, 0xa9, 0x8f, 0x83, 0x48, 0x7e, 0x4a, 0x64, 0x46, 0x32, 0xca, 0xae, + 0xf5, 0x3f, 0x3c, 0x32, 0x2b, 0xe4, 0x83, 0x17, 0xd3, 0x2c, 0xc3, 0x79, 0xa2, 0x9f, 0x0a, 0x51, + 0xb3, 0x0c, 0x7f, 0x73, 0xa0, 0xf7, 0x35, 0x65, 0x99, 0x7a, 0xa8, 0x49, 0x45, 0x79, 0x3b, 0x98, + 0x3d, 0x99, 0x3b, 0x99, 0x0b, 0x56, 0xc6, 0xa2, 0x64, 0x72, 0x5f, 0x4b, 0xff, 0xa5, 0x05, 0x6f, + 0xfc, 0x6d, 0x03, 0xd1, 0x6e, 0xb5, 0x94, 0xfe, 0x63, 0xb8, 0xbb, 0x9c, 0xfc, 0x37, 0xdf, 0xba, + 0x96, 0x6f, 0xd3, 0xbd, 0x3f, 0x6f, 0x06, 0xce, 0x5f, 0x37, 0x03, 0xe7, 0xef, 0x9b, 0x81, 0xf3, + 0xa3, 0x79, 0x65, 0x9e, 0x6f, 0xaa, 0xf7, 0xe1, 0xfb, 0xff, 0x04, 0x00, 0x00, 0xff, 0xff, 0x1c, + 0x7b, 0xad, 0x60, 0x83, 0x0a, 0x00, 0x00, } diff --git a/api/models/types.proto b/api/models/types.proto index fe0c685d..84bf8c51 100644 --- a/api/models/types.proto +++ b/api/models/types.proto @@ -35,6 +35,7 @@ message Release { string build_id = 3 [(gogoproto.moretags) = "datastore:\"build_id,noindex\""]; string status = 4 [(gogoproto.moretags) = "datastore:\"status,noindex\""]; int32 created_at = 5 [(gogoproto.moretags) = "datastore:\"created_at,noindex\""]; + int64 version = 6 [(gogoproto.moretags) = "datastore:\"version,noindex\""]; } message Resource { diff --git a/cloud/aws/provider.go b/cloud/aws/provider.go index 3eae68eb..c62bdea1 100644 --- a/cloud/aws/provider.go +++ b/cloud/aws/provider.go @@ -2,6 +2,7 @@ package aws import ( "fmt" + "sync" "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/session" @@ -17,6 +18,8 @@ type AwsCloud struct { DeploymentName string Region, SettingBucket string Access, Secret, Token string + + lock sync.Mutex } func (p *AwsCloud) config() *aws.Config { diff --git a/cloud/aws/releases.go b/cloud/aws/releases.go index 299dc90b..36a97153 100644 --- a/cloud/aws/releases.go +++ b/cloud/aws/releases.go @@ -47,6 +47,29 @@ func (a *AwsCloud) ReleaseDelete(app, id string) error { return nil } +func (a *AwsCloud) releaseCount(app string) (version int64) { + a.lock.Lock() + defer a.lock.Unlock() + + queryInput := &dynamodb.ScanInput{ + TableName: aws.String(a.dynamoReleases()), + Select: aws.String("COUNT"), + ExpressionAttributeValues: map[string]*dynamodb.AttributeValue{ + ":app": {S: aws.String(app)}, + }, + FilterExpression: aws.String("app=:app"), + } + + res, err := a.dynamodb().Scan(queryInput) + if err != nil { + log.Warnf("Fetching release count: %v", err) + } else { + version = *res.ScannedCount + } + + return version +} + func (a *AwsCloud) BuildRelease(b *pb.Build, options pb.ReleaseOptions) (*pb.Release, error) { image := fmt.Sprintf("%s.dkr.ecr.%s.amazonaws.com/%s:%s", os.Getenv("AWS_ACCOUNT_ID"), a.Region, a.ecrRepository(b.App), b.Id, @@ -69,6 +92,7 @@ func (a *AwsCloud) BuildRelease(b *pb.Build, options pb.ReleaseOptions) (*pb.Rel BuildId: b.Id, Status: pb.StatusCreated, CreatedAt: timestampNow(), + Version: a.releaseCount(b.App) + 1, } if err = a.releaseSave(r); err != nil { @@ -86,10 +110,12 @@ func (a *AwsCloud) BuildRelease(b *pb.Build, options pb.ReleaseOptions) (*pb.Rel app.BuildId = b.Id app.ReleaseId = r.Id + rversion := fmt.Sprintf("%d", r.Version) log.Debugf("Saving app state: %s err:%v", toJson(app), a.saveApp(app)) // note the mutate function - if err := common.UpdateApp(a.kubeClient(), b, a.DeploymentName, image, false, domains, envVars, cloud.AwsProvider); err != nil { + if err := common.UpdateApp(a.kubeClient(), b, a.DeploymentName, + image, false, domains, envVars, cloud.AwsProvider, rversion); err != nil { return nil, err } diff --git a/cloud/common/apps.go b/cloud/common/apps.go index 49ad643f..db6fb828 100644 --- a/cloud/common/apps.go +++ b/cloud/common/apps.go @@ -13,7 +13,9 @@ import ( func UpdateApp(c *kubernetes.Clientset, build *pb.Build, ns, image string, sqlProxy bool, - domains []string, envVars map[string]string, provider cloud.CloudProvider) error { + domains []string, envVars map[string]string, + provider cloud.CloudProvider, + version string) error { deployer, err := kube.NewDeployer(c) if err != nil { @@ -73,6 +75,7 @@ func UpdateApp(c *kubernetes.Clientset, build *pb.Build, Provider: provider, ServiceID: GetJobID(build.App, proctype), EnableCloudSqlProxy: sqlProxy, + Version: version, } if proctype == WebProcessKind || proctype == CmdProcessKind { @@ -84,5 +87,6 @@ func UpdateApp(c *kubernetes.Clientset, build *pb.Build, } } + // TODO: cleanup old resource based on req.Version return nil } diff --git a/cloud/google/builder.go b/cloud/google/builder.go index 6e16f2a0..52608bed 100644 --- a/cloud/google/builder.go +++ b/cloud/google/builder.go @@ -15,9 +15,6 @@ import ( "cloud.google.com/go/datastore" log "github.com/Sirupsen/logrus" pb "github.com/datacol-io/datacol/api/models" - "github.com/datacol-io/datacol/cloud" - "github.com/datacol-io/datacol/cloud/common" - sched "github.com/datacol-io/datacol/cloud/kube" "google.golang.org/api/cloudbuild/v1" "google.golang.org/api/googleapi" "google.golang.org/api/storage/v1" @@ -69,20 +66,6 @@ func (g *GCPCloud) BuildList(app string, limit int) (pb.Builds, error) { return builds, err } -func (g *GCPCloud) ReleaseList(app string, limit int) (pb.Releases, error) { - q := datastore.NewQuery(releaseKind).Namespace(g.DeploymentName).Filter("app = ", app).Limit(limit) - - var rs pb.Releases - _, err := g.datastore().GetAll(context.Background(), q, &rs) - - return rs, err -} - -func (g *GCPCloud) ReleaseDelete(app, id string) error { - ctx, key := g.nestedKey(buildKind, id) - return g.datastore().Delete(ctx, key) -} - func (g *GCPCloud) BuildCreate(app string, req *pb.CreateBuildOptions) (*pb.Build, error) { id := generateId("B", 5) @@ -198,58 +181,6 @@ func (g *GCPCloud) BuildLogsStream(id string) (io.Reader, error) { return nil, fmt.Errorf("Not supported on GCP.") } -func (g *GCPCloud) BuildRelease(b *pb.Build, options pb.ReleaseOptions) (*pb.Release, error) { - image := fmt.Sprintf("gcr.io/%v/%v:%v", g.Project, b.App, b.Id) - log.Debugf("---- Docker Image: %s", image) - - envVars, err := g.EnvironmentGet(b.App) - if err != nil { - return nil, err - } - - app, err := g.AppGet(b.App) - if err != nil { - return nil, err - } - - domains := app.Domains - for _, domain := range strings.Split(options.Domain, ",") { - domains = sched.MergeAppDomains(domains, domain) - } - - if err := common.UpdateApp(g.kubeClient(), b, g.DeploymentName, image, g.appLinkedDB(app), domains, envVars, cloud.GCPProvider); err != nil { - return nil, err - } - - if len(app.Domains) != len(domains) { - app.Domains = domains - - if err = g.saveApp(app); err != nil { - log.Warnf("datastore put failed: %v", err) - } - } - - r := &pb.Release{ - Id: generateId("R", 5), - App: b.App, - BuildId: b.Id, - Status: pb.StatusCreated, - CreatedAt: timestampNow(), - } - - ctx, key := g.nestedKey(releaseKind, r.Id) - _, err = g.datastore().Put(ctx, key, r) - - if err != nil { - return r, err - } - - app.ReleaseId = r.Id - app.BuildId = b.Id - - return r, g.saveApp(app) -} - func getBuildID(op *cloudbuild.Operation) (string, error) { if len(op.Metadata) == 0 { return "", fmt.Errorf("missing Metadata in operation") diff --git a/cloud/google/releases.go b/cloud/google/releases.go new file mode 100644 index 00000000..11c18de2 --- /dev/null +++ b/cloud/google/releases.go @@ -0,0 +1,99 @@ +package google + +import ( + "context" + "fmt" + "strings" + + "cloud.google.com/go/datastore" + log "github.com/Sirupsen/logrus" + pb "github.com/datacol-io/datacol/api/models" + "github.com/datacol-io/datacol/cloud" + "github.com/datacol-io/datacol/cloud/common" + sched "github.com/datacol-io/datacol/cloud/kube" +) + +func (g *GCPCloud) ReleaseList(app string, limit int) (pb.Releases, error) { + q := datastore.NewQuery(releaseKind).Namespace(g.DeploymentName).Filter("app = ", app).Limit(limit) + + var rs pb.Releases + _, err := g.datastore().GetAll(context.Background(), q, &rs) + + return rs, err +} + +func (g *GCPCloud) ReleaseDelete(app, id string) error { + ctx, key := g.nestedKey(buildKind, id) + return g.datastore().Delete(ctx, key) +} + +func (g *GCPCloud) BuildRelease(b *pb.Build, options pb.ReleaseOptions) (*pb.Release, error) { + image := fmt.Sprintf("gcr.io/%v/%v:%v", g.Project, b.App, b.Id) + log.Debugf("---- Docker Image: %s", image) + + envVars, err := g.EnvironmentGet(b.App) + if err != nil { + return nil, err + } + + app, err := g.AppGet(b.App) + if err != nil { + return nil, err + } + + domains := app.Domains + for _, domain := range strings.Split(options.Domain, ",") { + domains = sched.MergeAppDomains(domains, domain) + } + + r := &pb.Release{ + Id: generateId("R", 5), + App: b.App, + BuildId: b.Id, + Status: pb.StatusCreated, + CreatedAt: timestampNow(), + Version: g.releaseCount(b.App) + 1, + } + + rversion := fmt.Sprintf("%d", r.Version) + + if err := common.UpdateApp(g.kubeClient(), b, g.DeploymentName, image, g.appLinkedDB(app), + domains, envVars, cloud.GCPProvider, rversion); err != nil { + return nil, err + } + + if len(app.Domains) != len(domains) { + app.Domains = domains + + if err = g.saveApp(app); err != nil { + log.Warnf("datastore put failed: %v", err) + } + } + + ctx, key := g.nestedKey(releaseKind, r.Id) + _, err = g.datastore().Put(ctx, key, r) + + if err != nil { + return r, err + } + + app.ReleaseId = r.Id + app.BuildId = b.Id + + return r, g.saveApp(app) +} + +func (g *GCPCloud) releaseCount(app string) (version int64) { + q := datastore.NewQuery(releaseKind). + Namespace(g.DeploymentName). + Filter("app = ", app) + + total, err := g.datastore().Count(context.Background(), q) + if err != nil { + log.Warnf("fetching release total: %v", err) + } + + version = int64(total) + + return +} diff --git a/cloud/kube/deployer.go b/cloud/kube/deployer.go index dd4c76d5..f38ae46a 100644 --- a/cloud/kube/deployer.go +++ b/cloud/kube/deployer.go @@ -21,6 +21,7 @@ const ( heritage string = "datacol" appLabel string = "app" typeLabel string = "type" + versionLabel string = "version" runProcessKind string = "run" ) @@ -230,8 +231,7 @@ func (r *Deployer) CreateOrUpdateDeployment(payload *DeployRequest) (*v1beta1.De if err == nil { found = true - i, _ := findContainer(d, payload.ServiceID) - if i >= 0 { + if i, _ := findContainer(d, payload.ServiceID); i >= 0 { d.Spec.Template.Spec.Containers[i] = newContainer(payload) //TODO: we are only updating containers schema for existing deployment. Add support for updating any any schema change //Below is one workaround of it. diff --git a/cloud/kube/deployment.go b/cloud/kube/deployment.go index e8f11b6e..7745a2a5 100644 --- a/cloud/kube/deployment.go +++ b/cloud/kube/deployment.go @@ -55,9 +55,8 @@ func newPodMetadata(req *DeployRequest) metav1.ObjectMeta { return metav1.ObjectMeta{ Annotations: req.Tags, Labels: map[string]string{ - "app": req.App, - "version": req.Version, - "type": req.Proctype, + appLabel: req.App, + typeLabel: req.Proctype, managedBy: heritage, }, Name: req.ServiceID, diff --git a/cloud/kube/pod.go b/cloud/kube/pod.go index 7e38161d..35b0b74f 100644 --- a/cloud/kube/pod.go +++ b/cloud/kube/pod.go @@ -116,8 +116,7 @@ func getPodsForDeployment(c *kubernetes.Clientset, dp *v1beta1.Deployment) ([]v1 func getLatestPodsForDeployment(c *kubernetes.Clientset, dp *v1beta1.Deployment) ([]v1.Pod, error) { selector := klabels.Set(dp.Spec.Selector.MatchLabels).AsSelector() res, err := c.Core().Pods(dp.Namespace).List(metav1.ListOptions{ - LabelSelector: selector.String(), - ResourceVersion: dp.ResourceVersion, + LabelSelector: selector.String(), }) if err != nil { @@ -153,7 +152,6 @@ func podEvents(c *kubernetes.Clientset, pod *v1.Pod) (*v1.EventList, error) { res, err := c.Core().Events(pod.Namespace).List(metav1.ListOptions{ FieldSelector: klabels.Set(fields).AsSelector().String(), - // ResourceVersion: pod.ObjectMeta.ResourceVersion, }) if err != nil { return res, err diff --git a/cloud/local/build.go b/cloud/local/build.go index 3492099c..951b2761 100644 --- a/cloud/local/build.go +++ b/cloud/local/build.go @@ -119,15 +119,17 @@ func (g *LocalCloud) BuildRelease(b *pb.Build, options pb.ReleaseOptions) (*pb.R return nil, err } - if err := common.UpdateApp(g.kubeClient(), b, g.Name, image, false, []string{}, envVars, cloud.LocalProvider); err != nil { - return nil, err - } - r := &pb.Release{ Id: common.GenerateId("R", 5), App: b.App, BuildId: b.Id, Status: pb.StatusCreated, + Version: int64(len(g.Releases) + 1), + } + + if err := common.UpdateApp(g.kubeClient(), b, g.Name, image, false, + []string{}, envVars, cloud.LocalProvider, fmt.Sprintf("%d", r.Version)); err != nil { + return nil, err } g.Releases = append(g.Releases, r) diff --git a/cmd/build.go b/cmd/build.go index 5747f3dd..5ccf4f45 100644 --- a/cmd/build.go +++ b/cmd/build.go @@ -10,6 +10,7 @@ import ( "time" log "github.com/Sirupsen/logrus" + term "github.com/appscode/go/term" pbs "github.com/datacol-io/datacol/api/controller" pb "github.com/datacol-io/datacol/api/models" "github.com/datacol-io/datacol/client" @@ -27,7 +28,7 @@ import ( func init() { stdcli.AddCommand(cli.Command{ Name: "build", - Usage: "build an app from Dockerfile or app.yaml (App-Engine)", + Usage: "build an app from Dockerfile", Action: cmdBuild, Flags: []cli.Flag{ &cli.StringFlag{ @@ -35,23 +36,25 @@ func init() { Usage: "branch or commit Id of git repository", }, }, - Subcommands: []cli.Command{ - { - Name: "list", - Usage: "get builds for an app", - Action: cmdBuildList, - Flags: []cli.Flag{ - &cli.IntFlag{ - Name: "limit, n", - Usage: "Limit the number of recent builds to fetch", - Value: 5, - }, - }, + }) + + stdcli.AddCommand(cli.Command{ + Name: "builds", + Usage: "manage the builds for an app", + Action: cmdBuildList, + Flags: []cli.Flag{ + &cli.IntFlag{ + Name: "limit, n", + Usage: "Limit the number of recent builds to fetch", + Value: 5, }, + }, + Subcommands: []cli.Command{ { - Name: "delete", - Usage: "delete a build", - Action: cmdBuildDelete, + Name: "delete", + Usage: "delete a build", + ArgsUsage: "", + Action: cmdBuildDelete, }, }, }) @@ -87,12 +90,11 @@ func cmdBuildDelete(c *cli.Context) error { defer close() if c.NArg() == 0 { - stdcli.ExitOnError(fmt.Errorf("Please provide id of the build")) + term.Warningln("No build Id provided") + stdcli.Usage(c) } - bid := c.Args().First() - - stdcli.ExitOnError(api.DeleteBuild(name, bid)) + stdcli.ExitOnError(api.DeleteBuild(name, c.Args().First())) fmt.Println("DONE") return nil diff --git a/cmd/ps.go b/cmd/ps.go index 33540f43..32d31407 100644 --- a/cmd/ps.go +++ b/cmd/ps.go @@ -19,11 +19,6 @@ func init() { Action: cmdAppPS, Flags: []cli.Flag{&appFlag}, Subcommands: []cli.Command{ - { - Name: "scale", - Usage: "scale the process", - Action: cmdAppScale, - }, { Name: "start", Usage: "start a process", @@ -36,6 +31,14 @@ func init() { }, }, }) + + stdcli.AddCommand(cli.Command{ + Name: "scale", + Usage: "scale processes in an app", + Action: cmdAppScale, + ArgsUsage: ": ...", + Flags: []cli.Flag{&appFlag}, + }) } func cmdAppPS(c *cli.Context) error { From 705f0834bc308b575b78f94404043c09ef3c6741 Mon Sep 17 00:00:00 2001 From: dinesh Date: Thu, 19 Apr 2018 15:16:38 +0530 Subject: [PATCH 09/13] Refactoring kube and common packages --- cloud/aws/apps.go | 4 ++-- cloud/aws/environment.go | 2 +- cloud/aws/logs.go | 2 +- cloud/aws/process.go | 4 ++-- cloud/aws/releases.go | 9 +++++++-- cloud/google/apps.go | 4 ++-- cloud/google/cloudsql.go | 2 +- cloud/google/environment.go | 2 +- cloud/google/logs.go | 2 +- cloud/google/process.go | 4 ++-- cloud/google/releases.go | 4 ++-- cloud/local/apps.go | 4 ++-- cloud/local/build.go | 2 +- cloud/local/deploy.go | 4 ++-- {cloud/common => common}/apps.go | 2 +- {cloud/common => common}/procfile.go | 0 {cloud/common => common}/procfile_test.go | 0 {cloud/common => common}/util.go | 2 +- {cloud/kube => k8s}/common.go | 0 {cloud/kube => k8s}/deployer.go | 0 {cloud/kube => k8s}/deployment.go | 0 {cloud/kube => k8s}/helper.go | 0 {cloud/kube => k8s}/helper_test.go | 0 {cloud/kube => k8s}/ingress.go | 0 {cloud/kube => k8s}/logs.go | 0 {cloud/kube => k8s}/pod.go | 0 {cloud/kube => k8s}/process.go | 0 27 files changed, 29 insertions(+), 24 deletions(-) rename {cloud/common => common}/apps.go (97%) rename {cloud/common => common}/procfile.go (100%) rename {cloud/common => common}/procfile_test.go (100%) rename {cloud/common => common}/util.go (98%) rename {cloud/kube => k8s}/common.go (100%) rename {cloud/kube => k8s}/deployer.go (100%) rename {cloud/kube => k8s}/deployment.go (100%) rename {cloud/kube => k8s}/helper.go (100%) rename {cloud/kube => k8s}/helper_test.go (100%) rename {cloud/kube => k8s}/ingress.go (100%) rename {cloud/kube => k8s}/logs.go (100%) rename {cloud/kube => k8s}/pod.go (100%) rename {cloud/kube => k8s}/process.go (100%) diff --git a/cloud/aws/apps.go b/cloud/aws/apps.go index de5f7f50..fa1ce436 100644 --- a/cloud/aws/apps.go +++ b/cloud/aws/apps.go @@ -12,8 +12,8 @@ import ( log "github.com/Sirupsen/logrus" pb "github.com/datacol-io/datacol/api/models" "github.com/datacol-io/datacol/cloud" - "github.com/datacol-io/datacol/cloud/common" - sched "github.com/datacol-io/datacol/cloud/kube" + "github.com/datacol-io/datacol/common" + sched "github.com/datacol-io/datacol/k8s" ) func (a *AwsCloud) AppList() (pb.Apps, error) { diff --git a/cloud/aws/environment.go b/cloud/aws/environment.go index f606008c..b11e6b98 100644 --- a/cloud/aws/environment.go +++ b/cloud/aws/environment.go @@ -11,7 +11,7 @@ import ( "github.com/aws/aws-sdk-go/aws/awserr" "github.com/aws/aws-sdk-go/service/s3" pb "github.com/datacol-io/datacol/api/models" - "github.com/datacol-io/datacol/cloud/common" + "github.com/datacol-io/datacol/common" ) func (a *AwsCloud) s3KeyForEnv(name string) string { diff --git a/cloud/aws/logs.go b/cloud/aws/logs.go index 178ef4ec..f8df120c 100644 --- a/cloud/aws/logs.go +++ b/cloud/aws/logs.go @@ -4,7 +4,7 @@ import ( "io" pb "github.com/datacol-io/datacol/api/models" - sched "github.com/datacol-io/datacol/cloud/kube" + sched "github.com/datacol-io/datacol/k8s" ) func (a *AwsCloud) LogStream(app string, w io.Writer, opts pb.LogStreamOptions) error { diff --git a/cloud/aws/process.go b/cloud/aws/process.go index 8d4fd141..aad07f0f 100644 --- a/cloud/aws/process.go +++ b/cloud/aws/process.go @@ -7,8 +7,8 @@ import ( pb "github.com/datacol-io/datacol/api/models" "github.com/datacol-io/datacol/cloud" - "github.com/datacol-io/datacol/cloud/common" - "github.com/datacol-io/datacol/cloud/kube" + "github.com/datacol-io/datacol/common" + kube "github.com/datacol-io/datacol/k8s" ) func (p *AwsCloud) ProcessList(app string) ([]*pb.Process, error) { diff --git a/cloud/aws/releases.go b/cloud/aws/releases.go index 36a97153..63acc8da 100644 --- a/cloud/aws/releases.go +++ b/cloud/aws/releases.go @@ -11,8 +11,8 @@ import ( "github.com/aws/aws-sdk-go/service/dynamodb" pb "github.com/datacol-io/datacol/api/models" "github.com/datacol-io/datacol/cloud" - "github.com/datacol-io/datacol/cloud/common" - "github.com/datacol-io/datacol/cloud/kube" + "github.com/datacol-io/datacol/common" + kube "github.com/datacol-io/datacol/k8s" ) func (a *AwsCloud) dynamoReleases() string { @@ -139,6 +139,10 @@ func (a *AwsCloud) releaseSave(r *pb.Release) error { req.Item["status"] = &dynamodb.AttributeValue{S: aws.String(r.Status)} } + if r.Version > 0 { + req.Item["version"] = &dynamodb.AttributeValue{N: aws.String(fmt.Sprintf("%d", r.Version))} + } + _, err := a.dynamodb().PutItem(req) return err } @@ -150,6 +154,7 @@ func (a *AwsCloud) releaseFromItem(item map[string]*dynamodb.AttributeValue) *pb BuildId: coalesce(item["build_id"], ""), Status: coalesce(item["status"], ""), CreatedAt: int32(coalesceInt(item["created_at"], 0)), + Version: int64(coalesceInt(item["version"], 0)), } } diff --git a/cloud/google/apps.go b/cloud/google/apps.go index 787f59b1..58b047a5 100644 --- a/cloud/google/apps.go +++ b/cloud/google/apps.go @@ -9,8 +9,8 @@ import ( log "github.com/Sirupsen/logrus" pb "github.com/datacol-io/datacol/api/models" "github.com/datacol-io/datacol/cloud" - "github.com/datacol-io/datacol/cloud/common" - sched "github.com/datacol-io/datacol/cloud/kube" + "github.com/datacol-io/datacol/common" + sched "github.com/datacol-io/datacol/k8s" ) const appKind = "App" diff --git a/cloud/google/cloudsql.go b/cloud/google/cloudsql.go index dba86ed8..a5f0bc71 100644 --- a/cloud/google/cloudsql.go +++ b/cloud/google/cloudsql.go @@ -4,7 +4,7 @@ import ( "fmt" "github.com/datacol-io/datacol/cloud" - "github.com/datacol-io/datacol/cloud/kube" + kube "github.com/datacol-io/datacol/k8s" "k8s.io/api/core/v1" kerrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" diff --git a/cloud/google/environment.go b/cloud/google/environment.go index db1a4bd0..ae31ce0f 100644 --- a/cloud/google/environment.go +++ b/cloud/google/environment.go @@ -5,7 +5,7 @@ import ( "io" pb "github.com/datacol-io/datacol/api/models" - "github.com/datacol-io/datacol/cloud/common" + "github.com/datacol-io/datacol/common" "google.golang.org/api/googleapi" ) diff --git a/cloud/google/logs.go b/cloud/google/logs.go index 32eab010..d226f644 100644 --- a/cloud/google/logs.go +++ b/cloud/google/logs.go @@ -4,7 +4,7 @@ import ( "io" pb "github.com/datacol-io/datacol/api/models" - sched "github.com/datacol-io/datacol/cloud/kube" + sched "github.com/datacol-io/datacol/k8s" ) func (g *GCPCloud) LogStream(app string, w io.Writer, opts pb.LogStreamOptions) error { diff --git a/cloud/google/process.go b/cloud/google/process.go index 545c1767..51fe230c 100644 --- a/cloud/google/process.go +++ b/cloud/google/process.go @@ -6,8 +6,8 @@ import ( pb "github.com/datacol-io/datacol/api/models" "github.com/datacol-io/datacol/cloud" - "github.com/datacol-io/datacol/cloud/common" - "github.com/datacol-io/datacol/cloud/kube" + "github.com/datacol-io/datacol/common" + kube "github.com/datacol-io/datacol/k8s" ) func (g *GCPCloud) ProcessRun(name string, stream io.ReadWriter, command []string) error { diff --git a/cloud/google/releases.go b/cloud/google/releases.go index 11c18de2..9ece11ee 100644 --- a/cloud/google/releases.go +++ b/cloud/google/releases.go @@ -9,8 +9,8 @@ import ( log "github.com/Sirupsen/logrus" pb "github.com/datacol-io/datacol/api/models" "github.com/datacol-io/datacol/cloud" - "github.com/datacol-io/datacol/cloud/common" - sched "github.com/datacol-io/datacol/cloud/kube" + "github.com/datacol-io/datacol/common" + sched "github.com/datacol-io/datacol/k8s" ) func (g *GCPCloud) ReleaseList(app string, limit int) (pb.Releases, error) { diff --git a/cloud/local/apps.go b/cloud/local/apps.go index 68e8a545..a078aefb 100644 --- a/cloud/local/apps.go +++ b/cloud/local/apps.go @@ -9,8 +9,8 @@ import ( "github.com/appscode/go/log" pb "github.com/datacol-io/datacol/api/models" "github.com/datacol-io/datacol/cloud" - "github.com/datacol-io/datacol/cloud/common" - sched "github.com/datacol-io/datacol/cloud/kube" + "github.com/datacol-io/datacol/common" + sched "github.com/datacol-io/datacol/k8s" ) func (l *LocalCloud) AppList() (pb.Apps, error) { diff --git a/cloud/local/build.go b/cloud/local/build.go index 951b2761..ab6e35bd 100644 --- a/cloud/local/build.go +++ b/cloud/local/build.go @@ -10,7 +10,7 @@ import ( "github.com/appscode/go/crypto/rand" pb "github.com/datacol-io/datacol/api/models" "github.com/datacol-io/datacol/cloud" - "github.com/datacol-io/datacol/cloud/common" + "github.com/datacol-io/datacol/common" docker "github.com/fsouza/go-dockerclient" ) diff --git a/cloud/local/deploy.go b/cloud/local/deploy.go index 1434eee5..eed27bde 100644 --- a/cloud/local/deploy.go +++ b/cloud/local/deploy.go @@ -7,8 +7,8 @@ import ( pb "github.com/datacol-io/datacol/api/models" "github.com/datacol-io/datacol/cloud" - "github.com/datacol-io/datacol/cloud/common" - sched "github.com/datacol-io/datacol/cloud/kube" + "github.com/datacol-io/datacol/common" + sched "github.com/datacol-io/datacol/k8s" ) func (g *LocalCloud) K8sConfigPath() (string, error) { diff --git a/cloud/common/apps.go b/common/apps.go similarity index 97% rename from cloud/common/apps.go rename to common/apps.go index db6fb828..46a5b40c 100644 --- a/cloud/common/apps.go +++ b/common/apps.go @@ -6,7 +6,7 @@ import ( log "github.com/Sirupsen/logrus" pb "github.com/datacol-io/datacol/api/models" "github.com/datacol-io/datacol/cloud" - "github.com/datacol-io/datacol/cloud/kube" + kube "github.com/datacol-io/datacol/k8s" "k8s.io/apimachinery/pkg/util/intstr" "k8s.io/client-go/kubernetes" ) diff --git a/cloud/common/procfile.go b/common/procfile.go similarity index 100% rename from cloud/common/procfile.go rename to common/procfile.go diff --git a/cloud/common/procfile_test.go b/common/procfile_test.go similarity index 100% rename from cloud/common/procfile_test.go rename to common/procfile_test.go diff --git a/cloud/common/util.go b/common/util.go similarity index 98% rename from cloud/common/util.go rename to common/util.go index a3f8f66f..0b870745 100644 --- a/cloud/common/util.go +++ b/common/util.go @@ -12,7 +12,7 @@ import ( "github.com/appscode/go/crypto/rand" pb "github.com/datacol-io/datacol/api/models" "github.com/datacol-io/datacol/cloud" - sched "github.com/datacol-io/datacol/cloud/kube" + sched "github.com/datacol-io/datacol/k8s" "k8s.io/client-go/kubernetes" ) diff --git a/cloud/kube/common.go b/k8s/common.go similarity index 100% rename from cloud/kube/common.go rename to k8s/common.go diff --git a/cloud/kube/deployer.go b/k8s/deployer.go similarity index 100% rename from cloud/kube/deployer.go rename to k8s/deployer.go diff --git a/cloud/kube/deployment.go b/k8s/deployment.go similarity index 100% rename from cloud/kube/deployment.go rename to k8s/deployment.go diff --git a/cloud/kube/helper.go b/k8s/helper.go similarity index 100% rename from cloud/kube/helper.go rename to k8s/helper.go diff --git a/cloud/kube/helper_test.go b/k8s/helper_test.go similarity index 100% rename from cloud/kube/helper_test.go rename to k8s/helper_test.go diff --git a/cloud/kube/ingress.go b/k8s/ingress.go similarity index 100% rename from cloud/kube/ingress.go rename to k8s/ingress.go diff --git a/cloud/kube/logs.go b/k8s/logs.go similarity index 100% rename from cloud/kube/logs.go rename to k8s/logs.go diff --git a/cloud/kube/pod.go b/k8s/pod.go similarity index 100% rename from cloud/kube/pod.go rename to k8s/pod.go diff --git a/cloud/kube/process.go b/k8s/process.go similarity index 100% rename from cloud/kube/process.go rename to k8s/process.go From 6af9e4c2808726f51650be8e51ac3d7d6895b997 Mon Sep 17 00:00:00 2001 From: dinesh Date: Thu, 19 Apr 2018 15:58:04 +0530 Subject: [PATCH 10/13] code Janitor at work --- cloud/aws/logs.go | 5 +--- cloud/aws/process.go | 1 - cloud/aws/releases.go | 59 ++++++++++++++-------------------------- cloud/google/releases.go | 1 - 4 files changed, 22 insertions(+), 44 deletions(-) diff --git a/cloud/aws/logs.go b/cloud/aws/logs.go index f8df120c..50f145a4 100644 --- a/cloud/aws/logs.go +++ b/cloud/aws/logs.go @@ -8,8 +8,5 @@ import ( ) func (a *AwsCloud) LogStream(app string, w io.Writer, opts pb.LogStreamOptions) error { - ns := a.DeploymentName - c := a.kubeClient() - - return sched.LogStreamReq(c, w, ns, app, opts) + return sched.LogStreamReq(a.kubeClient(), w, a.DeploymentName, app, opts) } diff --git a/cloud/aws/process.go b/cloud/aws/process.go index aad07f0f..15380b1d 100644 --- a/cloud/aws/process.go +++ b/cloud/aws/process.go @@ -18,7 +18,6 @@ func (p *AwsCloud) ProcessList(app string) ([]*pb.Process, error) { func (p *AwsCloud) ProcessRun(name string, r io.ReadWriter, command []string) error { ns := p.DeploymentName cfg, _ := getKubeClientConfig(ns) - envVars, _ := p.EnvironmentGet(name) app, _ := p.AppGet(name) diff --git a/cloud/aws/releases.go b/cloud/aws/releases.go index 63acc8da..0f327aed 100644 --- a/cloud/aws/releases.go +++ b/cloud/aws/releases.go @@ -3,7 +3,6 @@ package aws import ( "fmt" "os" - "sort" "strings" log "github.com/Sirupsen/logrus" @@ -43,33 +42,6 @@ func (a *AwsCloud) ReleaseList(app string, limit int) (pb.Releases, error) { return releases, nil } -func (a *AwsCloud) ReleaseDelete(app, id string) error { - return nil -} - -func (a *AwsCloud) releaseCount(app string) (version int64) { - a.lock.Lock() - defer a.lock.Unlock() - - queryInput := &dynamodb.ScanInput{ - TableName: aws.String(a.dynamoReleases()), - Select: aws.String("COUNT"), - ExpressionAttributeValues: map[string]*dynamodb.AttributeValue{ - ":app": {S: aws.String(app)}, - }, - FilterExpression: aws.String("app=:app"), - } - - res, err := a.dynamodb().Scan(queryInput) - if err != nil { - log.Warnf("Fetching release count: %v", err) - } else { - version = *res.ScannedCount - } - - return version -} - func (a *AwsCloud) BuildRelease(b *pb.Build, options pb.ReleaseOptions) (*pb.Release, error) { image := fmt.Sprintf("%s.dkr.ecr.%s.amazonaws.com/%s:%s", os.Getenv("AWS_ACCOUNT_ID"), a.Region, a.ecrRepository(b.App), b.Id, @@ -158,18 +130,29 @@ func (a *AwsCloud) releaseFromItem(item map[string]*dynamodb.AttributeValue) *pb } } -func (a *AwsCloud) latestRelease(app string) *pb.Release { - allReleases, err := a.ReleaseList(app, 100) - if err != nil { - return nil +func (a *AwsCloud) ReleaseDelete(app, id string) error { + return notImplemented +} + +func (a *AwsCloud) releaseCount(app string) (version int64) { + a.lock.Lock() + defer a.lock.Unlock() + + queryInput := &dynamodb.ScanInput{ + TableName: aws.String(a.dynamoReleases()), + Select: aws.String("COUNT"), + ExpressionAttributeValues: map[string]*dynamodb.AttributeValue{ + ":app": {S: aws.String(app)}, + }, + FilterExpression: aws.String("app=:app"), } - if len(allReleases) > 0 { - sort.Slice(allReleases, func(i, j int) bool { - return allReleases[i].CreatedAt > allReleases[j].CreatedAt - }) - return allReleases[0] + res, err := a.dynamodb().Scan(queryInput) + if err != nil { + log.Warnf("Fetching release count: %v", err) } else { - return nil + version = *res.ScannedCount } + + return version } diff --git a/cloud/google/releases.go b/cloud/google/releases.go index 9ece11ee..be7879d9 100644 --- a/cloud/google/releases.go +++ b/cloud/google/releases.go @@ -94,6 +94,5 @@ func (g *GCPCloud) releaseCount(app string) (version int64) { } version = int64(total) - return } From 85de8cc04c27145315f73828851e63069c058995 Mon Sep 17 00:00:00 2001 From: dinesh Date: Thu, 19 Apr 2018 19:41:38 +0530 Subject: [PATCH 11/13] Adding domain API NAME: datacol domains - Manage your domains for an app USAGE: datacol domains command [command options] [arguments...] COMMANDS: add remove OPTIONS: --stack value stack name [$STACK] --help, -h show help --- CHANGELOG.md | 1 + api/controller/services.pb.go | 354 ++++++++++++++++----------- api/controller/services.pb.gw.go | 108 ++++++-- api/controller/services.proto | 28 ++- api/controller/services.swagger.json | 113 +++++---- api/domains.go | 37 +++ api/models/extra.go | 1 + api/server.go | 10 +- client/apps.go | 5 + client/build.go | 2 +- client/resource.go | 4 +- cloud/aws/apps.go | 13 + cloud/aws/releases.go | 13 +- cloud/google/apps.go | 13 + cloud/google/releases.go | 17 +- cloud/local/apps.go | 18 +- cloud/local/environ.go | 22 ++ cloud/provider.go | 1 + cmd/deploy.go | 5 - cmd/domains.go | 78 ++++++ common/apps.go | 31 +++ common/apps_test.go | 27 ++ k8s/deployment.go | 39 +-- k8s/helper.go | 62 +++-- k8s/helper_test.go | 62 +++-- 25 files changed, 737 insertions(+), 327 deletions(-) create mode 100644 api/domains.go create mode 100644 cloud/local/environ.go create mode 100644 cmd/domains.go create mode 100644 common/apps_test.go diff --git a/CHANGELOG.md b/CHANGELOG.md index 63c2625d..01c105b2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ This project adheres to [Semantic Versioning](http://semver.org/). - Async support for streaming logs from mutiple processes. - Making `datacol run` independent of shell ### Added +- [CLI] Added domains:{add, remove} API - [CLI] Renaming command `ps scale` to `scale` - [CLI] Renaming command `build list` to `builds` - [API] version label into k8s deployments diff --git a/api/controller/services.pb.go b/api/controller/services.pb.go index ae9158cb..3a3479ce 100644 --- a/api/controller/services.pb.go +++ b/api/controller/services.pb.go @@ -10,6 +10,7 @@ It is generated from these files: It has these top-level messages: ListRequest + ListResponse AppRequest AppListResponse AuthRequest @@ -20,7 +21,7 @@ It has these top-level messages: BuildLogResponse EnvSetRequest ResourceListResponse - BuildListRequest + AppListRequest BuildListResponse ProcessListResponse CreateResourceRequest @@ -32,6 +33,7 @@ It has these top-level messages: StreamMsg ReleaseListResponse CreateReleaseRequest + ListDomainReqponse */ package controller @@ -84,6 +86,22 @@ func (m *ListRequest) GetLimit() int32 { return 0 } +type ListResponse struct { + Items []string `protobuf:"bytes,1,rep,name=items" json:"items,omitempty"` +} + +func (m *ListResponse) Reset() { *m = ListResponse{} } +func (m *ListResponse) String() string { return proto.CompactTextString(m) } +func (*ListResponse) ProtoMessage() {} +func (*ListResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } + +func (m *ListResponse) GetItems() []string { + if m != nil { + return m.Items + } + return nil +} + type AppRequest struct { Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` RepoUrl string `protobuf:"bytes,2,opt,name=repo_url,json=repoUrl" json:"repo_url,omitempty"` @@ -92,7 +110,7 @@ type AppRequest struct { func (m *AppRequest) Reset() { *m = AppRequest{} } func (m *AppRequest) String() string { return proto.CompactTextString(m) } func (*AppRequest) ProtoMessage() {} -func (*AppRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } +func (*AppRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} } func (m *AppRequest) GetName() string { if m != nil { @@ -117,7 +135,7 @@ type AppListResponse struct { func (m *AppListResponse) Reset() { *m = AppListResponse{} } func (m *AppListResponse) String() string { return proto.CompactTextString(m) } func (*AppListResponse) ProtoMessage() {} -func (*AppListResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} } +func (*AppListResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} } func (m *AppListResponse) GetApps() []*models.App { if m != nil { @@ -147,7 +165,7 @@ type AuthRequest struct { func (m *AuthRequest) Reset() { *m = AuthRequest{} } func (m *AuthRequest) String() string { return proto.CompactTextString(m) } func (*AuthRequest) ProtoMessage() {} -func (*AuthRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} } +func (*AuthRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{4} } func (m *AuthRequest) GetPassword() string { if m != nil { @@ -167,7 +185,7 @@ type AuthResponse struct { func (m *AuthResponse) Reset() { *m = AuthResponse{} } func (m *AuthResponse) String() string { return proto.CompactTextString(m) } func (*AuthResponse) ProtoMessage() {} -func (*AuthResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{4} } +func (*AuthResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{5} } func (m *AuthResponse) GetHost() string { if m != nil { @@ -213,7 +231,7 @@ type CreateBuildRequest struct { func (m *CreateBuildRequest) Reset() { *m = CreateBuildRequest{} } func (m *CreateBuildRequest) String() string { return proto.CompactTextString(m) } func (*CreateBuildRequest) ProtoMessage() {} -func (*CreateBuildRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{5} } +func (*CreateBuildRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{6} } func (m *CreateBuildRequest) GetApp() string { if m != nil { @@ -244,7 +262,7 @@ type AppIdRequest struct { func (m *AppIdRequest) Reset() { *m = AppIdRequest{} } func (m *AppIdRequest) String() string { return proto.CompactTextString(m) } func (*AppIdRequest) ProtoMessage() {} -func (*AppIdRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{6} } +func (*AppIdRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{7} } func (m *AppIdRequest) GetApp() string { if m != nil { @@ -269,7 +287,7 @@ type BuildLogRequest struct { func (m *BuildLogRequest) Reset() { *m = BuildLogRequest{} } func (m *BuildLogRequest) String() string { return proto.CompactTextString(m) } func (*BuildLogRequest) ProtoMessage() {} -func (*BuildLogRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{7} } +func (*BuildLogRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{8} } func (m *BuildLogRequest) GetApp() string { if m != nil { @@ -300,7 +318,7 @@ type BuildLogResponse struct { func (m *BuildLogResponse) Reset() { *m = BuildLogResponse{} } func (m *BuildLogResponse) String() string { return proto.CompactTextString(m) } func (*BuildLogResponse) ProtoMessage() {} -func (*BuildLogResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{8} } +func (*BuildLogResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{9} } func (m *BuildLogResponse) GetPos() int32 { if m != nil { @@ -324,7 +342,7 @@ type EnvSetRequest struct { func (m *EnvSetRequest) Reset() { *m = EnvSetRequest{} } func (m *EnvSetRequest) String() string { return proto.CompactTextString(m) } func (*EnvSetRequest) ProtoMessage() {} -func (*EnvSetRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{9} } +func (*EnvSetRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{10} } func (m *EnvSetRequest) GetName() string { if m != nil { @@ -347,7 +365,7 @@ type ResourceListResponse struct { func (m *ResourceListResponse) Reset() { *m = ResourceListResponse{} } func (m *ResourceListResponse) String() string { return proto.CompactTextString(m) } func (*ResourceListResponse) ProtoMessage() {} -func (*ResourceListResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{10} } +func (*ResourceListResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{11} } func (m *ResourceListResponse) GetResources() []*models.Resource { if m != nil { @@ -356,24 +374,24 @@ func (m *ResourceListResponse) GetResources() []*models.Resource { return nil } -type BuildListRequest struct { +type AppListRequest struct { Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` Limit int32 `protobuf:"varint,2,opt,name=limit" json:"limit,omitempty"` } -func (m *BuildListRequest) Reset() { *m = BuildListRequest{} } -func (m *BuildListRequest) String() string { return proto.CompactTextString(m) } -func (*BuildListRequest) ProtoMessage() {} -func (*BuildListRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{11} } +func (m *AppListRequest) Reset() { *m = AppListRequest{} } +func (m *AppListRequest) String() string { return proto.CompactTextString(m) } +func (*AppListRequest) ProtoMessage() {} +func (*AppListRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{12} } -func (m *BuildListRequest) GetName() string { +func (m *AppListRequest) GetName() string { if m != nil { return m.Name } return "" } -func (m *BuildListRequest) GetLimit() int32 { +func (m *AppListRequest) GetLimit() int32 { if m != nil { return m.Limit } @@ -387,7 +405,7 @@ type BuildListResponse struct { func (m *BuildListResponse) Reset() { *m = BuildListResponse{} } func (m *BuildListResponse) String() string { return proto.CompactTextString(m) } func (*BuildListResponse) ProtoMessage() {} -func (*BuildListResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{12} } +func (*BuildListResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{13} } func (m *BuildListResponse) GetBuilds() []*models.Build { if m != nil { @@ -403,7 +421,7 @@ type ProcessListResponse struct { func (m *ProcessListResponse) Reset() { *m = ProcessListResponse{} } func (m *ProcessListResponse) String() string { return proto.CompactTextString(m) } func (*ProcessListResponse) ProtoMessage() {} -func (*ProcessListResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{13} } +func (*ProcessListResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{14} } func (m *ProcessListResponse) GetItems() []*models.Process { if m != nil { @@ -421,7 +439,7 @@ type CreateResourceRequest struct { func (m *CreateResourceRequest) Reset() { *m = CreateResourceRequest{} } func (m *CreateResourceRequest) String() string { return proto.CompactTextString(m) } func (*CreateResourceRequest) ProtoMessage() {} -func (*CreateResourceRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{14} } +func (*CreateResourceRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{15} } func (m *CreateResourceRequest) GetName() string { if m != nil { @@ -445,14 +463,14 @@ func (m *CreateResourceRequest) GetParams() map[string]string { } type AppResourceReq struct { - App string `protobuf:"bytes,1,opt,name=app" json:"app,omitempty"` - Name string `protobuf:"bytes,2,opt,name=name" json:"name,omitempty"` + App string `protobuf:"bytes,1,opt,name=app" json:"app,omitempty"` + Resource string `protobuf:"bytes,2,opt,name=resource" json:"resource,omitempty"` } func (m *AppResourceReq) Reset() { *m = AppResourceReq{} } func (m *AppResourceReq) String() string { return proto.CompactTextString(m) } func (*AppResourceReq) ProtoMessage() {} -func (*AppResourceReq) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{15} } +func (*AppResourceReq) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{16} } func (m *AppResourceReq) GetApp() string { if m != nil { @@ -461,9 +479,9 @@ func (m *AppResourceReq) GetApp() string { return "" } -func (m *AppResourceReq) GetName() string { +func (m *AppResourceReq) GetResource() string { if m != nil { - return m.Name + return m.Resource } return "" } @@ -475,7 +493,7 @@ type KubectlReq struct { func (m *KubectlReq) Reset() { *m = KubectlReq{} } func (m *KubectlReq) String() string { return proto.CompactTextString(m) } func (*KubectlReq) ProtoMessage() {} -func (*KubectlReq) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{16} } +func (*KubectlReq) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{17} } func (m *KubectlReq) GetArgs() []string { if m != nil { @@ -494,7 +512,7 @@ type CmdResponse struct { func (m *CmdResponse) Reset() { *m = CmdResponse{} } func (m *CmdResponse) String() string { return proto.CompactTextString(m) } func (*CmdResponse) ProtoMessage() {} -func (*CmdResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{17} } +func (*CmdResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{18} } func (m *CmdResponse) GetExitCode() int32 { if m != nil { @@ -534,7 +552,7 @@ type LogStreamReq struct { func (m *LogStreamReq) Reset() { *m = LogStreamReq{} } func (m *LogStreamReq) String() string { return proto.CompactTextString(m) } func (*LogStreamReq) ProtoMessage() {} -func (*LogStreamReq) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{18} } +func (*LogStreamReq) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{19} } func (m *LogStreamReq) GetName() string { if m != nil { @@ -572,7 +590,7 @@ type ProcessRunReq struct { func (m *ProcessRunReq) Reset() { *m = ProcessRunReq{} } func (m *ProcessRunReq) String() string { return proto.CompactTextString(m) } func (*ProcessRunReq) ProtoMessage() {} -func (*ProcessRunReq) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{19} } +func (*ProcessRunReq) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{20} } func (m *ProcessRunReq) GetName() string { if m != nil { @@ -595,7 +613,7 @@ type StreamMsg struct { func (m *StreamMsg) Reset() { *m = StreamMsg{} } func (m *StreamMsg) String() string { return proto.CompactTextString(m) } func (*StreamMsg) ProtoMessage() {} -func (*StreamMsg) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{20} } +func (*StreamMsg) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{21} } func (m *StreamMsg) GetData() []byte { if m != nil { @@ -611,7 +629,7 @@ type ReleaseListResponse struct { func (m *ReleaseListResponse) Reset() { *m = ReleaseListResponse{} } func (m *ReleaseListResponse) String() string { return proto.CompactTextString(m) } func (*ReleaseListResponse) ProtoMessage() {} -func (*ReleaseListResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{21} } +func (*ReleaseListResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{22} } func (m *ReleaseListResponse) GetReleases() []*models.Release { if m != nil { @@ -628,7 +646,7 @@ type CreateReleaseRequest struct { func (m *CreateReleaseRequest) Reset() { *m = CreateReleaseRequest{} } func (m *CreateReleaseRequest) String() string { return proto.CompactTextString(m) } func (*CreateReleaseRequest) ProtoMessage() {} -func (*CreateReleaseRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{22} } +func (*CreateReleaseRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{23} } func (m *CreateReleaseRequest) GetBuild() *models.Build { if m != nil { @@ -644,8 +662,25 @@ func (m *CreateReleaseRequest) GetDomain() string { return "" } +type ListDomainReqponse struct { + Url []string `protobuf:"bytes,1,rep,name=url" json:"url,omitempty"` +} + +func (m *ListDomainReqponse) Reset() { *m = ListDomainReqponse{} } +func (m *ListDomainReqponse) String() string { return proto.CompactTextString(m) } +func (*ListDomainReqponse) ProtoMessage() {} +func (*ListDomainReqponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{24} } + +func (m *ListDomainReqponse) GetUrl() []string { + if m != nil { + return m.Url + } + return nil +} + func init() { proto.RegisterType((*ListRequest)(nil), "controller.ListRequest") + proto.RegisterType((*ListResponse)(nil), "controller.ListResponse") proto.RegisterType((*AppRequest)(nil), "controller.AppRequest") proto.RegisterType((*AppListResponse)(nil), "controller.AppListResponse") proto.RegisterType((*AuthRequest)(nil), "controller.AuthRequest") @@ -656,7 +691,7 @@ func init() { proto.RegisterType((*BuildLogResponse)(nil), "controller.BuildLogResponse") proto.RegisterType((*EnvSetRequest)(nil), "controller.EnvSetRequest") proto.RegisterType((*ResourceListResponse)(nil), "controller.ResourceListResponse") - proto.RegisterType((*BuildListRequest)(nil), "controller.BuildListRequest") + proto.RegisterType((*AppListRequest)(nil), "controller.AppListRequest") proto.RegisterType((*BuildListResponse)(nil), "controller.BuildListResponse") proto.RegisterType((*ProcessListResponse)(nil), "controller.ProcessListResponse") proto.RegisterType((*CreateResourceRequest)(nil), "controller.CreateResourceRequest") @@ -668,6 +703,7 @@ func init() { proto.RegisterType((*StreamMsg)(nil), "controller.StreamMsg") proto.RegisterType((*ReleaseListResponse)(nil), "controller.ReleaseListResponse") proto.RegisterType((*CreateReleaseRequest)(nil), "controller.CreateReleaseRequest") + proto.RegisterType((*ListDomainReqponse)(nil), "controller.ListDomainReqponse") } // Reference imports to suppress errors if they are not otherwise used. @@ -688,13 +724,15 @@ type ProviderServiceClient interface { AppGet(ctx context.Context, in *AppRequest, opts ...grpc.CallOption) (*models.App, error) AppRestart(ctx context.Context, in *AppRequest, opts ...grpc.CallOption) (*google_protobuf1.Empty, error) AppDelete(ctx context.Context, in *AppRequest, opts ...grpc.CallOption) (*google_protobuf1.Empty, error) + // Update Domain API + AppUpdateDomain(ctx context.Context, in *AppResourceReq, opts ...grpc.CallOption) (*google_protobuf1.Empty, error) // Build Api BuildCreate(ctx context.Context, in *CreateBuildRequest, opts ...grpc.CallOption) (*models.Build, error) BuildImport(ctx context.Context, opts ...grpc.CallOption) (ProviderService_BuildImportClient, error) BuildRelease(ctx context.Context, in *CreateReleaseRequest, opts ...grpc.CallOption) (*models.Release, error) BuildGet(ctx context.Context, in *AppIdRequest, opts ...grpc.CallOption) (*models.Build, error) BuildDelete(ctx context.Context, in *AppIdRequest, opts ...grpc.CallOption) (*google_protobuf1.Empty, error) - BuildList(ctx context.Context, in *BuildListRequest, opts ...grpc.CallOption) (*BuildListResponse, error) + BuildList(ctx context.Context, in *AppListRequest, opts ...grpc.CallOption) (*BuildListResponse, error) BuildLogs(ctx context.Context, in *BuildLogRequest, opts ...grpc.CallOption) (*BuildLogResponse, error) EnvironmentGet(ctx context.Context, in *AppRequest, opts ...grpc.CallOption) (*models.EnvConfig, error) EnvironmentSet(ctx context.Context, in *EnvSetRequest, opts ...grpc.CallOption) (*google_protobuf1.Empty, error) @@ -780,6 +818,15 @@ func (c *providerServiceClient) AppDelete(ctx context.Context, in *AppRequest, o return out, nil } +func (c *providerServiceClient) AppUpdateDomain(ctx context.Context, in *AppResourceReq, opts ...grpc.CallOption) (*google_protobuf1.Empty, error) { + out := new(google_protobuf1.Empty) + err := grpc.Invoke(ctx, "/controller.ProviderService/AppUpdateDomain", in, out, c.cc, opts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *providerServiceClient) BuildCreate(ctx context.Context, in *CreateBuildRequest, opts ...grpc.CallOption) (*models.Build, error) { out := new(models.Build) err := grpc.Invoke(ctx, "/controller.ProviderService/BuildCreate", in, out, c.cc, opts...) @@ -850,7 +897,7 @@ func (c *providerServiceClient) BuildDelete(ctx context.Context, in *AppIdReques return out, nil } -func (c *providerServiceClient) BuildList(ctx context.Context, in *BuildListRequest, opts ...grpc.CallOption) (*BuildListResponse, error) { +func (c *providerServiceClient) BuildList(ctx context.Context, in *AppListRequest, opts ...grpc.CallOption) (*BuildListResponse, error) { out := new(BuildListResponse) err := grpc.Invoke(ctx, "/controller.ProviderService/BuildList", in, out, c.cc, opts...) if err != nil { @@ -1058,13 +1105,15 @@ type ProviderServiceServer interface { AppGet(context.Context, *AppRequest) (*models.App, error) AppRestart(context.Context, *AppRequest) (*google_protobuf1.Empty, error) AppDelete(context.Context, *AppRequest) (*google_protobuf1.Empty, error) + // Update Domain API + AppUpdateDomain(context.Context, *AppResourceReq) (*google_protobuf1.Empty, error) // Build Api BuildCreate(context.Context, *CreateBuildRequest) (*models.Build, error) BuildImport(ProviderService_BuildImportServer) error BuildRelease(context.Context, *CreateReleaseRequest) (*models.Release, error) BuildGet(context.Context, *AppIdRequest) (*models.Build, error) BuildDelete(context.Context, *AppIdRequest) (*google_protobuf1.Empty, error) - BuildList(context.Context, *BuildListRequest) (*BuildListResponse, error) + BuildList(context.Context, *AppListRequest) (*BuildListResponse, error) BuildLogs(context.Context, *BuildLogRequest) (*BuildLogResponse, error) EnvironmentGet(context.Context, *AppRequest) (*models.EnvConfig, error) EnvironmentSet(context.Context, *EnvSetRequest) (*google_protobuf1.Empty, error) @@ -1200,6 +1249,24 @@ func _ProviderService_AppDelete_Handler(srv interface{}, ctx context.Context, de return interceptor(ctx, in, info, handler) } +func _ProviderService_AppUpdateDomain_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(AppResourceReq) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ProviderServiceServer).AppUpdateDomain(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/controller.ProviderService/AppUpdateDomain", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ProviderServiceServer).AppUpdateDomain(ctx, req.(*AppResourceReq)) + } + return interceptor(ctx, in, info, handler) +} + func _ProviderService_BuildCreate_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(CreateBuildRequest) if err := dec(in); err != nil { @@ -1299,7 +1366,7 @@ func _ProviderService_BuildDelete_Handler(srv interface{}, ctx context.Context, } func _ProviderService_BuildList_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(BuildListRequest) + in := new(AppListRequest) if err := dec(in); err != nil { return nil, err } @@ -1311,7 +1378,7 @@ func _ProviderService_BuildList_Handler(srv interface{}, ctx context.Context, de FullMethod: "/controller.ProviderService/BuildList", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(ProviderServiceServer).BuildList(ctx, req.(*BuildListRequest)) + return srv.(ProviderServiceServer).BuildList(ctx, req.(*AppListRequest)) } return interceptor(ctx, in, info, handler) } @@ -1643,6 +1710,10 @@ var _ProviderService_serviceDesc = grpc.ServiceDesc{ MethodName: "AppDelete", Handler: _ProviderService_AppDelete_Handler, }, + { + MethodName: "AppUpdateDomain", + Handler: _ProviderService_AppUpdateDomain_Handler, + }, { MethodName: "BuildCreate", Handler: _ProviderService_BuildCreate_Handler, @@ -1744,105 +1815,108 @@ var _ProviderService_serviceDesc = grpc.ServiceDesc{ func init() { proto.RegisterFile("services.proto", fileDescriptor0) } var fileDescriptor0 = []byte{ - // 1585 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x58, 0x5b, 0x6f, 0x1b, 0xc5, - 0x17, 0xff, 0x6f, 0xe2, 0x5c, 0x7c, 0xec, 0xdc, 0x26, 0x37, 0xc7, 0x49, 0x93, 0x74, 0xaa, 0xbf, - 0x48, 0x83, 0x6a, 0x97, 0x82, 0xb8, 0xa4, 0xe5, 0x21, 0x49, 0x5d, 0x14, 0x11, 0x68, 0xd8, 0x50, - 0x85, 0x4b, 0xa1, 0xdd, 0xd8, 0x63, 0x67, 0xc9, 0x7a, 0x67, 0x98, 0x5d, 0xbb, 0x44, 0x55, 0x5f, - 0x10, 0x12, 0x1f, 0x80, 0x4f, 0xc4, 0x5b, 0x1f, 0x91, 0x78, 0x47, 0xa8, 0xe2, 0x1b, 0xf0, 0x05, - 0xd0, 0xdc, 0xd6, 0xb3, 0xf6, 0x3a, 0x84, 0xbe, 0x44, 0x73, 0x76, 0x66, 0x7e, 0xe7, 0x37, 0x67, - 0x7e, 0xe7, 0x9c, 0x71, 0x60, 0x3a, 0x22, 0xbc, 0xeb, 0xd7, 0x49, 0x54, 0x61, 0x9c, 0xc6, 0x14, - 0x41, 0x9d, 0x86, 0x31, 0xa7, 0x41, 0x40, 0x78, 0x79, 0xad, 0x45, 0x69, 0x2b, 0x20, 0x55, 0x8f, - 0xf9, 0x55, 0x2f, 0x0c, 0x69, 0xec, 0xc5, 0x3e, 0x0d, 0xf5, 0xca, 0x72, 0x89, 0xc5, 0x17, 0x8c, - 0x44, 0x55, 0xd2, 0x66, 0xf1, 0x85, 0xfa, 0xab, 0x67, 0xd6, 0xf5, 0x4c, 0xa3, 0xc3, 0xe5, 0x8e, - 0x64, 0xa0, 0xe7, 0x6f, 0xb5, 0xfc, 0xf8, 0xac, 0x73, 0x5a, 0xa9, 0xd3, 0x76, 0xb5, 0x45, 0x5b, - 0xb4, 0x2a, 0x3f, 0x9f, 0x76, 0x9a, 0xd2, 0x92, 0x86, 0x1c, 0xe9, 0xe5, 0xef, 0x58, 0xcb, 0x1b, - 0x5e, 0xec, 0xd5, 0x69, 0x70, 0xcb, 0xa7, 0x66, 0x28, 0xd9, 0xb5, 0x69, 0x83, 0x04, 0x51, 0x55, - 0xba, 0x55, 0xbb, 0xf0, 0x5d, 0x28, 0x1c, 0xfa, 0x51, 0xec, 0x92, 0xef, 0x3b, 0x24, 0x8a, 0xd1, - 0x12, 0x8c, 0xd3, 0x66, 0x33, 0x22, 0x71, 0xc9, 0xd9, 0x74, 0xb6, 0xc6, 0x5c, 0x6d, 0xa1, 0x05, - 0x18, 0x0b, 0xfc, 0xb6, 0x1f, 0x97, 0x46, 0xe4, 0x67, 0x65, 0xe0, 0xbb, 0x00, 0xbb, 0x8c, 0x99, - 0xbd, 0x08, 0x72, 0xa1, 0xd7, 0x26, 0x72, 0x67, 0xde, 0x95, 0x63, 0xb4, 0x02, 0x93, 0x9c, 0x30, - 0xfa, 0xa4, 0xc3, 0x03, 0xb9, 0x35, 0xef, 0x4e, 0x08, 0xfb, 0x11, 0x0f, 0x70, 0x13, 0x66, 0x76, - 0x19, 0x53, 0xce, 0x23, 0x46, 0xc3, 0x88, 0xa0, 0xff, 0x43, 0xce, 0x63, 0x2c, 0x2a, 0x39, 0x9b, - 0xa3, 0x5b, 0x85, 0x3b, 0x85, 0x8a, 0xe2, 0x5b, 0xd9, 0x65, 0x6c, 0x2f, 0xf7, 0xf2, 0x8f, 0x8d, - 0xff, 0xb9, 0x72, 0x3a, 0x9b, 0x8c, 0x45, 0x7d, 0xd4, 0xa6, 0x8e, 0x6f, 0x42, 0x61, 0xb7, 0x13, - 0x9f, 0x19, 0x96, 0x65, 0x98, 0x64, 0x5e, 0x14, 0x3d, 0xa3, 0xbc, 0xa1, 0x99, 0x26, 0x36, 0xfe, - 0xc9, 0x81, 0xa2, 0x5a, 0xab, 0x09, 0x21, 0xc8, 0x9d, 0xd1, 0x28, 0x36, 0x47, 0x12, 0xe3, 0xe4, - 0x98, 0x23, 0xd6, 0x31, 0x4b, 0x30, 0xc1, 0x38, 0xfd, 0x8e, 0xd4, 0x95, 0xf3, 0xbc, 0x6b, 0x4c, - 0xc1, 0x8a, 0x93, 0x96, 0x4f, 0xc3, 0x52, 0x4e, 0x4e, 0x68, 0x4b, 0xd2, 0xe0, 0xb4, 0xeb, 0x37, - 0x08, 0x2f, 0x8d, 0x69, 0x1a, 0xda, 0xc6, 0x8f, 0x01, 0xed, 0x73, 0xe2, 0xc5, 0x64, 0xaf, 0xe3, - 0x07, 0x0d, 0x43, 0x7c, 0x16, 0x46, 0x3d, 0xc6, 0x34, 0x15, 0x31, 0x14, 0x5e, 0xbb, 0x84, 0x47, - 0x02, 0x5c, 0xc7, 0x56, 0x9b, 0x1a, 0xbd, 0xde, 0xf4, 0x03, 0x22, 0x09, 0x15, 0xdd, 0xc4, 0xc6, - 0xb7, 0xa1, 0xb8, 0xcb, 0xd8, 0xc1, 0x25, 0xb8, 0xd3, 0x30, 0xe2, 0x37, 0x34, 0xe4, 0x88, 0xdf, - 0xc0, 0x35, 0x98, 0x91, 0x4c, 0x0e, 0x69, 0xeb, 0xca, 0x9b, 0xc4, 0x0a, 0x46, 0x23, 0x7d, 0x17, - 0x62, 0x88, 0x77, 0x60, 0xb6, 0x07, 0xa3, 0x03, 0xac, 0x57, 0x39, 0xc9, 0x2a, 0x75, 0xb9, 0x21, - 0x89, 0x4a, 0x23, 0x9b, 0xa3, 0x5b, 0x79, 0x57, 0x19, 0xf8, 0x3d, 0x98, 0xaa, 0x85, 0xdd, 0x63, - 0x12, 0x5f, 0x26, 0x36, 0x04, 0x39, 0xa1, 0x76, 0x73, 0x33, 0x62, 0x8c, 0x1f, 0xc0, 0x82, 0x4b, - 0x22, 0xda, 0xe1, 0x75, 0x92, 0x92, 0x5a, 0x05, 0xf2, 0x5c, 0x7f, 0x37, 0x7a, 0x9b, 0x35, 0x7a, - 0x33, 0x1b, 0xdc, 0xde, 0x12, 0x7c, 0xcf, 0x90, 0xb7, 0x92, 0x25, 0x8b, 0x43, 0x76, 0xa2, 0xec, - 0xc0, 0x9c, 0xb5, 0x3b, 0x51, 0xfb, 0xf8, 0xa9, 0xf8, 0x68, 0xfc, 0x4f, 0x19, 0xff, 0xea, 0xda, - 0xf5, 0x24, 0xbe, 0x07, 0xf3, 0x47, 0x9c, 0xd6, 0x49, 0x14, 0xf5, 0xed, 0x1e, 0x3b, 0x88, 0x49, - 0xdb, 0x6c, 0x9e, 0x31, 0x9b, 0xf5, 0x5a, 0x57, 0xcd, 0xe2, 0x5f, 0x1d, 0x58, 0x54, 0x62, 0x4a, - 0x4e, 0x75, 0x79, 0x04, 0xcf, 0xfd, 0xd0, 0x5c, 0xa3, 0x1c, 0xa3, 0x1a, 0x8c, 0x33, 0x8f, 0x7b, - 0x6d, 0x71, 0x97, 0xc2, 0xd3, 0xad, 0x4a, 0xaf, 0xf6, 0x55, 0x32, 0xa1, 0x2b, 0x47, 0x72, 0x7d, - 0x2d, 0x8c, 0xf9, 0x85, 0xab, 0x37, 0x97, 0x3f, 0x80, 0x82, 0xf5, 0x59, 0x5c, 0xfc, 0x39, 0xb9, - 0x30, 0x02, 0x3a, 0x27, 0x17, 0x22, 0x72, 0x5d, 0x2f, 0xe8, 0x98, 0xc4, 0x52, 0xc6, 0xce, 0xc8, - 0xfb, 0x0e, 0x7e, 0x17, 0xa6, 0x65, 0x99, 0x49, 0x9c, 0x64, 0xc8, 0x2f, 0x23, 0x2b, 0xf1, 0x26, - 0xc0, 0xc7, 0x9d, 0x53, 0x52, 0x8f, 0x03, 0xb1, 0x07, 0x41, 0xce, 0xe3, 0x2d, 0x15, 0xaf, 0xbc, - 0x2b, 0xc7, 0x38, 0x80, 0xc2, 0x7e, 0xbb, 0x91, 0xc4, 0x74, 0x15, 0xf2, 0xe4, 0x07, 0x3f, 0x7e, - 0x52, 0xa7, 0x0d, 0xa2, 0x35, 0x39, 0x29, 0x3e, 0xec, 0xd3, 0x86, 0x94, 0x2a, 0xe1, 0x5c, 0x3b, - 0x10, 0x43, 0x91, 0xdb, 0x51, 0xdc, 0x78, 0xd8, 0x31, 0x49, 0xaf, 0x2d, 0xfd, 0xbd, 0xc6, 0xb9, - 0xc9, 0x79, 0x65, 0xe1, 0x9f, 0x1d, 0x28, 0x1e, 0xd2, 0xd6, 0x71, 0xcc, 0x89, 0xd7, 0xd6, 0x94, - 0x06, 0xae, 0x60, 0x09, 0xc6, 0x9b, 0x34, 0x08, 0xe8, 0x33, 0xe9, 0x69, 0xd2, 0xd5, 0x16, 0xaa, - 0xc2, 0x58, 0xe4, 0x87, 0x75, 0x95, 0xcf, 0x85, 0x3b, 0x2b, 0x15, 0xd5, 0x75, 0x2a, 0xa6, 0x29, - 0x54, 0xee, 0xeb, 0xee, 0xe1, 0xaa, 0x75, 0xa6, 0x06, 0x88, 0x62, 0xaf, 0x79, 0x24, 0x36, 0xfe, - 0x10, 0xa6, 0x8c, 0x4e, 0x3a, 0xe1, 0x30, 0x26, 0x25, 0x98, 0xa8, 0xd3, 0x76, 0xdb, 0x93, 0x7a, - 0x10, 0x31, 0x33, 0x26, 0xde, 0x80, 0xbc, 0x3a, 0xc4, 0x27, 0x51, 0x2b, 0xc9, 0x3a, 0x47, 0xd6, - 0x19, 0x95, 0x75, 0x7b, 0x30, 0xef, 0x92, 0x80, 0x78, 0x51, 0x3a, 0xe9, 0xde, 0x14, 0xdd, 0x40, - 0x7e, 0x1e, 0x90, 0xad, 0x5e, 0xee, 0x26, 0x0b, 0xf0, 0x31, 0x2c, 0x18, 0x75, 0xa9, 0x29, 0xad, - 0xdb, 0x1b, 0x30, 0x26, 0x33, 0x43, 0x3a, 0x1c, 0xc8, 0x1a, 0x35, 0x27, 0xa2, 0xd8, 0xa0, 0x6d, - 0xcf, 0x37, 0x95, 0x51, 0x5b, 0x77, 0xfe, 0x9e, 0x87, 0x99, 0x23, 0x5d, 0x67, 0x8f, 0x55, 0x4b, - 0x47, 0x9f, 0x42, 0x4e, 0x14, 0x7d, 0xb4, 0x6c, 0x0b, 0xdb, 0x6a, 0x19, 0xe5, 0xd2, 0xe0, 0x84, - 0x3a, 0x10, 0x9e, 0xff, 0xf1, 0xf7, 0xbf, 0x7e, 0x19, 0x99, 0xc2, 0x93, 0xd5, 0xee, 0x5b, 0x55, - 0xaf, 0x13, 0x9f, 0xed, 0x38, 0xdb, 0xe8, 0x33, 0x98, 0xd0, 0x8d, 0x2d, 0x0d, 0x69, 0x95, 0x8e, - 0xf2, 0x6a, 0x0a, 0x32, 0xdd, 0x06, 0xf1, 0xac, 0x44, 0x05, 0xa4, 0x50, 0x45, 0xc7, 0xab, 0x41, - 0x7e, 0x97, 0x31, 0x15, 0x0e, 0xb4, 0xd4, 0xb7, 0xd7, 0x60, 0xda, 0xfd, 0xb2, 0x8f, 0x19, 0x63, - 0x91, 0x60, 0xf6, 0x00, 0xc6, 0x77, 0x19, 0xfb, 0x88, 0xc4, 0x57, 0xc3, 0x58, 0x96, 0x18, 0x73, - 0x68, 0xc6, 0x60, 0x54, 0x9f, 0x0b, 0x61, 0xbc, 0x40, 0xdf, 0xe8, 0xbe, 0x1f, 0xc5, 0x1e, 0x1f, - 0x8e, 0xb5, 0x34, 0x20, 0xd1, 0x9a, 0x78, 0xfd, 0xe0, 0x0d, 0x09, 0xbb, 0x82, 0x96, 0xfb, 0x60, - 0xab, 0x5c, 0x03, 0x7e, 0x2e, 0x4f, 0x7b, 0x9f, 0x04, 0xe4, 0x92, 0xd3, 0x0e, 0x43, 0xd7, 0xa4, - 0xb7, 0x07, 0x48, 0x1f, 0x41, 0x41, 0x4a, 0x44, 0x47, 0x71, 0x7d, 0xb0, 0x8c, 0xd9, 0xed, 0xb6, - 0x9c, 0xd6, 0x15, 0x46, 0x12, 0xb6, 0x88, 0x41, 0xc0, 0xaa, 0xca, 0x8c, 0xbe, 0xd4, 0x88, 0x07, - 0x6d, 0x46, 0x79, 0x8c, 0x16, 0x6d, 0xc4, 0x24, 0x3f, 0x86, 0x12, 0x5d, 0x91, 0x88, 0xf3, 0x78, - 0xae, 0x87, 0x58, 0xf5, 0x25, 0xd2, 0x96, 0x83, 0x4e, 0xa0, 0xa8, 0xd9, 0x48, 0xed, 0xa3, 0xcd, - 0xac, 0xa2, 0x6b, 0xa7, 0x45, 0xb9, 0x3f, 0x93, 0xf0, 0x82, 0xc4, 0x9f, 0xc6, 0x45, 0x81, 0x6f, - 0xb2, 0x0a, 0x1d, 0xc2, 0xa4, 0x04, 0x16, 0x22, 0x28, 0xf5, 0x85, 0xf6, 0x60, 0xd8, 0xe1, 0x53, - 0x42, 0xd0, 0x54, 0x9f, 0xfb, 0x8d, 0x17, 0xe8, 0x0b, 0x1d, 0x01, 0x7d, 0x57, 0xc3, 0x01, 0xaf, - 0x74, 0x5b, 0x36, 0x72, 0x1d, 0xf2, 0x49, 0xc7, 0x44, 0x6b, 0x36, 0x6e, 0x7f, 0x1b, 0x2e, 0x5f, - 0x1b, 0x32, 0xab, 0xb3, 0x49, 0xc7, 0x19, 0xd9, 0x71, 0xd6, 0x92, 0x68, 0x18, 0x27, 0xb4, 0x15, - 0xa1, 0xd5, 0x41, 0x98, 0xe4, 0xbd, 0x53, 0x5e, 0xcb, 0x9e, 0xd4, 0x2e, 0xd6, 0xa4, 0x8b, 0x25, - 0xb4, 0xd0, 0x77, 0x8a, 0x6a, 0x20, 0x80, 0x8f, 0x61, 0xba, 0x16, 0x76, 0x7d, 0x4e, 0xc3, 0x36, - 0x09, 0xe3, 0xcb, 0xb2, 0x6f, 0xce, 0x84, 0xbd, 0x16, 0x76, 0xf7, 0x69, 0xd8, 0xf4, 0x5b, 0x78, - 0x49, 0x42, 0xcf, 0xa2, 0x69, 0x01, 0x4d, 0xc2, 0xae, 0xa1, 0xfe, 0x75, 0x0a, 0xf4, 0x98, 0xc4, - 0x68, 0xc5, 0x06, 0x4d, 0x3d, 0x96, 0x86, 0x46, 0x5f, 0x83, 0xe3, 0x7e, 0xf0, 0x3a, 0x14, 0xac, - 0xf2, 0x3d, 0x94, 0xee, 0x86, 0xfd, 0x3d, 0xa3, 0xde, 0xe3, 0x55, 0x89, 0xbf, 0x88, 0xe6, 0x6d, - 0x09, 0x1a, 0x27, 0xa7, 0x30, 0xa5, 0xf7, 0xbc, 0xb6, 0x7a, 0x74, 0x25, 0xd9, 0x5e, 0x4e, 0xe3, - 0x7b, 0x8c, 0xbd, 0x50, 0x2a, 0x7a, 0x0a, 0x45, 0xfb, 0xf5, 0x37, 0xbc, 0x1e, 0x6f, 0xa6, 0x8f, - 0x32, 0xf8, 0x60, 0xc4, 0x8b, 0xd2, 0xd7, 0x0c, 0x9a, 0x52, 0xbe, 0xf4, 0xbb, 0x10, 0x3d, 0x12, - 0xa1, 0x52, 0xc6, 0x65, 0x37, 0x3b, 0xf0, 0xb6, 0x4c, 0x6b, 0x26, 0xc1, 0x33, 0xc1, 0x79, 0x0c, - 0xd3, 0x66, 0xa5, 0xae, 0x57, 0xd7, 0xff, 0xf5, 0xd9, 0x95, 0xe1, 0x44, 0x93, 0xc6, 0x7d, 0xa4, - 0xbf, 0xed, 0xa1, 0xbf, 0x66, 0x95, 0xd5, 0xec, 0xb7, 0xb3, 0xd9, 0x13, 0x3b, 0xec, 0xe1, 0x39, - 0x2a, 0x0f, 0xa0, 0x27, 0xc4, 0x33, 0x48, 0xbf, 0x21, 0xb1, 0xaf, 0x97, 0x37, 0xb2, 0xb0, 0xab, - 0x81, 0x1f, 0x9e, 0xab, 0x2b, 0x46, 0x7e, 0xef, 0x18, 0x8f, 0xc2, 0xe0, 0xbf, 0x3b, 0xba, 0x29, - 0x1d, 0xdd, 0x28, 0x5f, 0xcf, 0x74, 0xd4, 0x09, 0x2d, 0x57, 0x0f, 0x61, 0x42, 0x3f, 0x25, 0xd3, - 0xa1, 0xea, 0xbd, 0x2f, 0xcb, 0x29, 0x6d, 0x59, 0xaf, 0x4a, 0xd3, 0x8a, 0x51, 0x41, 0xb8, 0x39, - 0xd7, 0x28, 0x27, 0x00, 0xbd, 0x17, 0xd8, 0xb0, 0xd6, 0x91, 0xfd, 0x39, 0x5d, 0x8e, 0x99, 0x42, - 0xa9, 0xf2, 0x4e, 0xb8, 0xe5, 0xdc, 0x76, 0xd0, 0x53, 0x28, 0x58, 0x3f, 0x17, 0xae, 0x96, 0xbb, - 0x19, 0xbf, 0x2f, 0x70, 0x49, 0x3a, 0x41, 0x68, 0xd6, 0x76, 0x12, 0x08, 0xc8, 0x93, 0xc4, 0xc3, - 0xb1, 0xd7, 0x25, 0x28, 0x29, 0x5a, 0x0f, 0x28, 0x6f, 0xcb, 0x17, 0xe8, 0x50, 0xd5, 0x5c, 0x93, - 0x98, 0xcb, 0x68, 0xd1, 0xc6, 0x6c, 0x9a, 0x6d, 0xe8, 0x04, 0xf2, 0xc9, 0xf3, 0x38, 0x5d, 0x0d, - 0xec, 0x57, 0xf3, 0x95, 0xa2, 0x22, 0x0a, 0xaf, 0xbe, 0xc8, 0xdb, 0xce, 0x5e, 0xe9, 0xe5, 0xab, - 0x75, 0xe7, 0xb7, 0x57, 0xeb, 0xce, 0x9f, 0xaf, 0xd6, 0x9d, 0xaf, 0xac, 0xff, 0xdd, 0x9c, 0x8e, - 0x4b, 0x86, 0x6f, 0xff, 0x13, 0x00, 0x00, 0xff, 0xff, 0x05, 0xf4, 0xfb, 0xef, 0xe0, 0x11, 0x00, - 0x00, + // 1644 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x58, 0x5b, 0x6f, 0x1b, 0xc7, + 0x15, 0xee, 0xca, 0xd4, 0x85, 0x87, 0xd4, 0x6d, 0x74, 0xa3, 0x28, 0x5b, 0x52, 0xc7, 0x75, 0xab, + 0xca, 0x10, 0xd7, 0x55, 0x0b, 0xb4, 0x95, 0xdb, 0x02, 0x92, 0x4c, 0x17, 0x42, 0xd5, 0x5a, 0x5d, + 0x55, 0x50, 0x13, 0x3b, 0xb1, 0x57, 0xdc, 0x21, 0xb5, 0xd1, 0xee, 0xce, 0x78, 0x76, 0x49, 0x47, + 0x10, 0xf4, 0x12, 0x04, 0xc8, 0x0f, 0xc8, 0x2f, 0xca, 0x9b, 0x1f, 0x03, 0x04, 0xc8, 0x63, 0x10, + 0x18, 0xf9, 0x21, 0xc1, 0xdc, 0x96, 0xbb, 0xbc, 0xc8, 0x8a, 0x5f, 0x84, 0x39, 0x3b, 0x33, 0xdf, + 0xf9, 0xe6, 0xcc, 0x77, 0xce, 0x19, 0x0a, 0xa6, 0x62, 0xc2, 0x3b, 0x7e, 0x83, 0xc4, 0x35, 0xc6, + 0x69, 0x42, 0x11, 0x34, 0x68, 0x94, 0x70, 0x1a, 0x04, 0x84, 0x57, 0xef, 0xb6, 0x28, 0x6d, 0x05, + 0xc4, 0x76, 0x99, 0x6f, 0xbb, 0x51, 0x44, 0x13, 0x37, 0xf1, 0x69, 0xa4, 0x57, 0x56, 0x2b, 0x2c, + 0xb9, 0x64, 0x24, 0xb6, 0x49, 0xc8, 0x92, 0x4b, 0xf5, 0x57, 0xcf, 0xac, 0xea, 0x19, 0xaf, 0xcd, + 0xe5, 0x8e, 0x74, 0xa0, 0xe7, 0xb7, 0x5a, 0x7e, 0x72, 0xde, 0x3e, 0xab, 0x35, 0x68, 0x68, 0xb7, + 0x68, 0x8b, 0xda, 0xf2, 0xf3, 0x59, 0xbb, 0x29, 0x2d, 0x69, 0xc8, 0x91, 0x5e, 0xfe, 0xa7, 0xcc, + 0x72, 0xcf, 0x4d, 0xdc, 0x06, 0x0d, 0xb6, 0x7c, 0x6a, 0x86, 0x92, 0x5d, 0x48, 0x3d, 0x12, 0xc4, + 0xb6, 0x74, 0xab, 0x76, 0xe1, 0xc7, 0x50, 0x3a, 0xf4, 0xe3, 0xc4, 0x21, 0xaf, 0xdb, 0x24, 0x4e, + 0xd0, 0x22, 0x8c, 0xd1, 0x66, 0x33, 0x26, 0x49, 0xc5, 0x5a, 0xb7, 0x36, 0x46, 0x1d, 0x6d, 0xa1, + 0x79, 0x18, 0x0d, 0xfc, 0xd0, 0x4f, 0x2a, 0x23, 0xf2, 0xb3, 0x32, 0xf0, 0x6f, 0xa0, 0xac, 0x36, + 0xc7, 0x8c, 0x46, 0x31, 0x11, 0xab, 0xfc, 0x84, 0x84, 0x71, 0xc5, 0x5a, 0xbf, 0xb3, 0x51, 0x74, + 0x94, 0x81, 0x1f, 0x03, 0xec, 0x32, 0x66, 0x3c, 0x20, 0x28, 0x44, 0x6e, 0x48, 0x24, 0x7e, 0xd1, + 0x91, 0x63, 0xb4, 0x0c, 0x13, 0x9c, 0x30, 0xfa, 0xb2, 0xcd, 0x03, 0xe9, 0xa0, 0xe8, 0x8c, 0x0b, + 0xfb, 0x84, 0x07, 0xb8, 0x09, 0xd3, 0xbb, 0x8c, 0xe5, 0xbc, 0x3c, 0x80, 0x82, 0xcb, 0x98, 0x72, + 0x52, 0xda, 0x2e, 0xd5, 0xd4, 0xa9, 0x6a, 0xbb, 0x8c, 0xed, 0x15, 0xde, 0xfe, 0xb0, 0xf6, 0x2b, + 0x47, 0x4e, 0x0f, 0xa6, 0x9c, 0x39, 0xe0, 0x9d, 0xec, 0x01, 0xf1, 0xef, 0xa1, 0xb4, 0xdb, 0x4e, + 0xce, 0x0d, 0xcb, 0x2a, 0x4c, 0x30, 0x37, 0x8e, 0xdf, 0x50, 0xee, 0x69, 0xa6, 0xa9, 0x8d, 0xbf, + 0xb4, 0xa0, 0xac, 0xd6, 0x6a, 0x42, 0x08, 0x0a, 0xe7, 0x34, 0x4e, 0xcc, 0x91, 0xc4, 0x38, 0x3d, + 0xe6, 0x48, 0xe6, 0x98, 0x15, 0x18, 0x67, 0x9c, 0x7e, 0x46, 0x1a, 0xca, 0x79, 0xd1, 0x31, 0xa6, + 0x60, 0xc5, 0x49, 0xcb, 0xa7, 0x51, 0xa5, 0x20, 0x27, 0xb4, 0x25, 0x69, 0x70, 0xda, 0xf1, 0x3d, + 0xc2, 0x2b, 0xa3, 0x9a, 0x86, 0xb6, 0xf1, 0x0b, 0x40, 0xfb, 0x9c, 0xb8, 0x09, 0xd9, 0x6b, 0xfb, + 0x81, 0x67, 0x88, 0xcf, 0xc0, 0x1d, 0x97, 0x31, 0x4d, 0x45, 0x0c, 0x85, 0xd7, 0x0e, 0xe1, 0xb1, + 0x00, 0xd7, 0xb1, 0xd5, 0xa6, 0x46, 0x6f, 0x34, 0xfd, 0x80, 0x48, 0x42, 0x65, 0x27, 0xb5, 0xf1, + 0x23, 0x28, 0xef, 0x32, 0x76, 0x70, 0x03, 0xee, 0x14, 0x8c, 0xf8, 0x9e, 0x86, 0x1c, 0xf1, 0x3d, + 0x5c, 0x87, 0x69, 0xc9, 0xe4, 0x90, 0xb6, 0x6e, 0xbd, 0x49, 0xac, 0x60, 0x34, 0xd6, 0x77, 0x21, + 0x86, 0x78, 0x07, 0x66, 0xba, 0x30, 0x3a, 0xc0, 0x7a, 0x95, 0x95, 0xae, 0x52, 0x97, 0x1b, 0x91, + 0xb8, 0x32, 0xa2, 0x94, 0x26, 0x0d, 0xfc, 0x67, 0x98, 0xac, 0x47, 0x9d, 0x63, 0x92, 0xdc, 0x24, + 0x36, 0x04, 0x05, 0x91, 0x13, 0xe6, 0x66, 0xc4, 0x18, 0x3f, 0x85, 0x79, 0x87, 0xc4, 0xb4, 0xcd, + 0x1b, 0x24, 0x27, 0xb5, 0x1a, 0x14, 0xb9, 0xfe, 0x6e, 0xf4, 0x36, 0x63, 0xf4, 0x66, 0x36, 0x38, + 0xdd, 0x25, 0x78, 0x07, 0xa6, 0x52, 0xb5, 0x0e, 0x67, 0x30, 0x38, 0x99, 0x76, 0x60, 0x56, 0x1d, + 0x3c, 0xaf, 0xf5, 0xb1, 0x33, 0xf1, 0xd1, 0x78, 0x9f, 0x34, 0xde, 0xd5, 0xa5, 0xeb, 0x49, 0xfc, + 0x37, 0x98, 0x3b, 0xe2, 0xb4, 0x41, 0xe2, 0xb8, 0x67, 0xf7, 0xe8, 0x41, 0x9a, 0x8f, 0xa5, 0xed, + 0x69, 0xb3, 0x59, 0xaf, 0x75, 0xd4, 0x2c, 0xfe, 0xc6, 0x82, 0x05, 0x25, 0xa5, 0xf4, 0x4c, 0x37, + 0xc7, 0xef, 0xc2, 0x8f, 0xcc, 0x25, 0xca, 0x31, 0xaa, 0xc3, 0x18, 0x73, 0xb9, 0x1b, 0x8a, 0x9b, + 0x14, 0x9e, 0xb6, 0x6a, 0xdd, 0xfa, 0x58, 0x1b, 0x08, 0x5d, 0x3b, 0x92, 0xeb, 0xeb, 0x51, 0xc2, + 0x2f, 0x1d, 0xbd, 0xb9, 0xfa, 0x57, 0x28, 0x65, 0x3e, 0x8b, 0x6b, 0xbf, 0x20, 0x97, 0x46, 0x3e, + 0x17, 0xe4, 0x52, 0x44, 0xae, 0xe3, 0x06, 0x6d, 0x93, 0x56, 0xca, 0xd8, 0x19, 0xf9, 0x8b, 0x85, + 0xff, 0x21, 0x23, 0x9f, 0x71, 0x32, 0x40, 0x7c, 0x55, 0x51, 0x66, 0xd4, 0x02, 0x0d, 0x90, 0xda, + 0x78, 0x1d, 0xe0, 0x5f, 0xed, 0x33, 0xd2, 0x48, 0x02, 0xb1, 0x17, 0x41, 0xc1, 0xe5, 0x2d, 0x53, + 0xc7, 0xe4, 0x18, 0x07, 0x50, 0xda, 0x0f, 0xbd, 0x34, 0xb6, 0x2b, 0x50, 0x24, 0x9f, 0xfb, 0xc9, + 0xcb, 0x06, 0xf5, 0x88, 0x56, 0xe6, 0x84, 0xf8, 0xb0, 0x4f, 0x3d, 0x29, 0x58, 0xc2, 0xb9, 0x76, + 0x22, 0x86, 0x22, 0xc3, 0xe3, 0xc4, 0x7b, 0xd6, 0x36, 0xa9, 0xaf, 0x2d, 0xfd, 0xbd, 0xce, 0xb9, + 0xc9, 0x7c, 0x65, 0xe1, 0xaf, 0x2c, 0x28, 0x1f, 0xd2, 0xd6, 0x71, 0xc2, 0x89, 0x1b, 0x6a, 0x4a, + 0x7d, 0x57, 0xb1, 0x08, 0x63, 0x4d, 0x1a, 0x04, 0xf4, 0x8d, 0xf4, 0x34, 0xe1, 0x68, 0x0b, 0xd9, + 0x30, 0x1a, 0xfb, 0x51, 0x43, 0x65, 0x75, 0x69, 0x7b, 0xb9, 0xa6, 0x3a, 0x54, 0xcd, 0x34, 0x90, + 0xda, 0x13, 0xdd, 0x69, 0x1c, 0xb5, 0xce, 0x54, 0x02, 0xd1, 0x18, 0x34, 0x8f, 0xd4, 0xc6, 0x7f, + 0x87, 0x49, 0xa3, 0x97, 0x76, 0x34, 0x8c, 0x49, 0x05, 0xc6, 0x1b, 0x34, 0x0c, 0x5d, 0xa9, 0x0b, + 0x11, 0x33, 0x63, 0xe2, 0x35, 0x28, 0xaa, 0x43, 0xfc, 0x3b, 0x6e, 0xa5, 0xb9, 0x67, 0xc9, 0x6a, + 0xa3, 0x72, 0x6f, 0x0f, 0xe6, 0x1c, 0x12, 0x10, 0x37, 0xce, 0xa7, 0xde, 0x43, 0x71, 0x59, 0xf2, + 0x73, 0x9f, 0x7c, 0xf5, 0x72, 0x27, 0x5d, 0x80, 0x8f, 0x61, 0xde, 0xa8, 0x4c, 0x4d, 0x69, 0xfd, + 0xde, 0x87, 0x51, 0x99, 0x21, 0xd2, 0x61, 0x5f, 0xf6, 0xa8, 0x39, 0x11, 0x45, 0x8f, 0x86, 0xae, + 0x6f, 0xea, 0xa3, 0xb6, 0xf0, 0x6f, 0x01, 0x09, 0x46, 0x4f, 0xa4, 0xe5, 0x90, 0xd7, 0x69, 0x2d, + 0x12, 0x6d, 0x4a, 0x29, 0x43, 0x0c, 0xb7, 0xbf, 0x9f, 0x87, 0xe9, 0x23, 0x5d, 0x95, 0x8f, 0xd5, + 0x33, 0x01, 0xfd, 0x07, 0x0a, 0xa2, 0x45, 0xa0, 0xa5, 0x6c, 0x22, 0x64, 0x1a, 0x4c, 0xb5, 0xd2, + 0x3f, 0xa1, 0x0e, 0x8e, 0xe7, 0xbe, 0xf8, 0xee, 0xa7, 0xaf, 0x47, 0x26, 0xf1, 0x84, 0xdd, 0xf9, + 0x83, 0xed, 0xb6, 0x93, 0xf3, 0x1d, 0x6b, 0x13, 0xfd, 0x17, 0xc6, 0x75, 0x61, 0xc9, 0x43, 0x66, + 0x4a, 0x4d, 0x75, 0x25, 0x07, 0x99, 0x6f, 0x9a, 0x78, 0x46, 0xa2, 0x02, 0x52, 0xa8, 0xa2, 0x3f, + 0xd6, 0xa1, 0xb8, 0xcb, 0x98, 0x0a, 0x1b, 0x5a, 0xec, 0xd9, 0x6b, 0x30, 0xb3, 0xdd, 0xb5, 0x87, + 0x19, 0x63, 0xb1, 0x60, 0xf6, 0x14, 0xc6, 0x76, 0x19, 0xfb, 0x27, 0x49, 0x6e, 0x87, 0xb1, 0x24, + 0x31, 0x66, 0xd1, 0xb4, 0xc1, 0xb0, 0xaf, 0x84, 0x80, 0xae, 0xd1, 0x27, 0xfa, 0x95, 0x10, 0x27, + 0x2e, 0x1f, 0x8e, 0xb5, 0xd8, 0x27, 0xe5, 0xba, 0x78, 0x51, 0xe1, 0x35, 0x09, 0xbb, 0x8c, 0x96, + 0x7a, 0x60, 0x6d, 0xae, 0x01, 0xff, 0x27, 0x4f, 0xfb, 0x84, 0x04, 0xe4, 0x86, 0xd3, 0x0e, 0x43, + 0xd7, 0xa4, 0x37, 0xfb, 0x48, 0xbf, 0x92, 0xaf, 0x93, 0x13, 0xe6, 0xb9, 0x09, 0x51, 0x3a, 0x41, + 0xd5, 0x3e, 0xec, 0xb4, 0x24, 0x0d, 0xc5, 0x5f, 0x96, 0xf8, 0x73, 0xd5, 0x59, 0x81, 0xaf, 0xd4, + 0x17, 0xdb, 0x57, 0x2e, 0x63, 0xd7, 0xe8, 0x08, 0x4a, 0x52, 0xac, 0xfa, 0x9e, 0x56, 0xfb, 0x0b, + 0x6b, 0xb6, 0xfd, 0x57, 0xf3, 0x0a, 0xc7, 0x48, 0x02, 0x97, 0x31, 0x08, 0x60, 0xd5, 0x2b, 0xd0, + 0x47, 0x1a, 0xf1, 0x20, 0x64, 0x94, 0x27, 0x68, 0x21, 0x8b, 0x98, 0x66, 0xea, 0xfb, 0xa8, 0xe2, + 0xd9, 0x2e, 0xa2, 0xed, 0x4b, 0xa4, 0x0d, 0x0b, 0x9d, 0x42, 0x59, 0xb3, 0x91, 0x59, 0x88, 0xd6, + 0x07, 0xb5, 0x81, 0x6c, 0x82, 0x56, 0x7b, 0x73, 0x1a, 0xcf, 0x4b, 0xfc, 0x29, 0x5c, 0x16, 0xf8, + 0x26, 0xbf, 0xd1, 0x21, 0x4c, 0x48, 0x60, 0x21, 0xb3, 0x4a, 0x4f, 0x80, 0x0f, 0x86, 0x1d, 0x3e, + 0x27, 0x35, 0x4d, 0xf5, 0xca, 0xf7, 0xae, 0xd1, 0xff, 0x75, 0x04, 0xb4, 0x1a, 0x86, 0x03, 0xde, + 0x4a, 0x0f, 0x59, 0x64, 0x17, 0x8a, 0x69, 0x0f, 0xef, 0x53, 0x42, 0x36, 0x57, 0xef, 0x65, 0xe7, + 0xfa, 0xda, 0xbe, 0x89, 0x32, 0xca, 0x46, 0x59, 0x4b, 0xce, 0x33, 0x2e, 0x68, 0x2b, 0x46, 0x2b, + 0xfd, 0x30, 0xe9, 0xeb, 0xab, 0x7a, 0x77, 0xf0, 0xa4, 0x76, 0x71, 0x57, 0xba, 0x58, 0x44, 0xf3, + 0x3d, 0x67, 0xb0, 0x03, 0x01, 0x7c, 0x0c, 0x53, 0xf5, 0xa8, 0xe3, 0x73, 0x1a, 0x85, 0x24, 0x4a, + 0x6e, 0xca, 0xee, 0x59, 0x13, 0xf4, 0x7a, 0xd4, 0xd9, 0xa7, 0x51, 0xd3, 0x6f, 0xe1, 0x45, 0x09, + 0x3d, 0x83, 0xa6, 0x04, 0x34, 0x89, 0x3a, 0x86, 0xfa, 0xf3, 0x1c, 0xe8, 0x31, 0x49, 0xd0, 0x72, + 0x16, 0x34, 0xf7, 0x74, 0x1b, 0x1a, 0x7b, 0x0d, 0x8e, 0x7b, 0xc1, 0x1b, 0x50, 0xca, 0xb4, 0x91, + 0xa1, 0x74, 0xd7, 0xb2, 0xdf, 0x07, 0xf4, 0x1d, 0xbc, 0x22, 0xf1, 0x17, 0xd0, 0x5c, 0x56, 0x80, + 0xc6, 0xc9, 0x19, 0x4c, 0xea, 0x3d, 0x1f, 0xac, 0x1d, 0x5d, 0xa9, 0x36, 0x97, 0xf2, 0xf8, 0x22, + 0xd9, 0x95, 0x86, 0x5e, 0x41, 0x39, 0xfb, 0x16, 0x1d, 0x5e, 0xef, 0xd7, 0xf3, 0x47, 0xe9, 0x7f, + 0xbe, 0xe2, 0x05, 0xe9, 0x6b, 0x1a, 0x4d, 0x2a, 0x5f, 0xfa, 0x95, 0x8a, 0x4e, 0x44, 0xa8, 0x94, + 0x71, 0xd3, 0xcd, 0xf6, 0xbd, 0x74, 0xf3, 0x9a, 0x49, 0xf1, 0x4c, 0x70, 0x5e, 0xc0, 0x94, 0x59, + 0xa9, 0xab, 0xd5, 0xaf, 0xdf, 0xfb, 0x0c, 0x1c, 0xe0, 0x44, 0x93, 0xc6, 0x3d, 0xa4, 0x3f, 0xed, + 0xa2, 0x7f, 0x60, 0x15, 0xd7, 0xec, 0x37, 0x07, 0xb3, 0xf7, 0xb3, 0x61, 0x8f, 0x2e, 0x6e, 0xac, + 0xe3, 0xfd, 0xa4, 0x1f, 0x4a, 0xec, 0x07, 0xd5, 0xfb, 0x3d, 0xd8, 0xf2, 0x5a, 0x03, 0x3f, 0xba, + 0xb0, 0xaf, 0xcc, 0xd7, 0x6b, 0x14, 0x76, 0x8f, 0x72, 0x12, 0x05, 0xbf, 0xdc, 0xd9, 0x96, 0x74, + 0xf6, 0xbb, 0xea, 0x83, 0x41, 0xce, 0xda, 0x51, 0xaf, 0xbb, 0x67, 0x30, 0xae, 0x9f, 0xb6, 0xf9, + 0x90, 0x75, 0xdf, 0xbb, 0xd5, 0x9c, 0xc6, 0x32, 0xaf, 0x5c, 0xd3, 0xf2, 0x51, 0x49, 0xb8, 0xba, + 0xd0, 0x28, 0xa7, 0x00, 0xdd, 0x17, 0xe1, 0xb0, 0x06, 0x32, 0xf8, 0x73, 0xbe, 0x28, 0x33, 0x85, + 0x62, 0xf3, 0x76, 0xb4, 0x61, 0x3d, 0xb2, 0xd0, 0x73, 0x28, 0x65, 0x7e, 0xc6, 0xdc, 0x2e, 0x87, + 0x07, 0xfc, 0xee, 0xc9, 0xb3, 0xd6, 0x4e, 0xd0, 0x69, 0x0a, 0x7e, 0xec, 0x76, 0x08, 0x4a, 0xeb, + 0xd6, 0x53, 0xca, 0x43, 0xf9, 0x18, 0x1e, 0x2a, 0x9c, 0x7b, 0x12, 0x6e, 0x09, 0x2d, 0x64, 0x39, + 0x37, 0xcd, 0x36, 0x74, 0x0a, 0xc5, 0xf4, 0xa5, 0x9e, 0x2f, 0x08, 0xd9, 0x07, 0xfc, 0xad, 0x02, + 0x22, 0x6a, 0xaf, 0x16, 0xe4, 0x23, 0x6b, 0xaf, 0xf2, 0xf6, 0xdd, 0xaa, 0xf5, 0xed, 0xbb, 0x55, + 0xeb, 0xc7, 0x77, 0xab, 0xd6, 0xc7, 0x99, 0x7f, 0x39, 0x9d, 0x8d, 0x49, 0x86, 0x7f, 0xfc, 0x39, + 0x00, 0x00, 0xff, 0xff, 0x5e, 0xa0, 0x75, 0x51, 0x97, 0x12, 0x00, 0x00, } diff --git a/api/controller/services.pb.gw.go b/api/controller/services.pb.gw.go index bc193e4b..897ebca3 100644 --- a/api/controller/services.pb.gw.go +++ b/api/controller/services.pb.gw.go @@ -177,6 +177,41 @@ func request_ProviderService_AppDelete_0(ctx context.Context, marshaler runtime. } +var ( + filter_ProviderService_AppUpdateDomain_0 = &utilities.DoubleArray{Encoding: map[string]int{"app": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}} +) + +func request_ProviderService_AppUpdateDomain_0(ctx context.Context, marshaler runtime.Marshaler, client ProviderServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq AppResourceReq + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["app"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "app") + } + + protoReq.App, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "app", err) + } + + if err := runtime.PopulateQueryParameters(&protoReq, req.URL.Query(), filter_ProviderService_AppUpdateDomain_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := client.AppUpdateDomain(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + var ( filter_ProviderService_BuildCreate_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} ) @@ -327,7 +362,7 @@ var ( ) func request_ProviderService_BuildList_0(ctx context.Context, marshaler runtime.Marshaler, client ProviderServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq BuildListRequest + var protoReq AppListRequest var metadata runtime.ServerMetadata var ( @@ -650,26 +685,26 @@ func request_ProviderService_ResourceLink_0(ctx context.Context, marshaler runti _ = err ) - val, ok = pathParams["name"] + val, ok = pathParams["app"] if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "name") + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "app") } - protoReq.Name, err = runtime.String(val) + protoReq.App, err = runtime.String(val) if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "name", err) + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "app", err) } - val, ok = pathParams["app"] + val, ok = pathParams["resource"] if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "app") + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "resource") } - protoReq.App, err = runtime.String(val) + protoReq.Resource, err = runtime.String(val) if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "app", err) + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "resource", err) } msg, err := client.ResourceLink(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) @@ -688,26 +723,26 @@ func request_ProviderService_ResourceUnlink_0(ctx context.Context, marshaler run _ = err ) - val, ok = pathParams["name"] + val, ok = pathParams["app"] if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "name") + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "app") } - protoReq.Name, err = runtime.String(val) + protoReq.App, err = runtime.String(val) if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "name", err) + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "app", err) } - val, ok = pathParams["app"] + val, ok = pathParams["resource"] if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "app") + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "resource") } - protoReq.App, err = runtime.String(val) + protoReq.Resource, err = runtime.String(val) if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "app", err) + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "resource", err) } msg, err := client.ResourceUnlink(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) @@ -1073,6 +1108,35 @@ func RegisterProviderServiceHandlerClient(ctx context.Context, mux *runtime.Serv }) + mux.Handle("PUT", pattern_ProviderService_AppUpdateDomain_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(ctx) + defer cancel() + if cn, ok := w.(http.CloseNotifier); ok { + go func(done <-chan struct{}, closed <-chan bool) { + select { + case <-done: + case <-closed: + cancel() + } + }(ctx.Done(), cn.CloseNotify()) + } + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_ProviderService_AppUpdateDomain_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_ProviderService_AppUpdateDomain_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + mux.Handle("POST", pattern_ProviderService_BuildCreate_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(ctx) defer cancel() @@ -1727,6 +1791,8 @@ var ( pattern_ProviderService_AppDelete_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2}, []string{"v1", "apps", "name"}, "")) + pattern_ProviderService_AppUpdateDomain_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2}, []string{"v1", "domains", "app"}, "")) + pattern_ProviderService_BuildCreate_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"v1", "builds"}, "")) pattern_ProviderService_BuildImport_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v1", "builds", "import"}, "")) @@ -1757,15 +1823,15 @@ var ( pattern_ProviderService_ResourceDelete_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2}, []string{"v1", "resources", "name"}, "")) - pattern_ProviderService_ResourceLink_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"v1", "resources", "name", "link", "app"}, "")) + pattern_ProviderService_ResourceLink_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"v1", "resources", "app", "link", "resource"}, "")) - pattern_ProviderService_ResourceUnlink_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"v1", "resources", "name", "unlink", "app"}, "")) + pattern_ProviderService_ResourceUnlink_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"v1", "resources", "app", "unlink", "resource"}, "")) pattern_ProviderService_Kubectl_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"v1", "kubectl"}, "")) pattern_ProviderService_ProcessRun_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v1", "process", "run"}, "")) - pattern_ProviderService_ProcessList_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v1", "process", "list"}, "")) + pattern_ProviderService_ProcessList_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"v1", "process"}, "")) pattern_ProviderService_ProcessSave_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v1", "process", "formation"}, "")) @@ -1785,6 +1851,8 @@ var ( forward_ProviderService_AppDelete_0 = runtime.ForwardResponseMessage + forward_ProviderService_AppUpdateDomain_0 = runtime.ForwardResponseMessage + forward_ProviderService_BuildCreate_0 = runtime.ForwardResponseMessage forward_ProviderService_BuildImport_0 = runtime.ForwardResponseMessage diff --git a/api/controller/services.proto b/api/controller/services.proto index 03579473..a6668156 100644 --- a/api/controller/services.proto +++ b/api/controller/services.proto @@ -17,6 +17,10 @@ message ListRequest { int32 limit = 2; } +message ListResponse { + repeated string items = 1; +} + message AppRequest { string name = 1; string repo_url = 2; @@ -71,8 +75,7 @@ message ResourceListResponse { repeated models.Resource resources = 1; } - -message BuildListRequest { +message AppListRequest { string name = 1; int32 limit = 2; } @@ -93,7 +96,7 @@ message CreateResourceRequest { message AppResourceReq { string app = 1; - string name = 2; + string resource = 2; } message KubectlReq { @@ -132,6 +135,10 @@ message CreateReleaseRequest { string domain = 2; } +message ListDomainReqponse { + repeated string url = 1; +} + service ProviderService { rpc Auth(AuthRequest) returns (AuthResponse) { option (google.api.http) = { @@ -172,6 +179,13 @@ service ProviderService { }; } + //Update Domain API + rpc AppUpdateDomain(AppResourceReq) returns (google.protobuf.Empty) { + option (google.api.http) = { + put: "/v1/domains/{app}" + }; + } + //Build Api rpc BuildCreate(CreateBuildRequest) returns (models.Build) { option (google.api.http) = { @@ -203,7 +217,7 @@ service ProviderService { }; } - rpc BuildList(BuildListRequest) returns (BuildListResponse) { + rpc BuildList(AppListRequest) returns (BuildListResponse) { option (google.api.http) = { get: "/v1/builds/{name}" }; @@ -267,13 +281,13 @@ service ProviderService { rpc ResourceLink(AppResourceReq) returns (models.Resource) { option (google.api.http) = { - put: "/v1/resources/{name}/link/{app}" + put: "/v1/resources/{app}/link/{resource}" }; } rpc ResourceUnlink(AppResourceReq) returns (models.Resource) { option (google.api.http) = { - put: "/v1/resources/{name}/unlink/{app}" + put: "/v1/resources/{app}/unlink/{resource}" }; } @@ -293,7 +307,7 @@ service ProviderService { rpc ProcessList(AppRequest) returns (ProcessListResponse) { option (google.api.http) = { - get: "/v1/process/list" + get: "/v1/process" }; } diff --git a/api/controller/services.swagger.json b/api/controller/services.swagger.json index 915f6feb..4d90c143 100644 --- a/api/controller/services.swagger.json +++ b/api/controller/services.swagger.json @@ -333,6 +333,31 @@ ] } }, + "/v1/domains/{app}": { + "put": { + "summary": "Update Domain API", + "operationId": "AppUpdateDomain", + "responses": { + "200": { + "description": "", + "schema": { + "$ref": "#/definitions/protobufEmpty" + } + } + }, + "parameters": [ + { + "name": "app", + "in": "path", + "required": true, + "type": "string" + } + ], + "tags": [ + "ProviderService" + ] + } + }, "/v1/env/{name}": { "get": { "operationId": "EnvironmentGet", @@ -467,20 +492,26 @@ ] } }, - "/v1/process/formation": { + "/v1/process": { "get": { - "operationId": "ProcessSave", + "operationId": "ProcessList", "responses": { "200": { "description": "", "schema": { - "$ref": "#/definitions/protobufEmpty" + "$ref": "#/definitions/controllerProcessListResponse" } } }, "parameters": [ { - "name": "app", + "name": "name", + "in": "query", + "required": false, + "type": "string" + }, + { + "name": "repo_url", "in": "query", "required": false, "type": "string" @@ -491,26 +522,20 @@ ] } }, - "/v1/process/list": { + "/v1/process/formation": { "get": { - "operationId": "ProcessList", + "operationId": "ProcessSave", "responses": { "200": { "description": "", "schema": { - "$ref": "#/definitions/controllerProcessListResponse" + "$ref": "#/definitions/protobufEmpty" } } }, "parameters": [ { - "name": "name", - "in": "query", - "required": false, - "type": "string" - }, - { - "name": "repo_url", + "name": "app", "in": "query", "required": false, "type": "string" @@ -671,9 +696,9 @@ ] } }, - "/v1/resources/{name}": { - "get": { - "operationId": "ResourceGet", + "/v1/resources/{app}/link/{resource}": { + "put": { + "operationId": "ResourceLink", "responses": { "200": { "description": "", @@ -684,35 +709,43 @@ }, "parameters": [ { - "name": "name", + "name": "app", "in": "path", "required": true, "type": "string" }, { - "name": "repo_url", - "in": "query", - "required": false, + "name": "resource", + "in": "path", + "required": true, "type": "string" } ], "tags": [ "ProviderService" ] - }, - "delete": { - "operationId": "ResourceDelete", + } + }, + "/v1/resources/{app}/unlink/{resource}": { + "put": { + "operationId": "ResourceUnlink", "responses": { "200": { "description": "", "schema": { - "$ref": "#/definitions/protobufEmpty" + "$ref": "#/definitions/modelsResource" } } }, "parameters": [ { - "name": "name", + "name": "app", + "in": "path", + "required": true, + "type": "string" + }, + { + "name": "resource", "in": "path", "required": true, "type": "string" @@ -723,9 +756,9 @@ ] } }, - "/v1/resources/{name}/link/{app}": { - "put": { - "operationId": "ResourceLink", + "/v1/resources/{name}": { + "get": { + "operationId": "ResourceGet", "responses": { "200": { "description": "", @@ -742,25 +775,23 @@ "type": "string" }, { - "name": "app", - "in": "path", - "required": true, + "name": "repo_url", + "in": "query", + "required": false, "type": "string" } ], "tags": [ "ProviderService" ] - } - }, - "/v1/resources/{name}/unlink/{app}": { - "put": { - "operationId": "ResourceUnlink", + }, + "delete": { + "operationId": "ResourceDelete", "responses": { "200": { "description": "", "schema": { - "$ref": "#/definitions/modelsResource" + "$ref": "#/definitions/protobufEmpty" } } }, @@ -770,12 +801,6 @@ "in": "path", "required": true, "type": "string" - }, - { - "name": "app", - "in": "path", - "required": true, - "type": "string" } ], "tags": [ diff --git a/api/domains.go b/api/domains.go new file mode 100644 index 00000000..62e98e2f --- /dev/null +++ b/api/domains.go @@ -0,0 +1,37 @@ +package main + +import ( + "fmt" + + pbs "github.com/datacol-io/datacol/api/controller" + pb "github.com/datacol-io/datacol/api/models" + "github.com/golang/protobuf/ptypes/empty" + "golang.org/x/net/context" +) + +func (s *Server) AppUpdateDomain(ctx context.Context, req *pbs.AppResourceReq) (*empty.Empty, error) { + empty := &empty.Empty{} + if err := s.Provider.AppUpdateDomain(req.App, req.Resource); err != nil { + return nil, internalError(err, "Failed to add domain") + } + + // kick-off a new release to make it real into ingress + + app, err := s.Provider.AppGet(req.App) + if err != nil { + return nil, internalError(err, "Failed to fetch app") + } + + if app.BuildId == "" { + return empty, nil + } + + b, err := s.Provider.BuildGet(app.Name, app.BuildId) + if err != nil { + return nil, internalError(err, fmt.Sprintf("Failed to fetch build by %s", app.BuildId)) + } + + _, err = s.Provider.BuildRelease(b, pb.ReleaseOptions{}) + + return empty, err +} diff --git a/api/models/extra.go b/api/models/extra.go index 0c1da54e..795366f4 100644 --- a/api/models/extra.go +++ b/api/models/extra.go @@ -36,6 +36,7 @@ type Apps []*App type Builds []*Build type Releases []*Release type Resources []*Resource +type AppDomains []string type ReleaseOptions struct { Port int diff --git a/api/server.go b/api/server.go index 5b7399a3..5bbc8776 100644 --- a/api/server.go +++ b/api/server.go @@ -242,7 +242,7 @@ func (s *Server) BuildImport(stream pbs.ProviderService_BuildImportServer) error return stream.SendAndClose(emptyMsg) } -func (s *Server) BuildList(ctx context.Context, req *pbs.BuildListRequest) (*pbs.BuildListResponse, error) { +func (s *Server) BuildList(ctx context.Context, req *pbs.AppListRequest) (*pbs.BuildListResponse, error) { items, err := s.Provider.BuildList(req.Name, int(req.Limit)) if err != nil { return nil, err @@ -362,17 +362,17 @@ func (s *Server) ResourceDelete(ctx context.Context, req *pbs.AppRequest) (*empt } func (s *Server) ResourceLink(ctx context.Context, req *pbs.AppResourceReq) (*pb.Resource, error) { - ret, err := s.Provider.ResourceLink(req.App, req.Name) + ret, err := s.Provider.ResourceLink(req.App, req.Resource) if err != nil { - return nil, internalError(err, fmt.Sprintf("failed to link resource %s", req.Name)) + return nil, internalError(err, fmt.Sprintf("failed to link resource %s", req.Resource)) } return ret, nil } func (s *Server) ResourceUnlink(ctx context.Context, req *pbs.AppResourceReq) (*pb.Resource, error) { - ret, err := s.Provider.ResourceUnlink(req.App, req.Name) + ret, err := s.Provider.ResourceUnlink(req.App, req.Resource) if err != nil { - return nil, internalError(err, fmt.Sprintf("failed to unlink resource %s", req.Name)) + return nil, internalError(err, fmt.Sprintf("failed to unlink resource %s", req.Resource)) } return ret, nil } diff --git a/client/apps.go b/client/apps.go index 299cb7b4..c25848ee 100644 --- a/client/apps.go +++ b/client/apps.go @@ -37,6 +37,11 @@ func (c *Client) DeleteApp(name string) error { return err } +func (c *Client) AppDomainUpdate(name, domain string) error { + _, err := c.ProviderServiceClient.AppUpdateDomain(ctx, &pbs.AppResourceReq{App: name, Resource: domain}) + return err +} + func (c *Client) RestartApp(name string) error { _, err := c.ProviderServiceClient.AppRestart(ctx, &pbs.AppRequest{Name: name}) return err diff --git a/client/build.go b/client/build.go index bd7b155d..f5cd46ea 100644 --- a/client/build.go +++ b/client/build.go @@ -71,7 +71,7 @@ func (c *Client) CreateBuildGit(app *pb.App, version string, procfile []byte) (* } func (c *Client) GetBuilds(app string, limit int) (pb.Builds, error) { - ret, err := c.ProviderServiceClient.BuildList(ctx, &pbs.BuildListRequest{ + ret, err := c.ProviderServiceClient.BuildList(ctx, &pbs.AppListRequest{ Name: app, Limit: int32(limit), }) diff --git a/client/resource.go b/client/resource.go index 9de02ff9..4bcba22f 100644 --- a/client/resource.go +++ b/client/resource.go @@ -31,11 +31,11 @@ func (c *Client) DeleteResource(name string) error { } func (c *Client) CreateResourceLink(app, name string) error { - _, err := c.ProviderServiceClient.ResourceLink(ctx, &pbs.AppResourceReq{App: app, Name: name}) + _, err := c.ProviderServiceClient.ResourceLink(ctx, &pbs.AppResourceReq{App: app, Resource: name}) return err } func (c *Client) DeleteResourceLink(app, name string) error { - _, err := c.ProviderServiceClient.ResourceUnlink(ctx, &pbs.AppResourceReq{App: app, Name: name}) + _, err := c.ProviderServiceClient.ResourceUnlink(ctx, &pbs.AppResourceReq{App: app, Resource: name}) return err } diff --git a/cloud/aws/apps.go b/cloud/aws/apps.go index fa1ce436..7ee19a95 100644 --- a/cloud/aws/apps.go +++ b/cloud/aws/apps.go @@ -126,6 +126,19 @@ func (a *AwsCloud) AppDelete(name string) error { return nil } +// DomainUpdate updates list of Domains for an app +// domain can be example.com if you want to add or :example.com if you want to delete +func (p *AwsCloud) AppUpdateDomain(name, domain string) error { + app, err := p.AppGet(name) + if err != nil { + return err + } + + app.Domains = common.MergeAppDomains(app.Domains, domain) + + return p.saveApp(app) +} + func (p *AwsCloud) deleteAppResources(name string) error { svc := p.ecr() diff --git a/cloud/aws/releases.go b/cloud/aws/releases.go index 0f327aed..5a303973 100644 --- a/cloud/aws/releases.go +++ b/cloud/aws/releases.go @@ -3,7 +3,6 @@ package aws import ( "fmt" "os" - "strings" log "github.com/Sirupsen/logrus" "github.com/aws/aws-sdk-go/aws" @@ -11,7 +10,6 @@ import ( pb "github.com/datacol-io/datacol/api/models" "github.com/datacol-io/datacol/cloud" "github.com/datacol-io/datacol/common" - kube "github.com/datacol-io/datacol/k8s" ) func (a *AwsCloud) dynamoReleases() string { @@ -71,15 +69,6 @@ func (a *AwsCloud) BuildRelease(b *pb.Build, options pb.ReleaseOptions) (*pb.Rel return r, err } - domains := app.Domains - for _, domain := range strings.Split(options.Domain, ",") { - domains = kube.MergeAppDomains(domains, domain) - } - - if len(app.Domains) != len(domains) { - app.Domains = domains - } - app.BuildId = b.Id app.ReleaseId = r.Id rversion := fmt.Sprintf("%d", r.Version) @@ -87,7 +76,7 @@ func (a *AwsCloud) BuildRelease(b *pb.Build, options pb.ReleaseOptions) (*pb.Rel log.Debugf("Saving app state: %s err:%v", toJson(app), a.saveApp(app)) // note the mutate function if err := common.UpdateApp(a.kubeClient(), b, a.DeploymentName, - image, false, domains, envVars, cloud.AwsProvider, rversion); err != nil { + image, false, app.Domains, envVars, cloud.AwsProvider, rversion); err != nil { return nil, err } diff --git a/cloud/google/apps.go b/cloud/google/apps.go index 58b047a5..8716c485 100644 --- a/cloud/google/apps.go +++ b/cloud/google/apps.go @@ -81,6 +81,19 @@ func (g *GCPCloud) AppDelete(name string) error { return g.deleteAppFromDatastore(name) } +// DomainUpdate updates list of Domains for an app +// domain can be example.com if you want to add or :example.com if you want to delete +func (g *GCPCloud) AppUpdateDomain(name, domain string) error { + app, err := g.AppGet(name) + if err != nil { + return err + } + + app.Domains = common.MergeAppDomains(app.Domains, domain) + + return g.saveApp(app) +} + func (g *GCPCloud) saveApp(app *pb.App) error { ctx, key := g.nestedKey(appKind, app.Name) _, err := g.datastore().Put(ctx, key, app) diff --git a/cloud/google/releases.go b/cloud/google/releases.go index be7879d9..3754abeb 100644 --- a/cloud/google/releases.go +++ b/cloud/google/releases.go @@ -3,14 +3,12 @@ package google import ( "context" "fmt" - "strings" "cloud.google.com/go/datastore" log "github.com/Sirupsen/logrus" pb "github.com/datacol-io/datacol/api/models" "github.com/datacol-io/datacol/cloud" "github.com/datacol-io/datacol/common" - sched "github.com/datacol-io/datacol/k8s" ) func (g *GCPCloud) ReleaseList(app string, limit int) (pb.Releases, error) { @@ -41,11 +39,6 @@ func (g *GCPCloud) BuildRelease(b *pb.Build, options pb.ReleaseOptions) (*pb.Rel return nil, err } - domains := app.Domains - for _, domain := range strings.Split(options.Domain, ",") { - domains = sched.MergeAppDomains(domains, domain) - } - r := &pb.Release{ Id: generateId("R", 5), App: b.App, @@ -58,18 +51,10 @@ func (g *GCPCloud) BuildRelease(b *pb.Build, options pb.ReleaseOptions) (*pb.Rel rversion := fmt.Sprintf("%d", r.Version) if err := common.UpdateApp(g.kubeClient(), b, g.DeploymentName, image, g.appLinkedDB(app), - domains, envVars, cloud.GCPProvider, rversion); err != nil { + app.Domains, envVars, cloud.GCPProvider, rversion); err != nil { return nil, err } - if len(app.Domains) != len(domains) { - app.Domains = domains - - if err = g.saveApp(app); err != nil { - log.Warnf("datastore put failed: %v", err) - } - } - ctx, key := g.nestedKey(releaseKind, r.Id) _, err = g.datastore().Put(ctx, key, r) diff --git a/cloud/local/apps.go b/cloud/local/apps.go index a078aefb..c45531f2 100644 --- a/cloud/local/apps.go +++ b/cloud/local/apps.go @@ -2,8 +2,6 @@ package local import ( "fmt" - "io" - "io/ioutil" "time" "github.com/appscode/go/log" @@ -78,15 +76,15 @@ func (g *LocalCloud) AppDelete(name string) error { return nil } -func (g *LocalCloud) EnvironmentGet(name string) (pb.Environment, error) { - return common.SortEnvironment(g.EnvMap[name]), nil -} - -func (g *LocalCloud) EnvironmentSet(name string, body io.Reader) error { - data, err := ioutil.ReadAll(body) +// DomainUpdate updates list of Domains for an app +// domain can be example.com if you want to add or :example.com if you want to delete +func (g *LocalCloud) AppUpdateDomain(name, domain string) error { + app, err := g.AppGet(name) if err != nil { return err } - g.EnvMap[name] = common.LoadEnvironment(data) - return nil + + app.Domains = common.MergeAppDomains(app.Domains, domain) + + return g.saveApp(app) } diff --git a/cloud/local/environ.go b/cloud/local/environ.go new file mode 100644 index 00000000..489ea0e9 --- /dev/null +++ b/cloud/local/environ.go @@ -0,0 +1,22 @@ +package local + +import ( + "io" + "io/ioutil" + + pb "github.com/datacol-io/datacol/api/models" + "github.com/datacol-io/datacol/common" +) + +func (g *LocalCloud) EnvironmentGet(name string) (pb.Environment, error) { + return common.SortEnvironment(g.EnvMap[name]), nil +} + +func (g *LocalCloud) EnvironmentSet(name string, body io.Reader) error { + data, err := ioutil.ReadAll(body) + if err != nil { + return err + } + g.EnvMap[name] = common.LoadEnvironment(data) + return nil +} diff --git a/cloud/provider.go b/cloud/provider.go index 54be35c6..be6fc763 100644 --- a/cloud/provider.go +++ b/cloud/provider.go @@ -12,6 +12,7 @@ type Provider interface { AppDelete(string) error AppRestart(string) error AppList() (pb.Apps, error) + AppUpdateDomain(string, string) error EnvironmentGet(app string) (pb.Environment, error) EnvironmentSet(app string, body io.Reader) error diff --git a/cmd/deploy.go b/cmd/deploy.go index dbcf298a..ec8e9cc6 100644 --- a/cmd/deploy.go +++ b/cmd/deploy.go @@ -41,10 +41,6 @@ func init() { Name: "file, f", Usage: "path of Dockerfile or app.yaml", }, - &cli.StringFlag{ - Name: "domain, d", - Usage: "domain(s) to use with this app", - }, &cli.BoolTFlag{ //TODO: support expose in API Name: "expose", @@ -98,7 +94,6 @@ func cmdDeploy(c *cli.Context) error { fmt.Printf("Deploying build %s\n", build.Id) _, err = client.ReleaseBuild(build, pb.ReleaseOptions{ - Domain: c.String("domain"), Wait: c.Bool("wait"), Expose: c.BoolT("expose"), }) diff --git a/cmd/domains.go b/cmd/domains.go new file mode 100644 index 00000000..5aa7749a --- /dev/null +++ b/cmd/domains.go @@ -0,0 +1,78 @@ +package cmd + +import ( + "fmt" + + term "github.com/appscode/go/term" + "github.com/datacol-io/datacol/cmd/stdcli" + "github.com/urfave/cli" +) + +func init() { + stdcli.AddCommand(cli.Command{ + Name: "domains", + Usage: "Manage your domains for an app", + Action: cmdDomainsList, + Flags: []cli.Flag{&stackFlag}, + Subcommands: []cli.Command{ + { + Name: "add", + ArgsUsage: "", + Action: cmdAddDomain, + Flags: []cli.Flag{appFlag}, + }, + { + Name: "remove", + ArgsUsage: "", + Action: cmdRemoveDomain, + Flags: []cli.Flag{appFlag}, + }, + }, + }) +} + +func cmdDomainsList(c *cli.Context) error { + _, name, err := getDirApp(".") + stdcli.ExitOnError(err) + + api, close := getApiClient(c) + defer close() + + app, err := api.GetApp(name) + stdcli.ExitOnError(err) + + fmt.Println(toJson(app.Domains)) + return nil +} + +func cmdAddDomain(c *cli.Context) error { + stdcli.ExitOnError(modifyDomain(c, false)) + term.Infoln("DONE") + return nil +} + +func cmdRemoveDomain(c *cli.Context) error { + stdcli.ExitOnError(modifyDomain(c, true)) + term.Infoln("DONE") + return nil +} + +func modifyDomain(c *cli.Context, delete bool) error { + _, name, err := getDirApp(".") + stdcli.ExitOnError(err) + + api, close := getApiClient(c) + defer close() + + if c.NArg() < 1 { + term.Warningln("No domain provided.") + stdcli.Usage(c) + } + + domain := c.Args().First() + if delete { + domain = fmt.Sprintf(":%s", domain) + } + + return api.AppDomainUpdate(name, domain) +} diff --git a/common/apps.go b/common/apps.go index 46a5b40c..2c09ea0b 100644 --- a/common/apps.go +++ b/common/apps.go @@ -2,6 +2,7 @@ package common import ( "strconv" + "strings" log "github.com/Sirupsen/logrus" pb "github.com/datacol-io/datacol/api/models" @@ -90,3 +91,33 @@ func UpdateApp(c *kubernetes.Clientset, build *pb.Build, // TODO: cleanup old resource based on req.Version return nil } + +func MergeAppDomains(domains []string, item string) []string { + if item == "" { + return domains + } + + itemIndex := -1 + dotted := strings.HasPrefix(item, ":") + + if dotted { + item = item[1:] + } + + for i, d := range domains { + if d == item { + itemIndex = i + break + } + } + + if dotted && itemIndex >= 0 { + return append(domains[0:itemIndex], domains[itemIndex+1:]...) + } + + if !dotted && itemIndex == -1 { + return append(domains, item) + } + + return domains +} diff --git a/common/apps_test.go b/common/apps_test.go new file mode 100644 index 00000000..96c91d98 --- /dev/null +++ b/common/apps_test.go @@ -0,0 +1,27 @@ +package common_test + +import ( + "testing" + + "github.com/datacol-io/datacol/common" + "github.com/stretchr/testify/assert" +) + +func TestMergeAppDomains(t *testing.T) { + testcases := []struct { + domains []string + item string + expected []string + }{ + {[]string{"a.com"}, "a.com", []string{"a.com"}}, + {[]string{"a.com"}, "b.com", []string{"a.com", "b.com"}}, + {[]string{}, ":b.com", []string{}}, + {[]string{"a.com", "b.com"}, ":a.com", []string{"b.com"}}, + } + + for _, tc := range testcases { + t.Run(tc.item, func(t *testing.T) { + assert.Equal(t, common.MergeAppDomains(tc.domains, tc.item), tc.expected, "Should get correct domains") + }) + } +} diff --git a/k8s/deployment.go b/k8s/deployment.go index 7745a2a5..7ffaa33a 100644 --- a/k8s/deployment.go +++ b/k8s/deployment.go @@ -127,36 +127,41 @@ func newContainer(payload *DeployRequest) v1.Container { return container } -func newIngress(payload *DeployResponse, domains []string) *v1beta1.Ingress { - r := payload.Request - - if len(domains) == 0 { - domains = []string{fmt.Sprintf("%s.%s", r.ServiceID, defaultIngressDomain)} - } - +func ingressRulesManifest(service, path string, port intstr.IntOrString, domains []string) []v1beta1.IngressRule { rules := make([]v1beta1.IngressRule, len(domains)) for i, domain := range domains { - ingressPath := "/" - - if payload.Request.Provider == cloud.GCPProvider { - // It's important to have * after / since GCP GLBC load balancer doesn't support subresources automatically. - ingressPath = "/*" - } - rules[i] = v1beta1.IngressRule{ Host: domain, IngressRuleValue: v1beta1.IngressRuleValue{HTTP: &v1beta1.HTTPIngressRuleValue{ Paths: []v1beta1.HTTPIngressPath{{ - Path: ingressPath, + Path: path, Backend: v1beta1.IngressBackend{ - ServiceName: r.ServiceID, - ServicePort: r.ContainerPort, + ServiceName: service, + ServicePort: port, }, }}, }}, } } + return rules +} + +func newIngress(payload *DeployResponse, domains []string) *v1beta1.Ingress { + r := payload.Request + + if len(domains) == 0 { + domains = []string{fmt.Sprintf("%s.%s", r.ServiceID, defaultIngressDomain)} + } + + ingressPath := "/" + if payload.Request.Provider == cloud.GCPProvider { + // It's important to have * after / since GCP GLBC load balancer doesn't support subresources automatically. + ingressPath = "/*" + } + + rules := ingressRulesManifest(r.ServiceID, ingressPath, r.ContainerPort, domains) + //Note: making name dependent on namespace i.e. stackName will only provision one load-balancer per stack // change this if you want to allocate individual load balanacer for each app and use Name = payload.Request.ServiceID // Also if you change this remember to chage in AppGet to fetch IP of load balancer code diff --git a/k8s/helper.go b/k8s/helper.go index b96b6df2..433e9c22 100644 --- a/k8s/helper.go +++ b/k8s/helper.go @@ -2,7 +2,7 @@ package kube import ( "encoding/json" - "strings" + "fmt" log "github.com/Sirupsen/logrus" "k8s.io/api/extensions/v1beta1" @@ -22,37 +22,10 @@ func toJson(object interface{}) string { return string(dump) } -func MergeAppDomains(domains []string, item string) []string { - if item == "" { - return domains - } - - itemIndex := -1 - dotted := strings.HasPrefix(item, ":") - - if dotted { - item = item[1:] - } - - for i, d := range domains { - if d == item { - itemIndex = i - break - } - } - - if dotted && itemIndex >= 0 { - return append(domains[0:itemIndex], domains[itemIndex+1:]...) - } - - if !dotted && itemIndex == -1 { - return append(domains, item) - } - - return domains -} - +// Merge ingress rules from different applications since we share an ingress controller among +// different services. `source` will represent the rules for only an app func mergeIngressRules(dest *v1beta1.Ingress, source *v1beta1.Ingress) *v1beta1.Ingress { + // check if the app domains can be added for _, r := range source.Spec.Rules { foundAt := -1 for i, rr := range dest.Spec.Rules { @@ -69,7 +42,32 @@ func mergeIngressRules(dest *v1beta1.Ingress, source *v1beta1.Ingress) *v1beta1. } } - log.Debugf("ingress rules %s", toJson(dest.Spec)) + // check if the app domains should be removed + for i, r := range dest.Spec.Rules { + backend := r.IngressRuleValue.HTTP.Paths[0].Backend + serviceID := fmt.Sprintf("%s:%v", backend.ServiceName, backend.ServicePort) + related, found := false, false + + for _, rr := range source.Spec.Rules { + bk := rr.IngressRuleValue.HTTP.Paths[0].Backend + sid := fmt.Sprintf("%s:%v", bk.ServiceName, bk.ServicePort) + + if serviceID == sid { + related = true + } + + if rr.Host == r.Host { + found = true + break + } + } + + if related && !found { + dest.Spec.Rules = append(dest.Spec.Rules[:i], dest.Spec.Rules[i+1:]...) + } + } + + log.Debugf("final ingress rules %s", toJson(dest.Spec.Rules)) return dest } diff --git a/k8s/helper_test.go b/k8s/helper_test.go index 0627a419..0de44c6f 100644 --- a/k8s/helper_test.go +++ b/k8s/helper_test.go @@ -1,27 +1,57 @@ -package kube_test +package kube import ( "testing" - "github.com/datacol-io/datacol/cloud/kube" "github.com/stretchr/testify/assert" + "k8s.io/api/extensions/v1beta1" + "k8s.io/apimachinery/pkg/util/intstr" ) -func TestMergeAppDomains(t *testing.T) { - testcases := []struct { - domains []string - item string - expected []string - }{ - {[]string{"a.com"}, "a.com", []string{"a.com"}}, - {[]string{"a.com"}, "b.com", []string{"a.com", "b.com"}}, - {[]string{}, ":b.com", []string{}}, - {[]string{"a.com", "b.com"}, ":a.com", []string{"b.com"}}, +func TestMergeIngressRules(t *testing.T) { + { + ing1 := v1beta1.Ingress{Spec: v1beta1.IngressSpec{ + Rules: ingressRulesManifest("app1", "", intstr.FromInt(80), []string{"a1.com"}), + }} + + ing2 := v1beta1.Ingress{Spec: v1beta1.IngressSpec{ + Rules: ingressRulesManifest("app2", "", intstr.FromInt(80), []string{"a2.com"}), + }} + + ing := mergeIngressRules(&ing1, &ing2) + assert.Len(t, ing.Spec.Rules, 2) + + ing3 := mergeIngressRules(ing, &ing2) + assert.Len(t, ing3.Spec.Rules, 2) + + ing2.Spec.Rules[0].Host = "b1.com" + ing4 := mergeIngressRules(ing3, &ing2) + assert.Len(t, ing4.Spec.Rules, 2) + } + + { + ing1 := v1beta1.Ingress{Spec: v1beta1.IngressSpec{ + Rules: ingressRulesManifest("app1", "", intstr.FromInt(80), []string{"a1.com", "a2.com"}), + }} + + ing2 := v1beta1.Ingress{Spec: v1beta1.IngressSpec{ + Rules: ingressRulesManifest("app1", "", intstr.FromInt(80), []string{"a1.com", "a2.com", "b1.com"}), + }} + + ing := mergeIngressRules(&ing1, &ing2) + assert.Len(t, ing.Spec.Rules, 3) } - for _, tc := range testcases { - t.Run(tc.item, func(t *testing.T) { - assert.Equal(t, kube.MergeAppDomains(tc.domains, tc.item), tc.expected, "Should get correct domains") - }) + { + ing1 := v1beta1.Ingress{Spec: v1beta1.IngressSpec{ + Rules: ingressRulesManifest("app1", "", intstr.FromInt(80), []string{"a1.com", "a2.com"}), + }} + + ing2 := v1beta1.Ingress{Spec: v1beta1.IngressSpec{ + Rules: ingressRulesManifest("app1", "", intstr.FromInt(80), []string{"a1.com"}), + }} + + ing := mergeIngressRules(&ing1, &ing2) + assert.Len(t, ing.Spec.Rules, 1) } } From 7aa46ed07376a43792e37749e7bfb54db6c06900 Mon Sep 17 00:00:00 2001 From: dinesh Date: Sat, 21 Apr 2018 16:02:28 +0530 Subject: [PATCH 12/13] Remove code and description from GRCP errors --- CHANGELOG.md | 1 + cmd/run.go | 7 ++++++- cmd/stdcli/cli.go | 4 ++++ k8s/process.go | 2 ++ 4 files changed, 13 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 01c105b2..1bfc518f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ This project adheres to [Semantic Versioning](http://semver.org/). ## [UNRELEASED] - 0000-00-00 ### Fixes +- [CLI] Remove code and description from GRCP errors - [API] Skipping ephemeral pods while log streaming - [CLI] `ps` should list recent pods with tabular format (Added cpu, memory fields) - [API] Don't stream logs from crashed/failed pods diff --git a/cmd/run.go b/cmd/run.go index cb8f7add..4d8d27c5 100644 --- a/cmd/run.go +++ b/cmd/run.go @@ -36,10 +36,15 @@ func cmdAppRun(c *cli.Context) error { func prepareCommand(c *cli.Context) []string { args := c.Args() + + return append([]string{"env", fmt.Sprintf("TERM=%s", getTermEnv())}, args...) +} + +func getTermEnv() string { term := os.Getenv("TERM") if term == "" { term = "xterm" } - return append([]string{"env", fmt.Sprintf("TERM=%s", term)}, args...) + return term } diff --git a/cmd/stdcli/cli.go b/cmd/stdcli/cli.go index a12bc162..98399a17 100644 --- a/cmd/stdcli/cli.go +++ b/cmd/stdcli/cli.go @@ -14,6 +14,7 @@ import ( pb "github.com/datacol-io/datacol/api/models" rollbarAPI "github.com/stvp/rollbar" "github.com/urfave/cli" + "google.golang.org/grpc/status" ) var ( @@ -137,6 +138,9 @@ func CheckFlagsPresence(c *cli.Context, flags ...string) { func ExitOnError(err error) { if err != nil { + if gerr, ok := status.FromError(err); ok { + term.Fatalln(gerr.Message()) + } term.Fatalln(err) } } diff --git a/k8s/process.go b/k8s/process.go index 2431872f..e2f758b2 100644 --- a/k8s/process.go +++ b/k8s/process.go @@ -122,6 +122,8 @@ func ProcessList(c *kubernetes.Clientset, ns, app string) ([]*pb.Process, error) return nil, err } + log.Debugf("got %d pods for %s", len(pods), app) + if len(pods) == 0 { continue } From 03bbce05ae9d38bfe030f198c060c4da03125720 Mon Sep 17 00:00:00 2001 From: dinesh Date: Sat, 21 Apr 2018 16:33:12 +0530 Subject: [PATCH 13/13] Bump version to alpha.13 --- CHANGELOG.md | 2 ++ Makefile | 2 +- cmd/stdcli/cli.go | 2 +- hack/make.rb | 2 +- mini.json | 20 -------------------- 5 files changed, 5 insertions(+), 23 deletions(-) delete mode 100644 mini.json diff --git a/CHANGELOG.md b/CHANGELOG.md index 1bfc518f..7dd37f0d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,8 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). ## [UNRELEASED] - 0000-00-00 + +## [1.0.0-alpha.13] - 2018-04-21 ### Fixes - [CLI] Remove code and description from GRCP errors - [API] Skipping ephemeral pods while log streaming diff --git a/Makefile b/Makefile index 57bc31e4..c572d86b 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -version=1.0.0-alpha.12 +version=1.0.0-alpha.13 MODEL_PROTO_DIR=./api/models SERVICE_PROTO_DIR=./api/controller VEDNOR_GOOGLE_APIS=./vendor/github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis diff --git a/cmd/stdcli/cli.go b/cmd/stdcli/cli.go index 98399a17..39bf574c 100644 --- a/cmd/stdcli/cli.go +++ b/cmd/stdcli/cli.go @@ -26,7 +26,7 @@ var ( ) func init() { - Version = "1.0.0-alpha.12" + Version = "1.0.0-alpha.13" LocalAppDir = ".datacol" Binary = filepath.Base(os.Args[0]) Commands = []cli.Command{} diff --git a/hack/make.rb b/hack/make.rb index a36a067e..8aaa77f6 100644 --- a/hack/make.rb +++ b/hack/make.rb @@ -1,6 +1,6 @@ require 'rubygems' -$version = ENV.fetch('VERSION', "1.0.0-alpha.12") +$version = ENV.fetch('VERSION', "1.0.0-alpha.13") $env = ENV.fetch('DATACOL_ENV') # dev or prod $cgo = ENV.fetch("CGO_ENABLED", "0") diff --git a/mini.json b/mini.json deleted file mode 100644 index e79c6f09..00000000 --- a/mini.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "steps": [ - { - "name": "gcr.io/cloud-builders/go", - "env":[ - "GOOS=linux", - "GOARCH=amd64" - ], - "args": [ "build", "-o", "apictl", "-ldflags=\"-s -w\"", "./api"] - }, { - "name": "zip", - "args": ["apictl.zip", "apictl"] - }, { - "name": "gcr.io/cloud-builders/gsutil", - "args": ["cp", "apictl.zip", "datacol-dev/binaries/${_DATACOL_VERSION}/apictl.zip"] - }, { - "name": "gcr.io/cloud-builders/gsutil", - "args": ["acl", "ch", "-u", "allUsers:R", "gs://datacol-dev/binaries/${_DATACOL_VERSION}/apictl.zip"] - }] -}