This is an automated email from the ASF dual-hosted git repository.
houston pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/solr-operator.git
The following commit(s) were added to refs/heads/main by this push:
new 7c7f71b Allow for managed restarts across multiple SolrCloud
resources. (#349)
7c7f71b is described below
commit 7c7f71bb75ae9028c59d2a469a36bd1a1c310fe2
Author: Houston Putman <[email protected]>
AuthorDate: Fri Oct 22 14:47:26 2021 -0400
Allow for managed restarts across multiple SolrCloud resources. (#349)
---
api/v1beta1/solrcloud_types.go | 10 +-
controllers/solrcloud_controller.go | 5 +-
.../solrcloud_controller_externaldns_test.go | 14 +-
controllers/solrcloud_controller_ingress_test.go | 14 +-
controllers/solrcloud_controller_test.go | 2 +-
controllers/util/backup_util.go | 2 +-
controllers/util/common.go | 5 +
controllers/util/solr_update_util.go | 50 ++-
controllers/util/solr_update_util_test.go | 405 +++++++++++----------
helm/solr-operator/Chart.yaml | 7 +
10 files changed, 285 insertions(+), 229 deletions(-)
diff --git a/api/v1beta1/solrcloud_types.go b/api/v1beta1/solrcloud_types.go
index c7fcc6a..fb83951 100644
--- a/api/v1beta1/solrcloud_types.go
+++ b/api/v1beta1/solrcloud_types.go
@@ -1079,17 +1079,17 @@ func (sc *SolrCloud) WithDefaults() bool {
return sc.Spec.withDefaults()
}
-func (sc *SolrCloud) GetAllSolrNodeNames() []string {
+func (sc *SolrCloud) GetAllSolrPodNames() []string {
replicas := 1
if sc.Spec.Replicas != nil {
replicas = int(*sc.Spec.Replicas)
}
- nodeNames := make([]string, replicas)
+ podNames := make([]string, replicas)
statefulSetName := sc.StatefulSetName()
- for i := range nodeNames {
- nodeNames[i] = fmt.Sprintf("%s-%d", statefulSetName, i)
+ for i := range podNames {
+ podNames[i] = fmt.Sprintf("%s-%d", statefulSetName, i)
}
- return nodeNames
+ return podNames
}
func (sc *SolrCloud) BasicAuthSecretName() string {
diff --git a/controllers/solrcloud_controller.go
b/controllers/solrcloud_controller.go
index fa8f493..a5875ae 100644
--- a/controllers/solrcloud_controller.go
+++ b/controllers/solrcloud_controller.go
@@ -146,7 +146,7 @@ func (r *SolrCloudReconciler) Reconcile(ctx
context.Context, req ctrl.Request) (
return requeueOrNot, err
}
- solrNodeNames := instance.GetAllSolrNodeNames()
+ solrNodeNames := instance.GetAllSolrPodNames()
hostNameIpMap := make(map[string]string)
// Generate a service for every Node
@@ -397,7 +397,6 @@ func (r *SolrCloudReconciler) Reconcile(ctx
context.Context, req ctrl.Request) (
}
// Manage the updating of out-of-spec pods, if the Managed
UpdateStrategy has been specified.
- totalPodCount := int(*instance.Spec.Replicas)
if instance.Spec.UpdateStrategy.Method == solrv1beta1.ManagedUpdate &&
len(outOfDatePods)+len(outOfDatePodsNotStarted) > 0 {
updateLogger := logger.WithName("ManagedUpdateSelector")
@@ -416,7 +415,7 @@ func (r *SolrCloudReconciler) Reconcile(ctx
context.Context, req ctrl.Request) (
// Pick which pods should be deleted for an update.
// Don't exit on an error, which would only occur because of an
HTTP Exception. Requeue later instead.
- additionalPodsToUpdate, retryLater :=
util.DeterminePodsSafeToUpdate(instance, outOfDatePods, totalPodCount,
int(newStatus.ReadyReplicas), availableUpdatedPodCount,
len(outOfDatePodsNotStarted), updateLogger, authHeader)
+ additionalPodsToUpdate, retryLater :=
util.DeterminePodsSafeToUpdate(instance, outOfDatePods,
int(newStatus.ReadyReplicas), availableUpdatedPodCount,
len(outOfDatePodsNotStarted), updateLogger, authHeader)
podsToUpdate = append(podsToUpdate, additionalPodsToUpdate...)
for _, pod := range podsToUpdate {
diff --git a/controllers/solrcloud_controller_externaldns_test.go
b/controllers/solrcloud_controller_externaldns_test.go
index 4c2361a..5273096 100644
--- a/controllers/solrcloud_controller_externaldns_test.go
+++ b/controllers/solrcloud_controller_externaldns_test.go
@@ -130,7 +130,7 @@ var _ = FDescribe("SolrCloud controller - External DNS",
func() {
Expect(headlessService.Spec.Ports[0].TargetPort.StrVal).To(Equal("solr-client"),
"Wrong podPort name on headless Service")
By("making sure no individual Solr Node Services exist")
- expectNoServices(ctx, solrCloud, "Node service
shouldn't exist, but it does.", solrCloud.GetAllSolrNodeNames())
+ expectNoServices(ctx, solrCloud, "Node service
shouldn't exist, but it does.", solrCloud.GetAllSolrPodNames())
By("making sure no Ingress was created")
expectNoIngress(ctx, solrCloud,
solrCloud.CommonIngressName())
@@ -201,7 +201,7 @@ var _ = FDescribe("SolrCloud controller - External DNS",
func() {
Expect(headlessService.Spec.Ports[0].TargetPort.StrVal).To(Equal("solr-client"),
"Wrong podPort name on headless Service")
By("making sure no individual Solr Node Services exist")
- expectNoServices(ctx, solrCloud, "Node service
shouldn't exist, but it does.", solrCloud.GetAllSolrNodeNames())
+ expectNoServices(ctx, solrCloud, "Node service
shouldn't exist, but it does.", solrCloud.GetAllSolrPodNames())
By("making sure no Ingress was created")
expectNoIngress(ctx, solrCloud,
solrCloud.CommonIngressName())
@@ -272,7 +272,7 @@ var _ = FDescribe("SolrCloud controller - External DNS",
func() {
Expect(headlessService.Spec.Ports[0].TargetPort.StrVal).To(Equal("solr-client"),
"Wrong podPort name on headless Service")
By("making sure no individual Solr Node Services exist")
- expectNoServices(ctx, solrCloud, "Node service
shouldn't exist, but it does.", solrCloud.GetAllSolrNodeNames())
+ expectNoServices(ctx, solrCloud, "Node service
shouldn't exist, but it does.", solrCloud.GetAllSolrPodNames())
By("making sure no Ingress was created")
expectNoIngress(ctx, solrCloud,
solrCloud.CommonIngressName())
@@ -345,7 +345,7 @@ var _ = FDescribe("SolrCloud controller - External DNS",
func() {
Expect(headlessService.Spec.Ports[0].TargetPort.StrVal).To(Equal("solr-client"),
"Wrong podPort name on headless Service")
By("making sure no individual Solr Node Services exist")
- expectNoServices(ctx, solrCloud, "Node service
shouldn't exist, but it does.", solrCloud.GetAllSolrNodeNames())
+ expectNoServices(ctx, solrCloud, "Node service
shouldn't exist, but it does.", solrCloud.GetAllSolrPodNames())
By("making sure no Ingress was created")
expectNoIngress(ctx, solrCloud,
solrCloud.CommonIngressName())
@@ -418,7 +418,7 @@ var _ = FDescribe("SolrCloud controller - External DNS",
func() {
Expect(headlessService.Spec.Ports[0].TargetPort.StrVal).To(Equal("solr-client"),
"Wrong podPort name on headless Service")
By("making sure no individual Solr Node Services exist")
- expectNoServices(ctx, solrCloud, "Node service
shouldn't exist, but it does.", solrCloud.GetAllSolrNodeNames())
+ expectNoServices(ctx, solrCloud, "Node service
shouldn't exist, but it does.", solrCloud.GetAllSolrPodNames())
By("making sure no Ingress was created")
expectNoIngress(ctx, solrCloud,
solrCloud.CommonIngressName())
@@ -490,7 +490,7 @@ var _ = FDescribe("SolrCloud controller - External DNS",
func() {
Expect(headlessService.Spec.Ports[0].TargetPort.StrVal).To(Equal("solr-client"),
"Wrong podPort name on headless Service")
By("making sure no individual Solr Node Services exist")
- expectNoServices(ctx, solrCloud, "Node service
shouldn't exist, but it does.", solrCloud.GetAllSolrNodeNames())
+ expectNoServices(ctx, solrCloud, "Node service
shouldn't exist, but it does.", solrCloud.GetAllSolrPodNames())
By("making sure no Ingress was created")
expectNoIngress(ctx, solrCloud,
solrCloud.CommonIngressName())
@@ -558,7 +558,7 @@ var _ = FDescribe("SolrCloud controller - External DNS",
func() {
Expect(headlessService.Spec.Ports[0].TargetPort.StrVal).To(Equal("solr-client"),
"Wrong podPort name on headless Service")
By("making sure no individual Solr Node Services exist")
- expectNoServices(ctx, solrCloud, "Node service
shouldn't exist, but it does.", solrCloud.GetAllSolrNodeNames())
+ expectNoServices(ctx, solrCloud, "Node service
shouldn't exist, but it does.", solrCloud.GetAllSolrPodNames())
By("making sure no Ingress was created")
expectNoIngress(ctx, solrCloud,
solrCloud.CommonIngressName())
diff --git a/controllers/solrcloud_controller_ingress_test.go
b/controllers/solrcloud_controller_ingress_test.go
index 8bc1043..125c2b1 100644
--- a/controllers/solrcloud_controller_ingress_test.go
+++ b/controllers/solrcloud_controller_ingress_test.go
@@ -135,7 +135,7 @@ var _ = FDescribe("SolrCloud controller - Ingress", func() {
expectNoService(ctx, solrCloud,
solrCloud.HeadlessServiceName(), "Headless service shouldn't exist, but it
does.")
By("making sure the individual Solr Node Services exist
and route correctly")
- nodeNames := solrCloud.GetAllSolrNodeNames()
+ nodeNames := solrCloud.GetAllSolrPodNames()
Expect(nodeNames).To(HaveLen(replicas), "SolrCloud has
incorrect number of nodeNames.")
for _, nodeName := range nodeNames {
service := expectService(ctx, solrCloud,
nodeName, util.MergeLabelsOrAnnotations(statefulSet.Spec.Selector.MatchLabels,
map[string]string{"statefulset.kubernetes.io/pod-name": nodeName}), false)
@@ -218,7 +218,7 @@ var _ = FDescribe("SolrCloud controller - Ingress", func() {
Expect(headlessService.Spec.Ports[0].TargetPort.StrVal).To(Equal("solr-client"),
"Wrong podPort name on headless Service")
By("making sure no individual Solr Node Services exist")
- expectNoServices(ctx, solrCloud, "Node service
shouldn't exist, but it does.", solrCloud.GetAllSolrNodeNames())
+ expectNoServices(ctx, solrCloud, "Node service
shouldn't exist, but it does.", solrCloud.GetAllSolrPodNames())
By("making sure Ingress was created correctly")
ingress := expectIngress(ctx, solrCloud,
solrCloud.CommonIngressName())
@@ -283,7 +283,7 @@ var _ = FDescribe("SolrCloud controller - Ingress", func() {
expectNoService(ctx, solrCloud,
solrCloud.HeadlessServiceName(), "Headless service shouldn't exist, but it
does.")
By("making sure the individual Solr Node Services exist
and route correctly")
- nodeNames := solrCloud.GetAllSolrNodeNames()
+ nodeNames := solrCloud.GetAllSolrPodNames()
Expect(nodeNames).To(HaveLen(replicas), "SolrCloud has
incorrect number of nodeNames.")
for _, nodeName := range nodeNames {
service := expectService(ctx, solrCloud,
nodeName, util.MergeLabelsOrAnnotations(statefulSet.Spec.Selector.MatchLabels,
map[string]string{"statefulset.kubernetes.io/pod-name": nodeName}), false)
@@ -353,7 +353,7 @@ var _ = FDescribe("SolrCloud controller - Ingress", func() {
expectNoService(ctx, solrCloud,
solrCloud.HeadlessServiceName(), "Headless service shouldn't exist, but it
does.")
By("making sure the individual Solr Node Services exist
and route correctly")
- nodeNames := solrCloud.GetAllSolrNodeNames()
+ nodeNames := solrCloud.GetAllSolrPodNames()
Expect(nodeNames).To(HaveLen(replicas), "SolrCloud has
incorrect number of nodeNames.")
for _, nodeName := range nodeNames {
service := expectService(ctx, solrCloud,
nodeName, util.MergeLabelsOrAnnotations(statefulSet.Spec.Selector.MatchLabels,
map[string]string{"statefulset.kubernetes.io/pod-name": nodeName}), false)
@@ -428,7 +428,7 @@ var _ = FDescribe("SolrCloud controller - Ingress", func() {
expectNoService(ctx, solrCloud,
solrCloud.HeadlessServiceName(), "Headless service shouldn't exist, but it
does.")
By("making sure the individual Solr Node Services exist
and route correctly")
- nodeNames := solrCloud.GetAllSolrNodeNames()
+ nodeNames := solrCloud.GetAllSolrPodNames()
Expect(nodeNames).To(HaveLen(replicas), "SolrCloud has
incorrect number of nodeNames.")
for _, nodeName := range nodeNames {
service := expectService(ctx, solrCloud,
nodeName, util.MergeLabelsOrAnnotations(statefulSet.Spec.Selector.MatchLabels,
map[string]string{"statefulset.kubernetes.io/pod-name": nodeName}), false)
@@ -499,7 +499,7 @@ var _ = FDescribe("SolrCloud controller - Ingress", func() {
expectNoService(ctx, solrCloud,
solrCloud.HeadlessServiceName(), "Headless service shouldn't exist, but it
does.")
By("making sure the individual Solr Node Services exist
and route correctly")
- nodeNames := solrCloud.GetAllSolrNodeNames()
+ nodeNames := solrCloud.GetAllSolrPodNames()
Expect(nodeNames).To(HaveLen(replicas), "SolrCloud has
incorrect number of nodeNames.")
for _, nodeName := range nodeNames {
service := expectService(ctx, solrCloud,
nodeName, util.MergeLabelsOrAnnotations(statefulSet.Spec.Selector.MatchLabels,
map[string]string{"statefulset.kubernetes.io/pod-name": nodeName}), false)
@@ -573,7 +573,7 @@ var _ = FDescribe("SolrCloud controller - Ingress", func() {
expectNoService(ctx, solrCloud,
solrCloud.HeadlessServiceName(), "Headless service shouldn't exist, but it
does.")
By("making sure the individual Solr Node Services exist
and route correctly")
- nodeNames := solrCloud.GetAllSolrNodeNames()
+ nodeNames := solrCloud.GetAllSolrPodNames()
Expect(nodeNames).To(HaveLen(replicas), "SolrCloud has
incorrect number of nodeNames.")
for _, nodeName := range nodeNames {
service := expectService(ctx, solrCloud,
nodeName, util.MergeLabelsOrAnnotations(statefulSet.Spec.Selector.MatchLabels,
map[string]string{"statefulset.kubernetes.io/pod-name": nodeName}), false)
diff --git a/controllers/solrcloud_controller_test.go
b/controllers/solrcloud_controller_test.go
index 1c6dce4..3f07e22 100644
--- a/controllers/solrcloud_controller_test.go
+++ b/controllers/solrcloud_controller_test.go
@@ -406,7 +406,7 @@ var _ = FDescribe("SolrCloud controller - General", func() {
Expect(headlessService.Spec.Ports[0].TargetPort.StrVal).To(Equal("solr-client"),
"Wrong podPort name on headless Service")
By("making sure no individual Solr Node Services exist")
- expectNoServices(ctx, solrCloud, "Node service
shouldn't exist, but it does.", solrCloud.GetAllSolrNodeNames())
+ expectNoServices(ctx, solrCloud, "Node service
shouldn't exist, but it does.", solrCloud.GetAllSolrPodNames())
By("making sure no Ingress was created")
expectNoIngress(ctx, solrCloud,
solrCloud.CommonIngressName())
diff --git a/controllers/util/backup_util.go b/controllers/util/backup_util.go
index b06a8c5..d0dd2d8 100644
--- a/controllers/util/backup_util.go
+++ b/controllers/util/backup_util.go
@@ -388,7 +388,7 @@ func EnsureDirectoryForBackup(solrCloud *solr.SolrCloud,
backupRepository *solr.
if IsRepoManaged(backupRepository) {
backupPath := BackupLocationPath(backupRepository,
backup.Spec.Location)
return RunExecForPod(
- solrCloud.GetAllSolrNodeNames()[0],
+ solrCloud.GetAllSolrPodNames()[0],
solrCloud.Namespace,
[]string{"/bin/bash", "-c", "rm -rf " + backupPath + "
&& mkdir -p " + backupPath},
*config,
diff --git a/controllers/util/common.go b/controllers/util/common.go
index 16b91f3..fdd8ac2 100644
--- a/controllers/util/common.go
+++ b/controllers/util/common.go
@@ -39,6 +39,11 @@ var (
PublicReadOnlyPermissions int32 = 444
)
+func Replicas(num int) *int32 {
+ num32 := int32(num)
+ return &num32
+}
+
// Set the requeueAfter if it has not been set, or is greater than the new
time to requeue at
func updateRequeueAfter(requeueOrNot *reconcile.Result, newWait time.Duration)
{
if requeueOrNot.RequeueAfter <= 0 || requeueOrNot.RequeueAfter >
newWait {
diff --git a/controllers/util/solr_update_util.go
b/controllers/util/solr_update_util.go
index a825d26..72f373d 100644
--- a/controllers/util/solr_update_util.go
+++ b/controllers/util/solr_update_util.go
@@ -93,9 +93,9 @@ func scheduleNextRestartWithTime(restartSchedule string,
podTemplateAnnotations
// TODO:
// - Think about caching this for ~250 ms? Not a huge need to send these
requests milliseconds apart.
// - Might be too much complexity for very little gain.
-func DeterminePodsSafeToUpdate(cloud *solr.SolrCloud, outOfDatePods
[]corev1.Pod, totalPods int, readyPods int, availableUpdatedPodCount int,
outOfDatePodsNotStartedCount int, logger logr.Logger, httpHeaders
map[string]string) (podsToUpdate []corev1.Pod, retryLater bool) {
+func DeterminePodsSafeToUpdate(cloud *solr.SolrCloud, outOfDatePods
[]corev1.Pod, readyPods int, availableUpdatedPodCount int,
outOfDatePodsNotStartedCount int, logger logr.Logger, httpHeaders
map[string]string) (podsToUpdate []corev1.Pod, retryLater bool) {
// Before fetching the cluster state, be sure that there is room to
update at least 1 pod
- maxPodsUnavailable, unavailableUpdatedPodCount, maxPodsToUpdate :=
calculateMaxPodsToUpdate(cloud, totalPods, len(outOfDatePods),
outOfDatePodsNotStartedCount, availableUpdatedPodCount)
+ maxPodsUnavailable, unavailableUpdatedPodCount, maxPodsToUpdate :=
calculateMaxPodsToUpdate(cloud, len(outOfDatePods),
outOfDatePodsNotStartedCount, availableUpdatedPodCount)
if maxPodsToUpdate <= 0 {
logger.Info("Pod update selection canceled. The number of
updated pods unavailable equals or exceeds the calculated maxPodsUnavailable.",
"unavailableUpdatedPods", unavailableUpdatedPodCount,
"outOfDatePodsNotStarted", outOfDatePodsNotStartedCount, "maxPodsUnavailable",
maxPodsUnavailable)
@@ -126,7 +126,7 @@ func DeterminePodsSafeToUpdate(cloud *solr.SolrCloud,
outOfDatePods []corev1.Pod
// If the update logic already wants to retry later, then do
not pick any pods
if !retryLater {
logger.Info("Pod update selection started.",
"outOfDatePods", len(outOfDatePods), "maxPodsUnavailable", maxPodsUnavailable,
"unavailableUpdatedPods", unavailableUpdatedPodCount,
"outOfDatePodsNotStarted", outOfDatePodsNotStartedCount, "maxPodsToUpdate",
maxPodsToUpdate)
- podsToUpdate = pickPodsToUpdate(cloud, outOfDatePods,
clusterResp.ClusterStatus, overseerResp.Leader, totalPods, maxPodsToUpdate,
logger)
+ podsToUpdate = pickPodsToUpdate(cloud, outOfDatePods,
clusterResp.ClusterStatus, overseerResp.Leader, maxPodsToUpdate, logger)
// If there are no pods to upgrade, even though the
maxPodsToUpdate is >0, then retry later because the issue stems from cluster
state
// and clusterState changes will not call the
reconciler.
@@ -139,7 +139,8 @@ func DeterminePodsSafeToUpdate(cloud *solr.SolrCloud,
outOfDatePods []corev1.Pod
}
// calculateMaxPodsToUpdate determines the maximum number of additional pods
that can be updated.
-func calculateMaxPodsToUpdate(cloud *solr.SolrCloud, totalPods int,
outOfDatePodCount int, outOfDatePodsNotStartedCount int,
availableUpdatedPodCount int) (maxPodsUnavailable int,
unavailableUpdatedPodCount int, maxPodsToUpdate int) {
+func calculateMaxPodsToUpdate(cloud *solr.SolrCloud, outOfDatePodCount int,
outOfDatePodsNotStartedCount int, availableUpdatedPodCount int)
(maxPodsUnavailable int, unavailableUpdatedPodCount int, maxPodsToUpdate int) {
+ totalPods := int(*cloud.Spec.Replicas)
// In order to calculate the number of updated pods that are
unavailable take all pods, take the total pods and subtract those that are
available and updated, and those that are not updated.
unavailableUpdatedPodCount = totalPods - availableUpdatedPodCount -
outOfDatePodCount - outOfDatePodsNotStartedCount
// If the maxBatchNodeUpgradeSpec is passed as a decimal between 0 and
1, then calculate as a percentage of the number of nodes.
@@ -152,9 +153,8 @@ func calculateMaxPodsToUpdate(cloud *solr.SolrCloud,
totalPods int, outOfDatePod
}
func pickPodsToUpdate(cloud *solr.SolrCloud, outOfDatePods []corev1.Pod,
clusterStatus solr_api.SolrClusterStatus,
- overseer string, totalPods int, maxPodsToUpdate int, logger
logr.Logger) (podsToUpdate []corev1.Pod) {
-
- nodeContents, totalShardReplicas, shardReplicasNotActive :=
findSolrNodeContents(clusterStatus, overseer)
+ overseer string, maxPodsToUpdate int, logger logr.Logger) (podsToUpdate
[]corev1.Pod) {
+ nodeContents, totalShardReplicas, shardReplicasNotActive,
allManagedPodsLive := findSolrNodeContents(clusterStatus, overseer,
GetAllManagedSolrNodeNames(cloud))
sortNodePodsBySafety(outOfDatePods, nodeContents, cloud)
updateOptions := cloud.Spec.UpdateStrategy.ManagedUpdateOptions
@@ -168,7 +168,7 @@ func pickPodsToUpdate(cloud *solr.SolrCloud, outOfDatePods
[]corev1.Pod, cluster
for _, pod := range outOfDatePods {
isSafeToUpdate := true
- nodeName := SolrNodeName(cloud, pod)
+ nodeName := SolrNodeName(cloud, pod.Name)
nodeContent, isInClusterState := nodeContents[nodeName]
var reason string
// The overseerLeader can only be upgraded by itself
@@ -182,12 +182,14 @@ func pickPodsToUpdate(cloud *solr.SolrCloud,
outOfDatePods []corev1.Pod, cluster
// The overseerLeader can only be upgraded by
itself
// We want to update it when it's the last out
of date pods and all nodes are "live"
// But we want to make sure it still follows
the same replicasDown rules as the other nodes, so still use that logic
- if len(outOfDatePods) == 1 &&
len(clusterStatus.LiveNodes) == totalPods {
+ // This works if there are other solr nodes not
managed by this SolrCloud resource, because we just check that this is the last
+ // pod managed for this SolrCloud that has not
been updated.
+ if len(outOfDatePods) == 1 &&
allManagedPodsLive {
isSafeToUpdate = true
reason = "Pod is overseer and all other
nodes have been updated."
} else {
isSafeToUpdate = false
- reason = "Pod is overseer and must wait
for all other pods to be updated and healthy."
+ reason = "Pod is overseer and must wait
for all other pods to be updated and live."
}
}
// Only check the replicaSaftey if the node starts out
as isSafeToUpdate, otherwise the check is redundant
@@ -250,13 +252,13 @@ func pickPodsToUpdate(cloud *solr.SolrCloud,
outOfDatePods []corev1.Pod, cluster
func sortNodePodsBySafety(outOfDatePods []corev1.Pod, nodeMap
map[string]*SolrNodeContents, solrCloud *solr.SolrCloud) {
sort.SliceStable(outOfDatePods, func(i, j int) bool {
// First sort by if the node is in the ClusterState
- nodeI, hasNodeI := nodeMap[SolrNodeName(solrCloud,
outOfDatePods[i])]
+ nodeI, hasNodeI := nodeMap[SolrNodeName(solrCloud,
outOfDatePods[i].Name)]
if !hasNodeI {
return true
} else if nodeI.overseerLeader {
return false
}
- nodeJ, hasNodeJ := nodeMap[SolrNodeName(solrCloud,
outOfDatePods[j])]
+ nodeJ, hasNodeJ := nodeMap[SolrNodeName(solrCloud,
outOfDatePods[j].Name)]
if !hasNodeJ {
return false
} else if nodeJ.overseerLeader {
@@ -334,13 +336,14 @@ This aggregated info is returned as:
- A map from unique shard name (collection+shard) to the count of replicas
that are not active for that shard.
- If a node is not live, then all shards that live on that node will be
considered "not active"
*/
-func findSolrNodeContents(cluster solr_api.SolrClusterStatus, overseerLeader
string) (nodeContents map[string]*SolrNodeContents, totalShardReplicas
map[string]int, shardReplicasNotActive map[string]int) {
- nodeContents = map[string]*SolrNodeContents{}
- totalShardReplicas = map[string]int{}
- shardReplicasNotActive = map[string]int{}
+func findSolrNodeContents(cluster solr_api.SolrClusterStatus, overseerLeader
string, managedSolrNodeNames map[string]bool) (nodeContents
map[string]*SolrNodeContents, totalShardReplicas map[string]int,
shardReplicasNotActive map[string]int, allManagedPodsLive bool) {
+ nodeContents = make(map[string]*SolrNodeContents, 0)
+ totalShardReplicas = make(map[string]int, 0)
+ shardReplicasNotActive = make(map[string]int, 0)
// Update the info for each "live" node.
for _, nodeName := range cluster.LiveNodes {
contents, hasValue := nodeContents[nodeName]
+ delete(managedSolrNodeNames, nodeName)
if !hasValue {
contents = &SolrNodeContents{
nodeName: nodeName,
@@ -418,7 +421,7 @@ func findSolrNodeContents(cluster
solr_api.SolrClusterStatus, overseerLeader str
}
nodeContents[overseerLeader] = contents
}
- return nodeContents, totalShardReplicas, shardReplicasNotActive
+ return nodeContents, totalShardReplicas, shardReplicasNotActive,
len(managedSolrNodeNames) == 0
}
type SolrNodeContents struct {
@@ -457,6 +460,15 @@ func (nodeContents *SolrNodeContents) InClusterState()
bool {
}
// SolrNodeName takes a cloud and a pod and returns the Solr nodeName for that
pod
-func SolrNodeName(solrCloud *solr.SolrCloud, pod corev1.Pod) string {
- return fmt.Sprintf("%s:%d_solr",
solrCloud.AdvertisedNodeHost(pod.Name), solrCloud.NodePort())
+func SolrNodeName(solrCloud *solr.SolrCloud, podName string) string {
+ return fmt.Sprintf("%s:%d_solr", solrCloud.AdvertisedNodeHost(podName),
solrCloud.NodePort())
+}
+
+func GetAllManagedSolrNodeNames(solrCloud *solr.SolrCloud) map[string]bool {
+ podNames := solrCloud.GetAllSolrPodNames()
+ allNodeNames := make(map[string]bool, len(podNames))
+ for _, podName := range podNames {
+ allNodeNames[SolrNodeName(solrCloud, podName)] = true
+ }
+ return allNodeNames
}
diff --git a/controllers/util/solr_update_util_test.go
b/controllers/util/solr_update_util_test.go
index 8d2e5cb..2a7bffb 100644
--- a/controllers/util/solr_update_util_test.go
+++ b/controllers/util/solr_update_util_test.go
@@ -33,13 +33,14 @@ import (
func TestPickPodsToUpgrade(t *testing.T) {
log := ctrl.Log
- overseerLeader := "pod-0.foo-solrcloud-headless.default:2000_solr"
+ overseerLeader :=
"foo-solrcloud-0.foo-solrcloud-headless.default:2000_solr"
maxshardReplicasUnavailable := intstr.FromInt(1)
solrCloud := &solr.SolrCloud{
ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace:
"default"},
Spec: solr.SolrCloudSpec{
+ Replicas: Replicas(6),
SolrAddressability: solr.SolrAddressabilityOptions{
PodPort: 2000,
},
@@ -53,24 +54,24 @@ func TestPickPodsToUpgrade(t *testing.T) {
}
allPods := []corev1.Pod{
- {ObjectMeta: metav1.ObjectMeta{Name: "pod-0"}, Spec:
corev1.PodSpec{}},
- {ObjectMeta: metav1.ObjectMeta{Name: "pod-1"}, Spec:
corev1.PodSpec{}},
- {ObjectMeta: metav1.ObjectMeta{Name: "pod-2"}, Spec:
corev1.PodSpec{}},
- {ObjectMeta: metav1.ObjectMeta{Name: "pod-3"}, Spec:
corev1.PodSpec{}},
- {ObjectMeta: metav1.ObjectMeta{Name: "pod-4"}, Spec:
corev1.PodSpec{}},
- {ObjectMeta: metav1.ObjectMeta{Name: "pod-5"}, Spec:
corev1.PodSpec{}},
- {ObjectMeta: metav1.ObjectMeta{Name: "pod-6"}, Spec:
corev1.PodSpec{}},
+ {ObjectMeta: metav1.ObjectMeta{Name: "foo-solrcloud-0"}, Spec:
corev1.PodSpec{}},
+ {ObjectMeta: metav1.ObjectMeta{Name: "foo-solrcloud-1"}, Spec:
corev1.PodSpec{}},
+ {ObjectMeta: metav1.ObjectMeta{Name: "foo-solrcloud-2"}, Spec:
corev1.PodSpec{}},
+ {ObjectMeta: metav1.ObjectMeta{Name: "foo-solrcloud-3"}, Spec:
corev1.PodSpec{}},
+ {ObjectMeta: metav1.ObjectMeta{Name: "foo-solrcloud-4"}, Spec:
corev1.PodSpec{}},
+ {ObjectMeta: metav1.ObjectMeta{Name: "foo-solrcloud-5"}, Spec:
corev1.PodSpec{}},
+ {ObjectMeta: metav1.ObjectMeta{Name: "foo-solrcloud-6"}, Spec:
corev1.PodSpec{}},
}
halfPods := []corev1.Pod{
- {ObjectMeta: metav1.ObjectMeta{Name: "pod-0"}, Spec:
corev1.PodSpec{}},
- {ObjectMeta: metav1.ObjectMeta{Name: "pod-1"}, Spec:
corev1.PodSpec{}},
- {ObjectMeta: metav1.ObjectMeta{Name: "pod-3"}, Spec:
corev1.PodSpec{}},
- {ObjectMeta: metav1.ObjectMeta{Name: "pod-5"}, Spec:
corev1.PodSpec{}},
+ {ObjectMeta: metav1.ObjectMeta{Name: "foo-solrcloud-0"}, Spec:
corev1.PodSpec{}},
+ {ObjectMeta: metav1.ObjectMeta{Name: "foo-solrcloud-1"}, Spec:
corev1.PodSpec{}},
+ {ObjectMeta: metav1.ObjectMeta{Name: "foo-solrcloud-3"}, Spec:
corev1.PodSpec{}},
+ {ObjectMeta: metav1.ObjectMeta{Name: "foo-solrcloud-5"}, Spec:
corev1.PodSpec{}},
}
lastPod := []corev1.Pod{
- {ObjectMeta: metav1.ObjectMeta{Name: "pod-0"}, Spec:
corev1.PodSpec{}},
+ {ObjectMeta: metav1.ObjectMeta{Name: "foo-solrcloud-0"}, Spec:
corev1.PodSpec{}},
}
/*
@@ -79,18 +80,18 @@ func TestPickPodsToUpgrade(t *testing.T) {
// Normal inputs
maxshardReplicasUnavailable = intstr.FromInt(1)
- podsToUpgrade := getPodNames(pickPodsToUpdate(solrCloud, allPods,
testDownClusterStatus, overseerLeader, 6, 6, log))
- assert.ElementsMatch(t, []string{"pod-2", "pod-6"}, podsToUpgrade,
"Incorrect set of next pods to upgrade. Do to the down/non-live replicas, only
the node without replicas and one more can be upgraded.")
+ podsToUpgrade := getPodNames(pickPodsToUpdate(solrCloud, allPods,
testDownClusterStatus, overseerLeader, 6, log))
+ assert.ElementsMatch(t, []string{"foo-solrcloud-2", "foo-solrcloud-6"},
podsToUpgrade, "Incorrect set of next pods to upgrade. Do to the down/non-live
replicas, only the node without replicas and one more can be upgraded.")
// Test the maxBatchNodeUpgradeSpec
maxshardReplicasUnavailable = intstr.FromInt(1)
- podsToUpgrade = getPodNames(pickPodsToUpdate(solrCloud, allPods,
testDownClusterStatus, overseerLeader, 6, 1, log))
- assert.ElementsMatch(t, []string{"pod-6"}, podsToUpgrade, "Incorrect
set of next pods to upgrade. Only 1 node should be upgraded when
maxBatchNodeUpgradeSpec=1")
+ podsToUpgrade = getPodNames(pickPodsToUpdate(solrCloud, allPods,
testDownClusterStatus, overseerLeader, 1, log))
+ assert.ElementsMatch(t, []string{"foo-solrcloud-6"}, podsToUpgrade,
"Incorrect set of next pods to upgrade. Only 1 node should be upgraded when
maxBatchNodeUpgradeSpec=1")
// Test the maxShardReplicasDownSpec
maxshardReplicasUnavailable = intstr.FromInt(2)
- podsToUpgrade = getPodNames(pickPodsToUpdate(solrCloud, allPods,
testDownClusterStatus, overseerLeader, 6, 6, log))
- assert.ElementsMatch(t, []string{"pod-2", "pod-3", "pod-4", "pod-6"},
podsToUpgrade, "Incorrect set of next pods to upgrade.")
+ podsToUpgrade = getPodNames(pickPodsToUpdate(solrCloud, allPods,
testDownClusterStatus, overseerLeader, 6, log))
+ assert.ElementsMatch(t, []string{"foo-solrcloud-2", "foo-solrcloud-3",
"foo-solrcloud-4", "foo-solrcloud-6"}, podsToUpgrade, "Incorrect set of next
pods to upgrade.")
/*
Test upgrades with replicas in recovery (which are treated as
"active" when calculating how many nodes can be taken down) and a non-live node.
@@ -98,23 +99,23 @@ func TestPickPodsToUpgrade(t *testing.T) {
// Normal inputs
maxshardReplicasUnavailable = intstr.FromInt(1)
- podsToUpgrade = getPodNames(pickPodsToUpdate(solrCloud, allPods,
testRecoveringClusterStatus, overseerLeader, 6, 6, log))
- assert.ElementsMatch(t, []string{"pod-4", "pod-6"}, podsToUpgrade,
"Incorrect set of next pods to upgrade. Do to the recovering/down/non-live
replicas, only the non-live node and node without replicas can be upgraded.")
+ podsToUpgrade = getPodNames(pickPodsToUpdate(solrCloud, allPods,
testRecoveringClusterStatus, overseerLeader, 6, log))
+ assert.ElementsMatch(t, []string{"foo-solrcloud-4", "foo-solrcloud-6"},
podsToUpgrade, "Incorrect set of next pods to upgrade. Do to the
recovering/down/non-live replicas, only the non-live node and node without
replicas can be upgraded.")
// Test the maxBatchNodeUpgradeSpec
maxshardReplicasUnavailable = intstr.FromInt(1)
- podsToUpgrade = getPodNames(pickPodsToUpdate(solrCloud, allPods,
testRecoveringClusterStatus, overseerLeader, 6, 1, log))
- assert.ElementsMatch(t, []string{"pod-4"}, podsToUpgrade, "Incorrect
set of next pods to upgrade. Only 1 node should be upgraded when
maxBatchNodeUpgradeSpec=1, and it should be the non-live node.")
+ podsToUpgrade = getPodNames(pickPodsToUpdate(solrCloud, allPods,
testRecoveringClusterStatus, overseerLeader, 1, log))
+ assert.ElementsMatch(t, []string{"foo-solrcloud-4"}, podsToUpgrade,
"Incorrect set of next pods to upgrade. Only 1 node should be upgraded when
maxBatchNodeUpgradeSpec=1, and it should be the non-live node.")
// Test the maxShardReplicasDownSpec
maxshardReplicasUnavailable = intstr.FromInt(2)
- podsToUpgrade = getPodNames(pickPodsToUpdate(solrCloud, allPods,
testRecoveringClusterStatus, overseerLeader, 6, 6, log))
- assert.ElementsMatch(t, []string{"pod-2", "pod-3", "pod-4", "pod-6"},
podsToUpgrade, "Incorrect set of next pods to upgrade. More nodes should be
upgraded when maxShardReplicasDown=2")
+ podsToUpgrade = getPodNames(pickPodsToUpdate(solrCloud, allPods,
testRecoveringClusterStatus, overseerLeader, 6, log))
+ assert.ElementsMatch(t, []string{"foo-solrcloud-2", "foo-solrcloud-3",
"foo-solrcloud-4", "foo-solrcloud-6"}, podsToUpgrade, "Incorrect set of next
pods to upgrade. More nodes should be upgraded when maxShardReplicasDown=2")
// The overseer should be upgraded when given enough leeway
maxshardReplicasUnavailable = intstr.FromString("50%")
- podsToUpgrade = getPodNames(pickPodsToUpdate(solrCloud, lastPod,
testDownClusterStatus, overseerLeader, 6, 2, log))
- assert.ElementsMatch(t, []string{"pod-0"}, podsToUpgrade, "Incorrect
set of next pods to upgrade. The last pod, the overseer, should be chosen
because it has been given enough leeway.")
+ podsToUpgrade = getPodNames(pickPodsToUpdate(solrCloud, lastPod,
testDownClusterStatus, overseerLeader, 2, log))
+ assert.ElementsMatch(t, []string{"foo-solrcloud-0"}, podsToUpgrade,
"Incorrect set of next pods to upgrade. The last pod, the overseer, should be
chosen because it has been given enough leeway.")
/*
Test upgrades with a healthy cluster state.
@@ -122,18 +123,18 @@ func TestPickPodsToUpgrade(t *testing.T) {
// Normal inputs
maxshardReplicasUnavailable = intstr.FromInt(1)
- podsToUpgrade = getPodNames(pickPodsToUpdate(solrCloud, halfPods,
testHealthyClusterStatus, overseerLeader, 6, 6, log))
- assert.ElementsMatch(t, []string{"pod-1"}, podsToUpgrade, "Incorrect
set of next pods to upgrade. Do to replica placement, only the node with the
least leaders can be upgraded and replicas.")
+ podsToUpgrade = getPodNames(pickPodsToUpdate(solrCloud, halfPods,
testHealthyClusterStatus, overseerLeader, 6, log))
+ assert.ElementsMatch(t, []string{"foo-solrcloud-1"}, podsToUpgrade,
"Incorrect set of next pods to upgrade. Do to replica placement, only the node
with the least leaders can be upgraded and replicas.")
// Test the maxShardReplicasDownSpec
maxshardReplicasUnavailable = intstr.FromInt(2)
- podsToUpgrade = getPodNames(pickPodsToUpdate(solrCloud, halfPods,
testHealthyClusterStatus, overseerLeader, 6, 6, log))
- assert.ElementsMatch(t, []string{"pod-1", "pod-5"}, podsToUpgrade,
"Incorrect set of next pods to upgrade. More nodes should be upgraded when
maxShardReplicasDown=2")
+ podsToUpgrade = getPodNames(pickPodsToUpdate(solrCloud, halfPods,
testHealthyClusterStatus, overseerLeader, 6, log))
+ assert.ElementsMatch(t, []string{"foo-solrcloud-1", "foo-solrcloud-5"},
podsToUpgrade, "Incorrect set of next pods to upgrade. More nodes should be
upgraded when maxShardReplicasDown=2")
// The overseer should be upgraded when given enough leeway
maxshardReplicasUnavailable = intstr.FromString("50%")
- podsToUpgrade = getPodNames(pickPodsToUpdate(solrCloud, lastPod,
testDownClusterStatus, overseerLeader, 6, 2, log))
- assert.ElementsMatch(t, []string{"pod-0"}, podsToUpgrade, "Incorrect
set of next pods to upgrade. The last pod, the overseer, should be chosen
because it has been given enough leeway.")
+ podsToUpgrade = getPodNames(pickPodsToUpdate(solrCloud, lastPod,
testDownClusterStatus, overseerLeader, 2, log))
+ assert.ElementsMatch(t, []string{"foo-solrcloud-0"}, podsToUpgrade,
"Incorrect set of next pods to upgrade. The last pod, the overseer, should be
chosen because it has been given enough leeway.")
/*
Test the overseer node being taken down.
@@ -141,22 +142,38 @@ func TestPickPodsToUpgrade(t *testing.T) {
// The overseer should be not be upgraded if the clusterstate is not
healthy enough
maxshardReplicasUnavailable = intstr.FromInt(1)
- podsToUpgrade = getPodNames(pickPodsToUpdate(solrCloud, lastPod,
testRecoveringClusterStatus, overseerLeader, 6, 3, log))
+ podsToUpgrade = getPodNames(pickPodsToUpdate(solrCloud, lastPod,
testRecoveringClusterStatus, overseerLeader, 3, log))
assert.ElementsMatch(t, []string{}, podsToUpgrade, "Incorrect set of
next pods to upgrade. The overseer should be not be upgraded if the
clusterstate is not healthy enough.")
// The overseer should be not be upgraded if the clusterstate is not
healthy enough
- podsToUpgrade = getPodNames(pickPodsToUpdate(solrCloud, lastPod,
testRecoveringClusterStatus, overseerLeader, 6, 6, log))
+ podsToUpgrade = getPodNames(pickPodsToUpdate(solrCloud, lastPod,
testRecoveringClusterStatus, overseerLeader, 6, log))
assert.ElementsMatch(t, []string{}, podsToUpgrade, "Incorrect set of
next pods to upgrade. The overseer should be not be upgraded if there are other
non-live nodes.")
// The overseer should be upgraded when given enough leeway
maxshardReplicasUnavailable = intstr.FromInt(2)
- podsToUpgrade = getPodNames(pickPodsToUpdate(solrCloud, lastPod,
testDownClusterStatus, overseerLeader, 6, 6, log))
- assert.ElementsMatch(t, []string{"pod-0"}, podsToUpgrade, "Incorrect
set of next pods to upgrade. The overseer should be upgraded when given enough
leeway.")
+ podsToUpgrade = getPodNames(pickPodsToUpdate(solrCloud, lastPod,
testDownClusterStatus, overseerLeader, 6, log))
+ assert.ElementsMatch(t, []string{"foo-solrcloud-0"}, podsToUpgrade,
"Incorrect set of next pods to upgrade. The overseer should be upgraded when
given enough leeway.")
// The overseer should be upgraded when everything is healthy and it is
the last node
maxshardReplicasUnavailable = intstr.FromInt(1)
- podsToUpgrade = getPodNames(pickPodsToUpdate(solrCloud, lastPod,
testHealthyClusterStatus, overseerLeader, 6, 6, log))
- assert.ElementsMatch(t, []string{"pod-0"}, podsToUpgrade, "Incorrect
set of next pods to upgrade. The overseer should be upgraded when everything is
healthy and it is the last node")
+ podsToUpgrade = getPodNames(pickPodsToUpdate(solrCloud, lastPod,
testHealthyClusterStatus, overseerLeader, 6, log))
+ assert.ElementsMatch(t, []string{"foo-solrcloud-0"}, podsToUpgrade,
"Incorrect set of next pods to upgrade. The overseer should be upgraded when
everything is healthy and it is the last node")
+
+ /*
+ Test the overseer node being taken down when there might be
nodes managed outside of this SolrCloud resource
+ */
+
+ // The overseer should not be upgraded when everything is healthy and
it is the last node but one pod is not in the live nodes
+ maxshardReplicasUnavailable = intstr.FromInt(1)
+ solrCloud.Spec.Replicas = Replicas(7)
+ podsToUpgrade = getPodNames(pickPodsToUpdate(solrCloud, lastPod,
testHealthyClusterStatus, overseerLeader, 6, log))
+ assert.Empty(t, podsToUpgrade, "Incorrect set of next pods to upgrade.
The overseer should be not be upgraded when one of the managed pods is not
live")
+
+ // The overseer should be upgraded when everything is healthy and it is
the last node even though this SolrCloud resource doesn't manage all Nodes
+ maxshardReplicasUnavailable = intstr.FromInt(1)
+ solrCloud.Spec.Replicas = Replicas(4)
+ podsToUpgrade = getPodNames(pickPodsToUpdate(solrCloud, lastPod,
testHealthyClusterStatus, overseerLeader, 6, log))
+ assert.ElementsMatch(t, []string{"foo-solrcloud-0"}, podsToUpgrade,
"Incorrect set of next pods to upgrade. The overseer should be upgraded when
everything is healthy and it is the last node, even though this SolrCloud
resource doesn't manage all Nodes")
}
func TestPodUpgradeOrdering(t *testing.T) {
@@ -171,37 +188,37 @@ func TestPodUpgradeOrdering(t *testing.T) {
pods := make([]corev1.Pod, 13)
for i := range pods {
- pods[i] = corev1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "pod-"
+ strconv.Itoa(i)}, Spec: corev1.PodSpec{}}
+ pods[i] = corev1.Pod{ObjectMeta: metav1.ObjectMeta{Name:
"foo-solrcloud-" + strconv.Itoa(i)}, Spec: corev1.PodSpec{}}
}
nodeMap := map[string]*SolrNodeContents{
// This node should be last as it is the overseer
- SolrNodeName(solrCloud, pods[0]): {
- nodeName: SolrNodeName(solrCloud, pods[0]),
+ SolrNodeName(solrCloud, pods[0].Name): {
+ nodeName: SolrNodeName(solrCloud, pods[0].Name),
leaders: 4,
replicas: 10,
notDownReplicas: 10,
overseerLeader: true,
live: true,
},
- SolrNodeName(solrCloud, pods[1]): {
- nodeName: SolrNodeName(solrCloud, pods[1]),
+ SolrNodeName(solrCloud, pods[1].Name): {
+ nodeName: SolrNodeName(solrCloud, pods[1].Name),
leaders: 8,
replicas: 20,
notDownReplicas: 20,
overseerLeader: false,
live: false,
},
- SolrNodeName(solrCloud, pods[2]): {
- nodeName: SolrNodeName(solrCloud, pods[2]),
+ SolrNodeName(solrCloud, pods[2].Name): {
+ nodeName: SolrNodeName(solrCloud, pods[2].Name),
leaders: 0,
replicas: 16,
notDownReplicas: 16,
overseerLeader: false,
live: true,
},
- SolrNodeName(solrCloud, pods[3]): {
- nodeName: SolrNodeName(solrCloud, pods[3]),
+ SolrNodeName(solrCloud, pods[3].Name): {
+ nodeName: SolrNodeName(solrCloud, pods[3].Name),
leaders: 3,
replicas: 10,
notDownReplicas: 10,
@@ -209,57 +226,57 @@ func TestPodUpgradeOrdering(t *testing.T) {
live: true,
},
// This node should come second to last as it is not the
overseer, but it has the most leaders.
- SolrNodeName(solrCloud, pods[4]): {
- nodeName: SolrNodeName(solrCloud, pods[4]),
+ SolrNodeName(solrCloud, pods[4].Name): {
+ nodeName: SolrNodeName(solrCloud, pods[4].Name),
leaders: 10,
replicas: 10,
notDownReplicas: 10,
overseerLeader: false,
live: true,
},
- // This node should come after pod 3 since they are identically
ordered, but the name pod-3 comes before pod-5.
- SolrNodeName(solrCloud, pods[5]): {
- nodeName: SolrNodeName(solrCloud, pods[5]),
+ // This node should come after pod 3 since they are identically
ordered, but the name foo-solrcloud-3 comes before foo-solrcloud-5.
+ SolrNodeName(solrCloud, pods[5].Name): {
+ nodeName: SolrNodeName(solrCloud, pods[5].Name),
leaders: 3,
replicas: 12,
notDownReplicas: 12,
overseerLeader: false,
live: true,
},
- SolrNodeName(solrCloud, pods[6]): {
- nodeName: SolrNodeName(solrCloud, pods[6]),
+ SolrNodeName(solrCloud, pods[6].Name): {
+ nodeName: SolrNodeName(solrCloud, pods[6].Name),
leaders: 3,
replicas: 12,
notDownReplicas: 12,
overseerLeader: false,
live: false,
},
- SolrNodeName(solrCloud, pods[7]): {
- nodeName: SolrNodeName(solrCloud, pods[7]),
+ SolrNodeName(solrCloud, pods[7].Name): {
+ nodeName: SolrNodeName(solrCloud, pods[7].Name),
leaders: 3,
replicas: 12,
notDownReplicas: 12,
overseerLeader: false,
live: true,
},
- SolrNodeName(solrCloud, pods[8]): {
- nodeName: SolrNodeName(solrCloud, pods[8]),
+ SolrNodeName(solrCloud, pods[8].Name): {
+ nodeName: SolrNodeName(solrCloud, pods[8].Name),
leaders: 3,
replicas: 12,
notDownReplicas: 12,
overseerLeader: false,
live: true,
},
- SolrNodeName(solrCloud, pods[10]): {
- nodeName: SolrNodeName(solrCloud, pods[10]),
+ SolrNodeName(solrCloud, pods[10].Name): {
+ nodeName: SolrNodeName(solrCloud, pods[10].Name),
leaders: 0,
replicas: 0,
notDownReplicas: 0,
overseerLeader: false,
live: false,
},
- SolrNodeName(solrCloud, pods[11]): {
- nodeName: SolrNodeName(solrCloud, pods[11]),
+ SolrNodeName(solrCloud, pods[11].Name): {
+ nodeName: SolrNodeName(solrCloud, pods[11].Name),
leaders: 0,
replicas: 0,
notDownReplicas: 0,
@@ -268,7 +285,7 @@ func TestPodUpgradeOrdering(t *testing.T) {
},
}
- expectedOrdering := []string{"pod-12", "pod-9", "pod-10", "pod-6",
"pod-1", "pod-11", "pod-2", "pod-3", "pod-8", "pod-7", "pod-5", "pod-4",
"pod-0"}
+ expectedOrdering := []string{"foo-solrcloud-12", "foo-solrcloud-9",
"foo-solrcloud-10", "foo-solrcloud-6", "foo-solrcloud-1", "foo-solrcloud-11",
"foo-solrcloud-2", "foo-solrcloud-3", "foo-solrcloud-8", "foo-solrcloud-7",
"foo-solrcloud-5", "foo-solrcloud-4", "foo-solrcloud-0"}
sortNodePodsBySafety(pods, nodeMap, solrCloud)
foundOrdering := make([]string, len(pods))
@@ -279,13 +296,28 @@ func TestPodUpgradeOrdering(t *testing.T) {
}
func TestFindSolrNodeContents(t *testing.T) {
- overseerLeader := "pod-0.foo-solrcloud-headless.default:2000_solr"
+ overseerLeader :=
"foo-solrcloud-0.foo-solrcloud-headless.default:2000_solr"
+
+ // Test allManagedPodsLive when true
+ _, _, _, allManagedPodsLive :=
findSolrNodeContents(testRecoveringClusterStatus, overseerLeader,
map[string]bool{
+ "foo-solrcloud-2.foo-solrcloud-headless.default:2000_solr":
true,
+ "foo-solrcloud-6.foo-solrcloud-headless.default:2000_solr":
true,
+ })
+ assert.True(t, allManagedPodsLive, "allManagedPodsLive should be true,
because both managed pods are live in cluster status")
+
+ // Test allManagedPodsLive when false
+ _, _, _, allManagedPodsLive =
findSolrNodeContents(testRecoveringClusterStatus, overseerLeader,
map[string]bool{
+ "foo-solrcloud-2.foo-solrcloud-headless.default:2000_solr":
true,
+ "foo-solrcloud-6.foo-solrcloud-headless.default:2000_solr":
true,
+ "foo-solrcloud-4.foo-solrcloud-headless.default:2000_solr":
true,
+ })
+ assert.False(t, allManagedPodsLive, "allManagedPodsLive should be
false, because there is a managed pod that is not live")
- nodeContents, totalShardReplicas, shardReplicasNotActive :=
findSolrNodeContents(testRecoveringClusterStatus, overseerLeader)
+ nodeContents, totalShardReplicas, shardReplicasNotActive, _ :=
findSolrNodeContents(testRecoveringClusterStatus, overseerLeader,
map[string]bool{})
expectedNodeContents := map[string]*SolrNodeContents{
- "pod-0.foo-solrcloud-headless.default:2000_solr": {
- nodeName:
"pod-0.foo-solrcloud-headless.default:2000_solr",
+ "foo-solrcloud-0.foo-solrcloud-headless.default:2000_solr": {
+ nodeName:
"foo-solrcloud-0.foo-solrcloud-headless.default:2000_solr",
leaders: 0,
replicas: 2,
notDownReplicas: 1,
@@ -302,8 +334,8 @@ func TestFindSolrNodeContents(t *testing.T) {
overseerLeader: true,
live: true,
},
- "pod-1.foo-solrcloud-headless.default:2000_solr": {
- nodeName:
"pod-1.foo-solrcloud-headless.default:2000_solr",
+ "foo-solrcloud-1.foo-solrcloud-headless.default:2000_solr": {
+ nodeName:
"foo-solrcloud-1.foo-solrcloud-headless.default:2000_solr",
leaders: 1,
replicas: 2,
notDownReplicas: 2,
@@ -319,8 +351,8 @@ func TestFindSolrNodeContents(t *testing.T) {
overseerLeader: false,
live: true,
},
- "pod-2.foo-solrcloud-headless.default:2000_solr": {
- nodeName:
"pod-2.foo-solrcloud-headless.default:2000_solr",
+ "foo-solrcloud-2.foo-solrcloud-headless.default:2000_solr": {
+ nodeName:
"foo-solrcloud-2.foo-solrcloud-headless.default:2000_solr",
leaders: 0,
replicas: 2,
notDownReplicas: 2,
@@ -335,8 +367,8 @@ func TestFindSolrNodeContents(t *testing.T) {
overseerLeader: false,
live: true,
},
- "pod-3.foo-solrcloud-headless.default:2000_solr": {
- nodeName:
"pod-3.foo-solrcloud-headless.default:2000_solr",
+ "foo-solrcloud-3.foo-solrcloud-headless.default:2000_solr": {
+ nodeName:
"foo-solrcloud-3.foo-solrcloud-headless.default:2000_solr",
leaders: 2,
replicas: 3,
notDownReplicas: 1,
@@ -355,8 +387,8 @@ func TestFindSolrNodeContents(t *testing.T) {
overseerLeader: false,
live: true,
},
- "pod-4.foo-solrcloud-headless.default:2000_solr": {
- nodeName:
"pod-4.foo-solrcloud-headless.default:2000_solr",
+ "foo-solrcloud-4.foo-solrcloud-headless.default:2000_solr": {
+ nodeName:
"foo-solrcloud-4.foo-solrcloud-headless.default:2000_solr",
leaders: 0,
replicas: 1,
notDownReplicas: 1,
@@ -370,8 +402,8 @@ func TestFindSolrNodeContents(t *testing.T) {
overseerLeader: false,
live: false,
},
- "pod-5.foo-solrcloud-headless.default:2000_solr": {
- nodeName:
"pod-5.foo-solrcloud-headless.default:2000_solr",
+ "foo-solrcloud-5.foo-solrcloud-headless.default:2000_solr": {
+ nodeName:
"foo-solrcloud-5.foo-solrcloud-headless.default:2000_solr",
leaders: 1,
replicas: 3,
notDownReplicas: 3,
@@ -386,8 +418,8 @@ func TestFindSolrNodeContents(t *testing.T) {
overseerLeader: false,
live: true,
},
- "pod-6.foo-solrcloud-headless.default:2000_solr": {
- nodeName:
"pod-6.foo-solrcloud-headless.default:2000_solr",
+ "foo-solrcloud-6.foo-solrcloud-headless.default:2000_solr": {
+ nodeName:
"foo-solrcloud-6.foo-solrcloud-headless.default:2000_solr",
leaders: 0,
replicas: 0,
notDownReplicas: 0,
@@ -428,6 +460,7 @@ func TestCalculateMaxPodsToUpgrade(t *testing.T) {
solrCloud := &solr.SolrCloud{
ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace:
"default"},
Spec: solr.SolrCloudSpec{
+ Replicas: Replicas(10),
SolrAddressability: solr.SolrAddressabilityOptions{
PodPort: 2000,
},
@@ -440,38 +473,38 @@ func TestCalculateMaxPodsToUpgrade(t *testing.T) {
},
}
- foundMaxPodsUnavailable, foundUnavailableUpdatedPodCount,
foundMaxPodsToUpdate := calculateMaxPodsToUpdate(solrCloud, 10, 4, 0, 4)
+ foundMaxPodsUnavailable, foundUnavailableUpdatedPodCount,
foundMaxPodsToUpdate := calculateMaxPodsToUpdate(solrCloud, 4, 0, 4)
assert.Equal(t, 2, foundMaxPodsUnavailable, "Incorrect value of
maxPodsUnavailable given fromInt(2)")
assert.Equal(t, 2, foundUnavailableUpdatedPodCount, "Incorrect value of
unavailableUpdatedPodCount")
assert.Equal(t, 0, foundMaxPodsToUpdate, "Incorrect value of
maxPodsToUpdate")
- foundMaxPodsUnavailable, foundUnavailableUpdatedPodCount,
foundMaxPodsToUpdate = calculateMaxPodsToUpdate(solrCloud, 10, 4, 0, 3)
+ foundMaxPodsUnavailable, foundUnavailableUpdatedPodCount,
foundMaxPodsToUpdate = calculateMaxPodsToUpdate(solrCloud, 4, 0, 3)
assert.Equal(t, 2, foundMaxPodsUnavailable, "Incorrect value of
maxPodsUnavailable given fromInt(2)")
assert.Equal(t, 3, foundUnavailableUpdatedPodCount, "Incorrect value of
unavailableUpdatedPodCount")
assert.Equal(t, -1, foundMaxPodsToUpdate, "Incorrect value of
maxPodsToUpdate")
- foundMaxPodsUnavailable, foundUnavailableUpdatedPodCount,
foundMaxPodsToUpdate = calculateMaxPodsToUpdate(solrCloud, 10, 3, 1, 3)
+ foundMaxPodsUnavailable, foundUnavailableUpdatedPodCount,
foundMaxPodsToUpdate = calculateMaxPodsToUpdate(solrCloud, 3, 1, 3)
assert.Equal(t, 2, foundMaxPodsUnavailable, "Incorrect value of
maxPodsUnavailable given fromInt(2)")
assert.Equal(t, 3, foundUnavailableUpdatedPodCount, "Incorrect value of
unavailableUpdatedPodCount")
assert.Equal(t, -2, foundMaxPodsToUpdate, "Incorrect value of
maxPodsToUpdate")
maxPodsUnavailable = intstr.FromString("45%")
- foundMaxPodsUnavailable, foundUnavailableUpdatedPodCount,
foundMaxPodsToUpdate = calculateMaxPodsToUpdate(solrCloud, 10, 3, 0, 5)
+ foundMaxPodsUnavailable, foundUnavailableUpdatedPodCount,
foundMaxPodsToUpdate = calculateMaxPodsToUpdate(solrCloud, 3, 0, 5)
assert.Equal(t, 4, foundMaxPodsUnavailable, "Incorrect value of
maxPodsUnavailable given fromString(\"45%\")")
assert.Equal(t, 2, foundMaxPodsToUpdate, "Incorrect value of
maxPodsToUpdate")
maxPodsUnavailable = intstr.FromString("45%")
- foundMaxPodsUnavailable, foundUnavailableUpdatedPodCount,
foundMaxPodsToUpdate = calculateMaxPodsToUpdate(solrCloud, 10, 1, 2, 5)
+ foundMaxPodsUnavailable, foundUnavailableUpdatedPodCount,
foundMaxPodsToUpdate = calculateMaxPodsToUpdate(solrCloud, 1, 2, 5)
assert.Equal(t, 4, foundMaxPodsUnavailable, "Incorrect value of
maxPodsUnavailable given fromString(\"45%\")")
assert.Equal(t, 0, foundMaxPodsToUpdate, "Incorrect value of
maxPodsToUpdate")
maxPodsUnavailable = intstr.FromString("70%")
- foundMaxPodsUnavailable, foundUnavailableUpdatedPodCount,
foundMaxPodsToUpdate = calculateMaxPodsToUpdate(solrCloud, 10, 3, 0, 2)
+ foundMaxPodsUnavailable, foundUnavailableUpdatedPodCount,
foundMaxPodsToUpdate = calculateMaxPodsToUpdate(solrCloud, 3, 0, 2)
assert.Equal(t, 7, foundMaxPodsUnavailable, "Incorrect value of
maxPodsUnavailable given fromString(\"70%\")")
assert.Equal(t, 2, foundMaxPodsToUpdate, "Incorrect value of
maxPodsToUpdate")
solrCloud.Spec.UpdateStrategy.ManagedUpdateOptions.MaxPodsUnavailable =
nil
- foundMaxPodsUnavailable, foundUnavailableUpdatedPodCount,
foundMaxPodsToUpdate = calculateMaxPodsToUpdate(solrCloud, 10, 3, 0, 2)
+ foundMaxPodsUnavailable, foundUnavailableUpdatedPodCount,
foundMaxPodsToUpdate = calculateMaxPodsToUpdate(solrCloud, 3, 0, 2)
assert.Equal(t, 2, foundMaxPodsUnavailable, "Incorrect value of
maxPodsUnavailable given fromString(\"25%\")")
assert.Equal(t, -3, foundMaxPodsToUpdate, "Incorrect value of
maxPodsToUpdate")
}
@@ -488,25 +521,25 @@ func TestSolrNodeName(t *testing.T) {
}
pod := corev1.Pod{
- ObjectMeta: metav1.ObjectMeta{Name: "pod-0"},
+ ObjectMeta: metav1.ObjectMeta{Name: "foo-solrcloud-0"},
Spec: corev1.PodSpec{},
}
- assert.Equal(t, "pod-0.foo-solrcloud-headless.default:2000_solr",
SolrNodeName(solrCloud, pod), "Incorrect generation of Solr nodeName")
+ assert.Equal(t,
"foo-solrcloud-0.foo-solrcloud-headless.default:2000_solr",
SolrNodeName(solrCloud, pod.Name), "Incorrect generation of Solr nodeName")
solrCloud.Spec.SolrAddressability.PodPort = 3000
- assert.Equal(t, "pod-0.foo-solrcloud-headless.default:3000_solr",
SolrNodeName(solrCloud, pod), "Incorrect generation of Solr nodeName")
+ assert.Equal(t,
"foo-solrcloud-0.foo-solrcloud-headless.default:3000_solr",
SolrNodeName(solrCloud, pod.Name), "Incorrect generation of Solr nodeName")
}
var (
testRecoveringClusterStatus = solr_api.SolrClusterStatus{
LiveNodes: []string{
- "pod-0.foo-solrcloud-headless.default:2000_solr",
- "pod-1.foo-solrcloud-headless.default:2000_solr",
- "pod-2.foo-solrcloud-headless.default:2000_solr",
- "pod-3.foo-solrcloud-headless.default:2000_solr",
- "pod-5.foo-solrcloud-headless.default:2000_solr",
- "pod-6.foo-solrcloud-headless.default:2000_solr",
+
"foo-solrcloud-0.foo-solrcloud-headless.default:2000_solr",
+
"foo-solrcloud-1.foo-solrcloud-headless.default:2000_solr",
+
"foo-solrcloud-2.foo-solrcloud-headless.default:2000_solr",
+
"foo-solrcloud-3.foo-solrcloud-headless.default:2000_solr",
+
"foo-solrcloud-5.foo-solrcloud-headless.default:2000_solr",
+
"foo-solrcloud-6.foo-solrcloud-headless.default:2000_solr",
},
Collections: map[string]solr_api.SolrCollectionStatus{
"col1": {
@@ -516,24 +549,24 @@ var (
"rep-1-1-1": {
State:
solr_api.ReplicaActive,
Core:
"core1",
- NodeName:
"pod-0.foo-solrcloud-headless.default:2000_solr",
- BaseUrl:
"pod-0.foo-solrcloud-headless.default:2000/solr/rep-1-1-1",
+ NodeName:
"foo-solrcloud-0.foo-solrcloud-headless.default:2000_solr",
+ BaseUrl:
"foo-solrcloud-0.foo-solrcloud-headless.default:2000/solr/rep-1-1-1",
Leader: false,
Type:
solr_api.PULL,
},
"rep-1-1-2": {
State:
solr_api.ReplicaRecovering,
Core:
"core1",
- NodeName:
"pod-2.foo-solrcloud-headless.default:2000_solr",
- BaseUrl:
"pod-2.foo-solrcloud-headless.default:2000/solr/rep-1-1-2",
+ NodeName:
"foo-solrcloud-2.foo-solrcloud-headless.default:2000_solr",
+ BaseUrl:
"foo-solrcloud-2.foo-solrcloud-headless.default:2000/solr/rep-1-1-2",
Leader: false,
Type:
solr_api.TLOG,
},
"rep-1-1-3": {
State:
solr_api.ReplicaActive,
Core:
"core1",
- NodeName:
"pod-3.foo-solrcloud-headless.default:2000_solr",
- BaseUrl:
"pod-3.foo-solrcloud-headless.default:2000/solr/rep-1-1-3",
+ NodeName:
"foo-solrcloud-3.foo-solrcloud-headless.default:2000_solr",
+ BaseUrl:
"foo-solrcloud-3.foo-solrcloud-headless.default:2000/solr/rep-1-1-3",
Leader: true,
Type:
solr_api.TLOG,
},
@@ -545,24 +578,24 @@ var (
"rep-1-2-1": {
State:
solr_api.ReplicaActive,
Core:
"core1",
- NodeName:
"pod-2.foo-solrcloud-headless.default:2000_solr",
- BaseUrl:
"pod-2.foo-solrcloud-headless.default:2000/solr/rep-1-2-1",
+ NodeName:
"foo-solrcloud-2.foo-solrcloud-headless.default:2000_solr",
+ BaseUrl:
"foo-solrcloud-2.foo-solrcloud-headless.default:2000/solr/rep-1-2-1",
Leader: false,
Type:
solr_api.NRT,
},
"rep-1-2-2": {
State:
solr_api.ReplicaRecovering,
Core:
"core1",
- NodeName:
"pod-5.foo-solrcloud-headless.default:2000_solr",
- BaseUrl:
"pod-5.foo-solrcloud-headless.default:2000/solr/rep-1-2-2",
+ NodeName:
"foo-solrcloud-5.foo-solrcloud-headless.default:2000_solr",
+ BaseUrl:
"foo-solrcloud-5.foo-solrcloud-headless.default:2000/solr/rep-1-2-2",
Leader: false,
Type:
solr_api.NRT,
},
"rep-1-2-3": {
State:
solr_api.ReplicaActive,
Core:
"core1",
- NodeName:
"pod-1.foo-solrcloud-headless.default:2000_solr",
- BaseUrl:
"pod-1.foo-solrcloud-headless.default:2000/solr/rep-1-2-3",
+ NodeName:
"foo-solrcloud-1.foo-solrcloud-headless.default:2000_solr",
+ BaseUrl:
"foo-solrcloud-1.foo-solrcloud-headless.default:2000/solr/rep-1-2-3",
Leader: true,
Type:
solr_api.NRT,
},
@@ -579,24 +612,24 @@ var (
"rep-2-1-1": {
State:
solr_api.ReplicaActive,
Core:
"core1",
- NodeName:
"pod-4.foo-solrcloud-headless.default:2000_solr",
- BaseUrl:
"pod-4.foo-solrcloud-headless.default:2000/solr/rep-2-1-1",
+ NodeName:
"foo-solrcloud-4.foo-solrcloud-headless.default:2000_solr",
+ BaseUrl:
"foo-solrcloud-4.foo-solrcloud-headless.default:2000/solr/rep-2-1-1",
Leader: false,
Type:
solr_api.PULL,
},
"rep-2-1-2": {
State:
solr_api.ReplicaActive,
Core:
"core1",
- NodeName:
"pod-1.foo-solrcloud-headless.default:2000_solr",
- BaseUrl:
"pod-1.foo-solrcloud-headless.default:2000/solr/rep-2-1-2",
+ NodeName:
"foo-solrcloud-1.foo-solrcloud-headless.default:2000_solr",
+ BaseUrl:
"foo-solrcloud-1.foo-solrcloud-headless.default:2000/solr/rep-2-1-2",
Leader: false,
Type:
solr_api.TLOG,
},
"rep-2-1-3": {
State:
solr_api.ReplicaDown,
Core:
"core1",
- NodeName:
"pod-3.foo-solrcloud-headless.default:2000_solr",
- BaseUrl:
"pod-3.foo-solrcloud-headless.default:2000/solr/rep-2-1-3",
+ NodeName:
"foo-solrcloud-3.foo-solrcloud-headless.default:2000_solr",
+ BaseUrl:
"foo-solrcloud-3.foo-solrcloud-headless.default:2000/solr/rep-2-1-3",
Leader: true,
Type:
solr_api.TLOG,
},
@@ -608,32 +641,32 @@ var (
"rep-2-2-1": {
State:
solr_api.ReplicaDown,
Core:
"core1",
- NodeName:
"pod-3.foo-solrcloud-headless.default:2000_solr",
- BaseUrl:
"pod-3.foo-solrcloud-headless.default:2000/solr/rep-2-2-1",
+ NodeName:
"foo-solrcloud-3.foo-solrcloud-headless.default:2000_solr",
+ BaseUrl:
"foo-solrcloud-3.foo-solrcloud-headless.default:2000/solr/rep-2-2-1",
Leader: false,
Type:
solr_api.NRT,
},
"rep-2-2-2": {
State:
solr_api.ReplicaRecoveryFailed,
Core:
"core1",
- NodeName:
"pod-0.foo-solrcloud-headless.default:2000_solr",
- BaseUrl:
"pod-0.foo-solrcloud-headless.default:2000/solr/rep-2-2-2",
+ NodeName:
"foo-solrcloud-0.foo-solrcloud-headless.default:2000_solr",
+ BaseUrl:
"foo-solrcloud-0.foo-solrcloud-headless.default:2000/solr/rep-2-2-2",
Leader: false,
Type:
solr_api.NRT,
},
"rep-2-2-3": {
State:
solr_api.ReplicaActive,
Core:
"core1",
- NodeName:
"pod-5.foo-solrcloud-headless.default:2000_solr",
- BaseUrl:
"pod-5.foo-solrcloud-headless.default:2000/solr/rep-2-2-3",
+ NodeName:
"foo-solrcloud-5.foo-solrcloud-headless.default:2000_solr",
+ BaseUrl:
"foo-solrcloud-5.foo-solrcloud-headless.default:2000/solr/rep-2-2-3",
Leader: true,
Type:
solr_api.NRT,
},
"rep-2-2-4": {
State:
solr_api.ReplicaActive,
Core:
"core1",
- NodeName:
"pod-5.foo-solrcloud-headless.default:2000_solr",
- BaseUrl:
"pod-5.foo-solrcloud-headless.default:2000/solr/rep-2-2-4",
+ NodeName:
"foo-solrcloud-5.foo-solrcloud-headless.default:2000_solr",
+ BaseUrl:
"foo-solrcloud-5.foo-solrcloud-headless.default:2000/solr/rep-2-2-4",
Leader: false,
Type:
solr_api.NRT,
},
@@ -648,12 +681,12 @@ var (
testDownClusterStatus = solr_api.SolrClusterStatus{
LiveNodes: []string{
- "pod-0.foo-solrcloud-headless.default:2000_solr",
- "pod-1.foo-solrcloud-headless.default:2000_solr",
- "pod-2.foo-solrcloud-headless.default:2000_solr",
- "pod-3.foo-solrcloud-headless.default:2000_solr",
- "pod-4.foo-solrcloud-headless.default:2000_solr",
- "pod-5.foo-solrcloud-headless.default:2000_solr",
+
"foo-solrcloud-0.foo-solrcloud-headless.default:2000_solr",
+
"foo-solrcloud-1.foo-solrcloud-headless.default:2000_solr",
+
"foo-solrcloud-2.foo-solrcloud-headless.default:2000_solr",
+
"foo-solrcloud-3.foo-solrcloud-headless.default:2000_solr",
+
"foo-solrcloud-4.foo-solrcloud-headless.default:2000_solr",
+
"foo-solrcloud-5.foo-solrcloud-headless.default:2000_solr",
},
Collections: map[string]solr_api.SolrCollectionStatus{
"col1": {
@@ -663,24 +696,24 @@ var (
"rep-1-1-1": {
State:
solr_api.ReplicaActive,
Core:
"core1",
- NodeName:
"pod-0.foo-solrcloud-headless.default:2000_solr",
- BaseUrl:
"pod-0.foo-solrcloud-headless.default:2000/solr/rep-1-1-1",
+ NodeName:
"foo-solrcloud-0.foo-solrcloud-headless.default:2000_solr",
+ BaseUrl:
"foo-solrcloud-0.foo-solrcloud-headless.default:2000/solr/rep-1-1-1",
Leader: false,
Type:
solr_api.PULL,
},
"rep-1-1-2": {
State:
solr_api.ReplicaActive,
Core:
"core1",
- NodeName:
"pod-2.foo-solrcloud-headless.default:2000_solr",
- BaseUrl:
"pod-2.foo-solrcloud-headless.default:2000/solr/rep-1-1-2",
+ NodeName:
"foo-solrcloud-2.foo-solrcloud-headless.default:2000_solr",
+ BaseUrl:
"foo-solrcloud-2.foo-solrcloud-headless.default:2000/solr/rep-1-1-2",
Leader: false,
Type:
solr_api.TLOG,
},
"rep-1-1-3": {
State:
solr_api.ReplicaActive,
Core:
"core1",
- NodeName:
"pod-3.foo-solrcloud-headless.default:2000_solr",
- BaseUrl:
"pod-3.foo-solrcloud-headless.default:2000/solr/rep-1-1-3",
+ NodeName:
"foo-solrcloud-3.foo-solrcloud-headless.default:2000_solr",
+ BaseUrl:
"foo-solrcloud-3.foo-solrcloud-headless.default:2000/solr/rep-1-1-3",
Leader: true,
Type:
solr_api.TLOG,
},
@@ -692,24 +725,24 @@ var (
"rep-1-2-1": {
State:
solr_api.ReplicaActive,
Core:
"core1",
- NodeName:
"pod-2.foo-solrcloud-headless.default:2000_solr",
- BaseUrl:
"pod-2.foo-solrcloud-headless.default:2000/solr/rep-1-2-1",
+ NodeName:
"foo-solrcloud-2.foo-solrcloud-headless.default:2000_solr",
+ BaseUrl:
"foo-solrcloud-2.foo-solrcloud-headless.default:2000/solr/rep-1-2-1",
Leader: false,
Type:
solr_api.NRT,
},
"rep-1-2-2": {
State:
solr_api.ReplicaActive,
Core:
"core1",
- NodeName:
"pod-5.foo-solrcloud-headless.default:2000_solr",
- BaseUrl:
"pod-5.foo-solrcloud-headless.default:2000/solr/rep-1-2-2",
+ NodeName:
"foo-solrcloud-5.foo-solrcloud-headless.default:2000_solr",
+ BaseUrl:
"foo-solrcloud-5.foo-solrcloud-headless.default:2000/solr/rep-1-2-2",
Leader: false,
Type:
solr_api.NRT,
},
"rep-1-2-3": {
State:
solr_api.ReplicaActive,
Core:
"core1",
- NodeName:
"pod-1.foo-solrcloud-headless.default:2000_solr",
- BaseUrl:
"pod-1.foo-solrcloud-headless.default:2000/solr/rep-1-2-3",
+ NodeName:
"foo-solrcloud-1.foo-solrcloud-headless.default:2000_solr",
+ BaseUrl:
"foo-solrcloud-1.foo-solrcloud-headless.default:2000/solr/rep-1-2-3",
Leader: true,
Type:
solr_api.NRT,
},
@@ -726,24 +759,24 @@ var (
"rep-2-1-1": {
State:
solr_api.ReplicaActive,
Core:
"core1",
- NodeName:
"pod-4.foo-solrcloud-headless.default:2000_solr",
- BaseUrl:
"pod-4.foo-solrcloud-headless.default:2000/solr/rep-2-1-1",
+ NodeName:
"foo-solrcloud-4.foo-solrcloud-headless.default:2000_solr",
+ BaseUrl:
"foo-solrcloud-4.foo-solrcloud-headless.default:2000/solr/rep-2-1-1",
Leader: false,
Type:
solr_api.PULL,
},
"rep-2-1-2": {
State:
solr_api.ReplicaActive,
Core:
"core1",
- NodeName:
"pod-1.foo-solrcloud-headless.default:2000_solr",
- BaseUrl:
"pod-1.foo-solrcloud-headless.default:2000/solr/rep-2-1-2",
+ NodeName:
"foo-solrcloud-1.foo-solrcloud-headless.default:2000_solr",
+ BaseUrl:
"foo-solrcloud-1.foo-solrcloud-headless.default:2000/solr/rep-2-1-2",
Leader: false,
Type:
solr_api.TLOG,
},
"rep-2-1-3": {
State:
solr_api.ReplicaDown,
Core:
"core1",
- NodeName:
"pod-3.foo-solrcloud-headless.default:2000_solr",
- BaseUrl:
"pod-3.foo-solrcloud-headless.default:2000/solr/rep-2-1-3",
+ NodeName:
"foo-solrcloud-3.foo-solrcloud-headless.default:2000_solr",
+ BaseUrl:
"foo-solrcloud-3.foo-solrcloud-headless.default:2000/solr/rep-2-1-3",
Leader: true,
Type:
solr_api.TLOG,
},
@@ -755,32 +788,32 @@ var (
"rep-2-2-1": {
State:
solr_api.ReplicaDown,
Core:
"core1",
- NodeName:
"pod-3.foo-solrcloud-headless.default:2000_solr",
- BaseUrl:
"pod-3.foo-solrcloud-headless.default:2000/solr/rep-2-2-1",
+ NodeName:
"foo-solrcloud-3.foo-solrcloud-headless.default:2000_solr",
+ BaseUrl:
"foo-solrcloud-3.foo-solrcloud-headless.default:2000/solr/rep-2-2-1",
Leader: false,
Type:
solr_api.NRT,
},
"rep-2-2-2": {
State:
solr_api.ReplicaActive,
Core:
"core1",
- NodeName:
"pod-0.foo-solrcloud-headless.default:2000_solr",
- BaseUrl:
"pod-0.foo-solrcloud-headless.default:2000/solr/rep-2-2-2",
+ NodeName:
"foo-solrcloud-0.foo-solrcloud-headless.default:2000_solr",
+ BaseUrl:
"foo-solrcloud-0.foo-solrcloud-headless.default:2000/solr/rep-2-2-2",
Leader: false,
Type:
solr_api.NRT,
},
"rep-2-2-3": {
State:
solr_api.ReplicaActive,
Core:
"core1",
- NodeName:
"pod-5.foo-solrcloud-headless.default:2000_solr",
- BaseUrl:
"pod-5.foo-solrcloud-headless.default:2000/solr/rep-2-2-3",
+ NodeName:
"foo-solrcloud-5.foo-solrcloud-headless.default:2000_solr",
+ BaseUrl:
"foo-solrcloud-5.foo-solrcloud-headless.default:2000/solr/rep-2-2-3",
Leader: true,
Type:
solr_api.NRT,
},
"rep-2-2-4": {
State:
solr_api.ReplicaActive,
Core:
"core1",
- NodeName:
"pod-5.foo-solrcloud-headless.default:2000_solr",
- BaseUrl:
"pod-5.foo-solrcloud-headless.default:2000/solr/rep-2-2-4",
+ NodeName:
"foo-solrcloud-5.foo-solrcloud-headless.default:2000_solr",
+ BaseUrl:
"foo-solrcloud-5.foo-solrcloud-headless.default:2000/solr/rep-2-2-4",
Leader: false,
Type:
solr_api.NRT,
},
@@ -795,12 +828,12 @@ var (
testHealthyClusterStatus = solr_api.SolrClusterStatus{
LiveNodes: []string{
- "pod-0.foo-solrcloud-headless.default:2000_solr",
- "pod-1.foo-solrcloud-headless.default:2000_solr",
- "pod-2.foo-solrcloud-headless.default:2000_solr",
- "pod-3.foo-solrcloud-headless.default:2000_solr",
- "pod-4.foo-solrcloud-headless.default:2000_solr",
- "pod-5.foo-solrcloud-headless.default:2000_solr",
+
"foo-solrcloud-0.foo-solrcloud-headless.default:2000_solr",
+
"foo-solrcloud-1.foo-solrcloud-headless.default:2000_solr",
+
"foo-solrcloud-2.foo-solrcloud-headless.default:2000_solr",
+
"foo-solrcloud-3.foo-solrcloud-headless.default:2000_solr",
+
"foo-solrcloud-4.foo-solrcloud-headless.default:2000_solr",
+
"foo-solrcloud-5.foo-solrcloud-headless.default:2000_solr",
},
Collections: map[string]solr_api.SolrCollectionStatus{
"col1": {
@@ -810,24 +843,24 @@ var (
"rep-1-1-1": {
State:
solr_api.ReplicaActive,
Core:
"core1",
- NodeName:
"pod-0.foo-solrcloud-headless.default:2000_solr",
- BaseUrl:
"pod-0.foo-solrcloud-headless.default:2000/solr/rep-1-1-1",
+ NodeName:
"foo-solrcloud-0.foo-solrcloud-headless.default:2000_solr",
+ BaseUrl:
"foo-solrcloud-0.foo-solrcloud-headless.default:2000/solr/rep-1-1-1",
Leader: false,
Type:
solr_api.PULL,
},
"rep-1-1-2": {
State:
solr_api.ReplicaActive,
Core:
"core1",
- NodeName:
"pod-2.foo-solrcloud-headless.default:2000_solr",
- BaseUrl:
"pod-2.foo-solrcloud-headless.default:2000/solr/rep-1-1-2",
+ NodeName:
"foo-solrcloud-2.foo-solrcloud-headless.default:2000_solr",
+ BaseUrl:
"foo-solrcloud-2.foo-solrcloud-headless.default:2000/solr/rep-1-1-2",
Leader: false,
Type:
solr_api.TLOG,
},
"rep-1-1-3": {
State:
solr_api.ReplicaActive,
Core:
"core1",
- NodeName:
"pod-3.foo-solrcloud-headless.default:2000_solr",
- BaseUrl:
"pod-3.foo-solrcloud-headless.default:2000/solr/rep-1-1-3",
+ NodeName:
"foo-solrcloud-3.foo-solrcloud-headless.default:2000_solr",
+ BaseUrl:
"foo-solrcloud-3.foo-solrcloud-headless.default:2000/solr/rep-1-1-3",
Leader: true,
Type:
solr_api.TLOG,
},
@@ -839,24 +872,24 @@ var (
"rep-1-2-1": {
State:
solr_api.ReplicaActive,
Core:
"core1",
- NodeName:
"pod-2.foo-solrcloud-headless.default:2000_solr",
- BaseUrl:
"pod-2.foo-solrcloud-headless.default:2000/solr/rep-1-2-1",
+ NodeName:
"foo-solrcloud-2.foo-solrcloud-headless.default:2000_solr",
+ BaseUrl:
"foo-solrcloud-2.foo-solrcloud-headless.default:2000/solr/rep-1-2-1",
Leader: false,
Type:
solr_api.NRT,
},
"rep-1-2-2": {
State:
solr_api.ReplicaActive,
Core:
"core1",
- NodeName:
"pod-5.foo-solrcloud-headless.default:2000_solr",
- BaseUrl:
"pod-5.foo-solrcloud-headless.default:2000/solr/rep-1-2-2",
+ NodeName:
"foo-solrcloud-5.foo-solrcloud-headless.default:2000_solr",
+ BaseUrl:
"foo-solrcloud-5.foo-solrcloud-headless.default:2000/solr/rep-1-2-2",
Leader: false,
Type:
solr_api.NRT,
},
"rep-1-2-3": {
State:
solr_api.ReplicaActive,
Core:
"core1",
- NodeName:
"pod-1.foo-solrcloud-headless.default:2000_solr",
- BaseUrl:
"pod-1.foo-solrcloud-headless.default:2000/solr/rep-1-2-3",
+ NodeName:
"foo-solrcloud-1.foo-solrcloud-headless.default:2000_solr",
+ BaseUrl:
"foo-solrcloud-1.foo-solrcloud-headless.default:2000/solr/rep-1-2-3",
Leader: true,
Type:
solr_api.NRT,
},
@@ -873,24 +906,24 @@ var (
"rep-2-1-1": {
State:
solr_api.ReplicaActive,
Core:
"core1",
- NodeName:
"pod-4.foo-solrcloud-headless.default:2000_solr",
- BaseUrl:
"pod-4.foo-solrcloud-headless.default:2000/solr/rep-2-1-1",
+ NodeName:
"foo-solrcloud-4.foo-solrcloud-headless.default:2000_solr",
+ BaseUrl:
"foo-solrcloud-4.foo-solrcloud-headless.default:2000/solr/rep-2-1-1",
Leader: false,
Type:
solr_api.PULL,
},
"rep-2-1-2": {
State:
solr_api.ReplicaActive,
Core:
"core1",
- NodeName:
"pod-1.foo-solrcloud-headless.default:2000_solr",
- BaseUrl:
"pod-1.foo-solrcloud-headless.default:2000/solr/rep-2-1-2",
+ NodeName:
"foo-solrcloud-1.foo-solrcloud-headless.default:2000_solr",
+ BaseUrl:
"foo-solrcloud-1.foo-solrcloud-headless.default:2000/solr/rep-2-1-2",
Leader: false,
Type:
solr_api.TLOG,
},
"rep-2-1-3": {
State:
solr_api.ReplicaActive,
Core:
"core1",
- NodeName:
"pod-3.foo-solrcloud-headless.default:2000_solr",
- BaseUrl:
"pod-3.foo-solrcloud-headless.default:2000/solr/rep-2-1-3",
+ NodeName:
"foo-solrcloud-3.foo-solrcloud-headless.default:2000_solr",
+ BaseUrl:
"foo-solrcloud-3.foo-solrcloud-headless.default:2000/solr/rep-2-1-3",
Leader: true,
Type:
solr_api.TLOG,
},
@@ -902,32 +935,32 @@ var (
"rep-2-2-1": {
State:
solr_api.ReplicaActive,
Core:
"core1",
- NodeName:
"pod-3.foo-solrcloud-headless.default:2000_solr",
- BaseUrl:
"pod-3.foo-solrcloud-headless.default:2000/solr/rep-2-2-1",
+ NodeName:
"foo-solrcloud-3.foo-solrcloud-headless.default:2000_solr",
+ BaseUrl:
"foo-solrcloud-3.foo-solrcloud-headless.default:2000/solr/rep-2-2-1",
Leader: false,
Type:
solr_api.NRT,
},
"rep-2-2-2": {
State:
solr_api.ReplicaActive,
Core:
"core1",
- NodeName:
"pod-0.foo-solrcloud-headless.default:2000_solr",
- BaseUrl:
"pod-0.foo-solrcloud-headless.default:2000/solr/rep-2-2-2",
+ NodeName:
"foo-solrcloud-0.foo-solrcloud-headless.default:2000_solr",
+ BaseUrl:
"foo-solrcloud-0.foo-solrcloud-headless.default:2000/solr/rep-2-2-2",
Leader: false,
Type:
solr_api.NRT,
},
"rep-2-2-3": {
State:
solr_api.ReplicaActive,
Core:
"core1",
- NodeName:
"pod-5.foo-solrcloud-headless.default:2000_solr",
- BaseUrl:
"pod-5.foo-solrcloud-headless.default:2000/solr/rep-2-2-3",
+ NodeName:
"foo-solrcloud-5.foo-solrcloud-headless.default:2000_solr",
+ BaseUrl:
"foo-solrcloud-5.foo-solrcloud-headless.default:2000/solr/rep-2-2-3",
Leader: true,
Type:
solr_api.NRT,
},
"rep-2-2-4": {
State:
solr_api.ReplicaActive,
Core:
"core1",
- NodeName:
"pod-5.foo-solrcloud-headless.default:2000_solr",
- BaseUrl:
"pod-5.foo-solrcloud-headless.default:2000/solr/rep-2-2-4",
+ NodeName:
"foo-solrcloud-5.foo-solrcloud-headless.default:2000_solr",
+ BaseUrl:
"foo-solrcloud-5.foo-solrcloud-headless.default:2000/solr/rep-2-2-4",
Leader: false,
Type:
solr_api.NRT,
},
diff --git a/helm/solr-operator/Chart.yaml b/helm/solr-operator/Chart.yaml
index 96f1ff4..c5ea9af 100644
--- a/helm/solr-operator/Chart.yaml
+++ b/helm/solr-operator/Chart.yaml
@@ -125,6 +125,13 @@ annotations:
links:
- name: Github PR
url: https://github.com/apache/solr-operator/pull/345
+ - kind: fixed
+ description: Fix for managed restarts across connected SolrCloud
resources.
+ links:
+ - name: Github Issue
+ url: https://github.com/apache/solr-operator/issues/348
+ - name: Github PR
+ url: https://github.com/apache/solr-operator/pull/349
artifacthub.io/images: |
- name: solr-operator
image: apache/solr-operator:v0.5.0-prerelease