Repository: compose-spec/compose-go
Pull request #93 (2021-01-05 17:15:27)

Enable `all` as DeviceRequest.Count value and fix typo
Enable `all` as `Count` value and change `Diver`-> `Driver` in DeviceRequest struct.

Closes https://github.com/docker/dev-tooling-team/issues/264

Signed-off-by: aiordache <anca.iordache@docker.com>


Patch:
diff --git a/compatibility/deploy.go b/compatibility/deploy.go
index 4fb426a..dc7abd4 100644
--- a/compatibility/deploy.go
+++ b/compatibility/deploy.go
@@ -198,8 +198,8 @@ func (c *AllowList) CheckDeployResourcesDevicesIDs(s string, r types.DeviceReque
 
 func (c *AllowList) CheckDeployResourcesDevicesDriver(s string, r types.DeviceRequest) {
 	k := fmt.Sprintf("services.deploy.resources.%s.devices.driver", s)
-	if !c.supported(k) && r.Diver != "" {
-		r.Diver = ""
+	if !c.supported(k) && r.Driver != "" {
+		r.Driver = ""
 		c.Unsupported(k)
 	}
 }
diff --git a/loader/loader.go b/loader/loader.go
index 25399ef..a67c2a9 100644
--- a/loader/loader.go
+++ b/loader/loader.go
@@ -390,6 +390,7 @@ func createTransformHook(additionalTransformers ...Transformer) mapstructure.Dec
 		reflect.TypeOf(types.Duration(0)):                        transformStringToDuration,
 		reflect.TypeOf(types.DependsOnConfig{}):                  transformDependsOnConfig,
 		reflect.TypeOf(types.ExtendsConfig{}):                    transformExtendsConfig,
+		reflect.TypeOf(types.DeviceRequest{}):                    transformServiceDeviceRequest,
 	}
 
 	for _, transformer := range additionalTransformers {
@@ -843,6 +844,30 @@ var transformServicePort TransformerFunc = func(data interface{}) (interface{},
 	}
 }
 
+var transformServiceDeviceRequest TransformerFunc = func(data interface{}) (interface{}, error) {
+	switch value := data.(type) {
+	case map[string]interface{}:
+		count, ok := value["count"]
+		if ok {
+			switch val := count.(type) {
+			case int:
+				return value, nil
+			case string:
+				if strings.ToLower(val) == "all" {
+					value["count"] = -1
+					return value, nil
+				}
+				return data, errors.Errorf("invalid string value for 'count' (the only value allowed is 'all')")
+			default:
+				return data, errors.Errorf("invalid type %T for device count", val)
+			}
+		}
+		return data, nil
+	default:
+		return data, errors.Errorf("invalid type %T for resource reservation", value)
+	}
+}
+
 var transformStringSourceMap TransformerFunc = func(data interface{}) (interface{}, error) {
 	switch value := data.(type) {
 	case string:
diff --git a/types/types.go b/types/types.go
index 7d603ea..e9206f1 100644
--- a/types/types.go
+++ b/types/types.go
@@ -377,8 +377,8 @@ type Resource struct {
 
 type DeviceRequest struct {
 	Capabilities []string `mapstructure:"capabilities" yaml:"capabilities,omitempty" json:"capabilities,omitempty"`
-	Diver        string   `mapstructure:"driver" yaml:"driver,omitempty" json:"driver,omitempty"`
-	Count        int      `mapstructure:"count" yaml:"count,omitempty" json:"count,omitempty"`
+	Driver       string   `mapstructure:"driver" yaml:"driver,omitempty" json:"driver,omitempty"`
+	Count        int64    `mapstructure:"count" yaml:"count,omitempty" json:"count,omitempty"`
 	IDs          []string `mapstructure:"device_ids" yaml:"device_ids,omitempty" json:"device_ids,omitempty"`
 }
 


Test patch:
diff --git a/loader/loader_test.go b/loader/loader_test.go
index af1e4eb..48bc100 100644
--- a/loader/loader_test.go
+++ b/loader/loader_test.go
@@ -1697,3 +1697,35 @@ func TestLoadWithExtends(t *testing.T) {
 	}
 	assert.Check(t, is.DeepEqual(expServices, actual.Services))
 }
+
+func TestServiceDeviceRequestCount(t *testing.T) {
+	_, err := loadYAML(`
+services:
+  hello-world:
+    image: redis:alpine
+    deploy:
+      resources:
+        reservations:
+          devices:
+            - driver: nvidia
+              capabilities: [gpu]
+              count: all
+`)
+	assert.NilError(t, err)
+}
+
+func TestServiceDeviceRequestCountType(t *testing.T) {
+	_, err := loadYAML(`
+services:
+  hello-world:
+    image: redis:alpine
+    deploy:
+      resources:
+        reservations:
+          devices:
+            - driver: nvidia
+              capabilities: [gpu]
+              count: somestring
+`)
+	assert.ErrorContains(t, err, "invalid string value for 'count' (the only value allowed is 'all')")
+}