Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
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
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -462,6 +462,9 @@
- `v1api`: New package which can be used for communication with the STACKIT vpn v1 API
- `v1beta1api`: Align package to latest API specification
- `v1alpha1api`: Align package to latest API specification
- [v0.8.0](services/vpn/CHANGELOG.md#v080)
- `v1api`:
Comment thread
s-inter marked this conversation as resolved.
- **Feature:** Add new wait handlers for gateway creation (`CreateGatewayWaitHandler`), update (`UpdateGatewayWaitHandler`), and deletion (`DeleteGatewayWaitHandler`)

## Release (2026-04-07)
- `alb`: [v0.13.1](services/alb/CHANGELOG.md#v0131)
Expand Down
16 changes: 16 additions & 0 deletions examples/vpn/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
module github.com/stackitcloud/stackit-sdk-go/examples/vpn

go 1.25

// 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.
replace github.com/stackitcloud/stackit-sdk-go/services/vpn => ../../services/vpn

require (
github.com/stackitcloud/stackit-sdk-go/core v0.26.0
github.com/stackitcloud/stackit-sdk-go/services/vpn v0.8.0
)

require (
github.com/golang-jwt/jwt/v5 v5.3.1 // indirect
github.com/google/uuid v1.6.0 // indirect
)
8 changes: 8 additions & 0 deletions examples/vpn/go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
github.com/golang-jwt/jwt/v5 v5.3.1 h1:kYf81DTWFe7t+1VvL7eS+jKFVWaUnK9cB1qbwn63YCY=
github.com/golang-jwt/jwt/v5 v5.3.1/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE=
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/stackitcloud/stackit-sdk-go/core v0.26.0 h1:jQEb9gkehfp6VCP6TcYk7BI10cz4l0KM2L6hqYBH2QA=
github.com/stackitcloud/stackit-sdk-go/core v0.26.0/go.mod h1:WU1hhxnjXw2EV7CYa1nlEvNpMiRY6CvmIOaHuL3pOaA=
97 changes: 97 additions & 0 deletions examples/vpn/vpn.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
package main

import (
"context"
"fmt"
"os"

"github.com/stackitcloud/stackit-sdk-go/core/config"
vpn "github.com/stackitcloud/stackit-sdk-go/services/vpn/v1api"
)

func main() {
region := "eu01" // Region where the resources will be created
projectId := "PROJECT_ID" // the uuid of your STACKIT project
planId := "PLAN_ID" // the id of the plan you want to use for the VPN Gateway. You can get the available plans with `ListPlans`.

// STACKIT VPN enforces the following requirements for a secure PSK:
// - must be at least 20 characters long
// - must be at least 16 different characters
// - must have at least one upper case letter
// - must have at least one lower case letter
// - must have at least one number
psk := "Super.$ecret_Shared3Key12345"

// Create a new API client, that uses default authentication and configuration
vpnClient, err := vpn.NewAPIClient(
config.WithRegion(region),
)
if err != nil {
fmt.Fprintf(os.Stderr, "Creating API client: %v\n", err)
os.Exit(1)
}

// Create a VPN Gateway
createVpnGatewayPayload := vpn.CreateGatewayPayload{
DisplayName: "exampleVpnGateway",
PlanId: planId,
RoutingType: vpn.ROUTINGTYPE_ROUTE_BASED,
AvailabilityZones: vpn.CreateGatewayPayloadAvailabilityZones{
Tunnel1: "eu01-1",
Tunnel2: "eu01-2",
},
}

gatewayResp, err := vpnClient.DefaultAPI.CreateGateway(context.Background(), projectId, vpn.Region(region)).CreateGatewayPayload(createVpnGatewayPayload).Execute()
if err != nil {
fmt.Fprintf(os.Stderr, "Error when calling `CreateVpnGateway`: %v\n", err)
os.Exit(1)
}
fmt.Printf("Created VPN Gateway with id \"%s\".\n", *gatewayResp.Id)

// Create a VPN Connection
phase1 := vpn.TunnelConfigurationPhase1{
DhGroups: []string{"ecp384"},
EncryptionAlgorithms: []string{"aes256"},
IntegrityAlgorithms: []string{"sha2_384"},
}
phase2 := vpn.TunnelConfigurationPhase2{
DhGroups: []string{"ecp384"},
EncryptionAlgorithms: []string{"aes256"},
IntegrityAlgorithms: []string{"sha2_384"},
}
tunnel := vpn.TunnelConfiguration{
Phase1: phase1,
Phase2: phase2,
PreSharedKey: &psk,
RemoteAddress: "0.0.0.0",
}

createGatewayConnectionPayload := vpn.CreateGatewayConnectionPayload{
DisplayName: "exampleVpnConnection",
Tunnel1: tunnel,
Tunnel2: tunnel,
}
connectionResp, err := vpnClient.DefaultAPI.CreateGatewayConnection(context.Background(), projectId, vpn.Region(region), *gatewayResp.Id).CreateGatewayConnectionPayload(createGatewayConnectionPayload).Execute()
if err != nil {
fmt.Fprintf(os.Stderr, "Error when calling `CreateVpnConnection`: %v\n", err)
os.Exit(1)
}
fmt.Printf("Created VPN Connection with id \"%s\".\n", *connectionResp.Id)

// Delete the VPN Connection
err = vpnClient.DefaultAPI.DeleteGatewayConnection(context.Background(), projectId, vpn.Region(region), *gatewayResp.Id, *connectionResp.Id).Execute()
if err != nil {
fmt.Fprintf(os.Stderr, "Error when calling `DeleteVpnConnection`: %v\n", err)
os.Exit(1)
}
fmt.Printf("Deleted VPN Connection with id \"%s\".\n", *connectionResp.Id)

// Delete the VPN Gateway
err = vpnClient.DefaultAPI.DeleteGateway(context.Background(), projectId, vpn.Region(region), *gatewayResp.Id).Execute()
if err != nil {
fmt.Fprintf(os.Stderr, "Error when calling `DeleteVpnGateway`: %v\n", err)
os.Exit(1)
}
fmt.Printf("Deleted VPN Gateway with id \"%s\".\n", *gatewayResp.Id)
}
1 change: 1 addition & 0 deletions go.work
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ use (
./examples/sqlserverflex
./examples/telemetrylink
./examples/telemetryrouter
./examples/vpn
./examples/waiter
./services/alb
./services/albwaf
Expand Down
4 changes: 4 additions & 0 deletions services/vpn/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## v0.8.0
- `v1api`:
- **Feature:** Add new wait handlers for gateway creation (`CreateGatewayWaitHandler`), update (`UpdateGatewayWaitHandler`), and deletion (`DeleteGatewayWaitHandler`)

## v0.7.0
- `v1api`: New package which can be used for communication with the STACKIT vpn v1 API
- `v1beta1api`: Align package to latest API specification
Expand Down
2 changes: 1 addition & 1 deletion services/vpn/VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
v0.7.0
v0.8.0
5 changes: 4 additions & 1 deletion services/vpn/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@ module github.com/stackitcloud/stackit-sdk-go/services/vpn

go 1.25

require github.com/stackitcloud/stackit-sdk-go/core v0.26.0
require (
github.com/google/go-cmp v0.7.0
github.com/stackitcloud/stackit-sdk-go/core v0.26.0
)

require (
github.com/golang-jwt/jwt/v5 v5.3.1 // indirect
Expand Down
59 changes: 59 additions & 0 deletions services/vpn/v1api/wait/wait.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package wait

import (
"context"
"errors"
"time"

"github.com/stackitcloud/stackit-sdk-go/core/wait"
vpn "github.com/stackitcloud/stackit-sdk-go/services/vpn/v1api"
)

func createOrUpdateGatewayWaitHandler(ctx context.Context, a vpn.DefaultAPI, projectId string, region vpn.Region, gatewayId string) *wait.AsyncActionHandler[vpn.GatewayResponse] {
waitConfig := wait.WaiterHelper[vpn.GatewayResponse, vpn.GatewayStatus]{
FetchInstance: a.GetGateway(ctx, projectId, region, gatewayId).Execute,
GetState: func(resp *vpn.GatewayResponse) (vpn.GatewayStatus, error) {
if resp == nil {
return "", errors.New("could not get gateway status: response is nil")
}
if resp.State == nil {
return "", errors.New("could not get gateway status: state is nil")
}
return *resp.State, nil
},
ActiveState: []vpn.GatewayStatus{vpn.GATEWAYSTATUS_READY},
ErrorState: []vpn.GatewayStatus{vpn.GATEWAYSTATUS_ERROR, vpn.GATEWAYSTATUS_DELETING},
}

handler := wait.New(waitConfig.Wait())
handler.SetTimeout(45 * time.Minute)
return handler
}

func CreateGatewayWaitHandler(ctx context.Context, a vpn.DefaultAPI, projectId string, region vpn.Region, gatewayId string) *wait.AsyncActionHandler[vpn.GatewayResponse] {
return createOrUpdateGatewayWaitHandler(ctx, a, projectId, region, gatewayId)
}

func UpdateGatewayWaitHandler(ctx context.Context, a vpn.DefaultAPI, projectId string, region vpn.Region, gatewayId string) *wait.AsyncActionHandler[vpn.GatewayResponse] {
return createOrUpdateGatewayWaitHandler(ctx, a, projectId, region, gatewayId)
}

func DeleteGatewayWaitHandler(ctx context.Context, a vpn.DefaultAPI, projectId string, region vpn.Region, gatewayId string) *wait.AsyncActionHandler[vpn.GatewayResponse] {
waitConfig := wait.WaiterHelper[vpn.GatewayResponse, vpn.GatewayStatus]{
FetchInstance: a.GetGateway(ctx, projectId, region, gatewayId).Execute,
GetState: func(resp *vpn.GatewayResponse) (vpn.GatewayStatus, error) {
if resp == nil {
return "", errors.New("could not get gateway status: response is nil")
}
if resp.State == nil {
return "", errors.New("could not get gateway status: state is nil")
}
return *resp.State, nil
},
ErrorState: []vpn.GatewayStatus{vpn.GATEWAYSTATUS_ERROR},
}

handler := wait.New(waitConfig.Wait())
handler.SetTimeout(20 * time.Minute)
return handler
}
Loading
Loading