Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added support for updated behavior of linode API's (networkingip, rdns, instance) #1658

Open
wants to merge 64 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
64 commits
Select commit Hold shift + click to select a range
9bd4ae9
Added support for creating a linode with a reserved IP + adding addit…
AniJ98 Sep 23, 2024
c0451aa
Registered the resource and data source within the provider
AniJ98 Sep 26, 2024
3d09656
Implemented framework_resource, framework_datasource along with their…
AniJ98 Sep 26, 2024
aca9fc6
Made changes for maintaining consistency and readability
AniJ98 Sep 26, 2024
88701c1
Removed commented function
AniJ98 Sep 26, 2024
c9bb10d
temporarily changed linodego to point to the latest commit on main br…
AniJ98 Sep 26, 2024
c81f8d2
Merge branch 'dev' into ipreservation-existingendpoints
AniJ98 Sep 26, 2024
5fcc625
removed unused addReservedIPToInstance func
AniJ98 Sep 26, 2024
0eb8fa9
Merge branch 'ipreservation-existingendpoints' of https://github.com/…
AniJ98 Sep 26, 2024
c9196b8
temporarily changed linodego to point to the latest commit on main br…
AniJ98 Sep 26, 2024
950ab3b
Merge branch 'dev' into ipreservation-newendpoints
AniJ98 Sep 26, 2024
b6638d8
added go buil inegration || networkreservedips to prevent integration…
AniJ98 Sep 26, 2024
2b18460
Merge branch 'dev' into ipreservation-newendpoints
AniJ98 Oct 7, 2024
7a14802
Merge branch 'dev' into ipreservation-existingendpoints
AniJ98 Oct 7, 2024
be57ac7
removed unused import statement and changed linodego version to point…
AniJ98 Oct 8, 2024
38195df
removed unnecessary region filter from datasource
AniJ98 Oct 14, 2024
3267bec
formatting change
AniJ98 Oct 15, 2024
9c67fcf
added check for addition of ipv4 field post creation
AniJ98 Oct 15, 2024
4785460
Removed debug logic and statements
AniJ98 Oct 15, 2024
24493f8
Created a separate datasource for listing reserved IPs, added the cor…
AniJ98 Oct 16, 2024
66ce804
Fix for nil pointer dereference
AniJ98 Oct 21, 2024
1e97bea
Update go.mod to point to latest release of linodego
AniJ98 Oct 22, 2024
865a471
Added reserved field to linode_instance_ip schema
AniJ98 Oct 22, 2024
dbca935
committing branch
AniJ98 Oct 23, 2024
bcb763b
Merge pull request #1 from AniJ98/ipreservation-newendpoints
AniJ98 Oct 23, 2024
021e210
fix for plugin crash
AniJ98 Oct 23, 2024
f0eb534
Removed unused reservedIPObjectType struct, copyFrom function
AniJ98 Oct 24, 2024
f76bfbd
Separated the reserved IP allocation into linode_instance_reserved_ip…
AniJ98 Oct 24, 2024
506803f
pushing changes to go.mod and added reserved field
AniJ98 Oct 24, 2024
da79151
Made changes to add reserved field in the IP object of linode_instanc…
AniJ98 Oct 24, 2024
0276608
Merge branch 'ipreservation-existing+newendpoints' into ipreservation…
AniJ98 Oct 24, 2024
4bf15bc
Merge pull request #2 from AniJ98/ipreservation-existingendpoints
AniJ98 Oct 24, 2024
e1c17cb
changed the resource name to linode_instance_reserved_ip.test in the …
AniJ98 Oct 24, 2024
8d6cb69
added test for checking reserved status after deletion
AniJ98 Oct 25, 2024
e986a31
Created datasource for listing IP instance IP address
AniJ98 Oct 28, 2024
9369bd7
Removing the linode_instance_ips data source since it is already impl…
AniJ98 Oct 28, 2024
f420bbc
de-registering the datasource from framework_provider
AniJ98 Oct 28, 2024
4794189
Separated out the list networking ips (paginated response) to a diffe…
AniJ98 Oct 28, 2024
2cb26e8
modified the name of the datasource and registered it with the framew…
AniJ98 Oct 28, 2024
86d9e3c
created linode_networking_ip resource for allocating/creating reserve…
AniJ98 Oct 28, 2024
8dc5759
Fixed import bug for linode_reserved_ip resource
AniJ98 Oct 28, 2024
5ef370e
Fixed import bug for linode_reserved_ip resource
AniJ98 Oct 28, 2024
131ca71
The functionality of network ip assignment is now moved to a new reso…
AniJ98 Oct 29, 2024
2ea86e6
added functionality to update RDNS and reserved status of an IP Address
AniJ98 Oct 29, 2024
79aec4e
Removing the update reserved status from linode_rdns to move it to ne…
AniJ98 Oct 29, 2024
2001cf5
Adding the updated behvior of the rdns resource back to linode_rdns
AniJ98 Oct 30, 2024
e28442b
added test for checking updated behavior while listing linode ip addr…
AniJ98 Oct 31, 2024
3fa103a
Added test for filterig list of ip address on the reserved field
AniJ98 Oct 31, 2024
7e831bb
made changes to TestAccDataSourceNetworkingIP_list, TestAccDataSource…
AniJ98 Oct 31, 2024
e82cc76
Added test for reserved IP creation and allocation
AniJ98 Oct 31, 2024
0961729
made change to template function
AniJ98 Oct 31, 2024
92fc816
added test for network_ip_assign resource
AniJ98 Nov 4, 2024
0c8e68d
made changes to .gotf file for the resource_test
AniJ98 Nov 4, 2024
f659268
Merge branch 'dev' into ipreservation-newendpoints
AniJ98 Nov 5, 2024
95619ae
added more conditions to the existing multiple IP assign test
AniJ98 Nov 5, 2024
32fcbee
Merge branch 'ipreservation-newendpoints' into dev
AniJ98 Nov 7, 2024
2d1b50d
Merge branch 'ipreservation-remainingendpoints-final' into dev
AniJ98 Nov 7, 2024
7482a03
Merge pull request #4 from AniJ98/dev
AniJ98 Nov 7, 2024
3bccbf7
removing duplicate resource for adding reserved IP to linodes
AniJ98 Nov 7, 2024
e1e5539
modified test for assigning multiple reserved IP address to linodes i…
AniJ98 Nov 8, 2024
610bd45
made changes to existing tests for updating rdns, assigning IP addres…
AniJ98 Nov 12, 2024
f26fadc
Merge branch 'dev' into ipreservation-remainingendpoints-final
AniJ98 Nov 12, 2024
151b636
removed the replace line from the go.mod
AniJ98 Nov 13, 2024
0a8ded4
Merge branch 'ipreservation-remainingendpoints-final' of https://gith…
AniJ98 Nov 13, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -125,3 +125,5 @@ require (
sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect
sigs.k8s.io/yaml v1.3.0 // indirect
)


