fclient

package
v0.0.0-...-a334e65 Latest Latest
Warning

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

Go to latest
Published: Aug 11, 2025 License: MIT Imports: 9 Imported by: 0

Documentation

Overview

Package fclient provides functional programming wrappers for Kubernetes controller-runtime client.Client operations.

Index

Examples

Constants

This section is empty.

Variables

View Source
var UnitValue = Unit{}

UnitValue is the zero value of Unit type.

Functions

This section is empty.

Types

type CreateParams

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

CreateParams contains parameters for Create operations.

func ToCreateParams

func ToCreateParams(obj client.Object, opts ...client.CreateOption) CreateParams

ToCreateParams creates CreateParams from object and options.

type DeleteAllOfParams

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

DeleteAllOfParams contains parameters for DeleteAllOf operations.

func ToDeleteAllOfParams

func ToDeleteAllOfParams(opts ...client.DeleteAllOfOption) DeleteAllOfParams

ToDeleteAllOfParams creates DeleteAllOfParams from options.

type DeleteParams

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

DeleteParams contains parameters for Delete operations.

func ToDeleteParams

func ToDeleteParams(obj client.Object, opts ...client.DeleteOption) DeleteParams

ToDeleteParams creates DeleteParams from object and options.

type Either

type Either[T any] = ET.Either[error, T]

Either is a type alias for Either with error type.

type Env

type Env struct {
	Ctx    context.Context
	Client client.Client
}

Env represents the environment containing context and client for operations.

type GetParams

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

GetParams contains parameters for Get operations.

func ToGetParams

func ToGetParams(key client.ObjectKey, opts ...client.GetOption) GetParams

ToGetParams creates GetParams from key and options.

type IOEither

type IOEither[T any] = IOE.IOEither[error, T]

IOEither is a type alias for IOEither with error type.

type ListParams

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

ListParams contains parameters for List operations.

func ToListParams

func ToListParams(opts ...client.ListOption) ListParams

ToListParams creates ListParams from options.

type ObjectListPointer

type ObjectListPointer[T any] interface {
	client.ObjectList // Rule 1: T must implement client.ObjectList
	*T                // Rule 2: T must be a pointer type
}

ObjectListPointer is a type that constraints T to be a pointer type and implements client.ObjectList.

type ObjectPointer

type ObjectPointer[T any] interface {
	client.Object // Rule 1: T must implement client.Object
	*T            // Rule 2: T must be a pointer type
}

ObjectPointer is a type that constraints T to be a pointer type and implements client.Object.

type PatchParams

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

PatchParams contains parameters for Patch operations.

func ToPatchParams

func ToPatchParams(obj client.Object, patch client.Patch, opts ...client.PatchOption) PatchParams

ToPatchParams creates PatchParams from object, patch, and options.

type ReaderIOEither

type ReaderIOEither[T any] = RIOE.ReaderIOEither[Env, error, T]

ReaderIOEither is a type alias for ReaderIOEither with Env and error types.

func Create

func Create(p CreateParams) ReaderIOEither[Unit]

Create creates a Kubernetes object using the provided parameters.

func Delete

func Delete(p DeleteParams) ReaderIOEither[Unit]

Delete deletes a Kubernetes object using the provided parameters.

func DeleteAllOf

func DeleteAllOf[T any, OP ObjectPointer[T]](p DeleteAllOfParams) ReaderIOEither[Unit]

DeleteAllOf deletes all objects of a specific type using the provided parameters.

func Get

func Get[T any, OP ObjectPointer[T]](p GetParams) ReaderIOEither[OP]

Get retrieves a Kubernetes object using the provided parameters.

Example
package main

import (
	"context"
	"fmt"

	ET "github.com/IBM/fp-go/either"
	"github.com/appthrust/fcr/pkg/fclient"

	corev1 "k8s.io/api/core/v1"

	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/runtime"
	"sigs.k8s.io/controller-runtime/pkg/client"
	"sigs.k8s.io/controller-runtime/pkg/client/fake"
)

