Skip to content

Commit 999fab0

Browse files
committed
add support for config credentialspecs to compose
Signed-off-by: Drew Erny <[email protected]>
1 parent 23b54b8 commit 999fab0

5 files changed

Lines changed: 142 additions & 53 deletions

File tree

cli/compose/convert/service.go

Lines changed: 62 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -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
}

cli/compose/convert/service_test.go

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,7 @@ func TestConvertCredentialSpec(t *testing.T) {
318318
name string
319319
in composetypes.CredentialSpecConfig
320320
out *swarm.CredentialSpec
321+
configs []*swarm.ConfigReference
321322
expectedErr string
322323
}{
323324
{
@@ -343,10 +344,41 @@ func TestConvertCredentialSpec(t *testing.T) {
343344
in: composetypes.CredentialSpecConfig{Config: "0bt9dmxjvjiqermk6xrop3ekq", File: "somefile.json", Registry: "testing"},
344345
expectedErr: `invalid credential spec: cannot specify both "Config", "File", and "Registry"`,
345346
},
347+
{
348+
name: "missing-config-reference",
349+
in: composetypes.CredentialSpecConfig{Config: "missing"},
350+
expectedErr: "invalid credential spec: spec specifies config missing, but no such config can be found",
351+
configs: []*swarm.ConfigReference{
352+
{
353+
ConfigName: "someName",
354+
ConfigID: "missing",
355+
},
356+
},
357+
},
358+
{
359+
name: "namespaced-config",
360+
in: composetypes.CredentialSpecConfig{Config: "name"},
361+
configs: []*swarm.ConfigReference{
362+
{
363+
ConfigName: "namespaced-config_name",
364+
ConfigID: "someID",
365+
},
366+
},
367+
out: &swarm.CredentialSpec{Config: "someID"},
368+
},
346369
{
347370
name: "config",
348-
in: composetypes.CredentialSpecConfig{Config: "0bt9dmxjvjiqermk6xrop3ekq"},
349-
out: &swarm.CredentialSpec{Config: "0bt9dmxjvjiqermk6xrop3ekq"},
371+
in: composetypes.CredentialSpecConfig{Config: "someName"},
372+
configs: []*swarm.ConfigReference{
373+
{
374+
ConfigName: "someOtherName",
375+
ConfigID: "someOtherID",
376+
}, {
377+
ConfigName: "someName",
378+
ConfigID: "someID",
379+
},
380+
},
381+
out: &swarm.CredentialSpec{Config: "someID"},
350382
},
351383
{
352384
name: "file",
@@ -363,7 +395,8 @@ func TestConvertCredentialSpec(t *testing.T) {
363395
for _, tc := range tests {
364396
tc := tc
365397
t.Run(tc.name, func(t *testing.T) {
366-
swarmSpec, err := convertCredentialSpec(tc.in)
398+
namespace := NewNamespace(tc.name)
399+
swarmSpec, err := convertCredentialSpec(namespace, tc.in, tc.configs)
367400

368401
if tc.expectedErr != "" {
369402
assert.Error(t, err, tc.expectedErr)

cli/compose/schema/bindata.go

Lines changed: 37 additions & 37 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

cli/compose/schema/data/config_schema_v3.8.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,8 @@
115115
"target": {"type": "string"},
116116
"uid": {"type": "string"},
117117
"gid": {"type": "string"},
118-
"mode": {"type": "number"}
118+
"mode": {"type": "number"},
119+
"runtime": {"type": "boolean"}
119120
}
120121
}
121122
]

cli/compose/types/types.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -408,6 +408,11 @@ type FileReferenceConfig struct {
408408
UID string `yaml:",omitempty" json:"uid,omitempty"`
409409
GID string `yaml:",omitempty" json:"gid,omitempty"`
410410
Mode *uint32 `yaml:",omitempty" json:"mode,omitempty"`
411+
// Runtime is set `true` if reference isn't actually used as a File in
412+
// the service. Specifically, this currently only indicates that the Config
413+
// is used as a CredentialSpec. If this field is set `true`, then all other
414+
// fields besides `Source` must be empty.
415+
Runtime bool `yaml:",omitempty" json:"runtime,omitempty"`
411416
}
412417

413418
// ServiceConfigObjConfig is the config obj configuration for a service

0 commit comments

Comments
 (0)