idresolver.go 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. package idresolver
  2. import (
  3. "fmt"
  4. "golang.org/x/net/context"
  5. "github.com/docker/docker/api/types/swarm"
  6. "github.com/docker/docker/client"
  7. "github.com/docker/docker/pkg/stringid"
  8. )
  9. // IDResolver provides ID to Name resolution.
  10. type IDResolver struct {
  11. client client.APIClient
  12. noResolve bool
  13. cache map[string]string
  14. }
  15. // New creates a new IDResolver.
  16. func New(client client.APIClient, noResolve bool) *IDResolver {
  17. return &IDResolver{
  18. client: client,
  19. noResolve: noResolve,
  20. cache: make(map[string]string),
  21. }
  22. }
  23. func (r *IDResolver) get(ctx context.Context, t interface{}, id string) (string, error) {
  24. switch t := t.(type) {
  25. case swarm.Node:
  26. node, _, err := r.client.NodeInspectWithRaw(ctx, id)
  27. if err != nil {
  28. return id, nil
  29. }
  30. if node.Spec.Annotations.Name != "" {
  31. return node.Spec.Annotations.Name, nil
  32. }
  33. if node.Description.Hostname != "" {
  34. return node.Description.Hostname, nil
  35. }
  36. return id, nil
  37. case swarm.Service:
  38. service, _, err := r.client.ServiceInspectWithRaw(ctx, id)
  39. if err != nil {
  40. return id, nil
  41. }
  42. return service.Spec.Annotations.Name, nil
  43. case swarm.Task:
  44. // If the caller passes the full task there's no need to do a lookup.
  45. if t.ID == "" {
  46. var err error
  47. t, _, err = r.client.TaskInspectWithRaw(ctx, id)
  48. if err != nil {
  49. return id, nil
  50. }
  51. }
  52. taskID := stringid.TruncateID(t.ID)
  53. if t.ServiceID == "" {
  54. return taskID, nil
  55. }
  56. service, err := r.Resolve(ctx, swarm.Service{}, t.ServiceID)
  57. if err != nil {
  58. return "", err
  59. }
  60. return fmt.Sprintf("%s.%d.%s", service, t.Slot, taskID), nil
  61. default:
  62. return "", fmt.Errorf("unsupported type")
  63. }
  64. }
  65. // Resolve will attempt to resolve an ID to a Name by querying the manager.
  66. // Results are stored into a cache.
  67. // If the `-n` flag is used in the command-line, resolution is disabled.
  68. func (r *IDResolver) Resolve(ctx context.Context, t interface{}, id string) (string, error) {
  69. if r.noResolve {
  70. return id, nil
  71. }
  72. if name, ok := r.cache[id]; ok {
  73. return name, nil
  74. }
  75. name, err := r.get(ctx, t, id)
  76. if err != nil {
  77. return "", err
  78. }
  79. r.cache[id] = name
  80. return name, nil
  81. }