├── .github ├── CODEOWNERS ├── PULL_REQUEST_TEMPLATE.md └── workflows │ ├── add-untriaged.yaml │ ├── docker-build.yaml │ ├── functional-tests.yaml │ ├── go-linting.yaml │ ├── helm-linting.yaml │ ├── helm-release.yaml │ ├── make-install.yaml │ ├── release.yaml │ └── testing.yaml ├── .gitignore ├── .whitesource ├── CONTRIBUTING.md ├── K8sOperator.png ├── LICENSE ├── MAINTAINERS.md ├── README.md ├── THIRD_PARTY_NOTICES ├── charts ├── opensearch-cluster │ ├── .helmignore │ ├── CHANGELOG.md │ ├── Chart.yaml │ ├── README.md │ ├── templates │ │ ├── NOTES.txt │ │ ├── _helpers.tpl │ │ ├── actiongroups.yaml │ │ ├── cluster.yaml │ │ ├── componenttemplates.yaml │ │ ├── indextemplates.yaml │ │ ├── ingress.yaml │ │ ├── ismpolicies.yaml │ │ ├── roles.yaml │ │ ├── serviceaccount.yaml │ │ ├── tenants.yaml │ │ ├── userrolebinding.yaml │ │ └── users.yaml │ └── values.yaml └── opensearch-operator │ ├── CHANGELOG.md │ ├── Chart.yaml │ ├── README.md │ ├── files │ ├── opensearch.opster.io_opensearchactiongroups.yaml │ ├── opensearch.opster.io_opensearchclusters.yaml │ ├── opensearch.opster.io_opensearchcomponenttemplates.yaml │ ├── opensearch.opster.io_opensearchindextemplates.yaml │ ├── opensearch.opster.io_opensearchismpolicies.yaml │ ├── opensearch.opster.io_opensearchroles.yaml │ ├── opensearch.opster.io_opensearchtenants.yaml │ ├── opensearch.opster.io_opensearchuserrolebindings.yaml │ └── opensearch.opster.io_opensearchusers.yaml │ ├── templates │ ├── _helpers.tpl │ ├── opensearch-operator-controller-manager-deployment.yaml │ ├── opensearch-operator-controller-manager-metrics-service-svc.yaml │ ├── opensearch-operator-controller-manager-sa.yaml │ ├── opensearch-operator-crds.yaml │ ├── opensearch-operator-leader-election-role-role.yaml │ ├── opensearch-operator-leader-election-rolebinding-rb.yaml │ ├── opensearch-operator-manager-config-cm.yaml │ ├── opensearch-operator-manager-role-cr.yaml │ ├── opensearch-operator-manager-rolebinding.yaml │ ├── opensearch-operator-metrics-reader-cr.yaml │ ├── opensearch-operator-proxy-role-cr.yaml │ └── opensearch-operator-proxy-rolebinding.yaml │ └── values.yaml ├── ct.yaml ├── docs ├── designs │ ├── assets │ │ └── K8sOperator.png │ ├── configuration.md │ ├── crd.md │ ├── high-level.md │ ├── monitoring.md │ ├── opensearch-rbac.md │ ├── security.md │ └── upgrade.md ├── developing.md └── userguide │ ├── cluster-chart.md │ └── main.md ├── go.work ├── go.work.sum ├── jenkins └── release.jenkinsfile ├── opensearch-operator ├── .gitignore ├── .mockery.yaml ├── Dockerfile ├── Makefile ├── PROJECT ├── Tiltfile ├── api │ └── v1 │ │ ├── groupversion_info.go │ │ ├── opensearch_componenttemplate_types.go │ │ ├── opensearch_index_types.go │ │ ├── opensearch_indextemplate_types.go │ │ ├── opensearch_types.go │ │ ├── opensearchactiongroup_types.go │ │ ├── opensearchism_types.go │ │ ├── opensearchrole_types.go │ │ ├── opensearchtenant_types.go │ │ ├── opensearchuser_types.go │ │ ├── opensearchuserrolebinding_types.go │ │ ├── util.go │ │ └── zz_generated.deepcopy.go ├── config │ ├── crd │ │ ├── bases │ │ │ ├── crd-servicemonitor.yaml │ │ │ ├── opensearch.opster.io_opensearchactiongroups.yaml │ │ │ ├── opensearch.opster.io_opensearchclusters.yaml │ │ │ ├── opensearch.opster.io_opensearchcomponenttemplates.yaml │ │ │ ├── opensearch.opster.io_opensearchindextemplates.yaml │ │ │ ├── opensearch.opster.io_opensearchismpolicies.yaml │ │ │ ├── opensearch.opster.io_opensearchroles.yaml │ │ │ ├── opensearch.opster.io_opensearchtenants.yaml │ │ │ ├── opensearch.opster.io_opensearchuserrolebindings.yaml │ │ │ └── opensearch.opster.io_opensearchusers.yaml │ │ ├── kustomization.yaml │ │ ├── kustomizeconfig.yaml │ │ └── patches │ │ │ ├── cainjection_in_opensearch.yaml │ │ │ ├── cainjection_in_opensearchroles.yaml │ │ │ ├── cainjection_in_opensearchuserrolebindings.yaml │ │ │ ├── cainjection_in_opensearchusers.yaml │ │ │ ├── webhook_in_opensearch.yaml │ │ │ ├── webhook_in_opensearchroles.yaml │ │ │ ├── webhook_in_opensearchuserrolebindings.yaml │ │ │ └── webhook_in_opensearchusers.yaml │ ├── default │ │ ├── kustomization.yaml │ │ ├── manager_auth_proxy_patch.yaml │ │ └── manager_config_patch.yaml │ ├── manager │ │ ├── controller_manager_config.yaml │ │ ├── kustomization.yaml │ │ └── manager.yaml │ ├── prometheus │ │ ├── kustomization.yaml │ │ └── monitor.yaml │ ├── rbac │ │ ├── auth_proxy_client_clusterrole.yaml │ │ ├── auth_proxy_role.yaml │ │ ├── auth_proxy_role_binding.yaml │ │ ├── auth_proxy_service.yaml │ │ ├── kustomization.yaml │ │ ├── leader_election_role.yaml │ │ ├── leader_election_role_binding.yaml │ │ ├── opensearch_editor_role.yaml │ │ ├── opensearch_viewer_role.yaml │ │ ├── opensearchrole_editor_role.yaml │ │ ├── opensearchrole_viewer_role.yaml │ │ ├── opensearchuser_editor_role.yaml │ │ ├── opensearchuser_viewer_role.yaml │ │ ├── opensearchuserrolebinding_editor_role.yaml │ │ ├── opensearchuserrolebinding_viewer_role.yaml │ │ ├── role.yaml │ │ ├── role_binding.yaml │ │ └── service_account.yaml │ └── samples │ │ ├── opster_v1_opensearchactiongroup.yaml │ │ ├── opster_v1_opensearchcluster.yaml │ │ ├── opster_v1_opensearchrole.yaml │ │ ├── opster_v1_opensearchtenant.yaml │ │ ├── opster_v1_opensearchuser.yaml │ │ └── opster_v1_opensearchuserrolebinding.yaml ├── controllers │ ├── cluster_test.go │ ├── controller_settings.go │ ├── dashboard_test.go │ ├── opensearchController.go │ ├── opensearch_componenttemplate_controller.go │ ├── opensearch_indextemplate_controller.go │ ├── opensearchactiongroup_controller.go │ ├── opensearchism_controller.go │ ├── opensearchrole_controller.go │ ├── opensearchtenant_controller.go │ ├── opensearchuser_controller.go │ ├── opensearchuserrolebinding_controller.go │ ├── scaler_test.go │ ├── suite_test.go │ ├── suite_test_helpers.go │ └── tls_test.go ├── examples │ ├── 1.3.x │ │ ├── opensearch-cluster-initcontainer-resources.yaml │ │ ├── opensearch-cluster-securityconfig.yaml │ │ └── opensearch-cluster.yaml │ ├── 2.x │ │ ├── opensearch-cluster-custom-admin-user.yaml │ │ ├── opensearch-cluster-pdb.yaml │ │ ├── opensearch-cluster.yaml │ │ └── opensearch-hot-warm-cold.yaml │ ├── securityconfig-secret.yaml │ └── templates │ │ ├── opensearch-component-template.yaml │ │ └── opensearch-index-template.yaml ├── functionaltests │ ├── execute_tests.sh │ ├── go.mod │ ├── go.sum │ ├── helmtests │ │ ├── helmcrinstall_test.go │ │ └── main_test.go │ └── operatortests │ │ ├── deploy-and-upgrade.yaml │ │ ├── deploy_and_upgrade_test.go │ │ ├── dummy.yaml │ │ ├── dummy_test.go │ │ ├── helpers_test.go │ │ └── main_test.go ├── go.mod ├── go.sum ├── hack │ ├── boilerplate.go.txt │ ├── create-k3d-cluster.sh │ └── k3d-local.yaml ├── main.go ├── mocks │ └── github.com │ │ └── Opster │ │ └── opensearch-k8s-operator │ │ └── opensearch-operator │ │ └── pkg │ │ └── reconcilers │ │ └── k8s │ │ └── mock_K8sClient.go ├── opensearch-gateway │ ├── requests │ │ ├── ActionGroup.go │ │ ├── IsmPolicy.go │ │ ├── ReRouteMoveAction.go │ │ ├── RoleMapping.go │ │ ├── Roles.go │ │ ├── SnapshotRepository.go │ │ ├── Templates.go │ │ ├── Tenants.go │ │ └── Users.go │ ├── responses │ │ ├── CatHealthResponse.go │ │ ├── CatIndicesResponse.go │ │ ├── CatNodesResponse.go │ │ ├── CatShardsResponse.go │ │ ├── ClusterHealthResponse.go │ │ ├── ClusterRerouteResponse.go │ │ ├── ClusterSettingsResponse.go │ │ ├── EnableBalanceRoutingMode.go │ │ ├── IsmPolicy.go │ │ ├── MainPageResponse.go │ │ ├── NodesStatsResponse.go │ │ ├── SecurityResponse.go │ │ ├── SnapshotRepositoryResponse.go │ │ └── Templates.go │ └── services │ │ ├── errors.go │ │ ├── http_request.go │ │ ├── os_client.go │ │ ├── os_client_test.go │ │ ├── os_data_service.go │ │ ├── os_data_service_test.go │ │ ├── os_ism_service.go │ │ ├── os_security_service.go │ │ ├── os_snapshot_service.go │ │ ├── services_suite_test.go │ │ └── tests_helper.go └── pkg │ ├── builders │ ├── cluster.go │ ├── cluster_test.go │ ├── dashboards.go │ ├── dashboards_test.go │ └── suite_test.go │ ├── helpers │ ├── constants.go │ ├── helpers.go │ ├── helpers_suite_test.go │ ├── reconcile-helpers.go │ ├── reconcile-helpers_test.go │ ├── test-helpers.go │ └── translate.go │ ├── reconcilers │ ├── actiongroup.go │ ├── actiongroup_test.go │ ├── cluster.go │ ├── componenttemplate.go │ ├── componenttemplate_test.go │ ├── configuration.go │ ├── configuration_test.go │ ├── dashboards.go │ ├── dashboards_test.go │ ├── indextemplate.go │ ├── indextemplate_test.go │ ├── ismpolicy.go │ ├── ismpolicy_test.go │ ├── k8s │ │ └── client.go │ ├── reconcilers.go │ ├── role.go │ ├── role_test.go │ ├── rollingRestart.go │ ├── scaler.go │ ├── securityconfig.go │ ├── securityconfig_test.go │ ├── snapshotrepository.go │ ├── snapshotrepository_test.go │ ├── suite_test.go │ ├── tenant.go │ ├── tenant_test.go │ ├── tls.go │ ├── tls_test.go │ ├── upgrade.go │ ├── userrolebinding.go │ ├── userrolebinding_test.go │ ├── users.go │ ├── users_test.go │ └── util │ │ ├── util.go │ │ ├── util_suite_test.go │ │ └── util_test.go │ └── tls │ └── pki.go └── scripts └── build-image-multi-arch.sh /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @idanl21 @ido-opster @dbason @swoehrl-mw @prudhvigodithi @jochenkressin @pchmielnik @salyh 2 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ### Description 2 | _Describe what this change achieves._ 3 | 4 | ### Issues Resolved 5 | _List any issues this PR will resolve, e.g. Closes [...]._ 6 | 7 | ### Check List 8 | - [ ] Commits are signed per the DCO using --signoff 9 | - [ ] Unittest added for the new/changed functionality and all unit tests are successful 10 | - [ ] Customer-visible features documented 11 | - [ ] No linter warnings (`make lint`) 12 | 13 | If CRDs are changed: 14 | - [ ] CRD YAMLs updated (`make manifests`) and also copied into the helm chart 15 | - [ ] Changes to CRDs documented 16 | 17 | Please refer to the [PR guidelines](https://github.com/opensearch-project/opensearch-k8s-operator/blob/main/docs/developing.md#submitting-a-pr) before submitting this pull request. 18 | 19 | By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license. 20 | For more information on following Developer Certificate of Origin and signing off your commits, please check [here](https://github.com/opensearch-project/OpenSearch/blob/main/CONTRIBUTING.md#developer-certificate-of-origin). 21 | -------------------------------------------------------------------------------- /.github/workflows/add-untriaged.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | name: Apply 'untriaged' label during issue lifecycle 3 | 4 | on: 5 | issues: 6 | types: [opened, reopened, transferred] 7 | 8 | jobs: 9 | apply-label: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - uses: actions/github-script@v6 13 | with: 14 | script: | 15 | github.rest.issues.addLabels({ 16 | issue_number: context.issue.number, 17 | owner: context.repo.owner, 18 | repo: context.repo.repo, 19 | labels: ['untriaged'] 20 | }) 21 | 22 | -------------------------------------------------------------------------------- /.github/workflows/docker-build.yaml: -------------------------------------------------------------------------------- 1 | name: "Docker Build" 2 | on: 3 | pull_request: 4 | branches: 5 | - "main" 6 | jobs: 7 | docker-build: 8 | runs-on: ubuntu-latest 9 | name: Docker Build 10 | steps: 11 | - name: Checkout 12 | uses: actions/checkout@v4 13 | - name: Setup go 14 | uses: actions/setup-go@v5 15 | with: 16 | go-version-file: 'go.work' 17 | cache: false 18 | - name: Set up Docker Buildx 19 | uses: docker/setup-buildx-action@v3 20 | - name: Docker Build 21 | run: | 22 | cd opensearch-operator 23 | make docker-build-multiarch 24 | -------------------------------------------------------------------------------- /.github/workflows/functional-tests.yaml: -------------------------------------------------------------------------------- 1 | name: Functional tests 2 | on: [pull_request] 3 | 4 | jobs: 5 | operator: 6 | runs-on: ubuntu-latest 7 | steps: 8 | - name: Checkout code 9 | uses: actions/checkout@v4 10 | - name: Setup go 11 | uses: actions/setup-go@v5 12 | with: 13 | go-version-file: 'go.work' 14 | cache: false 15 | - uses: nolar/setup-k3d-k3s@v1 16 | with: 17 | version: v1 18 | k3d-name: opensearch-operator-tests 19 | k3d-args: --agents 2 -p 30000-30005:30000-30005@agent:0 20 | github-token: ${{ secrets.GITHUB_TOKEN }} 21 | - name: Run tests 22 | run: | 23 | set -e 24 | export CLUSTER_NAME=opensearch-operator-tests 25 | ## Check disk to avoid failed shard assignments due to watermarking 26 | df -h 27 | cd opensearch-operator 28 | ## Prepare kubeconfig 29 | k3d kubeconfig get $CLUSTER_NAME > functionaltests/kubeconfig 30 | export KUBECONFIG=$(pwd)/functionaltests/kubeconfig 31 | 32 | ## Build controller docker image 33 | make docker-build 34 | 35 | ## Import controller docker image 36 | k3d image import -c $CLUSTER_NAME controller:latest 37 | 38 | ## Install helm chart 39 | helm install opensearch-operator ../charts/opensearch-operator --set manager.image.repository=controller --set manager.image.tag=latest --set manager.image.pullPolicy=IfNotPresent --namespace default --wait 40 | cd functionaltests 41 | 42 | ## Run tests 43 | go test ./operatortests -timeout 30m 44 | 45 | cluster-helm-chart: 46 | runs-on: ubuntu-latest 47 | strategy: 48 | fail-fast: false 49 | matrix: 50 | version: 51 | - 3.0.0 52 | - 2.19.0 53 | - 1.3.20 54 | steps: 55 | - name: Checkout code 56 | uses: actions/checkout@v4 57 | - name: Setup go 58 | uses: actions/setup-go@v5 59 | with: 60 | go-version-file: 'go.work' 61 | cache: false 62 | - uses: nolar/setup-k3d-k3s@v1 63 | with: 64 | version: v1 65 | k3d-name: opensearch-operator-tests 66 | k3d-args: --agents 2 -p 30000-30005:30000-30005@agent:0 67 | github-token: ${{ secrets.GITHUB_TOKEN }} 68 | - name: Run tests 69 | run: | 70 | set -e 71 | export CLUSTER_NAME=opensearch-operator-tests 72 | ## Check disk to avoid failed shard assignments due to watermarking 73 | df -h 74 | cd opensearch-operator 75 | ## Prepare kubeconfig 76 | k3d kubeconfig get $CLUSTER_NAME > functionaltests/kubeconfig 77 | export KUBECONFIG=$(pwd)/functionaltests/kubeconfig 78 | 79 | ## Build controller docker image 80 | make docker-build 81 | 82 | ## Import controller docker image 83 | k3d image import -c $CLUSTER_NAME controller:latest 84 | 85 | ## Install helm chart 86 | helm install opensearch-operator ../charts/opensearch-operator --set manager.image.repository=controller --set manager.image.tag=latest --set manager.image.pullPolicy=IfNotPresent --namespace default --wait 87 | helm install opensearch-cluster ../charts/opensearch-cluster --set opensearchCluster.general.version=${{ matrix.version }} --set opensearchCluster.dashboards.version=${{ matrix.version }} --wait 88 | cd functionaltests 89 | 90 | ## Run tests 91 | go test ./helmtests -timeout 15m 92 | -------------------------------------------------------------------------------- /.github/workflows/go-linting.yaml: -------------------------------------------------------------------------------- 1 | name: Golang Lint 2 | on: [pull_request] 3 | 4 | jobs: 5 | golangci-lint: 6 | name: golangci lint 7 | runs-on: ubuntu-latest 8 | steps: 9 | - uses: actions/checkout@v4 10 | - name: Setup go 11 | uses: actions/setup-go@v5 12 | with: 13 | go-version-file: 'go.work' 14 | cache: false 15 | - name: lint go 16 | uses: golangci/golangci-lint-action@v4 17 | with: 18 | # Required: the version of golangci-lint is required and must be specified without patch version: we always use the latest patch version. 19 | version: v1.57 20 | working-directory: opensearch-operator 21 | args: --timeout=6m --skip-dirs="(^|/)responses($|/)" -v 22 | -------------------------------------------------------------------------------- /.github/workflows/helm-linting.yaml: -------------------------------------------------------------------------------- 1 | name: Helm Lint 2 | on: 3 | pull_request: 4 | paths: 5 | - 'charts/**' 6 | 7 | jobs: 8 | helm-lint: 9 | name: helm lint 10 | runs-on: ubuntu-latest 11 | steps: 12 | - uses: actions/checkout@v4 13 | - name: lint helm 14 | run: | 15 | set -e 16 | helm lint charts/opensearch-operator/ 17 | helm lint charts/opensearch-cluster/ 18 | -------------------------------------------------------------------------------- /.github/workflows/helm-release.yaml: -------------------------------------------------------------------------------- 1 | name: Release Helm Charts 2 | 3 | on: 4 | workflow_dispatch: 5 | push: 6 | branches: 7 | - main 8 | 9 | jobs: 10 | release: 11 | permissions: 12 | contents: write 13 | runs-on: ubuntu-latest 14 | steps: 15 | - name: Checkout 16 | uses: actions/checkout@v3 17 | with: 18 | fetch-depth: 0 19 | 20 | - name: Configure Git 21 | run: | 22 | git config user.name "$GITHUB_ACTOR" 23 | git config user.email "$GITHUB_ACTOR@users.noreply.github.com" 24 | 25 | - name: Install Helm 26 | uses: azure/setup-helm@v4 27 | env: 28 | GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" 29 | 30 | - name: Run chart-releaser for opensearch-cluster 31 | uses: helm/chart-releaser-action@v1.6.0 32 | with: 33 | skip_existing: true 34 | mark_as_latest: false 35 | env: 36 | CR_TOKEN: "${{ secrets.GITHUB_TOKEN }}" 37 | -------------------------------------------------------------------------------- /.github/workflows/make-install.yaml: -------------------------------------------------------------------------------- 1 | name: Make install 2 | on: [pull_request] 3 | 4 | jobs: 5 | make-install: 6 | runs-on: ubuntu-latest 7 | steps: 8 | - name: Checkout code 9 | uses: actions/checkout@v4 10 | - name: Setup go 11 | uses: actions/setup-go@v5 12 | with: 13 | go-version-file: 'go.work' 14 | cache: false 15 | - uses: nolar/setup-k3d-k3s@v1 16 | with: 17 | version: v1 18 | k3d-name: opensearch-operator-tests 19 | k3d-args: --agents 2 -p 30000-30005:30000-30005@agent:0 20 | github-token: ${{ secrets.GITHUB_TOKEN }} 21 | - name: make-install 22 | run: | 23 | set -e 24 | export CLUSTER_NAME=opensearch-operator-tests 25 | ## Check disk to avoid failed shard assignments due to watermarking 26 | df -h 27 | cd opensearch-operator 28 | 29 | make build manifests 30 | make install 31 | -------------------------------------------------------------------------------- /.github/workflows/release.yaml: -------------------------------------------------------------------------------- 1 | name: "Publish Release from tag" 2 | on: 3 | push: 4 | tags: 5 | - 'v*' 6 | jobs: 7 | release: 8 | runs-on: ubuntu-latest 9 | environment: 10 | name: k8s-operator 11 | name: Release 12 | steps: 13 | - name: Checkout 14 | uses: actions/checkout@v4 15 | with: 16 | fetch-depth: 0 17 | 18 | - name: Setup go 19 | uses: actions/setup-go@v5 20 | with: 21 | go-version-file: 'go.work' 22 | cache: false 23 | 24 | - name: Set up Docker Buildx 25 | uses: docker/setup-buildx-action@v3 26 | 27 | - name: set Env 28 | id: github-ver 29 | run: | 30 | echo "RELEASE_VERSION=${GITHUB_REF#refs/*/v}" >> $GITHUB_ENV 31 | 32 | - name: Make sure helm chart has correct versions 33 | run: | 34 | sed -i -e 's/^appVersion:.*/appVersion: '$RELEASE_VERSION'/' charts/opensearch-operator/Chart.yaml 35 | sed -i -e 's/^version:.*/version: '$RELEASE_VERSION'/' charts/opensearch-operator/Chart.yaml 36 | 37 | - name: Configure Git 38 | run: | 39 | git config user.name "$GITHUB_ACTOR" 40 | git config user.email "$GITHUB_ACTOR@users.noreply.github.com" 41 | 42 | - name: Install Helm 43 | uses: azure/setup-helm@v4 44 | env: 45 | GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" 46 | 47 | - name: Run chart-releaser for opensearch-operator 48 | uses: helm/chart-releaser-action@v1.6.0 49 | with: 50 | skip_existing: true 51 | mark_as_latest: false 52 | env: 53 | CR_TOKEN: "${{ secrets.GITHUB_TOKEN }}" 54 | 55 | - name: Create Release 56 | uses: softprops/action-gh-release@v2 57 | id: create_release 58 | with: 59 | draft: true 60 | prerelease: false 61 | token: ${{ secrets.GITHUB_TOKEN }} 62 | tag_name: ${{ github.ref }} 63 | name: ${{ github.ref }} 64 | 65 | -------------------------------------------------------------------------------- /.github/workflows/testing.yaml: -------------------------------------------------------------------------------- 1 | name: Testing 2 | on: [pull_request] 3 | 4 | jobs: 5 | unit-tests: 6 | runs-on: ubuntu-latest 7 | steps: 8 | - name: Checkout code 9 | uses: actions/checkout@v4 10 | - name: Setup go 11 | uses: actions/setup-go@v5 12 | with: 13 | go-version-file: 'go.work' 14 | cache: false 15 | - name: Test 16 | run: | 17 | cd opensearch-operator 18 | make test 19 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Binaries for programs and plugins 2 | *.exe 3 | *.exe~ 4 | *.dll 5 | *.so 6 | *.dylib 7 | 8 | # Test binary, built with `go test -c` 9 | *.test 10 | 11 | # Output of the go coverage tool, specifically when used with LiteIDE 12 | *.out 13 | 14 | # Dependency directories (remove the comment below to include it) 15 | # vendor/ 16 | bin/ 17 | testbin/ 18 | *.bin 19 | 20 | .vscode 21 | .idea/ 22 | 23 | opensearch-operator/functionaltests/kubeconfig 24 | 25 | # Macos files 26 | .DS_Store 27 | 28 | # Ignore direnv file 29 | .envrc 30 | -------------------------------------------------------------------------------- /.whitesource: -------------------------------------------------------------------------------- 1 | { 2 | "scanSettings": { 3 | "configMode": "AUTO", 4 | "configExternalURL": "", 5 | "projectToken": "", 6 | "baseBranches": [] 7 | }, 8 | "scanSettingsSAST": { 9 | "enableScan": false, 10 | "scanPullRequests": false, 11 | "incrementalScan": true, 12 | "baseBranches": [], 13 | "snippetSize": 10 14 | }, 15 | "checkRunSettings": { 16 | "vulnerableCheckRunConclusionLevel": "failure", 17 | "displayMode": "diff", 18 | "useMendCheckNames": true 19 | }, 20 | "checkRunSettingsSAST": { 21 | "checkRunConclusionLevel": "failure", 22 | "severityThreshold": "high" 23 | }, 24 | "issueSettings": { 25 | "minSeverityLevel": "LOW", 26 | "issueType": "DEPENDENCY" 27 | }, 28 | "remediateSettings": { 29 | "workflowRules": { 30 | "enabled": true 31 | } 32 | }, 33 | "imageSettings":{ 34 | "imageTracing":{ 35 | "enableImageTracingPR": false, 36 | "addRepositoryCoordinate": false, 37 | "addDockerfilePath": false, 38 | "addMendIdentifier": false 39 | } 40 | } 41 | } -------------------------------------------------------------------------------- /K8sOperator.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opensearch-project/opensearch-k8s-operator/6535cb9c684892f55f5a8c4cdb0398f140301cb0/K8sOperator.png -------------------------------------------------------------------------------- /MAINTAINERS.md: -------------------------------------------------------------------------------- 1 | # Maintainers 2 | 3 | | Maintainer | GitHub ID | Affiliation | 4 | | --------------- | --------- |--------------| 5 | | Idan Levy | [idanl21](https://github.com/idanl21) | Opster | 6 | | Ido | [ido-opster](https://github.com/ido-opster) | Opster | 7 | | Dan Bason | [dbason](https://github.com/dbason) | SUSE | 8 | | Sebastian Woehrl | [swoehrl-mw](https://github.com/swoehrl-mw) | MaibornWolff | 9 | | Prudhvi Godithi | [prudhvigodithi](https://github.com/prudhvigodithi) | Amazon | 10 | | Jochen Kressin | [jochenkressin](https://github.com/jochenkressin) | Eliatra | 11 | | Piotr Chmielnik | [pchmielnik](https://github.com/pchmielnik) | Eliatra | 12 | | Hendrik Saly | [salyh](https://github.com/salyh) | Eliatra | 13 | 14 | The following sections explain what maintainers do in this repo, and how they should be doing it. If you're interested in contributing, see [CONTRIBUTING](CONTRIBUTING.md). 15 | 16 | ## Release process 17 | 18 | To release a new version of the operator open Github in the browser, navigate to "Actions", select the workflow `Prepare and publish release`, select "Run workflow", then enter the version of the release (semver, x.y.z) and click "Run workflow". After a few seconds a new workflow run will start. It will do the following: 19 | 20 | * Run the test suite to make sure the version is functional 21 | * Update the helm chart for operator with the newest CRD YAMLs 22 | * Update `version` and `appVersion` in both the charts 23 | * Commit and push the chart changes 24 | * Tag the commit 25 | * Build and push the docker image 26 | * Create a new helm chart release using github pages 27 | * Create a new release on github in draft mode 28 | 29 | After the workflow has completed, navigate to releases and edit the new release. Generate a changelog, add any other needed information (upgrade instructions, warnings, incompatibilities, etc.) and then publish the release. 30 | 31 | In case it is needed you can also manually tag a commit for release, this will trigger a workflow that stars with the "Build and push the docker image" step. Make sure CRDs are up-to-date in the helm chart. 32 | 33 | After releasing a new version add it to the compatiblity matrix in the [README](README.md). 34 | -------------------------------------------------------------------------------- /charts/opensearch-cluster/.helmignore: -------------------------------------------------------------------------------- 1 | # Patterns to ignore when building packages. 2 | # This supports shell glob matching, relative path matching, and 3 | # negation (prefixed with !). Only one pattern per line. 4 | .DS_Store 5 | # Common VCS dirs 6 | .git/ 7 | .gitignore 8 | .bzr/ 9 | .bzrignore 10 | .hg/ 11 | .hgignore 12 | .svn/ 13 | # Common backup files 14 | *.swp 15 | *.bak 16 | *.tmp 17 | *.orig 18 | *~ 19 | # Various IDEs 20 | .project 21 | .idea/ 22 | *.tmproj 23 | .vscode/ 24 | -------------------------------------------------------------------------------- /charts/opensearch-cluster/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | All notable changes to this project will be documented in this file. 3 | 4 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 5 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 6 | 7 | --- 8 | ## [Unreleased] 9 | ### Added 10 | ### Changed 11 | ### Deprecated 12 | ### Removed 13 | ### Fixed 14 | ### Security 15 | --- 16 | 17 | ## [3.0.0] 18 | ### Added 19 | - Now it is possible to define any configuration that is supported by corresponding CRD by using exactly the same format 20 | as it is defined in the CRD 21 | - Support for all existing CRDs 22 | - Ingress configuration for Opensearch and Dashboards 23 | - Auto-generated README.md file with description for all possible configuration values 24 | ### Changed 25 | - `opensearchCluster` variable was replaced by `cluster`. The configuration structure of each custom resource (OpenSearchCluster, OpensearchIndexTemplate, etc) follows the corresponding CRD documentation 26 | ### Deprecated 27 | - opensearch-cluster helm chart is a fully refactored chart. Before upgrading to v3 check that [default chart values](../../charts/opensearch-cluster/values.yaml) 28 | matches with your configuration. 29 | ### Removed 30 | ### Fixed 31 | ### Security 32 | 33 | ## [2.6.1] 34 | ### Added 35 | ### Changed 36 | - Updated `version` and `appVersion` to `2.6.1` for the initial release after the helm release decouple. 37 | ### Deprecated 38 | ### Removed 39 | ### Fixed 40 | ### Security 41 | 42 | [Unreleased]: https://github.com/opensearch-project/opensearch-k8s-operator/compare/opensearch-operator-2.6.1...HEAD 43 | [2.6.1]: https://github.com/opensearch-project/opensearch-k8s-operator/compare/opensearch-operator-2.6.0...opensearch-operator-2.6.1 44 | 45 | -------------------------------------------------------------------------------- /charts/opensearch-cluster/Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v2 2 | name: opensearch-cluster 3 | description: A Helm chart for OpenSearch Cluster 4 | type: application 5 | 6 | ## The opensearch-cluster Helm Chart version 7 | version: 3.0.0 8 | 9 | ## The operator version 10 | appVersion: 2.7.0 11 | -------------------------------------------------------------------------------- /charts/opensearch-cluster/templates/NOTES.txt: -------------------------------------------------------------------------------- 1 | 1. Get the Opensearch application URL by running these commands: 2 | {{- if .Values.cluster.ingress.opensearch.enabled }} 3 | {{- range $host := .Values.cluster.ingress.opensearch.hosts }} 4 | {{- range .paths }} 5 | http{{ if $.Values.cluster.ingress.opensearch.tls }}s{{ end }}://{{ $host.host }}{{ .path }} 6 | {{- end }} 7 | {{- end }} 8 | {{- else }} 9 | export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "opster.io/opensearch-cluster={{ .Values.cluster.name | default (include "opensearch-cluster.name" .) }}" -o jsonpath="{.items[0].metadata.name}") 10 | export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}") 11 | kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 9200:$CONTAINER_PORT 12 | curl https://127.0.0.1:9200 -k 13 | {{- end }} 14 | 15 | {{ if .Values.cluster.dashboards.enable }} 16 | 2. Get the Dashboards application URL by running these commands: 17 | {{- if .Values.cluster.ingress.dashboards.enabled }} 18 | {{- range $host := .Values.cluster.ingress.dashboards.hosts }} 19 | {{- range .paths }} 20 | http{{ if $.Values.cluster.ingress.dashboards.tls }}s{{ end }}://{{ $host.host }}{{ .path }} 21 | {{- end }} 22 | {{- end }} 23 | {{- else if contains "NodePort" .Values.cluster.dashboards.service.type }} 24 | export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "opensearch-cluster.fullname" . }}) 25 | export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") 26 | echo http://$NODE_IP:$NODE_PORT 27 | {{- else if contains "LoadBalancer" .Values.cluster.dashboards.service.type }} 28 | NOTE: It may take a few minutes for the LoadBalancer IP to be available. 29 | You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "opensearch-cluster.fullname" . }}' 30 | export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "opensearch-cluster.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}") 31 | echo http://$SERVICE_IP:{{ .Values.service.port }} 32 | {{- else if contains "ClusterIP" .Values.cluster.dashboards.service.type }} 33 | export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "opensearch.cluster.dashboards={{ include "opensearch-cluster.name" . }}" -o jsonpath="{.items[0].metadata.name}") 34 | export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}") 35 | kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT 36 | Visit http://127.0.0.1:8080 to use your application 37 | {{- end }} 38 | {{- end }} 39 | -------------------------------------------------------------------------------- /charts/opensearch-cluster/templates/_helpers.tpl: -------------------------------------------------------------------------------- 1 | {{/* 2 | Expand the name of the chart. 3 | */}} 4 | {{- define "opensearch-cluster.name" -}} 5 | {{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} 6 | {{- end }} 7 | 8 | {{- define "opensearch-cluster.cluster-name" -}} 9 | {{- default .Values.cluster.name .Release.Name | trunc 63 | trimSuffix "-" }} 10 | {{- end }} 11 | 12 | {{/* 13 | Create a default fully qualified app name. 14 | We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). 15 | If release name contains chart name it will be used as a full name. 16 | */}} 17 | {{- define "opensearch-cluster.fullname" -}} 18 | {{- if .Values.fullnameOverride }} 19 | {{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} 20 | {{- else }} 21 | {{- $name := default .Chart.Name .Values.nameOverride }} 22 | {{- if contains $name .Release.Name }} 23 | {{- .Release.Name | trunc 63 | trimSuffix "-" }} 24 | {{- else }} 25 | {{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} 26 | {{- end }} 27 | {{- end }} 28 | {{- end }} 29 | 30 | {{/* 31 | Create chart name and version as used by the chart label. 32 | */}} 33 | {{- define "opensearch-cluster.chart" -}} 34 | {{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} 35 | {{- end }} 36 | 37 | {{/* 38 | Common labels 39 | */}} 40 | {{- define "opensearch-cluster.labels" -}} 41 | helm.sh/chart: {{ include "opensearch-cluster.chart" . }} 42 | {{- if .Chart.AppVersion }} 43 | app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} 44 | {{- end }} 45 | app.kubernetes.io/managed-by: {{ .Release.Service }} 46 | {{- with .Values.cluster.labels }} 47 | {{ . | toYaml }} 48 | {{- end }} 49 | {{- end }} 50 | 51 | {{/* 52 | Create the name of the service account to use 53 | */}} 54 | {{- define "opensearch-cluster.serviceAccountName" -}} 55 | {{- if .Values.serviceAccount.create }} 56 | {{- default (include "opensearch-cluster.fullname" .) .Values.serviceAccount.name }} 57 | {{- else }} 58 | {{- default "default" .Values.serviceAccount.name }} 59 | {{- end }} 60 | {{- end }} 61 | -------------------------------------------------------------------------------- /charts/opensearch-cluster/templates/actiongroups.yaml: -------------------------------------------------------------------------------- 1 | {{- $labels := include "opensearch-cluster.labels" . }} 2 | {{- $clusterName := include "opensearch-cluster.cluster-name" . }} 3 | {{- range .Values.actionGroups }} 4 | --- 5 | apiVersion: opensearch.opster.io/v1 6 | kind: OpensearchActionGroup 7 | metadata: 8 | name: {{ .name }} 9 | {{- with $.Values.cluster.annotations }} 10 | annotations: {{ . | toYaml | nindent 4 }} 11 | {{- end }} 12 | labels: {{ $labels | nindent 4 }} 13 | spec: 14 | opensearchCluster: 15 | name: {{ $clusterName }} 16 | {{- with .description }} 17 | description: {{ . | toString }} 18 | {{- end }} 19 | {{- with .allowedActions }} 20 | allowedActions: {{ . | toYaml | nindent 4 }} 21 | {{- end }} 22 | {{- with .type }} 23 | type: {{ . | toString }} 24 | {{- end }} 25 | {{- end }} 26 | -------------------------------------------------------------------------------- /charts/opensearch-cluster/templates/cluster.yaml: -------------------------------------------------------------------------------- 1 | {{- $clusterName := include "opensearch-cluster.cluster-name" . }} 2 | --- 3 | apiVersion: opensearch.opster.io/v1 4 | kind: OpenSearchCluster 5 | metadata: 6 | name: {{ $clusterName }} 7 | {{- with .Values.cluster.annotations }} 8 | annotations: {{ . | toYaml | nindent 4 }} 9 | {{- end }} 10 | labels: {{ include "opensearch-cluster.labels" . | nindent 4 }} 11 | spec: 12 | {{- with .Values.cluster.bootstrap }} 13 | bootstrap: {{ . | toYaml | nindent 4 }} 14 | {{- end }} 15 | {{- with .Values.cluster.confMgmt }} 16 | confMgmt: {{ . | toYaml | nindent 4 }} 17 | {{- end }} 18 | {{- with .Values.cluster.dashboards }} 19 | dashboards: 20 | {{- omit . "image" | toYaml | nindent 4 }} 21 | image: {{ .image }}:{{ .version }} 22 | {{- end }} 23 | {{- with .Values.cluster.general }} 24 | general: 25 | {{- omit . "image" "serviceName" | toYaml | nindent 4 }} 26 | image: {{ .image }}:{{ .version }} 27 | serviceName: {{ .serviceName | default $clusterName }} 28 | {{- end }} 29 | {{- with .Values.cluster.initHelper }} 30 | initHelper: {{ . | toYaml | nindent 4 }} 31 | {{- end }} 32 | {{- with .Values.cluster.nodePools }} 33 | nodePools: {{ . | toYaml | nindent 4 }} 34 | {{- end }} 35 | {{- with .Values.cluster.security }} 36 | security: 37 | tls: 38 | transport: 39 | {{- if .tls.transport.generate }} 40 | generate: {{ .tls.transport.generate }} 41 | {{- end }} 42 | {{- if .tls.transport.perNode }} 43 | perNode: {{ .tls.transport.perNode }} 44 | {{- end }} 45 | {{- with .tls.transport.caSecret }} 46 | caSecret: {{ . | toYaml | nindent 10 }} 47 | {{- end }} 48 | {{- with .tls.transport.adminDn }} 49 | adminDn: {{ . | toYaml | nindent 10 }} 50 | {{- end }} 51 | {{- with .tls.transport.nodesDn }} 52 | nodesDn: {{ . | toYaml | nindent 10 }} 53 | {{- end }} 54 | {{- with .tls.transport.secret }} 55 | secret: {{ . | toYaml | nindent 10 }} 56 | {{- end }} 57 | http: 58 | {{- if .tls.http.generate }} 59 | generate: {{ .tls.http.generate }} 60 | {{- end }} 61 | {{- with .tls.http.secret }} 62 | secret: {{ . | toYaml | nindent 10 }} 63 | {{- end }} 64 | {{- with .tls.http.caSecret }} 65 | caSecret: {{ . | toYaml | nindent 10 }} 66 | {{- end }} 67 | {{- with .config }} 68 | config: {{ . | toYaml | nindent 6 }} 69 | {{- end }} 70 | {{- end }} 71 | -------------------------------------------------------------------------------- /charts/opensearch-cluster/templates/componenttemplates.yaml: -------------------------------------------------------------------------------- 1 | {{- $labels := include "opensearch-cluster.labels" . }} 2 | {{- $clusterName := include "opensearch-cluster.cluster-name" . }} 3 | {{- range .Values.componentTemplates }} 4 | --- 5 | apiVersion: opensearch.opster.io/v1 6 | kind: OpensearchComponentTemplate 7 | metadata: 8 | name: {{ .name }} 9 | {{- with $.Values.cluster.annotations }} 10 | annotations: {{ . | toYaml | nindent 4 }} 11 | {{- end }} 12 | labels: {{ $labels | nindent 4 }} 13 | spec: 14 | opensearchCluster: 15 | name: {{ $clusterName }} 16 | allowAutoCreate: {{ .allowAutoCreate | default false }} 17 | {{- with .templateSpec }} 18 | template: {{ . | toYaml | nindent 4 }} 19 | {{- end }} 20 | {{- with .version }} 21 | version: {{ . }} 22 | {{- end }} 23 | {{- with ._meta }} 24 | _meta: {{ . | toYaml | nindent 4 }} 25 | {{- end }} 26 | {{- end }} 27 | -------------------------------------------------------------------------------- /charts/opensearch-cluster/templates/indextemplates.yaml: -------------------------------------------------------------------------------- 1 | {{- $labels := include "opensearch-cluster.labels" . }} 2 | {{- $clusterName := include "opensearch-cluster.cluster-name" . }} 3 | {{- range .Values.indexTemplates }} 4 | --- 5 | apiVersion: opensearch.opster.io/v1 6 | kind: OpensearchIndexTemplate 7 | metadata: 8 | name: {{ .name }} 9 | {{- with $.Values.cluster.annotations }} 10 | annotations: {{ . | toYaml | nindent 4 }} 11 | {{- end }} 12 | labels: {{ $labels | nindent 4 }} 13 | spec: 14 | opensearchCluster: 15 | name: {{ $clusterName }} 16 | {{- if not (eq .dataStream nil) }} 17 | dataStream: {{ .dataStream | toYaml | nindent 4 }} 18 | {{- end }} 19 | {{- with .indexPatterns }} 20 | indexPatterns: {{ . | toYaml | nindent 4 }} 21 | {{- end }} 22 | {{- with .composedOf }} 23 | composedOf: {{ . | toYaml | nindent 4 }} 24 | {{- end }} 25 | {{- with .priority }} 26 | priority: {{ . }} 27 | {{- end }} 28 | {{- with .templateSpec }} 29 | template: {{ . | toYaml | nindent 4 }} 30 | {{- end }} 31 | {{- with .version }} 32 | version: {{ . }} 33 | {{- end }} 34 | {{- with ._meta }} 35 | _meta: {{ . | toYaml | nindent 4 }} 36 | {{- end }} 37 | {{- end }} 38 | -------------------------------------------------------------------------------- /charts/opensearch-cluster/templates/ismpolicies.yaml: -------------------------------------------------------------------------------- 1 | {{- $labels := include "opensearch-cluster.labels" . }} 2 | {{- $clusterName := include "opensearch-cluster.cluster-name" . }} 3 | {{- range .Values.ismPolicies }} 4 | --- 5 | apiVersion: opensearch.opster.io/v1 6 | kind: OpenSearchISMPolicy 7 | metadata: 8 | name: {{ .name }} 9 | {{- with $.Values.cluster.annotations }} 10 | annotations: {{ . | toYaml | nindent 4 }} 11 | {{- end }} 12 | labels: {{ $labels | nindent 4 }} 13 | spec: 14 | defaultState: {{ .defaultState }} 15 | description: {{ .description }} 16 | {{- with .states }} 17 | states: {{ . | toYaml | nindent 4 }} 18 | {{- end }} 19 | {{- with .errorNotification }} 20 | errorNotification: {{ . | toYaml | nindent 4 }} 21 | {{- end }} 22 | {{- with .ismTemplate }} 23 | ismTemplate: {{ . | toYaml | nindent 4 }} 24 | {{- end }} 25 | opensearchCluster: 26 | name: {{ $clusterName }} 27 | {{- with .policyId }} 28 | policyId: {{ . }} 29 | {{- end }} 30 | {{- end }} 31 | -------------------------------------------------------------------------------- /charts/opensearch-cluster/templates/roles.yaml: -------------------------------------------------------------------------------- 1 | {{- $labels := include "opensearch-cluster.labels" . }} 2 | {{- $clusterName := include "opensearch-cluster.cluster-name" . }} 3 | {{- range .Values.roles }} 4 | --- 5 | apiVersion: opensearch.opster.io/v1 6 | kind: OpensearchRole 7 | metadata: 8 | name: {{ .name }} 9 | {{- with $.Values.cluster.annotations }} 10 | annotations: {{ . | toYaml | nindent 4 }} 11 | {{- end }} 12 | labels: {{ $labels | nindent 4 }} 13 | spec: 14 | opensearchCluster: 15 | name: {{ $clusterName }} 16 | {{- with .clusterPermissions }} 17 | clusterPermissions: {{ . | toYaml | nindent 4 }} 18 | {{- end }} 19 | {{- with .indexPermissions }} 20 | indexPermissions: {{ . | toYaml | nindent 4 }} 21 | {{- end }} 22 | {{- with .tenantPermissions }} 23 | tenantPermissions: {{ . | toYaml | nindent 4 }} 24 | {{- end }} 25 | {{- end }} 26 | -------------------------------------------------------------------------------- /charts/opensearch-cluster/templates/serviceaccount.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.serviceAccount.create -}} 2 | apiVersion: v1 3 | kind: ServiceAccount 4 | metadata: 5 | name: {{ include "opensearch-cluster.serviceAccountName" . }} 6 | labels: 7 | {{- include "opensearch-cluster.labels" . | nindent 4 }} 8 | {{- with .Values.serviceAccount.annotations }} 9 | annotations: 10 | {{- toYaml . | nindent 4 }} 11 | {{- end }} 12 | {{- end }} 13 | -------------------------------------------------------------------------------- /charts/opensearch-cluster/templates/tenants.yaml: -------------------------------------------------------------------------------- 1 | {{- $labels := include "opensearch-cluster.labels" . }} 2 | {{- $clusterName := include "opensearch-cluster.cluster-name" . }} 3 | {{- range .Values.tenants }} 4 | --- 5 | apiVersion: opensearch.opster.io/v1 6 | kind: OpensearchTenant 7 | metadata: 8 | name: {{ .name }} 9 | {{- with $.Values.cluster.annotations }} 10 | annotations: {{ . | toYaml | nindent 4 }} 11 | {{- end }} 12 | labels: {{ $labels | nindent 4 }} 13 | spec: 14 | opensearchCluster: 15 | name: {{ $clusterName }} 16 | {{- with .description }} 17 | description: {{ . | toString }} 18 | {{- end }} 19 | {{- end }} 20 | -------------------------------------------------------------------------------- /charts/opensearch-cluster/templates/userrolebinding.yaml: -------------------------------------------------------------------------------- 1 | {{- $labels := include "opensearch-cluster.labels" . }} 2 | {{- $clusterName := include "opensearch-cluster.cluster-name" . }} 3 | {{- range .Values.usersRoleBinding }} 4 | --- 5 | apiVersion: opensearch.opster.io/v1 6 | kind: OpensearchUserRoleBinding 7 | metadata: 8 | name: {{ .name }} 9 | {{- with $.Values.cluster.annotations }} 10 | annotations: {{ . | toYaml | nindent 4 }} 11 | {{- end }} 12 | labels: {{ $labels | nindent 4 }} 13 | spec: 14 | opensearchCluster: 15 | name: {{ $clusterName }} 16 | {{- with .users }} 17 | users: {{ . | toYaml | nindent 4 }} 18 | {{- end }} 19 | {{- with .backendRoles }} 20 | backendRoles: {{ . | toYaml | nindent 4 }} 21 | {{- end }} 22 | {{- with .roles }} 23 | roles: {{ . | toYaml | nindent 4 }} 24 | {{- end }} 25 | {{- end }} 26 | -------------------------------------------------------------------------------- /charts/opensearch-cluster/templates/users.yaml: -------------------------------------------------------------------------------- 1 | {{- $labels := include "opensearch-cluster.labels" . }} 2 | {{- $clusterName := include "opensearch-cluster.cluster-name" . }} 3 | {{- range .Values.users }} 4 | --- 5 | apiVersion: opensearch.opster.io/v1 6 | kind: OpensearchUser 7 | metadata: 8 | name: {{ .name }} 9 | {{- with $.Values.cluster.annotations }} 10 | annotations: {{ . | toYaml | nindent 4 }} 11 | {{- end }} 12 | labels: {{ $labels | nindent 4 }} 13 | spec: 14 | opensearchCluster: 15 | name: {{ $clusterName }} 16 | passwordFrom: 17 | name: {{ .secretName }} 18 | key: {{ .secretKey }} 19 | {{- with .backendRoles }} 20 | backendRoles: {{ . | toYaml | nindent 4 }} 21 | {{- end }} 22 | {{- with .opendistroSecurityRoles }} 23 | opendistroSecurityRoles: {{ . | toYaml | nindent 4 }} 24 | {{- end }} 25 | {{- end }} 26 | -------------------------------------------------------------------------------- /charts/opensearch-operator/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | All notable changes to this project will be documented in this file. 3 | 4 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 5 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 6 | 7 | --- 8 | ## [Unreleased] 9 | ### Added 10 | - Added support for custom image used by `kubeRbacProxy`. 11 | ### Changed 12 | ### Deprecated 13 | ### Removed 14 | ### Fixed 15 | ### Security 16 | 17 | --- 18 | ## [2.0.0] 19 | ### Added 20 | ### Changed 21 | - Modified `version` to `2.0.0` and `appVersion` to `v2.0`. 22 | - Allow chart image tag to pick from `appVersion`, unless explicitly passed `tag` values in `values.yaml` file. 23 | ### Deprecated 24 | ### Removed 25 | ### Fixed 26 | ### Security 27 | 28 | --- 29 | ## [1.0.3] 30 | ### Added 31 | ### Changed 32 | - Added missing spec `dashboards.additionalConfig` 33 | ### Deprecated 34 | ### Removed 35 | ### Fixed 36 | ### Security 37 | 38 | --- 39 | ## [1.0.2] 40 | ### Added 41 | ### Changed 42 | - Added README.md file to charts/ folder. 43 | ### Deprecated 44 | ### Removed 45 | ### Fixed 46 | ### Security 47 | 48 | --- 49 | ## [1.0.1] 50 | ### Added 51 | ### Changed 52 | - Updated version to 1.0.1 53 | ### Deprecated 54 | ### Removed 55 | ### Fixed 56 | ### Security 57 | 58 | [Unreleased]: https://github.com/opensearch-project/opensearch-k8s-operator/compare/opensearch-operator-2.0.0...HEAD 59 | [2.0.0]: https://github.com/opensearch-project/opensearch-k8s-operator/compare/opensearch-operator-1.0.3...opensearch-operator-2.0.0 60 | [1.0.3]: https://github.com/opensearch-project/opensearch-k8s-operator/compare/opensearch-operator-1.0.2...opensearch-operator-1.0.3 61 | [1.0.2]: https://github.com/opensearch-project/opensearch-k8s-operator/compare/opensearch-operator-1.0.1...opensearch-operator-1.0.2 62 | -------------------------------------------------------------------------------- /charts/opensearch-operator/Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v2 2 | name: opensearch-operator 3 | description: The OpenSearch Operator Helm chart for Kubernetes 4 | 5 | # A chart can be either an 'application' or a 'library' chart. 6 | # 7 | # Application charts are a collection of templates that can be packaged into versioned archives 8 | # to be deployed. 9 | # 10 | # Library charts provide useful utilities or functions for the chart developer. They're included as 11 | # a dependency of application charts to inject those utilities and functions into the rendering 12 | # pipeline. Library charts do not define any templates and therefore cannot be deployed. 13 | type: application 14 | 15 | # This is the opensearch-operator chart version. This version number should be incremented each time you make changes 16 | # to the chart and its templates, including the app version. 17 | # Versions are expected to follow Semantic Versioning (https://semver.org/) 18 | version: 2.7.0 19 | 20 | # This is the version number of the application being deployed (the operator). This version number should be 21 | # incremented each time you make changes to the application. Versions are not expected to 22 | # follow Semantic Versioning. They should reflect the version the application is using. 23 | # It is recommended to use it with quotes. 24 | appVersion: 2.7.0 25 | -------------------------------------------------------------------------------- /charts/opensearch-operator/README.md: -------------------------------------------------------------------------------- 1 | # OpenSearch-k8s-operator 2 | 3 | The Kubernetes [OpenSearch Operator](https://github.com/opensearch-project/opensearch-k8s-operator) is used for automating the deployment, provisioning, management, and orchestration of OpenSearch clusters and OpenSearch dashboards. 4 | 5 | ## Getting started 6 | 7 | The Operator can be easily installed using helm on any CNCF-certified Kubernetes cluster. Please refer to the [User Guide](https://github.com/opensearch-project/opensearch-k8s-operator/blob/main/docs/userguide/main.md) for more information. 8 | 9 | ### Installation Using Helm 10 | 11 | #### Get Repo Info 12 | ``` 13 | helm repo add opensearch-operator https://opensearch-project.github.io/opensearch-k8s-operator/ 14 | helm repo update 15 | ``` 16 | #### Install Chart 17 | ``` 18 | helm install [RELEASE_NAME] opensearch-operator/opensearch-operator 19 | ``` 20 | #### Uninstall Chart 21 | ``` 22 | helm uninstall [RELEASE_NAME] 23 | ``` 24 | #### Upgrade Chart 25 | ``` 26 | helm repo update 27 | helm upgrade [RELEASE_NAME] opensearch-operator/opensearch-operator 28 | ``` 29 | 30 | -------------------------------------------------------------------------------- /charts/opensearch-operator/files/opensearch.opster.io_opensearchtenants.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: apiextensions.k8s.io/v1 3 | kind: CustomResourceDefinition 4 | metadata: 5 | annotations: 6 | controller-gen.kubebuilder.io/version: v0.14.0 7 | name: opensearchtenants.opensearch.opster.io 8 | spec: 9 | group: opensearch.opster.io 10 | names: 11 | kind: OpensearchTenant 12 | listKind: OpensearchTenantList 13 | plural: opensearchtenants 14 | shortNames: 15 | - opensearchtenant 16 | singular: opensearchtenant 17 | scope: Namespaced 18 | versions: 19 | - name: v1 20 | schema: 21 | openAPIV3Schema: 22 | description: OpensearchTenant is the Schema for the opensearchtenants API 23 | properties: 24 | apiVersion: 25 | description: |- 26 | APIVersion defines the versioned schema of this representation of an object. 27 | Servers should convert recognized schemas to the latest internal value, and 28 | may reject unrecognized values. 29 | More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources 30 | type: string 31 | kind: 32 | description: |- 33 | Kind is a string value representing the REST resource this object represents. 34 | Servers may infer this from the endpoint the client submits requests to. 35 | Cannot be updated. 36 | In CamelCase. 37 | More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds 38 | type: string 39 | metadata: 40 | type: object 41 | spec: 42 | description: OpensearchTenantSpec defines the desired state of OpensearchTenant 43 | properties: 44 | description: 45 | type: string 46 | opensearchCluster: 47 | description: |- 48 | LocalObjectReference contains enough information to let you locate the 49 | referenced object inside the same namespace. 50 | properties: 51 | name: 52 | description: |- 53 | Name of the referent. 54 | More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names 55 | TODO: Add other useful fields. apiVersion, kind, uid? 56 | type: string 57 | type: object 58 | x-kubernetes-map-type: atomic 59 | required: 60 | - opensearchCluster 61 | type: object 62 | status: 63 | description: OpensearchTenantStatus defines the observed state of OpensearchTenant 64 | properties: 65 | existingTenant: 66 | type: boolean 67 | managedCluster: 68 | description: |- 69 | UID is a type that holds unique ID values, including UUIDs. Because we 70 | don't ONLY use UUIDs, this is an alias to string. Being a type captures 71 | intent and helps make sure that UIDs and names do not get conflated. 72 | type: string 73 | reason: 74 | type: string 75 | state: 76 | type: string 77 | type: object 78 | type: object 79 | served: true 80 | storage: true 81 | subresources: 82 | status: {} 83 | -------------------------------------------------------------------------------- /charts/opensearch-operator/templates/_helpers.tpl: -------------------------------------------------------------------------------- 1 | {{/* 2 | Expand the name of the chart. 3 | */}} 4 | {{- define "opensearch-operator.name" -}} 5 | {{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} 6 | {{- end }} 7 | 8 | {{/* 9 | Create a default fully qualified app name. 10 | We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). 11 | If release name contains chart name it will be used as a full name. 12 | */}} 13 | {{- define "opensearch-operator.fullname" -}} 14 | {{- if .Values.fullnameOverride }} 15 | {{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} 16 | {{- else }} 17 | {{- $name := default .Chart.Name .Values.nameOverride }} 18 | {{- if contains $name .Release.Name }} 19 | {{- .Release.Name | trunc 63 | trimSuffix "-" }} 20 | {{- else }} 21 | {{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} 22 | {{- end }} 23 | {{- end }} 24 | {{- end }} 25 | 26 | {{/* 27 | Create chart name and version as used by the chart label. 28 | */}} 29 | {{- define "opensearch-operator.chart" -}} 30 | {{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} 31 | {{- end }} 32 | 33 | {{/* 34 | Common labels 35 | */}} 36 | {{- define "opensearch-operator.labels" -}} 37 | helm.sh/chart: {{ include "opensearch-operator.chart" . }} 38 | {{ include "opensearch-operator.selectorLabels" . }} 39 | {{- if .Chart.AppVersion }} 40 | app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} 41 | {{- end }} 42 | app.kubernetes.io/managed-by: {{ .Release.Service }} 43 | {{- end }} 44 | 45 | {{/* 46 | Selector labels 47 | */}} 48 | {{- define "opensearch-operator.selectorLabels" -}} 49 | app.kubernetes.io/name: {{ include "opensearch-operator.name" . }} 50 | app.kubernetes.io/instance: {{ .Release.Name }} 51 | {{- end }} 52 | 53 | {{/* 54 | Create the name of the service account to use 55 | */}} 56 | {{- define "opensearch-operator.serviceAccountName" -}} 57 | {{- if .Values.serviceAccount.create }} 58 | {{- default (printf "%s-%s" (include "opensearch-operator.fullname" .) "controller-manager") .Values.serviceAccount.name }} 59 | {{- else }} 60 | {{- default "opensearch-operator-controller-manager" .Values.serviceAccount.name }} 61 | {{- end }} 62 | {{- end }} 63 | -------------------------------------------------------------------------------- /charts/opensearch-operator/templates/opensearch-operator-controller-manager-metrics-service-svc.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | labels: 5 | control-plane: controller-manager 6 | name: {{ include "opensearch-operator.fullname" . }}-controller-manager-metrics-service 7 | spec: 8 | ports: 9 | - name: https 10 | port: 8443 11 | targetPort: https 12 | selector: 13 | control-plane: controller-manager 14 | -------------------------------------------------------------------------------- /charts/opensearch-operator/templates/opensearch-operator-controller-manager-sa.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.serviceAccount.create -}} 2 | apiVersion: v1 3 | kind: ServiceAccount 4 | metadata: 5 | name: {{ include "opensearch-operator.serviceAccountName" . }} 6 | {{- end -}} 7 | -------------------------------------------------------------------------------- /charts/opensearch-operator/templates/opensearch-operator-crds.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.installCRDs -}} 2 | {{- range $path, $bytes := .Files.Glob "files/*.yaml" }} 3 | {{ $.Files.Get $path }} 4 | {{- end }} 5 | {{- end }} 6 | -------------------------------------------------------------------------------- /charts/opensearch-operator/templates/opensearch-operator-leader-election-role-role.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: Role 3 | metadata: 4 | name: {{ include "opensearch-operator.fullname" . }}-leader-election-role 5 | rules: 6 | - apiGroups: 7 | - "" 8 | resources: 9 | - configmaps 10 | verbs: 11 | - get 12 | - list 13 | - watch 14 | - create 15 | - update 16 | - patch 17 | - delete 18 | - apiGroups: 19 | - coordination.k8s.io 20 | resources: 21 | - leases 22 | verbs: 23 | - get 24 | - list 25 | - watch 26 | - create 27 | - update 28 | - patch 29 | - delete 30 | - apiGroups: 31 | - "" 32 | resources: 33 | - events 34 | verbs: 35 | - create 36 | - patch 37 | - apiGroups: 38 | - monitoring.coreos.com 39 | resources: 40 | - servicemonitors 41 | verbs: 42 | - create 43 | - delete 44 | - get 45 | - list 46 | - patch 47 | - update 48 | - watch 49 | -------------------------------------------------------------------------------- /charts/opensearch-operator/templates/opensearch-operator-leader-election-rolebinding-rb.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: RoleBinding 3 | metadata: 4 | name: {{ include "opensearch-operator.fullname" . }}-leader-election-rolebinding 5 | roleRef: 6 | apiGroup: rbac.authorization.k8s.io 7 | kind: Role 8 | name: {{ include "opensearch-operator.fullname" . }}-leader-election-role 9 | subjects: 10 | - kind: ServiceAccount 11 | name: {{ include "opensearch-operator.serviceAccountName" . }} 12 | -------------------------------------------------------------------------------- /charts/opensearch-operator/templates/opensearch-operator-manager-config-cm.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | data: 3 | controller_manager_config.yaml: | 4 | apiVersion: controller-runtime.sigs.k8s.io/v1alpha1 5 | kind: ControllerManagerConfig 6 | health: 7 | healthProbeBindAddress: :8081 8 | metrics: 9 | bindAddress: 127.0.0.1:8080 10 | webhook: 11 | port: 9443 12 | leaderElection: 13 | leaderElect: true 14 | resourceName: a867c7dc.opensearch.opster.io 15 | kind: ConfigMap 16 | metadata: 17 | name: {{ include "opensearch-operator.fullname" . }}-manager-config 18 | -------------------------------------------------------------------------------- /charts/opensearch-operator/templates/opensearch-operator-manager-rolebinding.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.useRoleBindings }} 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: RoleBinding 4 | metadata: 5 | name: {{ include "opensearch-operator.fullname" . }}-{{ .Release.Namespace }}-manager-rolebinding 6 | roleRef: 7 | apiGroup: rbac.authorization.k8s.io 8 | kind: ClusterRole 9 | name: {{ include "opensearch-operator.fullname" . }}-{{ .Release.Namespace }}-manager-role 10 | subjects: 11 | - kind: ServiceAccount 12 | name: {{ include "opensearch-operator.serviceAccountName" . }} 13 | namespace: {{ .Release.Namespace }} 14 | {{- else }} 15 | apiVersion: rbac.authorization.k8s.io/v1 16 | kind: ClusterRoleBinding 17 | metadata: 18 | name: {{ include "opensearch-operator.fullname" . }}-{{ .Release.Namespace }}-manager-rolebinding 19 | roleRef: 20 | apiGroup: rbac.authorization.k8s.io 21 | kind: ClusterRole 22 | name: {{ include "opensearch-operator.fullname" . }}-{{ .Release.Namespace }}-manager-role 23 | subjects: 24 | - kind: ServiceAccount 25 | name: {{ include "opensearch-operator.serviceAccountName" . }} 26 | namespace: {{ .Release.Namespace }} 27 | {{- end }} 28 | -------------------------------------------------------------------------------- /charts/opensearch-operator/templates/opensearch-operator-metrics-reader-cr.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRole 3 | metadata: 4 | name: {{ include "opensearch-operator.fullname" . }}-{{ .Release.Namespace }}-metrics-reader 5 | rules: 6 | - nonResourceURLs: 7 | - /metrics 8 | verbs: 9 | - get 10 | -------------------------------------------------------------------------------- /charts/opensearch-operator/templates/opensearch-operator-proxy-role-cr.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRole 3 | metadata: 4 | name: {{ include "opensearch-operator.fullname" . }}-{{ .Release.Namespace }}-proxy-role 5 | rules: 6 | - apiGroups: 7 | - authentication.k8s.io 8 | resources: 9 | - tokenreviews 10 | verbs: 11 | - create 12 | - apiGroups: 13 | - authorization.k8s.io 14 | resources: 15 | - subjectaccessreviews 16 | verbs: 17 | - create 18 | -------------------------------------------------------------------------------- /charts/opensearch-operator/templates/opensearch-operator-proxy-rolebinding.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.useRoleBindings }} 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: RoleBinding 4 | metadata: 5 | name: {{ include "opensearch-operator.fullname" . }}-{{ .Release.Namespace }}-proxy-rolebinding 6 | roleRef: 7 | apiGroup: rbac.authorization.k8s.io 8 | kind: ClusterRole 9 | name: {{ include "opensearch-operator.fullname" . }}-{{ .Release.Namespace }}-proxy-role 10 | subjects: 11 | - kind: ServiceAccount 12 | name: {{ include "opensearch-operator.serviceAccountName" . }} 13 | namespace: {{ .Release.Namespace }} 14 | {{- else }} 15 | apiVersion: rbac.authorization.k8s.io/v1 16 | kind: ClusterRoleBinding 17 | metadata: 18 | name: {{ include "opensearch-operator.fullname" . }}-{{ .Release.Namespace }}-proxy-rolebinding 19 | roleRef: 20 | apiGroup: rbac.authorization.k8s.io 21 | kind: ClusterRole 22 | name: {{ include "opensearch-operator.fullname" . }}-{{ .Release.Namespace }}-proxy-role 23 | subjects: 24 | - kind: ServiceAccount 25 | name: {{ include "opensearch-operator.serviceAccountName" . }} 26 | namespace: {{ .Release.Namespace }} 27 | {{- end }} 28 | -------------------------------------------------------------------------------- /charts/opensearch-operator/values.yaml: -------------------------------------------------------------------------------- 1 | nameOverride: "" 2 | fullnameOverride: "" 3 | 4 | podAnnotations: {} 5 | podLabels: {} 6 | nodeSelector: {} 7 | tolerations: [] 8 | securityContext: 9 | runAsNonRoot: true 10 | priorityClassName: "" 11 | manager: 12 | securityContext: 13 | allowPrivilegeEscalation: false 14 | extraEnv: [] 15 | resources: 16 | limits: 17 | cpu: 200m 18 | memory: 500Mi 19 | requests: 20 | cpu: 100m 21 | memory: 350Mi 22 | 23 | livenessProbe: 24 | failureThreshold: 3 25 | httpGet: 26 | path: /healthz 27 | port: 8081 28 | periodSeconds: 15 29 | successThreshold: 1 30 | timeoutSeconds: 3 31 | initialDelaySeconds: 10 32 | 33 | readinessProbe: 34 | failureThreshold: 3 35 | httpGet: 36 | path: /readyz 37 | port: 8081 38 | periodSeconds: 15 39 | successThreshold: 1 40 | timeoutSeconds: 3 41 | initialDelaySeconds: 10 42 | 43 | # Set this to false to disable the experimental parallel recovery in case you are experiencing problems 44 | parallelRecoveryEnabled: true 45 | # Set this to true to enable the standard go pprof endpoints on port 6060 (https://pkg.go.dev/net/http/pprof) 46 | # Should only be used for debugging purposes 47 | pprofEndpointsEnabled: false 48 | 49 | image: 50 | repository: opensearchproject/opensearch-operator 51 | ## tag default uses appVersion from Chart.yaml, to override specify tag tag: "v1.1" 52 | tag: "" 53 | pullPolicy: "Always" 54 | 55 | ## Optional array of imagePullSecrets containing private registry credentials 56 | imagePullSecrets: [] 57 | # - name: secretName 58 | 59 | dnsBase: cluster.local 60 | 61 | # Log level of the operator. Possible values: debug, info, warn, error 62 | loglevel: info 63 | 64 | # If a watchNamespace is specified, the manager's cache will be restricted to 65 | # watch objects in the desired namespace. Defaults is to watch all namespaces. 66 | watchNamespace: 67 | 68 | # Install the Custom Resource Definitions with Helm 69 | installCRDs: true 70 | 71 | serviceAccount: 72 | # Specifies whether a service account should be created 73 | create: true 74 | # Override the service account name. Defaults to opensearch-operator-controller-manager 75 | name: "" 76 | 77 | kubeRbacProxy: 78 | enable: true 79 | securityContext: 80 | allowPrivilegeEscalation: false 81 | readOnlyRootFilesystem: true 82 | capabilities: 83 | drop: 84 | - ALL 85 | resources: 86 | limits: 87 | cpu: 50m 88 | memory: 50Mi 89 | requests: 90 | cpu: 25m 91 | memory: 25Mi 92 | 93 | livenessProbe: 94 | failureThreshold: 3 95 | httpGet: 96 | path: /healthz 97 | port: 10443 98 | scheme: HTTPS 99 | periodSeconds: 15 100 | successThreshold: 1 101 | timeoutSeconds: 3 102 | initialDelaySeconds: 10 103 | 104 | readinessProbe: 105 | failureThreshold: 3 106 | httpGet: 107 | path: /healthz 108 | port: 10443 109 | scheme: HTTPS 110 | periodSeconds: 15 111 | successThreshold: 1 112 | timeoutSeconds: 3 113 | initialDelaySeconds: 10 114 | 115 | image: 116 | repository: "gcr.io/kubebuilder/kube-rbac-proxy" 117 | tag: "v0.15.0" 118 | 119 | ## If this is set to true, RoleBindings will be used instead of ClusterRoleBindings, inorder to restrict ClusterRoles 120 | ## to the namespace where the operator and OpenSearch cluster are in. In that case, specify the namespace where they 121 | ## are in in manager.watchNamespace field. 122 | ## If false, ClusterRoleBindings will be used 123 | useRoleBindings: false 124 | -------------------------------------------------------------------------------- /ct.yaml: -------------------------------------------------------------------------------- 1 | target-branch: main 2 | helm-extra-args: --timeout 800s 3 | -------------------------------------------------------------------------------- /docs/designs/assets/K8sOperator.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opensearch-project/opensearch-k8s-operator/6535cb9c684892f55f5a8c4cdb0398f140301cb0/docs/designs/assets/K8sOperator.png -------------------------------------------------------------------------------- /docs/designs/configuration.md: -------------------------------------------------------------------------------- 1 | # Cluster configuration 2 | 3 | The operator makes use of two methods for configuring a cluster. For user defined additional configuration key value pairs, these are added to the pods as environment variable. On startup the Opensearch containers will load the environment variables as Opensearch configuration. Security plugin configurations that are applied by the operator are added to the `opensearch.yml` config file which is then mounted into the container. 4 | 5 | ## Rolling restarts 6 | 7 | If a config file is being injected into the pods then a SHA1 hash is calculated for the content of the file and added as an annotation to the pods. This allows us to detect changes which will trigger restarts. For environment variable changes these will also result in a restart. 8 | 9 | For non data nodes the Kubernetes stateful set controller will restart the pods. For data nodes the rolling restart reconciler will detect if there is a pending change to the pods and gracefully restart them. 10 | 11 | ## Configuration changes during upgrades 12 | 13 | When a rolling upgrade is in flight non data nodes will not be modified to prevent unexpected restarts. These changes will be picked up after the data nodes have been upgraded. For data nodes the changes will be added. These will be picked up during the restarts for the rolling upgrade. If a data node pool has already been restarted they will be picked up by the restart reconciler. 14 | 15 | To achieve this the operator tracks the changes per node pool, and decides whether to update the hash and environment variables independently for each node pool. -------------------------------------------------------------------------------- /docs/designs/opensearch-rbac.md: -------------------------------------------------------------------------------- 1 | # Opensearch Roles, Users, and Role Mappings reconciliation 2 | Opensearch Roles, Users, and Role Mappings can be managed in a Kubernetes native fashion by reconciling custom resources against the Opensearch API. Each resource needs to contain a reference to an OpenSearchCluster resource to reconcile against. 3 | 4 | The reconciliation loop will need mechanisms to prevent overwriting or deleting Opensearch API objects that are not managed by k8s. The Opensearch cluster reference should also not be changed as this can lead to orphaned objects or unexpected behaviour. This is enforced by adding the Opensearch cluster reference to the status field when the object is first reconciled. On subsequent operations if this does not match the reconciler will raise an error. 5 | 6 | ## Users 7 | The name of the k8s OpensearchUser object will be the name of the User in Opensearch. The majority of the CRD matches the Opensearch API, however the password must be stored in a secret, and a reference is passed to the custom resource. 8 | 9 | When the user is created in the Opensearch API the k8s object UID is added as an attribute. On all subsequent CRUD operations the UID is checked, and if it is not present, or does not match, then the operation will not be completed. 10 | 11 | ## Roles 12 | The name of the k8s OpensearchRole object will be the name of the Role in Opensearch. The OpensearchRoleSpec matches the Opensearch Roles API. 13 | 14 | When an OpensearchRole is first reconciled the API is checked to see if the Role already exists. If it does it is marked in the resource status, and no CRUD operations will be performed against the Opensearch API. 15 | 16 | 17 | ## Role Mappings 18 | The operator uses OpensearchUserRoleBinding object that links users, backend roles and roles together in a many <-> many relationship. For each role the custom resource the operator will make sure there is a matching Role Mapping in the Opensearch API, that contains all of the users and backend roles that are in the resource. 19 | 20 | Due to the many <-> many nature of the binding, and the simplicity of Role Mappings there are not the same protections against CRUD operations. -------------------------------------------------------------------------------- /docs/userguide/cluster-chart.md: -------------------------------------------------------------------------------- 1 | # Install OpenSearchCluster Using Helm 2 | 3 | After installing the operator (please refer to the [User Guide](./main.md) for details) you can deploy OpenSearch clusters using a separate helm chart. 4 | 5 | ## Install Chart 6 | 7 | ```bash 8 | helm install [RELEASE_NAME] opensearch-operator/opensearch-cluster 9 | ``` 10 | 11 | ## Uninstall Chart 12 | 13 | ```bash 14 | helm uninstall [RELEASE_NAME] 15 | ``` 16 | 17 | ## Upgrade Chart 18 | 19 | ### Upgrading to version 3 20 | 21 | Version 3.0.0 of opensearch-cluster helm chart is a fully refactored chart. Before upgrading to v3 check that [default chart values](../../charts/opensearch-cluster/values.yaml) 22 | matches with your configuration. 23 | 24 | In v3 `opensearchCluster` variable was replaced by `cluster`. The configuration structure of each custom resource (OpenSearchCluster, OpensearchIndexTemplate, etc) follows the corresponding CRD documentation. 25 | 26 | **Make sure to test the upgrade process on none-production environment first.** 27 | 28 | If the cluster was installed by using the default `values.yaml`, then the upgrade could be done by running: 29 | 30 | ```bash 31 | helm repo update 32 | helm upgrade [RELEASE_NAME] opensearch-operator/opensearch-cluster 33 | ``` 34 | 35 | ## Configuring OpenSearch Cluster 36 | 37 | By default, the installation will deploy a node pool consisting of three master nodes with the dashboard enabled. For the entire configuration, check [helm chart values](../../charts/opensearch-cluster/values.yaml). 38 | 39 | To further customize your OpenSearchCluster installation, you can utilize configuration overrides and modify your `values.yaml`, this allows you to tailor various aspects of the installation to meet your specific requirements. 40 | Version 3 of the helm chart is designed to have configuration options with the same format and naming as it is defined in the operator doc. 41 | -------------------------------------------------------------------------------- /go.work: -------------------------------------------------------------------------------- 1 | go 1.22.1 2 | 3 | use ( 4 | ./opensearch-operator 5 | ./opensearch-operator/functionaltests 6 | ) 7 | -------------------------------------------------------------------------------- /opensearch-operator/.gitignore: -------------------------------------------------------------------------------- 1 | bin/ 2 | vendor/ 3 | testbin/ -------------------------------------------------------------------------------- /opensearch-operator/.mockery.yaml: -------------------------------------------------------------------------------- 1 | with-expecter: true 2 | packages: 3 | github.com/Opster/opensearch-k8s-operator/opensearch-operator/pkg/reconcilers/k8s: 4 | interfaces: 5 | K8sClient: 6 | -------------------------------------------------------------------------------- /opensearch-operator/Dockerfile: -------------------------------------------------------------------------------- 1 | # Build the manager binary 2 | FROM --platform=$BUILDPLATFORM golang:1.22.1 as builder 3 | 4 | WORKDIR /workspace 5 | # Copy the Go Modules manifests 6 | COPY go.mod go.mod 7 | COPY go.sum go.sum 8 | # cache deps before building and copying source so that we don't need to re-download as much 9 | # and so that source changes don't invalidate our downloaded layer 10 | RUN go mod download 11 | 12 | # Copy the go source 13 | COPY main.go main.go 14 | COPY api/ api/ 15 | COPY controllers/ controllers/ 16 | COPY pkg/ pkg/ 17 | COPY opensearch-gateway/ opensearch-gateway/ 18 | 19 | # Build 20 | ARG TARGETOS 21 | ARG TARGETARCH 22 | RUN CGO_ENABLED=0 GOOS=${TARGETOS} GOARCH=${TARGETARCH} go build -a -o manager main.go 23 | 24 | # Use distroless as minimal base image to package the manager binary 25 | # Refer to https://github.com/GoogleContainerTools/distroless for more details 26 | FROM --platform=$BUILDPLATFORM gcr.io/distroless/static:nonroot 27 | WORKDIR / 28 | COPY --from=builder /workspace/manager . 29 | USER 65532:65532 30 | 31 | ENTRYPOINT ["/manager"] 32 | -------------------------------------------------------------------------------- /opensearch-operator/PROJECT: -------------------------------------------------------------------------------- 1 | # Code generated by tool. DO NOT EDIT. 2 | # This file is used to track the info used to scaffold your project 3 | # and allow the plugins properly work. 4 | # More info: https://book.kubebuilder.io/reference/project-config.html 5 | domain: opensearch.opster.io 6 | layout: 7 | - go.kubebuilder.io/v3 8 | projectName: opensearch-operator 9 | repo: github.com/Opster/opensearch-k8s-operator/opensearch-operator 10 | resources: 11 | - api: 12 | crdVersion: v1 13 | namespaced: true 14 | controller: true 15 | domain: opensearch.opster.io 16 | group: opster 17 | kind: OpenSearchCluster 18 | path: opensearch.opster.io/api/v1 19 | version: v1 20 | - api: 21 | crdVersion: v1 22 | namespaced: true 23 | controller: true 24 | domain: opensearch.opster.io 25 | group: opster 26 | kind: OpensearchUser 27 | path: opensearch.opster.io/api/v1 28 | version: v1 29 | - api: 30 | crdVersion: v1 31 | namespaced: true 32 | controller: true 33 | domain: opensearch.opster.io 34 | group: opster 35 | kind: OpensearchRole 36 | path: opensearch.opster.io/api/v1 37 | version: v1 38 | - api: 39 | crdVersion: v1 40 | namespaced: true 41 | controller: true 42 | domain: opensearch.opster.io 43 | group: opster 44 | kind: OpensearchUserRoleBinding 45 | path: opensearch.opster.io/api/v1 46 | version: v1 47 | - api: 48 | crdVersion: v1 49 | namespaced: true 50 | controller: true 51 | domain: opensearch.opster.io 52 | group: opster 53 | kind: OpensearchIndexTemplate 54 | path: opensearch.opster.io/api/v1 55 | version: v1 56 | - api: 57 | crdVersion: v1 58 | namespaced: true 59 | controller: true 60 | domain: opensearch.opster.io 61 | group: opster 62 | kind: OpensearchComponentTemplate 63 | path: opensearch.opster.io/api/v1 64 | version: v1 65 | - domain: opensearch.opster.io 66 | group: opensearch.opster.io 67 | kind: OpensearchISMPolicy 68 | version: v1 69 | version: "3" 70 | -------------------------------------------------------------------------------- /opensearch-operator/Tiltfile: -------------------------------------------------------------------------------- 1 | set_team('52cc75cc-c4ed-462f-8ea7-a543d398a381') 2 | 3 | k8s_yaml(kustomize('config/default')) 4 | 5 | deps = ['controllers', 'main.go', 'api', 'pkg'] 6 | 7 | local_resource('Watch & Compile', 8 | 'CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -a -o bin/manager main.go', 9 | deps=deps) 10 | 11 | DOCKERFILE = '''FROM gcr.io/distroless/base:debug-nonroot 12 | WORKDIR / 13 | COPY ./bin/manager / 14 | USER 65532:65532 15 | 16 | ENTRYPOINT ["/manager"] 17 | ''' 18 | 19 | docker_build("controller", '.', 20 | dockerfile_contents=DOCKERFILE, 21 | only=['./bin/manager'], 22 | live_update=[sync('./bin/manager', '/manager')] 23 | ) -------------------------------------------------------------------------------- /opensearch-operator/api/v1/groupversion_info.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Package v1 contains API Schema definitions for the opster v1 API group 18 | // +kubebuilder:object:generate=true 19 | // +groupName=opensearch.opster.io 20 | package v1 21 | 22 | import ( 23 | "k8s.io/apimachinery/pkg/runtime/schema" 24 | "sigs.k8s.io/controller-runtime/pkg/scheme" 25 | ) 26 | 27 | var ( 28 | // GroupVersion is group version used to register these objects 29 | GroupVersion = schema.GroupVersion{Group: "opensearch.opster.io", Version: "v1"} 30 | 31 | // SchemeBuilder is used to add go types to the GroupVersionKind scheme 32 | SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion} 33 | 34 | // AddToScheme adds the types in this group-version to the given scheme. 35 | AddToScheme = SchemeBuilder.AddToScheme 36 | ) 37 | -------------------------------------------------------------------------------- /opensearch-operator/api/v1/opensearch_componenttemplate_types.go: -------------------------------------------------------------------------------- 1 | package v1 2 | 3 | import ( 4 | corev1 "k8s.io/api/core/v1" 5 | apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" 6 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 7 | "k8s.io/apimachinery/pkg/types" 8 | ) 9 | 10 | type OpensearchComponentTemplateState string 11 | 12 | const ( 13 | OpensearchComponentTemplatePending OpensearchComponentTemplateState = "PENDING" 14 | OpensearchComponentTemplateCreated OpensearchComponentTemplateState = "CREATED" 15 | OpensearchComponentTemplateError OpensearchComponentTemplateState = "ERROR" 16 | OpensearchComponentTemplateIgnored OpensearchComponentTemplateState = "IGNORED" 17 | ) 18 | 19 | //+kubebuilder:object:root=true 20 | //+kubebuilder:resource:shortName=opensearchcomponenttemplate 21 | //+kubebuilder:subresource:status 22 | 23 | // OpensearchComponentTemplate is the schema for the OpenSearch component templates API 24 | type OpensearchComponentTemplate struct { 25 | metav1.TypeMeta `json:",inline"` 26 | metav1.ObjectMeta `json:"metadata,omitempty"` 27 | 28 | Spec OpensearchComponentTemplateSpec `json:"spec,omitempty"` 29 | Status OpensearchComponentTemplateStatus `json:"status,omitempty"` 30 | } 31 | 32 | type OpensearchComponentTemplateStatus struct { 33 | State OpensearchComponentTemplateState `json:"state,omitempty"` 34 | Reason string `json:"reason,omitempty"` 35 | ExistingComponentTemplate *bool `json:"existingComponentTemplate,omitempty"` 36 | ManagedCluster *types.UID `json:"managedCluster,omitempty"` 37 | // Name of the currently managed component template 38 | ComponentTemplateName string `json:"componentTemplateName,omitempty"` 39 | } 40 | 41 | type OpensearchComponentTemplateSpec struct { 42 | OpensearchRef corev1.LocalObjectReference `json:"opensearchCluster"` 43 | 44 | // The name of the component template. Defaults to metadata.name 45 | // +immutable 46 | Name string `json:"name,omitempty"` 47 | 48 | // The template that should be applied 49 | Template OpensearchIndexSpec `json:"template"` 50 | 51 | // Version number used to manage the component template externally 52 | Version int `json:"version,omitempty"` 53 | 54 | // If true, then indices can be automatically created using this template 55 | AllowAutoCreate bool `json:"allowAutoCreate,omitempty"` 56 | 57 | // Optional user metadata about the component template 58 | Meta *apiextensionsv1.JSON `json:"_meta,omitempty"` 59 | } 60 | 61 | //+kubebuilder:object:root=true 62 | 63 | // OpensearchComponentTemplateList contains a list of OpensearchComponentTemplate 64 | type OpensearchComponentTemplateList struct { 65 | metav1.TypeMeta `json:",inline"` 66 | metav1.ListMeta `json:"metadata,omitempty"` 67 | Items []OpensearchComponentTemplate `json:"items"` 68 | } 69 | 70 | func init() { 71 | SchemeBuilder.Register(&OpensearchComponentTemplate{}, &OpensearchComponentTemplateList{}) 72 | } 73 | -------------------------------------------------------------------------------- /opensearch-operator/api/v1/opensearch_index_types.go: -------------------------------------------------------------------------------- 1 | package v1 2 | 3 | import ( 4 | apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" 5 | ) 6 | 7 | type OpensearchDatastreamTimestampFieldSpec struct { 8 | // Name of the field that are used for the DataStream 9 | Name string `json:"name"` 10 | } 11 | 12 | type OpensearchDatastreamSpec struct { 13 | // TimestampField for dataStream 14 | TimestampField OpensearchDatastreamTimestampFieldSpec `json:"timestamp_field,omitempty"` 15 | } 16 | 17 | // Describes the specs of an index 18 | type OpensearchIndexSpec struct { 19 | // Configuration options for the index 20 | Settings *apiextensionsv1.JSON `json:"settings,omitempty"` 21 | 22 | // Mapping for fields in the index 23 | Mappings *apiextensionsv1.JSON `json:"mappings,omitempty"` 24 | 25 | // Aliases to add 26 | Aliases map[string]OpensearchIndexAliasSpec `json:"aliases,omitempty"` 27 | } 28 | 29 | // Describes the specs of an index alias 30 | type OpensearchIndexAliasSpec struct { 31 | // The name of the index that the alias points to. 32 | Index string `json:"index,omitempty"` 33 | 34 | // The name of the alias. 35 | Alias string `json:"alias,omitempty"` 36 | 37 | // Query used to limit documents the alias can access. 38 | Filter *apiextensionsv1.JSON `json:"filter,omitempty"` 39 | 40 | // Value used to route indexing and search operations to a specific shard. 41 | Routing string `json:"routing,omitempty"` 42 | 43 | // If true, the index is the write index for the alias 44 | IsWriteIndex bool `json:"isWriteIndex,omitempty"` 45 | } 46 | -------------------------------------------------------------------------------- /opensearch-operator/api/v1/opensearch_indextemplate_types.go: -------------------------------------------------------------------------------- 1 | package v1 2 | 3 | import ( 4 | corev1 "k8s.io/api/core/v1" 5 | apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" 6 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 7 | "k8s.io/apimachinery/pkg/types" 8 | ) 9 | 10 | type OpensearchIndexTemplateState string 11 | 12 | const ( 13 | OpensearchIndexTemplatePending OpensearchIndexTemplateState = "PENDING" 14 | OpensearchIndexTemplateCreated OpensearchIndexTemplateState = "CREATED" 15 | OpensearchIndexTemplateError OpensearchIndexTemplateState = "ERROR" 16 | OpensearchIndexTemplateIgnored OpensearchIndexTemplateState = "IGNORED" 17 | ) 18 | 19 | //+kubebuilder:object:root=true 20 | //+kubebuilder:resource:shortName=opensearchindextemplate 21 | //+kubebuilder:subresource:status 22 | 23 | // OpensearchIndexTemplate is the schema for the OpenSearch index templates API 24 | type OpensearchIndexTemplate struct { 25 | metav1.TypeMeta `json:",inline"` 26 | metav1.ObjectMeta `json:"metadata,omitempty"` 27 | 28 | Spec OpensearchIndexTemplateSpec `json:"spec,omitempty"` 29 | Status OpensearchIndexTemplateStatus `json:"status,omitempty"` 30 | } 31 | 32 | type OpensearchIndexTemplateStatus struct { 33 | State OpensearchIndexTemplateState `json:"state,omitempty"` 34 | Reason string `json:"reason,omitempty"` 35 | ExistingIndexTemplate *bool `json:"existingIndexTemplate,omitempty"` 36 | ManagedCluster *types.UID `json:"managedCluster,omitempty"` 37 | // Name of the currently managed index template 38 | IndexTemplateName string `json:"indexTemplateName,omitempty"` 39 | } 40 | 41 | type OpensearchIndexTemplateSpec struct { 42 | OpensearchRef corev1.LocalObjectReference `json:"opensearchCluster"` 43 | 44 | // The name of the index template. Defaults to metadata.name 45 | // +immutable 46 | Name string `json:"name,omitempty"` 47 | 48 | // Array of wildcard expressions used to match the names of indices during creation 49 | IndexPatterns []string `json:"indexPatterns"` 50 | 51 | // The dataStream config that should be applied 52 | DataStream *OpensearchDatastreamSpec `json:"dataStream,omitempty"` 53 | 54 | // The template that should be applied 55 | Template OpensearchIndexSpec `json:"template,omitempty"` 56 | 57 | // An ordered list of component template names. Component templates are merged in the order specified, 58 | // meaning that the last component template specified has the highest precedence 59 | ComposedOf []string `json:"composedOf,omitempty"` 60 | 61 | // Priority to determine index template precedence when a new data stream or index is created. 62 | // The index template with the highest priority is chosen 63 | Priority int `json:"priority,omitempty"` 64 | 65 | // Version number used to manage the component template externally 66 | Version int `json:"version,omitempty"` 67 | 68 | // Optional user metadata about the index template 69 | Meta *apiextensionsv1.JSON `json:"_meta,omitempty"` 70 | } 71 | 72 | //+kubebuilder:object:root=true 73 | 74 | // OpensearchIndexTemplateList contains a list of OpensearchIndexTemplate 75 | type OpensearchIndexTemplateList struct { 76 | metav1.TypeMeta `json:",inline"` 77 | metav1.ListMeta `json:"metadata,omitempty"` 78 | Items []OpensearchIndexTemplate `json:"items"` 79 | } 80 | 81 | func init() { 82 | SchemeBuilder.Register(&OpensearchIndexTemplate{}, &OpensearchIndexTemplateList{}) 83 | } 84 | -------------------------------------------------------------------------------- /opensearch-operator/api/v1/opensearchactiongroup_types.go: -------------------------------------------------------------------------------- 1 | package v1 2 | 3 | import ( 4 | corev1 "k8s.io/api/core/v1" 5 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 6 | "k8s.io/apimachinery/pkg/types" 7 | ) 8 | 9 | type OpensearchActionGroupState string 10 | 11 | const ( 12 | OpensearchActionGroupPending OpensearchActionGroupState = "PENDING" 13 | OpensearchActionGroupCreated OpensearchActionGroupState = "CREATED" 14 | OpensearchActionGroupError OpensearchActionGroupState = "ERROR" 15 | OpensearchActionGroupIgnored OpensearchActionGroupState = "IGNORED" 16 | ) 17 | 18 | // OpensearchActionGroupSpec defines the desired state of OpensearchActionGroup 19 | type OpensearchActionGroupSpec struct { 20 | OpensearchRef corev1.LocalObjectReference `json:"opensearchCluster"` 21 | AllowedActions []string `json:"allowedActions"` 22 | Type string `json:"type,omitempty"` 23 | Description string `json:"description,omitempty"` 24 | } 25 | 26 | // OpensearchActionGroupStatus defines the observed state of OpensearchActionGroup 27 | type OpensearchActionGroupStatus struct { 28 | State OpensearchActionGroupState `json:"state,omitempty"` 29 | Reason string `json:"reason,omitempty"` 30 | ExistingActionGroup *bool `json:"existingActionGroup,omitempty"` 31 | ManagedCluster *types.UID `json:"managedCluster,omitempty"` 32 | } 33 | 34 | //+kubebuilder:object:root=true 35 | //+kubebuilder:resource:shortName=opensearchactiongroup 36 | //+kubebuilder:subresource:status 37 | 38 | // OpensearchActionGroup is the Schema for the opensearchactiongroups API 39 | type OpensearchActionGroup struct { 40 | metav1.TypeMeta `json:",inline"` 41 | metav1.ObjectMeta `json:"metadata,omitempty"` 42 | 43 | Spec OpensearchActionGroupSpec `json:"spec,omitempty"` 44 | Status OpensearchActionGroupStatus `json:"status,omitempty"` 45 | } 46 | 47 | //+kubebuilder:object:root=true 48 | 49 | // OpensearchActionGroupList contains a list of OpensearchActionGroup 50 | type OpensearchActionGroupList struct { 51 | metav1.TypeMeta `json:",inline"` 52 | metav1.ListMeta `json:"metadata,omitempty"` 53 | Items []OpensearchActionGroup `json:"items"` 54 | } 55 | 56 | func init() { 57 | SchemeBuilder.Register(&OpensearchActionGroup{}, &OpensearchActionGroupList{}) 58 | } 59 | -------------------------------------------------------------------------------- /opensearch-operator/api/v1/opensearchrole_types.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package v1 18 | 19 | import ( 20 | corev1 "k8s.io/api/core/v1" 21 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 22 | "k8s.io/apimachinery/pkg/types" 23 | ) 24 | 25 | type OpensearchRoleState string 26 | 27 | const ( 28 | OpensearchRoleStatePending OpensearchRoleState = "PENDING" 29 | OpensearchRoleStateCreated OpensearchRoleState = "CREATED" 30 | OpensearchRoleStateError OpensearchRoleState = "ERROR" 31 | OpensearchRoleIgnored OpensearchRoleState = "IGNORED" 32 | ) 33 | 34 | // OpensearchRoleSpec defines the desired state of OpensearchRole 35 | type OpensearchRoleSpec struct { 36 | OpensearchRef corev1.LocalObjectReference `json:"opensearchCluster"` 37 | ClusterPermissions []string `json:"clusterPermissions,omitempty"` 38 | IndexPermissions []IndexPermissionSpec `json:"indexPermissions,omitempty"` 39 | TenantPermissions []TenantPermissionsSpec `json:"tenantPermissions,omitempty"` 40 | } 41 | 42 | type IndexPermissionSpec struct { 43 | IndexPatterns []string `json:"indexPatterns,omitempty"` 44 | DocumentLevelSecurity string `json:"dls,omitempty"` 45 | FieldLevelSecurity []string `json:"fls,omitempty"` 46 | AllowedActions []string `json:"allowedActions,omitempty"` 47 | MaskedFields []string `json:"maskedFields,omitempty"` 48 | } 49 | 50 | type TenantPermissionsSpec struct { 51 | TenantPatterns []string `json:"tenantPatterns,omitempty"` 52 | AllowedActions []string `json:"allowedActions,omitempty"` 53 | } 54 | 55 | // OpensearchRoleStatus defines the observed state of OpensearchRole 56 | type OpensearchRoleStatus struct { 57 | State OpensearchRoleState `json:"state,omitempty"` 58 | Reason string `json:"reason,omitempty"` 59 | ExistingRole *bool `json:"existingRole,omitempty"` 60 | ManagedCluster *types.UID `json:"managedCluster,omitempty"` 61 | } 62 | 63 | //+kubebuilder:object:root=true 64 | //+kubebuilder:resource:shortName=opensearchrole 65 | //+kubebuilder:subresource:status 66 | 67 | // OpensearchRole is the Schema for the opensearchroles API 68 | type OpensearchRole struct { 69 | metav1.TypeMeta `json:",inline"` 70 | metav1.ObjectMeta `json:"metadata,omitempty"` 71 | 72 | Spec OpensearchRoleSpec `json:"spec,omitempty"` 73 | Status OpensearchRoleStatus `json:"status,omitempty"` 74 | } 75 | 76 | //+kubebuilder:object:root=true 77 | 78 | // OpensearchRoleList contains a list of OpensearchRole 79 | type OpensearchRoleList struct { 80 | metav1.TypeMeta `json:",inline"` 81 | metav1.ListMeta `json:"metadata,omitempty"` 82 | Items []OpensearchRole `json:"items"` 83 | } 84 | 85 | func init() { 86 | SchemeBuilder.Register(&OpensearchRole{}, &OpensearchRoleList{}) 87 | } 88 | -------------------------------------------------------------------------------- /opensearch-operator/api/v1/opensearchtenant_types.go: -------------------------------------------------------------------------------- 1 | package v1 2 | 3 | import ( 4 | corev1 "k8s.io/api/core/v1" 5 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 6 | "k8s.io/apimachinery/pkg/types" 7 | ) 8 | 9 | type OpensearchTenantState string 10 | 11 | const ( 12 | OpensearchTenantPending OpensearchTenantState = "PENDING" 13 | OpensearchTenantCreated OpensearchTenantState = "CREATED" 14 | OpensearchTenantError OpensearchTenantState = "ERROR" 15 | OpensearchTenantIgnored OpensearchTenantState = "IGNORED" 16 | ) 17 | 18 | // OpensearchTenantSpec defines the desired state of OpensearchTenant 19 | type OpensearchTenantSpec struct { 20 | OpensearchRef corev1.LocalObjectReference `json:"opensearchCluster"` 21 | Description string `json:"description,omitempty"` 22 | } 23 | 24 | // OpensearchTenantStatus defines the observed state of OpensearchTenant 25 | type OpensearchTenantStatus struct { 26 | State OpensearchTenantState `json:"state,omitempty"` 27 | Reason string `json:"reason,omitempty"` 28 | ExistingTenant *bool `json:"existingTenant,omitempty"` 29 | ManagedCluster *types.UID `json:"managedCluster,omitempty"` 30 | } 31 | 32 | //+kubebuilder:object:root=true 33 | //+kubebuilder:resource:shortName=opensearchtenant 34 | //+kubebuilder:subresource:status 35 | 36 | // OpensearchTenant is the Schema for the opensearchtenants API 37 | type OpensearchTenant struct { 38 | metav1.TypeMeta `json:",inline"` 39 | metav1.ObjectMeta `json:"metadata,omitempty"` 40 | 41 | Spec OpensearchTenantSpec `json:"spec,omitempty"` 42 | Status OpensearchTenantStatus `json:"status,omitempty"` 43 | } 44 | 45 | //+kubebuilder:object:root=true 46 | 47 | // OpensearchTenantList contains a list of OpensearchTenant 48 | type OpensearchTenantList struct { 49 | metav1.TypeMeta `json:",inline"` 50 | metav1.ListMeta `json:"metadata,omitempty"` 51 | Items []OpensearchTenant `json:"items"` 52 | } 53 | 54 | func init() { 55 | SchemeBuilder.Register(&OpensearchTenant{}, &OpensearchTenantList{}) 56 | } 57 | -------------------------------------------------------------------------------- /opensearch-operator/api/v1/opensearchuser_types.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package v1 18 | 19 | import ( 20 | corev1 "k8s.io/api/core/v1" 21 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 22 | "k8s.io/apimachinery/pkg/types" 23 | ) 24 | 25 | type OpensearchUserState string 26 | 27 | const ( 28 | OpensearchUserStatePending OpensearchUserState = "PENDING" 29 | OpensearchUserStateCreated OpensearchUserState = "CREATED" 30 | OpensearchUserStateError OpensearchUserState = "ERROR" 31 | ) 32 | 33 | // OpensearchUserSpec defines the desired state of OpensearchUser 34 | type OpensearchUserSpec struct { 35 | OpensearchRef corev1.LocalObjectReference `json:"opensearchCluster"` 36 | PasswordFrom corev1.SecretKeySelector `json:"passwordFrom"` 37 | OpendistroSecurityRoles []string `json:"opendistroSecurityRoles,omitempty"` 38 | BackendRoles []string `json:"backendRoles,omitempty"` 39 | Attributes map[string]string `json:"attributes,omitempty"` 40 | } 41 | 42 | // OpensearchUserStatus defines the observed state of OpensearchUser 43 | type OpensearchUserStatus struct { 44 | State OpensearchUserState `json:"state,omitempty"` 45 | Reason string `json:"reason,omitempty"` 46 | ManagedCluster *types.UID `json:"managedCluster,omitempty"` 47 | } 48 | 49 | //+kubebuilder:object:root=true 50 | //+kubebuilder:resource:shortName=opensearchuser 51 | //+kubebuilder:subresource:status 52 | 53 | // OpensearchUser is the Schema for the opensearchusers API 54 | type OpensearchUser struct { 55 | metav1.TypeMeta `json:",inline"` 56 | metav1.ObjectMeta `json:"metadata,omitempty"` 57 | 58 | Spec OpensearchUserSpec `json:"spec,omitempty"` 59 | Status OpensearchUserStatus `json:"status,omitempty"` 60 | } 61 | 62 | //+kubebuilder:object:root=true 63 | 64 | // OpensearchUserList contains a list of OpensearchUser 65 | type OpensearchUserList struct { 66 | metav1.TypeMeta `json:",inline"` 67 | metav1.ListMeta `json:"metadata,omitempty"` 68 | Items []OpensearchUser `json:"items"` 69 | } 70 | 71 | func init() { 72 | SchemeBuilder.Register(&OpensearchUser{}, &OpensearchUserList{}) 73 | } 74 | -------------------------------------------------------------------------------- /opensearch-operator/api/v1/opensearchuserrolebinding_types.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package v1 18 | 19 | import ( 20 | corev1 "k8s.io/api/core/v1" 21 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 22 | "k8s.io/apimachinery/pkg/types" 23 | ) 24 | 25 | type OpensearchUserRoleBindingState string 26 | 27 | const ( 28 | OpensearchUserRoleBindingPending OpensearchUserRoleBindingState = "PENDING" 29 | OpensearchUserRoleBindingStateCreated OpensearchUserRoleBindingState = "CREATED" 30 | OpensearchUserRoleBindingStateError OpensearchUserRoleBindingState = "ERROR" 31 | ) 32 | 33 | // OpensearchUserRoleBindingSpec defines the desired state of OpensearchUserRoleBinding 34 | type OpensearchUserRoleBindingSpec struct { 35 | OpensearchRef corev1.LocalObjectReference `json:"opensearchCluster"` 36 | Roles []string `json:"roles"` 37 | Users []string `json:"users,omitempty"` 38 | BackendRoles []string `json:"backendRoles,omitempty"` 39 | } 40 | 41 | // OpensearchUserRoleBindingStatus defines the observed state of OpensearchUserRoleBinding 42 | type OpensearchUserRoleBindingStatus struct { 43 | State OpensearchUserRoleBindingState `json:"state,omitempty"` 44 | Reason string `json:"reason,omitempty"` 45 | ManagedCluster *types.UID `json:"managedCluster,omitempty"` 46 | ProvisionedRoles []string `json:"provisionedRoles,omitempty"` 47 | ProvisionedUsers []string `json:"provisionedUsers,omitempty"` 48 | ProvisionedBackendRoles []string `json:"provisionedBackendRoles,omitempty"` 49 | } 50 | 51 | //+kubebuilder:object:root=true 52 | //+kubebuilder:resource:shortName=opensearchuserrolebinding 53 | //+kubebuilder:subresource:status 54 | 55 | // OpensearchUserRoleBinding is the Schema for the opensearchuserrolebindings API 56 | type OpensearchUserRoleBinding struct { 57 | metav1.TypeMeta `json:",inline"` 58 | metav1.ObjectMeta `json:"metadata,omitempty"` 59 | 60 | Spec OpensearchUserRoleBindingSpec `json:"spec,omitempty"` 61 | Status OpensearchUserRoleBindingStatus `json:"status,omitempty"` 62 | } 63 | 64 | //+kubebuilder:object:root=true 65 | 66 | // OpensearchUserRoleBindingList contains a list of OpensearchUserRoleBinding 67 | type OpensearchUserRoleBindingList struct { 68 | metav1.TypeMeta `json:",inline"` 69 | metav1.ListMeta `json:"metadata,omitempty"` 70 | Items []OpensearchUserRoleBinding `json:"items"` 71 | } 72 | 73 | func init() { 74 | SchemeBuilder.Register(&OpensearchUserRoleBinding{}, &OpensearchUserRoleBindingList{}) 75 | } 76 | -------------------------------------------------------------------------------- /opensearch-operator/api/v1/util.go: -------------------------------------------------------------------------------- 1 | package v1 2 | 3 | import "k8s.io/apimachinery/pkg/types" 4 | 5 | type OpensearchClusterSelector struct { 6 | Name string `json:"name,omitempty"` 7 | Namespace string `json:"namespace,omitempty"` 8 | } 9 | 10 | func (o *OpensearchClusterSelector) ObjectKey() types.NamespacedName { 11 | return types.NamespacedName{ 12 | Name: o.Name, 13 | Namespace: o.Namespace, 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /opensearch-operator/config/crd/bases/opensearch.opster.io_opensearchtenants.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: apiextensions.k8s.io/v1 3 | kind: CustomResourceDefinition 4 | metadata: 5 | annotations: 6 | controller-gen.kubebuilder.io/version: v0.14.0 7 | name: opensearchtenants.opensearch.opster.io 8 | spec: 9 | group: opensearch.opster.io 10 | names: 11 | kind: OpensearchTenant 12 | listKind: OpensearchTenantList 13 | plural: opensearchtenants 14 | shortNames: 15 | - opensearchtenant 16 | singular: opensearchtenant 17 | scope: Namespaced 18 | versions: 19 | - name: v1 20 | schema: 21 | openAPIV3Schema: 22 | description: OpensearchTenant is the Schema for the opensearchtenants API 23 | properties: 24 | apiVersion: 25 | description: |- 26 | APIVersion defines the versioned schema of this representation of an object. 27 | Servers should convert recognized schemas to the latest internal value, and 28 | may reject unrecognized values. 29 | More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources 30 | type: string 31 | kind: 32 | description: |- 33 | Kind is a string value representing the REST resource this object represents. 34 | Servers may infer this from the endpoint the client submits requests to. 35 | Cannot be updated. 36 | In CamelCase. 37 | More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds 38 | type: string 39 | metadata: 40 | type: object 41 | spec: 42 | description: OpensearchTenantSpec defines the desired state of OpensearchTenant 43 | properties: 44 | description: 45 | type: string 46 | opensearchCluster: 47 | description: |- 48 | LocalObjectReference contains enough information to let you locate the 49 | referenced object inside the same namespace. 50 | properties: 51 | name: 52 | description: |- 53 | Name of the referent. 54 | More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names 55 | TODO: Add other useful fields. apiVersion, kind, uid? 56 | type: string 57 | type: object 58 | x-kubernetes-map-type: atomic 59 | required: 60 | - opensearchCluster 61 | type: object 62 | status: 63 | description: OpensearchTenantStatus defines the observed state of OpensearchTenant 64 | properties: 65 | existingTenant: 66 | type: boolean 67 | managedCluster: 68 | description: |- 69 | UID is a type that holds unique ID values, including UUIDs. Because we 70 | don't ONLY use UUIDs, this is an alias to string. Being a type captures 71 | intent and helps make sure that UIDs and names do not get conflated. 72 | type: string 73 | reason: 74 | type: string 75 | state: 76 | type: string 77 | type: object 78 | type: object 79 | served: true 80 | storage: true 81 | subresources: 82 | status: {} 83 | -------------------------------------------------------------------------------- /opensearch-operator/config/crd/kustomization.yaml: -------------------------------------------------------------------------------- 1 | # This kustomization.yaml is not intended to be run by itself, 2 | # since it depends on service name and namespace that are out of this kustomize package. 3 | # It should be run by config/default 4 | resources: 5 | - bases/opensearch.opster.io_opensearchactiongroups.yaml 6 | - bases/opensearch.opster.io_opensearchclusters.yaml 7 | - bases/opensearch.opster.io_opensearchcomponenttemplates.yaml 8 | - bases/opensearch.opster.io_opensearchindextemplates.yaml 9 | - bases/opensearch.opster.io_opensearchroles.yaml 10 | - bases/opensearch.opster.io_opensearchtenants.yaml 11 | - bases/opensearch.opster.io_opensearchuserrolebindings.yaml 12 | - bases/opensearch.opster.io_opensearchusers.yaml 13 | - bases/opensearch.opster.io_opensearchismpolicies.yaml 14 | - bases/crd-servicemonitor.yaml 15 | #+kubebuilder:scaffold:crdkustomizeresource 16 | 17 | patchesStrategicMerge: 18 | # [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix. 19 | # patches here are for enabling the conversion webhook for each CRD 20 | #- patches/webhook_in_opensearch.yaml 21 | #- patches/webhook_in_opensearchusers.yaml 22 | #- patches/webhook_in_opensearchroles.yaml 23 | #- patches/webhook_in_opensearchuserrolebindings.yaml 24 | #+kubebuilder:scaffold:crdkustomizewebhookpatch 25 | 26 | # [CERTMANAGER] To enable webhook, uncomment all the sections with [CERTMANAGER] prefix. 27 | # patches here are for enabling the CA injection for each CRD 28 | #- patches/cainjection_in_opensearch.yaml 29 | #- patches/cainjection_in_opensearchusers.yaml 30 | #- patches/cainjection_in_opensearchroles.yaml 31 | #- patches/cainjection_in_opensearchuserrolebindings.yaml 32 | #+kubebuilder:scaffold:crdkustomizecainjectionpatch 33 | 34 | # the following config is for teaching kustomize how to do kustomization for CRDs. 35 | configurations: 36 | - kustomizeconfig.yaml 37 | -------------------------------------------------------------------------------- /opensearch-operator/config/crd/kustomizeconfig.yaml: -------------------------------------------------------------------------------- 1 | # This file is for teaching kustomize how to substitute name and namespace reference in CRD 2 | nameReference: 3 | - kind: Service 4 | version: v1 5 | fieldSpecs: 6 | - kind: CustomResourceDefinition 7 | version: v1 8 | group: apiextensions.k8s.io 9 | path: spec/conversion/webhook/clientConfig/service/name 10 | 11 | namespace: 12 | - kind: CustomResourceDefinition 13 | version: v1 14 | group: apiextensions.k8s.io 15 | path: spec/conversion/webhook/clientConfig/service/namespace 16 | create: false 17 | 18 | varReference: 19 | - path: metadata/annotations 20 | -------------------------------------------------------------------------------- /opensearch-operator/config/crd/patches/cainjection_in_opensearch.yaml: -------------------------------------------------------------------------------- 1 | # The following patch adds a directive for certmanager to inject CA into the CRD 2 | apiVersion: apiextensions.k8s.io/v1 3 | kind: CustomResourceDefinition 4 | metadata: 5 | annotations: 6 | cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME) 7 | name: opensearchcluster.opensearch.opster.io 8 | -------------------------------------------------------------------------------- /opensearch-operator/config/crd/patches/cainjection_in_opensearchroles.yaml: -------------------------------------------------------------------------------- 1 | # The following patch adds a directive for certmanager to inject CA into the CRD 2 | apiVersion: apiextensions.k8s.io/v1 3 | kind: CustomResourceDefinition 4 | metadata: 5 | annotations: 6 | cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME) 7 | name: opensearchroles.opster.opensearch.opster.io 8 | -------------------------------------------------------------------------------- /opensearch-operator/config/crd/patches/cainjection_in_opensearchuserrolebindings.yaml: -------------------------------------------------------------------------------- 1 | # The following patch adds a directive for certmanager to inject CA into the CRD 2 | apiVersion: apiextensions.k8s.io/v1 3 | kind: CustomResourceDefinition 4 | metadata: 5 | annotations: 6 | cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME) 7 | name: opensearchuserrolebindings.opster.opensearch.opster.io 8 | -------------------------------------------------------------------------------- /opensearch-operator/config/crd/patches/cainjection_in_opensearchusers.yaml: -------------------------------------------------------------------------------- 1 | # The following patch adds a directive for certmanager to inject CA into the CRD 2 | apiVersion: apiextensions.k8s.io/v1 3 | kind: CustomResourceDefinition 4 | metadata: 5 | annotations: 6 | cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME) 7 | name: opensearchusers.opster.opensearch.opster.io 8 | -------------------------------------------------------------------------------- /opensearch-operator/config/crd/patches/webhook_in_opensearch.yaml: -------------------------------------------------------------------------------- 1 | # The following patch enables a conversion webhook for the CRD 2 | apiVersion: apiextensions.k8s.io/v1 3 | kind: CustomResourceDefinition 4 | metadata: 5 | name: opensearchcluster.opensearch.opster.io 6 | spec: 7 | conversion: 8 | strategy: Webhook 9 | webhook: 10 | clientConfig: 11 | service: 12 | namespace: system 13 | name: webhook-service 14 | path: /convert 15 | conversionReviewVersions: 16 | - v1 17 | -------------------------------------------------------------------------------- /opensearch-operator/config/crd/patches/webhook_in_opensearchroles.yaml: -------------------------------------------------------------------------------- 1 | # The following patch enables a conversion webhook for the CRD 2 | apiVersion: apiextensions.k8s.io/v1 3 | kind: CustomResourceDefinition 4 | metadata: 5 | name: opensearchroles.opster.opensearch.opster.io 6 | spec: 7 | conversion: 8 | strategy: Webhook 9 | webhook: 10 | clientConfig: 11 | service: 12 | namespace: system 13 | name: webhook-service 14 | path: /convert 15 | conversionReviewVersions: 16 | - v1 17 | -------------------------------------------------------------------------------- /opensearch-operator/config/crd/patches/webhook_in_opensearchuserrolebindings.yaml: -------------------------------------------------------------------------------- 1 | # The following patch enables a conversion webhook for the CRD 2 | apiVersion: apiextensions.k8s.io/v1 3 | kind: CustomResourceDefinition 4 | metadata: 5 | name: opensearchuserrolebindings.opster.opensearch.opster.io 6 | spec: 7 | conversion: 8 | strategy: Webhook 9 | webhook: 10 | clientConfig: 11 | service: 12 | namespace: system 13 | name: webhook-service 14 | path: /convert 15 | conversionReviewVersions: 16 | - v1 17 | -------------------------------------------------------------------------------- /opensearch-operator/config/crd/patches/webhook_in_opensearchusers.yaml: -------------------------------------------------------------------------------- 1 | # The following patch enables a conversion webhook for the CRD 2 | apiVersion: apiextensions.k8s.io/v1 3 | kind: CustomResourceDefinition 4 | metadata: 5 | name: opensearchusers.opster.opensearch.opster.io 6 | spec: 7 | conversion: 8 | strategy: Webhook 9 | webhook: 10 | clientConfig: 11 | service: 12 | namespace: system 13 | name: webhook-service 14 | path: /convert 15 | conversionReviewVersions: 16 | - v1 17 | -------------------------------------------------------------------------------- /opensearch-operator/config/default/kustomization.yaml: -------------------------------------------------------------------------------- 1 | # Adds namespace to all resources. 2 | namespace: opensearch-operator-system 3 | 4 | # Value of this field is prepended to the 5 | # names of all resources, e.g. a deployment named 6 | # "wordpress" becomes "alices-wordpress". 7 | # Note that it should also match with the prefix (text before '-') of the namespace 8 | # field above. 9 | namePrefix: opensearch-operator- 10 | 11 | # Labels to add to all resources and selectors. 12 | #commonLabels: 13 | # someName: someValue 14 | 15 | bases: 16 | - ../crd 17 | - ../rbac 18 | - ../manager 19 | # [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix including the one in 20 | # crd/kustomization.yaml 21 | #- ../webhook 22 | # [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER'. 'WEBHOOK' components are required. 23 | #- ../certmanager 24 | # [PROMETHEUS] To enable prometheus monitor, uncomment all sections with 'PROMETHEUS'. 25 | #- ../prometheus 26 | 27 | patchesStrategicMerge: 28 | # Protect the /metrics endpoint by putting it behind auth. 29 | # If you want your controller-manager to expose the /metrics 30 | # endpoint w/o any authn/z, please comment the following line. 31 | - manager_auth_proxy_patch.yaml 32 | 33 | # Mount the controller config file for loading manager configurations 34 | # through a ComponentConfig type 35 | #- manager_config_patch.yaml 36 | 37 | # [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix including the one in 38 | # crd/kustomization.yaml 39 | #- manager_webhook_patch.yaml 40 | 41 | # [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER'. 42 | # Uncomment 'CERTMANAGER' sections in crd/kustomization.yaml to enable the CA injection in the admission webhooks. 43 | # 'CERTMANAGER' needs to be enabled to use ca injection 44 | #- webhookcainjection_patch.yaml 45 | 46 | # the following config is for teaching kustomize how to do var substitution 47 | vars: 48 | # [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER' prefix. 49 | #- name: CERTIFICATE_NAMESPACE # namespace of the certificate CR 50 | # objref: 51 | # kind: Certificate 52 | # group: cert-manager.io 53 | # version: v1 54 | # name: serving-cert # this name should match the one in certificate.yaml 55 | # fieldref: 56 | # fieldpath: metadata.namespace 57 | #- name: CERTIFICATE_NAME 58 | # objref: 59 | # kind: Certificate 60 | # group: cert-manager.io 61 | # version: v1 62 | # name: serving-cert # this name should match the one in certificate.yaml 63 | #- name: SERVICE_NAMESPACE # namespace of the service 64 | # objref: 65 | # kind: Service 66 | # version: v1 67 | # name: webhook-service 68 | # fieldref: 69 | # fieldpath: metadata.namespace 70 | #- name: SERVICE_NAME 71 | # objref: 72 | # kind: Service 73 | # version: v1 74 | # name: webhook-service 75 | -------------------------------------------------------------------------------- /opensearch-operator/config/default/manager_auth_proxy_patch.yaml: -------------------------------------------------------------------------------- 1 | # This patch inject a sidecar container which is a HTTP proxy for the 2 | # controller manager, it performs RBAC authorization against the Kubernetes API using SubjectAccessReviews. 3 | apiVersion: apps/v1 4 | kind: Deployment 5 | metadata: 6 | name: controller-manager 7 | namespace: system 8 | spec: 9 | template: 10 | spec: 11 | containers: 12 | - name: kube-rbac-proxy 13 | image: gcr.io/kubebuilder/kube-rbac-proxy:v0.8.0 14 | args: 15 | - "--secure-listen-address=0.0.0.0:8443" 16 | - "--upstream=http://127.0.0.1:8080/" 17 | - "--logtostderr=true" 18 | - "--v=10" 19 | ports: 20 | - containerPort: 8443 21 | name: https 22 | - name: manager 23 | args: 24 | - "--health-probe-bind-address=:8081" 25 | - "--metrics-bind-address=127.0.0.1:8080" 26 | - "--leader-elect" 27 | -------------------------------------------------------------------------------- /opensearch-operator/config/default/manager_config_patch.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: controller-manager 5 | namespace: system 6 | spec: 7 | template: 8 | spec: 9 | containers: 10 | - name: manager 11 | args: 12 | - "--config=controller_manager_config.yaml" 13 | volumeMounts: 14 | - name: manager-config 15 | mountPath: /controller_manager_config.yaml 16 | subPath: controller_manager_config.yaml 17 | volumes: 18 | - name: manager-config 19 | configMap: 20 | name: manager-config 21 | -------------------------------------------------------------------------------- /opensearch-operator/config/manager/controller_manager_config.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: controller-runtime.sigs.k8s.io/v1alpha1 2 | kind: ControllerManagerConfig 3 | health: 4 | healthProbeBindAddress: :8081 5 | metrics: 6 | bindAddress: 127.0.0.1:8080 7 | webhook: 8 | port: 9443 9 | leaderElection: 10 | leaderElect: true 11 | resourceName: a867c7dc.opensearch.opster.io 12 | -------------------------------------------------------------------------------- /opensearch-operator/config/manager/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | - manager.yaml 3 | 4 | generatorOptions: 5 | disableNameSuffixHash: true 6 | 7 | configMapGenerator: 8 | - files: 9 | - controller_manager_config.yaml 10 | name: manager-config 11 | apiVersion: kustomize.config.k8s.io/v1beta1 12 | kind: Kustomization 13 | images: 14 | - name: controller 15 | newName: controller 16 | newTag: latest 17 | -------------------------------------------------------------------------------- /opensearch-operator/config/manager/manager.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Namespace 3 | metadata: 4 | labels: 5 | control-plane: controller-manager 6 | name: system 7 | --- 8 | apiVersion: apps/v1 9 | kind: Deployment 10 | metadata: 11 | name: controller-manager 12 | namespace: system 13 | labels: 14 | control-plane: controller-manager 15 | spec: 16 | selector: 17 | matchLabels: 18 | control-plane: controller-manager 19 | replicas: 1 20 | template: 21 | metadata: 22 | labels: 23 | control-plane: controller-manager 24 | spec: 25 | securityContext: 26 | runAsNonRoot: true 27 | containers: 28 | - command: 29 | - /manager 30 | args: 31 | - --leader-elect 32 | image: controller:latest 33 | name: manager 34 | securityContext: 35 | allowPrivilegeEscalation: false 36 | livenessProbe: 37 | httpGet: 38 | path: /healthz 39 | port: 8081 40 | initialDelaySeconds: 15 41 | periodSeconds: 20 42 | readinessProbe: 43 | httpGet: 44 | path: /readyz 45 | port: 8081 46 | initialDelaySeconds: 5 47 | periodSeconds: 10 48 | resources: 49 | limits: 50 | cpu: 100m 51 | memory: 30Mi 52 | requests: 53 | cpu: 100m 54 | memory: 20Mi 55 | serviceAccountName: controller-manager 56 | terminationGracePeriodSeconds: 10 57 | -------------------------------------------------------------------------------- /opensearch-operator/config/prometheus/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | - monitor.yaml 3 | -------------------------------------------------------------------------------- /opensearch-operator/config/prometheus/monitor.yaml: -------------------------------------------------------------------------------- 1 | 2 | # Prometheus Monitor Service (Metrics) 3 | apiVersion: monitoring.coreos.com/v1 4 | kind: ServiceMonitor 5 | metadata: 6 | labels: 7 | control-plane: controller-manager 8 | name: controller-manager-metrics-monitor 9 | namespace: system 10 | spec: 11 | endpoints: 12 | - path: /metrics 13 | port: https 14 | scheme: https 15 | bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token 16 | tlsConfig: 17 | insecureSkipVerify: true 18 | selector: 19 | matchLabels: 20 | control-plane: controller-manager 21 | -------------------------------------------------------------------------------- /opensearch-operator/config/rbac/auth_proxy_client_clusterrole.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRole 3 | metadata: 4 | name: metrics-reader 5 | rules: 6 | - nonResourceURLs: 7 | - "/metrics" 8 | verbs: 9 | - get 10 | -------------------------------------------------------------------------------- /opensearch-operator/config/rbac/auth_proxy_role.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRole 3 | metadata: 4 | name: proxy-role 5 | rules: 6 | - apiGroups: 7 | - authentication.k8s.io 8 | resources: 9 | - tokenreviews 10 | verbs: 11 | - create 12 | - apiGroups: 13 | - authorization.k8s.io 14 | resources: 15 | - subjectaccessreviews 16 | verbs: 17 | - create 18 | -------------------------------------------------------------------------------- /opensearch-operator/config/rbac/auth_proxy_role_binding.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRoleBinding 3 | metadata: 4 | name: proxy-rolebinding 5 | roleRef: 6 | apiGroup: rbac.authorization.k8s.io 7 | kind: ClusterRole 8 | name: proxy-role 9 | subjects: 10 | - kind: ServiceAccount 11 | name: controller-manager 12 | namespace: system 13 | -------------------------------------------------------------------------------- /opensearch-operator/config/rbac/auth_proxy_service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | labels: 5 | control-plane: controller-manager 6 | name: controller-manager-metrics-service 7 | namespace: system 8 | spec: 9 | ports: 10 | - name: https 11 | port: 8443 12 | targetPort: https 13 | selector: 14 | control-plane: controller-manager 15 | -------------------------------------------------------------------------------- /opensearch-operator/config/rbac/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | # All RBAC will be applied under this service account in 3 | # the deployment namespace. You may comment out this resource 4 | # if your manager will use a service account that exists at 5 | # runtime. Be sure to update RoleBinding and ClusterRoleBinding 6 | # subjects if changing service account names. 7 | - service_account.yaml 8 | - role.yaml 9 | - role_binding.yaml 10 | - leader_election_role.yaml 11 | - leader_election_role_binding.yaml 12 | # Comment the following 4 lines if you want to disable 13 | # the auth proxy (https://github.com/brancz/kube-rbac-proxy) 14 | # which protects your /metrics endpoint. 15 | - auth_proxy_service.yaml 16 | - auth_proxy_role.yaml 17 | - auth_proxy_role_binding.yaml 18 | - auth_proxy_client_clusterrole.yaml 19 | -------------------------------------------------------------------------------- /opensearch-operator/config/rbac/leader_election_role.yaml: -------------------------------------------------------------------------------- 1 | # permissions to do leader election. 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: Role 4 | metadata: 5 | name: leader-election-role 6 | rules: 7 | - apiGroups: 8 | - "" 9 | resources: 10 | - configmaps 11 | verbs: 12 | - get 13 | - list 14 | - watch 15 | - create 16 | - update 17 | - patch 18 | - delete 19 | - apiGroups: 20 | - coordination.k8s.io 21 | resources: 22 | - leases 23 | verbs: 24 | - get 25 | - list 26 | - watch 27 | - create 28 | - update 29 | - patch 30 | - delete 31 | - apiGroups: 32 | - "" 33 | resources: 34 | - events 35 | verbs: 36 | - create 37 | - patch 38 | -------------------------------------------------------------------------------- /opensearch-operator/config/rbac/leader_election_role_binding.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: RoleBinding 3 | metadata: 4 | name: leader-election-rolebinding 5 | roleRef: 6 | apiGroup: rbac.authorization.k8s.io 7 | kind: Role 8 | name: leader-election-role 9 | subjects: 10 | - kind: ServiceAccount 11 | name: controller-manager 12 | namespace: system 13 | -------------------------------------------------------------------------------- /opensearch-operator/config/rbac/opensearch_editor_role.yaml: -------------------------------------------------------------------------------- 1 | # permissions for end users to edit os. 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: ClusterRole 4 | metadata: 5 | name: opensearchcluster-editor-role 6 | rules: 7 | - apiGroups: 8 | - opensearch.opster.io 9 | resources: 10 | - opensearchcluster 11 | verbs: 12 | - create 13 | - delete 14 | - get 15 | - list 16 | - patch 17 | - update 18 | - watch 19 | - apiGroups: 20 | - opensearch.opster.io 21 | resources: 22 | - opensearchcluster/status 23 | verbs: 24 | - get 25 | -------------------------------------------------------------------------------- /opensearch-operator/config/rbac/opensearch_viewer_role.yaml: -------------------------------------------------------------------------------- 1 | # permissions for end users to view os. 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: ClusterRole 4 | metadata: 5 | name: opensearchcluster-viewer-role 6 | rules: 7 | - apiGroups: 8 | - opensearch.opster.io 9 | resources: 10 | - opensearchcluster 11 | verbs: 12 | - get 13 | - list 14 | - watch 15 | - apiGroups: 16 | - opensearch.opster.io 17 | resources: 18 | - opensearchcluster/status 19 | verbs: 20 | - get 21 | -------------------------------------------------------------------------------- /opensearch-operator/config/rbac/opensearchrole_editor_role.yaml: -------------------------------------------------------------------------------- 1 | # permissions for end users to edit opensearchroles. 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: ClusterRole 4 | metadata: 5 | name: opensearchrole-editor-role 6 | rules: 7 | - apiGroups: 8 | - opster.opensearch.opster.io 9 | resources: 10 | - opensearchroles 11 | verbs: 12 | - create 13 | - delete 14 | - get 15 | - list 16 | - patch 17 | - update 18 | - watch 19 | - apiGroups: 20 | - opster.opensearch.opster.io 21 | resources: 22 | - opensearchroles/status 23 | verbs: 24 | - get 25 | -------------------------------------------------------------------------------- /opensearch-operator/config/rbac/opensearchrole_viewer_role.yaml: -------------------------------------------------------------------------------- 1 | # permissions for end users to view opensearchroles. 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: ClusterRole 4 | metadata: 5 | name: opensearchrole-viewer-role 6 | rules: 7 | - apiGroups: 8 | - opster.opensearch.opster.io 9 | resources: 10 | - opensearchroles 11 | verbs: 12 | - get 13 | - list 14 | - watch 15 | - apiGroups: 16 | - opster.opensearch.opster.io 17 | resources: 18 | - opensearchroles/status 19 | verbs: 20 | - get 21 | -------------------------------------------------------------------------------- /opensearch-operator/config/rbac/opensearchuser_editor_role.yaml: -------------------------------------------------------------------------------- 1 | # permissions for end users to edit opensearchusers. 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: ClusterRole 4 | metadata: 5 | name: opensearchuser-editor-role 6 | rules: 7 | - apiGroups: 8 | - opster.opensearch.opster.io 9 | resources: 10 | - opensearchusers 11 | verbs: 12 | - create 13 | - delete 14 | - get 15 | - list 16 | - patch 17 | - update 18 | - watch 19 | - apiGroups: 20 | - opster.opensearch.opster.io 21 | resources: 22 | - opensearchusers/status 23 | verbs: 24 | - get 25 | -------------------------------------------------------------------------------- /opensearch-operator/config/rbac/opensearchuser_viewer_role.yaml: -------------------------------------------------------------------------------- 1 | # permissions for end users to view opensearchusers. 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: ClusterRole 4 | metadata: 5 | name: opensearchuser-viewer-role 6 | rules: 7 | - apiGroups: 8 | - opster.opensearch.opster.io 9 | resources: 10 | - opensearchusers 11 | verbs: 12 | - get 13 | - list 14 | - watch 15 | - apiGroups: 16 | - opster.opensearch.opster.io 17 | resources: 18 | - opensearchusers/status 19 | verbs: 20 | - get 21 | -------------------------------------------------------------------------------- /opensearch-operator/config/rbac/opensearchuserrolebinding_editor_role.yaml: -------------------------------------------------------------------------------- 1 | # permissions for end users to edit opensearchuserrolebindings. 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: ClusterRole 4 | metadata: 5 | name: opensearchuserrolebinding-editor-role 6 | rules: 7 | - apiGroups: 8 | - opster.opensearch.opster.io 9 | resources: 10 | - opensearchuserrolebindings 11 | verbs: 12 | - create 13 | - delete 14 | - get 15 | - list 16 | - patch 17 | - update 18 | - watch 19 | - apiGroups: 20 | - opster.opensearch.opster.io 21 | resources: 22 | - opensearchuserrolebindings/status 23 | verbs: 24 | - get 25 | -------------------------------------------------------------------------------- /opensearch-operator/config/rbac/opensearchuserrolebinding_viewer_role.yaml: -------------------------------------------------------------------------------- 1 | # permissions for end users to view opensearchuserrolebindings. 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: ClusterRole 4 | metadata: 5 | name: opensearchuserrolebinding-viewer-role 6 | rules: 7 | - apiGroups: 8 | - opster.opensearch.opster.io 9 | resources: 10 | - opensearchuserrolebindings 11 | verbs: 12 | - get 13 | - list 14 | - watch 15 | - apiGroups: 16 | - opster.opensearch.opster.io 17 | resources: 18 | - opensearchuserrolebindings/status 19 | verbs: 20 | - get 21 | -------------------------------------------------------------------------------- /opensearch-operator/config/rbac/role_binding.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRoleBinding 3 | metadata: 4 | name: manager-rolebinding 5 | roleRef: 6 | apiGroup: rbac.authorization.k8s.io 7 | kind: ClusterRole 8 | name: manager-role 9 | subjects: 10 | - kind: ServiceAccount 11 | name: controller-manager 12 | namespace: system 13 | -------------------------------------------------------------------------------- /opensearch-operator/config/rbac/service_account.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ServiceAccount 3 | metadata: 4 | name: controller-manager 5 | namespace: system 6 | -------------------------------------------------------------------------------- /opensearch-operator/config/samples/opster_v1_opensearchactiongroup.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: opensearch.opster.io/v1 2 | kind: OpensearchActionGroup 3 | metadata: 4 | name: sample-action-group 5 | namespace: default 6 | spec: 7 | opensearchCluster: 8 | name: my-first-cluster 9 | allowedActions: 10 | - indices:admin/aliases/get 11 | - indices:admin/aliases/exists 12 | type: index 13 | description: Sample action group -------------------------------------------------------------------------------- /opensearch-operator/config/samples/opster_v1_opensearchcluster.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: opensearch.opster.io/v1 2 | kind: OpenSearchCluster 3 | metadata: 4 | name: opensearch-sample 5 | spec: 6 | # Add fields here 7 | foo: bar 8 | -------------------------------------------------------------------------------- /opensearch-operator/config/samples/opster_v1_opensearchrole.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: opster.opensearch.opster.io/v1 2 | kind: OpensearchRole 3 | metadata: 4 | name: opensearchrole-sample 5 | spec: 6 | # TODO(user): Add fields here 7 | -------------------------------------------------------------------------------- /opensearch-operator/config/samples/opster_v1_opensearchtenant.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: opensearch.opster.io/v1 2 | kind: OpensearchTenant 3 | metadata: 4 | name: sample-tenant 5 | namespace: default 6 | spec: 7 | opensearchCluster: 8 | name: my-first-cluster 9 | description: Sample tenant -------------------------------------------------------------------------------- /opensearch-operator/config/samples/opster_v1_opensearchuser.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: opster.opensearch.opster.io/v1 2 | kind: OpensearchUser 3 | metadata: 4 | name: opensearchuser-sample 5 | spec: 6 | # TODO(user): Add fields here 7 | -------------------------------------------------------------------------------- /opensearch-operator/config/samples/opster_v1_opensearchuserrolebinding.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: opster.opensearch.opster.io/v1 2 | kind: OpensearchUserRoleBinding 3 | metadata: 4 | name: opensearchuserrolebinding-sample 5 | spec: 6 | # TODO(user): Add fields here 7 | -------------------------------------------------------------------------------- /opensearch-operator/controllers/controller_settings.go: -------------------------------------------------------------------------------- 1 | package controllers 2 | 3 | const ( 4 | OpensearchFinalizer = "opster.io/opensearch-data" 5 | ) 6 | -------------------------------------------------------------------------------- /opensearch-operator/controllers/opensearch_componenttemplate_controller.go: -------------------------------------------------------------------------------- 1 | package controllers 2 | 3 | import ( 4 | "context" 5 | 6 | opsterv1 "github.com/Opster/opensearch-k8s-operator/opensearch-operator/api/v1" 7 | "github.com/Opster/opensearch-k8s-operator/opensearch-operator/pkg/reconcilers" 8 | "github.com/go-logr/logr" 9 | "k8s.io/apimachinery/pkg/runtime" 10 | "k8s.io/client-go/tools/record" 11 | ctrl "sigs.k8s.io/controller-runtime" 12 | "sigs.k8s.io/controller-runtime/pkg/client" 13 | "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" 14 | "sigs.k8s.io/controller-runtime/pkg/log" 15 | ) 16 | 17 | // OpensearchComponentTemplateReconciler reconciles a OpensearchComponentTemplate object 18 | type OpensearchComponentTemplateReconciler struct { 19 | client.Client 20 | Scheme *runtime.Scheme 21 | Recorder record.EventRecorder 22 | Instance *opsterv1.OpensearchComponentTemplate 23 | logr.Logger 24 | } 25 | 26 | //+kubebuilder:rbac:groups=opensearch.opster.io,resources=opensearchcomponenttemplates,verbs=get;list;watch;create;update;patch;delete 27 | //+kubebuilder:rbac:groups=opensearch.opster.io,resources=opensearchcomponenttemplates/status,verbs=get;update;patch 28 | //+kubebuilder:rbac:groups=opensearch.opster.io,resources=opensearchcomponenttemplates/finalizers,verbs=update 29 | 30 | // Reconcile is part of the main kubernetes reconciliation loop which aims to 31 | // move the current state of the cluster closer to the desired state. 32 | func (r *OpensearchComponentTemplateReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { 33 | r.Logger = log.FromContext(ctx).WithValues("componenttemplate", req.NamespacedName) 34 | r.Logger.Info("Reconciling OpensearchComponentTemplate") 35 | 36 | r.Instance = &opsterv1.OpensearchComponentTemplate{} 37 | err := r.Get(ctx, req.NamespacedName, r.Instance) 38 | if err != nil { 39 | return ctrl.Result{}, client.IgnoreNotFound(err) 40 | } 41 | 42 | componentTemplateReconciler := reconcilers.NewComponentTemplateReconciler( 43 | ctx, 44 | r.Client, 45 | r.Recorder, 46 | r.Instance, 47 | ) 48 | 49 | if r.Instance.DeletionTimestamp.IsZero() { 50 | controllerutil.AddFinalizer(r.Instance, OpensearchFinalizer) 51 | err = r.Client.Update(ctx, r.Instance) 52 | if err != nil { 53 | return ctrl.Result{}, err 54 | } 55 | return componentTemplateReconciler.Reconcile() 56 | } else { 57 | if controllerutil.ContainsFinalizer(r.Instance, OpensearchFinalizer) { 58 | err = componentTemplateReconciler.Delete() 59 | if err != nil { 60 | return ctrl.Result{}, err 61 | } 62 | controllerutil.RemoveFinalizer(r.Instance, OpensearchFinalizer) 63 | return ctrl.Result{}, r.Client.Update(ctx, r.Instance) 64 | } 65 | } 66 | 67 | return ctrl.Result{}, nil 68 | } 69 | 70 | // SetupWithManager sets up the controller with the Manager. 71 | func (r *OpensearchComponentTemplateReconciler) SetupWithManager(mgr ctrl.Manager) error { 72 | return ctrl.NewControllerManagedBy(mgr). 73 | For(&opsterv1.OpensearchComponentTemplate{}). 74 | Owns(&opsterv1.OpenSearchCluster{}). // Get notified when opensearch clusters change 75 | Complete(r) 76 | } 77 | -------------------------------------------------------------------------------- /opensearch-operator/controllers/opensearch_indextemplate_controller.go: -------------------------------------------------------------------------------- 1 | package controllers 2 | 3 | import ( 4 | "context" 5 | 6 | opsterv1 "github.com/Opster/opensearch-k8s-operator/opensearch-operator/api/v1" 7 | "github.com/Opster/opensearch-k8s-operator/opensearch-operator/pkg/reconcilers" 8 | "github.com/go-logr/logr" 9 | "k8s.io/apimachinery/pkg/runtime" 10 | "k8s.io/client-go/tools/record" 11 | ctrl "sigs.k8s.io/controller-runtime" 12 | "sigs.k8s.io/controller-runtime/pkg/client" 13 | "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" 14 | "sigs.k8s.io/controller-runtime/pkg/log" 15 | ) 16 | 17 | // OpensearchIndexTemplateReconciler reconciles a OpensearchIndexTemplate object 18 | type OpensearchIndexTemplateReconciler struct { 19 | client.Client 20 | Scheme *runtime.Scheme 21 | Recorder record.EventRecorder 22 | Instance *opsterv1.OpensearchIndexTemplate 23 | logr.Logger 24 | } 25 | 26 | //+kubebuilder:rbac:groups=opensearch.opster.io,resources=opensearchindextemplates,verbs=get;list;watch;create;update;patch;delete 27 | //+kubebuilder:rbac:groups=opensearch.opster.io,resources=opensearchindextemplates/status,verbs=get;update;patch 28 | //+kubebuilder:rbac:groups=opensearch.opster.io,resources=opensearchindextemplates/finalizers,verbs=update 29 | 30 | // Reconcile is part of the main kubernetes reconciliation loop which aims to 31 | // move the current state of the cluster closer to the desired state. 32 | func (r *OpensearchIndexTemplateReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { 33 | r.Logger = log.FromContext(ctx).WithValues("indextemplate", req.NamespacedName) 34 | r.Logger.Info("Reconciling OpensearchIndexTemplate") 35 | 36 | r.Instance = &opsterv1.OpensearchIndexTemplate{} 37 | err := r.Get(ctx, req.NamespacedName, r.Instance) 38 | if err != nil { 39 | return ctrl.Result{}, client.IgnoreNotFound(err) 40 | } 41 | 42 | indexTemplateReconciler := reconcilers.NewIndexTemplateReconciler( 43 | ctx, 44 | r.Client, 45 | r.Recorder, 46 | r.Instance, 47 | ) 48 | 49 | if r.Instance.DeletionTimestamp.IsZero() { 50 | controllerutil.AddFinalizer(r.Instance, OpensearchFinalizer) 51 | err = r.Client.Update(ctx, r.Instance) 52 | if err != nil { 53 | return ctrl.Result{}, err 54 | } 55 | return indexTemplateReconciler.Reconcile() 56 | } else { 57 | if controllerutil.ContainsFinalizer(r.Instance, OpensearchFinalizer) { 58 | err = indexTemplateReconciler.Delete() 59 | if err != nil { 60 | return ctrl.Result{}, err 61 | } 62 | controllerutil.RemoveFinalizer(r.Instance, OpensearchFinalizer) 63 | return ctrl.Result{}, r.Client.Update(ctx, r.Instance) 64 | } 65 | } 66 | 67 | return ctrl.Result{}, nil 68 | } 69 | 70 | // SetupWithManager sets up the controller with the Manager. 71 | func (r *OpensearchIndexTemplateReconciler) SetupWithManager(mgr ctrl.Manager) error { 72 | return ctrl.NewControllerManagedBy(mgr). 73 | For(&opsterv1.OpensearchIndexTemplate{}). 74 | Owns(&opsterv1.OpenSearchCluster{}). // Get notified when opensearch clusters change 75 | Complete(r) 76 | } 77 | -------------------------------------------------------------------------------- /opensearch-operator/controllers/opensearchactiongroup_controller.go: -------------------------------------------------------------------------------- 1 | package controllers 2 | 3 | import ( 4 | "context" 5 | 6 | opsterv1 "github.com/Opster/opensearch-k8s-operator/opensearch-operator/api/v1" 7 | "github.com/Opster/opensearch-k8s-operator/opensearch-operator/pkg/reconcilers" 8 | "github.com/Opster/opensearch-k8s-operator/opensearch-operator/pkg/reconcilers/k8s" 9 | "github.com/go-logr/logr" 10 | "k8s.io/apimachinery/pkg/runtime" 11 | "k8s.io/client-go/tools/record" 12 | ctrl "sigs.k8s.io/controller-runtime" 13 | "sigs.k8s.io/controller-runtime/pkg/client" 14 | "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" 15 | "sigs.k8s.io/controller-runtime/pkg/log" 16 | ) 17 | 18 | // OpensearchActionGroupReconciler reconciles a OpensearchActionGroup object 19 | type OpensearchActionGroupReconciler struct { 20 | client.Client 21 | Scheme *runtime.Scheme 22 | Recorder record.EventRecorder 23 | Instance *opsterv1.OpensearchActionGroup 24 | logr.Logger 25 | } 26 | 27 | //+kubebuilder:rbac:groups=opensearch.opster.io,resources=opensearchactiongroups,verbs=get;list;watch;create;update;patch;delete 28 | //+kubebuilder:rbac:groups=opensearch.opster.io,resources=opensearchactiongroups/status,verbs=get;update;patch 29 | //+kubebuilder:rbac:groups=opensearch.opster.io,resources=opensearchactiongroups/finalizers,verbs=update 30 | 31 | // Reconcile is part of the main kubernetes reconciliation loop which aims to 32 | // move the current state of the cluster closer to the desired state. 33 | func (r *OpensearchActionGroupReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { 34 | r.Logger = log.FromContext(ctx).WithValues("actiongroup", req.NamespacedName) 35 | r.Logger.Info("Reconciling OpensearchActionGroup") 36 | 37 | r.Instance = &opsterv1.OpensearchActionGroup{} 38 | err := r.Get(ctx, req.NamespacedName, r.Instance) 39 | if err != nil { 40 | return ctrl.Result{}, client.IgnoreNotFound(err) 41 | } 42 | 43 | actionGroupReconciler := reconcilers.NewActionGroupReconciler( 44 | k8s.NewK8sClient(r.Client, ctx), 45 | ctx, 46 | r.Recorder, 47 | r.Instance, 48 | ) 49 | 50 | if r.Instance.DeletionTimestamp.IsZero() { 51 | controllerutil.AddFinalizer(r.Instance, OpensearchFinalizer) 52 | err = r.Client.Update(ctx, r.Instance) 53 | if err != nil { 54 | return ctrl.Result{}, err 55 | } 56 | return actionGroupReconciler.Reconcile() 57 | } else { 58 | if controllerutil.ContainsFinalizer(r.Instance, OpensearchFinalizer) { 59 | err = actionGroupReconciler.Delete() 60 | if err != nil { 61 | return ctrl.Result{}, err 62 | } 63 | controllerutil.RemoveFinalizer(r.Instance, OpensearchFinalizer) 64 | return ctrl.Result{}, r.Client.Update(ctx, r.Instance) 65 | } 66 | } 67 | 68 | return ctrl.Result{}, nil 69 | } 70 | 71 | // SetupWithManager sets up the controller with the Manager. 72 | func (r *OpensearchActionGroupReconciler) SetupWithManager(mgr ctrl.Manager) error { 73 | return ctrl.NewControllerManagedBy(mgr). 74 | For(&opsterv1.OpensearchActionGroup{}). 75 | Owns(&opsterv1.OpenSearchCluster{}). // Get notified when opensearch clusters change 76 | Complete(r) 77 | } 78 | -------------------------------------------------------------------------------- /opensearch-operator/controllers/opensearchism_controller.go: -------------------------------------------------------------------------------- 1 | package controllers 2 | 3 | import ( 4 | "context" 5 | 6 | opsterv1 "github.com/Opster/opensearch-k8s-operator/opensearch-operator/api/v1" 7 | "github.com/Opster/opensearch-k8s-operator/opensearch-operator/pkg/reconcilers" 8 | "github.com/go-logr/logr" 9 | "k8s.io/apimachinery/pkg/runtime" 10 | "k8s.io/client-go/tools/record" 11 | ctrl "sigs.k8s.io/controller-runtime" 12 | "sigs.k8s.io/controller-runtime/pkg/client" 13 | "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" 14 | "sigs.k8s.io/controller-runtime/pkg/log" 15 | ) 16 | 17 | // OpensearchISMReconciler reconciles a ISMPolicy object 18 | type OpensearchISMPolicyReconciler struct { 19 | client.Client 20 | Scheme *runtime.Scheme 21 | Recorder record.EventRecorder 22 | Instance *opsterv1.OpenSearchISMPolicy 23 | logr.Logger 24 | } 25 | 26 | //+kubebuilder:rbac:groups=opensearch.opster.io,resources=opensearchismpolicies,verbs=get;list;watch;create;update;patch;delete 27 | //+kubebuilder:rbac:groups=opensearch.opster.io,resources=opensearchismpolicies/status,verbs=get;update;patch 28 | //+kubebuilder:rbac:groups=opensearch.opster.io,resources=opensearchismpolicies/finalizers,verbs=update 29 | 30 | // Reconcile is part of the main kubernetes reconciliation loop which aims to 31 | // move the current state of the cluster closer to the desired state. 32 | func (r *OpensearchISMPolicyReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { 33 | r.Logger = log.FromContext(ctx).WithValues("tenant", req.NamespacedName) 34 | r.Logger.Info("Reconciling OpensearchISMPolicy") 35 | r.Instance = &opsterv1.OpenSearchISMPolicy{} 36 | err := r.Get(ctx, req.NamespacedName, r.Instance) 37 | if err != nil { 38 | return ctrl.Result{}, client.IgnoreNotFound(err) 39 | } 40 | 41 | ismReconciler := reconcilers.NewIsmReconciler( 42 | ctx, 43 | r.Client, 44 | r.Recorder, 45 | r.Instance, 46 | ) 47 | if r.Instance.DeletionTimestamp.IsZero() { 48 | controllerutil.AddFinalizer(r.Instance, OpensearchFinalizer) 49 | err = r.Client.Update(ctx, r.Instance) 50 | if err != nil { 51 | return ctrl.Result{}, err 52 | } 53 | return ismReconciler.Reconcile() 54 | } else { 55 | if controllerutil.ContainsFinalizer(r.Instance, OpensearchFinalizer) { 56 | err = ismReconciler.Delete() 57 | if err != nil { 58 | return ctrl.Result{}, err 59 | } 60 | controllerutil.RemoveFinalizer(r.Instance, OpensearchFinalizer) 61 | return ctrl.Result{}, r.Client.Update(ctx, r.Instance) 62 | } 63 | } 64 | return ctrl.Result{}, nil 65 | } 66 | 67 | // SetupWithManager sets up the controller with the Manager. 68 | func (r *OpensearchISMPolicyReconciler) SetupWithManager(mgr ctrl.Manager) error { 69 | return ctrl.NewControllerManagedBy(mgr). 70 | For(&opsterv1.OpenSearchISMPolicy{}). 71 | Owns(&opsterv1.OpenSearchCluster{}). // Get notified when opensearch clusters change 72 | Complete(r) 73 | } 74 | -------------------------------------------------------------------------------- /opensearch-operator/controllers/opensearchrole_controller.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package controllers 18 | 19 | import ( 20 | "context" 21 | 22 | "github.com/go-logr/logr" 23 | "k8s.io/apimachinery/pkg/runtime" 24 | "k8s.io/client-go/tools/record" 25 | ctrl "sigs.k8s.io/controller-runtime" 26 | "sigs.k8s.io/controller-runtime/pkg/client" 27 | "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" 28 | "sigs.k8s.io/controller-runtime/pkg/log" 29 | 30 | opsterv1 "github.com/Opster/opensearch-k8s-operator/opensearch-operator/api/v1" 31 | "github.com/Opster/opensearch-k8s-operator/opensearch-operator/pkg/reconcilers" 32 | ) 33 | 34 | // OpensearchRoleReconciler reconciles a OpensearchRole object 35 | type OpensearchRoleReconciler struct { 36 | client.Client 37 | Scheme *runtime.Scheme 38 | Recorder record.EventRecorder 39 | Instance *opsterv1.OpensearchRole 40 | logr.Logger 41 | } 42 | 43 | //+kubebuilder:rbac:groups=opensearch.opster.io,resources=opensearchroles,verbs=get;list;watch;create;update;patch;delete 44 | //+kubebuilder:rbac:groups=opensearch.opster.io,resources=opensearchroles/status,verbs=get;update;patch 45 | //+kubebuilder:rbac:groups=opensearch.opster.io,resources=opensearchroles/finalizers,verbs=update 46 | 47 | // Reconcile is part of the main kubernetes reconciliation loop which aims to 48 | // move the current state of the cluster closer to the desired state. 49 | func (r *OpensearchRoleReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { 50 | r.Logger = log.FromContext(ctx).WithValues("role", req.NamespacedName) 51 | r.Logger.Info("Reconciling OpensearchRole") 52 | 53 | r.Instance = &opsterv1.OpensearchRole{} 54 | err := r.Get(ctx, req.NamespacedName, r.Instance) 55 | if err != nil { 56 | return ctrl.Result{}, client.IgnoreNotFound(err) 57 | } 58 | 59 | roleReconciler := reconcilers.NewRoleReconciler( 60 | r.Client, 61 | ctx, 62 | r.Recorder, 63 | r.Instance, 64 | ) 65 | 66 | if r.Instance.DeletionTimestamp.IsZero() { 67 | controllerutil.AddFinalizer(r.Instance, OpensearchFinalizer) 68 | err = r.Client.Update(ctx, r.Instance) 69 | if err != nil { 70 | return ctrl.Result{}, err 71 | } 72 | return roleReconciler.Reconcile() 73 | } else { 74 | if controllerutil.ContainsFinalizer(r.Instance, OpensearchFinalizer) { 75 | err = roleReconciler.Delete() 76 | if err != nil { 77 | return ctrl.Result{}, err 78 | } 79 | controllerutil.RemoveFinalizer(r.Instance, OpensearchFinalizer) 80 | return ctrl.Result{}, r.Client.Update(ctx, r.Instance) 81 | } 82 | } 83 | 84 | return ctrl.Result{}, nil 85 | } 86 | 87 | // SetupWithManager sets up the controller with the Manager. 88 | func (r *OpensearchRoleReconciler) SetupWithManager(mgr ctrl.Manager) error { 89 | return ctrl.NewControllerManagedBy(mgr). 90 | For(&opsterv1.OpensearchRole{}). 91 | Owns(&opsterv1.OpenSearchCluster{}). // Get notified when opensearch clusters change 92 | Complete(r) 93 | } 94 | -------------------------------------------------------------------------------- /opensearch-operator/controllers/opensearchtenant_controller.go: -------------------------------------------------------------------------------- 1 | package controllers 2 | 3 | import ( 4 | "context" 5 | 6 | opsterv1 "github.com/Opster/opensearch-k8s-operator/opensearch-operator/api/v1" 7 | "github.com/Opster/opensearch-k8s-operator/opensearch-operator/pkg/reconcilers" 8 | "github.com/go-logr/logr" 9 | "k8s.io/apimachinery/pkg/runtime" 10 | "k8s.io/client-go/tools/record" 11 | ctrl "sigs.k8s.io/controller-runtime" 12 | "sigs.k8s.io/controller-runtime/pkg/client" 13 | "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" 14 | "sigs.k8s.io/controller-runtime/pkg/log" 15 | ) 16 | 17 | // OpensearchTenantReconciler reconciles a OpensearchTenant object 18 | type OpensearchTenantReconciler struct { 19 | client.Client 20 | Scheme *runtime.Scheme 21 | Recorder record.EventRecorder 22 | Instance *opsterv1.OpensearchTenant 23 | logr.Logger 24 | } 25 | 26 | //+kubebuilder:rbac:groups=opensearch.opster.io,resources=opensearchtenants,verbs=get;list;watch;create;update;patch;delete 27 | //+kubebuilder:rbac:groups=opensearch.opster.io,resources=opensearchtenants/status,verbs=get;update;patch 28 | //+kubebuilder:rbac:groups=opensearch.opster.io,resources=opensearchtenants/finalizers,verbs=update 29 | 30 | // Reconcile is part of the main kubernetes reconciliation loop which aims to 31 | // move the current state of the cluster closer to the desired state. 32 | func (r *OpensearchTenantReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { 33 | r.Logger = log.FromContext(ctx).WithValues("tenant", req.NamespacedName) 34 | r.Logger.Info("Reconciling OpensearchTenant") 35 | 36 | r.Instance = &opsterv1.OpensearchTenant{} 37 | err := r.Get(ctx, req.NamespacedName, r.Instance) 38 | if err != nil { 39 | return ctrl.Result{}, client.IgnoreNotFound(err) 40 | } 41 | 42 | tenantReconciler := reconcilers.NewTenantReconciler( 43 | r.Client, 44 | ctx, 45 | r.Recorder, 46 | r.Instance, 47 | ) 48 | 49 | if r.Instance.DeletionTimestamp.IsZero() { 50 | controllerutil.AddFinalizer(r.Instance, OpensearchFinalizer) 51 | err = r.Client.Update(ctx, r.Instance) 52 | if err != nil { 53 | return ctrl.Result{}, err 54 | } 55 | return tenantReconciler.Reconcile() 56 | } else { 57 | if controllerutil.ContainsFinalizer(r.Instance, OpensearchFinalizer) { 58 | err = tenantReconciler.Delete() 59 | if err != nil { 60 | return ctrl.Result{}, err 61 | } 62 | controllerutil.RemoveFinalizer(r.Instance, OpensearchFinalizer) 63 | return ctrl.Result{}, r.Client.Update(ctx, r.Instance) 64 | } 65 | } 66 | 67 | return ctrl.Result{}, nil 68 | } 69 | 70 | // SetupWithManager sets up the controller with the Manager. 71 | func (r *OpensearchTenantReconciler) SetupWithManager(mgr ctrl.Manager) error { 72 | return ctrl.NewControllerManagedBy(mgr). 73 | For(&opsterv1.OpensearchTenant{}). 74 | Owns(&opsterv1.OpenSearchCluster{}). // Get notified when opensearch clusters change 75 | Complete(r) 76 | } 77 | -------------------------------------------------------------------------------- /opensearch-operator/controllers/opensearchuserrolebinding_controller.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package controllers 18 | 19 | import ( 20 | "context" 21 | 22 | "github.com/go-logr/logr" 23 | "k8s.io/apimachinery/pkg/runtime" 24 | "k8s.io/client-go/tools/record" 25 | ctrl "sigs.k8s.io/controller-runtime" 26 | "sigs.k8s.io/controller-runtime/pkg/client" 27 | "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" 28 | "sigs.k8s.io/controller-runtime/pkg/log" 29 | 30 | opsterv1 "github.com/Opster/opensearch-k8s-operator/opensearch-operator/api/v1" 31 | "github.com/Opster/opensearch-k8s-operator/opensearch-operator/pkg/reconcilers" 32 | ) 33 | 34 | // OpensearchUserRoleBindingReconciler reconciles a OpensearchUserRoleBinding object 35 | type OpensearchUserRoleBindingReconciler struct { 36 | client.Client 37 | Scheme *runtime.Scheme 38 | Recorder record.EventRecorder 39 | Instance *opsterv1.OpensearchUserRoleBinding 40 | logr.Logger 41 | } 42 | 43 | //+kubebuilder:rbac:groups=opensearch.opster.io,resources=opensearchuserrolebindings,verbs=get;list;watch;create;update;patch;delete 44 | //+kubebuilder:rbac:groups=opensearch.opster.io,resources=opensearchuserrolebindings/status,verbs=get;update;patch 45 | //+kubebuilder:rbac:groups=opensearch.opster.io,resources=opensearchuserrolebindings/finalizers,verbs=update 46 | 47 | // Reconcile is part of the main kubernetes reconciliation loop which aims to 48 | // move the current state of the cluster closer to the desired state. 49 | func (r *OpensearchUserRoleBindingReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { 50 | r.Logger = log.FromContext(ctx).WithValues("userrolebinding", req.NamespacedName) 51 | r.Logger.Info("Reconciling OpensearchUserRoleBinding") 52 | 53 | r.Instance = &opsterv1.OpensearchUserRoleBinding{} 54 | err := r.Get(ctx, req.NamespacedName, r.Instance) 55 | if err != nil { 56 | return ctrl.Result{}, client.IgnoreNotFound(err) 57 | } 58 | 59 | userRoleBindingReconciler := reconcilers.NewUserRoleBindingReconciler( 60 | r.Client, 61 | ctx, 62 | r.Recorder, 63 | r.Instance, 64 | ) 65 | 66 | if r.Instance.DeletionTimestamp.IsZero() { 67 | controllerutil.AddFinalizer(r.Instance, OpensearchFinalizer) 68 | err = r.Client.Update(ctx, r.Instance) 69 | if err != nil { 70 | return ctrl.Result{}, err 71 | } 72 | return userRoleBindingReconciler.Reconcile() 73 | } else { 74 | if controllerutil.ContainsFinalizer(r.Instance, OpensearchFinalizer) { 75 | err = userRoleBindingReconciler.Delete() 76 | if err != nil { 77 | return ctrl.Result{}, err 78 | } 79 | controllerutil.RemoveFinalizer(r.Instance, OpensearchFinalizer) 80 | return ctrl.Result{}, r.Client.Update(ctx, r.Instance) 81 | } 82 | } 83 | 84 | return ctrl.Result{}, nil 85 | } 86 | 87 | // SetupWithManager sets up the controller with the Manager. 88 | func (r *OpensearchUserRoleBindingReconciler) SetupWithManager(mgr ctrl.Manager) error { 89 | return ctrl.NewControllerManagedBy(mgr). 90 | For(&opsterv1.OpensearchUserRoleBinding{}). 91 | Owns(&opsterv1.OpenSearchCluster{}). // Get notified when opensearch clusters change 92 | Complete(r) 93 | } 94 | -------------------------------------------------------------------------------- /opensearch-operator/examples/1.3.x/opensearch-cluster-initcontainer-resources.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: opensearch.opster.io/v1 2 | kind: OpenSearchCluster 3 | metadata: 4 | name: test-init-resources 5 | namespace: default 6 | spec: 7 | general: 8 | version: 1.3.13 9 | httpPort: 9200 10 | vendor: opensearch 11 | serviceName: my-cluster 12 | pluginsList: ["repository-s3","https://github.com/aiven/prometheus-exporter-plugin-for-opensearch/releases/download/1.3.13.0/prometheus-exporter-1.3.13.0.zip"] 13 | initHelper: 14 | resources: 15 | requests: 16 | memory: "128Mi" 17 | cpu: "250m" 18 | limits: 19 | memory: "512Mi" 20 | cpu: "500m" 21 | dashboards: 22 | version: 1.3.13 23 | enable: true 24 | replicas: 1 25 | resources: 26 | requests: 27 | memory: "1Gi" 28 | cpu: "500m" 29 | limits: 30 | memory: "1Gi" 31 | cpu: "500m" 32 | confMgmt: 33 | smartScaler: true 34 | nodePools: 35 | - component: masters 36 | replicas: 1 37 | diskSize: "10Gi" 38 | nodeSelector: 39 | resources: 40 | requests: 41 | memory: "1Gi" 42 | cpu: "500m" 43 | limits: 44 | memory: "1Gi" 45 | cpu: "500m" 46 | roles: 47 | - "master" 48 | - "data" 49 | - component: nodes 50 | replicas: 1 51 | diskSize: "10Gi" 52 | nodeSelector: 53 | resources: 54 | requests: 55 | memory: "1Gi" 56 | cpu: "500m" 57 | limits: 58 | memory: "1Gi" 59 | cpu: "500m" 60 | roles: 61 | - "data" 62 | - component: coordinators 63 | replicas: 1 64 | diskSize: "10Gi" 65 | nodeSelector: 66 | resources: 67 | requests: 68 | memory: "1Gi" 69 | cpu: "500m" 70 | limits: 71 | memory: "1Gi" 72 | cpu: "500m" 73 | roles: 74 | - "ingest" 75 | -------------------------------------------------------------------------------- /opensearch-operator/examples/1.3.x/opensearch-cluster-securityconfig.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: opensearch.opster.io/v1 2 | kind: OpenSearchCluster 3 | metadata: 4 | name: my-cluster 5 | namespace: default 6 | spec: 7 | general: 8 | version: 1.3.16 9 | httpPort: 9200 10 | vendor: opensearch 11 | serviceName: my-cluster 12 | dashboards: 13 | version: 1.3.16 14 | enable: true 15 | replicas: 2 16 | resources: 17 | requests: 18 | memory: "1Gi" 19 | cpu: "500m" 20 | limits: 21 | memory: "1Gi" 22 | cpu: "500m" 23 | confMgmt: 24 | smartScaler: true 25 | security: 26 | config: 27 | securityConfigSecret: 28 | ##Pre create this secret with required security configs, to override the default settings 29 | name: securityconfig-secret 30 | tls: 31 | transport: 32 | generate: true 33 | http: 34 | generate: true 35 | nodePools: 36 | - component: masters 37 | replicas: 3 38 | diskSize: "30Gi" 39 | nodeSelector: 40 | resources: 41 | requests: 42 | memory: "2Gi" 43 | cpu: "500m" 44 | limits: 45 | memory: "2Gi" 46 | cpu: "500m" 47 | roles: 48 | - "master" 49 | - "data" 50 | - component: nodes 51 | replicas: 3 52 | diskSize: "100Gi" 53 | nodeSelector: 54 | resources: 55 | requests: 56 | memory: "2Gi" 57 | cpu: "500m" 58 | limits: 59 | memory: "2Gi" 60 | cpu: "500m" 61 | roles: 62 | - "data" 63 | - component: coordinators 64 | replicas: 3 65 | diskSize: "100Gi" 66 | nodeSelector: 67 | resources: 68 | requests: 69 | memory: "2Gi" 70 | cpu: "500m" 71 | limits: 72 | memory: "2Gi" 73 | cpu: "500m" 74 | roles: 75 | - "ingest" 76 | -------------------------------------------------------------------------------- /opensearch-operator/examples/1.3.x/opensearch-cluster.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: opensearch.opster.io/v1 2 | kind: OpenSearchCluster 3 | metadata: 4 | name: my-cluster 5 | namespace: default 6 | spec: 7 | general: 8 | version: 1.3.16 9 | httpPort: 9200 10 | vendor: opensearch 11 | serviceName: my-cluster 12 | monitoring: 13 | enable: true 14 | pluginsList: ["repository-s3"] 15 | dashboards: 16 | version: 1.3.16 17 | enable: true 18 | replicas: 2 19 | resources: 20 | requests: 21 | memory: "1Gi" 22 | cpu: "500m" 23 | limits: 24 | memory: "1Gi" 25 | cpu: "500m" 26 | confMgmt: 27 | smartScaler: true 28 | nodePools: 29 | - component: masters 30 | replicas: 3 31 | diskSize: "30Gi" 32 | nodeSelector: 33 | resources: 34 | requests: 35 | memory: "2Gi" 36 | cpu: "500m" 37 | limits: 38 | memory: "2Gi" 39 | cpu: "500m" 40 | roles: 41 | - "master" 42 | - "data" 43 | - component: nodes 44 | replicas: 3 45 | diskSize: "30Gi" 46 | nodeSelector: 47 | resources: 48 | requests: 49 | memory: "2Gi" 50 | cpu: "500m" 51 | limits: 52 | memory: "2Gi" 53 | cpu: "500m" 54 | roles: 55 | - "data" 56 | - component: coordinators 57 | replicas: 3 58 | diskSize: "30Gi" 59 | nodeSelector: 60 | resources: 61 | requests: 62 | memory: "2Gi" 63 | cpu: "500m" 64 | limits: 65 | memory: "2Gi" 66 | cpu: "500m" 67 | roles: 68 | - "ingest" 69 | -------------------------------------------------------------------------------- /opensearch-operator/examples/2.x/opensearch-cluster-custom-admin-user.yaml: -------------------------------------------------------------------------------- 1 | ## Use this example in case you want to deploy your cluster with an admin user with a custom password instead of the default (admin). 2 | 3 | apiVersion: opensearch.opster.io/v1 4 | kind: OpenSearchCluster 5 | metadata: 6 | name: my-cluster 7 | namespace: default 8 | spec: 9 | general: 10 | version: 2.14.0 11 | httpPort: 9200 12 | vendor: opensearch 13 | serviceName: my-cluster 14 | security: 15 | config: 16 | ## take a look at opensearch-k8s-operator/docs/userguide/main.md (Custom admin user) 17 | adminCredentialsSecret: 18 | name: admin-credentials-secret 19 | securityConfigSecret: 20 | name: securityconfig-secret 21 | tls: 22 | transport: 23 | generate: true 24 | http: 25 | generate: true 26 | dashboards: 27 | opensearchCredentialsSecret: 28 | name: admin-credentials-secret 29 | version: 2.14.0 30 | enable: true 31 | replicas: 2 32 | resources: 33 | requests: 34 | memory: "1Gi" 35 | cpu: "500m" 36 | limits: 37 | memory: "1Gi" 38 | cpu: "500m" 39 | confMgmt: 40 | smartScaler: true 41 | nodePools: 42 | - component: masters 43 | replicas: 3 44 | diskSize: "30Gi" 45 | nodeSelector: 46 | resources: 47 | requests: 48 | memory: "2Gi" 49 | cpu: "500m" 50 | limits: 51 | memory: "2Gi" 52 | cpu: "500m" 53 | roles: 54 | - "cluster_manager" 55 | - "data" 56 | -------------------------------------------------------------------------------- /opensearch-operator/examples/2.x/opensearch-cluster-pdb.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: opensearch.opster.io/v1 2 | kind: OpenSearchCluster 3 | metadata: 4 | name: my-cluster 5 | namespace: default 6 | spec: 7 | general: 8 | version: 2.14.0 9 | httpPort: 9200 10 | vendor: opensearch 11 | serviceName: my-cluster 12 | monitoring: 13 | enable: true 14 | dashboards: 15 | version: 2.14.0 16 | enable: true 17 | replicas: 1 18 | resources: 19 | requests: 20 | memory: "1Gi" 21 | cpu: "500m" 22 | limits: 23 | memory: "1Gi" 24 | cpu: "500m" 25 | confMgmt: 26 | smartScaler: true 27 | nodePools: 28 | - component: masters 29 | pdb: 30 | enable: true 31 | minAvailable: 1 32 | replicas: 3 33 | diskSize: "30Gi" 34 | nodeSelector: 35 | resources: 36 | requests: 37 | memory: "2Gi" 38 | cpu: "500m" 39 | limits: 40 | memory: "2Gi" 41 | cpu: "500m" 42 | roles: 43 | - "cluster_manager" 44 | - "data" 45 | - component: nodes 46 | replicas: 3 47 | diskSize: "30Gi" 48 | nodeSelector: 49 | resources: 50 | requests: 51 | memory: "2Gi" 52 | cpu: "500m" 53 | limits: 54 | memory: "2Gi" 55 | cpu: "500m" 56 | roles: 57 | - "data" 58 | - component: coordinators 59 | replicas: 3 60 | diskSize: "30Gi" 61 | nodeSelector: 62 | resources: 63 | requests: 64 | memory: "2Gi" 65 | cpu: "500m" 66 | limits: 67 | memory: "2Gi" 68 | cpu: "500m" 69 | roles: 70 | - "ingest" 71 | -------------------------------------------------------------------------------- /opensearch-operator/examples/2.x/opensearch-cluster.yaml: -------------------------------------------------------------------------------- 1 | #Minimal configuration of a cluster with version 2.X of the operator. 2 | #Note the replacement of 'master' role with 'cluster_manager' on line 49 3 | apiVersion: opensearch.opster.io/v1 4 | kind: OpenSearchCluster 5 | metadata: 6 | name: my-first-cluster 7 | namespace: default 8 | spec: 9 | security: 10 | config: 11 | tls: 12 | http: 13 | generate: true 14 | transport: 15 | generate: true 16 | perNode: true 17 | general: 18 | httpPort: 9200 19 | serviceName: my-first-cluster 20 | version: 2.14.0 21 | pluginsList: ["repository-s3"] 22 | drainDataNodes: true 23 | dashboards: 24 | tls: 25 | enable: true 26 | generate: true 27 | version: 2.14.0 28 | enable: true 29 | replicas: 1 30 | resources: 31 | requests: 32 | memory: "512Mi" 33 | cpu: "200m" 34 | limits: 35 | memory: "512Mi" 36 | cpu: "200m" 37 | nodePools: 38 | - component: masters 39 | replicas: 3 40 | resources: 41 | requests: 42 | memory: "4Gi" 43 | cpu: "1000m" 44 | limits: 45 | memory: "4Gi" 46 | cpu: "1000m" 47 | roles: 48 | - "data" 49 | - "cluster_manager" 50 | persistence: 51 | emptyDir: {} 52 | -------------------------------------------------------------------------------- /opensearch-operator/examples/2.x/opensearch-hot-warm-cold.yaml: -------------------------------------------------------------------------------- 1 | #Minimal configuration of a cluster with version 2.6.0 of the operator. 2 | #This example will stand up a cluster with managers, hot, warm and cold 3 | #nodes to test hot-warm architectures 4 | apiVersion: opensearch.opster.io/v1 5 | kind: OpenSearchCluster 6 | metadata: 7 | name: my-first-hot-warm-cold-cluster 8 | namespace: default 9 | spec: 10 | security: 11 | config: 12 | tls: 13 | http: 14 | generate: true 15 | transport: 16 | generate: true 17 | perNode: true 18 | general: 19 | httpPort: 9200 20 | setVMMaxMapCount: true 21 | serviceName: my-first-hot-warm-cold-cluster 22 | version: 2.14.0 23 | drainDataNodes: true 24 | dashboards: 25 | tls: 26 | enable: true 27 | generate: true 28 | version: 2.14.0 29 | enable: true 30 | replicas: 1 31 | resources: 32 | requests: 33 | memory: "512Mi" 34 | cpu: "200m" 35 | limits: 36 | memory: "512Mi" 37 | cpu: "200m" 38 | nodePools: 39 | - component: cluster-managers 40 | replicas: 3 41 | jvm: -Xmx2G -Xms2G 42 | resources: 43 | requests: 44 | memory: "4Gi" 45 | cpu: "1" 46 | limits: 47 | memory: "4Gi" 48 | cpu: "1" 49 | roles: 50 | - "cluster_manager" 51 | persistence: 52 | emptyDir: {} 53 | - component: hot-nodes 54 | replicas: 3 55 | diskSize: "100Gi" 56 | jvm: -Xmx2G -Xms2G 57 | resources: 58 | requests: 59 | memory: "4Gi" 60 | cpu: "1" 61 | limits: 62 | memory: "4Gi" 63 | cpu: "1" 64 | additionalConfig: 65 | node.attr.temp: "hot" 66 | roles: 67 | - "data" 68 | - "ingest" 69 | - component: warm-nodes 70 | replicas: 3 71 | diskSize: "200Gi" 72 | jvm: -Xmx2G -Xms2G 73 | resources: 74 | requests: 75 | memory: "4Gi" 76 | cpu: "1" 77 | limits: 78 | memory: "4Gi" 79 | cpu: "1" 80 | additionalConfig: 81 | node.attr.temp: "warm" 82 | roles: 83 | - "data" 84 | - component: cold-nodes 85 | replicas: 3 86 | diskSize: "200Gi" 87 | jvm: -Xmx2G -Xms2G 88 | resources: 89 | requests: 90 | memory: "4Gi" 91 | cpu: "1" 92 | limits: 93 | memory: "4Gi" 94 | cpu: "1" 95 | additionalConfig: 96 | node.attr.temp: "cold" 97 | roles: 98 | - "data" 99 | -------------------------------------------------------------------------------- /opensearch-operator/examples/templates/opensearch-component-template.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: opensearch.opster.io/v1 2 | kind: OpensearchComponentTemplate 3 | metadata: 4 | name: sample-component-template 5 | spec: 6 | opensearchCluster: 7 | name: my-first-cluster 8 | 9 | template: # required 10 | aliases: # optional 11 | my_alias: 12 | isWriteIndex: false 13 | index: 14 | settings: # optional 15 | number_of_shards: 2 16 | number_of_replicas: 1 17 | mappings: # optional 18 | properties: 19 | timestamp: 20 | type: date 21 | format: yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis 22 | value: 23 | type: double 24 | version: 1 # optional 25 | _meta: # optional 26 | description: example description 27 | -------------------------------------------------------------------------------- /opensearch-operator/examples/templates/opensearch-index-template.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: opensearch.opster.io/v1 2 | kind: OpensearchIndexTemplate 3 | metadata: 4 | name: sample-index-template 5 | spec: 6 | opensearchCluster: 7 | name: my-first-cluster 8 | 9 | name: logs_template # name of the index template - defaults to metadata.name 10 | 11 | indexPatterns: # required index patterns 12 | - "logs-2020-01-*" 13 | composedOf: # optional 14 | - sample-component-template 15 | priority: 100 # optional 16 | 17 | template: {} # optional 18 | version: 1 # optional 19 | _meta: {} # optional 20 | -------------------------------------------------------------------------------- /opensearch-operator/functionaltests/execute_tests.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | CLUSTER_NAME=opensearch-operator-tests 3 | 4 | ## Setup k3d cluster and prepare kubeconfig 5 | k3d cluster create $CLUSTER_NAME --agents 2 --kubeconfig-switch-context=false --kubeconfig-update-default=false -p "30000-30005:30000-30005@agent:0" --image=rancher/k3s:v1.22.17-k3s1 6 | k3d kubeconfig get $CLUSTER_NAME > kubeconfig 7 | export KUBECONFIG=$(pwd)/kubeconfig 8 | 9 | ## Build controller docker image 10 | cd .. 11 | make docker-build 12 | 13 | ## Import controller docker image 14 | k3d image import -c $CLUSTER_NAME controller:latest 15 | 16 | ## Install helm chart 17 | helm install opensearch-operator ../charts/opensearch-operator --set manager.image.repository=controller --set manager.image.tag=latest --set manager.image.pullPolicy=IfNotPresent --namespace default --wait 18 | helm install opensearch-cluster ../charts/opensearch-cluster --set OpenSearchClusterSpec.enabled=true --wait 19 | 20 | cd functionaltests 21 | 22 | ## Run tests 23 | go test ./operatortests -timeout 30m 24 | go test ./helmtests -timeout 20m 25 | ## Delete k3d cluster 26 | k3d cluster delete $CLUSTER_NAME 27 | -------------------------------------------------------------------------------- /opensearch-operator/functionaltests/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/Opster/opensearch-k8s-operator/functionaltests 2 | 3 | go 1.22.1 4 | 5 | require ( 6 | github.com/onsi/ginkgo/v2 v2.9.5 7 | github.com/onsi/gomega v1.27.7 8 | k8s.io/api v0.27.2 9 | k8s.io/apimachinery v0.27.2 10 | k8s.io/client-go v0.27.2 11 | sigs.k8s.io/controller-runtime v0.15.0 12 | ) 13 | 14 | require ( 15 | github.com/PuerkitoBio/purell v1.1.1 // indirect 16 | github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect 17 | github.com/davecgh/go-spew v1.1.1 // indirect 18 | github.com/emicklei/go-restful/v3 v3.8.0 // indirect 19 | github.com/evanphx/json-patch/v5 v5.6.0 // indirect 20 | github.com/go-logr/logr v1.2.3 // indirect 21 | github.com/go-openapi/jsonpointer v0.19.5 // indirect 22 | github.com/go-openapi/jsonreference v0.19.5 // indirect 23 | github.com/go-openapi/swag v0.19.14 // indirect 24 | github.com/gogo/protobuf v1.3.2 // indirect 25 | github.com/golang/protobuf v1.5.2 // indirect 26 | github.com/google/gnostic v0.5.7-v3refs // indirect 27 | github.com/google/go-cmp v0.5.8 // indirect 28 | github.com/google/gofuzz v1.1.0 // indirect 29 | github.com/imdario/mergo v0.3.12 // indirect 30 | github.com/josharian/intern v1.0.0 // indirect 31 | github.com/json-iterator/go v1.1.12 // indirect 32 | github.com/mailru/easyjson v0.7.6 // indirect 33 | github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect 34 | github.com/modern-go/reflect2 v1.0.2 // indirect 35 | github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect 36 | github.com/pkg/errors v0.9.1 // indirect 37 | github.com/spf13/pflag v1.0.5 // indirect 38 | golang.org/x/net v0.13.0 // indirect 39 | golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 // indirect 40 | golang.org/x/sys v0.10.0 // indirect 41 | golang.org/x/term v0.10.0 // indirect 42 | golang.org/x/text v0.11.0 // indirect 43 | golang.org/x/time v0.0.0-20220609170525-579cf78fd858 // indirect 44 | google.golang.org/appengine v1.6.7 // indirect 45 | google.golang.org/protobuf v1.28.0 // indirect 46 | gopkg.in/inf.v0 v0.9.1 // indirect 47 | gopkg.in/yaml.v2 v2.4.0 // indirect 48 | gopkg.in/yaml.v3 v3.0.1 // indirect 49 | k8s.io/klog/v2 v2.70.1 // indirect 50 | k8s.io/kube-openapi v0.0.0-20220803162953-67bda5d908f1 // indirect 51 | k8s.io/utils v0.0.0-20220728103510-ee6ede2d64ed // indirect 52 | sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 // indirect 53 | sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect 54 | sigs.k8s.io/yaml v1.3.0 // indirect 55 | ) 56 | -------------------------------------------------------------------------------- /opensearch-operator/functionaltests/helmtests/helmcrinstall_test.go: -------------------------------------------------------------------------------- 1 | package helmtests 2 | 3 | import ( 4 | "context" 5 | "time" 6 | 7 | . "github.com/onsi/ginkgo/v2" 8 | . "github.com/onsi/gomega" 9 | appsv1 "k8s.io/api/apps/v1" 10 | "sigs.k8s.io/controller-runtime/pkg/client" 11 | ) 12 | 13 | // The cluster has been created using Helm outside of this test. This test verifies the presence of the resources after the cluster is created. 14 | var _ = Describe("DeployWithHelm", Ordered, func() { 15 | name := "opensearch-cluster" 16 | namespace := "default" 17 | 18 | When("cluster is created using helm", Ordered, func() { 19 | It("should have 3 ready master pods", func() { 20 | sts := appsv1.StatefulSet{} 21 | Eventually(func() int32 { 22 | err := k8sClient.Get(context.Background(), client.ObjectKey{Name: name + "-masters", Namespace: namespace}, &sts) 23 | if err == nil { 24 | return sts.Status.ReadyReplicas 25 | } 26 | return 0 27 | }, time.Minute*15, time.Second*5).Should(Equal(int32(3))) 28 | }) 29 | 30 | It("should have a ready dashboards pod", func() { 31 | deployment := appsv1.Deployment{} 32 | Eventually(func() int32 { 33 | err := k8sClient.Get(context.Background(), client.ObjectKey{Name: name + "-dashboards", Namespace: namespace}, &deployment) 34 | if err == nil { 35 | return deployment.Status.ReadyReplicas 36 | } 37 | return 0 38 | }, time.Minute*5, time.Second*5).Should(Equal(int32(1))) 39 | }) 40 | }) 41 | }) 42 | -------------------------------------------------------------------------------- /opensearch-operator/functionaltests/helmtests/main_test.go: -------------------------------------------------------------------------------- 1 | package helmtests 2 | 3 | import ( 4 | "testing" 5 | 6 | . "github.com/onsi/ginkgo/v2" 7 | . "github.com/onsi/gomega" 8 | "k8s.io/client-go/tools/clientcmd" 9 | "sigs.k8s.io/controller-runtime/pkg/client" 10 | ) 11 | 12 | var ( 13 | k8sClient client.Client 14 | ) 15 | 16 | func TestAPIs(t *testing.T) { 17 | config, err := clientcmd.BuildConfigFromFlags("", "../kubeconfig") 18 | if err != nil { 19 | panic(err.Error()) 20 | } 21 | k8sClient, err = client.New(config, client.Options{}) 22 | if err != nil { 23 | panic(err.Error()) 24 | } 25 | RegisterFailHandler(Fail) 26 | 27 | RunSpecs(t, "HelmTests") 28 | } 29 | -------------------------------------------------------------------------------- /opensearch-operator/functionaltests/operatortests/deploy-and-upgrade.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: opensearch.opster.io/v1 2 | kind: OpenSearchCluster 3 | metadata: 4 | name: deploy-and-upgrade 5 | namespace: default 6 | spec: 7 | general: 8 | version: 1.3.0 9 | httpPort: 9200 10 | vendor: opensearch 11 | serviceName: deploy-and-upgrade 12 | additionalConfig: 13 | cluster.routing.allocation.disk.watermark.low: 500m 14 | cluster.routing.allocation.disk.watermark.high: 300m 15 | cluster.routing.allocation.disk.watermark.flood_stage: 100m 16 | confMgmt: 17 | smartScaler: true 18 | dashboards: 19 | version: 1.3.0 20 | enable: true 21 | replicas: 1 22 | resources: 23 | requests: 24 | memory: "1Gi" 25 | cpu: "500m" 26 | limits: 27 | memory: "1Gi" 28 | cpu: "500m" 29 | nodePools: 30 | - component: masters 31 | replicas: 3 32 | diskSize: "5Gi" 33 | NodeSelector: 34 | resources: 35 | requests: 36 | memory: "1Gi" 37 | cpu: "500m" 38 | limits: 39 | memory: "2Gi" 40 | cpu: "500m" 41 | roles: 42 | - "master" 43 | - "data" 44 | -------------------------------------------------------------------------------- /opensearch-operator/functionaltests/operatortests/dummy.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Secret 3 | metadata: 4 | name: dummy 5 | namespace: default 6 | type: Opaque 7 | stringData: 8 | foo: bar 9 | -------------------------------------------------------------------------------- /opensearch-operator/functionaltests/operatortests/dummy_test.go: -------------------------------------------------------------------------------- 1 | package operatortests 2 | 3 | import ( 4 | "time" 5 | 6 | . "github.com/onsi/ginkgo/v2" 7 | . "github.com/onsi/gomega" 8 | corev1 "k8s.io/api/core/v1" 9 | "sigs.k8s.io/controller-runtime/pkg/client" 10 | ) 11 | 12 | var _ = Describe("dummy", Ordered, func() { 13 | name := "dummy" 14 | namespace := "default" 15 | 16 | BeforeAll(func() { 17 | CreateKubernetesObjects(name) 18 | }) 19 | 20 | It("should have the secret", func() { 21 | secret := corev1.Secret{} 22 | Get(&secret, client.ObjectKey{Name: "dummy", Namespace: namespace}, time.Second*5) 23 | data, ok := secret.Data["foo"] 24 | Expect(ok).To(BeTrue()) 25 | Expect(string(data)).To(Equal("bar")) 26 | }) 27 | 28 | AfterAll(func() { 29 | Cleanup(name) 30 | }) 31 | }) 32 | -------------------------------------------------------------------------------- /opensearch-operator/functionaltests/operatortests/main_test.go: -------------------------------------------------------------------------------- 1 | package operatortests 2 | 3 | import ( 4 | "testing" 5 | 6 | opsterv1 "github.com/Opster/opensearch-k8s-operator/opensearch-operator/api/v1" 7 | . "github.com/onsi/ginkgo/v2" 8 | . "github.com/onsi/gomega" 9 | "k8s.io/apimachinery/pkg/runtime" 10 | utilruntime "k8s.io/apimachinery/pkg/util/runtime" 11 | clientgoscheme "k8s.io/client-go/kubernetes/scheme" 12 | "k8s.io/client-go/tools/clientcmd" 13 | "sigs.k8s.io/controller-runtime/pkg/client" 14 | ) 15 | 16 | var k8sClient client.Client 17 | 18 | func TestAPIs(t *testing.T) { 19 | config, err := clientcmd.BuildConfigFromFlags("", "../kubeconfig") 20 | if err != nil { 21 | panic(err.Error()) 22 | } 23 | scheme := runtime.NewScheme() 24 | utilruntime.Must(clientgoscheme.AddToScheme(scheme)) 25 | utilruntime.Must(opsterv1.AddToScheme(scheme)) 26 | k8sClient, err = client.New(config, client.Options{ 27 | Scheme: scheme, 28 | }) 29 | if err != nil { 30 | panic(err.Error()) 31 | } 32 | RegisterFailHandler(Fail) 33 | 34 | RunSpecs(t, "FunctionalTests") 35 | } 36 | -------------------------------------------------------------------------------- /opensearch-operator/hack/boilerplate.go.txt: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ -------------------------------------------------------------------------------- /opensearch-operator/hack/create-k3d-cluster.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # This script is based on https://github.com/tilt-dev/k3d-local-registry/blob/master/k3d-with-registry.sh 4 | 5 | # Starts a k3s cluster (via k3d) with local image registry enabled, 6 | # and with nodes annotated such that Tilt (https://tilt.dev/) can 7 | # auto-detect the registry. 8 | 9 | set -o errexit 10 | 11 | # desired cluster name (default is "k3s-default") 12 | CLUSTER_NAME="${CLUSTER_NAME:-k3s-tilt-opensearch}" 13 | 14 | KUBECONFIG= k3d cluster create \ 15 | --config $(dirname $0)/k3d-local.yaml \ 16 | --timeout 30s \ 17 | ${CLUSTER_NAME} "$@" 18 | -------------------------------------------------------------------------------- /opensearch-operator/hack/k3d-local.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: k3d.io/v1alpha2 2 | kind: Simple 3 | servers: 1 4 | agents: 1 5 | volumes: 6 | - volume: /etc/os-release:/etc/os-release 7 | registries: 8 | create: true 9 | options: 10 | k3s: 11 | extraServerArgs: 12 | - --kube-scheduler-arg=v=2 13 | - --log=/var/log/k3s.log 14 | - --alsologtostderr 15 | extraAgentArgs: 16 | - --kubelet-arg=v=2 17 | - --log=/var/log/k3s.log 18 | - --alsologtostderr 19 | -------------------------------------------------------------------------------- /opensearch-operator/opensearch-gateway/requests/ActionGroup.go: -------------------------------------------------------------------------------- 1 | package requests 2 | 3 | type ActionGroup struct { 4 | AllowedActions []string `json:"allowed_actions"` 5 | Type string `json:"type,omitempty"` 6 | Description string `json:"description,omitempty"` 7 | } 8 | -------------------------------------------------------------------------------- /opensearch-operator/opensearch-gateway/requests/ReRouteMoveAction.go: -------------------------------------------------------------------------------- 1 | package requests 2 | 3 | type ReRouteMoveAction struct { 4 | Index string `json:"index"` 5 | Shard string `json:"shard"` 6 | FromNode string `json:"from_node"` 7 | ToNode string `json:"to_node"` 8 | } 9 | -------------------------------------------------------------------------------- /opensearch-operator/opensearch-gateway/requests/RoleMapping.go: -------------------------------------------------------------------------------- 1 | package requests 2 | 3 | type RoleMapping struct { 4 | BackendRoles []string `json:"backend_roles,omitempty"` 5 | Hosts []string `json:"hosts,omitempty"` 6 | Users []string `json:"users,omitempty"` 7 | } 8 | -------------------------------------------------------------------------------- /opensearch-operator/opensearch-gateway/requests/Roles.go: -------------------------------------------------------------------------------- 1 | package requests 2 | 3 | type Role struct { 4 | ClusterPermissions []string `json:"cluster_permissions,omitempty"` 5 | IndexPermissions []IndexPermissionSpec `json:"index_permissions,omitempty"` 6 | TenantPermissions []TenantPermissionsSpec `json:"tenant_permissions,omitempty"` 7 | } 8 | 9 | type IndexPermissionSpec struct { 10 | IndexPatterns []string `json:"index_patterns,omitempty"` 11 | DocumentLevelSecurity string `json:"dls,omitempty"` 12 | FieldLevelSecurity []string `json:"fls,omitempty"` 13 | AllowedActions []string `json:"allowed_actions,omitempty"` 14 | MaskedFields []string `json:"masked_fields,omitempty"` 15 | } 16 | 17 | type TenantPermissionsSpec struct { 18 | TenantPatterns []string `json:"tenant_patterns,omitempty"` 19 | AllowedActions []string `json:"allowed_actions,omitempty"` 20 | } 21 | -------------------------------------------------------------------------------- /opensearch-operator/opensearch-gateway/requests/SnapshotRepository.go: -------------------------------------------------------------------------------- 1 | package requests 2 | 3 | type SnapshotRepository struct { 4 | Type string `json:"type"` 5 | Settings map[string]string `json:"settings,omitempty"` 6 | } 7 | -------------------------------------------------------------------------------- /opensearch-operator/opensearch-gateway/requests/Templates.go: -------------------------------------------------------------------------------- 1 | package requests 2 | 3 | import apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" 4 | 5 | type IndexTemplate struct { 6 | IndexPatterns []string `json:"index_patterns"` 7 | DataStream *Datastream `json:"data_stream,omitempty"` 8 | Template Index `json:"template,omitempty"` 9 | ComposedOf []string `json:"composed_of,omitempty"` 10 | Priority int `json:"priority,omitempty"` 11 | Version int `json:"version,omitempty"` 12 | Meta *apiextensionsv1.JSON `json:"_meta,omitempty"` 13 | } 14 | 15 | type ComponentTemplate struct { 16 | Template Index `json:"template"` 17 | Version int `json:"version,omitempty"` 18 | Meta *apiextensionsv1.JSON `json:"_meta,omitempty"` 19 | } 20 | 21 | type Index struct { 22 | Settings *apiextensionsv1.JSON `json:"settings,omitempty"` 23 | Mappings *apiextensionsv1.JSON `json:"mappings,omitempty"` 24 | Aliases map[string]IndexAlias `json:"aliases,omitempty"` 25 | } 26 | 27 | type DatastreamTimestampFieldSpec struct { 28 | Name string `json:"name"` 29 | } 30 | 31 | type Datastream struct { 32 | TimestampField *DatastreamTimestampFieldSpec `json:"timestamp_field,omitempty"` 33 | } 34 | 35 | type IndexAlias struct { 36 | Index string `json:"index,omitempty"` 37 | Alias string `json:"alias,omitempty"` 38 | Filter *apiextensionsv1.JSON `json:"filter,omitempty"` 39 | Routing string `json:"routing,omitempty"` 40 | IsWriteIndex bool `json:"is_write_index,omitempty"` 41 | } 42 | -------------------------------------------------------------------------------- /opensearch-operator/opensearch-gateway/requests/Tenants.go: -------------------------------------------------------------------------------- 1 | package requests 2 | 3 | type Tenant struct { 4 | Description string `json:"description"` 5 | } 6 | -------------------------------------------------------------------------------- /opensearch-operator/opensearch-gateway/requests/Users.go: -------------------------------------------------------------------------------- 1 | package requests 2 | 3 | type User struct { 4 | Password string `json:"password,omitempty"` 5 | OpendistroSecurityRoles []string `json:"opendistro_security_roles,omitempty"` 6 | BackendRoles []string `json:"backend_roles,omitempty"` 7 | Attributes map[string]string `json:"attributes,omitempty"` 8 | } 9 | -------------------------------------------------------------------------------- /opensearch-operator/opensearch-gateway/responses/CatHealthResponse.go: -------------------------------------------------------------------------------- 1 | package responses 2 | 3 | type CatHealthResponse struct { 4 | Cluster string `json:"cluster"` 5 | Status string `json:"status"` 6 | NodeTotal string `json:"node.total"` 7 | NodeData string `json:"node.data"` 8 | Shards string `json:"shards"` 9 | PrimaryShards string `json:"pri"` 10 | ReloadingShards string `json:"relo"` 11 | InitializingShards string `json:"init"` 12 | UnAssignShards string `json:"unassign"` 13 | PendingTasks string `json:"pending_tasks"` 14 | ActiveShardsPercent string `json:"active_shards_percent"` 15 | MaxTaskWaitTime string `json:"max_task_wait_time"` 16 | } 17 | -------------------------------------------------------------------------------- /opensearch-operator/opensearch-gateway/responses/CatIndicesResponse.go: -------------------------------------------------------------------------------- 1 | package responses 2 | 3 | type CatIndicesResponse struct { 4 | Health string `json:"health"` 5 | Status string `json:"status"` 6 | Index string `json:"index"` 7 | Uuid string `json:"uuid"` 8 | Pri string `json:"pri"` 9 | Rep string `json:"rep"` 10 | DocsCount string `json:"docs.count"` 11 | DocsDeleted string `json:"docs.deleted"` 12 | StoreSize string `json:"tore.size"` 13 | PriStoreSize string `json:"pri.store.size"` 14 | } 15 | -------------------------------------------------------------------------------- /opensearch-operator/opensearch-gateway/responses/CatNodesResponse.go: -------------------------------------------------------------------------------- 1 | package responses 2 | 3 | type CatNodesResponse struct { 4 | Ip string `json:"ip"` 5 | HeapPercent string `json:"heap.percent"` 6 | RamPercent string `json:"ram.percent"` 7 | Cpu string `json:"cpu"` 8 | Load1m string `json:"load_1m"` 9 | Load5m string `json:"load_5m"` 10 | Load15m string `json:"load_15m"` 11 | NodeRole string `json:"node.role"` 12 | Master string `json:"master"` 13 | Name string `json:"name"` 14 | } 15 | -------------------------------------------------------------------------------- /opensearch-operator/opensearch-gateway/responses/CatShardsResponse.go: -------------------------------------------------------------------------------- 1 | package responses 2 | 3 | type CatShardsResponse struct { 4 | Index string `json:"index" json:"i" json:"idx"` 5 | Shard string `json:"shard" json:"s" json:"sh"` 6 | PrimaryOrReplica string `json:"prirep" json:"p" json:"pr" json:"primaryOrReplica"` 7 | State string `json:"state" json:"st"` 8 | Docs string `json:"docs" json:"d" json:"dc"` 9 | Store string `json:"store" json:"sto"` 10 | Ip string `json:"ip"` 11 | NodeName string `json:"node" json:"n"` 12 | NodeId string `json:"id"` 13 | UnassignedAt string `json:"unassigned.at" json:"ua"` 14 | UnassignedDetails string `json:"ud" json:"unassigned.details" json:"completionSize"` 15 | UnassignedFor string `json:"uf" json:"unassigned.for" json:"completionSize"` 16 | UnassignedReason string `json:"ur" json:"unassigned.reason" json:"completionSize"` 17 | CompletionSize string `json:"cs" json:"completion.size" json:"completionSize"` 18 | } 19 | -------------------------------------------------------------------------------- /opensearch-operator/opensearch-gateway/responses/ClusterHealthResponse.go: -------------------------------------------------------------------------------- 1 | package responses 2 | 3 | type ClusterHealthResponse struct { 4 | Status string `json:"status,omitempty"` 5 | ActiveShards int `json:"active_shards,omitempty"` 6 | RelocatingShards int `json:"relocating_shards,omitempty"` 7 | InitializingShards int `json:"initializing_shards,omitempty"` 8 | UnassignedShards int `json:"unassigned_shards,omitempty"` 9 | PercentActive float32 `json:"active_shards_percent_as_number,omitempty"` 10 | Indices map[string]IndexHealth `json:"indices,omitempty"` 11 | } 12 | 13 | type IndexHealth struct { 14 | Status string `json:"status"` 15 | NumberOfShards int `json:"number_of_shards"` 16 | NumberOfReplicas int `json:"number_of_replicas"` 17 | ActivePrimaryShards int `json:"active_primary_shards"` 18 | ActiveShards int `json:"active_shards"` 19 | RelocatingShards int `json:"relocating_shards"` 20 | InitializingShards int `json:"initializing_shards"` 21 | UnassignedShards int `json:"unassigned_shards"` 22 | } 23 | -------------------------------------------------------------------------------- /opensearch-operator/opensearch-gateway/responses/ClusterRerouteResponse.go: -------------------------------------------------------------------------------- 1 | package responses 2 | 3 | type ClusterRerouteResponse struct { 4 | Acknowledged bool `json:"acknowledged"` 5 | State ClusterRerouteStateResponse `json:"state"` 6 | } 7 | 8 | type ClusterRerouteStateResponse struct { 9 | ClusterUuid string `json:"cluster_uuid"` 10 | Version int32 `json:"version"` 11 | StateUuid string `json:"state_uuid"` 12 | MasterNode string `json:"master_node"` 13 | Blocks map[string]string `json:"blocks"` 14 | Nodes map[string]ClusterRerouteStateNodeResponse `json:"nodes"` 15 | RoutingTable map[string]ClusterRerouteStateRoutingTableResponse `json:"routing_table"` 16 | RoutingNodes map[string][]ClusterRerouteStateRoutingNodesResponse `json:"routing_nodes"` 17 | } 18 | 19 | type ClusterRerouteStateNodeResponse struct { 20 | Name string `json:"name"` 21 | EphemeralId int32 `json:"ephemeral_id"` 22 | StateUuid string `json:"state_uuid"` 23 | TransportAddress string `json:"transport_address"` 24 | Attributes map[string]string `json:"attributes"` 25 | } 26 | 27 | type ClusterRerouteStateRoutingTableResponse struct { 28 | Indices map[string]ClusterRerouteStateRoutingTableIndicesShardsResponse `json:"indices"` 29 | } 30 | type ClusterRerouteStateRoutingNodesResponse struct { 31 | Unassigned []ClusterRerouteStateRoutingNodesUnAssignedResponse `json:"unassigned"` 32 | Nodes map[string][]ClusterRerouteStateRoutingTableIndicesShardsAllocationResponse `json:"nodes"` 33 | } 34 | 35 | type ClusterRerouteStateRoutingTableIndicesShardsResponse struct { 36 | Shards map[string][]ClusterRerouteStateRoutingTableIndicesShardsAllocationResponse `json:"shards"` 37 | } 38 | 39 | type ClusterRerouteStateRoutingTableIndicesShardsAllocationResponse struct { 40 | Index string `json:"index"` 41 | Shard int32 `json:"shard"` 42 | PrimaryOrReplica bool `json:"primary"` 43 | State string `json:"state"` 44 | Node string `json:"node"` 45 | RelocatingNode string `json:"relocating_node"` 46 | AllocationId map[string]string `json:"allocation_id"` 47 | } 48 | 49 | type ClusterRerouteStateRoutingNodesUnAssignedResponse struct { 50 | Index string `json:"index"` 51 | Shard int32 `json:"shard"` 52 | PrimaryOrReplica bool `json:"primary"` 53 | State string `json:"state"` 54 | Node string `json:"node"` 55 | RelocatingNode string `json:"relocating_node"` 56 | RecoverySource map[string]string `json:"recovery_source"` 57 | } 58 | 59 | type ClusterRerouteStateRoutingNodesUnAssignedInfoResponse struct { 60 | Reason string `json:"reason"` 61 | At string `json:"at"` 62 | FailedAttempts int32 `json:"failed_attempts"` 63 | FailedNodes []string `json:"failed_nodes"` 64 | Delayed bool `json:"delayed"` 65 | Details string `json:"details"` 66 | AllocationStatus string `json:"allocation_status"` 67 | } 68 | -------------------------------------------------------------------------------- /opensearch-operator/opensearch-gateway/responses/ClusterSettingsResponse.go: -------------------------------------------------------------------------------- 1 | package responses 2 | 3 | type ClusterSettingsResponse struct { 4 | Persistent map[string]interface{} `json:"persistent,omitempty"` 5 | Transient map[string]interface{} `json:"transient,omitempty"` 6 | } 7 | 8 | type FlatClusterSettingsResponse struct { 9 | Persistent Settings `json:"persistent,omitempty"` 10 | Transient Settings `json:"transient,omitempty"` 11 | } 12 | 13 | type Settings struct { 14 | ClusterRoutingAllocationEnable string `json:"cluster.routing.allocation.enable,omitempty"` 15 | ClusterRoutingAllocationExclude string `json:"cluster.routing.allocation.exclude._name,omitempty"` 16 | } 17 | -------------------------------------------------------------------------------- /opensearch-operator/opensearch-gateway/responses/EnableBalanceRoutingMode.go: -------------------------------------------------------------------------------- 1 | package responses 2 | 3 | type EnableBalanceRoutingMode int64 4 | 5 | const ( 6 | all EnableBalanceRoutingMode = iota 7 | primaries 8 | replicas 9 | none 10 | ) 11 | 12 | func (s EnableBalanceRoutingMode) String() string { 13 | switch s { 14 | case all: 15 | return "all" 16 | case primaries: 17 | return "primaries" 18 | case replicas: 19 | return "replicas" 20 | case none: 21 | return "none" 22 | } 23 | return "all" 24 | } 25 | -------------------------------------------------------------------------------- /opensearch-operator/opensearch-gateway/responses/IsmPolicy.go: -------------------------------------------------------------------------------- 1 | package responses 2 | 3 | import "github.com/Opster/opensearch-k8s-operator/opensearch-operator/opensearch-gateway/requests" 4 | 5 | type GetISMPolicyResponse struct { 6 | PolicyID string `json:"_id"` 7 | PrimaryTerm int `json:"_primary_term"` 8 | SequenceNumber int `json:"_seq_no"` 9 | Policy requests.ISMPolicySpec 10 | } 11 | -------------------------------------------------------------------------------- /opensearch-operator/opensearch-gateway/responses/MainPageResponse.go: -------------------------------------------------------------------------------- 1 | package responses 2 | 3 | type MainResponse struct { 4 | Name string `json:"name"` 5 | ClusterName string `json:"cluster_name"` 6 | ClusterUuid string `json:"cluster_uuid"` 7 | Version MainResponseVersion `json:"version"` 8 | Tagline string `json:"tagline"` 9 | } 10 | 11 | type MainResponseVersion struct { 12 | Distribution string `json:"distribution"` 13 | Number string `json:"number"` 14 | BuildType string `json:"build_type"` 15 | BuildHash string `json:"build_hash"` 16 | BuildDate string `json:"build_date"` 17 | BuildSnapshot bool `json:"build_snapshot"` 18 | LuceneVersion string `json:"lucene_version"` 19 | MinimumWireCompatibilityVersion string `json:"minimum_wire_compatibility_version"` 20 | MinimumIndexCompatibilityVersion string `json:"minimum_index_compatibility_version"` 21 | } 22 | -------------------------------------------------------------------------------- /opensearch-operator/opensearch-gateway/responses/NodesStatsResponse.go: -------------------------------------------------------------------------------- 1 | package responses 2 | 3 | type NodesStatsResponse struct { 4 | GeneralInfo NodesStatsGeneralInfoResponse `json:"_nodes"` 5 | ClusterName string `json:"cluster_name"` 6 | Nodes map[string]NodeStatResponse `json:"nodes"` 7 | } 8 | 9 | type NodesStatsGeneralInfoResponse struct { 10 | Total int `json:"total"` 11 | Successful int `json:"successful"` 12 | Failed int `json:"failed"` 13 | } 14 | 15 | type NodeStatResponse struct { 16 | Id string 17 | Name string `json:"name"` 18 | Timestamp uint64 `json:"timestamp"` 19 | TransportAddress string `json:"transport_address"` 20 | Host string `json:"host"` 21 | Ip string `json:"ip"` 22 | Roles []string `json:"roles"` 23 | Attributes map[string]string `json:"attributes"` 24 | Indices map[string]interface{} `json:"indices"` 25 | Os map[string]interface{} `json:"os"` 26 | Process map[string]interface{} `json:"process"` 27 | Jvm map[string]interface{} `json:"jvm"` 28 | ThreadPool map[string]NodeStatThreadPool `json:"thread_pool"` 29 | Fs map[string]interface{} `json:"fs"` 30 | Transport map[string]interface{} `json:"transport"` 31 | Http map[string]interface{} `json:"http"` 32 | Breakers map[string]NodeStatBreakers `json:"breakers"` 33 | Script map[string]interface{} `json:"script"` 34 | Discovery map[string]interface{} `json:"discovery"` 35 | Ingest map[string]interface{} `json:"ingest"` 36 | AdaptiveSelection map[string]NodeStatAdaptiveSelection `json:"adaptive_selection"` 37 | ScriptCache NodeStatScriptCache `json:"script_cache"` 38 | IndexingPressure map[string]interface{} `json:"indexing_pressure"` 39 | } 40 | 41 | type NodeStatThreadPool struct { 42 | Threads uint32 `json:"threads"` 43 | Queue uint32 `json:"queue"` 44 | Active uint32 `json:"active"` 45 | Rejected uint32 `json:"rejected"` 46 | Largest uint32 `json:"largest"` 47 | Completed uint32 `json:"completed"` 48 | } 49 | 50 | type NodeStatBreakers struct { 51 | LimitSizeInBytes uint64 `json:"limit_size_in_bytes"` 52 | EstimatedSizeInBytes uint64 `json:"estimated_size_in_bytes"` 53 | Overhead float32 `json:"overhead"` 54 | Tripped uint32 `json:"tripped"` 55 | } 56 | 57 | type NodeStatAdaptiveSelection struct { 58 | OutgoingSearches uint32 `json:"outgoing_searches"` 59 | AvgQueueSize uint32 `json:"avg_queue_size"` 60 | AvgServiceTimeNs uint32 `json:"avg_service_time_ns"` 61 | AvgResponseTimeNs uint32 `json:"avg_response_time_ns"` 62 | Rank string `json:"rank"` 63 | } 64 | 65 | type NodeStatScriptCache struct { 66 | Sum map[string]interface{} `json:"sum"` 67 | Contexts []NodeStatScriptContext `json:"contexts"` 68 | } 69 | 70 | type NodeStatScriptContext struct { 71 | Context string `json:"context"` 72 | Compilations uint32 `json:"compilations"` 73 | CacheEvictions uint32 `json:"cache_evictions"` 74 | CompilationLimitTriggered uint32 `json:"compilation_limit_triggered"` 75 | } 76 | -------------------------------------------------------------------------------- /opensearch-operator/opensearch-gateway/responses/SecurityResponse.go: -------------------------------------------------------------------------------- 1 | package responses 2 | 3 | import "github.com/Opster/opensearch-k8s-operator/opensearch-operator/opensearch-gateway/requests" 4 | 5 | type GetRoleMappingReponse map[string]requests.RoleMapping 6 | 7 | type GetRoleResponse map[string]requests.Role 8 | 9 | type GetUserResponse map[string]requests.User 10 | 11 | type GetActionGroupResponse map[string]requests.ActionGroup 12 | 13 | type GetTenantResponse map[string]requests.Tenant 14 | -------------------------------------------------------------------------------- /opensearch-operator/opensearch-gateway/responses/SnapshotRepositoryResponse.go: -------------------------------------------------------------------------------- 1 | package responses 2 | 3 | import "github.com/Opster/opensearch-k8s-operator/opensearch-operator/opensearch-gateway/requests" 4 | 5 | type SnapshotRepositoryResponse = map[string]requests.SnapshotRepository 6 | -------------------------------------------------------------------------------- /opensearch-operator/opensearch-gateway/responses/Templates.go: -------------------------------------------------------------------------------- 1 | package responses 2 | 3 | import "github.com/Opster/opensearch-k8s-operator/opensearch-operator/opensearch-gateway/requests" 4 | 5 | type GetIndexTemplatesResponse struct { 6 | IndexTemplates []IndexTemplate `json:"index_templates"` 7 | } 8 | 9 | type IndexTemplate struct { 10 | Name string `json:"name"` 11 | IndexTemplate requests.IndexTemplate `json:"index_template"` 12 | } 13 | 14 | type GetComponentTemplatesResponse struct { 15 | ComponentTemplates []ComponentTemplate `json:"component_templates"` 16 | } 17 | 18 | type ComponentTemplate struct { 19 | Name string `json:"name"` 20 | ComponentTemplate requests.ComponentTemplate `json:"component_template"` 21 | } 22 | -------------------------------------------------------------------------------- /opensearch-operator/opensearch-gateway/services/errors.go: -------------------------------------------------------------------------------- 1 | package services 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | ) 7 | 8 | var ( 9 | ErrClusterHealthOperation = errors.New("cluster health failed") 10 | ErrClusterSettingsOperation = errors.New("cluster settings failed") 11 | ErrCatIndicesOperation = errors.New("cat indices failed") 12 | ) 13 | 14 | func ErrClusterHealthGetFailed(resp string) error { 15 | return fmt.Errorf("get error %w: %s", ErrClusterHealthOperation, resp) 16 | } 17 | 18 | func ErrClusterSettingsGetFailed(resp string) error { 19 | return fmt.Errorf("get error %w: %s", ErrClusterSettingsOperation, resp) 20 | } 21 | 22 | func ErrCatIndicesFailed(resp string) error { 23 | return fmt.Errorf("%w: %s", ErrCatIndicesOperation, resp) 24 | } 25 | -------------------------------------------------------------------------------- /opensearch-operator/opensearch-gateway/services/http_request.go: -------------------------------------------------------------------------------- 1 | package services 2 | 3 | import ( 4 | "context" 5 | "io" 6 | "net/http" 7 | "strings" 8 | 9 | "github.com/opensearch-project/opensearch-go" 10 | "github.com/opensearch-project/opensearch-go/opensearchapi" 11 | ) 12 | 13 | // doHTTPGet performs a HTTP GET request 14 | func doHTTPGet(ctx context.Context, client *opensearch.Client, path strings.Builder) (*opensearchapi.Response, error) { 15 | req, err := http.NewRequest(http.MethodGet, path.String(), nil) 16 | if err != nil { 17 | return nil, err 18 | } 19 | 20 | if ctx != nil { 21 | req = req.WithContext(ctx) 22 | } 23 | 24 | res, err := client.Perform(req) 25 | if err != nil { 26 | return nil, err 27 | } 28 | 29 | return &opensearchapi.Response{StatusCode: res.StatusCode, Body: res.Body, Header: res.Header}, nil 30 | } 31 | 32 | // doHTTPHead performs a HTTP HEAD request 33 | func doHTTPHead(ctx context.Context, client *opensearch.Client, path strings.Builder) (*opensearchapi.Response, error) { 34 | req, err := http.NewRequest(http.MethodHead, path.String(), nil) 35 | if err != nil { 36 | return nil, err 37 | } 38 | 39 | if ctx != nil { 40 | req = req.WithContext(ctx) 41 | } 42 | 43 | res, err := client.Perform(req) 44 | if err != nil { 45 | return nil, err 46 | } 47 | 48 | return &opensearchapi.Response{StatusCode: res.StatusCode, Body: res.Body, Header: res.Header}, nil 49 | } 50 | 51 | // doHTTPPut performs a HTTP PUT request 52 | func doHTTPPut(ctx context.Context, client *opensearch.Client, path strings.Builder, body io.Reader) (*opensearchapi.Response, error) { 53 | req, err := http.NewRequest(http.MethodPut, path.String(), body) 54 | if err != nil { 55 | return nil, err 56 | } 57 | 58 | if ctx != nil { 59 | req = req.WithContext(ctx) 60 | } 61 | req.Header.Add(headerContentType, jsonContentHeader) 62 | 63 | res, err := client.Perform(req) 64 | if err != nil { 65 | return nil, err 66 | } 67 | 68 | return &opensearchapi.Response{StatusCode: res.StatusCode, Body: res.Body, Header: res.Header}, nil 69 | } 70 | 71 | // doHTTPDelete performs a HTTP DELETE request 72 | func doHTTPDelete(ctx context.Context, client *opensearch.Client, path strings.Builder) (*opensearchapi.Response, error) { 73 | req, err := http.NewRequest(http.MethodDelete, path.String(), nil) 74 | if err != nil { 75 | return nil, err 76 | } 77 | 78 | if ctx != nil { 79 | req = req.WithContext(ctx) 80 | } 81 | 82 | res, err := client.Perform(req) 83 | if err != nil { 84 | return nil, err 85 | } 86 | 87 | return &opensearchapi.Response{StatusCode: res.StatusCode, Body: res.Body, Header: res.Header}, nil 88 | } 89 | -------------------------------------------------------------------------------- /opensearch-operator/opensearch-gateway/services/os_data_service_test.go: -------------------------------------------------------------------------------- 1 | package services 2 | 3 | /* 4 | import ( 5 | . "github.com/onsi/ginkgo" 6 | . "github.com/onsi/gomega" 7 | "strings" 8 | "time" 9 | ) 10 | 11 | var _ = Describe("OpensearchCLuster data service tests", func() { 12 | // ctx := context.Background() 13 | 14 | // Define utility constants for object names and testing timeouts/durations and intervals. 15 | const ( 16 | timeout = time.Second * 120 17 | interval = time.Second * 1 18 | ) 19 | 20 | var ( 21 | ClusterClient *OsClusterClient = nil 22 | ) 23 | 24 | /// ------- Creation Check phase ------- 25 | 26 | BeforeEach(func() { 27 | By("Creating open search client ") 28 | Eventually(func() bool { 29 | clusterClient, err := NewOsClusterClient(TestClusterUrl, TestClusterUserName, TestClusterPassword) 30 | if err != nil { 31 | return false 32 | } 33 | ClusterClient = clusterClient 34 | return true 35 | }, timeout, interval).Should(BeTrue()) 36 | }) 37 | Context("Data Service Tests logic", func() { 38 | It("Test Has No Indices With No Replica", func() { 39 | mapping := strings.NewReader(`{ 40 | "settings": { 41 | "index": { 42 | "number_of_shards": 1, 43 | "number_of_replicas": 1 44 | } 45 | } 46 | }`) 47 | indexName := "indices-no-rep-test" 48 | _, err := DeleteIndex(ClusterClient, indexName) 49 | Expect(err).Should(BeNil()) 50 | success, err := CreateIndex(ClusterClient, indexName, mapping) 51 | Expect(err).Should(BeNil()) 52 | Expect(success == 200 || success == 201).Should(BeTrue()) 53 | hasNoReplicas, err := HasIndicesWithNoReplica(ClusterClient) 54 | Expect(err).Should(BeNil()) 55 | Expect(hasNoReplicas).ShouldNot(BeTrue()) 56 | _, err = DeleteIndex(ClusterClient, indexName) 57 | Expect(err).Should(BeNil()) 58 | }) 59 | It("Test Has Indices With No Replica", func() { 60 | mapping := strings.NewReader(`{ 61 | "settings": { 62 | "index": { 63 | "number_of_shards": 1, 64 | "number_of_replicas": 0 65 | } 66 | } 67 | }`) 68 | indexName := "indices-with-rep-test" 69 | _, err := DeleteIndex(ClusterClient, indexName) 70 | Expect(err).Should(BeNil()) 71 | hasNoReplicas := false 72 | success, err := CreateIndex(ClusterClient, indexName, mapping) 73 | Expect(err).Should(BeNil()) 74 | Expect(success == 200 || success == 201).Should(BeTrue()) 75 | hasNoReplicas, err = HasIndicesWithNoReplica(ClusterClient) 76 | Expect(err).Should(BeNil()) 77 | Expect(hasNoReplicas).Should(BeTrue()) 78 | _, err = DeleteIndex(ClusterClient, indexName) 79 | Expect(err).Should(BeNil()) 80 | }) 81 | It("Test Node Exclude", func() { 82 | nodeExcluded, err := AppendExcludeNodeHost(ClusterClient, "not-exists-node") 83 | Expect(err).Should(BeNil()) 84 | Expect(nodeExcluded).Should(BeTrue()) 85 | nodeExcluded, err = RemoveExcludeNodeHost(ClusterClient, "not-exists-node") 86 | Expect(err).Should(BeNil()) 87 | Expect(nodeExcluded).Should(BeTrue()) 88 | }) 89 | }) 90 | })*/ 91 | -------------------------------------------------------------------------------- /opensearch-operator/opensearch-gateway/services/os_ism_service.go: -------------------------------------------------------------------------------- 1 | package services 2 | 3 | import ( 4 | "context" 5 | "encoding/json" 6 | "errors" 7 | "fmt" 8 | 9 | "github.com/Opster/opensearch-k8s-operator/opensearch-operator/opensearch-gateway/requests" 10 | "github.com/Opster/opensearch-k8s-operator/opensearch-operator/opensearch-gateway/responses" 11 | "github.com/google/go-cmp/cmp" 12 | "github.com/google/go-cmp/cmp/cmpopts" 13 | "github.com/opensearch-project/opensearch-go/opensearchutil" 14 | "sigs.k8s.io/controller-runtime/pkg/log" 15 | ) 16 | 17 | var ErrNotFound = errors.New("policy not found") 18 | 19 | // ShouldUpdateISMPolicy checks if the passed policy is same as existing or needs update 20 | func ShouldUpdateISMPolicy(ctx context.Context, newPolicy, existingPolicy requests.ISMPolicy) (bool, error) { 21 | if cmp.Equal(newPolicy, existingPolicy, cmpopts.EquateEmpty()) { 22 | return false, nil 23 | } 24 | lg := log.FromContext(ctx).WithValues("os_service", "policy") 25 | lg.V(1).Info(fmt.Sprintf("existing policy: %+v", existingPolicy)) 26 | lg.V(1).Info(fmt.Sprintf("new policy: %+v", newPolicy)) 27 | lg.Info("policy exists and requires update") 28 | return true, nil 29 | } 30 | 31 | // GetPolicy fetches the passed policy 32 | func GetPolicy(ctx context.Context, service *OsClusterClient, policyName string) (*responses.GetISMPolicyResponse, error) { 33 | resp, err := service.GetISMConfig(ctx, policyName) 34 | if err != nil { 35 | return nil, err 36 | } 37 | defer resp.Body.Close() 38 | if resp.StatusCode == 404 { 39 | return nil, ErrNotFound 40 | } 41 | if resp.IsError() { 42 | return nil, fmt.Errorf("response from API is %s", resp.Status()) 43 | } 44 | ismResponse := responses.GetISMPolicyResponse{} 45 | if resp != nil && resp.Body != nil { 46 | err := json.NewDecoder(resp.Body).Decode(&ismResponse) 47 | if err != nil { 48 | return nil, err 49 | } 50 | return &ismResponse, nil 51 | } 52 | return nil, fmt.Errorf("response is empty") 53 | } 54 | 55 | // CreateISMPolicy creates the passed policy 56 | func CreateISMPolicy(ctx context.Context, service *OsClusterClient, ismpolicy requests.ISMPolicy, policyId string) error { 57 | spec := opensearchutil.NewJSONReader(ismpolicy) 58 | resp, err := service.PutISMConfig(ctx, policyId, spec) 59 | if err != nil { 60 | return err 61 | } 62 | defer resp.Body.Close() 63 | if resp.IsError() { 64 | return fmt.Errorf("failed to create ism policy: %s", resp.String()) 65 | } 66 | return nil 67 | } 68 | 69 | // UpdateISMPolicy updates the given policy 70 | func UpdateISMPolicy(ctx context.Context, service *OsClusterClient, ismpolicy requests.ISMPolicy, seqno, primterm *int, policyId string) error { 71 | spec := opensearchutil.NewJSONReader(ismpolicy) 72 | resp, err := service.UpdateISMConfig(ctx, policyId, *seqno, *primterm, spec) 73 | if err != nil { 74 | return err 75 | } 76 | defer resp.Body.Close() 77 | if resp.IsError() { 78 | return fmt.Errorf("failed to update ism policy: %s", resp.String()) 79 | } 80 | return nil 81 | } 82 | 83 | // DeleteISMPolicy deletes the given policy 84 | func DeleteISMPolicy(ctx context.Context, service *OsClusterClient, policyName string) error { 85 | resp, err := service.DeleteISMConfig(ctx, policyName) 86 | if err != nil { 87 | return err 88 | } 89 | defer resp.Body.Close() 90 | if resp.IsError() { 91 | return fmt.Errorf("failed to delete ism policy: %s", resp.String()) 92 | } 93 | return nil 94 | } 95 | -------------------------------------------------------------------------------- /opensearch-operator/opensearch-gateway/services/services_suite_test.go: -------------------------------------------------------------------------------- 1 | package services 2 | 3 | /* 4 | 5 | import ( 6 | "fmt" 7 | . "github.com/onsi/ginkgo" 8 | . "github.com/onsi/gomega" 9 | "k8s.io/utils/exec" 10 | "github.com/Opster/opensearch-k8s-operator/opensearch-operator/pkg/helpers" 11 | "path/filepath" 12 | "sigs.k8s.io/controller-runtime/pkg/envtest/printer" 13 | "testing" 14 | ) 15 | 16 | func TestServices(t *testing.T) { 17 | RegisterFailHandler(Fail) 18 | RunSpecsWithDefaultAndCustomReporters(t, 19 | "Services Suite", 20 | []Reporter{printer.NewlineReporter{}}) 21 | } 22 | 23 | const ( 24 | TestClusterUrl = "https://localhost:9111" 25 | TestClusterUserName = "admin" 26 | TestClusterPassword = "admin" 27 | ) 28 | 29 | var path = filepath.Join(helpers.GetOperatorRootPath(), "test_resources/docker-compose.yml") 30 | 31 | var _ = BeforeSuite(func() { 32 | cmd := exec.New().Command("docker-compose", "-f", path, "up", "-d") 33 | 34 | output, err := cmd.Output() 35 | fmt.Println(string(output)) 36 | fmt.Println(err) 37 | //Expect(err).NotTo(HaveOccurred()) 38 | }, 60) 39 | 40 | var _ = AfterSuite(func() { 41 | _, err := exec.New().Command("docker-compose", "-f", path, "down").Output() 42 | if err != nil { 43 | fmt.Println("failed to stop docker compose") 44 | } 45 | }) 46 | */ 47 | -------------------------------------------------------------------------------- /opensearch-operator/opensearch-gateway/services/tests_helper.go: -------------------------------------------------------------------------------- 1 | package services 2 | 3 | import ( 4 | "context" 5 | "github.com/opensearch-project/opensearch-go/opensearchapi" 6 | "strings" 7 | ) 8 | 9 | func CreateIndex(clusterClient *OsClusterClient, indexName string, mapping *strings.Reader) (int, error) { 10 | req := opensearchapi.IndicesCreateRequest{ 11 | Index: indexName, 12 | Body: mapping, 13 | } 14 | do, err := req.Do(context.Background(), clusterClient.client) 15 | return do.StatusCode, err 16 | 17 | } 18 | 19 | func UpdateIndexSettings(clusterClient *OsClusterClient, indexName string, mapping *strings.Reader) { 20 | req := opensearchapi.IndicesPutSettingsRequest{ 21 | Index: []string{indexName}, 22 | Body: mapping, 23 | } 24 | _, err := req.Do(context.Background(), clusterClient.client) 25 | if err != nil { 26 | return 27 | } 28 | 29 | } 30 | 31 | func DeleteIndex(clusterClient *OsClusterClient, indexName string) (int, error) { 32 | res, err := opensearchapi.IndicesDeleteRequest{Index: []string{indexName}}.Do(context.Background(), clusterClient.client) 33 | return res.StatusCode, err 34 | 35 | } 36 | -------------------------------------------------------------------------------- /opensearch-operator/pkg/builders/suite_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | First, it will contain the necessary imports. 4 | */ 5 | 6 | /* 7 | Copyright 2022 The Kubernetes authors. 8 | 9 | Licensed under the Apache License, Version 2.0 (the "License"); 10 | you may not use this file except in compliance with the License. 11 | You may obtain a copy of the License at 12 | 13 | http://www.apache.org/licenses/LICENSE-2.0 14 | 15 | Unless required by applicable law or agreed to in writing, software 16 | distributed under the License is distributed on an "AS IS" BASIS, 17 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | See the License for the specific language governing permissions and 19 | limitations under the License. 20 | */ 21 | // +kubebuilder:docs-gen:collapse=Apache License 22 | package builders 23 | 24 | import ( 25 | "context" 26 | "path/filepath" 27 | "testing" 28 | 29 | opsterv1 "github.com/Opster/opensearch-k8s-operator/opensearch-operator/api/v1" 30 | 31 | . "github.com/onsi/ginkgo/v2" 32 | . "github.com/onsi/gomega" 33 | corev1 "k8s.io/api/core/v1" 34 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 35 | "k8s.io/client-go/kubernetes/scheme" 36 | "sigs.k8s.io/controller-runtime/pkg/client" 37 | "sigs.k8s.io/controller-runtime/pkg/envtest" 38 | logf "sigs.k8s.io/controller-runtime/pkg/log" 39 | "sigs.k8s.io/controller-runtime/pkg/log/zap" 40 | //+kubebuilder:scaffold:imports 41 | ) 42 | 43 | // These tests use Ginkgo (BDD-style Go testing framework). Refer to 44 | // http://onsi.github.io/ginkgo/ to learn more about Ginkgo. 45 | 46 | // +kubebuilder:docs-gen:collapse=Imports 47 | 48 | var ( 49 | k8sClient client.Client 50 | testEnv *envtest.Environment 51 | cancel context.CancelFunc 52 | ) 53 | 54 | func TestAPIs(t *testing.T) { 55 | RegisterFailHandler(Fail) 56 | 57 | RunSpecs(t, "Builders Suite") 58 | } 59 | 60 | var _ = BeforeSuite(func() { 61 | logf.SetLogger(zap.New(zap.WriteTo(GinkgoWriter), zap.UseDevMode(true))) 62 | 63 | _, cancel = context.WithCancel(context.TODO()) 64 | 65 | By("bootstrapping test environment") 66 | testEnv = &envtest.Environment{ 67 | CRDDirectoryPaths: []string{filepath.Join("..", "..", "config", "crd", "bases")}, 68 | ErrorIfCRDPathMissing: true, 69 | } 70 | 71 | cfg, err := testEnv.Start() 72 | Expect(err).NotTo(HaveOccurred()) 73 | Expect(cfg).NotTo(BeNil()) 74 | 75 | err = scheme.AddToScheme(scheme.Scheme) 76 | Expect(err).NotTo(HaveOccurred()) 77 | err = opsterv1.AddToScheme(scheme.Scheme) 78 | Expect(err).NotTo(HaveOccurred()) 79 | 80 | k8sClient, err = client.New(cfg, client.Options{Scheme: scheme.Scheme}) 81 | Expect(err).NotTo(HaveOccurred()) 82 | Expect(k8sClient).NotTo(BeNil()) 83 | }) 84 | 85 | var _ = AfterSuite(func() { 86 | By("tearing down the test environment") 87 | cancel() 88 | err := testEnv.Stop() 89 | Expect(err).NotTo(HaveOccurred()) 90 | }) 91 | 92 | func CreateNamespace(k8sClient client.Client, name string) error { 93 | ns := corev1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: name}} 94 | return k8sClient.Create(context.Background(), &ns) 95 | } 96 | -------------------------------------------------------------------------------- /opensearch-operator/pkg/helpers/constants.go: -------------------------------------------------------------------------------- 1 | package helpers 2 | 3 | import ( 4 | "os" 5 | "strconv" 6 | ) 7 | 8 | const ( 9 | DashboardConfigName = "opensearch_dashboards.yml" 10 | DashboardChecksumName = "checksum/dashboards.yml" 11 | ClusterLabel = "opster.io/opensearch-cluster" 12 | NodePoolLabel = "opster.io/opensearch-nodepool" 13 | OsUserNameAnnotation = "opensearchuser/name" 14 | OsUserNamespaceAnnotation = "opensearchuser/namespace" 15 | DnsBaseEnvVariable = "DNS_BASE" 16 | ParallelRecoveryEnabled = "PARALLEL_RECOVERY_ENABLED" 17 | SkipInitContainerEnvVariable = "SKIP_INIT_CONTAINER" 18 | ) 19 | 20 | func SkipInitContainer() bool { 21 | env, found := os.LookupEnv(SkipInitContainerEnvVariable) 22 | 23 | if !found || len(env) == 0 { 24 | return false 25 | } 26 | ok, err := strconv.ParseBool(env) 27 | if err != nil { 28 | return false 29 | } 30 | return ok 31 | } 32 | 33 | func ClusterDnsBase() string { 34 | env, found := os.LookupEnv(DnsBaseEnvVariable) 35 | 36 | if !found || len(env) == 0 { 37 | env = "cluster.local" 38 | } 39 | 40 | return env 41 | } 42 | 43 | func ParallelRecoveryMode() bool { 44 | env, found := os.LookupEnv(ParallelRecoveryEnabled) 45 | 46 | if !found || len(env) == 0 { 47 | env = "true" 48 | } 49 | 50 | result, err := strconv.ParseBool(env) 51 | if err != nil { 52 | return true 53 | } 54 | return result 55 | } 56 | -------------------------------------------------------------------------------- /opensearch-operator/pkg/helpers/helpers_suite_test.go: -------------------------------------------------------------------------------- 1 | package helpers 2 | 3 | import ( 4 | "testing" 5 | 6 | . "github.com/onsi/ginkgo/v2" 7 | . "github.com/onsi/gomega" 8 | ) 9 | 10 | func TestHelpers(t *testing.T) { 11 | RegisterFailHandler(Fail) 12 | RunSpecs(t, "Helpers Suite") 13 | } 14 | -------------------------------------------------------------------------------- /opensearch-operator/pkg/helpers/reconcile-helpers_test.go: -------------------------------------------------------------------------------- 1 | package helpers 2 | 3 | import ( 4 | opsterv1 "github.com/Opster/opensearch-k8s-operator/opensearch-operator/api/v1" 5 | . "github.com/onsi/ginkgo/v2" 6 | . "github.com/onsi/gomega" 7 | ) 8 | 9 | var _ = DescribeTable("versionCheck reconciler", 10 | func(version string, specifiedHttpPort int32, expectedHttpPort int32, expectedSecurityConfigPort int32, expectedSecurityConfigPath string) { 11 | instance := &opsterv1.OpenSearchCluster{ 12 | Spec: opsterv1.ClusterSpec{ 13 | General: opsterv1.GeneralConfig{ 14 | Version: version, 15 | HttpPort: specifiedHttpPort, 16 | }, 17 | }, 18 | } 19 | 20 | actualHttpPort, actualSecurityConfigPort, actualConfigPath := VersionCheck(instance) 21 | 22 | Expect(actualHttpPort).To(Equal(expectedHttpPort)) 23 | Expect(actualSecurityConfigPort).To(Equal(expectedSecurityConfigPort)) 24 | Expect(actualConfigPath).To(Equal(expectedSecurityConfigPath)) 25 | }, 26 | Entry("When no http port is specified and version 1.3.0 is used", "1.3.0", int32(0), int32(9200), int32(9300), "/usr/share/opensearch/plugins/opensearch-security/securityconfig"), 27 | Entry("When no http port is specified and version 2.0 is used", "2.0", int32(0), int32(9200), int32(9200), "/usr/share/opensearch/config/opensearch-security"), 28 | Entry("When an http port is specified and version 1.3.0 is used", "1.3.0", int32(6000), int32(6000), int32(9300), "/usr/share/opensearch/plugins/opensearch-security/securityconfig"), 29 | Entry("When an http port is specified and version 2.0 is used", "2.0", int32(6000), int32(6000), int32(6000), "/usr/share/opensearch/config/opensearch-security"), 30 | ) 31 | -------------------------------------------------------------------------------- /opensearch-operator/pkg/helpers/test-helpers.go: -------------------------------------------------------------------------------- 1 | package helpers 2 | 3 | import ( 4 | "github.com/Opster/opensearch-k8s-operator/opensearch-operator/pkg/tls" 5 | corev1 "k8s.io/api/core/v1" 6 | "k8s.io/apimachinery/pkg/runtime" 7 | ) 8 | 9 | // A simple mock to use whenever a record.EventRecorder is needed for a test 10 | type MockEventRecorder struct{} 11 | 12 | func (r *MockEventRecorder) Event(object runtime.Object, eventtype, reason, message string) { 13 | } 14 | 15 | func (r *MockEventRecorder) Eventf(object runtime.Object, eventtype, reason, messageFmt string, args ...interface{}) { 16 | } 17 | 18 | func (r *MockEventRecorder) AnnotatedEventf(object runtime.Object, annotations map[string]string, eventtype, reason, messageFmt string, args ...interface{}) { 19 | } 20 | 21 | func CheckVolumeExists(volumes []corev1.Volume, volumeMounts []corev1.VolumeMount, secretName string, volumeName string) bool { 22 | for _, volume := range volumes { 23 | if volume.Name == volumeName { 24 | for _, mount := range volumeMounts { 25 | if mount.Name == volumeName { 26 | if volume.Secret != nil { 27 | return volume.Secret.SecretName == secretName 28 | } else if volume.ConfigMap != nil { 29 | return volume.ConfigMap.Name == secretName 30 | } 31 | } 32 | } 33 | return false 34 | } 35 | } 36 | return false 37 | } 38 | 39 | func HasKeyWithBytes(data map[string][]byte, key string) bool { 40 | _, exists := data[key] 41 | return exists 42 | } 43 | 44 | type PkiMock struct{} 45 | 46 | type CertMock struct{} 47 | 48 | func (cert *CertMock) SecretDataCA() map[string][]byte { 49 | return map[string][]byte{ 50 | "ca.crt": []byte("ca.crt"), 51 | "ca.key": []byte("ca.key"), 52 | } 53 | } 54 | 55 | func (cert *CertMock) SecretData(ca tls.Cert) map[string][]byte { 56 | return map[string][]byte{ 57 | "ca.crt": []byte("ca.crt"), 58 | "tls.key": []byte("tls.key"), 59 | "tls.crt": []byte("tls.crt"), 60 | } 61 | } 62 | 63 | func (cert *CertMock) KeyData() []byte { 64 | return []byte("tls.key") 65 | } 66 | 67 | func (cert *CertMock) CertData() []byte { 68 | return []byte("tls.crt") 69 | } 70 | 71 | func (ca *CertMock) CreateAndSignCertificate(commonName string, orgUnit string, dnsnames []string) (cert tls.Cert, err error) { 72 | return &CertMock{}, nil 73 | } 74 | 75 | func (pki *PkiMock) GenerateCA(name string) (ca tls.Cert, err error) { 76 | return &CertMock{}, nil 77 | } 78 | 79 | func (pki *PkiMock) CAFromSecret(data map[string][]byte) tls.Cert { 80 | return &CertMock{} 81 | } 82 | 83 | func NewMockPKI() tls.PKI { 84 | return &PkiMock{} 85 | } 86 | -------------------------------------------------------------------------------- /opensearch-operator/pkg/helpers/translate.go: -------------------------------------------------------------------------------- 1 | package helpers 2 | 3 | import ( 4 | v1 "github.com/Opster/opensearch-k8s-operator/opensearch-operator/api/v1" 5 | "github.com/Opster/opensearch-k8s-operator/opensearch-operator/opensearch-gateway/requests" 6 | ) 7 | 8 | // TranslateIndexTemplateToRequest rewrites the CRD format to the gateway format 9 | func TranslateIndexTemplateToRequest(spec v1.OpensearchIndexTemplateSpec) requests.IndexTemplate { 10 | request := requests.IndexTemplate{ 11 | IndexPatterns: spec.IndexPatterns, 12 | DataStream: TranslateDatastreamToRequest(spec.DataStream), 13 | Template: TranslateIndexToRequest(spec.Template), 14 | Priority: spec.Priority, 15 | Version: spec.Version, 16 | } 17 | if spec.Meta.Size() > 0 { 18 | request.Meta = spec.Meta 19 | } 20 | if len(spec.ComposedOf) > 0 { 21 | request.ComposedOf = spec.ComposedOf 22 | } 23 | 24 | return request 25 | } 26 | 27 | // TranslateComponentTemplateToRequest rewrites the CRD format to the gateway format 28 | func TranslateComponentTemplateToRequest(spec v1.OpensearchComponentTemplateSpec) requests.ComponentTemplate { 29 | request := requests.ComponentTemplate{ 30 | Template: TranslateIndexToRequest(spec.Template), 31 | Version: spec.Version, 32 | } 33 | if spec.Meta.Size() > 0 { 34 | request.Meta = spec.Meta 35 | } 36 | 37 | return request 38 | } 39 | 40 | // TranslateDatastreamToRequest rewrites the CRD format to the gateway format 41 | func TranslateDatastreamToRequest(spec *v1.OpensearchDatastreamSpec) *requests.Datastream { 42 | if spec == nil { 43 | return nil 44 | } 45 | request := requests.Datastream{} 46 | if spec.TimestampField.Name != "" { 47 | request.TimestampField = &requests.DatastreamTimestampFieldSpec{Name: spec.TimestampField.Name} 48 | } 49 | 50 | return &request 51 | } 52 | 53 | // TranslateIndexToRequest rewrites the CRD format to the gateway format 54 | func TranslateIndexToRequest(spec v1.OpensearchIndexSpec) requests.Index { 55 | aliases := make(map[string]requests.IndexAlias) 56 | for key, val := range spec.Aliases { 57 | aliases[key] = requests.IndexAlias{ 58 | Index: val.Index, 59 | Alias: val.Alias, 60 | Filter: val.Filter, 61 | Routing: val.Routing, 62 | IsWriteIndex: val.IsWriteIndex, 63 | } 64 | } 65 | 66 | request := requests.Index{} 67 | 68 | if len(aliases) > 0 { 69 | request.Aliases = aliases 70 | } 71 | if spec.Settings.Size() > 0 { 72 | request.Settings = spec.Settings 73 | } 74 | if spec.Mappings.Size() > 0 { 75 | request.Mappings = spec.Mappings 76 | } 77 | 78 | return request 79 | } 80 | -------------------------------------------------------------------------------- /opensearch-operator/pkg/reconcilers/suite_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022 The Kubernetes authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | // +kubebuilder:docs-gen:collapse=Apache License 17 | package reconcilers 18 | 19 | import ( 20 | "fmt" 21 | "testing" 22 | 23 | monitoring "github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring/v1" 24 | 25 | opsterv1 "github.com/Opster/opensearch-k8s-operator/opensearch-operator/api/v1" 26 | 27 | . "github.com/onsi/ginkgo/v2" 28 | . "github.com/onsi/gomega" 29 | "k8s.io/apimachinery/pkg/api/errors" 30 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 31 | 32 | "k8s.io/client-go/kubernetes/scheme" 33 | logf "sigs.k8s.io/controller-runtime/pkg/log" 34 | "sigs.k8s.io/controller-runtime/pkg/log/zap" 35 | //+kubebuilder:scaffold:imports 36 | ) 37 | 38 | // These tests use Ginkgo (BDD-style Go testing framework). Refer to 39 | // http://onsi.github.io/ginkgo/ to learn more about Ginkgo. 40 | 41 | // +kubebuilder:docs-gen:collapse=Imports 42 | 43 | func TestAPIs(t *testing.T) { 44 | RegisterFailHandler(Fail) 45 | RunSpecs(t, "Reconciler Suite") 46 | } 47 | 48 | var _ = BeforeSuite(func() { 49 | logf.SetLogger(zap.New(zap.WriteTo(GinkgoWriter), zap.UseDevMode(true))) 50 | 51 | err := scheme.AddToScheme(scheme.Scheme) 52 | Expect(err).NotTo(HaveOccurred()) 53 | err = opsterv1.AddToScheme(scheme.Scheme) 54 | Expect(err).NotTo(HaveOccurred()) 55 | err = monitoring.AddToScheme(scheme.Scheme) 56 | Expect(err).NotTo(HaveOccurred()) 57 | }) 58 | 59 | var _ = AfterSuite(func() { 60 | }) 61 | 62 | func NotFoundError() error { 63 | return &errors.StatusError{ErrStatus: metav1.Status{Reason: metav1.StatusReasonNotFound}} 64 | } 65 | 66 | func failMessage(mesg ...interface{}) { 67 | Fail(fmt.Sprintln(mesg...)) 68 | } 69 | -------------------------------------------------------------------------------- /opensearch-operator/pkg/reconcilers/util/util_suite_test.go: -------------------------------------------------------------------------------- 1 | package util 2 | 3 | import ( 4 | "testing" 5 | 6 | opsterv1 "github.com/Opster/opensearch-k8s-operator/opensearch-operator/api/v1" 7 | . "github.com/onsi/ginkgo/v2" 8 | . "github.com/onsi/gomega" 9 | "k8s.io/client-go/kubernetes/scheme" 10 | logf "sigs.k8s.io/controller-runtime/pkg/log" 11 | "sigs.k8s.io/controller-runtime/pkg/log/zap" 12 | ) 13 | 14 | func TestUtil(t *testing.T) { 15 | RegisterFailHandler(Fail) 16 | RunSpecs(t, "Util Suite") 17 | } 18 | 19 | var _ = BeforeSuite(func() { 20 | 21 | logf.SetLogger(zap.New(zap.WriteTo(GinkgoWriter), zap.UseDevMode(true))) 22 | 23 | err := scheme.AddToScheme(scheme.Scheme) 24 | Expect(err).NotTo(HaveOccurred()) 25 | err = opsterv1.AddToScheme(scheme.Scheme) 26 | Expect(err).NotTo(HaveOccurred()) 27 | }) 28 | 29 | var _ = AfterSuite(func() { 30 | }) 31 | --------------------------------------------------------------------------------