OLD | NEW |
---|---|
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 package cipd | 5 package cipd |
6 | 6 |
7 import ( | 7 import ( |
8 "bytes" | 8 "bytes" |
9 "encoding/json" | 9 "encoding/json" |
10 "errors" | 10 "errors" |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
60 Info packageInstanceInfo | 60 Info packageInstanceInfo |
61 } | 61 } |
62 | 62 |
63 // roleChangeMsg corresponds to RoleChange proto message on backend. | 63 // roleChangeMsg corresponds to RoleChange proto message on backend. |
64 type roleChangeMsg struct { | 64 type roleChangeMsg struct { |
65 Action string `json:"action"` | 65 Action string `json:"action"` |
66 Role string `json:"role"` | 66 Role string `json:"role"` |
67 Principal string `json:"principal"` | 67 Principal string `json:"principal"` |
68 } | 68 } |
69 | 69 |
70 // pendingProcessingError is returned by attachTags if package instance is not | |
71 // yet ready and the call should be retried later. | |
72 type pendingProcessingError struct { | |
73 message string | |
74 } | |
75 | |
76 func (e *pendingProcessingError) Error() string { | |
77 return e.message | |
78 } | |
79 | |
70 // newRemoteService is mocked in tests. | 80 // newRemoteService is mocked in tests. |
71 var newRemoteService = func(client *http.Client, url string, log logging.Logger) *remoteService { | 81 var newRemoteService = func(client *http.Client, url string, log logging.Logger) *remoteService { |
72 log.Infof("cipd: service URL is %s", url) | 82 log.Infof("cipd: service URL is %s", url) |
73 return &remoteService{ | 83 return &remoteService{ |
74 client: client, | 84 client: client, |
75 serviceURL: url, | 85 serviceURL: url, |
76 log: log, | 86 log: log, |
77 } | 87 } |
78 } | 88 } |
79 | 89 |
(...skipping 252 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
332 } | 342 } |
333 switch reply.Status { | 343 switch reply.Status { |
334 case "SUCCESS": | 344 case "SUCCESS": |
335 return nil | 345 return nil |
336 case "ERROR": | 346 case "ERROR": |
337 return errors.New(reply.ErrorMessage) | 347 return errors.New(reply.ErrorMessage) |
338 } | 348 } |
339 return fmt.Errorf("Unexpected reply status: %s", reply.Status) | 349 return fmt.Errorf("Unexpected reply status: %s", reply.Status) |
340 } | 350 } |
341 | 351 |
352 func (r *remoteService) attachTags(packageName, instanceID string, tags []string ) error { | |
353 // Tags will be passed in the request body, not via URL. | |
354 endpoint, err := tagsEndpoint(packageName, instanceID, nil) | |
355 if err != nil { | |
356 return err | |
357 } | |
358 | |
359 if len(tags) == 0 { | |
360 return errors.New("At least one tag must be provided") | |
361 } | |
362 for _, tag := range tags { | |
363 err = ValidateInstanceTag(tag) | |
364 if err != nil { | |
365 return err | |
366 } | |
367 } | |
368 var request struct { | |
369 Tags []string `json:"tags"` | |
370 } | |
371 request.Tags = tags | |
372 | |
373 var reply struct { | |
374 Status string `json:"status"` | |
375 ErrorMessage string `json:"error_message"` | |
376 } | |
nodir
2015/05/07 04:19:02
I like the fact that you can define a struct in Go
| |
377 err = r.makeRequest(endpoint, "POST", &request, &reply) | |
378 if err != nil { | |
379 return err | |
380 } | |
381 switch reply.Status { | |
382 case "SUCCESS": | |
383 return nil | |
384 case "PROCESSING_NOT_FINISHED_YET": | |
385 return &pendingProcessingError{message: reply.ErrorMessage} | |
nodir
2015/05/07 04:19:02
nit: I think you can omit `message: ` in simple ca
Vadim Sh.
2015/05/07 05:07:58
Done. I forget about this "feature".
| |
386 case "ERROR", "PROCESSING_FAILED": | |
387 return errors.New(reply.ErrorMessage) | |
388 } | |
389 return fmt.Errorf("Unexpected status when attaching tags: %s", reply.Sta tus) | |
nodir
2015/05/07 04:19:02
I wonder if you should panic in this case. How do
Vadim Sh.
2015/05/07 05:07:58
Simple: never panic. Once you start panicing, you'
nodir
2015/05/07 06:47:11
But this is a really-really unexpected condition :
Vadim Sh.
2015/05/07 06:50:06
No, not really. I can totally see how server can a
| |
390 } | |
391 | |
342 //////////////////////////////////////////////////////////////////////////////// | 392 //////////////////////////////////////////////////////////////////////////////// |
343 | 393 |
344 func instanceEndpoint(packageName, instanceID string) (string, error) { | 394 func instanceEndpoint(packageName, instanceID string) (string, error) { |
345 err := ValidatePackageName(packageName) | 395 err := ValidatePackageName(packageName) |
346 if err != nil { | 396 if err != nil { |
347 return "", err | 397 return "", err |
348 } | 398 } |
349 err = ValidateInstanceID(instanceID) | 399 err = ValidateInstanceID(instanceID) |
350 if err != nil { | 400 if err != nil { |
351 return "", err | 401 return "", err |
352 } | 402 } |
353 params := url.Values{} | 403 params := url.Values{} |
354 params.Add("package_name", packageName) | 404 params.Add("package_name", packageName) |
355 params.Add("instance_id", instanceID) | 405 params.Add("instance_id", instanceID) |
356 return "repo/v1/instance?" + params.Encode(), nil | 406 return "repo/v1/instance?" + params.Encode(), nil |
357 } | 407 } |
358 | 408 |
359 func aclEndpoint(packagePath string) (string, error) { | 409 func aclEndpoint(packagePath string) (string, error) { |
360 err := ValidatePackageName(packagePath) | 410 err := ValidatePackageName(packagePath) |
361 if err != nil { | 411 if err != nil { |
362 return "", err | 412 return "", err |
363 } | 413 } |
364 params := url.Values{} | 414 params := url.Values{} |
365 params.Add("package_path", packagePath) | 415 params.Add("package_path", packagePath) |
366 return "repo/v1/acl?" + params.Encode(), nil | 416 return "repo/v1/acl?" + params.Encode(), nil |
367 } | 417 } |
368 | 418 |
419 func tagsEndpoint(packageName, instanceID string, tags []string) (string, error) { | |
420 err := ValidatePackageName(packageName) | |
421 if err != nil { | |
422 return "", err | |
423 } | |
424 err = ValidateInstanceID(instanceID) | |
425 if err != nil { | |
426 return "", err | |
427 } | |
428 for _, tag := range tags { | |
429 err = ValidateInstanceTag(tag) | |
nodir
2015/05/07 04:19:02
why would you write this code if never used?
Vadim Sh.
2015/05/07 05:07:58
It will be used soonish for detachTags call. I can
| |
430 if err != nil { | |
431 return "", err | |
432 } | |
433 } | |
434 params := url.Values{} | |
435 params.Add("package_name", packageName) | |
436 params.Add("instance_id", instanceID) | |
437 for _, tag := range tags { | |
438 params.Add("tag", tag) | |
439 } | |
440 return "repo/v1/tags?" + params.Encode(), nil | |
441 } | |
442 | |
369 // convertTimestamp coverts string with int64 timestamp in microseconds since | 443 // convertTimestamp coverts string with int64 timestamp in microseconds since |
370 // to time.Time | 444 // to time.Time |
371 func convertTimestamp(ts string) (time.Time, error) { | 445 func convertTimestamp(ts string) (time.Time, error) { |
372 i, err := strconv.ParseInt(ts, 10, 64) | 446 i, err := strconv.ParseInt(ts, 10, 64) |
373 if err != nil { | 447 if err != nil { |
374 return time.Time{}, fmt.Errorf("Unexpected timestamp value '%s' in the server response", ts) | 448 return time.Time{}, fmt.Errorf("Unexpected timestamp value '%s' in the server response", ts) |
375 } | 449 } |
376 return time.Unix(0, i*1000), nil | 450 return time.Unix(0, i*1000), nil |
377 } | 451 } |
378 | 452 |
379 func makePackageInstanceInfo(msg packageInstanceMsg) (pi packageInstanceInfo, er r error) { | 453 func makePackageInstanceInfo(msg packageInstanceMsg) (pi packageInstanceInfo, er r error) { |
380 ts, err := convertTimestamp(msg.RegisteredTs) | 454 ts, err := convertTimestamp(msg.RegisteredTs) |
381 if err != nil { | 455 if err != nil { |
382 return | 456 return |
383 } | 457 } |
384 pi = packageInstanceInfo{ | 458 pi = packageInstanceInfo{ |
385 PackageName: msg.PackageName, | 459 PackageName: msg.PackageName, |
386 InstanceID: msg.InstanceID, | 460 InstanceID: msg.InstanceID, |
387 RegisteredBy: msg.RegisteredBy, | 461 RegisteredBy: msg.RegisteredBy, |
388 RegisteredTs: ts, | 462 RegisteredTs: ts, |
389 } | 463 } |
390 return | 464 return |
391 } | 465 } |
OLD | NEW |