replicasetlist.go 6.5 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
// Copyright 2015 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package main

import (
M
Marcin Maciaszczyk 已提交
18 19
	"log"

20
	"k8s.io/kubernetes/pkg/api"
21
	"k8s.io/kubernetes/pkg/api/unversioned"
22 23 24 25 26
	client "k8s.io/kubernetes/pkg/client/unversioned"
	"k8s.io/kubernetes/pkg/fields"
	"k8s.io/kubernetes/pkg/labels"
)

27
// ReplicaSetList contains a list of Replica Sets in the cluster.
28 29 30
type ReplicaSetList struct {
	// Unordered list of Replica Sets.
	ReplicaSets []ReplicaSet `json:"replicaSets"`
31 32
}

33
// ReplicaSet (aka. Replication Controller) plus zero or more Kubernetes services that
34 35 36
// target the Replica Set.
type ReplicaSet struct {
	// Name of the Replica Set.
37 38
	Name string `json:"name"`

39 40 41
	// Namespace this Replica Set is in.
	Namespace string `json:"namespace"`

42 43 44 45 46 47
	// Human readable description of this Replica Set.
	Description string `json:"description"`

	// Label of this Replica Set.
	Labels map[string]string `json:"labels"`

48 49
	// Aggergate information about pods belonging to this repolica set.
	Pods ReplicaSetPodInfo `json:"pods"`
50

51
	// Container images of the Replica Set.
52
	ContainerImages []string `json:"containerImages"`
53

54 55
	// Time the replica set was created.
	CreationTime unversioned.Time `json:"creationTime"`
56 57

	// Internal endpoints of all Kubernetes services have the same label selector as this Replica Set.
58
	InternalEndpoints []Endpoint `json:"internalEndpoints"`
59 60

	// External endpoints of all Kubernetes services have the same label selector as this Replica Set.
61
	ExternalEndpoints []Endpoint `json:"externalEndpoints"`
62 63
}

64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
// ReplicaSetPodInfo represents aggregate information about replica set pods.
type ReplicaSetPodInfo struct {
	// Number of pods that are created.
	Curret int `json:"current"`

	// Number of pods that are desired in this Replica Set.
	Desired int `json:"desired"`

	// Number of pods that are currently running.
	Running int `json:"running"`

	// Number of pods that are currently waiting.
	Waiting int `json:"waiting"`

	// Number of pods that are failed.
	Failed int `json:"failed"`
}

// GetReplicaSetList returns a list of all Replica Sets in the cluster.
83
func GetReplicaSetList(client *client.Client) (*ReplicaSetList, error) {
M
Marcin Maciaszczyk 已提交
84 85
	log.Printf("Getting list of all replica sets in the cluster")

86 87 88 89 90 91
	listEverything := unversioned.ListOptions{
		LabelSelector: unversioned.LabelSelector{labels.Everything()},
		FieldSelector: unversioned.FieldSelector{fields.Everything()},
	}

	replicaSets, err := client.ReplicationControllers(api.NamespaceAll).List(listEverything)
92 93 94 95 96

	if err != nil {
		return nil, err
	}

97 98 99 100 101 102 103
	services, err := client.Services(api.NamespaceAll).List(listEverything)

	if err != nil {
		return nil, err
	}

	pods, err := client.Pods(api.NamespaceAll).List(listEverything)
104 105 106 107 108

	if err != nil {
		return nil, err
	}

109
	return getReplicaSetList(replicaSets.Items, services.Items, pods.Items), nil
110 111 112 113 114
}

// Returns a list of all Replica Set model objects in the cluster, based on all Kubernetes
// Replica Set and Service API objects.
// The function processes all Replica Sets API objects and finds matching Services for them.
115 116
func getReplicaSetList(replicaSets []api.ReplicationController, services []api.Service,
	pods []api.Pod) *ReplicaSetList {
117

118
	replicaSetList := &ReplicaSetList{ReplicaSets: make([]ReplicaSet, 0)}
119

120
	for _, replicaSet := range replicaSets {
121
		var containerImages []string
122
		for _, container := range replicaSet.Spec.Template.Spec.Containers {
123 124 125
			containerImages = append(containerImages, container.Image)
		}

126
		matchingServices := getMatchingServices(services, &replicaSet)
127 128
		var internalEndpoints []Endpoint
		var externalEndpoints []Endpoint
129 130 131
		for _, service := range matchingServices {
			internalEndpoints = append(internalEndpoints,
				getInternalEndpoint(service.Name, service.Namespace, service.Spec.Ports))
132
			for _, externalIP := range service.Status.LoadBalancer.Ingress {
133
				externalEndpoints = append(externalEndpoints,
134
					getExternalEndpoint(externalIP, service.Spec.Ports))
135 136 137
			}
		}

138 139
		podInfo := getReplicaSetPodInfo(&replicaSet, pods)

140
		replicaSetList.ReplicaSets = append(replicaSetList.ReplicaSets, ReplicaSet{
141 142 143 144
			Name:              replicaSet.ObjectMeta.Name,
			Namespace:         replicaSet.ObjectMeta.Namespace,
			Description:       replicaSet.Annotations[DescriptionAnnotationKey],
			Labels:            replicaSet.ObjectMeta.Labels,
145
			Pods:              podInfo,
146 147 148 149
			ContainerImages:   containerImages,
			CreationTime:      replicaSet.ObjectMeta.CreationTimestamp,
			InternalEndpoints: internalEndpoints,
			ExternalEndpoints: externalEndpoints,
150 151 152
		})
	}

153 154 155
	return replicaSetList
}

156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178
func getReplicaSetPodInfo(replicaSet *api.ReplicationController, pods []api.Pod) ReplicaSetPodInfo {
	result := ReplicaSetPodInfo{
		Curret:  replicaSet.Status.Replicas,
		Desired: replicaSet.Spec.Replicas,
	}

	for _, pod := range pods {
		if pod.ObjectMeta.Namespace == replicaSet.ObjectMeta.Namespace &&
			isLabelSelectorMatching(replicaSet.Spec.Selector, pod.ObjectMeta.Labels) {
			switch pod.Status.Phase {
			case api.PodRunning:
				result.Running++
			case api.PodPending:
				result.Waiting++
			case api.PodFailed:
				result.Failed++
			}
		}
	}

	return result
}

179 180 181 182 183 184
// Returns all services that target the same Pods (or subset) as the given Replica Set.
func getMatchingServices(services []api.Service,
	replicaSet *api.ReplicationController) []api.Service {

	var matchingServices []api.Service
	for _, service := range services {
185 186 187
		if service.ObjectMeta.Namespace == replicaSet.ObjectMeta.Namespace &&
			isLabelSelectorMatching(service.Spec.Selector, replicaSet.Spec.Selector) {

188 189 190 191 192 193 194 195
			matchingServices = append(matchingServices, service)
		}
	}
	return matchingServices
}

// Returns true when a Service with the given selector targets the same Pods (or subset) that
// a Replica Set with the given selector.
196 197
func isLabelSelectorMatching(labelSelector map[string]string,
	testedObjectLabels map[string]string) bool {
198 199

	// If service has no selectors, then assume it targets different Pods.
200
	if len(labelSelector) == 0 {
201 202
		return false
	}
203 204
	for label, value := range labelSelector {
		if rsValue, ok := testedObjectLabels[label]; !ok || rsValue != value {
205 206 207 208
			return false
		}
	}
	return true
209
}