Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

feat(lb): add support for tags in LB IPs #2564

Merged
merged 9 commits into from
Jul 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions docs/data-sources/lb_ip.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,4 +50,6 @@ In addition to all above arguments, the following attributes are exported:

- `lb_id` - The ID of the associated Load Balancer, if any

- `tags` - The tags associated with this IP.

- `organization_id` - (Defaults to [provider](../index.md#organization_id) `organization_id`) The ID of the Organization the Load Balancer IP is associated with.
10 changes: 10 additions & 0 deletions docs/data-sources/lb_ips.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,22 @@ data "scaleway_lb_ips" "my_key" {
ip_cidr_range = "0.0.0.0/0"
zone = "fr-par-2"
}

# Find IPs that share the same tags and type
data "scaleway_lb_ips" "ips_by_tags_and_type" {
tags = [ "a tag" ]
ip_type = "ipv4"
}
```

## Argument Reference

- `ip_cidr_range` - (Optional) The IP CIDR range to filter for. IPs within a matching CIDR block are listed.

- `tags` - (Optional) List of tags used as filter. IPs with these exact tags are listed.

- `ip_type` - (Optional) The IP type used as a filter.

- `zone` - (Defaults to [provider](../index.md#zone) `zone`) The [zone](../guides/regions_and_zones.md#zones) in which the IPs exist.

## Attributes Reference
Expand Down
1 change: 1 addition & 0 deletions docs/resources/lb_ip.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ The following arguments are supported:
- `zone` - (Defaults to [provider](../index.md#zone) `zone`) The [zone](../guides/regions_and_zones.md#zones) in which the IP should be reserved.
- `project_id` - (Defaults to [provider](../index.md#project_id) `project_id`) The ID of the Project the IP is associated with.
- `reverse` - (Optional) The reverse domain associated with this IP.
- `tags` - (Optional) The tags associated with this IP.
- `is_ipv6` - (Optional) If true, creates a flexible IP with an IPv6 address.

## Attributes Reference
Expand Down
33 changes: 27 additions & 6 deletions internal/services/lb/ip.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,14 @@ func ResourceIP() *schema.Resource {
Default: false,
Description: "If true, creates a Flexible IP with an IPv6 address",
},
"tags": {
Type: schema.TypeList,
Elem: &schema.Schema{
Type: schema.TypeString,
},
Optional: true,
Description: "The tags associated with the flexible IP",
},
"region": regional.ComputedSchema(),
},
}
Expand All @@ -84,6 +92,7 @@ func resourceLbIPCreate(ctx context.Context, d *schema.ResourceData, m interface
ProjectID: types.ExpandStringPtr(d.Get("project_id")),
Reverse: types.ExpandStringPtr(d.Get("reverse")),
IsIPv6: d.Get("is_ipv6").(bool),
Tags: types.ExpandStrings(d.Get("tags")),
}

res, err := lbAPI.CreateIP(createReq, scw.WithContext(ctx))
Expand Down Expand Up @@ -139,6 +148,7 @@ func resourceLbIPRead(ctx context.Context, d *schema.ResourceData, m interface{}
_ = d.Set("ip_address", ip.IPAddress)
_ = d.Set("reverse", ip.Reverse)
_ = d.Set("lb_id", types.FlattenStringPtr(ip.LBID))
_ = d.Set("tags", ip.Tags)

isIPv6 := false
if ip.IPAddress != "" {
Expand Down Expand Up @@ -193,14 +203,25 @@ func resourceLbIPUpdate(ctx context.Context, d *schema.ResourceData, m interface
}
}

updateRequest := &lbSDK.ZonedAPIUpdateIPRequest{
Zone: zone,
IPID: ID,
}

hasChanged := false

if d.HasChange("reverse") {
req := &lbSDK.ZonedAPIUpdateIPRequest{
Zone: zone,
IPID: ID,
Reverse: types.ExpandStringPtr(d.Get("reverse")),
}
updateRequest.Reverse = types.ExpandStringPtr(d.Get("reverse"))
hasChanged = true
}

if d.HasChange("tags") {
updateRequest.Tags = types.ExpandUpdatedStringsPtr(d.Get("tags"))
hasChanged = true
}

_, err = lbAPI.UpdateIP(req, scw.WithContext(ctx))
if hasChanged {
_, err = lbAPI.UpdateIP(updateRequest, scw.WithContext(ctx))
if err != nil {
return diag.FromErr(err)
}
Expand Down
40 changes: 40 additions & 0 deletions internal/services/lb/ip_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,46 @@ func TestAccIP_IPv6(t *testing.T) {
})
}

func TestAccIP_WithTags(t *testing.T) {
tt := acctest.NewTestTools(t)
defer tt.Cleanup()
resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { acctest.PreCheck(t) },
ProviderFactories: tt.ProviderFactories,
CheckDestroy: lbchecks.IsIPDestroyed(tt),
Steps: []resource.TestStep{
{
Config: `
resource scaleway_lb_ip tags {
tags = [ "terraform-test", "lb", "ip" ]
}
`,
Check: resource.ComposeTestCheckFunc(
isIPPresent(tt, "scaleway_lb_ip.tags"),
resource.TestCheckResourceAttr("scaleway_lb_ip.tags", "tags.#", "3"),
resource.TestCheckResourceAttr("scaleway_lb_ip.tags", "tags.0", "terraform-test"),
resource.TestCheckResourceAttr("scaleway_lb_ip.tags", "tags.1", "lb"),
resource.TestCheckResourceAttr("scaleway_lb_ip.tags", "tags.2", "ip")),
},
{
Config: `
resource scaleway_lb_ip tags {
tags = [ "terraform-test", "lb", "ip", "updated" ]
}
`,
Check: resource.ComposeTestCheckFunc(
isIPPresent(tt, "scaleway_lb_ip.tags"),
resource.TestCheckResourceAttr("scaleway_lb_ip.tags", "tags.#", "4"),
resource.TestCheckResourceAttr("scaleway_lb_ip.tags", "tags.0", "terraform-test"),
resource.TestCheckResourceAttr("scaleway_lb_ip.tags", "tags.1", "lb"),
resource.TestCheckResourceAttr("scaleway_lb_ip.tags", "tags.2", "ip"),
resource.TestCheckResourceAttr("scaleway_lb_ip.tags", "tags.3", "updated"),
),
},
},
})
}

func isIPPresent(tt *acctest.TestTools, n string) resource.TestCheckFunc {
return func(state *terraform.State) error {
rs, ok := state.RootModule().Resources[n]
Expand Down
41 changes: 38 additions & 3 deletions internal/services/lb/ips_data_source.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,25 @@ func DataSourceIPs() *schema.Resource {
ValidateFunc: validation.IsCIDR,
Description: "IPs within a CIDR block like it are listed.",
},
"ip_type": {
Type: schema.TypeString,
Optional: true,
Default: lb.ListIPsRequestIPTypeAll.String(),
ValidateFunc: validation.StringInSlice([]string{
lb.ListIPsRequestIPTypeIPv4.String(),
lb.ListIPsRequestIPTypeIPv6.String(),
lb.ListIPsRequestIPTypeAll.String(),
}, false),
Description: "IP type to filter for",
},
"tags": {
Type: schema.TypeList,
Elem: &schema.Schema{
Type: schema.TypeString,
},
Optional: true,
Description: "IPs with these exact tags are listed",
},
"ips": {
Type: schema.TypeList,
Computed: true,
Expand All @@ -44,6 +63,13 @@ func DataSourceIPs() *schema.Resource {
Computed: true,
Type: schema.TypeString,
},
"tags": {
Computed: true,
Type: schema.TypeList,
Elem: &schema.Schema{
Type: schema.TypeString,
},
},
"zone": zonal.Schema(),
"organization_id": account.OrganizationIDSchema(),
"project_id": account.ProjectIDSchema(),
Expand All @@ -65,16 +91,22 @@ func DataSourceLbIPsRead(ctx context.Context, d *schema.ResourceData, m interfac
res, err := lbAPI.ListIPs(&lb.ZonedAPIListIPsRequest{
Zone: zone,
ProjectID: types.ExpandStringPtr(d.Get("project_id")),
Tags: types.ExpandStrings(d.Get("tags")),
IPType: lb.ListIPsRequestIPType(d.Get("ip_type").(string)),
}, scw.WithContext(ctx))
if err != nil {
return diag.FromErr(err)
}

var filteredList []*lb.IP
for i := range res.IPs {
if ipv4Match(d.Get("ip_cidr_range").(string), res.IPs[i].IPAddress) {
filteredList = append(filteredList, res.IPs[i])
if cidrRange, ok := d.GetOk("ip_cidr_range"); ok {
for i := range res.IPs {
if ipv4Match(cidrRange.(string), res.IPs[i].IPAddress) {
filteredList = append(filteredList, res.IPs[i])
}
}
} else {
filteredList = res.IPs
}

ips := []interface{}(nil)
Expand All @@ -87,6 +119,9 @@ func DataSourceLbIPsRead(ctx context.Context, d *schema.ResourceData, m interfac
rawIP["zone"] = string(zone)
rawIP["organization_id"] = ip.OrganizationID
rawIP["project_id"] = ip.ProjectID
if len(ip.Tags) > 0 {
rawIP["tags"] = ip.Tags
}

ips = append(ips, rawIP)
}
Expand Down
118 changes: 111 additions & 7 deletions internal/services/lb/ips_data_source_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,23 +29,127 @@ func TestAccDataSourceIPs_Basic(t *testing.T) {
resource scaleway_lb_ip ip2 {
}

data "scaleway_lb_ips" "lbs_by_cidr_range" {
data "scaleway_lb_ips" "ips_by_cidr_range" {
ip_cidr_range = "0.0.0.0/0"
depends_on = [scaleway_lb_ip.ip1, scaleway_lb_ip.ip2]
}
data "scaleway_lb_ips" "lbs_by_cidr_range_other_zone" {
data "scaleway_lb_ips" "ips_by_cidr_range_other_zone" {
ip_cidr_range = "0.0.0.0/0"
zone = "fr-par-2"
depends_on = [scaleway_lb_ip.ip1, scaleway_lb_ip.ip2]
}
`,
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttrSet("data.scaleway_lb_ips.lbs_by_cidr_range", "ips.0.id"),
resource.TestCheckResourceAttrSet("data.scaleway_lb_ips.lbs_by_cidr_range", "ips.0.ip_address"),
resource.TestCheckResourceAttrSet("data.scaleway_lb_ips.lbs_by_cidr_range", "ips.1.id"),
resource.TestCheckResourceAttrSet("data.scaleway_lb_ips.lbs_by_cidr_range", "ips.1.ip_address"),
resource.TestCheckResourceAttrSet("data.scaleway_lb_ips.ips_by_cidr_range", "ips.0.id"),
resource.TestCheckResourceAttrSet("data.scaleway_lb_ips.ips_by_cidr_range", "ips.0.ip_address"),
resource.TestCheckResourceAttrSet("data.scaleway_lb_ips.ips_by_cidr_range", "ips.1.id"),
resource.TestCheckResourceAttrSet("data.scaleway_lb_ips.ips_by_cidr_range", "ips.1.ip_address"),

resource.TestCheckNoResourceAttr("data.scaleway_lb_ips.lbs_by_cidr_range_other_zone", "ips.0.id"),
resource.TestCheckNoResourceAttr("data.scaleway_lb_ips.ips_by_cidr_range_other_zone", "ips.0.id"),
),
},
},
})
}

