@@ -109,7 +109,9 @@ func Service(
109109 }
110110
111111 var privileges swarm.Privileges
112- privileges .CredentialSpec , err = convertCredentialSpec (service .CredentialSpec )
112+ privileges .CredentialSpec , err = convertCredentialSpec (
113+ namespace , service .CredentialSpec , configs ,
114+ )
113115 if err != nil {
114116 return swarm.ServiceSpec {}, err
115117 }
@@ -308,11 +310,24 @@ func convertServiceConfigObjs(
308310 return nil , err
309311 }
310312
311- file := swarm .ConfigReferenceFileTarget (obj .File )
312- refs = append (refs , & swarm.ConfigReference {
313- File : & file ,
314- ConfigName : obj .Name ,
315- })
313+ // if the obj.File is identical to the zero-value of
314+ // swarmReferenceTarget, that means this is a Runtime-type config. This
315+ // code may have to be made more robust later, if Runtime targets start
316+ // including data or other targets are created, but for now it works
317+ // fine to do this check, and it's much easier than the alternatives
318+ // (which involve altering the swarmReferenceObject type)
319+ if (obj .File == swarmReferenceTarget {}) {
320+ refs = append (refs , & swarm.ConfigReference {
321+ ConfigName : obj .Name ,
322+ Runtime : & swarm.ConfigReferenceRuntimeTarget {},
323+ })
324+ } else {
325+ file := swarm .ConfigReferenceFileTarget (obj .File )
326+ refs = append (refs , & swarm.ConfigReference {
327+ File : & file ,
328+ ConfigName : obj .Name ,
329+ })
330+ }
316331 }
317332
318333 confs , err := servicecli .ParseConfigs (client , refs )
@@ -342,11 +357,6 @@ func convertFileObject(
342357 config composetypes.FileReferenceConfig ,
343358 lookup func (key string ) (composetypes.FileObjectConfig , error ),
344359) (swarmReferenceObject , error ) {
345- target := config .Target
346- if target == "" {
347- target = config .Source
348- }
349-
350360 obj , err := lookup (config .Source )
351361 if err != nil {
352362 return swarmReferenceObject {}, err
@@ -357,6 +367,28 @@ func convertFileObject(
357367 source = obj .Name
358368 }
359369
370+ // if the config is a Runtime config, that means we don't mount it as a
371+ // file in the container. This is used for supporting CredentialSpec
372+ // configs.
373+ if config .Runtime {
374+ if config .Target != "" || config .UID != "" || config .GID != "" || config .Mode != nil {
375+ return swarmReferenceObject {}, errors .Errorf (
376+ "config %v is a runtime config, but has file options set" ,
377+ config .Source ,
378+ )
379+ }
380+
381+ return swarmReferenceObject {
382+ Name : source ,
383+ // File is the zero-value for Runtime configs
384+ }, nil
385+ }
386+
387+ target := config .Target
388+ if target == "" {
389+ target = config .Source
390+ }
391+
360392 uid := config .UID
361393 gid := config .GID
362394 if uid == "" {
@@ -599,7 +631,7 @@ func convertDNSConfig(DNS []string, DNSSearch []string) (*swarm.DNSConfig, error
599631 return nil , nil
600632}
601633
602- func convertCredentialSpec (spec composetypes.CredentialSpecConfig ) (* swarm.CredentialSpec , error ) {
634+ func convertCredentialSpec (namespace Namespace , spec composetypes.CredentialSpecConfig , refs [] * swarm. ConfigReference ) (* swarm.CredentialSpec , error ) {
603635 var o []string
604636
605637 // Config was added in API v1.40
@@ -622,5 +654,23 @@ func convertCredentialSpec(spec composetypes.CredentialSpecConfig) (*swarm.Crede
622654 return nil , errors .Errorf ("invalid credential spec: cannot specify both %s, and %s" , strings .Join (o [:l - 1 ], ", " ), o [l - 1 ])
623655 }
624656 swarmCredSpec := swarm .CredentialSpec (spec )
657+ // if we're using a swarm Config for the credential spec, over-write it
658+ // here with the config ID
659+ if swarmCredSpec .Config != "" {
660+ for _ , config := range refs {
661+ if swarmCredSpec .Config == config .ConfigName {
662+ swarmCredSpec .Config = config .ConfigID
663+ return & swarmCredSpec , nil
664+ }
665+ }
666+ // if none of the configs match, try namespacing
667+ for _ , config := range refs {
668+ if namespace .Scope (swarmCredSpec .Config ) == config .ConfigName {
669+ swarmCredSpec .Config = config .ConfigID
670+ return & swarmCredSpec , nil
671+ }
672+ }
673+ return nil , errors .Errorf ("invalid credential spec: spec specifies config %v, but no such config can be found" , swarmCredSpec .Config )
674+ }
625675 return & swarmCredSpec , nil
626676}
0 commit comments