github.com/docker/compose-on-kubernetes@v0.5.0/internal/registry/stackregistry.go (about)

     1  package registry
     2  
     3  import (
     4  	"context"
     5  
     6  	iv "github.com/docker/compose-on-kubernetes/internal/internalversion"
     7  	"github.com/pkg/errors"
     8  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
     9  	"k8s.io/apimachinery/pkg/fields"
    10  	"k8s.io/apimachinery/pkg/labels"
    11  	"k8s.io/apimachinery/pkg/runtime"
    12  	"k8s.io/apiserver/pkg/registry/generic"
    13  	genericregistry "k8s.io/apiserver/pkg/registry/generic/registry"
    14  	"k8s.io/apiserver/pkg/registry/rest"
    15  	"k8s.io/apiserver/pkg/storage"
    16  	appsv1 "k8s.io/client-go/kubernetes/typed/apps/v1"
    17  	corev1 "k8s.io/client-go/kubernetes/typed/core/v1"
    18  	restclient "k8s.io/client-go/rest"
    19  )
    20  
    21  const composeOutOfDate = "# This compose file is outdated: the stack was updated by other means\n"
    22  
    23  // StackREST is a storage for stack resource
    24  type StackREST struct {
    25  	genericregistry.Store
    26  }
    27  
    28  type stackRESTGet interface {
    29  	GetStack(ctx context.Context, name string, options *metav1.GetOptions) (*iv.Stack, error)
    30  }
    31  
    32  type stackRESTStore interface {
    33  	stackRESTGet
    34  	CreateStack(ctx context.Context, newStack *iv.Stack, createValidation rest.ValidateObjectFunc, options *metav1.CreateOptions) (*iv.Stack, error)
    35  	UpdateStack(ctx context.Context, name string, transform StackTransform, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc,
    36  		forceAllowCreate bool, options *metav1.UpdateOptions) (*iv.Stack, bool, error)
    37  }
    38  
    39  // GetStack wraps the Get method in a more strictly typed way
    40  func (s *StackREST) GetStack(ctx context.Context, name string, options *metav1.GetOptions) (*iv.Stack, error) {
    41  	obj, err := s.Get(ctx, name, options)
    42  	if err != nil {
    43  		return nil, err
    44  	}
    45  	stack, ok := obj.(*iv.Stack)
    46  	if !ok {
    47  		return nil, errors.New("Object is not a stack")
    48  	}
    49  	return stack, nil
    50  }
    51  
    52  // CreateStack wraps the Create method in a more strictly typed way
    53  func (s *StackREST) CreateStack(ctx context.Context, newStack *iv.Stack, createValidation rest.ValidateObjectFunc, options *metav1.CreateOptions) (*iv.Stack, error) {
    54  	obj, err := s.Create(ctx, newStack, createValidation, options)
    55  	if err != nil {
    56  		return nil, err
    57  	}
    58  	stack, ok := obj.(*iv.Stack)
    59  	if !ok {
    60  		return nil, errors.New("Object is not a stack")
    61  	}
    62  	return stack, nil
    63  }
    64  
    65  // StackTransform is a transformation used in UpdateStack
    66  type StackTransform func(ctx context.Context, newObj *iv.Stack, oldObj *iv.Stack) (transformedNewObj *iv.Stack, err error)
    67  
    68  // UpdateStack wraps the Update method in a more strictly typed way
    69  func (s *StackREST) UpdateStack(ctx context.Context, name string, transform StackTransform,
    70  	createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc, forceAllowCreate bool, options *metav1.UpdateOptions) (*iv.Stack, bool, error) {
    71  	updateObjectInfo := rest.DefaultUpdatedObjectInfo(nil,
    72  		func(ctx context.Context, newObj runtime.Object, oldObj runtime.Object) (transformedNewObj runtime.Object, err error) {
    73  			if newObj == nil {
    74  				newObj = oldObj.DeepCopyObject()
    75  			}
    76  			oldStack, ok := oldObj.(*iv.Stack)
    77  			if !ok {
    78  				return nil, errors.New("oldObj is not a stack")
    79  			}
    80  			newStack, ok := newObj.(*iv.Stack)
    81  			if !ok {
    82  				return nil, errors.New("newObj is not a stack")
    83  			}
    84  			return transform(ctx, newStack, oldStack)
    85  		})
    86  	obj, created, err := s.Update(ctx, name, updateObjectInfo, createValidation, updateValidation, forceAllowCreate, options)
    87  	if err != nil {
    88  		return nil, false, err
    89  	}
    90  	stack, ok := obj.(*iv.Stack)
    91  	if !ok {
    92  		return nil, false, errors.New("result is not a stack")
    93  	}
    94  	return stack, created, err
    95  }
    96  
    97  // NewStackREST return a rest store
    98  func NewStackREST(version APIVersion, scheme rest.RESTDeleteStrategy, optsGetter generic.RESTOptionsGetter, config *restclient.Config) (*StackREST, error) {
    99  	coreClient, err := corev1.NewForConfig(config)
   100  	if err != nil {
   101  		return nil, err
   102  	}
   103  	appsClient, err := appsv1.NewForConfig(config)
   104  	if err != nil {
   105  		return nil, err
   106  	}
   107  	strategy := newStackStrategy(version, scheme, coreClient, appsClient)
   108  
   109  	store := &StackREST{
   110  		genericregistry.Store{
   111  			NewFunc:                  func() runtime.Object { return &iv.Stack{} },
   112  			NewListFunc:              func() runtime.Object { return &iv.StackList{} },
   113  			PredicateFunc:            matchStack,
   114  			DefaultQualifiedResource: iv.InternalSchemeGroupVersion.WithResource("stacks").GroupResource(),
   115  
   116  			CreateStrategy: strategy,
   117  			UpdateStrategy: strategy,
   118  			DeleteStrategy: strategy,
   119  			TableConvertor: stackTableConvertor{},
   120  		},
   121  	}
   122  	options := &generic.StoreOptions{RESTOptions: optsGetter, AttrFunc: getStackAttrs}
   123  	if err := store.CompleteWithOptions(options); err != nil {
   124  		return nil, err
   125  	}
   126  	return store, nil
   127  }
   128  
   129  func getStackAttrs(obj runtime.Object) (labels.Set, fields.Set, error) {
   130  	stack, ok := obj.(*iv.Stack)
   131  	if !ok {
   132  		return nil, nil, errors.New("given object is not a Stack")
   133  	}
   134  	return labels.Set(stack.ObjectMeta.Labels), stackToSelectableFields(stack), nil
   135  }
   136  
   137  func matchStack(label labels.Selector, field fields.Selector) storage.SelectionPredicate {
   138  	return storage.SelectionPredicate{
   139  		Label:    label,
   140  		Field:    field,
   141  		GetAttrs: getStackAttrs,
   142  	}
   143  }
   144  
   145  func stackToSelectableFields(obj *iv.Stack) fields.Set {
   146  	return generic.ObjectMetaFieldsSet(&obj.ObjectMeta, true)
   147  }