diff --git a/equinix/equinix_sweeper_test.go b/equinix/equinix_sweeper_test.go index b37a0ed4b..10905e5b2 100644 --- a/equinix/equinix_sweeper_test.go +++ b/equinix/equinix_sweeper_test.go @@ -1,50 +1,11 @@ package equinix import ( - "fmt" - "strconv" - "strings" "testing" - "time" - - "github.com/equinix/terraform-provider-equinix/internal/config" "github.com/hashicorp/terraform-plugin-testing/helper/resource" ) -const tstResourcePrefix = "tfacc" - func TestMain(m *testing.M) { resource.TestMain(m) } - -func sharedConfigForRegion(region string) (*config.Config, error) { - endpoint := getFromEnvDefault(config.EndpointEnvVar, config.DefaultBaseURL) - clientToken := getFromEnvDefault(config.ClientTokenEnvVar, "") - clientID := getFromEnvDefault(config.ClientIDEnvVar, "") - clientSecret := getFromEnvDefault(config.ClientSecretEnvVar, "") - clientTimeout := getFromEnvDefault(config.ClientTimeoutEnvVar, strconv.Itoa(config.DefaultTimeout)) - clientTimeoutInt, err := strconv.Atoi(clientTimeout) - if err != nil { - return nil, fmt.Errorf("cannot convert value of '%s' env variable to int", config.ClientTimeoutEnvVar) - } - metalAuthToken := getFromEnvDefault(config.MetalAuthTokenEnvVar, "") - - if clientToken == "" && (clientID == "" || clientSecret == "") && metalAuthToken == "" { - return nil, fmt.Errorf("To run acceptance tests sweeper, one of '%s' or pair '%s' - '%s' must be set for Equinix Fabric and Network Edge, and '%s' for Equinix Metal", - config.ClientTokenEnvVar, config.ClientIDEnvVar, config.ClientSecretEnvVar, config.MetalAuthTokenEnvVar) - } - - return &config.Config{ - AuthToken: metalAuthToken, - BaseURL: endpoint, - Token: clientToken, - ClientID: clientID, - ClientSecret: clientSecret, - RequestTimeout: time.Duration(clientTimeoutInt) * time.Second, - }, nil -} - -func isSweepableTestResource(namePrefix string) bool { - return strings.HasPrefix(namePrefix, tstResourcePrefix) -} diff --git a/equinix/provider.go b/equinix/provider.go index 6d8dd1117..d28ca90a8 100644 --- a/equinix/provider.go +++ b/equinix/provider.go @@ -3,7 +3,6 @@ package equinix import ( "context" "fmt" - "slices" "time" "github.com/equinix/terraform-provider-equinix/internal/config" @@ -14,6 +13,18 @@ import ( metal_port "github.com/equinix/terraform-provider-equinix/internal/resources/metal/port" "github.com/equinix/terraform-provider-equinix/internal/resources/metal/virtual_circuit" "github.com/equinix/terraform-provider-equinix/internal/resources/metal/vrf" + neaccount "github.com/equinix/terraform-provider-equinix/internal/resources/networkedge/account" + neacltemplate "github.com/equinix/terraform-provider-equinix/internal/resources/networkedge/acl_template" + nebgp "github.com/equinix/terraform-provider-equinix/internal/resources/networkedge/bgp" + nedevice "github.com/equinix/terraform-provider-equinix/internal/resources/networkedge/device" + nedevicelink "github.com/equinix/terraform-provider-equinix/internal/resources/networkedge/device_link" + nedevicesoftware "github.com/equinix/terraform-provider-equinix/internal/resources/networkedge/device_software" + nedevicetype "github.com/equinix/terraform-provider-equinix/internal/resources/networkedge/device_type" + nefile "github.com/equinix/terraform-provider-equinix/internal/resources/networkedge/file" + nedeviceplatform "github.com/equinix/terraform-provider-equinix/internal/resources/networkedge/platform" + nesshkey "github.com/equinix/terraform-provider-equinix/internal/resources/networkedge/ssh_key" + nesshuser "github.com/equinix/terraform-provider-equinix/internal/resources/networkedge/ssh_user" + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" @@ -93,11 +104,11 @@ func Provider() *schema.Provider { "equinix_fabric_ports": dataSourceFabricGetPortsByName(), "equinix_fabric_service_profile": dataSourceFabricServiceProfileReadByUuid(), "equinix_fabric_service_profiles": dataSourceFabricSearchServiceProfilesByName(), - "equinix_network_account": dataSourceNetworkAccount(), - "equinix_network_device": dataSourceNetworkDevice(), - "equinix_network_device_type": dataSourceNetworkDeviceType(), - "equinix_network_device_software": dataSourceNetworkDeviceSoftware(), - "equinix_network_device_platform": dataSourceNetworkDevicePlatform(), + "equinix_network_account": neaccount.DataSource(), + "equinix_network_device": nedevice.DataSource(), + "equinix_network_device_type": nedevicetype.DataSource(), + "equinix_network_device_software": nedevicesoftware.DataSource(), + "equinix_network_device_platform": nedeviceplatform.DataSource(), "equinix_metal_hardware_reservation": dataSourceMetalHardwareReservation(), "equinix_metal_metro": dataSourceMetalMetro(), "equinix_metal_facility": dataSourceMetalFacility(), @@ -121,13 +132,13 @@ func Provider() *schema.Provider { "equinix_fabric_connection": fabric_connection.Resource(), "equinix_fabric_routing_protocol": resourceFabricRoutingProtocol(), "equinix_fabric_service_profile": resourceFabricServiceProfile(), - "equinix_network_device": resourceNetworkDevice(), - "equinix_network_ssh_user": resourceNetworkSSHUser(), - "equinix_network_bgp": resourceNetworkBGP(), - "equinix_network_ssh_key": resourceNetworkSSHKey(), - "equinix_network_acl_template": resourceNetworkACLTemplate(), - "equinix_network_device_link": resourceNetworkDeviceLink(), - "equinix_network_file": resourceNetworkFile(), + "equinix_network_device": nedevice.Resource(), + "equinix_network_ssh_user": nesshuser.Resource(), + "equinix_network_bgp": nebgp.Resource(), + "equinix_network_ssh_key": nesshkey.Resource(), + "equinix_network_acl_template": neacltemplate.Resource(), + "equinix_network_device_link": nedevicelink.Resource(), + "equinix_network_file": nefile.Resource(), "equinix_metal_user_api_key": resourceMetalUserAPIKey(), "equinix_metal_project_api_key": resourceMetalProjectAPIKey(), "equinix_metal_device": metal_device.Resource(), @@ -200,65 +211,3 @@ func configureProvider(ctx context.Context, d *schema.ResourceData, p *schema.Pr } return &config, nil } - -// stringsFound returns true if all strings in source are found in target -// Deprecated: stringsFound is shared between provider, tests, and resources -// and is being relocated for package refactoring. -// Use github.com/equinix/terraform-provider-equinix/internal/comparisons.Subsets -func stringsFound(source []string, target []string) bool { - for i := range source { - if !slices.Contains(target, source[i]) { - return false - } - } - return true -} - -// isEmpty returns true if the value is nil or zero -// Deprecated: isEmpty is shared between provider, tests, and resources -// and is being relocated for package refactoring. -// Use github.com/equinix/terraform-provider-equinix/internal/comparisons.IsEmpty -func isEmpty(v interface{}) bool { - switch v := v.(type) { - case int: - return v == 0 - case *int: - return v == nil || *v == 0 - case string: - return v == "" - case *string: - return v == nil || *v == "" - case nil: - return true - default: - return false - } -} - -// slicesMatch returns true if all strings in s1 are found in s2 -// Deprecated: slicesMatch is shared between provider, tests, and resources -// and is being relocated for package refactoring. -// Use github.com/equinix/terraform-provider-equinix/internal/comparisons.SlicesMatch -func slicesMatch(s1, s2 []string) bool { - if len(s1) != len(s2) { - return false - } - visited := make([]bool, len(s1)) - for i := 0; i < len(s1); i++ { - found := false - for j := 0; j < len(s2); j++ { - if visited[j] { - continue - } - if s1[i] == s2[j] { - visited[j] = true - found = true - break - } - } - if !found { - return false - } - } - return true -} diff --git a/equinix/provider_test.go b/equinix/provider_test.go index a539aca3d..d8ce96d61 100644 --- a/equinix/provider_test.go +++ b/equinix/provider_test.go @@ -4,10 +4,9 @@ import ( "context" "fmt" "os" - "regexp" - "strings" "testing" + "github.com/equinix/terraform-provider-equinix/internal/comparisons" "github.com/equinix/terraform-provider-equinix/internal/config" "github.com/equinix/terraform-provider-equinix/internal/provider" "github.com/equinix/terraform-provider-equinix/version" @@ -45,11 +44,6 @@ var ( } ) -type testAccConfig struct { - ctx map[string]interface{} - config string -} - func init() { testAccProvider = Provider() testAccProviders = map[string]*schema.Provider{ @@ -71,54 +65,6 @@ func TestProvider(t *testing.T) { } } -// Deprecated test moved to internal/comparissons/comparisons_test.go -func TestProvider_stringsFound(t *testing.T) { - // given - needles := []string{"key1", "key5"} - hay := []string{"key1", "key2", "Key3", "key4", "key5"} - // when - result := stringsFound(needles, hay) - // then - assert.True(t, result, "Given strings were found") -} - -// Deprecated test moved to internal/comparissons/comparisons_test.go -func TestProvider_stringsFound_negative(t *testing.T) { - // given - needles := []string{"key1", "key6"} - hay := []string{"key1", "key2", "Key3", "key4", "key5"} - // when - result := stringsFound(needles, hay) - // then - assert.False(t, result, "Given strings were found") -} - -// Deprecated test moved to internal/comparissons/comparisons_test.go -func TestProvider_isEmpty(t *testing.T) { - // given - input := []interface{}{ - "test", - "", - nil, - 123, - 0, - 43.43, - } - expected := []bool{ - false, - true, - true, - false, - true, - false, - true, - } - // when then - for i := range input { - assert.Equal(t, expected[i], isEmpty(input[i]), "Input %v produces expected result %v", input[i], expected[i]) - } -} - func TestProvider_setSchemaValueIfNotEmpty(t *testing.T) { // given key := "test" @@ -137,43 +83,6 @@ func TestProvider_setSchemaValueIfNotEmpty(t *testing.T) { assert.False(t, ok, "Key was not set") } -// Deprecated test moved to internal/comparissons/comparisons_test.go -func TestProvider_slicesMatch(t *testing.T) { - // given - input := [][][]string{ - { - {"DC", "SV", "FR"}, - {"FR", "SV", "DC"}, - }, - { - {"SV"}, - {}, - }, - { - {"DC", "DC", "DC"}, - {"DC", "SV", "DC"}, - }, - { - {}, {}, - }, - } - expected := []bool{ - true, - false, - false, - true, - } - // when - results := make([]bool, len(expected)) - for i := range input { - results[i] = slicesMatch(input[i][0], input[i][1]) - } - // then - for i := range expected { - assert.Equal(t, expected[i], results[i]) - } -} - //‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ // Test helper functions //_______________________________________________________________________ @@ -198,37 +107,6 @@ func testAccPreCheck(t *testing.T) { } } -func newTestAccConfig(ctx map[string]interface{}) *testAccConfig { - return &testAccConfig{ - ctx: ctx, - config: "", - } -} - -func (t *testAccConfig) build() string { - return t.config -} - -// nprintf returns a string with all the placeholders replaced by the values from the params map -// -// Deprecated: nprintf is shared between NE resource tests and has been -// centralized ahead of those NE resources moving to separate packages. -// Use github.com/equinix/terraform-provider-equinix/internal/nprintf.NPrintf instead -func nprintf(format string, params map[string]interface{}) string { - for key, val := range params { - var strVal string - switch val.(type) { - case []string: - r := regexp.MustCompile(`" "`) - strVal = r.ReplaceAllString(fmt.Sprintf("%q", val), `", "`) - default: - strVal = fmt.Sprintf("%v", val) - } - format = strings.Replace(format, "%{"+key+"}", strVal, -1) - } - return format -} - func getFromEnv(varName string) (string, error) { if v := os.Getenv(varName); v != "" { return v, nil @@ -236,23 +114,8 @@ func getFromEnv(varName string) (string, error) { return "", fmt.Errorf("environmental variable '%s' is not set", varName) } -func getFromEnvDefault(varName string, defaultValue string) string { - if v := os.Getenv(varName); v != "" { - return v - } - return defaultValue -} - -func copyMap(source map[string]interface{}) map[string]interface{} { - target := make(map[string]interface{}) - for k, v := range source { - target[k] = v - } - return target -} - func setSchemaValueIfNotEmpty(key string, value interface{}, d *schema.ResourceData) error { - if !isEmpty(value) { + if !comparisons.IsEmpty(value) { return d.Set(key, value) } return nil diff --git a/equinix/resource_network_ssh_user_acc_test.go b/equinix/resource_network_ssh_user_acc_test.go deleted file mode 100644 index 0ac24bde3..000000000 --- a/equinix/resource_network_ssh_user_acc_test.go +++ /dev/null @@ -1,107 +0,0 @@ -package equinix - -import ( - "context" - "fmt" - "log" - - "github.com/equinix/terraform-provider-equinix/internal/config" - - "github.com/equinix/ne-go" - "github.com/hashicorp/terraform-plugin-testing/helper/resource" - "github.com/hashicorp/terraform-plugin-testing/terraform" -) - -// SSH User acc tests are in Device acc test tests -// reason: SSH User requires device to be provisioned and that is time consuming operation - -func init() { - resource.AddTestSweepers("equinix_network_ssh_user", &resource.Sweeper{ - Name: "equinix_network_ssh_user", - F: testSweepNetworkSSHUser, - }) -} - -func testSweepNetworkSSHUser(region string) error { - config, err := sharedConfigForRegion(region) - if err != nil { - return fmt.Errorf("[INFO][SWEEPER_LOG] Error getting configuration for sweeping Network SSH users: %s", err) - } - if err := config.Load(context.Background()); err != nil { - log.Printf("[INFO][SWEEPER_LOG] error loading configuration: %s", err) - return err - } - users, err := config.Ne.GetSSHUsers() - if err != nil { - log.Printf("[INFO][SWEEPER_LOG] error fetching NetworkSSHUser list: %s", err) - return err - } - for _, user := range users { - if !isSweepableTestResource(ne.StringValue(user.Username)) { - continue - } - if err := config.Ne.DeleteSSHUser(ne.StringValue(user.UUID)); err != nil { - log.Printf("[INFO][SWEEPER_LOG] error deleting NetworkSSHUser resource %s (%s): %s", ne.StringValue(user.UUID), ne.StringValue(user.Username), err) - } else { - log.Printf("[INFO][SWEEPER_LOG] sent delete request for NetworkSSHUser resource %s (%s)", ne.StringValue(user.UUID), ne.StringValue(user.Username)) - } - } - return nil -} - -func testAccNetworkDeviceUser(ctx map[string]interface{}) string { - config := nprintf(` -resource "equinix_network_ssh_user" "%{user-resourceName}" { - username = "%{user-username}" - password = "%{user-password}" - device_ids = [ - equinix_network_device.%{device-resourceName}.id`, ctx) - if _, ok := ctx["device-secondary_name"]; ok { - config += nprintf(`, - equinix_network_device.%{device-resourceName}.redundant_id`, ctx) - } - config += ` - ] -}` - return config -} - -func (t *testAccConfig) withSSHUser() *testAccConfig { - t.config += testAccNetworkDeviceUser(t.ctx) - return t -} - -func testAccNeSSHUserExists(resourceName string, user *ne.SSHUser) resource.TestCheckFunc { - return func(s *terraform.State) error { - rs, ok := s.RootModule().Resources[resourceName] - if !ok { - return fmt.Errorf("resource not found: %s", resourceName) - } - if rs.Primary.ID == "" { - return fmt.Errorf("resource has no ID attribute set") - } - client := testAccProvider.Meta().(*config.Config).Ne - resp, err := client.GetSSHUser(rs.Primary.ID) - if err != nil { - return fmt.Errorf("error when fetching SSH user '%s': %s", rs.Primary.ID, err) - } - *user = *resp - return nil - } -} - -func testAccNeSSHUserAttributes(user *ne.SSHUser, devices []*ne.Device, ctx map[string]interface{}) resource.TestCheckFunc { - return func(s *terraform.State) error { - if v, ok := ctx["username"]; ok && ne.StringValue(user.Username) != v.(string) { - return fmt.Errorf("name does not match %v - %v", ne.StringValue(user.Username), v) - } - deviceIDs := make([]string, len(devices)) - for i := range devices { - deviceIDs[i] = ne.StringValue(devices[i].UUID) - } - if !slicesMatch(deviceIDs, user.DeviceUUIDs) { - return fmt.Errorf("device_ids does not match %v - %v", deviceIDs, user.DeviceUUIDs) - } - return nil - } -} diff --git a/internal/acceptance/acceptance.go b/internal/acceptance/acceptance.go index 0e994f7aa..f7e65a23d 100644 --- a/internal/acceptance/acceptance.go +++ b/internal/acceptance/acceptance.go @@ -5,11 +5,9 @@ import ( "sync" "testing" - "github.com/equinix/terraform-provider-equinix/equinix" "github.com/equinix/terraform-provider-equinix/internal/config" "github.com/equinix/terraform-provider-equinix/internal/env" "github.com/equinix/terraform-provider-equinix/internal/provider" - "github.com/equinix/terraform-provider-equinix/version" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" terraformsdk "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" "github.com/hashicorp/terraform-plugin-testing/helper/resource" @@ -33,19 +31,6 @@ var ( testAccProviderConfigure sync.Once ) -func init() { - TestAccProvider = equinix.Provider() - TestAccProviders = map[string]*schema.Provider{ - "equinix": TestAccProvider, - } - TestExternalProviders = map[string]resource.ExternalProvider{ - "random": { - Source: "hashicorp/random", - }, - } - TestAccFrameworkProvider = provider.CreateFrameworkProvider(version.ProviderVersion).(*provider.FrameworkProvider) -} - func TestAccPreCheck(t *testing.T) { var err error diff --git a/internal/acceptance/acceptance_acc_test.go b/internal/acceptance/acceptance_acc_test.go new file mode 100644 index 000000000..4e703a951 --- /dev/null +++ b/internal/acceptance/acceptance_acc_test.go @@ -0,0 +1,22 @@ +package acceptance + +import ( + "github.com/equinix/terraform-provider-equinix/equinix" + "github.com/equinix/terraform-provider-equinix/internal/provider" + "github.com/equinix/terraform-provider-equinix/version" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-plugin-testing/helper/resource" +) + +func init() { + TestAccProvider = equinix.Provider() + TestAccProviders = map[string]*schema.Provider{ + "equinix": TestAccProvider, + } + TestExternalProviders = map[string]resource.ExternalProvider{ + "random": { + Source: "hashicorp/random", + }, + } + TestAccFrameworkProvider = provider.CreateFrameworkProvider(version.ProviderVersion).(*provider.FrameworkProvider) +} diff --git a/internal/comparisons/comparisons.go b/internal/comparisons/comparisons.go index 10f90708a..de33431c6 100644 --- a/internal/comparisons/comparisons.go +++ b/internal/comparisons/comparisons.go @@ -3,10 +3,9 @@ package comparisons import ( "cmp" "slices" - "strings" ) -// isEmpty returns true if the given value is empty +// IsEmpty returns true if the given value is empty func IsEmpty(v interface{}) bool { switch v := v.(type) { case int: @@ -37,7 +36,7 @@ func Subsets[T cmp.Ordered](s1, s2 []T) bool { return true } -// comparisons.SlicesMatch returns true if the two slices contain the same elements, regardless of order +// SlicesMatch returns true if the two slices contain the same elements, regardless of order func SlicesMatch[T cmp.Ordered](s1, s2 []T) bool { if len(s1) != len(s2) { return false @@ -53,15 +52,3 @@ func SlicesMatch[T cmp.Ordered](s1, s2 []T) bool { return slices.Equal(s1Copy, s2Copy) } - -// caseInsensitiveLess is a comparison function for sorting strings case-insensitively -func caseInsensitiveLess(s1, s2 string) int { - switch { - case strings.ToLower(s1) == strings.ToLower(s2): - return 0 - case strings.ToLower(s1) < strings.ToLower(s2): - return -1 - default: - return 1 - } -} diff --git a/internal/converters/converters.go b/internal/converters/converters.go index d5becd52f..463f4a52c 100644 --- a/internal/converters/converters.go +++ b/internal/converters/converters.go @@ -50,13 +50,13 @@ func ToLowerIf(v interface{}) string { return strings.ToLower(v.(string)) } -// from https://stackoverflow.com/a/45428032 -func Difference(a, b []string) []string { - mb := make(map[string]struct{}, len(b)) +// Difference returns the elements in `a` that aren't in `b`. +func Difference[T comparable](a, b []T) []T { + mb := make(map[T]struct{}, len(b)) for _, x := range b { mb[x] = struct{}{} } - var diff []string + var diff []T for _, x := range a { if _, found := mb[x]; !found { diff = append(diff, x) diff --git a/internal/nprintf/nprintf.go b/internal/nprintf/nprintf.go index 0b68397ff..d7bee71c1 100644 --- a/internal/nprintf/nprintf.go +++ b/internal/nprintf/nprintf.go @@ -6,8 +6,8 @@ import ( "strings" ) -// NPrintf is a helper function to replace placeholders in a string with values from a map -func NPrintf(format string, params map[string]interface{}) string { +// Nprintf is a helper function to replace placeholders in a string with values from a map +func Nprintf(format string, params map[string]interface{}) string { for key, val := range params { var strVal string switch val.(type) { diff --git a/internal/resources/metal/device/resource.go b/internal/resources/metal/device/resource.go index 9405998aa..588d6f8ae 100644 --- a/internal/resources/metal/device/resource.go +++ b/internal/resources/metal/device/resource.go @@ -9,12 +9,11 @@ import ( "path" "reflect" "regexp" + "slices" "sort" "strings" "time" - "slices" - "github.com/equinix/terraform-provider-equinix/internal/converters" "github.com/equinix/terraform-provider-equinix/internal/network" @@ -36,9 +35,7 @@ var ( ipAddressTypes = []string{"public_ipv4", "private_ipv4", "public_ipv6"} ) -var ( - deviceCommonIncludes = []string{"project", "metro", "facility", "hardware_reservation"} -) +var deviceCommonIncludes = []string{"project", "metro", "facility", "hardware_reservation"} func Resource() *schema.Resource { return &schema.Resource{ diff --git a/internal/resources/metal/device/sweeper.go b/internal/resources/metal/device/sweeper.go index cc0b5683a..8d79592c9 100644 --- a/internal/resources/metal/device/sweeper.go +++ b/internal/resources/metal/device/sweeper.go @@ -5,7 +5,6 @@ import ( "errors" "fmt" "log" - "slices" "github.com/equinix/equinix-sdk-go/services/metalv1" diff --git a/internal/resources/metal/port/resource.go b/internal/resources/metal/port/resource.go index fbcb01d69..b4571e2da 100644 --- a/internal/resources/metal/port/resource.go +++ b/internal/resources/metal/port/resource.go @@ -5,9 +5,8 @@ import ( "fmt" "log" "net/http" - "time" - "slices" + "time" "github.com/equinix/equinix-sdk-go/services/metalv1" equinix_errors "github.com/equinix/terraform-provider-equinix/internal/errors" diff --git a/internal/resources/metal/project/models.go b/internal/resources/metal/project/models.go index 3fe6b9ce2..e3d8a8949 100644 --- a/internal/resources/metal/project/models.go +++ b/internal/resources/metal/project/models.go @@ -117,7 +117,7 @@ func parseBGPConfig(ctx context.Context, bgpConfig *metalv1.BgpConfig) fwtypes.L return fwtypes.NewListNestedObjectValueOfNull[BGPConfigModel](ctx) } -// isEmptyBGPConfig checks if the provided BgpConfig is considered empty +// isEmptyMetalBGPConfig checks if the provided BgpConfig is considered empty func isEmptyMetalBGPConfig(bgp *metalv1.BgpConfig) bool { if metalv1.IsNil(bgp) { return true diff --git a/equinix/data_source_network_account.go b/internal/resources/networkedge/account/data_source.go similarity index 98% rename from equinix/data_source_network_account.go rename to internal/resources/networkedge/account/data_source.go index d54e18da0..4ac54ad8e 100644 --- a/equinix/data_source_network_account.go +++ b/internal/resources/networkedge/account/data_source.go @@ -1,4 +1,4 @@ -package equinix +package account import ( "context" @@ -32,7 +32,7 @@ var networkAccountDescriptions = map[string]string{ "ProjectID": "The unique identifier of Project Resource to which billing account is scoped to", } -func dataSourceNetworkAccount() *schema.Resource { +func DataSource() *schema.Resource { return &schema.Resource{ ReadContext: dataSourceNetworkAccountRead, Description: "Use this data source to get number and identifier of Equinix Network Edge billing account in a given metro location", diff --git a/equinix/data_source_network_account_acc_test.go b/internal/resources/networkedge/account/data_source_acc_test.go similarity index 79% rename from equinix/data_source_network_account_acc_test.go rename to internal/resources/networkedge/account/data_source_acc_test.go index d3c6d88e5..5e92bef6c 100644 --- a/equinix/data_source_network_account_acc_test.go +++ b/internal/resources/networkedge/account/data_source_acc_test.go @@ -1,4 +1,4 @@ -package equinix +package account import ( "fmt" @@ -6,6 +6,13 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-testing/helper/resource" + + "github.com/equinix/terraform-provider-equinix/internal/acceptance" + "github.com/equinix/terraform-provider-equinix/internal/nprintf" +) + +const ( + networkDeviceMetroEnvVar = "TF_ACC_NETWORK_DEVICE_METRO" ) func TestAccDataSourceNetworkAccount_basic(t *testing.T) { @@ -18,8 +25,8 @@ func TestAccDataSourceNetworkAccount_basic(t *testing.T) { } resourceName := fmt.Sprintf("data.equinix_network_account.%s", context["resourceName"].(string)) resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, + PreCheck: func() { acceptance.TestAccPreCheck(t) }, + Providers: acceptance.TestAccProviders, Steps: []resource.TestStep{ { Config: testAccDataSourceNetworkAccountConfig_basic(context), @@ -36,7 +43,7 @@ func TestAccDataSourceNetworkAccount_basic(t *testing.T) { } func testAccDataSourceNetworkAccountConfig_basic(ctx map[string]interface{}) string { - return nprintf(` + return nprintf.Nprintf(` data "equinix_network_account" "%{resourceName}" { metro_code = "%{metro_code}" status = "%{status}" diff --git a/equinix/resource_network_acl_template.go b/internal/resources/networkedge/acl_template/resource.go similarity index 99% rename from equinix/resource_network_acl_template.go rename to internal/resources/networkedge/acl_template/resource.go index 6ae8739f6..bce124192 100644 --- a/equinix/resource_network_acl_template.go +++ b/internal/resources/networkedge/acl_template/resource.go @@ -1,4 +1,4 @@ -package equinix +package acl_template import ( "context" @@ -81,7 +81,7 @@ var networkACLTemplateDeprecateDescriptions = map[string]string{ "Subnets": "Use Subnet instead", } -func resourceNetworkACLTemplate() *schema.Resource { +func Resource() *schema.Resource { return &schema.Resource{ CreateContext: resourceNetworkACLTemplateCreate, ReadContext: resourceNetworkACLTemplateRead, diff --git a/equinix/resource_network_acl_template_acc_test.go b/internal/resources/networkedge/acl_template/resource_acc_test.go similarity index 78% rename from equinix/resource_network_acl_template_acc_test.go rename to internal/resources/networkedge/acl_template/resource_acc_test.go index d6f0eee3a..8e7ea125d 100644 --- a/equinix/resource_network_acl_template_acc_test.go +++ b/internal/resources/networkedge/acl_template/resource_acc_test.go @@ -1,12 +1,12 @@ -package equinix +package acl_template import ( - "context" "fmt" - "log" "testing" + "github.com/equinix/terraform-provider-equinix/internal/acceptance" "github.com/equinix/terraform-provider-equinix/internal/config" + "github.com/equinix/terraform-provider-equinix/internal/nprintf" "github.com/equinix/ne-go" "github.com/hashicorp/terraform-plugin-testing/helper/acctest" @@ -14,43 +14,16 @@ import ( "github.com/hashicorp/terraform-plugin-testing/terraform" ) -func init() { - resource.AddTestSweepers("equinix_network_acl_template", &resource.Sweeper{ - Name: "equinix_network_acl_template", - F: testSweepNetworkACLTemplate, - }) -} +const ( + tstResourcePrefix = "tfacc" +) -func testSweepNetworkACLTemplate(region string) error { - config, err := sharedConfigForRegion(region) - if err != nil { - return fmt.Errorf("[INFO][SWEEPER_LOG] Error getting configuration for sweeping Network ACL Templates: %s", err) - } - if err := config.Load(context.Background()); err != nil { - log.Printf("[INFO][SWEEPER_LOG] error loading configuration: %s", err) - return err - } - templates, err := config.Ne.GetACLTemplates() - if err != nil { - log.Printf("[INFO][SWEEPER_LOG] error fetching Network ACL Templates list: %s", err) - return err - } - nonSweepableCount := 0 - for _, template := range templates { - if !isSweepableTestResource(ne.StringValue(template.Name)) { - nonSweepableCount++ - continue - } - if err := config.Ne.DeleteACLTemplate(ne.StringValue(template.UUID)); err != nil { - log.Printf("[INFO][SWEEPER_LOG] error deleting NetworkACLTemplate resource %s (%s): %s", ne.StringValue(template.UUID), ne.StringValue(template.Name), err) - } else { - log.Printf("[INFO][SWEEPER_LOG] sent delete request for NetworkACLTemplate resource %s (%s)", ne.StringValue(template.UUID), ne.StringValue(template.Name)) - } - } - if nonSweepableCount > 0 { - log.Printf("[INFO][SWEEPER_LOG] %d items were non-sweepable and skipped.", nonSweepableCount) +func copyMap(source map[string]interface{}) map[string]interface{} { + target := make(map[string]interface{}) + for k, v := range source { + target[k] = v } - return nil + return target } func TestAccNetworkACLTemplate(t *testing.T) { @@ -81,8 +54,8 @@ func TestAccNetworkACLTemplate(t *testing.T) { resourceName := "equinix_network_acl_template." + context["resourceName"].(string) var template ne.ACLTemplate resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, + PreCheck: func() { acceptance.TestAccPreCheck(t) }, + Providers: acceptance.TestAccProviders, Steps: []resource.TestStep{ { Config: testAccNetworkACLTemplate(context), @@ -110,7 +83,7 @@ func TestAccNetworkACLTemplate(t *testing.T) { } func testAccNetworkACLTemplate(ctx map[string]interface{}) string { - return nprintf(` + return nprintf.Nprintf(` resource "equinix_network_acl_template" "%{resourceName}" { name = "%{name}" description = "%{description}" @@ -146,7 +119,7 @@ func testAccNetworkACLTemplateExists(resourceName string, template *ne.ACLTempla if !ok { return fmt.Errorf("resource not found: %s", resourceName) } - client := testAccProvider.Meta().(*config.Config).Ne + client := acceptance.TestAccProvider.Meta().(*config.Config).Ne if rs.Primary.ID == "" { return fmt.Errorf("resource has no ID attribute set") } diff --git a/equinix/resource_network_acl_template_test.go b/internal/resources/networkedge/acl_template/resource_test.go similarity index 99% rename from equinix/resource_network_acl_template_test.go rename to internal/resources/networkedge/acl_template/resource_test.go index 412af39af..94cb5dd13 100644 --- a/equinix/resource_network_acl_template_test.go +++ b/internal/resources/networkedge/acl_template/resource_test.go @@ -1,12 +1,13 @@ -package equinix +package acl_template import ( "testing" "github.com/equinix/ne-go" - "github.com/equinix/terraform-provider-equinix/internal/converters" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/stretchr/testify/assert" + + "github.com/equinix/terraform-provider-equinix/internal/converters" ) func TestNetworkACLTemplate_createFromResourceData(t *testing.T) { diff --git a/internal/resources/networkedge/acl_template/sweeper.go b/internal/resources/networkedge/acl_template/sweeper.go new file mode 100644 index 000000000..2c482dcfc --- /dev/null +++ b/internal/resources/networkedge/acl_template/sweeper.go @@ -0,0 +1,51 @@ +package acl_template + +import ( + "context" + "fmt" + "log" + + "github.com/equinix/ne-go" + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + + "github.com/equinix/terraform-provider-equinix/internal/sweep" +) + +func AddTestSweeper() { + resource.AddTestSweepers("equinix_network_acl_template", &resource.Sweeper{ + Name: "equinix_network_acl_template", + F: testSweepNetworkACLTemplate, + }) +} + +func testSweepNetworkACLTemplate(region string) error { + config, err := sweep.SharedConfigForRegion(region) + if err != nil { + return fmt.Errorf("[INFO][SWEEPER_LOG] Error getting configuration for sweeping Network ACL Templates: %s", err) + } + if err := config.Load(context.Background()); err != nil { + log.Printf("[INFO][SWEEPER_LOG] error loading configuration: %s", err) + return err + } + templates, err := config.Ne.GetACLTemplates() + if err != nil { + log.Printf("[INFO][SWEEPER_LOG] error fetching Network ACL Templates list: %s", err) + return err + } + nonSweepableCount := 0 + for _, template := range templates { + if !sweep.IsSweepableTestResource(ne.StringValue(template.Name)) { + nonSweepableCount++ + continue + } + if err := config.Ne.DeleteACLTemplate(ne.StringValue(template.UUID)); err != nil { + log.Printf("[INFO][SWEEPER_LOG] error deleting NetworkACLTemplate resource %s (%s): %s", ne.StringValue(template.UUID), ne.StringValue(template.Name), err) + } else { + log.Printf("[INFO][SWEEPER_LOG] sent delete request for NetworkACLTemplate resource %s (%s)", ne.StringValue(template.UUID), ne.StringValue(template.Name)) + } + } + if nonSweepableCount > 0 { + log.Printf("[INFO][SWEEPER_LOG] %d items were non-sweepable and skipped.", nonSweepableCount) + } + return nil +} diff --git a/equinix/resource_network_bgp.go b/internal/resources/networkedge/bgp/resource.go similarity index 99% rename from equinix/resource_network_bgp.go rename to internal/resources/networkedge/bgp/resource.go index ff1a20892..0c916ac9c 100644 --- a/equinix/resource_network_bgp.go +++ b/internal/resources/networkedge/bgp/resource.go @@ -1,4 +1,4 @@ -package equinix +package bgp import ( "context" @@ -42,7 +42,7 @@ var networkBGPDescriptions = map[string]string{ "ProvisioningStatus": "BGP peering configuration provisioning status", } -func resourceNetworkBGP() *schema.Resource { +func Resource() *schema.Resource { return &schema.Resource{ CreateContext: resourceNetworkBGPCreate, ReadContext: resourceNetworkBGPRead, diff --git a/equinix/resource_network_bgp_acc_test.go b/internal/resources/networkedge/bgp/resource_acc_test.go similarity index 90% rename from equinix/resource_network_bgp_acc_test.go rename to internal/resources/networkedge/bgp/resource_acc_test.go index 01c7aa7cd..bb6670d7a 100644 --- a/equinix/resource_network_bgp_acc_test.go +++ b/internal/resources/networkedge/bgp/resource_acc_test.go @@ -1,10 +1,12 @@ -package equinix +package bgp import ( "fmt" "testing" + "github.com/equinix/terraform-provider-equinix/internal/acceptance" "github.com/equinix/terraform-provider-equinix/internal/config" + "github.com/equinix/terraform-provider-equinix/internal/nprintf" "github.com/equinix/ne-go" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" @@ -67,8 +69,8 @@ func TestAccNetworkBGP_CSR1000V_Single_AWS(t *testing.T) { resourceName := fmt.Sprintf("equinix_network_bgp.%s", context["bgp-resourceName"].(string)) var bgpConfig ne.BGPConfiguration resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, + PreCheck: func() { acceptance.TestAccPreCheck(t) }, + Providers: acceptance.TestAccProviders, Steps: []resource.TestStep{ { Config: newTestAccConfig(context).withDevice().withSSHUser().withVDConnection().withBGP().build(), @@ -104,7 +106,7 @@ func (t *testAccConfig) withBGP() *testAccConfig { func testAccNetworkBGP(ctx map[string]interface{}) string { var config string - config += nprintf(` + config += nprintf.Nprintf(` resource "equinix_network_bgp" "%{bgp-resourceName}" { connection_id = equinix_fabric_connection.%{connection-resourceName}.id local_ip_address = "%{bgp-local_ip_address}" @@ -112,13 +114,13 @@ resource "equinix_network_bgp" "%{bgp-resourceName}" { remote_ip_address = "%{bgp-remote_ip_address}" remote_asn = %{bgp-remote_asn}`, ctx) if _, ok := ctx["bgp-authentication_key"]; ok { - config += nprintf(` + config += nprintf.Nprintf(` authentication_key = "%{bgp-authentication_key}"`, ctx) } config += ` }` if _, ok := ctx["connection-secondary_name"]; ok { - config += nprintf(` + config += nprintf.Nprintf(` resource "equinix_network_bgp" "%{bgp-secondary_resourceName}" { connection_id = equinix_fabric_connection.%{connection-resourceName}.id local_ip_address = "%{bgp-secondary_local_ip_address}" @@ -126,7 +128,7 @@ resource "equinix_network_bgp" "%{bgp-secondary_resourceName}" { remote_ip_address = "%{bgp-secondary_remote_ip_address}" remote_asn = %{bgp-secondary_remote_asn}`, ctx) if _, ok := ctx["bgp-secondary_authentication_key"]; ok { - config += nprintf(` + config += nprintf.Nprintf(` authentication_key = "%{bgp-secondary_authentication_key}"`, ctx) } config += ` @@ -141,7 +143,7 @@ func testAccNeBGPExists(resourceName string, bgpConfig *ne.BGPConfiguration) res if !ok { return fmt.Errorf("resource not found: %s", resourceName) } - client := testAccProvider.Meta().(*config.Config).Ne + client := acceptance.TestAccProvider.Meta().(*config.Config).Ne if rs.Primary.ID == "" { return fmt.Errorf("resource has no ID attribute set") } @@ -199,20 +201,20 @@ func testAccVDFabricL2Connection(ctx map[string]interface{}) string { var config string if _, ok := ctx["zside-service_token"]; !ok { if _, ok := ctx["connection-profile_uuid"]; !ok { - config += nprintf(` + config += nprintf.Nprintf(` data "equinix_fabric_service_profile" "pri" { uuid = "%{fabric-service-profile-uuid}" }`, ctx) } } if _, ok := ctx["connection-secondary_profile_name"]; ok { - config += nprintf(` + config += nprintf.Nprintf(` data "equinix_fabric_service_profile" "sec" { uuid = "%{fabric-service-profile-uuid}" }`, ctx) } - config += nprintf(` + config += nprintf.Nprintf(` resource "equinix_fabric_connection" "%{connection-resourceName}" { name = "%{connection-name}" type = "EVPL_VC" @@ -250,98 +252,98 @@ a_side { }`, ctx) if _, ok := ctx["service_token"]; ok { - config += nprintf(` + config += nprintf.Nprintf(` service_token = "%{service_token}"`, ctx) } if _, ok := ctx["zside-service_token"]; ok { - config += nprintf(` + config += nprintf.Nprintf(` zside_service_token = "%{zside-service_token}"`, ctx) } if _, ok := ctx["zside-port_uuid"]; ok { - config += nprintf(` + config += nprintf.Nprintf(` zside_port_uuid = "%{zside-port_uuid}"`, ctx) } if _, ok := ctx["connection-purchase_order_number"]; ok { - config += nprintf(` + config += nprintf.Nprintf(` purchase_order_number = "%{connection-purchase_order_number}"`, ctx) } if _, ok := ctx["port-uuid"]; ok { - config += nprintf(` + config += nprintf.Nprintf(` port_uuid = "%{port-uuid}"`, ctx) } else if _, ok := ctx["port-resourceName"]; ok { - config += nprintf(` + config += nprintf.Nprintf(` port_uuid = data.equinix_ecx_port.%{port-resourceName}.id`, ctx) } if _, ok := ctx["connection-vlan_stag"]; ok { - config += nprintf(` + config += nprintf.Nprintf(` vlan_stag = %{connection-vlan_stag}`, ctx) } if _, ok := ctx["connection-vlan_ctag"]; ok { - config += nprintf(` + config += nprintf.Nprintf(` vlan_ctag = %{connection-vlan_ctag}`, ctx) } if _, ok := ctx["connection-named_tag"]; ok { - config += nprintf(` + config += nprintf.Nprintf(` named_tag = "%{connection-named_tag}"`, ctx) } if _, ok := ctx["connection-device_interface_id"]; ok { - config += nprintf(` + config += nprintf.Nprintf(` device_interface_id = %{connection-device_interface_id}`, ctx) } if _, ok := ctx["connection-secondary_name"]; ok { - config += nprintf(` + config += nprintf.Nprintf(` secondary_connection { name = "%{connection-secondary_name}"`, ctx) if _, ok := ctx["connection-secondary_profile_name"]; ok { - config += nprintf(` + config += nprintf.Nprintf(` profile_uuid = data.equinix_fabric_sellerprofile.sec.id`, ctx) } if _, ok := ctx["secondary-port_uuid"]; ok { - config += nprintf(` + config += nprintf.Nprintf(` port_uuid = "%{secondary-port_uuid}"`, ctx) } else if _, ok := ctx["port-secondary_resourceName"]; ok { - config += nprintf(` + config += nprintf.Nprintf(` port_uuid = data.equinix_ecx_port.%{port-secondary_resourceName}.id`, ctx) } if _, ok := ctx["device-secondary_name"]; ok { - config += nprintf(` + config += nprintf.Nprintf(` device_uuid = equinix_network_device.%{device-resourceName}.redundant_id`, ctx) } if _, ok := ctx["connection-secondary_vlan_stag"]; ok { - config += nprintf(` + config += nprintf.Nprintf(` vlan_stag = %{connection-secondary_vlan_stag}`, ctx) } if _, ok := ctx["connection-secondary_vlan_ctag"]; ok { - config += nprintf(` + config += nprintf.Nprintf(` vlan_ctag = %{connection-secondary_vlan_ctag}`, ctx) } if _, ok := ctx["connection-secondary_device_interface_id"]; ok { - config += nprintf(` + config += nprintf.Nprintf(` device_interface_id = %{connection-secondary_device_interface_id}`, ctx) } if _, ok := ctx["connection-secondary_speed"]; ok { - config += nprintf(` + config += nprintf.Nprintf(` speed = %{connection-secondary_speed}`, ctx) } if _, ok := ctx["connection-secondary_speed_unit"]; ok { - config += nprintf(` + config += nprintf.Nprintf(` speed_unit = "%{connection-secondary_speed_unit}"`, ctx) } if _, ok := ctx["connection-secondary_seller_metro_code"]; ok { - config += nprintf(` + config += nprintf.Nprintf(` seller_metro_code = "%{connection-secondary_seller_metro_code}"`, ctx) } if _, ok := ctx["connection-secondary_seller_region"]; ok { - config += nprintf(` + config += nprintf.Nprintf(` seller_region = "%{connection-secondary_seller_region}"`, ctx) } if _, ok := ctx["connection-secondary_authorization_key"]; ok { - config += nprintf(` + config += nprintf.Nprintf(` authorization_key = "%{connection-secondary_authorization_key}"`, ctx) } if _, ok := ctx["secondary-service_token"]; ok { - config += nprintf(` + config += nprintf.Nprintf(` service_token = "%{secondary-service_token}"`, ctx) } config += ` diff --git a/equinix/resource_network_bgp_test.go b/internal/resources/networkedge/bgp/resource_test.go similarity index 99% rename from equinix/resource_network_bgp_test.go rename to internal/resources/networkedge/bgp/resource_test.go index b4131f3c1..5046d6765 100644 --- a/equinix/resource_network_bgp_test.go +++ b/internal/resources/networkedge/bgp/resource_test.go @@ -1,4 +1,4 @@ -package equinix +package bgp import ( "context" diff --git a/internal/resources/networkedge/bgp/templates_acc_test.go b/internal/resources/networkedge/bgp/templates_acc_test.go new file mode 100644 index 000000000..a1e3e050d --- /dev/null +++ b/internal/resources/networkedge/bgp/templates_acc_test.go @@ -0,0 +1,461 @@ +package bgp + +import ( + "github.com/equinix/terraform-provider-equinix/internal/comparisons" + "github.com/equinix/terraform-provider-equinix/internal/nprintf" +) + +const ( + tstResourcePrefix = "tfacc" + + networkDeviceProjectId = "TF_ACC_NETWORK_DEVICE_PROJECT_ID" + networkDeviceAccountNameEnvVar = "TF_ACC_NETWORK_DEVICE_BILLING_ACCOUNT_NAME" + networkDeviceSecondaryAccountNameEnvVar = "TF_ACC_NETWORK_DEVICE_SECONDARY_BILLING_ACCOUNT_NAME" + networkDeviceMetroEnvVar = "TF_ACC_NETWORK_DEVICE_METRO" + networkDeviceSecondaryMetroEnvVar = "TF_ACC_NETWORK_DEVICE_SECONDARY_METRO" + networkDeviceCSRSDWANLicenseFileEnvVar = "TF_ACC_NETWORK_DEVICE_CSRSDWAN_LICENSE_FILE" + networkDeviceVSRXLicenseFileEnvVar = "TF_ACC_NETWORK_DEVICE_VSRX_LICENSE_FILE" + networkDeviceVersaController1EnvVar = "TF_ACC_NETWORK_DEVICE_VERSA_CONTROLLER1" + networkDeviceVersaController2EnvVar = "TF_ACC_NETWORK_DEVICE_VERSA_CONTROLLER2" + networkDeviceVersaLocalIDEnvVar = "TF_ACC_NETWORK_DEVICE_VERSA_LOCALID" + networkDeviceVersaRemoteIDEnvVar = "TF_ACC_NETWORK_DEVICE_VERSA_REMOTEID" + networkDeviceVersaSerialNumberEnvVar = "TF_ACC_NETWORK_DEVICE_VERSA_SERIAL" + networkDeviceCGENIXLicenseKeyEnvVar = "TF_ACC_NETWORK_DEVICE_CGENIX_LICENSE_KEY" + networkDeviceCGENIXLicenseSecretEnvVar = "TF_ACC_NETWORK_DEVICE_CGENIX_LICENSE_SECRET" + networkDevicePANWLicenseTokenEnvVar = "TF_ACC_NETWORK_DEVICE_PANW_LICENSE_TOKEN" +) + +type testAccConfig struct { + ctx map[string]interface{} + config string +} + +func newTestAccConfig(ctx map[string]interface{}) *testAccConfig { + return &testAccConfig{ + ctx: ctx, + config: "", + } +} + +func (t *testAccConfig) build() string { + return t.config +} + +func (t *testAccConfig) withDevice() *testAccConfig { + t.config += testAccNetworkDevice(t.ctx) + return t +} + +func copyMap(source map[string]interface{}) map[string]interface{} { + target := make(map[string]interface{}) + for k, v := range source { + target[k] = v + } + return target +} + +func testAccNetworkDeviceUser(ctx map[string]interface{}) string { + config := nprintf.Nprintf(` +resource "equinix_network_ssh_user" "%{user-resourceName}" { + username = "%{user-username}" + password = "%{user-password}" + device_ids = [ + equinix_network_device.%{device-resourceName}.id`, ctx) + if _, ok := ctx["device-secondary_name"]; ok { + config += nprintf.Nprintf(`, + equinix_network_device.%{device-resourceName}.redundant_id`, ctx) + } + config += ` + ] +}` + return config +} + +func testAccNetworkDevice(ctx map[string]interface{}) string { + var config string + config += nprintf.Nprintf(` +data "equinix_network_account" "test" { + metro_code = "%{device-metro_code}" + status = "Active" + project_id = "%{device-project_id}"`, ctx) + if v, ok := ctx["device-account_name"]; ok && !comparisons.IsEmpty(v) { + config += nprintf.Nprintf(` + name = "%{device-account_name}"`, ctx) + } + config += nprintf.Nprintf(` +}`, ctx) + if _, ok := ctx["device-secondary_metro_code"]; ok { + config += nprintf.Nprintf(` +data "equinix_network_account" "test-secondary" { + metro_code = "%{device-secondary_metro_code}" + status = "Active"`, ctx) + if v, ok := ctx["device-secondary_account_name"]; ok && !comparisons.IsEmpty(v) { + config += nprintf.Nprintf(` + name = "%{device-secondary_account_name}"`, ctx) + } + config += nprintf.Nprintf(` +}`, ctx) + } + config += nprintf.Nprintf(` +resource "equinix_network_device" "%{device-resourceName}" { + self_managed = %{device-self_managed} + byol = %{device-byol} + name = "%{device-name}" + metro_code = "%{device-metro_code}" + type_code = "%{device-type_code}" + project_id = "%{device-project_id}" + package_code = "%{device-package_code}" + notifications = %{device-notifications} + term_length = %{device-term_length} + account_number = data.equinix_network_account.test.number + version = "%{device-version}" + core_count = %{device-core_count}`, ctx) + if _, ok := ctx["device-purchase_order_number"]; ok { + config += nprintf.Nprintf(` + purchase_order_number = "%{device-purchase_order_number}"`, ctx) + } + if _, ok := ctx["device-purchase_order_number"]; ok { + config += nprintf.Nprintf(` + order_reference = "%{device-order_reference}"`, ctx) + } + if _, ok := ctx["device-additional_bandwidth"]; ok { + config += nprintf.Nprintf(` + additional_bandwidth = %{device-additional_bandwidth}`, ctx) + } + if _, ok := ctx["device-throughput"]; ok { + config += nprintf.Nprintf(` + throughput = %{device-throughput} + throughput_unit = "%{device-throughput_unit}"`, ctx) + } + if _, ok := ctx["device-hostname"]; ok { + config += nprintf.Nprintf(` + hostname = "%{device-hostname}"`, ctx) + } + if _, ok := ctx["device-interface_count"]; ok { + config += nprintf.Nprintf(` + interface_count = %{device-interface_count}`, ctx) + } + if _, ok := ctx["acl-resourceName"]; ok { + config += nprintf.Nprintf(` + acl_template_id = equinix_network_acl_template.%{acl-resourceName}.id`, ctx) + } + if _, ok := ctx["mgmtAcl-resourceName"]; ok { + config += nprintf.Nprintf(` + mgmt_acl_template_uuid = equinix_network_acl_template.%{mgmtAcl-resourceName}.id`, ctx) + } + if _, ok := ctx["sshkey-resourceName"]; ok { + config += nprintf.Nprintf(` + ssh_key { + username = "test" + key_name = equinix_network_ssh_key.%{sshkey-resourceName}.name + }`, ctx) + } + if _, ok := ctx["device-license_file"]; ok { + config += nprintf.Nprintf(` + license_file = "%{device-license_file}"`, ctx) + } + if _, ok := ctx["device-vendorConfig_enabled"]; ok { + config += nprintf.Nprintf(` + vendor_configuration = {`, ctx) + if _, ok := ctx["device-vendorConfig_siteId"]; ok { + config += nprintf.Nprintf(` + siteId = "%{device-vendorConfig_siteId}"`, ctx) + } + if _, ok := ctx["device-vendorConfig_systemIpAddress"]; ok { + config += nprintf.Nprintf(` + systemIpAddress = "%{device-vendorConfig_systemIpAddress}"`, ctx) + } + if _, ok := ctx["device-vendorConfig_licenseKey"]; ok { + config += nprintf.Nprintf(` + licenseKey = "%{device-vendorConfig_licenseKey}"`, ctx) + } + if _, ok := ctx["device-vendorConfig_licenseSecret"]; ok { + config += nprintf.Nprintf(` + licenseSecret = "%{device-vendorConfig_licenseSecret}"`, ctx) + } + if _, ok := ctx["device-vendorConfig_controller1"]; ok { + config += nprintf.Nprintf(` + controller1 = "%{device-vendorConfig_controller1}"`, ctx) + } + if _, ok := ctx["device-vendorConfig_controller2"]; ok { + config += nprintf.Nprintf(` + controller2 = "%{device-vendorConfig_controller2}"`, ctx) + } + if _, ok := ctx["device-vendorConfig_localId"]; ok { + config += nprintf.Nprintf(` + localId = "%{device-vendorConfig_localId}"`, ctx) + } + if _, ok := ctx["device-vendorConfig_remoteId"]; ok { + config += nprintf.Nprintf(` + remoteId = "%{device-vendorConfig_remoteId}"`, ctx) + } + if _, ok := ctx["device-vendorConfig_serialNumber"]; ok { + config += nprintf.Nprintf(` + serialNumber = "%{device-vendorConfig_serialNumber}"`, ctx) + } + config += nprintf.Nprintf(` + }`, ctx) + } + if _, ok := ctx["device-secondary_name"]; ok { + config += nprintf.Nprintf(` + secondary_device { + name = "%{device-secondary_name}"`, ctx) + if _, ok := ctx["device-secondary_metro_code"]; ok { + config += nprintf.Nprintf(` + metro_code = "%{device-secondary_metro_code}" + account_number = data.equinix_network_account.test-secondary.number`, ctx) + } else { + config += nprintf.Nprintf(` + metro_code = "%{device-metro_code}" + account_number = data.equinix_network_account.test.number`, ctx) + } + config += nprintf.Nprintf(` + notifications = %{device-secondary_notifications}`, ctx) + if _, ok := ctx["device-secondary_additional_bandwidth"]; ok { + config += nprintf.Nprintf(` + additional_bandwidth = %{device-secondary_additional_bandwidth}`, ctx) + } + if _, ok := ctx["device-secondary_hostname"]; ok { + config += nprintf.Nprintf(` + hostname = "%{device-secondary_hostname}"`, ctx) + } + if _, ok := ctx["acl-secondary_resourceName"]; ok { + config += nprintf.Nprintf(` + acl_template_id = equinix_network_acl_template.%{acl-secondary_resourceName}.id`, ctx) + } + if _, ok := ctx["mgmtAcl-secondary_resourceName"]; ok { + config += nprintf.Nprintf(` + mgmt_acl_template_uuid = equinix_network_acl_template.%{mgmtAcl-secondary_resourceName}.id`, ctx) + } + if _, ok := ctx["sshkey-resourceName"]; ok { + config += nprintf.Nprintf(` + ssh_key { + username = "test" + key_name = equinix_network_ssh_key.%{sshkey-resourceName}.name + }`, ctx) + } + if _, ok := ctx["device-secondary_license_file"]; ok { + config += nprintf.Nprintf(` + license_file = "%{device-secondary_license_file}"`, ctx) + } + if _, ok := ctx["device-secondary_vendorConfig_enabled"]; ok { + config += nprintf.Nprintf(` + vendor_configuration = {`, ctx) + if _, ok := ctx["device-secondary_vendorConfig_siteId"]; ok { + config += nprintf.Nprintf(` + siteId = "%{device-secondary_vendorConfig_siteId}"`, ctx) + } + if _, ok := ctx["device-secondary_vendorConfig_systemIpAddress"]; ok { + config += nprintf.Nprintf(` + systemIpAddress = "%{device-secondary_vendorConfig_systemIpAddress}"`, ctx) + } + if _, ok := ctx["device-secondary_vendorConfig_licenseKey"]; ok { + config += nprintf.Nprintf(` + licenseKey = "%{device-secondary_vendorConfig_licenseKey}"`, ctx) + } + if _, ok := ctx["device-secondary_vendorConfig_licenseSecret"]; ok { + config += nprintf.Nprintf(` + licenseSecret = "%{device-secondary_vendorConfig_licenseSecret}"`, ctx) + } + if _, ok := ctx["device-secondary_vendorConfig_controller1"]; ok { + config += nprintf.Nprintf(` + controller1 = "%{device-secondary_vendorConfig_controller1}"`, ctx) + } + if _, ok := ctx["device-secondary_vendorConfig_controller2"]; ok { + config += nprintf.Nprintf(` + controller2 = "%{device-secondary_vendorConfig_controller2}"`, ctx) + } + if _, ok := ctx["device-secondary_vendorConfig_localId"]; ok { + config += nprintf.Nprintf(` + localId = "%{device-secondary_vendorConfig_localId}"`, ctx) + } + if _, ok := ctx["device-secondary_vendorConfig_remoteId"]; ok { + config += nprintf.Nprintf(` + remoteId = "%{device-secondary_vendorConfig_remoteId}"`, ctx) + } + if _, ok := ctx["device-secondary_vendorConfig_serialNumber"]; ok { + config += nprintf.Nprintf(` + serialNumber = "%{device-secondary_vendorConfig_serialNumber}"`, ctx) + } + config += nprintf.Nprintf(` + }`, ctx) + } + config += ` + }` + } + if _, ok := ctx["device-cluster_name"]; ok { + config += nprintf.Nprintf(` + cluster_details { + cluster_name = "%{device-cluster_name}"`, ctx) + config += ` + node0 {` + if _, ok := ctx["device-node0_license_file_id"]; ok { + config += nprintf.Nprintf(` + license_file_id = "%{device-node0_license_file_id}"`, ctx) + } + if _, ok := ctx["device-node0_license_token"]; ok { + config += nprintf.Nprintf(` + license_token = "%{device-node0_license_token}"`, ctx) + } + if _, ok := ctx["device-node0_vendorConfig_enabled"]; ok { + config += nprintf.Nprintf(` + vendor_configuration {`, ctx) + if _, ok := ctx["device-node0_vendorConfig_hostname"]; ok { + config += nprintf.Nprintf(` + hostname = "%{device-node0_vendorConfig_hostname}"`, ctx) + } + if _, ok := ctx["device-node0_vendorConfig_adminPassword"]; ok { + config += nprintf.Nprintf(` + admin_password = "%{device-node0_vendorConfig_adminPassword}"`, ctx) + } + if _, ok := ctx["device-node0_vendorConfig_controller1"]; ok { + config += nprintf.Nprintf(` + controller1 = "%{device-node0_vendorConfig_controller1}"`, ctx) + } + if _, ok := ctx["device-node0_vendorConfig_activationKey"]; ok { + config += nprintf.Nprintf(` + activation_key = "%{device-node0_vendorConfig_activationKey}"`, ctx) + } + if _, ok := ctx["device-node0_vendorConfig_controllerFqdn"]; ok { + config += nprintf.Nprintf(` + controller_fqdn = "%{device-node0_vendorConfig_controllerFqdn}"`, ctx) + } + if _, ok := ctx["device-node0_vendorConfig_rootPassword"]; ok { + config += nprintf.Nprintf(` + root_password = "%{device-node0_vendorConfig_rootPassword}"`, ctx) + } + config += nprintf.Nprintf(` + }`, ctx) + } + config += ` + }` + config += ` + node1 {` + if _, ok := ctx["device-node1_license_file_id"]; ok { + config += nprintf.Nprintf(` + license_file_id = "%{device-node1_license_file_id}"`, ctx) + } + if _, ok := ctx["device-node1_license_token"]; ok { + config += nprintf.Nprintf(` + license_token = "%{device-node1_license_token}"`, ctx) + } + if _, ok := ctx["device-node1_vendorConfig_enabled"]; ok { + config += nprintf.Nprintf(` + vendor_configuration {`, ctx) + if _, ok := ctx["device-node1_vendorConfig_hostname"]; ok { + config += nprintf.Nprintf(` + hostname = "%{device-node1_vendorConfig_hostname}"`, ctx) + } + if _, ok := ctx["device-node1_vendorConfig_adminPassword"]; ok { + config += nprintf.Nprintf(` + admin_password = "%{device-node1_vendorConfig_adminPassword}"`, ctx) + } + if _, ok := ctx["device-node1_vendorConfig_controller1"]; ok { + config += nprintf.Nprintf(` + controller1 = "%{device-node1_vendorConfig_controller1}"`, ctx) + } + if _, ok := ctx["device-node1_vendorConfig_activationKey"]; ok { + config += nprintf.Nprintf(` + activation_key = "%{device-node1_vendorConfig_activationKey}"`, ctx) + } + if _, ok := ctx["device-node1_vendorConfig_controllerFqdn"]; ok { + config += nprintf.Nprintf(` + controller_fqdn = "%{device-node1_vendorConfig_controllerFqdn}"`, ctx) + } + if _, ok := ctx["device-node1_vendorConfig_rootPassword"]; ok { + config += nprintf.Nprintf(` + root_password = "%{device-node1_vendorConfig_rootPassword}"`, ctx) + } + config += nprintf.Nprintf(` + }`, ctx) + } + config += ` + }` + config += ` + }` + } + config += ` +}` + return config +} + +func testAccNetworkDeviceACL(ctx map[string]interface{}) string { + var config string + if _, ok := ctx["acl-name"]; ok { + config += nprintf.Nprintf(` +resource "equinix_network_acl_template" "%{acl-resourceName}" { + name = "%{acl-name}" + description = "%{acl-description}" + inbound_rule { + subnet = "10.0.0.0/24" + protocol = "IP" + src_port = "any" + dst_port = "any" + } +}`, ctx) + } + if _, ok := ctx["mgmtAcl-name"]; ok { + config += nprintf.Nprintf(` +resource "equinix_network_acl_template" "%{mgmtAcl-resourceName}" { + name = "%{mgmtAcl-name}" + description = "%{mgmtAcl-description}" + inbound_rule { + subnet = "11.0.0.0/24" + protocol = "IP" + src_port = "any" + dst_port = "any" + } +}`, ctx) + } + if _, ok := ctx["acl-secondary_name"]; ok { + config += nprintf.Nprintf(` +resource "equinix_network_acl_template" "%{acl-secondary_resourceName}" { + name = "%{acl-secondary_name}" + description = "%{acl-secondary_description}" + inbound_rule { + subnet = "192.0.0.0/24" + protocol = "IP" + src_port = "any" + dst_port = "any" + } +}`, ctx) + } + if _, ok := ctx["mgmtAcl-secondary_name"]; ok { + config += nprintf.Nprintf(` +resource "equinix_network_acl_template" "%{mgmtAcl-secondary_resourceName}" { + name = "%{mgmtAcl-secondary_name}" + description = "%{mgmtAcl-secondary_description}" + inbound_rule { + subnet = "193.0.0.0/24" + protocol = "IP" + src_port = "any" + dst_port = "any" + } +}`, ctx) + } + return config +} + +func testAccNetworkDeviceSSHKey(ctx map[string]interface{}) string { + return nprintf.Nprintf(` +resource "equinix_network_ssh_key" "%{sshkey-resourceName}" { + name = "%{sshkey-name}" + public_key = "%{sshkey-public_key}" +} +`, ctx) +} + +func (t *testAccConfig) withACL() *testAccConfig { + t.config += testAccNetworkDeviceACL(t.ctx) + return t +} + +func (t *testAccConfig) withSSHKey() *testAccConfig { + t.config += testAccNetworkDeviceSSHKey(t.ctx) + return t +} + +func (t *testAccConfig) withSSHUser() *testAccConfig { + t.config += testAccNetworkDeviceUser(t.ctx) + return t +} diff --git a/equinix/data_source_network_device.go b/internal/resources/networkedge/device/data_source.go similarity index 99% rename from equinix/data_source_network_device.go rename to internal/resources/networkedge/device/data_source.go index 3e8e220b9..b0f5a6b22 100644 --- a/equinix/data_source_network_device.go +++ b/internal/resources/networkedge/device/data_source.go @@ -1,4 +1,4 @@ -package equinix +package device import ( "context" @@ -675,7 +675,7 @@ func createDataSourceVendorConfigurationSchema() map[string]*schema.Schema { } } -func dataSourceNetworkDevice() *schema.Resource { +func DataSource() *schema.Resource { return &schema.Resource{ ReadContext: dataSourceNetworkDeviceRead, Description: "Use this data source to get details of Equinix Network Edge network device with a given Name or UUID", diff --git a/equinix/data_source_network_device_test.go b/internal/resources/networkedge/device/data_source_test.go similarity index 98% rename from equinix/data_source_network_device_test.go rename to internal/resources/networkedge/device/data_source_test.go index 82da58233..c21128223 100644 --- a/equinix/data_source_network_device_test.go +++ b/internal/resources/networkedge/device/data_source_test.go @@ -1,4 +1,4 @@ -package equinix +package device import ( "reflect" diff --git a/equinix/resource_network_device.go b/internal/resources/networkedge/device/resource.go similarity index 97% rename from equinix/resource_network_device.go rename to internal/resources/networkedge/device/resource.go index ef5aacfdf..a49bfe4e1 100644 --- a/equinix/resource_network_device.go +++ b/internal/resources/networkedge/device/resource.go @@ -1,4 +1,4 @@ -package equinix +package device import ( "context" @@ -10,6 +10,7 @@ import ( "slices" "time" + "github.com/equinix/terraform-provider-equinix/internal/comparisons" "github.com/equinix/terraform-provider-equinix/internal/config" "github.com/equinix/terraform-provider-equinix/internal/converters" equinix_schema "github.com/equinix/terraform-provider-equinix/internal/schema" @@ -218,7 +219,7 @@ var neDeviceVendorConfigDescriptions = map[string]string{ "PanoramaAuthKey": "Panorama Server Auth Key. This field is relevant only for Palo Alto Networks Firewall devices", } -func resourceNetworkDevice() *schema.Resource { +func Resource() *schema.Resource { return &schema.Resource{ CreateContext: resourceNetworkDeviceCreate, ReadContext: resourceNetworkDeviceRead, @@ -1403,49 +1404,49 @@ func expandNetworkDeviceSecondary(devices []interface{}) *ne.Device { } device := devices[0].(map[string]interface{}) transformed := &ne.Device{} - if v, ok := device[neDeviceSchemaNames["UUID"]]; ok && !isEmpty(v) { + if v, ok := device[neDeviceSchemaNames["UUID"]]; ok && !comparisons.IsEmpty(v) { transformed.UUID = ne.String(v.(string)) } - if v, ok := device[neDeviceSchemaNames["Name"]]; ok && !isEmpty(v) { + if v, ok := device[neDeviceSchemaNames["Name"]]; ok && !comparisons.IsEmpty(v) { transformed.Name = ne.String(v.(string)) } - if v, ok := device[neDeviceSchemaNames["ProjectID"]]; ok && !isEmpty(v) { + if v, ok := device[neDeviceSchemaNames["ProjectID"]]; ok && !comparisons.IsEmpty(v) { transformed.ProjectID = ne.String(v.(string)) } - if v, ok := device[neDeviceSchemaNames["MetroCode"]]; ok && !isEmpty(v) { + if v, ok := device[neDeviceSchemaNames["MetroCode"]]; ok && !comparisons.IsEmpty(v) { transformed.MetroCode = ne.String(v.(string)) } - if v, ok := device[neDeviceSchemaNames["HostName"]]; ok && !isEmpty(v) { + if v, ok := device[neDeviceSchemaNames["HostName"]]; ok && !comparisons.IsEmpty(v) { transformed.HostName = ne.String(v.(string)) } - if v, ok := device[neDeviceSchemaNames["LicenseToken"]]; ok && !isEmpty(v) { + if v, ok := device[neDeviceSchemaNames["LicenseToken"]]; ok && !comparisons.IsEmpty(v) { transformed.LicenseToken = ne.String(v.(string)) } - if v, ok := device[neDeviceSchemaNames["LicenseFile"]]; ok && !isEmpty(v) { + if v, ok := device[neDeviceSchemaNames["LicenseFile"]]; ok && !comparisons.IsEmpty(v) { transformed.LicenseFile = ne.String(v.(string)) } - if v, ok := device[neDeviceSchemaNames["LicenseFileID"]]; ok && !isEmpty(v) { + if v, ok := device[neDeviceSchemaNames["LicenseFileID"]]; ok && !comparisons.IsEmpty(v) { transformed.LicenseFileID = ne.String(v.(string)) } - if v, ok := device[neDeviceSchemaNames["CloudInitFileID"]]; ok && !isEmpty(v) { + if v, ok := device[neDeviceSchemaNames["CloudInitFileID"]]; ok && !comparisons.IsEmpty(v) { transformed.CloudInitFileID = ne.String(v.(string)) } - if v, ok := device[neDeviceSchemaNames["ACLTemplateUUID"]]; ok && !isEmpty(v) { + if v, ok := device[neDeviceSchemaNames["ACLTemplateUUID"]]; ok && !comparisons.IsEmpty(v) { transformed.ACLTemplateUUID = ne.String(v.(string)) } - if v, ok := device[neDeviceSchemaNames["MgmtAclTemplateUuid"]]; ok && !isEmpty(v) { + if v, ok := device[neDeviceSchemaNames["MgmtAclTemplateUuid"]]; ok && !comparisons.IsEmpty(v) { transformed.MgmtAclTemplateUuid = ne.String(v.(string)) } - if v, ok := device[neDeviceSchemaNames["AccountNumber"]]; ok && !isEmpty(v) { + if v, ok := device[neDeviceSchemaNames["AccountNumber"]]; ok && !comparisons.IsEmpty(v) { transformed.AccountNumber = ne.String(v.(string)) } if v, ok := device[neDeviceSchemaNames["Notifications"]]; ok { transformed.Notifications = converters.SetToStringList(v.(*schema.Set)) } - if v, ok := device[neDeviceSchemaNames["AdditionalBandwidth"]]; ok && !isEmpty(v) { + if v, ok := device[neDeviceSchemaNames["AdditionalBandwidth"]]; ok && !comparisons.IsEmpty(v) { transformed.AdditionalBandwidth = ne.Int(v.(int)) } - if v, ok := device[neDeviceSchemaNames["WanInterfaceId"]]; ok && !isEmpty(v) { + if v, ok := device[neDeviceSchemaNames["WanInterfaceId"]]; ok && !comparisons.IsEmpty(v) { transformed.WanInterfaceId = ne.String(v.(string)) } if v, ok := device[neDeviceSchemaNames["VendorConfiguration"]]; ok { @@ -1574,7 +1575,7 @@ func expandNetworkDeviceClusterDetails(clusterDetails []interface{}) *ne.Cluster } clusterDetail := clusterDetails[0].(map[string]interface{}) transformed := &ne.ClusterDetails{} - if v, ok := clusterDetail[neDeviceClusterSchemaNames["ClusterName"]]; ok && !isEmpty(v) { + if v, ok := clusterDetail[neDeviceClusterSchemaNames["ClusterName"]]; ok && !comparisons.IsEmpty(v) { transformed.ClusterName = ne.String(v.(string)) } if v, ok := clusterDetail[neDeviceClusterSchemaNames["Node0"]]; ok { @@ -1596,10 +1597,10 @@ func expandNetworkDeviceClusterNodeDetail(clusterNodeDetails []interface{}) *ne. if v, ok := clusterNodeDetail[neDeviceClusterNodeSchemaNames["VendorConfiguration"]]; ok { transformed.VendorConfiguration = expandVendorConfiguration(v.([]interface{})) } - if v, ok := clusterNodeDetail[neDeviceClusterNodeSchemaNames["LicenseFileId"]]; ok && !isEmpty(v) { + if v, ok := clusterNodeDetail[neDeviceClusterNodeSchemaNames["LicenseFileId"]]; ok && !comparisons.IsEmpty(v) { transformed.LicenseFileId = ne.String(v.(string)) } - if v, ok := clusterNodeDetail[neDeviceClusterNodeSchemaNames["LicenseToken"]]; ok && !isEmpty(v) { + if v, ok := clusterNodeDetail[neDeviceClusterNodeSchemaNames["LicenseToken"]]; ok && !comparisons.IsEmpty(v) { transformed.LicenseToken = ne.String(v.(string)) } return transformed @@ -1612,43 +1613,43 @@ func expandVendorConfiguration(vendorConfigs []interface{}) map[string]string { } vendorConfig := vendorConfigs[0].(map[string]interface{}) transformed := make(map[string]string) - if v, ok := vendorConfig[neDeviceVendorConfigSchemaNames["Hostname"]]; ok && !isEmpty(v) { + if v, ok := vendorConfig[neDeviceVendorConfigSchemaNames["Hostname"]]; ok && !comparisons.IsEmpty(v) { transformed["hostname"] = v.(string) } - if v, ok := vendorConfig[neDeviceVendorConfigSchemaNames["AdminPassword"]]; ok && !isEmpty(v) { + if v, ok := vendorConfig[neDeviceVendorConfigSchemaNames["AdminPassword"]]; ok && !comparisons.IsEmpty(v) { transformed["adminPassword"] = v.(string) } - if v, ok := vendorConfig[neDeviceVendorConfigSchemaNames["Controller1"]]; ok && !isEmpty(v) { + if v, ok := vendorConfig[neDeviceVendorConfigSchemaNames["Controller1"]]; ok && !comparisons.IsEmpty(v) { transformed["controller1"] = v.(string) } - if v, ok := vendorConfig[neDeviceVendorConfigSchemaNames["ActivationKey"]]; ok && !isEmpty(v) { + if v, ok := vendorConfig[neDeviceVendorConfigSchemaNames["ActivationKey"]]; ok && !comparisons.IsEmpty(v) { transformed["activationKey"] = v.(string) } - if v, ok := vendorConfig[neDeviceVendorConfigSchemaNames["ControllerFqdn"]]; ok && !isEmpty(v) { + if v, ok := vendorConfig[neDeviceVendorConfigSchemaNames["ControllerFqdn"]]; ok && !comparisons.IsEmpty(v) { transformed["controllerFqdn"] = v.(string) } - if v, ok := vendorConfig[neDeviceVendorConfigSchemaNames["RootPassword"]]; ok && !isEmpty(v) { + if v, ok := vendorConfig[neDeviceVendorConfigSchemaNames["RootPassword"]]; ok && !comparisons.IsEmpty(v) { transformed["rootPassword"] = v.(string) } - if v, ok := vendorConfig[neDeviceVendorConfigSchemaNames["PrivateAddress"]]; ok && !isEmpty(v) { + if v, ok := vendorConfig[neDeviceVendorConfigSchemaNames["PrivateAddress"]]; ok && !comparisons.IsEmpty(v) { transformed["privateAddress"] = v.(string) } - if v, ok := vendorConfig[neDeviceVendorConfigSchemaNames["PrivateCIDRMask"]]; ok && !isEmpty(v) { + if v, ok := vendorConfig[neDeviceVendorConfigSchemaNames["PrivateCIDRMask"]]; ok && !comparisons.IsEmpty(v) { transformed["privateCidrMask"] = v.(string) } - if v, ok := vendorConfig[neDeviceVendorConfigSchemaNames["LicenseKey"]]; ok && !isEmpty(v) { + if v, ok := vendorConfig[neDeviceVendorConfigSchemaNames["LicenseKey"]]; ok && !comparisons.IsEmpty(v) { transformed["licenseKey"] = v.(string) } - if v, ok := vendorConfig[neDeviceVendorConfigSchemaNames["LicenseID"]]; ok && !isEmpty(v) { + if v, ok := vendorConfig[neDeviceVendorConfigSchemaNames["LicenseID"]]; ok && !comparisons.IsEmpty(v) { transformed["licenseId"] = v.(string) } - if v, ok := vendorConfig[neDeviceVendorConfigSchemaNames["PrivateGateway"]]; ok && !isEmpty(v) { + if v, ok := vendorConfig[neDeviceVendorConfigSchemaNames["PrivateGateway"]]; ok && !comparisons.IsEmpty(v) { transformed["privateGateway"] = v.(string) } - if v, ok := vendorConfig[neDeviceVendorConfigSchemaNames["PanoramaIPAddress"]]; ok && !isEmpty(v) { + if v, ok := vendorConfig[neDeviceVendorConfigSchemaNames["PanoramaIPAddress"]]; ok && !comparisons.IsEmpty(v) { transformed["panoramaIpAddress"] = v.(string) } - if v, ok := vendorConfig[neDeviceVendorConfigSchemaNames["PanoramaAuthKey"]]; ok && !isEmpty(v) { + if v, ok := vendorConfig[neDeviceVendorConfigSchemaNames["PanoramaAuthKey"]]; ok && !comparisons.IsEmpty(v) { transformed["panoramaAuthKey"] = v.(string) } return transformed diff --git a/equinix/resource_network_device_acc_test.go b/internal/resources/networkedge/device/resource_acc_test.go similarity index 79% rename from equinix/resource_network_device_acc_test.go rename to internal/resources/networkedge/device/resource_acc_test.go index 00668a8be..64b6ca84c 100644 --- a/equinix/resource_network_device_acc_test.go +++ b/internal/resources/networkedge/device/resource_acc_test.go @@ -1,11 +1,11 @@ -package equinix +package device import ( - "context" "fmt" - "log" "testing" + "github.com/equinix/terraform-provider-equinix/internal/acceptance" + "github.com/equinix/terraform-provider-equinix/internal/comparisons" "github.com/equinix/terraform-provider-equinix/internal/config" "github.com/equinix/ne-go" @@ -15,73 +15,93 @@ import ( "github.com/hashicorp/terraform-plugin-testing/terraform" ) -const ( - networkDeviceProjectId = "TF_ACC_NETWORK_DEVICE_PROJECT_ID" - networkDeviceAccountNameEnvVar = "TF_ACC_NETWORK_DEVICE_BILLING_ACCOUNT_NAME" - networkDeviceSecondaryAccountNameEnvVar = "TF_ACC_NETWORK_DEVICE_SECONDARY_BILLING_ACCOUNT_NAME" - networkDeviceMetroEnvVar = "TF_ACC_NETWORK_DEVICE_METRO" - networkDeviceSecondaryMetroEnvVar = "TF_ACC_NETWORK_DEVICE_SECONDARY_METRO" - networkDeviceCSRSDWANLicenseFileEnvVar = "TF_ACC_NETWORK_DEVICE_CSRSDWAN_LICENSE_FILE" - networkDeviceVSRXLicenseFileEnvVar = "TF_ACC_NETWORK_DEVICE_VSRX_LICENSE_FILE" - networkDeviceVersaController1EnvVar = "TF_ACC_NETWORK_DEVICE_VERSA_CONTROLLER1" - networkDeviceVersaController2EnvVar = "TF_ACC_NETWORK_DEVICE_VERSA_CONTROLLER2" - networkDeviceVersaLocalIDEnvVar = "TF_ACC_NETWORK_DEVICE_VERSA_LOCALID" - networkDeviceVersaRemoteIDEnvVar = "TF_ACC_NETWORK_DEVICE_VERSA_REMOTEID" - networkDeviceVersaSerialNumberEnvVar = "TF_ACC_NETWORK_DEVICE_VERSA_SERIAL" - networkDeviceCGENIXLicenseKeyEnvVar = "TF_ACC_NETWORK_DEVICE_CGENIX_LICENSE_KEY" - networkDeviceCGENIXLicenseSecretEnvVar = "TF_ACC_NETWORK_DEVICE_CGENIX_LICENSE_SECRET" - networkDevicePANWLicenseTokenEnvVar = "TF_ACC_NETWORK_DEVICE_PANW_LICENSE_TOKEN" -) - -func init() { - resource.AddTestSweepers("equinix_network_device", &resource.Sweeper{ - Name: "equinix_network_device", - Dependencies: []string{"equinix_network_device_link"}, - F: testSweepNetworkDevice, - }) +func testAccNeSSHUserExists(resourceName string, user *ne.SSHUser) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[resourceName] + if !ok { + return fmt.Errorf("resource not found: %s", resourceName) + } + if rs.Primary.ID == "" { + return fmt.Errorf("resource has no ID attribute set") + } + client := acceptance.TestAccProvider.Meta().(*config.Config).Ne + resp, err := client.GetSSHUser(rs.Primary.ID) + if err != nil { + return fmt.Errorf("error when fetching SSH user '%s': %s", rs.Primary.ID, err) + } + *user = *resp + return nil + } } -func testSweepNetworkDevice(region string) error { - config, err := sharedConfigForRegion(region) - if err != nil { - return fmt.Errorf("[INFO][SWEEPER_LOG] Error getting configuration for sweeping Network devices: %s", err) - } - if err := config.Load(context.Background()); err != nil { - log.Printf("[INFO][SWEEPER_LOG] error loading configuration: %s", err) - return err - } - devices, err := config.Ne.GetDevices([]string{ - ne.DeviceStateInitializing, - ne.DeviceStateProvisioned, - ne.DeviceStateProvisioning, - ne.DeviceStateWaitingSecondary, - ne.DeviceStateWaitingClusterNodes, - ne.DeviceStateClusterSetUpInProgress, - ne.DeviceStateFailed, - }) - if err != nil { - log.Printf("[INFO][SWEEPER_LOG] error fetching NetworkDevice list: %s", err) - return err +func testAccNeSSHUserAttributes(user *ne.SSHUser, devices []*ne.Device, ctx map[string]interface{}) resource.TestCheckFunc { + return func(s *terraform.State) error { + if v, ok := ctx["username"]; ok && ne.StringValue(user.Username) != v.(string) { + return fmt.Errorf("name does not match %v - %v", ne.StringValue(user.Username), v) + } + deviceIDs := make([]string, len(devices)) + for i := range devices { + deviceIDs[i] = ne.StringValue(devices[i].UUID) + } + if !comparisons.SlicesMatch(deviceIDs, user.DeviceUUIDs) { + return fmt.Errorf("device_ids does not match %v - %v", deviceIDs, user.DeviceUUIDs) + } + return nil } - nonSweepableCount := 0 - for _, device := range devices { - if !isSweepableTestResource(ne.StringValue(device.Name)) { - nonSweepableCount++ - continue +} + +func testAccNetworkACLTemplateExists(resourceName string, template *ne.ACLTemplate) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[resourceName] + if !ok { + return fmt.Errorf("resource not found: %s", resourceName) } - if ne.StringValue(device.RedundancyType) != "PRIMARY" { - continue + client := acceptance.TestAccProvider.Meta().(*config.Config).Ne + if rs.Primary.ID == "" { + return fmt.Errorf("resource has no ID attribute set") } - if err := config.Ne.DeleteDevice(ne.StringValue(device.UUID)); err != nil { - log.Printf("[INFO][SWEEPER_LOG] error deleting NetworkDevice resource %s (%s): %s", ne.StringValue(device.UUID), ne.StringValue(device.Name), err) - } else { - log.Printf("[INFO][SWEEPER_LOG] sent delete request for NetworkDevice resource %s (%s)", ne.StringValue(device.UUID), ne.StringValue(device.Name)) + resp, err := client.GetACLTemplate(rs.Primary.ID) + if err != nil { + return fmt.Errorf("error when fetching ACL template '%s': %s", rs.Primary.ID, err) } + *template = *resp + return nil } - if nonSweepableCount > 0 { - log.Printf("[INFO][SWEEPER_LOG] %d items were non-sweepable and skipped.", nonSweepableCount) +} + +func testAccNetworkACLTemplateAttributes(template *ne.ACLTemplate, ctx map[string]interface{}) resource.TestCheckFunc { + return func(s *terraform.State) error { + if v, ok := ctx["name"]; ok && ne.StringValue(template.Name) != v.(string) { + return fmt.Errorf("name does not match %v - %v", ne.StringValue(template.Name), v) + } + if v, ok := ctx["description"]; ok && ne.StringValue(template.Description) != v.(string) { + return fmt.Errorf("description does not match %v - %v", ne.StringValue(template.Description), v) + } + if len(template.InboundRules) != 3 { + return fmt.Errorf("number of inbound rules does not match %v - %v", len(template.InboundRules), 3) + } + for i := 0; i < 3; i++ { + if ne.IntValue(template.InboundRules[i].SeqNo) != i+1 { + return fmt.Errorf("inbound_rule %d seqNo does not match %v - %v", i+1, ne.IntValue(template.InboundRules[i].SeqNo), i+1) + } + if v, ok := ctx[fmt.Sprintf("inbound_rule_%d_subnet", i+1)]; ok && ne.StringValue(template.InboundRules[i].Subnet) != v.(string) { + return fmt.Errorf("inbound_rule %d subnet does not match %v - %v", i+1, ne.StringValue(template.InboundRules[i].Subnet), v) + } + if v, ok := ctx[fmt.Sprintf("inbound_rule_%d_protocol", i+1)]; ok && ne.StringValue(template.InboundRules[i].Protocol) != v.(string) { + return fmt.Errorf("inbound_rule %d protocol does not match %v - %v", i+1, ne.StringValue(template.InboundRules[i].Protocol), v) + } + if v, ok := ctx[fmt.Sprintf("inbound_rule_%d_src_port", i+1)]; ok && ne.StringValue(template.InboundRules[i].SrcPort) != v.(string) { + return fmt.Errorf("inbound_rule %d src_port does not match %v - %v", i+1, ne.StringValue(template.InboundRules[i].SrcPort), v) + } + if v, ok := ctx[fmt.Sprintf("inbound_rule_%d_dst_port", i+1)]; ok && ne.StringValue(template.InboundRules[i].DstPort) != v.(string) { + return fmt.Errorf("inbound_rule %d dst_port does not match %v - %v", i+1, ne.StringValue(template.InboundRules[i].DstPort), v) + } + if v, ok := ctx[fmt.Sprintf("inbound_rule_%d_description", i+1)]; ok && ne.StringValue(template.InboundRules[i].Description) != v.(string) { + return fmt.Errorf("inbound_rule %d description does not match %v - %v", i+1, ne.StringValue(template.InboundRules[i].Description), v) + } + } + return nil } - return nil } func TestAccNetworkDevice_CSR1000V_HA_Managed_Sub(t *testing.T) { @@ -132,8 +152,8 @@ func TestAccNetworkDevice_CSR1000V_HA_Managed_Sub(t *testing.T) { var user ne.SSHUser var primaryACL, secondaryACL ne.ACLTemplate resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, + PreCheck: func() { acceptance.TestAccPreCheck(t) }, + Providers: acceptance.TestAccProviders, Steps: []resource.TestStep{ { Config: newTestAccConfig(context).withDevice().withSSHUser().build(), @@ -216,8 +236,8 @@ func TestAccNetworkDevice_CSR1000V_HA_Self_BYOL(t *testing.T) { var primary, secondary ne.Device var primaryACL, secondaryACL ne.ACLTemplate resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, + PreCheck: func() { acceptance.TestAccPreCheck(t) }, + Providers: acceptance.TestAccProviders, Steps: []resource.TestStep{ { Config: newTestAccConfig(context).withDevice().withSSHKey().build(), @@ -283,8 +303,8 @@ func TestAccNetworkDevice_vSRX_HA_Managed_Sub(t *testing.T) { var primary, secondary ne.Device var user ne.SSHUser resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, + PreCheck: func() { acceptance.TestAccPreCheck(t) }, + Providers: acceptance.TestAccProviders, Steps: []resource.TestStep{ { Config: newTestAccConfig(context).withDevice().build(), @@ -367,8 +387,8 @@ func TestAccNetworkDevice_vSRX_HA_Managed_BYOL(t *testing.T) { var primary, secondary ne.Device var user ne.SSHUser resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, + PreCheck: func() { acceptance.TestAccPreCheck(t) }, + Providers: acceptance.TestAccProviders, Steps: []resource.TestStep{ { Config: newTestAccConfig(context).withDevice().withACL().build(), @@ -438,8 +458,8 @@ func TestAccNetworkDevice_vSRX_HA_Self_BYOL(t *testing.T) { deviceResourceName := fmt.Sprintf("equinix_network_device.%s", context["device-resourceName"].(string)) var primary, secondary ne.Device resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, + PreCheck: func() { acceptance.TestAccPreCheck(t) }, + Providers: acceptance.TestAccProviders, Steps: []resource.TestStep{ { Config: newTestAccConfig(context).withDevice().withACL().withSSHKey().build(), @@ -502,8 +522,8 @@ func TestAccNetworkDevice_PaloAlto_HA_Managed_Sub(t *testing.T) { secACLResourceName := fmt.Sprintf("equinix_network_acl_template.%s", context["acl-secondary_resourceName"].(string)) userResourceName := fmt.Sprintf("equinix_network_ssh_user.%s", contextWithChanges["user-resourceName"].(string)) resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, + PreCheck: func() { acceptance.TestAccPreCheck(t) }, + Providers: acceptance.TestAccProviders, Steps: []resource.TestStep{ { Config: newTestAccConfig(context).withDevice().withACL().build(), @@ -582,8 +602,8 @@ func TestAccNetworkDevice_PaloAlto_HA_Self_BYOL(t *testing.T) { var primary, secondary ne.Device var primaryACL, secondaryACL ne.ACLTemplate resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, + PreCheck: func() { acceptance.TestAccPreCheck(t) }, + Providers: acceptance.TestAccProviders, Steps: []resource.TestStep{ { Config: newTestAccConfig(context).withDevice().withSSHKey().build(), @@ -660,8 +680,8 @@ func TestAccNetworkDevice_CSRSDWAN_HA_Self_BYOL(t *testing.T) { var primary, secondary ne.Device var primaryACL, secondaryACL ne.ACLTemplate resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, + PreCheck: func() { acceptance.TestAccPreCheck(t) }, + Providers: acceptance.TestAccProviders, Steps: []resource.TestStep{ { Config: newTestAccConfig(context).withDevice().withACL().build(), @@ -739,8 +759,8 @@ func TestAccNetworkDevice_Versa_HA_Self_BYOL(t *testing.T) { var primary, secondary ne.Device var primaryACL, secondaryACL ne.ACLTemplate resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, + PreCheck: func() { acceptance.TestAccPreCheck(t) }, + Providers: acceptance.TestAccProviders, Steps: []resource.TestStep{ { Config: newTestAccConfig(context).withDevice().withACL().build(), @@ -807,8 +827,8 @@ func TestAccNetworkDevice_CGENIX_HA_Self_BYOL(t *testing.T) { var primary, secondary ne.Device var primaryACL, secondaryACL ne.ACLTemplate resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, + PreCheck: func() { acceptance.TestAccPreCheck(t) }, + Providers: acceptance.TestAccProviders, Steps: []resource.TestStep{ { Config: newTestAccConfig(context).withDevice().withACL().build(), @@ -875,8 +895,8 @@ func TestAccNetworkDevice_PaloAlto_Cluster_Self_BYOL(t *testing.T) { var primary ne.Device var wanAcl, mgmtAcl ne.ACLTemplate resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, + PreCheck: func() { acceptance.TestAccPreCheck(t) }, + Providers: acceptance.TestAccProviders, Steps: []resource.TestStep{ { Config: newTestAccConfig(context).withDevice().withSSHKey().withACL().build(), @@ -912,7 +932,7 @@ func testAccNeDeviceExists(resourceName string, device *ne.Device) resource.Test if rs.Primary.ID == "" { return fmt.Errorf("resource has no ID attribute set") } - client := testAccProvider.Meta().(*config.Config).Ne + client := acceptance.TestAccProvider.Meta().(*config.Config).Ne resp, err := client.GetDevice(rs.Primary.ID) if err != nil { return fmt.Errorf("error when fetching network device '%s': %s", rs.Primary.ID, err) @@ -927,7 +947,7 @@ func testAccNeDeviceSecondaryExists(primary, secondary *ne.Device) resource.Test if ne.StringValue(primary.RedundantUUID) == "" { return fmt.Errorf("secondary device UUID is not set") } - client := testAccProvider.Meta().(*config.Config).Ne + client := acceptance.TestAccProvider.Meta().(*config.Config).Ne resp, err := client.GetDevice(ne.StringValue(primary.RedundantUUID)) if err != nil { return fmt.Errorf("error when fetching network device '%s': %s", ne.StringValue(primary.RedundantUUID), err) @@ -946,7 +966,7 @@ func testAccNeDevicePairExists(resourceName string, primary, secondary *ne.Devic if rs.Primary.ID == "" { return fmt.Errorf("resource has no ID attribute set") } - client := testAccProvider.Meta().(*config.Config).Ne + client := acceptance.TestAccProvider.Meta().(*config.Config).Ne resp, err := client.GetDevice(rs.Primary.ID) if err != nil { return fmt.Errorf("error when fetching primary network device '%s': %s", rs.Primary.ID, err) @@ -987,7 +1007,7 @@ func testAccNeDeviceAttributes(device *ne.Device, ctx map[string]interface{}) re if v, ok := ctx["device-package_code"]; ok && ne.StringValue(device.PackageCode) != v.(string) { return fmt.Errorf("device-package_code does not match %v - %v", ne.StringValue(device.PackageCode), v) } - if v, ok := ctx["device-notifications"]; ok && !slicesMatch(device.Notifications, v.([]string)) { + if v, ok := ctx["device-notifications"]; ok && !comparisons.SlicesMatch(device.Notifications, v.([]string)) { return fmt.Errorf("device-notifications does not match %v - %v", device.Notifications, v) } if v, ok := ctx["device-hostname"]; ok && ne.StringValue(device.HostName) != v.(string) { @@ -1136,7 +1156,7 @@ func testAccNeDeviceACL(resourceName string, device *ne.Device) resource.TestChe } templateId := rs.Primary.ID deviceID := ne.StringValue(device.UUID) - client := testAccProvider.Meta().(*config.Config).Ne + client := acceptance.TestAccProvider.Meta().(*config.Config).Ne if ne.StringValue(device.ACLTemplateUUID) != rs.Primary.ID { return fmt.Errorf("acl_template_id for device %s does not match %v - %v", deviceID, ne.StringValue(device.ACLTemplateUUID), templateId) } @@ -1223,392 +1243,3 @@ func testAccNeDeviceClusterNodeAttributes(device *ne.Device, ctx map[string]inte return nil } } - -func (t *testAccConfig) withDevice() *testAccConfig { - t.config += testAccNetworkDevice(t.ctx) - return t -} - -func (t *testAccConfig) withACL() *testAccConfig { - t.config += testAccNetworkDeviceACL(t.ctx) - return t -} - -func (t *testAccConfig) withSSHKey() *testAccConfig { - t.config += testAccNetworkDeviceSSHKey(t.ctx) - return t -} - -func testAccNetworkDevice(ctx map[string]interface{}) string { - var config string - config += nprintf(` -data "equinix_network_account" "test" { - metro_code = "%{device-metro_code}" - status = "Active" - project_id = "%{device-project_id}"`, ctx) - if v, ok := ctx["device-account_name"]; ok && !isEmpty(v) { - config += nprintf(` - name = "%{device-account_name}"`, ctx) - } - config += nprintf(` -}`, ctx) - if _, ok := ctx["device-secondary_metro_code"]; ok { - config += nprintf(` -data "equinix_network_account" "test-secondary" { - metro_code = "%{device-secondary_metro_code}" - status = "Active"`, ctx) - if v, ok := ctx["device-secondary_account_name"]; ok && !isEmpty(v) { - config += nprintf(` - name = "%{device-secondary_account_name}"`, ctx) - } - config += nprintf(` -}`, ctx) - } - config += nprintf(` -resource "equinix_network_device" "%{device-resourceName}" { - self_managed = %{device-self_managed} - byol = %{device-byol} - name = "%{device-name}" - metro_code = "%{device-metro_code}" - type_code = "%{device-type_code}" - project_id = "%{device-project_id}" - package_code = "%{device-package_code}" - notifications = %{device-notifications} - term_length = %{device-term_length} - account_number = data.equinix_network_account.test.number - version = "%{device-version}" - core_count = %{device-core_count}`, ctx) - if _, ok := ctx["device-purchase_order_number"]; ok { - config += nprintf(` - purchase_order_number = "%{device-purchase_order_number}"`, ctx) - } - if _, ok := ctx["device-purchase_order_number"]; ok { - config += nprintf(` - order_reference = "%{device-order_reference}"`, ctx) - } - if _, ok := ctx["device-additional_bandwidth"]; ok { - config += nprintf(` - additional_bandwidth = %{device-additional_bandwidth}`, ctx) - } - if _, ok := ctx["device-throughput"]; ok { - config += nprintf(` - throughput = %{device-throughput} - throughput_unit = "%{device-throughput_unit}"`, ctx) - } - if _, ok := ctx["device-hostname"]; ok { - config += nprintf(` - hostname = "%{device-hostname}"`, ctx) - } - if _, ok := ctx["device-interface_count"]; ok { - config += nprintf(` - interface_count = %{device-interface_count}`, ctx) - } - if _, ok := ctx["acl-resourceName"]; ok { - config += nprintf(` - acl_template_id = equinix_network_acl_template.%{acl-resourceName}.id`, ctx) - } - if _, ok := ctx["mgmtAcl-resourceName"]; ok { - config += nprintf(` - mgmt_acl_template_uuid = equinix_network_acl_template.%{mgmtAcl-resourceName}.id`, ctx) - } - if _, ok := ctx["sshkey-resourceName"]; ok { - config += nprintf(` - ssh_key { - username = "test" - key_name = equinix_network_ssh_key.%{sshkey-resourceName}.name - }`, ctx) - } - if _, ok := ctx["device-license_file"]; ok { - config += nprintf(` - license_file = "%{device-license_file}"`, ctx) - } - if _, ok := ctx["device-vendorConfig_enabled"]; ok { - config += nprintf(` - vendor_configuration = {`, ctx) - if _, ok := ctx["device-vendorConfig_siteId"]; ok { - config += nprintf(` - siteId = "%{device-vendorConfig_siteId}"`, ctx) - } - if _, ok := ctx["device-vendorConfig_systemIpAddress"]; ok { - config += nprintf(` - systemIpAddress = "%{device-vendorConfig_systemIpAddress}"`, ctx) - } - if _, ok := ctx["device-vendorConfig_licenseKey"]; ok { - config += nprintf(` - licenseKey = "%{device-vendorConfig_licenseKey}"`, ctx) - } - if _, ok := ctx["device-vendorConfig_licenseSecret"]; ok { - config += nprintf(` - licenseSecret = "%{device-vendorConfig_licenseSecret}"`, ctx) - } - if _, ok := ctx["device-vendorConfig_controller1"]; ok { - config += nprintf(` - controller1 = "%{device-vendorConfig_controller1}"`, ctx) - } - if _, ok := ctx["device-vendorConfig_controller2"]; ok { - config += nprintf(` - controller2 = "%{device-vendorConfig_controller2}"`, ctx) - } - if _, ok := ctx["device-vendorConfig_localId"]; ok { - config += nprintf(` - localId = "%{device-vendorConfig_localId}"`, ctx) - } - if _, ok := ctx["device-vendorConfig_remoteId"]; ok { - config += nprintf(` - remoteId = "%{device-vendorConfig_remoteId}"`, ctx) - } - if _, ok := ctx["device-vendorConfig_serialNumber"]; ok { - config += nprintf(` - serialNumber = "%{device-vendorConfig_serialNumber}"`, ctx) - } - config += nprintf(` - }`, ctx) - } - if _, ok := ctx["device-secondary_name"]; ok { - config += nprintf(` - secondary_device { - name = "%{device-secondary_name}"`, ctx) - if _, ok := ctx["device-secondary_metro_code"]; ok { - config += nprintf(` - metro_code = "%{device-secondary_metro_code}" - account_number = data.equinix_network_account.test-secondary.number`, ctx) - } else { - config += nprintf(` - metro_code = "%{device-metro_code}" - account_number = data.equinix_network_account.test.number`, ctx) - } - config += nprintf(` - notifications = %{device-secondary_notifications}`, ctx) - if _, ok := ctx["device-secondary_additional_bandwidth"]; ok { - config += nprintf(` - additional_bandwidth = %{device-secondary_additional_bandwidth}`, ctx) - } - if _, ok := ctx["device-secondary_hostname"]; ok { - config += nprintf(` - hostname = "%{device-secondary_hostname}"`, ctx) - } - if _, ok := ctx["acl-secondary_resourceName"]; ok { - config += nprintf(` - acl_template_id = equinix_network_acl_template.%{acl-secondary_resourceName}.id`, ctx) - } - if _, ok := ctx["mgmtAcl-secondary_resourceName"]; ok { - config += nprintf(` - mgmt_acl_template_uuid = equinix_network_acl_template.%{mgmtAcl-secondary_resourceName}.id`, ctx) - } - if _, ok := ctx["sshkey-resourceName"]; ok { - config += nprintf(` - ssh_key { - username = "test" - key_name = equinix_network_ssh_key.%{sshkey-resourceName}.name - }`, ctx) - } - if _, ok := ctx["device-secondary_license_file"]; ok { - config += nprintf(` - license_file = "%{device-secondary_license_file}"`, ctx) - } - if _, ok := ctx["device-secondary_vendorConfig_enabled"]; ok { - config += nprintf(` - vendor_configuration = {`, ctx) - if _, ok := ctx["device-secondary_vendorConfig_siteId"]; ok { - config += nprintf(` - siteId = "%{device-secondary_vendorConfig_siteId}"`, ctx) - } - if _, ok := ctx["device-secondary_vendorConfig_systemIpAddress"]; ok { - config += nprintf(` - systemIpAddress = "%{device-secondary_vendorConfig_systemIpAddress}"`, ctx) - } - if _, ok := ctx["device-secondary_vendorConfig_licenseKey"]; ok { - config += nprintf(` - licenseKey = "%{device-secondary_vendorConfig_licenseKey}"`, ctx) - } - if _, ok := ctx["device-secondary_vendorConfig_licenseSecret"]; ok { - config += nprintf(` - licenseSecret = "%{device-secondary_vendorConfig_licenseSecret}"`, ctx) - } - if _, ok := ctx["device-secondary_vendorConfig_controller1"]; ok { - config += nprintf(` - controller1 = "%{device-secondary_vendorConfig_controller1}"`, ctx) - } - if _, ok := ctx["device-secondary_vendorConfig_controller2"]; ok { - config += nprintf(` - controller2 = "%{device-secondary_vendorConfig_controller2}"`, ctx) - } - if _, ok := ctx["device-secondary_vendorConfig_localId"]; ok { - config += nprintf(` - localId = "%{device-secondary_vendorConfig_localId}"`, ctx) - } - if _, ok := ctx["device-secondary_vendorConfig_remoteId"]; ok { - config += nprintf(` - remoteId = "%{device-secondary_vendorConfig_remoteId}"`, ctx) - } - if _, ok := ctx["device-secondary_vendorConfig_serialNumber"]; ok { - config += nprintf(` - serialNumber = "%{device-secondary_vendorConfig_serialNumber}"`, ctx) - } - config += nprintf(` - }`, ctx) - } - config += ` - }` - } - if _, ok := ctx["device-cluster_name"]; ok { - config += nprintf(` - cluster_details { - cluster_name = "%{device-cluster_name}"`, ctx) - config += ` - node0 {` - if _, ok := ctx["device-node0_license_file_id"]; ok { - config += nprintf(` - license_file_id = "%{device-node0_license_file_id}"`, ctx) - } - if _, ok := ctx["device-node0_license_token"]; ok { - config += nprintf(` - license_token = "%{device-node0_license_token}"`, ctx) - } - if _, ok := ctx["device-node0_vendorConfig_enabled"]; ok { - config += nprintf(` - vendor_configuration {`, ctx) - if _, ok := ctx["device-node0_vendorConfig_hostname"]; ok { - config += nprintf(` - hostname = "%{device-node0_vendorConfig_hostname}"`, ctx) - } - if _, ok := ctx["device-node0_vendorConfig_adminPassword"]; ok { - config += nprintf(` - admin_password = "%{device-node0_vendorConfig_adminPassword}"`, ctx) - } - if _, ok := ctx["device-node0_vendorConfig_controller1"]; ok { - config += nprintf(` - controller1 = "%{device-node0_vendorConfig_controller1}"`, ctx) - } - if _, ok := ctx["device-node0_vendorConfig_activationKey"]; ok { - config += nprintf(` - activation_key = "%{device-node0_vendorConfig_activationKey}"`, ctx) - } - if _, ok := ctx["device-node0_vendorConfig_controllerFqdn"]; ok { - config += nprintf(` - controller_fqdn = "%{device-node0_vendorConfig_controllerFqdn}"`, ctx) - } - if _, ok := ctx["device-node0_vendorConfig_rootPassword"]; ok { - config += nprintf(` - root_password = "%{device-node0_vendorConfig_rootPassword}"`, ctx) - } - config += nprintf(` - }`, ctx) - } - config += ` - }` - config += ` - node1 {` - if _, ok := ctx["device-node1_license_file_id"]; ok { - config += nprintf(` - license_file_id = "%{device-node1_license_file_id}"`, ctx) - } - if _, ok := ctx["device-node1_license_token"]; ok { - config += nprintf(` - license_token = "%{device-node1_license_token}"`, ctx) - } - if _, ok := ctx["device-node1_vendorConfig_enabled"]; ok { - config += nprintf(` - vendor_configuration {`, ctx) - if _, ok := ctx["device-node1_vendorConfig_hostname"]; ok { - config += nprintf(` - hostname = "%{device-node1_vendorConfig_hostname}"`, ctx) - } - if _, ok := ctx["device-node1_vendorConfig_adminPassword"]; ok { - config += nprintf(` - admin_password = "%{device-node1_vendorConfig_adminPassword}"`, ctx) - } - if _, ok := ctx["device-node1_vendorConfig_controller1"]; ok { - config += nprintf(` - controller1 = "%{device-node1_vendorConfig_controller1}"`, ctx) - } - if _, ok := ctx["device-node1_vendorConfig_activationKey"]; ok { - config += nprintf(` - activation_key = "%{device-node1_vendorConfig_activationKey}"`, ctx) - } - if _, ok := ctx["device-node1_vendorConfig_controllerFqdn"]; ok { - config += nprintf(` - controller_fqdn = "%{device-node1_vendorConfig_controllerFqdn}"`, ctx) - } - if _, ok := ctx["device-node1_vendorConfig_rootPassword"]; ok { - config += nprintf(` - root_password = "%{device-node1_vendorConfig_rootPassword}"`, ctx) - } - config += nprintf(` - }`, ctx) - } - config += ` - }` - config += ` - }` - } - config += ` -}` - return config -} - -func testAccNetworkDeviceACL(ctx map[string]interface{}) string { - var config string - if _, ok := ctx["acl-name"]; ok { - config += nprintf(` -resource "equinix_network_acl_template" "%{acl-resourceName}" { - name = "%{acl-name}" - description = "%{acl-description}" - inbound_rule { - subnet = "10.0.0.0/24" - protocol = "IP" - src_port = "any" - dst_port = "any" - } -}`, ctx) - } - if _, ok := ctx["mgmtAcl-name"]; ok { - config += nprintf(` -resource "equinix_network_acl_template" "%{mgmtAcl-resourceName}" { - name = "%{mgmtAcl-name}" - description = "%{mgmtAcl-description}" - inbound_rule { - subnet = "11.0.0.0/24" - protocol = "IP" - src_port = "any" - dst_port = "any" - } -}`, ctx) - } - if _, ok := ctx["acl-secondary_name"]; ok { - config += nprintf(` -resource "equinix_network_acl_template" "%{acl-secondary_resourceName}" { - name = "%{acl-secondary_name}" - description = "%{acl-secondary_description}" - inbound_rule { - subnet = "192.0.0.0/24" - protocol = "IP" - src_port = "any" - dst_port = "any" - } -}`, ctx) - } - if _, ok := ctx["mgmtAcl-secondary_name"]; ok { - config += nprintf(` -resource "equinix_network_acl_template" "%{mgmtAcl-secondary_resourceName}" { - name = "%{mgmtAcl-secondary_name}" - description = "%{mgmtAcl-secondary_description}" - inbound_rule { - subnet = "193.0.0.0/24" - protocol = "IP" - src_port = "any" - dst_port = "any" - } -}`, ctx) - } - return config -} - -func testAccNetworkDeviceSSHKey(ctx map[string]interface{}) string { - return nprintf(` -resource "equinix_network_ssh_key" "%{sshkey-resourceName}" { - name = "%{sshkey-name}" - public_key = "%{sshkey-public_key}" -} -`, ctx) -} diff --git a/equinix/resource_network_device_test.go b/internal/resources/networkedge/device/resource_test.go similarity index 99% rename from equinix/resource_network_device_test.go rename to internal/resources/networkedge/device/resource_test.go index aefe03992..9ec3fdda1 100644 --- a/equinix/resource_network_device_test.go +++ b/internal/resources/networkedge/device/resource_test.go @@ -1,4 +1,4 @@ -package equinix +package device import ( "context" @@ -9,9 +9,10 @@ import ( "time" "github.com/equinix/ne-go" - "github.com/equinix/terraform-provider-equinix/internal/converters" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/stretchr/testify/assert" + + "github.com/equinix/terraform-provider-equinix/internal/converters" ) func TestNetworkDevice_createFromResourceData(t *testing.T) { diff --git a/internal/resources/networkedge/device/sweeper.go b/internal/resources/networkedge/device/sweeper.go new file mode 100644 index 000000000..e2059a5d5 --- /dev/null +++ b/internal/resources/networkedge/device/sweeper.go @@ -0,0 +1,63 @@ +package device + +import ( + "context" + "fmt" + "log" + + "github.com/equinix/ne-go" + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + + "github.com/equinix/terraform-provider-equinix/internal/sweep" +) + +func AddTestSweeper() { + resource.AddTestSweepers("equinix_network_device", &resource.Sweeper{ + Name: "equinix_network_device", + Dependencies: []string{"equinix_network_device_link"}, + F: testSweepNetworkDevice, + }) +} + +func testSweepNetworkDevice(region string) error { + config, err := sweep.SharedConfigForRegion(region) + if err != nil { + return fmt.Errorf("[INFO][SWEEPER_LOG] Error getting configuration for sweeping Network devices: %s", err) + } + if err := config.Load(context.Background()); err != nil { + log.Printf("[INFO][SWEEPER_LOG] error loading configuration: %s", err) + return err + } + devices, err := config.Ne.GetDevices([]string{ + ne.DeviceStateInitializing, + ne.DeviceStateProvisioned, + ne.DeviceStateProvisioning, + ne.DeviceStateWaitingSecondary, + ne.DeviceStateWaitingClusterNodes, + ne.DeviceStateClusterSetUpInProgress, + ne.DeviceStateFailed, + }) + if err != nil { + log.Printf("[INFO][SWEEPER_LOG] error fetching NetworkDevice list: %s", err) + return err + } + nonSweepableCount := 0 + for _, device := range devices { + if !sweep.IsSweepableTestResource(ne.StringValue(device.Name)) { + nonSweepableCount++ + continue + } + if ne.StringValue(device.RedundancyType) != "PRIMARY" { + continue + } + if err := config.Ne.DeleteDevice(ne.StringValue(device.UUID)); err != nil { + log.Printf("[INFO][SWEEPER_LOG] error deleting NetworkDevice resource %s (%s): %s", ne.StringValue(device.UUID), ne.StringValue(device.Name), err) + } else { + log.Printf("[INFO][SWEEPER_LOG] sent delete request for NetworkDevice resource %s (%s)", ne.StringValue(device.UUID), ne.StringValue(device.Name)) + } + } + if nonSweepableCount > 0 { + log.Printf("[INFO][SWEEPER_LOG] %d items were non-sweepable and skipped.", nonSweepableCount) + } + return nil +} diff --git a/internal/resources/networkedge/device/templates_acc_test.go b/internal/resources/networkedge/device/templates_acc_test.go new file mode 100644 index 000000000..129037117 --- /dev/null +++ b/internal/resources/networkedge/device/templates_acc_test.go @@ -0,0 +1,461 @@ +package device + +import ( + "github.com/equinix/terraform-provider-equinix/internal/comparisons" + "github.com/equinix/terraform-provider-equinix/internal/nprintf" +) + +const ( + tstResourcePrefix = "tfacc" + + networkDeviceProjectId = "TF_ACC_NETWORK_DEVICE_PROJECT_ID" + networkDeviceAccountNameEnvVar = "TF_ACC_NETWORK_DEVICE_BILLING_ACCOUNT_NAME" + networkDeviceSecondaryAccountNameEnvVar = "TF_ACC_NETWORK_DEVICE_SECONDARY_BILLING_ACCOUNT_NAME" + networkDeviceMetroEnvVar = "TF_ACC_NETWORK_DEVICE_METRO" + networkDeviceSecondaryMetroEnvVar = "TF_ACC_NETWORK_DEVICE_SECONDARY_METRO" + networkDeviceCSRSDWANLicenseFileEnvVar = "TF_ACC_NETWORK_DEVICE_CSRSDWAN_LICENSE_FILE" + networkDeviceVSRXLicenseFileEnvVar = "TF_ACC_NETWORK_DEVICE_VSRX_LICENSE_FILE" + networkDeviceVersaController1EnvVar = "TF_ACC_NETWORK_DEVICE_VERSA_CONTROLLER1" + networkDeviceVersaController2EnvVar = "TF_ACC_NETWORK_DEVICE_VERSA_CONTROLLER2" + networkDeviceVersaLocalIDEnvVar = "TF_ACC_NETWORK_DEVICE_VERSA_LOCALID" + networkDeviceVersaRemoteIDEnvVar = "TF_ACC_NETWORK_DEVICE_VERSA_REMOTEID" + networkDeviceVersaSerialNumberEnvVar = "TF_ACC_NETWORK_DEVICE_VERSA_SERIAL" + networkDeviceCGENIXLicenseKeyEnvVar = "TF_ACC_NETWORK_DEVICE_CGENIX_LICENSE_KEY" + networkDeviceCGENIXLicenseSecretEnvVar = "TF_ACC_NETWORK_DEVICE_CGENIX_LICENSE_SECRET" + networkDevicePANWLicenseTokenEnvVar = "TF_ACC_NETWORK_DEVICE_PANW_LICENSE_TOKEN" +) + +type testAccConfig struct { + ctx map[string]interface{} + config string +} + +func newTestAccConfig(ctx map[string]interface{}) *testAccConfig { + return &testAccConfig{ + ctx: ctx, + config: "", + } +} + +func (t *testAccConfig) build() string { + return t.config +} + +func (t *testAccConfig) withDevice() *testAccConfig { + t.config += testAccNetworkDevice(t.ctx) + return t +} + +func copyMap(source map[string]interface{}) map[string]interface{} { + target := make(map[string]interface{}) + for k, v := range source { + target[k] = v + } + return target +} + +func testAccNetworkDeviceUser(ctx map[string]interface{}) string { + config := nprintf.Nprintf(` +resource "equinix_network_ssh_user" "%{user-resourceName}" { + username = "%{user-username}" + password = "%{user-password}" + device_ids = [ + equinix_network_device.%{device-resourceName}.id`, ctx) + if _, ok := ctx["device-secondary_name"]; ok { + config += nprintf.Nprintf(`, + equinix_network_device.%{device-resourceName}.redundant_id`, ctx) + } + config += ` + ] +}` + return config +} + +func testAccNetworkDevice(ctx map[string]interface{}) string { + var config string + config += nprintf.Nprintf(` +data "equinix_network_account" "test" { + metro_code = "%{device-metro_code}" + status = "Active" + project_id = "%{device-project_id}"`, ctx) + if v, ok := ctx["device-account_name"]; ok && !comparisons.IsEmpty(v) { + config += nprintf.Nprintf(` + name = "%{device-account_name}"`, ctx) + } + config += nprintf.Nprintf(` +}`, ctx) + if _, ok := ctx["device-secondary_metro_code"]; ok { + config += nprintf.Nprintf(` +data "equinix_network_account" "test-secondary" { + metro_code = "%{device-secondary_metro_code}" + status = "Active"`, ctx) + if v, ok := ctx["device-secondary_account_name"]; ok && !comparisons.IsEmpty(v) { + config += nprintf.Nprintf(` + name = "%{device-secondary_account_name}"`, ctx) + } + config += nprintf.Nprintf(` +}`, ctx) + } + config += nprintf.Nprintf(` +resource "equinix_network_device" "%{device-resourceName}" { + self_managed = %{device-self_managed} + byol = %{device-byol} + name = "%{device-name}" + metro_code = "%{device-metro_code}" + type_code = "%{device-type_code}" + project_id = "%{device-project_id}" + package_code = "%{device-package_code}" + notifications = %{device-notifications} + term_length = %{device-term_length} + account_number = data.equinix_network_account.test.number + version = "%{device-version}" + core_count = %{device-core_count}`, ctx) + if _, ok := ctx["device-purchase_order_number"]; ok { + config += nprintf.Nprintf(` + purchase_order_number = "%{device-purchase_order_number}"`, ctx) + } + if _, ok := ctx["device-purchase_order_number"]; ok { + config += nprintf.Nprintf(` + order_reference = "%{device-order_reference}"`, ctx) + } + if _, ok := ctx["device-additional_bandwidth"]; ok { + config += nprintf.Nprintf(` + additional_bandwidth = %{device-additional_bandwidth}`, ctx) + } + if _, ok := ctx["device-throughput"]; ok { + config += nprintf.Nprintf(` + throughput = %{device-throughput} + throughput_unit = "%{device-throughput_unit}"`, ctx) + } + if _, ok := ctx["device-hostname"]; ok { + config += nprintf.Nprintf(` + hostname = "%{device-hostname}"`, ctx) + } + if _, ok := ctx["device-interface_count"]; ok { + config += nprintf.Nprintf(` + interface_count = %{device-interface_count}`, ctx) + } + if _, ok := ctx["acl-resourceName"]; ok { + config += nprintf.Nprintf(` + acl_template_id = equinix_network_acl_template.%{acl-resourceName}.id`, ctx) + } + if _, ok := ctx["mgmtAcl-resourceName"]; ok { + config += nprintf.Nprintf(` + mgmt_acl_template_uuid = equinix_network_acl_template.%{mgmtAcl-resourceName}.id`, ctx) + } + if _, ok := ctx["sshkey-resourceName"]; ok { + config += nprintf.Nprintf(` + ssh_key { + username = "test" + key_name = equinix_network_ssh_key.%{sshkey-resourceName}.name + }`, ctx) + } + if _, ok := ctx["device-license_file"]; ok { + config += nprintf.Nprintf(` + license_file = "%{device-license_file}"`, ctx) + } + if _, ok := ctx["device-vendorConfig_enabled"]; ok { + config += nprintf.Nprintf(` + vendor_configuration = {`, ctx) + if _, ok := ctx["device-vendorConfig_siteId"]; ok { + config += nprintf.Nprintf(` + siteId = "%{device-vendorConfig_siteId}"`, ctx) + } + if _, ok := ctx["device-vendorConfig_systemIpAddress"]; ok { + config += nprintf.Nprintf(` + systemIpAddress = "%{device-vendorConfig_systemIpAddress}"`, ctx) + } + if _, ok := ctx["device-vendorConfig_licenseKey"]; ok { + config += nprintf.Nprintf(` + licenseKey = "%{device-vendorConfig_licenseKey}"`, ctx) + } + if _, ok := ctx["device-vendorConfig_licenseSecret"]; ok { + config += nprintf.Nprintf(` + licenseSecret = "%{device-vendorConfig_licenseSecret}"`, ctx) + } + if _, ok := ctx["device-vendorConfig_controller1"]; ok { + config += nprintf.Nprintf(` + controller1 = "%{device-vendorConfig_controller1}"`, ctx) + } + if _, ok := ctx["device-vendorConfig_controller2"]; ok { + config += nprintf.Nprintf(` + controller2 = "%{device-vendorConfig_controller2}"`, ctx) + } + if _, ok := ctx["device-vendorConfig_localId"]; ok { + config += nprintf.Nprintf(` + localId = "%{device-vendorConfig_localId}"`, ctx) + } + if _, ok := ctx["device-vendorConfig_remoteId"]; ok { + config += nprintf.Nprintf(` + remoteId = "%{device-vendorConfig_remoteId}"`, ctx) + } + if _, ok := ctx["device-vendorConfig_serialNumber"]; ok { + config += nprintf.Nprintf(` + serialNumber = "%{device-vendorConfig_serialNumber}"`, ctx) + } + config += nprintf.Nprintf(` + }`, ctx) + } + if _, ok := ctx["device-secondary_name"]; ok { + config += nprintf.Nprintf(` + secondary_device { + name = "%{device-secondary_name}"`, ctx) + if _, ok := ctx["device-secondary_metro_code"]; ok { + config += nprintf.Nprintf(` + metro_code = "%{device-secondary_metro_code}" + account_number = data.equinix_network_account.test-secondary.number`, ctx) + } else { + config += nprintf.Nprintf(` + metro_code = "%{device-metro_code}" + account_number = data.equinix_network_account.test.number`, ctx) + } + config += nprintf.Nprintf(` + notifications = %{device-secondary_notifications}`, ctx) + if _, ok := ctx["device-secondary_additional_bandwidth"]; ok { + config += nprintf.Nprintf(` + additional_bandwidth = %{device-secondary_additional_bandwidth}`, ctx) + } + if _, ok := ctx["device-secondary_hostname"]; ok { + config += nprintf.Nprintf(` + hostname = "%{device-secondary_hostname}"`, ctx) + } + if _, ok := ctx["acl-secondary_resourceName"]; ok { + config += nprintf.Nprintf(` + acl_template_id = equinix_network_acl_template.%{acl-secondary_resourceName}.id`, ctx) + } + if _, ok := ctx["mgmtAcl-secondary_resourceName"]; ok { + config += nprintf.Nprintf(` + mgmt_acl_template_uuid = equinix_network_acl_template.%{mgmtAcl-secondary_resourceName}.id`, ctx) + } + if _, ok := ctx["sshkey-resourceName"]; ok { + config += nprintf.Nprintf(` + ssh_key { + username = "test" + key_name = equinix_network_ssh_key.%{sshkey-resourceName}.name + }`, ctx) + } + if _, ok := ctx["device-secondary_license_file"]; ok { + config += nprintf.Nprintf(` + license_file = "%{device-secondary_license_file}"`, ctx) + } + if _, ok := ctx["device-secondary_vendorConfig_enabled"]; ok { + config += nprintf.Nprintf(` + vendor_configuration = {`, ctx) + if _, ok := ctx["device-secondary_vendorConfig_siteId"]; ok { + config += nprintf.Nprintf(` + siteId = "%{device-secondary_vendorConfig_siteId}"`, ctx) + } + if _, ok := ctx["device-secondary_vendorConfig_systemIpAddress"]; ok { + config += nprintf.Nprintf(` + systemIpAddress = "%{device-secondary_vendorConfig_systemIpAddress}"`, ctx) + } + if _, ok := ctx["device-secondary_vendorConfig_licenseKey"]; ok { + config += nprintf.Nprintf(` + licenseKey = "%{device-secondary_vendorConfig_licenseKey}"`, ctx) + } + if _, ok := ctx["device-secondary_vendorConfig_licenseSecret"]; ok { + config += nprintf.Nprintf(` + licenseSecret = "%{device-secondary_vendorConfig_licenseSecret}"`, ctx) + } + if _, ok := ctx["device-secondary_vendorConfig_controller1"]; ok { + config += nprintf.Nprintf(` + controller1 = "%{device-secondary_vendorConfig_controller1}"`, ctx) + } + if _, ok := ctx["device-secondary_vendorConfig_controller2"]; ok { + config += nprintf.Nprintf(` + controller2 = "%{device-secondary_vendorConfig_controller2}"`, ctx) + } + if _, ok := ctx["device-secondary_vendorConfig_localId"]; ok { + config += nprintf.Nprintf(` + localId = "%{device-secondary_vendorConfig_localId}"`, ctx) + } + if _, ok := ctx["device-secondary_vendorConfig_remoteId"]; ok { + config += nprintf.Nprintf(` + remoteId = "%{device-secondary_vendorConfig_remoteId}"`, ctx) + } + if _, ok := ctx["device-secondary_vendorConfig_serialNumber"]; ok { + config += nprintf.Nprintf(` + serialNumber = "%{device-secondary_vendorConfig_serialNumber}"`, ctx) + } + config += nprintf.Nprintf(` + }`, ctx) + } + config += ` + }` + } + if _, ok := ctx["device-cluster_name"]; ok { + config += nprintf.Nprintf(` + cluster_details { + cluster_name = "%{device-cluster_name}"`, ctx) + config += ` + node0 {` + if _, ok := ctx["device-node0_license_file_id"]; ok { + config += nprintf.Nprintf(` + license_file_id = "%{device-node0_license_file_id}"`, ctx) + } + if _, ok := ctx["device-node0_license_token"]; ok { + config += nprintf.Nprintf(` + license_token = "%{device-node0_license_token}"`, ctx) + } + if _, ok := ctx["device-node0_vendorConfig_enabled"]; ok { + config += nprintf.Nprintf(` + vendor_configuration {`, ctx) + if _, ok := ctx["device-node0_vendorConfig_hostname"]; ok { + config += nprintf.Nprintf(` + hostname = "%{device-node0_vendorConfig_hostname}"`, ctx) + } + if _, ok := ctx["device-node0_vendorConfig_adminPassword"]; ok { + config += nprintf.Nprintf(` + admin_password = "%{device-node0_vendorConfig_adminPassword}"`, ctx) + } + if _, ok := ctx["device-node0_vendorConfig_controller1"]; ok { + config += nprintf.Nprintf(` + controller1 = "%{device-node0_vendorConfig_controller1}"`, ctx) + } + if _, ok := ctx["device-node0_vendorConfig_activationKey"]; ok { + config += nprintf.Nprintf(` + activation_key = "%{device-node0_vendorConfig_activationKey}"`, ctx) + } + if _, ok := ctx["device-node0_vendorConfig_controllerFqdn"]; ok { + config += nprintf.Nprintf(` + controller_fqdn = "%{device-node0_vendorConfig_controllerFqdn}"`, ctx) + } + if _, ok := ctx["device-node0_vendorConfig_rootPassword"]; ok { + config += nprintf.Nprintf(` + root_password = "%{device-node0_vendorConfig_rootPassword}"`, ctx) + } + config += nprintf.Nprintf(` + }`, ctx) + } + config += ` + }` + config += ` + node1 {` + if _, ok := ctx["device-node1_license_file_id"]; ok { + config += nprintf.Nprintf(` + license_file_id = "%{device-node1_license_file_id}"`, ctx) + } + if _, ok := ctx["device-node1_license_token"]; ok { + config += nprintf.Nprintf(` + license_token = "%{device-node1_license_token}"`, ctx) + } + if _, ok := ctx["device-node1_vendorConfig_enabled"]; ok { + config += nprintf.Nprintf(` + vendor_configuration {`, ctx) + if _, ok := ctx["device-node1_vendorConfig_hostname"]; ok { + config += nprintf.Nprintf(` + hostname = "%{device-node1_vendorConfig_hostname}"`, ctx) + } + if _, ok := ctx["device-node1_vendorConfig_adminPassword"]; ok { + config += nprintf.Nprintf(` + admin_password = "%{device-node1_vendorConfig_adminPassword}"`, ctx) + } + if _, ok := ctx["device-node1_vendorConfig_controller1"]; ok { + config += nprintf.Nprintf(` + controller1 = "%{device-node1_vendorConfig_controller1}"`, ctx) + } + if _, ok := ctx["device-node1_vendorConfig_activationKey"]; ok { + config += nprintf.Nprintf(` + activation_key = "%{device-node1_vendorConfig_activationKey}"`, ctx) + } + if _, ok := ctx["device-node1_vendorConfig_controllerFqdn"]; ok { + config += nprintf.Nprintf(` + controller_fqdn = "%{device-node1_vendorConfig_controllerFqdn}"`, ctx) + } + if _, ok := ctx["device-node1_vendorConfig_rootPassword"]; ok { + config += nprintf.Nprintf(` + root_password = "%{device-node1_vendorConfig_rootPassword}"`, ctx) + } + config += nprintf.Nprintf(` + }`, ctx) + } + config += ` + }` + config += ` + }` + } + config += ` +}` + return config +} + +func testAccNetworkDeviceACL(ctx map[string]interface{}) string { + var config string + if _, ok := ctx["acl-name"]; ok { + config += nprintf.Nprintf(` +resource "equinix_network_acl_template" "%{acl-resourceName}" { + name = "%{acl-name}" + description = "%{acl-description}" + inbound_rule { + subnet = "10.0.0.0/24" + protocol = "IP" + src_port = "any" + dst_port = "any" + } +}`, ctx) + } + if _, ok := ctx["mgmtAcl-name"]; ok { + config += nprintf.Nprintf(` +resource "equinix_network_acl_template" "%{mgmtAcl-resourceName}" { + name = "%{mgmtAcl-name}" + description = "%{mgmtAcl-description}" + inbound_rule { + subnet = "11.0.0.0/24" + protocol = "IP" + src_port = "any" + dst_port = "any" + } +}`, ctx) + } + if _, ok := ctx["acl-secondary_name"]; ok { + config += nprintf.Nprintf(` +resource "equinix_network_acl_template" "%{acl-secondary_resourceName}" { + name = "%{acl-secondary_name}" + description = "%{acl-secondary_description}" + inbound_rule { + subnet = "192.0.0.0/24" + protocol = "IP" + src_port = "any" + dst_port = "any" + } +}`, ctx) + } + if _, ok := ctx["mgmtAcl-secondary_name"]; ok { + config += nprintf.Nprintf(` +resource "equinix_network_acl_template" "%{mgmtAcl-secondary_resourceName}" { + name = "%{mgmtAcl-secondary_name}" + description = "%{mgmtAcl-secondary_description}" + inbound_rule { + subnet = "193.0.0.0/24" + protocol = "IP" + src_port = "any" + dst_port = "any" + } +}`, ctx) + } + return config +} + +func testAccNetworkDeviceSSHKey(ctx map[string]interface{}) string { + return nprintf.Nprintf(` +resource "equinix_network_ssh_key" "%{sshkey-resourceName}" { + name = "%{sshkey-name}" + public_key = "%{sshkey-public_key}" +} +`, ctx) +} + +func (t *testAccConfig) withACL() *testAccConfig { + t.config += testAccNetworkDeviceACL(t.ctx) + return t +} + +func (t *testAccConfig) withSSHKey() *testAccConfig { + t.config += testAccNetworkDeviceSSHKey(t.ctx) + return t +} + +func (t *testAccConfig) withSSHUser() *testAccConfig { + t.config += testAccNetworkDeviceUser(t.ctx) + return t +} diff --git a/equinix/resource_network_device_link.go b/internal/resources/networkedge/device_link/resource.go similarity index 99% rename from equinix/resource_network_device_link.go rename to internal/resources/networkedge/device_link/resource.go index 64639086f..33a83d016 100644 --- a/equinix/resource_network_device_link.go +++ b/internal/resources/networkedge/device_link/resource.go @@ -1,4 +1,4 @@ -package equinix +package device_link import ( "context" @@ -99,7 +99,7 @@ var networkDeviceLinkDeprecatedDescriptions = map[string]string{ "DestinationZoneCode": "DestinationZoneCode is not required", } -func resourceNetworkDeviceLink() *schema.Resource { +func Resource() *schema.Resource { return &schema.Resource{ CreateContext: resourceNetworkDeviceLinkCreate, ReadContext: resourceNetworkDeviceLinkRead, diff --git a/equinix/resource_network_device_link_acc_test.go b/internal/resources/networkedge/device_link/resource_acc_test.go similarity index 86% rename from equinix/resource_network_device_link_acc_test.go rename to internal/resources/networkedge/device_link/resource_acc_test.go index ea0d3e254..8913ecb14 100644 --- a/equinix/resource_network_device_link_acc_test.go +++ b/internal/resources/networkedge/device_link/resource_acc_test.go @@ -1,12 +1,12 @@ -package equinix +package device_link import ( - "context" "fmt" - "log" "testing" + "github.com/equinix/terraform-provider-equinix/internal/acceptance" "github.com/equinix/terraform-provider-equinix/internal/config" + "github.com/equinix/terraform-provider-equinix/internal/nprintf" "github.com/equinix/ne-go" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" @@ -15,43 +15,28 @@ import ( "github.com/hashicorp/terraform-plugin-testing/terraform" ) -func init() { - resource.AddTestSweepers("equinix_network_device_link", &resource.Sweeper{ - Name: "equinix_network_device_link", - F: testSweepNetworkDeviceLink, - }) -} - -func testSweepNetworkDeviceLink(region string) error { - config, err := sharedConfigForRegion(region) - if err != nil { - return fmt.Errorf("[INFO][SWEEPER_LOG] Error getting configuration for sweeping Network devices link: %s", err) - } - if err := config.Load(context.Background()); err != nil { - log.Printf("[INFO][SWEEPER_LOG] error loading configuration: %s", err) - return err - } - links, err := config.Ne.GetDeviceLinkGroups() - if err != nil { - log.Printf("[INFO][SWEEPER_LOG] error fetching device links list: %s", err) - return err - } - nonSweepableCount := 0 - for _, link := range links { - if !isSweepableTestResource(ne.StringValue(link.Name)) { - nonSweepableCount++ - continue +func testAccNeDevicePairExists(resourceName string, primary, secondary *ne.Device) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[resourceName] + if !ok { + return fmt.Errorf("resource not found: %s", resourceName) } - if err := config.Ne.DeleteDeviceLinkGroup(ne.StringValue(link.UUID)); err != nil { - log.Printf("[INFO][SWEEPER_LOG] error deleting NetworkDeviceLink resource %s (%s): %s", ne.StringValue(link.UUID), ne.StringValue(link.Name), err) - } else { - log.Printf("[INFO][SWEEPER_LOG] sent delete request for NetworkDeviceLink resource %s (%s)", ne.StringValue(link.UUID), ne.StringValue(link.Name)) + if rs.Primary.ID == "" { + return fmt.Errorf("resource has no ID attribute set") } + client := acceptance.TestAccProvider.Meta().(*config.Config).Ne + resp, err := client.GetDevice(rs.Primary.ID) + if err != nil { + return fmt.Errorf("error when fetching primary network device '%s': %s", rs.Primary.ID, err) + } + *primary = *resp + resp, err = client.GetDevice(ne.StringValue(resp.RedundantUUID)) + if err != nil { + return fmt.Errorf("error when fetching secondary network device '%s': %s", rs.Primary.ID, err) + } + *secondary = *resp + return nil } - if nonSweepableCount > 0 { - log.Printf("[INFO][SWEEPER_LOG] %d items were non-sweepable and skipped.", nonSweepableCount) - } - return nil } func TestAccNetworkDeviceLink(t *testing.T) { @@ -104,8 +89,8 @@ func TestAccNetworkDeviceLink(t *testing.T) { var deviceLink ne.DeviceLinkGroup var primaryDevice, secondaryDevice ne.Device resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, + PreCheck: func() { acceptance.TestAccPreCheck(t) }, + Providers: acceptance.TestAccProviders, Steps: []resource.TestStep{ { Config: newTestAccConfig(context).withDevice().withDeviceLink().build(), @@ -134,7 +119,7 @@ func (t *testAccConfig) withDeviceLink() *testAccConfig { func testAccNetworkDeviceLink(ctx map[string]interface{}) string { var config string - config += nprintf(` + config += nprintf.Nprintf(` resource "equinix_network_device_link" "%{link-resourceName}" { name = "%{link-name}" subnet = "%{link-subnet}" @@ -181,7 +166,7 @@ func testAccNeDeviceLinkExists(resourceName string, deviceLink *ne.DeviceLinkGro if !ok { return fmt.Errorf("resource not found: %s", resourceName) } - client := testAccProvider.Meta().(*config.Config).Ne + client := acceptance.TestAccProvider.Meta().(*config.Config).Ne if rs.Primary.ID == "" { return fmt.Errorf("resource has no ID attribute set") } diff --git a/equinix/resource_network_device_link_test.go b/internal/resources/networkedge/device_link/resource_test.go similarity index 99% rename from equinix/resource_network_device_link_test.go rename to internal/resources/networkedge/device_link/resource_test.go index 0d2962944..47f667bcb 100644 --- a/equinix/resource_network_device_link_test.go +++ b/internal/resources/networkedge/device_link/resource_test.go @@ -1,4 +1,4 @@ -package equinix +package device_link import ( "testing" diff --git a/internal/resources/networkedge/device_link/sweeper.go b/internal/resources/networkedge/device_link/sweeper.go new file mode 100644 index 000000000..a269f085c --- /dev/null +++ b/internal/resources/networkedge/device_link/sweeper.go @@ -0,0 +1,51 @@ +package device_link + +import ( + "context" + "fmt" + "log" + + "github.com/equinix/ne-go" + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + + "github.com/equinix/terraform-provider-equinix/internal/sweep" +) + +func AddTestSweeper() { + resource.AddTestSweepers("equinix_network_device_link", &resource.Sweeper{ + Name: "equinix_network_device_link", + F: testSweepNetworkDeviceLink, + }) +} + +func testSweepNetworkDeviceLink(region string) error { + config, err := sweep.SharedConfigForRegion(region) + if err != nil { + return fmt.Errorf("[INFO][SWEEPER_LOG] Error getting configuration for sweeping Network devices link: %s", err) + } + if err := config.Load(context.Background()); err != nil { + log.Printf("[INFO][SWEEPER_LOG] error loading configuration: %s", err) + return err + } + links, err := config.Ne.GetDeviceLinkGroups() + if err != nil { + log.Printf("[INFO][SWEEPER_LOG] error fetching device links list: %s", err) + return err + } + nonSweepableCount := 0 + for _, link := range links { + if !sweep.IsSweepableTestResource(ne.StringValue(link.Name)) { + nonSweepableCount++ + continue + } + if err := config.Ne.DeleteDeviceLinkGroup(ne.StringValue(link.UUID)); err != nil { + log.Printf("[INFO][SWEEPER_LOG] error deleting NetworkDeviceLink resource %s (%s): %s", ne.StringValue(link.UUID), ne.StringValue(link.Name), err) + } else { + log.Printf("[INFO][SWEEPER_LOG] sent delete request for NetworkDeviceLink resource %s (%s)", ne.StringValue(link.UUID), ne.StringValue(link.Name)) + } + } + if nonSweepableCount > 0 { + log.Printf("[INFO][SWEEPER_LOG] %d items were non-sweepable and skipped.", nonSweepableCount) + } + return nil +} diff --git a/internal/resources/networkedge/device_link/templates_acc_test.go b/internal/resources/networkedge/device_link/templates_acc_test.go new file mode 100644 index 000000000..657860ce9 --- /dev/null +++ b/internal/resources/networkedge/device_link/templates_acc_test.go @@ -0,0 +1,461 @@ +package device_link + +import ( + "github.com/equinix/terraform-provider-equinix/internal/comparisons" + "github.com/equinix/terraform-provider-equinix/internal/nprintf" +) + +const ( + tstResourcePrefix = "tfacc" + + networkDeviceProjectId = "TF_ACC_NETWORK_DEVICE_PROJECT_ID" + networkDeviceAccountNameEnvVar = "TF_ACC_NETWORK_DEVICE_BILLING_ACCOUNT_NAME" + networkDeviceSecondaryAccountNameEnvVar = "TF_ACC_NETWORK_DEVICE_SECONDARY_BILLING_ACCOUNT_NAME" + networkDeviceMetroEnvVar = "TF_ACC_NETWORK_DEVICE_METRO" + networkDeviceSecondaryMetroEnvVar = "TF_ACC_NETWORK_DEVICE_SECONDARY_METRO" + networkDeviceCSRSDWANLicenseFileEnvVar = "TF_ACC_NETWORK_DEVICE_CSRSDWAN_LICENSE_FILE" + networkDeviceVSRXLicenseFileEnvVar = "TF_ACC_NETWORK_DEVICE_VSRX_LICENSE_FILE" + networkDeviceVersaController1EnvVar = "TF_ACC_NETWORK_DEVICE_VERSA_CONTROLLER1" + networkDeviceVersaController2EnvVar = "TF_ACC_NETWORK_DEVICE_VERSA_CONTROLLER2" + networkDeviceVersaLocalIDEnvVar = "TF_ACC_NETWORK_DEVICE_VERSA_LOCALID" + networkDeviceVersaRemoteIDEnvVar = "TF_ACC_NETWORK_DEVICE_VERSA_REMOTEID" + networkDeviceVersaSerialNumberEnvVar = "TF_ACC_NETWORK_DEVICE_VERSA_SERIAL" + networkDeviceCGENIXLicenseKeyEnvVar = "TF_ACC_NETWORK_DEVICE_CGENIX_LICENSE_KEY" + networkDeviceCGENIXLicenseSecretEnvVar = "TF_ACC_NETWORK_DEVICE_CGENIX_LICENSE_SECRET" + networkDevicePANWLicenseTokenEnvVar = "TF_ACC_NETWORK_DEVICE_PANW_LICENSE_TOKEN" +) + +type testAccConfig struct { + ctx map[string]interface{} + config string +} + +func newTestAccConfig(ctx map[string]interface{}) *testAccConfig { + return &testAccConfig{ + ctx: ctx, + config: "", + } +} + +func (t *testAccConfig) build() string { + return t.config +} + +func (t *testAccConfig) withDevice() *testAccConfig { + t.config += testAccNetworkDevice(t.ctx) + return t +} + +func copyMap(source map[string]interface{}) map[string]interface{} { + target := make(map[string]interface{}) + for k, v := range source { + target[k] = v + } + return target +} + +func testAccNetworkDeviceUser(ctx map[string]interface{}) string { + config := nprintf.Nprintf(` +resource "equinix_network_ssh_user" "%{user-resourceName}" { + username = "%{user-username}" + password = "%{user-password}" + device_ids = [ + equinix_network_device.%{device-resourceName}.id`, ctx) + if _, ok := ctx["device-secondary_name"]; ok { + config += nprintf.Nprintf(`, + equinix_network_device.%{device-resourceName}.redundant_id`, ctx) + } + config += ` + ] +}` + return config +} + +func testAccNetworkDevice(ctx map[string]interface{}) string { + var config string + config += nprintf.Nprintf(` +data "equinix_network_account" "test" { + metro_code = "%{device-metro_code}" + status = "Active" + project_id = "%{device-project_id}"`, ctx) + if v, ok := ctx["device-account_name"]; ok && !comparisons.IsEmpty(v) { + config += nprintf.Nprintf(` + name = "%{device-account_name}"`, ctx) + } + config += nprintf.Nprintf(` +}`, ctx) + if _, ok := ctx["device-secondary_metro_code"]; ok { + config += nprintf.Nprintf(` +data "equinix_network_account" "test-secondary" { + metro_code = "%{device-secondary_metro_code}" + status = "Active"`, ctx) + if v, ok := ctx["device-secondary_account_name"]; ok && !comparisons.IsEmpty(v) { + config += nprintf.Nprintf(` + name = "%{device-secondary_account_name}"`, ctx) + } + config += nprintf.Nprintf(` +}`, ctx) + } + config += nprintf.Nprintf(` +resource "equinix_network_device" "%{device-resourceName}" { + self_managed = %{device-self_managed} + byol = %{device-byol} + name = "%{device-name}" + metro_code = "%{device-metro_code}" + type_code = "%{device-type_code}" + project_id = "%{device-project_id}" + package_code = "%{device-package_code}" + notifications = %{device-notifications} + term_length = %{device-term_length} + account_number = data.equinix_network_account.test.number + version = "%{device-version}" + core_count = %{device-core_count}`, ctx) + if _, ok := ctx["device-purchase_order_number"]; ok { + config += nprintf.Nprintf(` + purchase_order_number = "%{device-purchase_order_number}"`, ctx) + } + if _, ok := ctx["device-purchase_order_number"]; ok { + config += nprintf.Nprintf(` + order_reference = "%{device-order_reference}"`, ctx) + } + if _, ok := ctx["device-additional_bandwidth"]; ok { + config += nprintf.Nprintf(` + additional_bandwidth = %{device-additional_bandwidth}`, ctx) + } + if _, ok := ctx["device-throughput"]; ok { + config += nprintf.Nprintf(` + throughput = %{device-throughput} + throughput_unit = "%{device-throughput_unit}"`, ctx) + } + if _, ok := ctx["device-hostname"]; ok { + config += nprintf.Nprintf(` + hostname = "%{device-hostname}"`, ctx) + } + if _, ok := ctx["device-interface_count"]; ok { + config += nprintf.Nprintf(` + interface_count = %{device-interface_count}`, ctx) + } + if _, ok := ctx["acl-resourceName"]; ok { + config += nprintf.Nprintf(` + acl_template_id = equinix_network_acl_template.%{acl-resourceName}.id`, ctx) + } + if _, ok := ctx["mgmtAcl-resourceName"]; ok { + config += nprintf.Nprintf(` + mgmt_acl_template_uuid = equinix_network_acl_template.%{mgmtAcl-resourceName}.id`, ctx) + } + if _, ok := ctx["sshkey-resourceName"]; ok { + config += nprintf.Nprintf(` + ssh_key { + username = "test" + key_name = equinix_network_ssh_key.%{sshkey-resourceName}.name + }`, ctx) + } + if _, ok := ctx["device-license_file"]; ok { + config += nprintf.Nprintf(` + license_file = "%{device-license_file}"`, ctx) + } + if _, ok := ctx["device-vendorConfig_enabled"]; ok { + config += nprintf.Nprintf(` + vendor_configuration = {`, ctx) + if _, ok := ctx["device-vendorConfig_siteId"]; ok { + config += nprintf.Nprintf(` + siteId = "%{device-vendorConfig_siteId}"`, ctx) + } + if _, ok := ctx["device-vendorConfig_systemIpAddress"]; ok { + config += nprintf.Nprintf(` + systemIpAddress = "%{device-vendorConfig_systemIpAddress}"`, ctx) + } + if _, ok := ctx["device-vendorConfig_licenseKey"]; ok { + config += nprintf.Nprintf(` + licenseKey = "%{device-vendorConfig_licenseKey}"`, ctx) + } + if _, ok := ctx["device-vendorConfig_licenseSecret"]; ok { + config += nprintf.Nprintf(` + licenseSecret = "%{device-vendorConfig_licenseSecret}"`, ctx) + } + if _, ok := ctx["device-vendorConfig_controller1"]; ok { + config += nprintf.Nprintf(` + controller1 = "%{device-vendorConfig_controller1}"`, ctx) + } + if _, ok := ctx["device-vendorConfig_controller2"]; ok { + config += nprintf.Nprintf(` + controller2 = "%{device-vendorConfig_controller2}"`, ctx) + } + if _, ok := ctx["device-vendorConfig_localId"]; ok { + config += nprintf.Nprintf(` + localId = "%{device-vendorConfig_localId}"`, ctx) + } + if _, ok := ctx["device-vendorConfig_remoteId"]; ok { + config += nprintf.Nprintf(` + remoteId = "%{device-vendorConfig_remoteId}"`, ctx) + } + if _, ok := ctx["device-vendorConfig_serialNumber"]; ok { + config += nprintf.Nprintf(` + serialNumber = "%{device-vendorConfig_serialNumber}"`, ctx) + } + config += nprintf.Nprintf(` + }`, ctx) + } + if _, ok := ctx["device-secondary_name"]; ok { + config += nprintf.Nprintf(` + secondary_device { + name = "%{device-secondary_name}"`, ctx) + if _, ok := ctx["device-secondary_metro_code"]; ok { + config += nprintf.Nprintf(` + metro_code = "%{device-secondary_metro_code}" + account_number = data.equinix_network_account.test-secondary.number`, ctx) + } else { + config += nprintf.Nprintf(` + metro_code = "%{device-metro_code}" + account_number = data.equinix_network_account.test.number`, ctx) + } + config += nprintf.Nprintf(` + notifications = %{device-secondary_notifications}`, ctx) + if _, ok := ctx["device-secondary_additional_bandwidth"]; ok { + config += nprintf.Nprintf(` + additional_bandwidth = %{device-secondary_additional_bandwidth}`, ctx) + } + if _, ok := ctx["device-secondary_hostname"]; ok { + config += nprintf.Nprintf(` + hostname = "%{device-secondary_hostname}"`, ctx) + } + if _, ok := ctx["acl-secondary_resourceName"]; ok { + config += nprintf.Nprintf(` + acl_template_id = equinix_network_acl_template.%{acl-secondary_resourceName}.id`, ctx) + } + if _, ok := ctx["mgmtAcl-secondary_resourceName"]; ok { + config += nprintf.Nprintf(` + mgmt_acl_template_uuid = equinix_network_acl_template.%{mgmtAcl-secondary_resourceName}.id`, ctx) + } + if _, ok := ctx["sshkey-resourceName"]; ok { + config += nprintf.Nprintf(` + ssh_key { + username = "test" + key_name = equinix_network_ssh_key.%{sshkey-resourceName}.name + }`, ctx) + } + if _, ok := ctx["device-secondary_license_file"]; ok { + config += nprintf.Nprintf(` + license_file = "%{device-secondary_license_file}"`, ctx) + } + if _, ok := ctx["device-secondary_vendorConfig_enabled"]; ok { + config += nprintf.Nprintf(` + vendor_configuration = {`, ctx) + if _, ok := ctx["device-secondary_vendorConfig_siteId"]; ok { + config += nprintf.Nprintf(` + siteId = "%{device-secondary_vendorConfig_siteId}"`, ctx) + } + if _, ok := ctx["device-secondary_vendorConfig_systemIpAddress"]; ok { + config += nprintf.Nprintf(` + systemIpAddress = "%{device-secondary_vendorConfig_systemIpAddress}"`, ctx) + } + if _, ok := ctx["device-secondary_vendorConfig_licenseKey"]; ok { + config += nprintf.Nprintf(` + licenseKey = "%{device-secondary_vendorConfig_licenseKey}"`, ctx) + } + if _, ok := ctx["device-secondary_vendorConfig_licenseSecret"]; ok { + config += nprintf.Nprintf(` + licenseSecret = "%{device-secondary_vendorConfig_licenseSecret}"`, ctx) + } + if _, ok := ctx["device-secondary_vendorConfig_controller1"]; ok { + config += nprintf.Nprintf(` + controller1 = "%{device-secondary_vendorConfig_controller1}"`, ctx) + } + if _, ok := ctx["device-secondary_vendorConfig_controller2"]; ok { + config += nprintf.Nprintf(` + controller2 = "%{device-secondary_vendorConfig_controller2}"`, ctx) + } + if _, ok := ctx["device-secondary_vendorConfig_localId"]; ok { + config += nprintf.Nprintf(` + localId = "%{device-secondary_vendorConfig_localId}"`, ctx) + } + if _, ok := ctx["device-secondary_vendorConfig_remoteId"]; ok { + config += nprintf.Nprintf(` + remoteId = "%{device-secondary_vendorConfig_remoteId}"`, ctx) + } + if _, ok := ctx["device-secondary_vendorConfig_serialNumber"]; ok { + config += nprintf.Nprintf(` + serialNumber = "%{device-secondary_vendorConfig_serialNumber}"`, ctx) + } + config += nprintf.Nprintf(` + }`, ctx) + } + config += ` + }` + } + if _, ok := ctx["device-cluster_name"]; ok { + config += nprintf.Nprintf(` + cluster_details { + cluster_name = "%{device-cluster_name}"`, ctx) + config += ` + node0 {` + if _, ok := ctx["device-node0_license_file_id"]; ok { + config += nprintf.Nprintf(` + license_file_id = "%{device-node0_license_file_id}"`, ctx) + } + if _, ok := ctx["device-node0_license_token"]; ok { + config += nprintf.Nprintf(` + license_token = "%{device-node0_license_token}"`, ctx) + } + if _, ok := ctx["device-node0_vendorConfig_enabled"]; ok { + config += nprintf.Nprintf(` + vendor_configuration {`, ctx) + if _, ok := ctx["device-node0_vendorConfig_hostname"]; ok { + config += nprintf.Nprintf(` + hostname = "%{device-node0_vendorConfig_hostname}"`, ctx) + } + if _, ok := ctx["device-node0_vendorConfig_adminPassword"]; ok { + config += nprintf.Nprintf(` + admin_password = "%{device-node0_vendorConfig_adminPassword}"`, ctx) + } + if _, ok := ctx["device-node0_vendorConfig_controller1"]; ok { + config += nprintf.Nprintf(` + controller1 = "%{device-node0_vendorConfig_controller1}"`, ctx) + } + if _, ok := ctx["device-node0_vendorConfig_activationKey"]; ok { + config += nprintf.Nprintf(` + activation_key = "%{device-node0_vendorConfig_activationKey}"`, ctx) + } + if _, ok := ctx["device-node0_vendorConfig_controllerFqdn"]; ok { + config += nprintf.Nprintf(` + controller_fqdn = "%{device-node0_vendorConfig_controllerFqdn}"`, ctx) + } + if _, ok := ctx["device-node0_vendorConfig_rootPassword"]; ok { + config += nprintf.Nprintf(` + root_password = "%{device-node0_vendorConfig_rootPassword}"`, ctx) + } + config += nprintf.Nprintf(` + }`, ctx) + } + config += ` + }` + config += ` + node1 {` + if _, ok := ctx["device-node1_license_file_id"]; ok { + config += nprintf.Nprintf(` + license_file_id = "%{device-node1_license_file_id}"`, ctx) + } + if _, ok := ctx["device-node1_license_token"]; ok { + config += nprintf.Nprintf(` + license_token = "%{device-node1_license_token}"`, ctx) + } + if _, ok := ctx["device-node1_vendorConfig_enabled"]; ok { + config += nprintf.Nprintf(` + vendor_configuration {`, ctx) + if _, ok := ctx["device-node1_vendorConfig_hostname"]; ok { + config += nprintf.Nprintf(` + hostname = "%{device-node1_vendorConfig_hostname}"`, ctx) + } + if _, ok := ctx["device-node1_vendorConfig_adminPassword"]; ok { + config += nprintf.Nprintf(` + admin_password = "%{device-node1_vendorConfig_adminPassword}"`, ctx) + } + if _, ok := ctx["device-node1_vendorConfig_controller1"]; ok { + config += nprintf.Nprintf(` + controller1 = "%{device-node1_vendorConfig_controller1}"`, ctx) + } + if _, ok := ctx["device-node1_vendorConfig_activationKey"]; ok { + config += nprintf.Nprintf(` + activation_key = "%{device-node1_vendorConfig_activationKey}"`, ctx) + } + if _, ok := ctx["device-node1_vendorConfig_controllerFqdn"]; ok { + config += nprintf.Nprintf(` + controller_fqdn = "%{device-node1_vendorConfig_controllerFqdn}"`, ctx) + } + if _, ok := ctx["device-node1_vendorConfig_rootPassword"]; ok { + config += nprintf.Nprintf(` + root_password = "%{device-node1_vendorConfig_rootPassword}"`, ctx) + } + config += nprintf.Nprintf(` + }`, ctx) + } + config += ` + }` + config += ` + }` + } + config += ` +}` + return config +} + +func testAccNetworkDeviceACL(ctx map[string]interface{}) string { + var config string + if _, ok := ctx["acl-name"]; ok { + config += nprintf.Nprintf(` +resource "equinix_network_acl_template" "%{acl-resourceName}" { + name = "%{acl-name}" + description = "%{acl-description}" + inbound_rule { + subnet = "10.0.0.0/24" + protocol = "IP" + src_port = "any" + dst_port = "any" + } +}`, ctx) + } + if _, ok := ctx["mgmtAcl-name"]; ok { + config += nprintf.Nprintf(` +resource "equinix_network_acl_template" "%{mgmtAcl-resourceName}" { + name = "%{mgmtAcl-name}" + description = "%{mgmtAcl-description}" + inbound_rule { + subnet = "11.0.0.0/24" + protocol = "IP" + src_port = "any" + dst_port = "any" + } +}`, ctx) + } + if _, ok := ctx["acl-secondary_name"]; ok { + config += nprintf.Nprintf(` +resource "equinix_network_acl_template" "%{acl-secondary_resourceName}" { + name = "%{acl-secondary_name}" + description = "%{acl-secondary_description}" + inbound_rule { + subnet = "192.0.0.0/24" + protocol = "IP" + src_port = "any" + dst_port = "any" + } +}`, ctx) + } + if _, ok := ctx["mgmtAcl-secondary_name"]; ok { + config += nprintf.Nprintf(` +resource "equinix_network_acl_template" "%{mgmtAcl-secondary_resourceName}" { + name = "%{mgmtAcl-secondary_name}" + description = "%{mgmtAcl-secondary_description}" + inbound_rule { + subnet = "193.0.0.0/24" + protocol = "IP" + src_port = "any" + dst_port = "any" + } +}`, ctx) + } + return config +} + +func testAccNetworkDeviceSSHKey(ctx map[string]interface{}) string { + return nprintf.Nprintf(` +resource "equinix_network_ssh_key" "%{sshkey-resourceName}" { + name = "%{sshkey-name}" + public_key = "%{sshkey-public_key}" +} +`, ctx) +} + +func (t *testAccConfig) withACL() *testAccConfig { + t.config += testAccNetworkDeviceACL(t.ctx) + return t +} + +func (t *testAccConfig) withSSHKey() *testAccConfig { + t.config += testAccNetworkDeviceSSHKey(t.ctx) + return t +} + +func (t *testAccConfig) withSSHUser() *testAccConfig { + t.config += testAccNetworkDeviceUser(t.ctx) + return t +} diff --git a/equinix/data_source_network_device_software.go b/internal/resources/networkedge/device_software/data_source.go similarity index 97% rename from equinix/data_source_network_device_software.go rename to internal/resources/networkedge/device_software/data_source.go index 960e67611..a3b3686ae 100644 --- a/equinix/data_source_network_device_software.go +++ b/internal/resources/networkedge/device_software/data_source.go @@ -1,4 +1,4 @@ -package equinix +package device_software import ( "context" @@ -7,6 +7,7 @@ import ( "sort" "time" + "github.com/equinix/terraform-provider-equinix/internal/comparisons" "github.com/equinix/terraform-provider-equinix/internal/config" "github.com/equinix/terraform-provider-equinix/internal/converters" @@ -44,7 +45,7 @@ var networkDeviceSoftwareDescriptions = map[string]string{ const networkDeviceSoftwareDateLayout = "2006-01-02" -func dataSourceNetworkDeviceSoftware() *schema.Resource { +func DataSource() *schema.Resource { return &schema.Resource{ ReadContext: dataSourceNetworkDeviceSoftwareRead, Description: "Use this data source to get Equinix Network Edge device software details for a given device type.", @@ -133,7 +134,7 @@ func dataSourceNetworkDeviceSoftwareRead(ctx context.Context, d *schema.Resource if v, ok := d.GetOk(networkDeviceSoftwareSchemaNames["IsStable"]); ok && v.(bool) != ne.BoolValue(version.IsStable) { continue } - if !stringsFound(pkgCodes, version.PackageCodes) { + if !comparisons.Subsets(pkgCodes, version.PackageCodes) { continue } filtered = append(filtered, version) diff --git a/equinix/data_source_network_device_software_acc_test.go b/internal/resources/networkedge/device_software/data_source_acc_test.go similarity index 83% rename from equinix/data_source_network_device_software_acc_test.go rename to internal/resources/networkedge/device_software/data_source_acc_test.go index ea402ac77..c75159317 100644 --- a/equinix/data_source_network_device_software_acc_test.go +++ b/internal/resources/networkedge/device_software/data_source_acc_test.go @@ -1,10 +1,13 @@ -package equinix +package device_software import ( "fmt" "testing" "github.com/hashicorp/terraform-plugin-testing/helper/resource" + + "github.com/equinix/terraform-provider-equinix/internal/acceptance" + "github.com/equinix/terraform-provider-equinix/internal/nprintf" ) func TestAccDataSourceNetworkDeviceSoftware_versionRegex(t *testing.T) { @@ -17,8 +20,8 @@ func TestAccDataSourceNetworkDeviceSoftware_versionRegex(t *testing.T) { } resourceName := fmt.Sprintf("data.equinix_network_device_software.%s", context["resourceName"].(string)) resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, + PreCheck: func() { acceptance.TestAccPreCheck(t) }, + Providers: acceptance.TestAccProviders, Steps: []resource.TestStep{ { Config: testAccDataSourceNetworkDeviceSoftwareConfig_versionRegex(context), @@ -36,7 +39,7 @@ func TestAccDataSourceNetworkDeviceSoftware_versionRegex(t *testing.T) { } func testAccDataSourceNetworkDeviceSoftwareConfig_versionRegex(ctx map[string]interface{}) string { - return nprintf(` + return nprintf.Nprintf(` data "equinix_network_device_software" "%{resourceName}" { device_type = "%{device_type}" version_regex = "%{version_regex}" diff --git a/equinix/data_source_network_device_type.go b/internal/resources/networkedge/device_type/data_source.go similarity index 96% rename from equinix/data_source_network_device_type.go rename to internal/resources/networkedge/device_type/data_source.go index 62523c8e2..7811dce8f 100644 --- a/equinix/data_source_network_device_type.go +++ b/internal/resources/networkedge/device_type/data_source.go @@ -1,10 +1,11 @@ -package equinix +package device_type import ( "context" "fmt" "strings" + "github.com/equinix/terraform-provider-equinix/internal/comparisons" "github.com/equinix/terraform-provider-equinix/internal/config" "github.com/equinix/terraform-provider-equinix/internal/converters" equinix_validation "github.com/equinix/terraform-provider-equinix/internal/validation" @@ -33,7 +34,7 @@ var networkDeviceTypeDescriptions = map[string]string{ "MetroCodes": "List of metro codes where device type has to be available", } -func dataSourceNetworkDeviceType() *schema.Resource { +func DataSource() *schema.Resource { return &schema.Resource{ ReadContext: dataSourceNetworkDeviceTypeRead, Description: "Use this data source to get Equinix Network Edge device type details", @@ -106,7 +107,7 @@ func dataSourceNetworkDeviceTypeRead(ctx context.Context, d *schema.ResourceData if category != "" && !strings.EqualFold(ne.StringValue(deviceType.Category), category) { continue } - if !stringsFound(metroCodes, deviceType.MetroCodes) { + if !comparisons.Subsets(metroCodes, deviceType.MetroCodes) { continue } filtered = append(filtered, deviceType) diff --git a/equinix/data_source_network_device_type_acc_test.go b/internal/resources/networkedge/device_type/data_source_acc_test.go similarity index 77% rename from equinix/data_source_network_device_type_acc_test.go rename to internal/resources/networkedge/device_type/data_source_acc_test.go index b0be77e58..e8a27c2c3 100644 --- a/equinix/data_source_network_device_type_acc_test.go +++ b/internal/resources/networkedge/device_type/data_source_acc_test.go @@ -1,4 +1,4 @@ -package equinix +package device_type import ( "fmt" @@ -6,8 +6,13 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-testing/helper/resource" + + "github.com/equinix/terraform-provider-equinix/internal/acceptance" + "github.com/equinix/terraform-provider-equinix/internal/nprintf" ) +const networkDeviceMetroEnvVar = "TF_ACC_NETWORK_DEVICE_METRO" + func TestAccDataSourceNetworkDeviceType_basic(t *testing.T) { metro, _ := schema.EnvDefaultFunc(networkDeviceMetroEnvVar, "SV")() context := map[string]interface{}{ @@ -18,8 +23,8 @@ func TestAccDataSourceNetworkDeviceType_basic(t *testing.T) { } resourceName := fmt.Sprintf("data.equinix_network_device_type.%s", context["resourceName"].(string)) resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, + PreCheck: func() { acceptance.TestAccPreCheck(t) }, + Providers: acceptance.TestAccProviders, Steps: []resource.TestStep{ { Config: testAccDataSourceNetworkDeviceTypeConfig_basic(context), @@ -34,7 +39,7 @@ func TestAccDataSourceNetworkDeviceType_basic(t *testing.T) { } func testAccDataSourceNetworkDeviceTypeConfig_basic(ctx map[string]interface{}) string { - return nprintf(` + return nprintf.Nprintf(` data "equinix_network_device_type" "%{resourceName}" { category = "%{category}" vendor = "%{vendor}" diff --git a/equinix/resource_network_file.go b/internal/resources/networkedge/file/resource.go similarity index 96% rename from equinix/resource_network_file.go rename to internal/resources/networkedge/file/resource.go index 059a5b741..275d950ad 100644 --- a/equinix/resource_network_file.go +++ b/internal/resources/networkedge/file/resource.go @@ -1,4 +1,4 @@ -package equinix +package file import ( "context" @@ -8,13 +8,21 @@ import ( "github.com/equinix/ne-go" "github.com/equinix/rest-go" + "github.com/equinix/terraform-provider-equinix/internal/config" equinix_validation "github.com/equinix/terraform-provider-equinix/internal/validation" + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" ) +// neDeviceSchemaNames is a light copy of the map of Network Edge device schema field names +var neDeviceSchemaNames = map[string]string{ + "IsBYOL": "byol", + "IsSelfManaged": "self_managed", +} + var networkFileSchemaNames = map[string]string{ "UUID": "uuid", "FileName": "file_name", @@ -39,7 +47,7 @@ var networkFileDescriptions = map[string]string{ "Status": "File upload status", } -func resourceNetworkFile() *schema.Resource { +func Resource() *schema.Resource { return &schema.Resource{ CreateContext: resourceNetworkFileCreate, ReadContext: resourceNetworkFileRead, diff --git a/equinix/resource_network_file_acc_test.go b/internal/resources/networkedge/file/resource_acc_test.go similarity index 89% rename from equinix/resource_network_file_acc_test.go rename to internal/resources/networkedge/file/resource_acc_test.go index 303f4e448..b5208f49f 100644 --- a/equinix/resource_network_file_acc_test.go +++ b/internal/resources/networkedge/file/resource_acc_test.go @@ -1,10 +1,12 @@ -package equinix +package file import ( "fmt" "testing" + "github.com/equinix/terraform-provider-equinix/internal/acceptance" "github.com/equinix/terraform-provider-equinix/internal/config" + "github.com/equinix/terraform-provider-equinix/internal/nprintf" "github.com/equinix/ne-go" "github.com/hashicorp/terraform-plugin-testing/helper/acctest" @@ -12,6 +14,8 @@ import ( "github.com/hashicorp/terraform-plugin-testing/terraform" ) +const tstResourcePrefix = "tfacc" + func TestAccNetworkFile_VSRX(t *testing.T) { context := map[string]interface{}{ "resourceName": "test", @@ -26,8 +30,8 @@ func TestAccNetworkFile_VSRX(t *testing.T) { resourceName := fmt.Sprintf("equinix_network_file.%s", context["resourceName"].(string)) var file ne.File resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, + PreCheck: func() { acceptance.TestAccPreCheck(t) }, + Providers: acceptance.TestAccProviders, Steps: []resource.TestStep{ { Config: testAccNetworkFile(context), @@ -49,7 +53,7 @@ func TestAccNetworkFile_VSRX(t *testing.T) { } func testAccNetworkFile(ctx map[string]interface{}) string { - return nprintf(` + return nprintf.Nprintf(` resource "equinix_network_file" "%{resourceName}" { file_name = "%{fileName}" content = "%{content}" @@ -68,7 +72,7 @@ func testAccNetworkFileExists(resourceName string, file *ne.File) resource.TestC if !ok { return fmt.Errorf("resource not found: %s", resourceName) } - client := testAccProvider.Meta().(*config.Config).Ne + client := acceptance.TestAccProvider.Meta().(*config.Config).Ne if rs.Primary.ID == "" { return fmt.Errorf("resource has no ID attribute set") } diff --git a/equinix/resource_network_file_test.go b/internal/resources/networkedge/file/resource_test.go similarity index 99% rename from equinix/resource_network_file_test.go rename to internal/resources/networkedge/file/resource_test.go index c5b83e402..93b03327a 100644 --- a/equinix/resource_network_file_test.go +++ b/internal/resources/networkedge/file/resource_test.go @@ -1,4 +1,4 @@ -package equinix +package file import ( "testing" diff --git a/equinix/data_source_network_platform.go b/internal/resources/networkedge/platform/data_source.go similarity index 95% rename from equinix/data_source_network_platform.go rename to internal/resources/networkedge/platform/data_source.go index c4f62fbc7..73016ffc9 100644 --- a/equinix/data_source_network_platform.go +++ b/internal/resources/networkedge/platform/data_source.go @@ -1,9 +1,10 @@ -package equinix +package platform import ( "context" "fmt" + "github.com/equinix/terraform-provider-equinix/internal/comparisons" "github.com/equinix/terraform-provider-equinix/internal/config" "github.com/equinix/terraform-provider-equinix/internal/converters" @@ -35,7 +36,7 @@ var networkDevicePlatformDescriptions = map[string]string{ "LicenseOptions": "List of device licensing options to limit platform search result. Supported values: BYOL (Bring Your Own License), Sub (license subscription)", } -func dataSourceNetworkDevicePlatform() *schema.Resource { +func DataSource() *schema.Resource { return &schema.Resource{ ReadContext: dataSourceNetworkDevicePlatformRead, Description: "Use this data source to get Equinix Network Edge device platform configuration details for a given device type", @@ -124,19 +125,19 @@ func dataSourceNetworkDevicePlatformRead(ctx context.Context, d *schema.Resource } if v, ok := d.GetOk(networkDevicePlatformSchemaNames["PackageCodes"]); ok { pkgCodes := converters.SetToStringList(v.(*schema.Set)) - if !stringsFound(pkgCodes, platform.PackageCodes) { + if !comparisons.Subsets(pkgCodes, platform.PackageCodes) { continue } } if v, ok := d.GetOk(networkDevicePlatformSchemaNames["ManagementTypes"]); ok { mgmtTypes := converters.SetToStringList(v.(*schema.Set)) - if !stringsFound(mgmtTypes, platform.ManagementTypes) { + if !comparisons.Subsets(mgmtTypes, platform.ManagementTypes) { continue } } if v, ok := d.GetOk(networkDevicePlatformSchemaNames["LicenseOptions"]); ok { licOptions := converters.SetToStringList(v.(*schema.Set)) - if !stringsFound(licOptions, platform.LicenseOptions) { + if !comparisons.Subsets(licOptions, platform.LicenseOptions) { continue } } diff --git a/equinix/data_source_network_platform_acc_test.go b/internal/resources/networkedge/platform/data_source_acc_test.go similarity index 80% rename from equinix/data_source_network_platform_acc_test.go rename to internal/resources/networkedge/platform/data_source_acc_test.go index 482e93a86..308d75567 100644 --- a/equinix/data_source_network_platform_acc_test.go +++ b/internal/resources/networkedge/platform/data_source_acc_test.go @@ -1,10 +1,13 @@ -package equinix +package platform import ( "fmt" "testing" "github.com/hashicorp/terraform-plugin-testing/helper/resource" + + "github.com/equinix/terraform-provider-equinix/internal/acceptance" + "github.com/equinix/terraform-provider-equinix/internal/nprintf" ) func TestAccDataSourceNetworkDevicePlatform_basic(t *testing.T) { @@ -16,8 +19,8 @@ func TestAccDataSourceNetworkDevicePlatform_basic(t *testing.T) { } resourceName := fmt.Sprintf("data.equinix_network_device_platform.%s", context["resourceName"].(string)) resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, + PreCheck: func() { acceptance.TestAccPreCheck(t) }, + Providers: acceptance.TestAccProviders, Steps: []resource.TestStep{ { Config: testAccDataSourceNetworkDevicePlatformConfig_basic(context), @@ -33,7 +36,7 @@ func TestAccDataSourceNetworkDevicePlatform_basic(t *testing.T) { } func testAccDataSourceNetworkDevicePlatformConfig_basic(ctx map[string]interface{}) string { - return nprintf(` + return nprintf.Nprintf(` data "equinix_network_device_platform" "%{resourceName}" { device_type = "%{device_type}" flavor = "%{flavor}" diff --git a/equinix/resource_network_ssh_key.go b/internal/resources/networkedge/ssh_key/resource.go similarity index 98% rename from equinix/resource_network_ssh_key.go rename to internal/resources/networkedge/ssh_key/resource.go index 8c4853ef4..25e4bce04 100644 --- a/equinix/resource_network_ssh_key.go +++ b/internal/resources/networkedge/ssh_key/resource.go @@ -1,4 +1,4 @@ -package equinix +package ssh_key import ( "context" @@ -31,7 +31,7 @@ var networkSSHKeyDescriptions = map[string]string{ "ProjectID": "The unique identifier of Project Resource to which ssh key is scoped to", } -func resourceNetworkSSHKey() *schema.Resource { +func Resource() *schema.Resource { return &schema.Resource{ CreateContext: resourceNetworkSSHKeyCreate, ReadContext: resourceNetworkSSHKeyRead, diff --git a/equinix/resource_network_ssh_key_acc_test.go b/internal/resources/networkedge/ssh_key/resource_acc_test.go similarity index 66% rename from equinix/resource_network_ssh_key_acc_test.go rename to internal/resources/networkedge/ssh_key/resource_acc_test.go index b27de199a..bb2628fb8 100644 --- a/equinix/resource_network_ssh_key_acc_test.go +++ b/internal/resources/networkedge/ssh_key/resource_acc_test.go @@ -1,12 +1,12 @@ -package equinix +package ssh_key import ( - "context" "fmt" - "log" "testing" + "github.com/equinix/terraform-provider-equinix/internal/acceptance" "github.com/equinix/terraform-provider-equinix/internal/config" + "github.com/equinix/terraform-provider-equinix/internal/nprintf" "github.com/equinix/ne-go" "github.com/hashicorp/terraform-plugin-testing/helper/acctest" @@ -14,44 +14,7 @@ import ( "github.com/hashicorp/terraform-plugin-testing/terraform" ) -func init() { - resource.AddTestSweepers("equinix_network_ssh_key", &resource.Sweeper{ - Name: "equinix_network_ssh_key", - F: testSweepNetworkSSHKey, - }) -} - -func testSweepNetworkSSHKey(region string) error { - config, err := sharedConfigForRegion(region) - if err != nil { - return fmt.Errorf("[INFO][SWEEPER_LOG] Error getting configuration for sweeping Network SSH keys: %s", err) - } - if err := config.Load(context.Background()); err != nil { - log.Printf("[INFO][SWEEPER_LOG] error loading configuration: %s", err) - return err - } - keys, err := config.Ne.GetSSHPublicKeys() - if err != nil { - log.Printf("[INFO][SWEEPER_LOG] error fetching NetworkSSHKey list: %s", err) - return err - } - nonSweepableCount := 0 - for _, key := range keys { - if !isSweepableTestResource(ne.StringValue(key.Name)) { - nonSweepableCount++ - continue - } - if err := config.Ne.DeleteSSHPublicKey(ne.StringValue(key.UUID)); err != nil { - log.Printf("[INFO][SWEEPER_LOG] error deleting NetworkSSHKey resource %s (%s): %s", ne.StringValue(key.UUID), ne.StringValue(key.Name), err) - } else { - log.Printf("[INFO][SWEEPER_LOG] sent delete request for NetworkSSHKey resource %s (%s)", ne.StringValue(key.UUID), ne.StringValue(key.Name)) - } - } - if nonSweepableCount > 0 { - log.Printf("[INFO][SWEEPER_LOG] %d items were non-sweepable and skipped.", nonSweepableCount) - } - return nil -} +const tstResourcePrefix = "tfacc" func TestAccNetworkSSHKey(t *testing.T) { context := map[string]interface{}{ @@ -63,8 +26,8 @@ func TestAccNetworkSSHKey(t *testing.T) { resourceName := fmt.Sprintf("equinix_network_ssh_key.%s", context["resourceName"].(string)) var key ne.SSHPublicKey resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, + PreCheck: func() { acceptance.TestAccPreCheck(t) }, + Providers: acceptance.TestAccProviders, Steps: []resource.TestStep{ { Config: testAccNetworkSSHKey(context), @@ -84,7 +47,7 @@ func TestAccNetworkSSHKey(t *testing.T) { } func testAccNetworkSSHKey(ctx map[string]interface{}) string { - return nprintf(` + return nprintf.Nprintf(` resource "equinix_network_ssh_key" "%{resourceName}" { name = "%{name}" public_key = "%{public_key}" @@ -99,7 +62,7 @@ func testAccNetworkSSHKeyExists(resourceName string, key *ne.SSHPublicKey) resou if !ok { return fmt.Errorf("resource not found: %s", resourceName) } - client := testAccProvider.Meta().(*config.Config).Ne + client := acceptance.TestAccProvider.Meta().(*config.Config).Ne if rs.Primary.ID == "" { return fmt.Errorf("resource has no ID attribute set") } diff --git a/equinix/resource_network_ssh_key_test.go b/internal/resources/networkedge/ssh_key/resource_test.go similarity index 99% rename from equinix/resource_network_ssh_key_test.go rename to internal/resources/networkedge/ssh_key/resource_test.go index 3266a9dc6..08cf81989 100644 --- a/equinix/resource_network_ssh_key_test.go +++ b/internal/resources/networkedge/ssh_key/resource_test.go @@ -1,4 +1,4 @@ -package equinix +package ssh_key import ( "testing" diff --git a/internal/resources/networkedge/ssh_key/sweeper.go b/internal/resources/networkedge/ssh_key/sweeper.go new file mode 100644 index 000000000..7e221951d --- /dev/null +++ b/internal/resources/networkedge/ssh_key/sweeper.go @@ -0,0 +1,51 @@ +package ssh_key + +import ( + "context" + "fmt" + "log" + + "github.com/equinix/ne-go" + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + + "github.com/equinix/terraform-provider-equinix/internal/sweep" +) + +func AddTestSweeper() { + resource.AddTestSweepers("equinix_network_ssh_key", &resource.Sweeper{ + Name: "equinix_network_ssh_key", + F: testSweepNetworkSSHKey, + }) +} + +func testSweepNetworkSSHKey(region string) error { + config, err := sweep.SharedConfigForRegion(region) + if err != nil { + return fmt.Errorf("[INFO][SWEEPER_LOG] Error getting configuration for sweeping Network SSH keys: %s", err) + } + if err := config.Load(context.Background()); err != nil { + log.Printf("[INFO][SWEEPER_LOG] error loading configuration: %s", err) + return err + } + keys, err := config.Ne.GetSSHPublicKeys() + if err != nil { + log.Printf("[INFO][SWEEPER_LOG] error fetching NetworkSSHKey list: %s", err) + return err + } + nonSweepableCount := 0 + for _, key := range keys { + if !sweep.IsSweepableTestResource(ne.StringValue(key.Name)) { + nonSweepableCount++ + continue + } + if err := config.Ne.DeleteSSHPublicKey(ne.StringValue(key.UUID)); err != nil { + log.Printf("[INFO][SWEEPER_LOG] error deleting NetworkSSHKey resource %s (%s): %s", ne.StringValue(key.UUID), ne.StringValue(key.Name), err) + } else { + log.Printf("[INFO][SWEEPER_LOG] sent delete request for NetworkSSHKey resource %s (%s)", ne.StringValue(key.UUID), ne.StringValue(key.Name)) + } + } + if nonSweepableCount > 0 { + log.Printf("[INFO][SWEEPER_LOG] %d items were non-sweepable and skipped.", nonSweepableCount) + } + return nil +} diff --git a/equinix/resource_network_ssh_user.go b/internal/resources/networkedge/ssh_user/resource.go similarity index 98% rename from equinix/resource_network_ssh_user.go rename to internal/resources/networkedge/ssh_user/resource.go index 253b6cacb..a95bfd733 100644 --- a/equinix/resource_network_ssh_user.go +++ b/internal/resources/networkedge/ssh_user/resource.go @@ -1,4 +1,4 @@ -package equinix +package ssh_user import ( "context" @@ -28,7 +28,7 @@ var networkSSHUserDescriptions = map[string]string{ "DeviceUUIDs": "list of device identifiers to which user will have access", } -func resourceNetworkSSHUser() *schema.Resource { +func Resource() *schema.Resource { return &schema.Resource{ CreateContext: resourceNetworkSSHUserCreate, ReadContext: resourceNetworkSSHUserRead, diff --git a/internal/resources/networkedge/ssh_user/resource_acc_test.go b/internal/resources/networkedge/ssh_user/resource_acc_test.go new file mode 100644 index 000000000..846e5323d --- /dev/null +++ b/internal/resources/networkedge/ssh_user/resource_acc_test.go @@ -0,0 +1,4 @@ +package ssh_user + +// SSH User acc tests are in Device acc test tests +// reason: SSH User requires device to be provisioned and that is time consuming operation diff --git a/equinix/resource_network_ssh_user_test.go b/internal/resources/networkedge/ssh_user/resource_test.go similarity index 99% rename from equinix/resource_network_ssh_user_test.go rename to internal/resources/networkedge/ssh_user/resource_test.go index b9b471ff5..5cfa9e1fc 100644 --- a/equinix/resource_network_ssh_user_test.go +++ b/internal/resources/networkedge/ssh_user/resource_test.go @@ -1,12 +1,13 @@ -package equinix +package ssh_user import ( "testing" "github.com/equinix/ne-go" - "github.com/equinix/terraform-provider-equinix/internal/converters" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/stretchr/testify/assert" + + "github.com/equinix/terraform-provider-equinix/internal/converters" ) func TestNetworkSSHUser_resourceFromResourceData(t *testing.T) { diff --git a/internal/resources/networkedge/ssh_user/sweeper.go b/internal/resources/networkedge/ssh_user/sweeper.go new file mode 100644 index 000000000..dd5e8e71d --- /dev/null +++ b/internal/resources/networkedge/ssh_user/sweeper.go @@ -0,0 +1,46 @@ +package ssh_user + +import ( + "context" + "fmt" + "log" + + "github.com/equinix/ne-go" + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + + "github.com/equinix/terraform-provider-equinix/internal/sweep" +) + +func AddTestSweeper() { + resource.AddTestSweepers("equinix_network_ssh_user", &resource.Sweeper{ + Name: "equinix_network_ssh_user", + F: testSweepNetworkSSHUser, + }) +} + +func testSweepNetworkSSHUser(region string) error { + config, err := sweep.SharedConfigForRegion(region) + if err != nil { + return fmt.Errorf("[INFO][SWEEPER_LOG] Error getting configuration for sweeping Network SSH users: %s", err) + } + if err := config.Load(context.Background()); err != nil { + log.Printf("[INFO][SWEEPER_LOG] error loading configuration: %s", err) + return err + } + users, err := config.Ne.GetSSHUsers() + if err != nil { + log.Printf("[INFO][SWEEPER_LOG] error fetching NetworkSSHUser list: %s", err) + return err + } + for _, user := range users { + if !sweep.IsSweepableTestResource(ne.StringValue(user.Username)) { + continue + } + if err := config.Ne.DeleteSSHUser(ne.StringValue(user.UUID)); err != nil { + log.Printf("[INFO][SWEEPER_LOG] error deleting NetworkSSHUser resource %s (%s): %s", ne.StringValue(user.UUID), ne.StringValue(user.Username), err) + } else { + log.Printf("[INFO][SWEEPER_LOG] sent delete request for NetworkSSHUser resource %s (%s)", ne.StringValue(user.UUID), ne.StringValue(user.Username)) + } + } + return nil +} diff --git a/internal/sweep/sweep.go b/internal/sweep/sweep.go index 11a98d699..0fb539fa2 100644 --- a/internal/sweep/sweep.go +++ b/internal/sweep/sweep.go @@ -76,3 +76,30 @@ func GetConfigForMetal() (*config.Config, error) { RequestTimeout: time.Duration(clientTimeoutInt) * time.Second, }, nil } + +func SharedConfigForRegion(region string) (*config.Config, error) { + endpoint := env.GetWithDefault(config.EndpointEnvVar, config.DefaultBaseURL) + clientToken := env.GetWithDefault(config.ClientTokenEnvVar, "") + clientID := env.GetWithDefault(config.ClientIDEnvVar, "") + clientSecret := env.GetWithDefault(config.ClientSecretEnvVar, "") + clientTimeout := env.GetWithDefault(config.ClientTimeoutEnvVar, strconv.Itoa(config.DefaultTimeout)) + clientTimeoutInt, err := strconv.Atoi(clientTimeout) + if err != nil { + return nil, fmt.Errorf("cannot convert value of '%s' env variable to int", config.ClientTimeoutEnvVar) + } + metalAuthToken := env.GetWithDefault(config.MetalAuthTokenEnvVar, "") + + if clientToken == "" && (clientID == "" || clientSecret == "") && metalAuthToken == "" { + return nil, fmt.Errorf("To run acceptance tests sweeper, one of '%s' or pair '%s' - '%s' must be set for Equinix Fabric and Network Edge, and '%s' for Equinix Metal", + config.ClientTokenEnvVar, config.ClientIDEnvVar, config.ClientSecretEnvVar, config.MetalAuthTokenEnvVar) + } + + return &config.Config{ + AuthToken: metalAuthToken, + BaseURL: endpoint, + Token: clientToken, + ClientID: clientID, + ClientSecret: clientSecret, + RequestTimeout: time.Duration(clientTimeoutInt) * time.Second, + }, nil +} diff --git a/internal/sweep/sweep_test.go b/internal/sweep/sweep_test.go index 64722121f..08ca39cd2 100644 --- a/internal/sweep/sweep_test.go +++ b/internal/sweep/sweep_test.go @@ -4,7 +4,6 @@ import ( "testing" fabric_cloud_router "github.com/equinix/terraform-provider-equinix/internal/resources/fabric/cloud_router" - fabric_connection "github.com/equinix/terraform-provider-equinix/internal/resources/fabric/connection" "github.com/equinix/terraform-provider-equinix/internal/resources/metal/connection" "github.com/equinix/terraform-provider-equinix/internal/resources/metal/device" @@ -15,6 +14,11 @@ import ( "github.com/equinix/terraform-provider-equinix/internal/resources/metal/virtual_circuit" "github.com/equinix/terraform-provider-equinix/internal/resources/metal/vlan" "github.com/equinix/terraform-provider-equinix/internal/resources/metal/vrf" + ne_acl_template "github.com/equinix/terraform-provider-equinix/internal/resources/networkedge/acl_template" + ne_device "github.com/equinix/terraform-provider-equinix/internal/resources/networkedge/device" + ne_device_link "github.com/equinix/terraform-provider-equinix/internal/resources/networkedge/device_link" + ne_ssh_key "github.com/equinix/terraform-provider-equinix/internal/resources/networkedge/ssh_key" + ne_ssh_user "github.com/equinix/terraform-provider-equinix/internal/resources/networkedge/ssh_user" "github.com/hashicorp/terraform-plugin-testing/helper/resource" ) @@ -31,6 +35,11 @@ func addTestSweepers() { device.AddTestSweeper() fabric_cloud_router.AddTestSweeper() fabric_connection.AddTestSweeper() + ne_device.AddTestSweeper() + ne_device_link.AddTestSweeper() + ne_acl_template.AddTestSweeper() + ne_ssh_key.AddTestSweeper() + ne_ssh_user.AddTestSweeper() organization.AddTestSweeper() project.AddTestSweeper() ssh_key.AddTestSweeper()