Repository: compose-spec/compose-go
Pull request #209 (2021-11-24 19:05:56)

Add support for `device_cgroup_rules`
Service config option `device_cgroup_rules` was already included in [compose-spec.json](https://github.com/compose-spec/compose-go/blob/3f80afa60dbd7c58ca5be455ecf3625e9b53a593/schema/compose-spec.json#L200), but was left unmapped.

The proposed changes map `device_cgroup_rules` to ServiceConfig field `DeviceCgroupRules`.


Patch:
diff --git a/compatibility/checker.go b/compatibility/checker.go
index 12aedc9..9ababb8 100644
--- a/compatibility/checker.go
+++ b/compatibility/checker.go
@@ -55,6 +55,7 @@ type Checker interface {
 	CheckContainerName(service *types.ServiceConfig)
 	CheckCredentialSpec(service *types.ServiceConfig)
 	CheckDependsOn(service *types.ServiceConfig)
+	CheckDeviceCgroupRules(service *types.ServiceConfig)
 	CheckDevices(service *types.ServiceConfig)
 	CheckDNS(service *types.ServiceConfig)
 	CheckDNSOpts(service *types.ServiceConfig)
@@ -299,6 +300,7 @@ func CheckServiceConfig(service *types.ServiceConfig, c Checker) {
 			c.CheckUpdateConfigParallelism(UpdateConfigRollback, service.Deploy.RollbackConfig)
 		}
 	}
+	c.CheckDeviceCgroupRules(service)
 	c.CheckDevices(service)
 	c.CheckDNS(service)
 	c.CheckDNSOpts(service)
diff --git a/compatibility/services.go b/compatibility/services.go
index fc68dc2..68b65e0 100644
--- a/compatibility/services.go
+++ b/compatibility/services.go
@@ -198,6 +198,13 @@ func (c *AllowList) CheckDependsOn(service *types.ServiceConfig) {
 	}
 }
 
