github.com/argoproj/argo-events@v1.9.1/eventsources/persist/event_persist.go (about)

     1  package persist
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  
     7  	v1 "k8s.io/api/core/v1"
     8  	apierr "k8s.io/apimachinery/pkg/api/errors"
     9  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    10  	"k8s.io/client-go/kubernetes"
    11  
    12  	"github.com/argoproj/argo-events/common"
    13  	"github.com/argoproj/argo-events/pkg/apis/eventsource/v1alpha1"
    14  )
    15  
    16  type EventPersist interface {
    17  	Save(event *Event) error
    18  	Get(key string) (*Event, error)
    19  	IsEnabled() bool
    20  }
    21  
    22  type Event struct {
    23  	EventKey     string
    24  	EventPayload string
    25  }
    26  
    27  type ConfigMapPersist struct {
    28  	ctx              context.Context
    29  	kubeClient       kubernetes.Interface
    30  	name             string
    31  	namespace        string
    32  	createIfNotExist bool
    33  }
    34  
    35  func createConfigmap(ctx context.Context, client kubernetes.Interface, name, namespace string) (*v1.ConfigMap, error) {
    36  	cm := v1.ConfigMap{}
    37  	cm.Name = name
    38  	cm.Namespace = namespace
    39  	return client.CoreV1().ConfigMaps(namespace).Create(ctx, &cm, metav1.CreateOptions{})
    40  }
    41  
    42  func NewConfigMapPersist(ctx context.Context, client kubernetes.Interface, configmap *v1alpha1.ConfigMapPersistence, namespace string) (EventPersist, error) {
    43  	if configmap == nil {
    44  		return nil, fmt.Errorf("persistence configuration is nil")
    45  	}
    46  	_, err := client.CoreV1().ConfigMaps(namespace).Get(ctx, configmap.Name, metav1.GetOptions{})
    47  	if err != nil {
    48  		if apierr.IsNotFound(err) && configmap.CreateIfNotExist {
    49  			_, err = createConfigmap(ctx, client, configmap.Name, namespace)
    50  			if err != nil {
    51  				if !apierr.IsAlreadyExists(err) {
    52  					return nil, err
    53  				}
    54  			}
    55  		} else {
    56  			return nil, err
    57  		}
    58  	}
    59  	cmp := ConfigMapPersist{
    60  		ctx:              ctx,
    61  		kubeClient:       client,
    62  		name:             configmap.Name,
    63  		namespace:        namespace,
    64  		createIfNotExist: configmap.CreateIfNotExist,
    65  	}
    66  	return &cmp, nil
    67  }
    68  
    69  func (cmp *ConfigMapPersist) IsEnabled() bool {
    70  	return true
    71  }
    72  
    73  func (cmp *ConfigMapPersist) Save(event *Event) error {
    74  	if event == nil {
    75  		return fmt.Errorf("event object is nil")
    76  	}
    77  	// Using Connect util func for backoff retry if K8s API returns error
    78  	err := common.DoWithRetry(&common.DefaultBackoff, func() error {
    79  		cm, err := cmp.kubeClient.CoreV1().ConfigMaps(cmp.namespace).Get(cmp.ctx, cmp.name, metav1.GetOptions{})
    80  		if err != nil {
    81  			if apierr.IsNotFound(err) && cmp.createIfNotExist {
    82  				cm, err = createConfigmap(cmp.ctx, cmp.kubeClient, cmp.name, cmp.namespace)
    83  				if err != nil {
    84  					return err
    85  				}
    86  			} else {
    87  				return err
    88  			}
    89  		}
    90  
    91  		if len(cm.Data) == 0 {
    92  			cm.Data = make(map[string]string)
    93  		}
    94  
    95  		cm.Data[event.EventKey] = event.EventPayload
    96  		_, err = cmp.kubeClient.CoreV1().ConfigMaps(cmp.namespace).Update(cmp.ctx, cm, metav1.UpdateOptions{})
    97  
    98  		return err
    99  	})
   100  
   101  	if err != nil {
   102  		return err
   103  	}
   104  	return nil
   105  }
   106  
   107  func (cmp *ConfigMapPersist) Get(key string) (*Event, error) {
   108  	cm, err := cmp.kubeClient.CoreV1().ConfigMaps(cmp.namespace).Get(cmp.ctx, cmp.name, metav1.GetOptions{})
   109  	if err != nil {
   110  		if apierr.IsNotFound(err) {
   111  			return nil, nil
   112  		}
   113  		return nil, err
   114  	}
   115  	payload, exist := cm.Data[key]
   116  	if !exist {
   117  		return nil, nil
   118  	}
   119  	return &Event{EventKey: key, EventPayload: payload}, nil
   120  }
   121  
   122  type NullPersistence struct {
   123  }
   124  
   125  func (n *NullPersistence) Save(event *Event) error {
   126  	return nil
   127  }
   128  
   129  func (n *NullPersistence) Get(key string) (*Event, error) {
   130  	return nil, nil
   131  }
   132  
   133  func (cmp *NullPersistence) IsEnabled() bool {
   134  	return false
   135  }