func TestAccDataSourceIPs_WithType(t *testing.T) {
tt := acctest.NewTestTools(t)
defer tt.Cleanup()
resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { acctest.PreCheck(t) },
ProviderFactories: tt.ProviderFactories,
CheckDestroy: lbchecks.IsIPDestroyed(tt),
Steps: []resource.TestStep{
{
Config: `
resource scaleway_lb_ip ip1 {
}
`,
},
{
Config: `
resource scaleway_lb_ip ip1 {
}
resource scaleway_lb_ip ip2 {
is_ipv6 = true
}
`,
},
{
Config: `
resource scaleway_lb_ip ip1 {
}
resource scaleway_lb_ip ip2 {
is_ipv6 = true
}
resource scaleway_lb_ip ip3 {
}

data "scaleway_lb_ips" "ips_by_type" {
ip_type = "ipv4"
depends_on = [scaleway_lb_ip.ip1, scaleway_lb_ip.ip2, scaleway_lb_ip.ip3]
}
`,
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr("data.scaleway_lb_ips.ips_by_type", "ips.#", "2"),
resource.TestCheckResourceAttrSet("data.scaleway_lb_ips.ips_by_type", "ips.0.id"),
resource.TestCheckResourceAttrSet("data.scaleway_lb_ips.ips_by_type", "ips.0.ip_address"),
resource.TestCheckResourceAttrSet("data.scaleway_lb_ips.ips_by_type", "ips.1.id"),
resource.TestCheckResourceAttrSet("data.scaleway_lb_ips.ips_by_type", "ips.1.ip_address"),
),
},
},
})
}

