replicasetlist.go 5.5 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
// 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 (
	"k8s.io/kubernetes/pkg/api"
19
	"k8s.io/kubernetes/pkg/api/unversioned"
20 21 22 23 24
	client "k8s.io/kubernetes/pkg/client/unversioned"
	"k8s.io/kubernetes/pkg/fields"
	"k8s.io/kubernetes/pkg/labels"
)

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

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

37 38 39
	// Namespace this Replica Set is in.
	Namespace string `json:"namespace"`

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

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

46 47 48
	// Number of pods that are currently running.
	PodsRunning int `json:"podsRunning"`

49 50
	// Number of pods that are pending in this Replica Set.
	PodsPending int `json:"podsPending"`
51

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

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

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

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

65 66
// Returns a list of all Replica Sets in the cluster.
func GetReplicaSetList(client *client.Client) (*ReplicaSetList, error) {
B
bryk 已提交
67 68 69 70 71
	replicaSets, err := client.ReplicationControllers(api.NamespaceAll).List(
		unversioned.ListOptions{
			LabelSelector: unversioned.LabelSelector{labels.Everything()},
			FieldSelector: unversioned.FieldSelector{fields.Everything()},
		})
72 73 74 75 76

	if err != nil {
		return nil, err
	}

B
bryk 已提交
77 78 79 80 81
	services, err := client.Services(api.NamespaceAll).List(
		unversioned.ListOptions{
			LabelSelector: unversioned.LabelSelector{labels.Everything()},
			FieldSelector: unversioned.FieldSelector{fields.Everything()},
		})
82 83 84 85 86 87 88 89 90 91 92 93 94 95

	if err != nil {
		return nil, err
	}

	return getReplicaSetList(replicaSets.Items, services.Items), nil
}

// 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.
func getReplicaSetList(
	replicaSets []api.ReplicationController, services []api.Service) *ReplicaSetList {

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

98
	for _, replicaSet := range replicaSets {
99
		var containerImages []string
100
		for _, container := range replicaSet.Spec.Template.Spec.Containers {
101 102 103
			containerImages = append(containerImages, container.Image)
		}

104
		matchingServices := getMatchingServices(services, &replicaSet)
105 106
		var internalEndpoints []Endpoint
		var externalEndpoints []Endpoint
107 108 109 110 111
		for _, service := range matchingServices {
			internalEndpoints = append(internalEndpoints,
				getInternalEndpoint(service.Name, service.Namespace, service.Spec.Ports))
			for _, externalIp := range service.Status.LoadBalancer.Ingress {
				externalEndpoints = append(externalEndpoints,
112
					getExternalEndpoint(externalIp, service.Spec.Ports))
113 114 115
			}
		}

116
		replicaSetList.ReplicaSets = append(replicaSetList.ReplicaSets, ReplicaSet{
117 118 119 120 121 122 123 124 125 126
			Name:              replicaSet.ObjectMeta.Name,
			Namespace:         replicaSet.ObjectMeta.Namespace,
			Description:       replicaSet.Annotations[DescriptionAnnotationKey],
			Labels:            replicaSet.ObjectMeta.Labels,
			PodsRunning:       replicaSet.Status.Replicas,
			PodsPending:       replicaSet.Spec.Replicas - replicaSet.Status.Replicas,
			ContainerImages:   containerImages,
			CreationTime:      replicaSet.ObjectMeta.CreationTimestamp,
			InternalEndpoints: internalEndpoints,
			ExternalEndpoints: externalEndpoints,
127 128 129
		})
	}

130 131 132 133 134 135
	return replicaSetList
}

// 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 {
B
bryk 已提交
136
	// TODO(bryk): Match namespace too.
137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161

	var matchingServices []api.Service
	for _, service := range services {
		if isServiceMatchingReplicaSet(service.Spec.Selector, replicaSet.Spec.Selector) {
			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.
func isServiceMatchingReplicaSet(serviceSelector map[string]string,
	replicaSetSpecSelector map[string]string) bool {

	// If service has no selectors, then assume it targets different Pods.
	if len(serviceSelector) == 0 {
		return false
	}
	for label, value := range serviceSelector {
		if rsValue, ok := replicaSetSpecSelector[label]; !ok || rsValue != value {
			return false
		}
	}
	return true
162
}