Skip to content

Linode Interfaces: Consolidate InterfaceGeneration and LinodeInterfaces fields into InstanceCreateOptions #759

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

Conversation

lgarber-akamai
Copy link
Contributor

@lgarber-akamai lgarber-akamai commented May 27, 2025

📝 Description

This pull request consolidates the InterfaceGeneration and Interfaces fields from InstanceCreateOptionsWithLinodeInterfaces into the InstanceCreateOptions struct, overriding MarshalJSON and UnmarshalJSON to dynamically determine how fields should be serialized to and deserialized according to the API implementation.

This is necessary because the composition-based approach required significant flow changes in consumers due to the need to use a separate function and options struct. Additionally, the previous implementation did not allow the InterfaceGeneration to be specified when not using the composited struct.

✔️ How to Test

The following test steps assume you have pulled down this PR locally and are pointing at an account with access to Linode Interfaces.

Integration Testing

make fixtures TEST_ARGS="-run Interface"

Manual Testing

  1. In a linodego sandbox environment (e.g. dx-devenv), run the following:
package main

import (
	"encoding/json"
	"fmt"

	"github.com/davecgh/go-spew/spew"
	"github.com/linode/linodego"
)

func main() {
	withLinodeInterface, err := json.Marshal(
		linodego.InstanceCreateOptions{
			Label:               "test-instance",
			Region:              "us-mia",
			Type:                "g6-nanode-1",
			InterfaceGeneration: linodego.GenerationLinode,
			LinodeInterfaces: []linodego.LinodeInterfaceCreateOptions{
				{
					Public: &linodego.PublicInterfaceCreateOptions{},
				},
				{
					VLAN: &linodego.VLANInterface{
						Label: "test-vlan",
					},
				},
			},
		},
	)
	if err != nil {
		panic(err)
	}

	withConfigInterface, err := json.Marshal(
		linodego.InstanceCreateOptions{
			Label:               "test-instance",
			Region:              "us-mia",
			Type:                "g6-nanode-1",
			InterfaceGeneration: linodego.GenerationLegacyConfig,
			Interfaces: []linodego.InstanceConfigInterfaceCreateOptions{
				{
					Purpose: "public",
				},
				{
					Purpose: "vlan",
					Label:   "test-vlan",
				},
			},
		},
	)
	if err != nil {
		panic(err)
	}

	fmt.Printf("With Linode Interface: %s\n", string(withLinodeInterface))
	fmt.Printf("With Config Interface: %s\n", string(withConfigInterface))

	var withLinodeInterfaceParsed, withConfigInterfaceParsed linodego.InstanceCreateOptions

	if err := json.Unmarshal(withLinodeInterface, &withLinodeInterfaceParsed); err != nil {
		panic(err)
	}

	if err := json.Unmarshal(withConfigInterface, &withConfigInterfaceParsed); err != nil {
		panic(err)
	}

	fmt.Printf("With Linode Interface (parsed): %s\n", spew.Sdump(withLinodeInterfaceParsed.LinodeInterfaces))
	fmt.Printf("With Config Interface (parsed): %s\n", spew.Sdump(withConfigInterfaceParsed.Interfaces))
}
  1. Ensure the output matches the following:
With Linode Interface: {"region":"us-mia","type":"g6-nanode-1","label":"test-instance","interface_generation":"linode","interfaces":[{"public":{"ipv4":{},"ipv6":{}}},{"vlan":{"vlan_label":"test-vlan"}}]}
With Config Interface: {"region":"us-mia","type":"g6-nanode-1","label":"test-instance","interface_generation":"legacy_config","interfaces":[{"purpose":"public"},{"label":"test-vlan","purpose":"vlan"}]}

With Linode Interface (parsed): ([]linodego.LinodeInterfaceCreateOptions) (len=2 cap=2) {
 (linodego.LinodeInterfaceCreateOptions) {
  FirewallID: (*int)(<nil>),
  DefaultRoute: (*linodego.InterfaceDefaultRoute)(<nil>),
  Public: (*linodego.PublicInterfaceCreateOptions)(0x140001b51d0)({
   IPv4: (linodego.PublicInterfaceIPv4CreateOptions) {
    Addresses: ([]linodego.PublicInterfaceIPv4AddressCreateOptions) <nil>
   },
   IPv6: (linodego.PublicInterfaceIPv6CreateOptions) {
    Ranges: ([]linodego.PublicInterfaceIPv6RangeCreateOptions) <nil>
   }
  }),
  VPC: (*linodego.VPCInterfaceCreateOptions)(<nil>),
  VLAN: (*linodego.VLANInterface)(<nil>)
 },
 (linodego.LinodeInterfaceCreateOptions) {
  FirewallID: (*int)(<nil>),
  DefaultRoute: (*linodego.InterfaceDefaultRoute)(<nil>),
  Public: (*linodego.PublicInterfaceCreateOptions)(<nil>),
  VPC: (*linodego.VPCInterfaceCreateOptions)(<nil>),
  VLAN: (*linodego.VLANInterface)(0x14000130768)({
   Label: (string) (len=9) "test-vlan",
   IPAMAddress: (*string)(<nil>)
  })
 }
}

With Config Interface (parsed): ([]linodego.InstanceConfigInterfaceCreateOptions) (len=2 cap=2) {
 (linodego.InstanceConfigInterfaceCreateOptions) {
  IPAMAddress: (string) "",
  Label: (string) "",
  Purpose: (linodego.ConfigInterfacePurpose) (len=6) "public",
  Primary: (bool) false,
  SubnetID: (*int)(<nil>),
  IPv4: (*linodego.VPCIPv4)(<nil>),
  IPRanges: ([]string) <nil>
 },
 (linodego.InstanceConfigInterfaceCreateOptions) {
  IPAMAddress: (string) "",
  Label: (string) (len=9) "test-vlan",
  Purpose: (linodego.ConfigInterfacePurpose) (len=4) "vlan",
  Primary: (bool) false,
  SubnetID: (*int)(<nil>),
  IPv4: (*linodego.VPCIPv4)(<nil>),
  IPRanges: ([]string) <nil>
 }
}

@lgarber-akamai lgarber-akamai added the improvement for improvements in existing functionality in the changelog. label May 27, 2025
@lgarber-akamai lgarber-akamai changed the title ref: Consolidate InterfaceGeneration and LinodeInterfaces fields into InstanceCreateOptions Linode Interfaces: Consolidate InterfaceGeneration and LinodeInterfaces fields into InstanceCreateOptions May 27, 2025
@lgarber-akamai lgarber-akamai marked this pull request as ready for review May 27, 2025 19:38
@lgarber-akamai lgarber-akamai requested a review from a team as a code owner May 27, 2025 19:38
@lgarber-akamai lgarber-akamai requested review from ykim-akamai and ezilber-akamai and removed request for a team May 27, 2025 19:38
Copy link
Contributor

@ezilber-akamai ezilber-akamai left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice work! Integration and manual testing is working locally.

Copy link
Contributor

@ykim-akamai ykim-akamai left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, all tests pass locally

@lgarber-akamai lgarber-akamai merged commit 1cab31f into linode:proj/vpc-linodes-enhanced-interfaces Jun 11, 2025
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
improvement for improvements in existing functionality in the changelog.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants