Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
50 changes: 50 additions & 0 deletions docs/data-sources/vpn_gateway.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "stackit_vpn_gateway Data Source - stackit"
subcategory: ""
description: |-
VPN Gateway data source schema. Uses the default_region specified in the provider configuration as a fallback in case no region is defined on datasource level.
---

# stackit_vpn_gateway (Data Source)

VPN Gateway data source schema. Uses the `default_region` specified in the provider configuration as a fallback in case no `region` is defined on datasource level.



<!-- schema generated by tfplugindocs -->
## Schema

### Required

- `gateway_id` (String) The server-generated UUID of the VPN gateway.
- `project_id` (String) STACKIT project ID associated with the VPN gateway.

### Read-Only

- `availability_zones` (Attributes) Availability zones for the two tunnel endpoints. (see [below for nested schema](#nestedatt--availability_zones))
- `bgp` (Attributes) BGP configuration. Only applicable when routing_type is BGP_ROUTE_BASED. (see [below for nested schema](#nestedatt--bgp))
- `display_name` (String) A user-friendly name for the VPN gateway.
- `id` (String) Terraform's internal resource identifier. Structured as "`project_id`,`region`,`gateway_id`".
- `labels` (Map of String) Map of custom labels (key-value string pairs).
- `plan_id` (String) The service plan identifier (e.g. p500).
- `region` (String) STACKIT region (e.g. eu01).
- `routing_type` (String) Routing architecture: POLICY_BASED, ROUTE_BASED, or BGP_ROUTE_BASED.
- `state` (String) The current lifecycle state of the gateway (PENDING, READY, ERROR, DELETING).

<a id="nestedatt--availability_zones"></a>
### Nested Schema for `availability_zones`

Read-Only:

- `tunnel1` (String) Availability zone for tunnel 1.
- `tunnel2` (String) Availability zone for tunnel 2.


<a id="nestedatt--bgp"></a>
### Nested Schema for `bgp`

Read-Only:

- `local_asn` (Number) Local ASN for BGP (private ASN range, 64512-4294967294).
- `override_advertised_routes` (List of String) List of IPv4 CIDRs to advertise via BGP.
1 change: 1 addition & 0 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -212,3 +212,4 @@ Note: AWS specific checks must be skipped as they do not work on STACKIT. For de
- `sqlserverflex_custom_endpoint` (String) Custom endpoint for the SQL Server Flex service
- `token_custom_endpoint` (String) Custom endpoint for the token API, which is used to request access tokens when using the key flow
- `use_oidc` (Boolean) Enables OIDC for Authentication. This can also be sourced from the `STACKIT_USE_OIDC` Environment Variable. Defaults to `false`.
- `vpn_custom_endpoint` (String) Custom endpoint for the VPN service
74 changes: 74 additions & 0 deletions docs/resources/vpn_gateway.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "stackit_vpn_gateway Resource - stackit"
subcategory: ""
description: |-
VPN Gateway resource schema. Uses the default_region specified in the provider configuration as a fallback in case no region is defined on resource level.
---

# stackit_vpn_gateway (Resource)

VPN Gateway resource schema. Uses the `default_region` specified in the provider configuration as a fallback in case no `region` is defined on resource level.

## Example Usage

```terraform
resource "stackit_vpn_gateway" "example" {
project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
region = "eu01"
display_name = "example-vpn-gateway"
plan_id = "p500"
routing_type = "ROUTE_BASED"

availability_zones = {
tunnel1 = "eu01-1"
tunnel2 = "eu01-2"
}
}

# Only use the import statement, if you want to import an existing VPN gateway
import {
to = stackit_vpn_gateway.example
id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx,eu01,xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
}
```

<!-- schema generated by tfplugindocs -->
## Schema

### Required

- `availability_zones` (Attributes) Availability zones for the two tunnel endpoints. (see [below for nested schema](#nestedatt--availability_zones))
- `display_name` (String) A user-friendly name for the VPN gateway.
- `plan_id` (String) The service plan identifier (e.g. p500).
- `project_id` (String) STACKIT project ID associated with the VPN gateway.
- `routing_type` (String) Routing architecture: POLICY_BASED, ROUTE_BASED, or BGP_ROUTE_BASED.

### Optional

- `bgp` (Attributes) BGP configuration. Only applicable when routing_type is BGP_ROUTE_BASED. (see [below for nested schema](#nestedatt--bgp))
- `labels` (Map of String) Map of custom labels (key-value string pairs).
- `region` (String) STACKIT region (e.g. eu01).

### Read-Only

- `gateway_id` (String) The server-generated UUID of the VPN gateway.
- `id` (String) Terraform's internal resource identifier. Structured as "`project_id`,`region`,`gateway_id`".
- `state` (String) The current lifecycle state of the gateway (PENDING, READY, ERROR, DELETING).

<a id="nestedatt--availability_zones"></a>
### Nested Schema for `availability_zones`

Required:

- `tunnel1` (String) Availability zone for tunnel 1.
- `tunnel2` (String) Availability zone for tunnel 2.


<a id="nestedatt--bgp"></a>
### Nested Schema for `bgp`

Optional:

- `local_asn` (Number) Local ASN for BGP (private ASN range, 64512-4294967294).
- `override_advertised_routes` (List of String) List of IPv4 CIDRs to advertise via BGP. If omitted, SNA network ranges are advertised.
18 changes: 18 additions & 0 deletions examples/resources/stackit_vpn_gateway/resource.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
resource "stackit_vpn_gateway" "example" {
project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
region = "eu01"
display_name = "example-vpn-gateway"
plan_id = "p500"
routing_type = "ROUTE_BASED"

availability_zones = {
tunnel1 = "eu01-1"
tunnel2 = "eu01-2"
}
}

# Only use the import statement, if you want to import an existing VPN gateway
import {
to = stackit_vpn_gateway.example
id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx,eu01,xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
}
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ require (
github.com/stackitcloud/stackit-sdk-go/services/sfs v0.9.0
github.com/stackitcloud/stackit-sdk-go/services/ske v1.14.0
github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.10.0
github.com/stackitcloud/stackit-sdk-go/services/vpn v0.8.0
github.com/teambition/rrule-go v1.8.2
golang.org/x/mod v0.35.0
)
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -734,6 +734,8 @@ github.com/stackitcloud/stackit-sdk-go/services/ske v1.14.0 h1:Zy3yxmHzW+ydu1nae
github.com/stackitcloud/stackit-sdk-go/services/ske v1.14.0/go.mod h1:TbqmZhLMofmfl+HhVl6oHYcI3zvXTm1vRjN3A/fOkM4=
github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.10.0 h1:angvO3z0TGqZtdwTDsG/tgTw9hxB76A6leUsiUXQtME=
github.com/stackitcloud/stackit-sdk-go/services/sqlserverflex v1.10.0/go.mod h1:AiUoMAqQcOlMgDtkVJlqI7P/VGD5xjN3dYjERGnwN/M=
github.com/stackitcloud/stackit-sdk-go/services/vpn v0.8.0 h1:YCFkFcWLf6MaKGGuin5YztQGb5CadE/23ciCkvxJh1U=
github.com/stackitcloud/stackit-sdk-go/services/vpn v0.8.0/go.mod h1:toIjQk1dhxdUFVyCWJJja0w/0nFpDid8MWX0ukQfvfo=
github.com/stbenjam/no-sprintf-host-port v0.3.1 h1:AyX7+dxI4IdLBPtDbsGAyqiTSLpCP9hWRrXQDU4Cm/g=
github.com/stbenjam/no-sprintf-host-port v0.3.1/go.mod h1:ODbZesTCHMVKthBHskvUUexdcNHAQRXk9NpSsL8p/HQ=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
Expand Down
1 change: 1 addition & 0 deletions stackit/internal/core/core.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ type ProviderData struct {
ServiceEnablementCustomEndpoint string
SfsCustomEndpoint string
ServiceAccountCustomEndpoint string
VpnCustomEndpoint string
EnableBetaResources bool
Experiments []string

Expand Down
186 changes: 186 additions & 0 deletions stackit/internal/services/vpn/gateway/datasource.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
package gateway

import (
"context"
"errors"
"fmt"
"net/http"

"github.com/hashicorp/terraform-plugin-framework/datasource"
"github.com/hashicorp/terraform-plugin-framework/datasource/schema"
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
"github.com/hashicorp/terraform-plugin-framework/types"
"github.com/hashicorp/terraform-plugin-log/tflog"

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

"github.com/stackitcloud/terraform-provider-stackit/stackit/internal/core"
"github.com/stackitcloud/terraform-provider-stackit/stackit/internal/services/vpn/utils"

"github.com/stackitcloud/terraform-provider-stackit/stackit/internal/conversion"
"github.com/stackitcloud/terraform-provider-stackit/stackit/internal/validate"
)

var (
_ datasource.DataSource = (*vpnGatewayDataSource)(nil)
_ datasource.DataSourceWithConfigure = (*vpnGatewayDataSource)(nil)
)

type vpnGatewayDataSource struct {
client *vpn.APIClient
providerData core.ProviderData
}

func NewVPNGatewayDataSource() datasource.DataSource {
return &vpnGatewayDataSource{}
}

func (d *vpnGatewayDataSource) Configure(ctx context.Context, req datasource.ConfigureRequest, resp *datasource.ConfigureResponse) {
providerData, ok := conversion.ParseProviderData(ctx, req.ProviderData, &resp.Diagnostics)
if !ok {
return
}

apiClient := utils.ConfigureClient(ctx, &providerData, &resp.Diagnostics)
if resp.Diagnostics.HasError() {
return
}
d.client = apiClient
d.providerData = providerData
tflog.Info(ctx, "VPN client configured")
}

func (d *vpnGatewayDataSource) Metadata(_ context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) {
resp.TypeName = req.ProviderTypeName + "_vpn_gateway"
}

func (d *vpnGatewayDataSource) Schema(_ context.Context, _ datasource.SchemaRequest, resp *datasource.SchemaResponse) {
resp.Schema = schema.Schema{
Description: fmt.Sprintf("VPN Gateway data source schema. %s", core.DatasourceRegionFallbackDocstring),
Attributes: map[string]schema.Attribute{
"id": schema.StringAttribute{
Description: schemaDescriptions["id"],
Computed: true,
},
"project_id": schema.StringAttribute{
Description: schemaDescriptions["project_id"],
Required: true,
Validators: []validator.String{
validate.UUID(),
validate.NoSeparator(),
},
},
"region": schema.StringAttribute{
Description: schemaDescriptions["region"],
Computed: true,
},
"gateway_id": schema.StringAttribute{
Description: schemaDescriptions["gateway_id"],
Required: true,
Validators: []validator.String{
validate.UUID(),
validate.NoSeparator(),
},
},
"display_name": schema.StringAttribute{
Description: schemaDescriptions["display_name"],
Computed: true,
},
"plan_id": schema.StringAttribute{
Description: schemaDescriptions["plan_id"],
Computed: true,
},
"routing_type": schema.StringAttribute{
Description: schemaDescriptions["routing_type"],
Computed: true,
},
"availability_zones": schema.SingleNestedAttribute{
Description: schemaDescriptions["availability_zones"],
Computed: true,
Attributes: map[string]schema.Attribute{
"tunnel1": schema.StringAttribute{
Description: "Availability zone for tunnel 1.",
Computed: true,
},
"tunnel2": schema.StringAttribute{
Description: "Availability zone for tunnel 2.",
Computed: true,
},
},
},
"bgp": schema.SingleNestedAttribute{
Description: schemaDescriptions["bgp"],
Computed: true,
Attributes: map[string]schema.Attribute{
"local_asn": schema.Int64Attribute{
Description: "Local ASN for BGP (private ASN range, 64512-4294967294).",
Computed: true,
},
"override_advertised_routes": schema.ListAttribute{
Description: "List of IPv4 CIDRs to advertise via BGP.",
Computed: true,
ElementType: types.StringType,
},
},
},
"labels": schema.MapAttribute{
Description: schemaDescriptions["labels"],
Computed: true,
ElementType: types.StringType,
},
"state": schema.StringAttribute{
Description: schemaDescriptions["state"],
Computed: true,
},
},
}
}

func (d *vpnGatewayDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) { // nolint:gocritic // function signature required by Terraform
var model Model
diags := req.Config.Get(ctx, &model)
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
return
}

ctx = core.InitProviderContext(ctx)

projectId := model.ProjectID.ValueString()
region := d.providerData.GetRegionWithOverride(model.Region)
gatewayId := model.GatewayID.ValueString()

ctx = tflog.SetField(ctx, "project_id", projectId)
ctx = tflog.SetField(ctx, "region", region)
ctx = tflog.SetField(ctx, "gateway_id", gatewayId)

gatewayResponse, err := d.client.DefaultAPI.GetGateway(ctx, projectId, vpn.Region(region), gatewayId).Execute()
if err != nil {
var oapiErr *oapierror.GenericOpenAPIError
ok := errors.As(err, &oapiErr)
if ok && oapiErr.StatusCode == http.StatusNotFound {
resp.State.RemoveResource(ctx)
return
}
core.LogAndAddError(ctx, &resp.Diagnostics, "Error reading VPN gateway", fmt.Sprintf("Calling API: %v", err))
return
}
ctx = core.LogResponse(ctx)

err = mapFields(ctx, gatewayResponse, &model, region)
if err != nil {
core.LogAndAddError(ctx, &resp.Diagnostics, "Error reading VPN gateway", fmt.Sprintf("Processing response: %v", err))
return
}

// Set state
diags = resp.State.Set(ctx, model)
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
return
}
tflog.Info(ctx, "VPN gateway read", map[string]any{
"gateway_id": gatewayId,
})
}
Loading
Loading