Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright 2017 The LUCI Authors. All rights reserved. | |
| 2 // Use of this source code is governed under the Apache License, Version 2.0 | |
| 3 // that can be found in the LICENSE file. | |
| 4 | |
| 5 // Package main contains a tool to upload cipd packages to an isolate server. | |
| 6 package main | |
| 7 | |
| 8 import ( | |
| 9 "fmt" | |
| 10 "io" | |
| 11 "net/http" | |
| 12 "os" | |
| 13 | |
| 14 "github.com/maruel/subcommands" | |
| 15 "golang.org/x/net/context" | |
| 16 | |
| 17 "github.com/luci/luci-go/cipd/client/cipd" | |
| 18 "github.com/luci/luci-go/cipd/client/cipd/ensure" | |
| 19 cipdcli "github.com/luci/luci-go/cipd/client/cli" | |
| 20 "github.com/luci/luci-go/cipd/version" | |
| 21 "github.com/luci/luci-go/client/authcli" | |
| 22 "github.com/luci/luci-go/common/auth" | |
| 23 "github.com/luci/luci-go/common/cli" | |
| 24 "github.com/luci/luci-go/common/data/rand/mathrand" | |
| 25 "github.com/luci/luci-go/common/isolatedclient" | |
| 26 "github.com/luci/luci-go/common/logging" | |
| 27 | |
| 28 "github.com/luci/luci-go/hardcoded/chromeinfra" | |
| 29 ) | |
| 30 | |
| 31 func main() { | |
| 32 mathrand.SeedRandomly() | |
| 33 params := cipdcli.Parameters{ | |
| 34 DefaultAuthOptions: chromeinfra.DefaultAuthOptions(), | |
| 35 ServiceURL: chromeinfra.CIPDServiceURL, | |
| 36 } | |
| 37 os.Exit(subcommands.Run(GetApplication(params), os.Args[1:])) | |
| 38 } | |
| 39 | |
| 40 // GetApplication returns cli.Application. | |
| 41 // | |
| 42 // It instantiates CIPD CLI application as a basis (for context, env vars, etc), | |
| 43 // and replaces all commands there. | |
| 44 func GetApplication(params cipdcli.Parameters) *cli.Application { | |
| 45 app := *cipdcli.GetApplication(params) | |
| 46 app.Name = "cipd2isolate" | |
| 47 app.Title = "CIPD -> Isolate Uploader" | |
| 48 app.Commands = []*subcommands.Command{ | |
| 49 subcommands.CmdHelp, | |
| 50 version.SubcommandVersion, | |
| 51 | |
| 52 authcli.SubcommandInfo(params.DefaultAuthOptions, "auth-info", t rue), | |
| 53 authcli.SubcommandLogin(params.DefaultAuthOptions, "auth-login", false), | |
| 54 authcli.SubcommandLogout(params.DefaultAuthOptions, "auth-logout ", false), | |
| 55 | |
| 56 cmdIsolate(params), | |
| 57 } | |
| 58 return &app | |
| 59 } | |
| 60 | |
| 61 func cmdIsolate(params cipdcli.Parameters) *subcommands.Command { | |
| 62 return &subcommands.Command{ | |
| 63 UsageLine: "isolate [options]", | |
| 64 ShortDesc: "isolates contents of bunch of CIPD packages", | |
| 65 LongDesc: `Takes an 'ensure file' with description of some CIPD site root, ` + | |
| 66 `and produces *.isolated with same content`, | |
| 67 CommandRun: func() subcommands.CommandRun { | |
| 68 c := &isolateRun{} | |
| 69 | |
| 70 c.Flags.StringVar(&c.jsonOutput, "json-output", "", "Pat h to write operation results to.") | |
| 71 c.Flags.BoolVar(&c.verbose, "verbose", false, "Enable mo re logging.") | |
| 72 c.authFlags.Register(&c.Flags, params.DefaultAuthOptions ) | |
| 73 | |
| 74 c.Flags.StringVar(&c.cipdServiceURL, "cipd-service-url", params.ServiceURL, | |
| 75 "CIPD Backend URL. If provided via an 'ensure fi le', the URL in the file takes precedence.") | |
|
nodir
2017/03/16 18:57:34
this is odd. Maybe make flag default "" and if it
Vadim Sh.
2017/03/16 18:59:32
I copied this from CIPD client. I forgot why it is
| |
| 76 c.Flags.StringVar(&c.cipdCacheDir, "cipd-cache-dir", "", | |
| 77 fmt.Sprintf("Directory for shared CIPD cache (ca n also be set by %s env var).", cipdcli.CIPDCacheDir)) | |
| 78 c.Flags.StringVar(&c.ensureFile, "cipd-ensure-file", "", | |
| 79 `An "ensure" file with packages to isolate. See syntax described here: `+ | |
| 80 `https://godoc.org/github.com/luci/luci- go/cipd/client/cipd/ensure.`+ | |
| 81 ` Providing '-' will read from stdin.`) | |
| 82 c.Flags.StringVar(&c.workDir, "work-dir", "./c2i_work", "A directory to keep temporary files in.") | |
| 83 | |
| 84 c.isolatedFlags.Init(&c.Flags) | |
| 85 | |
| 86 return c | |
| 87 }, | |
| 88 } | |
| 89 } | |
| 90 | |
| 91 type isolateRun struct { | |
| 92 subcommands.CommandRunBase | |
| 93 | |
| 94 jsonOutput string | |
| 95 verbose bool | |
| 96 authFlags authcli.Flags | |
| 97 | |
| 98 cipdServiceURL string | |
| 99 cipdCacheDir string | |
| 100 ensureFile string | |
| 101 workDir string | |
| 102 | |
| 103 isolatedFlags isolatedclient.Flags | |
| 104 } | |
| 105 | |
| 106 // ModifyContext implements cli.ContextModificator. | |
| 107 func (r *isolateRun) ModifyContext(ctx context.Context) context.Context { | |
| 108 if r.verbose { | |
| 109 ctx = logging.SetLevel(ctx, logging.Debug) | |
| 110 } | |
| 111 return ctx | |
| 112 } | |
| 113 | |
| 114 // Run is the main entry point for 'cipd2isolate isolate'. | |
| 115 func (r *isolateRun) Run(a subcommands.Application, args []string, env subcomman ds.Env) int { | |
| 116 ctx := cli.GetContext(a, r, env) | |
| 117 | |
| 118 ensureFile, err := r.parseEnsureFile() | |
| 119 if err != nil { | |
| 120 fmt.Fprintf(os.Stderr, "failed to parse ensure file - %s\n", err ) | |
| 121 return 1 | |
| 122 } | |
| 123 | |
| 124 httpAuth, err := r.initHttpAuth(ctx) | |
| 125 if err != nil { | |
| 126 fmt.Fprintf(os.Stderr, "failed to initialize authentication - %s \n", err) | |
| 127 return 2 | |
| 128 } | |
| 129 | |
| 130 cipdClient, err := r.initCipdClient(ctx, httpAuth, ensureFile) | |
| 131 if err != nil { | |
| 132 fmt.Fprintf(os.Stderr, "failed to initialize CIPD client - %s\n" , err) | |
| 133 return 3 | |
| 134 } | |
| 135 | |
| 136 isolatedClient, err := r.initIsolatedClient(ctx, httpAuth) | |
| 137 if err != nil { | |
| 138 fmt.Fprintf(os.Stderr, "failed to initialize isolated client - % s\n", err) | |
| 139 return 4 | |
| 140 } | |
| 141 | |
| 142 if err = isolateCipdPackages(ctx, ensureFile, cipdClient, isolatedClient ); err != nil { | |
| 143 return 5 // errors are logged already | |
| 144 } | |
| 145 return 0 | |
| 146 } | |
| 147 | |
| 148 func (r *isolateRun) parseEnsureFile() (*ensure.File, error) { | |
| 149 if r.ensureFile == "" { | |
| 150 return nil, fmt.Errorf("not provided, use -cipd-ensure-file flag to provide") | |
| 151 } | |
| 152 var err error | |
| 153 var f io.ReadCloser | |
| 154 if r.ensureFile == "-" { | |
| 155 f = os.Stdin | |
| 156 } else { | |
| 157 if f, err = os.Open(r.ensureFile); err != nil { | |
| 158 return nil, err | |
| 159 } | |
| 160 } | |
| 161 defer f.Close() | |
|
nodir
2017/03/16 18:57:34
i assume nothing bad is going to happen if you clo
Vadim Sh.
2017/03/16 18:59:32
yes, this is fine.
| |
| 162 return ensure.ParseFile(f) | |
| 163 } | |
| 164 | |
| 165 func (r *isolateRun) initHttpAuth(ctx context.Context) (*http.Client, error) { | |
| 166 authOpts, err := r.authFlags.Options() | |
| 167 if err != nil { | |
| 168 return nil, err | |
| 169 } | |
| 170 return auth.NewAuthenticator(ctx, auth.SilentLogin, authOpts).Client() | |
| 171 } | |
| 172 | |
| 173 func (r *isolateRun) initCipdClient(ctx context.Context, httpAuth *http.Client, ensureFile *ensure.File) (cipd.Client, error) { | |
| 174 // Prefer the ServiceURL from the file (if set), and log a warning if th e user | |
| 175 // provided one on the command line that doesn't match the one in the fi le. | |
| 176 serviceURL := r.cipdServiceURL | |
| 177 if ensureFile.ServiceURL != "" { | |
| 178 if serviceURL != "" && serviceURL != ensureFile.ServiceURL { | |
| 179 logging.Warningf(ctx, "serviceURL in ensure file != -cip d-service-url on CLI (%q v %q). Using %q from file.", | |
| 180 ensureFile.ServiceURL, serviceURL, ensureFile.Se rviceURL) | |
| 181 } | |
| 182 serviceURL = ensureFile.ServiceURL | |
| 183 } | |
| 184 | |
| 185 cacheDir := r.cipdCacheDir | |
| 186 if cacheDir == "" { | |
| 187 var err error | |
| 188 cacheDir, err = cipdcli.CacheDir(ctx) | |
| 189 if err != nil { | |
| 190 return nil, err | |
| 191 } | |
| 192 } | |
| 193 | |
| 194 return cipd.NewClient(cipd.ClientOptions{ | |
| 195 ServiceURL: serviceURL, | |
| 196 Root: r.workDir, | |
| 197 UserAgent: cipdcli.UserAgent(ctx), | |
| 198 CacheDir: cacheDir, | |
| 199 AuthenticatedClient: httpAuth, | |
| 200 AnonymousClient: http.DefaultClient, | |
| 201 }) | |
| 202 } | |
| 203 | |
| 204 func (r *isolateRun) initIsolatedClient(ctx context.Context, httpAuth *http.Clie nt) (*isolatedclient.Client, error) { | |
| 205 if err := r.isolatedFlags.Parse(); err != nil { | |
| 206 return nil, err | |
| 207 } | |
| 208 return isolatedclient.New(http.DefaultClient, httpAuth, r.isolatedFlags. ServerURL, r.isolatedFlags.Namespace, nil, nil), nil | |
| 209 } | |
| OLD | NEW |