github.1git.de/docker/cli@v26.1.3+incompatible/cli/command/idresolver/idresolver.go (about)

     1  // FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
     2  //go:build go1.19
     3  
     4  package idresolver
     5  
     6  import (
     7  	"context"
     8  
     9  	"github.com/docker/docker/api/types"
    10  	"github.com/docker/docker/api/types/swarm"
    11  	"github.com/docker/docker/client"
    12  	"github.com/pkg/errors"
    13  )
    14  
    15  // IDResolver provides ID to Name resolution.
    16  type IDResolver struct {
    17  	client    client.APIClient
    18  	noResolve bool
    19  	cache     map[string]string
    20  }
    21  
    22  // New creates a new IDResolver.
    23  func New(apiClient client.APIClient, noResolve bool) *IDResolver {
    24  	return &IDResolver{
    25  		client:    apiClient,
    26  		noResolve: noResolve,
    27  		cache:     make(map[string]string),
    28  	}
    29  }
    30  
    31  func (r *IDResolver) get(ctx context.Context, t any, id string) (string, error) {
    32  	switch t.(type) {
    33  	case swarm.Node:
    34  		node, _, err := r.client.NodeInspectWithRaw(ctx, id)
    35  		if err != nil {
    36  			// TODO(thaJeztah): should error-handling be more specific, or is it ok to ignore any error?
    37  			return id, nil //nolint:nilerr // ignore nil-error being returned, as this is a best-effort.
    38  		}
    39  		if node.Spec.Annotations.Name != "" {
    40  			return node.Spec.Annotations.Name, nil
    41  		}
    42  		if node.Description.Hostname != "" {
    43  			return node.Description.Hostname, nil
    44  		}
    45  		return id, nil
    46  	case swarm.Service:
    47  		service, _, err := r.client.ServiceInspectWithRaw(ctx, id, types.ServiceInspectOptions{})
    48  		if err != nil {
    49  			// TODO(thaJeztah): should error-handling be more specific, or is it ok to ignore any error?
    50  			return id, nil //nolint:nilerr // ignore nil-error being returned, as this is a best-effort.
    51  		}
    52  		return service.Spec.Annotations.Name, nil
    53  	default:
    54  		return "", errors.Errorf("unsupported type")
    55  	}
    56  }
    57  
    58  // Resolve will attempt to resolve an ID to a Name by querying the manager.
    59  // Results are stored into a cache.
    60  // If the `-n` flag is used in the command-line, resolution is disabled.
    61  func (r *IDResolver) Resolve(ctx context.Context, t any, id string) (string, error) {
    62  	if r.noResolve {
    63  		return id, nil
    64  	}
    65  	if name, ok := r.cache[id]; ok {
    66  		return name, nil
    67  	}
    68  	name, err := r.get(ctx, t, id)
    69  	if err != nil {
    70  		return "", err
    71  	}
    72  	r.cache[id] = name
    73  	return name, nil
    74  }