func main() {
	resultToStr := func(result ET.Either[error, *corev1.ConfigMap]) string {
		return ET.Fold(
			func(err error) string { return fmt.Sprintf("Left(%T)", err) },
			func(cm *corev1.ConfigMap) string { return fmt.Sprintf("Right(%T)", cm) },
		)(result)
	}

	// Setup client
	scheme := runtime.NewScheme()
	_ = corev1.AddToScheme(scheme)
	cl := fake.NewClientBuilder().
		WithScheme(scheme).
		// Emulate that the API has a configmap named "exists"
		WithObjects(&corev1.ConfigMap{ObjectMeta: metav1.ObjectMeta{Name: "exists", Namespace: "default"}}).
		Build()

	// Setup environment for reader monad
	env := fclient.Env{Ctx: context.TODO(), Client: cl}

	// Example 1: Found → Right(*corev1.ConfigMap)
	params1 := fclient.ToGetParams(client.ObjectKey{Namespace: "default", Name: "exists"})
	result1 := fclient.Get[corev1.ConfigMap](params1)(env)()
	fmt.Printf("Example 1: %s\n", resultToStr(result1))

	// Example 2: NotFound → Left(*errors.StatusError)
	params2 := fclient.ToGetParams(client.ObjectKey{Namespace: "default", Name: "missing"})
	result2 := fclient.Get[corev1.ConfigMap](params2)(env)()
	fmt.Printf("Example 2: %s\n", resultToStr(result2))

}
Output:

Example 1: Right(*v1.ConfigMap)
Example 2: Left(*errors.StatusError)

func GetOption

func GetOption[T any, OP ObjectPointer[T]](p GetParams) ReaderIOEither[O.Option[OP]]

GetOption performs a Get and converts a not-found result into None.

It composes Get with IgnoreNotFound to return ReaderIOEither[option.Option[OP]] such that:

  • on success, the fetched object is wrapped in Some,
  • if the object does not exist (IsNotFound), it yields None instead of an error,
  • other errors are propagated unchanged.

Use when the absence of a resource is an expected outcome.

Example
package main

import (
	"context"
	"fmt"

	ET "github.com/IBM/fp-go/either"

	O "github.com/IBM/fp-go/option"
	"github.com/appthrust/fcr/pkg/fclient"

	corev1 "k8s.io/api/core/v1"

	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/runtime"
	"sigs.k8s.io/controller-runtime/pkg/client"
	"sigs.k8s.io/controller-runtime/pkg/client/fake"
)

func main() {
	resultToStr := func(result ET.Either[error, O.Option[*corev1.ConfigMap]]) string {
		return ET.Fold(
			func(err error) string { return fmt.Sprintf("Left(%T)", err) },
			func(opt O.Option[*corev1.ConfigMap]) string {
				return O.Fold(
					func() string { return "Right(None)" },
					func(cm *corev1.ConfigMap) string { return fmt.Sprintf("Right(Some(%T))", cm) },
				)(opt)
			},
		)(result)
	}

	// Setup client
	scheme := runtime.NewScheme()
	_ = corev1.AddToScheme(scheme)
	cl := fake.NewClientBuilder().
		WithScheme(scheme).
		// Emulate that the API has a configmap named "exists"
		WithObjects(&corev1.ConfigMap{ObjectMeta: metav1.ObjectMeta{Name: "exists", Namespace: "default"}}).
		Build()

	// Setup environment for reader monad
	env := fclient.Env{Ctx: context.TODO(), Client: cl}

	// Example1: Found → Some
	params1 := fclient.ToGetParams(client.ObjectKey{Namespace: "default", Name: "exists"})
	result1 := fclient.GetOption[corev1.ConfigMap](params1)(env)()
	fmt.Printf("Example 1: %s\n", resultToStr(result1))

	// Example 2: NotFound → None
	params2 := fclient.ToGetParams(client.ObjectKey{Namespace: "default", Name: "missing"})
	result2 := fclient.GetOption[corev1.ConfigMap](params2)(env)()
	fmt.Printf("Example 2: %s\n", resultToStr(result2))

}
Output:

Example 1: Right(Some(*v1.ConfigMap))
Example 2: Right(None)

func IgnoreNotFound

func IgnoreNotFound[T any, OP ObjectPointer[T]](rioe ReaderIOEither[OP]) ReaderIOEither[O.Option[OP]]

IgnoreNotFound turns NotFound errors into None.

It converts a ReaderIOEither[OP] into ReaderIOEither[option.Option[OP]] such that:

  • on success, the object is wrapped in Some,
  • if the error is considered not found by client.IgnoreNotFound, it yields None,
  • for any other error, the error is propagated unchanged.

Typically used after Get when the absence of a resource is not exceptional.

Example
package main

import (
	"context"
	"fmt"

	ET "github.com/IBM/fp-go/either"
	F "github.com/IBM/fp-go/function"

	O "github.com/IBM/fp-go/option"

	RIOE "github.com/IBM/fp-go/readerioeither"
	"github.com/appthrust/fcr/pkg/fclient"

	corev1 "k8s.io/api/core/v1"

	apierrors "k8s.io/apimachinery/pkg/api/errors"
)

