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

     1  package registry
     2  
     3  import (
     4  	"context"
     5  	"errors"
     6  	"fmt"
     7  	"reflect"
     8  	"strings"
     9  
    10  	"github.com/docker/compose-on-kubernetes/internal/conversions"
    11  	iv "github.com/docker/compose-on-kubernetes/internal/internalversion"
    12  	"github.com/docker/compose-on-kubernetes/internal/parsing"
    13  	log "github.com/sirupsen/logrus"
    14  	genericapirequest "k8s.io/apiserver/pkg/endpoints/request"
    15  )
    16  
    17  func prepareStackOwnership() prepareStep {
    18  	return func(ctx context.Context, _, stack *iv.Stack) error {
    19  		if user, ok := genericapirequest.UserFrom(ctx); ok {
    20  			stack.Spec.Owner.UserName = user.GetName()
    21  			stack.Spec.Owner.Groups = user.GetGroups()
    22  			stack.Spec.Owner.Extra = user.GetExtra()
    23  			log.Debugf("Set stack owner to %s", stack.Spec.Owner.UserName)
    24  			return nil
    25  		}
    26  		return errors.New("can't extract owner information from request")
    27  	}
    28  }
    29  
    30  func setFieldsForV1beta1Update(oldStack, newStack *iv.Stack) {
    31  	// mark stack as dirty if composfile has been updated
    32  	// if not, avoid re-parsing the same compose file
    33  	if newStack.Spec.ComposeFile != oldStack.Spec.ComposeFile {
    34  		// composefile was changed, drop the stack (will be reconciled just after)
    35  		newStack.Spec.Stack = nil
    36  	} else {
    37  		// The update likely dropped v1beta2 fields
    38  		newStack.Spec.Stack = oldStack.Spec.Stack
    39  	}
    40  }
    41  func setFieldsForV1beta2Update(oldStack, newStack *iv.Stack) {
    42  	// check if composefile is still up to date
    43  	// if the stack itself has been updated, we add a comment at compose file head
    44  	// warning the user that it is not in sync anymore with the structured stack
    45  	newStack.Spec.ComposeFile = oldStack.Spec.ComposeFile
    46  	specSame := reflect.DeepEqual(newStack.Spec.Stack, oldStack.Spec.Stack)
    47  	if !specSame && !strings.HasPrefix(newStack.Spec.ComposeFile, composeOutOfDate) && newStack.Spec.ComposeFile != "" {
    48  		newStack.Spec.ComposeFile = composeOutOfDate + newStack.Spec.ComposeFile
    49  	}
    50  }
    51  
    52  type fieldUpdatesFunc func(oldStack, newStack *iv.Stack)
    53  
    54  var fieldUpdatesFuncs = map[APIVersion]fieldUpdatesFunc{
    55  	APIV1beta1: setFieldsForV1beta1Update,
    56  	APIV1beta2: setFieldsForV1beta2Update,
    57  }
    58  
    59  func prepareFieldsForUpdate(version APIVersion) prepareStep {
    60  	if f, ok := fieldUpdatesFuncs[version]; ok {
    61  		return func(_ context.Context, oldStack, newStack *iv.Stack) error {
    62  			if oldStack != nil {
    63  				f(oldStack, newStack)
    64  			}
    65  			return nil
    66  		}
    67  	}
    68  	return func(_ context.Context, _, _ *iv.Stack) error {
    69  		return fmt.Errorf("unknown APIVersion %q", version)
    70  	}
    71  
    72  }
    73  
    74  func prepareStackFromComposefile(relaxedParsing bool) prepareStep {
    75  	return func(_ context.Context, _, newStack *iv.Stack) error {
    76  		if newStack.Spec.Stack == nil {
    77  			// creation or update from composefile subresource or from v1beta1 API
    78  			composeConfig, err := parsing.LoadStackData([]byte(newStack.Spec.ComposeFile), nil)
    79  			if err != nil {
    80  				if relaxedParsing {
    81  					newStack.Status = &iv.StackStatus{
    82  						Phase:   iv.StackFailure,
    83  						Message: fmt.Sprintf("parsing error: %s", err),
    84  					}
    85  					return nil
    86  				}
    87  				return fmt.Errorf("parsing error: %s", err)
    88  			}
    89  			newStack.Spec.Stack = conversions.FromComposeConfig(composeConfig)
    90  		}
    91  		return nil
    92  	}
    93  }