github.com/timstclair/heapster@v0.20.0-alpha1/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/deployment/deployment.go (about)

     1  /*
     2  Copyright 2015 The Kubernetes Authors All rights reserved.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package deployment
    18  
    19  import (
    20  	"fmt"
    21  	"hash/adler32"
    22  
    23  	"k8s.io/kubernetes/pkg/api"
    24  	"k8s.io/kubernetes/pkg/apis/extensions"
    25  	client "k8s.io/kubernetes/pkg/client/unversioned"
    26  	"k8s.io/kubernetes/pkg/fields"
    27  	"k8s.io/kubernetes/pkg/labels"
    28  	"k8s.io/kubernetes/pkg/util"
    29  )
    30  
    31  // Returns the old RCs targetted by the given Deployment.
    32  func GetOldRCs(deployment extensions.Deployment, c client.Interface) ([]*api.ReplicationController, error) {
    33  	namespace := deployment.ObjectMeta.Namespace
    34  	// 1. Find all pods whose labels match deployment.Spec.Selector
    35  	podList, err := c.Pods(namespace).List(labels.SelectorFromSet(deployment.Spec.Selector), fields.Everything())
    36  	if err != nil {
    37  		return nil, fmt.Errorf("error listing pods: %v", err)
    38  	}
    39  	// 2. Find the corresponding RCs for pods in podList.
    40  	// TODO: Right now we list all RCs and then filter. We should add an API for this.
    41  	oldRCs := map[string]api.ReplicationController{}
    42  	rcList, err := c.ReplicationControllers(namespace).List(labels.Everything(), fields.Everything())
    43  	if err != nil {
    44  		return nil, fmt.Errorf("error listing replication controllers: %v", err)
    45  	}
    46  	newRCTemplate := GetNewRCTemplate(deployment)
    47  	for _, pod := range podList.Items {
    48  		podLabelsSelector := labels.Set(pod.ObjectMeta.Labels)
    49  		for _, rc := range rcList.Items {
    50  			rcLabelsSelector := labels.SelectorFromSet(rc.Spec.Selector)
    51  			if rcLabelsSelector.Matches(podLabelsSelector) {
    52  				// Filter out RC that has the same pod template spec as the deployment - that is the new RC.
    53  				if api.Semantic.DeepEqual(rc.Spec.Template, &newRCTemplate) {
    54  					continue
    55  				}
    56  				oldRCs[rc.ObjectMeta.Name] = rc
    57  			}
    58  		}
    59  	}
    60  	requiredRCs := []*api.ReplicationController{}
    61  	for _, value := range oldRCs {
    62  		requiredRCs = append(requiredRCs, &value)
    63  	}
    64  	return requiredRCs, nil
    65  }
    66  
    67  // Returns an RC that matches the intent of the given deployment.
    68  // Returns nil if the new RC doesnt exist yet.
    69  func GetNewRC(deployment extensions.Deployment, c client.Interface) (*api.ReplicationController, error) {
    70  	namespace := deployment.ObjectMeta.Namespace
    71  	rcList, err := c.ReplicationControllers(namespace).List(labels.Everything(), fields.Everything())
    72  	if err != nil {
    73  		return nil, fmt.Errorf("error listing replication controllers: %v", err)
    74  	}
    75  	newRCTemplate := GetNewRCTemplate(deployment)
    76  
    77  	for _, rc := range rcList.Items {
    78  		if api.Semantic.DeepEqual(rc.Spec.Template, &newRCTemplate) {
    79  			// This is the new RC.
    80  			return &rc, nil
    81  		}
    82  	}
    83  	// new RC does not exist.
    84  	return nil, nil
    85  }
    86  
    87  // Returns the desired PodTemplateSpec for the new RC corresponding to the given RC.
    88  func GetNewRCTemplate(deployment extensions.Deployment) api.PodTemplateSpec {
    89  	// newRC will have the same template as in deployment spec, plus a unique label in some cases.
    90  	newRCTemplate := api.PodTemplateSpec{
    91  		ObjectMeta: deployment.Spec.Template.ObjectMeta,
    92  		Spec:       deployment.Spec.Template.Spec,
    93  	}
    94  	newRCTemplate.ObjectMeta.Labels = CloneAndAddLabel(
    95  		deployment.Spec.Template.ObjectMeta.Labels,
    96  		deployment.Spec.UniqueLabelKey,
    97  		GetPodTemplateSpecHash(newRCTemplate))
    98  	return newRCTemplate
    99  }
   100  
   101  // Clones the given map and returns a new map with the given key and value added.
   102  // Returns the given map, if labelKey is empty.
   103  func CloneAndAddLabel(labels map[string]string, labelKey string, labelValue uint32) map[string]string {
   104  	if labelKey == "" {
   105  		// Dont need to add a label.
   106  		return labels
   107  	}
   108  	// Clone.
   109  	newLabels := map[string]string{}
   110  	for key, value := range labels {
   111  		newLabels[key] = value
   112  	}
   113  	newLabels[labelKey] = fmt.Sprintf("%d", labelValue)
   114  	return newLabels
   115  }
   116  
   117  func GetPodTemplateSpecHash(template api.PodTemplateSpec) uint32 {
   118  	podTemplateSpecHasher := adler32.New()
   119  	util.DeepHashObject(podTemplateSpecHasher, template)
   120  	return podTemplateSpecHasher.Sum32()
   121  }
   122  
   123  // Returns the sum of Replicas of the given replication controllers.
   124  func GetReplicaCountForRCs(replicationControllers []*api.ReplicationController) int {
   125  	totalReplicaCount := 0
   126  	for _, rc := range replicationControllers {
   127  		totalReplicaCount += rc.Spec.Replicas
   128  	}
   129  	return totalReplicaCount
   130  }
   131  
   132  // Returns the number of available pods corresponding to the given RCs.
   133  func GetAvailablePodsForRCs(c client.Interface, rcs []*api.ReplicationController) (int, error) {
   134  	// TODO: Use MinReadySeconds once https://github.com/kubernetes/kubernetes/pull/12894 is merged.
   135  	allPods, err := getPodsForRCs(c, rcs)
   136  	if err != nil {
   137  		return 0, err
   138  	}
   139  	readyPodCount := 0
   140  	for _, pod := range allPods {
   141  		if api.IsPodReady(&pod) {
   142  			readyPodCount++
   143  		}
   144  	}
   145  	return readyPodCount, nil
   146  }
   147  
   148  func getPodsForRCs(c client.Interface, replicationControllers []*api.ReplicationController) ([]api.Pod, error) {
   149  	allPods := []api.Pod{}
   150  	for _, rc := range replicationControllers {
   151  		podList, err := c.Pods(rc.ObjectMeta.Namespace).List(labels.SelectorFromSet(rc.Spec.Selector), fields.Everything())
   152  		if err != nil {
   153  			return allPods, fmt.Errorf("error listing pods: %v", err)
   154  		}
   155  		allPods = append(allPods, podList.Items...)
   156  	}
   157  	return allPods, nil
   158  }