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
4 changes: 4 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,10 @@ test: manifests generate fmt vet envtest ## Run tests.
test-local: envtest ## Run tests.
KUBEBUILDER_ASSETS="$(shell $(ENVTEST) use $(ENVTEST_K8S_VERSION) -p path)" go test ./controllers/controller/... -coverprofile cover.out

.PHONY: test-e2e-hns
test-e2e-hns: ## Run the Hub-and-Spoke (partial mesh) control-plane e2e suite against a real, disposable Kind cluster.
go test -tags e2e -v -timeout 20m ./test/e2e/...

.PHONY: int-test
int-test: envtest
KUBEBUILDER_ASSETS="$(shell $(ENVTEST) use $(ENVTEST_K8S_VERSION) -p path)" go test ./controllers/controller/... -coverprofile cover.out
Expand Down
25 changes: 25 additions & 0 deletions apis/controller/v1alpha1/sliceconfig_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,31 @@ type SliceConfigSpec struct {
// RenewBefore is used for renew now!
RenewBefore *metav1.Time `json:"renewBefore,omitempty"`
VPNConfig *VPNConfiguration `json:"vpnConfig,omitempty"`
// Topology configures the inter-cluster connection topology for the slice.
// When absent, the slice uses full-mesh connectivity (existing behavior).
//+optional
Topology *TopologySpec `json:"topology,omitempty"`
}

// +kubebuilder:validation:Enum=FullMesh;HubAndSpoke
type TopologyMode string

const (
TopologyModeFullMesh TopologyMode = "FullMesh"
TopologyModeHubAndSpoke TopologyMode = "HubAndSpoke"
)

// TopologySpec defines the inter-cluster connection topology of the slice
type TopologySpec struct {
// Mode selects the connection topology. Absent defaults to FullMesh.
//+optional
Mode TopologyMode `json:"mode,omitempty"`
// Hubs lists the clusters acting as hubs when Mode is HubAndSpoke.
// Each entry must be a member of spec.clusters. All non-hub members
// become spokes. Exactly one hub is supported in this release.
//+optional
//+kubebuilder:validation:MaxItems=1
Hubs []string `json:"hubs,omitempty"`
}

// ExternalGatewayConfig is the configuration for external gateways like 'istio', etc/
Expand Down
25 changes: 25 additions & 0 deletions apis/controller/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

28 changes: 28 additions & 0 deletions apis/worker/v1alpha1/workerslicegateway_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,12 @@ type WorkerSliceGatewaySpec struct {
LocalGatewayConfig SliceGatewayConfig `json:"localGatewayConfig,omitempty"`
RemoteGatewayConfig SliceGatewayConfig `json:"remoteGatewayConfig,omitempty"`
GatewayNumber int `json:"gatewayNumber,omitempty"`
// RouteEntireSliceSubnet, when true, tells the worker to route the whole
// slice subnet (not just the peer gateway's subnet) via this gateway. The
// controller sets it on a spoke's gateway to the hub in HubAndSpoke topology,
// so a spoke forwards all slice-internal traffic (including traffic destined
// for other spokes) to the hub, which relays it.
RouteEntireSliceSubnet bool `json:"routeEntireSliceSubnet,omitempty"`
}

