2016-10-19 12:22:02 -04:00
|
|
|
package service
|
|
|
|
|
|
|
|
import (
|
2018-05-03 21:02:44 -04:00
|
|
|
"context"
|
|
|
|
|
2016-10-19 12:22:02 -04:00
|
|
|
"github.com/docker/docker/api/types"
|
|
|
|
"github.com/docker/docker/api/types/filters"
|
|
|
|
swarmtypes "github.com/docker/docker/api/types/swarm"
|
2017-05-08 13:51:30 -04:00
|
|
|
"github.com/docker/docker/client"
|
2017-03-09 13:23:45 -05:00
|
|
|
"github.com/pkg/errors"
|
2016-10-19 12:22:02 -04:00
|
|
|
)
|
|
|
|
|
2017-03-16 13:54:18 -04:00
|
|
|
// ParseSecrets retrieves the secrets with the requested names and fills
|
|
|
|
// secret IDs into the secret references.
|
2023-09-09 18:27:44 -04:00
|
|
|
func ParseSecrets(ctx context.Context, apiClient client.SecretAPIClient, requestedSecrets []*swarmtypes.SecretReference) ([]*swarmtypes.SecretReference, error) {
|
2017-06-07 11:02:46 -04:00
|
|
|
if len(requestedSecrets) == 0 {
|
|
|
|
return []*swarmtypes.SecretReference{}, nil
|
|
|
|
}
|
|
|
|
|
2016-10-27 20:57:38 -04:00
|
|
|
secretRefs := make(map[string]*swarmtypes.SecretReference)
|
2016-10-19 12:22:02 -04:00
|
|
|
|
|
|
|
for _, secret := range requestedSecrets {
|
2017-03-16 13:54:18 -04:00
|
|
|
if _, exists := secretRefs[secret.File.Name]; exists {
|
2017-03-09 13:23:45 -05:00
|
|
|
return nil, errors.Errorf("duplicate secret target for %s not allowed", secret.SecretName)
|
2016-11-15 10:04:36 -05:00
|
|
|
}
|
2017-03-16 13:54:18 -04:00
|
|
|
secretRef := new(swarmtypes.SecretReference)
|
|
|
|
*secretRef = *secret
|
|
|
|
secretRefs[secret.File.Name] = secretRef
|
2016-10-19 12:22:02 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
args := filters.NewArgs()
|
2016-10-27 20:57:38 -04:00
|
|
|
for _, s := range secretRefs {
|
2016-12-05 11:08:43 -05:00
|
|
|
args.Add("name", s.SecretName)
|
2016-10-19 12:22:02 -04:00
|
|
|
}
|
|
|
|
|
2023-11-20 11:38:50 -05:00
|
|
|
secrets, err := apiClient.SecretList(ctx, types.SecretListOptions{
|
2016-11-03 14:09:13 -04:00
|
|
|
Filters: args,
|
2016-10-19 12:22:02 -04:00
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2016-10-27 03:41:32 -04:00
|
|
|
foundSecrets := make(map[string]string)
|
2016-10-19 12:22:02 -04:00
|
|
|
for _, secret := range secrets {
|
2016-10-27 03:41:32 -04:00
|
|
|
foundSecrets[secret.Spec.Annotations.Name] = secret.ID
|
2016-10-19 12:22:02 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
addedSecrets := []*swarmtypes.SecretReference{}
|
|
|
|
|
2016-10-27 20:57:38 -04:00
|
|
|
for _, ref := range secretRefs {
|
|
|
|
id, ok := foundSecrets[ref.SecretName]
|
2016-10-27 20:18:12 -04:00
|
|
|
if !ok {
|
2017-03-09 13:23:45 -05:00
|
|
|
return nil, errors.Errorf("secret not found: %s", ref.SecretName)
|
2016-10-27 20:18:12 -04:00
|
|
|
}
|
|
|
|
|
2016-10-19 12:22:02 -04:00
|
|
|
// set the id for the ref to properly assign in swarm
|
|
|
|
// since swarm needs the ID instead of the name
|
2016-10-27 20:57:38 -04:00
|
|
|
ref.SecretID = id
|
|
|
|
addedSecrets = append(addedSecrets, ref)
|
2016-10-19 12:22:02 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
return addedSecrets, nil
|
|
|
|
}
|
2017-05-08 13:36:04 -04:00
|
|
|
|
|
|
|
// ParseConfigs retrieves the configs from the requested names and converts
|
|
|
|
// them to config references to use with the spec
|
2023-09-09 18:27:44 -04:00
|
|
|
func ParseConfigs(ctx context.Context, apiClient client.ConfigAPIClient, requestedConfigs []*swarmtypes.ConfigReference) ([]*swarmtypes.ConfigReference, error) {
|
2017-06-07 11:02:46 -04:00
|
|
|
if len(requestedConfigs) == 0 {
|
|
|
|
return []*swarmtypes.ConfigReference{}, nil
|
|
|
|
}
|
|
|
|
|
2019-03-27 16:44:32 -04:00
|
|
|
// the configRefs map has two purposes: it prevents duplication of config
|
2023-11-20 08:41:32 -05:00
|
|
|
// target filenames. It is used to get all configs, so we can resolve
|
2019-03-27 16:44:32 -04:00
|
|
|
// their IDs. unfortunately, there are other targets for ConfigReferences,
|
|
|
|
// besides just a File; specifically, the Runtime target, which is used for
|
|
|
|
// CredentialSpecs. Therefore, we need to have a list of ConfigReferences
|
|
|
|
// that are not File targets as well. at this time of writing, the only use
|
|
|
|
// for Runtime targets is CredentialSpecs. However, to future-proof this
|
|
|
|
// functionality, we should handle the case where multiple Runtime targets
|
|
|
|
// are in use for the same Config, and we should deduplicate
|
|
|
|
// such ConfigReferences, as no matter how many times the Config is used,
|
|
|
|
// it is only needed to be referenced once.
|
2017-05-08 13:36:04 -04:00
|
|
|
configRefs := make(map[string]*swarmtypes.ConfigReference)
|
2019-03-27 16:44:32 -04:00
|
|
|
runtimeRefs := make(map[string]*swarmtypes.ConfigReference)
|
2017-05-08 13:36:04 -04:00
|
|
|
|
|
|
|
for _, config := range requestedConfigs {
|
2019-03-28 15:06:06 -04:00
|
|
|
// copy the config, so we don't mutate the args
|
|
|
|
configRef := new(swarmtypes.ConfigReference)
|
|
|
|
*configRef = *config
|
|
|
|
|
2019-03-27 16:44:32 -04:00
|
|
|
if config.Runtime != nil {
|
|
|
|
// by assigning to a map based on ConfigName, if the same Config
|
|
|
|
// is required as a Runtime target for multiple purposes, we only
|
|
|
|
// include it once in the final set of configs.
|
|
|
|
runtimeRefs[config.ConfigName] = config
|
2019-03-28 15:06:06 -04:00
|
|
|
// continue, so we skip the logic below for handling file-type
|
|
|
|
// configs
|
|
|
|
continue
|
2019-03-27 16:44:32 -04:00
|
|
|
}
|
|
|
|
|
2017-05-08 13:36:04 -04:00
|
|
|
if _, exists := configRefs[config.File.Name]; exists {
|
|
|
|
return nil, errors.Errorf("duplicate config target for %s not allowed", config.ConfigName)
|
|
|
|
}
|
|
|
|
|
|
|
|
configRefs[config.File.Name] = configRef
|
|
|
|
}
|
|
|
|
|
|
|
|
args := filters.NewArgs()
|
|
|
|
for _, s := range configRefs {
|
|
|
|
args.Add("name", s.ConfigName)
|
|
|
|
}
|
2019-03-27 16:44:32 -04:00
|
|
|
for _, s := range runtimeRefs {
|
|
|
|
args.Add("name", s.ConfigName)
|
|
|
|
}
|
2017-05-08 13:36:04 -04:00
|
|
|
|
2023-11-20 11:38:50 -05:00
|
|
|
configs, err := apiClient.ConfigList(ctx, types.ConfigListOptions{
|
2017-05-08 13:36:04 -04:00
|
|
|
Filters: args,
|
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
foundConfigs := make(map[string]string)
|
|
|
|
for _, config := range configs {
|
|
|
|
foundConfigs[config.Spec.Annotations.Name] = config.ID
|
|
|
|
}
|
|
|
|
|
|
|
|
addedConfigs := []*swarmtypes.ConfigReference{}
|
|
|
|
|
|
|
|
for _, ref := range configRefs {
|
|
|
|
id, ok := foundConfigs[ref.ConfigName]
|
|
|
|
if !ok {
|
|
|
|
return nil, errors.Errorf("config not found: %s", ref.ConfigName)
|
|
|
|
}
|
|
|
|
|
|
|
|
// set the id for the ref to properly assign in swarm
|
|
|
|
// since swarm needs the ID instead of the name
|
|
|
|
ref.ConfigID = id
|
|
|
|
addedConfigs = append(addedConfigs, ref)
|
|
|
|
}
|
|
|
|
|
2019-03-27 16:44:32 -04:00
|
|
|
// unfortunately, because the key of configRefs and runtimeRefs is different
|
|
|
|
// values that may collide, we can't just do some fancy trickery to
|
|
|
|
// concat maps, we need to do two separate loops
|
|
|
|
for _, ref := range runtimeRefs {
|
|
|
|
id, ok := foundConfigs[ref.ConfigName]
|
|
|
|
if !ok {
|
|
|
|
return nil, errors.Errorf("config not found: %s", ref.ConfigName)
|
|
|
|
}
|
|
|
|
|
|
|
|
ref.ConfigID = id
|
|
|
|
addedConfigs = append(addedConfigs, ref)
|
|
|
|
}
|
|
|
|
|
2017-05-08 13:36:04 -04:00
|
|
|
return addedConfigs, nil
|
|
|
|
}
|