fix: state drift of "stackit_server" (#679)
* fix: State drift of "stackit_server" when using "stackit_server_network_interface_attach" * fix: tests * add acceptance tests for stackit_server_network_interface_attach
This commit is contained in:
parent
3e8dcc542b
commit
b7f56d1685
3 changed files with 172 additions and 22 deletions
|
|
@ -19,6 +19,7 @@ import (
|
|||
const (
|
||||
serverMachineType = "t1.1"
|
||||
updatedServerMachineType = "t1.2"
|
||||
nicAttachTfName = "second_network_interface"
|
||||
)
|
||||
|
||||
// Network resource data
|
||||
|
|
@ -53,6 +54,7 @@ var networkInterfaceResource = map[string]string{
|
|||
"project_id": testutil.ProjectId,
|
||||
"network_id": networkResource["network_id"],
|
||||
"name": "name",
|
||||
"tfName": "network_interface",
|
||||
}
|
||||
|
||||
// Volume resource data
|
||||
|
|
@ -200,14 +202,15 @@ func networkAreaRouteResourceConfig(labelValue string) string {
|
|||
)
|
||||
}
|
||||
|
||||
func networkInterfaceResourceConfig(name string) string {
|
||||
func networkInterfaceResourceConfig(resourceName, name string) string {
|
||||
return fmt.Sprintf(`
|
||||
resource "stackit_network_interface" "network_interface" {
|
||||
resource "stackit_network_interface" "%s" {
|
||||
project_id = stackit_network.network.project_id
|
||||
network_id = stackit_network.network.network_id
|
||||
name = "%s"
|
||||
}
|
||||
`,
|
||||
resourceName,
|
||||
name,
|
||||
)
|
||||
}
|
||||
|
|
@ -355,6 +358,19 @@ func imageResourceConfig(name string) string {
|
|||
)
|
||||
}
|
||||
|
||||
func networkInterfaceAttachmentResourceConfig(nicTfName string) string {
|
||||
return fmt.Sprintf(`
|
||||
resource "stackit_server_network_interface_attach" "attach_nic" {
|
||||
project_id = "%s"
|
||||
server_id = stackit_server.server.server_id
|
||||
network_interface_id = stackit_network_interface.%s.network_interface_id
|
||||
}
|
||||
`,
|
||||
testutil.ProjectId,
|
||||
nicTfName,
|
||||
)
|
||||
}
|
||||
|
||||
func testAccNetworkAreaConfig(areaname, networkranges, routeLabelValue string) string {
|
||||
return fmt.Sprintf("%s\n\n%s\n\n%s",
|
||||
testutil.IaaSProviderConfig(),
|
||||
|
|
@ -370,13 +386,15 @@ func testAccVolumeConfig(name, size string) string {
|
|||
)
|
||||
}
|
||||
|
||||
func testAccServerConfig(name, nameservers, serverName, machineType, interfacename string) string {
|
||||
return fmt.Sprintf("%s\n\n%s\n\n%s\n\n%s\n\n%s\n\n%s\n\n%s",
|
||||
func testAccServerConfig(name, nameservers, serverName, machineType, nicTfName, interfacename string) string {
|
||||
return fmt.Sprintf("%s\n\n%s\n\n%s\n\n%s\n\n%s\n\n%s\n\n%s\n\n%s\n\n%s",
|
||||
testutil.IaaSProviderConfig(),
|
||||
networkResourceConfig(name, nameservers),
|
||||
serverResourceConfig(serverName, machineType),
|
||||
volumeResourceConfig(volumeResource["name"], volumeResource["size"]),
|
||||
networkInterfaceResourceConfig(interfacename),
|
||||
networkInterfaceResourceConfig(nicTfName, interfacename),
|
||||
networkInterfaceResourceConfig(nicAttachTfName, fmt.Sprintf("%s-%s", interfacename, nicAttachTfName)),
|
||||
networkInterfaceAttachmentResourceConfig(nicAttachTfName),
|
||||
volumeAttachmentResourceConfig(),
|
||||
serviceAccountAttachmentResourceConfig(),
|
||||
)
|
||||
|
|
@ -390,11 +408,11 @@ func resourceConfigSecurityGroup(name, direction string) string {
|
|||
)
|
||||
}
|
||||
|
||||
func testAccPublicIpConfig(nameNetwork, nameservers, nameNetworkInterface, publicIpResourceConfig string) string {
|
||||
func testAccPublicIpConfig(nameNetwork, nameservers, nicTfName, nameNetworkInterface, publicIpResourceConfig string) string {
|
||||
return fmt.Sprintf("%s\n\n%s\n\n%s\n\n%s",
|
||||
testutil.IaaSProviderConfig(),
|
||||
networkResourceConfigRouted(nameNetwork, nameservers),
|
||||
networkInterfaceResourceConfig(nameNetworkInterface),
|
||||
networkInterfaceResourceConfig(nicTfName, nameNetworkInterface),
|
||||
publicIpResourceConfig,
|
||||
)
|
||||
}
|
||||
|
|
@ -659,6 +677,7 @@ func TestAccVolume(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestAccServer(t *testing.T) {
|
||||
networkInterfaceSecSchemaName := fmt.Sprintf("stackit_network_interface.%s", nicAttachTfName)
|
||||
resource.Test(t, resource.TestCase{
|
||||
ProtoV6ProviderFactories: testutil.TestAccProtoV6ProviderFactories,
|
||||
CheckDestroy: testAccCheckServerDestroy,
|
||||
|
|
@ -674,6 +693,7 @@ func TestAccServer(t *testing.T) {
|
|||
),
|
||||
serverResource["name"],
|
||||
serverResource["machine_type"],
|
||||
networkInterfaceResource["tfName"],
|
||||
networkInterfaceResource["name"],
|
||||
),
|
||||
Check: resource.ComposeAggregateTestCheckFunc(
|
||||
|
|
@ -697,6 +717,9 @@ func TestAccServer(t *testing.T) {
|
|||
resource.TestCheckResourceAttr("stackit_server.server", "labels.label1", serverResource["label1"]),
|
||||
resource.TestCheckResourceAttr("stackit_server.server", "user_data", serverResource["user_data"]),
|
||||
resource.TestCheckResourceAttrSet("stackit_server.server", "network_interfaces.0"),
|
||||
// The network interface which was attached by "stackit_server_network_interface_attach" should not appear here
|
||||
resource.TestCheckResourceAttr("stackit_server.server", "network_interfaces.#", "1"),
|
||||
resource.TestCheckNoResourceAttr("stackit_server.server", "network_interfaces.1"),
|
||||
resource.TestCheckResourceAttr("stackit_server.server", "boot_volume.size", serverResource["size"]),
|
||||
resource.TestCheckResourceAttr("stackit_server.server", "boot_volume.source_type", serverResource["source_type"]),
|
||||
resource.TestCheckResourceAttr("stackit_server.server", "boot_volume.source_id", serverResource["source_id"]),
|
||||
|
|
@ -714,6 +737,35 @@ func TestAccServer(t *testing.T) {
|
|||
resource.TestCheckResourceAttrSet("stackit_network_interface.network_interface", "network_interface_id"),
|
||||
resource.TestCheckResourceAttr("stackit_network_interface.network_interface", "name", networkInterfaceResource["name"]),
|
||||
|
||||
// Network Interface second
|
||||
resource.TestCheckResourceAttrPair(
|
||||
networkInterfaceSecSchemaName, "project_id",
|
||||
"stackit_network.network", "project_id",
|
||||
),
|
||||
resource.TestCheckResourceAttrPair(
|
||||
networkInterfaceSecSchemaName, "network_id",
|
||||
"stackit_network.network", "network_id",
|
||||
),
|
||||
resource.TestCheckResourceAttrSet(networkInterfaceSecSchemaName, "network_interface_id"),
|
||||
resource.TestCheckResourceAttr(
|
||||
networkInterfaceSecSchemaName, "name",
|
||||
fmt.Sprintf("%s-%s", networkInterfaceResource["name"], nicAttachTfName),
|
||||
),
|
||||
|
||||
// Network Interface Attachment
|
||||
resource.TestCheckResourceAttrPair(
|
||||
"stackit_server_network_interface_attach.attach_nic", "project_id",
|
||||
"stackit_network.network", "project_id",
|
||||
),
|
||||
resource.TestCheckResourceAttrPair(
|
||||
"stackit_server_network_interface_attach.attach_nic", "server_id",
|
||||
"stackit_server.server", "server_id",
|
||||
),
|
||||
resource.TestCheckResourceAttrPair(
|
||||
"stackit_server_network_interface_attach.attach_nic", "network_interface_id",
|
||||
networkInterfaceSecSchemaName, "network_interface_id",
|
||||
),
|
||||
|
||||
// Volume attachment
|
||||
resource.TestCheckResourceAttrPair(
|
||||
"stackit_server_volume_attach.attach_volume", "project_id",
|
||||
|
|
@ -768,6 +820,7 @@ func TestAccServer(t *testing.T) {
|
|||
),
|
||||
serverResource["name"],
|
||||
serverResource["machine_type"],
|
||||
networkInterfaceResource["tfName"],
|
||||
networkInterfaceResource["name"],
|
||||
),
|
||||
),
|
||||
|
|
@ -840,7 +893,7 @@ func TestAccServer(t *testing.T) {
|
|||
},
|
||||
ImportState: true,
|
||||
ImportStateVerify: true,
|
||||
ImportStateVerifyIgnore: []string{"boot_volume", "user_data"}, // Field is not mapped as it is only relevant on creation
|
||||
ImportStateVerifyIgnore: []string{"boot_volume", "user_data", "network_interfaces"}, // Field is not mapped as it is only relevant on creation
|
||||
},
|
||||
{
|
||||
ResourceName: "stackit_network_interface.network_interface",
|
||||
|
|
@ -862,6 +915,46 @@ func TestAccServer(t *testing.T) {
|
|||
ImportState: true,
|
||||
ImportStateVerify: true,
|
||||
},
|
||||
{
|
||||
ResourceName: networkInterfaceSecSchemaName,
|
||||
ImportStateIdFunc: func(s *terraform.State) (string, error) {
|
||||
r, ok := s.RootModule().Resources[networkInterfaceSecSchemaName]
|
||||
if !ok {
|
||||
return "", fmt.Errorf("couldn't find resource stackit_network_interface.%s", nicAttachTfName)
|
||||
}
|
||||
networkId, ok := r.Primary.Attributes["network_id"]
|
||||
if !ok {
|
||||
return "", fmt.Errorf("couldn't find attribute network_id")
|
||||
}
|
||||
networkInterfaceId, ok := r.Primary.Attributes["network_interface_id"]
|
||||
if !ok {
|
||||
return "", fmt.Errorf("couldn't find attribute network_interface_id")
|
||||
}
|
||||
return fmt.Sprintf("%s,%s,%s", testutil.ProjectId, networkId, networkInterfaceId), nil
|
||||
},
|
||||
ImportState: true,
|
||||
ImportStateVerify: true,
|
||||
},
|
||||
{
|
||||
ResourceName: "stackit_server_network_interface_attach.attach_nic",
|
||||
ImportStateIdFunc: func(s *terraform.State) (string, error) {
|
||||
r, ok := s.RootModule().Resources["stackit_server_network_interface_attach.attach_nic"]
|
||||
if !ok {
|
||||
return "", fmt.Errorf("couldn't find resource stackit_network_interface.%s", nicAttachTfName)
|
||||
}
|
||||
serverId, ok := r.Primary.Attributes["server_id"]
|
||||
if !ok {
|
||||
return "", fmt.Errorf("couldn't find attribute network_id")
|
||||
}
|
||||
networkInterfaceId, ok := r.Primary.Attributes["network_interface_id"]
|
||||
if !ok {
|
||||
return "", fmt.Errorf("couldn't find attribute network_interface_id")
|
||||
}
|
||||
return fmt.Sprintf("%s,%s,%s", testutil.ProjectId, serverId, networkInterfaceId), nil
|
||||
},
|
||||
ImportState: true,
|
||||
ImportStateVerify: false,
|
||||
},
|
||||
{
|
||||
ResourceName: "stackit_server_volume_attach.attach_volume",
|
||||
ImportStateIdFunc: func(s *terraform.State) (string, error) {
|
||||
|
|
@ -913,6 +1006,7 @@ func TestAccServer(t *testing.T) {
|
|||
),
|
||||
fmt.Sprintf("%s-updated", serverResource["name"]),
|
||||
updatedServerMachineType,
|
||||
networkInterfaceResource["tfName"],
|
||||
fmt.Sprintf("%s-updated", networkInterfaceResource["name"]),
|
||||
),
|
||||
Check: resource.ComposeAggregateTestCheckFunc(
|
||||
|
|
@ -950,6 +1044,35 @@ func TestAccServer(t *testing.T) {
|
|||
),
|
||||
resource.TestCheckResourceAttrSet("stackit_network_interface.network_interface", "network_interface_id"),
|
||||
resource.TestCheckResourceAttr("stackit_network_interface.network_interface", "name", fmt.Sprintf("%s-updated", networkInterfaceResource["name"])),
|
||||
|
||||
// Network Interface second
|
||||
resource.TestCheckResourceAttrPair(
|
||||
networkInterfaceSecSchemaName, "project_id",
|
||||
"stackit_network.network", "project_id",
|
||||
),
|
||||
resource.TestCheckResourceAttrPair(
|
||||
networkInterfaceSecSchemaName, "network_id",
|
||||
"stackit_network.network", "network_id",
|
||||
),
|
||||
resource.TestCheckResourceAttrSet(networkInterfaceSecSchemaName, "network_interface_id"),
|
||||
resource.TestCheckResourceAttr(
|
||||
networkInterfaceSecSchemaName, "name",
|
||||
fmt.Sprintf("%s-%s", fmt.Sprintf("%s-updated", networkInterfaceResource["name"]), nicAttachTfName),
|
||||
),
|
||||
|
||||
// Network Interface Attachment
|
||||
resource.TestCheckResourceAttrPair(
|
||||
"stackit_server_network_interface_attach.attach_nic", "project_id",
|
||||
networkInterfaceSecSchemaName, "project_id",
|
||||
),
|
||||
resource.TestCheckResourceAttrPair(
|
||||
"stackit_server_network_interface_attach.attach_nic", "server_id",
|
||||
"stackit_server.server", "server_id",
|
||||
),
|
||||
resource.TestCheckResourceAttrPair(
|
||||
"stackit_server_network_interface_attach.attach_nic", "network_interface_id",
|
||||
networkInterfaceSecSchemaName, "network_interface_id",
|
||||
),
|
||||
),
|
||||
},
|
||||
// Deletion is done by the framework implicitly
|
||||
|
|
@ -1107,6 +1230,7 @@ func TestAccPublicIp(t *testing.T) {
|
|||
"[%q]",
|
||||
networkResource["nameserver0"],
|
||||
),
|
||||
networkInterfaceResource["tfName"],
|
||||
networkInterfaceResource["name"],
|
||||
fmt.Sprintf(`
|
||||
resource "stackit_public_ip" "public_ip" {
|
||||
|
|
@ -1146,6 +1270,7 @@ func TestAccPublicIp(t *testing.T) {
|
|||
"[%q]",
|
||||
networkResource["nameserver0"],
|
||||
),
|
||||
networkInterfaceResource["tfName"],
|
||||
networkInterfaceResource["name"],
|
||||
fmt.Sprintf(`
|
||||
resource "stackit_public_ip" "public_ip" {
|
||||
|
|
@ -1198,6 +1323,7 @@ func TestAccPublicIp(t *testing.T) {
|
|||
"[%q]",
|
||||
networkResource["nameserver0"],
|
||||
),
|
||||
networkInterfaceResource["tfName"],
|
||||
networkInterfaceResource["name"],
|
||||
fmt.Sprintf(`
|
||||
resource "stackit_public_ip" "public_ip" {
|
||||
|
|
|
|||
|
|
@ -888,12 +888,39 @@ func mapFields(ctx context.Context, serverResp *iaas.Server, model *Model) error
|
|||
for _, nic := range *serverResp.Nics {
|
||||
respNics = append(respNics, *nic.NicId)
|
||||
}
|
||||
nicTF, diags := types.ListValueFrom(ctx, types.StringType, respNics)
|
||||
if diags.HasError() {
|
||||
return fmt.Errorf("failed to map networkInterfaces: %w", core.DiagsToError(diags))
|
||||
|
||||
var modelNics []string
|
||||
for _, modelNic := range model.NetworkInterfaces.Elements() {
|
||||
modelNicString, ok := modelNic.(types.String)
|
||||
if !ok {
|
||||
return fmt.Errorf("type assertion for network interfaces failed")
|
||||
}
|
||||
modelNics = append(modelNics, modelNicString.ValueString())
|
||||
}
|
||||
|
||||
model.NetworkInterfaces = nicTF
|
||||
var filteredNics []string
|
||||
for _, modelNic := range modelNics {
|
||||
for _, nic := range respNics {
|
||||
if nic == modelNic {
|
||||
filteredNics = append(filteredNics, nic)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Sorts the filteredNics based on the modelNics order
|
||||
resultNics := utils.ReconcileStringSlices(modelNics, filteredNics)
|
||||
|
||||
if len(resultNics) != 0 {
|
||||
nicTF, diags := types.ListValueFrom(ctx, types.StringType, resultNics)
|
||||
if diags.HasError() {
|
||||
return fmt.Errorf("failed to map networkInterfaces: %w", core.DiagsToError(diags))
|
||||
}
|
||||
|
||||
model.NetworkInterfaces = nicTF
|
||||
} else {
|
||||
model.NetworkInterfaces = types.ListNull(types.StringType)
|
||||
}
|
||||
} else {
|
||||
model.NetworkInterfaces = types.ListNull(types.StringType)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -98,16 +98,13 @@ func TestMapFields(t *testing.T) {
|
|||
Labels: types.MapValueMust(types.StringType, map[string]attr.Value{
|
||||
"key": types.StringValue("value"),
|
||||
}),
|
||||
ImageId: types.StringValue("image_id"),
|
||||
NetworkInterfaces: types.ListValueMust(types.StringType, []attr.Value{
|
||||
types.StringValue("nic1"),
|
||||
types.StringValue("nic2"),
|
||||
}),
|
||||
KeypairName: types.StringValue("keypair_name"),
|
||||
AffinityGroup: types.StringValue("group_id"),
|
||||
CreatedAt: types.StringValue(testTimestampValue),
|
||||
UpdatedAt: types.StringValue(testTimestampValue),
|
||||
LaunchedAt: types.StringValue(testTimestampValue),
|
||||
ImageId: types.StringValue("image_id"),
|
||||
NetworkInterfaces: types.ListNull(types.StringType),
|
||||
KeypairName: types.StringValue("keypair_name"),
|
||||
AffinityGroup: types.StringValue("group_id"),
|
||||
CreatedAt: types.StringValue(testTimestampValue),
|
||||
UpdatedAt: types.StringValue(testTimestampValue),
|
||||
LaunchedAt: types.StringValue(testTimestampValue),
|
||||
},
|
||||
true,
|
||||
},
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue