Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(199)

Side by Side Diff: go/src/infra/gae/epclient/epclient.go

Issue 1153473008: A client/server helper wrapper for endpoints in Go. (Closed) Base URL: https://chromium.googlesource.com/infra/infra.git@master
Patch Set: Use the real client generator! Created 5 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 // The following comment allows `go generate` to correctly generate clients
6 // for all endpoints services located in the "infra/gae/epservice" package.
7 //go:generate goapp run epclient.go
8
9 // EPClient will auto-generate endpoints clients from Google Cloud Endpoint
10 // service definitions. The tool assumes that:
11 // * all go endpoint service definitions occur in a package which has
12 // a public method `RegisterEndpointsService(*endpoints.Server) error`, and
13 // that calling this method will register the endpoints service with the
14 // provided server or return an error.
15 // * goapp exists in PATH (and understands all the import paths in the
16 // defined services)
17 // * google-api-go-generator exists in PATH.
dnj 2015/06/08 16:43:18 Could you "enforce" this by adding it as a Go depe
iannucci 2015/06/09 00:01:54 It's a 'main' package, so I can't add it as an imp
18 package main
19
20 import (
21 "bytes"
22 "encoding/json"
23 "flag"
24 "fmt"
25 "io/ioutil"
26 "os"
27 "os/exec"
28 "path/filepath"
29 "strings"
30 "text/template"
31 "time"
32
33 "infra/libs/jsutil"
34 )
35
36 var (
37 servicePackagesBase = flag.String("pkgs", "infra/gae/epservice",
38 "The base Go package to walk to find service definitions.")
39 outDir = flag.String("outdir", ".",
40 "The directory to generate the client libraries in.")
41 runOnly = flag.Bool("run", false,
42 "If set to true, will run the server and wait, without generatin g any clients.")
43 clearDatastore = flag.Bool("clear_datastore", false,
44 "If set to true, will clear the datastore when in 'run' mode.")
45 )
46
47 var serviceScript = `
48 package main
dnj 2015/06/08 16:43:18 Add "generated" comment, info, timestamp.
iannucci 2015/06/09 00:01:54 Done.
49
50 import (
51 "fmt"
52
53 {{range $idx, $pkg := .Pkgs}}
54 pkg{{$idx}} "{{$pkg.Imp}}"{{end}}
55
56 "github.com/GoogleCloudPlatform/go-endpoints/endpoints"
57 )
58
59 func init() {
60 var err error
61 server := endpoints.NewServer("")
62
63 {{range $idx, $pkg := .Pkgs }}
64 err = pkg{{$idx}}.RegisterEndpointsService(server)
65 if err != nil {
66 panic(fmt.Errorf("Error while registering service {{$pkg}}: %s", err))
67 }
68 {{end}}
69
70 server.HandleHTTP(nil)
71 }
72 `
73
74 const appYaml = `
75 application: epclient-tmp-app
dnj 2015/06/08 16:43:18 Add "generated" comment, info, timestamp.
iannucci 2015/06/09 00:01:54 Done.
76 version: nope
77 runtime: go
78 api_version: go1
79
80 handlers:
81 - url: /.*
82 script: _go_app
83 `
84
85 var temp = template.Must(template.New("service").Parse(serviceScript))
86
87 // Pkg holds the import and real filesystem paths of an endpoint service
88 // package. It's exported merely for reflection purposes, since it's used
89 // by text/template.
90 type Pkg struct {
91 Imp string
92 Pth string
93 }
94
95 func boom(err error) {
96 if err != nil {
97 panic(err)
98 }
99 }
100
101 func getPkgs() []Pkg {
102 cmd := exec.Command("goapp", "list", "-json", filepath.Join(*servicePack agesBase, "..."))
103 d, err := cmd.Output()
104 boom(err)
105
106 d = []byte("[" + strings.Replace(string(d), "}\n{", "},{", -1) + "]")
107
108 js := interface{}(nil)
109 boom(json.Unmarshal(d, &js))
110
111 ret := []Pkg{}
112
113 for _, m := range js.([]interface{}) {
114 ret = append(ret, Pkg{
115 jsutil.Get(m, "ImportPath").(string),
116 jsutil.Get(m, "Dir").(string),
117 })
118 }
119
120 return ret
121 }
122
123 func writeFiles(dir string, pkgs []Pkg) {
124 buf := &bytes.Buffer{}
125 if err := temp.Execute(buf, struct{ Pkgs []Pkg }{pkgs}); err != nil {
126 panic(err)
127 }
128
129 if err := ioutil.WriteFile(filepath.Join(dir, "app.go"), buf.Bytes(), 06 66); err != nil {
130 panic(err)
131 }
132
133 if err := ioutil.WriteFile(filepath.Join(dir, "app.yaml"), []byte(appYam l), 0666); err != nil {
134 panic(err)
135 }
136 }
137
138 func parseFlags() {
139 err := error(nil)
dnj 2015/06/08 16:43:17 I generally prefer "var err error" *shrug* Up to y
iannucci 2015/06/09 00:01:53 me too... I was getting bikeshedding elsewhere on
140 flag.Parse()
141 if *outDir == "" {
142 if *outDir, err = os.Getwd(); err != nil {
143 panic(err)
144 }
145 }
146 if *outDir, err = filepath.Abs(*outDir); err != nil {
147 panic(err)
148 }
149 }
150
151 func startServer(dir string) (func(), func()) {
152 args := []string{"serve"}
153 if *clearDatastore {
154 args = append(args, "-clear_datastore")
155 }
156 args = append(args, dir)
157 server := exec.Command("goapp", args...)
158 server.Stdout = os.Stdout
159 server.Stderr = os.Stderr
160 if err := server.Start(); err != nil {
161 panic(err)
162 }
163 time.Sleep(time.Second) // yeah yeah, sue me.
dnj 2015/06/08 16:43:18 Since you know the discovery service URL, you coul
iannucci 2015/06/09 00:01:54 Done.
164 fmt.Println("Discovery service up")
165
166 wait := func() { server.Wait() }
167 stop := func() {
168 server.Process.Signal(os.Interrupt)
169 wait()
170 }
171 return stop, wait
172 }
173
174 func generate() {
175 gencmd := exec.Command("google-api-go-generator", "-discoveryurl", "http ://localhost:8080/_ah/api/discovery/v1/apis", "-gendir", *outDir, "-cache=false" )
176 gencmd.Stdout = os.Stdout
177 gencmd.Stderr = os.Stderr
178 if err := gencmd.Run(); err != nil {
179 panic(err)
180 }
181 }
182
183 func main() {
184 parseFlags()
185
dnj 2015/06/08 16:43:18 Test that "google-api-go-generator" and "goapp" ar
iannucci 2015/06/09 00:01:53 Done.
186 pkgs := getPkgs()
187
188 dir, err := ioutil.TempDir("", "epclient_gen")
189 if err != nil {
190 panic(err)
191 }
192 defer os.RemoveAll(dir)
193
194 writeFiles(dir, pkgs)
195
196 stop, wait := startServer(dir)
197 defer stop()
198
199 if *runOnly {
200 wait()
201 } else {
202 generate()
203 }
204
205 // inject DoWithRetries methods.
206 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698