Skip to content

Commit 958af83

Browse files
Add Data Source Interconnect Location (#15065)
1 parent ad70e38 commit 958af83

7 files changed

+531
-0
lines changed

mmv1/third_party/terraform/provider/provider_mmv1_resources.go.tmpl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,8 @@ var handwrittenDatasources = map[string]*schema.Resource{
106106
"google_compute_instance_serial_port": compute.DataSourceGoogleComputeInstanceSerialPort(),
107107
"google_compute_instance_template": compute.DataSourceGoogleComputeInstanceTemplate(),
108108
"google_compute_instance_guest_attributes": compute.DataSourceGoogleComputeInstanceGuestAttributes(),
109+
"google_compute_interconnect_location": compute.DataSourceGoogleComputeInterconnectLocation(),
110+
"google_compute_interconnect_locations": compute.DataSourceGoogleComputeInterconnectLocations(),
109111
"google_compute_lb_ip_ranges": compute.DataSourceGoogleComputeLbIpRanges(),
110112
"google_compute_machine_types": compute.DataSourceGoogleComputeMachineTypes(),
111113
"google_compute_network": compute.DataSourceGoogleComputeNetwork(),
Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
package compute
2+
3+
import (
4+
"fmt"
5+
"regexp"
6+
"strings"
7+
8+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
9+
"github.com/hashicorp/terraform-provider-google/google/tpgresource"
10+
transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport"
11+
)
12+
13+
var (
14+
computeInterconnectLocationIdTemplate = "projects/%s/global/interconnectlocations/%s"
15+
computeInterconnectLocationLinkRegex = regexp.MustCompile(`projects/(.+)/global/interconnectlocations/(.+)$`)
16+
)
17+
18+
type ComputeInterconnectLocationId struct {
19+
Project string
20+
Name string
21+
}
22+
23+
func (s ComputeInterconnectLocationId) CanonicalId() string {
24+
return fmt.Sprintf(computeInterconnectLocationIdTemplate, s.Project, s.Name)
25+
}
26+
27+
// ParseComputeInterconnectLocationId parses IDs of the form:
28+
// - projects/{project}/global/interconnectlocations/{name}
29+
// - {project}/{name}
30+
// - {name} (requires config.Project)
31+
func ParseComputeInterconnectLocationId(id string, config *transport_tpg.Config) (*ComputeInterconnectLocationId, error) {
32+
var parts []string
33+
if computeInterconnectLocationLinkRegex.MatchString(id) {
34+
parts = computeInterconnectLocationLinkRegex.FindStringSubmatch(id)
35+
return &ComputeInterconnectLocationId{
36+
Project: parts[1],
37+
Name: parts[2],
38+
}, nil
39+
} else {
40+
parts = strings.Split(id, "/")
41+
}
42+
if len(parts) == 2 {
43+
return &ComputeInterconnectLocationId{
44+
Project: parts[0],
45+
Name: parts[1],
46+
}, nil
47+
} else if len(parts) == 1 {
48+
if config.Project == "" {
49+
return nil, fmt.Errorf("The default project for the provider must be set when using the `{name}` id format.")
50+
}
51+
return &ComputeInterconnectLocationId{
52+
Project: config.Project,
53+
Name: parts[0],
54+
}, nil
55+
}
56+
return nil, fmt.Errorf("Invalid interconnect location id. Expecting resource link, `{project}/{name}` or `{name}` format.")
57+
}
58+
func DataSourceGoogleComputeInterconnectLocation() *schema.Resource {
59+
return &schema.Resource{
60+
Read: dataSourceGoogleComputeInterconnectLocationRead,
61+
Schema: map[string]*schema.Schema{
62+
"name": {
63+
Type: schema.TypeString,
64+
Required: true,
65+
},
66+
"project": {
67+
Type: schema.TypeString,
68+
Optional: true,
69+
Computed: true,
70+
},
71+
"self_link": {
72+
Type: schema.TypeString,
73+
Computed: true,
74+
},
75+
"description": {
76+
Type: schema.TypeString,
77+
Computed: true,
78+
},
79+
"peeringdb_facility_id": {
80+
Type: schema.TypeString,
81+
Computed: true,
82+
},
83+
"address": {
84+
Type: schema.TypeString,
85+
Computed: true,
86+
},
87+
"facility_provider": {
88+
Type: schema.TypeString,
89+
Computed: true,
90+
},
91+
"facility_provider_facility_id": {
92+
Type: schema.TypeString,
93+
Computed: true,
94+
},
95+
"continent": {
96+
Type: schema.TypeString,
97+
Computed: true,
98+
},
99+
"city": {
100+
Type: schema.TypeString,
101+
Computed: true,
102+
},
103+
"availability_zone": {
104+
Type: schema.TypeString,
105+
Computed: true,
106+
},
107+
"status": {
108+
Type: schema.TypeString,
109+
Computed: true,
110+
},
111+
},
112+
}
113+
}
114+
func dataSourceGoogleComputeInterconnectLocationRead(d *schema.ResourceData, meta interface{}) error {
115+
config := meta.(*transport_tpg.Config)
116+
userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent)
117+
if err != nil {
118+
return err
119+
}
120+
project, err := tpgresource.GetProject(d, config)
121+
if err != nil {
122+
return err
123+
}
124+
name := d.Get("name").(string)
125+
id := fmt.Sprintf("projects/%s/global/interconnectlocations/%s", project, name)
126+
location, err := config.NewComputeClient(userAgent).InterconnectLocations.Get(project, name).Do()
127+
if err != nil {
128+
return transport_tpg.HandleDataSourceNotFoundError(err, d, fmt.Sprintf("InterconnectLocation Not Found : %s", name), id)
129+
}
130+
d.SetId(location.Name)
131+
if err := d.Set("project", project); err != nil {
132+
return fmt.Errorf("Error setting project: %s", err)
133+
}
134+
if err := d.Set("self_link", location.SelfLink); err != nil {
135+
return fmt.Errorf("Error setting self_link: %s", err)
136+
}
137+
if err := d.Set("description", location.Description); err != nil {
138+
return fmt.Errorf("Error setting description: %s", err)
139+
}
140+
if err := d.Set("peeringdb_facility_id", location.PeeringdbFacilityId); err != nil {
141+
return fmt.Errorf("Error setting peeringdb_facility_id: %s", err)
142+
}
143+
if err := d.Set("address", location.Address); err != nil {
144+
return fmt.Errorf("Error setting address: %s", err)
145+
}
146+
if err := d.Set("facility_provider", location.FacilityProvider); err != nil {
147+
return fmt.Errorf("Error setting facility_provider: %s", err)
148+
}
149+
if err := d.Set("facility_provider_facility_id", location.FacilityProviderFacilityId); err != nil {
150+
return fmt.Errorf("Error setting facility_provider_facility_id: %s", err)
151+
}
152+
if err := d.Set("continent", location.Continent); err != nil {
153+
return fmt.Errorf("Error setting continent: %s", err)
154+
}
155+
if err := d.Set("city", location.City); err != nil {
156+
return fmt.Errorf("Error setting city: %s", err)
157+
}
158+
if err := d.Set("availability_zone", location.AvailabilityZone); err != nil {
159+
return fmt.Errorf("Error setting availability_zone: %s", err)
160+
}
161+
if err := d.Set("status", location.Status); err != nil {
162+
return fmt.Errorf("Error setting status: %s", err)
163+
}
164+
d.SetId(id)
165+
return nil
166+
}
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
package compute_test
2+
3+
import (
4+
"fmt"
5+
"testing"
6+
7+
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
8+
"github.com/hashicorp/terraform-plugin-testing/terraform"
9+
"github.com/hashicorp/terraform-provider-google/google/acctest"
10+
"github.com/hashicorp/terraform-provider-google/google/services/compute"
11+
"github.com/hashicorp/terraform-provider-google/google/transport"
12+
)
13+
14+
var interconnectLoc = "z2z-us-west8-zone2-ncphxk-z"
15+
16+
func testAccDataSourceCheckInterconnectLocation() func(s *terraform.State) error {
17+
return func(s *terraform.State) error {
18+
data_source_name := "data.google_compute_interconnect_location.my_location"
19+
ds, ok := s.RootModule().Resources[data_source_name]
20+
if !ok {
21+
return fmt.Errorf("root module has no resource called %s", data_source_name)
22+
}
23+
ds_attr := ds.Primary.Attributes
24+
expected := map[string]string{
25+
"name": interconnectLoc,
26+
"description": "Zakim-to-Zakim location",
27+
"facility_provider": "Google",
28+
}
29+
for attr, expect_value := range expected {
30+
if ds_attr[attr] != expect_value {
31+
return fmt.Errorf("%s is %s; want %s", attr, ds_attr[attr], expect_value)
32+
}
33+
}
34+
if ds_attr["self_link"] == "" {
35+
return fmt.Errorf("self_link is not set")
36+
}
37+
return nil
38+
}
39+
}
40+
func TestAccDataSourceGoogleComputeInterconnectLocation_basic(t *testing.T) {
41+
acctest.VcrTest(t, resource.TestCase{
42+
PreCheck: func() { acctest.AccTestPreCheck(t) },
43+
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t),
44+
Steps: []resource.TestStep{
45+
{
46+
Config: testAccDataSourceGoogleComputeInterconnectLocationConfig(interconnectLoc),
47+
Check: resource.ComposeTestCheckFunc(
48+
testAccDataSourceCheckInterconnectLocation(),
49+
),
50+
},
51+
},
52+
})
53+
}
54+
func testAccDataSourceGoogleComputeInterconnectLocationConfig(locationName string) string {
55+
return fmt.Sprintf(`
56+
data "google_compute_interconnect_location" "my_location" {
57+
name = "%s"
58+
}
59+
`, locationName)
60+
}
61+
func TestParseComputeInterconnectLocationId(t *testing.T) {
62+
config := &transport.Config{Project: "my-project"}
63+
cases := []struct {
64+
id string
65+
wantProj string
66+
wantName string
67+
wantErr bool
68+
}{
69+
{"projects/my-project/global/interconnectlocations/z2z-us-west8-zone2-ncphxk-z", "my-project", interconnectLoc, false},
70+
{"my-project/z2z-us-west8-zone2-ncphxk-z", "my-project", interconnectLoc, false},
71+
{interconnectLoc, "my-project", interconnectLoc, false},
72+
{"invalid/format/extra", "", "", true},
73+
}
74+
for _, tc := range cases {
75+
got, err := compute.ParseComputeInterconnectLocationId(tc.id, config)
76+
if tc.wantErr {
77+
if err == nil {
78+
t.Errorf("ParseComputeInterconnectLocationId(%q) expected error, got nil", tc.id)
79+
}
80+
continue
81+
}
82+
if err != nil {
83+
t.Errorf("ParseComputeInterconnectLocationId(%q) unexpected error: %v", tc.id, err)
84+
continue
85+
}
86+
if got.Project != tc.wantProj || got.Name != tc.wantName {
87+
t.Errorf("ParseComputeInterconnectLocationId(%q) = (%q, %q), want (%q, %q)", tc.id, got.Project, got.Name, tc.wantProj, tc.wantName)
88+
}
89+
}
90+
}
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
package compute
2+
3+
import (
4+
"fmt"
5+
6+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
7+
"github.com/hashicorp/terraform-provider-google/google/tpgresource"
8+
transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport"
9+
)
10+
11+
func DataSourceGoogleComputeInterconnectLocations() *schema.Resource {
12+
return &schema.Resource{
13+
Read: dataSourceGoogleComputeInterconnectLocationsRead,
14+
Schema: map[string]*schema.Schema{
15+
"project": {
16+
Type: schema.TypeString,
17+
Optional: true,
18+
Computed: true,
19+
},
20+
"locations": {
21+
Type: schema.TypeList,
22+
Computed: true,
23+
Elem: &schema.Resource{
24+
Schema: map[string]*schema.Schema{
25+
"name": {
26+
Type: schema.TypeString,
27+
Computed: true,
28+
},
29+
"description": {
30+
Type: schema.TypeString,
31+
Computed: true,
32+
},
33+
"self_link": {
34+
Type: schema.TypeString,
35+
Computed: true,
36+
},
37+
"peeringdb_facility_id": {
38+
Type: schema.TypeString,
39+
Computed: true,
40+
},
41+
"address": {
42+
Type: schema.TypeString,
43+
Computed: true,
44+
},
45+
"facility_provider": {
46+
Type: schema.TypeString,
47+
Computed: true,
48+
},
49+
"facility_provider_facility_id": {
50+
Type: schema.TypeString,
51+
Computed: true,
52+
},
53+
"status": {
54+
Type: schema.TypeString,
55+
Computed: true,
56+
},
57+
"continent": {
58+
Type: schema.TypeString,
59+
Computed: true,
60+
},
61+
"city": {
62+
Type: schema.TypeString,
63+
Computed: true,
64+
},
65+
"availability_zone": {
66+
Type: schema.TypeString,
67+
Computed: true,
68+
},
69+
"supports_pzs": {
70+
Type: schema.TypeBool,
71+
Computed: true,
72+
},
73+
"available_features": {
74+
Type: schema.TypeList,
75+
Computed: true,
76+
Elem: &schema.Schema{
77+
Type: schema.TypeString,
78+
},
79+
},
80+
"available_link_types": {
81+
Type: schema.TypeList,
82+
Computed: true,
83+
Elem: &schema.Schema{
84+
Type: schema.TypeString,
85+
},
86+
},
87+
},
88+
},
89+
},
90+
},
91+
}
92+
}
93+
func dataSourceGoogleComputeInterconnectLocationsRead(d *schema.ResourceData, meta interface{}) error {
94+
config := meta.(*transport_tpg.Config)
95+
userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent)
96+
if err != nil {
97+
return err
98+
}
99+
project, err := tpgresource.GetProject(d, config)
100+
if err != nil {
101+
return err
102+
}
103+
d.SetId(fmt.Sprintf("projects/%s", project))
104+
list, err := config.NewComputeClient(userAgent).InterconnectLocations.List(project).Do()
105+
if err != nil {
106+
return fmt.Errorf("Error retrieving list of interconnect locations: %s", err)
107+
}
108+
var locations []map[string]interface{}
109+
for _, location := range list.Items {
110+
locations = append(locations, map[string]interface{}{
111+
"name": location.Name,
112+
"description": location.Description,
113+
"self_link": location.SelfLink,
114+
"peeringdb_facility_id": location.PeeringdbFacilityId,
115+
"address": location.Address,
116+
"facility_provider": location.FacilityProvider,
117+
"facility_provider_facility_id": location.FacilityProviderFacilityId,
118+
"status": location.Status,
119+
"continent": location.Continent,
120+
"city": location.City,
121+
"availability_zone": location.AvailabilityZone,
122+
"supports_pzs": location.SupportsPzs,
123+
"available_features": location.AvailableFeatures,
124+
"available_link_types": location.AvailableLinkTypes,
125+
})
126+
}
127+
if err := d.Set("locations", locations); err != nil {
128+
return fmt.Errorf("Error setting locations: %s", err)
129+
}
130+
return nil
131+
}

0 commit comments

Comments
 (0)