Skip to content

Commit 0333377

Browse files
authored
feat(lb): add support for certificates id list (#1152)
1 parent a7a0584 commit 0333377

File tree

5 files changed

+2541
-10
lines changed

5 files changed

+2541
-10
lines changed

docs/resources/lb_frontend.md

+38-2
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ description: |-
88

99
Creates and manages Scaleway Load-Balancer Frontends. For more information, see [the documentation](https://developers.scaleway.com/en/products/lb/zoned_api).
1010

11-
## Examples
11+
## Examples Usage
1212

1313
### Basic
1414

@@ -21,6 +21,40 @@ resource "scaleway_lb_frontend" "frontend01" {
2121
}
2222
```
2323

24+
## With Certificate
25+
26+
```hcl
27+
resource scaleway_lb_ip ip01 {}
28+
29+
resource scaleway_lb lb01 {
30+
ip_id = scaleway_lb_ip.ip01.id
31+
name = "test-lb"
32+
type = "lb-s"
33+
}
34+
35+
resource scaleway_lb_backend bkd01 {
36+
lb_id = scaleway_lb.lb01.id
37+
forward_protocol = "tcp"
38+
forward_port = 443
39+
proxy_protocol = "none"
40+
}
41+
42+
resource scaleway_lb_certificate cert01 {
43+
lb_id = scaleway_lb.lb01.id
44+
name = "test-cert-front-end"
45+
letsencrypt {
46+
common_name = "${replace(scaleway_lb_ip.ip01.ip_address,".", "-")}.lb.${scaleway_lb.lb01.region}.scw.cloud"
47+
}
48+
}
49+
50+
resource scaleway_lb_frontend frt01 {
51+
lb_id = scaleway_lb.lb01.id
52+
backend_id = scaleway_lb_backend.bkd01.id
53+
inbound_port = 443
54+
certificate_ids = [scaleway_lb_certificate.cert01.id]
55+
}
56+
```
57+
2458
## With ACLs
2559

2660
```hcl
@@ -94,7 +128,7 @@ The following arguments are supported:
94128

95129
- `timeout_client` - (Optional) Maximum inactivity time on the client side. (e.g.: `1s`)
96130

97-
- `certificate_id` - (Optional) Certificate ID that should be used by the frontend.
131+
- `certificate_ids` - (Optional) List of Certificate IDs that should be used by the frontend.
98132

99133
- `acl` - (Optional) A list of ACL rules to apply to the load-balancer frontend. Defined below.
100134

@@ -123,6 +157,8 @@ The following arguments are supported:
123157
In addition to all arguments above, the following attributes are exported:
124158

125159
- `id` - The ID of the load-balancer frontend.
160+
- `certificate_id` - (Deprecated) first certificate ID used by the frontend.
161+
126162

127163
## Import
128164

scaleway/helpers.go

+20
Original file line numberDiff line numberDiff line change
@@ -396,6 +396,17 @@ func expandStringsPtr(data interface{}) *[]string {
396396
return &stringSlice
397397
}
398398

399+
func expandSliceIDsPtr(rawIDs interface{}) *[]string {
400+
var stringSlice []string
401+
if _, ok := rawIDs.([]interface{}); !ok || rawIDs == nil {
402+
return &stringSlice
403+
}
404+
for _, s := range rawIDs.([]interface{}) {
405+
stringSlice = append(stringSlice, expandID(s.(string)))
406+
}
407+
return &stringSlice
408+
}
409+
399410
func expandStringsOrEmpty(data interface{}) []string {
400411
var stringSlice []string
401412
if _, ok := data.([]interface{}); !ok || data == nil {
@@ -440,6 +451,15 @@ func flattenSliceStringPtr(s []*string) interface{} {
440451
return res
441452
}
442453

454+
func flattenSliceIDs(certificates []string, zone scw.Zone) interface{} {
455+
res := []interface{}(nil)
456+
for _, certificateID := range certificates {
457+
res = append(res, newZonedIDString(zone, certificateID))
458+
}
459+
460+
return res
461+
}
462+
443463
func expandStringPtr(data interface{}) *string {
444464
if data == nil || data == "" {
445465
return nil

scaleway/resource_lb_frontend.go

+31-8
Original file line numberDiff line numberDiff line change
@@ -64,10 +64,19 @@ func resourceScalewayLbFrontend() *schema.Resource {
6464
Description: "Set the maximum inactivity time on the client side",
6565
},
6666
"certificate_id": {
67-
Type: schema.TypeString,
68-
Optional: true,
69-
ValidateFunc: validationUUIDorUUIDWithLocality(),
70-
Description: "Certificate ID",
67+
Type: schema.TypeString,
68+
Computed: true,
69+
Description: "Certificate ID",
70+
Deprecated: "Please use certificate_ids",
71+
},
72+
"certificate_ids": {
73+
Type: schema.TypeList,
74+
Optional: true,
75+
Elem: &schema.Schema{
76+
Type: schema.TypeString,
77+
ValidateFunc: validationUUIDorUUIDWithLocality(),
78+
},
79+
Description: "Collection of Certificate IDs related to the load balancer and domain",
7180
},
7281
"acl": {
7382
Type: schema.TypeList,
@@ -182,15 +191,22 @@ func resourceScalewayLbFrontendCreate(ctx context.Context, d *schema.ResourceDat
182191
if err != nil {
183192
return diag.FromErr(err)
184193
}
185-
res, err := lbAPI.CreateFrontend(&lb.ZonedAPICreateFrontendRequest{
194+
195+
createFrontendRequest := &lb.ZonedAPICreateFrontendRequest{
186196
Zone: zone,
187197
LBID: lbID,
188198
Name: expandOrGenerateString(d.Get("name"), "lb-frt"),
189199
InboundPort: int32(d.Get("inbound_port").(int)),
190200
BackendID: expandID(d.Get("backend_id")),
191201
TimeoutClient: timeoutClient,
192-
CertificateID: expandStringPtr(expandID(d.Get("certificate_id"))),
193-
}, scw.WithContext(ctx))
202+
}
203+
204+
certificatesRaw, certificatesExist := d.GetOk("certificate_ids")
205+
if certificatesExist {
206+
createFrontendRequest.CertificateIDs = expandSliceIDsPtr(certificatesRaw)
207+
}
208+
209+
res, err := lbAPI.CreateFrontend(createFrontendRequest, scw.WithContext(ctx))
194210
if err != nil {
195211
return diag.FromErr(err)
196212
}
@@ -235,6 +251,10 @@ func resourceScalewayLbFrontendRead(ctx context.Context, d *schema.ResourceData,
235251
_ = d.Set("certificate_id", "")
236252
}
237253

254+
if len(res.CertificateIDs) > 0 {
255+
_ = d.Set("certificate_ids", flattenSliceIDs(res.CertificateIDs, zone))
256+
}
257+
238258
//read related acls.
239259
resACL, err := lbAPI.ListACLs(&lb.ZonedAPIListACLsRequest{
240260
Zone: zone,
@@ -377,7 +397,10 @@ func resourceScalewayLbFrontendUpdate(ctx context.Context, d *schema.ResourceDat
377397
InboundPort: int32(d.Get("inbound_port").(int)),
378398
BackendID: expandID(d.Get("backend_id")),
379399
TimeoutClient: timeoutClient,
380-
CertificateID: expandStringPtr(expandID(d.Get("certificate_id"))),
400+
}
401+
402+
if d.HasChanges("certificate_ids") {
403+
req.CertificateIDs = expandSliceIDsPtr(d.Get("certificate_ids"))
381404
}
382405

383406
_, err = lbAPI.UpdateFrontend(req, scw.WithContext(ctx))

scaleway/resource_lb_frontend_test.go

+104
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,110 @@ func TestAccScalewayLbFrontend_Basic(t *testing.T) {
7878
})
7979
}
8080

81+
func TestAccScalewayLbFrontend_Certificate(t *testing.T) {
82+
tt := NewTestTools(t)
83+
defer tt.Cleanup()
84+
testDNSZone := fmt.Sprintf("test.%s", testDomain)
85+
resource.ParallelTest(t, resource.TestCase{
86+
PreCheck: func() { testAccPreCheck(t) },
87+
ProviderFactories: tt.ProviderFactories,
88+
CheckDestroy: testAccCheckScalewayLbFrontendDestroy(tt),
89+
Steps: []resource.TestStep{
90+
{
91+
Config: fmt.Sprintf(`
92+
resource scaleway_lb_ip ip01 {}
93+
94+
resource "scaleway_domain_record" "tf_A" {
95+
dns_zone = %[1]q
96+
name = "test"
97+
type = "A"
98+
data = "${scaleway_lb_ip.ip01.ip_address}"
99+
ttl = 3600
100+
priority = 1
101+
}
102+
103+
resource scaleway_lb lb01 {
104+
ip_id = scaleway_lb_ip.ip01.id
105+
name = "test-lb"
106+
type = "lb-s"
107+
}
108+
109+
resource scaleway_lb_backend bkd01 {
110+
lb_id = scaleway_lb.lb01.id
111+
forward_protocol = "http"
112+
forward_port = 80
113+
proxy_protocol = "none"
114+
}
115+
116+
resource scaleway_lb_certificate cert01 {
117+
lb_id = scaleway_lb.lb01.id
118+
name = "test-cert-front-end"
119+
letsencrypt {
120+
common_name = "${replace(scaleway_lb_ip.ip01.ip_address,".", "-")}.lb.${scaleway_lb.lb01.region}.scw.cloud"
121+
}
122+
}
123+
124+
resource scaleway_lb_certificate cert02 {
125+
lb_id = scaleway_lb.lb01.id
126+
name = "test-cert-front-end2"
127+
letsencrypt {
128+
common_name = %[2]q
129+
}
130+
}
131+
132+
resource scaleway_lb_frontend frt01 {
133+
lb_id = scaleway_lb.lb01.id
134+
backend_id = scaleway_lb_backend.bkd01.id
135+
inbound_port = 80
136+
certificate_ids = [scaleway_lb_certificate.cert01.id, scaleway_lb_certificate.cert02.id]
137+
}
138+
`, testDomain, testDNSZone),
139+
Check: resource.ComposeTestCheckFunc(
140+
testAccCheckScalewayLbFrontendExists(tt, "scaleway_lb_frontend.frt01"),
141+
testAccCheckScalewayFrontendCertificateExist(tt, "scaleway_lb_frontend.frt01", "scaleway_lb_certificate.cert01"),
142+
testAccCheckScalewayFrontendCertificateExist(tt, "scaleway_lb_frontend.frt01", "scaleway_lb_certificate.cert02"),
143+
resource.TestCheckResourceAttr("scaleway_lb_frontend.frt01",
144+
"certificate_ids.#", "2"),
145+
),
146+
},
147+
},
148+
})
149+
}
150+
func testAccCheckScalewayFrontendCertificateExist(tt *TestTools, f, c string) resource.TestCheckFunc {
151+
return func(s *terraform.State) error {
152+
rs, ok := s.RootModule().Resources[f]
153+
if !ok {
154+
return fmt.Errorf("resource not found: %s", f)
155+
}
156+
157+
cs, ok := s.RootModule().Resources[c]
158+
if !ok {
159+
return fmt.Errorf("resource not found: %s", c)
160+
}
161+
162+
lbAPI, zone, ID, err := lbAPIWithZoneAndID(tt.Meta, rs.Primary.ID)
163+
if err != nil {
164+
return err
165+
}
166+
167+
frEnd, err := lbAPI.GetFrontend(&lb.ZonedAPIGetFrontendRequest{
168+
FrontendID: ID,
169+
Zone: zone,
170+
})
171+
if err != nil {
172+
return err
173+
}
174+
175+
for _, id := range frEnd.CertificateIDs {
176+
if expandID(cs.Primary.ID) == id {
177+
return nil
178+
}
179+
}
180+
181+
return fmt.Errorf("certificate not found: %s", c)
182+
}
183+
}
184+
81185
func testAccCheckScalewayLbFrontendExists(tt *TestTools, n string) resource.TestCheckFunc {
82186
return func(s *terraform.State) error {
83187
rs, ok := s.RootModule().Resources[n]

0 commit comments

Comments
 (0)