10 changes: 10 additions & 0 deletions linode/framework_provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,10 @@ import (
"github.com/linode/terraform-provider-linode/v2/linode/nbs"
"github.com/linode/terraform-provider-linode/v2/linode/nbtypes"
"github.com/linode/terraform-provider-linode/v2/linode/networkingip"
"github.com/linode/terraform-provider-linode/v2/linode/networkingips"
"github.com/linode/terraform-provider-linode/v2/linode/networkipassignment"
"github.com/linode/terraform-provider-linode/v2/linode/networkreservedip"
"github.com/linode/terraform-provider-linode/v2/linode/networkreservedips"
"github.com/linode/terraform-provider-linode/v2/linode/networktransferprices"
"github.com/linode/terraform-provider-linode/v2/linode/objbucket"
"github.com/linode/terraform-provider-linode/v2/linode/objcluster"
Expand Down Expand Up @@ -225,13 +229,16 @@ func (p *FrameworkProvider) Resources(ctx context.Context) []func() resource.Res
placementgroup.NewResource,
placementgroupassignment.NewResource,
instancereservedipassignment.NewResource,
networkreservedip.NewResource,
rdns.NewResource,
sshkey.NewResource,
stackscript.NewResource,
token.NewResource,
volume.NewResource,
vpc.NewResource,
vpcsubnet.NewResource,
networkingip.NewResource,
networkipassignment.NewResource,
}
}

