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 }