Skip to content

Commit 9634203

Browse files
committed
changelogs, waiters, examples
1 parent e807be0 commit 9634203

File tree

9 files changed

+283
-20
lines changed

9 files changed

+283
-20
lines changed

CHANGELOG.md

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,15 @@
66
- **Feature:** Add new field `AltPort` to `ActiveHealthCheck`
77
- **Feature:** Add new field `Tls` to `HttpHealthCheck`
88
- **Breaking change:** Renamed `TargetPoolTlsConfig` to `TlsConfig`
9-
- `loadbalancer`: [v1.8.0](services/loadbalancer/CHANGELOG.md#v180)
10-
- **Feature:** Add new fields `AltPort` and `HttpHealthCheck` to `ActiveHealthCheck`
9+
- `loadbalancer`:
10+
- [v1.8.0](services/loadbalancer/CHANGELOG.md#v180)
11+
- **Feature:** Add new fields `AltPort` and `HttpHealthCheck` to `ActiveHealthCheck`
12+
- [v1.9.0](services/loadbalancer/CHANGELOG.md#v190)
13+
- **Feature:** Introduction of multi API version support for the loadbalancer SDK module. For more details please see the announcement on GitHub: https://github.com/stackitcloud/stackit-sdk-go/discussions/5062
14+
- `v1api`: New package which can be used for communication with the loadbalancer v1 API
15+
- `v2api`: New package which can be used for communication with the loadbalancer v2 API
16+
- **Deprecation:** The contents in the root of this SDK module including the `wait` package are marked as deprecated and will be removed after 2026-09-30. Switch to the new packages for the available API versions instead.
17+
- **Dependencies:** Bump STACKIT SDK core module from `v0.21.1` to `v0.22.0`
1118
- `resourcemanager`: [v0.19.0](services/resourcemanager/CHANGELOG.md#v0190)
1219
- **Feature:** Introduction of multi API version support for the resourcemanager SDK module. For more details please see the announcement on GitHub: https://github.com/stackitcloud/stackit-sdk-go/discussions/5062
1320
- `v0api`: New package which should be used for communication with the STACKIT Resourcemanager API in the future

examples/loadbalancer/go.mod

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,11 @@ module github.com/stackitcloud/stackit-sdk-go/examples/loadbalancer
22

33
go 1.21
44

5+
// This is not needed in production. This is only here to point the golangci linter to the local version instead of the last release on GitHub.
6+
replace github.com/stackitcloud/stackit-sdk-go/services/loadbalancer => ../../services/loadbalancer
7+
58
require (
6-
github.com/stackitcloud/stackit-sdk-go/core v0.21.1
9+
github.com/stackitcloud/stackit-sdk-go/core v0.22.0
710
github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.7.3
811
)
912

examples/loadbalancer/go.sum

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,5 @@ github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
44
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
55
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
66
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
7-
github.com/stackitcloud/stackit-sdk-go/core v0.21.1 h1:Y/PcAgM7DPYMNqum0MLv4n1mF9ieuevzcCIZYQfm3Ts=
8-
github.com/stackitcloud/stackit-sdk-go/core v0.21.1/go.mod h1:osMglDby4csGZ5sIfhNyYq1bS1TxIdPY88+skE/kkmI=
9-
github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.7.3 h1:d/qIj+XNaqByVbLvwpWoA0Ekv0yrONWyNswg4/jGX7Y=
10-
github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.7.3/go.mod h1:ClPE4TOM1FeaJiwTXvApq4gWaSgTLq6nU3PPHAIQDN4=
7+
github.com/stackitcloud/stackit-sdk-go/core v0.22.0 h1:6rViz7GnNwXSh51Lur5xuDzO8EWSZfN9J0HvEkBKq6c=
8+
github.com/stackitcloud/stackit-sdk-go/core v0.22.0/go.mod h1:osMglDby4csGZ5sIfhNyYq1bS1TxIdPY88+skE/kkmI=

examples/loadbalancer/loadbalancer.go

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import (
66
"os"
77

88
"github.com/stackitcloud/stackit-sdk-go/core/utils"
9-
"github.com/stackitcloud/stackit-sdk-go/services/loadbalancer"
9+
loadbalancer "github.com/stackitcloud/stackit-sdk-go/services/loadbalancer/v2api"
1010
)
1111

1212
func main() {
@@ -23,15 +23,15 @@ func main() {
2323
}
2424

2525
// List the load balancer instances for your project
26-
listInstancesResp, err := loadbalancerClient.ListLoadBalancers(context.Background(), projectId, region).Execute()
26+
listInstancesResp, err := loadbalancerClient.DefaultAPI.ListLoadBalancers(context.Background(), projectId, region).Execute()
2727
if err != nil {
2828
fmt.Fprintf(os.Stderr, "Error when calling `ListLoadBalancers`: %v\n", err)
2929
os.Exit(1)
3030
}
3131
if listInstancesResp.LoadBalancers == nil {
3232
fmt.Printf("Current project does not have any load balancer instances.\n")
3333
} else {
34-
lbs := *listInstancesResp.LoadBalancers
34+
lbs := listInstancesResp.LoadBalancers
3535
fmt.Printf("Number of instances: %v\n", len(lbs))
3636
}
3737

@@ -41,25 +41,25 @@ func main() {
4141
Options: &loadbalancer.LoadBalancerOptions{
4242
PrivateNetworkOnly: utils.Ptr(true),
4343
},
44-
Networks: &[]loadbalancer.Network{
44+
Networks: []loadbalancer.Network{
4545
{
4646
NetworkId: utils.Ptr("xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"),
47-
Role: utils.Ptr(loadbalancer.NETWORKROLE_LISTENERS_AND_TARGETS),
47+
Role: utils.Ptr("ROLE_LISTENERS_AND_TARGETS"),
4848
},
4949
},
50-
Listeners: &[]loadbalancer.Listener{
50+
Listeners: []loadbalancer.Listener{
5151
{
5252
DisplayName: utils.Ptr("example-listener"),
53-
Port: utils.Ptr(int64(1)),
54-
Protocol: utils.Ptr(loadbalancer.LISTENERPROTOCOL_TCP),
53+
Port: utils.Ptr(int32(1)),
54+
Protocol: utils.Ptr("PROTOCOL_TCP"),
5555
TargetPool: utils.Ptr("example-target-pool"),
5656
},
5757
},
58-
TargetPools: &[]loadbalancer.TargetPool{
58+
TargetPools: []loadbalancer.TargetPool{
5959
{
6060
Name: utils.Ptr("example-target-pool"),
61-
TargetPort: utils.Ptr(int64(1)),
62-
Targets: &[]loadbalancer.Target{
61+
TargetPort: utils.Ptr(int32(1)),
62+
Targets: []loadbalancer.Target{
6363
{
6464
DisplayName: utils.Ptr("example-target"),
6565
Ip: utils.Ptr("x.x.x.x"),
@@ -68,7 +68,7 @@ func main() {
6868
},
6969
},
7070
}
71-
createLoadBalancerRes, err := loadbalancerClient.CreateLoadBalancer(context.Background(), projectId, region).CreateLoadBalancerPayload(createLoadBalancerPayload).XRequestID("xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx").Execute()
71+
createLoadBalancerRes, err := loadbalancerClient.DefaultAPI.CreateLoadBalancer(context.Background(), projectId, region).CreateLoadBalancerPayload(createLoadBalancerPayload).XRequestID("xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx").Execute()
7272
if err != nil {
7373
fmt.Fprintf(os.Stderr, "Error when calling `CreateLoadBalancer`: %v\n", err)
7474
os.Exit(1)

services/loadbalancer/CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
## v1.9.0
2+
- **Feature:** Introduction of multi API version support for the loadbalancer SDK module. For more details please see the announcement on GitHub: https://github.com/stackitcloud/stackit-sdk-go/discussions/5062
3+
- `v1api`: New package which can be used for communication with the loadbalancer v1 API
4+
- `v2api`: New package which can be used for communication with the loadbalancer v2 API
5+
- **Deprecation:** The contents in the root of this SDK module including the `wait` package are marked as deprecated and will be removed after 2026-09-30. Switch to the new packages for the available API versions instead.
6+
- **Dependencies:** Bump STACKIT SDK core module from `v0.21.1` to `v0.22.0`
7+
18
## v1.8.0
29
- **Feature:** Add new fields `AltPort` and `HttpHealthCheck` to `ActiveHealthCheck`
310

services/loadbalancer/VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
v1.8.0
1+
v1.9.0
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
package wait
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"net/http"
7+
"strings"
8+
"time"
9+
10+
"github.com/stackitcloud/stackit-sdk-go/core/oapierror"
11+
"github.com/stackitcloud/stackit-sdk-go/core/wait"
12+
loadbalancer "github.com/stackitcloud/stackit-sdk-go/services/loadbalancer/v2api"
13+
)
14+
15+
// Load balancer instance status
16+
const (
17+
LOADBALANCERSTATUS_UNSPECIFIED = "STATUS_UNSPECIFIED"
18+
LOADBALANCERSTATUS_PENDING = "STATUS_PENDING"
19+
LOADBALANCERSTATUS_READY = "STATUS_READY"
20+
LOADBALANCERSTATUS_ERROR = "STATUS_ERROR"
21+
LOADBALANCERSTATUS_TERMINATING = "STATUS_TERMINATING"
22+
)
23+
24+
// CreateLoadBalancerWaitHandler will wait for load balancer creation
25+
func CreateLoadBalancerWaitHandler(ctx context.Context, a loadbalancer.DefaultAPI, projectId, region, instanceName string) *wait.AsyncActionHandler[loadbalancer.LoadBalancer] {
26+
handler := wait.New(func() (waitFinished bool, response *loadbalancer.LoadBalancer, err error) {
27+
s, err := a.GetLoadBalancer(ctx, projectId, region, instanceName).Execute()
28+
if err != nil {
29+
return false, nil, err
30+
}
31+
if s == nil || s.Name == nil || *s.Name != instanceName || s.Status == nil {
32+
return false, nil, nil
33+
}
34+
35+
var errors []string
36+
if len(s.Errors) > 0 {
37+
for _, err := range s.Errors {
38+
errors = append(errors, fmt.Sprintf("%s: %s", *err.Type, *err.Description))
39+
}
40+
return true, s, fmt.Errorf("create failed for instance with name %s, got status %s and errors: %s", instanceName, *s.Status, strings.Join(errors, ";"))
41+
}
42+
43+
switch *s.Status {
44+
case LOADBALANCERSTATUS_READY:
45+
return true, s, nil
46+
case LOADBALANCERSTATUS_UNSPECIFIED:
47+
return false, nil, nil
48+
case LOADBALANCERSTATUS_PENDING:
49+
return false, nil, nil
50+
case LOADBALANCERSTATUS_TERMINATING:
51+
return true, s, fmt.Errorf("create failed for instance with name %s, got status %s", instanceName, LOADBALANCERSTATUS_TERMINATING)
52+
case LOADBALANCERSTATUS_ERROR:
53+
return true, s, fmt.Errorf("create failed for instance with name %s, got status %s", instanceName, LOADBALANCERSTATUS_ERROR)
54+
default:
55+
return true, s, fmt.Errorf("instance with name %s has unexpected status %s", instanceName, *s.Status)
56+
}
57+
})
58+
handler.SetTimeout(45 * time.Minute)
59+
return handler
60+
}
61+
62+
// DeleteLoadBalancerWaitHandler will wait for load balancer deletion
63+
func DeleteLoadBalancerWaitHandler(ctx context.Context, a loadbalancer.DefaultAPI, projectId, region, instanceId string) *wait.AsyncActionHandler[struct{}] {
64+
handler := wait.New(func() (waitFinished bool, response *struct{}, err error) {
65+
_, err = a.GetLoadBalancer(ctx, projectId, region, instanceId).Execute()
66+
if err == nil {
67+
return false, nil, nil
68+
}
69+
oapiErr, ok := err.(*oapierror.GenericOpenAPIError) //nolint:errorlint //complaining that error.As should be used to catch wrapped errors, but this error should not be wrapped
70+
if !ok {
71+
return false, nil, fmt.Errorf("could not convert error to oapierror.GenericOpenAPIError")
72+
}
73+
if oapiErr.StatusCode != http.StatusNotFound {
74+
return false, nil, err
75+
}
76+
return true, nil, nil
77+
})
78+
handler.SetTimeout(15 * time.Minute)
79+
return handler
80+
}
Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
package wait
2+
3+
import (
4+
"context"
5+
"testing"
6+
"time"
7+
8+
"github.com/google/go-cmp/cmp"
9+
"github.com/stackitcloud/stackit-sdk-go/core/oapierror"
10+
"github.com/stackitcloud/stackit-sdk-go/core/utils"
11+
loadbalancer "github.com/stackitcloud/stackit-sdk-go/services/loadbalancer/v2api"
12+
)
13+
14+
const testRegion = "eu01"
15+
16+
type mockSettings struct {
17+
instanceName string
18+
instanceStatus *string
19+
instanceIsDeleted bool
20+
instanceGetFails bool
21+
}
22+
23+
func newAPIMock(settings *mockSettings) loadbalancer.DefaultAPI {
24+
return &loadbalancer.DefaultAPIServiceMock{
25+
GetLoadBalancerExecuteMock: utils.Ptr(func(_ loadbalancer.ApiGetLoadBalancerRequest) (*loadbalancer.LoadBalancer, error) {
26+
if settings.instanceGetFails {
27+
return nil, &oapierror.GenericOpenAPIError{
28+
StatusCode: 500,
29+
}
30+
}
31+
32+
if settings.instanceIsDeleted {
33+
return nil, &oapierror.GenericOpenAPIError{
34+
StatusCode: 404,
35+
}
36+
}
37+
38+
return &loadbalancer.LoadBalancer{
39+
Name: &settings.instanceName,
40+
Status: settings.instanceStatus,
41+
}, nil
42+
}),
43+
}
44+
}
45+
46+
func TestCreateInstanceWaitHandler(t *testing.T) {
47+
tests := []struct {
48+
desc string
49+
instanceGetFails bool
50+
instanceStatus *string
51+
wantErr bool
52+
wantResp bool
53+
}{
54+
{
55+
desc: "create_succeeded",
56+
instanceGetFails: false,
57+
instanceStatus: utils.Ptr(LOADBALANCERSTATUS_READY),
58+
wantErr: false,
59+
wantResp: true,
60+
},
61+
{
62+
desc: "create_failed",
63+
instanceGetFails: false,
64+
instanceStatus: utils.Ptr(LOADBALANCERSTATUS_ERROR),
65+
wantErr: true,
66+
wantResp: true,
67+
},
68+
{
69+
desc: "create_failed_2",
70+
instanceGetFails: false,
71+
instanceStatus: utils.Ptr(LOADBALANCERSTATUS_TERMINATING),
72+
wantErr: true,
73+
wantResp: true,
74+
},
75+
{
76+
desc: "instance_get_fails",
77+
instanceGetFails: true,
78+
wantErr: true,
79+
wantResp: false,
80+
},
81+
{
82+
desc: "timeout",
83+
instanceGetFails: false,
84+
instanceStatus: utils.Ptr(LOADBALANCERSTATUS_PENDING),
85+
wantErr: true,
86+
wantResp: false,
87+
},
88+
}
89+
for _, tt := range tests {
90+
t.Run(tt.desc, func(t *testing.T) {
91+
instanceName := "foo-bar"
92+
93+
apiClient := newAPIMock(&mockSettings{
94+
instanceName: instanceName,
95+
instanceStatus: tt.instanceStatus,
96+
instanceGetFails: tt.instanceGetFails,
97+
})
98+
99+
var wantRes *loadbalancer.LoadBalancer
100+
if tt.wantResp {
101+
wantRes = &loadbalancer.LoadBalancer{
102+
Name: &instanceName,
103+
Status: tt.instanceStatus,
104+
}
105+
}
106+
107+
handler := CreateLoadBalancerWaitHandler(context.Background(), apiClient, "", testRegion, instanceName)
108+
109+
gotRes, err := handler.SetTimeout(10 * time.Millisecond).WaitWithContext(context.Background())
110+
111+
if (err != nil) != tt.wantErr {
112+
t.Fatalf("handler error = %v, wantErr %v", err, tt.wantErr)
113+
}
114+
if !cmp.Equal(gotRes, wantRes) {
115+
t.Fatalf("handler gotRes = %v, want %v", gotRes, wantRes)
116+
}
117+
})
118+
}
119+
}
120+
121+
func TestDeleteInstanceWaitHandler(t *testing.T) {
122+
tests := []struct {
123+
desc string
124+
instanceGetFails bool
125+
instanceIsDeleted bool
126+
wantErr bool
127+
}{
128+
{
129+
desc: "delete_succeeded",
130+
instanceGetFails: false,
131+
instanceIsDeleted: true,
132+
wantErr: false,
133+
},
134+
{
135+
desc: "delete_failed",
136+
instanceGetFails: false,
137+
instanceIsDeleted: false,
138+
wantErr: true,
139+
},
140+
{
141+
desc: "get_fails",
142+
instanceGetFails: true,
143+
wantErr: true,
144+
},
145+
}
146+
for _, tt := range tests {
147+
t.Run(tt.desc, func(t *testing.T) {
148+
instanceName := "foo-bar"
149+
150+
apiClient := newAPIMock(&mockSettings{
151+
instanceGetFails: tt.instanceGetFails,
152+
instanceName: instanceName,
153+
instanceIsDeleted: tt.instanceIsDeleted,
154+
})
155+
156+
handler := DeleteLoadBalancerWaitHandler(context.Background(), apiClient, "", testRegion, instanceName)
157+
158+
_, err := handler.SetTimeout(10 * time.Millisecond).WaitWithContext(context.Background())
159+
160+
if (err != nil) != tt.wantErr {
161+
t.Fatalf("handler error = %v, wantErr %v", err, tt.wantErr)
162+
}
163+
})
164+
}
165+
}

services/loadbalancer/wait/wait.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,13 @@ const (
2929
var _ APIClientInterface = &loadbalancer.APIClient{}
3030

3131
// Interface needed for tests
32+
// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead
3233
type APIClientInterface interface {
3334
GetLoadBalancerExecute(ctx context.Context, projectId, region, name string) (*loadbalancer.LoadBalancer, error)
3435
}
3536

3637
// CreateLoadBalancerWaitHandler will wait for load balancer creation
38+
// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead
3739
func CreateLoadBalancerWaitHandler(ctx context.Context, a APIClientInterface, projectId, region, instanceName string) *wait.AsyncActionHandler[loadbalancer.LoadBalancer] {
3840
handler := wait.New(func() (waitFinished bool, response *loadbalancer.LoadBalancer, err error) {
3941
s, err := a.GetLoadBalancerExecute(ctx, projectId, region, instanceName)
@@ -72,6 +74,7 @@ func CreateLoadBalancerWaitHandler(ctx context.Context, a APIClientInterface, pr
7274
}
7375

7476
// DeleteLoadBalancerWaitHandler will wait for load balancer deletion
77+
// Deprecated: Will be removed after 2026-09-30. Move to the packages generated for each available API version instead
7578
func DeleteLoadBalancerWaitHandler(ctx context.Context, a APIClientInterface, projectId, region, instanceId string) *wait.AsyncActionHandler[struct{}] {
7679
handler := wait.New(func() (waitFinished bool, response *struct{}, err error) {
7780
_, err = a.GetLoadBalancerExecute(ctx, projectId, region, instanceId)

0 commit comments

Comments
 (0)