Skip to content
package pvc
import (
"context"
"github.com/ankitrgadiya/operatorlib/pkg/meta"
"github.com/ankitrgadiya/operatorlib/pkg/interfaces"
"github.com/imdario/mergo"
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
"github.com/pkg/errors"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"github.com/ankitrgadiya/operatorlib/syncer"
)
func (c Conf) Mutate() error {
var om *metav1.ObjectMeta
var accessModes []corev1.PersistentVolumeAccessMode
var resources corev1.ResourceRequirements
var err error
om, err = meta.MutateObjectMeta(c.Meta)
func Generate(m Mutate) (out corev1.PersistentVolumeClaim, err error) {
om, err := meta.MutateObjectMeta(m)
if err != nil {
return errors.Wrap(err, "failed to generate objectmeta")
return out, errors.Wrap(err, "failed to generate objectmeta")
}
if c.GenAccessModesFunc != nil {
accessModes, err = c.GenAccessModesFunc()
accessModes, err := m.GenAccessModes()
if err != nil {
return errors.Wrap(err, "failed to generate pvc accessmodes")
}
return out, errors.Wrap(err, "failed to generate pvc accessmodes")
}
if c.GenResourcesFunc != nil {
resources, err = c.GenResourcesFunc()
resources, err := m.GenResources()
if err != nil {
return errors.Wrap(err, "failed to generate pvc accessmodes")
}
return out, errors.Wrap(err, "failed to generate pvc accessmodes")
}
c.Object.ObjectMeta = *om
c.Object.Spec = corev1.PersistentVolumeClaimSpec{
out.ObjectMeta = *om
out.Spec = corev1.PersistentVolumeClaimSpec{
AccessModes: accessModes,
Resources: resources,
StorageClassName: c.StorageClassName,
}
return nil
// StorageClassName: c.StorageClassName,
}
func (c Conf) MakeObject() *corev1.PersistentVolumeClaim {
obj := &corev1.PersistentVolumeClaim{
ObjectMeta: metav1.ObjectMeta{
Name: c.ObjectName(),
Namespace: c.ObjectNamespace(),
},
return out, nil
}
return obj
}
func SyncObject(c Conf, ctx context.Context) (syncer.SyncResult, error) {
c.Object = c.MakeObject()
func (c Conf) Mutate() controllerutil.MutateFn {
PVCSyncer := syncer.NewObjectSyncer("App PVC", c.ObjectOwner(), c.Object, c.Reconcile, func() error {
if err := c.Mutate(); err != nil {
return func() error {
out, err := Generate(c)
if err != nil {
return err
}
return nil
})
result, err := syncer.Sync(ctx, PVCSyncer)
if err != nil {
return result, err
}
return result, nil
}
mergo.Merge(c.Obj, out)
func (c Conf) ObjectOwner() interfaces.Object {
return c.Meta.ObjectOwner()
}
func (c Conf) ObjectName() string {
return c.Meta.ObjectName()
return nil
}
func (c Conf) ObjectNamespace() string {
return c.Meta.ObjectNamespace()
}
......@@ -5,6 +5,7 @@ import (
"github.com/ankitrgadiya/operatorlib/pkg/meta"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/runtime"
)
type GenPVCFunc func(Conf) (*corev1.PersistentVolumeClaim, error)
......@@ -13,11 +14,25 @@ type GenResourcesFunc func() (corev1.ResourceRequirements, error)
type GenAccessModesFunc func() ([]corev1.PersistentVolumeAccessMode, error)
type Conf struct {
Meta meta.Mutate
Object *corev1.PersistentVolumeClaim
Owner interfaces.Object
Namespace string
Name string
OwnerReference bool
Reconcile interfaces.Reconcile
previousObject runtime.Object
Obj interfaces.Object
GenFinalizers meta.GenFinalizers
GenLabels meta.GenLabels
GenAnnotations meta.GenAnnotations
GenPVCFunc
StorageClassName *string
GenResourcesFunc
GenAccessModesFunc
}
type Mutate interface {
meta.Mutate
GenResources() (corev1.ResourceRequirements, error)
GenAccessModes() ([]corev1.PersistentVolumeAccessMode, error)
}
package secret
import (
"fmt"
"github.com/ankitrgadiya/operatorlib/pkg/interfaces"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/client-go/tools/record"
"sigs.k8s.io/controller-runtime/pkg/client"
)
func (c Conf) GenData() (out map[string][]byte, err error) {
if c.GenDataFunc != nil {
return c.GenDataFunc()
}
return out, nil
}
func (c Conf) GenStringData() (out map[string]string, err error) {
if c.GenStringDataFunc != nil {
return c.GenStringDataFunc()
}
return out, nil
}
func (c Conf) GenLabelsFunc() (map[string]string, error) {
var labels map[string]string
if c.GenLabels != nil {
return c.GenLabels()
}
return labels, nil
}
func (c Conf) GenAnnotationsFunc() (map[string]string, error) {
var annotations map[string]string
if c.GenAnnotations != nil {
return c.GenAnnotations()
}
return annotations, nil
}
func (c Conf) GenFinalizersFunc() ([]string, error) {
if c.GenFinalizers != nil {
return c.GenFinalizers()
}
return nil, nil
}
// Object returns the ObjectSyncer subject
func (s Conf) Object() interfaces.Object {
return s.Obj
}
// Object returns the ObjectSyncer subject
func (s Conf) ObjectName() string {
return s.Name
}
// Object returns the ObjectSyncer subject
func (s Conf) ObjectNamespace() string {
return s.Namespace
}
// ObjectOwner returns the ObjectSyncer owner
func (s Conf) ObjectOwner() interfaces.Object {
return s.Owner
}
// ObjectWithoutSecretData returns the ObjectSyncer subject without secret data
func (s Conf) ObjectWithoutSecretData() runtime.Object {
return stripSecrets(s.Obj)
}
// PreviousWithoutSecretData returns the ObjectSyncer previous subject without secret data
func (s Conf) PreviousWithoutSecretData() runtime.Object {
return stripSecrets(s.previousObject)
}
// ObjectType returns the type of the ObjectSyncer subject
func (s Conf) ObjectType() string {
return fmt.Sprintf("%T", s.Obj)
}
// OwnerType returns the type of the ObjectSyncer owner
func (s Conf) ObjectOwnerType() string {
return fmt.Sprintf("%T", s.Owner)
}
// OwnerType returns the type of the ObjectSyncer owner
func (s Conf) SetPreviousObject() {
// obj := s.Obj.DeepCopyObject().(*appsv1.Deployment)
// s.previousObject = obj
s.previousObject = s.Object()
//s.previousObject = s.Object()
return
}
// OwnerType returns the type of the ObjectSyncer owner
func (s Conf) GetClient() client.Client {
return s.Reconcile.GetClient()
}
// OwnerType returns the type of the ObjectSyncer owner
func (s Conf) GetScheme() *runtime.Scheme {
return s.Reconcile.GetScheme()
}
// OwnerType returns the type of the ObjectSyncer owner
func (s Conf) GetRecorder() record.EventRecorder {
return s.Reconcile.GetRecorder()
}
// stripSecrets returns the object without secretData
func stripSecrets(obj runtime.Object) runtime.Object {
// if obj is secret, don't print secret data
s, ok := obj.(*corev1.Secret)
if ok {
s.Data = nil
s.StringData = nil
return s
}
return obj
}
package secret
import (
"github.com/ankitrgadiya/operatorlib/pkg/meta"
"github.com/imdario/mergo"
"github.com/pkg/errors"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
)
func Generate(m Mutate) (out corev1.Secret, err error) {
om, err := meta.MutateObjectMeta(m)
data, err := m.GenData()
if err != nil {
return out, errors.Wrap(err, "failed to generate data")
}
// stringData, err := c.GenStringDataFunc()
// if err != nil {
// return errors.Wrap(err, "failed to generate string data")
// }
// data, err = mergeData(data, stringData)
// if err != nil {
// return errors.Wrap(err, "failed to merge string data and data")
// }
out.ObjectMeta = *om
out.Data = data
// out.Type = corev1.SecretType(m.Type())
return out, err
}
func (c Conf) Mutate() controllerutil.MutateFn {
return func() error {
out, err := Generate(c)
if err != nil {
return err
}
mergo.Merge(c.Obj, out)
return nil
}
}
func (c Conf) MakeObject() *corev1.Secret {
obj := &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: c.ObjectName(),
Namespace: c.ObjectNamespace(),
},
}
return obj
}
package secret
import (
"github.com/ankitrgadiya/operatorlib/pkg/interfaces"
"github.com/ankitrgadiya/operatorlib/pkg/meta"
corev1 "k8s.io/api/core/v1"
)
// GenSecretFunc defiens a function which generates Service object.
type GenSecretFunc func(Conf) (*corev1.Secret, error)
// GenDataFunc defines a function which generates map of string to
// byte slice for `Data` field in Secret object
type GenDataFunc func() (map[string][]byte, error)
// GenStringDataFunc defines a function which generates string map for
// `StringData` field in Secret object
type GenStringDataFunc func() (map[string]string, error)
type Conf struct {
Namespace string
Name string
Obj interfaces.Object
Reconcile interfaces.Reconcile
previousObject interfaces.Object
Owner interfaces.Object
OwnerReference bool
GenFinalizers meta.GenFinalizers
GenLabels meta.GenLabels
GenAnnotations meta.GenAnnotations
// GenSecretFunc defines a function to generate Secret object. The
// package comes with a default generate function. This field can
// be used to override the default function which is used by the
// operation functions.
GenSecretFunc
// GenDataFunc defines a function to generate data for Secret
GenDataFunc
// GenBinaryDataFunc defines a function to generate binary data
// for Secret
GenStringDataFunc
// Type defines the type of Secret
Type string
}
type Mutate interface {
meta.Mutate
GenData() (map[string][]byte, error)
GenStringData() (map[string]string, error)
}
package secret
import (
"github.com/imdario/mergo"
)
// mergeData utility function merges data and stringData. It does not
// override the alreadyexisting keys in data and only append the keys
// from stringData
func mergeData(data map[string][]byte, stringData map[string]string) (map[string][]byte, error) {
if stringData == nil {
return data, nil
}
newData := make(map[string][]byte, len(stringData))
for key, value := range stringData {
newData[key] = []byte(value)
}
err := mergo.Merge(&data, newData)
if err != nil {
return nil, err
}
return data, nil
}
package service
import (
"fmt"
"github.com/ankitrgadiya/operatorlib/pkg/interfaces"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/client-go/tools/record"
"sigs.k8s.io/controller-runtime/pkg/client"
)
func (c Conf) GenServicePorts() (out []corev1.ServicePort, err error) {
if c.GenServicePortsFunc != nil {
return c.GenServicePortsFunc()
}
return out, nil
}
func (c Conf) GenServiceSelector() (out map[string]string, err error) {
if c.GenServiceSelectorFunc != nil {
return c.GenServiceSelectorFunc()
}
return out, nil
}
func (c Conf) GenServiceType() (out corev1.ServiceType, err error) {
if c.GenServiceTypeFunc != nil {
return c.GenServiceTypeFunc()
}
return out, nil
}
func (c Conf) GenLabelsFunc() (map[string]string, error) {
var labels map[string]string
if c.GenLabels != nil {
return c.GenLabels()
}
return labels, nil
}
func (c Conf) GenAnnotationsFunc() (map[string]string, error) {
var annotations map[string]string
if c.GenAnnotations != nil {
return c.GenAnnotations()
}
return annotations, nil
}
func (c Conf) GenFinalizersFunc() ([]string, error) {
if c.GenFinalizers != nil {
return c.GenFinalizers()
}
return nil, nil
}
// Object returns the ObjectSyncer subject
func (s Conf) Object() interfaces.Object {
return s.Obj
}
// Object returns the ObjectSyncer subject
func (s Conf) ObjectName() string {
return s.Name
}
// Object returns the ObjectSyncer subject
func (s Conf) ObjectNamespace() string {
return s.Namespace
}
// ObjectOwner returns the ObjectSyncer owner
func (s Conf) ObjectOwner() interfaces.Object {
return s.Owner
}
// ObjectWithoutSecretData returns the ObjectSyncer subject without secret data
func (s Conf) ObjectWithoutSecretData() runtime.Object {
return stripSecrets(s.Obj)
}
// PreviousWithoutSecretData returns the ObjectSyncer previous subject without secret data
func (s Conf) PreviousWithoutSecretData() runtime.Object {
return stripSecrets(s.previousObject)
}
// ObjectType returns the type of the ObjectSyncer subject
func (s Conf) ObjectType() string {
return fmt.Sprintf("%T", s.Obj)
}
// OwnerType returns the type of the ObjectSyncer owner
func (s Conf) ObjectOwnerType() string {
return fmt.Sprintf("%T", s.Owner)
}
// OwnerType returns the type of the ObjectSyncer owner
func (s Conf) SetPreviousObject() {
// obj := s.Obj.DeepCopyObject().(*appsv1.Deployment)
// s.previousObject = obj
s.previousObject = s.Object()
//s.previousObject = s.Object()
return
}
// OwnerType returns the type of the ObjectSyncer owner
func (s Conf) GetClient() client.Client {
return s.Reconcile.GetClient()
}
// OwnerType returns the type of the ObjectSyncer owner
func (s Conf) GetScheme() *runtime.Scheme {
return s.Reconcile.GetScheme()
}
// OwnerType returns the type of the ObjectSyncer owner
func (s Conf) GetRecorder() record.EventRecorder {
return s.Reconcile.GetRecorder()
}
// stripSecrets returns the object without secretData
func stripSecrets(obj runtime.Object) runtime.Object {
// if obj is secret, don't print secret data
s, ok := obj.(*corev1.Secret)
if ok {
s.Data = nil
s.StringData = nil
return s
}
return obj
}
package service
import (
"github.com/ankitrgadiya/operatorlib/pkg/meta"
"github.com/imdario/mergo"
"github.com/pkg/errors"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
)
func Generate(m Mutate) (out corev1.Service, err error) {
om, err := meta.MutateObjectMeta(m)
ports, err := m.GenServicePorts()
if err != nil {
return out, errors.Wrap(err, "failed to generate service ports spec")
}
selectors, err := m.GenServiceSelector()
if err != nil {
return out, errors.Wrap(err, "failed to generate service selectors spec")
}
t, err := m.GenServiceType()
if err != nil {
return out, errors.Wrap(err, "failed to generate service type spec")
}
out.ObjectMeta = *om
out.Spec = corev1.ServiceSpec{
Ports: ports,
Selector: selectors,
Type: t,
}
return out, err
}
func (c Conf) Mutate() controllerutil.MutateFn {
return func() error {
out, err := Generate(c)
if err != nil {
return err
}
mergo.Merge(c.Obj, out)
return nil
}
}
func (c Conf) MakeObject() *corev1.Service {
obj := &corev1.Service{
ObjectMeta: metav1.ObjectMeta{
Name: c.ObjectName(),
Namespace: c.ObjectNamespace(),
},
}
return obj
}
package service
import (
"github.com/ankitrgadiya/operatorlib/pkg/interfaces"
"github.com/ankitrgadiya/operatorlib/pkg/meta"
corev1 "k8s.io/api/core/v1"
)
// GenServiceFunc defines a function which generates Service
type GenServiceFunc func(Conf) (*corev1.Service, error)
// GenServicePortsFunc defines a function which generates slice of
// ServicePort for Service
type GenServicePortsFunc func() ([]corev1.ServicePort, error)
// GenSelectorFunc defines a function which generates selectors for
// the Service
type GenServiceSelectorFunc func() (map[string]string, error)
type GenServiceTypeFunc func() (corev1.ServiceType, error)
type Conf struct {
Namespace string
Name string
Obj *corev1.Service
Reconcile interfaces.Reconcile
previousObject interfaces.Object
Owner interfaces.Object
OwnerReference bool
GenFinalizers meta.GenFinalizers
GenLabels meta.GenLabels
GenAnnotations meta.GenAnnotations
GenServiceFunc
// GenServicePortsFunc defines a function to generate ports for
// the Service
GenServicePortsFunc
// GenSelectorFunc defines a function to generate selector for the
// Service
GenServiceSelectorFunc
GenServiceTypeFunc
// Type defines the type of Service object to be created
Type string
}
type Mutate interface {
meta.Mutate
GenServicePorts() ([]corev1.ServicePort, error)
GenServiceSelector() (map[string]string, error)
GenServiceType() (corev1.ServiceType, error)
}
......@@ -96,7 +96,7 @@ func (s *ObjectSyncer) ObjectName() string {
// OwnerType returns the type of the ObjectSyncer owner
func (s *ObjectSyncer) SetPreviousObject() {
s.previousObject = s.Object().DeepCopyObject()
s.previousObject = s.Object()
//s.previousObject = s.Object()
return
}
......
......@@ -63,6 +63,8 @@ func Sync(ctx context.Context, s Interface) (SyncResult, error) {
result := SyncResult{}
recorder := s.GetRecorder()
s.SetPreviousObject()
key, err := getKey(s.Object())
if err != nil {
return result, err
......@@ -114,7 +116,7 @@ func (*WithoutOwner) GetOwner() interfaces.Object {
func Mutate(s Interface) controllerutil.MutateFn {
return func() error {
obj := s.Object()
s.SetPreviousObject()
mutate := s.Mutate()
err := mutate()
if err != nil {
......