ParseConfigs retrieves the configs from the requested names and converts them to config references to use with the spec
(ctx context.Context, apiClient client.ConfigAPIClient, requestedConfigs []*swarm.ConfigReference)
| 62 | // ParseConfigs retrieves the configs from the requested names and converts |
| 63 | // them to config references to use with the spec |
| 64 | func ParseConfigs(ctx context.Context, apiClient client.ConfigAPIClient, requestedConfigs []*swarm.ConfigReference) ([]*swarm.ConfigReference, error) { |
| 65 | if len(requestedConfigs) == 0 { |
| 66 | return []*swarm.ConfigReference{}, nil |
| 67 | } |
| 68 | |
| 69 | // the configRefs map has two purposes: it prevents duplication of config |
| 70 | // target filenames. It is used to get all configs, so we can resolve |
| 71 | // their IDs. unfortunately, there are other targets for ConfigReferences, |
| 72 | // besides just a File; specifically, the Runtime target, which is used for |
| 73 | // CredentialSpecs. Therefore, we need to have a list of ConfigReferences |
| 74 | // that are not File targets as well. at this time of writing, the only use |
| 75 | // for Runtime targets is CredentialSpecs. However, to future-proof this |
| 76 | // functionality, we should handle the case where multiple Runtime targets |
| 77 | // are in use for the same Config, and we should deduplicate |
| 78 | // such ConfigReferences, as no matter how many times the Config is used, |
| 79 | // it is only needed to be referenced once. |
| 80 | configRefs := make(map[string]*swarm.ConfigReference) |
| 81 | runtimeRefs := make(map[string]*swarm.ConfigReference) |
| 82 | |
| 83 | for _, config := range requestedConfigs { |
| 84 | // copy the config, so we don't mutate the args |
| 85 | configRef := new(swarm.ConfigReference) |
| 86 | *configRef = *config |
| 87 | |
| 88 | if config.Runtime != nil { |
| 89 | // by assigning to a map based on ConfigName, if the same Config |
| 90 | // is required as a Runtime target for multiple purposes, we only |
| 91 | // include it once in the final set of configs. |
| 92 | runtimeRefs[config.ConfigName] = config |
| 93 | // continue, so we skip the logic below for handling file-type |
| 94 | // configs |
| 95 | continue |
| 96 | } |
| 97 | |
| 98 | if _, exists := configRefs[config.File.Name]; exists { |
| 99 | return nil, fmt.Errorf("duplicate config target for %s not allowed", config.ConfigName) |
| 100 | } |
| 101 | |
| 102 | configRefs[config.File.Name] = configRef |
| 103 | } |
| 104 | |
| 105 | args := make(client.Filters) |
| 106 | for _, s := range configRefs { |
| 107 | args.Add("name", s.ConfigName) |
| 108 | } |
| 109 | for _, s := range runtimeRefs { |
| 110 | args.Add("name", s.ConfigName) |
| 111 | } |
| 112 | |
| 113 | res, err := apiClient.ConfigList(ctx, client.ConfigListOptions{ |
| 114 | Filters: args, |
| 115 | }) |
| 116 | if err != nil { |
| 117 | return nil, err |
| 118 | } |
| 119 | |
| 120 | foundConfigs := make(map[string]string) |
| 121 | for _, config := range res.Items { |
no test coverage detected
searching dependent graphs…