feat/networking-statefulset #3

Merged
litelotus merged 9 commits from feat/networking-statefulset into main 2026-05-28 11:18:03 +00:00
Owner
No description provided.
- pods/deployment.go: ContainerPort.Port is now pulumi.IntInput
- networking/service.go: ToolkitServiceDestinationPort.Port is now pulumi.IntInput
- networking/ingress_service_path.go: updated to use .ToIntOutput()
- Removed leftover src/volumes/longhorn.go that conflicted with the
  longhorn/ subpackage after PR merge

Ports can now reference outputs from other Pulumi resources directly
(e.g. another service's port output) without manual conversion.
Provides type-safe wrappers that accept both literals and Pulumi outputs
without requiring users to wrap every literal in pulumi.Int() / pulumi.String().

- types.Int(8080) for literal ints
- types.IntFrom(someResource.PortOutput) for dynamic values
- types.String("hello") for literal strings
- types.StringFrom(someResource.NameOutput) for dynamic values

Updated ContainerPort.Port and ToolkitServiceDestinationPort.Port to use
types.IntValue. Removed stale src/volumes/longhorn.go left from PR merge.
- networking/service.go: rewritten with cleaner API
  - ServicePort replaces ToolkitServiceDestinationPort (supports separate TargetPort)
  - ServiceType enum (ClusterIP, NodePort, LoadBalancer)
  - Deployment field auto-derives selector from a CreatedToolkitDeploymentRef
  - Protocol defaults to TCP if empty
  - buildPortArray/resolveSelector are private helpers (no fake error returns)
  - Removed Autoname (niche, cluttered the API)
- pods/deployment.go: added SelectorLabels() method for service interop
- networking/ingress_service_path.go: updated to use ServicePort type

Usage:
  svc, _ := networking.ToolkitServiceOptions{
      Name: "my-app",
      Deployment: &networking.CreatedToolkitDeploymentRef{
          SelectorLabels: deploy.SelectorLabels(),
      },
      Ports: map[string]networking.ServicePort{
          "http": {Port: types.Int(8080)},
      },
  }.CreateNewService(ctx)

  // Interop with non-toolkit Pulumi code:
  svc.Service.Metadata.Name()
- types/port_value.go: PortValue carries either a numeric port, a named
  port, or both (from a container ref). ToServiceTargetPort() emits the
  name as a string targetPort when available, letting Kubernetes resolve
  the number from the pod spec.
- pods/deployment.go: ContainerPort.Ref() returns a PortValue referencing
  that container's port by name + number.
- networking/service.go: ServicePort.TargetPort is now *PortValue, accepting
  numeric ports, named ports, or container port references.

Usage:
  httpPort := pods.ContainerPort{Name: "http", Port: types.Int(8080)}

  // Service references the container's port by name — stays in sync
  // even if the port number changes:
  svc, _ := networking.ToolkitServiceOptions{
      Ports: map[string]networking.ServicePort{
          "http": {Port: types.Int(80), TargetPort: ref(httpPort.Ref())},
      },
  }.CreateNewService(ctx)
- types/workload.go: PodWorkload interface — any workload (Deployment,
  StatefulSet) exposes its selector labels and container ports
- types/port_value.go: PortValue carries name + number from container refs.
  ToServiceTargetPort() emits the name string for k8s native resolution.
- pods/deployment.go: CreatedToolkitDeployment satisfies PodWorkload.
  deploy.Port("container", "port") returns a PortValue for direct use.
- networking/service.go: Workload field accepts any PodWorkload for
  auto-selector. ServicePort.TargetPort is now the primary field —
  Port defaults to TargetPort's number if nil.
- networking/ingress_service_path.go: uses named port for backend when
  available, falls back to numeric.
- Removed CreatedToolkitDeploymentRef (no longer needed).

Usage:
  deploy, _ := pods.ToolkitDeploymentOptions{
      Name: "my-app",
      Containers: []pods.ToolkitContainer{{
          Name: "app",
          Ports: []pods.ContainerPort{{Name: "http", Port: types.Int(8080)}},
      }},
  }.CreateNewDeployment(ctx)

  svc, _ := networking.ToolkitServiceOptions{
      Name:     "my-app",
      Workload: deploy,
      Ports: map[string]networking.ServicePort{
          "http": {TargetPort: deploy.Port("app", "http")},
      },
  }.CreateNewService(ctx)
- networking/ingress.go: complete rewrite
  - IngressRoute references a CreatedToolkitService directly
  - Port auto-resolved from service (single port = no config needed)
  - PortName for multi-port services (matches service Ports map key)
  - TLS enabled by default with configurable issuer and secret name
  - IngressClass configurable (no hardcoded traefik)
  - Path defaults to "/", PathType defaults to "Prefix"
  - Named port used on backend for resilience
- Removed ingress_service_path.go and ingress_resource_path.go
  (functionality absorbed into IngressRoute)

Usage:
  ingress, _ := networking.ToolkitIngressOptions{
      Name:         "my-app",
      Namespace:    ns,
      IngressClass: "traefik",
      Routes: map[string][]networking.IngressRoute{
          "app.example.com": {{Service: svc}},
      },
  }.CreateNewIngress(ctx)

  // Multi-path, multi-port:
  ingress, _ := networking.ToolkitIngressOptions{
      Name: "my-app",
      Routes: map[string][]networking.IngressRoute{
          "app.example.com": {
              {Service: svc, PortName: "http", Path: "/"},
              {Service: svc, PortName: "grpc", Path: "/grpc"},
          },
      },
      TLS: &networking.IngressTLS{ClusterIssuer: "cloudflare-issuer"},
  }.CreateNewIngress(ctx)
- networking/ingress.go: IngressRoute.GRPC flag auto-adds the
  traefik h2c backend scheme annotation for gRPC services
- networking/traefik/: new subpackage for Traefik-specific CRDs
  - ingress_route_tcp.go: placeholder for IngressRouteTCP (raw TCP
    routing for MQTT, custom protocols, database connections)
  - middleware.go: placeholder for Middleware chains
  - doc.go: package documentation

gRPC usage:
  Routes: map[string][]networking.IngressRoute{
      "grpc.example.com": {{Service: svc, GRPC: true}},
  }
- IngressClass is now a typed IngressClassType enum, not a raw string
- gRPC h2c annotation only emitted for IngressClassTraefik
- nginx backend-protocol annotation emitted for IngressClassNginx
- Easy to extend for angie or other controllers in future

Usage:
  IngressClass: networking.IngressClassTraefik
- pods/statefulset.go: ToolkitStatefulSetOptions creates a StatefulSet
  with its required headless Service auto-generated
  - VolumeClaimTemplates: per-pod PVCs via StorageClassProvider + StorageSize
  - PodManagementPolicy: OrderedReady (default) or Parallel
  - UpdateStrategy: RollingUpdate (default) or OnDelete
  - Reuses ToolkitContainer, buildContainerSpecs, buildVolumes from deployment
  - Satisfies types.PodWorkload interface (same service/ingress wiring)
  - deploy.Port() pattern works identically: sts.Port("app", "http")
  - HeadlessService and StatefulSet Pulumi resources exposed for interop

Usage:
  sts, _ := pods.ToolkitStatefulSetOptions{
      Name:      "postgres",
      Namespace: ns,
      Replicas:  intPtr(3),
      Containers: []pods.ToolkitContainer{{
          Name:  "postgres",
          Image: pulumi.String("postgres:16"),
          Ports: []pods.ContainerPort{{Name: "tcp", Port: types.Int(5432)}},
      }},
      VolumeClaimTemplates: []pods.VolumeClaimTemplate{{
          Name:         "data",
          Size:         volumes.StorageSize{Unit: "Gi", MinSize: 50},
          StorageClass: longhornSC,
      }},
  }.CreateNewStatefulSet(ctx)

  // Wire a service (same as deployments):
  svc, _ := networking.ToolkitServiceOptions{
      Name:     "postgres",
      Workload: sts,
      Ports: map[string]networking.ServicePort{
          "tcp": {TargetPort: sts.Port("postgres", "tcp")},
      },
  }.CreateNewService(ctx)
litelotus deleted branch feat/networking-statefulset 2026-05-28 12:10:25 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
homelab/kubernetes-toolkit!3
No description provided.