Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 /* | 5 /* |
| 6 Package cipd implements client side of Chrome Infra Package Deployer. | 6 Package cipd implements client side of Chrome Infra Package Deployer. |
| 7 | 7 |
| 8 TODO: write more. | 8 TODO: write more. |
| 9 | 9 |
| 10 Binary package file format (in free form representation): | 10 Binary package file format (in free form representation): |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 34 */ | 34 */ |
| 35 package cipd | 35 package cipd |
| 36 | 36 |
| 37 import ( | 37 import ( |
| 38 "bufio" | 38 "bufio" |
| 39 "errors" | 39 "errors" |
| 40 "fmt" | 40 "fmt" |
| 41 "io" | 41 "io" |
| 42 "net/http" | 42 "net/http" |
| 43 "os" | 43 "os" |
| 44 "path/filepath" | |
| 44 "sort" | 45 "sort" |
| 45 "strings" | 46 "strings" |
| 47 "sync" | |
| 46 "time" | 48 "time" |
| 47 | 49 |
| 48 "github.com/luci/luci-go/common/logging" | 50 "github.com/luci/luci-go/common/logging" |
| 49 | 51 |
| 50 "infra/tools/cipd/common" | 52 "infra/tools/cipd/common" |
| 53 "infra/tools/cipd/internal" | |
| 51 "infra/tools/cipd/local" | 54 "infra/tools/cipd/local" |
| 52 ) | 55 ) |
| 53 | 56 |
| 54 // PackageACLChangeAction defines a flavor of PackageACLChange. | 57 // PackageACLChangeAction defines a flavor of PackageACLChange. |
| 55 type PackageACLChangeAction string | 58 type PackageACLChangeAction string |
| 56 | 59 |
| 57 const ( | 60 const ( |
| 58 // GrantRole is used in PackageACLChange to request a role to be granted . | 61 // GrantRole is used in PackageACLChange to request a role to be granted . |
| 59 GrantRole PackageACLChangeAction = "GRANT" | 62 GrantRole PackageACLChangeAction = "GRANT" |
| 60 // RevokeRole is used in PackageACLChange to request a role to be revoke d. | 63 // RevokeRole is used in PackageACLChange to request a role to be revoke d. |
| 61 RevokeRole PackageACLChangeAction = "REVOKE" | 64 RevokeRole PackageACLChangeAction = "REVOKE" |
| 62 | 65 |
| 63 // CASFinalizationTimeout is how long to wait for CAS service to finaliz e the upload. | 66 // CASFinalizationTimeout is how long to wait for CAS service to finaliz e the upload. |
| 64 CASFinalizationTimeout = 1 * time.Minute | 67 CASFinalizationTimeout = 1 * time.Minute |
| 65 // SetRefTimeout is how long to wait for an instance to be processed whe n setting a ref. | 68 // SetRefTimeout is how long to wait for an instance to be processed whe n setting a ref. |
| 66 SetRefTimeout = 1 * time.Minute | 69 SetRefTimeout = 1 * time.Minute |
| 67 // TagAttachTimeout is how long to wait for an instance to be processed when attaching tags. | 70 // TagAttachTimeout is how long to wait for an instance to be processed when attaching tags. |
| 68 TagAttachTimeout = 1 * time.Minute | 71 TagAttachTimeout = 1 * time.Minute |
| 69 | 72 |
| 70 // UserAgent is HTTP user agent string for CIPD client. | 73 // UserAgent is HTTP user agent string for CIPD client. |
| 71 UserAgent = "cipd 1.0" | 74 UserAgent = "cipd 1.0" |
| 72 | 75 |
| 73 // ServiceURL is URL of a backend to connect to by default. | 76 // ServiceURL is URL of a backend to connect to by default. |
| 74 ServiceURL = "https://chrome-infra-packages.appspot.com" | 77 ServiceURL = "https://chrome-infra-packages.appspot.com" |
| 75 ) | 78 ) |
| 76 | 79 |
| 77 var ( | 80 var ( |
| 78 // ErrFinalizationTimeout is returned if CAS service can not finalize up load fast enough. | 81 // ErrFinalizationTimeout is returned if CAS service can not finalize up load fast enough. |
| 79 » ErrFinalizationTimeout = errors.New("Timeout while waiting for CAS servi ce to finalize the upload") | 82 » ErrFinalizationTimeout = errors.New("timeout while waiting for CAS servi ce to finalize the upload") |
| 80 // ErrBadUpload is returned when a package file is uploaded, but servers asks us to upload it again. | 83 // ErrBadUpload is returned when a package file is uploaded, but servers asks us to upload it again. |
| 81 » ErrBadUpload = errors.New("Package file is uploaded, but servers asks us to upload it again") | 84 » ErrBadUpload = errors.New("package file is uploaded, but servers asks us to upload it again") |
| 82 // ErrBadUploadSession is returned by UploadToCAS if provided UploadSess ion is not valid. | 85 // ErrBadUploadSession is returned by UploadToCAS if provided UploadSess ion is not valid. |
| 83 » ErrBadUploadSession = errors.New("UploadURL must be set if UploadSession ID is used") | 86 » ErrBadUploadSession = errors.New("uploadURL must be set if UploadSession ID is used") |
| 84 // ErrUploadSessionDied is returned by UploadToCAS if upload session sud denly disappeared. | 87 // ErrUploadSessionDied is returned by UploadToCAS if upload session sud denly disappeared. |
| 85 » ErrUploadSessionDied = errors.New("Upload session is unexpectedly missin g") | 88 » ErrUploadSessionDied = errors.New("upload session is unexpectedly missin g") |
| 86 // ErrNoUploadSessionID is returned by UploadToCAS if server didn't prov ide upload session ID. | 89 // ErrNoUploadSessionID is returned by UploadToCAS if server didn't prov ide upload session ID. |
| 87 » ErrNoUploadSessionID = errors.New("Server didn't provide upload session ID") | 90 » ErrNoUploadSessionID = errors.New("server didn't provide upload session ID") |
| 88 // ErrSetRefTimeout is returned when service refuses to move a ref for a long time. | 91 // ErrSetRefTimeout is returned when service refuses to move a ref for a long time. |
| 89 » ErrSetRefTimeout = errors.New("Timeout while moving a ref") | 92 » ErrSetRefTimeout = errors.New("timeout while moving a ref") |
| 90 // ErrAttachTagsTimeout is returned when service refuses to accept tags for a long time. | 93 // ErrAttachTagsTimeout is returned when service refuses to accept tags for a long time. |
| 91 » ErrAttachTagsTimeout = errors.New("Timeout while attaching tags") | 94 » ErrAttachTagsTimeout = errors.New("timeout while attaching tags") |
| 92 // ErrDownloadError is returned by FetchInstance on download errors. | 95 // ErrDownloadError is returned by FetchInstance on download errors. |
| 93 » ErrDownloadError = errors.New("Failed to download the package file after multiple attempts") | 96 » ErrDownloadError = errors.New("failed to download the package file after multiple attempts") |
| 94 // ErrUploadError is returned by RegisterInstance and UploadToCAS on upl oad errors. | 97 // ErrUploadError is returned by RegisterInstance and UploadToCAS on upl oad errors. |
| 95 » ErrUploadError = errors.New("Failed to upload the package file after mul tiple attempts") | 98 » ErrUploadError = errors.New("failed to upload the package file after mul tiple attempts") |
| 96 // ErrAccessDenined is returned by calls talking to backend on 401 or 40 3 HTTP errors. | 99 // ErrAccessDenined is returned by calls talking to backend on 401 or 40 3 HTTP errors. |
| 97 » ErrAccessDenined = errors.New("Access denied (not authenticated or not e nough permissions)") | 100 » ErrAccessDenined = errors.New("access denied (not authenticated or not e nough permissions)") |
| 98 // ErrBackendInaccessible is returned by calls talking to backed if it d oesn't response. | 101 // ErrBackendInaccessible is returned by calls talking to backed if it d oesn't response. |
| 99 » ErrBackendInaccessible = errors.New("Request to the backend failed after multiple attempts") | 102 » ErrBackendInaccessible = errors.New("request to the backend failed after multiple attempts") |
| 100 // ErrEnsurePackagesFailed is returned by EnsurePackages if something is not right. | 103 // ErrEnsurePackagesFailed is returned by EnsurePackages if something is not right. |
| 101 » ErrEnsurePackagesFailed = errors.New("Failed to update packages, see the log") | 104 » ErrEnsurePackagesFailed = errors.New("failed to update packages, see the log") |
| 102 ) | 105 ) |
| 103 | 106 |
| 104 // PackageACL is per package path per role access control list that is a part of | 107 // PackageACL is per package path per role access control list that is a part of |
| 105 // larger overall ACL: ACL for package "a/b/c" is a union of PackageACLs for "a" | 108 // larger overall ACL: ACL for package "a/b/c" is a union of PackageACLs for "a" |
| 106 // "a/b" and "a/b/c". | 109 // "a/b" and "a/b/c". |
| 107 type PackageACL struct { | 110 type PackageACL struct { |
| 108 // PackagePath is a package subpath this ACL is defined for. | 111 // PackagePath is a package subpath this ACL is defined for. |
| 109 PackagePath string | 112 PackagePath string |
| 110 // Role is a role that listed users have, e.g. 'READER', 'WRITER', ... | 113 // Role is a role that listed users have, e.g. 'READER', 'WRITER', ... |
| 111 Role string | 114 Role string |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 128 } | 131 } |
| 129 | 132 |
| 130 // UploadSession describes open CAS upload session. | 133 // UploadSession describes open CAS upload session. |
| 131 type UploadSession struct { | 134 type UploadSession struct { |
| 132 // ID identifies upload session in the backend. | 135 // ID identifies upload session in the backend. |
| 133 ID string | 136 ID string |
| 134 // URL is where to upload the data to. | 137 // URL is where to upload the data to. |
| 135 URL string | 138 URL string |
| 136 } | 139 } |
| 137 | 140 |
| 138 // Client provides high-level CIPD client interface. | 141 // Client provides high-level CIPD client interface. Thread safe. |
| 139 type Client interface { | 142 type Client interface { |
| 140 // FetchACL returns a list of PackageACL objects (parent paths first) th at | 143 // FetchACL returns a list of PackageACL objects (parent paths first) th at |
| 141 // together define the access control list for the given package subpath . | 144 // together define the access control list for the given package subpath . |
| 142 FetchACL(packagePath string) ([]PackageACL, error) | 145 FetchACL(packagePath string) ([]PackageACL, error) |
| 143 | 146 |
| 144 // ModifyACL applies a set of PackageACLChanges to a package path. | 147 // ModifyACL applies a set of PackageACLChanges to a package path. |
| 145 ModifyACL(packagePath string, changes []PackageACLChange) error | 148 ModifyACL(packagePath string, changes []PackageACLChange) error |
| 146 | 149 |
| 147 // UploadToCAS uploads package data blob to Content Addressed Store if i t is | 150 // UploadToCAS uploads package data blob to Content Addressed Store if i t is |
| 148 // not there already. The data is addressed by SHA1 hash (also known as | 151 // not there already. The data is addressed by SHA1 hash (also known as |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 184 // <package name> <desired version>. Whitespaces are ignored. Lines that start | 187 // <package name> <desired version>. Whitespaces are ignored. Lines that start |
| 185 // with '#' are ignored. Version can be specified as instance ID, tag or ref. | 188 // with '#' are ignored. Version can be specified as instance ID, tag or ref. |
| 186 // Will resolve tags and refs to concrete instance IDs by calling the ba ckend. | 189 // Will resolve tags and refs to concrete instance IDs by calling the ba ckend. |
| 187 ProcessEnsureFile(r io.Reader) ([]common.Pin, error) | 190 ProcessEnsureFile(r io.Reader) ([]common.Pin, error) |
| 188 | 191 |
| 189 // EnsurePackages is high-level interface for installation, removal and update | 192 // EnsurePackages is high-level interface for installation, removal and update |
| 190 // of packages inside the installation site root. Given a description of | 193 // of packages inside the installation site root. Given a description of |
| 191 // what packages (and versions) should be installed it will do all neces sary | 194 // what packages (and versions) should be installed it will do all neces sary |
| 192 // actions to bring the state of the site root to the desired one. | 195 // actions to bring the state of the site root to the desired one. |
| 193 EnsurePackages(pins []common.Pin) error | 196 EnsurePackages(pins []common.Pin) error |
| 197 | |
| 198 // Close should be called to dump any cached state to disk. | |
| 199 Close() | |
| 194 } | 200 } |
| 195 | 201 |
| 196 // HTTPClientFactory lazily creates http.Client to use for making requests. | 202 // HTTPClientFactory lazily creates http.Client to use for making requests. |
| 197 type HTTPClientFactory func() (*http.Client, error) | 203 type HTTPClientFactory func() (*http.Client, error) |
| 198 | 204 |
| 199 // ClientOptions is passed to NewClient factory function. | 205 // ClientOptions is passed to NewClient factory function. |
| 200 type ClientOptions struct { | 206 type ClientOptions struct { |
| 201 // ServiceURL is root URL of the backend service. | 207 // ServiceURL is root URL of the backend service. |
| 202 ServiceURL string | 208 ServiceURL string |
| 203 » // Root is a site root directory (where packages will be installed). It can | 209 |
| 204 » // be empty string if client is not going to be used to deploy or remove local packages. | 210 » // Root is a site root directory (a directory where packages will be |
| 211 » // installed to). It also hosts .cipd/* directory that tracks internal s tate | |
| 212 » // of installed packages and keeps various cache files. 'Root' can be an empty | |
| 213 » // string if the client is not going to be used to deploy or remove loca l | |
| 214 » // packages. In that case caches are also disabled. | |
| 205 Root string | 215 Root string |
| 216 | |
| 206 // Logger is a logger to use for logs (null-logger by default). | 217 // Logger is a logger to use for logs (null-logger by default). |
| 207 Logger logging.Logger | 218 Logger logging.Logger |
| 208 » // AuthenticatedClientFactory lazily creates http.Client to use for maki ng RPC requests. | 219 |
| 220 » // AuthenticatedClientFactory lazily creates http.Client to use for maki ng | |
| 221 » // RPC requests. | |
| 209 AuthenticatedClientFactory HTTPClientFactory | 222 AuthenticatedClientFactory HTTPClientFactory |
| 210 » // AnonymousClientFactory lazily creates http.Client to use for making r equests to storage. | 223 |
| 224 » // AnonymousClientFactory lazily creates http.Client to use for making | |
| 225 » // requests to storage. | |
| 211 AnonymousClientFactory HTTPClientFactory | 226 AnonymousClientFactory HTTPClientFactory |
| 227 | |
| 212 // UserAgent is put into User-Agent HTTP header with each request. | 228 // UserAgent is put into User-Agent HTTP header with each request. |
| 213 UserAgent string | 229 UserAgent string |
| 214 } | 230 } |
| 215 | 231 |
| 216 // NewClient initializes CIPD client object. | 232 // NewClient initializes CIPD client object. |
| 217 func NewClient(opts ClientOptions) Client { | 233 func NewClient(opts ClientOptions) Client { |
| 218 if opts.ServiceURL == "" { | 234 if opts.ServiceURL == "" { |
| 219 opts.ServiceURL = ServiceURL | 235 opts.ServiceURL = ServiceURL |
| 220 } | 236 } |
| 221 if opts.Logger == nil { | 237 if opts.Logger == nil { |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 236 } | 252 } |
| 237 c.remote = &remoteImpl{c} | 253 c.remote = &remoteImpl{c} |
| 238 c.storage = &storageImpl{c, uploadChunkSize} | 254 c.storage = &storageImpl{c, uploadChunkSize} |
| 239 c.deployer = local.NewDeployer(opts.Root, opts.Logger) | 255 c.deployer = local.NewDeployer(opts.Root, opts.Logger) |
| 240 return c | 256 return c |
| 241 } | 257 } |
| 242 | 258 |
| 243 type clientImpl struct { | 259 type clientImpl struct { |
| 244 ClientOptions | 260 ClientOptions |
| 245 | 261 |
| 246 » // clock provides current time and ability to sleep. | 262 » // lock protects lazily initialized portions of the client. |
| 263 » lock sync.Mutex | |
| 264 | |
| 265 » // clock provides current time and ability to sleep. Thread safe. | |
| 247 clock clock | 266 clock clock |
| 248 » // remote knows how to call backend REST API. | 267 |
| 268 » // remote knows how to call backend REST API. Thread safe. | |
| 249 remote remote | 269 remote remote |
| 270 | |
| 250 // storage knows how to upload and download raw binaries using signed UR Ls. | 271 // storage knows how to upload and download raw binaries using signed UR Ls. |
| 272 // Thread safe. | |
| 251 storage storage | 273 storage storage |
| 252 » // deployer knows how to install packages to local file system. | 274 |
| 275 » // deployer knows how to install packages to local file system. Thread s afe. | |
| 253 deployer local.Deployer | 276 deployer local.Deployer |
| 254 | 277 |
| 255 » // authClient is a lazily created http.Client to use for authenticated r equests. | 278 » // tagCache is used to cache (pkgname, tag) -> instanceID mapping. |
| 279 » // Thread safe, but lazily initialized under lock. | |
| 280 » tagCache internal.TagCache | |
| 281 | |
| 282 » // authClient is a lazily created http.Client to use for authenticated | |
| 283 » // requests. Thread safe, but lazily initialized under lock. | |
| 256 authClient *http.Client | 284 authClient *http.Client |
| 285 | |
| 257 // anonClient is a lazily created http.Client to use for anonymous reque sts. | 286 // anonClient is a lazily created http.Client to use for anonymous reque sts. |
| 287 // Thread safe, but lazily initialized under lock. | |
| 258 anonClient *http.Client | 288 anonClient *http.Client |
| 259 } | 289 } |
| 260 | 290 |
| 261 // doAuthenticatedHTTPRequest is used by remote implementation to make HTTP call s. | 291 // doAuthenticatedHTTPRequest is used by remote implementation to make HTTP call s. |
| 262 func (client *clientImpl) doAuthenticatedHTTPRequest(req *http.Request) (*http.R esponse, error) { | 292 func (client *clientImpl) doAuthenticatedHTTPRequest(req *http.Request) (*http.R esponse, error) { |
| 263 » if client.authClient == nil { | 293 » return client.doRequest(req, &client.authClient, client.AuthenticatedCli entFactory) |
| 264 » » var err error | |
| 265 » » client.authClient, err = client.AuthenticatedClientFactory() | |
| 266 » » if err != nil { | |
| 267 » » » return nil, err | |
| 268 » » } | |
| 269 » } | |
| 270 » return client.authClient.Do(req) | |
| 271 } | 294 } |
| 272 | 295 |
| 273 // doAnonymousHTTPRequest is used by storage implementation to make HTTP calls. | 296 // doAnonymousHTTPRequest is used by storage implementation to make HTTP calls. |
| 274 func (client *clientImpl) doAnonymousHTTPRequest(req *http.Request) (*http.Respo nse, error) { | 297 func (client *clientImpl) doAnonymousHTTPRequest(req *http.Request) (*http.Respo nse, error) { |
| 275 » if client.anonClient == nil { | 298 » return client.doRequest(req, &client.anonClient, client.AnonymousClientF actory) |
| 299 } | |
| 300 | |
| 301 // doRequest lazy-initializes http.Client by calling giving callback and then | |
|
tandrii(chromium)
2015/09/30 18:11:15
s/by calling giving callback/using provided factor
Vadim Sh.
2015/09/30 22:50:59
Done.
| |
| 302 // executes the request. | |
| 303 func (client *clientImpl) doRequest(req *http.Request, c **http.Client, fac HTTP ClientFactory) (*http.Response, error) { | |
| 304 » httpClient, err := func() (*http.Client, error) { | |
| 305 » » client.lock.Lock() | |
| 306 » » defer client.lock.Unlock() | |
| 276 var err error | 307 var err error |
| 277 » » client.anonClient, err = client.AnonymousClientFactory() | 308 » » if *c == nil { |
| 278 » » if err != nil { | 309 » » » *c, err = fac() |
| 279 » » » return nil, err | 310 » » } |
| 311 » » return *c, err | |
| 312 » }() | |
| 313 » if err != nil { | |
| 314 » » return nil, err | |
| 315 » } | |
| 316 » return httpClient.Do(req) | |
| 317 } | |
| 318 | |
| 319 // tagCachePath returns path to a tag cache file or "" if no root dir. | |
| 320 func (client *clientImpl) tagCachePath() string { | |
| 321 » if client.Root == "" { | |
| 322 » » return "" | |
| 323 » } | |
| 324 » return filepath.Join(client.Root, local.SiteServiceDir, "tagcache.db") | |
| 325 } | |
| 326 | |
| 327 // getTagCache lazy-initializes tagCache instance and returns it. | |
| 328 func (client *clientImpl) getTagCache() internal.TagCache { | |
| 329 » client.lock.Lock() | |
| 330 » defer client.lock.Unlock() | |
| 331 » if client.tagCache == nil { | |
| 332 » » if path := client.tagCachePath(); path != "" { | |
| 333 » » » var err error | |
| 334 » » » client.tagCache, err = internal.LoadTagCacheFromFile(pat h) | |
| 335 » » » if err != nil { | |
| 336 » » » » client.Logger.Warningf("cipd: failed to load tag cache - %s", err) | |
| 337 » » » » client.tagCache = internal.NewTagCache() | |
|
nodir
2015/09/30 19:08:23
remove this
Vadim Sh.
2015/09/30 22:50:59
Done.
| |
| 338 » » » } | |
| 339 » » } else { | |
| 340 » » » client.tagCache = internal.NewTagCache() | |
|
nodir
2015/09/30 19:08:23
remove this
Vadim Sh.
2015/09/30 22:50:58
Done.
| |
| 280 } | 341 } |
| 281 } | 342 } |
|
nodir
2015/09/30 19:08:23
add
if client.tagCache == nil {
client.TagCach
Vadim Sh.
2015/09/30 22:50:58
Done.
| |
| 282 » return client.anonClient.Do(req) | 343 » return client.tagCache |
| 344 } | |
| 345 | |
| 346 // closeTagCache dumps any changes made to tag cache to disk, if necessary. | |
| 347 // Called under lock. | |
|
tandrii(chromium)
2015/09/30 18:11:15
nit suggestion: s/.../Must be called under lock.
Vadim Sh.
2015/09/30 22:50:59
Done. Whatever.
| |
| 348 func (client *clientImpl) closeTagCache() { | |
| 349 » path := client.tagCachePath() | |
| 350 » if client.tagCache == nil || path == "" || !client.tagCache.Dirty() { | |
| 351 » » client.tagCache = nil | |
| 352 » » return | |
| 353 » } | |
| 354 » //It's tiny in size (and protobuf can't serialize to io.Reader anyway). Then | |
|
tandrii(chromium)
2015/09/30 18:11:15
nit: space between // and It
nit: s/Then/So,
Vadim Sh.
2015/09/30 22:50:59
Done.
| |
| 355 » // dump it to disk via FileSystem object to deal with possible concurren t | |
| 356 » // updates, missing directories, etc. | |
| 357 » fs := local.NewFileSystem(filepath.Dir(path), client.Logger) | |
| 358 » out, err := client.tagCache.Save() | |
| 359 » if err == nil { | |
| 360 » » err = fs.EnsureFile(path, out, 0666) | |
| 361 » } | |
| 362 » if err != nil { | |
| 363 » » client.Logger.Warningf("cipd: failed to update tag cache - %s", err) | |
| 364 » } | |
| 365 » client.tagCache = nil | |
| 283 } | 366 } |
| 284 | 367 |
| 285 func (client *clientImpl) FetchACL(packagePath string) ([]PackageACL, error) { | 368 func (client *clientImpl) FetchACL(packagePath string) ([]PackageACL, error) { |
| 286 return client.remote.fetchACL(packagePath) | 369 return client.remote.fetchACL(packagePath) |
| 287 } | 370 } |
| 288 | 371 |
| 289 func (client *clientImpl) ModifyACL(packagePath string, changes []PackageACLChan ge) error { | 372 func (client *clientImpl) ModifyACL(packagePath string, changes []PackageACLChan ge) error { |
| 290 return client.remote.modifyACL(packagePath, changes) | 373 return client.remote.modifyACL(packagePath, changes) |
| 291 } | 374 } |
| 292 | 375 |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 361 if err := common.ValidatePackageName(packageName); err != nil { | 444 if err := common.ValidatePackageName(packageName); err != nil { |
| 362 return common.Pin{}, err | 445 return common.Pin{}, err |
| 363 } | 446 } |
| 364 // Is it instance ID already? Don't bother calling the backend. | 447 // Is it instance ID already? Don't bother calling the backend. |
| 365 if common.ValidateInstanceID(version) == nil { | 448 if common.ValidateInstanceID(version) == nil { |
| 366 return common.Pin{PackageName: packageName, InstanceID: version} , nil | 449 return common.Pin{PackageName: packageName, InstanceID: version} , nil |
| 367 } | 450 } |
| 368 if err := common.ValidateInstanceVersion(version); err != nil { | 451 if err := common.ValidateInstanceVersion(version); err != nil { |
| 369 return common.Pin{}, err | 452 return common.Pin{}, err |
| 370 } | 453 } |
| 371 » return client.remote.resolveVersion(packageName, version) | 454 » // Use local cache when resolving tags to avoid round trips to backed wh en |
|
tandrii(chromium)
2015/09/30 18:11:15
s/backed/backend
Vadim Sh.
2015/09/30 22:50:59
Done.
| |
| 455 » // calling same 'cipd ensure' command again and again. | |
| 456 » isTag := common.ValidateInstanceTag(version) == nil | |
| 457 » if isTag { | |
| 458 » » cached := client.getTagCache().ResolveTag(packageName, version) | |
| 459 » » if cached.InstanceID != "" { | |
| 460 » » » return cached, nil | |
| 461 » » } | |
| 462 » } | |
| 463 » pin, err := client.remote.resolveVersion(packageName, version) | |
| 464 » if err != nil { | |
| 465 » » return pin, err | |
| 466 » } | |
| 467 » if isTag { | |
| 468 » » client.getTagCache().AddTag(pin, version) | |
| 469 » } | |
| 470 » return pin, nil | |
| 372 } | 471 } |
| 373 | 472 |
| 374 func (client *clientImpl) RegisterInstance(instance local.PackageInstance) error { | 473 func (client *clientImpl) RegisterInstance(instance local.PackageInstance) error { |
| 375 // Attempt to register. | 474 // Attempt to register. |
| 376 client.Logger.Infof("cipd: registering %s", instance.Pin()) | 475 client.Logger.Infof("cipd: registering %s", instance.Pin()) |
| 377 result, err := client.remote.registerInstance(instance.Pin()) | 476 result, err := client.remote.registerInstance(instance.Pin()) |
| 378 if err != nil { | 477 if err != nil { |
| 379 return err | 478 return err |
| 380 } | 479 } |
| 381 | 480 |
| (...skipping 240 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 622 } | 721 } |
| 623 } | 722 } |
| 624 | 723 |
| 625 if !fail { | 724 if !fail { |
| 626 client.Logger.Infof("All changes applied.") | 725 client.Logger.Infof("All changes applied.") |
| 627 return nil | 726 return nil |
| 628 } | 727 } |
| 629 return ErrEnsurePackagesFailed | 728 return ErrEnsurePackagesFailed |
| 630 } | 729 } |
| 631 | 730 |
| 731 func (client *clientImpl) Close() { | |
| 732 client.lock.Lock() | |
| 733 defer client.lock.Unlock() | |
| 734 client.closeTagCache() | |
| 735 client.authClient = nil | |
| 736 client.anonClient = nil | |
| 737 } | |
| 738 | |
| 632 //////////////////////////////////////////////////////////////////////////////// | 739 //////////////////////////////////////////////////////////////////////////////// |
| 633 // Private structs and interfaces. | 740 // Private structs and interfaces. |
| 634 | 741 |
| 635 type clock interface { | 742 type clock interface { |
| 636 now() time.Time | 743 now() time.Time |
| 637 sleep(time.Duration) | 744 sleep(time.Duration) |
| 638 } | 745 } |
| 639 | 746 |
| 640 type remote interface { | 747 type remote interface { |
| 641 fetchACL(packagePath string) ([]PackageACL, error) | 748 fetchACL(packagePath string) ([]PackageACL, error) |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 701 } | 808 } |
| 702 | 809 |
| 703 // buildInstanceIDMap builds mapping {package name -> instance ID}. | 810 // buildInstanceIDMap builds mapping {package name -> instance ID}. |
| 704 func buildInstanceIDMap(pins []common.Pin) map[string]string { | 811 func buildInstanceIDMap(pins []common.Pin) map[string]string { |
| 705 out := map[string]string{} | 812 out := map[string]string{} |
| 706 for _, p := range pins { | 813 for _, p := range pins { |
| 707 out[p.PackageName] = p.InstanceID | 814 out[p.PackageName] = p.InstanceID |
| 708 } | 815 } |
| 709 return out | 816 return out |
| 710 } | 817 } |
| OLD | NEW |