service

package
v0.7.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 1, 2026 License: Apache-2.0 Imports: 7 Imported by: 0

Documentation

Overview

Package service provides a builder and resource for managing Kubernetes Services.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func DefaultDeleteOnSuspendHandler

func DefaultDeleteOnSuspendHandler(_ *corev1.Service) bool

DefaultDeleteOnSuspendHandler provides the default decision of whether to delete the Service when the parent component is suspended.

It always returns false, leaving the Service untouched during suspension. Services are typically stateless routing objects that are safe to leave in place. Override with Builder.WithCustomSuspendDeletionDecision to delete the Service on suspend.

This function is used as the default handler by the Resource if no custom handler is registered via Builder.WithCustomSuspendDeletionDecision. It can be reused within custom handlers.

func DefaultGraceStatusHandler

func DefaultGraceStatusHandler(svc *corev1.Service) (concepts.GraceStatusWithReason, error)

DefaultGraceStatusHandler provides the default health assessment of a Service when the component's grace period has expired.

For LoadBalancer services, it reports Degraded if no ingress entries with an IP or hostname have been assigned to Status.LoadBalancer.Ingress, indicating that the external endpoint is not yet available. Once at least one ingress entry contains an IP or hostname, it reports Healthy.

For all other service types (ClusterIP, NodePort, ExternalName, headless), it immediately reports Healthy because these types are functional as soon as they exist.

This function is used as the default handler by the Resource if no custom handler is registered via Builder.WithCustomGraceStatus. It can be reused within custom handlers to augment the default behavior.

func DefaultOperationalStatusHandler

func DefaultOperationalStatusHandler(
	_ concepts.ConvergingOperation, svc *corev1.Service,
) (concepts.OperationalStatusWithReason, error)

DefaultOperationalStatusHandler is the default logic for determining if a Service is operational.

For LoadBalancer services, it reports OperationalStatusPending until at least one ingress entry (IP or hostname) is assigned to Status.LoadBalancer.Ingress, then reports OperationalStatusOperational.

For all other service types (ClusterIP, NodePort, ExternalName, headless), it immediately reports OperationalStatusOperational.

This function is used as the default handler by the Resource if no custom handler is registered via Builder.WithCustomOperationalStatus. It can be reused within custom handlers to augment the default behavior.

func DefaultSuspendMutationHandler

func DefaultSuspendMutationHandler(_ *Mutator) error

DefaultSuspendMutationHandler provides the default mutation applied to a Service when the component is suspended.

It is a no-op because the default behaviour leaves the Service unaffected by suspension.

This function is used as the default handler by the Resource if no custom handler is registered via Builder.WithCustomSuspendMutation. It can be reused within custom handlers.

func DefaultSuspensionStatusHandler

func DefaultSuspensionStatusHandler(_ *corev1.Service) (concepts.SuspensionStatusWithReason, error)

DefaultSuspensionStatusHandler reports the progress of the suspension process.

It always reports Suspended because the default behaviour is a no-op — the Service is left in place and requires no work to reach the suspended state.

This function is used as the default handler by the Resource if no custom handler is registered via Builder.WithCustomSuspendStatus. It can be reused within custom handlers.

Types

type Builder

type Builder struct {
	// contains filtered or unexported fields
}

Builder is a configuration helper for creating and customizing a Service Resource.

It provides a fluent API for registering mutations, status handlers, and data extractors. This builder ensures that the resulting Resource is properly initialized and validated before use in a reconciliation loop.

func NewBuilder

func NewBuilder(svc *corev1.Service) *Builder

NewBuilder initializes a new Builder with the provided Service object.

The Service object passed here serves as the "desired base state". During reconciliation, the Resource will attempt to make the cluster's state match this base state, modified by any registered mutations.

The provided Service must have at least a Name and Namespace set, which is validated during the Build() call.

func (*Builder) Build

func (b *Builder) Build() (*Resource, error)

Build validates the configuration and returns the initialized Resource.

It ensures that:

  • A base Service object was provided.
  • The Service has both a name and a namespace set.

If validation fails, an error is returned and the Resource should not be used.

func (*Builder) WithCustomGraceStatus

func (b *Builder) WithCustomGraceStatus(
	handler func(*corev1.Service) (concepts.GraceStatusWithReason, error),
) *Builder

WithCustomGraceStatus overrides the default logic for assessing the health of the Service when the component's grace period has expired.

The default behavior uses DefaultGraceStatusHandler, which considers LoadBalancer services degraded until an ingress IP or hostname is assigned, and all other service types immediately healthy.