func main() {
	resultToStr := func(result ET.Either[error, O.Option[*corev1.ConfigMap]]) string {
		return ET.Fold(
			func(err error) string { return fmt.Sprintf("Left(%T)", err) },
			func(opt O.Option[*corev1.ConfigMap]) string {
				return O.Fold(
					func() string { return "Right(None)" },
					func(cm *corev1.ConfigMap) string { return fmt.Sprintf("Right(Some(%T))", cm) },
				)(opt)
			},
		)(result)
	}

	// Set up environment for reader monad
	env := fclient.Env{Ctx: context.TODO()}

	// Example 1: Right(*corev1.ConfigMap) → Right(Some(*corev1.ConfigMap))
	result1 := F.Pipe1(
		RIOE.Right[fclient.Env, error](&corev1.ConfigMap{ /*...*/ }),
		fclient.IgnoreNotFound,
	)(env)()
	fmt.Printf("Example 1: %s\n", resultToStr(result1))

	// Example 2: Left(*errors.StatusError=NotFound) → Right(None)
	result2 := F.Pipe1(
		RIOE.Left[fclient.Env, *corev1.ConfigMap, error](apierrors.NewNotFound(corev1.Resource("configmaps"), "not-exists-config")),
		fclient.IgnoreNotFound,
	)(env)()
	fmt.Printf("Example 2: %s\n", resultToStr(result2))

	// Example 3: Left(*errors.StatusError) → Left(*errors.StatusError)
	result3 := F.Pipe1(
		RIOE.Left[fclient.Env, *corev1.ConfigMap, error](apierrors.NewBadRequest("bad request")),
		fclient.IgnoreNotFound,
	)(env)()
	fmt.Printf("Example 3: %s\n", resultToStr(result3))

}
Output:

Example 1: Right(Some(*v1.ConfigMap))
Example 2: Right(None)
Example 3: Left(*errors.StatusError)

func List

func List[T any, OLP ObjectListPointer[T]](p ListParams) ReaderIOEither[OLP]

List retrieves a list of Kubernetes objects using the provided parameters.

func ListItems

func ListItems[O any, OL any, OP ObjectPointer[O], OLP ObjectListPointer[OL]](p ListParams) ReaderIOEither[[]OP]

ListItems retrieves a list of Kubernetes objects and returns a list of pointers to the objects.

Example
package main

import (
	"context"
	"fmt"

	ET "github.com/IBM/fp-go/either"
	"github.com/appthrust/fcr/pkg/fclient"

	corev1 "k8s.io/api/core/v1"

	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/runtime"
	"sigs.k8s.io/controller-runtime/pkg/client"
	"sigs.k8s.io/controller-runtime/pkg/client/fake"
)

func main() {
	resultToStr := func(result ET.Either[error, []*corev1.ConfigMap]) string {
		return ET.Fold(
			func(err error) string { return fmt.Sprintf("Left(%T)", err) },
			func(configMaps []*corev1.ConfigMap) string {
				return fmt.Sprintf("Right([]*v1.ConfigMap with %d items)", len(configMaps))
			},
		)(result)
	}

	// Setup client
	scheme := runtime.NewScheme()
	_ = corev1.AddToScheme(scheme)
	cl := fake.NewClientBuilder().
		WithScheme(scheme).
		// Emulate that the API has multiple configmaps
		WithObjects(
			&corev1.ConfigMap{ObjectMeta: metav1.ObjectMeta{Name: "config1", Namespace: "default"}},
			&corev1.ConfigMap{ObjectMeta: metav1.ObjectMeta{Name: "config2", Namespace: "default"}},
			&corev1.ConfigMap{ObjectMeta: metav1.ObjectMeta{Name: "config3", Namespace: "kube-system"}},
		).
		Build()

	// Setup environment for reader monad
	env := fclient.Env{Ctx: context.TODO(), Client: cl}

	// Example 1: List all configmaps in default namespace
	params1 := fclient.ToListParams(client.InNamespace("default"))
	result1 := fclient.ListItems[corev1.ConfigMap, corev1.ConfigMapList](params1)(env)()
	fmt.Printf("Example 1: %s\n", resultToStr(result1))

	// Example 2: List all configmaps across all namespaces
	params2 := fclient.ToListParams()
	result2 := fclient.ListItems[corev1.ConfigMap, corev1.ConfigMapList](params2)(env)()
	fmt.Printf("Example 2: %s\n", resultToStr(result2))

	// Example 3: List configmaps with label selector (none exist with this label)
	params3 := fclient.ToListParams(client.MatchingLabels(map[string]string{"app": "nonexistent"}))
	result3 := fclient.ListItems[corev1.ConfigMap, corev1.ConfigMapList](params3)(env)()
	fmt.Printf("Example 3: %s\n", resultToStr(result3))

}
Output:

