// Returns a list of all Daemon Set model objects in the cluster, based on all Kubernetes // Daemon Set and Service API objects. // The function processes all Daemon Set API objects and finds matching Services for them. func getDaemonSetList(daemonSets []extensions.DaemonSet, pods []api.Pod, events []api.Event) *DaemonSetList { daemonSetList := &DaemonSetList{DaemonSets: make([]DaemonSet, 0)} for _, daemonSet := range daemonSets { matchingPods := make([]api.Pod, 0) for _, pod := range pods { if pod.ObjectMeta.Namespace == daemonSet.ObjectMeta.Namespace && common.IsLabelSelectorMatching(pod.ObjectMeta.Labels, daemonSet.Spec.Selector) { matchingPods = append(matchingPods, pod) } } podInfo := getDaemonSetPodInfo(&daemonSet, matchingPods) podErrors := event.GetPodsEventWarnings(events, matchingPods) podInfo.Warnings = podErrors daemonSetList.DaemonSets = append(daemonSetList.DaemonSets, DaemonSet{ ObjectMeta: common.NewObjectMeta(daemonSet.ObjectMeta), TypeMeta: common.NewTypeMeta(common.ResourceKindDaemonSet), Pods: podInfo, ContainerImages: common.GetContainerImages(&daemonSet.Spec.Template.Spec), }) } return daemonSetList }
func getDeploymentList(deployments []extensions.Deployment, pods []api.Pod, events []api.Event) *DeploymentList { deploymentList := &DeploymentList{ Deployments: make([]Deployment, 0), } for _, deployment := range deployments { matchingPods := common.FilterNamespacedPodsBySelector(pods, deployment.ObjectMeta.Namespace, deployment.Spec.Selector.MatchLabels) podInfo := getPodInfo(&deployment, matchingPods) podInfo.Warnings = event.GetPodsEventWarnings(events, matchingPods) deploymentList.Deployments = append(deploymentList.Deployments, Deployment{ ObjectMeta: common.NewObjectMeta(deployment.ObjectMeta), TypeMeta: common.NewTypeMeta(common.ResourceKindDeployment), ContainerImages: common.GetContainerImages(&deployment.Spec.Template.Spec), Pods: podInfo, }) } return deploymentList }
// Returns a list of all Replication Controller model objects in the cluster, based on all Kubernetes // Replication Controller and Service API objects. func getReplicationControllerList(replicationControllers []api.ReplicationController, pods []api.Pod, events []api.Event) *ReplicationControllerList { replicationControllerList := &ReplicationControllerList{ ReplicationControllers: make([]ReplicationController, 0), } for _, replicationController := range replicationControllers { matchingPods := make([]api.Pod, 0) for _, pod := range pods { if pod.ObjectMeta.Namespace == replicationController.ObjectMeta.Namespace && common.IsSelectorMatching(replicationController.Spec.Selector, pod.ObjectMeta.Labels) { matchingPods = append(matchingPods, pod) } } podInfo := getReplicationPodInfo(&replicationController, matchingPods) podErrors := event.GetPodsEventWarnings(events, matchingPods) podInfo.Warnings = podErrors replicationControllerList.ReplicationControllers = append(replicationControllerList.ReplicationControllers, ReplicationController{ ObjectMeta: common.NewObjectMeta(replicationController.ObjectMeta), TypeMeta: common.NewTypeMeta(common.ResourceKindReplicationController), Pods: podInfo, ContainerImages: common.GetContainerImages(&replicationController.Spec.Template.Spec), }) } return replicationControllerList }
func ToPetSet(petSet *apps.PetSet, podInfo *common.PodInfo) PetSet { return PetSet{ ObjectMeta: common.NewObjectMeta(petSet.ObjectMeta), TypeMeta: common.NewTypeMeta(common.ResourceKindPetSet), ContainerImages: common.GetContainerImages(&petSet.Spec.Template.Spec), Pods: *podInfo, } }
func ToReplicaSet(replicaSet *extensions.ReplicaSet, podInfo *common.PodInfo) ReplicaSet { return ReplicaSet{ ObjectMeta: common.NewObjectMeta(replicaSet.ObjectMeta), TypeMeta: common.NewTypeMeta(common.ResourceKindReplicaSet), ContainerImages: common.GetContainerImages(&replicaSet.Spec.Template.Spec), Pods: *podInfo, } }
func ToJob(job *batch.Job, podInfo *common.PodInfo) Job { return Job{ ObjectMeta: common.NewObjectMeta(job.ObjectMeta), TypeMeta: common.NewTypeMeta(common.ResourceKindJob), ContainerImages: common.GetContainerImages(&job.Spec.Template.Spec), Pods: *podInfo, } }
// ToServiceDetail returns api service object based on kubernetes service object func ToServiceDetail(service *api.Service) ServiceDetail { return ServiceDetail{ ObjectMeta: common.NewObjectMeta(service.ObjectMeta), TypeMeta: common.NewTypeMeta(common.ResourceKindService), InternalEndpoint: common.GetInternalEndpoint(service.Name, service.Namespace, service.Spec.Ports), ExternalEndpoints: common.GetExternalEndpoints(service), Selector: service.Spec.Selector, ClusterIP: service.Spec.ClusterIP, Type: service.Spec.Type, } }
func ToPod(pod *api.Pod, metrics *MetricsByPod) Pod { podDetail := Pod{ ObjectMeta: common.NewObjectMeta(pod.ObjectMeta), TypeMeta: common.NewTypeMeta(common.ResourceKindPod), PodPhase: pod.Status.Phase, PodIP: pod.Status.PodIP, RestartCount: getRestartCount(*pod), } if metrics != nil && metrics.MetricsMap[pod.Namespace] != nil { metric := metrics.MetricsMap[pod.Namespace][pod.Name] podDetail.Metrics = &metric } return podDetail }
func getReplicaSetDetail(replicaSet *extensions.ReplicaSet, heapsterClient client.HeapsterClient, events *common.EventList, pods []api.Pod) ReplicaSetDetail { matchingPods := common.FilterNamespacedPodsByLabelSelector(pods, replicaSet.ObjectMeta.Namespace, replicaSet.Spec.Selector) podInfo := getPodInfo(replicaSet, matchingPods) return ReplicaSetDetail{ ObjectMeta: common.NewObjectMeta(replicaSet.ObjectMeta), TypeMeta: common.NewTypeMeta(common.ResourceKindReplicaSet), ContainerImages: common.GetContainerImages(&replicaSet.Spec.Template.Spec), PodInfo: podInfo, PodList: pod.CreatePodList(matchingPods, heapsterClient), EventList: *events, } }
// AppendEvents appends events from source slice to target events representation. func AppendEvents(source []api.Event, target common.EventList) common.EventList { for _, event := range source { target.Events = append(target.Events, common.Event{ ObjectMeta: common.NewObjectMeta(event.ObjectMeta), TypeMeta: common.NewTypeMeta(common.ResourceKindEvent), Message: event.Message, SourceComponent: event.Source.Component, SourceHost: event.Source.Host, SubObject: event.InvolvedObject.FieldPath, Count: event.Count, FirstSeen: event.FirstTimestamp, LastSeen: event.LastTimestamp, Reason: event.Reason, Type: event.Type, }) } return target }
func getPetSetDetail(petSet *apps.PetSet, heapsterClient client.HeapsterClient, events *common.EventList, pods []api.Pod) PetSetDetail { matchingPods := common.FilterNamespacedPodsByLabelSelector(pods, petSet.ObjectMeta.Namespace, petSet.Spec.Selector) podInfo := common.GetPodInfo(int32(petSet.Status.Replicas), int32(petSet.Spec.Replicas), matchingPods) return PetSetDetail{ ObjectMeta: common.NewObjectMeta(petSet.ObjectMeta), TypeMeta: common.NewTypeMeta(common.ResourceKindPetSet), ContainerImages: common.GetContainerImages(&petSet.Spec.Template.Spec), PodInfo: podInfo, PodList: pod.CreatePodList(matchingPods, heapsterClient), EventList: *events, } }
// GetReplicationControllerDetail returns detailed information about the given replication // controller in the given namespace. func GetReplicationControllerDetail(client k8sClient.Interface, heapsterClient client.HeapsterClient, namespace, name string) (*ReplicationControllerDetail, error) { log.Printf("Getting details of %s replication controller in %s namespace", name, namespace) replicationControllerWithPods, err := getRawReplicationControllerWithPods(client, namespace, name) if err != nil { return nil, err } replicationController := replicationControllerWithPods.ReplicationController pods := replicationControllerWithPods.Pods services, err := client.Services(namespace).List(api.ListOptions{ LabelSelector: labels.Everything(), FieldSelector: fields.Everything(), }) if err != nil { return nil, err } replicationControllerDetail := &ReplicationControllerDetail{ ObjectMeta: common.NewObjectMeta(replicationController.ObjectMeta), TypeMeta: common.NewTypeMeta(common.ResourceKindReplicationController), LabelSelector: replicationController.Spec.Selector, PodInfo: getReplicationPodInfo(replicationController, pods.Items), ServiceList: resourceService.ServiceList{Services: make([]resourceService.Service, 0)}, } matchingServices := getMatchingServices(services.Items, replicationController) for _, service := range matchingServices { replicationControllerDetail.ServiceList.Services = append( replicationControllerDetail.ServiceList.Services, resourceService.ToService(&service)) } for _, container := range replicationController.Spec.Template.Spec.Containers { replicationControllerDetail.ContainerImages = append(replicationControllerDetail.ContainerImages, container.Image) } replicationControllerDetail.Pods = pod.CreatePodList(pods.Items, heapsterClient) return replicationControllerDetail, nil }
// Returns detailed information about the given daemon set in the given namespace. func GetDaemonSetDetail(client k8sClient.Interface, heapsterClient client.HeapsterClient, namespace, name string) (*DaemonSetDetail, error) { log.Printf("Getting details of %s daemon set in %s namespace", name, namespace) daemonSetWithPods, err := getRawDaemonSetWithPods(client, namespace, name) if err != nil { return nil, err } daemonSet := daemonSetWithPods.DaemonSet pods := daemonSetWithPods.Pods services, err := client.Services(namespace).List(api.ListOptions{ LabelSelector: labels.Everything(), FieldSelector: fields.Everything(), }) if err != nil { return nil, err } daemonSetDetail := &DaemonSetDetail{ ObjectMeta: common.NewObjectMeta(daemonSet.ObjectMeta), TypeMeta: common.NewTypeMeta(common.ResourceKindDaemonSet), LabelSelector: daemonSet.Spec.Selector, PodInfo: getDaemonSetPodInfo(daemonSet, pods.Items), ServiceList: resourceService.ServiceList{Services: make([]resourceService.Service, 0)}, } matchingServices := getMatchingServicesforDS(services.Items, daemonSet) for _, service := range matchingServices { daemonSetDetail.ServiceList.Services = append(daemonSetDetail.ServiceList.Services, resourceService.ToService(&service)) } for _, container := range daemonSet.Spec.Template.Spec.Containers { daemonSetDetail.ContainerImages = append(daemonSetDetail.ContainerImages, container.Image) } daemonSetDetail.Pods = pod.CreatePodList(pods.Items, heapsterClient) return daemonSetDetail, nil }
func toNodeDetail(node api.Node, pods pod.PodList, eventList common.EventList, allocatedResources NodeAllocatedResources) NodeDetail { return NodeDetail{ ObjectMeta: common.NewObjectMeta(node.ObjectMeta), TypeMeta: common.NewTypeMeta(common.ResourceKindNode), Phase: node.Status.Phase, ExternalID: node.Spec.ExternalID, ProviderID: node.Spec.ProviderID, PodCIDR: node.Spec.PodCIDR, Unschedulable: node.Spec.Unschedulable, NodeInfo: node.Status.NodeInfo, Conditions: node.Status.Conditions, ContainerImages: getContainerImages(node), PodList: pods, EventList: eventList, AllocatedResources: allocatedResources, } }
func getJobDetail(job *batch.Job, heapsterClient client.HeapsterClient, events *common.EventList, pods []api.Pod) JobDetail { matchingPods := common.FilterNamespacedPodsBySelector(pods, job.ObjectMeta.Namespace, job.Spec.Selector.MatchLabels) podInfo := getPodInfo(job, matchingPods) return JobDetail{ ObjectMeta: common.NewObjectMeta(job.ObjectMeta), TypeMeta: common.NewTypeMeta(common.ResourceKindJob), ContainerImages: common.GetContainerImages(&job.Spec.Template.Spec), PodInfo: podInfo, PodList: pod.CreatePodList(matchingPods, heapsterClient), EventList: *events, Parallelism: job.Spec.Parallelism, Completions: job.Spec.Completions, } }
func getDeploymentDetail(deployment *extensions.Deployment, oldRs []*extensions.ReplicaSet, newRs *extensions.ReplicaSet, pods []api.Pod, events *common.EventList, rawEvents []api.Event) *DeploymentDetail { var newReplicaSet replicaset.ReplicaSet if newRs != nil { newRsPodInfo := common.GetPodInfo(newRs.Status.Replicas, newRs.Spec.Replicas, pods) newReplicaSet = replicaset.ToReplicaSet(newRs, &newRsPodInfo) } oldReplicaSets := make([]extensions.ReplicaSet, len(oldRs)) for i, replicaSet := range oldRs { oldReplicaSets[i] = *replicaSet } oldReplicaSetList := replicaset.ToReplicaSetList(oldReplicaSets, pods, rawEvents) var rollingUpdateStrategy *RollingUpdateStrategy if deployment.Spec.Strategy.RollingUpdate != nil { rollingUpdateStrategy = &RollingUpdateStrategy{ MaxSurge: deployment.Spec.Strategy.RollingUpdate.MaxSurge.IntValue(), MaxUnavailable: deployment.Spec.Strategy.RollingUpdate.MaxUnavailable.IntValue(), } } return &DeploymentDetail{ ObjectMeta: common.NewObjectMeta(deployment.ObjectMeta), TypeMeta: common.NewTypeMeta(common.ResourceKindDeployment), Selector: deployment.Spec.Selector.MatchLabels, StatusInfo: GetStatusInfo(&deployment.Status), Strategy: deployment.Spec.Strategy.Type, MinReadySeconds: deployment.Spec.MinReadySeconds, RollingUpdateStrategy: rollingUpdateStrategy, OldReplicaSetList: *oldReplicaSetList, NewReplicaSet: newReplicaSet, RevisionHistoryLimit: deployment.Spec.RevisionHistoryLimit, EventList: *events, } }
func toNode(node api.Node) Node { return Node{ ObjectMeta: common.NewObjectMeta(node.ObjectMeta), TypeMeta: common.NewTypeMeta(common.ResourceKindNode), } }
func TestGetDeploymentDetail(t *testing.T) { podList := &api.PodList{} eventList := &api.EventList{} deployment := &extensions.Deployment{ ObjectMeta: api.ObjectMeta{ Name: "test-name", Labels: map[string]string{"track": "beta"}, }, Spec: extensions.DeploymentSpec{ Selector: &unversioned.LabelSelector{MatchLabels: map[string]string{"foo": "bar"}}, Replicas: 4, MinReadySeconds: 5, Strategy: extensions.DeploymentStrategy{ Type: extensions.RollingUpdateDeploymentStrategyType, RollingUpdate: &extensions.RollingUpdateDeployment{ MaxSurge: intstr.FromInt(1), MaxUnavailable: intstr.FromString("1"), }, }, Template: api.PodTemplateSpec{ ObjectMeta: api.ObjectMeta{ Name: "test-pod-name", Labels: map[string]string{"track": "beta"}, }, }, }, Status: extensions.DeploymentStatus{ Replicas: 4, UpdatedReplicas: 2, AvailableReplicas: 3, UnavailableReplicas: 1, }, } podTemplateSpec := deploymentutil.GetNewReplicaSetTemplate(deployment) newReplicaSet := extensions.ReplicaSet{ ObjectMeta: api.ObjectMeta{ Name: "replica-set-1", Namespace: "test-namespace", }, Spec: extensions.ReplicaSetSpec{ Template: podTemplateSpec, }, } replicaSetList := &extensions.ReplicaSetList{ Items: []extensions.ReplicaSet{ newReplicaSet, { ObjectMeta: api.ObjectMeta{ Name: "replica-set-2", Namespace: "test-namespace", }, }, }, } cases := []struct { namespace, name string expectedActions []string deployment *extensions.Deployment expected *DeploymentDetail }{ { "test-namespace", "test-name", []string{"get", "list", "list", "list"}, deployment, &DeploymentDetail{ ObjectMeta: common.ObjectMeta{ Name: "test-name", Labels: map[string]string{"track": "beta"}, }, TypeMeta: common.TypeMeta{Kind: common.ResourceKindDeployment}, Selector: map[string]string{"foo": "bar"}, StatusInfo: StatusInfo{ Replicas: 4, Updated: 2, Available: 3, Unavailable: 1, }, Strategy: "RollingUpdate", MinReadySeconds: 5, RollingUpdateStrategy: &RollingUpdateStrategy{ MaxSurge: 1, MaxUnavailable: 1, }, OldReplicaSetList: replicaset.ReplicaSetList{ReplicaSets: []replicaset.ReplicaSet{}}, NewReplicaSet: replicaset.ReplicaSet{ ObjectMeta: common.NewObjectMeta(newReplicaSet.ObjectMeta), TypeMeta: common.NewTypeMeta(common.ResourceKindReplicaSet), Pods: common.PodInfo{Warnings: []common.Event{}}, }, EventList: common.EventList{ Namespace: "test-namespace", Events: []common.Event{}, }, }, }, } for _, c := range cases { fakeClient := testclient.NewSimpleFake(c.deployment, replicaSetList, podList, eventList) actual, _ := GetDeploymentDetail(fakeClient, c.namespace, c.name) actions := fakeClient.Actions() if len(actions) != len(c.expectedActions) { t.Errorf("Unexpected actions: %v, expected %d actions got %d", actions, len(c.expectedActions), len(actions)) continue } for i, verb := range c.expectedActions { if actions[i].GetVerb() != verb { t.Errorf("Unexpected action: %+v, expected %s", actions[i], verb) } } if !reflect.DeepEqual(actual, c.expected) { t.Errorf("GetDeploymentDetail(client, namespace, name) == \ngot: %#v, \nexpected %#v", actual, c.expected) } } }