mirror of
https://github.com/bpg/terraform-provider-proxmox.git
synced 2025-06-30 18:42:58 +00:00
feat(lxc): add support for device_passthrough
config option (#1706)
Signed-off-by: Tarasa24 <tarasa24@tarasa24.dev>
This commit is contained in:
parent
c57dc78119
commit
7cbd1b46fa
@ -170,6 +170,13 @@ output "ubuntu_container_public_key" {
|
|||||||
Can be specified with a unit suffix (e.g. `10G`).
|
Can be specified with a unit suffix (e.g. `10G`).
|
||||||
- `volume` (Required) Volume, device or directory to mount into the
|
- `volume` (Required) Volume, device or directory to mount into the
|
||||||
container.
|
container.
|
||||||
|
- `device_passthrough` - (Optional) Device to pass through to the container (multiple blocks supported).
|
||||||
|
- `deny_write` - (Optional) Deny the container to write to the device (defaults to `false`).
|
||||||
|
- `gid` - (Optional) Group ID to be assigned to the device node.
|
||||||
|
- `mode` - (Optional) Access mode to be set on the device node. Must be a
|
||||||
|
4-digit octal number.
|
||||||
|
- `path` - (Required) Device to pass through to the container (e.g. `/dev/sda`).
|
||||||
|
- `uid` - (Optional) User ID to be assigned to the device node.
|
||||||
- `network_interface` - (Optional) A network interface (multiple blocks
|
- `network_interface` - (Optional) A network interface (multiple blocks
|
||||||
supported).
|
supported).
|
||||||
- `bridge` - (Optional) The name of the network bridge (defaults
|
- `bridge` - (Optional) The name of the network bridge (defaults
|
||||||
|
@ -75,6 +75,9 @@ func TestAccResourceContainer(t *testing.T) {
|
|||||||
size = "4G"
|
size = "4G"
|
||||||
path = "mnt/local"
|
path = "mnt/local"
|
||||||
}
|
}
|
||||||
|
device_passthrough {
|
||||||
|
path = "/dev/zero"
|
||||||
|
}
|
||||||
description = <<-EOT
|
description = <<-EOT
|
||||||
my
|
my
|
||||||
description
|
description
|
||||||
@ -199,6 +202,9 @@ func TestAccResourceContainer(t *testing.T) {
|
|||||||
size = "4G"
|
size = "4G"
|
||||||
path = "mnt/local"
|
path = "mnt/local"
|
||||||
}
|
}
|
||||||
|
device_passthrough {
|
||||||
|
path = "/dev/zero"
|
||||||
|
}
|
||||||
initialization {
|
initialization {
|
||||||
hostname = "test"
|
hostname = "test"
|
||||||
ip_config {
|
ip_config {
|
||||||
|
@ -51,6 +51,7 @@ type CreateRequestBody struct {
|
|||||||
IgnoreUnpackErrors *types.CustomBool `json:"ignore-unpack-errors,omitempty" url:"force,omitempty,int"`
|
IgnoreUnpackErrors *types.CustomBool `json:"ignore-unpack-errors,omitempty" url:"force,omitempty,int"`
|
||||||
Lock *string `json:"lock,omitempty" url:"lock,omitempty,int"`
|
Lock *string `json:"lock,omitempty" url:"lock,omitempty,int"`
|
||||||
MountPoints CustomMountPointArray `json:"mp,omitempty" url:"mp,omitempty,numbered"`
|
MountPoints CustomMountPointArray `json:"mp,omitempty" url:"mp,omitempty,numbered"`
|
||||||
|
DevicePassthrough CustomDevicePassthroughArray `json:"dev,omitempty" url:"dev,omitempty,numbered"`
|
||||||
NetworkInterfaces CustomNetworkInterfaceArray `json:"net,omitempty" url:"net,omitempty,numbered"`
|
NetworkInterfaces CustomNetworkInterfaceArray `json:"net,omitempty" url:"net,omitempty,numbered"`
|
||||||
OSTemplateFileVolume *string `json:"ostemplate,omitempty" url:"ostemplate,omitempty"`
|
OSTemplateFileVolume *string `json:"ostemplate,omitempty" url:"ostemplate,omitempty"`
|
||||||
OSType *string `json:"ostype,omitempty" url:"ostype,omitempty"`
|
OSType *string `json:"ostype,omitempty" url:"ostype,omitempty"`
|
||||||
@ -116,6 +117,18 @@ type CustomNetworkInterface struct {
|
|||||||
Type *string `json:"type,omitempty" url:"type,omitempty"`
|
Type *string `json:"type,omitempty" url:"type,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CustomDevicePassthroughArray is an array of CustomDevicePassthrough.
|
||||||
|
type CustomDevicePassthroughArray []CustomDevicePassthrough
|
||||||
|
|
||||||
|
// CustomDevicePassthrough contains the values for the "dev[n]" properties.
|
||||||
|
type CustomDevicePassthrough struct {
|
||||||
|
DenyWrite *types.CustomBool `json:"deny-write,omitempty" url:"deny-write,omitempty,int"`
|
||||||
|
Path string `json:"path" url:"path"`
|
||||||
|
UID *int `json:"uid,omitempty" url:"uid,omitempty"`
|
||||||
|
GID *int `json:"gid,omitempty" url:"gid,omitempty"`
|
||||||
|
Mode *string `json:"mode,omitempty" url:"mode,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
// CustomNetworkInterfaceArray is an array of CustomNetworkInterface.
|
// CustomNetworkInterfaceArray is an array of CustomNetworkInterface.
|
||||||
type CustomNetworkInterfaceArray []CustomNetworkInterface
|
type CustomNetworkInterfaceArray []CustomNetworkInterface
|
||||||
|
|
||||||
@ -169,6 +182,14 @@ type GetResponseData struct {
|
|||||||
Hostname *string `json:"hostname,omitempty"`
|
Hostname *string `json:"hostname,omitempty"`
|
||||||
Lock *types.CustomBool `json:"lock,omitempty"`
|
Lock *types.CustomBool `json:"lock,omitempty"`
|
||||||
LXCConfiguration *[][2]string `json:"lxc,omitempty"`
|
LXCConfiguration *[][2]string `json:"lxc,omitempty"`
|
||||||
|
DevicePassthrough0 *CustomDevicePassthrough `json:"dev0,omitempty"`
|
||||||
|
DevicePassthrough1 *CustomDevicePassthrough `json:"dev1,omitempty"`
|
||||||
|
DevicePassthrough2 *CustomDevicePassthrough `json:"dev2,omitempty"`
|
||||||
|
DevicePassthrough3 *CustomDevicePassthrough `json:"dev3,omitempty"`
|
||||||
|
DevicePassthrough4 *CustomDevicePassthrough `json:"dev4,omitempty"`
|
||||||
|
DevicePassthrough5 *CustomDevicePassthrough `json:"dev5,omitempty"`
|
||||||
|
DevicePassthrough6 *CustomDevicePassthrough `json:"dev6,omitempty"`
|
||||||
|
DevicePassthrough7 *CustomDevicePassthrough `json:"dev7,omitempty"`
|
||||||
MountPoint0 *CustomMountPoint `json:"mp0,omitempty"`
|
MountPoint0 *CustomMountPoint `json:"mp0,omitempty"`
|
||||||
MountPoint1 *CustomMountPoint `json:"mp1,omitempty"`
|
MountPoint1 *CustomMountPoint `json:"mp1,omitempty"`
|
||||||
MountPoint2 *CustomMountPoint `json:"mp2,omitempty"`
|
MountPoint2 *CustomMountPoint `json:"mp2,omitempty"`
|
||||||
@ -276,6 +297,55 @@ func (r *CustomFeatures) EncodeValues(key string, v *url.Values) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// EncodeValues converts a CustomDevicePassthrough struct to a URL value.
|
||||||
|
func (r *CustomDevicePassthrough) EncodeValues(key string, v *url.Values) error {
|
||||||
|
var values []string
|
||||||
|
|
||||||
|
if r.DenyWrite != nil {
|
||||||
|
if *r.DenyWrite {
|
||||||
|
values = append(values, "deny-write=1")
|
||||||
|
} else {
|
||||||
|
values = append(values, "deny-write=0")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if r.Path != "" {
|
||||||
|
values = append(values, fmt.Sprintf("path=%s", r.Path))
|
||||||
|
}
|
||||||
|
|
||||||
|
if r.UID != nil {
|
||||||
|
values = append(values, fmt.Sprintf("uid=%d", *r.UID))
|
||||||
|
}
|
||||||
|
|
||||||
|
if r.GID != nil {
|
||||||
|
values = append(values, fmt.Sprintf("gid=%d", *r.GID))
|
||||||
|
}
|
||||||
|
|
||||||
|
if r.Mode != nil && *r.Mode != "" {
|
||||||
|
values = append(values, fmt.Sprintf("mode=%s", *r.Mode))
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(values) > 0 {
|
||||||
|
v.Add(key, strings.Join(values, ","))
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// EncodeValues converts a CustomDevicePassthroughArray array to multiple URL values.
|
||||||
|
func (r CustomDevicePassthroughArray) EncodeValues(
|
||||||
|
key string,
|
||||||
|
v *url.Values,
|
||||||
|
) error {
|
||||||
|
for i, d := range r {
|
||||||
|
if err := d.EncodeValues(fmt.Sprintf("%s%d", key, i), v); err != nil {
|
||||||
|
return fmt.Errorf("failed to encode CustomDevicePassthroughArray: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// EncodeValues converts a CustomMountPoint struct to a URL value.
|
// EncodeValues converts a CustomMountPoint struct to a URL value.
|
||||||
func (r *CustomMountPoint) EncodeValues(key string, v *url.Values) error {
|
func (r *CustomMountPoint) EncodeValues(key string, v *url.Values) error {
|
||||||
var values []string
|
var values []string
|
||||||
@ -587,6 +657,56 @@ func (r *CustomFeatures) UnmarshalJSON(b []byte) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UnmarshalJSON converts a CustomDevicePassthrough string to an object.
|
||||||
|
func (r *CustomDevicePassthrough) UnmarshalJSON(b []byte) error {
|
||||||
|
var s string
|
||||||
|
|
||||||
|
err := json.Unmarshal(b, &s)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("unable to unmarshal CustomDevicePassthrough: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
pairs := strings.Split(s, ",")
|
||||||
|
|
||||||
|
var path string
|
||||||
|
|
||||||
|
for _, p := range pairs {
|
||||||
|
v := strings.Split(strings.TrimSpace(p), "=")
|
||||||
|
|
||||||
|
if len(v) == 1 {
|
||||||
|
path = v[0]
|
||||||
|
} else if len(v) == 2 {
|
||||||
|
switch v[0] {
|
||||||
|
case "deny-write":
|
||||||
|
bv := types.CustomBool(v[1] == "1")
|
||||||
|
r.DenyWrite = &bv
|
||||||
|
case "path":
|
||||||
|
path = v[1]
|
||||||
|
case "uid":
|
||||||
|
iv, err := strconv.Atoi(v[1])
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("unable to unmarshal 'uid': %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
r.UID = &iv
|
||||||
|
case "gid":
|
||||||
|
iv, err := strconv.Atoi(v[1])
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("unable to unmarshal 'gid': %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
r.GID = &iv
|
||||||
|
case "mode":
|
||||||
|
r.Mode = &v[1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
r.Path = path
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// UnmarshalJSON converts a CustomMountPoint string to an object.
|
// UnmarshalJSON converts a CustomMountPoint string to an object.
|
||||||
func (r *CustomMountPoint) UnmarshalJSON(b []byte) error {
|
func (r *CustomMountPoint) UnmarshalJSON(b []byte) error {
|
||||||
var s string
|
var s string
|
||||||
|
@ -10,6 +10,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"regexp"
|
||||||
"sort"
|
"sort"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
@ -140,6 +141,12 @@ const (
|
|||||||
mkMountPointShared = "shared"
|
mkMountPointShared = "shared"
|
||||||
mkMountPointSize = "size"
|
mkMountPointSize = "size"
|
||||||
mkMountPointVolume = "volume"
|
mkMountPointVolume = "volume"
|
||||||
|
mkDevicePassthroughDenyWrite = "deny_write"
|
||||||
|
mkDevicePassthrough = "device_passthrough" // #nosec G101
|
||||||
|
mkDevicePassthroughPath = "path"
|
||||||
|
mkDevicePassthroughUID = "uid"
|
||||||
|
mkDevicePassthroughGID = "gid"
|
||||||
|
mkDevicePassthroughMode = "mode"
|
||||||
mkNetworkInterface = "network_interface"
|
mkNetworkInterface = "network_interface"
|
||||||
mkNetworkInterfaceBridge = "bridge"
|
mkNetworkInterfaceBridge = "bridge"
|
||||||
mkNetworkInterfaceEnabled = "enabled"
|
mkNetworkInterfaceEnabled = "enabled"
|
||||||
@ -680,6 +687,49 @@ func Container() *schema.Resource {
|
|||||||
MaxItems: 8,
|
MaxItems: 8,
|
||||||
MinItems: 0,
|
MinItems: 0,
|
||||||
},
|
},
|
||||||
|
mkDevicePassthrough: {
|
||||||
|
Type: schema.TypeList,
|
||||||
|
Description: "Device to pass through to the container",
|
||||||
|
Optional: true,
|
||||||
|
Elem: &schema.Resource{
|
||||||
|
Schema: map[string]*schema.Schema{
|
||||||
|
mkDevicePassthroughDenyWrite: {
|
||||||
|
Type: schema.TypeBool,
|
||||||
|
Description: "Deny the container to write to the device",
|
||||||
|
Optional: true,
|
||||||
|
Default: false,
|
||||||
|
},
|
||||||
|
mkDevicePassthroughGID: {
|
||||||
|
Type: schema.TypeInt,
|
||||||
|
Description: "Group ID to be assigned to the device node",
|
||||||
|
Optional: true,
|
||||||
|
ValidateDiagFunc: validation.ToDiagFunc(validation.IntAtLeast(0)),
|
||||||
|
},
|
||||||
|
mkDevicePassthroughMode: {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Description: "Access mode to be set on the device node (e.g. 0666)",
|
||||||
|
Optional: true,
|
||||||
|
ValidateDiagFunc: validation.ToDiagFunc(validation.StringMatch(
|
||||||
|
regexp.MustCompile(`0[0-7]{3}`), "Octal access mode",
|
||||||
|
)),
|
||||||
|
},
|
||||||
|
mkDevicePassthroughPath: {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Description: "Device to pass through to the container",
|
||||||
|
Required: true,
|
||||||
|
ValidateDiagFunc: validation.ToDiagFunc(validation.StringIsNotEmpty),
|
||||||
|
},
|
||||||
|
mkDevicePassthroughUID: {
|
||||||
|
Type: schema.TypeInt,
|
||||||
|
Description: "Device UID in the container",
|
||||||
|
Optional: true,
|
||||||
|
ValidateDiagFunc: validation.ToDiagFunc(validation.IntAtLeast(0)),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
MaxItems: 8,
|
||||||
|
MinItems: 0,
|
||||||
|
},
|
||||||
mkNetworkInterface: {
|
mkNetworkInterface: {
|
||||||
Type: schema.TypeList,
|
Type: schema.TypeList,
|
||||||
Description: "The network interfaces",
|
Description: "The network interfaces",
|
||||||
@ -1209,6 +1259,36 @@ func containerCreateClone(ctx context.Context, d *schema.ResourceData, m interfa
|
|||||||
updateBody.Swap = &memorySwap
|
updateBody.Swap = &memorySwap
|
||||||
}
|
}
|
||||||
|
|
||||||
|
devicePassthrough := d.Get(mkDevicePassthrough).([]interface{})
|
||||||
|
|
||||||
|
devicePassthroughArray := make(
|
||||||
|
containers.CustomDevicePassthroughArray,
|
||||||
|
len(devicePassthrough),
|
||||||
|
)
|
||||||
|
|
||||||
|
for di, dv := range devicePassthrough {
|
||||||
|
devicePassthroughMap := dv.(map[string]interface{})
|
||||||
|
devicePassthroughObject := containers.CustomDevicePassthrough{}
|
||||||
|
|
||||||
|
denyWrite := types.CustomBool(
|
||||||
|
devicePassthroughMap[mkDevicePassthroughDenyWrite].(bool),
|
||||||
|
)
|
||||||
|
gid := devicePassthroughMap[mkDevicePassthroughGID].(int)
|
||||||
|
mode := devicePassthroughMap[mkDevicePassthroughMode].(string)
|
||||||
|
path := devicePassthroughMap[mkDevicePassthroughPath].(string)
|
||||||
|
uid := devicePassthroughMap[mkDevicePassthroughUID].(int)
|
||||||
|
|
||||||
|
devicePassthroughObject.DenyWrite = &denyWrite
|
||||||
|
devicePassthroughObject.GID = &gid
|
||||||
|
devicePassthroughObject.Mode = &mode
|
||||||
|
devicePassthroughObject.Path = path
|
||||||
|
devicePassthroughObject.UID = &uid
|
||||||
|
|
||||||
|
devicePassthroughArray[di] = devicePassthroughObject
|
||||||
|
}
|
||||||
|
|
||||||
|
updateBody.DevicePassthrough = devicePassthroughArray
|
||||||
|
|
||||||
networkInterface := d.Get(mkNetworkInterface).([]interface{})
|
networkInterface := d.Get(mkNetworkInterface).([]interface{})
|
||||||
|
|
||||||
if len(networkInterface) == 0 {
|
if len(networkInterface) == 0 {
|
||||||
@ -2232,6 +2312,65 @@ func containerRead(ctx context.Context, d *schema.ResourceData, m interface{}) d
|
|||||||
initialization[mkInitializationHostname] = ""
|
initialization[mkInitializationHostname] = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
devicePassthroughArray := []*containers.CustomDevicePassthrough{
|
||||||
|
containerConfig.DevicePassthrough0,
|
||||||
|
containerConfig.DevicePassthrough1,
|
||||||
|
containerConfig.DevicePassthrough2,
|
||||||
|
containerConfig.DevicePassthrough3,
|
||||||
|
containerConfig.DevicePassthrough4,
|
||||||
|
containerConfig.DevicePassthrough5,
|
||||||
|
containerConfig.DevicePassthrough6,
|
||||||
|
containerConfig.DevicePassthrough7,
|
||||||
|
}
|
||||||
|
|
||||||
|
devicePassthroughList := make([]interface{}, 0, len(devicePassthroughArray))
|
||||||
|
|
||||||
|
for _, dp := range devicePassthroughArray {
|
||||||
|
if dp == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
devicePassthrough := map[string]interface{}{}
|
||||||
|
|
||||||
|
if dp.DenyWrite != nil {
|
||||||
|
devicePassthrough[mkDevicePassthroughDenyWrite] = *dp.DenyWrite
|
||||||
|
} else {
|
||||||
|
devicePassthrough[mkDevicePassthroughDenyWrite] = false
|
||||||
|
}
|
||||||
|
|
||||||
|
if dp.GID != nil {
|
||||||
|
devicePassthrough[mkDevicePassthroughGID] = *dp.GID
|
||||||
|
} else {
|
||||||
|
devicePassthrough[mkDevicePassthroughGID] = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
if dp.Mode != nil {
|
||||||
|
devicePassthrough[mkDevicePassthroughMode] = *dp.Mode
|
||||||
|
} else {
|
||||||
|
devicePassthrough[mkDevicePassthroughMode] = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
devicePassthrough[mkDevicePassthroughPath] = dp.Path
|
||||||
|
|
||||||
|
if dp.UID != nil {
|
||||||
|
devicePassthrough[mkDevicePassthroughUID] = *dp.UID
|
||||||
|
} else {
|
||||||
|
devicePassthrough[mkDevicePassthroughUID] = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
devicePassthroughList = append(devicePassthroughList, devicePassthrough)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(clone) > 0 {
|
||||||
|
if len(devicePassthroughList) > 0 {
|
||||||
|
err := d.Set(mkDevicePassthrough, devicePassthroughList)
|
||||||
|
diags = append(diags, diag.FromErr(err)...)
|
||||||
|
}
|
||||||
|
} else if len(devicePassthroughList) > 0 {
|
||||||
|
err := d.Set(mkDevicePassthrough, devicePassthroughList)
|
||||||
|
diags = append(diags, diag.FromErr(err)...)
|
||||||
|
}
|
||||||
|
|
||||||
mountPointArray := []*containers.CustomMountPoint{
|
mountPointArray := []*containers.CustomMountPoint{
|
||||||
containerConfig.MountPoint0,
|
containerConfig.MountPoint0,
|
||||||
containerConfig.MountPoint1,
|
containerConfig.MountPoint1,
|
||||||
@ -2860,6 +2999,40 @@ func containerUpdate(ctx context.Context, d *schema.ResourceData, m interface{})
|
|||||||
rebootRequired = true
|
rebootRequired = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Prepare the new device passthrough configuration.
|
||||||
|
if d.HasChange(mkDevicePassthrough) {
|
||||||
|
_, newDevicePassthrough := d.GetChange(mkDevicePassthrough)
|
||||||
|
|
||||||
|
devicePassthrough := newDevicePassthrough.([]interface{})
|
||||||
|
devicePassthroughArray := make(
|
||||||
|
containers.CustomDevicePassthroughArray,
|
||||||
|
len(devicePassthrough),
|
||||||
|
)
|
||||||
|
|
||||||
|
for i, dp := range devicePassthrough {
|
||||||
|
devicePassthroughMap := dp.(map[string]interface{})
|
||||||
|
devicePassthroughObject := containers.CustomDevicePassthrough{}
|
||||||
|
|
||||||
|
denyWrite := types.CustomBool(devicePassthroughMap[mkDevicePassthroughDenyWrite].(bool))
|
||||||
|
gid := devicePassthroughMap[mkDevicePassthroughGID].(int)
|
||||||
|
mode := devicePassthroughMap[mkDevicePassthroughMode].(string)
|
||||||
|
path := devicePassthroughMap[mkDevicePassthroughPath].(string)
|
||||||
|
uid := devicePassthroughMap[mkDevicePassthroughUID].(int)
|
||||||
|
|
||||||
|
devicePassthroughObject.DenyWrite = &denyWrite
|
||||||
|
devicePassthroughObject.GID = &gid
|
||||||
|
devicePassthroughObject.Mode = &mode
|
||||||
|
devicePassthroughObject.Path = path
|
||||||
|
devicePassthroughObject.UID = &uid
|
||||||
|
|
||||||
|
devicePassthroughArray[i] = devicePassthroughObject
|
||||||
|
}
|
||||||
|
|
||||||
|
updateBody.DevicePassthrough = devicePassthroughArray
|
||||||
|
|
||||||
|
rebootRequired = true
|
||||||
|
}
|
||||||
|
|
||||||
// Prepare the new mount point configuration.
|
// Prepare the new mount point configuration.
|
||||||
if d.HasChange(mkMountPoint) {
|
if d.HasChange(mkMountPoint) {
|
||||||
_, newMountPoints := d.GetChange(mkMountPoint)
|
_, newMountPoints := d.GetChange(mkMountPoint)
|
||||||
|
@ -41,6 +41,7 @@ func TestContainerSchema(t *testing.T) {
|
|||||||
mkInitialization,
|
mkInitialization,
|
||||||
mkHookScriptFileID,
|
mkHookScriptFileID,
|
||||||
mkMemory,
|
mkMemory,
|
||||||
|
mkDevicePassthrough,
|
||||||
mkMountPoint,
|
mkMountPoint,
|
||||||
mkOperatingSystem,
|
mkOperatingSystem,
|
||||||
mkPoolID,
|
mkPoolID,
|
||||||
@ -61,6 +62,7 @@ func TestContainerSchema(t *testing.T) {
|
|||||||
mkInitialization: schema.TypeList,
|
mkInitialization: schema.TypeList,
|
||||||
mkHookScriptFileID: schema.TypeString,
|
mkHookScriptFileID: schema.TypeString,
|
||||||
mkMemory: schema.TypeList,
|
mkMemory: schema.TypeList,
|
||||||
|
mkDevicePassthrough: schema.TypeList,
|
||||||
mkMountPoint: schema.TypeList,
|
mkMountPoint: schema.TypeList,
|
||||||
mkOperatingSystem: schema.TypeList,
|
mkOperatingSystem: schema.TypeList,
|
||||||
mkPoolID: schema.TypeString,
|
mkPoolID: schema.TypeString,
|
||||||
@ -243,6 +245,27 @@ func TestContainerSchema(t *testing.T) {
|
|||||||
mkMemorySwap: schema.TypeInt,
|
mkMemorySwap: schema.TypeInt,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
devicePassthroughSchema := test.AssertNestedSchemaExistence(t, s, mkDevicePassthrough)
|
||||||
|
|
||||||
|
test.AssertRequiredArguments(t, devicePassthroughSchema, []string{
|
||||||
|
mkDevicePassthroughPath,
|
||||||
|
})
|
||||||
|
|
||||||
|
test.AssertOptionalArguments(t, devicePassthroughSchema, []string{
|
||||||
|
mkDevicePassthroughDenyWrite,
|
||||||
|
mkDevicePassthroughGID,
|
||||||
|
mkDevicePassthroughMode,
|
||||||
|
mkDevicePassthroughUID,
|
||||||
|
})
|
||||||
|
|
||||||
|
test.AssertValueTypes(t, devicePassthroughSchema, map[string]schema.ValueType{
|
||||||
|
mkDevicePassthroughDenyWrite: schema.TypeBool,
|
||||||
|
mkDevicePassthroughGID: schema.TypeInt,
|
||||||
|
mkDevicePassthroughMode: schema.TypeString,
|
||||||
|
mkDevicePassthroughPath: schema.TypeString,
|
||||||
|
mkDevicePassthroughUID: schema.TypeInt,
|
||||||
|
})
|
||||||
|
|
||||||
mountPointSchema := test.AssertNestedSchemaExistence(t, s, mkMountPoint)
|
mountPointSchema := test.AssertNestedSchemaExistence(t, s, mkMountPoint)
|
||||||
|
|
||||||
test.AssertOptionalArguments(t, mountPointSchema, []string{
|
test.AssertOptionalArguments(t, mountPointSchema, []string{
|
||||||
|
Loading…
Reference in New Issue
Block a user