mirror of
https://github.com/bpg/terraform-provider-proxmox.git
synced 2025-08-24 04:18:33 +00:00
chore: cleanup resource validators & utility code (#438)
* chore: cleanup resource validators & utility code * fix linter errors
This commit is contained in:
parent
6781c03ca1
commit
b2a27f3ccf
2
Makefile
2
Makefile
@ -72,7 +72,7 @@ init:
|
|||||||
go get ./...
|
go get ./...
|
||||||
|
|
||||||
test:
|
test:
|
||||||
go test -v ./...
|
go test ./...
|
||||||
|
|
||||||
lint:
|
lint:
|
||||||
go run -modfile=tools/go.mod github.com/golangci/golangci-lint/cmd/golangci-lint run --fix
|
go run -modfile=tools/go.mod github.com/golangci/golangci-lint/cmd/golangci-lint run --fix
|
||||||
|
@ -12,7 +12,7 @@ import (
|
|||||||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
|
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
"github.com/bpg/terraform-provider-proxmox/proxmoxtf/structure"
|
"github.com/bpg/terraform-provider-proxmox/proxmoxtf/test"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TestAliasSchemaInstantiation tests whether the AliasSchema instance can be instantiated.
|
// TestAliasSchemaInstantiation tests whether the AliasSchema instance can be instantiated.
|
||||||
@ -25,18 +25,18 @@ func TestAliasSchemaInstantiation(t *testing.T) {
|
|||||||
func TestAliasSchema(t *testing.T) {
|
func TestAliasSchema(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
s := AliasSchema()
|
r := schema.Resource{Schema: AliasSchema()}
|
||||||
|
|
||||||
structure.AssertRequiredArguments(t, s, []string{
|
test.AssertRequiredArguments(t, &r, []string{
|
||||||
mkAliasName,
|
mkAliasName,
|
||||||
})
|
})
|
||||||
|
|
||||||
structure.AssertComputedAttributes(t, s, []string{
|
test.AssertComputedAttributes(t, &r, []string{
|
||||||
mkAliasCIDR,
|
mkAliasCIDR,
|
||||||
mkAliasComment,
|
mkAliasComment,
|
||||||
})
|
})
|
||||||
|
|
||||||
structure.AssertValueTypes(t, s, map[string]schema.ValueType{
|
test.AssertValueTypes(t, &r, map[string]schema.ValueType{
|
||||||
mkAliasName: schema.TypeString,
|
mkAliasName: schema.TypeString,
|
||||||
mkAliasCIDR: schema.TypeString,
|
mkAliasCIDR: schema.TypeString,
|
||||||
mkAliasComment: schema.TypeString,
|
mkAliasComment: schema.TypeString,
|
||||||
|
@ -12,7 +12,7 @@ import (
|
|||||||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
|
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
"github.com/bpg/terraform-provider-proxmox/proxmoxtf/structure"
|
"github.com/bpg/terraform-provider-proxmox/proxmoxtf/test"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TestAliasesSchemaInstantiation tests whether the AliasesSchema instance can be instantiated.
|
// TestAliasesSchemaInstantiation tests whether the AliasesSchema instance can be instantiated.
|
||||||
@ -25,13 +25,13 @@ func TestAliasesSchemaInstantiation(t *testing.T) {
|
|||||||
func TestAliasesSchema(t *testing.T) {
|
func TestAliasesSchema(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
s := AliasesSchema()
|
r := schema.Resource{Schema: AliasesSchema()}
|
||||||
|
|
||||||
structure.AssertComputedAttributes(t, s, []string{
|
test.AssertComputedAttributes(t, &r, []string{
|
||||||
mkAliasesAliasNames,
|
mkAliasesAliasNames,
|
||||||
})
|
})
|
||||||
|
|
||||||
structure.AssertValueTypes(t, s, map[string]schema.ValueType{
|
test.AssertValueTypes(t, &r, map[string]schema.ValueType{
|
||||||
mkAliasesAliasNames: schema.TypeList,
|
mkAliasesAliasNames: schema.TypeList,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@ import (
|
|||||||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
|
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
"github.com/bpg/terraform-provider-proxmox/proxmoxtf/structure"
|
"github.com/bpg/terraform-provider-proxmox/proxmoxtf/test"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TestIPSetSchemaInstantiation tests whether the IPSetSchema instance can be instantiated.
|
// TestIPSetSchemaInstantiation tests whether the IPSetSchema instance can be instantiated.
|
||||||
@ -25,32 +25,32 @@ func TestIPSetSchemaInstantiation(t *testing.T) {
|
|||||||
func TestIPSetSchema(t *testing.T) {
|
func TestIPSetSchema(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
s := IPSetSchema()
|
r := schema.Resource{Schema: IPSetSchema()}
|
||||||
|
|
||||||
structure.AssertRequiredArguments(t, s, []string{
|
test.AssertRequiredArguments(t, &r, []string{
|
||||||
mkIPSetName,
|
mkIPSetName,
|
||||||
})
|
})
|
||||||
|
|
||||||
structure.AssertComputedAttributes(t, s, []string{
|
test.AssertComputedAttributes(t, &r, []string{
|
||||||
mkIPSetCIDR,
|
mkIPSetCIDR,
|
||||||
mkIPSetCIDRComment,
|
mkIPSetCIDRComment,
|
||||||
})
|
})
|
||||||
|
|
||||||
structure.AssertValueTypes(t, s, map[string]schema.ValueType{
|
test.AssertValueTypes(t, &r, map[string]schema.ValueType{
|
||||||
mkIPSetName: schema.TypeString,
|
mkIPSetName: schema.TypeString,
|
||||||
mkIPSetCIDR: schema.TypeList,
|
mkIPSetCIDR: schema.TypeList,
|
||||||
mkIPSetCIDRComment: schema.TypeString,
|
mkIPSetCIDRComment: schema.TypeString,
|
||||||
})
|
})
|
||||||
|
|
||||||
cirdSchema := structure.AssertNestedSchemaExistence(t, s, mkIPSetCIDR).Schema
|
cird := test.AssertNestedSchemaExistence(t, &r, mkIPSetCIDR)
|
||||||
|
|
||||||
structure.AssertComputedAttributes(t, cirdSchema, []string{
|
test.AssertComputedAttributes(t, cird, []string{
|
||||||
mkIPSetCIDRName,
|
mkIPSetCIDRName,
|
||||||
mkIPSetCIDRNoMatch,
|
mkIPSetCIDRNoMatch,
|
||||||
mkIPSetCIDRComment,
|
mkIPSetCIDRComment,
|
||||||
})
|
})
|
||||||
|
|
||||||
structure.AssertValueTypes(t, cirdSchema, map[string]schema.ValueType{
|
test.AssertValueTypes(t, cird, map[string]schema.ValueType{
|
||||||
mkIPSetCIDRName: schema.TypeString,
|
mkIPSetCIDRName: schema.TypeString,
|
||||||
mkIPSetCIDRNoMatch: schema.TypeBool,
|
mkIPSetCIDRNoMatch: schema.TypeBool,
|
||||||
mkIPSetCIDRComment: schema.TypeString,
|
mkIPSetCIDRComment: schema.TypeString,
|
||||||
|
@ -12,7 +12,7 @@ import (
|
|||||||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
|
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
"github.com/bpg/terraform-provider-proxmox/proxmoxtf/structure"
|
"github.com/bpg/terraform-provider-proxmox/proxmoxtf/test"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TestIPSetsSchemaInstantiation tests whether the IPSetsSchema instance can be instantiated.
|
// TestIPSetsSchemaInstantiation tests whether the IPSetsSchema instance can be instantiated.
|
||||||
@ -25,13 +25,13 @@ func TestIPSetsSchemaInstantiation(t *testing.T) {
|
|||||||
func TestIPSetsSchema(t *testing.T) {
|
func TestIPSetsSchema(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
s := IPSetsSchema()
|
r := schema.Resource{Schema: IPSetsSchema()}
|
||||||
|
|
||||||
structure.AssertComputedAttributes(t, s, []string{
|
test.AssertComputedAttributes(t, &r, []string{
|
||||||
mkIPSetsIPSetNames,
|
mkIPSetsIPSetNames,
|
||||||
})
|
})
|
||||||
|
|
||||||
structure.AssertValueTypes(t, s, map[string]schema.ValueType{
|
test.AssertValueTypes(t, &r, map[string]schema.ValueType{
|
||||||
mkIPSetsIPSetNames: schema.TypeList,
|
mkIPSetsIPSetNames: schema.TypeList,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@ import (
|
|||||||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
|
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
"github.com/bpg/terraform-provider-proxmox/proxmoxtf/structure"
|
"github.com/bpg/terraform-provider-proxmox/proxmoxtf/test"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TestRuleInstantiation tests whether the RuleSchema instance can be instantiated.
|
// TestRuleInstantiation tests whether the RuleSchema instance can be instantiated.
|
||||||
@ -25,14 +25,14 @@ func TestRuleSchemaInstantiation(t *testing.T) {
|
|||||||
func TestRuleSchema(t *testing.T) {
|
func TestRuleSchema(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
ruleSchema := RuleSchema()
|
r := schema.Resource{Schema: RuleSchema()}
|
||||||
|
|
||||||
structure.AssertRequiredArguments(t, ruleSchema, []string{
|
test.AssertRequiredArguments(t, &r, []string{
|
||||||
mkRuleAction,
|
mkRuleAction,
|
||||||
mkRuleType,
|
mkRuleType,
|
||||||
})
|
})
|
||||||
|
|
||||||
structure.AssertComputedAttributes(t, ruleSchema, []string{
|
test.AssertComputedAttributes(t, &r, []string{
|
||||||
mkRuleComment,
|
mkRuleComment,
|
||||||
mkRuleDest,
|
mkRuleDest,
|
||||||
mkRuleDPort,
|
mkRuleDPort,
|
||||||
@ -45,7 +45,7 @@ func TestRuleSchema(t *testing.T) {
|
|||||||
mkRuleSPort,
|
mkRuleSPort,
|
||||||
})
|
})
|
||||||
|
|
||||||
structure.AssertValueTypes(t, ruleSchema, map[string]schema.ValueType{
|
test.AssertValueTypes(t, &r, map[string]schema.ValueType{
|
||||||
mkRulePos: schema.TypeInt,
|
mkRulePos: schema.TypeInt,
|
||||||
mkRuleAction: schema.TypeString,
|
mkRuleAction: schema.TypeString,
|
||||||
mkRuleType: schema.TypeString,
|
mkRuleType: schema.TypeString,
|
||||||
|
@ -12,7 +12,7 @@ import (
|
|||||||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
|
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
"github.com/bpg/terraform-provider-proxmox/proxmoxtf/structure"
|
"github.com/bpg/terraform-provider-proxmox/proxmoxtf/test"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TestSecurityGroupSchemaInstantiation tests whether the SecurityGroupSchema instance can be instantiated.
|
// TestSecurityGroupSchemaInstantiation tests whether the SecurityGroupSchema instance can be instantiated.
|
||||||
@ -25,18 +25,18 @@ func TestSecurityGroupSchemaInstantiation(t *testing.T) {
|
|||||||
func TestSecurityGroupSchema(t *testing.T) {
|
func TestSecurityGroupSchema(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
s := SecurityGroupSchema()
|
r := schema.Resource{Schema: SecurityGroupSchema()}
|
||||||
|
|
||||||
structure.AssertRequiredArguments(t, s, []string{
|
test.AssertRequiredArguments(t, &r, []string{
|
||||||
mkSecurityGroupName,
|
mkSecurityGroupName,
|
||||||
})
|
})
|
||||||
|
|
||||||
structure.AssertComputedAttributes(t, s, []string{
|
test.AssertComputedAttributes(t, &r, []string{
|
||||||
mkSecurityGroupComment,
|
mkSecurityGroupComment,
|
||||||
mkRules,
|
mkRules,
|
||||||
})
|
})
|
||||||
|
|
||||||
structure.AssertValueTypes(t, s, map[string]schema.ValueType{
|
test.AssertValueTypes(t, &r, map[string]schema.ValueType{
|
||||||
mkSecurityGroupName: schema.TypeString,
|
mkSecurityGroupName: schema.TypeString,
|
||||||
mkSecurityGroupComment: schema.TypeString,
|
mkSecurityGroupComment: schema.TypeString,
|
||||||
mkRules: schema.TypeList,
|
mkRules: schema.TypeList,
|
||||||
|
@ -12,7 +12,7 @@ import (
|
|||||||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
|
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
"github.com/bpg/terraform-provider-proxmox/proxmoxtf/structure"
|
"github.com/bpg/terraform-provider-proxmox/proxmoxtf/test"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TestSecurityGroupsSchemaInstantiation tests whether the SecurityGroupsSchema instance can be instantiated.
|
// TestSecurityGroupsSchemaInstantiation tests whether the SecurityGroupsSchema instance can be instantiated.
|
||||||
@ -25,13 +25,13 @@ func TestSecurityGroupsSchemaInstantiation(t *testing.T) {
|
|||||||
func TestSecurityGroupsSchema(t *testing.T) {
|
func TestSecurityGroupsSchema(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
s := SecurityGroupsSchema()
|
r := schema.Resource{Schema: SecurityGroupsSchema()}
|
||||||
|
|
||||||
structure.AssertComputedAttributes(t, s, []string{
|
test.AssertComputedAttributes(t, &r, []string{
|
||||||
mkSecurityGroupsSecurityGroupNames,
|
mkSecurityGroupsSecurityGroupNames,
|
||||||
})
|
})
|
||||||
|
|
||||||
structure.AssertValueTypes(t, s, map[string]schema.ValueType{
|
test.AssertValueTypes(t, &r, map[string]schema.ValueType{
|
||||||
mkSecurityGroupsSecurityGroupNames: schema.TypeList,
|
mkSecurityGroupsSecurityGroupNames: schema.TypeList,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,7 @@ import (
|
|||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
"github.com/bpg/terraform-provider-proxmox/proxmoxtf/resource/firewall"
|
"github.com/bpg/terraform-provider-proxmox/proxmoxtf/resource/firewall"
|
||||||
"github.com/bpg/terraform-provider-proxmox/proxmoxtf/structure"
|
"github.com/bpg/terraform-provider-proxmox/proxmoxtf/test"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TestSecurityGroupInstantiation tests whether the SecurityGroup instance can be instantiated.
|
// TestSecurityGroupInstantiation tests whether the SecurityGroup instance can be instantiated.
|
||||||
@ -26,20 +26,20 @@ func TestSecurityGroupInstantiation(t *testing.T) {
|
|||||||
func TestSecurityGroupSchema(t *testing.T) {
|
func TestSecurityGroupSchema(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
s := SecurityGroup().Schema
|
s := SecurityGroup()
|
||||||
|
|
||||||
structure.AssertRequiredArguments(t, s, []string{
|
test.AssertRequiredArguments(t, s, []string{
|
||||||
mkSecurityGroupName,
|
mkSecurityGroupName,
|
||||||
})
|
})
|
||||||
|
|
||||||
structure.AssertOptionalArguments(t, s, []string{
|
test.AssertOptionalArguments(t, s, []string{
|
||||||
mkSecurityGroupComment,
|
mkSecurityGroupComment,
|
||||||
})
|
})
|
||||||
|
|
||||||
structure.AssertValueTypes(t, s, map[string]schema.ValueType{
|
test.AssertValueTypes(t, s, map[string]schema.ValueType{
|
||||||
mkSecurityGroupName: schema.TypeString,
|
mkSecurityGroupName: schema.TypeString,
|
||||||
mkSecurityGroupComment: schema.TypeString,
|
mkSecurityGroupComment: schema.TypeString,
|
||||||
})
|
})
|
||||||
|
|
||||||
structure.AssertNestedSchemaExistence(t, s, firewall.MkRule)
|
test.AssertNestedSchemaExistence(t, s, firewall.MkRule)
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,7 @@ import (
|
|||||||
"github.com/bpg/terraform-provider-proxmox/proxmox/nodes/containers"
|
"github.com/bpg/terraform-provider-proxmox/proxmox/nodes/containers"
|
||||||
"github.com/bpg/terraform-provider-proxmox/proxmoxtf"
|
"github.com/bpg/terraform-provider-proxmox/proxmoxtf"
|
||||||
"github.com/bpg/terraform-provider-proxmox/proxmoxtf/resource/validator"
|
"github.com/bpg/terraform-provider-proxmox/proxmoxtf/resource/validator"
|
||||||
|
"github.com/bpg/terraform-provider-proxmox/proxmoxtf/structure"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -571,7 +572,7 @@ func Container() *schema.Resource {
|
|||||||
Description: "Volume size (only used for volume mount points)",
|
Description: "Volume size (only used for volume mount points)",
|
||||||
Optional: true,
|
Optional: true,
|
||||||
Default: dvResourceVirtualEnvironmentContainerMountPointSize,
|
Default: dvResourceVirtualEnvironmentContainerMountPointSize,
|
||||||
ValidateDiagFunc: getFileSizeValidator(),
|
ValidateDiagFunc: validator.FileSize(),
|
||||||
},
|
},
|
||||||
mkResourceVirtualEnvironmentContainerMountPointVolume: {
|
mkResourceVirtualEnvironmentContainerMountPointVolume: {
|
||||||
Type: schema.TypeString,
|
Type: schema.TypeString,
|
||||||
@ -618,7 +619,7 @@ func Container() *schema.Resource {
|
|||||||
DiffSuppressFunc: func(k, old, new string, d *schema.ResourceData) bool {
|
DiffSuppressFunc: func(k, old, new string, d *schema.ResourceData) bool {
|
||||||
return new == ""
|
return new == ""
|
||||||
},
|
},
|
||||||
ValidateDiagFunc: getMACAddressValidator(),
|
ValidateDiagFunc: validator.MACAddress(),
|
||||||
},
|
},
|
||||||
mkResourceVirtualEnvironmentContainerNetworkInterfaceName: {
|
mkResourceVirtualEnvironmentContainerNetworkInterfaceName: {
|
||||||
Type: schema.TypeString,
|
Type: schema.TypeString,
|
||||||
@ -666,7 +667,7 @@ func Container() *schema.Resource {
|
|||||||
Description: "The ID of an OS template file",
|
Description: "The ID of an OS template file",
|
||||||
Required: true,
|
Required: true,
|
||||||
ForceNew: true,
|
ForceNew: true,
|
||||||
ValidateDiagFunc: getFileIDValidator(),
|
ValidateDiagFunc: validator.FileID(),
|
||||||
},
|
},
|
||||||
mkResourceVirtualEnvironmentContainerOperatingSystemType: {
|
mkResourceVirtualEnvironmentContainerOperatingSystemType: {
|
||||||
Type: schema.TypeString,
|
Type: schema.TypeString,
|
||||||
@ -704,7 +705,7 @@ func Container() *schema.Resource {
|
|||||||
Type: schema.TypeString,
|
Type: schema.TypeString,
|
||||||
ValidateFunc: validation.StringIsNotEmpty,
|
ValidateFunc: validation.StringIsNotEmpty,
|
||||||
},
|
},
|
||||||
DiffSuppressFunc: suppressIfListsAreEqualIgnoringOrder,
|
DiffSuppressFunc: structure.SuppressIfListsAreEqualIgnoringOrder,
|
||||||
DiffSuppressOnRefresh: true,
|
DiffSuppressOnRefresh: true,
|
||||||
},
|
},
|
||||||
mkResourceVirtualEnvironmentContainerTemplate: {
|
mkResourceVirtualEnvironmentContainerTemplate: {
|
||||||
@ -1123,7 +1124,7 @@ func containerCreateCustom(ctx context.Context, d *schema.ResourceData, m interf
|
|||||||
nodeName := d.Get(mkResourceVirtualEnvironmentContainerNodeName).(string)
|
nodeName := d.Get(mkResourceVirtualEnvironmentContainerNodeName).(string)
|
||||||
resource := Container()
|
resource := Container()
|
||||||
|
|
||||||
consoleBlock, err := getSchemaBlock(
|
consoleBlock, err := structure.GetSchemaBlock(
|
||||||
resource,
|
resource,
|
||||||
d,
|
d,
|
||||||
[]string{mkResourceVirtualEnvironmentContainerConsole},
|
[]string{mkResourceVirtualEnvironmentContainerConsole},
|
||||||
@ -1140,7 +1141,7 @@ func containerCreateCustom(ctx context.Context, d *schema.ResourceData, m interf
|
|||||||
consoleMode := consoleBlock[mkResourceVirtualEnvironmentContainerConsoleMode].(string)
|
consoleMode := consoleBlock[mkResourceVirtualEnvironmentContainerConsoleMode].(string)
|
||||||
consoleTTYCount := consoleBlock[mkResourceVirtualEnvironmentContainerConsoleTTYCount].(int)
|
consoleTTYCount := consoleBlock[mkResourceVirtualEnvironmentContainerConsoleTTYCount].(int)
|
||||||
|
|
||||||
cpuBlock, err := getSchemaBlock(
|
cpuBlock, err := structure.GetSchemaBlock(
|
||||||
resource,
|
resource,
|
||||||
d,
|
d,
|
||||||
[]string{mkResourceVirtualEnvironmentContainerCPU},
|
[]string{mkResourceVirtualEnvironmentContainerCPU},
|
||||||
@ -1157,7 +1158,7 @@ func containerCreateCustom(ctx context.Context, d *schema.ResourceData, m interf
|
|||||||
|
|
||||||
description := d.Get(mkResourceVirtualEnvironmentContainerDescription).(string)
|
description := d.Get(mkResourceVirtualEnvironmentContainerDescription).(string)
|
||||||
|
|
||||||
diskBlock, err := getSchemaBlock(
|
diskBlock, err := structure.GetSchemaBlock(
|
||||||
resource,
|
resource,
|
||||||
d,
|
d,
|
||||||
[]string{mkResourceVirtualEnvironmentContainerDisk},
|
[]string{mkResourceVirtualEnvironmentContainerDisk},
|
||||||
@ -1181,7 +1182,7 @@ func containerCreateCustom(ctx context.Context, d *schema.ResourceData, m interf
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
featuresBlock, err := getSchemaBlock(
|
featuresBlock, err := structure.GetSchemaBlock(
|
||||||
resource,
|
resource,
|
||||||
d,
|
d,
|
||||||
[]string{mkResourceVirtualEnvironmentContainerFeatures},
|
[]string{mkResourceVirtualEnvironmentContainerFeatures},
|
||||||
@ -1282,7 +1283,7 @@ func containerCreateCustom(ctx context.Context, d *schema.ResourceData, m interf
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
memoryBlock, err := getSchemaBlock(
|
memoryBlock, err := structure.GetSchemaBlock(
|
||||||
resource,
|
resource,
|
||||||
d,
|
d,
|
||||||
[]string{mkResourceVirtualEnvironmentContainerMemory},
|
[]string{mkResourceVirtualEnvironmentContainerMemory},
|
||||||
@ -2273,7 +2274,7 @@ func containerUpdate(ctx context.Context, d *schema.ResourceData, m interface{})
|
|||||||
|
|
||||||
// Prepare the new console configuration.
|
// Prepare the new console configuration.
|
||||||
if d.HasChange(mkResourceVirtualEnvironmentContainerConsole) {
|
if d.HasChange(mkResourceVirtualEnvironmentContainerConsole) {
|
||||||
consoleBlock, err := getSchemaBlock(
|
consoleBlock, err := structure.GetSchemaBlock(
|
||||||
resource,
|
resource,
|
||||||
d,
|
d,
|
||||||
[]string{mkResourceVirtualEnvironmentContainerConsole},
|
[]string{mkResourceVirtualEnvironmentContainerConsole},
|
||||||
@ -2299,7 +2300,7 @@ func containerUpdate(ctx context.Context, d *schema.ResourceData, m interface{})
|
|||||||
|
|
||||||
// Prepare the new CPU configuration.
|
// Prepare the new CPU configuration.
|
||||||
if d.HasChange(mkResourceVirtualEnvironmentContainerCPU) {
|
if d.HasChange(mkResourceVirtualEnvironmentContainerCPU) {
|
||||||
cpuBlock, err := getSchemaBlock(
|
cpuBlock, err := structure.GetSchemaBlock(
|
||||||
resource,
|
resource,
|
||||||
d,
|
d,
|
||||||
[]string{mkResourceVirtualEnvironmentContainerCPU},
|
[]string{mkResourceVirtualEnvironmentContainerCPU},
|
||||||
@ -2396,7 +2397,7 @@ func containerUpdate(ctx context.Context, d *schema.ResourceData, m interface{})
|
|||||||
|
|
||||||
// Prepare the new memory configuration.
|
// Prepare the new memory configuration.
|
||||||
if d.HasChange(mkResourceVirtualEnvironmentContainerMemory) {
|
if d.HasChange(mkResourceVirtualEnvironmentContainerMemory) {
|
||||||
memoryBlock, err := getSchemaBlock(
|
memoryBlock, err := structure.GetSchemaBlock(
|
||||||
resource,
|
resource,
|
||||||
d,
|
d,
|
||||||
[]string{mkResourceVirtualEnvironmentContainerMemory},
|
[]string{mkResourceVirtualEnvironmentContainerMemory},
|
||||||
@ -2561,7 +2562,7 @@ func containerUpdate(ctx context.Context, d *schema.ResourceData, m interface{})
|
|||||||
|
|
||||||
// Prepare the new operating system configuration.
|
// Prepare the new operating system configuration.
|
||||||
if d.HasChange(mkResourceVirtualEnvironmentContainerOperatingSystem) {
|
if d.HasChange(mkResourceVirtualEnvironmentContainerOperatingSystem) {
|
||||||
operatingSystem, err := getSchemaBlock(
|
operatingSystem, err := structure.GetSchemaBlock(
|
||||||
resource,
|
resource,
|
||||||
d,
|
d,
|
||||||
[]string{mkResourceVirtualEnvironmentContainerOperatingSystem},
|
[]string{mkResourceVirtualEnvironmentContainerOperatingSystem},
|
||||||
|
@ -29,6 +29,7 @@ import (
|
|||||||
|
|
||||||
"github.com/bpg/terraform-provider-proxmox/proxmox/api"
|
"github.com/bpg/terraform-provider-proxmox/proxmox/api"
|
||||||
"github.com/bpg/terraform-provider-proxmox/proxmoxtf"
|
"github.com/bpg/terraform-provider-proxmox/proxmoxtf"
|
||||||
|
"github.com/bpg/terraform-provider-proxmox/proxmoxtf/resource/validator"
|
||||||
"github.com/bpg/terraform-provider-proxmox/utils"
|
"github.com/bpg/terraform-provider-proxmox/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -69,7 +70,7 @@ func File() *schema.Resource {
|
|||||||
Optional: true,
|
Optional: true,
|
||||||
ForceNew: true,
|
ForceNew: true,
|
||||||
Default: dvResourceVirtualEnvironmentFileContentType,
|
Default: dvResourceVirtualEnvironmentFileContentType,
|
||||||
ValidateDiagFunc: getContentTypeValidator(),
|
ValidateDiagFunc: validator.ContentType(),
|
||||||
},
|
},
|
||||||
mkResourceVirtualEnvironmentFileDatastoreID: {
|
mkResourceVirtualEnvironmentFileDatastoreID: {
|
||||||
Type: schema.TypeString,
|
Type: schema.TypeString,
|
||||||
@ -523,7 +524,7 @@ func fileGetContentType(d *schema.ResourceData) (*string, diag.Diagnostics) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ctValidator := getContentTypeValidator()
|
ctValidator := validator.ContentType()
|
||||||
diags := ctValidator(contentType, cty.GetAttrPath(mkResourceVirtualEnvironmentFileContentType))
|
diags := ctValidator(contentType, cty.GetAttrPath(mkResourceVirtualEnvironmentFileContentType))
|
||||||
|
|
||||||
return &contentType, diags
|
return &contentType, diags
|
||||||
|
@ -12,7 +12,7 @@ import (
|
|||||||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
|
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
"github.com/bpg/terraform-provider-proxmox/proxmoxtf/structure"
|
"github.com/bpg/terraform-provider-proxmox/proxmoxtf/test"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TestAliasInstantiation tests whether the Alias instance can be instantiated.
|
// TestAliasInstantiation tests whether the Alias instance can be instantiated.
|
||||||
@ -25,20 +25,20 @@ func TestAliasInstantiation(t *testing.T) {
|
|||||||
func TestAliasSchema(t *testing.T) {
|
func TestAliasSchema(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
s := Alias().Schema
|
s := Alias()
|
||||||
|
|
||||||
structure.AssertRequiredArguments(t, s, []string{
|
test.AssertRequiredArguments(t, s, []string{
|
||||||
mkAliasName,
|
mkAliasName,
|
||||||
mkAliasCIDR,
|
mkAliasCIDR,
|
||||||
})
|
})
|
||||||
|
|
||||||
structure.AssertOptionalArguments(t, s, []string{
|
test.AssertOptionalArguments(t, s, []string{
|
||||||
mkSelectorVMID,
|
mkSelectorVMID,
|
||||||
mkSelectorNodeName,
|
mkSelectorNodeName,
|
||||||
mkAliasComment,
|
mkAliasComment,
|
||||||
})
|
})
|
||||||
|
|
||||||
structure.AssertValueTypes(t, s, map[string]schema.ValueType{
|
test.AssertValueTypes(t, s, map[string]schema.ValueType{
|
||||||
mkAliasName: schema.TypeString,
|
mkAliasName: schema.TypeString,
|
||||||
mkAliasCIDR: schema.TypeString,
|
mkAliasCIDR: schema.TypeString,
|
||||||
mkAliasComment: schema.TypeString,
|
mkAliasComment: schema.TypeString,
|
||||||
|
@ -12,7 +12,7 @@ import (
|
|||||||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
|
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
"github.com/bpg/terraform-provider-proxmox/proxmoxtf/structure"
|
"github.com/bpg/terraform-provider-proxmox/proxmoxtf/test"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TestIPSetInstantiation tests whether the IPSet
|
// TestIPSetInstantiation tests whether the IPSet
|
||||||
@ -26,37 +26,37 @@ func TestIPSetInstantiation(t *testing.T) {
|
|||||||
func TestIPSetSchema(t *testing.T) {
|
func TestIPSetSchema(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
s := IPSet().Schema
|
s := IPSet()
|
||||||
|
|
||||||
structure.AssertRequiredArguments(t, s, []string{
|
test.AssertRequiredArguments(t, s, []string{
|
||||||
mkIPSetName,
|
mkIPSetName,
|
||||||
})
|
})
|
||||||
|
|
||||||
structure.AssertOptionalArguments(t, s, []string{
|
test.AssertOptionalArguments(t, s, []string{
|
||||||
mkSelectorVMID,
|
mkSelectorVMID,
|
||||||
mkSelectorNodeName,
|
mkSelectorNodeName,
|
||||||
mkIPSetCIDR,
|
mkIPSetCIDR,
|
||||||
mkIPSetCIDRComment,
|
mkIPSetCIDRComment,
|
||||||
})
|
})
|
||||||
|
|
||||||
structure.AssertValueTypes(t, s, map[string]schema.ValueType{
|
test.AssertValueTypes(t, s, map[string]schema.ValueType{
|
||||||
mkIPSetName: schema.TypeString,
|
mkIPSetName: schema.TypeString,
|
||||||
mkIPSetCIDR: schema.TypeList,
|
mkIPSetCIDR: schema.TypeList,
|
||||||
mkIPSetCIDRComment: schema.TypeString,
|
mkIPSetCIDRComment: schema.TypeString,
|
||||||
})
|
})
|
||||||
|
|
||||||
nested := structure.AssertNestedSchemaExistence(t, s, mkIPSetCIDR).Schema
|
nested := test.AssertNestedSchemaExistence(t, s, mkIPSetCIDR)
|
||||||
|
|
||||||
structure.AssertRequiredArguments(t, nested, []string{
|
test.AssertRequiredArguments(t, nested, []string{
|
||||||
mkIPSetCIDRName,
|
mkIPSetCIDRName,
|
||||||
})
|
})
|
||||||
|
|
||||||
structure.AssertOptionalArguments(t, nested, []string{
|
test.AssertOptionalArguments(t, nested, []string{
|
||||||
mkIPSetCIDRComment,
|
mkIPSetCIDRComment,
|
||||||
mkIPSetCIDRNoMatch,
|
mkIPSetCIDRNoMatch,
|
||||||
})
|
})
|
||||||
|
|
||||||
structure.AssertValueTypes(t, nested, map[string]schema.ValueType{
|
test.AssertValueTypes(t, nested, map[string]schema.ValueType{
|
||||||
mkIPSetCIDRName: schema.TypeString,
|
mkIPSetCIDRName: schema.TypeString,
|
||||||
mkIPSetCIDRComment: schema.TypeString,
|
mkIPSetCIDRComment: schema.TypeString,
|
||||||
mkIPSetCIDRNoMatch: schema.TypeBool,
|
mkIPSetCIDRNoMatch: schema.TypeBool,
|
||||||
|
@ -12,7 +12,7 @@ import (
|
|||||||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
|
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
"github.com/bpg/terraform-provider-proxmox/proxmoxtf/structure"
|
"github.com/bpg/terraform-provider-proxmox/proxmoxtf/test"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TestOptionsInstantiation tests whether the Options instance can be instantiated.
|
// TestOptionsInstantiation tests whether the Options instance can be instantiated.
|
||||||
@ -25,9 +25,9 @@ func TestOptionsInstantiation(t *testing.T) {
|
|||||||
func TestOptionsSchema(t *testing.T) {
|
func TestOptionsSchema(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
s := Options().Schema
|
s := Options()
|
||||||
|
|
||||||
structure.AssertOptionalArguments(t, s, []string{
|
test.AssertOptionalArguments(t, s, []string{
|
||||||
mkDHCP,
|
mkDHCP,
|
||||||
mkEnabled,
|
mkEnabled,
|
||||||
mkIPFilter,
|
mkIPFilter,
|
||||||
@ -40,7 +40,7 @@ func TestOptionsSchema(t *testing.T) {
|
|||||||
mkRadv,
|
mkRadv,
|
||||||
})
|
})
|
||||||
|
|
||||||
structure.AssertValueTypes(t, s, map[string]schema.ValueType{
|
test.AssertValueTypes(t, s, map[string]schema.ValueType{
|
||||||
mkDHCP: schema.TypeBool,
|
mkDHCP: schema.TypeBool,
|
||||||
mkEnabled: schema.TypeBool,
|
mkEnabled: schema.TypeBool,
|
||||||
mkIPFilter: schema.TypeBool,
|
mkIPFilter: schema.TypeBool,
|
||||||
|
@ -12,7 +12,7 @@ import (
|
|||||||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
|
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
"github.com/bpg/terraform-provider-proxmox/proxmoxtf/structure"
|
"github.com/bpg/terraform-provider-proxmox/proxmoxtf/test"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TestRuleInstantiation tests whether the Rules instance can be instantiated.
|
// TestRuleInstantiation tests whether the Rules instance can be instantiated.
|
||||||
@ -25,20 +25,20 @@ func TestRuleInstantiation(t *testing.T) {
|
|||||||
func TestRuleSchema(t *testing.T) {
|
func TestRuleSchema(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
rulesSchema := Rules().Schema
|
rules := Rules()
|
||||||
|
|
||||||
structure.AssertRequiredArguments(t, rulesSchema, []string{
|
test.AssertRequiredArguments(t, rules, []string{
|
||||||
MkRule,
|
MkRule,
|
||||||
})
|
})
|
||||||
|
|
||||||
structure.AssertOptionalArguments(t, rulesSchema, []string{
|
test.AssertOptionalArguments(t, rules, []string{
|
||||||
mkSelectorVMID,
|
mkSelectorVMID,
|
||||||
mkSelectorNodeName,
|
mkSelectorNodeName,
|
||||||
})
|
})
|
||||||
|
|
||||||
ruleSchema := structure.AssertNestedSchemaExistence(t, rulesSchema, MkRule).Schema
|
nested := test.AssertNestedSchemaExistence(t, rules, MkRule)
|
||||||
|
|
||||||
structure.AssertOptionalArguments(t, ruleSchema, []string{
|
test.AssertOptionalArguments(t, nested, []string{
|
||||||
mkSecurityGroup,
|
mkSecurityGroup,
|
||||||
mkRuleAction,
|
mkRuleAction,
|
||||||
mkRuleType,
|
mkRuleType,
|
||||||
@ -54,7 +54,7 @@ func TestRuleSchema(t *testing.T) {
|
|||||||
mkRuleSPort,
|
mkRuleSPort,
|
||||||
})
|
})
|
||||||
|
|
||||||
structure.AssertValueTypes(t, ruleSchema, map[string]schema.ValueType{
|
test.AssertValueTypes(t, nested, map[string]schema.ValueType{
|
||||||
mkRulePos: schema.TypeInt,
|
mkRulePos: schema.TypeInt,
|
||||||
mkRuleAction: schema.TypeString,
|
mkRuleAction: schema.TypeString,
|
||||||
mkRuleType: schema.TypeString,
|
mkRuleType: schema.TypeString,
|
||||||
|
@ -1,582 +0,0 @@
|
|||||||
/*
|
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
||||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package resource
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"reflect"
|
|
||||||
"regexp"
|
|
||||||
"sort"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
"unicode"
|
|
||||||
|
|
||||||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
|
|
||||||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
|
|
||||||
|
|
||||||
"github.com/bpg/terraform-provider-proxmox/internal/types"
|
|
||||||
"github.com/bpg/terraform-provider-proxmox/proxmox/nodes/vms"
|
|
||||||
)
|
|
||||||
|
|
||||||
func getBIOSValidator() schema.SchemaValidateDiagFunc {
|
|
||||||
return validation.ToDiagFunc(validation.StringInSlice([]string{
|
|
||||||
"ovmf",
|
|
||||||
"seabios",
|
|
||||||
}, false))
|
|
||||||
}
|
|
||||||
|
|
||||||
func getContentTypeValidator() schema.SchemaValidateDiagFunc {
|
|
||||||
return validation.ToDiagFunc(validation.StringInSlice([]string{
|
|
||||||
"backup",
|
|
||||||
"iso",
|
|
||||||
"snippets",
|
|
||||||
"vztmpl",
|
|
||||||
}, false))
|
|
||||||
}
|
|
||||||
|
|
||||||
//nolint:unused
|
|
||||||
func getCPUFlagsValidator() schema.SchemaValidateDiagFunc {
|
|
||||||
return validation.ToDiagFunc(func(i interface{}, k string) (ws []string, es []error) {
|
|
||||||
list, ok := i.([]interface{})
|
|
||||||
|
|
||||||
if !ok {
|
|
||||||
es = append(es, fmt.Errorf("expected type of %s to be []interface{}", k))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
validator := validation.StringInSlice([]string{
|
|
||||||
"+aes",
|
|
||||||
"-aes",
|
|
||||||
"+amd-no-ssb",
|
|
||||||
"-amd-no-ssb",
|
|
||||||
"+amd-ssbd",
|
|
||||||
"-amd-ssbd",
|
|
||||||
"+hv-evmcs",
|
|
||||||
"-hv-evmcs",
|
|
||||||
"+hv-tlbflush",
|
|
||||||
"-hv-tlbflush",
|
|
||||||
"+ibpb",
|
|
||||||
"-ibpb",
|
|
||||||
"+md-clear",
|
|
||||||
"-md-clear",
|
|
||||||
"+pcid",
|
|
||||||
"-pcid",
|
|
||||||
"+pdpe1gb",
|
|
||||||
"-pdpe1gb",
|
|
||||||
"+spec-ctrl",
|
|
||||||
"-spec-ctrl",
|
|
||||||
"+ssbd",
|
|
||||||
"-ssbd",
|
|
||||||
"+virt-ssbd",
|
|
||||||
"-virt-ssbd",
|
|
||||||
}, false)
|
|
||||||
|
|
||||||
for li, lv := range list {
|
|
||||||
v, ok := lv.(string)
|
|
||||||
|
|
||||||
if !ok {
|
|
||||||
es = append(es, fmt.Errorf("expected type of %s[%d] to be string", k, li))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
warns, errs := validator(v, k)
|
|
||||||
|
|
||||||
ws = append(ws, warns...)
|
|
||||||
es = append(es, errs...)
|
|
||||||
|
|
||||||
if len(es) > 0 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func getCPUTypeValidator() schema.SchemaValidateDiagFunc {
|
|
||||||
standardTypes := []string{
|
|
||||||
"486",
|
|
||||||
"Broadwell",
|
|
||||||
"Broadwell-IBRS",
|
|
||||||
"Broadwell-noTSX",
|
|
||||||
"Broadwell-noTSX-IBRS",
|
|
||||||
"Cascadelake-Server",
|
|
||||||
"Cascadelake-Server-noTSX",
|
|
||||||
"Cascadelake-Server-v2",
|
|
||||||
"Cascadelake-Server-v4",
|
|
||||||
"Cascadelake-Server-v5",
|
|
||||||
"Conroe",
|
|
||||||
"Cooperlake",
|
|
||||||
"Cooperlake-v2",
|
|
||||||
"EPYC",
|
|
||||||
"EPYC-IBPB",
|
|
||||||
"EPYC-Milan",
|
|
||||||
"EPYC-Rome",
|
|
||||||
"EPYC-Rome-v2",
|
|
||||||
"EPYC-v3",
|
|
||||||
"Haswell",
|
|
||||||
"Haswell-IBRS",
|
|
||||||
"Haswell-noTSX",
|
|
||||||
"Haswell-noTSX-IBRS",
|
|
||||||
"Icelake-Client",
|
|
||||||
"Icelake-Client-noTSX",
|
|
||||||
"Icelake-Server",
|
|
||||||
"Icelake-Server-noTSX",
|
|
||||||
"Icelake-Server-v3",
|
|
||||||
"Icelake-Server-v4",
|
|
||||||
"Icelake-Server-v5",
|
|
||||||
"Icelake-Server-v6",
|
|
||||||
"IvyBridge",
|
|
||||||
"IvyBridge-IBRS",
|
|
||||||
"KnightsMill",
|
|
||||||
"Nehalem",
|
|
||||||
"Nehalem-IBRS",
|
|
||||||
"Opteron_G1",
|
|
||||||
"Opteron_G2",
|
|
||||||
"Opteron_G3",
|
|
||||||
"Opteron_G4",
|
|
||||||
"Opteron_G5",
|
|
||||||
"Penryn",
|
|
||||||
"SandyBridge",
|
|
||||||
"SandyBridge-IBRS",
|
|
||||||
"SapphireRapids",
|
|
||||||
"Skylake-Client",
|
|
||||||
"Skylake-Client-IBRS",
|
|
||||||
"Skylake-Client-noTSX-IBRS",
|
|
||||||
"Skylake-Client-v4",
|
|
||||||
"Skylake-Server",
|
|
||||||
"Skylake-Server-IBRS",
|
|
||||||
"Skylake-Server-noTSX-IBRS",
|
|
||||||
"Skylake-Server-v4",
|
|
||||||
"Skylake-Server-v5",
|
|
||||||
"Westmere",
|
|
||||||
"Westmere-IBRS",
|
|
||||||
"athlon",
|
|
||||||
"core2duo",
|
|
||||||
"coreduo",
|
|
||||||
"host",
|
|
||||||
"kvm32",
|
|
||||||
"kvm64",
|
|
||||||
"max",
|
|
||||||
"pentium",
|
|
||||||
"pentium2",
|
|
||||||
"pentium3",
|
|
||||||
"phenom",
|
|
||||||
"qemu32",
|
|
||||||
"qemu64",
|
|
||||||
"x86-64-v2",
|
|
||||||
"x86-64-v2-AES",
|
|
||||||
"x86-64-v3",
|
|
||||||
"x86-64-v4",
|
|
||||||
}
|
|
||||||
|
|
||||||
return validation.ToDiagFunc(validation.Any(
|
|
||||||
validation.StringInSlice(standardTypes, false),
|
|
||||||
validation.StringMatch(regexp.MustCompile(`^custom-.+$`), "must be a valid custom CPU type"),
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
func getFileFormatValidator() schema.SchemaValidateDiagFunc {
|
|
||||||
return validation.ToDiagFunc(validation.StringInSlice([]string{
|
|
||||||
"qcow2",
|
|
||||||
"raw",
|
|
||||||
"vmdk",
|
|
||||||
}, false))
|
|
||||||
}
|
|
||||||
|
|
||||||
func getFileIDValidator() schema.SchemaValidateDiagFunc {
|
|
||||||
return validation.ToDiagFunc(func(i interface{}, k string) (ws []string, es []error) {
|
|
||||||
v, ok := i.(string)
|
|
||||||
|
|
||||||
if !ok {
|
|
||||||
es = append(es, fmt.Errorf("expected type of %s to be string", k))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if v != "" {
|
|
||||||
r := regexp.MustCompile(`^(?i)[a-z\d\-_]+:([a-z\d\-_]+/)?.+$`)
|
|
||||||
ok := r.MatchString(v)
|
|
||||||
|
|
||||||
if !ok {
|
|
||||||
es = append(es, fmt.Errorf("expected %s to be a valid file identifier (datastore-name:iso/some-file.img), got %s", k, v))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func getFileSizeValidator() schema.SchemaValidateDiagFunc {
|
|
||||||
return validation.ToDiagFunc(func(i interface{}, k string) ([]string, []error) {
|
|
||||||
v, ok := i.(string)
|
|
||||||
var es []error
|
|
||||||
|
|
||||||
if !ok {
|
|
||||||
es = append(es, fmt.Errorf("expected type of %s to be string", k))
|
|
||||||
return nil, es
|
|
||||||
}
|
|
||||||
|
|
||||||
if v != "" {
|
|
||||||
_, err := types.ParseDiskSize(v)
|
|
||||||
if err != nil {
|
|
||||||
es = append(es, fmt.Errorf("expected %s to be a valid file size (100, 1M, 1G), got %s", k, v))
|
|
||||||
return nil, es
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return []string{}, es
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func getKeyboardLayoutValidator() schema.SchemaValidateDiagFunc {
|
|
||||||
return validation.ToDiagFunc(validation.StringInSlice([]string{
|
|
||||||
"da",
|
|
||||||
"de",
|
|
||||||
"de-ch",
|
|
||||||
"en-gb",
|
|
||||||
"en-us",
|
|
||||||
"es",
|
|
||||||
"fi",
|
|
||||||
"fr",
|
|
||||||
"fr-be",
|
|
||||||
"fr-ca",
|
|
||||||
"fr-ch",
|
|
||||||
"hu",
|
|
||||||
"is",
|
|
||||||
"it",
|
|
||||||
"ja",
|
|
||||||
"lt",
|
|
||||||
"mk",
|
|
||||||
"nl",
|
|
||||||
"no",
|
|
||||||
"pl",
|
|
||||||
"pt",
|
|
||||||
"pt-br",
|
|
||||||
"sl",
|
|
||||||
"sv",
|
|
||||||
"tr",
|
|
||||||
}, false))
|
|
||||||
}
|
|
||||||
|
|
||||||
func diskDigitPrefix(s string) string {
|
|
||||||
for i, r := range s {
|
|
||||||
if unicode.IsDigit(r) {
|
|
||||||
return s[:i]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
|
|
||||||
func getMACAddressValidator() schema.SchemaValidateDiagFunc {
|
|
||||||
return validation.ToDiagFunc(func(i interface{}, k string) (ws []string, es []error) {
|
|
||||||
v, ok := i.(string)
|
|
||||||
|
|
||||||
if !ok {
|
|
||||||
es = append(es, fmt.Errorf("expected type of %s to be string", k))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if v != "" {
|
|
||||||
r := regexp.MustCompile(`^[A-Z\d]{2}(:[A-Z\d]{2}){5}$`)
|
|
||||||
ok := r.MatchString(v)
|
|
||||||
|
|
||||||
if !ok {
|
|
||||||
es = append(es, fmt.Errorf("expected %s to be a valid MAC address (A0:B1:C2:D3:E4:F5), got %s", k, v))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func getNetworkDeviceModelValidator() schema.SchemaValidateDiagFunc {
|
|
||||||
return validation.ToDiagFunc(validation.StringInSlice([]string{"e1000", "rtl8139", "virtio", "vmxnet3"}, false))
|
|
||||||
}
|
|
||||||
|
|
||||||
func getQEMUAgentTypeValidator() schema.SchemaValidateDiagFunc {
|
|
||||||
return validation.ToDiagFunc(validation.StringInSlice([]string{"isa", "virtio"}, false))
|
|
||||||
}
|
|
||||||
|
|
||||||
func getSchemaBlock(r *schema.Resource, d *schema.ResourceData, k []string, i int, allowDefault bool) (map[string]interface{}, error) {
|
|
||||||
var resourceBlock map[string]interface{}
|
|
||||||
var resourceData interface{}
|
|
||||||
var resourceSchema *schema.Schema
|
|
||||||
|
|
||||||
for ki, kv := range k {
|
|
||||||
if ki == 0 {
|
|
||||||
resourceData = d.Get(kv)
|
|
||||||
resourceSchema = r.Schema[kv]
|
|
||||||
} else {
|
|
||||||
mapValues := resourceData.([]interface{})
|
|
||||||
|
|
||||||
if len(mapValues) <= i {
|
|
||||||
return resourceBlock, fmt.Errorf("index out of bounds %d", i)
|
|
||||||
}
|
|
||||||
|
|
||||||
mapValue := mapValues[i].(map[string]interface{})
|
|
||||||
|
|
||||||
resourceData = mapValue[kv]
|
|
||||||
resourceSchema = resourceSchema.Elem.(*schema.Resource).Schema[kv]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
list := resourceData.([]interface{})
|
|
||||||
|
|
||||||
if len(list) == 0 {
|
|
||||||
if allowDefault {
|
|
||||||
listDefault, err := resourceSchema.DefaultValue()
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
list = listDefault.([]interface{})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(list) > i {
|
|
||||||
resourceBlock = list[i].(map[string]interface{})
|
|
||||||
}
|
|
||||||
|
|
||||||
return resourceBlock, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func getTimeoutValidator() schema.SchemaValidateDiagFunc {
|
|
||||||
return validation.ToDiagFunc(func(i interface{}, k string) (ws []string, es []error) {
|
|
||||||
v, ok := i.(string)
|
|
||||||
|
|
||||||
if !ok {
|
|
||||||
es = append(es, fmt.Errorf("expected type of %s to be string", k))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err := time.ParseDuration(v)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
es = append(es, fmt.Errorf("expected value of %s to be a duration - got: %s", k, v))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func getVGAMemoryValidator() schema.SchemaValidateDiagFunc {
|
|
||||||
return validation.ToDiagFunc(validation.IntBetween(4, 512))
|
|
||||||
}
|
|
||||||
|
|
||||||
func getVGATypeValidator() schema.SchemaValidateDiagFunc {
|
|
||||||
return validation.ToDiagFunc(validation.StringInSlice([]string{
|
|
||||||
"cirrus",
|
|
||||||
"qxl",
|
|
||||||
"qxl2",
|
|
||||||
"qxl3",
|
|
||||||
"qxl4",
|
|
||||||
"serial0",
|
|
||||||
"serial1",
|
|
||||||
"serial2",
|
|
||||||
"serial3",
|
|
||||||
"std",
|
|
||||||
"virtio",
|
|
||||||
"vmware",
|
|
||||||
}, false))
|
|
||||||
}
|
|
||||||
|
|
||||||
func getSCSIHardwareValidator() schema.SchemaValidateDiagFunc {
|
|
||||||
return validation.ToDiagFunc(validation.StringInSlice([]string{
|
|
||||||
"lsi",
|
|
||||||
"lsi53c810",
|
|
||||||
"virtio-scsi-pci",
|
|
||||||
"virtio-scsi-single",
|
|
||||||
"megasas",
|
|
||||||
"pvscsi",
|
|
||||||
}, false))
|
|
||||||
}
|
|
||||||
|
|
||||||
func getIDEInterfaceValidator() schema.SchemaValidateDiagFunc {
|
|
||||||
return validation.ToDiagFunc(validation.StringInSlice([]string{
|
|
||||||
"ide0",
|
|
||||||
"ide1",
|
|
||||||
"ide2",
|
|
||||||
"ide3",
|
|
||||||
}, false))
|
|
||||||
}
|
|
||||||
|
|
||||||
// suppressIfListsAreEqualIgnoringOrder is a customdiff.SuppressionFunc that suppresses
|
|
||||||
// changes to a list if the old and new lists are equal, ignoring the order of the
|
|
||||||
// elements.
|
|
||||||
// It will be called for each list item, so it is not super efficient. It is
|
|
||||||
// recommended to use it only for small lists.
|
|
||||||
// Ref: https://github.com/hashicorp/terraform-plugin-sdk/issues/477
|
|
||||||
func suppressIfListsAreEqualIgnoringOrder(key, _, _ string, d *schema.ResourceData) bool {
|
|
||||||
// the key is a path to the list item, not the list itself, e.g. "tags.0"
|
|
||||||
lastDotIndex := strings.LastIndex(key, ".")
|
|
||||||
if lastDotIndex != -1 {
|
|
||||||
key = key[:lastDotIndex]
|
|
||||||
}
|
|
||||||
|
|
||||||
oldData, newData := d.GetChange(key)
|
|
||||||
if oldData == nil || newData == nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
oldArray := oldData.([]interface{})
|
|
||||||
newArray := newData.([]interface{})
|
|
||||||
|
|
||||||
if len(oldArray) != len(newArray) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
oldEvents := make([]string, len(oldArray))
|
|
||||||
newEvents := make([]string, len(newArray))
|
|
||||||
|
|
||||||
for i, oldEvt := range oldArray {
|
|
||||||
oldEvents[i] = fmt.Sprint(oldEvt)
|
|
||||||
}
|
|
||||||
|
|
||||||
for j, newEvt := range newArray {
|
|
||||||
newEvents[j] = fmt.Sprint(newEvt)
|
|
||||||
}
|
|
||||||
|
|
||||||
sort.Strings(oldEvents)
|
|
||||||
sort.Strings(newEvents)
|
|
||||||
|
|
||||||
return reflect.DeepEqual(oldEvents, newEvents)
|
|
||||||
}
|
|
||||||
|
|
||||||
func getDiskInfo(resp *vms.GetResponseData, d *schema.ResourceData) map[string]*vms.CustomStorageDevice {
|
|
||||||
currentDisk := d.Get(mkResourceVirtualEnvironmentVMDisk)
|
|
||||||
|
|
||||||
currentDiskList := currentDisk.([]interface{})
|
|
||||||
currentDiskMap := map[string]map[string]interface{}{}
|
|
||||||
|
|
||||||
for _, v := range currentDiskList {
|
|
||||||
diskMap := v.(map[string]interface{})
|
|
||||||
diskInterface := diskMap[mkResourceVirtualEnvironmentVMDiskInterface].(string)
|
|
||||||
|
|
||||||
currentDiskMap[diskInterface] = diskMap
|
|
||||||
}
|
|
||||||
|
|
||||||
storageDevices := map[string]*vms.CustomStorageDevice{}
|
|
||||||
|
|
||||||
storageDevices["ide0"] = resp.IDEDevice0
|
|
||||||
storageDevices["ide1"] = resp.IDEDevice1
|
|
||||||
storageDevices["ide2"] = resp.IDEDevice2
|
|
||||||
storageDevices["ide3"] = resp.IDEDevice3
|
|
||||||
|
|
||||||
storageDevices["sata0"] = resp.SATADevice0
|
|
||||||
storageDevices["sata1"] = resp.SATADevice1
|
|
||||||
storageDevices["sata2"] = resp.SATADevice2
|
|
||||||
storageDevices["sata3"] = resp.SATADevice3
|
|
||||||
storageDevices["sata4"] = resp.SATADevice4
|
|
||||||
storageDevices["sata5"] = resp.SATADevice5
|
|
||||||
|
|
||||||
storageDevices["scsi0"] = resp.SCSIDevice0
|
|
||||||
storageDevices["scsi1"] = resp.SCSIDevice1
|
|
||||||
storageDevices["scsi2"] = resp.SCSIDevice2
|
|
||||||
storageDevices["scsi3"] = resp.SCSIDevice3
|
|
||||||
storageDevices["scsi4"] = resp.SCSIDevice4
|
|
||||||
storageDevices["scsi5"] = resp.SCSIDevice5
|
|
||||||
storageDevices["scsi6"] = resp.SCSIDevice6
|
|
||||||
storageDevices["scsi7"] = resp.SCSIDevice7
|
|
||||||
storageDevices["scsi8"] = resp.SCSIDevice8
|
|
||||||
storageDevices["scsi9"] = resp.SCSIDevice9
|
|
||||||
storageDevices["scsi10"] = resp.SCSIDevice10
|
|
||||||
storageDevices["scsi11"] = resp.SCSIDevice11
|
|
||||||
storageDevices["scsi12"] = resp.SCSIDevice12
|
|
||||||
storageDevices["scsi13"] = resp.SCSIDevice13
|
|
||||||
|
|
||||||
storageDevices["virtio0"] = resp.VirtualIODevice0
|
|
||||||
storageDevices["virtio1"] = resp.VirtualIODevice1
|
|
||||||
storageDevices["virtio2"] = resp.VirtualIODevice2
|
|
||||||
storageDevices["virtio3"] = resp.VirtualIODevice3
|
|
||||||
storageDevices["virtio4"] = resp.VirtualIODevice4
|
|
||||||
storageDevices["virtio5"] = resp.VirtualIODevice5
|
|
||||||
storageDevices["virtio6"] = resp.VirtualIODevice6
|
|
||||||
storageDevices["virtio7"] = resp.VirtualIODevice7
|
|
||||||
storageDevices["virtio8"] = resp.VirtualIODevice8
|
|
||||||
storageDevices["virtio9"] = resp.VirtualIODevice9
|
|
||||||
storageDevices["virtio10"] = resp.VirtualIODevice10
|
|
||||||
storageDevices["virtio11"] = resp.VirtualIODevice11
|
|
||||||
storageDevices["virtio12"] = resp.VirtualIODevice12
|
|
||||||
storageDevices["virtio13"] = resp.VirtualIODevice13
|
|
||||||
storageDevices["virtio14"] = resp.VirtualIODevice14
|
|
||||||
storageDevices["virtio15"] = resp.VirtualIODevice15
|
|
||||||
|
|
||||||
for k, v := range storageDevices {
|
|
||||||
if v != nil {
|
|
||||||
if currentDiskMap[k] != nil {
|
|
||||||
if currentDiskMap[k][mkResourceVirtualEnvironmentVMDiskFileID] != nil {
|
|
||||||
fileID := currentDiskMap[k][mkResourceVirtualEnvironmentVMDiskFileID].(string)
|
|
||||||
v.FileID = &fileID
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// defensive copy of the loop variable
|
|
||||||
iface := k
|
|
||||||
v.Interface = &iface
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return storageDevices
|
|
||||||
}
|
|
||||||
|
|
||||||
// getDiskDatastores returns a list of the used datastores in a VM
|
|
||||||
func getDiskDatastores(vm *vms.GetResponseData, d *schema.ResourceData) []string {
|
|
||||||
storageDevices := getDiskInfo(vm, d)
|
|
||||||
datastoresSet := map[string]int{}
|
|
||||||
|
|
||||||
for _, diskInfo := range storageDevices {
|
|
||||||
// Ignore empty storage devices and storage devices (like ide) which may not have any media mounted
|
|
||||||
if diskInfo == nil || diskInfo.FileVolume == "none" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
fileIDParts := strings.Split(diskInfo.FileVolume, ":")
|
|
||||||
datastoresSet[fileIDParts[0]] = 1
|
|
||||||
}
|
|
||||||
|
|
||||||
if vm.EFIDisk != nil {
|
|
||||||
fileIDParts := strings.Split(vm.EFIDisk.FileVolume, ":")
|
|
||||||
datastoresSet[fileIDParts[0]] = 1
|
|
||||||
}
|
|
||||||
|
|
||||||
datastores := []string{}
|
|
||||||
for datastore := range datastoresSet {
|
|
||||||
datastores = append(datastores, datastore)
|
|
||||||
}
|
|
||||||
|
|
||||||
return datastores
|
|
||||||
}
|
|
||||||
|
|
||||||
func getPCIInfo(resp *vms.GetResponseData, _ *schema.ResourceData) map[string]*vms.CustomPCIDevice {
|
|
||||||
pciDevices := map[string]*vms.CustomPCIDevice{}
|
|
||||||
|
|
||||||
pciDevices["hostpci0"] = resp.PCIDevice0
|
|
||||||
pciDevices["hostpci1"] = resp.PCIDevice1
|
|
||||||
pciDevices["hostpci2"] = resp.PCIDevice2
|
|
||||||
pciDevices["hostpci3"] = resp.PCIDevice3
|
|
||||||
|
|
||||||
return pciDevices
|
|
||||||
}
|
|
||||||
|
|
||||||
func getCloudInitTypeValidator() schema.SchemaValidateDiagFunc {
|
|
||||||
return validation.ToDiagFunc(validation.StringInSlice([]string{
|
|
||||||
"configdrive2",
|
|
||||||
"nocloud",
|
|
||||||
}, false))
|
|
||||||
}
|
|
||||||
|
|
||||||
func parseImportIDWithNodeName(id string) (string, string, error) {
|
|
||||||
nodeName, id, found := strings.Cut(id, "/")
|
|
||||||
|
|
||||||
if !found {
|
|
||||||
return "", "", fmt.Errorf("unexpected format of ID (%s), expected node/id", id)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nodeName, id, nil
|
|
||||||
}
|
|
78
proxmoxtf/resource/validator/file.go
Normal file
78
proxmoxtf/resource/validator/file.go
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
/*
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package validator
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"regexp"
|
||||||
|
|
||||||
|
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
|
||||||
|
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
|
||||||
|
|
||||||
|
"github.com/bpg/terraform-provider-proxmox/internal/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
// FileFormat returns a schema validation function for a file format.
|
||||||
|
func FileFormat() schema.SchemaValidateDiagFunc {
|
||||||
|
return validation.ToDiagFunc(validation.StringInSlice([]string{
|
||||||
|
"qcow2",
|
||||||
|
"raw",
|
||||||
|
"vmdk",
|
||||||
|
}, false))
|
||||||
|
}
|
||||||
|
|
||||||
|
// FileID returns a schema validation function for a file identifier.
|
||||||
|
func FileID() schema.SchemaValidateDiagFunc {
|
||||||
|
return validation.ToDiagFunc(func(i interface{}, k string) ([]string, []error) {
|
||||||
|
v, ok := i.(string)
|
||||||
|
|
||||||
|
var ws []string
|
||||||
|
var es []error
|
||||||
|
|
||||||
|
if !ok {
|
||||||
|
es = append(es, fmt.Errorf("expected type of %s to be string", k))
|
||||||
|
return ws, es
|
||||||
|
}
|
||||||
|
|
||||||
|
if v != "" {
|
||||||
|
r := regexp.MustCompile(`^(?i)[a-z\d\-_]+:([a-z\d\-_]+/)?.+$`)
|
||||||
|
ok := r.MatchString(v)
|
||||||
|
|
||||||
|
if !ok {
|
||||||
|
es = append(es, fmt.Errorf(
|
||||||
|
"expected %s to be a valid file identifier (datastore-name:iso/some-file.img), got %s", k, v,
|
||||||
|
))
|
||||||
|
return ws, es
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ws, es
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// FileSize is a schema validation function for file size.
|
||||||
|
func FileSize() schema.SchemaValidateDiagFunc {
|
||||||
|
return validation.ToDiagFunc(func(i interface{}, k string) ([]string, []error) {
|
||||||
|
v, ok := i.(string)
|
||||||
|
var es []error
|
||||||
|
|
||||||
|
if !ok {
|
||||||
|
es = append(es, fmt.Errorf("expected type of %s to be string", k))
|
||||||
|
return nil, es
|
||||||
|
}
|
||||||
|
|
||||||
|
if v != "" {
|
||||||
|
_, err := types.ParseDiskSize(v)
|
||||||
|
if err != nil {
|
||||||
|
es = append(es, fmt.Errorf("expected %s to be a valid file size (100, 1M, 1G), got %s", k, v))
|
||||||
|
return nil, es
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return []string{}, es
|
||||||
|
})
|
||||||
|
}
|
@ -8,69 +8,35 @@ package validator
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"regexp"
|
||||||
|
|
||||||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
|
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
|
||||||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
|
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
|
||||||
)
|
)
|
||||||
|
|
||||||
// VLANIDsValidator returns a schema validation function for VLAN IDs.
|
// MACAddress is a schema validation function for MAC address.
|
||||||
func VLANIDsValidator() schema.SchemaValidateDiagFunc {
|
func MACAddress() schema.SchemaValidateDiagFunc {
|
||||||
return validation.ToDiagFunc(func(i interface{}, k string) ([]string, []error) {
|
return validation.ToDiagFunc(func(i interface{}, k string) ([]string, []error) {
|
||||||
min := 1
|
v, ok := i.(string)
|
||||||
max := 4094
|
|
||||||
|
|
||||||
var ws []string
|
var ws []string
|
||||||
var es []error
|
var es []error
|
||||||
|
|
||||||
list, ok := i.([]interface{})
|
if !ok {
|
||||||
|
es = append(es, fmt.Errorf("expected type of %s to be string", k))
|
||||||
|
return ws, es
|
||||||
|
}
|
||||||
|
|
||||||
|
if v != "" {
|
||||||
|
r := regexp.MustCompile(`^[A-Z\d]{2}(:[A-Z\d]{2}){5}$`)
|
||||||
|
ok := r.MatchString(v)
|
||||||
|
|
||||||
if !ok {
|
if !ok {
|
||||||
es = append(es, fmt.Errorf("expected type of %s to be []interface{}", k))
|
es = append(es, fmt.Errorf("expected %s to be a valid MAC address (A0:B1:C2:D3:E4:F5), got %s", k, v))
|
||||||
return ws, es
|
return ws, es
|
||||||
}
|
}
|
||||||
|
|
||||||
for li, lv := range list {
|
|
||||||
v, ok := lv.(int)
|
|
||||||
|
|
||||||
if !ok {
|
|
||||||
es = append(es, fmt.Errorf("expected type of %s[%d] to be int", k, li))
|
|
||||||
return ws, es
|
|
||||||
}
|
|
||||||
|
|
||||||
if v != -1 {
|
|
||||||
if v < min || v > max {
|
|
||||||
es = append(es, fmt.Errorf("expected %s[%d] to be in the range (%d - %d), got %d", k, li, min, max, v))
|
|
||||||
return ws, es
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ws, es
|
return ws, es
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// NodeNetworkInterfaceBondingModes returns a schema validation function for a node network interface bonding mode.
|
|
||||||
func NodeNetworkInterfaceBondingModes() schema.SchemaValidateDiagFunc {
|
|
||||||
return validation.ToDiagFunc(validation.StringInSlice([]string{
|
|
||||||
"balance-rr",
|
|
||||||
"active-backup",
|
|
||||||
"balance-xor",
|
|
||||||
"broadcast",
|
|
||||||
"802.3ad",
|
|
||||||
"balance-tlb",
|
|
||||||
"balance-alb",
|
|
||||||
"balance-slb",
|
|
||||||
"lacp-balance-slb",
|
|
||||||
"lacp-balance-tcp",
|
|
||||||
}, false))
|
|
||||||
}
|
|
||||||
|
|
||||||
// NodeNetworkInterfaceBondingTransmitHashPolicies returns a schema validation function for a node network interface
|
|
||||||
// bonding transmit hash policy.
|
|
||||||
func NodeNetworkInterfaceBondingTransmitHashPolicies() schema.SchemaValidateDiagFunc {
|
|
||||||
return validation.ToDiagFunc(validation.StringInSlice([]string{
|
|
||||||
"layer2",
|
|
||||||
"layer2+3",
|
|
||||||
"layer3+4",
|
|
||||||
}, false))
|
|
||||||
}
|
|
||||||
|
@ -8,6 +8,8 @@ package validator
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"regexp"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
|
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
|
||||||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
|
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
|
||||||
@ -39,3 +41,222 @@ func VMID() schema.SchemaValidateDiagFunc {
|
|||||||
return ws, es
|
return ws, es
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// BIOS returns a schema validation function for a BIOS type.
|
||||||
|
func BIOS() schema.SchemaValidateDiagFunc {
|
||||||
|
return validation.ToDiagFunc(validation.StringInSlice([]string{
|
||||||
|
"ovmf",
|
||||||
|
"seabios",
|
||||||
|
}, false))
|
||||||
|
}
|
||||||
|
|
||||||
|
// ContentType returns a schema validation function for a content type on a storage device.
|
||||||
|
func ContentType() schema.SchemaValidateDiagFunc {
|
||||||
|
return validation.ToDiagFunc(validation.StringInSlice([]string{
|
||||||
|
"backup",
|
||||||
|
"iso",
|
||||||
|
"snippets",
|
||||||
|
"vztmpl",
|
||||||
|
}, false))
|
||||||
|
}
|
||||||
|
|
||||||
|
// CPUType returns a schema validation function for a CPU type.
|
||||||
|
func CPUType() schema.SchemaValidateDiagFunc {
|
||||||
|
standardTypes := []string{
|
||||||
|
"486",
|
||||||
|
"Broadwell",
|
||||||
|
"Broadwell-IBRS",
|
||||||
|
"Broadwell-noTSX",
|
||||||
|
"Broadwell-noTSX-IBRS",
|
||||||
|
"Cascadelake-Server",
|
||||||
|
"Cascadelake-Server-noTSX",
|
||||||
|
"Cascadelake-Server-v2",
|
||||||
|
"Cascadelake-Server-v4",
|
||||||
|
"Cascadelake-Server-v5",
|
||||||
|
"Conroe",
|
||||||
|
"Cooperlake",
|
||||||
|
"Cooperlake-v2",
|
||||||
|
"EPYC",
|
||||||
|
"EPYC-IBPB",
|
||||||
|
"EPYC-Milan",
|
||||||
|
"EPYC-Rome",
|
||||||
|
"EPYC-Rome-v2",
|
||||||
|
"EPYC-v3",
|
||||||
|
"Haswell",
|
||||||
|
"Haswell-IBRS",
|
||||||
|
"Haswell-noTSX",
|
||||||
|
"Haswell-noTSX-IBRS",
|
||||||
|
"Icelake-Client",
|
||||||
|
"Icelake-Client-noTSX",
|
||||||
|
"Icelake-Server",
|
||||||
|
"Icelake-Server-noTSX",
|
||||||
|
"Icelake-Server-v3",
|
||||||
|
"Icelake-Server-v4",
|
||||||
|
"Icelake-Server-v5",
|
||||||
|
"Icelake-Server-v6",
|
||||||
|
"IvyBridge",
|
||||||
|
"IvyBridge-IBRS",
|
||||||
|
"KnightsMill",
|
||||||
|
"Nehalem",
|
||||||
|
"Nehalem-IBRS",
|
||||||
|
"Opteron_G1",
|
||||||
|
"Opteron_G2",
|
||||||
|
"Opteron_G3",
|
||||||
|
"Opteron_G4",
|
||||||
|
"Opteron_G5",
|
||||||
|
"Penryn",
|
||||||
|
"SandyBridge",
|
||||||
|
"SandyBridge-IBRS",
|
||||||
|
"SapphireRapids",
|
||||||
|
"Skylake-Client",
|
||||||
|
"Skylake-Client-IBRS",
|
||||||
|
"Skylake-Client-noTSX-IBRS",
|
||||||
|
"Skylake-Client-v4",
|
||||||
|
"Skylake-Server",
|
||||||
|
"Skylake-Server-IBRS",
|
||||||
|
"Skylake-Server-noTSX-IBRS",
|
||||||
|
"Skylake-Server-v4",
|
||||||
|
"Skylake-Server-v5",
|
||||||
|
"Westmere",
|
||||||
|
"Westmere-IBRS",
|
||||||
|
"athlon",
|
||||||
|
"core2duo",
|
||||||
|
"coreduo",
|
||||||
|
"host",
|
||||||
|
"kvm32",
|
||||||
|
"kvm64",
|
||||||
|
"max",
|
||||||
|
"pentium",
|
||||||
|
"pentium2",
|
||||||
|
"pentium3",
|
||||||
|
"phenom",
|
||||||
|
"qemu32",
|
||||||
|
"qemu64",
|
||||||
|
"x86-64-v2",
|
||||||
|
"x86-64-v2-AES",
|
||||||
|
"x86-64-v3",
|
||||||
|
"x86-64-v4",
|
||||||
|
}
|
||||||
|
|
||||||
|
return validation.ToDiagFunc(validation.Any(
|
||||||
|
validation.StringInSlice(standardTypes, false),
|
||||||
|
validation.StringMatch(regexp.MustCompile(`^custom-.+$`), "must be a valid custom CPU type"),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
// NetworkDeviceModel is a schema validation function for network device models.
|
||||||
|
func NetworkDeviceModel() schema.SchemaValidateDiagFunc {
|
||||||
|
return validation.ToDiagFunc(validation.StringInSlice([]string{"e1000", "rtl8139", "virtio", "vmxnet3"}, false))
|
||||||
|
}
|
||||||
|
|
||||||
|
// QEMUAgentType is a schema validation function for QEMU agent types.
|
||||||
|
func QEMUAgentType() schema.SchemaValidateDiagFunc {
|
||||||
|
return validation.ToDiagFunc(validation.StringInSlice([]string{"isa", "virtio"}, false))
|
||||||
|
}
|
||||||
|
|
||||||
|
// KeyboardLayout is a schema validation function for keyboard layouts.
|
||||||
|
func KeyboardLayout() schema.SchemaValidateDiagFunc {
|
||||||
|
return validation.ToDiagFunc(validation.StringInSlice([]string{
|
||||||
|
"da",
|
||||||
|
"de",
|
||||||
|
"de-ch",
|
||||||
|
"en-gb",
|
||||||
|
"en-us",
|
||||||
|
"es",
|
||||||
|
"fi",
|
||||||
|
"fr",
|
||||||
|
"fr-be",
|
||||||
|
"fr-ca",
|
||||||
|
"fr-ch",
|
||||||
|
"hu",
|
||||||
|
"is",
|
||||||
|
"it",
|
||||||
|
"ja",
|
||||||
|
"lt",
|
||||||
|
"mk",
|
||||||
|
"nl",
|
||||||
|
"no",
|
||||||
|
"pl",
|
||||||
|
"pt",
|
||||||
|
"pt-br",
|
||||||
|
"sl",
|
||||||
|
"sv",
|
||||||
|
"tr",
|
||||||
|
}, false))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Timeout is a schema validation function for timeouts.
|
||||||
|
func Timeout() schema.SchemaValidateDiagFunc {
|
||||||
|
return validation.ToDiagFunc(func(i interface{}, k string) ([]string, []error) {
|
||||||
|
v, ok := i.(string)
|
||||||
|
|
||||||
|
var ws []string
|
||||||
|
var es []error
|
||||||
|
|
||||||
|
if !ok {
|
||||||
|
es = append(es, fmt.Errorf("expected type of %s to be string", k))
|
||||||
|
return ws, es
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err := time.ParseDuration(v)
|
||||||
|
if err != nil {
|
||||||
|
es = append(es, fmt.Errorf("expected value of %s to be a duration - got: %s", k, v))
|
||||||
|
return ws, es
|
||||||
|
}
|
||||||
|
|
||||||
|
return ws, es
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// VGAMemory is a schema validation function for VGA memory sizes.
|
||||||
|
func VGAMemory() schema.SchemaValidateDiagFunc {
|
||||||
|
return validation.ToDiagFunc(validation.IntBetween(4, 512))
|
||||||
|
}
|
||||||
|
|
||||||
|
// VGAType is a schema validation function for VGA device types.
|
||||||
|
func VGAType() schema.SchemaValidateDiagFunc {
|
||||||
|
return validation.ToDiagFunc(validation.StringInSlice([]string{
|
||||||
|
"cirrus",
|
||||||
|
"qxl",
|
||||||
|
"qxl2",
|
||||||
|
"qxl3",
|
||||||
|
"qxl4",
|
||||||
|
"serial0",
|
||||||
|
"serial1",
|
||||||
|
"serial2",
|
||||||
|
"serial3",
|
||||||
|
"std",
|
||||||
|
"virtio",
|
||||||
|
"vmware",
|
||||||
|
}, false))
|
||||||
|
}
|
||||||
|
|
||||||
|
// SCSIHardware is a schema validation function for SCSI hardware.
|
||||||
|
func SCSIHardware() schema.SchemaValidateDiagFunc {
|
||||||
|
return validation.ToDiagFunc(validation.StringInSlice([]string{
|
||||||
|
"lsi",
|
||||||
|
"lsi53c810",
|
||||||
|
"virtio-scsi-pci",
|
||||||
|
"virtio-scsi-single",
|
||||||
|
"megasas",
|
||||||
|
"pvscsi",
|
||||||
|
}, false))
|
||||||
|
}
|
||||||
|
|
||||||
|
// IDEInterface is a schema validation function for IDE interfaces.
|
||||||
|
func IDEInterface() schema.SchemaValidateDiagFunc {
|
||||||
|
return validation.ToDiagFunc(validation.StringInSlice([]string{
|
||||||
|
"ide0",
|
||||||
|
"ide1",
|
||||||
|
"ide2",
|
||||||
|
"ide3",
|
||||||
|
}, false))
|
||||||
|
}
|
||||||
|
|
||||||
|
// CloudInitType is a schema validation function for cloud-init types.
|
||||||
|
func CloudInitType() schema.SchemaValidateDiagFunc {
|
||||||
|
return validation.ToDiagFunc(validation.StringInSlice([]string{
|
||||||
|
"configdrive2",
|
||||||
|
"nocloud",
|
||||||
|
}, false))
|
||||||
|
}
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package resource
|
package validator
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
@ -33,7 +33,7 @@ func Test_getCPUTypeValidator(t *testing.T) {
|
|||||||
t.Parallel()
|
t.Parallel()
|
||||||
require := require.New(t)
|
require := require.New(t)
|
||||||
|
|
||||||
f := getCPUTypeValidator()
|
f := CPUType()
|
||||||
res := f(tt.value, nil)
|
res := f(tt.value, nil)
|
||||||
|
|
||||||
if tt.valid {
|
if tt.valid {
|
||||||
@ -44,38 +44,3 @@ func Test_getCPUTypeValidator(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func Test_parseImportIDWIthNodeName(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
tests := []struct {
|
|
||||||
name string
|
|
||||||
value string
|
|
||||||
valid bool
|
|
||||||
expectedNodeName string
|
|
||||||
expectedID string
|
|
||||||
}{
|
|
||||||
{"empty", "", false, "", ""},
|
|
||||||
{"missing slash", "invalid", false, "", ""},
|
|
||||||
{"valid", "host/id", true, "host", "id"},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, tt := range tests {
|
|
||||||
tt := tt
|
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
require := require.New(t)
|
|
||||||
|
|
||||||
nodeName, id, err := parseImportIDWithNodeName(tt.value)
|
|
||||||
|
|
||||||
if !tt.valid {
|
|
||||||
require.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
require.Nil(err)
|
|
||||||
require.Equal(tt.expectedNodeName, nodeName)
|
|
||||||
require.Equal(tt.expectedID, id)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
@ -14,6 +14,7 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
"unicode"
|
||||||
|
|
||||||
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
|
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
|
||||||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff"
|
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff"
|
||||||
@ -25,6 +26,7 @@ import (
|
|||||||
"github.com/bpg/terraform-provider-proxmox/proxmox/nodes/vms"
|
"github.com/bpg/terraform-provider-proxmox/proxmox/nodes/vms"
|
||||||
"github.com/bpg/terraform-provider-proxmox/proxmoxtf"
|
"github.com/bpg/terraform-provider-proxmox/proxmoxtf"
|
||||||
"github.com/bpg/terraform-provider-proxmox/proxmoxtf/resource/validator"
|
"github.com/bpg/terraform-provider-proxmox/proxmoxtf/resource/validator"
|
||||||
|
"github.com/bpg/terraform-provider-proxmox/proxmoxtf/structure"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -305,7 +307,7 @@ func VM() *schema.Resource {
|
|||||||
Description: "The maximum amount of time to wait for data from the QEMU agent to become available",
|
Description: "The maximum amount of time to wait for data from the QEMU agent to become available",
|
||||||
Optional: true,
|
Optional: true,
|
||||||
Default: dvResourceVirtualEnvironmentVMAgentTimeout,
|
Default: dvResourceVirtualEnvironmentVMAgentTimeout,
|
||||||
ValidateDiagFunc: getTimeoutValidator(),
|
ValidateDiagFunc: validator.Timeout(),
|
||||||
},
|
},
|
||||||
mkResourceVirtualEnvironmentVMAgentTrim: {
|
mkResourceVirtualEnvironmentVMAgentTrim: {
|
||||||
Type: schema.TypeBool,
|
Type: schema.TypeBool,
|
||||||
@ -318,7 +320,7 @@ func VM() *schema.Resource {
|
|||||||
Description: "The QEMU agent interface type",
|
Description: "The QEMU agent interface type",
|
||||||
Optional: true,
|
Optional: true,
|
||||||
Default: dvResourceVirtualEnvironmentVMAgentType,
|
Default: dvResourceVirtualEnvironmentVMAgentType,
|
||||||
ValidateDiagFunc: getQEMUAgentTypeValidator(),
|
ValidateDiagFunc: validator.QEMUAgentType(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -370,7 +372,7 @@ func VM() *schema.Resource {
|
|||||||
Description: "The BIOS implementation",
|
Description: "The BIOS implementation",
|
||||||
Optional: true,
|
Optional: true,
|
||||||
Default: dvResourceVirtualEnvironmentVMBIOS,
|
Default: dvResourceVirtualEnvironmentVMBIOS,
|
||||||
ValidateDiagFunc: getBIOSValidator(),
|
ValidateDiagFunc: validator.BIOS(),
|
||||||
},
|
},
|
||||||
mkResourceVirtualEnvironmentVMCDROM: {
|
mkResourceVirtualEnvironmentVMCDROM: {
|
||||||
Type: schema.TypeList,
|
Type: schema.TypeList,
|
||||||
@ -398,14 +400,14 @@ func VM() *schema.Resource {
|
|||||||
Description: "The file id",
|
Description: "The file id",
|
||||||
Optional: true,
|
Optional: true,
|
||||||
Default: dvResourceVirtualEnvironmentVMCDROMFileID,
|
Default: dvResourceVirtualEnvironmentVMCDROMFileID,
|
||||||
ValidateDiagFunc: getFileIDValidator(),
|
ValidateDiagFunc: validator.FileID(),
|
||||||
},
|
},
|
||||||
mkResourceVirtualEnvironmentVMCDROMInterface: {
|
mkResourceVirtualEnvironmentVMCDROMInterface: {
|
||||||
Type: schema.TypeString,
|
Type: schema.TypeString,
|
||||||
Description: "The CDROM interface",
|
Description: "The CDROM interface",
|
||||||
Optional: true,
|
Optional: true,
|
||||||
Default: dvResourceVirtualEnvironmentVMCDROMInterface,
|
Default: dvResourceVirtualEnvironmentVMCDROMInterface,
|
||||||
ValidateDiagFunc: getIDEInterfaceValidator(),
|
ValidateDiagFunc: validator.IDEInterface(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -529,7 +531,7 @@ func VM() *schema.Resource {
|
|||||||
Description: "The emulated CPU type",
|
Description: "The emulated CPU type",
|
||||||
Optional: true,
|
Optional: true,
|
||||||
Default: dvResourceVirtualEnvironmentVMCPUType,
|
Default: dvResourceVirtualEnvironmentVMCPUType,
|
||||||
ValidateDiagFunc: getCPUTypeValidator(),
|
ValidateDiagFunc: validator.CPUType(),
|
||||||
},
|
},
|
||||||
mkResourceVirtualEnvironmentVMCPUUnits: {
|
mkResourceVirtualEnvironmentVMCPUUnits: {
|
||||||
Type: schema.TypeInt,
|
Type: schema.TypeInt,
|
||||||
@ -588,7 +590,7 @@ func VM() *schema.Resource {
|
|||||||
Optional: true,
|
Optional: true,
|
||||||
ForceNew: true,
|
ForceNew: true,
|
||||||
Computed: true,
|
Computed: true,
|
||||||
ValidateDiagFunc: getFileFormatValidator(),
|
ValidateDiagFunc: validator.FileFormat(),
|
||||||
},
|
},
|
||||||
mkResourceVirtualEnvironmentVMDiskFileID: {
|
mkResourceVirtualEnvironmentVMDiskFileID: {
|
||||||
Type: schema.TypeString,
|
Type: schema.TypeString,
|
||||||
@ -596,7 +598,7 @@ func VM() *schema.Resource {
|
|||||||
Optional: true,
|
Optional: true,
|
||||||
ForceNew: true,
|
ForceNew: true,
|
||||||
Default: dvResourceVirtualEnvironmentVMDiskFileID,
|
Default: dvResourceVirtualEnvironmentVMDiskFileID,
|
||||||
ValidateDiagFunc: getFileIDValidator(),
|
ValidateDiagFunc: validator.FileID(),
|
||||||
},
|
},
|
||||||
mkResourceVirtualEnvironmentVMDiskSize: {
|
mkResourceVirtualEnvironmentVMDiskSize: {
|
||||||
Type: schema.TypeInt,
|
Type: schema.TypeInt,
|
||||||
@ -695,7 +697,7 @@ func VM() *schema.Resource {
|
|||||||
Optional: true,
|
Optional: true,
|
||||||
ForceNew: true,
|
ForceNew: true,
|
||||||
Computed: true,
|
Computed: true,
|
||||||
ValidateDiagFunc: getFileFormatValidator(),
|
ValidateDiagFunc: validator.FileFormat(),
|
||||||
},
|
},
|
||||||
mkResourceVirtualEnvironmentVMEFIDiskType: {
|
mkResourceVirtualEnvironmentVMEFIDiskType: {
|
||||||
Type: schema.TypeString,
|
Type: schema.TypeString,
|
||||||
@ -875,7 +877,7 @@ func VM() *schema.Resource {
|
|||||||
Optional: true,
|
Optional: true,
|
||||||
ForceNew: true,
|
ForceNew: true,
|
||||||
Default: dvResourceVirtualEnvironmentVMInitializationUserDataFileID,
|
Default: dvResourceVirtualEnvironmentVMInitializationUserDataFileID,
|
||||||
ValidateDiagFunc: getFileIDValidator(),
|
ValidateDiagFunc: validator.FileID(),
|
||||||
},
|
},
|
||||||
mkResourceVirtualEnvironmentVMInitializationVendorDataFileID: {
|
mkResourceVirtualEnvironmentVMInitializationVendorDataFileID: {
|
||||||
Type: schema.TypeString,
|
Type: schema.TypeString,
|
||||||
@ -883,7 +885,7 @@ func VM() *schema.Resource {
|
|||||||
Optional: true,
|
Optional: true,
|
||||||
ForceNew: true,
|
ForceNew: true,
|
||||||
Default: dvResourceVirtualEnvironmentVMInitializationVendorDataFileID,
|
Default: dvResourceVirtualEnvironmentVMInitializationVendorDataFileID,
|
||||||
ValidateDiagFunc: getFileIDValidator(),
|
ValidateDiagFunc: validator.FileID(),
|
||||||
},
|
},
|
||||||
mkResourceVirtualEnvironmentVMInitializationNetworkDataFileID: {
|
mkResourceVirtualEnvironmentVMInitializationNetworkDataFileID: {
|
||||||
Type: schema.TypeString,
|
Type: schema.TypeString,
|
||||||
@ -891,7 +893,7 @@ func VM() *schema.Resource {
|
|||||||
Optional: true,
|
Optional: true,
|
||||||
ForceNew: true,
|
ForceNew: true,
|
||||||
Default: dvResourceVirtualEnvironmentVMInitializationNetworkDataFileID,
|
Default: dvResourceVirtualEnvironmentVMInitializationNetworkDataFileID,
|
||||||
ValidateDiagFunc: getFileIDValidator(),
|
ValidateDiagFunc: validator.FileID(),
|
||||||
},
|
},
|
||||||
mkResourceVirtualEnvironmentVMInitializationMetaDataFileID: {
|
mkResourceVirtualEnvironmentVMInitializationMetaDataFileID: {
|
||||||
Type: schema.TypeString,
|
Type: schema.TypeString,
|
||||||
@ -899,7 +901,7 @@ func VM() *schema.Resource {
|
|||||||
Optional: true,
|
Optional: true,
|
||||||
ForceNew: true,
|
ForceNew: true,
|
||||||
Default: dvResourceVirtualEnvironmentVMInitializationMetaDataFileID,
|
Default: dvResourceVirtualEnvironmentVMInitializationMetaDataFileID,
|
||||||
ValidateDiagFunc: getFileIDValidator(),
|
ValidateDiagFunc: validator.FileID(),
|
||||||
},
|
},
|
||||||
mkResourceVirtualEnvironmentVMInitializationType: {
|
mkResourceVirtualEnvironmentVMInitializationType: {
|
||||||
Type: schema.TypeString,
|
Type: schema.TypeString,
|
||||||
@ -907,7 +909,7 @@ func VM() *schema.Resource {
|
|||||||
Optional: true,
|
Optional: true,
|
||||||
ForceNew: true,
|
ForceNew: true,
|
||||||
Default: dvResourceVirtualEnvironmentVMInitializationType,
|
Default: dvResourceVirtualEnvironmentVMInitializationType,
|
||||||
ValidateDiagFunc: getCloudInitTypeValidator(),
|
ValidateDiagFunc: validator.CloudInitType(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -985,7 +987,7 @@ func VM() *schema.Resource {
|
|||||||
Description: "The keyboard layout",
|
Description: "The keyboard layout",
|
||||||
Optional: true,
|
Optional: true,
|
||||||
Default: dvResourceVirtualEnvironmentVMKeyboardLayout,
|
Default: dvResourceVirtualEnvironmentVMKeyboardLayout,
|
||||||
ValidateDiagFunc: getKeyboardLayoutValidator(),
|
ValidateDiagFunc: validator.KeyboardLayout(),
|
||||||
},
|
},
|
||||||
mkResourceVirtualEnvironmentVMMachine: {
|
mkResourceVirtualEnvironmentVMMachine: {
|
||||||
Type: schema.TypeString,
|
Type: schema.TypeString,
|
||||||
@ -1084,14 +1086,14 @@ func VM() *schema.Resource {
|
|||||||
Description: "The MAC address",
|
Description: "The MAC address",
|
||||||
Optional: true,
|
Optional: true,
|
||||||
Computed: true,
|
Computed: true,
|
||||||
ValidateDiagFunc: getMACAddressValidator(),
|
ValidateDiagFunc: validator.MACAddress(),
|
||||||
},
|
},
|
||||||
mkResourceVirtualEnvironmentVMNetworkDeviceModel: {
|
mkResourceVirtualEnvironmentVMNetworkDeviceModel: {
|
||||||
Type: schema.TypeString,
|
Type: schema.TypeString,
|
||||||
Description: "The model",
|
Description: "The model",
|
||||||
Optional: true,
|
Optional: true,
|
||||||
Default: dvResourceVirtualEnvironmentVMNetworkDeviceModel,
|
Default: dvResourceVirtualEnvironmentVMNetworkDeviceModel,
|
||||||
ValidateDiagFunc: getNetworkDeviceModelValidator(),
|
ValidateDiagFunc: validator.NetworkDeviceModel(),
|
||||||
},
|
},
|
||||||
mkResourceVirtualEnvironmentVMNetworkDeviceRateLimit: {
|
mkResourceVirtualEnvironmentVMNetworkDeviceRateLimit: {
|
||||||
Type: schema.TypeFloat,
|
Type: schema.TypeFloat,
|
||||||
@ -1208,7 +1210,7 @@ func VM() *schema.Resource {
|
|||||||
Type: schema.TypeString,
|
Type: schema.TypeString,
|
||||||
ValidateFunc: validation.StringIsNotEmpty,
|
ValidateFunc: validation.StringIsNotEmpty,
|
||||||
},
|
},
|
||||||
DiffSuppressFunc: suppressIfListsAreEqualIgnoringOrder,
|
DiffSuppressFunc: structure.SuppressIfListsAreEqualIgnoringOrder,
|
||||||
DiffSuppressOnRefresh: true,
|
DiffSuppressOnRefresh: true,
|
||||||
},
|
},
|
||||||
mkResourceVirtualEnvironmentVMTemplate: {
|
mkResourceVirtualEnvironmentVMTemplate: {
|
||||||
@ -1280,14 +1282,14 @@ func VM() *schema.Resource {
|
|||||||
Description: "The VGA memory in megabytes (4-512 MB)",
|
Description: "The VGA memory in megabytes (4-512 MB)",
|
||||||
Optional: true,
|
Optional: true,
|
||||||
Default: dvResourceVirtualEnvironmentVMVGAMemory,
|
Default: dvResourceVirtualEnvironmentVMVGAMemory,
|
||||||
ValidateDiagFunc: getVGAMemoryValidator(),
|
ValidateDiagFunc: validator.VGAMemory(),
|
||||||
},
|
},
|
||||||
mkResourceVirtualEnvironmentVMVGAType: {
|
mkResourceVirtualEnvironmentVMVGAType: {
|
||||||
Type: schema.TypeString,
|
Type: schema.TypeString,
|
||||||
Description: "The VGA type",
|
Description: "The VGA type",
|
||||||
Optional: true,
|
Optional: true,
|
||||||
Default: dvResourceVirtualEnvironmentVMVGAType,
|
Default: dvResourceVirtualEnvironmentVMVGAType,
|
||||||
ValidateDiagFunc: getVGATypeValidator(),
|
ValidateDiagFunc: validator.VGAType(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -1308,7 +1310,7 @@ func VM() *schema.Resource {
|
|||||||
Description: "The SCSI hardware type",
|
Description: "The SCSI hardware type",
|
||||||
Optional: true,
|
Optional: true,
|
||||||
Default: dvResourceVirtualEnvironmentVMSCSIHardware,
|
Default: dvResourceVirtualEnvironmentVMSCSIHardware,
|
||||||
ValidateDiagFunc: getSCSIHardwareValidator(),
|
ValidateDiagFunc: validator.SCSIHardware(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
CreateContext: vmCreate,
|
CreateContext: vmCreate,
|
||||||
@ -1975,7 +1977,7 @@ func vmCreateCustom(ctx context.Context, d *schema.ResourceData, m interface{})
|
|||||||
|
|
||||||
acpi := types.CustomBool(d.Get(mkResourceVirtualEnvironmentVMACPI).(bool))
|
acpi := types.CustomBool(d.Get(mkResourceVirtualEnvironmentVMACPI).(bool))
|
||||||
|
|
||||||
agentBlock, err := getSchemaBlock(
|
agentBlock, err := structure.GetSchemaBlock(
|
||||||
resource,
|
resource,
|
||||||
d,
|
d,
|
||||||
[]string{mkResourceVirtualEnvironmentVMAgent},
|
[]string{mkResourceVirtualEnvironmentVMAgent},
|
||||||
@ -1998,7 +2000,7 @@ func vmCreateCustom(ctx context.Context, d *schema.ResourceData, m interface{})
|
|||||||
|
|
||||||
bios := d.Get(mkResourceVirtualEnvironmentVMBIOS).(string)
|
bios := d.Get(mkResourceVirtualEnvironmentVMBIOS).(string)
|
||||||
|
|
||||||
cdromBlock, err := getSchemaBlock(
|
cdromBlock, err := structure.GetSchemaBlock(
|
||||||
resource,
|
resource,
|
||||||
d,
|
d,
|
||||||
[]string{mkResourceVirtualEnvironmentVMCDROM},
|
[]string{mkResourceVirtualEnvironmentVMCDROM},
|
||||||
@ -2020,7 +2022,7 @@ func vmCreateCustom(ctx context.Context, d *schema.ResourceData, m interface{})
|
|||||||
cdromFileID = "cdrom"
|
cdromFileID = "cdrom"
|
||||||
}
|
}
|
||||||
|
|
||||||
cpuBlock, err := getSchemaBlock(
|
cpuBlock, err := structure.GetSchemaBlock(
|
||||||
resource,
|
resource,
|
||||||
d,
|
d,
|
||||||
[]string{mkResourceVirtualEnvironmentVMCPU},
|
[]string{mkResourceVirtualEnvironmentVMCPU},
|
||||||
@ -2088,7 +2090,7 @@ func vmCreateCustom(ctx context.Context, d *schema.ResourceData, m interface{})
|
|||||||
pciDeviceObjects := vmGetHostPCIDeviceObjects(d)
|
pciDeviceObjects := vmGetHostPCIDeviceObjects(d)
|
||||||
|
|
||||||
keyboardLayout := d.Get(mkResourceVirtualEnvironmentVMKeyboardLayout).(string)
|
keyboardLayout := d.Get(mkResourceVirtualEnvironmentVMKeyboardLayout).(string)
|
||||||
memoryBlock, err := getSchemaBlock(
|
memoryBlock, err := structure.GetSchemaBlock(
|
||||||
resource,
|
resource,
|
||||||
d,
|
d,
|
||||||
[]string{mkResourceVirtualEnvironmentVMMemory},
|
[]string{mkResourceVirtualEnvironmentVMMemory},
|
||||||
@ -2111,7 +2113,7 @@ func vmCreateCustom(ctx context.Context, d *schema.ResourceData, m interface{})
|
|||||||
|
|
||||||
nodeName := d.Get(mkResourceVirtualEnvironmentVMNodeName).(string)
|
nodeName := d.Get(mkResourceVirtualEnvironmentVMNodeName).(string)
|
||||||
|
|
||||||
operatingSystem, err := getSchemaBlock(
|
operatingSystem, err := structure.GetSchemaBlock(
|
||||||
resource,
|
resource,
|
||||||
d,
|
d,
|
||||||
[]string{mkResourceVirtualEnvironmentVMOperatingSystem},
|
[]string{mkResourceVirtualEnvironmentVMOperatingSystem},
|
||||||
@ -2721,7 +2723,7 @@ func vmGetDiskDeviceObjects(
|
|||||||
ssd := types.CustomBool(block[mkResourceVirtualEnvironmentVMDiskSSD].(bool))
|
ssd := types.CustomBool(block[mkResourceVirtualEnvironmentVMDiskSSD].(bool))
|
||||||
discard := block[mkResourceVirtualEnvironmentVMDiskDiscard].(string)
|
discard := block[mkResourceVirtualEnvironmentVMDiskDiscard].(string)
|
||||||
|
|
||||||
speedBlock, err := getSchemaBlock(
|
speedBlock, err := structure.GetSchemaBlock(
|
||||||
resource,
|
resource,
|
||||||
d,
|
d,
|
||||||
[]string{mkResourceVirtualEnvironmentVMDisk, mkResourceVirtualEnvironmentVMDiskSpeed},
|
[]string{mkResourceVirtualEnvironmentVMDisk, mkResourceVirtualEnvironmentVMDiskSpeed},
|
||||||
@ -3016,7 +3018,7 @@ func vmGetSerialDeviceValidator() schema.SchemaValidateDiagFunc {
|
|||||||
func vmGetVGADeviceObject(d *schema.ResourceData) (*vms.CustomVGADevice, error) {
|
func vmGetVGADeviceObject(d *schema.ResourceData) (*vms.CustomVGADevice, error) {
|
||||||
resource := VM()
|
resource := VM()
|
||||||
|
|
||||||
vgaBlock, err := getSchemaBlock(
|
vgaBlock, err := structure.GetSchemaBlock(
|
||||||
resource,
|
resource,
|
||||||
d,
|
d,
|
||||||
[]string{mkResourceVirtualEnvironmentVMVGA},
|
[]string{mkResourceVirtualEnvironmentVMVGA},
|
||||||
@ -4126,7 +4128,7 @@ func vmReadNetworkValues(
|
|||||||
if started {
|
if started {
|
||||||
if vmConfig.Agent != nil && vmConfig.Agent.Enabled != nil && *vmConfig.Agent.Enabled {
|
if vmConfig.Agent != nil && vmConfig.Agent.Enabled != nil && *vmConfig.Agent.Enabled {
|
||||||
resource := VM()
|
resource := VM()
|
||||||
agentBlock, err := getSchemaBlock(
|
agentBlock, err := structure.GetSchemaBlock(
|
||||||
resource,
|
resource,
|
||||||
d,
|
d,
|
||||||
[]string{mkResourceVirtualEnvironmentVMAgent},
|
[]string{mkResourceVirtualEnvironmentVMAgent},
|
||||||
@ -4453,7 +4455,7 @@ func vmUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.D
|
|||||||
|
|
||||||
// Prepare the new agent configuration.
|
// Prepare the new agent configuration.
|
||||||
if d.HasChange(mkResourceVirtualEnvironmentVMAgent) {
|
if d.HasChange(mkResourceVirtualEnvironmentVMAgent) {
|
||||||
agentBlock, err := getSchemaBlock(
|
agentBlock, err := structure.GetSchemaBlock(
|
||||||
resource,
|
resource,
|
||||||
d,
|
d,
|
||||||
[]string{mkResourceVirtualEnvironmentVMAgent},
|
[]string{mkResourceVirtualEnvironmentVMAgent},
|
||||||
@ -4513,7 +4515,7 @@ func vmUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.D
|
|||||||
|
|
||||||
// Prepare the new CD-ROM configuration.
|
// Prepare the new CD-ROM configuration.
|
||||||
if d.HasChange(mkResourceVirtualEnvironmentVMCDROM) {
|
if d.HasChange(mkResourceVirtualEnvironmentVMCDROM) {
|
||||||
cdromBlock, err := getSchemaBlock(
|
cdromBlock, err := structure.GetSchemaBlock(
|
||||||
resource,
|
resource,
|
||||||
d,
|
d,
|
||||||
[]string{mkResourceVirtualEnvironmentVMCDROM},
|
[]string{mkResourceVirtualEnvironmentVMCDROM},
|
||||||
@ -4564,7 +4566,7 @@ func vmUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.D
|
|||||||
|
|
||||||
// Prepare the new CPU configuration.
|
// Prepare the new CPU configuration.
|
||||||
if d.HasChange(mkResourceVirtualEnvironmentVMCPU) {
|
if d.HasChange(mkResourceVirtualEnvironmentVMCPU) {
|
||||||
cpuBlock, err := getSchemaBlock(
|
cpuBlock, err := structure.GetSchemaBlock(
|
||||||
resource,
|
resource,
|
||||||
d,
|
d,
|
||||||
[]string{mkResourceVirtualEnvironmentVMCPU},
|
[]string{mkResourceVirtualEnvironmentVMCPU},
|
||||||
@ -4726,7 +4728,7 @@ func vmUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.D
|
|||||||
|
|
||||||
// Prepare the new memory configuration.
|
// Prepare the new memory configuration.
|
||||||
if d.HasChange(mkResourceVirtualEnvironmentVMMemory) {
|
if d.HasChange(mkResourceVirtualEnvironmentVMMemory) {
|
||||||
memoryBlock, err := getSchemaBlock(
|
memoryBlock, err := structure.GetSchemaBlock(
|
||||||
resource,
|
resource,
|
||||||
d,
|
d,
|
||||||
[]string{mkResourceVirtualEnvironmentVMMemory},
|
[]string{mkResourceVirtualEnvironmentVMMemory},
|
||||||
@ -4775,7 +4777,7 @@ func vmUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.D
|
|||||||
|
|
||||||
// Prepare the new operating system configuration.
|
// Prepare the new operating system configuration.
|
||||||
if d.HasChange(mkResourceVirtualEnvironmentVMOperatingSystem) {
|
if d.HasChange(mkResourceVirtualEnvironmentVMOperatingSystem) {
|
||||||
operatingSystem, err := getSchemaBlock(
|
operatingSystem, err := structure.GetSchemaBlock(
|
||||||
resource,
|
resource,
|
||||||
d,
|
d,
|
||||||
[]string{mkResourceVirtualEnvironmentVMOperatingSystem},
|
[]string{mkResourceVirtualEnvironmentVMOperatingSystem},
|
||||||
@ -5112,3 +5114,138 @@ func vmDelete(ctx context.Context, d *schema.ResourceData, m interface{}) diag.D
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func diskDigitPrefix(s string) string {
|
||||||
|
for i, r := range s {
|
||||||
|
if unicode.IsDigit(r) {
|
||||||
|
return s[:i]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
func getDiskInfo(resp *vms.GetResponseData, d *schema.ResourceData) map[string]*vms.CustomStorageDevice {
|
||||||
|
currentDisk := d.Get(mkResourceVirtualEnvironmentVMDisk)
|
||||||
|
|
||||||
|
currentDiskList := currentDisk.([]interface{})
|
||||||
|
currentDiskMap := map[string]map[string]interface{}{}
|
||||||
|
|
||||||
|
for _, v := range currentDiskList {
|
||||||
|
diskMap := v.(map[string]interface{})
|
||||||
|
diskInterface := diskMap[mkResourceVirtualEnvironmentVMDiskInterface].(string)
|
||||||
|
|
||||||
|
currentDiskMap[diskInterface] = diskMap
|
||||||
|
}
|
||||||
|
|
||||||
|
storageDevices := map[string]*vms.CustomStorageDevice{}
|
||||||
|
|
||||||
|
storageDevices["ide0"] = resp.IDEDevice0
|
||||||
|
storageDevices["ide1"] = resp.IDEDevice1
|
||||||
|
storageDevices["ide2"] = resp.IDEDevice2
|
||||||
|
storageDevices["ide3"] = resp.IDEDevice3
|
||||||
|
|
||||||
|
storageDevices["sata0"] = resp.SATADevice0
|
||||||
|
storageDevices["sata1"] = resp.SATADevice1
|
||||||
|
storageDevices["sata2"] = resp.SATADevice2
|
||||||
|
storageDevices["sata3"] = resp.SATADevice3
|
||||||
|
storageDevices["sata4"] = resp.SATADevice4
|
||||||
|
storageDevices["sata5"] = resp.SATADevice5
|
||||||
|
|
||||||
|
storageDevices["scsi0"] = resp.SCSIDevice0
|
||||||
|
storageDevices["scsi1"] = resp.SCSIDevice1
|
||||||
|
storageDevices["scsi2"] = resp.SCSIDevice2
|
||||||
|
storageDevices["scsi3"] = resp.SCSIDevice3
|
||||||
|
storageDevices["scsi4"] = resp.SCSIDevice4
|
||||||
|
storageDevices["scsi5"] = resp.SCSIDevice5
|
||||||
|
storageDevices["scsi6"] = resp.SCSIDevice6
|
||||||
|
storageDevices["scsi7"] = resp.SCSIDevice7
|
||||||
|
storageDevices["scsi8"] = resp.SCSIDevice8
|
||||||
|
storageDevices["scsi9"] = resp.SCSIDevice9
|
||||||
|
storageDevices["scsi10"] = resp.SCSIDevice10
|
||||||
|
storageDevices["scsi11"] = resp.SCSIDevice11
|
||||||
|
storageDevices["scsi12"] = resp.SCSIDevice12
|
||||||
|
storageDevices["scsi13"] = resp.SCSIDevice13
|
||||||
|
|
||||||
|
storageDevices["virtio0"] = resp.VirtualIODevice0
|
||||||
|
storageDevices["virtio1"] = resp.VirtualIODevice1
|
||||||
|
storageDevices["virtio2"] = resp.VirtualIODevice2
|
||||||
|
storageDevices["virtio3"] = resp.VirtualIODevice3
|
||||||
|
storageDevices["virtio4"] = resp.VirtualIODevice4
|
||||||
|
storageDevices["virtio5"] = resp.VirtualIODevice5
|
||||||
|
storageDevices["virtio6"] = resp.VirtualIODevice6
|
||||||
|
storageDevices["virtio7"] = resp.VirtualIODevice7
|
||||||
|
storageDevices["virtio8"] = resp.VirtualIODevice8
|
||||||
|
storageDevices["virtio9"] = resp.VirtualIODevice9
|
||||||
|
storageDevices["virtio10"] = resp.VirtualIODevice10
|
||||||
|
storageDevices["virtio11"] = resp.VirtualIODevice11
|
||||||
|
storageDevices["virtio12"] = resp.VirtualIODevice12
|
||||||
|
storageDevices["virtio13"] = resp.VirtualIODevice13
|
||||||
|
storageDevices["virtio14"] = resp.VirtualIODevice14
|
||||||
|
storageDevices["virtio15"] = resp.VirtualIODevice15
|
||||||
|
|
||||||
|
for k, v := range storageDevices {
|
||||||
|
if v != nil {
|
||||||
|
if currentDiskMap[k] != nil {
|
||||||
|
if currentDiskMap[k][mkResourceVirtualEnvironmentVMDiskFileID] != nil {
|
||||||
|
fileID := currentDiskMap[k][mkResourceVirtualEnvironmentVMDiskFileID].(string)
|
||||||
|
v.FileID = &fileID
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// defensive copy of the loop variable
|
||||||
|
iface := k
|
||||||
|
v.Interface = &iface
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return storageDevices
|
||||||
|
}
|
||||||
|
|
||||||
|
// getDiskDatastores returns a list of the used datastores in a VM.
|
||||||
|
func getDiskDatastores(vm *vms.GetResponseData, d *schema.ResourceData) []string {
|
||||||
|
storageDevices := getDiskInfo(vm, d)
|
||||||
|
datastoresSet := map[string]int{}
|
||||||
|
|
||||||
|
for _, diskInfo := range storageDevices {
|
||||||
|
// Ignore empty storage devices and storage devices (like ide) which may not have any media mounted
|
||||||
|
if diskInfo == nil || diskInfo.FileVolume == "none" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
fileIDParts := strings.Split(diskInfo.FileVolume, ":")
|
||||||
|
datastoresSet[fileIDParts[0]] = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
if vm.EFIDisk != nil {
|
||||||
|
fileIDParts := strings.Split(vm.EFIDisk.FileVolume, ":")
|
||||||
|
datastoresSet[fileIDParts[0]] = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
datastores := []string{}
|
||||||
|
for datastore := range datastoresSet {
|
||||||
|
datastores = append(datastores, datastore)
|
||||||
|
}
|
||||||
|
|
||||||
|
return datastores
|
||||||
|
}
|
||||||
|
|
||||||
|
func getPCIInfo(resp *vms.GetResponseData, _ *schema.ResourceData) map[string]*vms.CustomPCIDevice {
|
||||||
|
pciDevices := map[string]*vms.CustomPCIDevice{}
|
||||||
|
|
||||||
|
pciDevices["hostpci0"] = resp.PCIDevice0
|
||||||
|
pciDevices["hostpci1"] = resp.PCIDevice1
|
||||||
|
pciDevices["hostpci2"] = resp.PCIDevice2
|
||||||
|
pciDevices["hostpci3"] = resp.PCIDevice3
|
||||||
|
|
||||||
|
return pciDevices
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseImportIDWithNodeName(id string) (string, string, error) {
|
||||||
|
nodeName, id, found := strings.Cut(id, "/")
|
||||||
|
|
||||||
|
if !found {
|
||||||
|
return "", "", fmt.Errorf("unexpected format of ID (%s), expected node/id", id)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nodeName, id, nil
|
||||||
|
}
|
||||||
|
@ -10,6 +10,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
|
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
"github.com/bpg/terraform-provider-proxmox/proxmoxtf/test"
|
"github.com/bpg/terraform-provider-proxmox/proxmoxtf/test"
|
||||||
)
|
)
|
||||||
@ -437,3 +438,38 @@ func TestVMSchema(t *testing.T) {
|
|||||||
mkResourceVirtualEnvironmentVMVGAType: schema.TypeString,
|
mkResourceVirtualEnvironmentVMVGAType: schema.TypeString,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Test_parseImportIDWIthNodeName(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
value string
|
||||||
|
valid bool
|
||||||
|
expectedNodeName string
|
||||||
|
expectedID string
|
||||||
|
}{
|
||||||
|
{"empty", "", false, "", ""},
|
||||||
|
{"missing slash", "invalid", false, "", ""},
|
||||||
|
{"valid", "host/id", true, "host", "id"},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
tt := tt
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
require := require.New(t)
|
||||||
|
|
||||||
|
nodeName, id, err := parseImportIDWithNodeName(tt.value)
|
||||||
|
|
||||||
|
if !tt.valid {
|
||||||
|
require.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
require.Nil(err)
|
||||||
|
require.Equal(tt.expectedNodeName, nodeName)
|
||||||
|
require.Equal(tt.expectedID, id)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
122
proxmoxtf/structure/schema.go
Normal file
122
proxmoxtf/structure/schema.go
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
/*
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package structure
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"reflect"
|
||||||
|
"sort"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
|
||||||
|
)
|
||||||
|
|
||||||
|
// MergeSchema merges the map[string]*schema.Schema from src into dst. Safety
|
||||||
|
// against conflicts is enforced by panicking.
|
||||||
|
func MergeSchema(dst, src map[string]*schema.Schema) {
|
||||||
|
for k, v := range src {
|
||||||
|
if _, ok := dst[k]; ok {
|
||||||
|
panic(fmt.Errorf("conflicting schema key: %s", k))
|
||||||
|
}
|
||||||
|
|
||||||
|
dst[k] = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetSchemaBlock returns a map[string]interface{} of a nested resource by key(s) from a schema.ResourceData.
|
||||||
|
func GetSchemaBlock(
|
||||||
|
r *schema.Resource,
|
||||||
|
d *schema.ResourceData,
|
||||||
|
k []string,
|
||||||
|
i int,
|
||||||
|
allowDefault bool,
|
||||||
|
) (map[string]interface{}, error) {
|
||||||
|
var resourceBlock map[string]interface{}
|
||||||
|
|
||||||
|
var resourceData interface{}
|
||||||
|
|
||||||
|
var resourceSchema *schema.Schema
|
||||||
|
|
||||||
|
for ki, kv := range k {
|
||||||
|
if ki == 0 {
|
||||||
|
resourceData = d.Get(kv)
|
||||||
|
resourceSchema = r.Schema[kv]
|
||||||
|
} else {
|
||||||
|
mapValues := resourceData.([]interface{})
|
||||||
|
|
||||||
|
if len(mapValues) <= i {
|
||||||
|
return resourceBlock, fmt.Errorf("index out of bounds %d", i)
|
||||||
|
}
|
||||||
|
|
||||||
|
mapValue := mapValues[i].(map[string]interface{})
|
||||||
|
|
||||||
|
resourceData = mapValue[kv]
|
||||||
|
resourceSchema = resourceSchema.Elem.(*schema.Resource).Schema[kv]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
list := resourceData.([]interface{})
|
||||||
|
|
||||||
|
if len(list) == 0 {
|
||||||
|
if allowDefault {
|
||||||
|
listDefault, err := resourceSchema.DefaultValue()
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to get default value for %s: %w", strings.Join(k, "."), err)
|
||||||
|
}
|
||||||
|
|
||||||
|
list = listDefault.([]interface{})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(list) > i {
|
||||||
|
resourceBlock = list[i].(map[string]interface{})
|
||||||
|
}
|
||||||
|
|
||||||
|
return resourceBlock, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SuppressIfListsAreEqualIgnoringOrder is a customdiff.SuppressionFunc that suppresses
|
||||||
|
// changes to a list if the old and new lists are equal, ignoring the order of the
|
||||||
|
// elements.
|
||||||
|
// It will be called for each list item, so it is not super efficient. It is
|
||||||
|
// recommended to use it only for small lists.
|
||||||
|
// Ref: https://github.com/hashicorp/terraform-plugin-sdk/issues/477
|
||||||
|
func SuppressIfListsAreEqualIgnoringOrder(key, _, _ string, d *schema.ResourceData) bool {
|
||||||
|
// the key is a path to the list item, not the list itself, e.g. "tags.0"
|
||||||
|
lastDotIndex := strings.LastIndex(key, ".")
|
||||||
|
if lastDotIndex != -1 {
|
||||||
|
key = key[:lastDotIndex]
|
||||||
|
}
|
||||||
|
|
||||||
|
oldData, newData := d.GetChange(key)
|
||||||
|
if oldData == nil || newData == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
oldArray := oldData.([]interface{})
|
||||||
|
newArray := newData.([]interface{})
|
||||||
|
|
||||||
|
if len(oldArray) != len(newArray) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
oldEvents := make([]string, len(oldArray))
|
||||||
|
newEvents := make([]string, len(newArray))
|
||||||
|
|
||||||
|
for i, oldEvt := range oldArray {
|
||||||
|
oldEvents[i] = fmt.Sprint(oldEvt)
|
||||||
|
}
|
||||||
|
|
||||||
|
for j, newEvt := range newArray {
|
||||||
|
newEvents[j] = fmt.Sprint(newEvt)
|
||||||
|
}
|
||||||
|
|
||||||
|
sort.Strings(oldEvents)
|
||||||
|
sort.Strings(newEvents)
|
||||||
|
|
||||||
|
return reflect.DeepEqual(oldEvents, newEvents)
|
||||||
|
}
|
@ -1,70 +0,0 @@
|
|||||||
/*
|
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
||||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package structure
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
"github.com/stretchr/testify/require"
|
|
||||||
)
|
|
||||||
|
|
||||||
// AssertComputedAttributes asserts that the given keys are present in the schema and are computed.
|
|
||||||
func AssertComputedAttributes(t *testing.T, s map[string]*schema.Schema, keys []string) {
|
|
||||||
t.Helper()
|
|
||||||
|
|
||||||
for _, v := range keys {
|
|
||||||
require.NotNil(t, s[v], "Error in Schema: Missing definition for \"%s\"", v)
|
|
||||||
assert.True(t, s[v].Computed, "Error in Schema: Attribute \"%s\" is not computed", v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// AssertNestedSchemaExistence asserts that the given key is present in the schema and is a nested schema.
|
|
||||||
func AssertNestedSchemaExistence(t *testing.T, s map[string]*schema.Schema, key string) *schema.Resource {
|
|
||||||
t.Helper()
|
|
||||||
|
|
||||||
sh, ok := s[key].Elem.(*schema.Resource)
|
|
||||||
|
|
||||||
if !ok {
|
|
||||||
t.Fatalf("Error in Schema: Missing nested schema for \"%s\"", key)
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return sh
|
|
||||||
}
|
|
||||||
|
|
||||||
// AssertOptionalArguments asserts that the given keys are present in the schema and are optional.
|
|
||||||
func AssertOptionalArguments(t *testing.T, s map[string]*schema.Schema, keys []string) {
|
|
||||||
t.Helper()
|
|
||||||
|
|
||||||
for _, v := range keys {
|
|
||||||
require.NotNil(t, s[v], "Error in Schema: Missing definition for \"%s\"", v)
|
|
||||||
assert.True(t, s[v].Optional, "Error in Schema: Argument \"%s\" is not optional", v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// AssertRequiredArguments asserts that the given keys are present in the schema and are required.
|
|
||||||
func AssertRequiredArguments(t *testing.T, s map[string]*schema.Schema, keys []string) {
|
|
||||||
t.Helper()
|
|
||||||
|
|
||||||
for _, v := range keys {
|
|
||||||
require.NotNil(t, s[v], "Error in Schema: Missing definition for \"%s\"", v)
|
|
||||||
assert.True(t, s[v].Required, "Error in Schema: Argument \"%s\" is not required", v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// AssertValueTypes asserts that the given keys are present in the schema and are of the given type.
|
|
||||||
func AssertValueTypes(t *testing.T, s map[string]*schema.Schema, f map[string]schema.ValueType) {
|
|
||||||
t.Helper()
|
|
||||||
|
|
||||||
for fn, ft := range f {
|
|
||||||
require.NotNil(t, s[fn], "Error in Schema: Missing definition for \"%s\"", fn)
|
|
||||||
assert.Equal(t, ft, s[fn].Type, "Error in Schema: Argument or attribute \"%s\" is not of type \"%v\"", fn, ft)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,25 +0,0 @@
|
|||||||
/*
|
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
||||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package structure
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
|
|
||||||
)
|
|
||||||
|
|
||||||
// MergeSchema merges the map[string]*schema.Schema from src into dst. Safety
|
|
||||||
// against conflicts is enforced by panicking.
|
|
||||||
func MergeSchema(dst, src map[string]*schema.Schema) {
|
|
||||||
for k, v := range src {
|
|
||||||
if _, ok := dst[k]; ok {
|
|
||||||
panic(fmt.Errorf("conflicting schema key: %s", k))
|
|
||||||
}
|
|
||||||
|
|
||||||
dst[k] = v
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user