Skip to content

Commit 3f20de7

Browse files
bdchathamclaude
andauthored
refactor: simplify NetworkingConfig to public/private presence signal (#76)
* refactor: simplify NetworkingConfig to empty presence signal Strip NetworkingConfig down to an empty struct. The presence of networking: {} means public (ClusterIP Service + HTTPRoutes), absence means private (headless Services only). Removed: - ExternalServiceConfig (Type, Annotations) — always ClusterIP now - GatewayRouteConfig — unused annotation passthrough - NetworkIsolationConfig / AuthorizationPolicy — deferred until isolation requirements are defined - LoadBalancer readiness gate — replaced with DNS hostname check - External P2P address propagation — LB-specific, no longer applies - ControllerSA field — only used by removed AuthorizationPolicy - ConditionExternalServiceReady, ConditionIsolationReady conditions - AuthorizationPolicy RBAC markers Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: address review findings from adversarial review - Remove SEI_CONTROLLER_SA_PRINCIPAL from base manager manifest - Update sample manifest to use networking: {} (removed stale schema) - Restore ServiceMonitor orphaning on Retain deletion policy - Fix stale comments referencing LoadBalancer and AuthorizationPolicy - Update Networking field godoc to reflect public/private semantics - Rename external_address_test.go to route_resolvable_test.go - Regenerate CRDs with updated field descriptions Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 8c760be commit 3f20de7

19 files changed

Lines changed: 219 additions & 1163 deletions

api/v1alpha1/networking_types.go

Lines changed: 9 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,5 @@
11
package v1alpha1
22

3-
import (
4-
corev1 "k8s.io/api/core/v1"
5-
)
6-
73
// DeletionPolicy controls what happens to managed networking resources
84
// and child SeiNodes when their parent is deleted.
95
// +kubebuilder:validation:Enum=Delete;Retain
@@ -14,83 +10,14 @@ const (
1410
DeletionPolicyRetain DeletionPolicy = "Retain"
1511
)
1612

17-
// NetworkingConfig controls how the group is exposed to traffic.
13+
// NetworkingConfig enables public networking for the deployment.
1814
//
19-
// Routing uses the Kubernetes Gateway API exclusively; the platform must
20-
// install the Gateway API CRDs (v1+) and a Gateway implementation such
21-
// as Istio before HTTPRoute resources will take effect.
22-
type NetworkingConfig struct {
23-
// Service creates a non-headless Service shared across all replicas.
24-
// Each SeiNode still gets its own headless Service for pod DNS.
25-
// +optional
26-
Service *ExternalServiceConfig `json:"service,omitempty"`
27-
28-
// Gateway provides optional annotations for generated HTTPRoute resources.
29-
// HTTPRoutes are generated automatically when the node mode has public
30-
// ports and the platform Gateway env vars are configured. This field is
31-
// only needed to add custom annotations to the HTTPRoute metadata.
32-
// +optional
33-
Gateway *GatewayRouteConfig `json:"gateway,omitempty"`
34-
35-
// Isolation configures network-level access control for node pods.
36-
// +optional
37-
Isolation *NetworkIsolationConfig `json:"isolation,omitempty"`
38-
}
39-
40-
// ExternalServiceConfig defines the shared non-headless Service.
41-
// Ports are derived automatically from the node mode via
42-
// seiconfig.NodePortsForMode — no manual port selection needed.
43-
type ExternalServiceConfig struct {
44-
// Type is the Kubernetes Service type.
45-
// +optional
46-
// +kubebuilder:default=ClusterIP
47-
// +kubebuilder:validation:Enum=ClusterIP;LoadBalancer;NodePort
48-
Type corev1.ServiceType `json:"type,omitempty"`
49-
50-
// Annotations are merged onto the Service metadata.
51-
// +optional
52-
Annotations map[string]string `json:"annotations,omitempty"`
53-
}
54-
55-
// GatewayRouteConfig creates gateway.networking.k8s.io/v1 HTTPRoute resources
56-
// targeting the platform Gateway (configured via SEI_GATEWAY_NAME and
57-
// SEI_GATEWAY_NAMESPACE environment variables on the controller).
15+
// When present, the controller creates a ClusterIP Service (as the
16+
// HTTPRoute backend) and generates HTTPRoute resources on the platform
17+
// Gateway for each protocol the node mode supports. Hostnames are
18+
// derived automatically from the deployment name, namespace, and the
19+
// platform domain env vars.
5820
//
59-
// Hostnames are derived automatically from the deployment name, protocol,
60-
// and the platform domain (SEI_GATEWAY_DOMAIN). Which protocols get
61-
// HTTPRoutes is determined by the node mode via seiconfig.NodePortsForMode.
62-
type GatewayRouteConfig struct {
63-
// Annotations are merged onto HTTPRoute metadata.
64-
// +optional
65-
Annotations map[string]string `json:"annotations,omitempty"`
66-
}
67-
68-
// NetworkIsolationConfig defines network-level access control.
69-
type NetworkIsolationConfig struct {
70-
// AuthorizationPolicy creates an Istio AuthorizationPolicy
71-
// restricting which identities can reach node pods.
72-
// +optional
73-
AuthorizationPolicy *AuthorizationPolicyConfig `json:"authorizationPolicy,omitempty"`
74-
}
75-
76-
// AuthorizationPolicyConfig defines allowed traffic sources.
77-
type AuthorizationPolicyConfig struct {
78-
// AllowedSources defines who can reach this group's pods.
79-
// The controller generates an ALLOW policy; traffic from
80-
// sources not listed here is denied.
81-
// +kubebuilder:validation:MinItems=1
82-
AllowedSources []TrafficSource `json:"allowedSources"`
83-
}
84-
85-
// TrafficSource identifies a set of callers by Istio identity.
86-
// +kubebuilder:validation:XValidation:rule="has(self.principals) || has(self.namespaces)",message="at least one of principals or namespaces must be set"
87-
type TrafficSource struct {
88-
// Principals are SPIFFE identities (e.g.
89-
// "cluster.local/ns/istio-system/sa/istio-ingressgateway").
90-
// +optional
91-
Principals []string `json:"principals,omitempty"`
92-
93-
// Namespaces allows all pods in these namespaces.
94-
// +optional
95-
Namespaces []string `json:"namespaces,omitempty"`
96-
}
21+
// When absent (nil), the deployment is private — only per-node headless
22+
// Services exist for in-cluster access.
23+
type NetworkingConfig struct{}

api/v1alpha1/seinodedeployment_types.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,10 @@ type SeiNodeDeploymentSpec struct {
3030
// +optional
3131
Genesis *GenesisCeremonyConfig `json:"genesis,omitempty"`
3232

33-
// Networking controls how the group is exposed to traffic.
34-
// Networking resources are shared across all replicas.
33+
// Networking enables public networking for the deployment.
34+
// When present, the controller creates a ClusterIP Service and
35+
// HTTPRoutes on the platform Gateway. When absent, the deployment
36+
// is private with only per-node headless Services.
3537
// +optional
3638
Networking *NetworkingConfig `json:"networking,omitempty"`
3739

@@ -303,9 +305,7 @@ type DeploymentStatus struct {
303305
// Status condition types for SeiNodeDeployment.
304306
const (
305307
ConditionNodesReady = "NodesReady"
306-
ConditionExternalServiceReady = "ExternalServiceReady"
307308
ConditionRouteReady = "RouteReady"
308-
ConditionIsolationReady = "IsolationReady"
309309
ConditionServiceMonitorReady = "ServiceMonitorReady"
310310
ConditionGenesisCeremonyComplete = "GenesisCeremonyComplete"
311311
ConditionPlanInProgress = "PlanInProgress"

api/v1alpha1/zz_generated.deepcopy.go

Lines changed: 1 addition & 127 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

cmd/main.go

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -177,14 +177,12 @@ func main() {
177177
os.Exit(1)
178178
}
179179

180-
controllerSA := os.Getenv("SEI_CONTROLLER_SA_PRINCIPAL")
181180
//nolint:staticcheck // migrating to events.EventRecorder API is a separate effort
182181
recorder := mgr.GetEventRecorderFor("seinodedeployment-controller")
183182
if err := (&nodedeploymentcontroller.SeiNodeDeploymentReconciler{
184183
Client: kc,
185184
Scheme: mgr.GetScheme(),
186185
Recorder: recorder,
187-
ControllerSA: controllerSA,
188186
GatewayName: platformCfg.GatewayName,
189187
GatewayNamespace: platformCfg.GatewayNamespace,
190188
GatewayDomain: platformCfg.GatewayDomain,

0 commit comments

Comments
 (0)