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

     1  package controller
     2  
     3  import (
     4  	"github.com/docker/compose-on-kubernetes/api/compose/latest"
     5  	"github.com/docker/compose-on-kubernetes/api/labels"
     6  	"github.com/docker/compose-on-kubernetes/internal/stackresources"
     7  	"github.com/pkg/errors"
     8  	log "github.com/sirupsen/logrus"
     9  	appstypes "k8s.io/api/apps/v1"
    10  	coretypes "k8s.io/api/core/v1"
    11  	"k8s.io/apimachinery/pkg/api/meta"
    12  )
    13  
    14  // NameAndNamespace is a name/namespace pair
    15  type NameAndNamespace struct {
    16  	Namespace string
    17  	Name      string
    18  }
    19  
    20  func (n *NameAndNamespace) objKey() string {
    21  	return stackresources.ObjKey(n.Namespace, n.Name)
    22  }
    23  
    24  func extractStackNameAndNamespace(obj interface{}) (NameAndNamespace, error) {
    25  	if stack, ok := obj.(*latest.Stack); ok {
    26  		return NameAndNamespace{Name: stack.Name, Namespace: stack.Namespace}, nil
    27  	}
    28  	m, err := meta.Accessor(obj)
    29  	if err != nil {
    30  		return NameAndNamespace{}, err
    31  	}
    32  	lbls := m.GetLabels()
    33  	if lbls == nil {
    34  		return NameAndNamespace{}, errors.New("resource is not owned by a stack")
    35  	}
    36  	stackName, ok := lbls[labels.ForStackName]
    37  	if !ok {
    38  		return NameAndNamespace{}, errors.New("resource is not owned by a stack")
    39  	}
    40  	namespace := m.GetNamespace()
    41  	return NameAndNamespace{Name: stackName, Namespace: namespace}, nil
    42  }
    43  
    44  func generateStatus(stack *latest.Stack, resources []interface{}) latest.StackStatus {
    45  	log.Debugf("Generating status for stack %s/%s", stack.Namespace, stack.Name)
    46  	remainingNames := make(map[string]struct{})
    47  	for _, svc := range stack.Spec.Services {
    48  		remainingNames[svc.Name] = struct{}{}
    49  	}
    50  	for _, r := range resources {
    51  		switch v := r.(type) {
    52  		case *appstypes.Deployment:
    53  			desired := int32(1)
    54  			if v.Spec.Replicas != nil {
    55  				desired = *v.Spec.Replicas
    56  			}
    57  			if desired == v.Status.ReadyReplicas {
    58  				delete(remainingNames, v.Name)
    59  			}
    60  			log.Debugf("Deployment %s has %d/%d", v.Name, v.Status.ReadyReplicas, desired)
    61  		case *appstypes.StatefulSet:
    62  			desired := int32(1)
    63  			if v.Spec.Replicas != nil {
    64  				desired = *v.Spec.Replicas
    65  			}
    66  			if desired == v.Status.ReadyReplicas {
    67  				delete(remainingNames, v.Name)
    68  			}
    69  			log.Debugf("Statefulset %s has %d/%d", v.Name, v.Status.ReadyReplicas, desired)
    70  		case *appstypes.DaemonSet:
    71  			if v.Status.NumberUnavailable == 0 {
    72  				delete(remainingNames, v.Name)
    73  			}
    74  			log.Debugf("Daemonset %s has %d unavailable", v.Name, v.Status.NumberUnavailable)
    75  		case *coretypes.Service:
    76  			// ignore
    77  		default:
    78  			log.Warnf("Unexpected type %T", v)
    79  		}
    80  	}
    81  	if len(remainingNames) != 0 {
    82  		log.Debugf("Services %v have not been seen", remainingNames)
    83  		return statusProgressing()
    84  	}
    85  	log.Debugf("Stack is available")
    86  	return statusAvailable()
    87  }
    88  
    89  func statusAvailable() latest.StackStatus {
    90  	return latest.StackStatus{
    91  		Phase:   latest.StackAvailable,
    92  		Message: "Stack is started",
    93  	}
    94  }
    95  
    96  func byStackIndexer(obj interface{}) ([]string, error) {
    97  	m, err := meta.Accessor(obj)
    98  	if err != nil {
    99  		return nil, err
   100  	}
   101  	lbls := m.GetLabels()
   102  	if lbls == nil {
   103  		return []string{}, nil
   104  	}
   105  	stackName, ok := lbls[labels.ForStackName]
   106  	if !ok {
   107  		return []string{}, nil
   108  	}
   109  	namespace := m.GetNamespace()
   110  	if namespace == "" {
   111  		return []string{stackName}, nil
   112  	}
   113  	return []string{stackresources.ObjKey(namespace, stackName)}, nil
   114  }