in controllers/solrcloud_controller.go [805:932]
func createCloudStatus(solrCloud *solrv1beta1.SolrCloud,
newStatus *solrv1beta1.SolrCloudStatus, statefulSetStatus appsv1.StatefulSetStatus, podSelector labels.Selector,
podList []corev1.Pod) (outOfDatePods util.OutOfDatePodSegmentation, availableUpdatedPodCount int, shouldRequeue bool, err error) {
var otherVersions []string
nodeNames := make([]string, len(podList))
nodeStatusMap := map[string]solrv1beta1.SolrNodeStatus{}
newStatus.Replicas = statefulSetStatus.Replicas
newStatus.UpToDateNodes = int32(0)
newStatus.ReadyReplicas = int32(0)
newStatus.PodSelector = podSelector.String()
backupReposAvailable := make(map[string]bool, len(solrCloud.Spec.BackupRepositories))
for _, repo := range solrCloud.Spec.BackupRepositories {
backupReposAvailable[repo.Name] = false
}
for podIdx, p := range podList {
nodeNames[podIdx] = p.Name
nodeStatus := solrv1beta1.SolrNodeStatus{}
nodeStatus.Name = p.Name
nodeStatus.NodeName = p.Spec.NodeName
nodeStatus.InternalAddress = solrCloud.UrlScheme(false) + "://" + solrCloud.InternalNodeUrl(nodeStatus.Name, true)
if solrCloud.Spec.SolrAddressability.External != nil && !solrCloud.Spec.SolrAddressability.External.HideNodes {
nodeStatus.ExternalAddress = solrCloud.UrlScheme(true) + "://" + solrCloud.ExternalNodeUrl(nodeStatus.Name, solrCloud.Spec.SolrAddressability.External.DomainName, true)
}
if len(p.Status.ContainerStatuses) > 0 {
// The first container should always be running solr
nodeStatus.Version = solrv1beta1.ImageVersion(p.Spec.Containers[0].Image)
if nodeStatus.Version != solrCloud.Spec.SolrImage.Tag {
otherVersions = append(otherVersions, nodeStatus.Version)
}
}
// Check whether the node is considered "ready" by kubernetes
nodeStatus.Ready = false
nodeStatus.ScheduledForDeletion = false
podIsScheduledForUpdate := false
for _, condition := range p.Status.Conditions {
if condition.Type == corev1.PodReady {
nodeStatus.Ready = condition.Status == corev1.ConditionTrue
} else if condition.Type == util.SolrIsNotStoppedReadinessCondition {
nodeStatus.ScheduledForDeletion = condition.Status == corev1.ConditionFalse
podIsScheduledForUpdate = nodeStatus.ScheduledForDeletion && condition.Reason == string(PodUpdate)
}
}
if nodeStatus.Ready {
newStatus.ReadyReplicas += 1
}
// Merge BackupRepository availability for this pod
backupReposAvailableForPod := util.GetAvailableBackupRepos(&p)
for repo, availableSoFar := range backupReposAvailable {
backupReposAvailable[repo] = (availableSoFar || podIdx == 0) && backupReposAvailableForPod[repo]
}
// A pod is out of date if it's revision label is not equal to the statefulSetStatus' updateRevision.
// Assume the pod is up-to-date if we don't have an updateRevision from the statefulSet status.
// This should only happen when the statefulSet has just been created, so it's not a big deal.
// NOTE: This is usually because the statefulSet status wasn't fetched, not because the fetched updateRevision
// is empty.
updateRevision := statefulSetStatus.UpdateRevision
nodeStatus.SpecUpToDate = updateRevision == "" || p.Labels["controller-revision-hash"] == updateRevision
if nodeStatus.SpecUpToDate {
newStatus.UpToDateNodes += 1
if nodeStatus.Ready {
// If the pod is up-to-date and is available, increase the counter
availableUpdatedPodCount += 1
}
} else {
containerNotStarted := false
if !nodeStatus.Ready {
containerNotStarted = true
// Gather whether the solr container has started or not.
// If it hasn't, then the pod can safely be deleted irrespective of maxNodesUnavailable.
// This is useful for podTemplate updates that override pod specs that failed to start, such as containers with images that do not exist.
for _, containerStatus := range p.Status.ContainerStatuses {
if containerStatus.Name == util.SolrNodeContainer {
containerNotStarted = containerStatus.Started == nil || !*containerStatus.Started
}
}
}
if podIsScheduledForUpdate {
outOfDatePods.ScheduledForDeletion = append(outOfDatePods.ScheduledForDeletion, p)
} else if containerNotStarted {
outOfDatePods.NotStarted = append(outOfDatePods.NotStarted, p)
} else {
outOfDatePods.Running = append(outOfDatePods.Running, p)
}
}
nodeStatusMap[nodeStatus.Name] = nodeStatus
}
sort.Strings(nodeNames)
newStatus.SolrNodes = make([]solrv1beta1.SolrNodeStatus, len(nodeNames))
for idx, nodeName := range nodeNames {
newStatus.SolrNodes[idx] = nodeStatusMap[nodeName]
}
if len(backupReposAvailable) > 0 {
newStatus.BackupRepositoriesAvailable = backupReposAvailable
allPodsBackupReady := len(backupReposAvailable) > 0
for _, backupRepo := range solrCloud.Spec.BackupRepositories {
allPodsBackupReady = allPodsBackupReady && backupReposAvailable[backupRepo.Name]
if !allPodsBackupReady {
break
}
}
newStatus.BackupRestoreReady = allPodsBackupReady
}
// If there are multiple versions of solr running, use the first otherVersion as the current running solr version of the cloud
if len(otherVersions) > 0 {
newStatus.TargetVersion = solrCloud.Spec.SolrImage.Tag
newStatus.Version = otherVersions[0]
} else {
newStatus.TargetVersion = ""
newStatus.Version = solrCloud.Spec.SolrImage.Tag
}
newStatus.InternalCommonAddress = solrCloud.UrlScheme(false) + "://" + solrCloud.InternalCommonUrl(true)
if solrCloud.Spec.SolrAddressability.External != nil && !solrCloud.Spec.SolrAddressability.External.HideCommon {
extAddress := solrCloud.UrlScheme(true) + "://" + solrCloud.ExternalCommonUrl(solrCloud.Spec.SolrAddressability.External.DomainName, true)
newStatus.ExternalCommonAddress = &extAddress
}
shouldRequeue = newStatus.ReadyReplicas != statefulSetStatus.ReadyReplicas || newStatus.Replicas != statefulSetStatus.Replicas || newStatus.UpToDateNodes != statefulSetStatus.UpdatedReplicas
return outOfDatePods, availableUpdatedPodCount, shouldRequeue, nil
}