diff --git a/components/engine/daemon/cluster/helpers.go b/components/engine/daemon/cluster/helpers.go index eee426bd48..6523a80e1c 100644 --- a/components/engine/daemon/cluster/helpers.go +++ b/components/engine/daemon/cluster/helpers.go @@ -24,116 +24,178 @@ func getSwarm(ctx context.Context, c swarmapi.ControlClient) (*swarmapi.Cluster, func getNode(ctx context.Context, c swarmapi.ControlClient, input string) (*swarmapi.Node, error) { // GetNode to match via full ID. - rg, err := c.GetNode(ctx, &swarmapi.GetNodeRequest{NodeID: input}) - if err != nil { - // If any error (including NotFound), ListNodes to match via full name. - rl, err := c.ListNodes(ctx, &swarmapi.ListNodesRequest{Filters: &swarmapi.ListNodesRequest_Filters{Names: []string{input}}}) - - if err != nil || len(rl.Nodes) == 0 { - // If any error or 0 result, ListNodes to match via ID prefix. - rl, err = c.ListNodes(ctx, &swarmapi.ListNodesRequest{Filters: &swarmapi.ListNodesRequest_Filters{IDPrefixes: []string{input}}}) - } - - if err != nil { - return nil, err - } - - if len(rl.Nodes) == 0 { - err := fmt.Errorf("node %s not found", input) - return nil, errors.NewRequestNotFoundError(err) - } - - if l := len(rl.Nodes); l > 1 { - return nil, fmt.Errorf("node %s is ambiguous (%d matches found)", input, l) - } - - return rl.Nodes[0], nil + if rg, err := c.GetNode(ctx, &swarmapi.GetNodeRequest{NodeID: input}); err == nil { + return rg.Node, nil } - return rg.Node, nil + + // If any error (including NotFound), ListNodes to match via full name. + rl, err := c.ListNodes(ctx, &swarmapi.ListNodesRequest{ + Filters: &swarmapi.ListNodesRequest_Filters{ + Names: []string{input}, + }, + }) + if err != nil || len(rl.Nodes) == 0 { + // If any error or 0 result, ListNodes to match via ID prefix. + rl, err = c.ListNodes(ctx, &swarmapi.ListNodesRequest{ + Filters: &swarmapi.ListNodesRequest_Filters{ + IDPrefixes: []string{input}, + }, + }) + } + if err != nil { + return nil, err + } + + if len(rl.Nodes) == 0 { + err := fmt.Errorf("node %s not found", input) + return nil, errors.NewRequestNotFoundError(err) + } + + if l := len(rl.Nodes); l > 1 { + return nil, fmt.Errorf("node %s is ambiguous (%d matches found)", input, l) + } + + return rl.Nodes[0], nil } func getService(ctx context.Context, c swarmapi.ControlClient, input string) (*swarmapi.Service, error) { // GetService to match via full ID. - rg, err := c.GetService(ctx, &swarmapi.GetServiceRequest{ServiceID: input}) - if err != nil { - // If any error (including NotFound), ListServices to match via full name. - rl, err := c.ListServices(ctx, &swarmapi.ListServicesRequest{Filters: &swarmapi.ListServicesRequest_Filters{Names: []string{input}}}) - if err != nil || len(rl.Services) == 0 { - // If any error or 0 result, ListServices to match via ID prefix. - rl, err = c.ListServices(ctx, &swarmapi.ListServicesRequest{Filters: &swarmapi.ListServicesRequest_Filters{IDPrefixes: []string{input}}}) - } - - if err != nil { - return nil, err - } - - if len(rl.Services) == 0 { - err := fmt.Errorf("service %s not found", input) - return nil, errors.NewRequestNotFoundError(err) - } - - if l := len(rl.Services); l > 1 { - return nil, fmt.Errorf("service %s is ambiguous (%d matches found)", input, l) - } - - return rl.Services[0], nil + if rg, err := c.GetService(ctx, &swarmapi.GetServiceRequest{ServiceID: input}); err == nil { + return rg.Service, nil } - return rg.Service, nil + + // If any error (including NotFound), ListServices to match via full name. + rl, err := c.ListServices(ctx, &swarmapi.ListServicesRequest{ + Filters: &swarmapi.ListServicesRequest_Filters{ + Names: []string{input}, + }, + }) + if err != nil || len(rl.Services) == 0 { + // If any error or 0 result, ListServices to match via ID prefix. + rl, err = c.ListServices(ctx, &swarmapi.ListServicesRequest{ + Filters: &swarmapi.ListServicesRequest_Filters{ + IDPrefixes: []string{input}, + }, + }) + } + if err != nil { + return nil, err + } + + if len(rl.Services) == 0 { + err := fmt.Errorf("service %s not found", input) + return nil, errors.NewRequestNotFoundError(err) + } + + if l := len(rl.Services); l > 1 { + return nil, fmt.Errorf("service %s is ambiguous (%d matches found)", input, l) + } + + return rl.Services[0], nil } func getTask(ctx context.Context, c swarmapi.ControlClient, input string) (*swarmapi.Task, error) { // GetTask to match via full ID. - rg, err := c.GetTask(ctx, &swarmapi.GetTaskRequest{TaskID: input}) - if err != nil { - // If any error (including NotFound), ListTasks to match via full name. - rl, err := c.ListTasks(ctx, &swarmapi.ListTasksRequest{Filters: &swarmapi.ListTasksRequest_Filters{Names: []string{input}}}) - - if err != nil || len(rl.Tasks) == 0 { - // If any error or 0 result, ListTasks to match via ID prefix. - rl, err = c.ListTasks(ctx, &swarmapi.ListTasksRequest{Filters: &swarmapi.ListTasksRequest_Filters{IDPrefixes: []string{input}}}) - } - - if err != nil { - return nil, err - } - - if len(rl.Tasks) == 0 { - err := fmt.Errorf("task %s not found", input) - return nil, errors.NewRequestNotFoundError(err) - } - - if l := len(rl.Tasks); l > 1 { - return nil, fmt.Errorf("task %s is ambiguous (%d matches found)", input, l) - } - - return rl.Tasks[0], nil + if rg, err := c.GetTask(ctx, &swarmapi.GetTaskRequest{TaskID: input}); err == nil { + return rg.Task, nil } - return rg.Task, nil + + // If any error (including NotFound), ListTasks to match via full name. + rl, err := c.ListTasks(ctx, &swarmapi.ListTasksRequest{ + Filters: &swarmapi.ListTasksRequest_Filters{ + Names: []string{input}, + }, + }) + if err != nil || len(rl.Tasks) == 0 { + // If any error or 0 result, ListTasks to match via ID prefix. + rl, err = c.ListTasks(ctx, &swarmapi.ListTasksRequest{ + Filters: &swarmapi.ListTasksRequest_Filters{ + IDPrefixes: []string{input}, + }, + }) + } + if err != nil { + return nil, err + } + + if len(rl.Tasks) == 0 { + err := fmt.Errorf("task %s not found", input) + return nil, errors.NewRequestNotFoundError(err) + } + + if l := len(rl.Tasks); l > 1 { + return nil, fmt.Errorf("task %s is ambiguous (%d matches found)", input, l) + } + + return rl.Tasks[0], nil +} + +func getSecret(ctx context.Context, c swarmapi.ControlClient, input string) (*swarmapi.Secret, error) { + // attempt to lookup secret by full ID + if rg, err := c.GetSecret(ctx, &swarmapi.GetSecretRequest{SecretID: input}); err == nil { + return rg.Secret, nil + } + + // If any error (including NotFound), ListSecrets to match via full name. + rl, err := c.ListSecrets(ctx, &swarmapi.ListSecretsRequest{ + Filters: &swarmapi.ListSecretsRequest_Filters{ + Names: []string{input}, + }, + }) + if err != nil || len(rl.Secrets) == 0 { + // If any error or 0 result, ListSecrets to match via ID prefix. + rl, err = c.ListSecrets(ctx, &swarmapi.ListSecretsRequest{ + Filters: &swarmapi.ListSecretsRequest_Filters{ + IDPrefixes: []string{input}, + }, + }) + } + if err != nil { + return nil, err + } + + if len(rl.Secrets) == 0 { + err := fmt.Errorf("secret %s not found", input) + return nil, errors.NewRequestNotFoundError(err) + } + + if l := len(rl.Secrets); l > 1 { + return nil, fmt.Errorf("secret %s is ambiguous (%d matches found)", input, l) + } + + return rl.Secrets[0], nil } func getNetwork(ctx context.Context, c swarmapi.ControlClient, input string) (*swarmapi.Network, error) { // GetNetwork to match via full ID. - rg, err := c.GetNetwork(ctx, &swarmapi.GetNetworkRequest{NetworkID: input}) - if err != nil { - // If any error (including NotFound), ListNetworks to match via ID prefix and full name. - rl, err := c.ListNetworks(ctx, &swarmapi.ListNetworksRequest{Filters: &swarmapi.ListNetworksRequest_Filters{Names: []string{input}}}) - if err != nil || len(rl.Networks) == 0 { - rl, err = c.ListNetworks(ctx, &swarmapi.ListNetworksRequest{Filters: &swarmapi.ListNetworksRequest_Filters{IDPrefixes: []string{input}}}) - } - - if err != nil { - return nil, err - } - - if len(rl.Networks) == 0 { - return nil, fmt.Errorf("network %s not found", input) - } - - if l := len(rl.Networks); l > 1 { - return nil, fmt.Errorf("network %s is ambiguous (%d matches found)", input, l) - } - - return rl.Networks[0], nil + if rg, err := c.GetNetwork(ctx, &swarmapi.GetNetworkRequest{NetworkID: input}); err == nil { + return rg.Network, nil } - return rg.Network, nil + + // If any error (including NotFound), ListNetworks to match via ID prefix and full name. + rl, err := c.ListNetworks(ctx, &swarmapi.ListNetworksRequest{ + Filters: &swarmapi.ListNetworksRequest_Filters{ + Names: []string{input}, + }, + }) + if err != nil || len(rl.Networks) == 0 { + rl, err = c.ListNetworks(ctx, &swarmapi.ListNetworksRequest{ + Filters: &swarmapi.ListNetworksRequest_Filters{ + IDPrefixes: []string{input}, + }, + }) + } + if err != nil { + return nil, err + } + + if len(rl.Networks) == 0 { + return nil, fmt.Errorf("network %s not found", input) + } + + if l := len(rl.Networks); l > 1 { + return nil, fmt.Errorf("network %s is ambiguous (%d matches found)", input, l) + } + + return rl.Networks[0], nil } diff --git a/components/engine/daemon/cluster/secrets.go b/components/engine/daemon/cluster/secrets.go index 8cde36f729..240b561047 100644 --- a/components/engine/daemon/cluster/secrets.go +++ b/components/engine/daemon/cluster/secrets.go @@ -1,63 +1,14 @@ package cluster import ( - "fmt" - "strings" - apitypes "github.com/docker/docker/api/types" types "github.com/docker/docker/api/types/swarm" "github.com/docker/docker/daemon/cluster/convert" swarmapi "github.com/docker/swarmkit/api" - "golang.org/x/net/context" ) -func getSecretByNameOrIDPrefix(ctx context.Context, state *nodeState, nameOrIDPrefix string) (*swarmapi.Secret, error) { - // attempt to lookup secret by full ID - if r, err := state.controlClient.GetSecret(ctx, &swarmapi.GetSecretRequest{ - SecretID: nameOrIDPrefix, - }); err == nil { - return r.Secret, nil - } - - // attempt to lookup secret by full name and partial ID - // Note here ListSecretRequest_Filters operate with `or` - r, err := state.controlClient.ListSecrets(ctx, &swarmapi.ListSecretsRequest{ - Filters: &swarmapi.ListSecretsRequest_Filters{ - Names: []string{nameOrIDPrefix}, - IDPrefixes: []string{nameOrIDPrefix}, - }, - }) - if err != nil { - return nil, err - } - - // attempt to lookup secret by full name - for _, s := range r.Secrets { - if s.Spec.Annotations.Name == nameOrIDPrefix { - return s, nil - } - } - // attempt to lookup secret by partial ID (prefix) - // return error if more than one matches found (ambiguous) - n := 0 - var found *swarmapi.Secret - for _, s := range r.Secrets { - if strings.HasPrefix(s.ID, nameOrIDPrefix) { - found = s - n++ - } - } - if n > 1 { - return nil, fmt.Errorf("secret %s is ambiguous (%d matches found)", nameOrIDPrefix, n) - } - if found == nil { - return nil, fmt.Errorf("no such secret: %s", nameOrIDPrefix) - } - return found, nil -} - // GetSecret returns a secret from a managed swarm cluster -func (c *Cluster) GetSecret(nameOrIDPrefix string) (types.Secret, error) { +func (c *Cluster) GetSecret(input string) (types.Secret, error) { c.mu.RLock() defer c.mu.RUnlock() @@ -69,7 +20,7 @@ func (c *Cluster) GetSecret(nameOrIDPrefix string) (types.Secret, error) { ctx, cancel := c.getRequestContext() defer cancel() - secret, err := getSecretByNameOrIDPrefix(ctx, &state, nameOrIDPrefix) + secret, err := getSecret(ctx, state.controlClient, input) if err != nil { return types.Secret{}, err } @@ -133,7 +84,7 @@ func (c *Cluster) CreateSecret(s types.SecretSpec) (string, error) { } // RemoveSecret removes a secret from a managed swarm cluster. -func (c *Cluster) RemoveSecret(nameOrIDPrefix string) error { +func (c *Cluster) RemoveSecret(input string) error { c.mu.RLock() defer c.mu.RUnlock() @@ -145,7 +96,7 @@ func (c *Cluster) RemoveSecret(nameOrIDPrefix string) error { ctx, cancel := c.getRequestContext() defer cancel() - secret, err := getSecretByNameOrIDPrefix(ctx, &state, nameOrIDPrefix) + secret, err := getSecret(ctx, state.controlClient, input) if err != nil { return err }