Skip to content

Commit eba62ce

Browse files
authored
Merge branch 'main' into update-doc-links
2 parents 4a4efbc + 0611c06 commit eba62ce

File tree

10 files changed

+359
-1
lines changed

10 files changed

+359
-1
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
- [v1.2.4](services/iaas/CHANGELOG.md#v124)
1313
- Bump STACKIT SDK resourcemanager module from `v0.18.1` to `v0.18.2`
1414
- `logs`:
15+
- [v0.3.0](services/logs/CHANGELOG.md#v030)
16+
- **Feature:** Add new wait handlers for instance creation (`CreateLogsInstanceWaitHandler`), and instance deletion (`DeleteLogsInstanceWaitHandler`)
1517
- [v0.2.0](services/logs/CHANGELOG.md#v020)
1618
- **Feature:** Add support for access token GET endpoint
1719
- [v0.1.1](services/logs/CHANGELOG.md#v011)

examples/logs/go.mod

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
module github.com/stackitcloud/stackit-sdk-go/examples/logs
2+
3+
go 1.21
4+
5+
require (
6+
github.com/stackitcloud/stackit-sdk-go/core v0.20.1
7+
github.com/stackitcloud/stackit-sdk-go/services/logs v0.1.0
8+
)
9+
10+
require (
11+
github.com/golang-jwt/jwt/v5 v5.3.0 // indirect
12+
github.com/google/uuid v1.6.0 // indirect
13+
)

examples/logs/go.sum

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
github.com/golang-jwt/jwt/v5 v5.3.0 h1:pv4AsKCKKZuqlgs5sUmn4x8UlGa0kEVt/puTpKx9vvo=
2+
github.com/golang-jwt/jwt/v5 v5.3.0/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE=
3+
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
4+
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
5+
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
6+
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
7+
github.com/stackitcloud/stackit-sdk-go/core v0.20.1 h1:odiuhhRXmxvEvnVTeZSN9u98edvw2Cd3DcnkepncP3M=
8+
github.com/stackitcloud/stackit-sdk-go/core v0.20.1/go.mod h1:fqto7M82ynGhEnpZU6VkQKYWYoFG5goC076JWXTUPRQ=
9+
github.com/stackitcloud/stackit-sdk-go/services/logs v0.1.0 h1:Fck91pz2Oxk8dUd2lOdnsIMWSCzBzAHJp7ivqAJ59is=
10+
github.com/stackitcloud/stackit-sdk-go/services/logs v0.1.0/go.mod h1:VM+++rhzI2/lvhyGKg0FCiEfnrADWykcdHLbECrl6T0=

examples/logs/logs.go

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
package main
2+
3+
import (
4+
"context"
5+
"log"
6+
7+
"github.com/stackitcloud/stackit-sdk-go/core/config"
8+
"github.com/stackitcloud/stackit-sdk-go/core/utils"
9+
"github.com/stackitcloud/stackit-sdk-go/services/logs"
10+
)
11+
12+
func main() {
13+
ctx := context.Background()
14+
15+
projectId := "PROJECT_ID" // the uuid of your STACKIT project
16+
regionId := "eu01"
17+
18+
client, err := logs.NewAPIClient(
19+
config.WithRegion(regionId),
20+
)
21+
if err != nil {
22+
log.Fatalf("[Logs API] Creating API client: %v\n", err)
23+
}
24+
25+
// Create a Logs Instance
26+
var createdInstance string
27+
createInstancePayload := logs.CreateLogsInstancePayload{
28+
DisplayName: utils.Ptr("my-logs-instance"),
29+
RetentionDays: utils.Ptr(int64(1)),
30+
}
31+
createResp, err := client.CreateLogsInstance(ctx, projectId, regionId).
32+
CreateLogsInstancePayload(createInstancePayload).
33+
Execute()
34+
if err != nil {
35+
log.Fatalf("[Logs API] Error when calling `CreateLogsInstance`: %v\n", err)
36+
}
37+
createdInstance = *createResp.Id
38+
log.Printf("[Logs API] Created Logs Instance with ID \"%s\".\n", createdInstance)
39+
40+
// List Logs Instances
41+
listResp, err := client.ListLogsInstances(ctx, projectId, regionId).Execute()
42+
if err != nil {
43+
log.Fatalf("[Logs API] Error when calling `ListLogsInstances`: %v\n", err)
44+
}
45+
log.Printf("[Logs API] Retrieved %d Logs Instances.\n", len(*listResp.Instances))
46+
47+
// Get the created Logs Instance
48+
getResp, err := client.GetLogsInstance(ctx, projectId, regionId, createdInstance).Execute()
49+
if err != nil {
50+
log.Fatalf("[Logs API] Error when calling `GetLogsInstance`: %v\n", err)
51+
}
52+
log.Printf("[Logs API] Retrieved Logs Instance with ID \"%s\" and Display Name \"%s\".\n", *getResp.Id, *getResp.DisplayName)
53+
54+
// Update the created Logs Instance
55+
updatePayload := logs.UpdateLogsInstancePayload{
56+
DisplayName: utils.Ptr("my-updated-logs-instance"),
57+
RetentionDays: utils.Ptr(int64(7)),
58+
}
59+
updateResp, err := client.UpdateLogsInstance(ctx, projectId, regionId, createdInstance).
60+
UpdateLogsInstancePayload(updatePayload).
61+
Execute()
62+
if err != nil {
63+
log.Fatalf("[Logs API] Error when calling `UpdateLogsInstance`: %v\n", err)
64+
}
65+
log.Printf("[Logs API] Updated Logs Instance with ID \"%s\" to Display Name \"%s\".\n", *updateResp.Id, *updateResp.DisplayName)
66+
67+
// Create an Access Token
68+
createTokenPayload := logs.CreateAccessTokenPayload{
69+
DisplayName: utils.Ptr("my-access-token"),
70+
Permissions: &[]string{"read"},
71+
}
72+
createTokenResp, err := client.CreateAccessToken(ctx, projectId, regionId, createdInstance).
73+
CreateAccessTokenPayload(createTokenPayload).
74+
Execute()
75+
if err != nil {
76+
log.Fatalf("[Logs API] Error when calling `CreateAccessToken`: %v\n", err)
77+
}
78+
log.Printf("[Logs API] Created Access Token with ID \"%s\".\n", *createTokenResp.Id)
79+
80+
// Add Access Token to Logs Instance
81+
err = client.UpdateAccessToken(ctx, projectId, regionId, createdInstance, *createTokenResp.Id).
82+
// needs at least an empty payload
83+
UpdateAccessTokenPayload(logs.UpdateAccessTokenPayload{}).
84+
Execute()
85+
if err != nil {
86+
log.Fatalf("[Logs API] Error when calling `UpdateAccessToken`: %v\n", err)
87+
}
88+
89+
// Delete all Access Tokens from Logs Instance
90+
tokenList, err := client.DeleteAllAccessTokens(ctx, projectId, regionId, createdInstance).Execute()
91+
if err != nil {
92+
log.Fatalf("[Logs API] Error when calling `DeleteAllAccessTokens`: %v\n", err)
93+
}
94+
log.Printf("[Logs API] Deleted %d Access Tokens from Logs Instance with ID \"%s\".\n", len(*tokenList.Tokens), createdInstance)
95+
96+
// Delete the created Logs Instance
97+
err = client.DeleteLogsInstance(ctx, projectId, regionId, createdInstance).Execute()
98+
if err != nil {
99+
log.Fatalf("[Logs API] Error when calling `DeleteLogsInstance`: %v\n", err)
100+
}
101+
log.Printf("[Logs API] Deleted Logs Instance with ID \"%s\".\n", createdInstance)
102+
}

go.work

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ use (
1414
./examples/kms
1515
./examples/loadbalancer
1616
./examples/logme
17+
./examples/logs
1718
./examples/mariadb
1819
./examples/middleware
1920
./examples/mongodbflex

services/logs/CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
## v0.3.0
2+
- **Feature:** Add new wait handlers for instance creation (`CreateLogsInstanceWaitHandler`), and instance deletion (`DeleteLogsInstanceWaitHandler`)
3+
14
## v0.2.0
25
- **Feature:** Add support for access token GET endpoint
36

services/logs/VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
v0.2.0
1+
v0.3.0

services/logs/go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ module github.com/stackitcloud/stackit-sdk-go/services/logs
33
go 1.21
44

55
require (
6+
github.com/google/go-cmp v0.7.0
67
github.com/google/uuid v1.6.0
78
github.com/stackitcloud/stackit-sdk-go/core v0.20.1
89
)

services/logs/wait/wait.go

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
package wait
2+
3+
import (
4+
"context"
5+
"errors"
6+
"fmt"
7+
"net/http"
8+
"time"
9+
10+
"github.com/stackitcloud/stackit-sdk-go/core/oapierror"
11+
"github.com/stackitcloud/stackit-sdk-go/core/wait"
12+
"github.com/stackitcloud/stackit-sdk-go/services/logs"
13+
)
14+
15+
type APIClientInterface interface {
16+
GetLogsInstanceExecute(ctx context.Context, projectId string, regionId string, instanceId string) (*logs.LogsInstance, error)
17+
}
18+
19+
func CreateLogsInstanceWaitHandler(ctx context.Context, client APIClientInterface, projectID, region, instanceID string) *wait.AsyncActionHandler[logs.LogsInstance] {
20+
handler := wait.New(func() (waitFinished bool, response *logs.LogsInstance, err error) {
21+
instance, err := client.GetLogsInstanceExecute(ctx, projectID, region, instanceID)
22+
if err != nil {
23+
return false, nil, err
24+
}
25+
if instance.Id == nil || instance.Status == nil {
26+
return false, nil, fmt.Errorf("get instance, project: %q, region: %q, instanceID: %q: missing id or status", projectID, region, instanceID)
27+
}
28+
if *instance.Id == instanceID && *instance.Status == logs.LOGSINSTANCESTATUS_ACTIVE {
29+
return true, instance, nil
30+
}
31+
if *instance.Status == logs.LOGSINSTANCESTATUS_DELETING {
32+
return true, nil, fmt.Errorf("creating log instance failed, instance is being deleted")
33+
}
34+
return false, nil, nil
35+
})
36+
handler.SetTimeout(10 * time.Minute)
37+
return handler
38+
}
39+
40+
func DeleteLogsInstanceWaitHandler(ctx context.Context, client APIClientInterface, projectID, region, instanceID string) *wait.AsyncActionHandler[logs.LogsInstance] {
41+
handler := wait.New(func() (waitFinished bool, response *logs.LogsInstance, err error) {
42+
_, err = client.GetLogsInstanceExecute(ctx, projectID, region, instanceID)
43+
// the instances is still gettable, e.g. not deleted, when the errors is null
44+
if err == nil {
45+
return false, nil, nil
46+
}
47+
var oapiError *oapierror.GenericOpenAPIError
48+
if errors.As(err, &oapiError) {
49+
if statusCode := oapiError.StatusCode; statusCode == http.StatusNotFound {
50+
return true, nil, nil
51+
}
52+
}
53+
return false, nil, err
54+
})
55+
handler.SetTimeout(10 * time.Minute)
56+
return handler
57+
}

services/logs/wait/wait_test.go

Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
package wait
2+
3+
import (
4+
"context"
5+
"net/http"
6+
"testing"
7+
"time"
8+
9+
"github.com/google/go-cmp/cmp"
10+
"github.com/google/uuid"
11+
"github.com/stackitcloud/stackit-sdk-go/core/oapierror"
12+
"github.com/stackitcloud/stackit-sdk-go/core/utils"
13+
"github.com/stackitcloud/stackit-sdk-go/services/logs"
14+
)
15+
16+
type apiClientMock struct {
17+
getFails bool
18+
returnInstance bool
19+
statusCode int
20+
getLogsResponse *logs.LogsInstance
21+
}
22+
23+
func (a *apiClientMock) GetLogsInstanceExecute(_ context.Context, _, _, _ string) (*logs.LogsInstance, error) {
24+
if a.getFails {
25+
return nil, &oapierror.GenericOpenAPIError{
26+
StatusCode: a.statusCode,
27+
}
28+
}
29+
if !a.returnInstance {
30+
return nil, nil
31+
}
32+
return a.getLogsResponse, nil
33+
}
34+
35+
var projectId = uuid.NewString()
36+
var instanceId = uuid.NewString()
37+
38+
const region = "eu01"
39+
40+
func TestCreateLogsInstanceWaitHandler(t *testing.T) {
41+
tests := []struct {
42+
description string
43+
getFails bool
44+
wantErr bool
45+
wantResp bool
46+
returnInstance bool
47+
getLogsResponse *logs.LogsInstance
48+
}{
49+
{
50+
description: "create succeeded",
51+
getFails: false,
52+
wantErr: false,
53+
wantResp: true,
54+
returnInstance: true,
55+
getLogsResponse: &logs.LogsInstance{
56+
Id: utils.Ptr(instanceId),
57+
Status: utils.Ptr(logs.LOGSINSTANCESTATUS_ACTIVE),
58+
},
59+
},
60+
{
61+
description: "create failed with error",
62+
getFails: true,
63+
wantErr: true,
64+
wantResp: false,
65+
returnInstance: true,
66+
getLogsResponse: &logs.LogsInstance{
67+
Id: utils.Ptr(instanceId),
68+
Status: utils.Ptr(logs.LOGSINSTANCESTATUS_ACTIVE),
69+
},
70+
},
71+
{
72+
description: "create without id",
73+
getFails: false,
74+
wantErr: true,
75+
wantResp: false,
76+
returnInstance: true,
77+
getLogsResponse: &logs.LogsInstance{
78+
Status: utils.Ptr(logs.LOGSINSTANCESTATUS_ACTIVE),
79+
},
80+
},
81+
{
82+
description: "create without status",
83+
getFails: false,
84+
wantErr: true,
85+
wantResp: false,
86+
returnInstance: true,
87+
getLogsResponse: &logs.LogsInstance{
88+
Id: utils.Ptr(instanceId),
89+
},
90+
},
91+
{
92+
description: "instance deleting",
93+
getFails: false,
94+
wantErr: true,
95+
wantResp: false,
96+
returnInstance: true,
97+
getLogsResponse: &logs.LogsInstance{
98+
Id: utils.Ptr(instanceId),
99+
Status: utils.Ptr(logs.LOGSINSTANCESTATUS_DELETING),
100+
},
101+
},
102+
}
103+
for _, tt := range tests {
104+
t.Run(tt.description, func(t *testing.T) {
105+
client := &apiClientMock{
106+
getFails: tt.getFails,
107+
getLogsResponse: tt.getLogsResponse,
108+
returnInstance: tt.returnInstance,
109+
}
110+
var instanceWanted *logs.LogsInstance
111+
if tt.wantResp {
112+
instanceWanted = tt.getLogsResponse
113+
}
114+
115+
handler := CreateLogsInstanceWaitHandler(context.Background(), client, projectId, region, instanceId)
116+
117+
response, err := handler.SetTimeout(10 * time.Millisecond).WaitWithContext(context.Background())
118+
119+
if (err != nil) != tt.wantErr {
120+
t.Fatalf("handler error = %v, wantErr %v", err, tt.wantErr)
121+
}
122+
if !cmp.Equal(response, instanceWanted) {
123+
t.Fatalf("handler gotRes = %v, want %v", response, instanceWanted)
124+
}
125+
})
126+
}
127+
}
128+
129+
func TestDeleteLogsInstanceWaitHandler(t *testing.T) {
130+
tests := []struct {
131+
description string
132+
getFails bool
133+
wantErr bool
134+
statusCode int
135+
}{
136+
{
137+
description: "delete succeeded",
138+
getFails: true,
139+
statusCode: http.StatusNotFound,
140+
},
141+
{
142+
description: "delete failed with error",
143+
getFails: true,
144+
wantErr: true,
145+
statusCode: http.StatusInternalServerError,
146+
},
147+
{
148+
description: "delete still in progress",
149+
getFails: false,
150+
wantErr: true,
151+
statusCode: http.StatusOK,
152+
},
153+
}
154+
for _, tt := range tests {
155+
t.Run(tt.description, func(t *testing.T) {
156+
client := &apiClientMock{
157+
getFails: tt.getFails,
158+
returnInstance: false,
159+
statusCode: tt.statusCode,
160+
getLogsResponse: nil,
161+
}
162+
handler := DeleteLogsInstanceWaitHandler(context.Background(), client, projectId, region, instanceId)
163+
_, err := handler.SetTimeout(10 * time.Millisecond).WaitWithContext(context.Background())
164+
if (err != nil) != tt.wantErr {
165+
t.Fatalf("handler error = %v, wantErr %v", err, tt.wantErr)
166+
}
167+
})
168+
}
169+
}

0 commit comments

Comments
 (0)