If you want to augment the default behavior, you can call DefaultGraceStatusHandler within your custom handler.

func (*Builder) WithCustomOperationalStatus

func (b *Builder) WithCustomOperationalStatus(
	handler func(concepts.ConvergingOperation, *corev1.Service) (concepts.OperationalStatusWithReason, error),
) *Builder

WithCustomOperationalStatus overrides the default logic for determining if the Service is operational.

The default behavior uses DefaultOperationalStatusHandler, which considers LoadBalancer services pending until an ingress IP or hostname is assigned, and all other service types immediately operational.

If you want to augment the default behavior, you can call DefaultOperationalStatusHandler within your custom handler.

func (*Builder) WithCustomSuspendDeletionDecision

func (b *Builder) WithCustomSuspendDeletionDecision(
	handler func(*corev1.Service) bool,
) *Builder

WithCustomSuspendDeletionDecision overrides the decision of whether to delete the Service when the component is suspended.

The default behavior uses DefaultDeleteOnSuspendHandler, which returns false because Services are stateless routing objects that are safe to leave in place.

If you want to augment the default behavior, you can call DefaultDeleteOnSuspendHandler within your custom handler.

func (*Builder) WithCustomSuspendMutation

func (b *Builder) WithCustomSuspendMutation(
	handler func(*Mutator) error,
) *Builder

WithCustomSuspendMutation defines how the Service should be modified when the component is suspended.

The default behavior uses DefaultSuspendMutationHandler, which is a no-op because the default behaviour leaves the Service unaffected by suspension.

If you want to augment the default behavior, you can call DefaultSuspendMutationHandler within your custom handler.

func (*Builder) WithCustomSuspendStatus

func (b *Builder) WithCustomSuspendStatus(
	handler func(*corev1.Service) (concepts.SuspensionStatusWithReason, error),
) *Builder

WithCustomSuspendStatus overrides how the progress of suspension is reported.

The default behavior uses DefaultSuspensionStatusHandler, which always reports Suspended because the default behaviour leaves the Service untouched.

If you want to augment the default behavior, you can call DefaultSuspensionStatusHandler within your custom handler.

func (*Builder) WithDataExtractor

func (b *Builder) WithDataExtractor(
	extractor func(corev1.Service) error,
) *Builder

WithDataExtractor registers a function to harvest information from the Service after it has been successfully reconciled.

This is useful for capturing auto-generated fields (like assigned ClusterIP or LoadBalancer ingress) and making them available to other components or resources via the framework's data extraction mechanism.

func (*Builder) WithGuard added in v0.4.0

func (b *Builder) WithGuard(
	guard func(corev1.Service) (concepts.GuardStatusWithReason, error),
) *Builder

WithGuard registers a guard precondition that is evaluated before the Service is applied during reconciliation. If the guard returns Blocked, the Service and all resources registered after it are skipped until the guard clears. Passing nil clears any previously registered guard.

func (*Builder) WithMutation

func (b *Builder) WithMutation(m Mutation) *Builder

WithMutation registers a feature-based mutation for the Service.

Mutations are applied sequentially during the Mutate() phase of reconciliation. They are typically used by Features to modify ports, selectors, or other service configuration.

Since mutations are often version-gated, the provided feature.Mutation should contain the logic to determine if and how the mutation is applied based on the component's current version or configuration.

type Mutation

type Mutation feature.Mutation[*Mutator]

Mutation defines a mutation that is applied to a service Mutator only if its associated feature gate is enabled.

type Mutator

type Mutator struct {
	// contains filtered or unexported fields
}

Mutator is a high-level helper for modifying a Kubernetes Service.

It uses a "plan-and-apply" pattern: mutations are recorded first, then applied to the Service in a single controlled pass when Apply() is called.

The Mutator maintains feature boundaries: each feature's mutations are planned together and applied in the order the features were registered.

Mutator implements editors.ObjectMutator.

func NewMutator

func NewMutator(svc *corev1.Service) *Mutator

NewMutator creates a new Mutator for the given Service. The constructor creates the initial feature scope automatically.

func (*Mutator) Apply

func (m *Mutator) Apply() error

Apply executes all recorded mutation intents on the underlying Service.

Execution order across all registered features:

  1. Metadata edits (in registration order within each feature)
  2. Service spec edits (in registration order within each feature)

Features are applied in the order they were registered. Later features observe the Service as modified by all previous features.

After all edits are applied, auto-allocated NodePort values that were present before mutations are restored for NodePort and LoadBalancer Services when the resulting port's NodePort is 0 (unset). This prevents mutations that replace ports via EnsurePort from unintentionally clearing server-assigned NodePorts.

