Skip to content

Commit

Permalink
feat: Add new virtual IP and virtual IP member resources
Browse files Browse the repository at this point in the history
  • Loading branch information
joaopalet committed Nov 26, 2024
1 parent 1051995 commit 3ca6773
Show file tree
Hide file tree
Showing 10 changed files with 1,598 additions and 22 deletions.
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ require (
github.com/stackitcloud/stackit-sdk-go/services/argus v0.11.0
github.com/stackitcloud/stackit-sdk-go/services/dns v0.12.0
github.com/stackitcloud/stackit-sdk-go/services/iaas v0.16.0
github.com/stackitcloud/stackit-sdk-go/services/iaasalpha v0.1.12-alpha
github.com/stackitcloud/stackit-sdk-go/services/iaasalpha v0.1.13-alpha
github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v0.17.0
github.com/stackitcloud/stackit-sdk-go/services/logme v0.20.0
github.com/stackitcloud/stackit-sdk-go/services/mariadb v0.20.0
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -157,8 +157,8 @@ github.com/stackitcloud/stackit-sdk-go/services/dns v0.12.0 h1:NypnmRbvjCX7ANJej
github.com/stackitcloud/stackit-sdk-go/services/dns v0.12.0/go.mod h1:mv8U7kuclXo+0VpDHtBCkve/3i9h1yT+RAId/MUi+C8=
github.com/stackitcloud/stackit-sdk-go/services/iaas v0.16.0 h1:geyW780gqNxzSsPvmlxy3kUUJaRA4eiF9V3b2Ibcdjs=
github.com/stackitcloud/stackit-sdk-go/services/iaas v0.16.0/go.mod h1:YfuN+eXuqr846xeRyW2Vf1JM2jU0ikeQa76dDI66RsM=
github.com/stackitcloud/stackit-sdk-go/services/iaasalpha v0.1.12-alpha h1:jwpif4t2gthmKmCXsQ84rmtDdcZkw4QQTFiCd7nTW8M=
github.com/stackitcloud/stackit-sdk-go/services/iaasalpha v0.1.12-alpha/go.mod h1:nW/6vvumUHA7o1/JOOqsrEOBNrRHombEKB1U4jmg2wU=
github.com/stackitcloud/stackit-sdk-go/services/iaasalpha v0.1.13-alpha h1:s+Ew1kJSZhvOrN7OwJ9uKlPtzt8xR+Aqi9bZfdT+4CM=
github.com/stackitcloud/stackit-sdk-go/services/iaasalpha v0.1.13-alpha/go.mod h1:nW/6vvumUHA7o1/JOOqsrEOBNrRHombEKB1U4jmg2wU=
github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v0.17.0 h1:06CGP64CEk3Zg6i9kZCMRdmCzLLiyMWQqGK1teBr9Oc=
github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v0.17.0/go.mod h1:JL94zc8K0ebWs+DBGXR28vNCF0EFV54ZLUtrlXOvWgA=
github.com/stackitcloud/stackit-sdk-go/services/logme v0.20.0 h1:V0UGP7JEa4Q8SsZFUJsKgLGaoPruLn2KVKnqQtaoWCU=
Expand Down
221 changes: 204 additions & 17 deletions stackit/internal/services/iaas/iaas_acc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import (
"github.com/stackitcloud/stackit-sdk-go/core/config"
"github.com/stackitcloud/stackit-sdk-go/core/utils"
"github.com/stackitcloud/stackit-sdk-go/services/iaas"
"github.com/stackitcloud/stackit-sdk-go/services/iaasalpha"
"github.com/stackitcloud/terraform-provider-stackit/stackit/internal/core"
"github.com/stackitcloud/terraform-provider-stackit/stackit/internal/testutil"
)
Expand Down Expand Up @@ -53,7 +52,7 @@ var networkAreaRouteResource = map[string]string{
var networkInterfaceResource = map[string]string{
"project_id": testutil.ProjectId,
"network_id": networkResource["network_id"],
"name": "name",
"name": fmt.Sprintf("tf-acc-%s", acctest.RandStringFromCharSet(5, acctest.CharSetAlpha)),
}

// Volume resource data
Expand Down Expand Up @@ -110,6 +109,14 @@ var keyPairResource = map[string]string{
"label1-updated": "value1-updated",
}

// Virtual IP resource data
var virtualIpResource = map[string]string{
"project_id": testutil.ProjectId,
"name": fmt.Sprintf("acc-test-%s", acctest.RandStringFromCharSet(5, acctest.CharSetAlphaNum)),
"label1": "value1",
"label1-updated": "value1-updated",
}

func networkResourceConfig(name, nameservers string) string {
return fmt.Sprintf(`
resource "stackit_network" "network" {
Expand Down Expand Up @@ -304,6 +311,37 @@ func serviceAccountAttachmentResourceConfig() string {
)
}

func virtualIPResourceConfig(labelValue string) string {
// Network resource name must match the one from "networkResourceConfig"
return fmt.Sprintf(`
resource "stackit_virtual_ip" "virtual_ip" {
project_id = "%s"
network_id = stackit_network.network.network_id
name = "%s"
labels = {
"label1" = "%s"
}
}
`,
testutil.ProjectId,
virtualIpResource["name"],
labelValue,
)
}

func virtualIPMemberResourceConfig() string {
return fmt.Sprintf(`
resource "stackit_virtual_ip_member" "virtual_ip_member" {
project_id = "%s"
network_id = stackit_network.network.network_id
virtual_ip_id = stackit_virtual_ip.virtual_ip.virtual_ip_id
network_interface_id = stackit_network_interface.network_interface.network_interface_id
}
`,
testutil.ProjectId,
)
}

func testAccNetworkAreaConfig(areaname, networkranges, routeLabelValue string) string {
return fmt.Sprintf("%s\n\n%s\n\n%s",
testutil.IaaSProviderConfig(),
Expand Down Expand Up @@ -354,6 +392,16 @@ func testAccKeyPairConfig(keyPairResourceConfig string) string {
)
}

func testAccVirtualIPConfig(labelValue string) string {
return fmt.Sprintf("%s\n\n%s\n\n%s\n\n%s\n\n%s",
testutil.IaaSProviderConfig(),
networkResourceConfig(networkResource["name"], fmt.Sprintf(`["%s", "%s"]`, networkResource["nameserver0"], networkResource["nameserver1"])),
networkInterfaceResourceConfig(networkInterfaceResource["name"]),
virtualIPResourceConfig(labelValue),
virtualIPMemberResourceConfig(),
)
}

func TestAccNetworkArea(t *testing.T) {
resource.Test(t, resource.TestCase{
ProtoV6ProviderFactories: testutil.TestAccProtoV6ProviderFactories,
Expand Down Expand Up @@ -1282,6 +1330,105 @@ func TestAccKeyPair(t *testing.T) {
})
}

func TestAccVirtualIP(t *testing.T) {
resource.Test(t, resource.TestCase{
ProtoV6ProviderFactories: testutil.TestAccProtoV6ProviderFactories,
CheckDestroy: testAccCheckIaaSNetworkDestroy, // Virtual IP is deleted with the network
Steps: []resource.TestStep{

// Creation
{
Config: testAccVirtualIPConfig(virtualIpResource["label1"]),
Check: resource.ComposeAggregateTestCheckFunc(
// Virtual IP
resource.TestCheckResourceAttr("stackit_virtual_ip.virtual_ip", "project_id", virtualIpResource["project_id"]),
resource.TestCheckResourceAttr("stackit_virtual_ip.virtual_ip", "labels.label1", virtualIpResource["label1"]),
resource.TestCheckResourceAttr("stackit_virtual_ip.virtual_ip", "name", virtualIpResource["name"]),
resource.TestCheckResourceAttrSet("stackit_virtual_ip.virtual_ip", "virtual_ip_id"),
resource.TestCheckResourceAttrSet("stackit_virtual_ip.virtual_ip", "ip"),
resource.TestCheckResourceAttrPair("stackit_virtual_ip.virtual_ip", "network_id", "stackit_network.network", "network_id"),

// Virtual IP member
resource.TestCheckResourceAttrPair(
"stackit_virtual_ip_member.virtual_ip_member", "project_id",
"stackit_virtual_ip.virtual_ip", "project_id",
),
resource.TestCheckResourceAttrPair(
"stackit_virtual_ip_member.virtual_ip_member", "network_id",
"stackit_virtual_ip.virtual_ip", "network_id",
),
resource.TestCheckResourceAttrPair(
"stackit_virtual_ip_member.virtual_ip_member", "virtual_ip_id",
"stackit_virtual_ip.virtual_ip", "virtual_ip_id",
),
resource.TestCheckResourceAttrPair(
"stackit_virtual_ip_member.virtual_ip_member", "network_interface_id",
"stackit_network_interface.network_interface", "network_interface_id",
),
),
},
// Data source
{
Config: fmt.Sprintf(`
%s
data "stackit_virtual_ip" "virtual_ip" {
project_id = stackit_virtual_ip.virtual_ip.project_id
network_id = stackit_virtual_ip.virtual_ip.network_id
virtual_ip_id = stackit_virtual_ip.virtual_ip.virtual_ip_id
}
`,
testAccVirtualIPConfig(virtualIpResource["label1"]),
),
Check: resource.ComposeAggregateTestCheckFunc(
// Instance
resource.TestCheckResourceAttr("data.stackit_virtual_ip.virtual_ip", "project_id", virtualIpResource["project_id"]),
resource.TestCheckResourceAttrPair(
"stackit_virtual_ip.virtual_ip", "virtual_ip_id",
"data.stackit_virtual_ip.virtual_ip", "virtual_ip_id",
),
resource.TestCheckResourceAttr("stackit_virtual_ip.virtual_ip", "labels.label1", virtualIpResource["label1"]),
resource.TestCheckResourceAttr("stackit_virtual_ip.virtual_ip", "name", virtualIpResource["name"]),
resource.TestCheckResourceAttrPair("stackit_virtual_ip.virtual_ip", "ip", "data.stackit_virtual_ip.virtual_ip", "ip"),
resource.TestCheckResourceAttrPair("stackit_virtual_ip.virtual_ip", "network_id", "data.stackit_virtual_ip.virtual_ip", "network_id"),
),
},
// Import
{
ResourceName: "stackit_virtual_ip.virtual_ip",
ImportStateIdFunc: func(s *terraform.State) (string, error) {
r, ok := s.RootModule().Resources["stackit_virtual_ip.virtual_ip"]
if !ok {
return "", fmt.Errorf("couldn't find resource stackit_virtual_ip.virtual_ip")
}
networkId, ok := r.Primary.Attributes["network_id"]
if !ok {
return "", fmt.Errorf("couldn't find attribute network_id")
}
virtualIpId, ok := r.Primary.Attributes["virtual_ip_id"]
if !ok {
return "", fmt.Errorf("couldn't find attribute virtual_ip_id")
}
return fmt.Sprintf("%s,%s,%s", testutil.ProjectId, networkId, virtualIpId), nil
},
ImportState: true,
ImportStateVerify: true,
},
// Update
{
Config: testAccVirtualIPConfig(virtualIpResource["label1-updated"]),
Check: resource.ComposeAggregateTestCheckFunc(
resource.TestCheckResourceAttr("stackit_virtual_ip.virtual_ip", "project_id", virtualIpResource["project_id"]),
resource.TestCheckResourceAttr("stackit_virtual_ip.virtual_ip", "labels.label1", virtualIpResource["label1-updated"]),
resource.TestCheckResourceAttr("stackit_virtual_ip.virtual_ip", "name", virtualIpResource["name"]),
resource.TestCheckResourceAttrSet("stackit_virtual_ip.virtual_ip", "virtual_ip_id"),
),
},
// Deletion is done by the framework implicitly
},
})
}

func testAccCheckNetworkAreaDestroy(s *terraform.State) error {
ctx := context.Background()
var client *iaas.APIClient
Expand Down Expand Up @@ -1378,27 +1525,19 @@ func testAccCheckIaaSVolumeDestroy(s *terraform.State) error {

func testAccCheckServerDestroy(s *terraform.State) error {
ctx := context.Background()
var alphaClient *iaas.APIClient
var client *iaas.APIClient
var err error
var alphaErr error
if testutil.IaaSCustomEndpoint == "" {
alphaClient, alphaErr = iaas.NewAPIClient(
config.WithRegion("eu01"),
)
client, err = iaas.NewAPIClient(
config.WithRegion("eu01"),
)
} else {
alphaClient, alphaErr = iaas.NewAPIClient(
config.WithEndpoint(testutil.IaaSCustomEndpoint),
)
client, err = iaas.NewAPIClient(
config.WithRegion("eu01"),
)
}
if err != nil || alphaErr != nil {
return fmt.Errorf("creating client: %w, %w", err, alphaErr)
if err != nil {
return fmt.Errorf("creating client: %w", err)
}

// Servers
Expand All @@ -1413,7 +1552,7 @@ func testAccCheckServerDestroy(s *terraform.State) error {
serversToDestroy = append(serversToDestroy, serverId)
}

serversResp, err := alphaClient.ListServersExecute(ctx, testutil.ProjectId)
serversResp, err := client.ListServersExecute(ctx, testutil.ProjectId)
if err != nil {
return fmt.Errorf("getting serversResp: %w", err)
}
Expand All @@ -1424,7 +1563,7 @@ func testAccCheckServerDestroy(s *terraform.State) error {
continue
}
if utils.Contains(serversToDestroy, *servers[i].Id) {
err := alphaClient.DeleteServerExecute(ctx, testutil.ProjectId, *servers[i].Id)
err := client.DeleteServerExecute(ctx, testutil.ProjectId, *servers[i].Id)
if err != nil {
return fmt.Errorf("destroying server %s during CheckDestroy: %w", *servers[i].Id, err)
}
Expand Down Expand Up @@ -1560,14 +1699,14 @@ func testAccCheckIaaSPublicIpDestroy(s *terraform.State) error {

func testAccCheckIaaSKeyPairDestroy(s *terraform.State) error {
ctx := context.Background()
var client *iaasalpha.APIClient
var client *iaas.APIClient
var err error
if testutil.IaaSCustomEndpoint == "" {
client, err = iaasalpha.NewAPIClient(
client, err = iaas.NewAPIClient(
config.WithRegion("eu01"),
)
} else {
client, err = iaasalpha.NewAPIClient(
client, err = iaas.NewAPIClient(
config.WithEndpoint(testutil.IaaSCustomEndpoint),
)
}
Expand Down Expand Up @@ -1603,3 +1742,51 @@ func testAccCheckIaaSKeyPairDestroy(s *terraform.State) error {
}
return nil
}

func testAccCheckIaaSNetworkDestroy(s *terraform.State) error {
ctx := context.Background()
var client *iaas.APIClient
var err error
if testutil.IaaSCustomEndpoint == "" {
client, err = iaas.NewAPIClient(
config.WithRegion("eu01"),
)
} else {
client, err = iaas.NewAPIClient(
config.WithEndpoint(testutil.IaaSCustomEndpoint),
)
}
if err != nil {
return fmt.Errorf("creating client: %w", err)
}

networksToDestroy := []string{}
for _, rs := range s.RootModule().Resources {
if rs.Type != "stackit_network" {
continue
}
// network terraform ID: "[project_id],[network_id]"
networkId := strings.Split(rs.Primary.ID, core.Separator)[1]
networksToDestroy = append(networksToDestroy, networkId)
}

networksResp, err := client.ListNetworksExecute(ctx, testutil.ProjectId)
if err != nil {
return fmt.Errorf("getting networksResp: %w", err)
}

networks := *networksResp.Items
for i := range networks {
if networks[i].NetworkId == nil {
continue
}
if utils.Contains(networksToDestroy, *networks[i].NetworkId) {
err := client.DeleteNetworkExecute(ctx, testutil.ProjectId, *networks[i].NetworkId)
if err != nil {
return fmt.Errorf("destroying network %s during CheckDestroy: %w", *networks[i].NetworkId, err)
}
}
}

return nil
}
4 changes: 2 additions & 2 deletions stackit/internal/services/iaas/publicipassociate/resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ func (r *publicIpAssociateResource) Configure(ctx context.Context, req resource.
return
}

core.LogAndAddWarning(ctx, &resp.Diagnostics, "The `stackit_public_ip_associate` resource should not be used together with the `stackit_public_ip` resource for the same public IP or for the same network interface.",
core.LogAndAddWarning(ctx, &resp.Diagnostics, `The "stackit_public_ip_associate" resource should not be used together with the "stackit_public_ip" resource for the same public IP or for the same network interface.`,
"Using both resources together for the same public IP or network interface WILL lead to conflicts, as they both have control of the public IP and network interface association.")

r.client = apiClient
Expand All @@ -112,7 +112,7 @@ func (r *publicIpAssociateResource) Schema(_ context.Context, _ resource.SchemaR
"main": "Associates an existing public IP to a network interface. " +
"This is useful for situations where you have a pre-allocated public IP or unable to use the `stackit_public_ip` resource to create a new public IP. " +
"Must have a `region` specified in the provider configuration.",
"warning_message": "The `stackit_public_ip_associate` resource should not be used together with the `stackit_public_ip` resource for the same public IP or for the same network interface. \n" +
"warning_message": `The "stackit_public_ip_associate" resource should not be used together with the "stackit_public_ip" resource for the same public IP or for the same network interface. \n` +
"Using both resources together for the same public IP or network interface WILL lead to conflicts, as they both have control of the public IP and network interface association.",
}
resp.Schema = schema.Schema{
Expand Down
Loading

0 comments on commit 3ca6773

Please sign in to comment.