Skip to content

Commit 8045e96

Browse files
authored
fix(load-balancer): wait for action of managed certificate (#1144)
The action from creating the managed certificate was not awaited, which could cause issues where the creation fails, but this is not reported back on the Service. We now await the action and report its status back to the controller.
1 parent f66b1ce commit 8045e96

File tree

5 files changed

+25
-11
lines changed

5 files changed

+25
-11
lines changed

hcloud/cloud.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@ func (c *cloud) LoadBalancer() (cloudprovider.LoadBalancer, bool) {
187187
lbOps := &hcops.LoadBalancerOps{
188188
LBClient: &c.client.LoadBalancer,
189189
RobotClient: c.robotClient,
190-
CertOps: &hcops.CertificateOps{CertClient: &c.client.Certificate},
190+
CertOps: &hcops.CertificateOps{ActionClient: &c.client.Action, CertClient: &c.client.Certificate},
191191
ActionClient: &c.client.Action,
192192
NetworkClient: &c.client.Network,
193193
NetworkID: c.networkID,

internal/hcops/certificates.go

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ type HCloudCertificateClient interface {
2020

2121
// CertificateOps implements all operations regarding Hetzner Cloud Certificates.
2222
type CertificateOps struct {
23-
CertClient HCloudCertificateClient
23+
ActionClient HCloudActionClient
24+
CertClient HCloudCertificateClient
2425
}
2526

2627
// GetCertificateByNameOrID obtains a certificate from the Hetzner Cloud
@@ -81,12 +82,18 @@ func (co *CertificateOps) CreateManagedCertificate(
8182
DomainNames: domains,
8283
Labels: labels,
8384
}
84-
_, _, err := co.CertClient.CreateCertificate(ctx, opts)
85+
result, _, err := co.CertClient.CreateCertificate(ctx, opts)
8586
if hcloud.IsError(err, hcloud.ErrorCodeUniquenessError) {
8687
return fmt.Errorf("%s: %w", op, ErrAlreadyExists)
8788
}
8889
if err != nil {
8990
return fmt.Errorf("%s: %w", op, err)
9091
}
92+
93+
err = co.ActionClient.WaitFor(ctx, result.Action)
94+
if err != nil {
95+
return fmt.Errorf("%s: %w", op, err)
96+
}
97+
9198
return nil
9299
}

internal/hcops/certificates_test.go

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ func TestCertificateOps_CreateManagedCertificate(t *testing.T) {
171171
{
172172
Name: "certificate creation successful",
173173
Mock: func(_ *testing.T, tt *certificateOpsTestCase) {
174-
res := hcloud.CertificateCreateResult{Certificate: &hcloud.Certificate{ID: 1}}
174+
res := hcloud.CertificateCreateResult{Certificate: &hcloud.Certificate{ID: 1}, Action: &hcloud.Action{ID: 2}}
175175
tt.CertClient.
176176
On("CreateCertificate", tt.Ctx, hcloud.CertificateCreateOpts{
177177
Name: "test-cert",
@@ -180,6 +180,7 @@ func TestCertificateOps_CreateManagedCertificate(t *testing.T) {
180180
Labels: map[string]string{"key": "value"},
181181
}).
182182
Return(res, nil, nil)
183+
tt.ActionClient.On("WaitFor", tt.Ctx, &hcloud.Action{ID: 2}).Return(nil)
183184
},
184185
Perform: func(t *testing.T, tt *certificateOpsTestCase) {
185186
err := tt.CertOps.CreateManagedCertificate(
@@ -204,9 +205,10 @@ type certificateOpsTestCase struct {
204205
ClientErr error
205206

206207
// Set in run before actual test execution
207-
Ctx context.Context
208-
CertOps *hcops.CertificateOps
209-
CertClient *mocks.CertificateClient
208+
Ctx context.Context
209+
CertOps *hcops.CertificateOps
210+
CertClient *mocks.CertificateClient
211+
ActionClient *mocks.ActionClient
210212
}
211213

212214
func (tt *certificateOpsTestCase) run(t *testing.T) {
@@ -215,7 +217,9 @@ func (tt *certificateOpsTestCase) run(t *testing.T) {
215217
tt.Ctx = context.Background()
216218
tt.CertClient = &mocks.CertificateClient{}
217219
tt.CertClient.Test(t)
218-
tt.CertOps = &hcops.CertificateOps{CertClient: tt.CertClient}
220+
tt.ActionClient = &mocks.ActionClient{}
221+
tt.ActionClient.Test(t)
222+
tt.CertOps = &hcops.CertificateOps{ActionClient: tt.ActionClient, CertClient: tt.CertClient}
219223

220224
if tt.Mock != nil {
221225
tt.Mock(t, tt)

internal/hcops/load_balancer_internal_test.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@ func TestHCLBServiceOptsBuilder(t *testing.T) {
2929
mock func(t *testing.T, tt *testCase)
3030

3131
// Set during test setup
32-
certClient *mocks.CertificateClient
32+
certClient *mocks.CertificateClient
33+
actionClient *mocks.ActionClient
3334
}
3435

3536
tests := []testCase{
@@ -429,6 +430,8 @@ func TestHCLBServiceOptsBuilder(t *testing.T) {
429430
t.Run(tt.name, func(t *testing.T) {
430431
tt.certClient = &mocks.CertificateClient{}
431432
tt.certClient.Test(t)
433+
tt.actionClient = &mocks.ActionClient{}
434+
tt.actionClient.Test(t)
432435

433436
if tt.mock != nil {
434437
tt.mock(t, &tt)
@@ -442,7 +445,7 @@ func TestHCLBServiceOptsBuilder(t *testing.T) {
442445
Annotations: map[string]string{},
443446
},
444447
},
445-
CertOps: &CertificateOps{CertClient: tt.certClient},
448+
CertOps: &CertificateOps{ActionClient: tt.actionClient, CertClient: tt.certClient},
446449
cfg: tt.cfg,
447450
}
448451
for k, v := range tt.serviceAnnotations {

internal/hcops/testing.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ func NewLoadBalancerOpsFixture(t *testing.T) *LoadBalancerOpsFixture {
4646

4747
fx.LBOps = &LoadBalancerOps{
4848
LBClient: fx.LBClient,
49-
CertOps: &CertificateOps{CertClient: fx.CertClient},
49+
CertOps: &CertificateOps{ActionClient: fx.ActionClient, CertClient: fx.CertClient},
5050
ActionClient: fx.ActionClient,
5151
NetworkClient: fx.NetworkClient,
5252
RobotClient: fx.RobotClient,

0 commit comments

Comments
 (0)