func TestAccDataSourceIPs_WithTags(t *testing.T) {
tt := acctest.NewTestTools(t)
defer tt.Cleanup()
resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { acctest.PreCheck(t) },
ProviderFactories: tt.ProviderFactories,
CheckDestroy: lbchecks.IsIPDestroyed(tt),
Steps: []resource.TestStep{
{
Config: `
resource scaleway_lb_ip ip1 {
tags = [ "ipv4", "ip" ]
}
`,
},
{
Config: `
resource scaleway_lb_ip ip1 {
tags = [ "ipv4", "ip" ]
}
resource scaleway_lb_ip ip2 {
tags = [ "ipv4", "ip" ]
}
`,
},
{
Config: `
resource scaleway_lb_ip ip1 {
tags = [ "ipv4", "ip" ]
}
resource scaleway_lb_ip ip2 {
tags = [ "ipv4", "ip" ]
}
resource scaleway_lb_ip ip3 {
tags = [ "other", "tags" ]
}

data "scaleway_lb_ips" "ips_by_tags" {
tags = [ "ipv4", "ip" ]
depends_on = [scaleway_lb_ip.ip1, scaleway_lb_ip.ip2, scaleway_lb_ip.ip3]
}
`,
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr("data.scaleway_lb_ips.ips_by_tags", "ips.#", "2"),
resource.TestCheckResourceAttrSet("data.scaleway_lb_ips.ips_by_tags", "ips.0.id"),
resource.TestCheckResourceAttrSet("data.scaleway_lb_ips.ips_by_tags", "ips.0.ip_address"),
resource.TestCheckResourceAttrSet("data.scaleway_lb_ips.ips_by_tags", "ips.1.id"),
resource.TestCheckResourceAttrSet("data.scaleway_lb_ips.ips_by_tags", "ips.1.ip_address"),
),
},
},
Expand Down
Loading
Loading