Expand Down Expand Up @@ -300,5 +307,8 @@ func (p *FrameworkProvider) DataSources(ctx context.Context) []func() datasource
placementgroups.NewDataSource,
childaccount.NewDataSource,
childaccounts.NewDataSource,
networkreservedip.NewDataSourceFetch,
networkreservedips.NewDataSourceList,
networkingips.NewDataSource,
}
}
5 changes: 5 additions & 0 deletions linode/instance/resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -830,6 +830,11 @@ func updateResource(ctx context.Context, d *schema.ResourceData, meta interface{
}
}

if d.HasChange("ipv4") {
// Log a warning that direct IP changes are not supported
return diag.Errorf("Changing IPv4 addresses after instance creation is not directly supported. The attempted change will be ignored.")
}

// Don't reboot if the Linode should be powered off
if !bootedNull && !booted {
rebootInstance = false
Expand Down
67 changes: 63 additions & 4 deletions linode/instance/resource_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2899,27 +2899,24 @@ func checkComputeInstanceDisk(instance *linodego.Instance, label string, size in
}

func TestAccResourceInstance_withReservedIP(t *testing.T) {
acceptance.OptInTest(t)
t.Parallel()

var instance linodego.Instance
resourceName := "linode_instance.foobar"
instanceName := acctest.RandomWithPrefix("tf_test")
rootPass := acctest.RandString(16)
reservedIP := "50.116.51.242" // Use a test IP or fetch a real reserved IP

resource.Test(t, resource.TestCase{
PreCheck: func() { acceptance.PreCheck(t) },
ProtoV5ProviderFactories: acceptance.ProtoV5ProviderFactories,
CheckDestroy: acceptance.CheckInstanceDestroy,
Steps: []resource.TestStep{
{
Config: tmpl.WithReservedIP(t, instanceName, acceptance.PublicKeyMaterial, testRegion, rootPass, reservedIP),
Config: tmpl.WithReservedIP(t, instanceName, acceptance.PublicKeyMaterial, testRegion, rootPass),
Check: resource.ComposeTestCheckFunc(
acceptance.CheckInstanceExists(resourceName, &instance),
resource.TestCheckResourceAttr(resourceName, "label", instanceName),
resource.TestCheckResourceAttr(resourceName, "ipv4.#", "1"),
resource.TestCheckResourceAttr(resourceName, "ipv4.0", reservedIP),
),
},
{
Expand All @@ -2931,3 +2928,65 @@ func TestAccResourceInstance_withReservedIP(t *testing.T) {
},
})
}

func TestAccResourceInstance_deleteWithReservedIP(t *testing.T) {
t.Parallel()
var instance linodego.Instance
resourceName := "linode_instance.foobar"
testRegion := "us-east"
reservedIP := ""
instanceName := acctest.RandomWithPrefix("tf_test")
ipResourceName := "linode_reserved_ip.test"
rootPass := acctest.RandString(16)
resource.Test(t, resource.TestCase{
PreCheck: func() { acceptance.PreCheck(t) },
ProtoV5ProviderFactories: acceptance.ProtoV5ProviderFactories,
CheckDestroy: acceptance.CheckInstanceDestroy,
Steps: []resource.TestStep{
{
Config: tmpl.WithReservedIP(t, instanceName, acceptance.PublicKeyMaterial, testRegion, rootPass),
Check: resource.ComposeTestCheckFunc(
acceptance.CheckInstanceExists(resourceName, &instance),
resource.TestCheckResourceAttr(resourceName, "label", instanceName),
resource.TestCheckResourceAttr(resourceName, "ipv4.#", "1"),
func(s *terraform.State) error {
rs, ok := s.RootModule().Resources[ipResourceName]
if !ok {
return fmt.Errorf("Not found: %s", ipResourceName)
}
reservedIP = rs.Primary.Attributes["address"]
return nil
},
),
},
{
Config: tmpl.OnlyReservedIP(t, testRegion), // This config only includes the reserved IP resource
Check: resource.ComposeTestCheckFunc(
func(s *terraform.State) error {
client := acceptance.TestAccProvider.Meta().(*helper.ProviderMeta).Client

// Check if the instance is deleted
_, err := client.GetInstance(context.Background(), instance.ID)
if err == nil {
return fmt.Errorf("Linode instance %d still exists", instance.ID)
}
if apiErr, ok := err.(*linodego.Error); ok && apiErr.Code != 404 {
return fmt.Errorf("Error requesting Linode instance %d: %s", instance.ID, err)
}

// Check if the Reserved IP still exists and is reserved
ip, err := client.GetIPAddress(context.Background(), reservedIP)
if err != nil {
return fmt.Errorf("Error checking if Reserved IP exists: %s", err)
}
if !ip.Reserved {
return fmt.Errorf("Reserved IP %s is no longer reserved after instance deletion", reservedIP)
}

return nil
},
),
},
},
})
}
13 changes: 10 additions & 3 deletions linode/instance/tmpl/template.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package tmpl

import (
"fmt"
"testing"

"github.com/linode/linodego"
Expand Down Expand Up @@ -28,7 +29,6 @@ type TemplateData struct {
AssignedGroup string

DiskEncryption *linodego.InstanceDiskEncryption
IPv4 []string
}

func Basic(t testing.TB, label, pubKey, region string, rootPass string) string {
Expand Down Expand Up @@ -743,15 +743,22 @@ func WithPG(t testing.TB, label, region, assignedGroup string, groups []string)
})
}

func WithReservedIP(t *testing.T, label, pubKey, region, rootPass string, reservedIP string) string {
func WithReservedIP(t *testing.T, label, pubKey, region, rootPass string) string {
generatedConfig := acceptance.ExecuteTemplate(t,
"instance_with_reserved_ip", TemplateData{
Label: label,
PubKey: pubKey,
Image: acceptance.TestImageLatest,
Region: region,
RootPass: rootPass,
IPv4: []string{reservedIP},
})
return generatedConfig
}

func OnlyReservedIP(t *testing.T, region string) string {
return fmt.Sprintf(`
resource "linode_reserved_ip" "test" {
region = "%s"
}
`, region)
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,20 @@

{{ template "e2e_test_firewall" . }}

resource "linode_reserved_ip" "test" {
region = "{{ .Region }}"
}

resource "linode_instance" "foobar" {
label = "{{ .Label }}"
type = "g6-nanode-1"
region = "{{ .Region }}"
image = "{{ .Image }}"
firewall_id = linode_firewall.e2e_test_firewall.id

root_pass = "{{ .RootPass }}"
authorized_keys = ["{{ .PubKey }}"]

ipv4 = [{{ range $index, $ip := .IPv4 }}{{ if $index }}, {{ end }}"{{ $ip }}"{{ end }}]
ipv4 = [linode_reserved_ip.test.address]
}

{{ end }}
1 change: 0 additions & 1 deletion linode/instanceip/framework_resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,6 @@ func (r *Resource) Read(
if resp.Diagnostics.HasError() {
return
}

ip, err := client.GetInstanceIPAddress(ctx, linodeID, address)
if err != nil {
if lerr, ok := err.(*linodego.Error); ok && lerr.Code == 404 {
Expand Down
1 change: 1 addition & 0 deletions linode/instanceip/tmpl/template.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ type TemplateData struct {
Label string
ApplyImmediately bool
Region string
Address string
}

func Basic(t testing.TB, instanceLabel, region string, applyImmediately bool) string {
Expand Down
31 changes: 31 additions & 0 deletions linode/instancenetworking/datasource_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,3 +80,34 @@ func TestAccDataSourceInstanceNetworking_vpc(t *testing.T) {
},
})
}

func TestAccDataSourceInstanceNetworking_basicwithReseved(t *testing.T) {
t.Parallel()

var instance linodego.Instance

name := acctest.RandomWithPrefix("tf_test")
resource.Test(t, resource.TestCase{
PreCheck: func() { acceptance.PreCheck(t) },
ProtoV5ProviderFactories: acceptance.ProtoV5ProviderFactories,
CheckDestroy: acceptance.CheckInstanceDestroy,
Steps: []resource.TestStep{
{
Config: tmpl.DataBasic_withReservedField(t, name, testRegion),
},
{
Config: tmpl.DataBasic_withReservedField(t, name, testRegion),
Check: resource.ComposeTestCheckFunc(
acceptance.CheckInstanceExists("linode_instance.foobar", &instance),
resource.TestCheckResourceAttrSet(testInstanceNetworkResName, "ipv4.0.private.#"),
resource.TestCheckResourceAttrSet(testInstanceNetworkResName, "ipv4.0.public.#"),
resource.TestCheckResourceAttrSet(testInstanceNetworkResName, "ipv4.0.reserved.#"),
resource.TestCheckResourceAttrSet(testInstanceNetworkResName, "ipv4.0.shared.#"),
resource.TestCheckResourceAttrSet(testInstanceNetworkResName, "ipv6.0.global.#"),
resource.TestCheckResourceAttrSet(testInstanceNetworkResName, "ipv6.0.link_local.%"),
resource.TestCheckResourceAttrSet(testInstanceNetworkResName, "ipv6.0.slaac.%"),
),
},
},
})
}
22 changes: 22 additions & 0 deletions linode/instancenetworking/tmpl/data_basic_reserved.gotf
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{{ define "instance_networking_data_basic_with_reserved" }}

resource "linode_instance" "foobar" {
label = "{{.Label}}"
type = "g6-nanode-1"
region = "{{ .Region }}"
image = "linode/debian12"
}

resource "linode_networking_ip" "reserved_ip" {
region = "{{ .Region }}"
public = true
type = "ipv4"
reserved = true
linode_id = linode_instance.foobar.id
}

data "linode_instance_networking" "test" {
linode_id = linode_instance.foobar.id
}

{{ end }}
8 changes: 8 additions & 0 deletions linode/instancenetworking/tmpl/template.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,11 @@ func DataVPC(t testing.TB, label, region, subnetIPv4, interfaceIPv4 string) stri
InterfaceIPv4: interfaceIPv4,
})
}

func DataBasic_withReservedField(t *testing.T, instanceLabel, region string) string {
return acceptance.ExecuteTemplate(t,
"instance_networking_data_basic_with_reserved", TemplateData{
Label: instanceLabel,
Region: region,
})
}
1 change: 1 addition & 0 deletions linode/networkingip/datasource_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ func TestAccDataSourceNetworkingIP_basic(t *testing.T) {
resource.TestMatchResourceAttr(dataResourceName, "gateway", regexp.MustCompile(`\.1$`)),
resource.TestCheckResourceAttr(dataResourceName, "type", "ipv4"),
resource.TestCheckResourceAttr(dataResourceName, "public", "true"),
resource.TestCheckResourceAttrSet(dataResourceName, "reserved"),
resource.TestCheckResourceAttr(dataResourceName, "prefix", "24"),
resource.TestMatchResourceAttr(dataResourceName, "rdns", regexp.MustCompile(`.ip.linodeusercontent.com$`)),
),
Expand Down
2 changes: 2 additions & 0 deletions linode/networkingip/framework_datasource.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ func (data *DataSourceModel) parseIP(ip *linodego.InstanceIP) {
data.RDNS = types.StringValue(ip.RDNS)
data.LinodeID = types.Int64Value(int64(ip.LinodeID))
data.Region = types.StringValue(ip.Region)
data.Reserved = types.BoolValue(ip.Reserved)

id, _ := json.Marshal(ip)

Expand All @@ -51,6 +52,7 @@ type DataSourceModel struct {
Type types.String `tfsdk:"type"`
Public types.Bool `tfsdk:"public"`
RDNS types.String `tfsdk:"rdns"`
Reserved types.Bool `tfsdk:"reserved"`
LinodeID types.Int64 `tfsdk:"linode_id"`
Region types.String `tfsdk:"region"`
ID types.String `tfsdk:"id"`
Expand Down
5 changes: 5 additions & 0 deletions linode/networkingip/framework_datasource_schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,11 @@ var frameworkDatasourceSchema = schema.Schema{
Description: "The Region this IP address resides in.",
Computed: true,
},
"reserved": schema.BoolAttribute{
Description: "Whether the IPv4 address should be reserved.",
Computed: true,
},

"id": schema.StringAttribute{
Description: "A unique identifier for this datasource.",
Computed: true,
Expand Down
Loading