├── .buildkite ├── Dockerfile-ci ├── docker-compose.yml ├── hooks │ ├── pre-command │ └── pre-exit ├── image-release-pipeline.yml ├── pipeline-test-e2e.yml ├── pipeline.yml └── test.sh ├── .codecov.yml ├── .dockerignore ├── .excludecoverage ├── .excludelint ├── .gitattributes ├── .github ├── ISSUE_TEMPLATE.md └── PULL_REQUEST_TEMPLATE.md ├── .gitignore ├── .gitmodules ├── .golangci.yml ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── Dockerfile ├── LICENSE ├── Makefile ├── NOTICE.txt ├── README.md ├── _redirects ├── assets ├── default-config.tmpl └── default-config.yaml ├── build ├── build-docker.sh ├── install-dep.sh └── package-helm-charts.sh ├── bundle.yaml ├── cmd ├── docgen │ ├── api.go │ └── main.go └── m3db-operator │ └── main.go ├── config └── crd │ └── operator.m3db.io_m3dbclusters.yaml ├── docker └── images.json ├── example ├── config-map.yaml ├── etcd │ ├── etcd-basic.yaml │ ├── etcd-kind.yaml │ ├── etcd-minikube.yaml │ └── etcd-pd.yaml ├── m3db-cluster-per-zone-storageclass.yaml ├── m3db-cluster.yaml ├── m3db-kind.yaml ├── m3db-local.yaml ├── prometheus-servicemonitor.yaml ├── simple-cluster.yaml ├── storage-fast-gcp.yaml ├── storage-fast-minikube.yaml └── storage-m3db-gcp.yaml ├── generated └── mocks │ └── generate.go ├── go.mod ├── go.sum ├── hack ├── custom-boilerplate.go.txt ├── update-generated.sh └── verify-generated.sh ├── helm └── m3db-operator │ ├── Chart.yaml │ ├── LICENSE │ ├── NOTES.txt │ ├── README.md │ ├── templates │ ├── 00_operator.m3db.io_m3dbclusters.yaml │ ├── cluster_role.yaml │ ├── cluster_role_binding.yaml │ ├── service_account.yaml │ └── stateful_set.yaml │ └── values.yaml ├── integration ├── e2e │ ├── README.md │ ├── basic_test.go │ ├── dummy.go │ └── main_test.go ├── harness │ ├── dummy.go │ ├── etcd.go │ ├── harness.go │ ├── m3admin.go │ ├── m3dbcluster.go │ ├── operator.go │ └── run_suite.go └── manifests │ ├── cluster-regional.yaml │ ├── cluster-zonal.yaml │ ├── etcd.yaml │ └── operator.yaml ├── pkg ├── apis │ └── m3dboperator │ │ ├── register.go │ │ └── v1alpha1 │ │ ├── cluster.go │ │ ├── cluster_test.go │ │ ├── doc.go │ │ ├── namespace.go │ │ ├── pod_identity.go │ │ ├── register.go │ │ └── zz_generated.deepcopy.go ├── assets │ ├── assets_test.go │ └── statik.go ├── client │ ├── clientset │ │ └── versioned │ │ │ ├── clientset.go │ │ │ ├── doc.go │ │ │ ├── fake │ │ │ ├── clientset_generated.go │ │ │ ├── doc.go │ │ │ └── register.go │ │ │ ├── scheme │ │ │ ├── doc.go │ │ │ └── register.go │ │ │ └── typed │ │ │ └── m3dboperator │ │ │ └── v1alpha1 │ │ │ ├── doc.go │ │ │ ├── fake │ │ │ ├── doc.go │ │ │ ├── fake_m3dbcluster.go │ │ │ └── fake_m3dboperator_client.go │ │ │ ├── generated_expansion.go │ │ │ ├── m3dbcluster.go │ │ │ └── m3dboperator_client.go │ ├── informers │ │ └── externalversions │ │ │ ├── factory.go │ │ │ ├── generic.go │ │ │ ├── internalinterfaces │ │ │ └── factory_interfaces.go │ │ │ └── m3dboperator │ │ │ ├── interface.go │ │ │ └── v1alpha1 │ │ │ ├── interface.go │ │ │ └── m3dbcluster.go │ └── listers │ │ └── m3dboperator │ │ └── v1alpha1 │ │ ├── expansion_generated.go │ │ └── m3dbcluster.go ├── controller │ ├── add_cluster.go │ ├── add_cluster_test.go │ ├── common_test.go │ ├── controller.go │ ├── controller_test.go │ ├── fixtures │ │ ├── cluster-3-zones.yaml │ │ └── cluster-simple.yaml │ ├── m3admin_client.go │ ├── m3admin_client_test.go │ ├── options.go │ ├── options_test.go │ ├── update_cluster.go │ ├── update_cluster_test.go │ └── util_test.go ├── k8sops │ ├── annotations │ │ ├── annotations.go │ │ └── annotations_test.go │ ├── k8sops.go │ ├── labels │ │ ├── labels.go │ │ └── labels_test.go │ ├── m3db │ │ ├── common.go │ │ ├── common_test.go │ │ ├── config_map.go │ │ ├── config_map_test.go │ │ ├── fixtures │ │ │ └── testM3DBCluster.yaml │ │ ├── generators.go │ │ ├── generators_test.go │ │ ├── k8sops.go │ │ ├── k8sops_mock.go │ │ ├── k8sops_test.go │ │ ├── placement.go │ │ ├── placement_test.go │ │ ├── ports.go │ │ ├── services.go │ │ ├── services_test.go │ │ ├── statefulset.go │ │ ├── statefulset_test.go │ │ └── types.go │ └── podidentity │ │ ├── options.go │ │ ├── options_test.go │ │ ├── provider.go │ │ ├── provider_mock.go │ │ └── provider_test.go ├── m3admin │ ├── client.go │ ├── client_mock.go │ ├── client_test.go │ ├── health │ │ ├── client.go │ │ ├── client_test.go │ │ └── types.go │ ├── jsonpb.go │ ├── m3admin_test.go │ ├── namespace │ │ ├── client.go │ │ ├── client_mock.go │ │ ├── client_test.go │ │ ├── fixtures │ │ │ └── success.json │ │ ├── namespace.go │ │ ├── namespace_test.go │ │ ├── presets.go │ │ └── types.go │ ├── options.go │ ├── placement │ │ ├── client.go │ │ ├── client_mock.go │ │ ├── client_test.go │ │ ├── options.go │ │ ├── options_test.go │ │ └── types.go │ └── topic │ │ ├── client.go │ │ ├── client_mock.go │ │ ├── client_test.go │ │ ├── options.go │ │ ├── options_test.go │ │ └── types.go └── util │ └── eventer │ ├── eventer.go │ ├── eventer_test.go │ └── options.go ├── scripts ├── auto-gen.sh ├── kind-create-cluster.sh ├── migrate_etcd_0.1_0.2.sh ├── prep_changelog.sh └── run_e2e_tests.sh └── tools.go /.buildkite/Dockerfile-ci: -------------------------------------------------------------------------------- 1 | FROM golang:1.18-stretch 2 | 3 | RUN mkdir /helm && \ 4 | cd /helm && \ 5 | wget -q -O helm.tgz https://get.helm.sh/helm-v3.0.2-linux-amd64.tar.gz && \ 6 | tar xzvf helm.tgz && \ 7 | mv linux-amd64/helm /bin && \ 8 | rm -rf /helm 9 | -------------------------------------------------------------------------------- /.buildkite/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | services: 3 | app: 4 | build: 5 | context: ./ 6 | dockerfile: Dockerfile-ci 7 | volumes: 8 | - ../:/go/src/github.com/m3db/m3db-operator 9 | environment: 10 | - CI 11 | - BUILDKITE 12 | - BUILDKITE_AGENT_ACCESS_TOKEN 13 | - BUILDKITE_JOB_ID 14 | - BUILDKITE_BUILD_ID 15 | - BUILDKITE_BUILD_NUMBER 16 | - BUILDKITE_BRANCH 17 | - BUILDKITE_BUILD_URL 18 | - BUILDKITE_PROJECT_SLUG 19 | - BUILDKITE_COMMIT 20 | - BUILDKITE_PULL_REQUEST 21 | - BUILDKITE_TAG 22 | - CODECOV_TOKEN 23 | -------------------------------------------------------------------------------- /.buildkite/hooks/pre-command: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set +u 4 | 5 | echo "--- :golang: Setting up Golang build environment" 6 | 7 | if [[ ! -z "${GIMME_GO_VERSION:-}" ]] && [[ "$GIMME_GO_VERSION" != "" ]]; then 8 | eval "$(.ci/gimme.sh ${GIMME_GO_VERSION})" 9 | else 10 | echo "No \$GIMME_GO_VERSION set, skipping..." 11 | fi 12 | 13 | echo "--- :buildkite: :codecov: environment variables" 14 | export CI="true" # required by codecov.sh 15 | export CODECOV_TOKEN="$CODECOV_TOKEN_M3DB_OPERATOR" 16 | -------------------------------------------------------------------------------- /.buildkite/hooks/pre-exit: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -eo pipefail 4 | 5 | # If there was a kind cluster created during CI, tear it down. 6 | KIND="$HOME/bin/kind" 7 | if [[ -f "$KIND" ]]; then 8 | echo "--- :kubernetes: deleting kind cluster" 9 | $KIND get clusters -q | while read -r CLUSTER; do 10 | $KIND delete cluster --name "$CLUSTER" 11 | done 12 | fi 13 | 14 | echo "--- :git: cleaning checkout" 15 | git clean -dffx 16 | -------------------------------------------------------------------------------- /.buildkite/image-release-pipeline.yml: -------------------------------------------------------------------------------- 1 | steps: 2 | - wait 3 | - name: ":docker: build quay.io/m3db" 4 | command: ".ci/docker/build.sh" 5 | env: 6 | M3_DOCKER_REPO: quay.io/m3db 7 | PUSH_SHA_TAG: true 8 | agents: 9 | queue: builders 10 | timeout_in_minutes: 60 11 | retry: 12 | automatic: 13 | limit: 1 14 | manual: true 15 | plugins: 16 | - docker-login#v2.0.1: 17 | server: quay.io 18 | username: m3db+buildkite 19 | password-env: QUAY_M3DB_TOKEN 20 | - name: ":docker: build quay.io/m3" 21 | command: ".ci/docker/build.sh" 22 | env: 23 | M3_DOCKER_REPO: quay.io/m3 24 | PUSH_SHA_TAG: true 25 | agents: 26 | queue: builders 27 | timeout_in_minutes: 60 28 | retry: 29 | automatic: 30 | limit: 1 31 | manual: true 32 | plugins: 33 | - docker-login#v2.0.1: 34 | server: quay.io 35 | username: m3+buildkite 36 | password-env: QUAY_M3_TOKEN 37 | -------------------------------------------------------------------------------- /.buildkite/pipeline-test-e2e.yml: -------------------------------------------------------------------------------- 1 | steps: 2 | - name: ":kubernetes: e2e tests" 3 | command: make clean test-e2e 4 | env: 5 | CGO_ENABLED: 0 6 | GIMME_GO_VERSION: 1.18.x 7 | plugins: 8 | gopath-checkout#v1.0.1: 9 | import: github.com/m3db/m3db-operator 10 | timeout_in_minutes: 20 11 | agents: 12 | queue: default 13 | retry: 14 | automatic: 15 | limit: 1 16 | manual: true 17 | -------------------------------------------------------------------------------- /.buildkite/pipeline.yml: -------------------------------------------------------------------------------- 1 | common: &common 2 | timeout_in_minutes: 20 3 | agents: 4 | queue: workers 5 | retry: 6 | # Automatically retry failures one time. 7 | automatic: 8 | limit: 1 9 | # Allow manual retries. 10 | manual: true 11 | 12 | steps: 13 | - name: "Check for :docker: build" 14 | command: ".ci/docker/check_do_docker.sh" 15 | agents: 16 | queue: init 17 | timeout_in_minutes: 10 18 | retry: 19 | automatic: 20 | limit: 1 21 | manual: true 22 | - name: Unit 23 | command: .buildkite/test.sh 24 | plugins: 25 | docker-compose#v2.5.1: 26 | run: app 27 | config: .buildkite/docker-compose.yml 28 | workdir: /go/src/github.com/m3db/m3db-operator 29 | <<: *common 30 | -------------------------------------------------------------------------------- /.buildkite/test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -exuo pipefail 4 | 5 | export PACKAGE=github.com/m3db/m3db-operator 6 | 7 | echo "--- :git: Updating git submodules" 8 | git submodule update --init --recursive 9 | echo "--- Running unit tests" 10 | make clean-all test-ci-unit lint bins test-all-gen build-integration 11 | -------------------------------------------------------------------------------- /.codecov.yml: -------------------------------------------------------------------------------- 1 | coverage: 2 | precision: 2 3 | round: down 4 | range: "70...100" 5 | 6 | status: 7 | project: 8 | default: on 9 | patch: 10 | default: on 11 | changes: 12 | default: on 13 | 14 | ignore: 15 | - "pkg/client/**/*" 16 | - "**/*generated.go" 17 | - "**/*generated*.go" 18 | 19 | comment: 20 | layout: "header, reach, diff, flags, footer" 21 | behavior: default 22 | require_changes: no 23 | require_base: no 24 | require_head: yes 25 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | /vendor 2 | /out 3 | /_tools 4 | -------------------------------------------------------------------------------- /.excludecoverage: -------------------------------------------------------------------------------- 1 | _mock.go 2 | vendor/ 3 | _tools/ 4 | zz_generated.deepcopy.go 5 | pkg/client/ 6 | integration/ 7 | -------------------------------------------------------------------------------- /.excludelint: -------------------------------------------------------------------------------- 1 | (vendor/) 2 | (generated/) 3 | (_mock.go) 4 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | /pkg/client/clientset/** linguist-generated=true 2 | /pkg/client/listers/** linguist-generated=true 3 | /pkg/client/informers/** linguist-generated=true 4 | *zz_generated*.go linguist-generated=true 5 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | Thanks for opening an issue for the M3DB Operator! We'd love to help you, but we need the following information included 2 | with any issue: 3 | 4 | * What version of the operator are you running? Please include the docker tag. If using `master`, please include the git 5 | SHA logged when the operator first starts. 6 | 7 | * What version of Kubernetes are you running? Please include the output of `kubectl version`. 8 | 9 | * What are you trying to do? 10 | 11 | * What did you expect to happen? 12 | 13 | * What happened? 14 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | Thanks for contributing to the M3DB Operator! We'd love to accept your contribution, but we require that most issues 2 | outside of trivial changes such as typo corrections have an issue associated with the pull request. So please [open an 3 | issue](https://github.com/m3db/m3db-operator/issues/new) first! 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # OSX artifacts 2 | .DS_Store 3 | 4 | # Dev artifacts 5 | .vscode/ 6 | .idea 7 | 8 | # Binaries for programs and plugins 9 | *.so 10 | *.dylib 11 | 12 | # Test binary, build with `go test -c` 13 | *.test 14 | 15 | # Output of the go coverage tool, specifically when used with LiteIDE 16 | *.out 17 | test.log 18 | 19 | # Disregard vendor packages 20 | _tools/ 21 | vendor/ 22 | 23 | # Ignore build artifacts 24 | out/**/* 25 | site/ 26 | 27 | # ci artifacts 28 | .ci/ 29 | test.log 30 | profile.cov 31 | 32 | # helm binaries 33 | linux-amd64/ 34 | 35 | # Helm packages 36 | helm/**/*.tgz 37 | 38 | # Vim swap files 39 | *.swp 40 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule ".ci"] 2 | path = .ci 3 | url = https://github.com/m3db/ci-scripts.git 4 | branch = master 5 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, sex characteristics, gender identity and expression, 9 | level of experience, education, socio-economic status, nationality, personal 10 | appearance, race, religion, or sexual identity and orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | * Using welcoming and inclusive language 18 | * Being respectful of differing viewpoints and experiences 19 | * Gracefully accepting constructive criticism 20 | * Focusing on what is best for the community 21 | * Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | * The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | * Trolling, insulting/derogatory comments, and personal or political attacks 28 | * Public or private harassment 29 | * Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | * Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or 41 | reject comments, commits, code, wiki edits, issues, and other contributions 42 | that are not aligned to this Code of Conduct, or to ban temporarily or 43 | permanently any contributor for other behaviors that they deem inappropriate, 44 | threatening, offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies both within project spaces and in public spaces 49 | when an individual is representing the project or its community. Examples of 50 | representing a project or community include using an official project e-mail 51 | address, posting via an official social media account, or acting as an appointed 52 | representative at an online or offline event. Representation of a project may be 53 | further defined and clarified by project maintainers. 54 | 55 | ## Enforcement 56 | 57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 58 | reported by contacting the project team at m3db-operator-maintainers@googlegroups.com. All 59 | complaints will be reviewed and investigated and will result in a response that 60 | is deemed necessary and appropriate to the circumstances. The project team is 61 | obligated to maintain confidentiality with regard to the reporter of an incident. 62 | Further details of specific enforcement policies may be posted separately. 63 | 64 | Project maintainers who do not follow or enforce the Code of Conduct in good 65 | faith may face temporary or permanent repercussions as determined by other 66 | members of the project's leadership. 67 | 68 | ## Attribution 69 | 70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 71 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html 72 | 73 | [homepage]: https://www.contributor-covenant.org 74 | 75 | For answers to common questions about this code of conduct, see 76 | https://www.contributor-covenant.org/faq 77 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | We welcome your help building the M3 Operator. 4 | 5 | ## Getting Started 6 | 7 | The M3 Operator uses `dep` to manage dependencies. To get started: 8 | 9 | ```shell 10 | git submodule update --init --recursive 11 | make install-tools 12 | ``` 13 | 14 | ## Making A Change 15 | 16 | - Before making any significant changes, please [open an issue](https://github.com/m3db/m3db-operator/issues). 17 | - Discussing your proposed changes ahead of time maked the contribution process smoother for everyone. 18 | 19 | Once the changes are discussed and you have your code ready, make sure that tests are passing: 20 | 21 | ```bash 22 | make test-all 23 | ``` 24 | 25 | Your pull request is most likely to be accepted if it: 26 | 27 | - Includes tests for new functionality. 28 | - Follows the guidelines in [Effective Go](https://golang.org/doc/effective_go.html) and the [Go team's common code 29 | review comments](https://github.com/golang/go/wiki/CodeReviewComments). 30 | - Has a [good commit message](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html). 31 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # stage 1: build 2 | FROM golang:1.18-alpine3.16 AS builder 3 | LABEL maintainer="The m3db-operator Authors " 4 | 5 | # Install CA certs for curl 6 | RUN apk add --update ca-certificates openssl && \ 7 | rm -rf /var/cache/apk/* 8 | 9 | # Install Build Binaries 10 | RUN apk add --update curl git make bash 11 | 12 | # Add source code 13 | RUN mkdir -p /go/src/github.com/m3db/m3db-operator 14 | ADD . /go/src/github.com/m3db/m3db-operator 15 | 16 | # Build m3dbnode binary 17 | RUN cd /go/src/github.com/m3db/m3db-operator/ && \ 18 | git submodule update --init && \ 19 | make m3db-operator 20 | 21 | # stage 2: lightweight "release" 22 | FROM alpine:latest 23 | LABEL maintainer="The m3db-operator Authors " 24 | 25 | COPY --from=builder /go/src/github.com/m3db/m3db-operator/out/m3db-operator /bin/m3db-operator 26 | 27 | ENTRYPOINT [ "/bin/m3db-operator" ] 28 | -------------------------------------------------------------------------------- /NOTICE.txt: -------------------------------------------------------------------------------- 1 | M3DB Operator includes derived work from Prometheus Operator 2 | (https://github.com/coreos/prometheus-operator) under the Apache License 2.0: 3 | 4 | Copyright 2016 The prometheus-operator Authors 5 | 6 | Licensed under the Apache License, Version 2.0 (the "License"); 7 | you may not use this file except in compliance with the License. 8 | You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | 18 | The derived work can be found in the files: 19 | - cmd/docgen/main.go 20 | - cmd/docgen/api.go 21 | -------------------------------------------------------------------------------- /_redirects: -------------------------------------------------------------------------------- 1 | # Redirect all requests to the operator docs on the main docs site. 2 | 3 | /* https://m3db.io/docs/operator/:splat 301! 4 | -------------------------------------------------------------------------------- /assets/default-config.tmpl: -------------------------------------------------------------------------------- 1 | {{- if .CarbonIngester }} 2 | coordinator: 3 | carbon: 4 | ingester: 5 | listenAddress: "0.0.0.0:7204" 6 | {{- else }} 7 | coordinator: {} 8 | {{- end }} 9 | 10 | db: 11 | hostID: 12 | resolver: file 13 | file: 14 | path: /etc/m3db/pod-identity/identity 15 | timeout: 5m 16 | 17 | client: 18 | writeConsistencyLevel: majority 19 | readConsistencyLevel: unstrict_majority 20 | 21 | discovery: 22 | config: 23 | service: 24 | env: "{{ .Env }}" 25 | zone: embedded 26 | service: m3db 27 | cacheDir: /var/lib/m3kv 28 | etcdClusters: 29 | - zone: embedded 30 | endpoints: 31 | {{- range .Endpoints }} 32 | - "{{- . }}" 33 | {{- end }} 34 | -------------------------------------------------------------------------------- /assets/default-config.yaml: -------------------------------------------------------------------------------- 1 | coordinator: 2 | carbon: 3 | ingester: 4 | listenAddress: "0.0.0.0:7204" 5 | 6 | db: 7 | hostID: 8 | resolver: file 9 | file: 10 | path: /etc/m3db/pod-identity/identity 11 | timeout: 5m 12 | 13 | client: 14 | writeConsistencyLevel: majority 15 | readConsistencyLevel: unstrict_majority 16 | 17 | discovery: 18 | config: 19 | service: 20 | env: default_env 21 | zone: embedded 22 | service: m3db 23 | cacheDir: /var/lib/m3kv 24 | etcdClusters: 25 | - zone: embedded 26 | endpoints: 27 | - http://etcd-0.etcd:2379 28 | - http://etcd-1.etcd:2379 29 | - http://etcd-2.etcd:2379 -------------------------------------------------------------------------------- /build/build-docker.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -o errexit 4 | set -o nounset 5 | set -o pipefail 6 | 7 | if ! which docker > /dev/null; then 8 | echo "docker needs to be installed" 9 | exit 1 10 | fi 11 | 12 | : ${IMAGE:?"Need to set IMAGE, e.g. gcr.io//-operator"} 13 | 14 | GITSHA="$(git rev-parse --short=8 HEAD)" 15 | 16 | echo "building container ${IMAGE}:${GITSHA}..." 17 | docker build -t "${IMAGE}:${GITSHA}" -f Dockerfile . 18 | docker tag "${IMAGE}:${GITSHA}" "${IMAGE}:latest" 19 | docker tag "${IMAGE}:${GITSHA}" "${IMAGE}:${GITSHA}" 20 | docker push "${IMAGE}:${GITSHA}" 21 | docker push "${IMAGE}:latest" 22 | -------------------------------------------------------------------------------- /build/install-dep.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | if ! type brew &> /dev/null; then 4 | curl https://raw.githubusercontent.com/golang/dep/master/install.sh | sh 5 | else 6 | brew install dep 7 | fi 8 | -------------------------------------------------------------------------------- /build/package-helm-charts.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -ex 4 | 5 | # M3 Charts 6 | BUCKET="gs://m3-helm-charts/stable/" 7 | CHART_DIRECTORY="$(pwd)/helm" 8 | CHARTS=( m3db-operator ) 9 | REPO_NAME="m3-charts-push" 10 | HELM_PACKAGE_DIRECTORY=$(mktemp -d) 11 | HELMTMP=$(mktemp -d) 12 | 13 | function cleanup() { 14 | rm -rf "${HELM_PACKAGE_DIRECTORY}" 15 | rm -rf "$HELMTMP" 16 | } 17 | 18 | trap cleanup EXIT 19 | 20 | # Helm 21 | HELM_URL=https://get.helm.sh/helm-v3.0.2-linux-amd64.tar.gz 22 | HELM_TARBALL="helm.tgz" 23 | 24 | install_helm () { 25 | # Download and install helm 26 | ( 27 | cd "$HELMTMP" 28 | wget -q -O $HELM_TARBALL "$HELM_URL" 29 | tar zxvf $HELM_TARBALL 30 | ) 31 | PATH="${PATH}:${HELMTMP}/linux-amd64/bin" 32 | export PATH 33 | 34 | # Install helm gcs plugin if not installed 35 | if [[ $(helm plugin list | grep "^gcs") == "" ]]; then 36 | # NB(schallert): You must build and install this locally until the next 37 | # release is cut. 38 | helm plugin install https://github.com/hayorov/helm-gcs 39 | fi 40 | } 41 | 42 | package_helm () { 43 | for CHART_NAME in "${CHARTS[@]}"; 44 | do 45 | ( 46 | # Package 47 | helm repo add "${REPO_NAME}" "${BUCKET}" 48 | helm package "${CHART_DIRECTORY}/${CHART_NAME}" -d "${HELM_PACKAGE_DIRECTORY}" 49 | 50 | # Push 51 | VERSION=$(grep "^version" "helm/${CHART_NAME}/Chart.yaml" | awk '{print $2}') 52 | helm gcs push --public "${HELM_PACKAGE_DIRECTORY}/${CHART_NAME}-${VERSION}.tgz" "${REPO_NAME}" 53 | ) 54 | done 55 | } 56 | 57 | if ! command -v helm; then 58 | install_helm 59 | fi 60 | 61 | package_helm 62 | -------------------------------------------------------------------------------- /cmd/docgen/main.go: -------------------------------------------------------------------------------- 1 | // Modifications Copyright (c) 2018 Uber Technologies, Inc. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | // Copyright 2016 The prometheus-operator Authors 22 | // 23 | // Licensed under the Apache License, Version 2.0 (the "License"); 24 | // you may not use this file except in compliance with the License. 25 | // You may obtain a copy of the License at 26 | // 27 | // http://www.apache.org/licenses/LICENSE-2.0 28 | // 29 | // Unless required by applicable law or agreed to in writing, software 30 | // distributed under the License is distributed on an "AS IS" BASIS, 31 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 32 | // See the License for the specific language governing permissions and 33 | // limitations under the License. 34 | 35 | package main 36 | 37 | import ( 38 | "os" 39 | ) 40 | 41 | func main() { 42 | switch os.Args[1] { 43 | case "api": 44 | printAPIDocs(os.Args[2:]...) 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /docker/images.json: -------------------------------------------------------------------------------- 1 | { 2 | "images": { 3 | "m3db-operator": { 4 | "dockerfile": "Dockerfile", 5 | "name": "m3db-operator" 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /example/etcd/etcd-basic.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: etcd 5 | labels: 6 | app: etcd 7 | spec: 8 | ports: 9 | - port: 2379 10 | name: client 11 | - port: 2380 12 | name: peer 13 | clusterIP: None 14 | selector: 15 | app: etcd 16 | --- 17 | apiVersion: v1 18 | kind: Service 19 | metadata: 20 | name: etcd-cluster 21 | labels: 22 | app: etcd 23 | spec: 24 | selector: 25 | app: etcd 26 | ports: 27 | - port: 2379 28 | protocol: TCP 29 | type: ClusterIP 30 | --- 31 | apiVersion: apps/v1 32 | kind: StatefulSet 33 | metadata: 34 | name: etcd 35 | labels: 36 | app: etcd 37 | spec: 38 | serviceName: "etcd" 39 | replicas: 3 40 | selector: 41 | matchLabels: 42 | app: etcd 43 | template: 44 | metadata: 45 | labels: 46 | app: etcd 47 | spec: 48 | containers: 49 | - name: etcd 50 | image: quay.io/coreos/etcd:v3.3.10 51 | command: 52 | - "etcd" 53 | - "--name" 54 | - "$(MY_POD_NAME)" 55 | - "--listen-peer-urls" 56 | - "http://$(MY_IP):2380" 57 | - "--listen-client-urls" 58 | - "http://$(MY_IP):2379,http://127.0.0.1:2379" 59 | - "--advertise-client-urls" 60 | - "http://$(MY_POD_NAME).etcd:2379" 61 | - "--initial-cluster-token" 62 | - "etcd-cluster-1" 63 | - "--initial-advertise-peer-urls" 64 | - "http://$(MY_POD_NAME).etcd:2380" 65 | - "--initial-cluster" 66 | - "etcd-0=http://etcd-0.etcd:2380,etcd-1=http://etcd-1.etcd:2380,etcd-2=http://etcd-2.etcd:2380" 67 | - "--initial-cluster-state" 68 | - "new" 69 | - "--data-dir" 70 | - "/var/lib/etcd" 71 | ports: 72 | - containerPort: 2379 73 | name: client 74 | - containerPort: 2380 75 | name: peer 76 | env: 77 | - name: MY_IP 78 | valueFrom: 79 | fieldRef: 80 | fieldPath: status.podIP 81 | - name: MY_POD_NAME 82 | valueFrom: 83 | fieldRef: 84 | fieldPath: metadata.name 85 | - name: ETCDCTL_API 86 | value: "3" 87 | -------------------------------------------------------------------------------- /example/etcd/etcd-kind.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: etcd 5 | labels: 6 | app: etcd 7 | spec: 8 | ports: 9 | - port: 2379 10 | name: client 11 | - port: 2380 12 | name: peer 13 | clusterIP: None 14 | selector: 15 | app: etcd 16 | --- 17 | apiVersion: v1 18 | kind: Service 19 | metadata: 20 | name: etcd-cluster 21 | labels: 22 | app: etcd 23 | spec: 24 | selector: 25 | app: etcd 26 | ports: 27 | - port: 2379 28 | protocol: TCP 29 | type: ClusterIP 30 | --- 31 | apiVersion: apps/v1 32 | kind: StatefulSet 33 | metadata: 34 | name: etcd 35 | labels: 36 | app: etcd 37 | spec: 38 | serviceName: "etcd" 39 | replicas: 3 40 | selector: 41 | matchLabels: 42 | app: etcd 43 | template: 44 | metadata: 45 | labels: 46 | app: etcd 47 | spec: 48 | containers: 49 | - name: etcd 50 | # 3.3.18 51 | image: gcr.io/etcd-development/etcd@sha256:e80582131febde2862a530660cb74c6b1cb2e1d2b443e6c563139cedc636f2e7 52 | imagePullPolicy: IfNotPresent 53 | command: 54 | - "etcd" 55 | - "--name" 56 | - "$(MY_POD_NAME)" 57 | - "--listen-peer-urls" 58 | - "http://$(MY_IP):2380" 59 | - "--listen-client-urls" 60 | - "http://$(MY_IP):2379,http://127.0.0.1:2379" 61 | - "--advertise-client-urls" 62 | - "http://$(MY_POD_NAME).etcd:2379" 63 | - "--initial-cluster-token" 64 | - "etcd-cluster-1" 65 | - "--initial-advertise-peer-urls" 66 | - "http://$(MY_POD_NAME).etcd:2380" 67 | - "--initial-cluster" 68 | - "etcd-0=http://etcd-0.etcd:2380,etcd-1=http://etcd-1.etcd:2380,etcd-2=http://etcd-2.etcd:2380" 69 | - "--initial-cluster-state" 70 | - "new" 71 | - "--data-dir" 72 | - "/var/lib/etcd" 73 | ports: 74 | - containerPort: 2379 75 | name: client 76 | - containerPort: 2380 77 | name: peer 78 | volumeMounts: 79 | - name: etcd-data 80 | mountPath: /var/lib/etcd 81 | env: 82 | - name: MY_IP 83 | valueFrom: 84 | fieldRef: 85 | fieldPath: status.podIP 86 | - name: MY_POD_NAME 87 | valueFrom: 88 | fieldRef: 89 | fieldPath: metadata.name 90 | - name: ETCDCTL_API 91 | value: "3" 92 | # Kind has a default storageclass. No need to set storageClassName. 93 | volumeClaimTemplates: 94 | - metadata: 95 | name: etcd-data 96 | spec: 97 | accessModes: 98 | - ReadWriteOnce 99 | resources: 100 | requests: 101 | storage: 4Gi 102 | limits: 103 | storage: 4Gi 104 | -------------------------------------------------------------------------------- /example/etcd/etcd-minikube.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: etcd 5 | labels: 6 | app: etcd 7 | spec: 8 | ports: 9 | - port: 2379 10 | name: client 11 | - port: 2380 12 | name: peer 13 | clusterIP: None 14 | selector: 15 | app: etcd 16 | --- 17 | apiVersion: v1 18 | kind: Service 19 | metadata: 20 | name: etcd-cluster 21 | labels: 22 | app: etcd 23 | spec: 24 | selector: 25 | app: etcd 26 | ports: 27 | - port: 2379 28 | protocol: TCP 29 | type: ClusterIP 30 | --- 31 | apiVersion: apps/v1 32 | kind: StatefulSet 33 | metadata: 34 | name: etcd 35 | labels: 36 | app: etcd 37 | spec: 38 | serviceName: "etcd" 39 | replicas: 3 40 | selector: 41 | matchLabels: 42 | app: etcd 43 | template: 44 | metadata: 45 | labels: 46 | app: etcd 47 | spec: 48 | containers: 49 | - name: etcd 50 | image: quay.io/coreos/etcd:v3.3.10 51 | command: 52 | - "etcd" 53 | - "--name" 54 | - "$(MY_POD_NAME)" 55 | - "--listen-peer-urls" 56 | - "http://$(MY_IP):2380" 57 | - "--listen-client-urls" 58 | - "http://$(MY_IP):2379,http://127.0.0.1:2379" 59 | - "--advertise-client-urls" 60 | - "http://$(MY_POD_NAME).etcd:2379" 61 | - "--initial-cluster-token" 62 | - "etcd-cluster-1" 63 | - "--initial-advertise-peer-urls" 64 | - "http://$(MY_POD_NAME).etcd:2380" 65 | - "--initial-cluster" 66 | - "etcd-0=http://etcd-0.etcd:2380,etcd-1=http://etcd-1.etcd:2380,etcd-2=http://etcd-2.etcd:2380" 67 | - "--initial-cluster-state" 68 | - "new" 69 | - "--data-dir" 70 | - "/var/lib/etcd" 71 | ports: 72 | - containerPort: 2379 73 | name: client 74 | - containerPort: 2380 75 | name: peer 76 | env: 77 | - name: MY_IP 78 | valueFrom: 79 | fieldRef: 80 | fieldPath: status.podIP 81 | - name: MY_POD_NAME 82 | valueFrom: 83 | fieldRef: 84 | fieldPath: metadata.name 85 | -------------------------------------------------------------------------------- /example/etcd/etcd-pd.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: etcd 5 | labels: 6 | app: etcd 7 | spec: 8 | ports: 9 | - port: 2379 10 | name: client 11 | - port: 2380 12 | name: peer 13 | clusterIP: None 14 | selector: 15 | app: etcd 16 | --- 17 | apiVersion: v1 18 | kind: Service 19 | metadata: 20 | name: etcd-cluster 21 | labels: 22 | app: etcd 23 | spec: 24 | selector: 25 | app: etcd 26 | ports: 27 | - port: 2379 28 | protocol: TCP 29 | type: ClusterIP 30 | --- 31 | apiVersion: apps/v1 32 | kind: StatefulSet 33 | metadata: 34 | name: etcd 35 | labels: 36 | app: etcd 37 | spec: 38 | serviceName: "etcd" 39 | replicas: 3 40 | selector: 41 | matchLabels: 42 | app: etcd 43 | template: 44 | metadata: 45 | labels: 46 | app: etcd 47 | spec: 48 | containers: 49 | - name: etcd 50 | # 3.3.18 51 | image: gcr.io/etcd-development/etcd@sha256:e80582131febde2862a530660cb74c6b1cb2e1d2b443e6c563139cedc636f2e7 52 | imagePullPolicy: IfNotPresent 53 | command: 54 | - "etcd" 55 | - "--name" 56 | - "$(MY_POD_NAME)" 57 | - "--listen-peer-urls" 58 | - "http://$(MY_IP):2380" 59 | - "--listen-client-urls" 60 | - "http://$(MY_IP):2379,http://127.0.0.1:2379" 61 | - "--advertise-client-urls" 62 | - "http://$(MY_POD_NAME).etcd:2379" 63 | - "--initial-cluster-token" 64 | - "etcd-cluster-1" 65 | - "--initial-advertise-peer-urls" 66 | - "http://$(MY_POD_NAME).etcd:2380" 67 | - "--initial-cluster" 68 | - "etcd-0=http://etcd-0.etcd:2380,etcd-1=http://etcd-1.etcd:2380,etcd-2=http://etcd-2.etcd:2380" 69 | - "--initial-cluster-state" 70 | - "new" 71 | - "--data-dir" 72 | - "/var/lib/etcd" 73 | ports: 74 | - containerPort: 2379 75 | name: client 76 | - containerPort: 2380 77 | name: peer 78 | volumeMounts: 79 | - name: etcd-data 80 | mountPath: /var/lib/etcd 81 | env: 82 | - name: MY_IP 83 | valueFrom: 84 | fieldRef: 85 | fieldPath: status.podIP 86 | - name: MY_POD_NAME 87 | valueFrom: 88 | fieldRef: 89 | fieldPath: metadata.name 90 | - name: ETCDCTL_API 91 | value: "3" 92 | volumeClaimTemplates: 93 | - metadata: 94 | name: etcd-data 95 | spec: 96 | storageClassName: fast 97 | accessModes: 98 | - ReadWriteOnce 99 | resources: 100 | requests: 101 | storage: 30Gi 102 | limits: 103 | storage: 30Gi 104 | -------------------------------------------------------------------------------- /example/m3db-cluster-per-zone-storageclass.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | kind: StorageClass 3 | apiVersion: storage.k8s.io/v1 4 | metadata: 5 | name: fast-east1-b 6 | provisioner: kubernetes.io/gce-pd 7 | parameters: 8 | type: pd-ssd 9 | zone: us-east1-b 10 | --- 11 | kind: StorageClass 12 | apiVersion: storage.k8s.io/v1 13 | metadata: 14 | name: fast-east1-c 15 | provisioner: kubernetes.io/gce-pd 16 | parameters: 17 | type: pd-ssd 18 | zone: us-east1-c 19 | --- 20 | kind: StorageClass 21 | apiVersion: storage.k8s.io/v1 22 | metadata: 23 | name: fast-east1-d 24 | provisioner: kubernetes.io/gce-pd 25 | parameters: 26 | type: pd-ssd 27 | zone: us-east1-d 28 | --- 29 | apiVersion: operator.m3db.io/v1alpha1 30 | kind: M3DBCluster 31 | metadata: 32 | name: m3db-cluster-pv 33 | spec: 34 | image: quay.io/m3db/m3dbnode:latest 35 | replicationFactor: 3 36 | numberOfShards: 1024 37 | isolationGroups: 38 | - name: zone-b 39 | numInstances: 1 40 | storageClassName: fast-east1-b 41 | nodeAffinityTerms: 42 | - key: failure-domain.beta.kubernetes.io/zone 43 | values: 44 | - us-east1-b 45 | - name: zone-c 46 | numInstances: 1 47 | storageClassName: fast-east1-c 48 | nodeAffinityTerms: 49 | - key: failure-domain.beta.kubernetes.io/zone 50 | values: 51 | - us-east1-c 52 | - name: zone-d 53 | numInstances: 1 54 | storageClassName: fast-east1-d 55 | nodeAffinityTerms: 56 | - key: failure-domain.beta.kubernetes.io/zone 57 | values: 58 | - us-east1-d 59 | etcdEndpoints: 60 | - http://etcd-0.etcd:2379 61 | - http://etcd-1.etcd:2379 62 | - http://etcd-2.etcd:2379 63 | namespaces: 64 | - name: metrics-10s:2d 65 | preset: 10s:2d 66 | podIdentityConfig: 67 | # Using no sources will default to just PodName, which is what we want as 68 | # remote PVs can move around with the pod 69 | sources: [] 70 | dataDirVolumeClaimTemplate: 71 | metadata: 72 | name: m3db-data 73 | spec: 74 | accessModes: 75 | - ReadWriteOnce 76 | # this field will be overwritten per-statefulset 77 | storageClassName: unused 78 | resources: 79 | requests: 80 | storage: 100Gi 81 | -------------------------------------------------------------------------------- /example/m3db-cluster.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: operator.m3db.io/v1alpha1 2 | kind: M3DBCluster 3 | metadata: 4 | name: m3db-cluster 5 | spec: 6 | image: quay.io/m3db/m3dbnode:latest 7 | replicationFactor: 3 8 | numberOfShards: 256 9 | isolationGroups: 10 | - name: group1 11 | numInstances: 1 12 | nodeAffinityTerms: 13 | - key: failure-domain.beta.kubernetes.io/zone 14 | values: 15 | - us-east1-b 16 | - name: group2 17 | numInstances: 1 18 | nodeAffinityTerms: 19 | - key: failure-domain.beta.kubernetes.io/zone 20 | values: 21 | - us-east1-c 22 | - name: group3 23 | numInstances: 1 24 | nodeAffinityTerms: 25 | - key: failure-domain.beta.kubernetes.io/zone 26 | values: 27 | - us-east1-d 28 | namespaces: 29 | - name: metrics-10s:2d 30 | preset: 10s:2d 31 | etcdEndpoints: 32 | - http://etcd-0.etcd:2379 33 | - http://etcd-1.etcd:2379 34 | - http://etcd-2.etcd:2379 35 | containerResources: 36 | requests: 37 | memory: 4Gi 38 | cpu: '1' 39 | limits: 40 | memory: 32Gi 41 | cpu: '8' 42 | -------------------------------------------------------------------------------- /example/m3db-kind.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: operator.m3db.io/v1alpha1 2 | kind: M3DBCluster 3 | metadata: 4 | name: m3db-cluster 5 | spec: 6 | image: quay.io/m3db/m3dbnode:latest 7 | replicationFactor: 3 8 | numberOfShards: 256 9 | isolationGroups: 10 | - name: group1 11 | numInstances: 1 12 | nodeAffinityTerms: 13 | - key: failure-domain.beta.kubernetes.io/zone 14 | values: 15 | - us-east1-b 16 | - name: group2 17 | numInstances: 1 18 | nodeAffinityTerms: 19 | - key: failure-domain.beta.kubernetes.io/zone 20 | values: 21 | - us-east1-c 22 | - name: group3 23 | numInstances: 1 24 | nodeAffinityTerms: 25 | - key: failure-domain.beta.kubernetes.io/zone 26 | values: 27 | - us-east1-d 28 | namespaces: 29 | - name: metrics-10s:2d 30 | preset: 10s:2d 31 | etcdEndpoints: 32 | - http://etcd-0.etcd:2379 33 | - http://etcd-1.etcd:2379 34 | - http://etcd-2.etcd:2379 35 | containerResources: 36 | requests: 37 | memory: 4Gi 38 | cpu: '1' 39 | limits: 40 | memory: 4Gi 41 | # Kind has a default storageclass. No need to set storageClassName. 42 | dataDirVolumeClaimTemplate: 43 | metadata: 44 | name: m3db-data 45 | spec: 46 | accessModes: 47 | - ReadWriteOnce 48 | resources: 49 | requests: 50 | storage: 30Gi 51 | -------------------------------------------------------------------------------- /example/m3db-local.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: operator.m3db.io/v1alpha1 2 | kind: M3DBCluster 3 | metadata: 4 | name: simple-cluster 5 | spec: 6 | image: quay.io/m3db/m3dbnode:latest 7 | replicationFactor: 3 8 | numberOfShards: 256 9 | etcdEndpoints: 10 | - http://etcd-0.etcd:2379 11 | - http://etcd-1.etcd:2379 12 | - http://etcd-2.etcd:2379 13 | isolationGroups: 14 | - name: group1 15 | numInstances: 1 16 | - name: group2 17 | numInstances: 1 18 | - name: group3 19 | numInstances: 1 20 | podIdentityConfig: 21 | sources: 22 | - PodUID 23 | namespaces: 24 | - name: metrics-10s:2d 25 | preset: 10s:2d 26 | -------------------------------------------------------------------------------- /example/prometheus-servicemonitor.yaml: -------------------------------------------------------------------------------- 1 | # ServiceMonitor to scrape metrics from all M3DB pods when using the prometheus 2 | # operator. 3 | apiVersion: monitoring.coreos.com/v1 4 | kind: ServiceMonitor 5 | metadata: 6 | labels: 7 | k8s-app: m3dbnode 8 | name: m3dbnode 9 | spec: 10 | endpoints: 11 | - bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token 12 | interval: 10s 13 | metricRelabelings: 14 | - sourceLabels: 15 | - pod 16 | targetLabel: instance 17 | port: debug 18 | relabelings: 19 | - sourceLabels: 20 | - __meta_kubernetes_service_label_operator_m3db_io_cluster 21 | targetLabel: cluster 22 | scrapeTimeout: 5s 23 | namespaceSelector: 24 | any: true 25 | selector: 26 | matchLabels: 27 | operator.m3db.io/app: m3db 28 | -------------------------------------------------------------------------------- /example/simple-cluster.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: operator.m3db.io/v1alpha1 2 | kind: M3DBCluster 3 | metadata: 4 | name: simple-cluster 5 | spec: 6 | image: quay.io/m3db/m3dbnode:latest 7 | replicationFactor: 3 8 | numberOfShards: 256 9 | etcdEndpoints: 10 | - http://etcd-0.etcd:2379 11 | - http://etcd-1.etcd:2379 12 | - http://etcd-2.etcd:2379 13 | isolationGroups: 14 | - name: group1 15 | numInstances: 1 16 | nodeAffinityTerms: 17 | - key: failure-domain.beta.kubernetes.io/zone 18 | values: 19 | - us-east1-b 20 | - name: group2 21 | numInstances: 1 22 | nodeAffinityTerms: 23 | - key: failure-domain.beta.kubernetes.io/zone 24 | values: 25 | - us-east1-c 26 | - name: group3 27 | numInstances: 1 28 | nodeAffinityTerms: 29 | - key: failure-domain.beta.kubernetes.io/zone 30 | values: 31 | - us-east1-d 32 | namespaces: 33 | - name: metrics-10s:2d 34 | preset: 10s:2d 35 | -------------------------------------------------------------------------------- /example/storage-fast-gcp.yaml: -------------------------------------------------------------------------------- 1 | kind: StorageClass 2 | apiVersion: storage.k8s.io/v1 3 | metadata: 4 | name: fast # for etcd cluster 5 | provisioner: kubernetes.io/gce-pd 6 | parameters: 7 | type: pd-ssd 8 | volumeBindingMode: WaitForFirstConsumer 9 | -------------------------------------------------------------------------------- /example/storage-fast-minikube.yaml: -------------------------------------------------------------------------------- 1 | kind: StorageClass 2 | apiVersion: storage.k8s.io/v1 3 | metadata: 4 | namespace: kube-system 5 | name: standard 6 | annotations: 7 | storageclass.beta.kubernetes.io/is-default-class: "true" 8 | labels: 9 | addonmanager.kubernetes.io/mode: Reconcile 10 | 11 | provisioner: k8s.io/minikube-hostpath 12 | --- 13 | apiVersion: v1 14 | kind: PersistentVolume 15 | metadata: 16 | name: minikube-pv 17 | spec: 18 | accessModes: 19 | - ReadWriteOnce 20 | capacity: 21 | storage: 10Gi 22 | hostPath: 23 | path: "/tmp/" 24 | -------------------------------------------------------------------------------- /example/storage-m3db-gcp.yaml: -------------------------------------------------------------------------------- 1 | kind: StorageClass 2 | apiVersion: storage.k8s.io/v1 3 | metadata: 4 | name: m3db-sc # for m3db cluster 5 | provisioner: kubernetes.io/gce-pd 6 | reclaimPolicy: Retain 7 | parameters: 8 | type: pd-ssd -------------------------------------------------------------------------------- /generated/mocks/generate.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2016 Uber Technologies, Inc. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | // mockgen rules for generating mocks using file mode 22 | //go:generate sh -c "mockgen -package=placement -destination=$GOPATH/src/$PACKAGE/pkg/m3admin/placement/client_mock.go -source=$GOPATH/src/$PACKAGE/pkg/m3admin/placement/types.go" 23 | //go:generate sh -c "mockgen -package=namespace -destination=$GOPATH/src/$PACKAGE/pkg/m3admin/namespace/client_mock.go -source=$GOPATH/src/$PACKAGE/pkg/m3admin/namespace/types.go" 24 | //go:generate sh -c "mockgen -package=topic -destination=$GOPATH/src/$PACKAGE/pkg/m3admin/topic/client_mock.go -source=$GOPATH/src/$PACKAGE/pkg/m3admin/topic/types.go" 25 | //go:generate sh -c "mockgen -package=m3admin -destination=$GOPATH/src/$PACKAGE/pkg/m3admin/client_mock.go -source=$GOPATH/src/$PACKAGE/pkg/m3admin/client.go" 26 | //go:generate sh -c "mockgen -package=m3db -destination=$GOPATH/src/$PACKAGE/pkg/k8sops/m3db/k8sops_mock.go -source=$GOPATH/src/$PACKAGE/pkg/k8sops/m3db/types.go" 27 | //go:generate sh -c "mockgen -package=podidentity -destination=$GOPATH/src/$PACKAGE/pkg/k8sops/podidentity/provider_mock.go -source=$GOPATH/src/$PACKAGE/pkg/k8sops/podidentity/provider.go" 28 | 29 | package mocks 30 | -------------------------------------------------------------------------------- /hack/custom-boilerplate.go.txt: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2019 Uber Technologies, Inc. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /hack/update-generated.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright 2017 The Kubernetes Authors. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | set -o errexit 18 | set -o nounset 19 | set -o pipefail 20 | 21 | SCRIPT_ROOT=$(dirname "${BASH_SOURCE[0]}")/.. 22 | CODEGEN_PKG=${CODEGEN_PKG:-$(cd "${SCRIPT_ROOT}"; ls -d -1 ./vendor/k8s.io/code-generator 2>/dev/null || echo ../code-generator)} 23 | GEN_GROUPS="${CODEGEN_PKG}/generate-groups.sh" 24 | 25 | chmod +x "$GEN_GROUPS" 26 | "$GEN_GROUPS" all\ 27 | github.com/m3db/m3db-operator/pkg/client \ 28 | github.com/m3db/m3db-operator/pkg/apis \ 29 | m3dboperator:v1alpha1 \ 30 | --go-header-file "${SCRIPT_ROOT}/hack/custom-boilerplate.go.txt" \ 31 | "$@" 32 | 33 | # Generate CRD spec and schema. 34 | controller-gen crd:generateEmbeddedObjectMeta=true paths=./pkg/apis/m3dboperator/v1alpha1/ +output:dir=helm/m3db-operator/templates 35 | 36 | # Ensure helm bundles the CRD first. 37 | ( 38 | cd helm/m3db-operator/templates 39 | mv operator.m3db.io_m3dbclusters.yaml 00_operator.m3db.io_m3dbclusters.yaml 40 | ) 41 | -------------------------------------------------------------------------------- /hack/verify-generated.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Copyright 2017 The Kubernetes Authors. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | set -o errexit 18 | set -o nounset 19 | set -o pipefail 20 | 21 | SCRIPT_ROOT=$(dirname "${BASH_SOURCE}")/.. 22 | 23 | DIFFROOT="${SCRIPT_ROOT}/pkg" 24 | TMP_DIFFROOT="${SCRIPT_ROOT}/_tmp/pkg" 25 | _tmp="${SCRIPT_ROOT}/_tmp" 26 | 27 | cleanup() { 28 | rm -rf "${_tmp}" 29 | } 30 | trap "cleanup" EXIT SIGINT 31 | 32 | cleanup 33 | 34 | mkdir -p "${TMP_DIFFROOT}" 35 | cp -a "${DIFFROOT}"/* "${TMP_DIFFROOT}" 36 | 37 | "${SCRIPT_ROOT}/hack/update-generated.sh" 38 | echo "diffing ${DIFFROOT} against freshly generated codegen" 39 | ret=0 40 | diff -Naupr "${DIFFROOT}" "${TMP_DIFFROOT}" || ret=$? 41 | cp -a "${TMP_DIFFROOT}"/* "${DIFFROOT}" 42 | if [[ $ret -eq 0 ]] 43 | then 44 | echo "${DIFFROOT} up to date." 45 | else 46 | echo "${DIFFROOT} is out of date. Please run hack/update-generated.sh" 47 | exit 1 48 | fi 49 | -------------------------------------------------------------------------------- /helm/m3db-operator/Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | name: m3db-operator 3 | version: 0.14.0 4 | # TODO(PS) - helm has issues with GKE's SemVer 5 | # Error: Chart requires kubernetesVersion: >=1.10.6 which is incompatible with Kubernetes v1.10.7-gke.2 6 | # 7 | #kubeVersion: ">=1.10.7" 8 | description: Kubernetes operator for M3DB timeseries database 9 | keywords: 10 | - operator 11 | - m3 12 | home: https://github.com/m3db/m3db-operator 13 | sources: 14 | - https://github.com/m3db/m3db-operator 15 | maintainers: 16 | - name: m3 Authors 17 | email: m3db@googlegroups.com 18 | url: https://operator.m3db.io/ 19 | engine: gotpl 20 | icon: https://raw.githubusercontent.com/m3db/m3/master/docs/theme/assets/images/M3-logo.png 21 | appVersion: ">0.4.7" 22 | tillerVersion: ">=2.11.0" 23 | -------------------------------------------------------------------------------- /helm/m3db-operator/NOTES.txt: -------------------------------------------------------------------------------- 1 | ___ _ _ 2 | / _ \ _ __ ___ _ __ __ _| |_ ___ _ __ | |__ __ _ ___ 3 | | | | | '_ \ / _ \ '__/ _` | __/ _ \| '__| | '_ \ / _` / __| 4 | | |_| | |_) | __/ | | (_| | || (_) | | | | | | (_| \__ \ 5 | \___/| .__/ \___|_| \__,_|\__\___/|_| |_| |_|\__,_|___/ 6 | |_| 7 | _ _ _ _ _ _ 8 | | |__ ___ ___ _ __ (_)_ __ ___| |_ __ _| | | ___ __| | 9 | | '_ \ / _ \/ _ \ '_ \ | | '_ \/ __| __/ _` | | |/ _ \/ _` | 10 | | |_) | __/ __/ | | | | | | | \__ \ || (_| | | | __/ (_| | 11 | |_.__/ \___|\___|_| |_| |_|_| |_|___/\__\__,_|_|_|\___|\__,_| 12 | 13 | -------------------------------------------------------------------------------- /helm/m3db-operator/README.md: -------------------------------------------------------------------------------- 1 | ### Helm Charts for M3DB clusters on Kubernetes 2 | 3 | ### Prerequisite 4 | 5 | [Install helm](https://docs.helm.sh/using_helm/#installing-helm) 6 | 7 | ### Installing m3db-operator chart 8 | 9 | ``` 10 | cd helm/m3db-operator 11 | helm package . 12 | helm install m3db-operator-0.0.1.tgz 13 | ``` 14 | 15 | -------------------------------------------------------------------------------- /helm/m3db-operator/templates/cluster_role.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRole 3 | metadata: 4 | name: {{ .Values.operator.name }} 5 | rules: 6 | - apiGroups: ["extensions"] 7 | resources: ["deployments", "replicasets", "daemonsets"] 8 | verbs: ["create", "get", "update", "delete", "list"] 9 | - apiGroups: ["storage.k8s.io"] 10 | resources: ["storageclasses"] 11 | verbs: ["get", "list", "create", "delete", "deletecollection"] 12 | - apiGroups: [""] 13 | resources: ["persistentvolumes", "persistentvolumeclaims", "services", "secrets", "configmaps"] 14 | verbs: ["create", "get", "update", "delete", "list"] 15 | - apiGroups: ["batch"] 16 | resources: ["cronjobs", "jobs"] 17 | verbs: ["create", "get", "deletecollection", "delete"] 18 | - apiGroups: [""] 19 | resources: ["pods"] 20 | verbs: ["list", "get", "watch", "update", "patch"] 21 | - apiGroups: ["apps"] 22 | resources: ["statefulsets", "deployments"] 23 | verbs: ["*"] 24 | - apiGroups: ["operator.m3db.io"] 25 | resources: ["*"] 26 | verbs: ["*"] 27 | - apiGroups: [""] 28 | resources: ["events"] 29 | verbs: ["create", "patch"] 30 | - apiGroups: [""] 31 | resources: ["nodes"] 32 | verbs: ["get", "list", "watch"] 33 | -------------------------------------------------------------------------------- /helm/m3db-operator/templates/cluster_role_binding.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRoleBinding 3 | metadata: 4 | name: {{ .Values.operator.name }} 5 | roleRef: 6 | apiGroup: rbac.authorization.k8s.io 7 | kind: ClusterRole 8 | name: {{ .Values.operator.name }} 9 | subjects: 10 | - kind: ServiceAccount 11 | name: {{ .Values.operator.name }} 12 | namespace: {{ .Release.Namespace }} 13 | -------------------------------------------------------------------------------- /helm/m3db-operator/templates/service_account.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ServiceAccount 3 | metadata: 4 | name: {{ .Values.operator.name }} 5 | namespace: {{ .Release.Namespace }} 6 | -------------------------------------------------------------------------------- /helm/m3db-operator/templates/stateful_set.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: StatefulSet 3 | metadata: 4 | name: {{ .Values.operator.name }} 5 | namespace: {{ .Release.Namespace }} 6 | spec: 7 | serviceName: {{ .Values.operator.name }} 8 | replicas: 1 9 | selector: 10 | matchLabels: 11 | name: {{ .Values.operator.name }} 12 | template: 13 | metadata: 14 | labels: 15 | name: {{ .Values.operator.name }} 16 | spec: 17 | securityContext: 18 | runAsNonRoot: true 19 | runAsUser: 65534 20 | runAsGroup: 65534 21 | containers: 22 | - name: {{ .Values.operator.name }} 23 | image: {{ .Values.image.repository}}:{{ .Values.image.tag }} 24 | command: 25 | - m3db-operator 26 | imagePullPolicy: Always 27 | env: 28 | - name: ENVIRONMENT 29 | value: {{ .Values.environment }} 30 | serviceAccount: {{ .Values.operator.name }} 31 | -------------------------------------------------------------------------------- /helm/m3db-operator/values.yaml: -------------------------------------------------------------------------------- 1 | operator: 2 | name: m3db-operator 3 | image: 4 | repository: quay.io/m3db/m3db-operator 5 | tag: v0.14.0 6 | environment: production 7 | -------------------------------------------------------------------------------- /integration/e2e/README.md: -------------------------------------------------------------------------------- 1 | # E2E Tests 2 | 3 | This directory contains the framework for testing the M3DB Operator against "real" Kubernetes clusters. It tests basic 4 | functionality as well as operator behavior under various failure scenarios. 5 | 6 | Design of this framework is influenced by CoreOS's excellent [etcd-operator](https://github.com/coreos/etcd-operator) 7 | and [prometheus-operator](https://github.com/coreos/prometheus-operator) e2e tests. 8 | 9 | ## WARNING! 10 | 11 | This test framework will attempt to only make modifications to namespaces it creates which start with the prefix 12 | `m3db-e2e-test`. It will attempt to clean those namespaces up at the end of test runs. 13 | 14 | **HOWEVER**, to test failure scenarios the framework may have to modify resources outside of its namespaces (such as 15 | persistent volumes). For this reason, it is not recommended to run this test suite against production clusters. In the 16 | future we will add config parameters to not modify objects outside of our namespaces, but it is still not recommended to 17 | run these tests against production clusters. 18 | 19 | Scripts are included for creating clusters on GKE which would be safe to test against in isolation. 20 | 21 | ## Running the tests 22 | 23 | **NOTE**: If you are running on a platform such as GKE you may need to grant your user the ability to create roles. From 24 | the [GKE 25 | docs](https://cloud.google.com/kubernetes-engine/docs/how-to/role-based-access-control#prerequisites_for_using_role-based_access_control): 26 | ``` 27 | kubectl create clusterrolebinding cluster-admin-binding \ 28 | --clusterrole cluster-admin --user $USER_ACCOUNT 29 | ``` 30 | 31 | It is generally a good idea to run the tests a clean go test cache, otherwise running the tests with the same test code 32 | may cause cached tests to run. The make target accomplishes this by running `go clean -testcache` first. 33 | 34 | ``` 35 | # With a working Kubernetes cluster and a correctly configured current kubectl context: 36 | $ make test-e2e 37 | --- test-e2e 38 | go test -v -tags integration ./integration/e2e 39 | 2018-11-22T15:36:41.370-0500 INFO setting up test suite 40 | 2018-11-22T15:36:44.206-0500 INFO creating namespace {"namespace": "m3db-e2e-test-1"} 41 | ... 42 | ``` 43 | -------------------------------------------------------------------------------- /integration/e2e/basic_test.go: -------------------------------------------------------------------------------- 1 | // +build integration 2 | 3 | // Copyright (c) 2018 Uber Technologies, Inc. 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE. 22 | 23 | package e2e 24 | 25 | import ( 26 | "context" 27 | "sort" 28 | "testing" 29 | "time" 30 | 31 | "github.com/m3db/m3db-operator/integration/harness" 32 | 33 | "k8s.io/apimachinery/pkg/util/wait" 34 | 35 | "github.com/stretchr/testify/assert" 36 | "github.com/stretchr/testify/require" 37 | "go.uber.org/zap" 38 | ) 39 | 40 | const ( 41 | placementCheckInterval = 5 * time.Second 42 | placementCheckTimeout = 5 * time.Minute 43 | ) 44 | 45 | func TestCreateCluster_Regional(t *testing.T) { 46 | h := harness.Global 47 | ctx := context.Background() 48 | 49 | cluster, err := h.CreateM3DBCluster(ctx, "cluster-regional.yaml") 50 | require.NoError(t, err) 51 | 52 | cl, err := h.NewPlacementClient(cluster) 53 | require.NoError(t, err) 54 | 55 | err = wait.Poll(placementCheckInterval, placementCheckTimeout, func() (bool, error) { 56 | pl, err := cl.Get() 57 | if err != nil { 58 | h.Logger.Warn("error fetching placement", zap.Error(err)) 59 | return false, nil 60 | } 61 | 62 | if pl.NumInstances() != 3 { 63 | h.Logger.Info("waiting for 3 instances to exist") 64 | return false, nil 65 | } 66 | 67 | isoGroups := []string{} 68 | for _, inst := range pl.Instances() { 69 | if !inst.IsAvailable() { 70 | h.Logger.Info("waiting for instance to be available", zap.String("instance", inst.ID())) 71 | return false, nil 72 | } 73 | isoGroups = append(isoGroups, inst.IsolationGroup()) 74 | } 75 | 76 | sort.Strings(isoGroups) 77 | assert.Equal(t, []string{"group1", "group2", "group3"}, isoGroups) 78 | 79 | return true, nil 80 | }) 81 | 82 | require.NoError(t, err) 83 | } 84 | 85 | func TestCreateCluster_Zonal(t *testing.T) { 86 | h := harness.Global 87 | ctx := context.Background() 88 | 89 | cluster, err := h.CreateM3DBCluster(ctx, "cluster-zonal.yaml") 90 | require.NoError(t, err) 91 | 92 | cl, err := h.NewPlacementClient(cluster) 93 | require.NoError(t, err) 94 | 95 | err = wait.Poll(placementCheckInterval, placementCheckTimeout, func() (bool, error) { 96 | pl, err := cl.Get() 97 | if err != nil { 98 | h.Logger.Warn("error fetching placement", zap.Error(err)) 99 | return false, nil 100 | } 101 | 102 | if pl.NumInstances() != 3 { 103 | h.Logger.Info("waiting for 3 instances to exist") 104 | return false, nil 105 | } 106 | 107 | isoGroups := []string{} 108 | for _, inst := range pl.Instances() { 109 | if !inst.IsAvailable() { 110 | h.Logger.Info("waiting for instance to be available", zap.String("instance", inst.ID())) 111 | return false, nil 112 | } 113 | isoGroups = append(isoGroups, inst.IsolationGroup()) 114 | } 115 | 116 | sort.Strings(isoGroups) 117 | assert.Equal(t, []string{"group1", "group2", "group3"}, isoGroups) 118 | 119 | return true, nil 120 | }) 121 | 122 | require.NoError(t, err) 123 | } 124 | -------------------------------------------------------------------------------- /integration/e2e/dummy.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018 Uber Technologies, Inc. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | package e2e 22 | 23 | // This file merely exists to have a non-build constraint excluded go file in 24 | // the integration tests. 25 | -------------------------------------------------------------------------------- /integration/e2e/main_test.go: -------------------------------------------------------------------------------- 1 | // +build integration 2 | 3 | // Copyright (c) 2018 Uber Technologies, Inc. 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE. 22 | 23 | package e2e 24 | 25 | import ( 26 | "testing" 27 | 28 | _ "k8s.io/client-go/plugin/pkg/client/auth/gcp" 29 | 30 | "github.com/m3db/m3db-operator/integration/harness" 31 | ) 32 | 33 | func TestMain(m *testing.M) { 34 | harness.RunSuite(m) 35 | } 36 | -------------------------------------------------------------------------------- /integration/harness/dummy.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018 Uber Technologies, Inc. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | package harness 22 | 23 | // This file merely exists to have a non-build constraint excluded go file in 24 | // the integration tests. 25 | -------------------------------------------------------------------------------- /integration/harness/m3admin.go: -------------------------------------------------------------------------------- 1 | // +build integration 2 | 3 | // Copyright (c) 2018 Uber Technologies, Inc. 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE. 22 | 23 | package harness 24 | 25 | import ( 26 | "fmt" 27 | 28 | myspec "github.com/m3db/m3db-operator/pkg/apis/m3dboperator/v1alpha1" 29 | "github.com/m3db/m3db-operator/pkg/k8sops" 30 | "github.com/m3db/m3db-operator/pkg/k8sops/m3db" 31 | "github.com/m3db/m3db-operator/pkg/m3admin" 32 | "github.com/m3db/m3db-operator/pkg/m3admin/placement" 33 | ) 34 | 35 | // NewPlacementClient constructs an m3admin placement client for the tests. 36 | func (h *Harness) NewPlacementClient(cluster *myspec.M3DBCluster) (placement.Client, error) { 37 | svc, err := m3db.GenerateCoordinatorService(cluster) 38 | if err != nil { 39 | return nil, err 40 | } 41 | 42 | env := k8sops.DefaultM3ClusterEnvironmentName(cluster) 43 | adminCl := m3admin.NewClient( 44 | m3admin.WithEnvironment(env), 45 | m3admin.WithZone(cluster.Spec.Zone), 46 | ) 47 | url := fmt.Sprintf(proxyBaseURLFmt, h.Namespace, svc.Name, "7201") 48 | h.Logger.Sugar().Infof("calling url '%s' with env '%s'", url, env) 49 | cl, err := placement.NewClient( 50 | placement.WithClient(adminCl), 51 | placement.WithURL(url), 52 | ) 53 | if err != nil { 54 | return nil, err 55 | } 56 | 57 | return cl, nil 58 | } 59 | -------------------------------------------------------------------------------- /integration/harness/m3dbcluster.go: -------------------------------------------------------------------------------- 1 | // +build integration 2 | 3 | // Copyright (c) 2018 Uber Technologies, Inc. 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE. 22 | 23 | package harness 24 | 25 | import ( 26 | "context" 27 | "os" 28 | "path/filepath" 29 | 30 | myspec "github.com/m3db/m3db-operator/pkg/apis/m3dboperator/v1alpha1" 31 | 32 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 33 | "k8s.io/apimachinery/pkg/util/yaml" 34 | 35 | "go.uber.org/zap" 36 | ) 37 | 38 | // CreateM3DBCluster creates an m3db cluster from a predefined manifest. 39 | func (h *Harness) CreateM3DBCluster(ctx context.Context, filename string) (*myspec.M3DBCluster, error) { 40 | path := filepath.Join("../manifests", filename) 41 | 42 | f, err := os.Open(path) 43 | if err != nil { 44 | return nil, err 45 | } 46 | 47 | reader := yaml.NewYAMLOrJSONDecoder(f, 2048) 48 | 49 | cluster := &myspec.M3DBCluster{} 50 | 51 | for _, iface := range []interface{}{ 52 | cluster, 53 | } { 54 | 55 | if err := reader.Decode(iface); err != nil { 56 | return nil, err 57 | } 58 | } 59 | 60 | h.Logger.Info("creating m3dbcluster", zap.String("m3dbcluster", cluster.Name)) 61 | cluster, err = h.CRDClient.OperatorV1alpha1().M3DBClusters(h.Namespace). 62 | Create(ctx, cluster, metav1.CreateOptions{}) 63 | if err != nil { 64 | return nil, err 65 | } 66 | 67 | return cluster, nil 68 | } 69 | -------------------------------------------------------------------------------- /integration/harness/operator.go: -------------------------------------------------------------------------------- 1 | // +build integration 2 | 3 | // Copyright (c) 2018 Uber Technologies, Inc. 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE. 22 | 23 | package harness 24 | 25 | import ( 26 | "context" 27 | "os" 28 | 29 | appsv1 "k8s.io/api/apps/v1" 30 | corev1 "k8s.io/api/core/v1" 31 | rbacv1 "k8s.io/api/rbac/v1" 32 | "k8s.io/apimachinery/pkg/api/errors" 33 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 34 | "k8s.io/apimachinery/pkg/util/yaml" 35 | 36 | "go.uber.org/zap" 37 | ) 38 | 39 | func (h *Harness) installOperator(ctx context.Context) error { 40 | f, err := os.Open("../manifests/operator.yaml") 41 | if err != nil { 42 | return err 43 | } 44 | 45 | reader := yaml.NewYAMLOrJSONDecoder(f, 2048) 46 | 47 | sa := &corev1.ServiceAccount{} 48 | role := &rbacv1.ClusterRole{} 49 | rb := &rbacv1.ClusterRoleBinding{} 50 | sts := &appsv1.StatefulSet{} 51 | 52 | for _, iface := range []interface{}{ 53 | sa, 54 | role, 55 | rb, 56 | sts, 57 | } { 58 | if err := reader.Decode(iface); err != nil { 59 | return err 60 | } 61 | } 62 | 63 | h.Logger.Info("creating serviceaccount", zap.String("serviceaccount", sa.Name)) 64 | if _, err := h.KubeClient.CoreV1().ServiceAccounts(h.Namespace). 65 | Create(ctx, sa, metav1.CreateOptions{}); err != nil { 66 | if !errors.IsAlreadyExists(err) { 67 | return err 68 | } 69 | h.Logger.Info("found existing serviceaccount") 70 | } 71 | 72 | rc := h.KubeClient.RbacV1() 73 | 74 | if !h.Flags.SkipCreateRBAC { 75 | h.Logger.Info("creating clusterrole", zap.String("role", role.Name)) 76 | if _, err := rc.ClusterRoles().Create(ctx, role, metav1.CreateOptions{}); err != nil { 77 | if !errors.IsAlreadyExists(err) { 78 | return err 79 | } 80 | h.Logger.Info("found existing clusterrole") 81 | } 82 | 83 | h.Logger.Info("creating rolebinding", zap.String("rolebinding", rb.Name)) 84 | if _, err := rc.ClusterRoleBindings().Create(ctx, rb, metav1.CreateOptions{}); err != nil { 85 | if !errors.IsAlreadyExists(err) { 86 | return err 87 | } 88 | h.Logger.Info("found existing clusterrolebinding") 89 | } 90 | } 91 | 92 | h.Logger.Info("creating statefulset", zap.String("statefulset", sts.Name)) 93 | _, err = h.KubeClient.AppsV1().StatefulSets(h.Namespace).Create(ctx, sts, metav1.CreateOptions{}) 94 | return err 95 | } 96 | -------------------------------------------------------------------------------- /integration/harness/run_suite.go: -------------------------------------------------------------------------------- 1 | // +build integration 2 | 3 | // Copyright (c) 2018 Uber Technologies, Inc. 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE. 22 | 23 | package harness 24 | 25 | import ( 26 | "context" 27 | "flag" 28 | "fmt" 29 | "os" 30 | "path/filepath" 31 | "testing" 32 | 33 | "go.uber.org/zap" 34 | "go.uber.org/zap/zapcore" 35 | ) 36 | 37 | func exitErr() { 38 | os.Exit(1) 39 | } 40 | 41 | func buildLogger(flags *Flags) *zap.Logger { 42 | cfg := zap.NewDevelopmentConfig() 43 | cfg.DisableCaller = true 44 | cfg.DisableStacktrace = true 45 | cfg.Level = zap.NewAtomicLevelAt(zapcore.InfoLevel) 46 | 47 | logger, err := cfg.Build() 48 | if err != nil { 49 | fmt.Fprintf(os.Stderr, "error building logger: %v", err) 50 | exitErr() 51 | } 52 | 53 | return logger 54 | } 55 | 56 | func homeKubeConfig() string { 57 | home := os.Getenv("HOME") 58 | if home == "" { 59 | fmt.Fprintf(os.Stderr, "$HOME cannot be empty if not setting kubeconfig path") 60 | exitErr() 61 | } 62 | 63 | return filepath.Join(home, ".kube", "config") 64 | } 65 | 66 | // Flags define parameters for the test. 67 | type Flags struct { 68 | KubeConfig string 69 | Verbose bool 70 | SkipCreateNamespace bool 71 | SkipDeleteNamespace bool 72 | SkipCreateRBAC bool 73 | SkipDeleteRBAC bool 74 | } 75 | 76 | // RunSuite runs the test suite. 77 | func RunSuite(m *testing.M) { 78 | flags := Flags{} 79 | flag.StringVar(&flags.KubeConfig, "kubeconfig", "", "Path to kubeconfig (default $HOME/.kube/config)") 80 | flag.BoolVar(&flags.Verbose, "debug", false, "enable debug logging") 81 | flag.BoolVar(&flags.SkipCreateNamespace, "skip-create-ns", false, "skip namespace creation") 82 | flag.BoolVar(&flags.SkipDeleteNamespace, "skip-delete-ns", false, "skip namespace deletion") 83 | flag.BoolVar(&flags.SkipCreateRBAC, "skip-create-rbac", false, "skip RBAC resource creation") 84 | flag.BoolVar(&flags.SkipDeleteRBAC, "skip-delete-rbac", false, "skip RBAC resource deletion") 85 | flag.Parse() 86 | 87 | if flags.KubeConfig == "" { 88 | flags.KubeConfig = homeKubeConfig() 89 | } 90 | 91 | logger := buildLogger(nil) 92 | logger.Info("setting up test suite") 93 | 94 | opts := &suiteOpts{ 95 | flags: flags, 96 | logger: logger, 97 | } 98 | 99 | harness, err := buildSuite(opts) 100 | if err != nil { 101 | logger.Fatal("error building suite", zap.Error(err)) 102 | } 103 | 104 | ctx := context.Background() 105 | if err := harness.setupSuite(ctx); err != nil { 106 | logger.Fatal("error setting up suite", zap.Error(err)) 107 | } 108 | 109 | Global = harness 110 | 111 | code := m.Run() 112 | 113 | if err := harness.teardownSuite(ctx); err != nil { 114 | logger.Fatal("error tearing down suite") 115 | } 116 | 117 | os.Exit(code) 118 | } 119 | -------------------------------------------------------------------------------- /integration/manifests/cluster-regional.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: operator.m3db.io/v1alpha1 2 | kind: M3DBCluster 3 | metadata: 4 | name: m3db-cluster-test-regional-1 5 | spec: 6 | image: quay.io/m3db/m3dbnode:master 7 | replicationFactor: 3 8 | numberOfShards: 256 9 | etcdEndpoints: 10 | - http://etcd-0.etcd:2379 11 | - http://etcd-1.etcd:2379 12 | - http://etcd-2.etcd:2379 13 | isolationGroups: 14 | - name: group1 15 | numInstances: 1 16 | nodeAffinityTerms: 17 | - key: failure-domain.beta.kubernetes.io/zone 18 | values: 19 | - us-east1-b 20 | - name: group2 21 | numInstances: 1 22 | nodeAffinityTerms: 23 | - key: failure-domain.beta.kubernetes.io/zone 24 | values: 25 | - us-east1-c 26 | - name: group3 27 | numInstances: 1 28 | nodeAffinityTerms: 29 | - key: failure-domain.beta.kubernetes.io/zone 30 | values: 31 | - us-east1-d 32 | namespaces: 33 | - name: metrics-10s:2d 34 | preset: 10s:2d 35 | -------------------------------------------------------------------------------- /integration/manifests/cluster-zonal.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: operator.m3db.io/v1alpha1 2 | kind: M3DBCluster 3 | metadata: 4 | name: m3db-cluster-test-zonal-1 5 | spec: 6 | image: quay.io/m3db/m3dbnode:latest 7 | replicationFactor: 3 8 | numberOfShards: 256 9 | etcdEndpoints: 10 | - http://etcd-0.etcd:2379 11 | - http://etcd-1.etcd:2379 12 | - http://etcd-2.etcd:2379 13 | isolationGroups: 14 | - name: group1 15 | numInstances: 1 16 | nodeAffinityTerms: 17 | - key: failure-domain.beta.kubernetes.io/zone 18 | values: 19 | - us-east1-b 20 | - name: group2 21 | numInstances: 1 22 | nodeAffinityTerms: 23 | - key: failure-domain.beta.kubernetes.io/zone 24 | values: 25 | - us-east1-b 26 | - name: group3 27 | numInstances: 1 28 | nodeAffinityTerms: 29 | - key: failure-domain.beta.kubernetes.io/zone 30 | values: 31 | - us-east1-b 32 | namespaces: 33 | - name: metrics-10s:2d 34 | preset: 10s:2d 35 | -------------------------------------------------------------------------------- /integration/manifests/etcd.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: etcd 5 | labels: 6 | app: etcd 7 | spec: 8 | ports: 9 | - port: 2379 10 | name: client 11 | - port: 2380 12 | name: peer 13 | clusterIP: None 14 | selector: 15 | app: etcd 16 | --- 17 | apiVersion: v1 18 | kind: Service 19 | metadata: 20 | name: etcd-cluster 21 | labels: 22 | app: etcd 23 | spec: 24 | selector: 25 | app: etcd 26 | ports: 27 | - port: 2379 28 | protocol: TCP 29 | type: ClusterIP 30 | --- 31 | apiVersion: apps/v1 32 | kind: StatefulSet 33 | metadata: 34 | name: etcd 35 | labels: 36 | app: etcd 37 | spec: 38 | serviceName: "etcd" 39 | replicas: 3 40 | selector: 41 | matchLabels: 42 | app: etcd 43 | template: 44 | metadata: 45 | labels: 46 | app: etcd 47 | spec: 48 | containers: 49 | - name: etcd 50 | # 3.3.18 51 | image: gcr.io/etcd-development/etcd@sha256:e80582131febde2862a530660cb74c6b1cb2e1d2b443e6c563139cedc636f2e7 52 | imagePullPolicy: IfNotPresent 53 | command: 54 | - "etcd" 55 | - "--name" 56 | - "$(MY_POD_NAME)" 57 | - "--listen-peer-urls" 58 | - "http://$(MY_IP):2380" 59 | - "--listen-client-urls" 60 | - "http://$(MY_IP):2379,http://127.0.0.1:2379" 61 | - "--advertise-client-urls" 62 | - "http://$(MY_POD_NAME).etcd:2379" 63 | - "--initial-cluster-token" 64 | - "etcd-cluster-1" 65 | - "--initial-advertise-peer-urls" 66 | - "http://$(MY_POD_NAME).etcd:2380" 67 | - "--initial-cluster" 68 | - "etcd-0=http://etcd-0.etcd:2380,etcd-1=http://etcd-1.etcd:2380,etcd-2=http://etcd-2.etcd:2380" 69 | - "--initial-cluster-state" 70 | - "new" 71 | - "--data-dir" 72 | - "/var/lib/etcd" 73 | ports: 74 | - containerPort: 2379 75 | name: client 76 | - containerPort: 2380 77 | name: peer 78 | volumeMounts: 79 | - name: etcd-data 80 | mountPath: /var/lib/etcd 81 | env: 82 | - name: MY_IP 83 | valueFrom: 84 | fieldRef: 85 | fieldPath: status.podIP 86 | - name: MY_POD_NAME 87 | valueFrom: 88 | fieldRef: 89 | fieldPath: metadata.name 90 | - name: ETCDCTL_API 91 | value: "3" 92 | # Kind has a default storageclass. No need to set storageClassName. 93 | volumeClaimTemplates: 94 | - metadata: 95 | name: etcd-data 96 | spec: 97 | accessModes: 98 | - ReadWriteOnce 99 | resources: 100 | requests: 101 | storage: 4Gi 102 | limits: 103 | storage: 4Gi 104 | -------------------------------------------------------------------------------- /integration/manifests/operator.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v1 3 | kind: ServiceAccount 4 | metadata: 5 | name: operator-test-sa 6 | --- 7 | apiVersion: rbac.authorization.k8s.io/v1beta1 8 | kind: ClusterRole 9 | metadata: 10 | name: operator-e2e-test 11 | rules: 12 | - apiGroups: ["extensions"] 13 | resources: ["deployments", "replicasets", "daemonsets"] 14 | verbs: ["create", "get", "update", "delete", "list"] 15 | - apiGroups: ["apiextensions.k8s.io"] 16 | resources: ["customresourcedefinitions"] 17 | verbs: ["create", "get", "update", "delete", "list"] 18 | - apiGroups: ["storage.k8s.io"] 19 | resources: ["storageclasses"] 20 | verbs: ["get", "list", "create", "delete", "deletecollection"] 21 | - apiGroups: [""] 22 | resources: ["persistentvolumes", "persistentvolumeclaims", "services", "secrets", "configmaps"] 23 | verbs: ["create", "get", "update", "delete", "list"] 24 | - apiGroups: ["batch"] 25 | resources: ["cronjobs", "jobs"] 26 | verbs: ["create", "get", "deletecollection", "delete"] 27 | - apiGroups: [""] 28 | resources: ["pods"] 29 | verbs: ["list", "get", "watch", "update", "patch"] 30 | - apiGroups: ["apps"] 31 | resources: ["statefulsets", "deployments"] 32 | verbs: ["*"] 33 | - apiGroups: ["operator.m3db.io"] 34 | resources: ["*"] 35 | verbs: ["*"] 36 | - apiGroups: [""] 37 | resources: ["events"] 38 | verbs: ["create", "patch"] 39 | - apiGroups: [""] 40 | resources: ["nodes"] 41 | verbs: ["get", "list", "watch"] 42 | --- 43 | apiVersion: rbac.authorization.k8s.io/v1beta1 44 | kind: ClusterRoleBinding 45 | metadata: 46 | name: operator-e2e-test 47 | roleRef: 48 | apiGroup: rbac.authorization.k8s.io 49 | kind: ClusterRole 50 | name: operator-e2e-test 51 | subjects: 52 | - kind: ServiceAccount 53 | name: operator-test-sa 54 | namespace: m3db-e2e-test-1 55 | --- 56 | apiVersion: apps/v1 57 | kind: StatefulSet 58 | metadata: 59 | name: m3db-operator 60 | spec: 61 | serviceName: m3db-operator 62 | replicas: 1 63 | selector: 64 | matchLabels: 65 | name: m3db-operator 66 | template: 67 | metadata: 68 | labels: 69 | name: m3db-operator 70 | spec: 71 | securityContext: 72 | runAsNonRoot: true 73 | runAsUser: 65534 74 | runAsGroup: 65534 75 | containers: 76 | - name: m3db-operator 77 | image: m3db-operator-kind 78 | imagePullPolicy: Never 79 | serviceAccount: operator-test-sa 80 | -------------------------------------------------------------------------------- /pkg/apis/m3dboperator/register.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018 Uber Technologies, Inc. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | package m3dboperator 22 | 23 | import ( 24 | "fmt" 25 | 26 | "k8s.io/apimachinery/pkg/runtime/schema" 27 | ) 28 | 29 | const ( 30 | // M3DBClusterResourceKind is the custom resource kind. 31 | M3DBClusterResourceKind = "M3DBCluster" 32 | 33 | // ResourcePlural and GroupName comprise the fully qualified DNS name 34 | // for the cluster. Naming must follow the convention stated below 35 | // 36 | // a DNS-1123 subdomain must consist of lower case alphanumeric characters, 37 | // '-' or '.', and must start and end with an alphanumeric character 38 | // (e.g. 'example.com', regex used for validation is 39 | // '[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*') 40 | 41 | // M3DBClusterResourcePlural is the plural form of custom resource kind. 42 | M3DBClusterResourcePlural = "m3dbclusters" 43 | 44 | // GroupName is the group that the custom resource belongs to. 45 | GroupName = "operator.m3db.io" 46 | 47 | // Version sets the version of the custom resource. 48 | Version = "v1alpha1" 49 | ) 50 | 51 | var ( 52 | // M3DBClustersName is the fully qualified name of the M3DBCluster CRD. 53 | M3DBClustersName = fmt.Sprintf("%s.%s", M3DBClusterResourcePlural, GroupName) 54 | 55 | // SchemeGroupVersion is the schema version of the group 56 | SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: Version} 57 | ) 58 | -------------------------------------------------------------------------------- /pkg/apis/m3dboperator/v1alpha1/doc.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018 Uber Technologies, Inc. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | // +k8s:deepcopy-gen=package,register 22 | 23 | // Package v1alpha1 is the v1alpha1 version of the API. 24 | // +groupName=operator.m3db.io 25 | package v1alpha1 26 | -------------------------------------------------------------------------------- /pkg/apis/m3dboperator/v1alpha1/pod_identity.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018 Uber Technologies, Inc. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | package v1alpha1 22 | 23 | // PodIdentitySource indicates a pre-defined source for deriving pod identity. 24 | type PodIdentitySource string 25 | 26 | const ( 27 | // PodIdentitySourcePodUID derives identity from UID of the pod. 28 | PodIdentitySourcePodUID PodIdentitySource = "PodUID" 29 | 30 | // PodIdentitySourceNodeSpecProviderID derives identity from the 'providerID' 31 | // spec field of the node. 32 | PodIdentitySourceNodeSpecProviderID PodIdentitySource = "NodeSpecProviderID" 33 | 34 | // PodIdentitySourceNodeName derives identity from the node's name. 35 | PodIdentitySourceNodeName PodIdentitySource = "NodeName" 36 | ) 37 | 38 | // PodIdentity contains all the fields that may be used to identify a pod's 39 | // identity in the M3DB placement. Any non-empty fields will be used to identity 40 | // uniqueness of a pod for the purpose of M3DB replace operations. 41 | type PodIdentity struct { 42 | Name string `json:"name,omitempty"` 43 | UID string `json:"uid,omitempty"` 44 | NodeName string `json:"nodeName,omitempty"` 45 | NodeExternalID string `json:"nodeExternalID,omitempty"` 46 | NodeProviderID string `json:"nodeProviderID,omitempty"` 47 | } 48 | 49 | // PodIdentityConfig contains cluster-level configuration for deriving pod 50 | // identity. 51 | type PodIdentityConfig struct { 52 | // Sources enumerates the sources from which to derive pod identity. Note that 53 | // a pod's name will always be used. If empty, defaults to pod name and 54 | // UID. 55 | Sources []PodIdentitySource `json:"sources"` 56 | } 57 | -------------------------------------------------------------------------------- /pkg/apis/m3dboperator/v1alpha1/register.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018 Uber Technologies, Inc. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | package v1alpha1 22 | 23 | import ( 24 | m3dboperator "github.com/m3db/m3db-operator/pkg/apis/m3dboperator" 25 | 26 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 27 | "k8s.io/apimachinery/pkg/runtime" 28 | "k8s.io/apimachinery/pkg/runtime/schema" 29 | ) 30 | 31 | // SchemeGroupVersion is group version used to register these objects 32 | var SchemeGroupVersion = schema.GroupVersion{Group: m3dboperator.GroupName, Version: m3dboperator.Version} 33 | 34 | // Resource takes an unqualified resource and returns a Group qualified GroupResource 35 | func Resource(resource string) schema.GroupResource { 36 | return SchemeGroupVersion.WithResource(resource).GroupResource() 37 | } 38 | 39 | // localSchemeBuilder and AddToScheme will stay in k8s.io/kubernetes. 40 | var ( 41 | // SchemeBuilder provides the schemebuilder 42 | SchemeBuilder runtime.SchemeBuilder 43 | 44 | // AddToScheme will provide the addtoscheme function 45 | AddToScheme = localSchemeBuilder.AddToScheme 46 | 47 | localSchemeBuilder = &SchemeBuilder 48 | ) 49 | 50 | func init() { 51 | // We only register manually written functions here. The registration of the 52 | // generated functions takes place in the generated files. The separation 53 | // makes the code compile even when the generated files are missing. 54 | localSchemeBuilder.Register(addKnownTypes) 55 | } 56 | 57 | // Adds the list of known types to api.Scheme. 58 | func addKnownTypes(scheme *runtime.Scheme) error { 59 | scheme.AddKnownTypes(SchemeGroupVersion, 60 | &M3DBCluster{}, 61 | &M3DBClusterList{}, 62 | ) 63 | metav1.AddToGroupVersion(scheme, SchemeGroupVersion) 64 | return nil 65 | } 66 | -------------------------------------------------------------------------------- /pkg/assets/assets_test.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2021 Uber Technologies, Inc. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | package assets 22 | 23 | import ( 24 | "io/ioutil" 25 | "testing" 26 | 27 | "github.com/rakyll/statik/fs" 28 | "github.com/stretchr/testify/require" 29 | ) 30 | 31 | func TestAssetsGenerated(t *testing.T) { 32 | hfs, err := fs.New() 33 | require.NoError(t, err) 34 | 35 | packaged, err := fs.ReadFile(hfs, "/default-config.tmpl") 36 | require.NoError(t, err) 37 | 38 | raw, err := ioutil.ReadFile("../../assets/default-config.tmpl") 39 | require.NoError(t, err) 40 | 41 | require.Equal(t, string(raw), string(packaged)) 42 | } 43 | -------------------------------------------------------------------------------- /pkg/assets/statik.go: -------------------------------------------------------------------------------- 1 | // Code generated by statik. DO NOT EDIT. 2 | 3 | // Copyright (c) 2019 Uber Technologies, Inc. 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE. 22 | package assets 23 | 24 | import ( 25 | "github.com/rakyll/statik/fs" 26 | ) 27 | 28 | func init() { 29 | data := "PK\x03\x04\x14\x00\x08\x00\x08\x00\x00\x00!(\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x13\x00 \x00default-config.tmplUT\x05\x00\x01\x80Cm8tQ\xdd\xaa\xdb0\x0c\xbe\xcfS\x88\xdc')\xeb\xc6\xc0w\xa3\xddEa\xef0\x1c[m\xb59r\x91U\x8f.\xe4\xdd\x0fN\x9a\x14\xce\xe1\xe0\x1bY\xfa\xf8~\xf8\xc6\xb1\x01:C{\xb0\xd2G>\xf1\x05\x93\xa2\xc04U.F\xf1\xc4V\xa3\x98\n\xc0\xcd\x802\x01\xd0\x13\xb6\xfc\x00\x02%E\xfe\xe1\xbd`J\x06\xea];?\xf3\xfd\xcb\xeek]\x15 \x0c \xdf\x93\xc28-7\xf6Pn\x95\xef\x0b\xe15&=\x1d\x17j\xc1\x14CF1p\xa6\x80\xf3\xaa\x0c\xab\xee\xcd\xea\xd5@\x87\xea\xbaa\xef\xfb\xee\x16}C\x1eYI\x1f\xdd:<\xb1J\x03\xc6\xbb\x1a\xf86T%N d]\x88\xfe )\x1e\"\xa79\x86{\xfc\xc2\x8c\xc1\xc0`\xffDY \x04\xad\xff\x08\xb9sR!\xa7\xbf7l\x05\xe0)\xb9\x98Q\x1e\x0b\xbb\x8b|\xa6\xcbj9\xa1dr[\x02\x00\xe4l\xa0\x1eGh\x7fr\x86i\xaa\xb7\xcb\xff\xc8h\x00\x87\x1e\xbdG\xbf\xadW\x06(\x91\xb7\xad\xb3\xee\x8aG\x12\x03]\xb6\xd2\x05\xea\xbba\xff7\xbfd\xd4\xf9C\xb8\x97\xd6\xd2K\xbc\xf9L\xa4\xf8\xf2\xb7H\xac\xc9\xcc%\x89\xe5\x0b\x16\x8f\xcfm)\xec\x05nJ\x82\x06\xda\xd9\xff\xda\xe94Uo\x01\x00\x00\xff\xffPK\x07\x08\x106\xc5\x92@\x01\x00\x00^\x02\x00\x00PK\x03\x04\x14\x00\x08\x00\x08\x00\x00\x00!(\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x13\x00 \x00default-config.yamlUT\x05\x00\x01\x80Cm8\x8c\x91\xc1N\xc30\x0c\x86\xef}\nk\xf7-c\x03M\xe4\x86\xb6\x0b\x12\xef0\xa5\xb1\xb7\x1a\xd2\xa4r\xdc\xa2\xf1\xf4(+\xed\x90\xd0$\xd4C\x9d?_~\xffN|J\x82\x1c\x9d&\xb1\x15\x80wR\xa7X*\x00\x8eg\xcaJ2\xae\x00\x02g\xa5\xf8\x82(\x94\xb3\x85\xc5zu\xfd\xecn\xb3~\\T\x15\xd6\x05lR\xd6\xd7\xc3xD(\xa70\x90X8q\xa0\xabT\x8a\xc9\xafs\xdaX0\xa4\xde\xb4[\xacM\x97p\xc9HQY/f*~X\xe5\x96R\xaf\x16\x9e\xda\xaa\xc4\x0cLQG\xa3Oa\xa5}\x8a\xf9\x1a\xcf_\xdeh\xa0`\xa1u\xefI&\x03!\x87\x7f\x91>f\x15\xf6z\x9c\xd9\n\x009\xfb4\x90\\Fw\x9f\xe2\x89\xcfS\xe4L2\xb0\x9f'\x00\xa08X@:\xb9>\xe8\x91\xe20o|\xa5H\x16\xa8\xad \x91p\x96'\x03(\x13\xcf\xaaw\xbe\xa1\x03\x8b\x05381\x81k\xd3n?nf\xa4\x1e\xf7\xa1/\x8f\x91o\xbd\x97\xf7\x9a\x94X\xd8%\x8e\xfa\x8b.|\xa3\xdaYSn\x1c\x97\xebU\xf9\xd9\xcdv\xf7|\x97y\xf8\x07\xb3\xb91\xdf\x01\x00\x00\xff\xffPK\x07\x08\xc9\xa5\xd5\x97$\x01\x00\x00L\x02\x00\x00PK\x01\x02\x14\x03\x14\x00\x08\x00\x08\x00\x00\x00!(\x106\xc5\x92@\x01\x00\x00^\x02\x00\x00\x13\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\x00\x00\x00\x00default-config.tmplUT\x05\x00\x01\x80Cm8PK\x01\x02\x14\x03\x14\x00\x08\x00\x08\x00\x00\x00!(\xc9\xa5\xd5\x97$\x01\x00\x00L\x02\x00\x00\x13\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\x8a\x01\x00\x00default-config.yamlUT\x05\x00\x01\x80Cm8PK\x05\x06\x00\x00\x00\x00\x02\x00\x02\x00\x94\x00\x00\x00\xf8\x02\x00\x00\x00\x00" 30 | fs.Register(data) 31 | } 32 | -------------------------------------------------------------------------------- /pkg/client/clientset/versioned/doc.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2019 Uber Technologies, Inc. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | // Code generated by client-gen. DO NOT EDIT. 22 | 23 | // This package has the automatically generated clientset. 24 | package versioned 25 | -------------------------------------------------------------------------------- /pkg/client/clientset/versioned/fake/clientset_generated.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2019 Uber Technologies, Inc. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | // Code generated by client-gen. DO NOT EDIT. 22 | 23 | package fake 24 | 25 | import ( 26 | clientset "github.com/m3db/m3db-operator/pkg/client/clientset/versioned" 27 | operatorv1alpha1 "github.com/m3db/m3db-operator/pkg/client/clientset/versioned/typed/m3dboperator/v1alpha1" 28 | fakeoperatorv1alpha1 "github.com/m3db/m3db-operator/pkg/client/clientset/versioned/typed/m3dboperator/v1alpha1/fake" 29 | "k8s.io/apimachinery/pkg/runtime" 30 | "k8s.io/apimachinery/pkg/watch" 31 | "k8s.io/client-go/discovery" 32 | fakediscovery "k8s.io/client-go/discovery/fake" 33 | "k8s.io/client-go/testing" 34 | ) 35 | 36 | // NewSimpleClientset returns a clientset that will respond with the provided objects. 37 | // It's backed by a very simple object tracker that processes creates, updates and deletions as-is, 38 | // without applying any validations and/or defaults. It shouldn't be considered a replacement 39 | // for a real clientset and is mostly useful in simple unit tests. 40 | func NewSimpleClientset(objects ...runtime.Object) *Clientset { 41 | o := testing.NewObjectTracker(scheme, codecs.UniversalDecoder()) 42 | for _, obj := range objects { 43 | if err := o.Add(obj); err != nil { 44 | panic(err) 45 | } 46 | } 47 | 48 | cs := &Clientset{tracker: o} 49 | cs.discovery = &fakediscovery.FakeDiscovery{Fake: &cs.Fake} 50 | cs.AddReactor("*", "*", testing.ObjectReaction(o)) 51 | cs.AddWatchReactor("*", func(action testing.Action) (handled bool, ret watch.Interface, err error) { 52 | gvr := action.GetResource() 53 | ns := action.GetNamespace() 54 | watch, err := o.Watch(gvr, ns) 55 | if err != nil { 56 | return false, nil, err 57 | } 58 | return true, watch, nil 59 | }) 60 | 61 | return cs 62 | } 63 | 64 | // Clientset implements clientset.Interface. Meant to be embedded into a 65 | // struct to get a default implementation. This makes faking out just the method 66 | // you want to test easier. 67 | type Clientset struct { 68 | testing.Fake 69 | discovery *fakediscovery.FakeDiscovery 70 | tracker testing.ObjectTracker 71 | } 72 | 73 | func (c *Clientset) Discovery() discovery.DiscoveryInterface { 74 | return c.discovery 75 | } 76 | 77 | func (c *Clientset) Tracker() testing.ObjectTracker { 78 | return c.tracker 79 | } 80 | 81 | var ( 82 | _ clientset.Interface = &Clientset{} 83 | _ testing.FakeClient = &Clientset{} 84 | ) 85 | 86 | // OperatorV1alpha1 retrieves the OperatorV1alpha1Client 87 | func (c *Clientset) OperatorV1alpha1() operatorv1alpha1.OperatorV1alpha1Interface { 88 | return &fakeoperatorv1alpha1.FakeOperatorV1alpha1{Fake: &c.Fake} 89 | } 90 | -------------------------------------------------------------------------------- /pkg/client/clientset/versioned/fake/doc.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2019 Uber Technologies, Inc. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | // Code generated by client-gen. DO NOT EDIT. 22 | 23 | // This package has the automatically generated fake clientset. 24 | package fake 25 | -------------------------------------------------------------------------------- /pkg/client/clientset/versioned/fake/register.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2019 Uber Technologies, Inc. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | // Code generated by client-gen. DO NOT EDIT. 22 | 23 | package fake 24 | 25 | import ( 26 | operatorv1alpha1 "github.com/m3db/m3db-operator/pkg/apis/m3dboperator/v1alpha1" 27 | v1 "k8s.io/apimachinery/pkg/apis/meta/v1" 28 | runtime "k8s.io/apimachinery/pkg/runtime" 29 | schema "k8s.io/apimachinery/pkg/runtime/schema" 30 | serializer "k8s.io/apimachinery/pkg/runtime/serializer" 31 | utilruntime "k8s.io/apimachinery/pkg/util/runtime" 32 | ) 33 | 34 | var scheme = runtime.NewScheme() 35 | var codecs = serializer.NewCodecFactory(scheme) 36 | 37 | var localSchemeBuilder = runtime.SchemeBuilder{ 38 | operatorv1alpha1.AddToScheme, 39 | } 40 | 41 | // AddToScheme adds all types of this clientset into the given scheme. This allows composition 42 | // of clientsets, like in: 43 | // 44 | // import ( 45 | // "k8s.io/client-go/kubernetes" 46 | // clientsetscheme "k8s.io/client-go/kubernetes/scheme" 47 | // aggregatorclientsetscheme "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme" 48 | // ) 49 | // 50 | // kclientset, _ := kubernetes.NewForConfig(c) 51 | // _ = aggregatorclientsetscheme.AddToScheme(clientsetscheme.Scheme) 52 | // 53 | // After this, RawExtensions in Kubernetes types will serialize kube-aggregator types 54 | // correctly. 55 | var AddToScheme = localSchemeBuilder.AddToScheme 56 | 57 | func init() { 58 | v1.AddToGroupVersion(scheme, schema.GroupVersion{Version: "v1"}) 59 | utilruntime.Must(AddToScheme(scheme)) 60 | } 61 | -------------------------------------------------------------------------------- /pkg/client/clientset/versioned/scheme/doc.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2019 Uber Technologies, Inc. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | // Code generated by client-gen. DO NOT EDIT. 22 | 23 | // This package contains the scheme of the automatically generated clientset. 24 | package scheme 25 | -------------------------------------------------------------------------------- /pkg/client/clientset/versioned/scheme/register.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2019 Uber Technologies, Inc. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | // Code generated by client-gen. DO NOT EDIT. 22 | 23 | package scheme 24 | 25 | import ( 26 | operatorv1alpha1 "github.com/m3db/m3db-operator/pkg/apis/m3dboperator/v1alpha1" 27 | v1 "k8s.io/apimachinery/pkg/apis/meta/v1" 28 | runtime "k8s.io/apimachinery/pkg/runtime" 29 | schema "k8s.io/apimachinery/pkg/runtime/schema" 30 | serializer "k8s.io/apimachinery/pkg/runtime/serializer" 31 | utilruntime "k8s.io/apimachinery/pkg/util/runtime" 32 | ) 33 | 34 | var Scheme = runtime.NewScheme() 35 | var Codecs = serializer.NewCodecFactory(Scheme) 36 | var ParameterCodec = runtime.NewParameterCodec(Scheme) 37 | var localSchemeBuilder = runtime.SchemeBuilder{ 38 | operatorv1alpha1.AddToScheme, 39 | } 40 | 41 | // AddToScheme adds all types of this clientset into the given scheme. This allows composition 42 | // of clientsets, like in: 43 | // 44 | // import ( 45 | // "k8s.io/client-go/kubernetes" 46 | // clientsetscheme "k8s.io/client-go/kubernetes/scheme" 47 | // aggregatorclientsetscheme "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme" 48 | // ) 49 | // 50 | // kclientset, _ := kubernetes.NewForConfig(c) 51 | // _ = aggregatorclientsetscheme.AddToScheme(clientsetscheme.Scheme) 52 | // 53 | // After this, RawExtensions in Kubernetes types will serialize kube-aggregator types 54 | // correctly. 55 | var AddToScheme = localSchemeBuilder.AddToScheme 56 | 57 | func init() { 58 | v1.AddToGroupVersion(Scheme, schema.GroupVersion{Version: "v1"}) 59 | utilruntime.Must(AddToScheme(Scheme)) 60 | } 61 | -------------------------------------------------------------------------------- /pkg/client/clientset/versioned/typed/m3dboperator/v1alpha1/doc.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2019 Uber Technologies, Inc. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | // Code generated by client-gen. DO NOT EDIT. 22 | 23 | // This package has the automatically generated typed clients. 24 | package v1alpha1 25 | -------------------------------------------------------------------------------- /pkg/client/clientset/versioned/typed/m3dboperator/v1alpha1/fake/doc.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2019 Uber Technologies, Inc. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | // Code generated by client-gen. DO NOT EDIT. 22 | 23 | // Package fake has the automatically generated clients. 24 | package fake 25 | -------------------------------------------------------------------------------- /pkg/client/clientset/versioned/typed/m3dboperator/v1alpha1/fake/fake_m3dboperator_client.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2019 Uber Technologies, Inc. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | // Code generated by client-gen. DO NOT EDIT. 22 | 23 | package fake 24 | 25 | import ( 26 | v1alpha1 "github.com/m3db/m3db-operator/pkg/client/clientset/versioned/typed/m3dboperator/v1alpha1" 27 | rest "k8s.io/client-go/rest" 28 | testing "k8s.io/client-go/testing" 29 | ) 30 | 31 | type FakeOperatorV1alpha1 struct { 32 | *testing.Fake 33 | } 34 | 35 | func (c *FakeOperatorV1alpha1) M3DBClusters(namespace string) v1alpha1.M3DBClusterInterface { 36 | return &FakeM3DBClusters{c, namespace} 37 | } 38 | 39 | // RESTClient returns a RESTClient that is used to communicate 40 | // with API server by this client implementation. 41 | func (c *FakeOperatorV1alpha1) RESTClient() rest.Interface { 42 | var ret *rest.RESTClient 43 | return ret 44 | } 45 | -------------------------------------------------------------------------------- /pkg/client/clientset/versioned/typed/m3dboperator/v1alpha1/generated_expansion.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2019 Uber Technologies, Inc. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | // Code generated by client-gen. DO NOT EDIT. 22 | 23 | package v1alpha1 24 | 25 | type M3DBClusterExpansion interface{} 26 | -------------------------------------------------------------------------------- /pkg/client/informers/externalversions/generic.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2019 Uber Technologies, Inc. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | // Code generated by informer-gen. DO NOT EDIT. 22 | 23 | package externalversions 24 | 25 | import ( 26 | "fmt" 27 | 28 | v1alpha1 "github.com/m3db/m3db-operator/pkg/apis/m3dboperator/v1alpha1" 29 | schema "k8s.io/apimachinery/pkg/runtime/schema" 30 | cache "k8s.io/client-go/tools/cache" 31 | ) 32 | 33 | // GenericInformer is type of SharedIndexInformer which will locate and delegate to other 34 | // sharedInformers based on type 35 | type GenericInformer interface { 36 | Informer() cache.SharedIndexInformer 37 | Lister() cache.GenericLister 38 | } 39 | 40 | type genericInformer struct { 41 | informer cache.SharedIndexInformer 42 | resource schema.GroupResource 43 | } 44 | 45 | // Informer returns the SharedIndexInformer. 46 | func (f *genericInformer) Informer() cache.SharedIndexInformer { 47 | return f.informer 48 | } 49 | 50 | // Lister returns the GenericLister. 51 | func (f *genericInformer) Lister() cache.GenericLister { 52 | return cache.NewGenericLister(f.Informer().GetIndexer(), f.resource) 53 | } 54 | 55 | // ForResource gives generic access to a shared informer of the matching type 56 | // TODO extend this to unknown resources with a client pool 57 | func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource) (GenericInformer, error) { 58 | switch resource { 59 | // Group=operator.m3db.io, Version=v1alpha1 60 | case v1alpha1.SchemeGroupVersion.WithResource("m3dbclusters"): 61 | return &genericInformer{resource: resource.GroupResource(), informer: f.Operator().V1alpha1().M3DBClusters().Informer()}, nil 62 | 63 | } 64 | 65 | return nil, fmt.Errorf("no informer found for %v", resource) 66 | } 67 | -------------------------------------------------------------------------------- /pkg/client/informers/externalversions/internalinterfaces/factory_interfaces.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2019 Uber Technologies, Inc. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | // Code generated by informer-gen. DO NOT EDIT. 22 | 23 | package internalinterfaces 24 | 25 | import ( 26 | time "time" 27 | 28 | versioned "github.com/m3db/m3db-operator/pkg/client/clientset/versioned" 29 | v1 "k8s.io/apimachinery/pkg/apis/meta/v1" 30 | runtime "k8s.io/apimachinery/pkg/runtime" 31 | cache "k8s.io/client-go/tools/cache" 32 | ) 33 | 34 | // NewInformerFunc takes versioned.Interface and time.Duration to return a SharedIndexInformer. 35 | type NewInformerFunc func(versioned.Interface, time.Duration) cache.SharedIndexInformer 36 | 37 | // SharedInformerFactory a small interface to allow for adding an informer without an import cycle 38 | type SharedInformerFactory interface { 39 | Start(stopCh <-chan struct{}) 40 | InformerFor(obj runtime.Object, newFunc NewInformerFunc) cache.SharedIndexInformer 41 | } 42 | 43 | // TweakListOptionsFunc is a function that transforms a v1.ListOptions. 44 | type TweakListOptionsFunc func(*v1.ListOptions) 45 | -------------------------------------------------------------------------------- /pkg/client/informers/externalversions/m3dboperator/interface.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2019 Uber Technologies, Inc. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | // Code generated by informer-gen. DO NOT EDIT. 22 | 23 | package m3dboperator 24 | 25 | import ( 26 | internalinterfaces "github.com/m3db/m3db-operator/pkg/client/informers/externalversions/internalinterfaces" 27 | v1alpha1 "github.com/m3db/m3db-operator/pkg/client/informers/externalversions/m3dboperator/v1alpha1" 28 | ) 29 | 30 | // Interface provides access to each of this group's versions. 31 | type Interface interface { 32 | // V1alpha1 provides access to shared informers for resources in V1alpha1. 33 | V1alpha1() v1alpha1.Interface 34 | } 35 | 36 | type group struct { 37 | factory internalinterfaces.SharedInformerFactory 38 | namespace string 39 | tweakListOptions internalinterfaces.TweakListOptionsFunc 40 | } 41 | 42 | // New returns a new Interface. 43 | func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface { 44 | return &group{factory: f, namespace: namespace, tweakListOptions: tweakListOptions} 45 | } 46 | 47 | // V1alpha1 returns a new v1alpha1.Interface. 48 | func (g *group) V1alpha1() v1alpha1.Interface { 49 | return v1alpha1.New(g.factory, g.namespace, g.tweakListOptions) 50 | } 51 | -------------------------------------------------------------------------------- /pkg/client/informers/externalversions/m3dboperator/v1alpha1/interface.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2019 Uber Technologies, Inc. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | // Code generated by informer-gen. DO NOT EDIT. 22 | 23 | package v1alpha1 24 | 25 | import ( 26 | internalinterfaces "github.com/m3db/m3db-operator/pkg/client/informers/externalversions/internalinterfaces" 27 | ) 28 | 29 | // Interface provides access to all the informers in this group version. 30 | type Interface interface { 31 | // M3DBClusters returns a M3DBClusterInformer. 32 | M3DBClusters() M3DBClusterInformer 33 | } 34 | 35 | type version struct { 36 | factory internalinterfaces.SharedInformerFactory 37 | namespace string 38 | tweakListOptions internalinterfaces.TweakListOptionsFunc 39 | } 40 | 41 | // New returns a new Interface. 42 | func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface { 43 | return &version{factory: f, namespace: namespace, tweakListOptions: tweakListOptions} 44 | } 45 | 46 | // M3DBClusters returns a M3DBClusterInformer. 47 | func (v *version) M3DBClusters() M3DBClusterInformer { 48 | return &m3DBClusterInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} 49 | } 50 | -------------------------------------------------------------------------------- /pkg/client/listers/m3dboperator/v1alpha1/expansion_generated.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2019 Uber Technologies, Inc. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | // Code generated by lister-gen. DO NOT EDIT. 22 | 23 | package v1alpha1 24 | 25 | // M3DBClusterListerExpansion allows custom methods to be added to 26 | // M3DBClusterLister. 27 | type M3DBClusterListerExpansion interface{} 28 | 29 | // M3DBClusterNamespaceListerExpansion allows custom methods to be added to 30 | // M3DBClusterNamespaceLister. 31 | type M3DBClusterNamespaceListerExpansion interface{} 32 | -------------------------------------------------------------------------------- /pkg/controller/fixtures/cluster-3-zones.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: operator.m3db.io/v1alpha1 3 | kind: M3DBCluster 4 | metadata: 5 | name: cluster-zones 6 | namespace: fake 7 | spec: 8 | image: foo/m3dbnode:latest 9 | replicationFactor: 3 10 | numberOfShards: 8 11 | isolationGroups: 12 | - name: us-fake1-a 13 | numInstances: 3 14 | nodeAffinityTerms: 15 | - key: failure-domain.beta.kubernetes.io/zone 16 | values: 17 | - us-fake1-a 18 | - name: us-fake1-b 19 | numInstances: 3 20 | nodeAffinityTerms: 21 | - key: failure-domain.beta.kubernetes.io/zone 22 | values: 23 | - us-fake1-b 24 | - name: us-fake1-c 25 | numInstances: 3 26 | nodeAffinityTerms: 27 | - key: failure-domain.beta.kubernetes.io/zone 28 | values: 29 | - us-fake1-c 30 | namespaces: 31 | - name: metrics-10s:2d 32 | preset: 10s:2d 33 | etcdEndpoints: 34 | - "a" 35 | - "b" 36 | containerResources: 37 | requests: 38 | memory: 1Gi 39 | cpu: '1' 40 | limits: 41 | memory: 2Gi 42 | cpu: '2' 43 | -------------------------------------------------------------------------------- /pkg/controller/fixtures/cluster-simple.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: operator.m3db.io/v1alpha1 3 | kind: M3DBCluster 4 | metadata: 5 | name: cluster-simple 6 | namespace: fake 7 | spec: 8 | image: fake.fake/fake/m3dbnode:latest 9 | replicationFactor: 3 10 | numberOfShards: 8 11 | isolationGroups: 12 | - name: group1 13 | numInstances: 1 14 | nodeAffinityTerms: 15 | - key: failure-domain.beta.kubernetes.io/zone 16 | values: 17 | - us-fake1-b 18 | - name: group2 19 | numInstances: 1 20 | nodeAffinityTerms: 21 | - key: failure-domain.beta.kubernetes.io/zone 22 | values: 23 | - us-fake1-c 24 | - name: group3 25 | numInstances: 1 26 | nodeAffinityTerms: 27 | - key: failure-domain.beta.kubernetes.io/zone 28 | values: 29 | - us-fake1-d 30 | namespaces: 31 | - name: metrics-10s:2d 32 | preset: 10s:2d 33 | etcdEndpoints: 34 | - "a" 35 | - "b" 36 | containerResources: 37 | requests: 38 | memory: 1Gi 39 | cpu: '1' 40 | limits: 41 | memory: 2Gi 42 | cpu: '2' 43 | -------------------------------------------------------------------------------- /pkg/controller/options_test.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018 Uber Technologies, Inc. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | package controller 22 | 23 | import ( 24 | "testing" 25 | 26 | clientsetfake "github.com/m3db/m3db-operator/pkg/client/clientset/versioned/fake" 27 | m3dbinformers "github.com/m3db/m3db-operator/pkg/client/informers/externalversions" 28 | "github.com/m3db/m3db-operator/pkg/k8sops/m3db" 29 | "github.com/m3db/m3db-operator/pkg/k8sops/podidentity" 30 | 31 | kubeinformers "k8s.io/client-go/informers" 32 | kubefake "k8s.io/client-go/kubernetes/fake" 33 | 34 | "github.com/golang/mock/gomock" 35 | "github.com/stretchr/testify/assert" 36 | "github.com/uber-go/tally" 37 | "go.uber.org/zap" 38 | ) 39 | 40 | func TestOptions(t *testing.T) { 41 | mc := gomock.NewController(t) 42 | defer mc.Finish() 43 | 44 | opts := &options{} 45 | 46 | kubeClient := kubefake.NewSimpleClientset() 47 | crdClient := clientsetfake.NewSimpleClientset() 48 | client := m3db.NewMockK8sops(mc) 49 | provider := podidentity.NewMockProvider(mc) 50 | for _, o := range []Option{ 51 | WithScope(tally.NoopScope), 52 | WithLogger(zap.NewNop()), 53 | WithKClient(client), 54 | WithCRDClient(crdClient), 55 | WithKubeClient(kubeClient), 56 | WithPodIdentityProvider(provider), 57 | WithKubeInformerFactory(kubeinformers.NewSharedInformerFactory(kubeClient, 0)), 58 | WithM3DBClusterInformerFactory(m3dbinformers.NewSharedInformerFactory(crdClient, 0)), 59 | } { 60 | assert.NotNil(t, o) 61 | o.execute(opts) 62 | } 63 | 64 | assert.NoError(t, opts.validate()) 65 | } 66 | -------------------------------------------------------------------------------- /pkg/controller/util_test.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018 Uber Technologies, Inc. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | package controller 22 | 23 | import ( 24 | "fmt" 25 | "os" 26 | "testing" 27 | 28 | myspec "github.com/m3db/m3db-operator/pkg/apis/m3dboperator/v1alpha1" 29 | clientsetFake "github.com/m3db/m3db-operator/pkg/client/clientset/versioned/fake" 30 | "github.com/m3db/m3db-operator/pkg/k8sops/m3db" 31 | 32 | kubeExtFake "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/fake" 33 | "k8s.io/apimachinery/pkg/util/yaml" 34 | kubeFake "k8s.io/client-go/kubernetes/fake" 35 | 36 | "github.com/stretchr/testify/require" 37 | "go.uber.org/zap" 38 | ) 39 | 40 | func getFixture(filename string, t *testing.T) *myspec.M3DBCluster { 41 | spec := &myspec.M3DBCluster{} 42 | file, err := os.Open(fmt.Sprintf("./fixtures/%s", filename)) 43 | if err != nil { 44 | t.Logf("Failed to read fixtures file: %v ", err) 45 | t.Fail() 46 | } 47 | err = yaml.NewYAMLOrJSONDecoder(file, 2048).Decode(spec) 48 | if err != nil { 49 | t.Logf("Unmarshal error: %v", err) 50 | t.Fail() 51 | } 52 | return spec 53 | } 54 | 55 | func newFakeK8sops(t *testing.T) m3db.K8sops { 56 | logger := zap.NewNop() 57 | kubeCli := kubeFake.NewSimpleClientset() 58 | kubeExt := kubeExtFake.NewSimpleClientset() 59 | crdCli := clientsetFake.NewSimpleClientset() 60 | k, err := m3db.New( 61 | m3db.WithCRDClient(crdCli), 62 | m3db.WithExtClient(kubeExt), 63 | m3db.WithKClient(kubeCli), 64 | m3db.WithLogger(logger), 65 | ) 66 | require.NoError(t, err) 67 | return k 68 | } 69 | -------------------------------------------------------------------------------- /pkg/k8sops/annotations/annotations.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2019 Uber Technologies, Inc. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | // Package annotations defines constants and helpers for annotations used 22 | // throughout the m3db operator. 23 | package annotations 24 | 25 | import ( 26 | myspec "github.com/m3db/m3db-operator/pkg/apis/m3dboperator/v1alpha1" 27 | "github.com/m3db/m3db-operator/pkg/k8sops/labels" 28 | ) 29 | 30 | const ( 31 | // App is the label used to identify the application. 32 | App = labels.App 33 | // AppM3DB is the value for "App" common to all operator-created clusters. 34 | AppM3DB = labels.AppM3DB 35 | // Cluster is the label identifying what m3db cluster an object is a part of. 36 | Cluster = labels.Cluster 37 | // Update is the annotation used by the operator to determine if a StatefulSet is 38 | // allowed to be updated. 39 | Update = "operator.m3db.io/update" 40 | // ParallelUpdate is the annotation used by the operator to determine if a StatefulSet 41 | // is allowed to be updated in parallel. 42 | ParallelUpdate = "operator.m3db.io/parallel-update" 43 | // ParallelUpdateInProgress is the annotation used by the operator indicate a parallel update 44 | // is underway. This annotation should only be used by the operator. 45 | ParallelUpdateInProgress = "operator.m3db.io/parallel-update-in-progress" 46 | // EnabledVal is the value that indicates an annotation is enabled. 47 | EnabledVal = "enabled" 48 | ) 49 | 50 | // BaseAnnotations returns the base annotations we apply to all objects 51 | // created by the operator for a given cluster. 52 | func BaseAnnotations(cluster *myspec.M3DBCluster) map[string]string { 53 | base := map[string]string{ 54 | App: AppM3DB, 55 | Cluster: cluster.Name, 56 | } 57 | if configured := cluster.Spec.Annotations; configured != nil { 58 | for k, v := range configured { 59 | base[k] = v 60 | } 61 | } 62 | 63 | return base 64 | } 65 | 66 | // PodAnnotations is for specifying annotations that are only to be 67 | // applied to the pods such as prometheus scrape tags 68 | func PodAnnotations(cluster *myspec.M3DBCluster) map[string]string { 69 | base := BaseAnnotations(cluster) 70 | for k := range cluster.Spec.PodMetadata.Annotations { 71 | // accept any user-specified annotations if its safe to do so 72 | if _, found := base[k]; !found { 73 | base[k] = cluster.Spec.PodMetadata.Annotations[k] 74 | } 75 | } 76 | 77 | return base 78 | } 79 | 80 | // Copy the provided annotations to a new map. 81 | func Copy(annotations map[string]string) map[string]string { 82 | m := make(map[string]string, len(annotations)) 83 | for k, v := range annotations { 84 | m[k] = v 85 | } 86 | return m 87 | } 88 | -------------------------------------------------------------------------------- /pkg/k8sops/annotations/annotations_test.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018 Uber Technologies, Inc. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | package annotations 22 | 23 | import ( 24 | "testing" 25 | 26 | myspec "github.com/m3db/m3db-operator/pkg/apis/m3dboperator/v1alpha1" 27 | 28 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 29 | 30 | "github.com/stretchr/testify/assert" 31 | ) 32 | 33 | func TestGenerateBaseAnnotations(t *testing.T) { 34 | cluster := &myspec.M3DBCluster{ 35 | ObjectMeta: metav1.ObjectMeta{ 36 | Name: "cluster-foo", 37 | }, 38 | } 39 | 40 | annotations := BaseAnnotations(cluster) 41 | expAnnotations := map[string]string{ 42 | "operator.m3db.io/app": "m3db", 43 | "operator.m3db.io/cluster": "cluster-foo", 44 | } 45 | 46 | assert.Equal(t, expAnnotations, annotations) 47 | 48 | cluster.Spec.Annotations = map[string]string{"foo": "bar"} 49 | annotations = BaseAnnotations(cluster) 50 | expAnnotations["foo"] = "bar" 51 | 52 | assert.Equal(t, expAnnotations, annotations) 53 | } 54 | 55 | func TestGeneratePodAnnotations(t *testing.T) { 56 | cluster := &myspec.M3DBCluster{ 57 | ObjectMeta: metav1.ObjectMeta{ 58 | Name: "cluster-foo", 59 | }, 60 | Spec: myspec.ClusterSpec{ 61 | PodMetadata: metav1.ObjectMeta{ 62 | Annotations: map[string]string{ 63 | "pod-annotation": "some-annotation", 64 | }, 65 | }, 66 | }, 67 | } 68 | 69 | annotations := PodAnnotations(cluster) 70 | expAnnotations := map[string]string{ 71 | "operator.m3db.io/app": "m3db", 72 | "operator.m3db.io/cluster": "cluster-foo", 73 | "pod-annotation": "some-annotation", 74 | } 75 | 76 | assert.Equal(t, expAnnotations, annotations) 77 | 78 | cluster.Spec.Annotations = map[string]string{"foo": "bar"} 79 | annotations = PodAnnotations(cluster) 80 | expAnnotations["foo"] = "bar" 81 | expAnnotations["pod-annotation"] = "some-annotation" 82 | 83 | assert.Equal(t, expAnnotations, annotations) 84 | } 85 | -------------------------------------------------------------------------------- /pkg/k8sops/k8sops.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020 Uber Technologies, Inc. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | package k8sops 22 | 23 | import ( 24 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 25 | ) 26 | 27 | // DefaultM3ClusterEnvironmentName returns the environment under which cluster 28 | // topology and runtime configuration will be stored. This ensures that multiple 29 | // m3db clusters won't conflict with each other when sharing a backing etcd 30 | // store. 31 | func DefaultM3ClusterEnvironmentName(obj metav1.ObjectMetaAccessor) string { 32 | m := obj.GetObjectMeta() 33 | return m.GetNamespace() + "/" + m.GetName() 34 | } 35 | -------------------------------------------------------------------------------- /pkg/k8sops/labels/labels.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018 Uber Technologies, Inc. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | // Package labels defines constants and helpers for labels used throughout the 22 | // m3db operator. 23 | package labels 24 | 25 | import ( 26 | myspec "github.com/m3db/m3db-operator/pkg/apis/m3dboperator/v1alpha1" 27 | ) 28 | 29 | const ( 30 | // App is the label used to identify the application. 31 | App = "operator.m3db.io/app" 32 | // AppM3DB is the value for "App" common to all operator-created clusters. 33 | AppM3DB = "m3db" 34 | // Cluster is the label identifying what m3db cluster an object is a part of. 35 | Cluster = "operator.m3db.io/cluster" 36 | // IsolationGroup identifies what isolation group an object is in. 37 | IsolationGroup = "operator.m3db.io/isolation-group" 38 | // StatefulSet identifies what StatefulSet an object belongs to. 39 | StatefulSet = "operator.m3db.io/stateful-set" 40 | // Component identifies what component of the M3 stack an object is part of. 41 | Component = "operator.m3db.io/component" 42 | // ComponentM3DBNode indicates a component is a dbnode. 43 | ComponentM3DBNode = "m3dbnode" 44 | // ComponentCoordinator indicates a component is a coordinator. 45 | ComponentCoordinator = "coordinator" 46 | // EtcdDeletionFinalizer is the finalizer used to delete cluster data stored 47 | // in etcd. 48 | EtcdDeletionFinalizer = "operator.m3db.io/etcd-deletion" 49 | ) 50 | 51 | // BaseLabels returns the base labels we apply to all objects created by the 52 | // operator for a given cluster. 53 | func BaseLabels(cluster *myspec.M3DBCluster) map[string]string { 54 | base := map[string]string{ 55 | App: AppM3DB, 56 | Cluster: cluster.Name, 57 | } 58 | 59 | for k, v := range cluster.Spec.Labels { 60 | base[k] = v 61 | } 62 | 63 | return base 64 | } 65 | -------------------------------------------------------------------------------- /pkg/k8sops/labels/labels_test.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018 Uber Technologies, Inc. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | package labels 22 | 23 | import ( 24 | "testing" 25 | 26 | myspec "github.com/m3db/m3db-operator/pkg/apis/m3dboperator/v1alpha1" 27 | 28 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 29 | 30 | "github.com/stretchr/testify/assert" 31 | ) 32 | 33 | func TestGenerateBaseLabels(t *testing.T) { 34 | cluster := &myspec.M3DBCluster{ 35 | ObjectMeta: metav1.ObjectMeta{ 36 | Name: "cluster-foo", 37 | }, 38 | } 39 | 40 | labels := BaseLabels(cluster) 41 | expLabels := map[string]string{ 42 | "operator.m3db.io/app": "m3db", 43 | "operator.m3db.io/cluster": "cluster-foo", 44 | } 45 | 46 | assert.Equal(t, expLabels, labels) 47 | 48 | cluster.Spec.Labels = map[string]string{"foo": "bar"} 49 | labels = BaseLabels(cluster) 50 | expLabels["foo"] = "bar" 51 | assert.Equal(t, expLabels, labels) 52 | } 53 | -------------------------------------------------------------------------------- /pkg/k8sops/m3db/common.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018 Uber Technologies, Inc. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | package m3db 22 | 23 | import ( 24 | "fmt" 25 | 26 | typedcorev1 "k8s.io/client-go/kubernetes/typed/core/v1" 27 | ) 28 | 29 | const ( 30 | headlessServicePrefix = "m3dbnode-" 31 | coordinatorServicePrefix = "m3coordinator-" 32 | ) 33 | 34 | // StatefulSetName provides a formatted string to use for naming StatefulSets 35 | func StatefulSetName(clusterName string, stsID int) string { 36 | return fmt.Sprintf("%s-rep%d", clusterName, stsID) 37 | } 38 | 39 | // HeadlessServiceName returns a name for the cluster's headless service. 40 | func HeadlessServiceName(clusterName string) string { 41 | return headlessServicePrefix + clusterName 42 | } 43 | 44 | // CoordinatorServiceName returns a name for a cluster's coordinator service. 45 | func CoordinatorServiceName(clusterName string) string { 46 | return coordinatorServicePrefix + clusterName 47 | } 48 | 49 | // TODO(schallert): should figure out a better way to abstract this other than 50 | // exposing all of CoreV1() 51 | func (k *k8sWrapper) Events(namespace string) typedcorev1.EventInterface { 52 | return k.kclient.CoreV1().Events(namespace) 53 | } 54 | -------------------------------------------------------------------------------- /pkg/k8sops/m3db/common_test.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018 Uber Technologies, Inc. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | package m3db 22 | 23 | import ( 24 | "testing" 25 | 26 | "github.com/stretchr/testify/require" 27 | ) 28 | 29 | func TestCommon(t *testing.T) { 30 | ssName := StatefulSetName("testCluster", 1) 31 | require.Equal(t, "testCluster-rep1", ssName) 32 | } 33 | -------------------------------------------------------------------------------- /pkg/k8sops/m3db/fixtures/testM3DBCluster.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: operator.m3db.io/v1alpha1 3 | kind: M3DBCluster 4 | metadata: 5 | name: m3db-cluster 6 | namespace: foo 7 | spec: 8 | image: fake.fake/fake/m3dbnode:latest 9 | replicationFactor: 3 10 | numberOfShards: 8 11 | enableCarbonIngester: true 12 | serviceAccountName: "m3db-account1" 13 | imagePullSecrets: 14 | - name: secret1 15 | isolationGroups: 16 | - name: us-fake1-a 17 | numInstances: 1 18 | nodeAffinityTerms: 19 | - key: zone 20 | values: 21 | - zone-a 22 | - name: us-fake1-b 23 | numInstances: 1 24 | nodeAffinityTerms: 25 | - key: zone 26 | values: 27 | - zone-a 28 | - name: us-fake1-c 29 | numInstances: 1 30 | nodeAffinityTerms: 31 | - key: zone 32 | values: 33 | - zone-a 34 | namespaces: 35 | - name: metrics-10s:2d 36 | preset: 10s:2d 37 | containerResources: 38 | requests: 39 | memory: 1Gi 40 | cpu: '1' 41 | limits: 42 | memory: 2Gi 43 | cpu: '2' 44 | podSecurityContext: 45 | fsGroup: 10 46 | securityContext: 47 | runAsUser: 20 48 | priorityClassName: m3db-priority 49 | etcdEndpoints: 50 | - ep0 51 | - ep1 52 | dataDirVolumeClaimTemplate: 53 | metadata: 54 | name: fake-data 55 | spec: 56 | accessModes: 57 | - ReadWriteOnce 58 | storageClassName: fake-sc 59 | resources: 60 | requests: 61 | storage: 1Gi 62 | limits: 63 | storage: 1Gi 64 | tolerations: 65 | - key: m3db-dedicated 66 | effect: NoSchedule 67 | operator: Exists 68 | -------------------------------------------------------------------------------- /pkg/k8sops/m3db/k8sops.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018 Uber Technologies, Inc. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | package m3db 22 | 23 | import ( 24 | genclient "github.com/m3db/m3db-operator/pkg/client/clientset/versioned" 25 | 26 | apiextensionsclient "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset" 27 | "k8s.io/client-go/kubernetes" 28 | 29 | "go.uber.org/zap" 30 | ) 31 | 32 | // Option provides an interface that can be used for setter options with the 33 | // constructor 34 | type Option interface { 35 | execute(*k8sWrapper) error 36 | } 37 | 38 | type optionFn func(k *k8sWrapper) error 39 | 40 | func (fn optionFn) execute(k *k8sWrapper) error { 41 | return fn(k) 42 | } 43 | 44 | // WithLogger is a setter to override the default logger 45 | func WithLogger(logger *zap.Logger) Option { 46 | return optionFn(func(k *k8sWrapper) error { 47 | k.logger = logger 48 | return nil 49 | }) 50 | } 51 | 52 | // WithCRDClient is a setter to override the default CRD client 53 | func WithCRDClient(crdClient genclient.Interface) Option { 54 | return optionFn(func(k *k8sWrapper) error { 55 | k.crdClient = crdClient 56 | return nil 57 | }) 58 | } 59 | 60 | // WithKClient is a setter to override the default Kubernetes client 61 | func WithKClient(kclient kubernetes.Interface) Option { 62 | return optionFn(func(k *k8sWrapper) error { 63 | k.kclient = kclient 64 | return nil 65 | }) 66 | } 67 | 68 | // WithExtClient is a setter to override the default Extensions Client 69 | func WithExtClient(extClient apiextensionsclient.Interface) Option { 70 | return optionFn(func(k *k8sWrapper) error { 71 | k.kubeExt = extClient 72 | return nil 73 | }) 74 | } 75 | 76 | // k8sWrapper encapsulates kubernetes API client dependencies. 77 | type k8sWrapper struct { 78 | crdClient genclient.Interface 79 | kclient kubernetes.Interface 80 | kubeExt apiextensionsclient.Interface 81 | logger *zap.Logger 82 | } 83 | 84 | // New creates a new instance of k8sops 85 | func New(opts ...Option) (K8sops, error) { 86 | k8 := &k8sWrapper{} 87 | for _, o := range opts { 88 | if err := o.execute(k8); err != nil { 89 | return nil, err 90 | } 91 | } 92 | 93 | return k8, nil 94 | } 95 | -------------------------------------------------------------------------------- /pkg/k8sops/m3db/k8sops_test.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018 Uber Technologies, Inc. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | package m3db 22 | 23 | import ( 24 | "fmt" 25 | "os" 26 | "testing" 27 | 28 | myspec "github.com/m3db/m3db-operator/pkg/apis/m3dboperator/v1alpha1" 29 | clientsetFake "github.com/m3db/m3db-operator/pkg/client/clientset/versioned/fake" 30 | 31 | appsv1 "k8s.io/api/apps/v1" 32 | kubeExtFake "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/fake" 33 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 34 | "k8s.io/apimachinery/pkg/util/yaml" 35 | kubeFake "k8s.io/client-go/kubernetes/fake" 36 | 37 | "github.com/stretchr/testify/require" 38 | "go.uber.org/zap" 39 | ) 40 | 41 | func newFakeK8sops(t *testing.T) K8sops { 42 | logger := zap.NewNop() 43 | kubeCli := kubeFake.NewSimpleClientset(&appsv1.StatefulSet{ 44 | ObjectMeta: metav1.ObjectMeta{ 45 | Namespace: "foo", 46 | Name: "m3db-cluster-rep0", 47 | }, 48 | }) 49 | kubeExt := kubeExtFake.NewSimpleClientset() 50 | crdCli := clientsetFake.NewSimpleClientset() 51 | k, err := New( 52 | WithCRDClient(crdCli), 53 | WithExtClient(kubeExt), 54 | WithKClient(kubeCli), 55 | WithLogger(logger), 56 | ) 57 | require.NoError(t, err) 58 | return k 59 | } 60 | 61 | func getFixture(filename string, t *testing.T) *myspec.M3DBCluster { 62 | spec := &myspec.M3DBCluster{} 63 | file, err := os.Open(fmt.Sprintf("./fixtures/%s", filename)) 64 | if err != nil { 65 | t.Logf("Failed to read fixtures file: %v ", err) 66 | t.Fail() 67 | } 68 | err = yaml.NewYAMLOrJSONDecoder(file, 2048).Decode(&spec) 69 | if err != nil { 70 | t.Logf("Unmarshal error: %v", err) 71 | t.Fail() 72 | } 73 | return spec 74 | } 75 | -------------------------------------------------------------------------------- /pkg/k8sops/m3db/placement.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018 Uber Technologies, Inc. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | package m3db 22 | 23 | import ( 24 | "fmt" 25 | "strings" 26 | "text/template" 27 | 28 | myspec "github.com/m3db/m3db-operator/pkg/apis/m3dboperator/v1alpha1" 29 | "github.com/m3db/m3db-operator/pkg/k8sops/labels" 30 | "github.com/m3db/m3db-operator/pkg/k8sops/podidentity" 31 | 32 | "github.com/m3db/m3/src/cluster/generated/proto/placementpb" 33 | 34 | corev1 "k8s.io/api/core/v1" 35 | 36 | pkgerrors "github.com/pkg/errors" 37 | ) 38 | 39 | const ( 40 | _zoneEmbedded = "embedded" 41 | defaultM3DBPort = 9000 42 | defaultNodeEndpointFormat = "{{ .PodName }}.{{ .M3DBService }}:{{ .Port }}" 43 | ) 44 | 45 | type endpointContext struct { 46 | PodName string 47 | M3DBService string 48 | PodNamespace string 49 | Port uint32 50 | } 51 | 52 | // PlacementInstanceFromPod creates a new m3cluster placement instance given a 53 | // pod spec. 54 | func PlacementInstanceFromPod(cluster *myspec.M3DBCluster, pod *corev1.Pod, idProvider podidentity.Provider) (*placementpb.Instance, error) { 55 | isoGroup, ok := pod.ObjectMeta.Labels[labels.IsolationGroup] 56 | if !ok { 57 | return nil, fmt.Errorf("could not find label %s in %v", labels.IsolationGroup, pod.ObjectMeta.Labels) 58 | } 59 | 60 | id, err := idProvider.Identity(pod, cluster) 61 | if err != nil { 62 | return nil, err 63 | } 64 | 65 | idStr, err := podidentity.IdentityJSON(id) 66 | if err != nil { 67 | return nil, err 68 | } 69 | 70 | epFmt := cluster.Spec.NodeEndpointFormat 71 | if epFmt == "" { 72 | epFmt = defaultNodeEndpointFormat 73 | } 74 | 75 | str := &strings.Builder{} 76 | epCtx := endpointContext{ 77 | PodName: pod.Name, 78 | PodNamespace: pod.Namespace, 79 | M3DBService: HeadlessServiceName(cluster.Name), 80 | Port: defaultM3DBPort, 81 | } 82 | 83 | tmpl, err := template.New("nodeEndpoint").Parse(epFmt) 84 | if err != nil { 85 | return nil, pkgerrors.WithMessage(err, "cannot construct node endpoint template") 86 | } 87 | if err := tmpl.Execute(str, epCtx); err != nil { 88 | return nil, pkgerrors.WithMessage(err, "cannot execute node endpoint template") 89 | } 90 | 91 | zone := cluster.Spec.Zone 92 | if zone == "" { 93 | zone = _zoneEmbedded 94 | } 95 | 96 | instance := &placementpb.Instance{ 97 | Id: idStr, 98 | IsolationGroup: isoGroup, 99 | Zone: zone, 100 | Weight: 100, 101 | Hostname: pod.Name + "." + epCtx.M3DBService, 102 | Endpoint: str.String(), 103 | Port: defaultM3DBPort, 104 | } 105 | 106 | return instance, nil 107 | } 108 | -------------------------------------------------------------------------------- /pkg/k8sops/m3db/ports.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018 Uber Technologies, Inc. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | package m3db 22 | 23 | // Port represents a port number. 24 | type Port int32 25 | 26 | // Ports used by M3DB nodes and coordinator nodes. 27 | const ( 28 | PortM3DBNodeClient Port = 9000 29 | PortM3DBNodeCluster = 9001 30 | PortM3DBHTTPNode = 9002 31 | PortM3DBHTTPCluster = 9003 32 | PortM3DBDebug = 9004 33 | 34 | PortM3Coordinator = 7201 35 | PortM3CoordinatorMetrics = 7203 36 | PortM3CoordinatorCarbon = 7204 37 | ) 38 | -------------------------------------------------------------------------------- /pkg/k8sops/m3db/services_test.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018 Uber Technologies, Inc. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | package m3db 22 | 23 | import ( 24 | "context" 25 | "testing" 26 | 27 | "github.com/stretchr/testify/require" 28 | ) 29 | 30 | func TestService(t *testing.T) { 31 | const svcName = "m3dbnode-m3db-cluster" 32 | fixture := getFixture("testM3DBCluster.yaml", t) 33 | svcCfg, err := GenerateM3DBService(fixture) 34 | require.NoError(t, err) 35 | k := newFakeK8sops(t) 36 | ctx := context.Background() 37 | svc, err := k.GetService(ctx, fixture, svcName) 38 | require.Nil(t, svc) 39 | require.NotNil(t, err) 40 | err = k.EnsureService(ctx, fixture, svcCfg) 41 | require.Nil(t, err) 42 | svc, err = k.GetService(ctx, fixture, svcName) 43 | require.NotNil(t, svc) 44 | require.Nil(t, err) 45 | err = k.EnsureService(ctx, fixture, svcCfg) 46 | require.Nil(t, err) 47 | err = k.DeleteService(ctx, fixture, svcName) 48 | require.Nil(t, err) 49 | err = k.DeleteService(ctx, fixture, svcName) 50 | require.NotNil(t, err) 51 | } 52 | -------------------------------------------------------------------------------- /pkg/k8sops/m3db/types.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018 Uber Technologies, Inc. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | package m3db 22 | 23 | import ( 24 | "context" 25 | 26 | myspec "github.com/m3db/m3db-operator/pkg/apis/m3dboperator/v1alpha1" 27 | 28 | v1 "k8s.io/api/core/v1" 29 | typedcorev1 "k8s.io/client-go/kubernetes/typed/core/v1" 30 | ) 31 | 32 | // K8sops provides an interface for various Kubernetes API calls 33 | type K8sops interface { 34 | // GetService simply gets a service by name 35 | GetService(ctx context.Context, cluster *myspec.M3DBCluster, name string) (*v1.Service, error) 36 | 37 | // DeleteService simply deletes a service by name 38 | DeleteService(ctx context.Context, cluster *myspec.M3DBCluster, name string) error 39 | 40 | // EnsureService will create a service by name if it doesn't exist 41 | EnsureService(ctx context.Context, cluster *myspec.M3DBCluster, svc *v1.Service) error 42 | 43 | // Events returns an Event interface for a given namespace. 44 | Events(namespace string) typedcorev1.EventInterface 45 | } 46 | -------------------------------------------------------------------------------- /pkg/k8sops/podidentity/options.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018 Uber Technologies, Inc. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | package podidentity 22 | 23 | import ( 24 | "errors" 25 | 26 | corelisters "k8s.io/client-go/listers/core/v1" 27 | 28 | "go.uber.org/zap" 29 | ) 30 | 31 | // Option configures a pod identity provider. 32 | type Option interface { 33 | execute(*options) 34 | } 35 | 36 | type options struct { 37 | logger *zap.Logger 38 | nodeLister corelisters.NodeLister 39 | } 40 | 41 | type optionFn func(o *options) 42 | 43 | func (fn optionFn) execute(o *options) { 44 | fn(o) 45 | } 46 | 47 | // WithLogger configures the provider's logger. 48 | func WithLogger(l *zap.Logger) Option { 49 | return optionFn(func(o *options) { 50 | o.logger = l 51 | }) 52 | } 53 | 54 | // WithNodeLister configures the node lister. 55 | func WithNodeLister(n corelisters.NodeLister) Option { 56 | return optionFn(func(o *options) { 57 | o.nodeLister = n 58 | }) 59 | } 60 | 61 | func (o *options) validate() error { 62 | switch { 63 | case o.nodeLister == nil: 64 | return errors.New("ID provider node informer cannot be empty") 65 | } 66 | return nil 67 | } 68 | -------------------------------------------------------------------------------- /pkg/k8sops/podidentity/options_test.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018 Uber Technologies, Inc. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | package podidentity 22 | 23 | import ( 24 | "testing" 25 | 26 | kubeinformers "k8s.io/client-go/informers" 27 | kubefake "k8s.io/client-go/kubernetes/fake" 28 | 29 | "github.com/stretchr/testify/assert" 30 | "go.uber.org/zap" 31 | ) 32 | 33 | func TestOptions(t *testing.T) { 34 | opts := &options{} 35 | 36 | assert.Error(t, opts.validate()) 37 | 38 | kubeInformer := kubeinformers.NewSharedInformerFactory(kubefake.NewSimpleClientset(), 0) 39 | nodeLister := kubeInformer.Core().V1().Nodes().Lister() 40 | 41 | logger := zap.NewNop() 42 | for _, o := range []Option{ 43 | WithLogger(logger), 44 | WithNodeLister(nodeLister), 45 | } { 46 | o.execute(opts) 47 | } 48 | 49 | assert.Equal(t, logger, opts.logger) 50 | assert.Equal(t, nodeLister, opts.nodeLister) 51 | err := opts.validate() 52 | assert.NoError(t, err) 53 | } 54 | -------------------------------------------------------------------------------- /pkg/k8sops/podidentity/provider_mock.go: -------------------------------------------------------------------------------- 1 | // Code generated by MockGen. DO NOT EDIT. 2 | // Source: github.com/m3db/m3db-operator/pkg/k8sops/podidentity/provider.go 3 | 4 | // Copyright (c) 2022 Uber Technologies, Inc. 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | 24 | // Package podidentity is a generated GoMock package. 25 | package podidentity 26 | 27 | import ( 28 | "reflect" 29 | 30 | "github.com/m3db/m3db-operator/pkg/apis/m3dboperator/v1alpha1" 31 | 32 | "github.com/golang/mock/gomock" 33 | "k8s.io/api/core/v1" 34 | ) 35 | 36 | // MockProvider is a mock of Provider interface. 37 | type MockProvider struct { 38 | ctrl *gomock.Controller 39 | recorder *MockProviderMockRecorder 40 | } 41 | 42 | // MockProviderMockRecorder is the mock recorder for MockProvider. 43 | type MockProviderMockRecorder struct { 44 | mock *MockProvider 45 | } 46 | 47 | // NewMockProvider creates a new mock instance. 48 | func NewMockProvider(ctrl *gomock.Controller) *MockProvider { 49 | mock := &MockProvider{ctrl: ctrl} 50 | mock.recorder = &MockProviderMockRecorder{mock} 51 | return mock 52 | } 53 | 54 | // EXPECT returns an object that allows the caller to indicate expected use. 55 | func (m *MockProvider) EXPECT() *MockProviderMockRecorder { 56 | return m.recorder 57 | } 58 | 59 | // Identity mocks base method. 60 | func (m *MockProvider) Identity(pod *v1.Pod, cluster *v1alpha1.M3DBCluster) (*v1alpha1.PodIdentity, error) { 61 | m.ctrl.T.Helper() 62 | ret := m.ctrl.Call(m, "Identity", pod, cluster) 63 | ret0, _ := ret[0].(*v1alpha1.PodIdentity) 64 | ret1, _ := ret[1].(error) 65 | return ret0, ret1 66 | } 67 | 68 | // Identity indicates an expected call of Identity. 69 | func (mr *MockProviderMockRecorder) Identity(pod, cluster interface{}) *gomock.Call { 70 | mr.mock.ctrl.T.Helper() 71 | return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Identity", reflect.TypeOf((*MockProvider)(nil).Identity), pod, cluster) 72 | } 73 | -------------------------------------------------------------------------------- /pkg/m3admin/client_mock.go: -------------------------------------------------------------------------------- 1 | // Code generated by MockGen. DO NOT EDIT. 2 | // Source: github.com/m3db/m3db-operator/pkg/m3admin/client.go 3 | 4 | // Copyright (c) 2022 Uber Technologies, Inc. 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE. 23 | 24 | // Package m3admin is a generated GoMock package. 25 | package m3admin 26 | 27 | import ( 28 | "bytes" 29 | "net/http" 30 | "reflect" 31 | 32 | "github.com/gogo/protobuf/proto" 33 | "github.com/golang/mock/gomock" 34 | ) 35 | 36 | // MockClient is a mock of Client interface. 37 | type MockClient struct { 38 | ctrl *gomock.Controller 39 | recorder *MockClientMockRecorder 40 | } 41 | 42 | // MockClientMockRecorder is the mock recorder for MockClient. 43 | type MockClientMockRecorder struct { 44 | mock *MockClient 45 | } 46 | 47 | // NewMockClient creates a new mock instance. 48 | func NewMockClient(ctrl *gomock.Controller) *MockClient { 49 | mock := &MockClient{ctrl: ctrl} 50 | mock.recorder = &MockClientMockRecorder{mock} 51 | return mock 52 | } 53 | 54 | // EXPECT returns an object that allows the caller to indicate expected use. 55 | func (m *MockClient) EXPECT() *MockClientMockRecorder { 56 | return m.recorder 57 | } 58 | 59 | // DoHTTPJSONPBRequest mocks base method. 60 | func (m *MockClient) DoHTTPJSONPBRequest(action, url string, request, response proto.Message, opts ...RequestOption) error { 61 | m.ctrl.T.Helper() 62 | varargs := []interface{}{action, url, request, response} 63 | for _, a := range opts { 64 | varargs = append(varargs, a) 65 | } 66 | ret := m.ctrl.Call(m, "DoHTTPJSONPBRequest", varargs...) 67 | ret0, _ := ret[0].(error) 68 | return ret0 69 | } 70 | 71 | // DoHTTPJSONPBRequest indicates an expected call of DoHTTPJSONPBRequest. 72 | func (mr *MockClientMockRecorder) DoHTTPJSONPBRequest(action, url, request, response interface{}, opts ...interface{}) *gomock.Call { 73 | mr.mock.ctrl.T.Helper() 74 | varargs := append([]interface{}{action, url, request, response}, opts...) 75 | return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DoHTTPJSONPBRequest", reflect.TypeOf((*MockClient)(nil).DoHTTPJSONPBRequest), varargs...) 76 | } 77 | 78 | // DoHTTPRequest mocks base method. 79 | func (m *MockClient) DoHTTPRequest(action, url string, data *bytes.Buffer, opts ...RequestOption) (*http.Response, error) { 80 | m.ctrl.T.Helper() 81 | varargs := []interface{}{action, url, data} 82 | for _, a := range opts { 83 | varargs = append(varargs, a) 84 | } 85 | ret := m.ctrl.Call(m, "DoHTTPRequest", varargs...) 86 | ret0, _ := ret[0].(*http.Response) 87 | ret1, _ := ret[1].(error) 88 | return ret0, ret1 89 | } 90 | 91 | // DoHTTPRequest indicates an expected call of DoHTTPRequest. 92 | func (mr *MockClientMockRecorder) DoHTTPRequest(action, url, data interface{}, opts ...interface{}) *gomock.Call { 93 | mr.mock.ctrl.T.Helper() 94 | varargs := append([]interface{}{action, url, data}, opts...) 95 | return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DoHTTPRequest", reflect.TypeOf((*MockClient)(nil).DoHTTPRequest), varargs...) 96 | } 97 | -------------------------------------------------------------------------------- /pkg/m3admin/health/types.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018 Uber Technologies, Inc. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | package health 22 | 23 | // Client provides the interface for checking cluster health. 24 | type Client interface { 25 | // Bootstrapped returns true or false depending on the/ bootstrapped state 26 | // of the provided dbnode. 27 | Bootstrapped(namespace string, podName string) (bool, error) 28 | } 29 | -------------------------------------------------------------------------------- /pkg/m3admin/jsonpb.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2019 Uber Technologies, Inc. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | package m3admin 22 | 23 | import ( 24 | "io" 25 | 26 | "github.com/gogo/protobuf/jsonpb" 27 | "github.com/gogo/protobuf/proto" 28 | ) 29 | 30 | // JSONPBUnmarshal unmarshals a JSON protobuf message, allowing 31 | // for backwards compatible changes by allowing unknown fields to 32 | // exist when unmarshalling response (new fields will get added 33 | // and need to be able to be unmarshalled by an old operator 34 | // calling endpoints on a new coordinator or DB node). 35 | func JSONPBUnmarshal(r io.Reader, msg proto.Message) error { 36 | unmarshaller := &jsonpb.Unmarshaler{AllowUnknownFields: true} 37 | return unmarshaller.Unmarshal(r, msg) 38 | } 39 | 40 | // JSONPBMarshal marshals a JSON protobuf message, just using 41 | // defaults for the marshaller currently. 42 | func JSONPBMarshal(w io.Writer, msg proto.Message) error { 43 | marshaller := &jsonpb.Marshaler{} 44 | return marshaller.Marshal(w, msg) 45 | } 46 | -------------------------------------------------------------------------------- /pkg/m3admin/m3admin_test.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2016 Uber Technologies, Inc. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | package m3admin 22 | -------------------------------------------------------------------------------- /pkg/m3admin/namespace/fixtures/success.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /pkg/m3admin/namespace/types.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018 Uber Technologies, Inc. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | package namespace 22 | 23 | import ( 24 | "github.com/m3db/m3/src/query/generated/proto/admin" 25 | ) 26 | 27 | // Client provides the interface to interact with the namespace API 28 | type Client interface { 29 | // Create will create a namepace for the given request. 30 | Create(request *admin.NamespaceAddRequest) error 31 | // List will retrieve all namespaces in the current cluster. The registry in 32 | // the namespace response is guaranteed to be non-nil if err == nil. 33 | List() (*admin.NamespaceGetResponse, error) 34 | // Delete will delete a namespace given a name 35 | Delete(namespace string) error 36 | // Ready will attempt to mark a namespace as ready. 37 | Ready(request *admin.NamespaceReadyRequest) error 38 | } 39 | -------------------------------------------------------------------------------- /pkg/m3admin/options.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018 Uber Technologies, Inc. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | package m3admin 22 | 23 | import ( 24 | retryhttp "github.com/hashicorp/go-retryablehttp" 25 | "go.uber.org/zap" 26 | ) 27 | 28 | // Option configures an m3admin client. 29 | type Option interface { 30 | execute(*options) 31 | } 32 | 33 | type optionFn func(o *options) 34 | 35 | func (f optionFn) execute(o *options) { 36 | f(o) 37 | } 38 | 39 | type options struct { 40 | logger *zap.Logger 41 | client *retryhttp.Client 42 | environment string 43 | zone string 44 | } 45 | 46 | // WithLogger configures a logger for the client. If not set a noop logger will 47 | // be used. 48 | func WithLogger(l *zap.Logger) Option { 49 | return optionFn(func(o *options) { 50 | o.logger = l 51 | }) 52 | } 53 | 54 | // WithHTTPClient configures an http client for the m3admin client. If not set, 55 | // go-retryablehttp's default client will be used. Note that the retry client's 56 | // logger will be overridden with the stdlog-wrapped wrapped zap logger. 57 | func WithHTTPClient(cl *retryhttp.Client) Option { 58 | return optionFn(func(o *options) { 59 | o.client = cl 60 | }) 61 | } 62 | 63 | // WithEnvironment controls the Cluster-Environment-Name header to 64 | // m3coordinator. 65 | func WithEnvironment(e string) Option { 66 | return optionFn(func(o *options) { 67 | o.environment = e 68 | }) 69 | } 70 | 71 | // WithZone controls the Cluster-Zone-Name header to m3coordinator. 72 | func WithZone(z string) Option { 73 | return optionFn(func(o *options) { 74 | o.zone = z 75 | }) 76 | } 77 | 78 | // RequestOption defines a per-request option. 79 | type RequestOption interface { 80 | execute(*reqOptions) 81 | } 82 | 83 | type reqOptionFn func(o *reqOptions) 84 | 85 | func (f reqOptionFn) execute(o *reqOptions) { 86 | f(o) 87 | } 88 | 89 | type reqOptions struct { 90 | headers map[string]string 91 | } 92 | 93 | // WithHeader adds a header to a request. It can be specified multiple times. 94 | func WithHeader(name, value string) RequestOption { 95 | return reqOptionFn(func(o *reqOptions) { 96 | if o.headers == nil { 97 | o.headers = make(map[string]string) 98 | } 99 | o.headers[name] = value 100 | }) 101 | } 102 | -------------------------------------------------------------------------------- /pkg/m3admin/placement/options.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018 Uber Technologies, Inc. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | package placement 22 | 23 | import ( 24 | "net/url" 25 | 26 | "github.com/m3db/m3db-operator/pkg/m3admin" 27 | 28 | "go.uber.org/zap" 29 | ) 30 | 31 | // Option provides an interface that can be used for setter options with the 32 | // constructor 33 | type Option interface { 34 | execute(*placementClient) error 35 | } 36 | 37 | type optionFn func(p *placementClient) error 38 | 39 | func (fn optionFn) execute(p *placementClient) error { 40 | return fn(p) 41 | } 42 | 43 | // WithURL is a setter to override the default URL 44 | func WithURL(u string) Option { 45 | return optionFn(func(p *placementClient) error { 46 | if _, err := url.ParseRequestURI(u); err != nil { 47 | return err 48 | } 49 | p.url = u 50 | return nil 51 | }) 52 | } 53 | 54 | // WithLogger is a setter to override the default logger 55 | func WithLogger(logger *zap.Logger) Option { 56 | return optionFn(func(p *placementClient) error { 57 | p.logger = logger 58 | return nil 59 | }) 60 | } 61 | 62 | // WithClient configures an m3admin client. 63 | func WithClient(cl m3admin.Client) Option { 64 | return optionFn(func(p *placementClient) error { 65 | p.client = cl 66 | return nil 67 | }) 68 | } 69 | -------------------------------------------------------------------------------- /pkg/m3admin/placement/options_test.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018 Uber Technologies, Inc. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | package placement 22 | 23 | import ( 24 | "testing" 25 | 26 | "github.com/m3db/m3db-operator/pkg/m3admin" 27 | 28 | "github.com/stretchr/testify/assert" 29 | "go.uber.org/zap" 30 | ) 31 | 32 | func TestOptions(t *testing.T) { 33 | client := &placementClient{} 34 | 35 | opt := WithURL("...") 36 | assert.Error(t, opt.execute(client)) 37 | 38 | const url = "http://localhost:1234" 39 | l := zap.NewNop() 40 | m3cl := m3admin.NewClient() 41 | opts := []Option{ 42 | WithURL(url), 43 | WithLogger(l), 44 | WithClient(m3cl), 45 | } 46 | 47 | for _, opt := range opts { 48 | assert.NoError(t, opt.execute(client)) 49 | } 50 | 51 | assert.Equal(t, l, client.logger) 52 | assert.Equal(t, m3cl, client.client) 53 | assert.Equal(t, url, client.url) 54 | } 55 | -------------------------------------------------------------------------------- /pkg/m3admin/placement/types.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018 Uber Technologies, Inc. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | package placement 22 | 23 | import ( 24 | "github.com/m3db/m3/src/cluster/generated/proto/placementpb" 25 | m3placement "github.com/m3db/m3/src/cluster/placement" 26 | "github.com/m3db/m3/src/query/generated/proto/admin" 27 | ) 28 | 29 | // Client provides the interface to interact with the placement API 30 | type Client interface { 31 | // Init will initialize a placement give a valid placement request 32 | Init(request *admin.PlacementInitRequest) error 33 | // Set will forcefully override a placement with a given value. 34 | Set(request *admin.PlacementSetRequest) error 35 | // Get will provide the current placement 36 | Get() (placement m3placement.Placement, err error) 37 | // Delete will delete the current placement 38 | Delete() error 39 | // Add will add an instance to the placement 40 | Add(instances []*placementpb.Instance) error 41 | // Remove removes instances with the given IDs from the placement. 42 | Remove(instanceIds []string) error 43 | // Replace replaces one instance with another. 44 | Replace(leavingInstanceID string, newInstance placementpb.Instance) error 45 | } 46 | -------------------------------------------------------------------------------- /pkg/m3admin/topic/options.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018 Uber Technologies, Inc. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | package topic 22 | 23 | import ( 24 | "net/url" 25 | 26 | "github.com/m3db/m3db-operator/pkg/m3admin" 27 | 28 | "go.uber.org/zap" 29 | ) 30 | 31 | // Option provides an interface that can be used for setter options with the 32 | // constructor 33 | type Option interface { 34 | execute(*topicClient) error 35 | } 36 | 37 | type optionFn func(p *topicClient) error 38 | 39 | func (fn optionFn) execute(p *topicClient) error { 40 | return fn(p) 41 | } 42 | 43 | // WithURL is a setter to override the default URL 44 | func WithURL(u string) Option { 45 | return optionFn(func(p *topicClient) error { 46 | if _, err := url.ParseRequestURI(u); err != nil { 47 | return err 48 | } 49 | p.url = u 50 | return nil 51 | }) 52 | } 53 | 54 | // WithLogger is a setter to override the default logger 55 | func WithLogger(logger *zap.Logger) Option { 56 | return optionFn(func(p *topicClient) error { 57 | p.logger = logger 58 | return nil 59 | }) 60 | } 61 | 62 | // WithClient configures an m3admin client. 63 | func WithClient(cl m3admin.Client) Option { 64 | return optionFn(func(p *topicClient) error { 65 | p.client = cl 66 | return nil 67 | }) 68 | } 69 | -------------------------------------------------------------------------------- /pkg/m3admin/topic/options_test.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018 Uber Technologies, Inc. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | package topic 22 | 23 | import ( 24 | "testing" 25 | 26 | "github.com/m3db/m3db-operator/pkg/m3admin" 27 | 28 | "github.com/stretchr/testify/assert" 29 | "go.uber.org/zap" 30 | ) 31 | 32 | func TestOptions(t *testing.T) { 33 | client := &topicClient{} 34 | 35 | opt := WithURL("...") 36 | assert.Error(t, opt.execute(client)) 37 | 38 | const url = "http://localhost:1234" 39 | l := zap.NewNop() 40 | m3cl := m3admin.NewClient() 41 | opts := []Option{ 42 | WithURL(url), 43 | WithLogger(l), 44 | WithClient(m3cl), 45 | } 46 | 47 | for _, opt := range opts { 48 | assert.NoError(t, opt.execute(client)) 49 | } 50 | 51 | assert.Equal(t, l, client.logger) 52 | assert.Equal(t, m3cl, client.client) 53 | assert.Equal(t, url, client.url) 54 | } 55 | -------------------------------------------------------------------------------- /pkg/m3admin/topic/types.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018 Uber Technologies, Inc. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | package topic 22 | 23 | import ( 24 | "github.com/m3db/m3/src/msg/generated/proto/topicpb" 25 | m3topic "github.com/m3db/m3/src/msg/topic" 26 | "github.com/m3db/m3/src/query/generated/proto/admin" 27 | ) 28 | 29 | // Client provides the interface to interact with the topic APIs. 30 | type Client interface { 31 | Init(name string, req *admin.TopicInitRequest) error 32 | Get(topicName string) (m3topic.Topic, error) 33 | Delete(topicName string) error 34 | Add(topicName string, consumerSvc *topicpb.ConsumerService) error 35 | } 36 | -------------------------------------------------------------------------------- /pkg/util/eventer/eventer_test.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018 Uber Technologies, Inc. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | package eventer 22 | 23 | import ( 24 | "testing" 25 | 26 | "github.com/m3db/m3db-operator/pkg/client/clientset/versioned/scheme" 27 | 28 | "k8s.io/apimachinery/pkg/runtime" 29 | "k8s.io/apimachinery/pkg/runtime/schema" 30 | kubeFake "k8s.io/client-go/kubernetes/fake" 31 | 32 | "github.com/stretchr/testify/assert" 33 | "github.com/stretchr/testify/require" 34 | "go.uber.org/zap" 35 | ) 36 | 37 | var ( 38 | creator runtime.ObjectCreater = scheme.Scheme 39 | ) 40 | 41 | func TestNop(t *testing.T) { 42 | p := NewNopPoster() 43 | p.NormalEvent(nil, "foo", "bar") 44 | p.WarningEvent(nil, "foo", "bar") 45 | } 46 | 47 | func TestNormalEvent(t *testing.T) { 48 | testObject, err := creator.New(schema.GroupVersionKind{}) 49 | // empty object will throw error 50 | assert.Error(t, err) 51 | 52 | testEventer := testNewEventRecorder(t) 53 | testEventer.NormalEvent(testObject, ReasonAdding, "this is a normal event") 54 | } 55 | 56 | func TestWarningEvent(t *testing.T) { 57 | testObject, err := creator.New(schema.GroupVersionKind{}) 58 | // empty object will throw error 59 | assert.Error(t, err) 60 | 61 | testEventer := testNewEventRecorder(t) 62 | testEventer.WarningEvent(testObject, ReasonFailSync, "this is a warning event") 63 | } 64 | 65 | func testNewEventRecorder(t *testing.T) Poster { 66 | testEventer, err := NewEventRecorder( 67 | WithClient(kubeFake.NewSimpleClientset()), 68 | WithLogger(zap.NewNop()), 69 | WithNamespace("test"), 70 | WithComponent("testy")) 71 | 72 | require.NotNil(t, testEventer) 73 | require.NoError(t, err) 74 | return testEventer 75 | } 76 | -------------------------------------------------------------------------------- /pkg/util/eventer/options.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2016 Uber Technologies, Inc. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | package eventer 22 | 23 | import ( 24 | "k8s.io/client-go/kubernetes" 25 | 26 | "go.uber.org/zap" 27 | ) 28 | 29 | // Option provides configuration of an eventer. 30 | type Option interface { 31 | execute(*options) 32 | } 33 | 34 | type options struct { 35 | kubeClient kubernetes.Interface 36 | logger *zap.Logger 37 | namespace string 38 | component string 39 | } 40 | 41 | type optionFn func(o *options) 42 | 43 | func (fn optionFn) execute(o *options) { 44 | fn(o) 45 | } 46 | 47 | // WithClient sets a client for the eventer (required). 48 | func WithClient(c kubernetes.Interface) Option { 49 | return optionFn(func(o *options) { 50 | o.kubeClient = c 51 | }) 52 | } 53 | 54 | // WithLogger sets a logger for the eventer. If not set a noop logger will 55 | // be used. 56 | func WithLogger(l *zap.Logger) Option { 57 | return optionFn(func(o *options) { 58 | o.logger = l 59 | }) 60 | } 61 | 62 | // WithNamespace sets a namespace for the eventer. 63 | func WithNamespace(ns string) Option { 64 | return optionFn(func(o *options) { 65 | o.namespace = ns 66 | }) 67 | } 68 | 69 | // WithComponent sets a component for the eventer. 70 | func WithComponent(c string) Option { 71 | return optionFn(func(o *options) { 72 | o.component = c 73 | }) 74 | } 75 | -------------------------------------------------------------------------------- /scripts/auto-gen.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | source "$(dirname $0)/../.ci/variables.sh" 3 | 4 | set -ex 5 | 6 | add_license() { 7 | local FILE="$1" 8 | update-license $FILE 9 | } 10 | 11 | export -f add_license 12 | 13 | autogen_clear() { 14 | local DIR="$1" 15 | find $DIR -mindepth 2 -type f -name '*.go' -exec rm -f {} \; 16 | } 17 | 18 | remove_matching_files() { 19 | local DIR=$1 20 | local FILE_PATTERN=$2 21 | find $DIR -type f -name "$FILE_PATTERN" -exec rm -f {} \; 22 | } 23 | 24 | autogen_cleanup() { 25 | local DIR="$1" 26 | find $DIR -type f -name "*.go" -exec /bin/bash -c 'add_license $0' {} \; 27 | } 28 | 29 | mocks_cleanup_helper() { 30 | local FILE=$0 31 | local DIR=$(dirname $FILE) 32 | add_license $FILE 33 | 34 | # NB(xichen): there is an open issue (https://github.com/golang/mock/issues/30) 35 | # with mockgen that causes the generated mock files to have vendored packages 36 | # in the import list. For now we are working around it by removing the vendored 37 | # path. Also sed -i'' does not work with BSD sed shipped with OS X, whereas 38 | # sed -i '' doesn't work with GNU sed, so we work around it by redirecting to a 39 | # temp file first and moving it back later. 40 | sed "s|$VENDOR_PATH/||" $FILE > $FILE.tmp && mv $FILE.tmp $FILE 41 | 42 | # Strip GOPATH from the source file path 43 | sed "s|Source: $GOPATH/src/\(.*\.go\)|Source: \1|" $FILE > $FILE.tmp && mv $FILE.tmp $FILE 44 | 45 | # NB(prateek): running genclean makes mock-gen idempotent. 46 | # NB(xichen): genclean should be run after the vendor path is stripped. 47 | basePkg=$(echo $DIR | sed -e "s@${GOPATH}/src/@@g") 48 | genclean -cleanup-selfref=false -pkg $basePkg -out $FILE -in $FILE 49 | gofmt -w $FILE 50 | } 51 | 52 | export -f mocks_cleanup_helper 53 | 54 | mocks_cleanup() { 55 | local MOCK_PATTERN=$1 56 | for DIR in $SRC; 57 | do 58 | find $DIR -name "$MOCK_PATTERN" -type f -exec /bin/bash -c 'mocks_cleanup_helper $0' {} \; 59 | done 60 | } 61 | 62 | generics_cleanup() { 63 | local GEN_FILES_PATTERN=$1 64 | for DIR in $SRC; 65 | do 66 | find $DIR -name "$GEN_FILES_PATTERN" -type f -exec /bin/bash -c 'add_license $0' {} \; 67 | done 68 | } 69 | 70 | if [ $# -ne 2 ] || [ -z "$1" ] || [ -z "$2" ]; then 71 | echo "usage: auto-gen.sh output_directory file_generation_rules_directory" 72 | exit 1 73 | fi 74 | 75 | if [[ "$2" = *"generated/mocks"* ]]; then 76 | remove_matching_files $1 "*_mock.go" 77 | elif [[ "$2" = *"generated/generics"* ]]; then 78 | remove_matching_files $1 "*.gen.go" 79 | else 80 | autogen_clear $1 81 | fi 82 | 83 | go generate $PACKAGE/$2 84 | 85 | if [[ "$2" = *"generated/mocks"* ]]; then 86 | mocks_cleanup "*_mock.go" 87 | elif [[ "$2" = *"generated/generics"* ]]; then 88 | generics_cleanup "*.gen.go" 89 | else 90 | autogen_cleanup $1 91 | fi 92 | -------------------------------------------------------------------------------- /scripts/kind-create-cluster.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -exo pipefail 4 | 5 | echo "--- :kubernetes: Installing kind" 6 | 7 | KUBE_VERSION=${KUBE_VERSION:-v1.16.15} 8 | KIND_VERSION=${KIND_VERSION:-0.10.0} 9 | CLUSTER_NAME=kind 10 | L_UNAME=$(uname | tr "[:upper:]" "[:lower:]") 11 | 12 | mkdir -p "$HOME/bin" 13 | export PATH="$HOME/bin:$PATH" 14 | 15 | # Use command -v so that user can have kind in PATH but outside of "$HOME/bin". 16 | if [[ ! $(command -v kind) || "$BUILDKITE" == "true" ]]; then 17 | curl -sL -o "$HOME/bin/kind" "https://github.com/kubernetes-sigs/kind/releases/download/v${KIND_VERSION}/kind-${L_UNAME}-amd64" 18 | chmod +x "$HOME/bin/kind" 19 | fi 20 | 21 | if [[ "$(kind --version)" != "kind version ${KIND_VERSION}" ]]; then 22 | echo "expected kind version ${KIND_VERSION}, got $(kind --version)" 23 | exit 1 24 | fi 25 | 26 | if [[ ! $(command -v kubectl) || "$BUILDKITE" == "true" ]]; then 27 | curl -sL -o "$HOME/bin/kubectl" "https://storage.googleapis.com/kubernetes-release/release/$KUBE_VERSION/bin/${L_UNAME}/amd64/kubectl" 28 | chmod +x "$HOME/bin/kubectl" 29 | fi 30 | 31 | 32 | echo "--- :kubernetes: Deleting existing kind clusters" 33 | kind get clusters -q | while read -r CLUSTER; do 34 | kind delete cluster --name "$CLUSTER" 35 | done 36 | 37 | echo "--- :kubernetes: Creating kind cluster" 38 | 39 | # NB(schallert): starting in 1.17, we'll want to move away from the deprecated 40 | # "failure-domain" labels: 41 | # https://kubernetes.io/docs/reference/labels-annotations-taints/#failure-domainbetakubernetesiozone. 42 | 43 | cat > cluster.yaml < 0.2" 15 | echo "Usage: ETCD_NS= ETCD_POD= M3DB_NS= M3DB_CLUSTER= ./migrate_etcd_0.1_0.2.sh" 16 | exit 0 17 | fi 18 | 19 | CLUSTER=$M3DB_CLUSTER 20 | NS=$M3DB_NS 21 | 22 | if ! kubectl get -n "$NS" m3dbcluster "$CLUSTER" > /dev/null; then 23 | echo "Could not find m3dbcluster $CLUSTER in namespace $NS" 24 | exit 1 25 | fi 26 | 27 | ENV="$NS/$CLUSTER" 28 | echo "Copying namespace and placement data from env=default_env to env=$ENV" 29 | 30 | 31 | # Put placement bytes (includes trailing newline) into TMP 32 | kubectl exec -n "$ETCD_NS" "$ETCD_POD" -- env ETCDCTL_API=3 etcdctl get --print-value-only _sd.placement/default_env/m3db > "$TMP" 33 | 34 | # Trim newline in a cross-platform (OSX + Linux) manner and put in new key 35 | N=$(<"$TMP" wc -c) 36 | N=$((N-1)) 37 | head -c "$N" "$TMP" | kubectl exec -i -n "$ETCD_NS" "$ETCD_POD" -- env ETCDCTL_API=3 etcdctl put "_sd.placement/$ENV/m3db" 38 | 39 | # Repeat for namespaces 40 | kubectl exec -n "$ETCD_NS" "$ETCD_POD" -- env ETCDCTL_API=3 etcdctl get --print-value-only _kv/default_env/m3db.node.namespaces > "$TMP" 41 | N=$(<"$TMP" wc -c) 42 | N=$((N-1)) 43 | head -c "$N" "$TMP" | kubectl exec -i -n "$ETCD_NS" "$ETCD_POD" -- env ETCDCTL_API=3 etcdctl put "_kv/$ENV/m3db.node.namespaces" 44 | -------------------------------------------------------------------------------- /scripts/prep_changelog.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | PRS=$(mktemp) 4 | NUMS=$(mktemp) 5 | 6 | function cleanup() { 7 | rm -f "$PRS" "$NUMS" 8 | } 9 | 10 | trap cleanup EXIT 11 | 12 | grep -Eo '\(#[0-9]+\)' CHANGELOG.md | while read -r PR; do 13 | NUM=$(<<<"$PR" grep -Eo '[0-9]+') 14 | echo "$NUM" >> "$NUMS" 15 | echo "[$NUM]: https://github.com/m3db/m3db-operator/pull/$NUM" >> "$PRS" 16 | done 17 | 18 | sort "$NUMS" | uniq | while read -r NUM; do 19 | EXPR="s@(#${NUM})@([#${NUM}][$NUM])@g" 20 | if [[ "$(uname)" == "Darwin" ]]; then 21 | sed -i '' -e "$EXPR" CHANGELOG.md 22 | else 23 | sed -i "$EXPR" CHANGELOG.md 24 | fi 25 | done 26 | 27 | sort "$PRS" | uniq >> CHANGELOG.md 28 | -------------------------------------------------------------------------------- /scripts/run_e2e_tests.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -ex 4 | 5 | function cleanup() { 6 | pkill -f "kubectl proxy" 7 | } 8 | 9 | function main() { 10 | readonly NAMESPACE="m3db-e2e-test-1" 11 | 12 | command -v kubectl > /dev/null || (echo "error: need kubectl installed" && exit 1) 13 | 14 | # Check that we can reasonably connect to a cluster 15 | kubectl cluster-info > /dev/null || (echo "unable to fetch cluster info" && exit 1) 16 | 17 | # Delete the namespace in the case it exists 18 | kubectl delete namespace $NAMESPACE 2> /dev/null || true 19 | 20 | # Wait until it's gone 21 | local NSCOUNT=0 22 | while [[ $NSCOUNT -lt 10 ]]; do 23 | if kubectl get namespace $NAMESPACE 2>&1 | grep -q "not found"; then 24 | break 25 | else 26 | echo "waiting for namespace to be deleted" 27 | sleep 5 28 | ((NSCOUNT++)) 29 | fi 30 | done 31 | 32 | # If a kubectl proxy process is running, delete and wait until it's dead 33 | if pgrep -f 'kubectl proxy'; then 34 | pkill -f 'kubectl proxy' 35 | local PROXYCOUNT=0 36 | while [[ $PROXYCOUNT -lt 10 ]]; do 37 | if pgrep -fq 'kubectl proxy'; then 38 | echo "waiting for proxy proccess to die" 39 | sleep 5 40 | ((PROXYCOUNT++)) 41 | else 42 | break 43 | fi 44 | done 45 | fi 46 | 47 | trap cleanup EXIT 48 | 49 | if [[ -z "$SKIP_DOCKER_BUILD" ]]; then 50 | docker build -t m3db-operator-kind . 51 | kind load docker-image m3db-operator-kind 52 | fi 53 | 54 | kubectl proxy & 55 | go clean -testcache 56 | go test -v -tags integration ./integration/e2e 57 | } 58 | 59 | main 60 | -------------------------------------------------------------------------------- /tools.go: -------------------------------------------------------------------------------- 1 | //go:build tools 2 | // +build tools 3 | 4 | package tools 5 | 6 | import ( 7 | _ "github.com/axw/gocov/gocov" 8 | _ "github.com/cirocosta/grafana-sync" 9 | _ "github.com/fossas/fossa-cli/cmd/fossa" 10 | _ "github.com/go-swagger/go-swagger/cmd/swagger" 11 | _ "github.com/golang/mock/mockgen" 12 | _ "github.com/golangci/golangci-lint/cmd/golangci-lint" 13 | _ "github.com/m3db/build-tools/linters/badtime" 14 | _ "github.com/m3db/build-tools/linters/importorder" 15 | _ "github.com/m3db/build-tools/utilities/genclean" 16 | _ "github.com/m3db/tools/update-license" 17 | _ "github.com/rakyll/statik" 18 | _ "golang.org/x/lint/golint" 19 | _ "k8s.io/code-generator" 20 | _ "sigs.k8s.io/controller-tools/cmd/controller-gen" 21 | ) 22 | --------------------------------------------------------------------------------