OSDN Git Service

new repo
[bytom/vapor.git] / vendor / golang.org / x / net / http2 / h2demo / launch.go
1 // Copyright 2014 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4
5 // +build ignore
6
7 package main
8
9 import (
10         "bufio"
11         "bytes"
12         "encoding/json"
13         "flag"
14         "fmt"
15         "io"
16         "io/ioutil"
17         "log"
18         "net/http"
19         "os"
20         "strings"
21         "time"
22
23         "golang.org/x/oauth2"
24         "golang.org/x/oauth2/google"
25         compute "google.golang.org/api/compute/v1"
26 )
27
28 var (
29         proj     = flag.String("project", "symbolic-datum-552", "name of Project")
30         zone     = flag.String("zone", "us-central1-a", "GCE zone")
31         mach     = flag.String("machinetype", "n1-standard-1", "Machine type")
32         instName = flag.String("instance_name", "http2-demo", "Name of VM instance.")
33         sshPub   = flag.String("ssh_public_key", "", "ssh public key file to authorize. Can modify later in Google's web UI anyway.")
34         staticIP = flag.String("static_ip", "130.211.116.44", "Static IP to use. If empty, automatic.")
35
36         writeObject  = flag.String("write_object", "", "If non-empty, a VM isn't created and the flag value is Google Cloud Storage bucket/object to write. The contents from stdin.")
37         publicObject = flag.Bool("write_object_is_public", false, "Whether the object created by --write_object should be public.")
38 )
39
40 func readFile(v string) string {
41         slurp, err := ioutil.ReadFile(v)
42         if err != nil {
43                 log.Fatalf("Error reading %s: %v", v, err)
44         }
45         return strings.TrimSpace(string(slurp))
46 }
47
48 var config = &oauth2.Config{
49         // The client-id and secret should be for an "Installed Application" when using
50         // the CLI. Later we'll use a web application with a callback.
51         ClientID:     readFile("client-id.dat"),
52         ClientSecret: readFile("client-secret.dat"),
53         Endpoint:     google.Endpoint,
54         Scopes: []string{
55                 compute.DevstorageFullControlScope,
56                 compute.ComputeScope,
57                 "https://www.googleapis.com/auth/sqlservice",
58                 "https://www.googleapis.com/auth/sqlservice.admin",
59         },
60         RedirectURL: "urn:ietf:wg:oauth:2.0:oob",
61 }
62
63 const baseConfig = `#cloud-config
64 coreos:
65   units:
66     - name: h2demo.service
67       command: start
68       content: |
69         [Unit]
70         Description=HTTP2 Demo
71         
72         [Service]
73         ExecStartPre=/bin/bash -c 'mkdir -p /opt/bin && curl -s -o /opt/bin/h2demo http://storage.googleapis.com/http2-demo-server-tls/h2demo && chmod +x /opt/bin/h2demo'
74         ExecStart=/opt/bin/h2demo --prod
75         RestartSec=5s
76         Restart=always
77         Type=simple
78         
79         [Install]
80         WantedBy=multi-user.target
81 `
82
83 func main() {
84         flag.Parse()
85         if *proj == "" {
86                 log.Fatalf("Missing --project flag")
87         }
88         prefix := "https://www.googleapis.com/compute/v1/projects/" + *proj
89         machType := prefix + "/zones/" + *zone + "/machineTypes/" + *mach
90
91         const tokenFileName = "token.dat"
92         tokenFile := tokenCacheFile(tokenFileName)
93         tokenSource := oauth2.ReuseTokenSource(nil, tokenFile)
94         token, err := tokenSource.Token()
95         if err != nil {
96                 if *writeObject != "" {
97                         log.Fatalf("Can't use --write_object without a valid token.dat file already cached.")
98                 }
99                 log.Printf("Error getting token from %s: %v", tokenFileName, err)
100                 log.Printf("Get auth code from %v", config.AuthCodeURL("my-state"))
101                 fmt.Print("\nEnter auth code: ")
102                 sc := bufio.NewScanner(os.Stdin)
103                 sc.Scan()
104                 authCode := strings.TrimSpace(sc.Text())
105                 token, err = config.Exchange(oauth2.NoContext, authCode)
106                 if err != nil {
107                         log.Fatalf("Error exchanging auth code for a token: %v", err)
108                 }
109                 if err := tokenFile.WriteToken(token); err != nil {
110                         log.Fatalf("Error writing to %s: %v", tokenFileName, err)
111                 }
112                 tokenSource = oauth2.ReuseTokenSource(token, nil)
113         }
114
115         oauthClient := oauth2.NewClient(oauth2.NoContext, tokenSource)
116
117         if *writeObject != "" {
118                 writeCloudStorageObject(oauthClient)
119                 return
120         }
121
122         computeService, _ := compute.New(oauthClient)
123
124         natIP := *staticIP
125         if natIP == "" {
126                 // Try to find it by name.
127                 aggAddrList, err := computeService.Addresses.AggregatedList(*proj).Do()
128                 if err != nil {
129                         log.Fatal(err)
130                 }
131                 // http://godoc.org/code.google.com/p/google-api-go-client/compute/v1#AddressAggregatedList
132         IPLoop:
133                 for _, asl := range aggAddrList.Items {
134                         for _, addr := range asl.Addresses {
135                                 if addr.Name == *instName+"-ip" && addr.Status == "RESERVED" {
136                                         natIP = addr.Address
137                                         break IPLoop
138                                 }
139                         }
140                 }
141         }
142
143         cloudConfig := baseConfig
144         if *sshPub != "" {
145                 key := strings.TrimSpace(readFile(*sshPub))
146                 cloudConfig += fmt.Sprintf("\nssh_authorized_keys:\n    - %s\n", key)
147         }
148         if os.Getenv("USER") == "bradfitz" {
149                 cloudConfig += fmt.Sprintf("\nssh_authorized_keys:\n    - %s\n", "ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAIEAwks9dwWKlRC+73gRbvYtVg0vdCwDSuIlyt4z6xa/YU/jTDynM4R4W10hm2tPjy8iR1k8XhDv4/qdxe6m07NjG/By1tkmGpm1mGwho4Pr5kbAAy/Qg+NLCSdAYnnE00FQEcFOC15GFVMOW2AzDGKisReohwH9eIzHPzdYQNPRWXE= bradfitz@papag.bradfitz.com")
150         }
151         const maxCloudConfig = 32 << 10 // per compute API docs
152         if len(cloudConfig) > maxCloudConfig {
153                 log.Fatalf("cloud config length of %d bytes is over %d byte limit", len(cloudConfig), maxCloudConfig)
154         }
155
156         instance := &compute.Instance{
157                 Name:        *instName,
158                 Description: "Go Builder",
159                 MachineType: machType,
160                 Disks:       []*compute.AttachedDisk{instanceDisk(computeService)},
161                 Tags: &compute.Tags{
162                         Items: []string{"http-server", "https-server"},
163                 },
164                 Metadata: &compute.Metadata{
165                         Items: []*compute.MetadataItems{
166                                 {
167                                         Key:   "user-data",
168                                         Value: &cloudConfig,
169                                 },
170                         },
171                 },
172                 NetworkInterfaces: []*compute.NetworkInterface{
173                         {
174                                 AccessConfigs: []*compute.AccessConfig{
175                                         {
176                                                 Type:  "ONE_TO_ONE_NAT",
177                                                 Name:  "External NAT",
178                                                 NatIP: natIP,
179                                         },
180                                 },
181                                 Network: prefix + "/global/networks/default",
182                         },
183                 },
184                 ServiceAccounts: []*compute.ServiceAccount{
185                         {
186                                 Email: "default",
187                                 Scopes: []string{
188                                         compute.DevstorageFullControlScope,
189                                         compute.ComputeScope,
190                                 },
191                         },
192                 },
193         }
194
195         log.Printf("Creating instance...")
196         op, err := computeService.Instances.Insert(*proj, *zone, instance).Do()
197         if err != nil {
198                 log.Fatalf("Failed to create instance: %v", err)
199         }
200         opName := op.Name
201         log.Printf("Created. Waiting on operation %v", opName)
202 OpLoop:
203         for {
204                 time.Sleep(2 * time.Second)
205                 op, err := computeService.ZoneOperations.Get(*proj, *zone, opName).Do()
206                 if err != nil {
207                         log.Fatalf("Failed to get op %s: %v", opName, err)
208                 }
209                 switch op.Status {
210                 case "PENDING", "RUNNING":
211                         log.Printf("Waiting on operation %v", opName)
212                         continue
213                 case "DONE":
214                         if op.Error != nil {
215                                 for _, operr := range op.Error.Errors {
216                                         log.Printf("Error: %+v", operr)
217                                 }
218                                 log.Fatalf("Failed to start.")
219                         }
220                         log.Printf("Success. %+v", op)
221                         break OpLoop
222                 default:
223                         log.Fatalf("Unknown status %q: %+v", op.Status, op)
224                 }
225         }
226
227         inst, err := computeService.Instances.Get(*proj, *zone, *instName).Do()
228         if err != nil {
229                 log.Fatalf("Error getting instance after creation: %v", err)
230         }
231         ij, _ := json.MarshalIndent(inst, "", "    ")
232         log.Printf("Instance: %s", ij)
233 }
234
235 func instanceDisk(svc *compute.Service) *compute.AttachedDisk {
236         const imageURL = "https://www.googleapis.com/compute/v1/projects/coreos-cloud/global/images/coreos-stable-444-5-0-v20141016"
237         diskName := *instName + "-disk"
238
239         return &compute.AttachedDisk{
240                 AutoDelete: true,
241                 Boot:       true,
242                 Type:       "PERSISTENT",
243                 InitializeParams: &compute.AttachedDiskInitializeParams{
244                         DiskName:    diskName,
245                         SourceImage: imageURL,
246                         DiskSizeGb:  50,
247                 },
248         }
249 }
250
251 func writeCloudStorageObject(httpClient *http.Client) {
252         content := os.Stdin
253         const maxSlurp = 1 << 20
254         var buf bytes.Buffer
255         n, err := io.CopyN(&buf, content, maxSlurp)
256         if err != nil && err != io.EOF {
257                 log.Fatalf("Error reading from stdin: %v, %v", n, err)
258         }
259         contentType := http.DetectContentType(buf.Bytes())
260
261         req, err := http.NewRequest("PUT", "https://storage.googleapis.com/"+*writeObject, io.MultiReader(&buf, content))
262         if err != nil {
263                 log.Fatal(err)
264         }
265         req.Header.Set("x-goog-api-version", "2")
266         if *publicObject {
267                 req.Header.Set("x-goog-acl", "public-read")
268         }
269         req.Header.Set("Content-Type", contentType)
270         res, err := httpClient.Do(req)
271         if err != nil {
272                 log.Fatal(err)
273         }
274         if res.StatusCode != 200 {
275                 res.Write(os.Stderr)
276                 log.Fatalf("Failed.")
277         }
278         log.Printf("Success.")
279         os.Exit(0)
280 }
281
282 type tokenCacheFile string
283
284 func (f tokenCacheFile) Token() (*oauth2.Token, error) {
285         slurp, err := ioutil.ReadFile(string(f))
286         if err != nil {
287                 return nil, err
288         }
289         t := new(oauth2.Token)
290         if err := json.Unmarshal(slurp, t); err != nil {
291                 return nil, err
292         }
293         return t, nil
294 }
295
296 func (f tokenCacheFile) WriteToken(t *oauth2.Token) error {
297         jt, err := json.Marshal(t)
298         if err != nil {
299                 return err
300         }
301         return ioutil.WriteFile(string(f), jt, 0600)
302 }