Merge branch 'main' into refactor/permissions-manager

# Conflicts:
#	management/internals/modules/reverseproxy/service/manager/api.go
#	management/server/http/testing/testing_tools/channel/channel.go
This commit is contained in:
pascal
2026-03-27 14:37:29 +01:00
125 changed files with 11320 additions and 413 deletions
+1
View File
@@ -22,6 +22,7 @@ type Client interface {
GetDeviceAuthorizationFlow(serverKey wgtypes.Key) (*proto.DeviceAuthorizationFlow, error)
GetPKCEAuthorizationFlow(serverKey wgtypes.Key) (*proto.PKCEAuthorizationFlow, error)
GetNetworkMap(sysInfo *system.Info) (*proto.NetworkMap, error)
GetServerURL() string
IsHealthy() bool
SyncMeta(sysInfo *system.Info) error
Logout() error
+42 -1
View File
@@ -5,6 +5,8 @@ import (
"errors"
"fmt"
"io"
"os"
"strconv"
"sync"
"time"
@@ -29,6 +31,10 @@ import (
const ConnectTimeout = 10 * time.Second
const (
// EnvMaxRecvMsgSize overrides the default gRPC max receive message size (4 MB)
// for the management client connection. Value is in bytes.
EnvMaxRecvMsgSize = "NB_MANAGEMENT_GRPC_MAX_MSG_SIZE"
errMsgMgmtPublicKey = "failed getting Management Service public key: %s"
errMsgNoMgmtConnection = "no connection to management"
)
@@ -46,6 +52,7 @@ type GrpcClient struct {
conn *grpc.ClientConn
connStateCallback ConnStateNotifier
connStateCallbackLock sync.RWMutex
serverURL string
}
type ExposeRequest struct {
@@ -66,13 +73,41 @@ type ExposeResponse struct {
PortAutoAssigned bool
}
// MaxRecvMsgSize returns the configured max gRPC receive message size from
// the environment, or 0 if unset (which uses the gRPC default of 4 MB).
func MaxRecvMsgSize() int {
val := os.Getenv(EnvMaxRecvMsgSize)
if val == "" {
return 0
}
size, err := strconv.Atoi(val)
if err != nil {
log.Warnf("invalid %s value %q, using default: %v", EnvMaxRecvMsgSize, val, err)
return 0
}
if size <= 0 {
log.Warnf("invalid %s value %d, must be positive, using default", EnvMaxRecvMsgSize, size)
return 0
}
return size
}
// NewClient creates a new client to Management service
func NewClient(ctx context.Context, addr string, ourPrivateKey wgtypes.Key, tlsEnabled bool) (*GrpcClient, error) {
var conn *grpc.ClientConn
var extraOpts []grpc.DialOption
if maxSize := MaxRecvMsgSize(); maxSize > 0 {
extraOpts = append(extraOpts, grpc.WithDefaultCallOptions(grpc.MaxCallRecvMsgSize(maxSize)))
log.Infof("management gRPC max receive message size set to %d bytes", maxSize)
}
operation := func() error {
var err error
conn, err = nbgrpc.CreateConnection(ctx, addr, tlsEnabled, wsproxy.ManagementComponent)
conn, err = nbgrpc.CreateConnection(ctx, addr, tlsEnabled, wsproxy.ManagementComponent, extraOpts...)
if err != nil {
return fmt.Errorf("create connection: %w", err)
}
@@ -93,9 +128,15 @@ func NewClient(ctx context.Context, addr string, ourPrivateKey wgtypes.Key, tlsE
ctx: ctx,
conn: conn,
connStateCallbackLock: sync.RWMutex{},
serverURL: addr,
}, nil
}
// GetServerURL returns the management server URL
func (c *GrpcClient) GetServerURL() string {
return c.serverURL
}
// Close closes connection to the Management Service
func (c *GrpcClient) Close() error {
return c.conn.Close()
+95
View File
@@ -0,0 +1,95 @@
package client
import (
"context"
"net"
"os"
"strings"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
mgmtProto "github.com/netbirdio/netbird/shared/management/proto"
)
func TestMaxRecvMsgSize(t *testing.T) {
tests := []struct {
name string
envValue string
expected int
}{
{name: "unset returns 0", envValue: "", expected: 0},
{name: "valid value", envValue: "10485760", expected: 10485760},
{name: "non-numeric returns 0", envValue: "abc", expected: 0},
{name: "negative returns 0", envValue: "-1", expected: 0},
{name: "zero returns 0", envValue: "0", expected: 0},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Setenv(EnvMaxRecvMsgSize, tt.envValue)
if tt.envValue == "" {
os.Unsetenv(EnvMaxRecvMsgSize)
}
assert.Equal(t, tt.expected, MaxRecvMsgSize())
})
}
}
// largeSyncServer implements just the Sync RPC, returning a response larger than the default 4MB limit.
type largeSyncServer struct {
mgmtProto.UnimplementedManagementServiceServer
responseSize int
}
func (s *largeSyncServer) GetServerKey(_ context.Context, _ *mgmtProto.Empty) (*mgmtProto.ServerKeyResponse, error) {
// Return a response with a large WiretrusteeConfig to exceed the default limit.
padding := strings.Repeat("x", s.responseSize)
return &mgmtProto.ServerKeyResponse{
Key: padding,
}, nil
}
func TestMaxRecvMsgSizeIntegration(t *testing.T) {
const payloadSize = 5 * 1024 * 1024 // 5MB, exceeds 4MB default
lis, err := net.Listen("tcp", "127.0.0.1:0")
require.NoError(t, err)
srv := grpc.NewServer()
mgmtProto.RegisterManagementServiceServer(srv, &largeSyncServer{responseSize: payloadSize})
go func() { _ = srv.Serve(lis) }()
t.Cleanup(srv.Stop)
t.Run("default limit rejects large message", func(t *testing.T) {
conn, err := grpc.NewClient(
lis.Addr().String(),
grpc.WithTransportCredentials(insecure.NewCredentials()),
)
require.NoError(t, err)
defer conn.Close()
client := mgmtProto.NewManagementServiceClient(conn)
_, err = client.GetServerKey(context.Background(), &mgmtProto.Empty{})
require.Error(t, err)
assert.Contains(t, err.Error(), "received message larger than max")
})
t.Run("increased limit accepts large message", func(t *testing.T) {
conn, err := grpc.NewClient(
lis.Addr().String(),
grpc.WithTransportCredentials(insecure.NewCredentials()),
grpc.WithDefaultCallOptions(grpc.MaxCallRecvMsgSize(10*1024*1024)),
)
require.NoError(t, err)
defer conn.Close()
client := mgmtProto.NewManagementServiceClient(conn)
resp, err := client.GetServerKey(context.Background(), &mgmtProto.Empty{})
require.NoError(t, err)
assert.Len(t, resp.Key, payloadSize)
})
}
+9
View File
@@ -19,6 +19,7 @@ type MockClient struct {
LoginFunc func(serverKey wgtypes.Key, info *system.Info, sshKey []byte, dnsLabels domain.List) (*proto.LoginResponse, error)
GetDeviceAuthorizationFlowFunc func(serverKey wgtypes.Key) (*proto.DeviceAuthorizationFlow, error)
GetPKCEAuthorizationFlowFunc func(serverKey wgtypes.Key) (*proto.PKCEAuthorizationFlow, error)
GetServerURLFunc func() string
SyncMetaFunc func(sysInfo *system.Info) error
LogoutFunc func() error
JobFunc func(ctx context.Context, msgHandler func(msg *proto.JobRequest) *proto.JobResponse) error
@@ -92,6 +93,14 @@ func (m *MockClient) GetNetworkMap(_ *system.Info) (*proto.NetworkMap, error) {
return nil, nil
}
// GetServerURL mock implementation of GetServerURL from mgm.Client interface
func (m *MockClient) GetServerURL() string {
if m.GetServerURLFunc == nil {
return ""
}
return m.GetServerURLFunc()
}
func (m *MockClient) SyncMeta(sysInfo *system.Info) error {
if m.SyncMetaFunc == nil {
return nil
+299
View File
@@ -89,6 +89,10 @@ tags:
- name: Event Streaming Integrations
description: Manage event streaming integrations.
x-cloud-only: true
- name: Notifications
description: Manage notification channels for account event alerts.
x-cloud-only: true
components:
schemas:
@@ -2995,6 +2999,11 @@ components:
type: boolean
description: Whether the service is enabled
example: true
terminated:
type: boolean
description: Whether the service has been terminated. Terminated services cannot be updated. Services that violate the Terms of Service will be terminated.
readOnly: true
example: false
pass_host_header:
type: boolean
description: When true, the original client Host header is passed through to the backend instead of being rewritten to the backend's address
@@ -3336,6 +3345,10 @@ components:
type: boolean
description: Whether the cluster supports binding arbitrary TCP/UDP ports
example: true
require_subdomain:
type: boolean
description: Whether a subdomain label is required in front of this domain. When true, the domain cannot be used bare.
example: false
required:
- id
- domain
@@ -4381,6 +4394,123 @@ components:
type: string
description: The newly generated SCIM API token
example: "nbs_F3f0d..."
NotificationChannelType:
type: string
description: The type of notification channel.
enum:
- email
- webhook
example: "email"
NotificationEventType:
type: string
description: |
An activity event type code. See `GET /api/integrations/notifications/types` for the full list
of supported event types and their human-readable descriptions.
example: "user.join"
EmailTarget:
type: object
description: Target configuration for email notification channels.
properties:
emails:
type: array
description: List of email addresses to send notifications to.
minItems: 1
items:
type: string
format: email
example: [ "admin@example.com", "ops@example.com" ]
required:
- emails
WebhookTarget:
type: object
description: Target configuration for webhook notification channels.
properties:
url:
type: string
format: uri
description: The webhook endpoint URL to send notifications to.
example: "https://hooks.example.com/netbird"
headers:
type: object
additionalProperties:
type: string
description: |
Custom HTTP headers sent with each webhook request.
Values are write-only; in GET responses all values are masked.
example:
Authorization: "Bearer token"
X-Webhook-Secret: "secret"
required:
- url
NotificationChannelRequest:
type: object
description: Request body for creating or updating a notification channel.
properties:
type:
$ref: '#/components/schemas/NotificationChannelType'
target:
description: |
Channel-specific target configuration. The shape depends on the `type` field:
- `email`: requires an `EmailTarget` object
- `webhook`: requires a `WebhookTarget` object
oneOf:
- $ref: '#/components/schemas/EmailTarget'
- $ref: '#/components/schemas/WebhookTarget'
event_types:
type: array
description: List of activity event type codes this channel subscribes to.
items:
$ref: '#/components/schemas/NotificationEventType'
example: [ "user.join", "peer.user.add", "peer.login.expire" ]
enabled:
type: boolean
description: Whether this notification channel is active.
example: true
required:
- type
- event_types
- enabled
NotificationChannelResponse:
type: object
description: A notification channel configuration.
properties:
id:
type: string
description: Unique identifier of the notification channel.
readOnly: true
example: "ch8i4ug6lnn4g9hqv7m0"
type:
$ref: '#/components/schemas/NotificationChannelType'
target:
description: |
Channel-specific target configuration. The shape depends on the `type` field:
- `email`: an `EmailTarget` object
- `webhook`: a `WebhookTarget` object
oneOf:
- $ref: '#/components/schemas/EmailTarget'
- $ref: '#/components/schemas/WebhookTarget'
event_types:
type: array
description: List of activity event type codes this channel subscribes to.
items:
$ref: '#/components/schemas/NotificationEventType'
example: [ "user.join", "peer.user.add", "peer.login.expire" ]
enabled:
type: boolean
description: Whether this notification channel is active.
example: true
required:
- id
- type
- event_types
- enabled
NotificationTypeEntry:
type: object
description: A map of event type codes to their human-readable descriptions.
additionalProperties:
type: string
example:
user.join: "User joined"
BypassResponse:
type: object
description: Response for bypassed peer operations.
@@ -10058,3 +10188,172 @@ paths:
"$ref": "#/components/responses/not_found"
'500':
"$ref": "#/components/responses/internal_error"
/api/integrations/notifications/types:
get:
tags:
- Notifications
summary: List Notification Event Types
description: |
Returns a map of all supported activity event type codes to their
human-readable descriptions. Use these codes when configuring
`event_types` on notification channels.
operationId: listNotificationEventTypes
responses:
'200':
description: A map of event type codes to descriptions.
content:
application/json:
schema:
$ref: '#/components/schemas/NotificationTypeEntry'
'400':
"$ref": "#/components/responses/bad_request"
'401':
"$ref": "#/components/responses/requires_authentication"
'403':
"$ref": "#/components/responses/forbidden"
'404':
"$ref": "#/components/responses/not_found"
'500':
"$ref": "#/components/responses/internal_error"
/api/integrations/notifications/channels:
get:
tags:
- Notifications
summary: List Notification Channels
description: Retrieves all notification channels configured for the authenticated account.
operationId: listNotificationChannels
responses:
'200':
description: A list of notification channels.
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/NotificationChannelResponse'
'400':
"$ref": "#/components/responses/bad_request"
'401':
"$ref": "#/components/responses/requires_authentication"
'403':
"$ref": "#/components/responses/forbidden"
'404':
"$ref": "#/components/responses/not_found"
'500':
"$ref": "#/components/responses/internal_error"
post:
tags:
- Notifications
summary: Create Notification Channel
description: |
Creates a new notification channel for the authenticated account.
Supported channel types are `email` and `webhook`.
operationId: createNotificationChannel
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/NotificationChannelRequest'
responses:
'200':
description: Notification channel created successfully.
content:
application/json:
schema:
$ref: '#/components/schemas/NotificationChannelResponse'
'400':
"$ref": "#/components/responses/bad_request"
'401':
"$ref": "#/components/responses/requires_authentication"
'403':
"$ref": "#/components/responses/forbidden"
'404':
"$ref": "#/components/responses/not_found"
'500':
"$ref": "#/components/responses/internal_error"
/api/integrations/notifications/channels/{channelId}:
parameters:
- name: channelId
in: path
required: true
description: The unique identifier of the notification channel.
schema:
type: string
example: "ch8i4ug6lnn4g9hqv7m0"
get:
tags:
- Notifications
summary: Get Notification Channel
description: Retrieves a specific notification channel by its ID.
operationId: getNotificationChannel
responses:
'200':
description: Successfully retrieved the notification channel.
content:
application/json:
schema:
$ref: '#/components/schemas/NotificationChannelResponse'
'400':
"$ref": "#/components/responses/bad_request"
'401':
"$ref": "#/components/responses/requires_authentication"
'403':
"$ref": "#/components/responses/forbidden"
'404':
"$ref": "#/components/responses/not_found"
'500':
"$ref": "#/components/responses/internal_error"
put:
tags:
- Notifications
summary: Update Notification Channel
description: Updates an existing notification channel.
operationId: updateNotificationChannel
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/NotificationChannelRequest'
responses:
'200':
description: Notification channel updated successfully.
content:
application/json:
schema:
$ref: '#/components/schemas/NotificationChannelResponse'
'400':
"$ref": "#/components/responses/bad_request"
'401':
"$ref": "#/components/responses/requires_authentication"
'403':
"$ref": "#/components/responses/forbidden"
'404':
"$ref": "#/components/responses/not_found"
'500':
"$ref": "#/components/responses/internal_error"
delete:
tags:
- Notifications
summary: Delete Notification Channel
description: Deletes a notification channel by its ID.
operationId: deleteNotificationChannel
responses:
'200':
description: Notification channel deleted successfully.
content:
application/json:
schema:
type: object
example: { }
'400':
"$ref": "#/components/responses/bad_request"
'401':
"$ref": "#/components/responses/requires_authentication"
'403':
"$ref": "#/components/responses/forbidden"
'404':
"$ref": "#/components/responses/not_found"
'500':
"$ref": "#/components/responses/internal_error"
+232
View File
@@ -9,6 +9,7 @@ import (
"time"
"github.com/oapi-codegen/runtime"
openapi_types "github.com/oapi-codegen/runtime/types"
)
const (
@@ -664,6 +665,24 @@ func (e NetworkResourceType) Valid() bool {
}
}
// Defines values for NotificationChannelType.
const (
NotificationChannelTypeEmail NotificationChannelType = "email"
NotificationChannelTypeWebhook NotificationChannelType = "webhook"
)
// Valid indicates whether the value is a known member of the NotificationChannelType enum.
func (e NotificationChannelType) Valid() bool {
switch e {
case NotificationChannelTypeEmail:
return true
case NotificationChannelTypeWebhook:
return true
default:
return false
}
}
// Defines values for PeerNetworkRangeCheckAction.
const (
PeerNetworkRangeCheckActionAllow PeerNetworkRangeCheckAction = "allow"
@@ -1893,6 +1912,12 @@ type EDRSentinelOneResponse struct {
UpdatedAt time.Time `json:"updated_at"`
}
// EmailTarget Target configuration for email notification channels.
type EmailTarget struct {
// Emails List of email addresses to send notifications to.
Emails []openapi_types.Email `json:"emails"`
}
// ErrorResponse Standard error response. Note: The exact structure of this error response is inferred from `util.WriteErrorResponse` and `util.WriteError` usage in the provided Go code, as a specific Go struct for errors was not provided.
type ErrorResponse struct {
// Message A human-readable error message.
@@ -2666,6 +2691,67 @@ type NetworkTrafficUser struct {
Name string `json:"name"`
}
// NotificationChannelRequest Request body for creating or updating a notification channel.
type NotificationChannelRequest struct {
// Enabled Whether this notification channel is active.
Enabled bool `json:"enabled"`
// EventTypes List of activity event type codes this channel subscribes to.
EventTypes []NotificationEventType `json:"event_types"`
// Target Channel-specific target configuration. The shape depends on the `type` field:
// - `email`: requires an `EmailTarget` object
// - `webhook`: requires a `WebhookTarget` object
Target *NotificationChannelRequest_Target `json:"target,omitempty"`
// Type The type of notification channel.
Type NotificationChannelType `json:"type"`
}
// NotificationChannelRequest_Target Channel-specific target configuration. The shape depends on the `type` field:
// - `email`: requires an `EmailTarget` object
// - `webhook`: requires a `WebhookTarget` object
type NotificationChannelRequest_Target struct {
union json.RawMessage
}
// NotificationChannelResponse A notification channel configuration.
type NotificationChannelResponse struct {
// Enabled Whether this notification channel is active.
Enabled bool `json:"enabled"`
// EventTypes List of activity event type codes this channel subscribes to.
EventTypes []NotificationEventType `json:"event_types"`
// Id Unique identifier of the notification channel.
Id *string `json:"id,omitempty"`
// Target Channel-specific target configuration. The shape depends on the `type` field:
// - `email`: an `EmailTarget` object
// - `webhook`: a `WebhookTarget` object
Target *NotificationChannelResponse_Target `json:"target,omitempty"`
// Type The type of notification channel.
Type NotificationChannelType `json:"type"`
}
// NotificationChannelResponse_Target Channel-specific target configuration. The shape depends on the `type` field:
// - `email`: an `EmailTarget` object
// - `webhook`: a `WebhookTarget` object
type NotificationChannelResponse_Target struct {
union json.RawMessage
}
// NotificationChannelType The type of notification channel.
type NotificationChannelType string
// NotificationEventType An activity event type code. See `GET /api/integrations/notifications/types` for the full list
// of supported event types and their human-readable descriptions.
type NotificationEventType = string
// NotificationTypeEntry A map of event type codes to their human-readable descriptions.
type NotificationTypeEntry map[string]string
// OSVersionCheck Posture check for the version of operating system
type OSVersionCheck struct {
// Android Posture check for the version of operating system
@@ -3406,6 +3492,9 @@ type ReverseProxyDomain struct {
// Id Domain ID
Id string `json:"id"`
// RequireSubdomain Whether a subdomain label is required in front of this domain. When true, the domain cannot be used bare.
RequireSubdomain *bool `json:"require_subdomain,omitempty"`
// SupportsCustomPorts Whether the cluster supports binding arbitrary TCP/UDP ports
SupportsCustomPorts *bool `json:"supports_custom_ports,omitempty"`
@@ -3629,6 +3718,9 @@ type Service struct {
// Targets List of target backends for this service
Targets []ServiceTarget `json:"targets"`
// Terminated Whether the service has been terminated. Terminated services cannot be updated. Services that violate the Terms of Service will be terminated.
Terminated *bool `json:"terminated,omitempty"`
}
// ServiceMode Service mode. "http" for L7 reverse proxy, "tcp"/"udp"/"tls" for L4 passthrough.
@@ -4208,6 +4300,16 @@ type UserRequest struct {
Role string `json:"role"`
}
// WebhookTarget Target configuration for webhook notification channels.
type WebhookTarget struct {
// Headers Custom HTTP headers sent with each webhook request.
// Values are write-only; in GET responses all values are masked.
Headers *map[string]string `json:"headers,omitempty"`
// Url The webhook endpoint URL to send notifications to.
Url string `json:"url"`
}
// WorkloadRequest defines model for WorkloadRequest.
type WorkloadRequest struct {
union json.RawMessage
@@ -4561,6 +4663,12 @@ type PostApiIntegrationsMspTenantsIdSubscriptionJSONRequestBody PostApiIntegrati
// PostApiIntegrationsMspTenantsIdUnlinkJSONRequestBody defines body for PostApiIntegrationsMspTenantsIdUnlink for application/json ContentType.
type PostApiIntegrationsMspTenantsIdUnlinkJSONRequestBody PostApiIntegrationsMspTenantsIdUnlinkJSONBody
// CreateNotificationChannelJSONRequestBody defines body for CreateNotificationChannel for application/json ContentType.
type CreateNotificationChannelJSONRequestBody = NotificationChannelRequest
// UpdateNotificationChannelJSONRequestBody defines body for UpdateNotificationChannel for application/json ContentType.
type UpdateNotificationChannelJSONRequestBody = NotificationChannelRequest
// CreateSCIMIntegrationJSONRequestBody defines body for CreateSCIMIntegration for application/json ContentType.
type CreateSCIMIntegrationJSONRequestBody = CreateScimIntegrationRequest
@@ -4657,6 +4765,130 @@ type PutApiUsersUserIdPasswordJSONRequestBody = PasswordChangeRequest
// PostApiUsersUserIdTokensJSONRequestBody defines body for PostApiUsersUserIdTokens for application/json ContentType.
type PostApiUsersUserIdTokensJSONRequestBody = PersonalAccessTokenRequest
// AsEmailTarget returns the union data inside the NotificationChannelRequest_Target as a EmailTarget
func (t NotificationChannelRequest_Target) AsEmailTarget() (EmailTarget, error) {
var body EmailTarget
err := json.Unmarshal(t.union, &body)
return body, err
}
// FromEmailTarget overwrites any union data inside the NotificationChannelRequest_Target as the provided EmailTarget
func (t *NotificationChannelRequest_Target) FromEmailTarget(v EmailTarget) error {
b, err := json.Marshal(v)
t.union = b
return err
}
// MergeEmailTarget performs a merge with any union data inside the NotificationChannelRequest_Target, using the provided EmailTarget
func (t *NotificationChannelRequest_Target) MergeEmailTarget(v EmailTarget) error {
b, err := json.Marshal(v)
if err != nil {
return err
}
merged, err := runtime.JSONMerge(t.union, b)
t.union = merged
return err
}
// AsWebhookTarget returns the union data inside the NotificationChannelRequest_Target as a WebhookTarget
func (t NotificationChannelRequest_Target) AsWebhookTarget() (WebhookTarget, error) {
var body WebhookTarget
err := json.Unmarshal(t.union, &body)
return body, err
}
// FromWebhookTarget overwrites any union data inside the NotificationChannelRequest_Target as the provided WebhookTarget
func (t *NotificationChannelRequest_Target) FromWebhookTarget(v WebhookTarget) error {
b, err := json.Marshal(v)
t.union = b
return err
}
// MergeWebhookTarget performs a merge with any union data inside the NotificationChannelRequest_Target, using the provided WebhookTarget
func (t *NotificationChannelRequest_Target) MergeWebhookTarget(v WebhookTarget) error {
b, err := json.Marshal(v)
if err != nil {
return err
}
merged, err := runtime.JSONMerge(t.union, b)
t.union = merged
return err
}
func (t NotificationChannelRequest_Target) MarshalJSON() ([]byte, error) {
b, err := t.union.MarshalJSON()
return b, err
}
func (t *NotificationChannelRequest_Target) UnmarshalJSON(b []byte) error {
err := t.union.UnmarshalJSON(b)
return err
}
// AsEmailTarget returns the union data inside the NotificationChannelResponse_Target as a EmailTarget
func (t NotificationChannelResponse_Target) AsEmailTarget() (EmailTarget, error) {
var body EmailTarget
err := json.Unmarshal(t.union, &body)
return body, err
}
// FromEmailTarget overwrites any union data inside the NotificationChannelResponse_Target as the provided EmailTarget
func (t *NotificationChannelResponse_Target) FromEmailTarget(v EmailTarget) error {
b, err := json.Marshal(v)
t.union = b
return err
}
// MergeEmailTarget performs a merge with any union data inside the NotificationChannelResponse_Target, using the provided EmailTarget
func (t *NotificationChannelResponse_Target) MergeEmailTarget(v EmailTarget) error {
b, err := json.Marshal(v)
if err != nil {
return err
}
merged, err := runtime.JSONMerge(t.union, b)
t.union = merged
return err
}
// AsWebhookTarget returns the union data inside the NotificationChannelResponse_Target as a WebhookTarget
func (t NotificationChannelResponse_Target) AsWebhookTarget() (WebhookTarget, error) {
var body WebhookTarget
err := json.Unmarshal(t.union, &body)
return body, err
}
// FromWebhookTarget overwrites any union data inside the NotificationChannelResponse_Target as the provided WebhookTarget
func (t *NotificationChannelResponse_Target) FromWebhookTarget(v WebhookTarget) error {
b, err := json.Marshal(v)
t.union = b
return err
}
// MergeWebhookTarget performs a merge with any union data inside the NotificationChannelResponse_Target, using the provided WebhookTarget
func (t *NotificationChannelResponse_Target) MergeWebhookTarget(v WebhookTarget) error {
b, err := json.Marshal(v)
if err != nil {
return err
}
merged, err := runtime.JSONMerge(t.union, b)
t.union = merged
return err
}
func (t NotificationChannelResponse_Target) MarshalJSON() ([]byte, error) {
b, err := t.union.MarshalJSON()
return b, err
}
func (t *NotificationChannelResponse_Target) UnmarshalJSON(b []byte) error {
err := t.union.UnmarshalJSON(b)
return err
}
// AsBundleWorkloadRequest returns the union data inside the WorkloadRequest as a BundleWorkloadRequest
func (t WorkloadRequest) AsBundleWorkloadRequest() (BundleWorkloadRequest, error) {
var body BundleWorkloadRequest
+17 -5
View File
@@ -181,8 +181,11 @@ type ProxyCapabilities struct {
state protoimpl.MessageState `protogen:"open.v1"`
// Whether the proxy can bind arbitrary ports for TCP/UDP/TLS services.
SupportsCustomPorts *bool `protobuf:"varint,1,opt,name=supports_custom_ports,json=supportsCustomPorts,proto3,oneof" json:"supports_custom_ports,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
// Whether the proxy requires a subdomain label in front of its cluster domain.
// When true, tenants cannot use the cluster domain bare.
RequireSubdomain *bool `protobuf:"varint,2,opt,name=require_subdomain,json=requireSubdomain,proto3,oneof" json:"require_subdomain,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *ProxyCapabilities) Reset() {
@@ -222,6 +225,13 @@ func (x *ProxyCapabilities) GetSupportsCustomPorts() bool {
return false
}
func (x *ProxyCapabilities) GetRequireSubdomain() bool {
if x != nil && x.RequireSubdomain != nil {
return *x.RequireSubdomain
}
return false
}
// GetMappingUpdateRequest is sent to initialise a mapping stream.
type GetMappingUpdateRequest struct {
state protoimpl.MessageState `protogen:"open.v1"`
@@ -1872,10 +1882,12 @@ var File_proxy_service_proto protoreflect.FileDescriptor
const file_proxy_service_proto_rawDesc = "" +
"\n" +
"\x13proxy_service.proto\x12\n" +
"management\x1a\x1egoogle/protobuf/duration.proto\x1a\x1fgoogle/protobuf/timestamp.proto\"f\n" +
"management\x1a\x1egoogle/protobuf/duration.proto\x1a\x1fgoogle/protobuf/timestamp.proto\"\xae\x01\n" +
"\x11ProxyCapabilities\x127\n" +
"\x15supports_custom_ports\x18\x01 \x01(\bH\x00R\x13supportsCustomPorts\x88\x01\x01B\x18\n" +
"\x16_supports_custom_ports\"\xe6\x01\n" +
"\x15supports_custom_ports\x18\x01 \x01(\bH\x00R\x13supportsCustomPorts\x88\x01\x01\x120\n" +
"\x11require_subdomain\x18\x02 \x01(\bH\x01R\x10requireSubdomain\x88\x01\x01B\x18\n" +
"\x16_supports_custom_portsB\x14\n" +
"\x12_require_subdomain\"\xe6\x01\n" +
"\x17GetMappingUpdateRequest\x12\x19\n" +
"\bproxy_id\x18\x01 \x01(\tR\aproxyId\x12\x18\n" +
"\aversion\x18\x02 \x01(\tR\aversion\x129\n" +
@@ -31,6 +31,9 @@ service ProxyService {
message ProxyCapabilities {
// Whether the proxy can bind arbitrary ports for TCP/UDP/TLS services.
optional bool supports_custom_ports = 1;
// Whether the proxy requires a subdomain label in front of its cluster domain.
// When true, accounts cannot use the cluster domain bare.
optional bool require_subdomain = 2;
}
// GetMappingUpdateRequest is sent to initialise a mapping stream.