Skip to content

Commit

Permalink
Merge branch 'main' into remove-ingress-nodeServices
Browse files Browse the repository at this point in the history
  • Loading branch information
janhoy authored Jan 10, 2025
2 parents 7d48a1d + 77d27a0 commit 087faff
Show file tree
Hide file tree
Showing 21 changed files with 252 additions and 13 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
[![Docker Pulls](https://img.shields.io/docker/pulls/apache/solr-operator)](https://hub.docker.com/r/apache/solr-operator/)
[![Slack](https://img.shields.io/badge/slack-join_chat-white.svg?logo=slack&style=social)](https://kubernetes.slack.com/messages/solr-operator)

The __[Solr Operator](https://solr.apache.org/operator/)__ is the official way of managing an Apache Solr ecosystem within Kubernetes.
The __[Solr Operator](https://solr.apache.org/operator/)__ is the official way of managing Apache SolrCloud deployments within Kubernetes.
It is built on top of the [Kube Builder](https://github.com/kubernetes-sigs/kubebuilder) framework.
Please visit the [official site](https://solr.apache.org/operator/) for more information.

Expand Down
4 changes: 4 additions & 0 deletions api/v1beta1/common_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,10 @@ type PodOptions struct {
// +optional
ServiceAccountName string `json:"serviceAccountName,omitempty"`

// Should process namespace sharing be enabled on created pods
// +optional
ShareProcessNamespace bool `json:"shareProcessNamespace,omitempty"`

// Optional PodSpreadTopologyConstraints to use when scheduling pods.
// More information here: https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/
//
Expand Down
4 changes: 4 additions & 0 deletions config/crd/bases/solr.apache.org_solrclouds.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5082,6 +5082,10 @@ spec:
serviceAccountName:
description: Optional Service Account to run the pod under.
type: string
shareProcessNamespace:
description: Should process namespace sharing be enabled on
created pods
type: boolean
sidecarContainers:
description: Sidecar containers to run in the pod. These are
in addition to the Solr Container
Expand Down
4 changes: 4 additions & 0 deletions config/crd/bases/solr.apache.org_solrprometheusexporters.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3173,6 +3173,10 @@ spec:
serviceAccountName:
description: Optional Service Account to run the pod under.
type: string
shareProcessNamespace:
description: Should process namespace sharing be enabled on
created pods
type: boolean
sidecarContainers:
description: Sidecar containers to run in the pod. These are
in addition to the Solr Container
Expand Down
11 changes: 7 additions & 4 deletions controllers/solrcloud_controller_basic_auth_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -351,10 +351,13 @@ func expectBasicAuthConfigOnPodTemplateWithGomega(g Gomega, solrCloud *solrv1bet

func expectPutSecurityJsonInZkCmd(g Gomega, expInitContainer *corev1.Container) {
g.Expect(expInitContainer).To(Not(BeNil()), "Didn't find the setup-zk InitContainer in the sts!")
expCmd := "ZK_SECURITY_JSON=$(/opt/solr/server/scripts/cloud-scripts/zkcli.sh -zkhost ${ZK_HOST} -cmd get /security.json || echo 'failed-to-get-security.json'); " +
"if [ ${#ZK_SECURITY_JSON} -lt 3 ]; then " +
"echo $SECURITY_JSON > /tmp/security.json; " +
"/opt/solr/server/scripts/cloud-scripts/zkcli.sh -zkhost ${ZK_HOST} -cmd putfile /security.json /tmp/security.json; echo \"put security.json in ZK\"; fi"
expCmd := "solr zk cp zk:/security.json /tmp/current_security.json >/dev/null 2>&1; " +
"GET_CURRENT_SECURITY_JSON_EXIT_CODE=$?; if [ ${GET_CURRENT_SECURITY_JSON_EXIT_CODE} -eq 0 ]; then " +
"if [ ! -s /tmp/current_security.json ] || grep -q '^{}$' /tmp/current_security.json ]; then " +
"echo $SECURITY_JSON > /tmp/security.json; solr zk cp /tmp/security.json zk:/security.json >/dev/null 2>&1; " +
" echo 'Blank security.json found. Put new security.json in ZK'; fi; elif [ ${GET_CURRENT_SECURITY_JSON_EXIT_CODE} -eq 1 ]; then " +
" echo $SECURITY_JSON > /tmp/security.json; solr zk cp /tmp/security.json zk:/security.json >/dev/null 2>&1; " +
" echo 'No security.json found. Put new security.json in ZK'; fi"
g.Expect(expInitContainer.Command[2]).To(ContainSubstring(expCmd), "setup-zk initContainer not configured to bootstrap security.json!")
}

Expand Down
5 changes: 5 additions & 0 deletions controllers/solrcloud_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (
"github.com/apache/solr-operator/controllers/util"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
. "github.com/onsi/gomega/gstruct"
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
Expand Down Expand Up @@ -146,6 +147,7 @@ var _ = FDescribe("SolrCloud controller - General", func() {
Expect(statefulSet.Spec.Template.Spec.Volumes).To(HaveLen(len(extraVolumes)+3), "Pod has wrong number of volumes")
Expect(statefulSet.Spec.Template.Spec.Volumes[3].Name).To(Equal(extraVolumes[0].Name), "Additional Volume from podOptions not loaded into pod properly.")
Expect(statefulSet.Spec.Template.Spec.Volumes[3].VolumeSource).To(Equal(extraVolumes[0].Source), "Additional Volume from podOptions not loaded into pod properly.")
Expect(statefulSet.Spec.Template.Spec.ShareProcessNamespace).Should(PointTo(BeFalse()))
Expect(statefulSet.Spec.Template.Spec.ReadinessGates).To(ContainElement(corev1.PodReadinessGate{ConditionType: util.SolrIsNotStoppedReadinessCondition}), "All pods should contain the isNotStopped readinessGate.")

By("testing the Solr Common Service")
Expand All @@ -169,6 +171,7 @@ var _ = FDescribe("SolrCloud controller - General", func() {

FContext("Solr Cloud with Custom Kube Options", func() {
three := intstr.FromInt(3)
testShareProcessNamespace := true
BeforeEach(func() {
replicas := int32(4)
solrCloud.Spec = solrv1beta1.SolrCloudSpec{
Expand Down Expand Up @@ -213,6 +216,7 @@ var _ = FDescribe("SolrCloud controller - General", func() {
TopologySpreadConstraints: testTopologySpreadConstraints,
DefaultInitContainerResources: testResources2,
InitContainers: extraContainers1,
ShareProcessNamespace: testShareProcessNamespace,
},
StatefulSetOptions: &solrv1beta1.StatefulSetOptions{
Annotations: testSSAnnotations,
Expand Down Expand Up @@ -284,6 +288,7 @@ var _ = FDescribe("SolrCloud controller - General", func() {
Expect(statefulSet.Spec.Template.Spec.ServiceAccountName).To(Equal(testServiceAccountName), "Incorrect serviceAccountName")
Expect(statefulSet.Spec.Template.Spec.TopologySpreadConstraints).To(HaveLen(len(testTopologySpreadConstraints)), "Wrong number of topologySpreadConstraints")
Expect(statefulSet.Spec.Template.Spec.TopologySpreadConstraints[0]).To(Equal(testTopologySpreadConstraints[0]), "Wrong first topologySpreadConstraint")
Expect(statefulSet.Spec.Template.Spec.ShareProcessNamespace).To(Equal(&testShareProcessNamespace), "Wrong shareProcessNamespace value")
expectedSecondTopologyConstraint := testTopologySpreadConstraints[1].DeepCopy()
expectedSecondTopologyConstraint.LabelSelector = statefulSet.Spec.Selector
Expect(statefulSet.Spec.Template.Spec.TopologySpreadConstraints[1]).To(Equal(*expectedSecondTopologyConstraint), "Wrong second topologySpreadConstraint")
Expand Down
18 changes: 14 additions & 4 deletions controllers/util/solr_security_util.go
Original file line number Diff line number Diff line change
Expand Up @@ -237,10 +237,20 @@ func addHostHeaderToProbe(httpGet *corev1.HTTPGetAction, host string) {
}

func cmdToPutSecurityJsonInZk() string {
scriptsDir := "/opt/solr/server/scripts/cloud-scripts"
cmd := " ZK_SECURITY_JSON=$(%s/zkcli.sh -zkhost ${ZK_HOST} -cmd get /security.json || echo 'failed-to-get-security.json'); "
cmd += "if [ ${#ZK_SECURITY_JSON} -lt 3 ]; then echo $SECURITY_JSON > /tmp/security.json; %s/zkcli.sh -zkhost ${ZK_HOST} -cmd putfile /security.json /tmp/security.json; echo \"put security.json in ZK\"; fi"
return fmt.Sprintf(cmd, scriptsDir, scriptsDir)
cmd := " solr zk cp zk:/security.json /tmp/current_security.json >/dev/null 2>&1; " +
" GET_CURRENT_SECURITY_JSON_EXIT_CODE=$?; " +
"if [ ${GET_CURRENT_SECURITY_JSON_EXIT_CODE} -eq 0 ]; then " + // JSON already exists
"if [ ! -s /tmp/current_security.json ] || grep -q '^{}$' /tmp/current_security.json ]; then " + // File doesn't exist, is empty, or is just '{}'
" echo $SECURITY_JSON > /tmp/security.json;" +
" solr zk cp /tmp/security.json zk:/security.json >/dev/null 2>&1; " +
" echo 'Blank security.json found. Put new security.json in ZK'; " +
"fi; " + // TODO: Consider checking a diff and still applying over the top
"elif [ ${GET_CURRENT_SECURITY_JSON_EXIT_CODE} -eq 1 ]; then " + // JSON doesn't exist, but not other error types
" echo $SECURITY_JSON > /tmp/security.json;" +
" solr zk cp /tmp/security.json zk:/security.json >/dev/null 2>&1; " +
" echo 'No security.json found. Put new security.json in ZK'; " +
"fi"
return cmd
}

// Add auth data to the supplied Context using secrets already resolved (stored in the SecurityConfig)
Expand Down
3 changes: 3 additions & 0 deletions controllers/util/solr_util.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ var (
// zkConnectionString: the connectionString of the ZK instance to connect to
func GenerateStatefulSet(solrCloud *solr.SolrCloud, solrCloudStatus *solr.SolrCloudStatus, hostNameIPs map[string]string, reconcileConfigInfo map[string]string, tls *TLSCerts, security *SecurityConfig) *appsv1.StatefulSet {
terminationGracePeriod := int64(60)
shareProcessNamespace := false
solrPodPort := solrCloud.Spec.SolrAddressability.PodPort
defaultFSGroup := int64(DefaultSolrGroup)

Expand Down Expand Up @@ -122,6 +123,7 @@ func GenerateStatefulSet(solrCloud *solr.SolrCloud, solrCloudStatus *solr.SolrCl
if customPodOptions.TerminationGracePeriodSeconds != nil {
terminationGracePeriod = *customPodOptions.TerminationGracePeriodSeconds
}
shareProcessNamespace = customPodOptions.ShareProcessNamespace
}

// The isNotStopped readiness gate will always be used for managedUpdates
Expand Down Expand Up @@ -543,6 +545,7 @@ func GenerateStatefulSet(solrCloud *solr.SolrCloud, solrCloudStatus *solr.SolrCl

Spec: corev1.PodSpec{
TerminationGracePeriodSeconds: &terminationGracePeriod,
ShareProcessNamespace: &shareProcessNamespace,
SecurityContext: &corev1.PodSecurityContext{
FSGroup: &defaultFSGroup,
},
Expand Down
5 changes: 5 additions & 0 deletions docs/development.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,11 @@ export PATH="$PATH:$GOPATH/bin" # You likely want to add this line to your ~/.ba
make install-dependencies
```

Note: if you have previously installed/older versions of dependencies, you can first clear these dependencies with:
```bash
make clean
```

## Build the Solr CRDs

If you have changed anything in the [APIs directory](/api/v1beta1), you will need to run the following command to regenerate all Solr CRDs.
Expand Down
5 changes: 3 additions & 2 deletions docs/solr-cloud/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ Child Pages:
- [Managed Updates](managed-updates.md)
- [Scaling](scaling.md)

The Solr Operator supports creating and managing Solr Clouds.
The Solr Operator supports creating and managing Solr Clouds clusters via its 'solrcloud' resource.
(Note: running Solr in "standalone" mode is not supported.)

This page outlines how to create, update and delete a SolrCloud in Kubernetes.

Expand Down Expand Up @@ -131,4 +132,4 @@ spec:
repository: myprivate-repo.jfrog.io/solr
tag: 8.2.0
imagePullSecret: "k8s-docker-registry-secret"
```
```
4 changes: 2 additions & 2 deletions docs/solr-cloud/solr-cloud-crd.md
Original file line number Diff line number Diff line change
Expand Up @@ -171,9 +171,9 @@ Please refer to the [SolrBackup documentation](../solr-backup) for more informat

## Zookeeper Reference

Solr Clouds require an Apache Zookeeper to connect to.
All SolrCloud resources run Solr in "cloud" mode, and require access to an Apache ZooKeeper cluster for state-management.

The Solr operator gives a few options.
The Solr operator gives a few options for ZooKeeper access:

- Connecting to an already running zookeeper ensemble via [connection strings](#zk-connection-info)
- [Spinning up a provided](#provided-instance) Zookeeper Ensemble in the same namespace via the [Zookeeper Operator](https://github.com/pravega/zookeeper-operator)
Expand Down
24 changes: 24 additions & 0 deletions helm/solr-operator/Chart.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ annotations:
url: https://dist.apache.org/repos/dist/release/solr/KEYS
# Add change log for a single release here.
# Allowed syntax is described at: https://artifacthub.io/docs/topics/annotations/helm/#example
# 'kind' accepts values: "added", "changed", "deprecated", "removed", "fixed" and "security"
artifacthub.io/changes: |
- kind: fixed
description: gen-pkcs12-keystore initContainer now supports 'ca.crt'-less TLS secrets
Expand All @@ -61,6 +62,13 @@ annotations:
url: https://github.com/apache/solr-operator/issues/684
- name: Github PR
url: https://github.com/apache/solr-operator/pull/685
- kind: added
description: SolrClouds now support namespace sharing among pod containers in a pod.
links:
- name: Github Issue
url: https://github.com/apache/solr-operator/issues/716
- name: Github PR
url: https://github.com/apache/solr-operator/pull/735
- kind: changed
description: SolrClouds now support auto-readOnlyRootFilesystem setting.
links:
Expand Down Expand Up @@ -103,6 +111,22 @@ annotations:
url: https://github.com/apache/solr-operator/issues/682
- name: Github PR
url: https://github.com/apache/solr-operator/pull/692
- kind: fixed
description: setup-zk initContainer now gracefully handles absent security.json on initial upload.
links:
- name: Github Issue
url: https://github.com/apache/solr-operator/issues/720
- name: Additional Github Issue
url: https://github.com/apache/solr-operator/issues/731
- name: Github PR
url: https://github.com/apache/solr-operator/pull/738
- kind: added
description: "'imagePullSecret' now used when fetching operator image, if provided."
links:
- name: Github Issue
url: https://github.com/apache/solr-operator/issues/718
- name: Github PR
url: https://github.com/apache/solr-operator/pull/734
- kind: fixed
description: The operator will now delete ingress and per-node services when external ingress is disabled.
links:
Expand Down
1 change: 1 addition & 0 deletions helm/solr-operator/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ The command removes all the Kubernetes components associated with the chart and
| image.repository | string | `"apache/solr-operator"` | The repository of the Solr Operator image |
| image.tag | string | `"v0.9.0-prerelease"` | The tag/version of the Solr Operator to run |
| image.pullPolicy | string | `"IfNotPresent"` | |
| image.imagePullSecret | string | `""` | PullSecret for the Solr Operator image |
| fullnameOverride | string | `""` | A custom name for the Solr Operator Deployment |
| nameOverride | string | `""` | |
| replicaCount | int | `1` | The number of Solr Operator pods to run |
Expand Down
8 changes: 8 additions & 0 deletions helm/solr-operator/crds/crds.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5343,6 +5343,10 @@ spec:
serviceAccountName:
description: Optional Service Account to run the pod under.
type: string
shareProcessNamespace:
description: Should process namespace sharing be enabled on
created pods
type: boolean
sidecarContainers:
description: Sidecar containers to run in the pod. These are
in addition to the Solr Container
Expand Down Expand Up @@ -19456,6 +19460,10 @@ spec:
serviceAccountName:
description: Optional Service Account to run the pod under.
type: string
shareProcessNamespace:
description: Should process namespace sharing be enabled on
created pods
type: boolean
sidecarContainers:
description: Sidecar containers to run in the pod. These are
in addition to the Solr Container
Expand Down
3 changes: 3 additions & 0 deletions helm/solr-operator/templates/deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ spec:
- name: {{ .Chart.Name }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
{{- if .Values.image.imagePullSecret }}
imagePullSecret: {{ .Values.image.imagePullSecret }}
{{- end }}
args:
{{- if or (index .Values "zookeeper-operator" "install") (index .Values "zookeeper-operator" "use") }}
- -zk-operator=true
Expand Down
1 change: 1 addition & 0 deletions helm/solr-operator/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ image:
repository: apache/solr-operator
tag: v0.9.0-prerelease
pullPolicy: IfNotPresent
imagePullSecret: ""

nameOverride: ""
fullnameOverride: ""
Expand Down
1 change: 1 addition & 0 deletions helm/solr/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,7 @@ When using the helm chart, omit `customSolrKubeOptions.`
| podOptions.tolerations | []object | | Specify a list of Kubernetes tolerations for the Solr pod |
| podOptions.topologySpreadConstraints | []object | | Specify a list of Kubernetes topologySpreadConstraints for the Solr pod. No need to provide a `labelSelector`, as the Solr Operator will default that for you. More information can be found in [the documentation](https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/). |
| podOptions.serviceAccountName | string | | Optional serviceAccount to run the Solr pods under |
| podOptions.shareProcessNamespace | boolean | false | Whether containers in a pod should share the same process namespace. |
| podOptions.priorityClassName | string | | Optional priorityClassName for the Solr pod |
| podOptions.sidecarContainers | []object | | An optional list of additional containers to run along side the Solr in its pod |
| podOptions.initContainers | []object | | An optional list of additional initContainers to run before the Solr container starts |
Expand Down
3 changes: 3 additions & 0 deletions helm/solr/templates/_custom_option_helpers.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ resources:
{{- if (include "solr.serviceAccountName.solr" .) -}}
serviceAccountName: {{ include "solr.serviceAccountName.solr" . }}
{{ end }}
{{- if .Values.podOptions.shareProcessNamespace -}}
shareProcessNamespace: {{ .Values.podOptions.shareProcessNamespace }}
{{ end }}
{{- if .Values.podOptions.priorityClassName -}}
priorityClassName: {{ .Values.podOptions.priorityClassName }}
{{ end }}
Expand Down
2 changes: 2 additions & 0 deletions helm/solr/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,8 @@ podOptions:
# Set Solr service account individually instead of the global "serviceAccount.name"
serviceAccountName: ""

shareProcessNamespace: false

# Manage where the Solr pods are scheduled
affinity: {}
tolerations: []
Expand Down
69 changes: 69 additions & 0 deletions tests/e2e/solrcloud_security_json_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package e2e

import (
"context"
solrv1beta1 "github.com/apache/solr-operator/api/v1beta1"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
"k8s.io/utils/pointer"
)

var _ = FDescribe("E2E - SolrCloud - Security JSON", func() {
var (
solrCloud *solrv1beta1.SolrCloud
)

BeforeEach(func() {
solrCloud = generateBaseSolrCloudWithSecurityJSON(1)
})

JustBeforeEach(func(ctx context.Context) {
By("generating the security.json secret and basic auth secret")
generateSolrSecuritySecret(ctx, solrCloud)
generateSolrBasicAuthSecret(ctx, solrCloud)

By("creating the SolrCloud")
Expect(k8sClient.Create(ctx, solrCloud)).To(Succeed())

DeferCleanup(func(ctx context.Context) {
cleanupTest(ctx, solrCloud)
})

By("Waiting for the SolrCloud to come up healthy")
solrCloud = expectSolrCloudToBeReady(ctx, solrCloud)

By("creating a first Solr Collection")
createAndQueryCollection(ctx, solrCloud, "basic", 1, 1)
})

FContext("Provided Zookeeper", func() {
BeforeEach(func() {
solrCloud.Spec.ZookeeperRef = &solrv1beta1.ZookeeperRef{
ProvidedZookeeper: &solrv1beta1.ZookeeperSpec{
Replicas: pointer.Int32(1),
Ephemeral: &solrv1beta1.ZKEphemeral{},
},
}
})

// All testing will be done in the "JustBeforeEach" logic, no additional tests required here
FIt("Starts correctly", func(ctx context.Context) {})
})
})
Loading

0 comments on commit 087faff

Please sign in to comment.