You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@solr.apache.org by ho...@apache.org on 2021/07/06 17:06:11 UTC

[solr-operator] branch main updated: Introduce a Helm chart for Solr Cloud (#276)

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 7051ac7  Introduce a Helm chart for Solr Cloud (#276)
7051ac7 is described below

commit 7051ac72d40a12e31f786cd4d1b0b0f27cc902ad
Author: Houston Putman <ho...@apache.org>
AuthorDate: Tue Jul 6 13:06:04 2021 -0400

    Introduce a Helm chart for Solr Cloud (#276)
---
 Makefile                                           |  19 +-
 docs/local_tutorial.md                             |  46 +---
 hack/release/artifacts/build_helm.sh               |   3 +-
 .../set_signing_key.sh}                            |  26 ++-
 hack/release/version/propagate_version.sh          |  17 +-
 .../version/remove_version_specific_info.sh        |  30 ++-
 hack/release/wizard/releaseWizard.py               |  25 ++-
 hack/release/wizard/releaseWizard.yaml             |  28 ++-
 helm/solr-operator/.helmignore                     |   2 +-
 helm/solr-operator/Chart.yaml                      |  23 +-
 helm/solr-operator/README.md                       |   4 +-
 helm/{solr-operator => solr}/.helmignore           |  17 +-
 helm/solr/Chart.yaml                               |  68 ++++++
 helm/solr/LICENSE                                  | 202 +++++++++++++++++
 helm/solr/NOTICE                                   |   7 +
 helm/solr/README.md                                | 237 +++++++++++++++++++
 helm/solr/templates/NOTES.txt                      |   0
 helm/solr/templates/_custom_option_helpers.tpl     | 240 ++++++++++++++++++++
 helm/solr/templates/_helpers.tpl                   |  80 +++++++
 helm/solr/templates/solrcloud.yaml                 | 193 ++++++++++++++++
 helm/solr/values.yaml                              | 250 +++++++++++++++++++++
 21 files changed, 1442 insertions(+), 75 deletions(-)

diff --git a/Makefile b/Makefile
index acaa3dc..acd5f35 100644
--- a/Makefile
+++ b/Makefile
@@ -57,7 +57,7 @@ tag:
 clean:
 	rm -rf ./bin
 	rm -rf ./release-artifacts
-	rm -rf ./helm/solr-operator/charts ./helm/solr-operator/Chart.lock
+	rm -rf ./helm/*/charts ./helm/*/Chart.lock
 	rm -rf ./cover.out
 	rm -rf ./generated-check
 
@@ -158,7 +158,7 @@ check-generated:
 	diff --recursive api generated-check/api
 
 check-helm:
-	helm lint helm/solr-operator
+	helm lint helm/*
 
 check-mod:
 	rm -rf generated-check
@@ -188,13 +188,14 @@ test:
 # Helm
 ###
 
-# Build the docker image for the operator
+# Build the dependencies for all Helm charts
 helm-dependency-build:
 	helm dependency build helm/solr-operator
+	helm dependency build helm/solr
 
-# Push the docker image for the operator
+# Deploy the current version of the Solr Operator via its helm chart
 helm-deploy-operator: helm-dependency-build docker-build
-	helm install solr-operator helm/solr-operator --set image.version=$(TAG) --set image.repository=$(REPOSITORY)
+	helm install solr-operator helm/solr-operator --set image.version=$(TAG) --set image.repository=$(IMG) --set image.pullPolicy=Never
 
 
 ###
@@ -204,10 +205,10 @@ helm-deploy-operator: helm-dependency-build docker-build
 # Build the docker image for the operator
 docker-build:
 	docker build --build-arg GIT_SHA=$(GIT_SHA) . -t solr-operator -f ./build/Dockerfile
-	docker tag solr-operator ${IMG}:${TAG}
-	docker tag solr-operator ${IMG}:latest
+	docker tag solr-operator $(IMG):$(TAG)
+	docker tag solr-operator $(IMG):latest
 
 # Push the docker image for the operator
 docker-push:
-	docker push ${IMG}:${TAG}
-	docker push ${IMG}:latest
+	docker push $(IMG):$(TAG)
+	docker push $(IMG):latest
diff --git a/docs/local_tutorial.md b/docs/local_tutorial.md
index fb2d2b7..0a11a98 100644
--- a/docs/local_tutorial.md
+++ b/docs/local_tutorial.md
@@ -105,23 +105,13 @@ After inspecting the status of you Kube cluster, you should see a deployment for
 To start a Solr Cloud cluster, we will create a yaml that will tell the Solr Operator what version of Solr Cloud to run, and how many nodes, with how much memory etc.
 
 ```bash
-# Create a  a 3-node cluster v8.3 with 300m Heap each:
-cat <<EOF | kubectl apply -f -
-apiVersion: solr.apache.org/v1beta1
-kind: SolrCloud
-metadata:
-  name: example
-spec:
-  replicas: 3
-  solrImage:
-    tag: "8.3"
-  solrJavaMem: "-Xms300m -Xmx300m"
-  solrAddressability:
-    external:
-      method: Ingress
-      domainName: "ing.local.domain"
-      useExternalAddress: true
-EOF
+# Create a 3-node cluster v8.3 with 300m Heap each:
+helm install example-solr apache-solr/solr --version 0.4.0-prerelease \
+  --set image.tag=8.3 \
+  --set solrOptions.javaMemory="-Xms300m -Xmx300m" \
+  --set addressability.external.method=Ingress \
+  --set addressability.external.domainName="ing.local.domain" \
+  --set addressability.external.useExternalAddress="true"
 
 # The solr-operator has created a new resource type 'solrclouds' which we can query
 # Check the status live as the deploy happens
@@ -192,6 +182,7 @@ spec:
 
 Make sure that you are not overwriting the `SolrCloud.Spec.replicas` field when doing `kubectl apply`,
 otherwise you will be undoing the autoscaler's work.
+By default, the helm chart does not set the `replicas` field, so it is safe to use with the HPA.
 
 ## Upgrade to newer version
 
@@ -201,23 +192,10 @@ So we wish to upgrade to a newer Solr version:
 # Take note of the current version, which is 8.3.1
 curl -s http://default-example-solrcloud.ing.local.domain/solr/admin/info/system | grep solr-i
 
-# Update the solrCloud configuration with the new version, keeping 5 nodes
-cat <<EOF | kubectl apply -f -
-apiVersion: solr.apache.org/v1beta1
-kind: SolrCloud
-metadata:
-  name: example
-spec:
-  replicas: 5
-  solrImage:
-    tag: "8.7"
-  solrJavaMem: "-Xms300m -Xmx300m"
-  solrAddressability:
-    external:
-      method: Ingress
-      domainName: "ing.local.domain"
-      useExternalAddress: true
-EOF
+# Update the solrCloud configuration with the new version, keeping all previous settings and the number of nodes set by the autoscaler.
+helm upgrade example-solr apache-solr/solr --version 0.4.0-prerelease \
+  --reuse-values \
+  --set image.tag=8.7
 
 # Click the 'Show all details" button in Admin UI and start hitting the "Refresh" button
 # See how the operator upgrades one pod at a time. Solr version is in the 'node' column
diff --git a/hack/release/artifacts/build_helm.sh b/hack/release/artifacts/build_helm.sh
index 8524283..445a736 100755
--- a/hack/release/artifacts/build_helm.sh
+++ b/hack/release/artifacts/build_helm.sh
@@ -85,7 +85,8 @@ if [[ -n "${APACHE_ID:-}" ]]; then
   printf "\n\nPackaging and signing helm chart. Please provide the passphrase for your GPG key when prompted below.\nThe prompt may be subtle, but look at the cursor.\n"
 fi
 
-helm package -u helm/* --app-version "${VERSION}" --version "${VERSION#v}" -d "${HELM_RELEASE_DIR}" "${SIGNING_INFO[@]}"
+helm package -u helm/solr-operator --app-version "${VERSION}" --version "${VERSION#v}" -d "${HELM_RELEASE_DIR}" "${SIGNING_INFO[@]}"
+helm package -u helm/solr --version "${VERSION#v}" -d "${HELM_RELEASE_DIR}" "${SIGNING_INFO[@]}"
 
 if [[ "${CREATED_SECURE_RING}" = true ]]; then
   # Remove the temporary secret key ring
diff --git a/hack/release/version/remove_version_specific_info.sh b/hack/release/artifacts/set_signing_key.sh
similarity index 61%
copy from hack/release/version/remove_version_specific_info.sh
copy to hack/release/artifacts/set_signing_key.sh
index 77d5240..c5e2586 100755
--- a/hack/release/version/remove_version_specific_info.sh
+++ b/hack/release/artifacts/set_signing_key.sh
@@ -23,19 +23,22 @@ set -u
 
 show_help() {
 cat << EOF
-Usage: ./hack/release/version/remove_version_specific_info.sh [-h]
+Usage: ./hack/release/artifacts/set_signing_key.sh -f GPG_FINGERPRINT [-h]
 
-Remove information in the project specific to a previous version.
+Set the GPG Signing Key fingerprint where it needs to be set before a release.
 Requires:
  * yq
 
     -h  Display this help and exit
+    -f  Full GPG Key fingerprint to use when signing artifacts
 EOF
 }
 
 OPTIND=1
-while getopts h opt; do
+while getopts hf: opt; do
     case $opt in
+        f)  GPG_FINGERPRINT=$OPTARG
+            ;;
         h)
             show_help
             exit 0
@@ -47,10 +50,17 @@ while getopts h opt; do
     esac
 done
 shift "$((OPTIND-1))"   # Discard the options and sentinel --
+if [[ -z "${GPG_FINGERPRINT:-}" ]]; then
+  echo "Specify an GPG Signing key fingerprint -f, or through the GPG_FINGERPRINT env var" >&2 && exit 1
+fi
+
+echo "Setting the GPG Signing key fingerprint throughout the repo."
+
+SIGNING_KEY_SET=".annotations.\"artifacthub.io/signKey\" |= \"fingerprint: ${GPG_FINGERPRINT}
+url: https://dist.apache.org/repos/dist/release/solr/KEYS
+\""
 
-echo "Removing information specific to the previous release"
+# Set Signing key for ArtifactHub in Chart.yaml
+yq -i eval "${SIGNING_KEY_SET}" helm/solr-operator/Chart.yaml
 
-# Reset ArtifactHub changelog in Chart.yaml
-yq -i eval '.annotations."artifacthub.io/changes" |= "- Change 1
-- Change 2
-"' helm/solr-operator/Chart.yaml
+yq -i eval "${SIGNING_KEY_SET}" helm/solr/Chart.yaml
diff --git a/hack/release/version/propagate_version.sh b/hack/release/version/propagate_version.sh
index 28a9944..8d25238 100755
--- a/hack/release/version/propagate_version.sh
+++ b/hack/release/version/propagate_version.sh
@@ -65,6 +65,8 @@ IS_PRE_RELEASE="false"
 if [[ "${VERSION_SUFFIX}" =~ .*prerelease ]]; then
   IS_PRE_RELEASE="true"
 fi
+
+# Update Solr Operator Helm Chart version
 {
   cat helm/solr-operator/Chart.yaml | \
   awk '$0 ~ /^v/ && $1 == "version:"{$1 = $1; $2 = "'"${VERSION#v}"'"} 1' | \
@@ -73,8 +75,15 @@ fi
   sed -E "s|image: apache/solr-operator:(.*)|image: apache/solr-operator:${VERSION}|g"
 } > helm/solr-operator/Chart.yaml.tmp && mv helm/solr-operator/Chart.yaml.tmp helm/solr-operator/Chart.yaml
 
+# Update Solr Helm Chart version
+{
+  cat helm/solr/Chart.yaml | \
+  awk '$0 ~ /^v/ && $1 == "version:"{$1 = $1; $2 = "'"${VERSION#v}"'"} 1' | \
+  awk '$1 == "artifacthub.io/prerelease:"{$1 = "  "$1; $2 = "\"'"${IS_PRE_RELEASE}"'\""} 1'
+} > helm/solr/Chart.yaml.tmp && mv helm/solr/Chart.yaml.tmp helm/solr/Chart.yaml
+
 
-# Update Helm README.md
+# Update Solr Operator Helm README.md
 {
   cat helm/solr-operator/README.md | \
   sed -E 's/^\| image.tag \| string \| `".*"` \|/\| image.tag \| string \| `"'${VERSION}'"` \|/g' | \
@@ -82,6 +91,12 @@ fi
   sed -E "s|^(helm.+--version )[^ <]+|\1${VERSION#v}|g"
 } > helm/solr-operator/README.md.tmp && mv helm/solr-operator/README.md.tmp helm/solr-operator/README.md
 
+# Update Solr Helm README.md
+{
+  cat helm/solr/README.md | \
+  sed -E "s|^(helm.+--version )[^ <]+|\1${VERSION#v}|g"
+} > helm/solr/README.md.tmp && mv helm/solr/README.md.tmp helm/solr/README.md
+
 
 # Update Docs (Remove this when docs are generated with versioning info)
 {
diff --git a/hack/release/version/remove_version_specific_info.sh b/hack/release/version/remove_version_specific_info.sh
index 77d5240..cf44886 100755
--- a/hack/release/version/remove_version_specific_info.sh
+++ b/hack/release/version/remove_version_specific_info.sh
@@ -50,7 +50,29 @@ shift "$((OPTIND-1))"   # Discard the options and sentinel --
 
 echo "Removing information specific to the previous release"
 
-# Reset ArtifactHub changelog in Chart.yaml
-yq -i eval '.annotations."artifacthub.io/changes" |= "- Change 1
-- Change 2
-"' helm/solr-operator/Chart.yaml
+CHANGE_LIST_REMOVAL='.annotations."artifacthub.io/changes" |= "- kind: added
+  description: Addition 1
+  links:
+    - name: Github Issue
+      url: https://github.com/issue-url
+- kind: changed
+  description: Change 2
+  links:
+    - name: Github PR
+      url: https://github.com/pr-url
+"'
+
+SIGNING_KEY_REMOVAL=".annotations.\"artifacthub.io/signKey\" |= \"fingerprint: <fingerprint>
+url: https://dist.apache.org/repos/dist/release/solr/KEYS
+\""
+
+SECURITY_FIX_REMOVAL='.annotations."artifacthub.io/containsSecurityUpdates" = "false"'
+
+# Reset ArtifactHub info in Chart.yaml
+yq -i eval "${CHANGE_LIST_REMOVAL}" helm/solr-operator/Chart.yaml
+yq -i eval "${SIGNING_KEY_REMOVAL}" helm/solr-operator/Chart.yaml
+yq -i eval "${SECURITY_FIX_REMOVAL}" helm/solr-operator/Chart.yaml
+
+yq -i eval "${CHANGE_LIST_REMOVAL}" helm/solr/Chart.yaml
+yq -i eval "${SIGNING_KEY_REMOVAL}" helm/solr/Chart.yaml
+yq -i eval "${SECURITY_FIX_REMOVAL}" helm/solr/Chart.yaml
diff --git a/hack/release/wizard/releaseWizard.py b/hack/release/wizard/releaseWizard.py
index 05555ef..cf20f03 100755
--- a/hack/release/wizard/releaseWizard.py
+++ b/hack/release/wizard/releaseWizard.py
@@ -98,6 +98,7 @@ def expand_jinja(text, vars=None):
         'release_version_refguide': state.get_refguide_release() ,
         'state': state,
         'gpg_key': state.get_gpg_key(),
+        'gpg_fingerprint': state.get_gpg_fingerprint(),
         'epoch': unix_time_millis(datetime.utcnow()),
         'get_next_version': state.get_next_version(),
         'get_next_major_version': state.get_next_major_version(),
@@ -309,6 +310,13 @@ class ReleaseState:
         else:
             return None
 
+    def get_gpg_fingerprint(self):
+        gpg_task = self.get_todo_by_id('gpg')
+        if gpg_task.is_done():
+            return gpg_task.get_state()['gpg_fingerprint']
+        else:
+            return None
+
     def get_release_date(self):
         publish_task = self.get_todo_by_id('publish_docker_image')
         if publish_task.is_done():
@@ -1111,19 +1119,23 @@ def configure_pgp(gpg_todo):
     if keyid_linenum:
         keyid_line = lines[keyid_linenum]
         assert keyid_line.startswith('LDAP PGP key: ')
-        gpg_id = keyid_line[14:].replace(" ", "")[-8:]
+        gpg_fingerprint = keyid_line[14:].replace(" ", "")
+        gpg_id = gpg_fingerprint[-8:]
+
         print("Found gpg key id %s on file at Apache (https://home.apache.org/keys/group/solr.asc)" % gpg_id)
     else:
         print(textwrap.dedent("""\
             Could not find your GPG key from Apache servers.
             Please make sure you have registered your key ID in
             id.apache.org, see links for more info."""))
-        gpg_id = str(input("Enter your key ID manually, 8 last characters (ENTER=skip): "))
-        if gpg_id.strip() == '':
+        gpg_fingerprint = str(input("Enter your full key fingerprint manually (ENTER=skip): "))
+
+        if gpg_fingerprint.strip() == '':
             return False
-        elif len(gpg_id) != 8:
-            print("gpg id must be the last 8 characters of your key id")
-        gpg_id = gpg_id.upper()
+        elif len(gpg_fingerprint) != 40:
+            print("gpg fingerprint must be the full 40 characters of your key")
+        gpg_fingerprint = gpg_fingerprint.upper()
+        gpg_id = gpg_fingerprint[-8:]
     try:
         res = run("gpg --list-secret-keys %s" % gpg_id)
         print("Found key %s on your private gpg keychain" % gpg_id)
@@ -1204,6 +1216,7 @@ def configure_pgp(gpg_todo):
             return False
 
     gpg_state['apache_id'] = id
+    gpg_state['gpg_fingerprint'] = gpg_fingerprint
     gpg_state['gpg_key'] = gpg_id
     return True
 
diff --git a/hack/release/wizard/releaseWizard.yaml b/hack/release/wizard/releaseWizard.yaml
index 08e4da3..c578e6f 100644
--- a/hack/release/wizard/releaseWizard.yaml
+++ b/hack/release/wizard/releaseWizard.yaml
@@ -637,6 +637,8 @@ groups:
   - !Todo
     id: helm_change_log
     title: Add changelog to the helm chart
+    links:
+      - https://www.apache.org/foundation/voting.html
     commands: !Commands
       root_folder: '{{ git_checkout_folder }}'
       confirm_each_command: false
@@ -657,7 +659,14 @@ groups:
           comment: |
             Add changelog at annotations.'artifacthub.io/changes', in helm/solr-operator/Chart.yaml.
             This will replace the "Change 1" and "Change 2" lines.
-            You can only input the changelog as a single-layer bulleted list.
+            The Changelog format is described here: https://artifacthub.io/docs/topics/annotations/helm/#example
+          tee: true
+        - !Command
+          cmd: "{{ editor }} helm/solr/Chart.yaml"
+          comment: |
+            Add changelog at annotations.'artifacthub.io/changes', in helm/solr/Chart.yaml.
+            This will replace the "Change 1" and "Change 2" lines.
+            The Changelog format is described here: https://artifacthub.io/docs/topics/annotations/helm/#example
           tee: true
         - !Command
           cmd: git commit -am "Solr Operator {{ release_version }} Changelog"
@@ -728,6 +737,11 @@ groups:
         logfile: propagate_version.log
         tee: true
       - !Command
+        cmd: ./hack/release/artifacts/set_signing_key.sh -f "{{ gpg_fingerprint | default('<gpg_fingerprint>', True) }}"
+        comment: Set the signing key throughout the repo.
+        logfile: set_signing_key.log
+        tee: true
+      - !Command
         cmd: git commit -am "Solr Operator {{ release_version }} Release"
         comment: "We are only committing with the new version, we will not push to the release branch until after the vote has succeeded."
         logfile: commit.log
@@ -846,16 +860,17 @@ groups:
         apache/solr-operator:{{ release_version }}-rc{{ rc_number }}
 
       The RC Helm repo can be added with:
-        helm repo add solr-operator-rc https://dist.apache.org/repos/dist/dev/solr/solr-operator/{{ build_rc.rc_folder | default("<rc_folder>", True) }}/helm-charts
+        helm repo add apache-solr-rc https://dist.apache.org/repos/dist/dev/solr/solr-operator/{{ build_rc.rc_folder | default("<rc_folder>", True) }}/helm-charts
 
-      You can install the RC Solr Operator and Solr CRDs with:
+      You can install the RC Solr Operator and Solr CRDs and an example Solr Cloud with:
         curl -sL0 "https://dist.apache.org/repos/dist/release/solr/KEYS" | gpg --import --quiet
         # This will export your public keys into a format that helm can understand.
         # Skip verification by removing "--verify" in the helm command below.
         if ! (gpg --no-default-keyring --keyring=~/.gnupg/pubring.gpg --list-keys "{{ gpg_key | default("<gpg_key_id>", True) }}"); then gpg --export >~/.gnupg/pubring.gpg; fi
         kubectl create -f https://dist.apache.org/repos/dist/dev/solr/solr-operator/{{ build_rc.rc_folder | default("<rc_folder>", True) }}/crds/all-with-dependencies.yaml || \
           kubectl replace -f https://dist.apache.org/repos/dist/dev/solr/solr-operator/{{ build_rc.rc_folder | default("<rc_folder>", True) }}/crds/all-with-dependencies.yaml
-        helm install --verify solr-operator solr-operator-rc/solr-operator --set image.tag={{ release_version }}-rc{{ rc_number }}
+        helm install --verify solr-operator apache-solr-rc/solr-operator --set image.tag={{ release_version }}-rc{{ rc_number }}
+        helm install --verify example apache-solr-rc/solr
 
       You can run the full smoke tester directly with this command: (First checkout the {{ release_branch }} branch of the solr-operator)
 
@@ -1137,10 +1152,13 @@ groups:
       - publish_docker_image
       - publish_helm_charts
     description: |
-      Check to make sure that ArtifactHub has successfully loaded the {{ release_version }} Helm Chart.
+      Check to make sure that ArtifactHub has successfully loaded the {{ release_version }} version of the Solr Operator and Solr Helm Charts.
       Mark this as complete when you have confirmed all aspects of the chart in artifactHub.
+
+      The ChangeLog is very finicky, so make sure that it renders correctly.
     links:
       - https://artifacthub.io/packages/helm/apache-solr/solr-operator
+      - https://artifacthub.io/packages/helm/apache-solr/solr
 - !TodoGroup
   id: website
   title: Update the website
diff --git a/helm/solr-operator/.helmignore b/helm/solr-operator/.helmignore
index c975369..17b07a3 100644
--- a/helm/solr-operator/.helmignore
+++ b/helm/solr-operator/.helmignore
@@ -34,4 +34,4 @@
 .project
 .idea/
 *.tmproj
-.vscode/
\ No newline at end of file
+.vscode/
diff --git a/helm/solr-operator/Chart.yaml b/helm/solr-operator/Chart.yaml
index 6491412..85e7114 100644
--- a/helm/solr-operator/Chart.yaml
+++ b/helm/solr-operator/Chart.yaml
@@ -43,10 +43,27 @@ annotations:
   artifacthub.io/operator: "true"
   artifacthub.io/operatorCapabilities: Seamless Upgrades
   artifacthub.io/prerelease: "true"
-  # Add change log for a single release here, only single-layered bulleted list allowed.
+  artifacthub.io/recommendations: |
+    - url: https://artifacthub.io/packages/helm/apache-solr/solr
+  artifacthub.io/links: |
+    - name: "Tutorials"
+      url: https://solr.apache.org/operator/resources#tutorials
+  artifacthub.io/signKey: |
+    fingerprint: <fingerprint>
+    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
   artifacthub.io/changes: |
-    - Change 1
-    - Change 2
+    - kind: added
+      description: Addition 1
+      links:
+        - name: Github Issue
+          url: https://github.com/issue-url
+    - kind: changed
+      description: Change 2
+      links:
+        - name: Github PR
+          url: https://github.com/pr-url
   artifacthub.io/images: |
     - name: solr-operator
       image: apache/solr-operator:v0.4.0-prerelease
diff --git a/helm/solr-operator/README.md b/helm/solr-operator/README.md
index 6f35429..9866ee5 100644
--- a/helm/solr-operator/README.md
+++ b/helm/solr-operator/README.md
@@ -9,7 +9,7 @@ Documentation around using the Solr Operator can be found at it's [official site
 
 ## Upgrade Notes
 
-Before upgrading your Solr Operator to a newer version, **please refer to the [Upgrade Notes](https://apache.github.io/solr-operator/docs/upgrade-notes.html).
+Before upgrading your Solr Operator to a newer version, **please refer to the [Upgrade Notes](https://apache.github.io/solr-operator/docs/upgrade-notes.html)**.
 There may be breaking changes between the version you are running and the version you want to upgrade to.
 
 ## Using the Helm Chart
@@ -179,7 +179,7 @@ The command removes all the Kubernetes components associated with the chart and
 | serviceAccount.create | boolean | `true` | Create a serviceAccount to be used for this operator. This serviceAccount will be given the permissions specified in the operator's RBAC rules. |
 | serviceAccount.name | string | `""` | If `serviceAccount.create` is set to `false`, the name of an existing serviceAccount in the target namespace **must** be provided to run the Solr Operator with. This serviceAccount with be given the operator's RBAC rules. | |
 | resources.limits | map[string]string |  | Provide Resource limits for the Solr Operator container |
-| resources.limits | map[string]string |  | Provide Resource requests for the Solr Operator container |
+| resources.requests | map[string]string |  | Provide Resource requests for the Solr Operator container |
 | labels | map[string]string |  | Custom labels to add to the Solr Operator pod |
 | annotations | map[string]string |  | Custom annotations to add to the Solr Operator pod |
 | nodeSelector | map[string]string |  | Add a node selector for the Solr Operator pod, to specify where it can be scheduled |
diff --git a/helm/solr-operator/.helmignore b/helm/solr/.helmignore
similarity index 58%
copy from helm/solr-operator/.helmignore
copy to helm/solr/.helmignore
index c975369..d62ed34 100644
--- a/helm/solr-operator/.helmignore
+++ b/helm/solr/.helmignore
@@ -14,6 +14,21 @@
 # limitations under the License.
 
 # Patterns to ignore when building packages.
+# 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.
+
 # This supports shell glob matching, relative path matching, and
 # negation (prefixed with !). Only one pattern per line.
 .DS_Store
@@ -34,4 +49,4 @@
 .project
 .idea/
 *.tmproj
-.vscode/
\ No newline at end of file
+.vscode/
diff --git a/helm/solr/Chart.yaml b/helm/solr/Chart.yaml
new file mode 100644
index 0000000..2783507
--- /dev/null
+++ b/helm/solr/Chart.yaml
@@ -0,0 +1,68 @@
+# 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.
+
+apiVersion: v2
+name: solr
+description: A SolrCloud cluser running on Kubernetes via the Solr Operator
+
+version: 0.4.0-prerelease
+appVersion: 8.9.0
+kubeVersion: ">= 1.16.0-0"
+home: https://solr.apache.org
+sources:
+  - https://github.com/apache/solr
+  - https://github.com/apache/solr-operator
+keywords:
+  - solr
+  - apache
+  - search
+  - lucene
+maintainers:
+  - name: Solr Dev Community
+    email: dev@solr.apache.org
+  - name: Houston Putman
+    email: houston@apache.org
+icon: https://solr.apache.org/theme/images/identity/Solr_Logo_on_white.png
+annotations:
+  artifacthub.io/operator: "false"
+  artifacthub.io/prerelease: "true"
+  # Add change log for a single release here.
+  # Allowed syntax is described at: https://artifacthub.io/docs/topics/annotations/helm/#example
+  artifacthub.io/changes: |
+    - kind: added
+      description: Official Solr Helm chart created. Works with the Solr Operator.
+      links:
+        - name: Github Issue
+          url: https://github.com/apache/solr-operator/issues/112
+        - name: Github PR
+          url: https://github.com/apache/solr-operator/pull/276
+  artifacthub.io/containsSecurityUpdates: "false"
+  artifacthub.io/recommendations: |
+    - url: https://artifacthub.io/packages/helm/apache-solr/solr-operator
+  artifacthub.io/links: |
+    - name: "Solr Source"
+      url: https://github.com/apache/solr
+    - name: "Helm Chart Source"
+      url: https://github.com/apache/solr-operator
+    - name: "Solr Documentation"
+      url: https://solr.apache.org/guide/
+    - name: "Solr on Kube Tutorials"
+      url: https://solr.apache.org/operator/resources#tutorials
+  artifacthub.io/images: |
+    - name: solr
+      image: apache/solr:8.9
+  artifacthub.io/signKey: |
+    fingerprint: <fingerprint>
+    url: https://dist.apache.org/repos/dist/release/solr/KEYS
diff --git a/helm/solr/LICENSE b/helm/solr/LICENSE
new file mode 100644
index 0000000..d645695
--- /dev/null
+++ b/helm/solr/LICENSE
@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
diff --git a/helm/solr/NOTICE b/helm/solr/NOTICE
new file mode 100644
index 0000000..bb5bdda
--- /dev/null
+++ b/helm/solr/NOTICE
@@ -0,0 +1,7 @@
+==============================================================
+ Apache Solr Operator
+ Copyright 2006-2021 The Apache Software Foundation
+==============================================================
+
+This product includes software developed at
+The Apache Software Foundation (http://www.apache.org/).
diff --git a/helm/solr/README.md b/helm/solr/README.md
new file mode 100644
index 0000000..001cf5f
--- /dev/null
+++ b/helm/solr/README.md
@@ -0,0 +1,237 @@
+Apache Solr
+=============
+
+Apache Solr is the popular, blazing-fast, open source enterprise search platform built on Apache Luceneā„¢.
+
+Solr is highly reliable, scalable and fault tolerant, providing distributed indexing, replication and load-balanced querying, automated failover and recovery, centralized configuration and more.
+Solr powers the search and navigation features of many of the world's largest internet sites.
+
+Documentation around using Apache Solr can be found on it's [official site](https://solr.apache.org).
+
+## Tutorials
+
+Check out the following tutorials on getting started with Solr.
+
+- [Solr on Kubernetes Tutorials](https://solr.apache.org/operator/resources.html#tutorials)
+- [Using Solr Tutorials](https://solr.apache.org/resources.html#tutorials)
+
+## Dependencies
+
+This Helm chart relies on the [Solr Operator](https://solr.apache.org/operator) being installed.
+You can install the Solr Operator via it's [Helm chart](https://artifacthub.io/packages/helm/apache-solr/solr-operator).
+
+If you are using a provided Zookeeper instance for your Solr Cloud, then you must also install the [Zookeeper Operator](https://github.com/pravega/zookeeper-operator).
+However, it is [installed by default as a dependency](https://artifacthub.io/packages/helm/apache-solr/solr-operator#installing-the-zookeeper-operator) when using the Solr Operator Helm chart.
+
+Please make sure that the same version of the Solr Operator chart and Solr chart are installed.
+The Solr version can be any supported version of Solr you wish to run, but the _chart version_ must match the chart version of the Solr Operator that you have installed.
+
+## Upgrade Notes
+
+Before upgrading your Solr Operator and Solr Helm chart version, **please refer to the [Upgrade Notes](https://apache.github.io/solr-operator/docs/upgrade-notes.html)**.
+There may be breaking changes between the version you are using and the version you want to upgrade to.
+
+## Using the Helm Chart
+
+### Installing the Chart
+
+To install the Solr Operator for the first time in your cluster, you can use the latest version or a specific version, run with the following commands:
+
+```bash
+helm install example apache-solr/solr --version 0.4.0-prerelease --set image.tag=8.8.0
+```
+
+The command deploys the a SolrCloud object on the Kubernetes cluster with the default configuration.
+The [Solr Operator](https://solr.apache.org/operator) is then in charge of creating the necessary Kubernetes resources to run that Solr Cloud.
+The [configuration](#chart-values) section lists the parameters that can be configured during installation.
+
+_Note that the Helm chart version does not contain a `v` prefix, which the Solr Operator release versions do._
+
+### Upgrading Solr
+
+If you are upgrading your SolrCloud deployment, you should always use a specific version of the chart and upgrade **after [upgrading the Solr Operator](https://artifacthub.io/packages/helm/apache-solr/solr-operator#upgrading-the-solr-operator) to the same version**:
+
+```bash
+helm upgrade example apache-solr/solr --version 0.4.0-prerelease --reuse-values --set image.tag=8.9.0
+```
+
+The upgrade will be done according to the `upgradeStrategy.method` chosen in the values.
+Be sure to select the [update strategy](https://apache.github.io/solr-operator/docs/solr-cloud/solr-cloud-crd.html#update-strategy) that best fits your use case.
+However, the `Managed` strategy is highly recommended.
+
+### Uninstalling the Chart
+
+To uninstall/delete the Solr Cloud, run:
+
+```bash
+helm uninstall example
+```
+
+The command removes the SolrCloud resource, and then Kubernetes will garbage collect the resources owned by that SolrCloud, including the StatefulSet, Services, ConfigMap, etc.
+
+## Chart Values
+
+### Running Solr
+
+| Key | Type | Default | Description |
+|-----|------|---------|-------------|
+| fullnameOverride | string | `""` | A custom name for the Solr Operator Deployment |
+| nameOverride | string | `""` |  |
+| replicas | int | `3` | The number of Solr pods to run in the Solr Cloud. If you want to use autoScaling, do not set this field. |
+| image.repository | string | `"apache/solr"` | The repository of the Solr image |
+| image.tag | string | `"8.9"` | The tag/version of Solr to run |
+| image.pullPolicy | string |  | PullPolicy for the Solr image, defaults to the empty Pod behavior |
+| image.imagePullSecret | string |  | PullSecret for the Solr image |
+| busyBoxImage.repository | string | `"busybox"` | The repository of the BusyBox image |
+| busyBoxImage.tag | string | `"1.28.0-glibc"` | The tag/version of BusyBox to run |
+| busyBoxImage.pullPolicy | string |  | PullPolicy for the BusyBox image, defaults to the empty Pod behavior |
+| busyBoxImage.imagePullSecret | string |  | PullSecret for the BusyBox image |
+| solrOptions.javaMemory | string | `"-Xms1g -Xmx2g"` | PullSecret for the BusyBox image |
+| solrOptions.javaOpts | string | `""` | Additional java arguments to pass via the command line |
+| solrOptions.logLevel | string | `"INFO"` | Log level to run Solr under |
+| solrOptions.gcTune | string | `""` | GC Tuning parameters for Solr |
+| solrOptions.security.authenticationType | string | `""` | Type of authentication to use for Solr |
+| solrOptions.security.basicAuthSecret | string | `""` | Name of Secret in the same namespace that stores the basicAuth information for the Solr user |
+| solrOptions.security.probesRequireAuth | boolean | | Whether the probes for the SolrCloud pod require auth |
+| updateStrategy.method | string | `"Managed"` | The method for conducting updates of Solr pods. Either `Managed`, `StatefulSet` or `Manual`. See the [docs](https://apache.github.io/solr-operator/docs/solr-cloud/solr-cloud-crd.html#update-strategy) for more information |
+| updateStrategy.managedUpdate.maxPodsUnavailable | int-or-string | `"25%"` | The number of Solr pods in a Solr Cloud that are allowed to be unavailable during the rolling restart. Either a static number, or a percentage representing the percentage of total pods requested for the statefulSet. |
+| updateStrategy.managedUpdate.maxShardReplicasUnavailable | int-or-string | `1` | The number of replicas for each shard allowed to be unavailable during the restart. Either a static number, or a percentage representing the percentage of the number of replicas for a shard. |
+
+### Data Storage Options
+
+See the [documentation](https://apache.github.io/solr-operator/docs/solr-cloud/solr-cloud-crd.html#data-storage) for more information.
+
+| Key | Type | Default | Description |
+|-----|------|---------|-------------|
+| dataStorage.type | string | `"ephemeral"` | Whether your Solr data storage should be `ephemeral` or `persistent`. The `storage.<ephemeral,persistent>.*` options are used only if their storage type is selected here. |
+| dataStorage.capacity | string | `"20Gi"` | Capacity for your data storage, ephemeral or persistent |
+| dataStorage.ephemeral.emptyDir | object | | Specify options for and ephemeral emptyDir volume to store Solr data. |
+| dataStorage.ephemeral.hostPath | object | | Specify options for and ephemeral hostPath volume to store Solr data. Is not used when `emptyDir` is specified. |
+| dataStorage.persistent.reclaimPolicy | string | `"Retain"` | Determines whether to delete or keep the PVCs when Solr is deleted or scaled down. Either `Retain` or `Delete`. |
+| dataStorage.persistent.pvc.name | string | | Override the default Solr data PVC base-name |
+| dataStorage.persistent.pvc.annotations | map[string]string | | Set the annotations for your Solr data PVCs |
+| dataStorage.persistent.pvc.labels | map[string]string | | Set the labels for your Solr data PVCs |
+| dataStorage.persistent.pvc.storageClassName | string | | Override the default storageClass for your Solr data PVCs |
+| dataStorage.backupRestoreOptions.volume | object | | A read-write-many volume that can be attached to all Solr pods, for the purpose of storing backup data. This is required when using the SolrBackup CRD. |
+| dataStorage.backupRestoreOptions.directory | string | | Override the default backup-restore volume location in the Solr container |
+
+### Addressability Options
+
+See the [documentation](https://apache.github.io/solr-operator/docs/solr-cloud/solr-cloud-crd.html#addressability) for more information.
+
+If providing external addressability, then `method` and `domainName` must be provided.
+External addressability is disabled by default.
+
+| Key | Type | Default | Description |
+|-----|------|---------|-------------|
+| addressability.podPort | int | `8983` | The port that Solr should listen on within the pod. |
+| addressability.commonServicePort | int | `` | The port that Solr's load-balancing common service should listen on. |
+| addressability.kubeDomain | string | | The cluster domain the Kubernetes is addressed under. Overrides the `global.clusterDomain` option. |
+| addressability.external.method | string | | The method by which Solr should be made addressable outside of the Kubernetes cluster. Either `Ingress` or `ExternalDNS` |
+| addressability.external.domainName | string | | The base domain name that Solr nodes should be addressed under. |
+| addressability.external.additionalDomainNames | []string | | Additional base domain names that Solr nodes should be addressed under. These are not used to advertise Solr locations, just the `domainName` is. |
+| addressability.external.hideNodes | boolean | `false` | Do not make the individual Solr nodes addressable outside of the Kubernetes cluster. |
+| addressability.external.hideCommon | boolean | `false` | Do not make the load-balanced common Solr endpoint addressable outside of the Kubernetes cluster. |
+| addressability.external.nodePortOverride | int | | Override the port of individual Solr nodes when using the `Ingress` method. This will default to `80` if using an Ingress without TLS and `443` when using an Ingress with TLS. |
+
+
+### ZK Options
+
+Specify what ZooKeeper cluster your SolrCloud should connect to.
+If you specify `zk.address` or `zk.externalAddress`, then no ZooKeeper cluster will be created for you.
+If neither of those options are specified, then a new ZooKeeper cluster will be created by the [Zookeeper Operator](https://github.com/pravega/zookeeper-operator), with the settings provided under `zk.provided.*`.
+
+Currently the Zookeeper Operator does not support ACLs, so do not use the provided ZK cluster in conjunction with them.
+
+| Key | Type | Default | Description |
+|-----|------|---------|-------------|
+| zk.chroot | string | | A ZooKeeper Node to host all the information for this SolrCloud under |
+| zk.uniqueChroot | boolean | `false` | If true, this will add the `/<namespace>/<name>` to the end of the provided chroot, if any is provided. This will let you deploy multiple Solr Clouds without having to manage the specific chroots yourself. |
+| zk.address | string | | An existing ZooKeeper cluster address to use for Solr. Must be reachable within the Kubernetes cluster. |
+| zk.externalAddress | string | | An existing ZooKeeper cluster address to use for Solr. Must be reachable within and outside the Kubernetes cluster. |
+| zk.provided.replicas | int | `3` | The number of replicas to run for your ZooKeeper cluster. |
+| zk.provided.image.repository | string | `"pravega/zookeeper"` | The repository of the Solr image |
+| zk.provided.image.tag | string | | The tag/version of Zookeeper to run. Generally leave this blank, so that the Zookeeper Operator can manage it. |
+| zk.provided.image.pullPolicy | string | `"IfNotPresent"` | PullPolicy for the ZooKeeper image |
+| zk.provided.image.imagePullSecret | string |  | PullSecret for the ZooKeeper image |
+| zk.provided.persistence.reclaimPolicy | string | `"Retain"` | Determines whether to delete or keep the PVCs when ZooKeeper is deleted or scaled down. Either `Retain` or `Delete`. |
+| zk.provided.persistence.spec | object | | A PVC Spec for the ZooKeeper PVC(s) |
+| zk.provided.zookeeperPodPolicy.affinity | string |  | PullSecret for the ZooKeeper image |
+| zk.provided.zookeeperPodPolicy.resources.limits | map[string]string |  | Provide Resource limits for the ZooKeeper containers |
+| zk.provided.zookeeperPodPolicy.resources.requests | map[string]string |  | Provide Resource requests for the ZooKeeper containers |
+| zk.provided.zookeeperPodPolicy.nodeSelector | map[string]string |  | Add a node selector for the ZooKeeper pod, to specify where it can be scheduled |
+| zk.provided.zookeeperPodPolicy.affinity | object |  | Add Kubernetes affinity information for the ZooKeeper pod |
+| zk.provided.zookeeperPodPolicy.tolerations | []object |  | Specify a list of Kubernetes tolerations for the ZooKeeper pod |
+| zk.provided.zookeeperPodPolicy.envVars | []object |  | List of additional environment variables for the ZooKeeper container |
+| zk.acl.secret | string |  | Name of a secret in the same namespace as the Solr cloud that stores the ZK admin ACL information |
+| zk.acl.usernameKey | string |  | Key in the Admin ACL Secret that stores the ACL username |
+| zk.acl.passwordKey | string |  | Key in the Admin ACL Secret that stores the ACL password |
+| zk.readOnlyAcl.secret | string |  | Name of a secret in the same namespace as the Solr cloud that stores the ZK read-only ACL information |
+| zk.readOnlyAcl.usernameKey | string |  | Key in the read-only ACL Secret that stores the ACL username |
+| zk.readOnlyAcl.passwordKey | string |  | Key in the read-only ACL Secret that stores the ACL password |
+
+### TLS Options
+
+See [documentation](https://apache.github.io/solr-operator/docs/solr-cloud/solr-cloud-crd.html#enable-tls-between-solr-pods) for more information.
+
+Solr TLS is disabled by default. Provide any of the following to enable it.
+
+| Key | Type | Default | Description |
+|-----|------|---------|-------------|
+| solrTLS.clientAuth | string | `"None"` | Whether clientAuth is Needed, Wanted or None in Solr |
+| solrTLS.verifyClientHostname | boolean | `false` | Whether Solr should verify client hostnames |
+| solrTLS.checkPeerName | boolean | `false` | Whether Solr should check peer names |
+| solrTLS.restartOnTLSSecretUpdate | boolean | `false` | Whether Solr pods should auto-restart when the TLS Secrets are updated |
+| solrTLS.pkcs12Secret.name | string |  | Name of the Secret that stores the Solr TLS pkcs12 file |
+| solrTLS.pkcs12Secret.key | string |  | Key in the Secret that stores the Solr TLS pkcs12 file |
+| solrTLS.keyStorePasswordSecret.name | string |  | Name of the Secret that stores the Solr TLS keystore |
+| solrTLS.keyStorePasswordSecret.key | string |  | Key in the Secret that stores the Solr TLS keystore |
+| solrTLS.trustStoreSecret.name | string |  | Name of the Secret that stores the Solr TLS truststore |
+| solrTLS.trustStoreSecret.key | string |  | Key in the Secret that stores the Solr TLS truststore |
+| solrTLS.trustStorePasswordSecret.name | string |  | Name of the Secret that stores the Solr TLS truststore password |
+| solrTLS.trustStorePasswordSecret.key | string |  | Key in the Secret that stores the Solr TLS truststore password |
+| solrTLS.trustStorePasswordSecret.key | string |  | Key in the Secret that stores the Solr TLS truststore password |
+
+### Global Options
+
+| Key | Type | Default | Description |
+|-----|------|---------|-------------|
+| global.imagePullSecrets | []object |  | The list of imagePullSecrets to include in pods |
+| global.clusterDomain | string |  | The cluster domain the Kubernetes is addressed under. |
+
+### Custom Kubernetes Options
+
+| Key | Type | Default | Description |
+|-----|------|---------|-------------|
+| podOptions.annotations | map[string]string |  | Custom annotations to add to the Solr pod |
+| podOptions.labels | map[string]string |  | Custom labels to add to the Solr pod |
+| podOptions.resources.limits | map[string]string |  | Provide Resource limits for the Solr container |
+| podOptions.resources.requests | map[string]string |  | Provide Resource requests for the Solr container |
+| podOptions.nodeSelector | map[string]string |  | Add a node selector for the Solr pod, to specify where it can be scheduled |
+| podOptions.affinity | object |  | Add Kubernetes affinity information for the Solr pod |
+| podOptions.tolerations | []object |  | Specify a list of Kubernetes tolerations for the Solr pod |
+| podOptions.priorityClassName | string | | Give a 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 |
+| podOptions.envVars | []object |  | List of additional environment variables for the Solr container |
+| podOptions.podSecurityContext | object |  | Security context for the Solr pod |
+| podOptions.terminationGracePeriodSeconds | int |  | Optional amount of time to wait for Solr to stop on its own, before manually killing it |
+| podOptions.livenessProbe | object |  | Custom liveness probe for the Solr container |
+| podOptions.readinessProbe | object |  | Custom readiness probe for the Solr container |
+| podOptions.startupProbe | object |  | Custom startup probe for the Solr container |
+| podOptions.imagePullSecrets | []object |  | List of image pull secrets to inject into the Solr pod, in addition to `global.imagePullSecrets` |
+| podOptions.volumes | []object |  | List of additional volumes to attach to the Solr pod, and optionally how to mount them to the Solr container |
+| statefulSetOptions.annotations | map[string]string |  | Custom annotations to add to the Solr statefulSet |
+| statefulSetOptions.labels | map[string]string |  | Custom labels to add to the Solr statefulSet |
+| statefulSetOptions.podManagementPolicy | string | `"Parallel"` | Policy for how Solr pods should be managed in the statefulSet, ["OrderedReady" or "Parallel"](https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#pod-management-policies) |
+| commonServiceOptions.annotations | map[string]string |  | Custom annotations to add to the Solr common service |
+| commonServiceOptions.labels | map[string]string |  | Custom labels to add to the Solr common service |
+| headlessServiceOptions.annotations | map[string]string |  | Custom annotations to add to the Solr headless service |
+| headlessServiceOptions.labels | map[string]string |  | Custom labels to add to the Solr headless service |
+| nodeServiceOptions.annotations | map[string]string |  | Custom annotations to add to the Solr node service(s) |
+| nodeServiceOptions.labels | map[string]string |  | Custom labels to add to the Solr node service(s) |
+| ingressOptions.annotations | map[string]string |  | Custom annotations to add to the Solr ingress, if it exists |
+| ingressOptions.labels | map[string]string |  | Custom labels to add to the Solr ingress, if it exists |
+| configMapOptions.annotations | map[string]string |  | Custom annotations to add to the Solr configMap |
+| configMapOptions.labels | map[string]string |  | Custom labels to add to the Solr configMap |
+| configMapOptions.providedConfigMap | string |  | Provide an existing configMap for the Solr XML and/or Solr log4j files. *ADVANCED* |
diff --git a/helm/solr/templates/NOTES.txt b/helm/solr/templates/NOTES.txt
new file mode 100644
index 0000000..e69de29
diff --git a/helm/solr/templates/_custom_option_helpers.tpl b/helm/solr/templates/_custom_option_helpers.tpl
new file mode 100644
index 0000000..1a7995c
--- /dev/null
+++ b/helm/solr/templates/_custom_option_helpers.tpl
@@ -0,0 +1,240 @@
+{{/*
+   * 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.
+   */}}
+
+{{/* vim: set filetype=mustache: */}}
+
+{{/*
+The values within Pod Options for a SolrCloud
+*/}}
+{{- define "solr.custom-kube-options.pod.filler" -}}
+{{- if .Values.podOptions.labels -}}
+labels:
+  {{- toYaml .Values.podOptions.labels | nindent 2 }}
+{{ end }}
+{{- if .Values.podOptions.annotations -}}
+annotations:
+  {{- toYaml .Values.podOptions.annotations | nindent 2 }}
+{{ end }}
+{{- if .Values.podOptions.resources -}}
+resources:
+  {{- toYaml .Values.podOptions.resources | nindent 2 }}
+{{ end }}
+{{- if .Values.podOptions.priorityClassName -}}
+priorityClassName: {{ .Values.podOptions.priorityClassName }}
+{{ end }}
+{{- if .Values.podOptions.envVars -}}
+envVars:
+  {{- toYaml .Values.podOptions.envVars | nindent 2 }}
+{{ end }}
+{{- if .Values.podOptions.affinity -}}
+affinity:
+  {{- toYaml .Values.podOptions.affinity | nindent 2 }}
+{{ end }}
+{{- if .Values.podOptions.tolerations -}}
+tolerations:
+  {{- toYaml .Values.podOptions.tolerations | nindent 2 }}
+{{ end }}
+{{- if .Values.podOptions.nodeSelector -}}
+nodeSelector:
+  {{- toYaml .Values.podOptions.nodeSelector | nindent 2 }}
+{{ end }}
+{{- if .Values.podOptions.podSecurityContext -}}
+podSecurityContext:
+  {{- toYaml .Values.podOptions.podSecurityContext | nindent 2 }}
+{{ end }}
+{{- if (or .Values.podOptions.imagePullSecrets .Values.global.imagePullSecrets) -}}
+imagePullSecrets:
+  {{- toYaml (append .Values.podOptions.imagePullSecrets .Values.global.imagePullSecrets) | nindent 2 }}
+{{ end }}
+{{- if .Values.podOptions.volumes -}}
+volumes:
+  {{- toYaml .Values.podOptions.volumes | nindent 2 }}
+{{ end }}
+{{- if .Values.podOptions.terminationGracePeriodSeconds -}}
+terminationGracePeriodSeconds: {{ .Values.podOptions.terminationGracePeriodSeconds }}
+{{ end }}
+{{- if .Values.podOptions.livenessProbe -}}
+livenessProbe:
+  {{- toYaml .Values.podOptions.livenessProbe | nindent 2 }}
+{{ end }}
+{{- if .Values.podOptions.readinessProbe -}}
+readinessProbe:
+  {{- toYaml .Values.podOptions.readinessProbe | nindent 2 }}
+{{ end }}
+{{- if .Values.podOptions.startupProbe -}}
+startupProbe:
+  {{- toYaml .Values.podOptions.startupProbe | nindent 2 }}
+{{ end }}
+{{- if .Values.podOptions.sidecarContainers -}}
+sidecarContainers:
+  {{- toYaml .Values.podOptions.sidecarContainers | nindent 2 }}
+{{ end }}
+{{- if .Values.podOptions.initContainers -}}
+initContainers:
+  {{- toYaml .Values.podOptions.initContainers | nindent 2 }}
+{{ end }}
+{{- end -}}
+
+{{/*
+The values within StatefulSet Options for a SolrCloud
+*/}}
+{{- define "solr.custom-kube-options.stateful-set.filler" }}
+{{- if .Values.statefulSetOptions.labels -}}
+labels:
+  {{- toYaml .Values.statefulSetOptions.labels | nindent 2 }}
+{{ end }}
+{{- if .Values.statefulSetOptions.annotations -}}
+annotations:
+  {{- toYaml .Values.statefulSetOptions.annotations | nindent 2 }}
+{{ end }}
+{{- if .Values.statefulSetOptions.podManagementPolicy -}}
+podManagementPolicy: {{ .Values.statefulSetOptions.podManagementPolicy }}
+{{ end }}
+{{- end -}}
+
+{{/*
+The values within Ingress Options for a SolrCloud
+*/}}
+{{- define "solr.custom-kube-options.ingress.filler" -}}
+{{- if .Values.ingressOptions.labels -}}
+labels:
+  {{- toYaml .Values.ingressOptions.labels | nindent 2 }}
+{{ end }}
+{{- if .Values.ingressOptions.annotations -}}
+annotations:
+  {{- toYaml .Values.ingressOptions.annotations | nindent 2 }}
+{{ end }}
+{{- end -}}
+
+{{/*
+The values within ConfigMap Options for a SolrCloud
+*/}}
+{{- define "solr.custom-kube-options.config-map.filler" -}}
+{{- if .Values.configMapOptions.labels -}}
+labels:
+  {{- toYaml .Values.configMapOptions.labels | nindent 2 }}
+{{ end }}
+{{- if .Values.configMapOptions.annotations -}}
+annotations:
+  {{- toYaml .Values.configMapOptions.annotations | nindent 2 }}
+{{ end }}
+{{- if .Values.configMapOptions.providedConfigMap -}}
+providedConfigMap: {{ .Values.configMapOptions.providedConfigMap }}
+{{ end }}
+{{- end -}}
+
+{{/*
+The values within CommonService Options for a SolrCloud
+*/}}
+{{- define "solr.custom-kube-options.common-service.filler" -}}
+{{- if .Values.commonServiceOptions.labels -}}
+labels:
+  {{- toYaml .Values.commonServiceOptions.labels | nindent 2 }}
+{{ end }}
+{{- if .Values.commonServiceOptions.annotations -}}
+annotations:
+  {{- toYaml .Values.commonServiceOptions.annotations | nindent 2 }}
+{{ end }}
+{{- end -}}
+
+{{/*
+The values within HeadlessService Options for a SolrCloud
+*/}}
+{{- define "solr.custom-kube-options.headless-service.filler" -}}
+{{- if .Values.headlessServiceOptions.labels -}}
+labels:
+  {{- toYaml .Values.headlessServiceOptions.labels | nindent 2 }}
+{{ end }}
+{{- if .Values.headlessServiceOptions.annotations -}}
+annotations:
+  {{- toYaml .Values.headlessServiceOptions.annotations | nindent 2 }}
+{{ end }}
+{{- end -}}
+
+{{/*
+The values within NodeService Options for a SolrCloud
+*/}}
+{{- define "solr.custom-kube-options.node-service.filler" -}}
+{{- if .Values.nodeServiceOptions.labels -}}
+labels:
+  {{- toYaml .Values.nodeServiceOptions.labels | nindent 2 }}
+{{ end }}
+{{- if .Values.nodeServiceOptions.annotations -}}
+annotations:
+  {{- toYaml .Values.nodeServiceOptions.annotations | nindent 2 }}
+{{ end }}
+{{- end -}}
+
+{{/*
+Provides all customKubeOptions values for a SolrCloud
+*/}}
+{{- define "solr.custom-kube-options.filler" -}}
+{{- with (include "solr.custom-kube-options.pod.filler" .) -}}
+{{- if . -}}
+podOptions:
+  {{- . | nindent 2 -}}
+{{ end }}
+{{ end }}
+{{- with (include "solr.custom-kube-options.stateful-set.filler" .) -}}
+{{- if . -}}
+statefulSetOptions:
+  {{- . | nindent 2 -}}
+{{ end }}
+{{ end }}
+{{- with (include "solr.custom-kube-options.common-service.filler" .) -}}
+{{- if . -}}
+commonServiceOptions:
+  {{- . | nindent 2 -}}
+{{ end }}
+{{ end }}
+{{- with (include "solr.custom-kube-options.headless-service.filler" .) -}}
+{{- if . -}}
+headlessServiceOptions:
+  {{- . | nindent 2 -}}
+{{ end }}
+{{ end }}
+{{- with (include "solr.custom-kube-options.node-service.filler" .) -}}
+{{- if . -}}
+nodeServiceOptions:
+  {{- . | nindent 2 -}}
+{{ end }}
+{{ end }}
+{{- with (include "solr.custom-kube-options.config-map.filler" .) -}}
+{{- if . -}}
+configMapOptions:
+  {{- . | nindent 2 -}}
+{{ end }}
+{{ end }}
+{{- with (include "solr.custom-kube-options.ingress.filler" .) -}}
+{{- if . -}}
+ingressOptions:
+  {{- . | nindent 2 -}}
+{{ end }}
+{{ end }}
+{{- end -}}
+
+{{/*
+Provides the nodeServiceOptions for the SolrCloud, if any are given
+*/}}
+{{- define "solr.custom-kube-options" -}}
+{{- with (include "solr.custom-kube-options.filler" .) -}}
+{{- if . -}}
+customSolrKubeOptions:
+  {{- . | nindent 2 -}}
+{{ end }}
+{{ end }}
+{{- end -}}
diff --git a/helm/solr/templates/_helpers.tpl b/helm/solr/templates/_helpers.tpl
new file mode 100644
index 0000000..fdc03a3
--- /dev/null
+++ b/helm/solr/templates/_helpers.tpl
@@ -0,0 +1,80 @@
+{{/*
+   * 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.
+   */}}
+
+{{/* vim: set filetype=mustache: */}}
+{{/*
+Expand the name of the chart.
+*/}}
+{{- define "solr.name" -}}
+{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
+{{- end }}
+
+{{/*
+Create a default fully qualified app name.
+We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
+If release name contains chart name it will be used as a full name.
+*/}}
+{{- define "solr.fullname" -}}
+{{- if .Values.fullnameOverride }}
+{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
+{{- else }}
+{{- $name := default .Chart.Name .Values.nameOverride }}
+{{- if contains $name .Release.Name }}
+{{- .Release.Name | trunc 63 | trimSuffix "-" }}
+{{- else }}
+{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
+{{- end }}
+{{- end }}
+{{- end }}
+
+{{/*
+Provides the name of the solrcloud object (the fullname without '-solrcloud' appended)
+*/}}
+{{- define "solr.fullname-no-suffix" -}}
+{{ include "solr.fullname" . | trimSuffix "-solrcloud" | trimSuffix "-solr" }}
+{{- end }}
+
+{{/*
+Create chart name and version as used by the chart label.
+*/}}
+{{- define "solr.chart" -}}
+{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
+{{- end }}
+
+{{/*
+Common labels
+*/}}
+{{- define "solr.labels" -}}
+helm.sh/chart: {{ include "solr.chart" . }}
+{{ include "solr.selectorLabels" . }}
+app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
+{{- end }}
+
+{{/*
+Selector labels
+*/}}
+{{- define "solr.selectorLabels" -}}
+app.kubernetes.io/name: {{ include "solr.name" . }}
+app.kubernetes.io/instance: {{ .Release.Name }}
+{{- end }}
+
+{{/*
+ZK ChRoot
+*/}}
+{{ define "solr.zk.chroot" }}
+/{{ printf "%s%s" (trimSuffix "/" .Values.zk.chroot) (ternary (printf "/%s/%s" .Release.Namespace (include "solr.fullname" .)) "" .Values.zk.uniqueChroot) | trimPrefix "/" }}
+{{ end }}
diff --git a/helm/solr/templates/solrcloud.yaml b/helm/solr/templates/solrcloud.yaml
new file mode 100644
index 0000000..b4efce1
--- /dev/null
+++ b/helm/solr/templates/solrcloud.yaml
@@ -0,0 +1,193 @@
+# 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.
+
+apiVersion: solr.apache.org/v1beta1
+kind: SolrCloud
+metadata:
+  name: {{ include "solr.fullname-no-suffix" . }}
+  labels:
+    {{- include "solr.labels" . | nindent 4 }}
+spec:
+  {{- if (quote .Values.replicas) }}
+  replicas: {{ .Values.replicas }}
+  {{- end }}
+  {{- if .Values.image }}
+  solrImage:
+    {{- if .Values.image.repository }}
+    repository: {{ .Values.image.repository }}
+    {{- end }}
+    {{- if .Values.image.tag }}
+    tag: {{ .Values.image.tag | quote }}
+    {{- end }}
+    {{- if .Values.image.pullPolicy }}
+    pullPolicy: {{ .Values.image.pullPolicy }}
+    {{- end }}
+    {{- if .Values.image.imagePullSecret }}
+    imagePullSecret: {{ .Values.image.imagePullSecret }}
+    {{- end }}
+  {{- end }}
+
+  {{- if .Values.busyBoxImage }}
+  busyBoxImage:
+    {{- if .Values.busyBoxImage.repository }}
+    repository: {{ .Values.busyBoxImage.repository }}
+    {{- end }}
+    {{- if .Values.busyBoxImage.tag }}
+    tag: {{ .Values.busyBoxImage.tag | quote }}
+    {{- end }}
+    {{- if .Values.busyBoxImage.pullPolicy }}
+    pullPolicy: {{ .Values.busyBoxImage.pullPolicy }}
+    {{- end }}
+    {{- if .Values.busyBoxImage.imagePullSecret }}
+    imagePullSecret: {{ .Values.busyBoxImage.imagePullSecret }}
+    {{- end }}
+  {{- end }}
+
+  {{- if .Values.solrOptions.javaMemory }}
+  solrJavaMem: {{ .Values.solrOptions.javaMemory | quote }}
+  {{- end }}
+  {{- if .Values.solrOptions.logLevel }}
+  solrLogLevel: {{ .Values.solrOptions.logLevel }}
+  {{- end }}
+  {{- if .Values.solrOptions.gcTune }}
+  solrGCTune: {{ .Values.solrOptions.gcTune | quote }}
+  {{- end }}
+  {{- if .Values.solrOptions.javaOpts }}
+  solrOpts: {{ .Values.solrOptions.javaOpts | quote }}
+  {{- end }}
+
+  {{- if .Values.solrOptions.security }}
+  solrSecurity:
+    {{- toYaml .Values.solrOptions.security | nindent 4 }}
+  {{- end }}
+
+  {{- if (or .Values.addressability .Values.global.clusterDomain) }}
+  solrAddressability:
+    {{- if .Values.addressability.podPort }}
+    podPort: {{ .Values.addressability.podPort }}
+    {{- end }}
+    {{- if .Values.addressability.commonServicePort }}
+    commonServicePort: {{ .Values.addressability.commonServicePort }}
+    {{- end }}
+    {{- if .Values.addressability.external }}
+    external:
+      {{- toYaml .Values.addressability.external | nindent 6 }}
+    {{- end }}
+    {{- if .Values.addressability.kubeDomain | default .Values.global.clusterDomain }}
+    kubeDomain: {{ .Values.addressability.kubeDomain | default .Values.global.clusterDomain | quote }}
+    {{- end }}
+  {{- end }}
+
+  {{- if .Values.updateStrategy }}
+  updateStrategy:
+    {{- toYaml .Values.updateStrategy | nindent 4 }}
+  {{- end }}
+
+  {{- if .Values.dataStorage }}
+  dataStorage:
+    {{- if eq .Values.dataStorage.type "persistent" }}
+    persistent:
+      reclaimPolicy: {{ .Values.dataStorage.persistent.reclaimPolicy }}
+      pvcTemplate:
+        metadata:
+          name: {{ .Values.dataStorage.persistent.pvc.name | quote }}
+          {{- if .Values.dataStorage.persistent.pvc.labels }}
+          labels:
+            {{- toYaml .Values.dataStorage.persistent.pvc.labels | nindent 12 }}
+          {{- end }}
+          {{- if .Values.dataStorage.persistent.pvc.annotations }}
+          annotations:
+            {{- toYaml .Values.dataStorage.persistent.pvc.annotations | nindent 12 }}
+          {{- end }}
+        spec:
+          {{- if .Values.dataStorage.capacity }}
+          resources:
+            requests:
+              storage: {{ .Values.dataStorage.capacity | quote }}
+          {{- end }}
+          storageClassName: {{ .Values.dataStorage.persistent.pvc.storageClassName | quote }}
+    {{- else }}
+    ephemeral:
+      {{- if (and .Values.dataStorage.ephemeral.hostPath (not .Values.dataStorage.ephemeral.emptyDir)) }}
+      hostPath:
+        {{- toYaml .Values.dataStorage.ephemeral.hostPath | nindent 8 }}
+      {{- else if (or .Values.dataStorage.ephemeral.emptyDir .Values.dataStorage.capacity) }}
+      emptyDir:
+        {{- if .Values.dataStorage.ephemeral.emptyDir }}
+        {{- toYaml .Values.dataStorage.ephemeral.emptyDir | nindent 8 }}
+        {{- end }}
+        {{- if .Values.dataStorage.capacity }}
+        sizeLimit: {{ .Values.dataStorage.capacity | quote }}
+        {{- end }}
+      {{- end }}
+    {{- end }}
+    {{- if .Values.dataStorage.backupRestoreOptions }}
+    backupRestoreOptions:
+      {{- toYaml .Values.dataStorage.backupRestoreOptions | nindent 6 }}
+    {{- end }}
+  {{- end }}
+
+  {{- if .Values.solrTLS }}
+  solrTLS:
+    {{- toYaml .Values.solrTLS | nindent 4 }}
+  {{- end }}
+
+  {{- include "solr.custom-kube-options" . | nindent 2 -}}
+
+  {{- if .Values.zk -}}
+  zookeeperRef:
+    {{- if (or .Values.zk.address .Values.zk.externalAddress) }}
+    connectionInfo:
+      internalConnectionString: {{ .Values.zk.address | default .Values.zk.externalAddress | quote }}
+      {{- if .Values.zk.externalAddress }}
+      externalAddress: {{ .Values.zk.externalAddress | quote }}
+      {{- end }}
+      chroot: {{ trim (include "solr.zk.chroot" .) | quote }}
+      {{- if .Values.zk.acl }}
+      acl:
+        {{- toYaml .Values.zk.acl | nindent 8 }}
+      {{- end }}
+      {{- if .Values.zk.readOnlyAcl }}
+      readOnlyAcl:
+        {{- toYaml .Values.zk.readOnlyAcl | nindent 8 }}
+      {{- end }}
+    {{- else }}
+    provided:
+      chroot: {{ trim (include "solr.zk.chroot" .) | quote }}
+      {{- if .Values.zk.provided.replicas }}
+      replicas: {{ .Values.zk.provided.replicas }}
+      {{- end }}
+      {{- if .Values.zk.provided.image }}
+      image:
+        {{- toYaml .Values.zk.provided.image | nindent 8 }}
+      {{- end }}
+      {{- if .Values.zk.provided.persistence }}
+      persistence:
+        {{- toYaml .Values.zk.provided.persistence | nindent 8 }}
+      {{- end }}
+      {{- if .Values.zk.provided.zookeeperPodPolicy }}
+      zookeeperPodPolicy:
+        {{- toYaml .Values.zk.provided.zookeeperPodPolicy | nindent 8 }}
+      {{- end }}
+      {{- if .Values.zk.acl }}
+      acl:
+        {{- toYaml .Values.zk.acl | nindent 8 }}
+      {{- end }}
+      {{- if .Values.zk.readOnlyAcl }}
+      readOnlyAcl:
+        {{- toYaml .Values.zk.readOnlyAcl | nindent 8 }}
+      {{- end }}
+    {{- end }}
+  {{- end -}}
diff --git a/helm/solr/values.yaml b/helm/solr/values.yaml
new file mode 100644
index 0000000..d29f46e
--- /dev/null
+++ b/helm/solr/values.yaml
@@ -0,0 +1,250 @@
+# 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.
+
+# Default values for solr.
+# This is a YAML-formatted file.
+# Declare variables to be passed into your templates.
+
+nameOverride: ""
+fullnameOverride: ""
+
+# If you want to use autoScaling, do not set this field
+replicas: null
+
+global:
+  imagePullSecrets: []
+  clusterDomain: ""
+
+image:
+  repository: "solr"
+  tag: "8.8.2"
+  # Default pullPolicy is empty, which is Always for "latest" tags and IfNotPresent for all others.
+  pullPolicy: ""
+  imagePullSecret: ""
+
+busyBoxImage: {}
+  # repository: "busybox"
+  # tag: "1.28.0-glibc"
+  # pullPolicy: ""
+  # imagePullSecret: ""
+
+solrOptions:
+  javaMemory: ""
+  javaOpts: ""
+  logLevel: ""
+  gcTune: ""
+
+  # Enable authentication for the Solr Cloud
+  # More information can be found at:
+  # https://apache.github.io/solr-operator/docs/solr-cloud/solr-cloud-crd.html#authentication-and-authorization
+  security: {}
+    # authenticationType: Basic
+    # basicAuthSecret: secret-name
+    # probesRequireAuth: false
+
+
+# Specify how the SolrCloud should be addressable
+# https://apache.github.io/solr-operator/docs/solr-cloud/solr-cloud-crd.html#addressability
+addressability:
+  podPort: 8983
+  commonServicePort: null
+  # kubeDomain is defaulted by global.clusterDomain if it's not provided
+  kubeDomain: ""
+  # Use external to provide endpoint(s) for your SolrCloud outside of Kubernetes
+  external: {}
+    # method: "Ingress"
+    # domainName: "example.com"
+    # additionalDomainNames: []
+    # hideNodes: false
+    # hideCommon: false
+    # nodePortOverride: null
+
+# Specify how rolling updates should be managed for the Solr StatefulSet
+# https://apache.github.io/solr-operator/docs/solr-cloud/solr-cloud-crd.html#update-strategy
+updateStrategy:
+  method: "Managed"
+  # Options for the managed update method
+  managed: {}
+    # The number of Solr pods in a Solr Cloud that are allowed to be unavailable during the rolling restart.
+    # More pods may become unavailable during the restart, however the Solr Operator will not kill pods if the limit has already been reached.
+    # Either a static number, or a percentage representing the percentage of total pods requested for the statefulSet.
+    # maxPodsUnavailable: "25%"
+
+    # The number of replicas for each shard allowed to be unavailable during the restart.
+    # Either a static number, or a percentage representing the percentage of the number of replicas for a shard.
+    # Defaults to 1
+    # maxShardReplicasUnavailable: 1
+
+# More information can be found at:
+# https://apache.github.io/solr-operator/docs/solr-cloud/solr-cloud-crd.html#data-storage
+dataStorage:
+  # Either persistent or ephemeral
+  type: "ephemeral"
+
+  # Specify a capacity for your data storage.
+  # This effects both ephemeral and persistent storage.
+  capacity: "20Gi"
+
+  # Options for ephemeral storage. Only used if type = "ephemeral"
+  ephemeral: {}
+    # emptyDir: {}
+    # hostPath: {}
+
+  # Options for persistent storage. Only used if type = "persistent"
+  persistent:
+    reclaimPolicy: "Retain"
+    pvc:
+      name: ""
+      labels: {}
+      annotations: {}
+      storageClassName: ""
+
+  # BackupRestoreOptions is required when using this cloud with the SolrBackup CRD.
+  backupRestoreOptions: {}
+    # volume: {}
+    # directory: ""
+
+zk:
+  # A ZooKeeper Node to host all the information for this SolrCloud under
+  chroot: ""
+  # If true, this will add the "/<namespace>/<name>" to the end of the provided chroot, if any is provided.
+  # This will let you deploy multiple Solr Clouds without having to manage the specific chroots yourself.
+  uniqueChroot: false
+
+  # Use an existing ZooKeeper cluster
+  # Address available within the Kubernetes Cluster
+  address: ""
+  # Address available both within and outside the Kubernetes Cluster
+  externalAddress: ""
+
+  # If no "address" is provided, this defines the ZookeeperCluster created for this SolrCloud
+  provided:
+    replicas: 3
+    image: {}
+      # repository: "pravega/zookeeper"
+      # tag: ""
+      # pullPolicy: IfNotPresent
+      # imagePullSecret: ""
+    persistence: {}
+      # reclaimPolicy: "Retain"
+      # spec: {}
+    zookeeperPodPolicy: {}
+      # affinity: {}
+      # tolerations: []
+      # nodeSelector: {}
+      # env: []
+      # resources: {}
+
+  # Use this section to inject ACL information for your zookeeper from a Kube secret in the same namespace as your SolrCloud
+  acl: {}
+    # secret: zk-acls
+    # usernameKey: username
+    # passwordKey: password
+
+  # Use this section to inject ACL information for your zookeeper from a Kube secret in the same namespace as your SolrCloud
+  readOnlyAcl: {}
+    # secret: zk-acls
+    # usernameKey: username
+    # passwordKey: password
+
+# Enable TLS between your SolrCloud nodes
+# More information can be found at:
+# https://apache.github.io/solr-operator/docs/solr-cloud/solr-cloud-crd.html#enable-tls-between-solr-pods
+solrTLS: {}
+  # pkcs12Secret:
+  #   name: secret-name
+  #   key: pkcs12-key
+  # keyStorePasswordSecret:
+  #   name: secret-name
+  #   key: password-key
+  # trustStoreSecret:
+  #   name: secret-name
+  #   key: truststore-key
+  # trustStorePasswordSecret:
+  #   name: secret-name
+  #   key: password-key
+  # clientAuth: None
+  # verifyClientHostname: false
+  # checkPeerName: false
+  # restartOnTLSSecretUpdate: false
+
+# Customize the Solr Pod for your needs
+podOptions:
+  annotations: {}
+  labels: {}
+
+  # Add extra sidecar or init containers, e.g. for log or metrics forwarding
+  sidecarContainers: []
+  initContainers: []
+
+  priorityClassName: ""
+  envVars: []
+  affinity: {}
+  tolerations: []
+  nodeSelector: {}
+  podSecurityContext: {}
+  terminationGracePeriodSeconds: null
+
+  # Probes for the Solr pods
+  livenessProbe: {}
+  readinessProbe: {}
+  startupProbe: {}
+
+  imagePullSecrets: []
+
+  resources: {}
+    # limits:
+    #   cpu: "2"
+    #   memory: 10G
+    # requests:
+    #   cpu: 500m
+    #   memory: 4G
+
+  volumes: []
+    # - name:
+    #   defaultContainerMount: {}
+    #   source: {}
+
+statefulSetOptions:
+  annotations: {}
+  labels: {}
+
+  # Specify a podManagementPolicy when you want control over how scale-ups and scale-downs occur
+  # https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#pod-management-policies
+  # The default is: Parallel
+  podManagementPolicy: ""
+
+commonServiceOptions:
+  annotations: {}
+  labels: {}
+
+headlessServiceOptions:
+  annotations: {}
+  labels: {}
+
+nodeServiceOptions:
+  annotations: {}
+  labels: {}
+
+ingressOptions:
+  annotations: {}
+  labels: {}
+
+configMapOptions:
+  annotations: {}
+  labels: {}
+
+  # This is an extremely advanced option, do not use it without understanding the requirements of the solr.xml you provide.
+  providedConfigMap: ""