type SliceGatewayConfig struct {
Expand All @@ -61,9 +67,31 @@ type GatewayCredentials struct {
}

// WorkerSliceGatewayStatus defines the observed state of WorkerSliceGateway
// Gateway connection states reported by the worker on WorkerSliceGatewayStatus.
const (
// GatewayConnectionStateConnected means the gateway tunnel is up (at least
// one HA gateway pod reports its tunnel established).
GatewayConnectionStateConnected = "Connected"
// GatewayConnectionStateNotConnected means the tunnel is down (all gateway
// pods report their tunnel not established).
GatewayConnectionStateNotConnected = "NotConnected"
// GatewayConnectionStatePending means no connectivity has been reported yet.
// An empty ConnectionState is treated as Pending by the controller-side aggregation.
GatewayConnectionStatePending = "Pending"
)

type WorkerSliceGatewayStatus struct {
GatewayNumber int `json:"gatewayNumber,omitempty"`
ClusterInsertionIndex int `json:"clusterInsertionIndex,omitempty"`
// ConnectionState is the connectivity state of this gateway link as reported
// by the worker: Connected, NotConnected or Pending. Empty means Pending.
ConnectionState string `json:"connectionState,omitempty"`
// LastTransitionTime is the time ConnectionState last changed.
LastTransitionTime *metav1.Time `json:"lastTransitionTime,omitempty"`
// Reason is a short, machine-readable reason for the current ConnectionState.
Reason string `json:"reason,omitempty"`
// Message is a human-readable description of the current ConnectionState.
Message string `json:"message,omitempty"`
}

//+kubebuilder:object:root=true
Expand Down
6 changes: 5 additions & 1 deletion apis/worker/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

22 changes: 22 additions & 0 deletions config/crd/bases/controller.kubeslice.io_sliceconfigs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,28 @@ spec:
type: string
standardQosProfileName:
type: string
topology:
description: |-
Topology configures the inter-cluster connection topology for the slice.
When absent, the slice uses full-mesh connectivity (existing behavior).
properties:
hubs:
description: |-
Hubs lists the clusters acting as hubs when Mode is HubAndSpoke.
Each entry must be a member of spec.clusters. All non-hub members
become spokes. Exactly one hub is supported in this release.
items:
type: string
maxItems: 1
type: array
mode:
description: Mode selects the connection topology. Absent defaults
to FullMesh.
enum:
- FullMesh
- HubAndSpoke
type: string
type: object
vpnConfig:
description: VPNConfiguration defines the additional (optional) VPN
Configuration to customise
Expand Down
25 changes: 25 additions & 0 deletions config/crd/bases/worker.kubeslice.io_workerslicegateways.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,14 @@ spec:
vpnIp:
type: string
type: object
routeEntireSliceSubnet:
description: |-
RouteEntireSliceSubnet, when true, tells the worker to route the whole
slice subnet (not just the peer gateway's subnet) via this gateway. The
controller sets it on a spoke's gateway to the hub in HubAndSpoke topology,
so a spoke forwards all slice-internal traffic (including traffic destined
for other spokes) to the hub, which relays it.
type: boolean
sliceName:
type: string
type: object
Expand All @@ -131,8 +139,25 @@ spec:
properties:
clusterInsertionIndex:
type: integer
connectionState:
description: 'ConnectionState is the connectivity state of this gateway
link as reported by the worker: Connected, NotConnected or Pending.
Empty means Pending.'
type: string
gatewayNumber:
type: integer
lastTransitionTime:
description: LastTransitionTime is the time ConnectionState last changed.
format: date-time
type: string
message:
description: Message is a human-readable description of the current
ConnectionState.
type: string
reason:
description: Reason is a short, machine-readable reason for the current
ConnectionState.
type: string
type: object
type: object
served: true
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Sample SliceConfig using the HubAndSpoke topology.
#
# worker-1 acts as the hub; worker-2 and worker-3 become spokes (all
# non-hub members are spokes).
#
# Note: this sample exercises the API and validation only. As of this
# release the controller does not yet consume spec.topology to change
# gateway/peer link creation (that is follow-up implementation work);
# the intended result once it does is hub<->spoke links only
# (worker-1<->worker-2, worker-1<->worker-3) and no spoke<->spoke link.
#
# Omitting spec.topology entirely (or setting mode: FullMesh with no
# hubs) keeps the existing full-mesh behavior.
apiVersion: controller.kubeslice.io/v1alpha1
kind: SliceConfig
metadata:
name: hub-and-spoke-slice
spec:
sliceType: Application
sliceSubnet: 10.1.0.0/16
sliceGatewayProvider:
sliceGatewayType: OpenVPN
sliceCaType: Local
sliceIpamType: Local
clusters:
- worker-1
- worker-2
- worker-3
topology:
mode: HubAndSpoke
hubs:
- worker-1
qosProfileDetails:
queueType: HTB
priority: 1
tcType: BANDWIDTH_CONTROL
bandwidthCeilingKbps: 5120
bandwidthGuaranteedKbps: 2560
dscpClass: AF11
Loading