+func (c *AllowList) CheckDeviceCgroupRules(service *types.ServiceConfig) {
+	if !c.supported("services.device_cgroup_rules") && len(service.DeviceCgroupRules) != 0 {
+		service.DeviceCgroupRules = nil
+		c.Unsupported("services.device_cgroup_rules")
+	}
+}
+
 func (c *AllowList) CheckDevices(service *types.ServiceConfig) {
 	if !c.supported("services.devices") && len(service.Devices) != 0 {
 		service.Devices = nil
diff --git a/loader/full-example.yml b/loader/full-example.yml
index 529d28b..c13c58d 100644
--- a/loader/full-example.yml
+++ b/loader/full-example.yml
@@ -85,6 +85,10 @@ services:
           - spread: node.labels.az
       endpoint_mode: dnsrr
 
+    device_cgroup_rules:
+      - "c 1:3 mr"
+      - "a 7:* rmw"
+
     devices:
       - "/dev/ttyUSB0:/dev/ttyUSB0"
 
diff --git a/types/types.go b/types/types.go
index 1aff90c..7f953bf 100644
--- a/types/types.go
+++ b/types/types.go
@@ -88,89 +88,90 @@ type ServiceConfig struct {
 	Name     string   `yaml:"-" json:"-"`
 	Profiles []string `mapstructure:"profiles" yaml:"profiles,omitempty" json:"profiles,omitempty"`
 
-	Build           *BuildConfig                     `yaml:",omitempty" json:"build,omitempty"`
-	BlkioConfig     *BlkioConfig                     `mapstructure:"blkio_config" yaml:",omitempty" json:"blkio_config,omitempty"`
-	CapAdd          []string                         `mapstructure:"cap_add" yaml:"cap_add,omitempty" json:"cap_add,omitempty"`
-	CapDrop         []string                         `mapstructure:"cap_drop" yaml:"cap_drop,omitempty" json:"cap_drop,omitempty"`
-	CgroupParent    string                           `mapstructure:"cgroup_parent" yaml:"cgroup_parent,omitempty" json:"cgroup_parent,omitempty"`
-	CPUCount        int64                            `mapstructure:"cpu_count" yaml:"cpu_count,omitempty" json:"cpu_count,omitempty"`
-	CPUPercent      float32                          `mapstructure:"cpu_percent" yaml:"cpu_percent,omitempty" json:"cpu_percent,omitempty"`
-	CPUPeriod       int64                            `mapstructure:"cpu_period" yaml:"cpu_period,omitempty" json:"cpu_period,omitempty"`
-	CPUQuota        int64                            `mapstructure:"cpu_quota" yaml:"cpu_quota,omitempty" json:"cpu_quota,omitempty"`
-	CPURTPeriod     int64                            `mapstructure:"cpu_rt_period" yaml:"cpu_rt_period,omitempty" json:"cpu_rt_period,omitempty"`
-	CPURTRuntime    int64                            `mapstructure:"cpu_rt_runtime" yaml:"cpu_rt_runtime,omitempty" json:"cpu_rt_runtime,omitempty"`
-	CPUS            float32                          `mapstructure:"cpus" yaml:"cpus,omitempty" json:"cpus,omitempty"`
-	CPUSet          string                           `mapstructure:"cpuset" yaml:"cpuset,omitempty" json:"cpuset,omitempty"`
-	CPUShares       int64                            `mapstructure:"cpu_shares" yaml:"cpu_shares,omitempty" json:"cpu_shares,omitempty"`
-	Command         ShellCommand                     `yaml:",omitempty" json:"command,omitempty"`
-	Configs         []ServiceConfigObjConfig         `yaml:",omitempty" json:"configs,omitempty"`
-	ContainerName   string                           `mapstructure:"container_name" yaml:"container_name,omitempty" json:"container_name,omitempty"`
-	CredentialSpec  *CredentialSpecConfig            `mapstructure:"credential_spec" yaml:"credential_spec,omitempty" json:"credential_spec,omitempty"`
-	DependsOn       DependsOnConfig                  `mapstructure:"depends_on" yaml:"depends_on,omitempty" json:"depends_on,omitempty"`
-	Deploy          *DeployConfig                    `yaml:",omitempty" json:"deploy,omitempty"`
-	Devices         []string                         `yaml:",omitempty" json:"devices,omitempty"`
-	DNS             StringList                       `yaml:",omitempty" json:"dns,omitempty"`
-	DNSOpts         []string                         `mapstructure:"dns_opt" yaml:"dns_opt,omitempty" json:"dns_opt,omitempty"`
-	DNSSearch       StringList                       `mapstructure:"dns_search" yaml:"dns_search,omitempty" json:"dns_search,omitempty"`
-	Dockerfile      string                           `yaml:"dockerfile,omitempty" json:"dockerfile,omitempty"`
-	DomainName      string                           `mapstructure:"domainname" yaml:"domainname,omitempty" json:"domainname,omitempty"`
-	Entrypoint      ShellCommand                     `yaml:",omitempty" json:"entrypoint,omitempty"`
-	Environment     MappingWithEquals                `yaml:",omitempty" json:"environment,omitempty"`
-	EnvFile         StringList                       `mapstructure:"env_file" yaml:"env_file,omitempty" json:"env_file,omitempty"`
-	Expose          StringOrNumberList               `yaml:",omitempty" json:"expose,omitempty"`
-	Extends         ExtendsConfig                    `yaml:"extends,omitempty" json:"extends,omitempty"`
-	ExternalLinks   []string                         `mapstructure:"external_links" yaml:"external_links,omitempty" json:"external_links,omitempty"`
-	ExtraHosts      HostsList                        `mapstructure:"extra_hosts" yaml:"extra_hosts,omitempty" json:"extra_hosts,omitempty"`
-	GroupAdd        []string                         `mapstructure:"group_add" yaml:"group_add,omitempty" json:"group_add,omitempty"`
-	Hostname        string                           `yaml:",omitempty" json:"hostname,omitempty"`
-	HealthCheck     *HealthCheckConfig               `yaml:",omitempty" json:"healthcheck,omitempty"`
-	Image           string                           `yaml:",omitempty" json:"image,omitempty"`
-	Init            *bool                            `yaml:",omitempty" json:"init,omitempty"`
-	Ipc             string                           `yaml:",omitempty" json:"ipc,omitempty"`
-	Isolation       string                           `mapstructure:"isolation" yaml:"isolation,omitempty" json:"isolation,omitempty"`
-	Labels          Labels                           `yaml:",omitempty" json:"labels,omitempty"`
-	CustomLabels    Labels                           `yaml:"-" json:"-"`
-	Links           []string                         `yaml:",omitempty" json:"links,omitempty"`
-	Logging         *LoggingConfig                   `yaml:",omitempty" json:"logging,omitempty"`
-	LogDriver       string                           `mapstructure:"log_driver" yaml:"log_driver,omitempty" json:"log_driver,omitempty"`
-	LogOpt          map[string]string                `mapstructure:"log_opt" yaml:"log_opt,omitempty" json:"log_opt,omitempty"`
-	MemLimit        UnitBytes                        `mapstructure:"mem_limit" yaml:"mem_limit,omitempty" json:"mem_limit,omitempty"`
-	MemReservation  UnitBytes                        `mapstructure:"mem_reservation" yaml:"mem_reservation,omitempty" json:"mem_reservation,omitempty"`
-	MemSwapLimit    UnitBytes                        `mapstructure:"memswap_limit" yaml:"memswap_limit,omitempty" json:"memswap_limit,omitempty"`
-	MemSwappiness   UnitBytes                        `mapstructure:"mem_swappiness" yaml:"mem_swappiness,omitempty" json:"mem_swappiness,omitempty"`
-	MacAddress      string                           `mapstructure:"mac_address" yaml:"mac_address,omitempty" json:"mac_address,omitempty"`
-	Net             string                           `yaml:"net,omitempty" json:"net,omitempty"`
-	NetworkMode     string                           `mapstructure:"network_mode" yaml:"network_mode,omitempty" json:"network_mode,omitempty"`
-	Networks        map[string]*ServiceNetworkConfig `yaml:",omitempty" json:"networks,omitempty"`
-	OomKillDisable  bool                             `mapstructure:"oom_kill_disable" yaml:"oom_kill_disable,omitempty" json:"oom_kill_disable,omitempty"`
-	OomScoreAdj     int64                            `mapstructure:"oom_score_adj" yaml:"oom_score_adj,omitempty" json:"oom_score_adj,omitempty"`
-	Pid             string                           `yaml:",omitempty" json:"pid,omitempty"`
-	PidsLimit       int64                            `mapstructure:"pids_limit" yaml:"pids_limit,omitempty" json:"pids_limit,omitempty"`
-	Platform        string                           `yaml:",omitempty" json:"platform,omitempty"`
-	Ports           []ServicePortConfig              `yaml:",omitempty" json:"ports,omitempty"`
-	Privileged      bool                             `yaml:",omitempty" json:"privileged,omitempty"`
-	PullPolicy      string                           `mapstructure:"pull_policy" yaml:"pull_policy,omitempty" json:"pull_policy,omitempty"`
-	ReadOnly        bool                             `mapstructure:"read_only" yaml:"read_only,omitempty" json:"read_only,omitempty"`
-	Restart         string                           `yaml:",omitempty" json:"restart,omitempty"`
-	Runtime         string                           `yaml:",omitempty" json:"runtime,omitempty"`
-	Scale           int                              `yaml:"-" json:"-"`
-	Secrets         []ServiceSecretConfig            `yaml:",omitempty" json:"secrets,omitempty"`
-	SecurityOpt     []string                         `mapstructure:"security_opt" yaml:"security_opt,omitempty" json:"security_opt,omitempty"`
-	ShmSize         UnitBytes                        `mapstructure:"shm_size" yaml:"shm_size,omitempty" json:"shm_size,omitempty"`
-	StdinOpen       bool                             `mapstructure:"stdin_open" yaml:"stdin_open,omitempty" json:"stdin_open,omitempty"`
-	StopGracePeriod *Duration                        `mapstructure:"stop_grace_period" yaml:"stop_grace_period,omitempty" json:"stop_grace_period,omitempty"`
-	StopSignal      string                           `mapstructure:"stop_signal" yaml:"stop_signal,omitempty" json:"stop_signal,omitempty"`
-	Sysctls         Mapping                          `yaml:",omitempty" json:"sysctls,omitempty"`
-	Tmpfs           StringList                       `yaml:",omitempty" json:"tmpfs,omitempty"`
-	Tty             bool                             `mapstructure:"tty" yaml:"tty,omitempty" json:"tty,omitempty"`
-	Ulimits         map[string]*UlimitsConfig        `yaml:",omitempty" json:"ulimits,omitempty"`
-	User            string                           `yaml:",omitempty" json:"user,omitempty"`
-	UserNSMode      string                           `mapstructure:"userns_mode" yaml:"userns_mode,omitempty" json:"userns_mode,omitempty"`
-	Uts             string                           `yaml:"uts,omitempty" json:"uts,omitempty"`
-	VolumeDriver    string                           `mapstructure:"volume_driver" yaml:"volume_driver,omitempty" json:"volume_driver,omitempty"`
-	Volumes         []ServiceVolumeConfig            `yaml:",omitempty" json:"volumes,omitempty"`
-	VolumesFrom     []string                         `mapstructure:"volumes_from" yaml:"volumes_from,omitempty" json:"volumes_from,omitempty"`
-	WorkingDir      string                           `mapstructure:"working_dir" yaml:"working_dir,omitempty" json:"working_dir,omitempty"`
+	Build             *BuildConfig                     `yaml:",omitempty" json:"build,omitempty"`
+	BlkioConfig       *BlkioConfig                     `mapstructure:"blkio_config" yaml:",omitempty" json:"blkio_config,omitempty"`
+	CapAdd            []string                         `mapstructure:"cap_add" yaml:"cap_add,omitempty" json:"cap_add,omitempty"`
+	CapDrop           []string                         `mapstructure:"cap_drop" yaml:"cap_drop,omitempty" json:"cap_drop,omitempty"`
+	CgroupParent      string                           `mapstructure:"cgroup_parent" yaml:"cgroup_parent,omitempty" json:"cgroup_parent,omitempty"`
+	CPUCount          int64                            `mapstructure:"cpu_count" yaml:"cpu_count,omitempty" json:"cpu_count,omitempty"`
+	CPUPercent        float32                          `mapstructure:"cpu_percent" yaml:"cpu_percent,omitempty" json:"cpu_percent,omitempty"`
+	CPUPeriod         int64                            `mapstructure:"cpu_period" yaml:"cpu_period,omitempty" json:"cpu_period,omitempty"`
+	CPUQuota          int64                            `mapstructure:"cpu_quota" yaml:"cpu_quota,omitempty" json:"cpu_quota,omitempty"`
+	CPURTPeriod       int64                            `mapstructure:"cpu_rt_period" yaml:"cpu_rt_period,omitempty" json:"cpu_rt_period,omitempty"`
+	CPURTRuntime      int64                            `mapstructure:"cpu_rt_runtime" yaml:"cpu_rt_runtime,omitempty" json:"cpu_rt_runtime,omitempty"`
+	CPUS              float32                          `mapstructure:"cpus" yaml:"cpus,omitempty" json:"cpus,omitempty"`
+	CPUSet            string                           `mapstructure:"cpuset" yaml:"cpuset,omitempty" json:"cpuset,omitempty"`
+	CPUShares         int64                            `mapstructure:"cpu_shares" yaml:"cpu_shares,omitempty" json:"cpu_shares,omitempty"`
+	Command           ShellCommand                     `yaml:",omitempty" json:"command,omitempty"`
+	Configs           []ServiceConfigObjConfig         `yaml:",omitempty" json:"configs,omitempty"`
+	ContainerName     string                           `mapstructure:"container_name" yaml:"container_name,omitempty" json:"container_name,omitempty"`
+	CredentialSpec    *CredentialSpecConfig            `mapstructure:"credential_spec" yaml:"credential_spec,omitempty" json:"credential_spec,omitempty"`
+	DependsOn         DependsOnConfig                  `mapstructure:"depends_on" yaml:"depends_on,omitempty" json:"depends_on,omitempty"`
+	Deploy            *DeployConfig                    `yaml:",omitempty" json:"deploy,omitempty"`
+	DeviceCgroupRules []string                         `mapstructure:"device_cgroup_rules" yaml:"device_cgroup_rules,omitempty" json:"device_cgroup_rules,omitempty"`
+	Devices           []string                         `yaml:",omitempty" json:"devices,omitempty"`
+	DNS               StringList                       `yaml:",omitempty" json:"dns,omitempty"`
+	DNSOpts           []string                         `mapstructure:"dns_opt" yaml:"dns_opt,omitempty" json:"dns_opt,omitempty"`
+	DNSSearch         StringList                       `mapstructure:"dns_search" yaml:"dns_search,omitempty" json:"dns_search,omitempty"`
+	Dockerfile        string                           `yaml:"dockerfile,omitempty" json:"dockerfile,omitempty"`
+	DomainName        string                           `mapstructure:"domainname" yaml:"domainname,omitempty" json:"domainname,omitempty"`
+	Entrypoint        ShellCommand                     `yaml:",omitempty" json:"entrypoint,omitempty"`
+	Environment       MappingWithEquals                `yaml:",omitempty" json:"environment,omitempty"`
+	EnvFile           StringList                       `mapstructure:"env_file" yaml:"env_file,omitempty" json:"env_file,omitempty"`
+	Expose            StringOrNumberList               `yaml:",omitempty" json:"expose,omitempty"`
+	Extends           ExtendsConfig                    `yaml:"extends,omitempty" json:"extends,omitempty"`
+	ExternalLinks     []string                         `mapstructure:"external_links" yaml:"external_links,omitempty" json:"external_links,omitempty"`
+	ExtraHosts        HostsList                        `mapstructure:"extra_hosts" yaml:"extra_hosts,omitempty" json:"extra_hosts,omitempty"`
+	GroupAdd          []string                         `mapstructure:"group_add" yaml:"group_add,omitempty" json:"group_add,omitempty"`
+	Hostname          string                           `yaml:",omitempty" json:"hostname,omitempty"`
+	HealthCheck       *HealthCheckConfig               `yaml:",omitempty" json:"healthcheck,omitempty"`
+	Image             string                           `yaml:",omitempty" json:"image,omitempty"`
+	Init              *bool                            `yaml:",omitempty" json:"init,omitempty"`
+	Ipc               string                           `yaml:",omitempty" json:"ipc,omitempty"`
+	Isolation         string                           `mapstructure:"isolation" yaml:"isolation,omitempty" json:"isolation,omitempty"`
+	Labels            Labels                           `yaml:",omitempty" json:"labels,omitempty"`
+	CustomLabels      Labels                           `yaml:"-" json:"-"`
+	Links             []string                         `yaml:",omitempty" json:"links,omitempty"`
+	Logging           *LoggingConfig                   `yaml:",omitempty" json:"logging,omitempty"`
+	LogDriver         string                           `mapstructure:"log_driver" yaml:"log_driver,omitempty" json:"log_driver,omitempty"`
+	LogOpt            map[string]string                `mapstructure:"log_opt" yaml:"log_opt,omitempty" json:"log_opt,omitempty"`
+	MemLimit          UnitBytes                        `mapstructure:"mem_limit" yaml:"mem_limit,omitempty" json:"mem_limit,omitempty"`
+	MemReservation    UnitBytes                        `mapstructure:"mem_reservation" yaml:"mem_reservation,omitempty" json:"mem_reservation,omitempty"`
+	MemSwapLimit      UnitBytes                        `mapstructure:"memswap_limit" yaml:"memswap_limit,omitempty" json:"memswap_limit,omitempty"`
+	MemSwappiness     UnitBytes                        `mapstructure:"mem_swappiness" yaml:"mem_swappiness,omitempty" json:"mem_swappiness,omitempty"`
+	MacAddress        string                           `mapstructure:"mac_address" yaml:"mac_address,omitempty" json:"mac_address,omitempty"`
+	Net               string                           `yaml:"net,omitempty" json:"net,omitempty"`
+	NetworkMode       string                           `mapstructure:"network_mode" yaml:"network_mode,omitempty" json:"network_mode,omitempty"`
+	Networks          map[string]*ServiceNetworkConfig `yaml:",omitempty" json:"networks,omitempty"`
+	OomKillDisable    bool                             `mapstructure:"oom_kill_disable" yaml:"oom_kill_disable,omitempty" json:"oom_kill_disable,omitempty"`
+	OomScoreAdj       int64                            `mapstructure:"oom_score_adj" yaml:"oom_score_adj,omitempty" json:"oom_score_adj,omitempty"`
+	Pid               string                           `yaml:",omitempty" json:"pid,omitempty"`
+	PidsLimit         int64                            `mapstructure:"pids_limit" yaml:"pids_limit,omitempty" json:"pids_limit,omitempty"`
+	Platform          string                           `yaml:",omitempty" json:"platform,omitempty"`
+	Ports             []ServicePortConfig              `yaml:",omitempty" json:"ports,omitempty"`
+	Privileged        bool                             `yaml:",omitempty" json:"privileged,omitempty"`
+	PullPolicy        string                           `mapstructure:"pull_policy" yaml:"pull_policy,omitempty" json:"pull_policy,omitempty"`
+	ReadOnly          bool                             `mapstructure:"read_only" yaml:"read_only,omitempty" json:"read_only,omitempty"`
+	Restart           string                           `yaml:",omitempty" json:"restart,omitempty"`
+	Runtime           string                           `yaml:",omitempty" json:"runtime,omitempty"`
+	Scale             int                              `yaml:"-" json:"-"`
+	Secrets           []ServiceSecretConfig            `yaml:",omitempty" json:"secrets,omitempty"`
+	SecurityOpt       []string                         `mapstructure:"security_opt" yaml:"security_opt,omitempty" json:"security_opt,omitempty"`
+	ShmSize           UnitBytes                        `mapstructure:"shm_size" yaml:"shm_size,omitempty" json:"shm_size,omitempty"`
+	StdinOpen         bool                             `mapstructure:"stdin_open" yaml:"stdin_open,omitempty" json:"stdin_open,omitempty"`
+	StopGracePeriod   *Duration                        `mapstructure:"stop_grace_period" yaml:"stop_grace_period,omitempty" json:"stop_grace_period,omitempty"`
+	StopSignal        string                           `mapstructure:"stop_signal" yaml:"stop_signal,omitempty" json:"stop_signal,omitempty"`
+	Sysctls           Mapping                          `yaml:",omitempty" json:"sysctls,omitempty"`
+	Tmpfs             StringList                       `yaml:",omitempty" json:"tmpfs,omitempty"`
+	Tty               bool                             `mapstructure:"tty" yaml:"tty,omitempty" json:"tty,omitempty"`
+	Ulimits           map[string]*UlimitsConfig        `yaml:",omitempty" json:"ulimits,omitempty"`
+	User              string                           `yaml:",omitempty" json:"user,omitempty"`
+	UserNSMode        string                           `mapstructure:"userns_mode" yaml:"userns_mode,omitempty" json:"userns_mode,omitempty"`
+	Uts               string                           `yaml:"uts,omitempty" json:"uts,omitempty"`
+	VolumeDriver      string                           `mapstructure:"volume_driver" yaml:"volume_driver,omitempty" json:"volume_driver,omitempty"`
+	Volumes           []ServiceVolumeConfig            `yaml:",omitempty" json:"volumes,omitempty"`
+	VolumesFrom       []string                         `mapstructure:"volumes_from" yaml:"volumes_from,omitempty" json:"volumes_from,omitempty"`
+	WorkingDir        string                           `mapstructure:"working_dir" yaml:"working_dir,omitempty" json:"working_dir,omitempty"`
 
 	Extensions map[string]interface{} `yaml:",inline" json:"-"`
 }


Test patch:
diff --git a/loader/full-struct_test.go b/loader/full-struct_test.go
index 3ffcc76..4709b2e 100644
--- a/loader/full-struct_test.go
+++ b/loader/full-struct_test.go
@@ -139,6 +139,10 @@ func services(workingDir, homeDir string) []types.ServiceConfig {
 				},
 				EndpointMode: "dnsrr",
 			},
+      DeviceCgroupRules: []string{
+        "c 1:3 mr",
+        "a 7:* rmw",
+      },
 			Devices:    []string{"/dev/ttyUSB0:/dev/ttyUSB0"},
 			DNS:        []string{"8.8.8.8", "9.9.9.9"},
 			DNSSearch:  []string{"dc1.example.com", "dc2.example.com"},
@@ -640,6 +644,9 @@ func fullExampleYAML(workingDir, homeDir string) string {
         - spread: node.labels.az
         max_replicas_per_node: 5
       endpoint_mode: dnsrr
+    device_cgroup_rules:
+    - c 1:3 mr
+    - a 7:* rmw
     devices:
     - /dev/ttyUSB0:/dev/ttyUSB0
     dns:
@@ -1184,6 +1191,10 @@ func fullExampleJSON(workingDir, homeDir string) string {
         },
         "endpoint_mode": "dnsrr"
       },
+      "device_cgroup_rules": [
+        "c 1:3 mr",
+        "a 7:* rmw"
+      ],
       "devices": [
         "/dev/ttyUSB0:/dev/ttyUSB0"
       ],