Example 1: Right([]*v1.ConfigMap with 2 items)
Example 2: Right([]*v1.ConfigMap with 3 items)
Example 3: Right([]*v1.ConfigMap with 0 items)

func Patch

Patch patches a Kubernetes object using the provided parameters.

func PickListItems

func PickListItems[O any, OL any, OP ObjectPointer[O], OLP ObjectListPointer[OL]](rioe ReaderIOEither[OLP]) ReaderIOEither[[]OP]

PickListItems extracts the items from a Kubernetes list object.

Example
package main

import (
	"context"
	"fmt"

	ET "github.com/IBM/fp-go/either"
	F "github.com/IBM/fp-go/function"
	"github.com/appthrust/fcr/pkg/fclient"

	corev1 "k8s.io/api/core/v1"

	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/runtime"
	"sigs.k8s.io/controller-runtime/pkg/client"
	"sigs.k8s.io/controller-runtime/pkg/client/fake"
)

func main() {
	resultToStr := func(result ET.Either[error, []*corev1.ConfigMap]) string {
		return ET.Fold(
			func(err error) string { return fmt.Sprintf("Left(%T)", err) },
			func(configMaps []*corev1.ConfigMap) string {
				return fmt.Sprintf("Right([]*v1.ConfigMap with %d items)", len(configMaps))
			},
		)(result)
	}

	// Setup client
	scheme := runtime.NewScheme()
	_ = corev1.AddToScheme(scheme)
	cl := fake.NewClientBuilder().
		WithScheme(scheme).
		// Emulate that the API has multiple configmaps
		WithObjects(
			&corev1.ConfigMap{ObjectMeta: metav1.ObjectMeta{Name: "config1", Namespace: "default"}},
			&corev1.ConfigMap{ObjectMeta: metav1.ObjectMeta{Name: "config2", Namespace: "default"}},
			&corev1.ConfigMap{ObjectMeta: metav1.ObjectMeta{Name: "config3", Namespace: "kube-system"}},
		).
		Build()

	// Setup environment for reader monad
	env := fclient.Env{Ctx: context.TODO(), Client: cl}

	// Setup list parameters
	params := fclient.ToListParams(client.InNamespace("default"))

	// Example 1: Use PickListItems to transform List result
	listResult := fclient.List[corev1.ConfigMapList](params)
	pickResult := fclient.PickListItems[corev1.ConfigMap](listResult)(env)()
	fmt.Printf("Example 1: %s\n", resultToStr(pickResult))

	// Example 2: Use PickListItems with F.Pipe1 for composition
	composedResult := F.Pipe1(
		fclient.List[corev1.ConfigMapList](params),
		fclient.PickListItems[corev1.ConfigMap],
	)(env)()
	fmt.Printf("Example 2: %s\n", resultToStr(composedResult))

}
Output:

Example 1: Right([]*v1.ConfigMap with 2 items)
Example 2: Right([]*v1.ConfigMap with 2 items)

func StatusPatch

func StatusPatch(p StatusPatchParams) ReaderIOEither[Unit]

StatusPatch patches the status of a Kubernetes object using the provided parameters.

func StatusUpdate

func StatusUpdate(p StatusUpdateParams) ReaderIOEither[Unit]

StatusUpdate updates the status of a Kubernetes object using the provided parameters.

func Update

func Update(p UpdateParams) ReaderIOEither[Unit]

Update updates a Kubernetes object using the provided parameters.

type StatusPatchParams

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

StatusPatchParams contains parameters for status patch operations.

func ToStatusPatchParams

func ToStatusPatchParams(obj client.Object, patch client.Patch, opts ...client.SubResourcePatchOption) StatusPatchParams

ToStatusPatchParams creates StatusPatchParams from object, patch, and options.

type StatusUpdateParams

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

StatusUpdateParams contains parameters for status update operations.

func ToStatusUpdateParams

func ToStatusUpdateParams(obj client.Object, opts ...client.SubResourceUpdateOption) StatusUpdateParams

ToStatusUpdateParams creates StatusUpdateParams from object and options.

type Unit

type Unit = struct{}

Unit represents the unit type (empty struct).

type UpdateParams

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

UpdateParams contains parameters for Update operations.

func ToUpdateParams

func ToUpdateParams(obj client.Object, opts ...client.UpdateOption) UpdateParams

ToUpdateParams creates UpdateParams from object and options.

Jump to

Keyboard shortcuts

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