func (*Mutator) EditObjectMetadata

func (m *Mutator) EditObjectMetadata(edit func(*editors.ObjectMetaEditor) error)

EditObjectMetadata records a mutation for the Service's own metadata.

Metadata edits are applied before service spec edits within the same feature. A nil edit function is ignored.

func (*Mutator) EditServiceSpec

func (m *Mutator) EditServiceSpec(edit func(*editors.ServiceSpecEditor) error)

EditServiceSpec records a mutation for the Service's spec.

The editor provides structured operations (SetType, EnsurePort, SetSelector, etc.) as well as Raw() for free-form access. Service spec edits are applied after metadata edits within the same feature, in registration order.

A nil edit function is ignored.

func (*Mutator) NextFeature

func (m *Mutator) NextFeature()

NextFeature advances to a new feature planning scope. All subsequent mutation registrations will be grouped into this scope until NextFeature is called again.

The first scope is created automatically by NewMutator. This method is called by the framework between mutations to maintain per-feature ordering semantics.

type Resource

type Resource struct {
	// contains filtered or unexported fields
}

Resource is a high-level abstraction for managing a Kubernetes Service within a controller's reconciliation loop.

It implements the following component interfaces:

  • component.Resource: for basic identity and mutation behaviour.
  • concepts.Operational: for tracking whether the Service is operational.
  • concepts.Graceful: for health assessment after the component's grace period expires.
  • concepts.Suspendable: for participating in the component suspension lifecycle.
  • concepts.Guardable: for conditional reconciliation based on a guard precondition.
  • concepts.DataExtractable: for exporting values after successful reconciliation.

func (*Resource) ConvergingStatus

ConvergingStatus reports the operational status of the Service.

By default, it uses DefaultOperationalStatusHandler, which considers LoadBalancer services pending until an ingress IP or hostname is assigned, and all other service types immediately operational.

func (*Resource) DeleteOnSuspend

func (r *Resource) DeleteOnSuspend() bool

DeleteOnSuspend determines whether the Service should be deleted from the cluster when the parent component is suspended.

By default, it uses DefaultDeleteOnSuspendHandler, which returns false — the Service is left in place during suspension.

func (*Resource) ExtractData

func (r *Resource) ExtractData() error

ExtractData executes all registered data extractor functions against a deep copy of the reconciled Service.

This is called by the framework after successful reconciliation, allowing the component to read generated or updated values such as assigned ClusterIP or LoadBalancer ingress from the Service.

func (*Resource) GraceStatus

func (r *Resource) GraceStatus() (concepts.GraceStatusWithReason, error)

GraceStatus reports the health of the Service after the component's grace period has expired.

By default, it uses DefaultGraceStatusHandler, which considers LoadBalancer services degraded until an ingress IP or hostname is assigned, and all other service types immediately healthy.

func (*Resource) GuardStatus added in v0.4.0

func (r *Resource) GuardStatus() (concepts.GuardStatusWithReason, error)

GuardStatus evaluates the resource's guard precondition. If no guard was registered, the resource is unconditionally unblocked.

func (*Resource) Identity

func (r *Resource) Identity() string

Identity returns a unique identifier for the Service in the format "v1/Service/<namespace>/<name>".

func (*Resource) Mutate

func (r *Resource) Mutate(current client.Object) error

Mutate transforms the current state of a Kubernetes Service into the desired state.

The mutation process follows this order:

  1. Feature mutations: all registered feature-gated mutations are applied in order.
  2. Suspension: if the resource is in a suspending state, the suspension mutation is applied.

func (*Resource) Object

func (r *Resource) Object() (client.Object, error)

Object returns a deep copy of the underlying Kubernetes Service object.

The returned object implements client.Object, making it compatible with controller-runtime's Client for Create, Update, and Patch operations.

func (*Resource) PreviewObject added in v0.6.0

func (r *Resource) PreviewObject() (*corev1.Service, error)

PreviewObject returns the Service as it would appear after feature mutations have been applied, without modifying the resource's internal state.

Suspension mutations are not applied; the preview reflects content state only.

func (*Resource) Suspend

func (r *Resource) Suspend() error

Suspend triggers the suspension of the Service.

The default handler is a no-op — the Service is left unaffected by suspension.

func (*Resource) SuspensionStatus

func (r *Resource) SuspensionStatus() (concepts.SuspensionStatusWithReason, error)

SuspensionStatus reports the progress of the suspension process.

By default, it uses DefaultSuspensionStatusHandler, which always reports Suspended because the default behaviour leaves the Service untouched.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL