Skip to content

Commit 8158217

Browse files
committed
prefer canonical transform vs DecodeMapStructure
Signed-off-by: Nicolas De Loof <[email protected]>
1 parent 48d3a5b commit 8158217

File tree

5 files changed

+47
-55
lines changed

5 files changed

+47
-55
lines changed

loader/loader_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2205,7 +2205,7 @@ services:
22052205
count: 2
22062206
device_ids: ["my-device-id"]
22072207
`)
2208-
assert.ErrorContains(t, err, `invalid "count" and "device_ids" are attributes are exclusive`)
2208+
assert.ErrorContains(t, err, `"count" and "device_ids" attributes are exclusive`)
22092209
}
22102210

22112211
func TestServiceDeviceRequestCapabilitiesMandatory(t *testing.T) {
@@ -2221,7 +2221,7 @@ services:
22212221
- driver: nvidia
22222222
count: 2
22232223
`)
2224-
assert.ErrorContains(t, err, `"capabilities" attribute is mandatory for device request definition`)
2224+
assert.ErrorContains(t, err, `capabilities is required`)
22252225
}
22262226

22272227
func TestServicePullPolicy(t *testing.T) {

schema/compose-spec.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -642,7 +642,10 @@
642642
"options":{"$ref": "#/definitions/list_or_dict"}
643643
},
644644
"additionalProperties": false,
645-
"patternProperties": {"^x-": {}}
645+
"patternProperties": {"^x-": {}},
646+
"required": [
647+
"capabilities"
648+
]
646649
}
647650
},
648651

transform/canonical.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ func init() {
2929
transformers["services.*.build.secrets.*"] = transformFileMount
3030
transformers["services.*.build.additional_contexts"] = transformKeyValue
3131
transformers["services.*.depends_on"] = transformDependsOn
32+
transformers["services.*.deploy.resources.reservations.devices.*"] = transformDeviceRequest
3233
transformers["services.*.env_file"] = transformEnvFile
3334
transformers["services.*.extends"] = transformExtends
3435
transformers["services.*.networks"] = transformServiceNetworks

transform/devices.go

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/*
2+
Copyright 2020 The Compose Specification Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package transform
18+
19+
import (
20+
"fmt"
21+
22+
"github.com/compose-spec/compose-go/v2/tree"
23+
)
24+
25+
func transformDeviceRequest(data any, p tree.Path, ignoreParseError bool) (any, error) {
26+
switch v := data.(type) {
27+
case map[string]any:
28+
_, hasCount := v["count"]
29+
_, hasIds := v["device_ids"]
30+
if hasCount && hasIds {
31+
return nil, fmt.Errorf(`%s: "count" and "device_ids" attributes are exclusive`, p)
32+
}
33+
if !hasCount && !hasIds {
34+
v["count"] = "all"
35+
}
36+
return transformMapping(v, p, ignoreParseError)
37+
default:
38+
return data, fmt.Errorf("%s: invalid type %T for device request", p, v)
39+
}
40+
}

types/device.go

Lines changed: 0 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -51,55 +51,3 @@ func (c *DeviceCount) DecodeMapstructure(value interface{}) error {
5151
}
5252
return nil
5353
}
54-
55-
func (d *DeviceRequest) DecodeMapstructure(value interface{}) error {
56-
v, ok := value.(map[string]any)
57-
if !ok {
58-
return fmt.Errorf("invalid device request type %T", value)
59-
}
60-
if _, okCaps := v["capabilities"]; !okCaps {
61-
return fmt.Errorf(`"capabilities" attribute is mandatory for device request definition`)
62-
}
63-
if _, okCount := v["count"]; okCount {
64-
if _, okDeviceIds := v["device_ids"]; okDeviceIds {
65-
return fmt.Errorf(`invalid "count" and "device_ids" are attributes are exclusive`)
66-
}
67-
}
68-
d.Count = DeviceCount(-1)
69-
70-
capabilities := v["capabilities"]
71-
caps := StringList{}
72-
if err := caps.DecodeMapstructure(capabilities); err != nil {
73-
return err
74-
}
75-
d.Capabilities = caps
76-
if driver, ok := v["driver"]; ok {
77-
if val, ok := driver.(string); ok {
78-
d.Driver = val
79-
} else {
80-
return fmt.Errorf("invalid type for driver value: %T", driver)
81-
}
82-
}
83-
if count, ok := v["count"]; ok {
84-
if err := d.Count.DecodeMapstructure(count); err != nil {
85-
return err
86-
}
87-
}
88-
if deviceIDs, ok := v["device_ids"]; ok {
89-
ids := StringList{}
90-
if err := ids.DecodeMapstructure(deviceIDs); err != nil {
91-
return err
92-
}
93-
d.IDs = ids
94-
d.Count = DeviceCount(len(ids))
95-
}
96-
97-
d.Options = Mapping{}
98-
if options, ok := v["options"].(map[string]any); ok {
99-
for k, v := range options {
100-
d.Options[k] = fmt.Sprint(v)
101-
}
102-
}
103-
return nil
104-
105-
}

0 commit comments

Comments
 (0)