From 8f9bded93887ae3606d0e2e5f2fb85c0e374198a Mon Sep 17 00:00:00 2001 From: SDK Generator Bot Date: Tue, 15 Sep 2026 13:27:16 +0000 Subject: [PATCH 1/2] Generate vpn --- services/vpn/oas_commit | 2 +- .../vpn/models/bgp_filter_rule_match.py | 4 ++-- .../stackit/vpn/models/bgp_tunnel_config.py | 4 ++-- .../src/stackit/vpn/models/network_config.py | 20 +++++++++++++++++-- 4 files changed, 23 insertions(+), 7 deletions(-) diff --git a/services/vpn/oas_commit b/services/vpn/oas_commit index ec6f0b9d6..35b7f4140 100644 --- a/services/vpn/oas_commit +++ b/services/vpn/oas_commit @@ -1 +1 @@ -b7d1b614138d667d378a5fd45e2a91539a7fb02e +7e7c0c6d141ef436fa9dee1e9724936562b7d6da diff --git a/services/vpn/src/stackit/vpn/models/bgp_filter_rule_match.py b/services/vpn/src/stackit/vpn/models/bgp_filter_rule_match.py index a23894d6f..1651dfa43 100644 --- a/services/vpn/src/stackit/vpn/models/bgp_filter_rule_match.py +++ b/services/vpn/src/stackit/vpn/models/bgp_filter_rule_match.py @@ -29,7 +29,7 @@ class BGPFilterRuleMatch(BaseModel): """ # noqa: E501 as_path_contains_any: Optional[ - Annotated[List[Annotated[int, Field(le=4294967294, strict=True, ge=64512)]], Field(max_length=10)] + Annotated[List[Annotated[int, Field(le=4294967294, strict=True, ge=1)]], Field(max_length=10)] ] = Field( default=None, description="Matches if the AS-PATH contains any one of the listed ASNs (logical OR within the list). Treated as an unordered set; ordering is not preserved by the storage layer. When combined with firstASN, both conditions must hold (logical AND, consistent with the rest of the match block). If firstASN is also listed here, its presence as the first hop is sufficient to satisfy this list; no duplicate hop is required. ", @@ -39,7 +39,7 @@ class BGPFilterRuleMatch(BaseModel): default=None, description="Matches if the route carries any one of these BGP standard communities (logical OR within the list). Format is 'asn:value' per RFC 1997 (both halves must fit in a uint32, i.e. 0..4294967295). Extended, large and well-known communities are not supported. ", ) - first_asn: Optional[Annotated[int, Field(le=4294967294, strict=True, ge=64512)]] = Field( + first_asn: Optional[Annotated[int, Field(le=4294967294, strict=True, ge=1)]] = Field( default=None, description="Matches if the first ASN (immediate neighbor) in the AS-PATH equals this ASN. Combines with asPathContainsAny using logical AND: when both are set, the first ASN must equal firstASN AND the path must additionally contain at least one ASN from asPathContainsAny. ", alias="firstASN", diff --git a/services/vpn/src/stackit/vpn/models/bgp_tunnel_config.py b/services/vpn/src/stackit/vpn/models/bgp_tunnel_config.py index 2e99ce04e..0b1d25b93 100644 --- a/services/vpn/src/stackit/vpn/models/bgp_tunnel_config.py +++ b/services/vpn/src/stackit/vpn/models/bgp_tunnel_config.py @@ -33,8 +33,8 @@ class BGPTunnelConfig(BaseModel): description="UUID of the BGPFilter to apply to incoming routes from this tunnel's BGP neighbor. The filter must exist in the same gateway. Multiple tunnels may reference the same BGPFilter; in that case the rules' 'match.peer' field can be used to scope behavior per neighbor. Outbound filtering is not yet supported; use gateway.bgp.overrideAdvertisedRoutes to control what is advertised. ", alias="inboundFilterId", ) - remote_asn: Annotated[int, Field(le=4294967294, strict=True, ge=64512)] = Field( - description="ASN for private use (reserved by IANA), both 16Bit and 32Bit ranges are valid (RFC 6996). ", + remote_asn: Annotated[int, Field(le=4294967294, strict=True, ge=1)] = Field( + description='Number of an Autonomous System. Both 16Bit and 32Bit ranges are supported, excluding values reserved by: * RFC 7607 (0) * RFC 6793 (23456, AS_TRANS) * RFC 7300 (65535 and 4294967295, the "Last ASNs") ', alias="remoteAsn", ) __properties: ClassVar[List[str]] = ["inboundFilterId", "remoteAsn"] diff --git a/services/vpn/src/stackit/vpn/models/network_config.py b/services/vpn/src/stackit/vpn/models/network_config.py index e28febf12..7d8b3d0fc 100644 --- a/services/vpn/src/stackit/vpn/models/network_config.py +++ b/services/vpn/src/stackit/vpn/models/network_config.py @@ -15,10 +15,11 @@ import json import pprint +import re # noqa: F401 from typing import Any, ClassVar, Dict, List, Optional, Set from uuid import UUID -from pydantic import BaseModel, ConfigDict, Field +from pydantic import BaseModel, ConfigDict, Field, field_validator from pydantic_core import to_jsonable_python from typing_extensions import Annotated, Self @@ -28,7 +29,7 @@ class NetworkConfig(BaseModel): NetworkConfig """ # noqa: E501 - predefined_network_prefix: Optional[List[Annotated[str, Field(strict=True)]]] = Field( + predefined_network_prefix: Optional[Annotated[str, Field(strict=True)]] = Field( default=None, description="The IPv4 network prefix (CIDR notation) allocated for the VPN gateway. Must have a prefix length of /28 or larger. Once the gateway is created, is not possible to change this attribute. ", alias="predefinedNetworkPrefix", @@ -38,6 +39,21 @@ class NetworkConfig(BaseModel): ) __properties: ClassVar[List[str]] = ["predefinedNetworkPrefix", "routingTableId"] + @field_validator("predefined_network_prefix") + def predefined_network_prefix_validate_regular_expression(cls, value): + """Validates the regular expression""" + if value is None: + return value + + if not isinstance(value, str): + value = str(value) + + if not re.match(r"^((25[0-5]|(2[0-4]|1\d|[1-9]|)\d)\.?\b){4}(\/([0-9]|[1-2][0-9]|3[0-2]))?$", value): + raise ValueError( + r"must validate the regular expression /^((25[0-5]|(2[0-4]|1\d|[1-9]|)\d)\.?\b){4}(\/([0-9]|[1-2][0-9]|3[0-2]))?$/" + ) + return value + model_config = ConfigDict( validate_by_name=True, validate_by_alias=True, From 2f58c6d0935f69ff76ef7a43a01bc52041b8f4a9 Mon Sep 17 00:00:00 2001 From: Jonas Schlecht Date: Wed, 16 Sep 2026 14:47:31 +0200 Subject: [PATCH 2/2] chore(vpn): add changelogs --- CHANGELOG.md | 4 ++++ services/vpn/CHANGELOG.md | 4 ++++ services/vpn/pyproject.toml | 2 +- services/vpn/uv.lock | 2 +- 4 files changed, 10 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b37ad8725..3cc6e48cf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,10 @@ - `telemetryrouter`: - [v0.6.0](services/telemetryrouter/CHANGELOG.md#v060) - **Feature:** Add `disabled` field to `ConfigFilter` to allow disabling a filter without removing it +- `vpn`: + - [v0.7.2](services/vpn/CHANGELOG.md#v072) + - **Breaking Change:** `predefined_network_prefix` attribute in `NetworkConfig` model class changed type from `Optional[List[str]]` to `Optional[str]` to match actual API behavior + - **Improvement:** Relax minimum ASN validation to `1` (previously `64512`) for `as_path_contains_any` and `first_asn` in `BGPFilterRuleMatch` and `remote_asn` in `BGPTunnelConfig` ## Release (2026-09-14) diff --git a/services/vpn/CHANGELOG.md b/services/vpn/CHANGELOG.md index f162e8daa..bff803954 100644 --- a/services/vpn/CHANGELOG.md +++ b/services/vpn/CHANGELOG.md @@ -1,3 +1,7 @@ +## v0.7.2 +- **Breaking Change:** `predefined_network_prefix` attribute in `NetworkConfig` model class changed type from `Optional[List[str]]` to `Optional[str]` to match actual API behavior +- **Improvement:** Relax minimum ASN validation to `1` (previously `64512`) for `as_path_contains_any` and `first_asn` in `BGPFilterRuleMatch` and `remote_asn` in `BGPTunnelConfig` + ## v0.7.1 - **Fix:** Corrected an invalid `pyproject.toml` build configuration (`wheel-sources` instead of `wheel.sources`) that caused `import stackit.vpn` to fail with `ModuleNotFoundError` diff --git a/services/vpn/pyproject.toml b/services/vpn/pyproject.toml index 6c6ab64e7..08ddb4e4a 100644 --- a/services/vpn/pyproject.toml +++ b/services/vpn/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "stackit-vpn" -version = "v0.7.1" +version = "v0.7.2" description = "STACKIT VPN API" authors = [{name = "STACKIT Developer Tools", email = "developer-tools@stackit.cloud"}] requires-python = ">=3.10,<4.0" diff --git a/services/vpn/uv.lock b/services/vpn/uv.lock index 5bd42ffce..3ec91c739 100644 --- a/services/vpn/uv.lock +++ b/services/vpn/uv.lock @@ -1057,7 +1057,7 @@ dev = [ [[package]] name = "stackit-vpn" -version = "0.7.1" +version = "0.7.2" source = { editable = "." } dependencies = [ { name = "pydantic" },